From 876b56ee5b6e79c0f4d808434290d3c6ffb1f6f2 Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Mon, 27 Feb 2023 16:37:35 -0700 Subject: [PATCH 01/58] Add shapefile format option to various incarnations of file format flag type and doc. --- src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 | 4 ++-- src/Infrastructure/Util/include/ESMC_Util.h | 15 +++++++++++---- src/Infrastructure/Util/src/ESMF_UtilTypes.F90 | 8 +++++--- src/doc/ESMF_options.tex | 4 +++- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 b/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 index 426a4c5d86..1b47eb5639 100644 --- a/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 +++ b/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 @@ -1875,8 +1875,8 @@ function ESMF_MeshCreateFromFile(filename, fileformat, keywordEnforcer, & ! \item [filename] ! The name of the grid file ! \item[fileformat] -! The file format. The valid options are {\tt ESMF\_FILEFORMAT\_SCRIP}, {\tt ESMF\_FILEFORMAT\_ESMFMESH} and -! {\tt ESMF\_FILEFORMAT\_UGRID}. +! The file format. The valid options are {\tt ESMF\_FILEFORMAT\_SCRIP}, {\tt ESMF\_FILEFORMAT\_ESMFMESH}, +! {\tt ESMF\_FILEFORMAT\_UGRID}, and {\tt ESMF\_FILEFORMAT\_SHAPEFILE}. ! Please see Section~\ref{const:fileformatflag} for a detailed description of the options. ! \item[{[convertToDual]}] ! if {\tt .true.}, the mesh will be converted to its dual. If not specified, diff --git a/src/Infrastructure/Util/include/ESMC_Util.h b/src/Infrastructure/Util/include/ESMC_Util.h index b9f53c9b51..ee5ae0c8f9 100644 --- a/src/Infrastructure/Util/include/ESMC_Util.h +++ b/src/Infrastructure/Util/include/ESMC_Util.h @@ -65,10 +65,17 @@ enum ESMC_ExtrapMethod_Flag {ESMC_EXTRAPMETHOD_NONE=0, ESMC_EXTRAPMETHOD_CREEP, ESMC_EXTRAPMETHOD_CREEP_NRST_D}; -enum ESMC_FileFormat_Flag {ESMC_FILEFORMAT_UNDEFINED, ESMC_FILEFORMAT_VTK, - ESMC_FILEFORMAT_SCRIP, ESMC_FILEFORMAT_ESMFMESH, - ESMC_FILEFORMAT_ESMCGRID, ESMC_FILEFORMAT_UGRID, - ESMC_FILEFORMAT_GRIDSPEC}; +enum ESMC_FileFormat_Flag {ESMC_FILEFORMAT_UNDEFINED=0, + ESMC_FILEFORMAT_VTK, + ESMC_FILEFORMAT_SCRIP, + ESMC_FILEFORMAT_ESMFMESH, + ESMC_FILEFORMAT_ESMFGRID, + ESMC_FILEFORMAT_UGRID, + ESMC_FILEFORMAT_CFGRID, + ESMC_FILEFORMAT_GRIDSPEC, + ESMC_FILEFORMAT_MOSAIC, + ESMC_FILEFORMAT_TILE, + ESMC_FILEFORMAT_SHAPEFILE}; typedef enum ESMC_FileMode_Flag {ESMC_FILEMODE_BASIC, ESMC_FILEMODE_WITHAUX} ESMC_FileMode_Flag; diff --git a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 index c4c59e8827..3f34763f12 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 +++ b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 @@ -908,8 +908,9 @@ module ESMF_UtilTypesMod ESMF_FILEFORMAT_CFGRID = ESMF_FileFormat_Flag(6), & ESMF_FILEFORMAT_GRIDSPEC = ESMF_FileFormat_Flag(6), & ESMF_FILEFORMAT_MOSAIC = ESMF_FileFormat_Flag(7), & - ESMF_FILEFORMAT_TILE = ESMF_FileFormat_Flag(8) - + ESMF_FILEFORMAT_TILE = ESMF_FileFormat_Flag(8), & + ESMF_FILEFORMAT_SHAPEFILE = ESMF_FileFormat_Flag(9) + !------------------------------------------------------------------------------ ! @@ -1227,7 +1228,8 @@ module ESMF_UtilTypesMod ESMF_FILEFORMAT_ESMFMESH, ESMF_FILEFORMAT_ESMFGRID, & ESMF_FILEFORMAT_UGRID, ESMF_FILEFORMAT_GRIDSPEC, & ESMF_FILEFORMAT_CFGRID, ESMF_FILEFORMAT_MOSAIC, & - ESMF_FILEFORMAT_UNKNOWN, ESMF_FILEFORMAT_TILE + ESMF_FILEFORMAT_UNKNOWN, ESMF_FILEFORMAT_TILE, & + ESMF_FILEFORMAT_SHAPEFILE public ESMF_FileMode_Flag, ESMF_FILEMODE_BASIC, ESMF_FILEMODE_WITHAUX diff --git a/src/doc/ESMF_options.tex b/src/doc/ESMF_options.tex index be4a678c60..5faaecba0a 100644 --- a/src/doc/ESMF_options.tex +++ b/src/doc/ESMF_options.tex @@ -275,7 +275,9 @@ \subsection{ESMF\_FILEFORMAT} the format accepted by the SCRIP regridding tool~\cite{ref:SCRIP}. See section\ref{sec:fileformat:scrip} for more detailed description. \item [ESMF\_FILEFORMAT\_UGRID] CF-convention unstructured grid file format. This format is a proposed extension to the -CF-conventions for unstructured grid data model. See section~\ref{sec:fileformat:ugrid} for more detailed description. + CF-conventions for unstructured grid data model. See section~\ref{sec:fileformat:ugrid} for more detailed description. + +\item [ESMF\_FILEFORMAT\_SHAPEFILE] Shapefile file format. This format is a vector data file format commonly used for geospatial analysis. \end{description} From 04fd53e6a8e340949beeb3eb2be88282960f6b59 Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Wed, 1 Mar 2023 17:15:29 -0700 Subject: [PATCH 02/58] Add initial simple unit test for mesh create from shapefile. --- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 8a28562b55..6410f7fd1f 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -328,6 +328,27 @@ program ESMF_MeshFileIOUTest call ESMF_Test((rc==ESMC_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) #endif !----------------------------------------------------------------------------- + + + !----------------------------------------------------------------------------- + !NEX_UTest + write(name, *) "Test creating a mesh from a shape file." + write(failMsg, *) "Did not return ESMF_SUCCESS" + + ! initialize check variables + correct=.true. + rc=ESMF_SUCCESS + + call test_create_mesh_from_SH_file(correct, rc) + +#ifdef ESMF_PIO + call ESMF_Test(((rc.eq.ESMF_SUCCESS)), name, failMsg, result, ESMF_SRCLINE) +#else + write(failMsg, *) "Did not return ESMC_RC_LIB_NOT_PRESENT" + call ESMF_Test((rc==ESMC_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) +#endif + !----------------------------------------------------------------------------- + #endif !------------------------------------------------------------------------ @@ -6865,6 +6886,51 @@ subroutine check_mesh_node_redist_from_file(correct, rc) end subroutine check_mesh_node_redist_from_file + +! Read in a shapefile and make sure that mesh create from file doesn't return errors. +! This is an initial quick test to use for the start of development just to get things going. +! More precise verifications will be done in following tests. +subroutine test_create_mesh_from_SH_file(correct, rc) + logical :: correct + integer :: rc + type(ESMF_Mesh) :: mesh + integer :: petCount, localPet + type(ESMF_VM) :: vm + type(ESMF_DistGrid) :: nodeDistgrid, elemDistgrid + integer, allocatable :: elemIds(:) + integer :: numElems, numPerPet, numThisPet + integer :: minId,maxId + integer :: i, pos + + ! Init correct + correct=.true. + + ! get global VM + call ESMF_VMGetGlobal(vm, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_VMGet(vm, localPet=localPet, petCount=petCount, rc=rc) + if (rc /= ESMF_SUCCESS) return + + ! Create Mesh from shape file + mesh=ESMF_MeshCreate("data/test_shape.shp", & + fileformat=ESMF_FILEFORMAT_SHAPEFILE, & + rc=rc) + if (rc /= ESMF_SUCCESS) return + + + !! Write mesh for debugging + ! call ESMF_MeshWrite(mesh,"test_mesh",rc=rc) + ! if (rc /= ESMF_SUCCESS) return + + ! Get rid of Mesh + ! TODO: Uncomment when above is working + !call ESMF_MeshDestroy(mesh, rc=rc) + if (rc /= ESMF_SUCCESS) return + + ! Return success + rc=ESMF_SUCCESS + +end subroutine test_create_mesh_from_SH_file end program ESMF_MeshFileIOUTest From b50ef16ca4bb42a54208fa2360a0a7df26cddb48 Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Mon, 13 Mar 2023 16:25:31 -0600 Subject: [PATCH 03/58] Since using shapefile will mean not all Mesh I/O is PIO, move PIO down into individual file format methods and reaarange PIO ifdefs. --- .../Mesh/src/ESMCI_Mesh_FileIO.C | 180 ++++++++++-------- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 11 +- 2 files changed, 111 insertions(+), 80 deletions(-) diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index 9a0dd8d406..61c60352e0 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -69,19 +69,15 @@ //----------------------------------------------------------------------------- using namespace ESMCI; -// These internal functions will only be used if PIO is avaiable -#ifdef ESMF_PIO // Prototypes of per format mesh creates from below -void ESMCI_mesh_create_from_ESMFMesh_file(int pioSystemDesc, - char *filename, +void ESMCI_mesh_create_from_ESMFMesh_file(char *filename, bool add_user_area, ESMC_CoordSys_Flag coord_sys, ESMCI::DistGrid *elem_distgrid, Mesh **out_mesh); -void ESMCI_mesh_create_from_UGRID_file(int pioSystemDesc, - char *filename, +void ESMCI_mesh_create_from_UGRID_file(char *filename, bool add_user_area, ESMC_CoordSys_Flag coord_sys, ESMC_MeshLoc_Flag maskFlag, @@ -89,8 +85,7 @@ void ESMCI_mesh_create_from_UGRID_file(int pioSystemDesc, ESMCI::DistGrid *elem_distgrid, Mesh **out_mesh); -void ESMCI_mesh_create_from_SCRIP_file(int pioSystemDesc, - char *filename, +void ESMCI_mesh_create_from_SCRIP_file(char *filename, bool add_user_area, ESMC_CoordSys_Flag coord_sys, ESMCI::DistGrid *elem_distgrid, @@ -100,10 +95,6 @@ void ESMCI_mesh_create_redist_mesh(Mesh *in_mesh, ESMCI::DistGrid *node_distgrid, ESMCI::DistGrid *elem_distgrid, Mesh **out_mesh); -#endif // ifdef ESMF_PIO - - - // INPUTS: // filename - file name in NULL delimited form @@ -131,8 +122,6 @@ void ESMCI_mesh_create_from_file(char *filename, #undef ESMC_METHOD #define ESMC_METHOD "ESMCI_mesh_create_from_file()" -// Will only work if PIO is available -#ifdef ESMF_PIO // printf("in new scalable mesh create from file filename=%s\n",filename); @@ -157,30 +146,6 @@ void ESMCI_mesh_create_from_file(char *filename, - //// Set up PIO - - // Get VM - ESMCI::VM *vm=VM::getCurrent(&localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - &localrc)) throw localrc; - - // Get VM info - int local_pet = vm->getLocalPet(); - MPI_Comm mpi_comm = vm->getMpi_c(); - int pet_count = vm->getPetCount(); - int pets_per_Ssi = vm->getSsiMaxPetCount(); - - // Initialize IO system - int num_iotasks = pet_count/pets_per_Ssi; - int stride = pets_per_Ssi; - int pioSystemDesc; - int piorc; - - piorc = PIOc_Init_Intracomm(mpi_comm, num_iotasks, stride, 0, PIO_REARR_SUBSET, &pioSystemDesc); - if (!CHECKPIOERROR(piorc, std::string("Unable to init PIO Intracomm for file: ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - // Since we are swapping nodes and elems in convert_to_dual, // can't use elem_distgrid to read from file in that case. ESMCI::DistGrid *elem_distgrid_for_file_read=NULL; @@ -190,20 +155,20 @@ void ESMCI_mesh_create_from_file(char *filename, // Create Mesh based on the file format Mesh *tmp_mesh; if (fileformat == ESMC_FILEFORMAT_ESMFMESH) { - ESMCI_mesh_create_from_ESMFMesh_file(pioSystemDesc, filename, + ESMCI_mesh_create_from_ESMFMesh_file(filename, add_user_area, coord_sys, elem_distgrid_for_file_read, &tmp_mesh); } else if (fileformat == ESMC_FILEFORMAT_UGRID) { - ESMCI_mesh_create_from_UGRID_file(pioSystemDesc, filename, + ESMCI_mesh_create_from_UGRID_file(filename, add_user_area, coord_sys, maskFlag, maskVarName, elem_distgrid_for_file_read, &tmp_mesh); } else if (fileformat == ESMC_FILEFORMAT_SCRIP) { - ESMCI_mesh_create_from_SCRIP_file(pioSystemDesc, filename, + ESMCI_mesh_create_from_SCRIP_file(filename, add_user_area, coord_sys, elem_distgrid_for_file_read, &tmp_mesh); @@ -214,14 +179,6 @@ void ESMCI_mesh_create_from_file(char *filename, } - - // Free IO system - piorc = PIOc_free_iosystem(pioSystemDesc); - if (!CHECKPIOERROR(piorc, std::string("Error freeing pio file system description "), - ESMF_RC_FILE_OPEN, localrc)) throw localrc;; - - - // If requested, create dual from read in file if (convert_to_dual) { @@ -292,16 +249,57 @@ void ESMCI_mesh_create_from_file(char *filename, // We've gotten to bottom successfully, so return success if(rc != NULL) *rc = ESMF_SUCCESS; -#else - ESMC_LogDefault.MsgFoundError(ESMC_RC_LIB_NOT_PRESENT, - "This functionality requires ESMF to be built with the PIO library enabled." , - ESMC_CONTEXT, rc); -#endif } // These internal functions will only be used if PIO is available #ifdef ESMF_PIO +static void _init_pioSystem(int &pioSystemDesc) { +#undef ESMC_METHOD +#define ESMC_METHOD "_create_pioSystemDesc()" + + // Local return codes + int localrc; + int piorc; + + + // Get VM + ESMCI::VM *vm=VM::getCurrent(&localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // Get VM info + int local_pet = vm->getLocalPet(); + MPI_Comm mpi_comm = vm->getMpi_c(); + int pet_count = vm->getPetCount(); + int pets_per_Ssi = vm->getSsiMaxPetCount(); + + // Initialize IO system + int num_iotasks = pet_count/pets_per_Ssi; + int stride = pets_per_Ssi; + + piorc = PIOc_Init_Intracomm(mpi_comm, num_iotasks, stride, 0, PIO_REARR_SUBSET, &pioSystemDesc); + if (!CHECKPIOERROR(piorc, std::string("Unable to init PIO Intracomm"), + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + +} + +static void _free_pioSystem(int pioSystemDesc) { + + // Return codes + int localrc; + int piorc; + + // Free IO system + piorc = PIOc_free_iosystem(pioSystemDesc); + if (!CHECKPIOERROR(piorc, std::string("Error freeing pio file system description "), + ESMF_RC_FILE_OPEN, localrc)) throw localrc;; + +} + +#endif // ifdef ESMF_PIO + + // This method checks to see if optional pole info is in the file, and // if it is, then it uses it to mark the pole edges in the passed in mesh @@ -383,8 +381,7 @@ void ESMCI_mesh_mark_poles_from_ESMFMesh_file(int pioFileDesc, char *filename, M // OUTPUTS: // out_mesh - the new mesh created from the file // -void ESMCI_mesh_create_from_ESMFMesh_file(int pioSystemDesc, - char *filename, +void ESMCI_mesh_create_from_ESMFMesh_file(char *filename, bool add_user_area, ESMC_CoordSys_Flag coord_sys, ESMCI::DistGrid *elem_distgrid, @@ -392,18 +389,26 @@ void ESMCI_mesh_create_from_ESMFMesh_file(int pioSystemDesc, #undef ESMC_METHOD #define ESMC_METHOD "ESMCI_mesh_create_from_ESMFMesh_file()" + // Init output + *out_mesh=NULL; + + // Will only work if PIO is available +#ifdef ESMF_PIO + // Declare some handy variables int localrc; int rc; int piorc; - // Init output - *out_mesh=NULL; - // Try-catch block around main part of method try { + //// Set up PIO System + int pioSystemDesc; + _init_pioSystem(pioSystemDesc); + + //// Open file via PIO // Set pio_type based on what's available @@ -652,6 +657,9 @@ void ESMCI_mesh_create_from_ESMFMesh_file(int pioSystemDesc, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; + // Free PIO System + _free_pioSystem(pioSystemDesc); + } catch(std::exception &x) { @@ -675,6 +683,15 @@ void ESMCI_mesh_create_from_ESMFMesh_file(int pioSystemDesc, "Caught unknown exception", ESMC_CONTEXT, &rc); throw rc; // To be caught one level up so we know where the error came from } + + +#else + int localrc; + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_LIB_NOT_PRESENT, + "This functionality requires ESMF to be built with the PIO library enabled." , + ESMC_CONTEXT, &localrc)) throw localrc; +#endif + } // @@ -692,8 +709,7 @@ void ESMCI_mesh_create_from_ESMFMesh_file(int pioSystemDesc, // OUTPUTS: // out_mesh - the new mesh created from the file // -void ESMCI_mesh_create_from_UGRID_file(int pioSystemDesc, - char *filename, +void ESMCI_mesh_create_from_UGRID_file(char *filename, bool add_user_area, ESMC_CoordSys_Flag coord_sys, ESMC_MeshLoc_Flag maskFlag, @@ -703,17 +719,25 @@ void ESMCI_mesh_create_from_UGRID_file(int pioSystemDesc, #undef ESMC_METHOD #define ESMC_METHOD "ESMCI_mesh_create_from_UGRID_file()" + // Init output + *out_mesh=NULL; + + // Will only work if PIO is available +#ifdef ESMF_PIO + // Declare some handy variables int localrc; int rc; int piorc; - // Init output - *out_mesh=NULL; - // Try-catch block around main part of method try { + //// Set up PIO System + int pioSystemDesc; + _init_pioSystem(pioSystemDesc); + + //// Open file via PIO // Set pio_type based on what's available @@ -983,9 +1007,10 @@ void ESMCI_mesh_create_from_UGRID_file(int pioSystemDesc, if (!CHECKPIOERROR(piorc, std::string("Error closing file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; - // Throw() << "Not finished with UGRID yet!"; - + // Free PIO System + _free_pioSystem(pioSystemDesc); + } catch(std::exception &x) { // catch Mesh exception return code @@ -1008,6 +1033,14 @@ void ESMCI_mesh_create_from_UGRID_file(int pioSystemDesc, "Caught unknown exception", ESMC_CONTEXT, &rc); throw rc; // To be caught one level up so we know where the error came from } + +#else + int localrc; + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_LIB_NOT_PRESENT, + "This functionality requires ESMF to be built with the PIO library enabled." , + ESMC_CONTEXT, &localrc)) throw localrc; +#endif + } // @@ -1023,12 +1056,11 @@ void ESMCI_mesh_create_from_UGRID_file(int pioSystemDesc, // OUTPUTS: // out_mesh - the new mesh created from the file // -void ESMCI_mesh_create_from_SCRIP_file(int pioSystemDesc, - char *filename, - bool add_user_area, - ESMC_CoordSys_Flag coord_sys, - ESMCI::DistGrid *elem_distgrid, - Mesh **out_mesh){ +void ESMCI_mesh_create_from_SCRIP_file(char *filename, + bool add_user_area, + ESMC_CoordSys_Flag coord_sys, + ESMCI::DistGrid *elem_distgrid, + Mesh **out_mesh){ #undef ESMC_METHOD #define ESMC_METHOD "ESMCI_mesh_create_from_SCRIP_file()" @@ -1073,8 +1105,7 @@ void ESMCI_mesh_create_from_SCRIP_file(int pioSystemDesc, vm->barrier(); // Call into ESMFMesh format read to create mesh from converted file - ESMCI_mesh_create_from_ESMFMesh_file(pioSystemDesc, - esmfmesh_filename, + ESMCI_mesh_create_from_ESMFMesh_file(esmfmesh_filename, add_user_area, coord_sys, elem_distgrid, @@ -1235,4 +1266,3 @@ void ESMCI_mesh_create_redist_mesh(Mesh *in_mesh, } -#endif // ifdef ESMF_PIO diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 6410f7fd1f..13fd7eb867 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -341,12 +341,13 @@ program ESMF_MeshFileIOUTest call test_create_mesh_from_SH_file(correct, rc) -#ifdef ESMF_PIO +! TODO: CHANGE ESMF_PIO TO THE SHAPEFILE EQUIVALENT +!#ifdef ESMF_PIO call ESMF_Test(((rc.eq.ESMF_SUCCESS)), name, failMsg, result, ESMF_SRCLINE) -#else - write(failMsg, *) "Did not return ESMC_RC_LIB_NOT_PRESENT" - call ESMF_Test((rc==ESMC_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) -#endif +!#else +! write(failMsg, *) "Did not return ESMC_RC_LIB_NOT_PRESENT" +! call ESMF_Test((rc==ESMC_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) +!#endif !----------------------------------------------------------------------------- #endif From 5210dc7193ed74fdeed1f53ab35239d45fd22caa Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Mon, 13 Mar 2023 19:09:35 -0600 Subject: [PATCH 04/58] Add skeleton method for creating a mesh from a shapefile. Also, fix issue with file format flag Fortran-C correspondance. --- .../Mesh/src/ESMCI_Mesh_FileIO.C | 73 +++++++++++++++++++ .../Util/src/ESMF_UtilTypes.F90 | 8 +- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index 61c60352e0..b118e8764f 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -91,6 +91,9 @@ void ESMCI_mesh_create_from_SCRIP_file(char *filename, ESMCI::DistGrid *elem_distgrid, Mesh **out_mesh); +void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, + Mesh **out_mesh); + void ESMCI_mesh_create_redist_mesh(Mesh *in_mesh, ESMCI::DistGrid *node_distgrid, ESMCI::DistGrid *elem_distgrid, @@ -172,6 +175,11 @@ void ESMCI_mesh_create_from_file(char *filename, add_user_area, coord_sys, elem_distgrid_for_file_read, &tmp_mesh); + + } else if (fileformat == ESMC_FILEFORMAT_SHAPEFILE) { + ESMCI_mesh_create_from_SHAPEFILE_file(filename, + &tmp_mesh); + } else { if (ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_VALUE, " Unrecognized file format.", @@ -1266,3 +1274,68 @@ void ESMCI_mesh_create_redist_mesh(Mesh *in_mesh, } + + +// +// Create a Mesh from a SHAPEFILE format file +// +// INPUTS: +// filename - file name in NULL delimited form +// +// OUTPUTS: +// out_mesh - the new mesh created from the file +// +void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, + Mesh **out_mesh){ +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI_mesh_create_from_SHAPEFILE_file()" + + // Init output + *out_mesh=NULL; + + // Declare some handy variables + int localrc; + int rc; + + + // Try-catch block around main part of method + try { + + + + + // Return an error, because this isn't implemented yet + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_NOT_IMPL, + "Creating a Mesh from a shapefile format file not finished yet.", + ESMC_CONTEXT, &localrc)) throw localrc; + + + } catch(std::exception &x) { + + // catch Mesh exception return code + if (x.what()) { + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, + x.what(), ESMC_CONTEXT,&rc); + } else { + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, + "UNKNOWN", ESMC_CONTEXT,&rc); + } + throw rc; // To be caught one level up so we know where the error came from + + }catch(int localrc){ + // catch standard ESMF return code + ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT,&rc); + throw rc; // To be caught one level up so we know where the error came from + + } catch(...){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, + "Caught unknown exception", ESMC_CONTEXT, &rc); + throw rc; // To be caught one level up so we know where the error came from + } + + +} + + + + diff --git a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 index 3f34763f12..8d9c30c6b5 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 +++ b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 @@ -906,10 +906,10 @@ module ESMF_UtilTypesMod ESMF_FILEFORMAT_ESMFGRID = ESMF_FileFormat_Flag(4), & ESMF_FILEFORMAT_UGRID = ESMF_FileFormat_Flag(5), & ESMF_FILEFORMAT_CFGRID = ESMF_FileFormat_Flag(6), & - ESMF_FILEFORMAT_GRIDSPEC = ESMF_FileFormat_Flag(6), & - ESMF_FILEFORMAT_MOSAIC = ESMF_FileFormat_Flag(7), & - ESMF_FILEFORMAT_TILE = ESMF_FileFormat_Flag(8), & - ESMF_FILEFORMAT_SHAPEFILE = ESMF_FileFormat_Flag(9) + ESMF_FILEFORMAT_GRIDSPEC = ESMF_FileFormat_Flag(7), & + ESMF_FILEFORMAT_MOSAIC = ESMF_FileFormat_Flag(8), & + ESMF_FILEFORMAT_TILE = ESMF_FileFormat_Flag(9), & + ESMF_FILEFORMAT_SHAPEFILE = ESMF_FileFormat_Flag(10) !------------------------------------------------------------------------------ From eb5804567e78e96124d3c1d0269fbc88d91ee225 Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Wed, 15 Mar 2023 14:52:06 -0600 Subject: [PATCH 05/58] Add files to contain shapefile mesh information read methods. --- .../Mesh/include/ESMCI_SHAPEFILE_Util.h | 58 +++++++++++++++ .../Mesh/src/ESMCI_Mesh_FileIO.C | 14 +++- .../Mesh/src/ESMCI_SHAPEFILE_Util.C | 74 +++++++++++++++++++ src/Infrastructure/Mesh/src/makefile | 1 + 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h create mode 100644 src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C diff --git a/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h b/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h new file mode 100644 index 0000000000..1c36a1ed1f --- /dev/null +++ b/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h @@ -0,0 +1,58 @@ +// $Id$ +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//============================================================================== + +//============================================================================== +// +// This file contains the Fortran interface code to link F90 and C++. +// +//------------------------------------------------------------------------------ +// INCLUDES +//------------------------------------------------------------------------------ + +#ifndef ESMCI_SHAPEFILE_UTIL_H +#define ESMCI_SHAPEFILE_UTIL_H + +#include +#include +#include + +#include "ESMCI_Macros.h" +#include "ESMCI_F90Interface.h" +#include "ESMCI_LogErr.h" +#include "ESMCI_VM.h" +#include "ESMCI_CoordSys.h" +#include "ESMCI_Array.h" +#include "ESMCI_DistGrid.h" + +#include "Mesh/include/ESMCI_Mesh.h" + +// These internal functions can only be used if SHAPEFILE is available +//#ifdef ESMF_PIO + +// TODO: Change when we know name of shapefile include file +//#include + +//----------------------------------------------------------------------------- + // leave the following line as-is; it will insert the cvs ident string + // into the object file for tracking purposes. +// static const char *const version = "$Id$"; +//----------------------------------------------------------------------------- + + +using namespace ESMCI; + +void get_example_from_SHAPEFILE_file(char *filename, int &example); + + +//#endif // ifdef ESMF_PIO + +#endif // ESMCI_SHAPEFILE_UTIL_H diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index b118e8764f..c648e438d4 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -43,10 +43,12 @@ #include "Mesh/include/ESMCI_MeshRedist.h" #include "Mesh/include/ESMCI_MeshDual.h" #include "Mesh/include/ESMCI_Mesh_Glue.h" +#include "IO/include/ESMC_IOScrip2ESMF.h" #include "Mesh/include/ESMCI_FileIO_Util.h" #include "Mesh/include/ESMCI_ESMFMesh_Util.h" #include "Mesh/include/ESMCI_UGRID_Util.h" -#include "IO/include/ESMC_IOScrip2ESMF.h" +#include "Mesh/include/ESMCI_SHAPEFILE_Util.h" + #ifdef ESMF_PNETCDF # define _PNETCDF @@ -1301,10 +1303,18 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, // Try-catch block around main part of method try { - + // Example just to make sure everything is compiling correctly + int example; + get_example_from_SHAPEFILE_file(filename, example); + if (example == 3) { + printf("Example subroutine is working (example=%d)!\n",example); + } + + //// Fill in code getting things from shapefile and creating parts of the Mesh here // Return an error, because this isn't implemented yet + // TODO: GET RID OF THE FOLLOWING LINE WHEN THIS SUBROUTINE IS CREATING A VALID MESH if (ESMC_LogDefault.MsgFoundError(ESMC_RC_NOT_IMPL, "Creating a Mesh from a shapefile format file not finished yet.", ESMC_CONTEXT, &localrc)) throw localrc; diff --git a/src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C b/src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C new file mode 100644 index 0000000000..62613035a2 --- /dev/null +++ b/src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C @@ -0,0 +1,74 @@ +// $Id$ +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//============================================================================== + +//============================================================================== +// +// This file contains the Fortran interface code to link F90 and C++. +// +//------------------------------------------------------------------------------ +// INCLUDES +//------------------------------------------------------------------------------ + +#include +#include +#include +#include + +#include "ESMCI_Macros.h" +#include "ESMCI_F90Interface.h" +#include "ESMCI_LogErr.h" +#include "ESMCI_VM.h" +#include "ESMCI_CoordSys.h" +#include "ESMCI_Array.h" +#include "ESMC_Util.h" + +#include "ESMCI_TraceMacros.h" // for profiling + +#include "Mesh/include/ESMCI_Mesh.h" +#include "Mesh/include/Legacy/ESMCI_MeshRead.h" +#include "Mesh/include/Regridding/ESMCI_MeshRegrid.h" //only for the conservative flag in add_elements +#include "Mesh/include/Legacy/ESMCI_MeshVTK.h" +#include "Mesh/include/Legacy/ESMCI_ParEnv.h" +#include "Mesh/include/Legacy/ESMCI_MeshUtils.h" +#include "Mesh/include/Legacy/ESMCI_GlobalIds.h" +#include "Mesh/include/ESMCI_MeshRedist.h" +#include "Mesh/include/ESMCI_MeshDual.h" +#include "Mesh/include/ESMCI_Mesh_Glue.h" +#include "Mesh/include/ESMCI_FileIO_Util.h" + +// These internal functions can only be used if PIO is available +//#ifdef ESMF_PIO + +// TODO: SWITCH THIS TO SHAPELIB, WHEN WE KNOW WHAT IT'S CALLED +//#include + +//----------------------------------------------------------------------------- + // leave the following line as-is; it will insert the cvs ident string + // into the object file for tracking purposes. + static const char *const version = "$Id$"; +//----------------------------------------------------------------------------- +using namespace ESMCI; + + +void get_example_from_SHAPEFILE_file(char *filename, int &example) { +#undef ESMC_METHOD +#define ESMC_METHOD "get_coordDim_from_ESMFMesh_file()" + + + // Set example + example=3; + +} + + +//#endif // ifdef ESMF_PIO + diff --git a/src/Infrastructure/Mesh/src/makefile b/src/Infrastructure/Mesh/src/makefile index 1c93f3bfaa..f89a1bfa69 100644 --- a/src/Infrastructure/Mesh/src/makefile +++ b/src/Infrastructure/Mesh/src/makefile @@ -13,6 +13,7 @@ SOURCEC = \ ESMCI_FileIO_Util.C \ ESMCI_ESMFMesh_Util.C \ ESMCI_UGRID_Util.C \ + ESMCI_SHAPEFILE_Util.C \ ESMCI_Mesh_FileIO.C \ ESMCI_GToM_Util.C \ ESMCI_Mesh_GToM_Glue.C \ From 792f97576616b2a31ea7f02366c8d0e9da3c609a Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Wed, 15 Mar 2023 16:54:35 -0600 Subject: [PATCH 06/58] Add ESMF_SHAPEFILE environment variables for building with shapefile library. --- build/common.mk | 32 +++++++++++++++++++ makefile | 24 ++++++++++++++ .../Mesh/include/ESMCI_SHAPEFILE_Util.h | 8 ++--- .../Mesh/src/ESMCI_Mesh_FileIO.C | 16 +++++++++- .../Mesh/src/ESMCI_SHAPEFILE_Util.C | 6 ++-- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 10 +++--- 6 files changed, 82 insertions(+), 14 deletions(-) diff --git a/build/common.mk b/build/common.mk index 95cab7e1c9..2c6b4aa6f8 100644 --- a/build/common.mk +++ b/build/common.mk @@ -1612,6 +1612,38 @@ ESMF_F90LINKRPATHSTHIRD += $(ESMF_F90RPATHPREFIX)$(ESMF_PNETCDF_LIBPATH) endif endif +#------------------------------------------------------------------------------- +# SHAPEFILE C++ API +#------------------------------------------------------------------------------- +ifeq ($(ESMF_SHAPEFILE),standard) +ifneq ($(origin ESMF_SHAPEFILE_LIBS), environment) +# BOB: LEAVE BLANK UNTIL I KNOW NAME OF SHAPEFILE LIB +#ESMF_SHAPEFILE_LIBS = -lxerces-c +ESMF_SHAPEFILE_LIBS = +endif +endif + +ifdef ESMF_SHAPEFILE +ESMF_CPPFLAGS += -DESMF_SHAPEFILE=1 +ifdef ESMF_SHAPEFILE_INCLUDE +ESMF_CXXCOMPILEPATHSTHIRD += -I$(ESMF_SHAPEFILE_INCLUDE) +ESMF_F90COMPILEPATHSTHIRD += -I$(ESMF_SHAPEFILE_INCLUDE) +endif +ifdef ESMF_SHAPEFILE_LIBS +ESMF_CXXLINKLIBS += $(ESMF_SHAPEFILE_LIBS) +ESMF_CXXLINKRPATHSTHIRD += $(addprefix $(ESMF_CXXRPATHPREFIX),$(subst -L,,$(filter -L%,$(ESMF_SHAPEFILE_LIBS)))) +ESMF_F90LINKLIBS += $(ESMF_SHAPEFILE_LIBS) +ESMF_F90LINKRPATHSTHIRD += $(addprefix $(ESMF_F90RPATHPREFIX),$(subst -L,,$(filter -L%,$(ESMF_SHAPEFILE_LIBS)))) +endif +ifdef ESMF_SHAPEFILE_LIBPATH +ESMF_CXXLINKPATHSTHIRD += -L$(ESMF_SHAPEFILE_LIBPATH) +ESMF_F90LINKPATHSTHIRD += -L$(ESMF_SHAPEFILE_LIBPATH) +ESMF_CXXLINKRPATHSTHIRD += $(ESMF_CXXRPATHPREFIX)$(ESMF_SHAPEFILE_LIBPATH) +ESMF_F90LINKRPATHSTHIRD += $(ESMF_F90RPATHPREFIX)$(ESMF_SHAPEFILE_LIBPATH) +endif +endif + + #------------------------------------------------------------------------------- # XERCES C++ XML API #------------------------------------------------------------------------------- diff --git a/makefile b/makefile index 71461b1099..b908d307f8 100644 --- a/makefile +++ b/makefile @@ -254,6 +254,18 @@ endif echo "ESMF_PIO_LIBPATH: $(ESMF_PIO_LIBPATH)" ; \ fi; \ fi + -@if [ -n "$(ESMF_SHAPEFILE)" ] ; then \ + echo "ESMF_SHAPEFILE: $(ESMF_SHAPEFILE)" ; \ + if [ -n "$(ESMF_SHAPEFILE_INCLUDE)" ] ; then \ + echo "ESMF_SHAPEFILE_INCLUDE: $(ESMF_SHAPEFILE_INCLUDE)" ; \ + fi; \ + if [ -n "$(ESMF_SHAPEFILE_LIBS)" ] ; then \ + echo "ESMF_SHAPEFILE_LIBS: $(ESMF_SHAPEFILE_LIBS)" ; \ + fi; \ + if [ -n "$(ESMF_SHAPEFILE_LIBPATH)" ] ; then \ + echo "ESMF_SHAPEFILE_LIBPATH: $(ESMF_SHAPEFILE_LIBPATH)" ; \ + fi; \ + fi -@if [ -n "$(ESMF_XERCES)" ] ; then \ echo "ESMF_XERCES: $(ESMF_XERCES)" ; \ if [ -n "$(ESMF_XERCES_INCLUDE)" ] ; then \ @@ -639,6 +651,18 @@ endif echo "# ESMF_PIO_LIBPATH: $(ESMF_PIO_LIBPATH)" >> $(MKINFO) ; \ fi; \ fi + -@if [ -n "$(ESMF_SHAPEFILE)" ] ; then \ + echo "# ESMF_SHAPEFILE: $(ESMF_SHAPEFILE)" >> $(MKINFO) ; \ + if [ -n "$(ESMF_SHAPEFILE_INCLUDE)" ] ; then \ + echo "# ESMF_SHAPEFILE_INCLUDE: $(ESMF_SHAPEFILE_INCLUDE)" >> $(MKINFO) ; \ + fi; \ + if [ -n "$(ESMF_SHAPEFILE_LIBS)" ] ; then \ + echo "# ESMF_SHAPEFILE_LIBS: $(ESMF_SHAPEFILE_LIBS)" >> $(MKINFO) ; \ + fi; \ + if [ -n "$(ESMF_SHAPEFILE_LIBPATH)" ] ; then \ + echo "# ESMF_SHAPEFILE_LIBPATH: $(ESMF_SHAPEFILE_LIBPATH)" >> $(MKINFO) ; \ + fi; \ + fi -@if [ -n "$(ESMF_XERCES)" ] ; then \ echo "# ESMF_XERCES: $(ESMF_XERCES)" >> $(MKINFO) ; \ if [ -n "$(ESMF_XERCES_INCLUDE)" ] ; then \ diff --git a/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h b/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h index 1c36a1ed1f..12bb764392 100644 --- a/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h +++ b/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h @@ -33,10 +33,8 @@ #include "ESMCI_Array.h" #include "ESMCI_DistGrid.h" -#include "Mesh/include/ESMCI_Mesh.h" - // These internal functions can only be used if SHAPEFILE is available -//#ifdef ESMF_PIO +#ifdef ESMF_SHAPEFILE // TODO: Change when we know name of shapefile include file //#include @@ -50,9 +48,9 @@ using namespace ESMCI; -void get_example_from_SHAPEFILE_file(char *filename, int &example); +void get_example_from_SHAPEFILE_file(int &example); -//#endif // ifdef ESMF_PIO +#endif // ifdef ESMF_SHAPEFILE #endif // ESMCI_SHAPEFILE_UTIL_H diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index c648e438d4..4f7f7d4c98 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -1295,6 +1295,9 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, // Init output *out_mesh=NULL; + // Will only work if SHAPEFILE is available +#ifdef ESMF_SHAPEFILE + // Declare some handy variables int localrc; int rc; @@ -1303,9 +1306,13 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, // Try-catch block around main part of method try { + // DEBUG OUTPUT filename + printf("In shapefile method filename=%s\n",filename); + + // Example just to make sure everything is compiling correctly int example; - get_example_from_SHAPEFILE_file(filename, example); + get_example_from_SHAPEFILE_file(example); if (example == 3) { printf("Example subroutine is working (example=%d)!\n",example); } @@ -1343,6 +1350,13 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, throw rc; // To be caught one level up so we know where the error came from } +#else // ifdef ESMF_SHAPEFILE + int localrc; + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_LIB_NOT_PRESENT, + "This functionality requires ESMF to be built with a shapefile library." , + ESMC_CONTEXT, &localrc)) throw localrc; +#endif // ifdef ESMF_SHAPEFILE + } diff --git a/src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C b/src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C index 62613035a2..dd735d7543 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_SHAPEFILE_Util.C @@ -46,7 +46,7 @@ #include "Mesh/include/ESMCI_FileIO_Util.h" // These internal functions can only be used if PIO is available -//#ifdef ESMF_PIO +#ifdef ESMF_SHAPEFILE // TODO: SWITCH THIS TO SHAPELIB, WHEN WE KNOW WHAT IT'S CALLED //#include @@ -59,7 +59,7 @@ using namespace ESMCI; -void get_example_from_SHAPEFILE_file(char *filename, int &example) { +void get_example_from_SHAPEFILE_file(int &example) { #undef ESMC_METHOD #define ESMC_METHOD "get_coordDim_from_ESMFMesh_file()" @@ -70,5 +70,5 @@ void get_example_from_SHAPEFILE_file(char *filename, int &example) { } -//#endif // ifdef ESMF_PIO +#endif // ifdef ESMF_SHAPEFILE diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 13fd7eb867..4b44f1cf11 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -342,12 +342,12 @@ program ESMF_MeshFileIOUTest call test_create_mesh_from_SH_file(correct, rc) ! TODO: CHANGE ESMF_PIO TO THE SHAPEFILE EQUIVALENT -!#ifdef ESMF_PIO +#ifdef ESMF_SHAPEFILE call ESMF_Test(((rc.eq.ESMF_SUCCESS)), name, failMsg, result, ESMF_SRCLINE) -!#else -! write(failMsg, *) "Did not return ESMC_RC_LIB_NOT_PRESENT" -! call ESMF_Test((rc==ESMC_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) -!#endif +#else + write(failMsg, *) "Did not return ESMC_RC_LIB_NOT_PRESENT" + call ESMF_Test((rc==ESMC_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) +#endif !----------------------------------------------------------------------------- #endif From f834e4df753990d7c980a9ba26597dff8447e169 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Wed, 31 May 2023 11:51:27 -0400 Subject: [PATCH 07/58] OK. Built routine infrastructure. ML --- #gisDev.org# | 75 + .#gisDev.org | 1 + gisDev.org | 75 + settings.sh | 13 + ...MCI_SHAPEFILE_Util.h => ESMCI_GDAL_Util.h} | 19 +- .../Mesh/src/#ESMCI_UGRID_Util.C# | 1129 ++++ .../Mesh/src/.#ESMCI_UGRID_Util.C | 1 + ...MCI_SHAPEFILE_Util.C => ESMCI_GDAL_Util.C} | 96 +- .../Mesh/src/ESMCI_Mesh_FileIO.C | 30 +- src/Infrastructure/Mesh/src/makefile | 2 +- .../Mesh/tests/ESMCI_MeshCapGenUTest.C | 537 ++ .../Mesh/tests/ESMCI_MeshCapRegridGenUTest.C | 5091 +++++++++++++++++ 12 files changed, 7048 insertions(+), 21 deletions(-) create mode 100644 #gisDev.org# create mode 120000 .#gisDev.org create mode 100644 gisDev.org create mode 100755 settings.sh rename src/Infrastructure/Mesh/include/{ESMCI_SHAPEFILE_Util.h => ESMCI_GDAL_Util.h} (76%) create mode 100644 src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# create mode 120000 src/Infrastructure/Mesh/src/.#ESMCI_UGRID_Util.C rename src/Infrastructure/Mesh/src/{ESMCI_SHAPEFILE_Util.C => ESMCI_GDAL_Util.C} (51%) create mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C create mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C diff --git a/#gisDev.org# b/#gisDev.org# new file mode 100644 index 0000000000..a7a0fb619e --- /dev/null +++ b/#gisDev.org# @@ -0,0 +1,75 @@ +#+TODO: TODO IN-PROGRESS ISSUES BETA WAITING DONE + +* From Bob - 3/15/23 +** Basics +I’ve added a new unit test in the file: + /src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +This test is called test_create_mesh_from_SH_file() and all it does is call mesh create from file +with the new flag ESMF_FILEFORMAT_SHAPEFILE this calls down through the layers to the new +subroutine ESMCI_mesh_create_from_SHAPEFILE_file() in the file + /src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +this is a good place to add the high level implementation of the mesh create code. You can see +analogous code in + ESMCI_mesh_create_from_ESMFMesh_file() +in the same file. I also added a place to put the shapefile specific calls in the file + ESMCI_SHAPEFILE_Util.C +in the same directory. I added an example subroutine: + get_example_from_SHAPEFILE_file() +in there, just to make sure that all the compiling works. Feel free to get rid of that. + +** Enviroment + In order for ESMF to be built with the shapefile library I also added the environment variables +to the ESMF build: + ESMF_SHAPEFILE + ESMF_SHAPEFILE_INCLUDE + ESMF_SHAPEFILE_LIBPATH + ESMF_SHAPEFILE_LIBS + +I didn’t know anything about the library for the shapefile stuff so you will need to fill them in: + - ESMF_SHAPEFILE just needs to be defined to something (e.g. ON) + - ESMF_SHAPEFILE_LIBS is the name of the library e.g. -lshapelib ??? + - ESMF_SHAPEFILE_INCLUDE is the path to the shapefile include file + - ESMF_SHAPEFILE_LIBPATH is the path to the shapfile library + +** shplib +I didn’t have the shapefile library built, so this might take a bit of experimenting, but it should +be approximately correct. Making sure it works is probably a good place to start. + Along these lines I didn’t know the name of the include file, so that’ll have to be changed +around line 52 of ESMCI_SHAPEFILE_Util.C and line 40 of + /src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h +(in the place where it says #include replace pio.h with the shapefile one) + +** Where to add new code/modules +If you have more code that you want to add (or that you’ve added already) that you don’t think will +fit in ESMCI_SHAPEFILE_Util.C, then we can add a new directory in + /src/Infrastructure/IO +(e.g. /src/Infrastructure/IO/SHAPEFILE ) + +** Unit test +The new unit test I added for this references the file data/test_shape.shp, this file doesn’t exist. +You can change that name and add a new small test file into + /src/Infrastructure/Mesh/tests/data . +If in the test directory (/src/Infrastructure/Mesh/tests) you do: + $ make RUN_ESMF_MeshFileIOUTestUNI +it will copy the data and run all the tests in the file ESMF_MeshFileIOUTest.F90 The test will be +run and the results will appear in the directory: + /test/*/* +Once you’ve done it once via the makefile you can then run the tests in that directory just by +doing mpirun -np 1 ./ESMF_MeshFileIOUTest + +** Fin +I know that’s a lot of information, so feel free to ask lots of questions. I think once we get things +moving it shouldn’t be hard to bring this capability in, but there might be some back and forth at +the beginning just to get both of us on the same page. + +* Structure & Flow + openfile + get_elementconn_from... + get_nodecount_from... + get_coords_from... + +* Questions: +** What about CRS and projection to/from GEOS? +Will area (spatial extent) be conserved? e.g. if the GIS CRS is curvilinear, is the mapping in ESMF able to handle that? +i.e. is ESMF mapping only planar? +*** Solution: add a transformation routine from->to. e.g. from ESMF planar to GIS curvilear, or vice versa diff --git a/.#gisDev.org b/.#gisDev.org new file mode 120000 index 0000000000..c0e2ed48d9 --- /dev/null +++ b/.#gisDev.org @@ -0,0 +1 @@ +ilcentro@localhost.localdomain.717886:1682835154 \ No newline at end of file diff --git a/gisDev.org b/gisDev.org new file mode 100644 index 0000000000..f96558388d --- /dev/null +++ b/gisDev.org @@ -0,0 +1,75 @@ +#+TODO: TODO IN-PROGRESS ISSUES BETA WAITING DONE + +* From Bob - 3/15/23 +** Basics +I’ve added a new unit test in the file: + /src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +This test is called test_create_mesh_from_SH_file() and all it does is call mesh create from file +with the new flag ESMF_FILEFORMAT_SHAPEFILE this calls down through the layers to the new +subroutine ESMCI_mesh_create_from_SHAPEFILE_file() in the file + /src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +this is a good place to add the high level implementation of the mesh create code. You can see +analogous code in + ESMCI_mesh_create_from_ESMFMesh_file() +in the same file. I also added a place to put the shapefile specific calls in the file + ESMCI_SHAPEFILE_Util.C +in the same directory. I added an example subroutine: + get_example_from_SHAPEFILE_file() +in there, just to make sure that all the compiling works. Feel free to get rid of that. + +** Enviroment + In order for ESMF to be built with the shapefile library I also added the environment variables +to the ESMF build: + ESMF_SHAPEFILE + ESMF_SHAPEFILE_INCLUDE + ESMF_SHAPEFILE_LIBPATH + ESMF_SHAPEFILE_LIBS + +I didn’t know anything about the library for the shapefile stuff so you will need to fill them in: + - ESMF_SHAPEFILE just needs to be defined to something (e.g. ON) + - ESMF_SHAPEFILE_LIBS is the name of the library e.g. -lshapelib ??? + - ESMF_SHAPEFILE_INCLUDE is the path to the shapefile include file + - ESMF_SHAPEFILE_LIBPATH is the path to the shapfile library + +** shplib +I didn’t have the shapefile library built, so this might take a bit of experimenting, but it should +be approximately correct. Making sure it works is probably a good place to start. + Along these lines I didn’t know the name of the include file, so that’ll have to be changed +around line 52 of ESMCI_SHAPEFILE_Util.C and line 40 of + /src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h +(in the place where it says #include replace pio.h with the shapefile one) + +** Where to add new code/modules +If you have more code that you want to add (or that you’ve added already) that you don’t think will +fit in ESMCI_SHAPEFILE_Util.C, then we can add a new directory in + /src/Infrastructure/IO +(e.g. /src/Infrastructure/IO/SHAPEFILE ) + +** Unit test +The new unit test I added for this references the file data/test_shape.shp, this file doesn’t exist. +You can change that name and add a new small test file into + /src/Infrastructure/Mesh/tests/data . +If in the test directory (/src/Infrastructure/Mesh/tests) you do: + $ make RUN_ESMF_MeshFileIOUTestUNI +it will copy the data and run all the tests in the file ESMF_MeshFileIOUTest.F90 The test will be +run and the results will appear in the directory: + /test/*/* +Once you’ve done it once via the makefile you can then run the tests in that directory just by +doing mpirun -np 1 ./ESMF_MeshFileIOUTest + +** Fin +I know that’s a lot of information, so feel free to ask lots of questions. I think once we get things +moving it shouldn’t be hard to bring this capability in, but there might be some back and forth at +the beginning just to get both of us on the same page. + +* Structure & Flow + get_elementconn_from... + get_nodecount_from... + get_coords_from... + + +* Questions: +** What about CRS and projection to/from GEOS? +Will area (spatial extent) be conserved? e.g. if the GIS CRS is curvilinear, is the mapping in ESMF able to handle that? +i.e. is ESMF mapping only planar? +*** Solution: add a transformation routine from->to. e.g. from ESMF planar to GIS curvilear, or vice versa diff --git a/settings.sh b/settings.sh new file mode 100755 index 0000000000..14269417f7 --- /dev/null +++ b/settings.sh @@ -0,0 +1,13 @@ +module load mpi/openmpi-x86_64 +export ESMF_DIR=/home/ilcentro/Work/NASA/ALI/ESMF +export ESMF_COMM=openmpi +export ESMF_PIO=internal +export ESMF_NETCDF=nc-config +export ESMF_NETCDF_INCLUDE=/usr/lib64/gfortran/modules +export ESMF_NETCDFF_INCLUDE=/usr/lib64/gfortran/modules +export ESMF_SHAPEFILE=true +export ESMF_SHAPEFILE_INCLUDE=/usr/include/gdal +#export ESMF_SHAPEFILE_INCLUDE=/usr/include +export ESMF_SHAPEFILE_LIBPATH=/usr/lib64 +#export ESMF_SHAPEFILE_LIBS=-lshp +export ESMF_SHAPEFILE_LIBS=-lgdal diff --git a/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h similarity index 76% rename from src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h rename to src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h index 12bb764392..0a5c6d6bc2 100644 --- a/src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h +++ b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h @@ -37,7 +37,9 @@ #ifdef ESMF_SHAPEFILE // TODO: Change when we know name of shapefile include file -//#include +#include +#include +#include //----------------------------------------------------------------------------- // leave the following line as-is; it will insert the cvs ident string @@ -48,8 +50,19 @@ using namespace ESMCI; -void get_example_from_SHAPEFILE_file(int &example); - +void open_(); +void get_mesh_topo_id_from_SHP_file(); +void get_dim_from_SHP_file(); +void get_elementConn_id_from_SHP_file(); +void get_elementCount_from_SHP_file(); +void get_elementConn_info_from_SHP_file(); +void get_nodeCoord_ids_from_SHP_file(); +void get_nodeCount_from_SHP_file(); +void get_coords_from_SHP_file(); +void get_coordsys_from_SHP_file(); +void get_elemCoord_ids_from_SHP_file(); +void get_mask_from_SHP_file(); +void ESMCI_mesh_create_from_SHP_file(); #endif // ifdef ESMF_SHAPEFILE diff --git a/src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# b/src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# new file mode 100644 index 0000000000..8598493318 --- /dev/null +++ b/src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# @@ -0,0 +1,1129 @@ +// $Id$ +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//============================================================================== + +//============================================================================== +// +// This file contains the Fortran interface code to link F90 and C++. +// +//------------------------------------------------------------------------------ +// INCLUDES +//------------------------------------------------------------------------------ + +#include +#include +#include +#include + +#include "ESMCI_Macros.h" +#include "ESMCI_F90Interface.h" +#include "ESMCI_LogErr.h" +#include "ESMCI_VM.h" +#include "ESMCI_CoordSys.h" +#include "ESMCI_Array.h" +#include "ESMC_Util.h" + +#include "ESMCI_TraceMacros.h" // for profiling + +#include "Mesh/include/ESMCI_Mesh.h" +#include "Mesh/include/Legacy/ESMCI_MeshRead.h" +#include "Mesh/include/Regridding/ESMCI_MeshRegrid.h" //only for the conservative flag in add_elements +#include "Mesh/include/Legacy/ESMCI_MeshVTK.h" +#include "Mesh/include/Legacy/ESMCI_ParEnv.h" +#include "Mesh/include/Legacy/ESMCI_MeshUtils.h" +#include "Mesh/include/Legacy/ESMCI_GlobalIds.h" +#include "Mesh/include/ESMCI_MeshRedist.h" +#include "Mesh/include/ESMCI_MeshDual.h" +#include "Mesh/include/ESMCI_Mesh_Glue.h" +#include "Mesh/include/ESMCI_FileIO_Util.h" + +// These internal functions can only be used if PIO is available +#ifdef ESMF_PIO + +#ifdef ESMF_PNETCDF +# define _PNETCDF +#include +# elif ESMF_NETCDF +# define _NETCDF +# include +#endif + +#include +#include "IO/include/ESMCI_PIO_Handler.h" + +//----------------------------------------------------------------------------- + // leave the following line as-is; it will insert the cvs ident string + // into the object file for tracking purposes. + static const char *const version = "$Id$"; +//----------------------------------------------------------------------------- +using namespace ESMCI; + +// Get the id of mesh topology dummy variable +// TODO: allow the user to specify the name of the mesh topo variable +void get_mesh_topo_id_from_UGRID_file(int pioFileDesc, char *filename, int &mesh_topo_id) { +#undef ESMC_METHOD +#define ESMC_METHOD "get_mesh_topo_id_from_UGRID_file()" + + // Declare some useful vars + int dimid; + int localrc; + int piorc; + + // Get number of variables in the file + int num_vars=0; + piorc = PIOc_inq(pioFileDesc, NULL, &num_vars, NULL, NULL); + if (!CHECKPIOERROR(piorc, std::string("Error reading number of variables from file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + + // Loop over variables to find the first one that looks like mesh topo + mesh_topo_id=-1; + for (int v=0; v= 2); + + // Get information about the units attribute for first variable + PIO_Offset units0_len; + piorc = PIOc_inq_att(pioFileDesc, nodeCoord_ids[0], "units", &type, &units0_len); + if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from first node coordinates varible in file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + + // Debug + //printf("units len=%d\n",len); + + // Get units attribute + char *units0=new char[units0_len+1]; // +1 for NULL terminator (sometimes the len from PIO doesn't seem to include that so adding just in case) + piorc = PIOc_get_att_text(pioFileDesc, nodeCoord_ids[0], "units", units0); + if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from first node coordinates variable in file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + + // Add null terminator + units0[units0_len]='\0'; + + // Debug + //printf("units value=%s\n",units); + + + // Look at units to determine coordinate system + // Using strncmp to only compare chars that match + // the unit name because sometimes the units can + // have garbage on the end. + ESMC_CoordSys_Flag coord_sys0; + if (strncmp(units0,"degrees",7) == 0) { + coord_sys0=ESMC_COORDSYS_SPH_DEG; + } else if (strncmp(units0,"radians",7) == 0) { + coord_sys0=ESMC_COORDSYS_SPH_RAD; + } else if (strncmp(units0,"km",2) == 0) { + coord_sys0=ESMC_COORDSYS_CART; + } else if (strncmp(units0,"kilometers",10) == 0) { + coord_sys0=ESMC_COORDSYS_CART; + } else if (strncmp(units0,"m",1) == 0) { + coord_sys0=ESMC_COORDSYS_CART; + } else if (strncmp(units0,"meters",6) == 0) { + coord_sys0=ESMC_COORDSYS_CART; + } else { + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, + "Unrecognized units for first node coords variable", + ESMC_CONTEXT, &localrc)) throw localrc; + } + + // Get rid of units0 string + delete [] units0; + + // Get information about the units attribute for first variable + PIO_Offset units1_len; + piorc = PIOc_inq_att(pioFileDesc, nodeCoord_ids[1], "units", &type, &units1_len); + if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from second node coordinates varible in file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + + // Debug + //printf("units len=%d\n",len); + + // Get units attribute + char *units1=new char[units1_len+1]; // +1 for NULL terminator (sometimes the len from PIO doesn't seem to include that so adding just in case) + piorc = PIOc_get_att_text(pioFileDesc, nodeCoord_ids[1], "units", units1); + if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from second coordinates variable in file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + + // Add null terminator + units1[units1_len]='\0'; + + // Look at units to determine coordinate system + // Using strncmp to only compare chars that match + // the unit name because sometimes the units can + // have garbage on the end. + ESMC_CoordSys_Flag coord_sys1; + if (strncmp(units1,"degrees",7) == 0) { + coord_sys1=ESMC_COORDSYS_SPH_DEG; + } else if (strncmp(units1,"radians",7) == 0) { + coord_sys1=ESMC_COORDSYS_SPH_RAD; + } else if (strncmp(units1,"km",2) == 0) { + coord_sys1=ESMC_COORDSYS_CART; + } else if (strncmp(units1,"kilometers",10) == 0) { + coord_sys1=ESMC_COORDSYS_CART; + } else if (strncmp(units1,"m",1) == 0) { + coord_sys1=ESMC_COORDSYS_CART; + } else if (strncmp(units1,"meters",6) == 0) { + coord_sys1=ESMC_COORDSYS_CART; + } else { + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, + " unrecognized units for second node coords variable", + ESMC_CONTEXT, &localrc)) throw localrc; + } + + // Get rid of units0 string + delete [] units1; + + + // If first and second coord sys match, then use, otherwise complain. + if (coord_sys0 == coord_sys1) { + coord_sys=coord_sys0; + } else { + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, + "Coordinate system of first and second node coord. variables must be the same.", + ESMC_CONTEXT, &localrc)) throw localrc; + } + + // Do I need to check what the units of the 3rd coordinate are? It doesn't really + // matter as long as it's a height, so why constrain the user unnecessarily? Unless we + // are going to just constrain them to one specific unit, but we are already allowing both + // m and km, so I don't think that we can go down to 1... + +} + + +void get_elemCoord_ids_from_UGRID_file(int pioFileDesc, char *filename, int mesh_topo_id, int dim, int *elemCoord_ids, int ¢erCoordsPresent) { +#undef ESMC_METHOD +#define ESMC_METHOD "get_elemCoord_ids_from_UGRID_file()" + + // Declare some useful vars + int dimid; + int localrc; + int piorc; + nc_type type; + + // Init centerCoordsPresent to 0 (for the case it isn't present) + centerCoordsPresent=0; + + // Get elem coordinate attribute depending on dim + PIO_Offset len_elem_coord_attr; + char *elem_coord_attr; + if (dim == 2) { + + // Get attribute len + piorc = PIOc_inq_att(pioFileDesc, mesh_topo_id, "face_coordinates", &type, &len_elem_coord_attr); + + // If they aren't present, then leave (init. as not present above) + if (piorc != PIO_NOERR) return; + + // Allocate space + elem_coord_attr=new char[len_elem_coord_attr+1]; // +1 for null terminator + + // Get attribute value + piorc = PIOc_get_att_text(pioFileDesc, mesh_topo_id, "face_coordinates", elem_coord_attr); + if (!CHECKPIOERROR(piorc, std::string("Couldn't find face_coordinates attribute on mesh topology var in file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + + } else if (dim == 3) { + // Get attribute len + piorc = PIOc_inq_att(pioFileDesc, mesh_topo_id, "volume_coordinates", &type, &len_elem_coord_attr); + + // If they aren't present, then leave (init. as not present above) + if (piorc != PIO_NOERR) return; + + // Allocate space + elem_coord_attr=new char[len_elem_coord_attr+1]; // +1 for null terminator + + // Get attribute value + piorc = PIOc_get_att_text(pioFileDesc, mesh_topo_id, "volume_coordinates", elem_coord_attr); + if (!CHECKPIOERROR(piorc, std::string("Couldn't find volume_coordinates attribute on mesh topology var in file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + } else { + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, + " Currently only 2 or 3 dimensional meshes are supported.", + ESMC_CONTEXT, &localrc)) throw localrc; + + } + + + // Array of pointers to names + // Make same length as attribute because that will always be greater than the possible number of contained names + char **elem_coord_names=new char*[len_elem_coord_attr+1]; + + // Loop finding names + int num_elem_coord_names=0; + bool prev_is_space=true; // Initial previous is space + for (int i=0; i ESMF_MAXDIM) { + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, + "Mask variable has more dimensions that are supported.", + ESMC_CONTEXT, &localrc)) throw localrc; + } + + // Get dim ids + int dim_ids[ESMF_MAXDIM]; + piorc = PIOc_inq_vardimid(pioFileDesc, mask_id, dim_ids); + if (!CHECKPIOERROR(piorc, std::string("Error finding the dim ids of the mask variable in file ") + filename, + ESMF_RC_FILE_OPEN, localrc)) throw localrc; + + // Get the size of the dimensions + int dim_sizes[ESMF_MAXDIM]; + for (int d=0; d +#include +#include +#include //----------------------------------------------------------------------------- // leave the following line as-is; it will insert the cvs ident string @@ -59,16 +61,98 @@ using namespace ESMCI; -void get_example_from_SHAPEFILE_file(int &example) { +// Get the id of mesh topology dummy variable +// TODO: allow the user to specify the name of the mesh topo variable +void get_mesh_topo_id_from_SHP_file(){ #undef ESMC_METHOD -#define ESMC_METHOD "get_coordDim_from_ESMFMesh_file()" +#define ESMC_METHOD "get_mesh_topo_id_from_SHP_file()" +} + + +// Get the dimension of the mesh in the SHP file +// (This dimension is both the pdim and orig_sdim of the mesh) +void get_dim_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_dim_from_SHP_file()" - // Set example - example=3; - } +// Get the id of the elementConn array +void get_elementConn_id_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_elementConn_id_from_SHP_file()" + +} + + +void get_elementCount_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_elementCount_from_SHP_file()" + +} + + +// Get elementConn info out from a SHP file. +// Note that the output is a 1D array +// (The elem conn info is collapsed to get rid of unnecessary values) +void get_elementConn_info_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_elementConn_info_from_SHP_file()" + +} + + +// Get the ids of the node coordinate variables +// nodeCoord_ids - must at least be of size dim +void get_nodeCoord_ids_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_nodeCoord_ids_from_SHP_file()" + +} + + +void get_nodeCount_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_nodeCount_from_SHP_file()" + +} + + +// Get coords from SHP format file +void get_coords_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_coords_from_SHP_file()" + +} + + + +/* XMRKX */ +void get_coordsys_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "_get_coordsys_from_SHP_file()" + +} + + +void get_elemCoord_ids_from_SHP_file(){ +#undef ESMC_METHOD +#define ESMC_METHOD "get_elemCoord_ids_from_SHP_file()" + +} + + +// Get mask from a variable in a SHP format file +// This was set up to work for either element or node masks. The variable just has +// to have the correct size, and the global count and ids have to be for +// the correct entity (either elems or nodes). +void get_mask_from_SHP_file() { +#undef ESMC_METHOD +#define ESMC_METHOD "get_mask_from_SHP_file()" + +} + #endif // ifdef ESMF_SHAPEFILE diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index 4f7f7d4c98..089187afa7 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -64,6 +64,9 @@ #include "IO/include/ESMCI_PIO_Handler.h" #endif +#ifdef ESMF_SHAPEFILE +#include +#endif //----------------------------------------------------------------------------- // leave the following line as-is; it will insert the cvs ident string // into the object file for tracking purposes. @@ -1306,25 +1309,30 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, // Try-catch block around main part of method try { + // Get VM + ESMCI::VM *vm=VM::getCurrent(&localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // Get VM info + int local_pet = vm->getLocalPet(); + int pet_count = vm->getPetCount(); + + // Bound all of this by local_pet == 0 for now (MSL) + if (local_pet == 0) { // DEBUG OUTPUT filename printf("In shapefile method filename=%s\n",filename); - - // Example just to make sure everything is compiling correctly - int example; - get_example_from_SHAPEFILE_file(example); - if (example == 3) { - printf("Example subroutine is working (example=%d)!\n",example); - } - //// Fill in code getting things from shapefile and creating parts of the Mesh here + // Open file + } // Return an error, because this isn't implemented yet // TODO: GET RID OF THE FOLLOWING LINE WHEN THIS SUBROUTINE IS CREATING A VALID MESH - if (ESMC_LogDefault.MsgFoundError(ESMC_RC_NOT_IMPL, - "Creating a Mesh from a shapefile format file not finished yet.", - ESMC_CONTEXT, &localrc)) throw localrc; + //if (ESMC_LogDefault.MsgFoundError(ESMC_RC_NOT_IMPL, + // "Creating a Mesh from a shapefile format file not finished yet.", + // ESMC_CONTEXT, &localrc)) throw localrc; } catch(std::exception &x) { diff --git a/src/Infrastructure/Mesh/src/makefile b/src/Infrastructure/Mesh/src/makefile index f89a1bfa69..6140893f0d 100644 --- a/src/Infrastructure/Mesh/src/makefile +++ b/src/Infrastructure/Mesh/src/makefile @@ -13,7 +13,7 @@ SOURCEC = \ ESMCI_FileIO_Util.C \ ESMCI_ESMFMesh_Util.C \ ESMCI_UGRID_Util.C \ - ESMCI_SHAPEFILE_Util.C \ + ESMCI_GDAL_Util.C \ ESMCI_Mesh_FileIO.C \ ESMCI_GToM_Util.C \ ESMCI_Mesh_GToM_Glue.C \ diff --git a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C new file mode 100644 index 0000000000..148b044587 --- /dev/null +++ b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C @@ -0,0 +1,537 @@ +//============================================================================== +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//============================================================================== +#ifndef MPICH_IGNORE_CXX_SEEK +#define MPICH_IGNORE_CXX_SEEK +#endif +#include + +// ESMF header +#include "ESMC.h" + +// ESMF Test header +#include "ESMC_Test.h" + +#if defined ESMF_MOAB +#include "ESMCI_MBMesh.h" +#include "ESMCI_MBMesh_Glue.h" +#include "ESMCI_MCTGen.C" +#endif + +#include "ESMCI_MeshCap.h" +#include "ESMCI_Mesh.h" + +#include +#include +#include +#include +#include +#include +#include //find_if +#include + +struct FindPair { + FindPair (std::string first, std::string second) \ + : m_first_value(first), m_second_value(second) {} + + std::string m_first_value; + std::string m_second_value; + bool operator() (const std::pair &p) { + return (p.first == m_first_value && p.second == m_second_value); + } +}; + +void combine(const std::string &api, const std::string &mesh, + const std::string &nativeormb){ + int localrc; + int rc = ESMF_FAILURE; + + std::string failMsg = "FAIL"; + int result = 0; + +#if defined ESMF_MOAB + MCTGen *generate = new MCTGen(); +#endif + + int nvmb = 1; + if (nativeormb == "Native") nvmb = 0; + + int localPet, petCount; + ESMC_VM vm; + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + std::array buffer; + buffer.fill(0); + time_t rawtime; + time(&rawtime); + const auto timeinfo = localtime(&rawtime); + strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); + std::string timeStr(buffer.data()); + + std::string name = timeStr + " - " + "PET " + std::to_string(localPet) + " - " + + nativeormb + " Mesh - " + api + " - " + mesh; + +#if defined ESMF_MOAB + try { + std::shared_ptr test = generate->mesh_map[mesh](localrc); + + test->name = name; + test->nativeormb = nvmb; + // test->verbosity = 3; + // test->tol = 1.e-15; + // test->print(); + + if (localrc == ESMF_SUCCESS) localrc = test->build(); + if (localrc == ESMF_SUCCESS) rc = test->function_map[api](); + + // test is a shared_ptr so no need to delete + // delete test; + } + CATCH_MCT_FAIL(&rc) +#else + rc = ESMF_SUCCESS; +#endif + +#if defined ESMF_MOAB + delete generate; +#endif + + ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), + &result, __FILE__, __LINE__, 0); + +} + +int main(int argc, char *argv[]) { +#undef ESMC_METHOD +#define ESMC_METHOD "MeshCapUTest::main()" + + int rc; + int localPet, petCount; + ESMC_VM vm; + + std::string failMsg = "FAIL"; + // break this up so it doesn't count as an additional test + std::string nex_test_tag = "//NEX_"; + nex_test_tag.append("UTest\n"); + int result = 0; + + //---------------------------------------------------------------------------- + // Start the test with an alternate name for log and stdout files + ESMC_TestStart("ESMCI_MeshCapGenUTest.C", __LINE__, 0); + + //---------------------------------------------------------------------------- + rc=ESMC_LogSet(true); + + // Get parallel information + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + // output stream to write test tag to the generated source file + std::ofstream tagfile; + tagfile.open("ESMCI_MeshCapGenUTest.C", std::ios_base::app); + + // this is an easy way to comment a single line to toggle mbmesh/native + bool mbmesh = false; + mbmesh = true; + bool native = false; + native = true; + + // these are bound to MCT in constructor, must match! + std::vector test_apis; + test_apis.push_back("createget"); + test_apis.push_back("dual"); + test_apis.push_back("redist_elem"); + test_apis.push_back("redist_node"); + test_apis.push_back("redist_elno"); + test_apis.push_back("serialize"); + test_apis.push_back("to_pointlist_elem"); + test_apis.push_back("to_pointlist_node"); + test_apis.push_back("write_vtk"); + + // these are bound to MCTGen in constructor, must match! + std::vector test_meshes_native; + test_meshes_native.push_back("quad_2d_cart"); + test_meshes_native.push_back("quad_2d_sph_deg"); + test_meshes_native.push_back("quad_2d_sph_rad"); + test_meshes_native.push_back("tri_2d_cart"); + test_meshes_native.push_back("tri_2d_sph_deg"); + test_meshes_native.push_back("tri_2d_sph_rad"); + test_meshes_native.push_back("hex_3d_cart"); + test_meshes_native.push_back("hex_3d_sph_deg"); + test_meshes_native.push_back("hex_3d_sph_rad"); + test_meshes_native.push_back("mix_2d_cart"); + test_meshes_native.push_back("mix_2d_sph_deg"); + test_meshes_native.push_back("mix_2d_sph_rad"); + test_meshes_native.push_back("periodic_2d_sph_deg"); + test_meshes_native.push_back("periodic_2d_sph_rad"); + // cannot get info from ngons + // test_meshes_native.push_back("ngon_2d_cart"); + // test_meshes_native.push_back("ngon_2d_sph_deg"); + // test_meshes_native.push_back("ngon_2d_sph_rad"); + + // these are bound to MCTGen in constructor, must match! + std::vector test_meshes_mbmesh; + test_meshes_mbmesh.push_back("quad_2d_cart"); + test_meshes_mbmesh.push_back("quad_2d_sph_deg"); + test_meshes_mbmesh.push_back("quad_2d_sph_rad"); + test_meshes_mbmesh.push_back("tri_2d_cart"); + test_meshes_mbmesh.push_back("tri_2d_sph_deg"); + test_meshes_mbmesh.push_back("tri_2d_sph_rad"); + test_meshes_mbmesh.push_back("hex_3d_cart"); + test_meshes_mbmesh.push_back("hex_3d_sph_deg"); + test_meshes_mbmesh.push_back("hex_3d_sph_rad"); + test_meshes_mbmesh.push_back("mix_2d_cart"); + test_meshes_mbmesh.push_back("mix_2d_sph_deg"); + test_meshes_mbmesh.push_back("mix_2d_sph_rad"); + test_meshes_mbmesh.push_back("ngon_2d_cart"); + test_meshes_mbmesh.push_back("ngon_2d_sph_deg"); + test_meshes_mbmesh.push_back("ngon_2d_sph_rad"); + test_meshes_mbmesh.push_back("periodic_2d_sph_deg"); + test_meshes_mbmesh.push_back("periodic_2d_sph_rad"); + + // skip the following tests + std::vector> skip_test_mbmesh = {\ + // dual not implemented in 3d + {"dual", "hex_3d_cart"}, + {"dual", "hex_3d_sph_deg"}, + {"dual", "hex_3d_sph_rad"}, + // ESMCI_MBMesh_Redist.C, line:2336:Could not find a suitable processor for this element + {"redist_node", "tri_2d_cart"}, + {"redist_node", "tri_2d_sph_deg"}, + {"redist_node", "tri_2d_sph_rad"}, + + }; + + std::vector> skip_test_native = {\ + // dual not implemented in 3d + // Creation of a dual mesh isn't supported for Meshes of parametric dim greater than 3. + {"dual", "hex_3d_cart"}, + {"dual", "hex_3d_sph_deg"}, + {"dual", "hex_3d_sph_rad"}, + }; + + + if (mbmesh) { + for (const auto api: test_apis) { + for (const auto mesh: test_meshes_mbmesh) { + // don't run cases that hang + auto skip_itr = std::find_if(skip_test_mbmesh.begin(), skip_test_mbmesh.end(), + FindPair(api, mesh)); + + if (skip_itr != skip_test_mbmesh.end()) { + continue; + } else { + combine(api, mesh, "MBMesh"); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + + if (native) { + for (const auto api: test_apis) { + for (const auto mesh: test_meshes_native) { + // don't run cases that hang + auto skip_itr = std::find_if(skip_test_native.begin(), skip_test_native.end(), + FindPair(api, mesh)); + + if (skip_itr != skip_test_native.end()) { + continue; + } else { + combine(api, mesh, "Native"); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + + tagfile.close(); + + //---------------------------------------------------------------------------- + ESMC_TestEnd("ESMCI_MeshCapGenUTest.C", __LINE__, 0); + + return 0; +} +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest diff --git a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C new file mode 100644 index 0000000000..52f3cc146c --- /dev/null +++ b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C @@ -0,0 +1,5091 @@ +//============================================================================== +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//============================================================================== +#ifndef MPICH_IGNORE_CXX_SEEK +#define MPICH_IGNORE_CXX_SEEK +#endif +#include + +// ESMF header +#include "ESMC.h" + +// ESMF Test header +#include "ESMC_Test.h" + +#if defined ESMF_MOAB +#include "ESMCI_MBMesh.h" +#include "ESMCI_MBMesh_Glue.h" +#include "ESMCI_MCTGen.C" +#endif + +#include +#include +#include +#include +#include +#include +#include //find_if +#include +#include + +struct FindAnyPair { + FindAnyPair (std::string a, std::string b, std::string c, std::string d, + std::string e, std::string f, std::string g, std::string h) + : a_val(a), b_val(b), c_val(c), d_val(d), + e_val(e), f_val(f), g_val(g), h_val(h) {} + + std::string a_val; + std::string b_val; + std::string c_val; + std::string d_val; + std::string e_val; + std::string f_val; + std::string g_val; + std::string h_val; + bool operator() + ( const std::pair &p ) { + return (((p.first == a_val) || (p.first == b_val) || + (p.first == c_val) || (p.first == d_val) || + (p.first == e_val) || (p.first == f_val) || + (p.first == g_val) || (p.first == h_val)) && + ((p.second == a_val) || (p.second == b_val) || + (p.second == c_val) || (p.second == d_val) || + (p.second == e_val) || (p.second == f_val) || + (p.second == g_val) || (p.second == h_val))); + } +}; + +void combine(const std::string &api, const std::string &mesh, + const std::string &nativeormb, + const std::string &maptype, + const std::string &normtype, + const std::string &poletype, + const std::string &extrapmethod, + const std::string &unmappedaction, + const std::string &ignoredegenerate){ + int localrc; + int rc = ESMF_FAILURE; + + std::string failMsg = "FAIL"; + std::string dash = " - "; + int result = 0; + +#if defined ESMF_MOAB + MCTGen *generate = new MCTGen(); +#endif + + int nvmb = 1; + if (nativeormb == "Native") nvmb = 0; + + int localPet, petCount; + ESMC_VM vm; + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + std::array buffer; + buffer.fill(0); + time_t rawtime; + time(&rawtime); + const auto timeinfo = localtime(&rawtime); + strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); + std::string timeStr(buffer.data()); + + std::string name = timeStr + dash + "PET " + std::to_string(localPet) + dash + + nativeormb + " Mesh - " + api + dash + mesh + + dash + maptype + dash + normtype + dash + poletype + + dash + extrapmethod + dash + unmappedaction + + dash + ignoredegenerate; + +#if defined ESMF_MOAB + try { + std::shared_ptr test = generate->mesh_map[mesh](localrc); + + test->name = name; + test->nativeormb = nvmb; + // test->verbosity = 3; + // test->tol = 1.e-15; + // test->print(); + + // convert parameters to integers + int mt = test->MapType[maptype]; + int nt = test->NormType[normtype]; + int pt = test->PoleType[poletype]; + int em = test->ExtrapMethod[extrapmethod]; + int ua = test->UnmappedAction[unmappedaction]; + int id = test->IgnoreDegenerate[ignoredegenerate]; + + if (localrc == ESMF_SUCCESS) localrc = test->build(); + if (localrc == ESMF_SUCCESS) rc = test->regrid_map[api](mt, nt, pt, + em, ua, id); + + // test is a shared_ptr so no need to delete + // delete test; + } + CATCH_MCT_FAIL(&rc) +#else + rc = ESMF_SUCCESS; +#endif + +#if defined ESMF_MOAB + delete generate; +#endif + + ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), + &result, __FILE__, __LINE__, 0); +} + +int main(int argc, char *argv[]) { +#undef ESMC_METHOD +#define ESMC_METHOD "MBMeshRegidUTest::main()" + + int rc, localrc; + int localPet, petCount; + ESMC_VM vm; + + std::string failMsg = "FAIL"; + // break this up so it doesn't count as an additional test + std::string nex_test_tag = "//NEX_"; + nex_test_tag.append("UTest\n"); + int result = 0; + + //---------------------------------------------------------------------------- + // Start the test with an alternate name for log and stdout files + ESMC_TestStart("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); + + //---------------------------------------------------------------------------- + rc=ESMC_LogSet(true); + + // Get parallel information + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + // output stream to write test tag to the generated source file + std::ofstream tagfile; + tagfile.open("ESMCI_MeshCapRegridGenUTest.C", std::ios_base::app); + + // this is an easy way to comment a single line to toggle mbmesh/native + bool mbmesh = false; + mbmesh = true; + bool native = false; + native = true; + + std::vector test_apis_mbmesh; + test_apis_mbmesh.push_back("bilinear"); + test_apis_mbmesh.push_back("conservative"); + test_apis_mbmesh.push_back("nearest_d2s"); + test_apis_mbmesh.push_back("nearest_s2d"); + // Not yet available with MBMesh + // test_apis_mbmesh.push_back("conservative_2nd"); + // test_apis_mbmesh.push_back("patch"); + + std::vector test_apis_native; + test_apis_native.push_back("bilinear"); + test_apis_native.push_back("conservative"); + test_apis_native.push_back("conservative_2nd"); + test_apis_native.push_back("nearest_d2s"); + test_apis_native.push_back("nearest_s2d"); + test_apis_native.push_back("patch"); + + // these are bound to MCTGen in constructor, must match! + std::vector test_meshes; + test_meshes.push_back("quad_2d_cart"); + test_meshes.push_back("quad_2d_sph_deg"); + test_meshes.push_back("quad_2d_sph_rad"); + test_meshes.push_back("tri_2d_cart"); + test_meshes.push_back("tri_2d_sph_deg"); + test_meshes.push_back("tri_2d_sph_rad"); + test_meshes.push_back("hex_3d_cart"); + test_meshes.push_back("hex_3d_sph_deg"); + test_meshes.push_back("hex_3d_sph_rad"); + test_meshes.push_back("mix_2d_cart"); + test_meshes.push_back("mix_2d_sph_deg"); + test_meshes.push_back("mix_2d_sph_rad"); + test_meshes.push_back("ngon_2d_cart"); + test_meshes.push_back("ngon_2d_sph_deg"); + test_meshes.push_back("ngon_2d_sph_rad"); + test_meshes.push_back("periodic_2d_sph_deg"); + test_meshes.push_back("periodic_2d_sph_rad"); + + // method dependent, and mesh dependent + std::vector test_regrid_maptype; + test_regrid_maptype.push_back("MAP_CARTAPPROX"); + test_regrid_maptype.push_back("MAP_GREATCIRCLE"); + + // only conservative methods, all meshes + std::vector test_regrid_normtype; + test_regrid_normtype.push_back("NORM_DSTAREA"); + test_regrid_normtype.push_back("NORM_FRACAREA"); + + // all methods, but only for periodic grids + std::vector test_regrid_poletype; + test_regrid_poletype.push_back("POLE_NONE"); + test_regrid_poletype.push_back("POLE_ALL"); + test_regrid_poletype.push_back("POLE_NPNT"); + test_regrid_poletype.push_back("POLE_TEETH"); + + // all methods except nn, but only for meshes with destination larger than source + std::vector test_regrid_extrapmethod; + test_regrid_extrapmethod.push_back("EXTRAP_NONE"); + test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_STOD"); + test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_IDAVG"); + test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_D"); + test_regrid_extrapmethod.push_back("EXTRAP_CREEP"); + test_regrid_extrapmethod.push_back("EXTRAP_CREEP_NRST_D"); + + // all methods except nn, but only for meshes with destination larger than source + std::vector test_regrid_unmappedaction; + test_regrid_unmappedaction.push_back("UNMAPPED_THROWERROR"); + test_regrid_unmappedaction.push_back("UNMAPPED_IGNORE"); + + // all methods except nn, but only meshes with degenerate, clockwise or concave elements + std::vector test_regrid_ignoredegenerate; + test_regrid_ignoredegenerate.push_back("DONOT_IGNORE_DEGENERATE"); + test_regrid_ignoredegenerate.push_back("IGNORE_DEGENERATE"); + + + + std::vector> skip_test_mbmesh = {\ + // conservative not supported with ngons + {"conservative", "ngon_2d_cart"}, + {"conservative", "ngon_2d_sph_deg"}, + {"conservative", "ngon_2d_sph_rad"}, + // extrapolation methods not supported (why do EXTRAP_NEAREST_STOD, EXTRAP_NEAREST_IDAVG work?) + {"bilinear", "EXTRAP_NEAREST_D"}, + {"bilinear", "EXTRAP_CREEP"}, + {"bilinear", "EXTRAP_CREEP_NRST_D"}, + {"patch", "EXTRAP_NEAREST_D"}, + {"patch", "EXTRAP_CREEP"}, + {"patch", "EXTRAP_CREEP_NRST_D"}, + }; + + std::vector> skip_test_native = {\ + // meshes with ngons return incorrect element count with native + {"bilinear", "ngon_2d_cart"}, + {"bilinear", "ngon_2d_sph_deg"}, + {"bilinear", "ngon_2d_sph_rad"}, + {"patch", "ngon_2d_cart"}, + {"patch", "ngon_2d_sph_deg"}, + {"patch", "ngon_2d_sph_rad"}, + {"conservative", "ngon_2d_cart"}, + {"conservative", "ngon_2d_sph_deg"}, + {"conservative", "ngon_2d_sph_rad"}, + {"conservative_2nd", "ngon_2d_cart"}, + {"conservative_2nd", "ngon_2d_sph_deg"}, + {"conservative_2nd", "ngon_2d_sph_rad"}, + // Conservative not supported on 3D spherical meshes + {"conservative", "hex_3d_sph_deg"}, + {"conservative", "hex_3d_sph_rad"}, + }; + + std::vector> skip_test_common = {\ + // patch not supported in 3d + {"patch", "hex_3d_cart"}, + {"patch", "hex_3d_sph_deg"}, + {"patch", "hex_3d_sph_rad"}, + // conservative_2nd not supported in 3d + {"conservative_2nd", "hex_3d_cart"}, + {"conservative_2nd", "hex_3d_sph_deg"}, + {"conservative_2nd", "hex_3d_sph_rad"}, + // creep fill extrapolation not supported in 3D + {"hex_3d_cart", "EXTRAP_CREEP"}, + {"hex_3d_sph_deg", "EXTRAP_CREEP"}, + {"hex_3d_sph_rad", "EXTRAP_CREEP"}, + {"hex_3d_cart", "EXTRAP_CREEP_NRST_D"}, + {"hex_3d_sph_deg", "EXTRAP_CREEP_NRST_D"}, + {"hex_3d_sph_rad", "EXTRAP_CREEP_NRST_D"}, + // conservative is not supported with extrapolation + {"conservative", "EXTRAP_NEAREST_STOD"}, + {"conservative", "EXTRAP_NEAREST_IDAVG"}, + {"conservative", "EXTRAP_NEAREST_D"}, + {"conservative", "EXTRAP_CREEP"}, + {"conservative", "EXTRAP_CREEP_NRST_D"}, + {"conservative_2nd", "EXTRAP_NEAREST_STOD"}, + {"conservative_2nd", "EXTRAP_NEAREST_IDAVG"}, + {"conservative_2nd", "EXTRAP_NEAREST_D"}, + {"conservative_2nd", "EXTRAP_CREEP"}, + {"conservative_2nd", "EXTRAP_CREEP_NRST_D"}, + // the following are exceptions due to design, do not represent limitations per se + // conservative only works with great circles + {"conservative", "MAP_CARTAPPROX"}, + {"conservative_2nd", "MAP_CARTAPPROX"}, + // cartesian only works with straight lines + {"quad_2d_cart", "MAP_GREATCIRCLE"}, + {"tri_2d_cart", "MAP_GREATCIRCLE"}, + {"hex_3d_cart", "MAP_GREATCIRCLE"}, + {"mix_2d_cart", "MAP_GREATCIRCLE"}, + {"ngon_2d_cart", "MAP_GREATCIRCLE"}, + // nearest doesn't touch on any of the regrid options, only allow defaults + {"nearest_d2s", "MAP_GREATCIRCLE"}, + {"nearest_d2s", "POLE_ALL"}, + {"nearest_d2s", "POLE_NPNT"}, + {"nearest_d2s", "POLE_TEETH"}, + {"nearest_d2s", "EXTRAP_NEAREST_STOD"}, + {"nearest_d2s", "EXTRAP_NEAREST_IDAVG"}, + {"nearest_d2s", "EXTRAP_NEAREST_D"}, + {"nearest_d2s", "EXTRAP_CREEP"}, + {"nearest_d2s", "EXTRAP_CREEP_NRST_D"}, + {"nearest_d2s", "UNMAPPED_IGNORE"}, + {"nearest_d2s", "IGNORE_DEGENERATE"}, + {"nearest_s2d", "MAP_GREATCIRCLE"}, + {"nearest_s2d", "POLE_ALL"}, + {"nearest_s2d", "POLE_NPNT"}, + {"nearest_s2d", "POLE_TEETH"}, + {"nearest_s2d", "EXTRAP_NEAREST_STOD"}, + {"nearest_s2d", "EXTRAP_NEAREST_IDAVG"}, + {"nearest_s2d", "EXTRAP_NEAREST_D"}, + {"nearest_s2d", "EXTRAP_CREEP"}, + {"nearest_s2d", "EXTRAP_CREEP_NRST_D"}, + {"nearest_s2d", "UNMAPPED_IGNORE"}, + {"nearest_s2d", "IGNORE_DEGENERATE"}, + // only run pole options with periodic meshes + {"quad_2d_cart", "POLE_ALL"}, + {"quad_2d_sph_deg", "POLE_ALL"}, + {"quad_2d_sph_rad", "POLE_ALL"}, + {"tri_2d_cart", "POLE_ALL"}, + {"tri_2d_sph_deg", "POLE_ALL"}, + {"tri_2d_sph_rad", "POLE_ALL"}, + {"hex_3d_cart", "POLE_ALL"}, + {"hex_3d_sph_deg", "POLE_ALL"}, + {"hex_3d_sph_rad", "POLE_ALL"}, + {"mix_2d_cart", "POLE_ALL"}, + {"mix_2d_sph_deg", "POLE_ALL"}, + {"mix_2d_sph_rad", "POLE_ALL"}, + {"ngon_2d_cart", "POLE_ALL"}, + {"ngon_2d_sph_deg", "POLE_ALL"}, + {"ngon_2d_sph_rad", "POLE_ALL"}, + {"quad_2d_cart", "POLE_NPNT"}, + {"quad_2d_sph_deg", "POLE_NPNT"}, + {"quad_2d_sph_rad", "POLE_NPNT"}, + {"tri_2d_cart", "POLE_NPNT"}, + {"tri_2d_sph_deg", "POLE_NPNT"}, + {"tri_2d_sph_rad", "POLE_NPNT"}, + {"hex_3d_cart", "POLE_NPNT"}, + {"hex_3d_sph_deg", "POLE_NPNT"}, + {"hex_3d_sph_rad", "POLE_NPNT"}, + {"mix_2d_cart", "POLE_NPNT"}, + {"mix_2d_sph_deg", "POLE_NPNT"}, + {"mix_2d_sph_rad", "POLE_NPNT"}, + {"ngon_2d_cart", "POLE_NPNT"}, + {"ngon_2d_sph_deg", "POLE_NPNT"}, + {"ngon_2d_sph_rad", "POLE_NPNT"}, + {"quad_2d_cart", "POLE_TEETH"}, + {"quad_2d_sph_deg", "POLE_TEETH"}, + {"quad_2d_sph_rad", "POLE_TEETH"}, + {"tri_2d_cart", "POLE_TEETH"}, + {"tri_2d_sph_deg", "POLE_TEETH"}, + {"tri_2d_sph_rad", "POLE_TEETH"}, + {"hex_3d_cart", "POLE_TEETH"}, + {"hex_3d_sph_deg", "POLE_TEETH"}, + {"hex_3d_sph_rad", "POLE_TEETH"}, + {"mix_2d_cart", "POLE_TEETH"}, + {"mix_2d_sph_deg", "POLE_TEETH"}, + {"mix_2d_sph_rad", "POLE_TEETH"}, + {"ngon_2d_cart", "POLE_TEETH"}, + {"ngon_2d_sph_deg", "POLE_TEETH"}, + {"ngon_2d_sph_rad", "POLE_TEETH"}, + }; + + + if (mbmesh) { + for (const auto api: test_apis_mbmesh) { + for (const auto mesh: test_meshes) { + for (const auto mt: test_regrid_maptype) { + for (const auto nt: test_regrid_normtype) { + for (const auto pt: test_regrid_poletype) { + for (const auto em: test_regrid_extrapmethod) { + for (const auto ua: test_regrid_unmappedaction) { + for (const auto id: test_regrid_ignoredegenerate) { + auto skip_itr_common = std::find_if(skip_test_common.begin(), + skip_test_common.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + auto skip_itr_mbmesh = std::find_if(skip_test_mbmesh.begin(), + skip_test_mbmesh.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + if ((skip_itr_common != skip_test_common.end()) || + (skip_itr_mbmesh != skip_test_mbmesh.end())) { + continue; + } else { + combine(api, mesh, "MBMesh", mt, nt, pt, em, ua, id); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + } + } + } + } + } + } + + if (native) { + for (const auto api: test_apis_native) { + for (const auto mesh: test_meshes) { + for (const auto mt: test_regrid_maptype) { + for (const auto nt: test_regrid_normtype) { + for (const auto pt: test_regrid_poletype) { + for (const auto em: test_regrid_extrapmethod) { + for (const auto ua: test_regrid_unmappedaction) { + for (const auto id: test_regrid_ignoredegenerate) { + auto skip_itr_common = std::find_if(skip_test_common.begin(), + skip_test_common.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + auto skip_itr_native = std::find_if(skip_test_native.begin(), + skip_test_native.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + if ((skip_itr_common != skip_test_common.end()) || + (skip_itr_native != skip_test_native.end())) { + continue; + } else { + combine(api, mesh, "Native", mt, nt, pt, em, ua, id); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + } + } + } + } + } + } + + tagfile.close(); + + //---------------------------------------------------------------------------- + ESMC_TestEnd("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); + + return 0; +} +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest From 2b9b599bb79b092212cac9514d10ec045005f27a Mon Sep 17 00:00:00 2001 From: Michael Long Date: Mon, 5 Jun 2023 09:27:09 -0400 Subject: [PATCH 08/58] OK. Basic GDAL/OGR shapefile open-and-read routine is in place and working in serial (local_pet == 0). MSL --- #gisDev.org# | 75 - build/common.mk | 42 +- makefile | 32 +- settings.sh | 8 +- .../Mesh/include/ESMCI_GDAL_Util.h | 30 +- .../Mesh/src/#ESMCI_UGRID_Util.C# | 1129 ---- .../Mesh/src/.#ESMCI_UGRID_Util.C | 1 - src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C | 275 +- .../Mesh/src/ESMCI_Mesh_FileIO.C | 54 +- .../Mesh/src/ESMCI_UGRID_Util.C | 2 +- .../Mesh/tests/ESMCI_MeshCapGenUTest.C | 537 -- .../Mesh/tests/ESMCI_MeshCapRegridGenUTest.C | 5091 ----------------- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 2 +- .../Mesh/tests/data/test_shape.dbf | Bin 0 -> 132 bytes .../Mesh/tests/data/test_shape.prj | 1 + .../Mesh/tests/data/test_shape.shp | Bin 0 -> 340 bytes .../Mesh/tests/data/test_shape.shx | Bin 0 -> 116 bytes 17 files changed, 295 insertions(+), 6984 deletions(-) delete mode 100644 #gisDev.org# delete mode 100644 src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# delete mode 120000 src/Infrastructure/Mesh/src/.#ESMCI_UGRID_Util.C delete mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C delete mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C create mode 100644 src/Infrastructure/Mesh/tests/data/test_shape.dbf create mode 100644 src/Infrastructure/Mesh/tests/data/test_shape.prj create mode 100644 src/Infrastructure/Mesh/tests/data/test_shape.shp create mode 100644 src/Infrastructure/Mesh/tests/data/test_shape.shx diff --git a/#gisDev.org# b/#gisDev.org# deleted file mode 100644 index a7a0fb619e..0000000000 --- a/#gisDev.org# +++ /dev/null @@ -1,75 +0,0 @@ -#+TODO: TODO IN-PROGRESS ISSUES BETA WAITING DONE - -* From Bob - 3/15/23 -** Basics -I’ve added a new unit test in the file: - /src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 -This test is called test_create_mesh_from_SH_file() and all it does is call mesh create from file -with the new flag ESMF_FILEFORMAT_SHAPEFILE this calls down through the layers to the new -subroutine ESMCI_mesh_create_from_SHAPEFILE_file() in the file - /src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C -this is a good place to add the high level implementation of the mesh create code. You can see -analogous code in - ESMCI_mesh_create_from_ESMFMesh_file() -in the same file. I also added a place to put the shapefile specific calls in the file - ESMCI_SHAPEFILE_Util.C -in the same directory. I added an example subroutine: - get_example_from_SHAPEFILE_file() -in there, just to make sure that all the compiling works. Feel free to get rid of that. - -** Enviroment - In order for ESMF to be built with the shapefile library I also added the environment variables -to the ESMF build: - ESMF_SHAPEFILE - ESMF_SHAPEFILE_INCLUDE - ESMF_SHAPEFILE_LIBPATH - ESMF_SHAPEFILE_LIBS - -I didn’t know anything about the library for the shapefile stuff so you will need to fill them in: - - ESMF_SHAPEFILE just needs to be defined to something (e.g. ON) - - ESMF_SHAPEFILE_LIBS is the name of the library e.g. -lshapelib ??? - - ESMF_SHAPEFILE_INCLUDE is the path to the shapefile include file - - ESMF_SHAPEFILE_LIBPATH is the path to the shapfile library - -** shplib -I didn’t have the shapefile library built, so this might take a bit of experimenting, but it should -be approximately correct. Making sure it works is probably a good place to start. - Along these lines I didn’t know the name of the include file, so that’ll have to be changed -around line 52 of ESMCI_SHAPEFILE_Util.C and line 40 of - /src/Infrastructure/Mesh/include/ESMCI_SHAPEFILE_Util.h -(in the place where it says #include replace pio.h with the shapefile one) - -** Where to add new code/modules -If you have more code that you want to add (or that you’ve added already) that you don’t think will -fit in ESMCI_SHAPEFILE_Util.C, then we can add a new directory in - /src/Infrastructure/IO -(e.g. /src/Infrastructure/IO/SHAPEFILE ) - -** Unit test -The new unit test I added for this references the file data/test_shape.shp, this file doesn’t exist. -You can change that name and add a new small test file into - /src/Infrastructure/Mesh/tests/data . -If in the test directory (/src/Infrastructure/Mesh/tests) you do: - $ make RUN_ESMF_MeshFileIOUTestUNI -it will copy the data and run all the tests in the file ESMF_MeshFileIOUTest.F90 The test will be -run and the results will appear in the directory: - /test/*/* -Once you’ve done it once via the makefile you can then run the tests in that directory just by -doing mpirun -np 1 ./ESMF_MeshFileIOUTest - -** Fin -I know that’s a lot of information, so feel free to ask lots of questions. I think once we get things -moving it shouldn’t be hard to bring this capability in, but there might be some back and forth at -the beginning just to get both of us on the same page. - -* Structure & Flow - openfile - get_elementconn_from... - get_nodecount_from... - get_coords_from... - -* Questions: -** What about CRS and projection to/from GEOS? -Will area (spatial extent) be conserved? e.g. if the GIS CRS is curvilinear, is the mapping in ESMF able to handle that? -i.e. is ESMF mapping only planar? -*** Solution: add a transformation routine from->to. e.g. from ESMF planar to GIS curvilear, or vice versa diff --git a/build/common.mk b/build/common.mk index 2c6b4aa6f8..456b925cde 100644 --- a/build/common.mk +++ b/build/common.mk @@ -1613,33 +1613,33 @@ endif endif #------------------------------------------------------------------------------- -# SHAPEFILE C++ API +# GDAL C++ API #------------------------------------------------------------------------------- -ifeq ($(ESMF_SHAPEFILE),standard) -ifneq ($(origin ESMF_SHAPEFILE_LIBS), environment) -# BOB: LEAVE BLANK UNTIL I KNOW NAME OF SHAPEFILE LIB -#ESMF_SHAPEFILE_LIBS = -lxerces-c -ESMF_SHAPEFILE_LIBS = +ifeq ($(ESMF_GDAL),standard) +ifneq ($(origin ESMF_GDAL_LIBS), environment) +# BOB: LEAVE BLANK UNTIL I KNOW NAME OF GDAL LIB +#ESMF_GDAL_LIBS = -lxerces-c +ESMF_GDAL_LIBS = endif endif -ifdef ESMF_SHAPEFILE -ESMF_CPPFLAGS += -DESMF_SHAPEFILE=1 -ifdef ESMF_SHAPEFILE_INCLUDE -ESMF_CXXCOMPILEPATHSTHIRD += -I$(ESMF_SHAPEFILE_INCLUDE) -ESMF_F90COMPILEPATHSTHIRD += -I$(ESMF_SHAPEFILE_INCLUDE) +ifdef ESMF_GDAL +ESMF_CPPFLAGS += -DESMF_GDAL=1 +ifdef ESMF_GDAL_INCLUDE +ESMF_CXXCOMPILEPATHSTHIRD += -I$(ESMF_GDAL_INCLUDE) +ESMF_F90COMPILEPATHSTHIRD += -I$(ESMF_GDAL_INCLUDE) endif -ifdef ESMF_SHAPEFILE_LIBS -ESMF_CXXLINKLIBS += $(ESMF_SHAPEFILE_LIBS) -ESMF_CXXLINKRPATHSTHIRD += $(addprefix $(ESMF_CXXRPATHPREFIX),$(subst -L,,$(filter -L%,$(ESMF_SHAPEFILE_LIBS)))) -ESMF_F90LINKLIBS += $(ESMF_SHAPEFILE_LIBS) -ESMF_F90LINKRPATHSTHIRD += $(addprefix $(ESMF_F90RPATHPREFIX),$(subst -L,,$(filter -L%,$(ESMF_SHAPEFILE_LIBS)))) +ifdef ESMF_GDAL_LIBS +ESMF_CXXLINKLIBS += $(ESMF_GDAL_LIBS) +ESMF_CXXLINKRPATHSTHIRD += $(addprefix $(ESMF_CXXRPATHPREFIX),$(subst -L,,$(filter -L%,$(ESMF_GDAL_LIBS)))) +ESMF_F90LINKLIBS += $(ESMF_GDAL_LIBS) +ESMF_F90LINKRPATHSTHIRD += $(addprefix $(ESMF_F90RPATHPREFIX),$(subst -L,,$(filter -L%,$(ESMF_GDAL_LIBS)))) endif -ifdef ESMF_SHAPEFILE_LIBPATH -ESMF_CXXLINKPATHSTHIRD += -L$(ESMF_SHAPEFILE_LIBPATH) -ESMF_F90LINKPATHSTHIRD += -L$(ESMF_SHAPEFILE_LIBPATH) -ESMF_CXXLINKRPATHSTHIRD += $(ESMF_CXXRPATHPREFIX)$(ESMF_SHAPEFILE_LIBPATH) -ESMF_F90LINKRPATHSTHIRD += $(ESMF_F90RPATHPREFIX)$(ESMF_SHAPEFILE_LIBPATH) +ifdef ESMF_GDAL_LIBPATH +ESMF_CXXLINKPATHSTHIRD += -L$(ESMF_GDAL_LIBPATH) +ESMF_F90LINKPATHSTHIRD += -L$(ESMF_GDAL_LIBPATH) +ESMF_CXXLINKRPATHSTHIRD += $(ESMF_CXXRPATHPREFIX)$(ESMF_GDAL_LIBPATH) +ESMF_F90LINKRPATHSTHIRD += $(ESMF_F90RPATHPREFIX)$(ESMF_GDAL_LIBPATH) endif endif diff --git a/makefile b/makefile index b908d307f8..ebb4635925 100644 --- a/makefile +++ b/makefile @@ -254,16 +254,16 @@ endif echo "ESMF_PIO_LIBPATH: $(ESMF_PIO_LIBPATH)" ; \ fi; \ fi - -@if [ -n "$(ESMF_SHAPEFILE)" ] ; then \ - echo "ESMF_SHAPEFILE: $(ESMF_SHAPEFILE)" ; \ - if [ -n "$(ESMF_SHAPEFILE_INCLUDE)" ] ; then \ - echo "ESMF_SHAPEFILE_INCLUDE: $(ESMF_SHAPEFILE_INCLUDE)" ; \ + -@if [ -n "$(ESMF_GDAL)" ] ; then \ + echo "ESMF_GDAL: $(ESMF_GDAL)" ; \ + if [ -n "$(ESMF_GDAL_INCLUDE)" ] ; then \ + echo "ESMF_GDAL_INCLUDE: $(ESMF_GDAL_INCLUDE)" ; \ fi; \ - if [ -n "$(ESMF_SHAPEFILE_LIBS)" ] ; then \ - echo "ESMF_SHAPEFILE_LIBS: $(ESMF_SHAPEFILE_LIBS)" ; \ + if [ -n "$(ESMF_GDAL_LIBS)" ] ; then \ + echo "ESMF_GDAL_LIBS: $(ESMF_GDAL_LIBS)" ; \ fi; \ - if [ -n "$(ESMF_SHAPEFILE_LIBPATH)" ] ; then \ - echo "ESMF_SHAPEFILE_LIBPATH: $(ESMF_SHAPEFILE_LIBPATH)" ; \ + if [ -n "$(ESMF_GDAL_LIBPATH)" ] ; then \ + echo "ESMF_GDAL_LIBPATH: $(ESMF_GDAL_LIBPATH)" ; \ fi; \ fi -@if [ -n "$(ESMF_XERCES)" ] ; then \ @@ -651,16 +651,16 @@ endif echo "# ESMF_PIO_LIBPATH: $(ESMF_PIO_LIBPATH)" >> $(MKINFO) ; \ fi; \ fi - -@if [ -n "$(ESMF_SHAPEFILE)" ] ; then \ - echo "# ESMF_SHAPEFILE: $(ESMF_SHAPEFILE)" >> $(MKINFO) ; \ - if [ -n "$(ESMF_SHAPEFILE_INCLUDE)" ] ; then \ - echo "# ESMF_SHAPEFILE_INCLUDE: $(ESMF_SHAPEFILE_INCLUDE)" >> $(MKINFO) ; \ + -@if [ -n "$(ESMF_GDAL)" ] ; then \ + echo "# ESMF_GDAL: $(ESMF_GDAL)" >> $(MKINFO) ; \ + if [ -n "$(ESMF_GDAL_INCLUDE)" ] ; then \ + echo "# ESMF_GDAL_INCLUDE: $(ESMF_GDAL_INCLUDE)" >> $(MKINFO) ; \ fi; \ - if [ -n "$(ESMF_SHAPEFILE_LIBS)" ] ; then \ - echo "# ESMF_SHAPEFILE_LIBS: $(ESMF_SHAPEFILE_LIBS)" >> $(MKINFO) ; \ + if [ -n "$(ESMF_GDAL_LIBS)" ] ; then \ + echo "# ESMF_GDAL_LIBS: $(ESMF_GDAL_LIBS)" >> $(MKINFO) ; \ fi; \ - if [ -n "$(ESMF_SHAPEFILE_LIBPATH)" ] ; then \ - echo "# ESMF_SHAPEFILE_LIBPATH: $(ESMF_SHAPEFILE_LIBPATH)" >> $(MKINFO) ; \ + if [ -n "$(ESMF_GDAL_LIBPATH)" ] ; then \ + echo "# ESMF_GDAL_LIBPATH: $(ESMF_GDAL_LIBPATH)" >> $(MKINFO) ; \ fi; \ fi -@if [ -n "$(ESMF_XERCES)" ] ; then \ diff --git a/settings.sh b/settings.sh index 14269417f7..4af79aa5de 100755 --- a/settings.sh +++ b/settings.sh @@ -5,9 +5,9 @@ export ESMF_PIO=internal export ESMF_NETCDF=nc-config export ESMF_NETCDF_INCLUDE=/usr/lib64/gfortran/modules export ESMF_NETCDFF_INCLUDE=/usr/lib64/gfortran/modules -export ESMF_SHAPEFILE=true -export ESMF_SHAPEFILE_INCLUDE=/usr/include/gdal +export ESMF_GDAL=true +export ESMF_GDAL_INCLUDE=/usr/include/gdal #export ESMF_SHAPEFILE_INCLUDE=/usr/include -export ESMF_SHAPEFILE_LIBPATH=/usr/lib64 +export ESMF_GDAL_LIBPATH=/usr/lib64 #export ESMF_SHAPEFILE_LIBS=-lshp -export ESMF_SHAPEFILE_LIBS=-lgdal +export ESMF_GDAL_LIBS=-lgdal diff --git a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h index 0a5c6d6bc2..0ea83e6674 100644 --- a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h +++ b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h @@ -18,8 +18,8 @@ // INCLUDES //------------------------------------------------------------------------------ -#ifndef ESMCI_SHAPEFILE_UTIL_H -#define ESMCI_SHAPEFILE_UTIL_H +#ifndef ESMCI_GDAL_UTIL_H +#define ESMCI_GDAL_UTIL_H #include #include @@ -33,10 +33,8 @@ #include "ESMCI_Array.h" #include "ESMCI_DistGrid.h" -// These internal functions can only be used if SHAPEFILE is available -#ifdef ESMF_SHAPEFILE - -// TODO: Change when we know name of shapefile include file +// These internal functions can only be used if GDAL is available +#ifdef ESMF_GDAL #include #include #include @@ -50,20 +48,14 @@ using namespace ESMCI; +// general routines void open_(); -void get_mesh_topo_id_from_SHP_file(); -void get_dim_from_SHP_file(); -void get_elementConn_id_from_SHP_file(); -void get_elementCount_from_SHP_file(); -void get_elementConn_info_from_SHP_file(); -void get_nodeCoord_ids_from_SHP_file(); -void get_nodeCount_from_SHP_file(); -void get_coords_from_SHP_file(); -void get_coordsys_from_SHP_file(); -void get_elemCoord_ids_from_SHP_file(); -void get_mask_from_SHP_file(); + +// shapefile routines +void get_dim_from_SHP_file(OGRDataSourceH hDS, char *filename, int &dim); +void process_shapefile(OGRDataSourceH hDS); void ESMCI_mesh_create_from_SHP_file(); -#endif // ifdef ESMF_SHAPEFILE +#endif // ifdef ESMF_GDAL -#endif // ESMCI_SHAPEFILE_UTIL_H +#endif // ESMCI_GDAL_UTIL_H diff --git a/src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# b/src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# deleted file mode 100644 index 8598493318..0000000000 --- a/src/Infrastructure/Mesh/src/#ESMCI_UGRID_Util.C# +++ /dev/null @@ -1,1129 +0,0 @@ -// $Id$ -// -// Earth System Modeling Framework -// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, -// Massachusetts Institute of Technology, Geophysical Fluid Dynamics -// Laboratory, University of Michigan, National Centers for Environmental -// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, -// NASA Goddard Space Flight Center. -// Licensed under the University of Illinois-NCSA License. -// -//============================================================================== - -//============================================================================== -// -// This file contains the Fortran interface code to link F90 and C++. -// -//------------------------------------------------------------------------------ -// INCLUDES -//------------------------------------------------------------------------------ - -#include -#include -#include -#include - -#include "ESMCI_Macros.h" -#include "ESMCI_F90Interface.h" -#include "ESMCI_LogErr.h" -#include "ESMCI_VM.h" -#include "ESMCI_CoordSys.h" -#include "ESMCI_Array.h" -#include "ESMC_Util.h" - -#include "ESMCI_TraceMacros.h" // for profiling - -#include "Mesh/include/ESMCI_Mesh.h" -#include "Mesh/include/Legacy/ESMCI_MeshRead.h" -#include "Mesh/include/Regridding/ESMCI_MeshRegrid.h" //only for the conservative flag in add_elements -#include "Mesh/include/Legacy/ESMCI_MeshVTK.h" -#include "Mesh/include/Legacy/ESMCI_ParEnv.h" -#include "Mesh/include/Legacy/ESMCI_MeshUtils.h" -#include "Mesh/include/Legacy/ESMCI_GlobalIds.h" -#include "Mesh/include/ESMCI_MeshRedist.h" -#include "Mesh/include/ESMCI_MeshDual.h" -#include "Mesh/include/ESMCI_Mesh_Glue.h" -#include "Mesh/include/ESMCI_FileIO_Util.h" - -// These internal functions can only be used if PIO is available -#ifdef ESMF_PIO - -#ifdef ESMF_PNETCDF -# define _PNETCDF -#include -# elif ESMF_NETCDF -# define _NETCDF -# include -#endif - -#include -#include "IO/include/ESMCI_PIO_Handler.h" - -//----------------------------------------------------------------------------- - // leave the following line as-is; it will insert the cvs ident string - // into the object file for tracking purposes. - static const char *const version = "$Id$"; -//----------------------------------------------------------------------------- -using namespace ESMCI; - -// Get the id of mesh topology dummy variable -// TODO: allow the user to specify the name of the mesh topo variable -void get_mesh_topo_id_from_UGRID_file(int pioFileDesc, char *filename, int &mesh_topo_id) { -#undef ESMC_METHOD -#define ESMC_METHOD "get_mesh_topo_id_from_UGRID_file()" - - // Declare some useful vars - int dimid; - int localrc; - int piorc; - - // Get number of variables in the file - int num_vars=0; - piorc = PIOc_inq(pioFileDesc, NULL, &num_vars, NULL, NULL); - if (!CHECKPIOERROR(piorc, std::string("Error reading number of variables from file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - // Loop over variables to find the first one that looks like mesh topo - mesh_topo_id=-1; - for (int v=0; v= 2); - - // Get information about the units attribute for first variable - PIO_Offset units0_len; - piorc = PIOc_inq_att(pioFileDesc, nodeCoord_ids[0], "units", &type, &units0_len); - if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from first node coordinates varible in file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - // Debug - //printf("units len=%d\n",len); - - // Get units attribute - char *units0=new char[units0_len+1]; // +1 for NULL terminator (sometimes the len from PIO doesn't seem to include that so adding just in case) - piorc = PIOc_get_att_text(pioFileDesc, nodeCoord_ids[0], "units", units0); - if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from first node coordinates variable in file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - // Add null terminator - units0[units0_len]='\0'; - - // Debug - //printf("units value=%s\n",units); - - - // Look at units to determine coordinate system - // Using strncmp to only compare chars that match - // the unit name because sometimes the units can - // have garbage on the end. - ESMC_CoordSys_Flag coord_sys0; - if (strncmp(units0,"degrees",7) == 0) { - coord_sys0=ESMC_COORDSYS_SPH_DEG; - } else if (strncmp(units0,"radians",7) == 0) { - coord_sys0=ESMC_COORDSYS_SPH_RAD; - } else if (strncmp(units0,"km",2) == 0) { - coord_sys0=ESMC_COORDSYS_CART; - } else if (strncmp(units0,"kilometers",10) == 0) { - coord_sys0=ESMC_COORDSYS_CART; - } else if (strncmp(units0,"m",1) == 0) { - coord_sys0=ESMC_COORDSYS_CART; - } else if (strncmp(units0,"meters",6) == 0) { - coord_sys0=ESMC_COORDSYS_CART; - } else { - if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, - "Unrecognized units for first node coords variable", - ESMC_CONTEXT, &localrc)) throw localrc; - } - - // Get rid of units0 string - delete [] units0; - - // Get information about the units attribute for first variable - PIO_Offset units1_len; - piorc = PIOc_inq_att(pioFileDesc, nodeCoord_ids[1], "units", &type, &units1_len); - if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from second node coordinates varible in file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - // Debug - //printf("units len=%d\n",len); - - // Get units attribute - char *units1=new char[units1_len+1]; // +1 for NULL terminator (sometimes the len from PIO doesn't seem to include that so adding just in case) - piorc = PIOc_get_att_text(pioFileDesc, nodeCoord_ids[1], "units", units1); - if (!CHECKPIOERROR(piorc, std::string("Error with getting units attribute from second coordinates variable in file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - // Add null terminator - units1[units1_len]='\0'; - - // Look at units to determine coordinate system - // Using strncmp to only compare chars that match - // the unit name because sometimes the units can - // have garbage on the end. - ESMC_CoordSys_Flag coord_sys1; - if (strncmp(units1,"degrees",7) == 0) { - coord_sys1=ESMC_COORDSYS_SPH_DEG; - } else if (strncmp(units1,"radians",7) == 0) { - coord_sys1=ESMC_COORDSYS_SPH_RAD; - } else if (strncmp(units1,"km",2) == 0) { - coord_sys1=ESMC_COORDSYS_CART; - } else if (strncmp(units1,"kilometers",10) == 0) { - coord_sys1=ESMC_COORDSYS_CART; - } else if (strncmp(units1,"m",1) == 0) { - coord_sys1=ESMC_COORDSYS_CART; - } else if (strncmp(units1,"meters",6) == 0) { - coord_sys1=ESMC_COORDSYS_CART; - } else { - if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, - " unrecognized units for second node coords variable", - ESMC_CONTEXT, &localrc)) throw localrc; - } - - // Get rid of units0 string - delete [] units1; - - - // If first and second coord sys match, then use, otherwise complain. - if (coord_sys0 == coord_sys1) { - coord_sys=coord_sys0; - } else { - if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, - "Coordinate system of first and second node coord. variables must be the same.", - ESMC_CONTEXT, &localrc)) throw localrc; - } - - // Do I need to check what the units of the 3rd coordinate are? It doesn't really - // matter as long as it's a height, so why constrain the user unnecessarily? Unless we - // are going to just constrain them to one specific unit, but we are already allowing both - // m and km, so I don't think that we can go down to 1... - -} - - -void get_elemCoord_ids_from_UGRID_file(int pioFileDesc, char *filename, int mesh_topo_id, int dim, int *elemCoord_ids, int ¢erCoordsPresent) { -#undef ESMC_METHOD -#define ESMC_METHOD "get_elemCoord_ids_from_UGRID_file()" - - // Declare some useful vars - int dimid; - int localrc; - int piorc; - nc_type type; - - // Init centerCoordsPresent to 0 (for the case it isn't present) - centerCoordsPresent=0; - - // Get elem coordinate attribute depending on dim - PIO_Offset len_elem_coord_attr; - char *elem_coord_attr; - if (dim == 2) { - - // Get attribute len - piorc = PIOc_inq_att(pioFileDesc, mesh_topo_id, "face_coordinates", &type, &len_elem_coord_attr); - - // If they aren't present, then leave (init. as not present above) - if (piorc != PIO_NOERR) return; - - // Allocate space - elem_coord_attr=new char[len_elem_coord_attr+1]; // +1 for null terminator - - // Get attribute value - piorc = PIOc_get_att_text(pioFileDesc, mesh_topo_id, "face_coordinates", elem_coord_attr); - if (!CHECKPIOERROR(piorc, std::string("Couldn't find face_coordinates attribute on mesh topology var in file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - } else if (dim == 3) { - // Get attribute len - piorc = PIOc_inq_att(pioFileDesc, mesh_topo_id, "volume_coordinates", &type, &len_elem_coord_attr); - - // If they aren't present, then leave (init. as not present above) - if (piorc != PIO_NOERR) return; - - // Allocate space - elem_coord_attr=new char[len_elem_coord_attr+1]; // +1 for null terminator - - // Get attribute value - piorc = PIOc_get_att_text(pioFileDesc, mesh_topo_id, "volume_coordinates", elem_coord_attr); - if (!CHECKPIOERROR(piorc, std::string("Couldn't find volume_coordinates attribute on mesh topology var in file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - } else { - if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, - " Currently only 2 or 3 dimensional meshes are supported.", - ESMC_CONTEXT, &localrc)) throw localrc; - - } - - - // Array of pointers to names - // Make same length as attribute because that will always be greater than the possible number of contained names - char **elem_coord_names=new char*[len_elem_coord_attr+1]; - - // Loop finding names - int num_elem_coord_names=0; - bool prev_is_space=true; // Initial previous is space - for (int i=0; i ESMF_MAXDIM) { - if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, - "Mask variable has more dimensions that are supported.", - ESMC_CONTEXT, &localrc)) throw localrc; - } - - // Get dim ids - int dim_ids[ESMF_MAXDIM]; - piorc = PIOc_inq_vardimid(pioFileDesc, mask_id, dim_ids); - if (!CHECKPIOERROR(piorc, std::string("Error finding the dim ids of the mask variable in file ") + filename, - ESMF_RC_FILE_OPEN, localrc)) throw localrc; - - // Get the size of the dimensions - int dim_sizes[ESMF_MAXDIM]; - for (int d=0; d @@ -60,99 +60,216 @@ //----------------------------------------------------------------------------- using namespace ESMCI; +int i; -// Get the id of mesh topology dummy variable -// TODO: allow the user to specify the name of the mesh topo variable -void get_mesh_topo_id_from_SHP_file(){ -#undef ESMC_METHOD -#define ESMC_METHOD "get_mesh_topo_id_from_SHP_file()" +int ftr = 0; +int totpoints = 0; -} +int numNodes, numElems; +int *nodeIDs; +int *elemConn,*numElemConn; +//double *nodeXCoords,*nodeYCoords; +// Routines +int processPolygon(OGRGeometryH fGeom, int runtyp, double *nodeXCoords, double *nodeYCoords); +int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords); // Get the dimension of the mesh in the SHP file // (This dimension is both the pdim and orig_sdim of the mesh) -void get_dim_from_SHP_file(){ +void get_dim_from_SHP_file(OGRDataSourceH hDS, char *filename, int &dim) { #undef ESMC_METHOD #define ESMC_METHOD "get_dim_from_SHP_file()" -} - - -// Get the id of the elementConn array -void get_elementConn_id_from_SHP_file(){ -#undef ESMC_METHOD -#define ESMC_METHOD "get_elementConn_id_from_SHP_file()" - -} - - -void get_elementCount_from_SHP_file(){ -#undef ESMC_METHOD -#define ESMC_METHOD "get_elementCount_from_SHP_file()" - -} - - -// Get elementConn info out from a SHP file. -// Note that the output is a 1D array -// (The elem conn info is collapsed to get rid of unnecessary values) -void get_elementConn_info_from_SHP_file(){ -#undef ESMC_METHOD -#define ESMC_METHOD "get_elementConn_info_from_SHP_file()" - -} - - -// Get the ids of the node coordinate variables -// nodeCoord_ids - must at least be of size dim -void get_nodeCoord_ids_from_SHP_file(){ -#undef ESMC_METHOD -#define ESMC_METHOD "get_nodeCoord_ids_from_SHP_file()" - -} - - -void get_nodeCount_from_SHP_file(){ -#undef ESMC_METHOD -#define ESMC_METHOD "get_nodeCount_from_SHP_file()" + // value fixed for now. Just assume horizontal dims. + // Geometries will be 'flattened' if they are 3D. + // -- MSL 5/31/2023 + dim = 2; + return; } - -// Get coords from SHP format file -void get_coords_from_SHP_file(){ -#undef ESMC_METHOD -#define ESMC_METHOD "get_coords_from_SHP_file()" - +void process_shapefile(OGRDataSourceH hDS) { + int nElements; + double *nodeXCoords,*nodeYCoords; + +// OGRRegisterAll(); // register all the drivers + +// OGRDataSourceH hDS; + OGRLayerH hLayer; + OGRFeatureH hFeature; + + char filename[200]; + + // Step 1 + + // Access the layer (associate the handle) + // Assume that index 0 is the layer we want. + hLayer = OGR_DS_GetLayer( hDS, 0 ); + + // Get the number of elements + nElements = OGR_L_GetFeatureCount(hLayer,1); + + printf("Number of shapefile elements: %d\n\n",nElements); + + // Step 2: + + // Rewind to the beginning, just in case + OGR_L_ResetReading(hLayer); + + // Loop through features in layer and establish extents for allocation + while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) { + OGRGeometryH hGeom,fGeom; + + // Get geometry handles + hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon + fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring + + printf("Feature %d geom: %d (Polygon is %d)\n",ftr+1,wkbFlatten(OGR_G_GetGeometryType(hGeom)),wkbPolygon); + + // ADD POLYGON + if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { + processPolygon(fGeom,0, NULL, NULL); + } + // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS + else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ + processMultiPolygon(hGeom,0, NULL, NULL); + } + + // Cleanup + OGR_F_Destroy( hFeature ); + } + + // Step 3: + // Allocate vars + // -- numNodes - there are as many connections as nodes + numNodes = totpoints; // At this point, un-trimmed. Points will repeat + // -- numElems + numElems = ftr; // This is an assumption! + // -- nodeIDs + nodeIDs = (int *)malloc(numNodes*sizeof(int)); + // -- node[X,Y]Coords + nodeXCoords = (double *)malloc(numNodes*sizeof(double)); + nodeYCoords = (double *)malloc(numNodes*sizeof(double)); + // -- elemConn +// elemConn = (int *)malloc(numNodes*sizeof(int)); <- nodeIDs is already this, right? + // -- numElemConn + numElemConn = (int *)malloc(numElems*sizeof(int)); + + // Reset counters + ftr = 0; // Zero features + totpoints = 0; // Zero number of points + + // Rewind to the beginning, just in case + OGR_L_ResetReading(hLayer); + + // Loop through features in layer and establish extents for allocation + while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) { + OGRGeometryH hGeom,fGeom; + + // Get geometry handles + hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon + fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring + + // ADD POLYGON + if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { + processPolygon(fGeom,1, nodeXCoords, nodeYCoords); + } + // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS + else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ + processMultiPolygon(hGeom,1, nodeXCoords, nodeYCoords); + } + + // Cleanup + OGR_F_Destroy( hFeature ); + } + + printf("\n"); + printf("N Features: %d\n",ftr); + printf("N Points: %d\n",totpoints); + + // Dump vals + printf("Coords: \n"); + for (i=0;i #endif //----------------------------------------------------------------------------- @@ -1299,13 +1299,12 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, *out_mesh=NULL; // Will only work if SHAPEFILE is available -#ifdef ESMF_SHAPEFILE +#ifdef ESMF_GDAL // Declare some handy variables int localrc; int rc; - // Try-catch block around main part of method try { @@ -1320,14 +1319,49 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, // Bound all of this by local_pet == 0 for now (MSL) if (local_pet == 0) { - // DEBUG OUTPUT filename - printf("In shapefile method filename=%s\n",filename); + // DEBUG OUTPUT filename + printf("In shapefile method filename=%s\n",filename); - //// Fill in code getting things from shapefile and creating parts of the Mesh here + //// Fill in code getting things from shapefile and creating parts of the Mesh here - // Open file + // Open file + OGRDataSourceH hDS; + if (access(filename, F_OK) == 0) { + OGRRegisterAll(); // register all the drivers + hDS = OGROpen( filename, FALSE, NULL ); + if( hDS == NULL ) + { + printf( "Open failed: %s, %d\n", CPLGetLastErrorMsg(), CPLGetLastErrorNo() ); + Throw(); + } + } else { + printf("Cannot access shapefile\n"); + Throw(); + } + + // Get DIM var + int dim; + get_dim_from_SHP_file(hDS, filename, dim); + + // Get shapefile params + process_shapefile(hDS); + // Convert mesh dim from file into pdim and orig_sdim to use in mesh create + int pdim, orig_sdim; + if (dim == 2) { + pdim=orig_sdim=2; + } else if (dim == 3) { + pdim=orig_sdim=3; + } else { + Throw() << "Meshes can only be created with dim=2 or 3."; + } + + OGR_DS_Destroy( hDS ); } + + localrc = 0; + printf("rc: %d localrc: %d\n", rc, localrc); + // Return an error, because this isn't implemented yet // TODO: GET RID OF THE FOLLOWING LINE WHEN THIS SUBROUTINE IS CREATING A VALID MESH //if (ESMC_LogDefault.MsgFoundError(ESMC_RC_NOT_IMPL, @@ -1358,12 +1392,12 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, throw rc; // To be caught one level up so we know where the error came from } -#else // ifdef ESMF_SHAPEFILE +#else // ifdef ESMF_GDAL int localrc; if (ESMC_LogDefault.MsgFoundError(ESMC_RC_LIB_NOT_PRESENT, "This functionality requires ESMF to be built with a shapefile library." , ESMC_CONTEXT, &localrc)) throw localrc; -#endif // ifdef ESMF_SHAPEFILE +#endif // ifdef ESMF_GDAL } diff --git a/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C b/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C index 72cca927d9..8598493318 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C @@ -163,7 +163,7 @@ void get_mesh_topo_id_from_UGRID_file(int pioFileDesc, char *filename, int &mesh void get_dim_from_UGRID_file(int pioFileDesc, char *filename, int mesh_topo_id, int &dim) { #undef ESMC_METHOD -#define ESMC_METHOD "get_dim _from_UGRID_file()" +#define ESMC_METHOD "get_dim_from_UGRID_file()" // Declare some useful vars int dimid; diff --git a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C deleted file mode 100644 index 148b044587..0000000000 --- a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C +++ /dev/null @@ -1,537 +0,0 @@ -//============================================================================== -// -// Earth System Modeling Framework -// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, -// Massachusetts Institute of Technology, Geophysical Fluid Dynamics -// Laboratory, University of Michigan, National Centers for Environmental -// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, -// NASA Goddard Space Flight Center. -// Licensed under the University of Illinois-NCSA License. -// -//============================================================================== -#ifndef MPICH_IGNORE_CXX_SEEK -#define MPICH_IGNORE_CXX_SEEK -#endif -#include - -// ESMF header -#include "ESMC.h" - -// ESMF Test header -#include "ESMC_Test.h" - -#if defined ESMF_MOAB -#include "ESMCI_MBMesh.h" -#include "ESMCI_MBMesh_Glue.h" -#include "ESMCI_MCTGen.C" -#endif - -#include "ESMCI_MeshCap.h" -#include "ESMCI_Mesh.h" - -#include -#include -#include -#include -#include -#include -#include //find_if -#include - -struct FindPair { - FindPair (std::string first, std::string second) \ - : m_first_value(first), m_second_value(second) {} - - std::string m_first_value; - std::string m_second_value; - bool operator() (const std::pair &p) { - return (p.first == m_first_value && p.second == m_second_value); - } -}; - -void combine(const std::string &api, const std::string &mesh, - const std::string &nativeormb){ - int localrc; - int rc = ESMF_FAILURE; - - std::string failMsg = "FAIL"; - int result = 0; - -#if defined ESMF_MOAB - MCTGen *generate = new MCTGen(); -#endif - - int nvmb = 1; - if (nativeormb == "Native") nvmb = 0; - - int localPet, petCount; - ESMC_VM vm; - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - std::array buffer; - buffer.fill(0); - time_t rawtime; - time(&rawtime); - const auto timeinfo = localtime(&rawtime); - strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); - std::string timeStr(buffer.data()); - - std::string name = timeStr + " - " + "PET " + std::to_string(localPet) + " - " + - nativeormb + " Mesh - " + api + " - " + mesh; - -#if defined ESMF_MOAB - try { - std::shared_ptr test = generate->mesh_map[mesh](localrc); - - test->name = name; - test->nativeormb = nvmb; - // test->verbosity = 3; - // test->tol = 1.e-15; - // test->print(); - - if (localrc == ESMF_SUCCESS) localrc = test->build(); - if (localrc == ESMF_SUCCESS) rc = test->function_map[api](); - - // test is a shared_ptr so no need to delete - // delete test; - } - CATCH_MCT_FAIL(&rc) -#else - rc = ESMF_SUCCESS; -#endif - -#if defined ESMF_MOAB - delete generate; -#endif - - ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), - &result, __FILE__, __LINE__, 0); - -} - -int main(int argc, char *argv[]) { -#undef ESMC_METHOD -#define ESMC_METHOD "MeshCapUTest::main()" - - int rc; - int localPet, petCount; - ESMC_VM vm; - - std::string failMsg = "FAIL"; - // break this up so it doesn't count as an additional test - std::string nex_test_tag = "//NEX_"; - nex_test_tag.append("UTest\n"); - int result = 0; - - //---------------------------------------------------------------------------- - // Start the test with an alternate name for log and stdout files - ESMC_TestStart("ESMCI_MeshCapGenUTest.C", __LINE__, 0); - - //---------------------------------------------------------------------------- - rc=ESMC_LogSet(true); - - // Get parallel information - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - // output stream to write test tag to the generated source file - std::ofstream tagfile; - tagfile.open("ESMCI_MeshCapGenUTest.C", std::ios_base::app); - - // this is an easy way to comment a single line to toggle mbmesh/native - bool mbmesh = false; - mbmesh = true; - bool native = false; - native = true; - - // these are bound to MCT in constructor, must match! - std::vector test_apis; - test_apis.push_back("createget"); - test_apis.push_back("dual"); - test_apis.push_back("redist_elem"); - test_apis.push_back("redist_node"); - test_apis.push_back("redist_elno"); - test_apis.push_back("serialize"); - test_apis.push_back("to_pointlist_elem"); - test_apis.push_back("to_pointlist_node"); - test_apis.push_back("write_vtk"); - - // these are bound to MCTGen in constructor, must match! - std::vector test_meshes_native; - test_meshes_native.push_back("quad_2d_cart"); - test_meshes_native.push_back("quad_2d_sph_deg"); - test_meshes_native.push_back("quad_2d_sph_rad"); - test_meshes_native.push_back("tri_2d_cart"); - test_meshes_native.push_back("tri_2d_sph_deg"); - test_meshes_native.push_back("tri_2d_sph_rad"); - test_meshes_native.push_back("hex_3d_cart"); - test_meshes_native.push_back("hex_3d_sph_deg"); - test_meshes_native.push_back("hex_3d_sph_rad"); - test_meshes_native.push_back("mix_2d_cart"); - test_meshes_native.push_back("mix_2d_sph_deg"); - test_meshes_native.push_back("mix_2d_sph_rad"); - test_meshes_native.push_back("periodic_2d_sph_deg"); - test_meshes_native.push_back("periodic_2d_sph_rad"); - // cannot get info from ngons - // test_meshes_native.push_back("ngon_2d_cart"); - // test_meshes_native.push_back("ngon_2d_sph_deg"); - // test_meshes_native.push_back("ngon_2d_sph_rad"); - - // these are bound to MCTGen in constructor, must match! - std::vector test_meshes_mbmesh; - test_meshes_mbmesh.push_back("quad_2d_cart"); - test_meshes_mbmesh.push_back("quad_2d_sph_deg"); - test_meshes_mbmesh.push_back("quad_2d_sph_rad"); - test_meshes_mbmesh.push_back("tri_2d_cart"); - test_meshes_mbmesh.push_back("tri_2d_sph_deg"); - test_meshes_mbmesh.push_back("tri_2d_sph_rad"); - test_meshes_mbmesh.push_back("hex_3d_cart"); - test_meshes_mbmesh.push_back("hex_3d_sph_deg"); - test_meshes_mbmesh.push_back("hex_3d_sph_rad"); - test_meshes_mbmesh.push_back("mix_2d_cart"); - test_meshes_mbmesh.push_back("mix_2d_sph_deg"); - test_meshes_mbmesh.push_back("mix_2d_sph_rad"); - test_meshes_mbmesh.push_back("ngon_2d_cart"); - test_meshes_mbmesh.push_back("ngon_2d_sph_deg"); - test_meshes_mbmesh.push_back("ngon_2d_sph_rad"); - test_meshes_mbmesh.push_back("periodic_2d_sph_deg"); - test_meshes_mbmesh.push_back("periodic_2d_sph_rad"); - - // skip the following tests - std::vector> skip_test_mbmesh = {\ - // dual not implemented in 3d - {"dual", "hex_3d_cart"}, - {"dual", "hex_3d_sph_deg"}, - {"dual", "hex_3d_sph_rad"}, - // ESMCI_MBMesh_Redist.C, line:2336:Could not find a suitable processor for this element - {"redist_node", "tri_2d_cart"}, - {"redist_node", "tri_2d_sph_deg"}, - {"redist_node", "tri_2d_sph_rad"}, - - }; - - std::vector> skip_test_native = {\ - // dual not implemented in 3d - // Creation of a dual mesh isn't supported for Meshes of parametric dim greater than 3. - {"dual", "hex_3d_cart"}, - {"dual", "hex_3d_sph_deg"}, - {"dual", "hex_3d_sph_rad"}, - }; - - - if (mbmesh) { - for (const auto api: test_apis) { - for (const auto mesh: test_meshes_mbmesh) { - // don't run cases that hang - auto skip_itr = std::find_if(skip_test_mbmesh.begin(), skip_test_mbmesh.end(), - FindPair(api, mesh)); - - if (skip_itr != skip_test_mbmesh.end()) { - continue; - } else { - combine(api, mesh, "MBMesh"); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - - if (native) { - for (const auto api: test_apis) { - for (const auto mesh: test_meshes_native) { - // don't run cases that hang - auto skip_itr = std::find_if(skip_test_native.begin(), skip_test_native.end(), - FindPair(api, mesh)); - - if (skip_itr != skip_test_native.end()) { - continue; - } else { - combine(api, mesh, "Native"); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - - tagfile.close(); - - //---------------------------------------------------------------------------- - ESMC_TestEnd("ESMCI_MeshCapGenUTest.C", __LINE__, 0); - - return 0; -} -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest diff --git a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C deleted file mode 100644 index 52f3cc146c..0000000000 --- a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C +++ /dev/null @@ -1,5091 +0,0 @@ -//============================================================================== -// -// Earth System Modeling Framework -// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, -// Massachusetts Institute of Technology, Geophysical Fluid Dynamics -// Laboratory, University of Michigan, National Centers for Environmental -// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, -// NASA Goddard Space Flight Center. -// Licensed under the University of Illinois-NCSA License. -// -//============================================================================== -#ifndef MPICH_IGNORE_CXX_SEEK -#define MPICH_IGNORE_CXX_SEEK -#endif -#include - -// ESMF header -#include "ESMC.h" - -// ESMF Test header -#include "ESMC_Test.h" - -#if defined ESMF_MOAB -#include "ESMCI_MBMesh.h" -#include "ESMCI_MBMesh_Glue.h" -#include "ESMCI_MCTGen.C" -#endif - -#include -#include -#include -#include -#include -#include -#include //find_if -#include -#include - -struct FindAnyPair { - FindAnyPair (std::string a, std::string b, std::string c, std::string d, - std::string e, std::string f, std::string g, std::string h) - : a_val(a), b_val(b), c_val(c), d_val(d), - e_val(e), f_val(f), g_val(g), h_val(h) {} - - std::string a_val; - std::string b_val; - std::string c_val; - std::string d_val; - std::string e_val; - std::string f_val; - std::string g_val; - std::string h_val; - bool operator() - ( const std::pair &p ) { - return (((p.first == a_val) || (p.first == b_val) || - (p.first == c_val) || (p.first == d_val) || - (p.first == e_val) || (p.first == f_val) || - (p.first == g_val) || (p.first == h_val)) && - ((p.second == a_val) || (p.second == b_val) || - (p.second == c_val) || (p.second == d_val) || - (p.second == e_val) || (p.second == f_val) || - (p.second == g_val) || (p.second == h_val))); - } -}; - -void combine(const std::string &api, const std::string &mesh, - const std::string &nativeormb, - const std::string &maptype, - const std::string &normtype, - const std::string &poletype, - const std::string &extrapmethod, - const std::string &unmappedaction, - const std::string &ignoredegenerate){ - int localrc; - int rc = ESMF_FAILURE; - - std::string failMsg = "FAIL"; - std::string dash = " - "; - int result = 0; - -#if defined ESMF_MOAB - MCTGen *generate = new MCTGen(); -#endif - - int nvmb = 1; - if (nativeormb == "Native") nvmb = 0; - - int localPet, petCount; - ESMC_VM vm; - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - std::array buffer; - buffer.fill(0); - time_t rawtime; - time(&rawtime); - const auto timeinfo = localtime(&rawtime); - strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); - std::string timeStr(buffer.data()); - - std::string name = timeStr + dash + "PET " + std::to_string(localPet) + dash + - nativeormb + " Mesh - " + api + dash + mesh + - dash + maptype + dash + normtype + dash + poletype + - dash + extrapmethod + dash + unmappedaction + - dash + ignoredegenerate; - -#if defined ESMF_MOAB - try { - std::shared_ptr test = generate->mesh_map[mesh](localrc); - - test->name = name; - test->nativeormb = nvmb; - // test->verbosity = 3; - // test->tol = 1.e-15; - // test->print(); - - // convert parameters to integers - int mt = test->MapType[maptype]; - int nt = test->NormType[normtype]; - int pt = test->PoleType[poletype]; - int em = test->ExtrapMethod[extrapmethod]; - int ua = test->UnmappedAction[unmappedaction]; - int id = test->IgnoreDegenerate[ignoredegenerate]; - - if (localrc == ESMF_SUCCESS) localrc = test->build(); - if (localrc == ESMF_SUCCESS) rc = test->regrid_map[api](mt, nt, pt, - em, ua, id); - - // test is a shared_ptr so no need to delete - // delete test; - } - CATCH_MCT_FAIL(&rc) -#else - rc = ESMF_SUCCESS; -#endif - -#if defined ESMF_MOAB - delete generate; -#endif - - ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), - &result, __FILE__, __LINE__, 0); -} - -int main(int argc, char *argv[]) { -#undef ESMC_METHOD -#define ESMC_METHOD "MBMeshRegidUTest::main()" - - int rc, localrc; - int localPet, petCount; - ESMC_VM vm; - - std::string failMsg = "FAIL"; - // break this up so it doesn't count as an additional test - std::string nex_test_tag = "//NEX_"; - nex_test_tag.append("UTest\n"); - int result = 0; - - //---------------------------------------------------------------------------- - // Start the test with an alternate name for log and stdout files - ESMC_TestStart("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); - - //---------------------------------------------------------------------------- - rc=ESMC_LogSet(true); - - // Get parallel information - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - // output stream to write test tag to the generated source file - std::ofstream tagfile; - tagfile.open("ESMCI_MeshCapRegridGenUTest.C", std::ios_base::app); - - // this is an easy way to comment a single line to toggle mbmesh/native - bool mbmesh = false; - mbmesh = true; - bool native = false; - native = true; - - std::vector test_apis_mbmesh; - test_apis_mbmesh.push_back("bilinear"); - test_apis_mbmesh.push_back("conservative"); - test_apis_mbmesh.push_back("nearest_d2s"); - test_apis_mbmesh.push_back("nearest_s2d"); - // Not yet available with MBMesh - // test_apis_mbmesh.push_back("conservative_2nd"); - // test_apis_mbmesh.push_back("patch"); - - std::vector test_apis_native; - test_apis_native.push_back("bilinear"); - test_apis_native.push_back("conservative"); - test_apis_native.push_back("conservative_2nd"); - test_apis_native.push_back("nearest_d2s"); - test_apis_native.push_back("nearest_s2d"); - test_apis_native.push_back("patch"); - - // these are bound to MCTGen in constructor, must match! - std::vector test_meshes; - test_meshes.push_back("quad_2d_cart"); - test_meshes.push_back("quad_2d_sph_deg"); - test_meshes.push_back("quad_2d_sph_rad"); - test_meshes.push_back("tri_2d_cart"); - test_meshes.push_back("tri_2d_sph_deg"); - test_meshes.push_back("tri_2d_sph_rad"); - test_meshes.push_back("hex_3d_cart"); - test_meshes.push_back("hex_3d_sph_deg"); - test_meshes.push_back("hex_3d_sph_rad"); - test_meshes.push_back("mix_2d_cart"); - test_meshes.push_back("mix_2d_sph_deg"); - test_meshes.push_back("mix_2d_sph_rad"); - test_meshes.push_back("ngon_2d_cart"); - test_meshes.push_back("ngon_2d_sph_deg"); - test_meshes.push_back("ngon_2d_sph_rad"); - test_meshes.push_back("periodic_2d_sph_deg"); - test_meshes.push_back("periodic_2d_sph_rad"); - - // method dependent, and mesh dependent - std::vector test_regrid_maptype; - test_regrid_maptype.push_back("MAP_CARTAPPROX"); - test_regrid_maptype.push_back("MAP_GREATCIRCLE"); - - // only conservative methods, all meshes - std::vector test_regrid_normtype; - test_regrid_normtype.push_back("NORM_DSTAREA"); - test_regrid_normtype.push_back("NORM_FRACAREA"); - - // all methods, but only for periodic grids - std::vector test_regrid_poletype; - test_regrid_poletype.push_back("POLE_NONE"); - test_regrid_poletype.push_back("POLE_ALL"); - test_regrid_poletype.push_back("POLE_NPNT"); - test_regrid_poletype.push_back("POLE_TEETH"); - - // all methods except nn, but only for meshes with destination larger than source - std::vector test_regrid_extrapmethod; - test_regrid_extrapmethod.push_back("EXTRAP_NONE"); - test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_STOD"); - test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_IDAVG"); - test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_D"); - test_regrid_extrapmethod.push_back("EXTRAP_CREEP"); - test_regrid_extrapmethod.push_back("EXTRAP_CREEP_NRST_D"); - - // all methods except nn, but only for meshes with destination larger than source - std::vector test_regrid_unmappedaction; - test_regrid_unmappedaction.push_back("UNMAPPED_THROWERROR"); - test_regrid_unmappedaction.push_back("UNMAPPED_IGNORE"); - - // all methods except nn, but only meshes with degenerate, clockwise or concave elements - std::vector test_regrid_ignoredegenerate; - test_regrid_ignoredegenerate.push_back("DONOT_IGNORE_DEGENERATE"); - test_regrid_ignoredegenerate.push_back("IGNORE_DEGENERATE"); - - - - std::vector> skip_test_mbmesh = {\ - // conservative not supported with ngons - {"conservative", "ngon_2d_cart"}, - {"conservative", "ngon_2d_sph_deg"}, - {"conservative", "ngon_2d_sph_rad"}, - // extrapolation methods not supported (why do EXTRAP_NEAREST_STOD, EXTRAP_NEAREST_IDAVG work?) - {"bilinear", "EXTRAP_NEAREST_D"}, - {"bilinear", "EXTRAP_CREEP"}, - {"bilinear", "EXTRAP_CREEP_NRST_D"}, - {"patch", "EXTRAP_NEAREST_D"}, - {"patch", "EXTRAP_CREEP"}, - {"patch", "EXTRAP_CREEP_NRST_D"}, - }; - - std::vector> skip_test_native = {\ - // meshes with ngons return incorrect element count with native - {"bilinear", "ngon_2d_cart"}, - {"bilinear", "ngon_2d_sph_deg"}, - {"bilinear", "ngon_2d_sph_rad"}, - {"patch", "ngon_2d_cart"}, - {"patch", "ngon_2d_sph_deg"}, - {"patch", "ngon_2d_sph_rad"}, - {"conservative", "ngon_2d_cart"}, - {"conservative", "ngon_2d_sph_deg"}, - {"conservative", "ngon_2d_sph_rad"}, - {"conservative_2nd", "ngon_2d_cart"}, - {"conservative_2nd", "ngon_2d_sph_deg"}, - {"conservative_2nd", "ngon_2d_sph_rad"}, - // Conservative not supported on 3D spherical meshes - {"conservative", "hex_3d_sph_deg"}, - {"conservative", "hex_3d_sph_rad"}, - }; - - std::vector> skip_test_common = {\ - // patch not supported in 3d - {"patch", "hex_3d_cart"}, - {"patch", "hex_3d_sph_deg"}, - {"patch", "hex_3d_sph_rad"}, - // conservative_2nd not supported in 3d - {"conservative_2nd", "hex_3d_cart"}, - {"conservative_2nd", "hex_3d_sph_deg"}, - {"conservative_2nd", "hex_3d_sph_rad"}, - // creep fill extrapolation not supported in 3D - {"hex_3d_cart", "EXTRAP_CREEP"}, - {"hex_3d_sph_deg", "EXTRAP_CREEP"}, - {"hex_3d_sph_rad", "EXTRAP_CREEP"}, - {"hex_3d_cart", "EXTRAP_CREEP_NRST_D"}, - {"hex_3d_sph_deg", "EXTRAP_CREEP_NRST_D"}, - {"hex_3d_sph_rad", "EXTRAP_CREEP_NRST_D"}, - // conservative is not supported with extrapolation - {"conservative", "EXTRAP_NEAREST_STOD"}, - {"conservative", "EXTRAP_NEAREST_IDAVG"}, - {"conservative", "EXTRAP_NEAREST_D"}, - {"conservative", "EXTRAP_CREEP"}, - {"conservative", "EXTRAP_CREEP_NRST_D"}, - {"conservative_2nd", "EXTRAP_NEAREST_STOD"}, - {"conservative_2nd", "EXTRAP_NEAREST_IDAVG"}, - {"conservative_2nd", "EXTRAP_NEAREST_D"}, - {"conservative_2nd", "EXTRAP_CREEP"}, - {"conservative_2nd", "EXTRAP_CREEP_NRST_D"}, - // the following are exceptions due to design, do not represent limitations per se - // conservative only works with great circles - {"conservative", "MAP_CARTAPPROX"}, - {"conservative_2nd", "MAP_CARTAPPROX"}, - // cartesian only works with straight lines - {"quad_2d_cart", "MAP_GREATCIRCLE"}, - {"tri_2d_cart", "MAP_GREATCIRCLE"}, - {"hex_3d_cart", "MAP_GREATCIRCLE"}, - {"mix_2d_cart", "MAP_GREATCIRCLE"}, - {"ngon_2d_cart", "MAP_GREATCIRCLE"}, - // nearest doesn't touch on any of the regrid options, only allow defaults - {"nearest_d2s", "MAP_GREATCIRCLE"}, - {"nearest_d2s", "POLE_ALL"}, - {"nearest_d2s", "POLE_NPNT"}, - {"nearest_d2s", "POLE_TEETH"}, - {"nearest_d2s", "EXTRAP_NEAREST_STOD"}, - {"nearest_d2s", "EXTRAP_NEAREST_IDAVG"}, - {"nearest_d2s", "EXTRAP_NEAREST_D"}, - {"nearest_d2s", "EXTRAP_CREEP"}, - {"nearest_d2s", "EXTRAP_CREEP_NRST_D"}, - {"nearest_d2s", "UNMAPPED_IGNORE"}, - {"nearest_d2s", "IGNORE_DEGENERATE"}, - {"nearest_s2d", "MAP_GREATCIRCLE"}, - {"nearest_s2d", "POLE_ALL"}, - {"nearest_s2d", "POLE_NPNT"}, - {"nearest_s2d", "POLE_TEETH"}, - {"nearest_s2d", "EXTRAP_NEAREST_STOD"}, - {"nearest_s2d", "EXTRAP_NEAREST_IDAVG"}, - {"nearest_s2d", "EXTRAP_NEAREST_D"}, - {"nearest_s2d", "EXTRAP_CREEP"}, - {"nearest_s2d", "EXTRAP_CREEP_NRST_D"}, - {"nearest_s2d", "UNMAPPED_IGNORE"}, - {"nearest_s2d", "IGNORE_DEGENERATE"}, - // only run pole options with periodic meshes - {"quad_2d_cart", "POLE_ALL"}, - {"quad_2d_sph_deg", "POLE_ALL"}, - {"quad_2d_sph_rad", "POLE_ALL"}, - {"tri_2d_cart", "POLE_ALL"}, - {"tri_2d_sph_deg", "POLE_ALL"}, - {"tri_2d_sph_rad", "POLE_ALL"}, - {"hex_3d_cart", "POLE_ALL"}, - {"hex_3d_sph_deg", "POLE_ALL"}, - {"hex_3d_sph_rad", "POLE_ALL"}, - {"mix_2d_cart", "POLE_ALL"}, - {"mix_2d_sph_deg", "POLE_ALL"}, - {"mix_2d_sph_rad", "POLE_ALL"}, - {"ngon_2d_cart", "POLE_ALL"}, - {"ngon_2d_sph_deg", "POLE_ALL"}, - {"ngon_2d_sph_rad", "POLE_ALL"}, - {"quad_2d_cart", "POLE_NPNT"}, - {"quad_2d_sph_deg", "POLE_NPNT"}, - {"quad_2d_sph_rad", "POLE_NPNT"}, - {"tri_2d_cart", "POLE_NPNT"}, - {"tri_2d_sph_deg", "POLE_NPNT"}, - {"tri_2d_sph_rad", "POLE_NPNT"}, - {"hex_3d_cart", "POLE_NPNT"}, - {"hex_3d_sph_deg", "POLE_NPNT"}, - {"hex_3d_sph_rad", "POLE_NPNT"}, - {"mix_2d_cart", "POLE_NPNT"}, - {"mix_2d_sph_deg", "POLE_NPNT"}, - {"mix_2d_sph_rad", "POLE_NPNT"}, - {"ngon_2d_cart", "POLE_NPNT"}, - {"ngon_2d_sph_deg", "POLE_NPNT"}, - {"ngon_2d_sph_rad", "POLE_NPNT"}, - {"quad_2d_cart", "POLE_TEETH"}, - {"quad_2d_sph_deg", "POLE_TEETH"}, - {"quad_2d_sph_rad", "POLE_TEETH"}, - {"tri_2d_cart", "POLE_TEETH"}, - {"tri_2d_sph_deg", "POLE_TEETH"}, - {"tri_2d_sph_rad", "POLE_TEETH"}, - {"hex_3d_cart", "POLE_TEETH"}, - {"hex_3d_sph_deg", "POLE_TEETH"}, - {"hex_3d_sph_rad", "POLE_TEETH"}, - {"mix_2d_cart", "POLE_TEETH"}, - {"mix_2d_sph_deg", "POLE_TEETH"}, - {"mix_2d_sph_rad", "POLE_TEETH"}, - {"ngon_2d_cart", "POLE_TEETH"}, - {"ngon_2d_sph_deg", "POLE_TEETH"}, - {"ngon_2d_sph_rad", "POLE_TEETH"}, - }; - - - if (mbmesh) { - for (const auto api: test_apis_mbmesh) { - for (const auto mesh: test_meshes) { - for (const auto mt: test_regrid_maptype) { - for (const auto nt: test_regrid_normtype) { - for (const auto pt: test_regrid_poletype) { - for (const auto em: test_regrid_extrapmethod) { - for (const auto ua: test_regrid_unmappedaction) { - for (const auto id: test_regrid_ignoredegenerate) { - auto skip_itr_common = std::find_if(skip_test_common.begin(), - skip_test_common.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - auto skip_itr_mbmesh = std::find_if(skip_test_mbmesh.begin(), - skip_test_mbmesh.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - if ((skip_itr_common != skip_test_common.end()) || - (skip_itr_mbmesh != skip_test_mbmesh.end())) { - continue; - } else { - combine(api, mesh, "MBMesh", mt, nt, pt, em, ua, id); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - } - } - } - } - } - } - - if (native) { - for (const auto api: test_apis_native) { - for (const auto mesh: test_meshes) { - for (const auto mt: test_regrid_maptype) { - for (const auto nt: test_regrid_normtype) { - for (const auto pt: test_regrid_poletype) { - for (const auto em: test_regrid_extrapmethod) { - for (const auto ua: test_regrid_unmappedaction) { - for (const auto id: test_regrid_ignoredegenerate) { - auto skip_itr_common = std::find_if(skip_test_common.begin(), - skip_test_common.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - auto skip_itr_native = std::find_if(skip_test_native.begin(), - skip_test_native.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - if ((skip_itr_common != skip_test_common.end()) || - (skip_itr_native != skip_test_native.end())) { - continue; - } else { - combine(api, mesh, "Native", mt, nt, pt, em, ua, id); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - } - } - } - } - } - } - - tagfile.close(); - - //---------------------------------------------------------------------------- - ESMC_TestEnd("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); - - return 0; -} -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 4b44f1cf11..5df6ceca0b 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -342,7 +342,7 @@ program ESMF_MeshFileIOUTest call test_create_mesh_from_SH_file(correct, rc) ! TODO: CHANGE ESMF_PIO TO THE SHAPEFILE EQUIVALENT -#ifdef ESMF_SHAPEFILE +#ifdef ESMF_GDAL call ESMF_Test(((rc.eq.ESMF_SUCCESS)), name, failMsg, result, ESMF_SRCLINE) #else write(failMsg, *) "Did not return ESMC_RC_LIB_NOT_PRESENT" diff --git a/src/Infrastructure/Mesh/tests/data/test_shape.dbf b/src/Infrastructure/Mesh/tests/data/test_shape.dbf new file mode 100644 index 0000000000000000000000000000000000000000..9eebe3f8e89ec184c22cb5dc9a9d289ebbb259fd GIT binary patch literal 132 xcmZRsX60gHU|?`$Py~`_Ae@20FEKY2D(VcP6`&j##j8+~T3n)l4-iry1pw*K4io?Y literal 0 HcmV?d00001 diff --git a/src/Infrastructure/Mesh/tests/data/test_shape.prj b/src/Infrastructure/Mesh/tests/data/test_shape.prj new file mode 100644 index 0000000000..f45cbadf00 --- /dev/null +++ b/src/Infrastructure/Mesh/tests/data/test_shape.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/src/Infrastructure/Mesh/tests/data/test_shape.shp b/src/Infrastructure/Mesh/tests/data/test_shape.shp new file mode 100644 index 0000000000000000000000000000000000000000..fe86c17ceec5366e085b4303e659641d4d0ffa3c GIT binary patch literal 340 zcmZQzQ0HR64pzNjW?*2&E(a9Nbbv@jLTLyO2gwK&x4>-{%#26}kU|z5hCqZ7YEk)E hH8BB2k?e)(g{ejO0n=WXS{Mye3)2e|N9RX6000K-3=;qV literal 0 HcmV?d00001 diff --git a/src/Infrastructure/Mesh/tests/data/test_shape.shx b/src/Infrastructure/Mesh/tests/data/test_shape.shx new file mode 100644 index 0000000000000000000000000000000000000000..df0e4661aef26f3685d597caaffeb59358e0a291 GIT binary patch literal 116 qcmZQzQ0HR64y;} Date: Tue, 13 Jun 2023 08:35:30 -0400 Subject: [PATCH 09/58] This version will process US county files. (This was a surprise!) so it's being committed. Still needs some clean-up but that can wait MSL --- .#gisDev.org | 1 - .../Mesh/include/ESMCI_GDAL_Util.h | 4 +- src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C | 96 ++++++++++++------- .../Mesh/src/ESMCI_Mesh_FileIO.C | 84 ++++++++++++++-- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 13 ++- 5 files changed, 148 insertions(+), 50 deletions(-) delete mode 120000 .#gisDev.org diff --git a/.#gisDev.org b/.#gisDev.org deleted file mode 120000 index c0e2ed48d9..0000000000 --- a/.#gisDev.org +++ /dev/null @@ -1 +0,0 @@ -ilcentro@localhost.localdomain.717886:1682835154 \ No newline at end of file diff --git a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h index 0ea83e6674..95bab4f1b6 100644 --- a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h +++ b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h @@ -53,7 +53,9 @@ void open_(); // shapefile routines void get_dim_from_SHP_file(OGRDataSourceH hDS, char *filename, int &dim); -void process_shapefile(OGRDataSourceH hDS); +void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, int *&nodeIDs, int *&elemIDs, + int *&elemConn, int *&numElemConn, + int *totNumElemConn, int *numNodes, int *numElems); void ESMCI_mesh_create_from_SHP_file(); #endif // ifdef ESMF_GDAL diff --git a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C index 63e722ca01..3ec94455f9 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C @@ -65,14 +65,12 @@ int i; int ftr = 0; int totpoints = 0; -int numNodes, numElems; -int *nodeIDs; -int *elemConn,*numElemConn; +//int numNodes, numElems; //double *nodeXCoords,*nodeYCoords; // Routines -int processPolygon(OGRGeometryH fGeom, int runtyp, double *nodeXCoords, double *nodeYCoords); -int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords); +int processPolygon(OGRGeometryH fGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn); +int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn); // Get the dimension of the mesh in the SHP file // (This dimension is both the pdim and orig_sdim of the mesh) @@ -88,8 +86,12 @@ void get_dim_from_SHP_file(OGRDataSourceH hDS, char *filename, int &dim) { return; } -void process_shapefile(OGRDataSourceH hDS) { +void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, + int *&nodeIDs, int *&elemIDs, int *&elemConn, + int *&numElemConn, int *totNumElemConn, int *numNodes, int *numElems) { int nElements; +// int *nodeIDs; +// int *elemConn;//,*numElemConn; double *nodeXCoords,*nodeYCoords; // OGRRegisterAll(); // register all the drivers @@ -128,11 +130,11 @@ void process_shapefile(OGRDataSourceH hDS) { // ADD POLYGON if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { - processPolygon(fGeom,0, NULL, NULL); + processPolygon(fGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); } // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ - processMultiPolygon(hGeom,0, NULL, NULL); + processMultiPolygon(hGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); } // Cleanup @@ -142,18 +144,22 @@ void process_shapefile(OGRDataSourceH hDS) { // Step 3: // Allocate vars // -- numNodes - there are as many connections as nodes - numNodes = totpoints; // At this point, un-trimmed. Points will repeat + *numNodes = totpoints; // At this point, un-trimmed. Points will repeat + *totNumElemConn = totpoints; // -- numElems - numElems = ftr; // This is an assumption! + *numElems = ftr; // This is an assumption! // -- nodeIDs - nodeIDs = (int *)malloc(numNodes*sizeof(int)); + nodeIDs = new int[totpoints]; +// nodeIDs = (int *)malloc(totpoints*sizeof(int)); // -- node[X,Y]Coords - nodeXCoords = (double *)malloc(numNodes*sizeof(double)); - nodeYCoords = (double *)malloc(numNodes*sizeof(double)); + nodeXCoords = (double *)malloc(*numNodes*sizeof(double)); + nodeYCoords = (double *)malloc(*numNodes*sizeof(double)); // -- elemConn -// elemConn = (int *)malloc(numNodes*sizeof(int)); <- nodeIDs is already this, right? + elemConn = (int *)malloc(*numNodes*sizeof(int)); //<- nodeIDs is already this, right? + // -- elemIDs + elemIDs = (int *)malloc(*numElems*sizeof(int)); // -- numElemConn - numElemConn = (int *)malloc(numElems*sizeof(int)); + numElemConn = (int *)malloc(*numElems*sizeof(int)); // Reset counters ftr = 0; // Zero features @@ -172,11 +178,11 @@ void process_shapefile(OGRDataSourceH hDS) { // ADD POLYGON if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { - processPolygon(fGeom,1, nodeXCoords, nodeYCoords); + processPolygon(fGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); } // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ - processMultiPolygon(hGeom,1, nodeXCoords, nodeYCoords); + processMultiPolygon(hGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); } // Cleanup @@ -186,26 +192,35 @@ void process_shapefile(OGRDataSourceH hDS) { printf("\n"); printf("N Features: %d\n",ftr); printf("N Points: %d\n",totpoints); + printf("numNodes: %d\n",numNodes); - // Dump vals + nodeCoords= new double[2*totpoints]; + + // Pass OGR Values to Mesh arrays printf("Coords: \n"); + int j = 0; for (i=0;i=0; i--) { + nodeXCoords[totpoints+ii] = OGR_G_GetX(fGeom, i); + nodeYCoords[totpoints+ii] = OGR_G_GetY(fGeom, i); + nodeIDs[totpoints+ii] = totpoints+ii+1; // increment from 1, not 0 + elemConn[totpoints+ii] = totpoints+ii+1; + ii++; } - numElemConn[ftr] = points; + numElemConn[ftr] = points-1; + elemIDs[ftr] = ftr+1; } // Successful query @@ -242,7 +267,8 @@ int processPolygon(OGRGeometryH fGeom, int runtyp, double *nodeXCoords, double * return 0; } -int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords) { +int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, + int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn) { // runtyp: if 0, just counting things. // if 1, populating arrays int j; @@ -260,10 +286,10 @@ int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, dou // ADD POLYGON if (wkbFlatten(OGR_G_GetGeometryType(fGeom)) == wkbPolygon) { - processPolygon(mGeom,runtyp, nodeXCoords, nodeYCoords); + processPolygon(mGeom,runtyp, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); } // Or RECURSE INTO SUB MULTIPOLYGON else if(wkbFlatten(OGR_G_GetGeometryType(fGeom)) == wkbMultiPolygon) { - processMultiPolygon(fGeom,runtyp, nodeXCoords, nodeYCoords); + processMultiPolygon(fGeom,runtyp, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); } } // printf("\n"); diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index 1d9c0124c4..b8a68d1999 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -1339,12 +1339,39 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, Throw(); } - // Get DIM var + // Get DIM var - currently forced to 2D int dim; get_dim_from_SHP_file(hDS, filename, dim); // Get shapefile params - process_shapefile(hDS); + int num_nodes; + int num_elems=0, totNumElemConn=0; + int *numElemConn=NULL, *elemConn=NULL; + double *nodeCoords=NULL; + int *node_IDs=NULL; + int *elem_IDs=NULL; + + // Processes polygons in hDS. Polygons are flattened to 2D + process_shapefile(hDS,nodeCoords,node_IDs,elem_IDs,elemConn,numElemConn, + &totNumElemConn, &num_nodes, &num_elems); + + // TBD: Coord system conversion + + /* At this point, we've read the shapfile and defined + - num_nodes + - num_elems + - nodeCoords + - numElemConn + - node_IDs + */ + +//\\ printf("totnumelemconn: %d\n", totNumElemConn); +//\\ printf("num_nodes: %d\n", num_nodes); +//\\ printf("num_elems: %d\n", num_elems); +//\\ int i; +//\\ for (i=0;i<2*num_nodes;i+=2) { +//\\ printf("nodeCoords %.2f, %.2f\n",nodeCoords[i],nodeCoords[i+1]); +//\\ } // Convert mesh dim from file into pdim and orig_sdim to use in mesh create int pdim, orig_sdim; @@ -1356,11 +1383,56 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, Throw() << "Meshes can only be created with dim=2 or 3."; } + // Get coordsys from file + ESMC_CoordSys_Flag coord_sys_mesh=ESMC_COORDSYS_SPH_DEG; // Assume "degrees" for now. +// NOTE DEFINED YET get_coordsys_from_SHP_file(pioFileDesc, filename, dim, nodeCoord_ids, coord_sys_file); + + // Create Mesh + ESMCI_meshcreate(out_mesh, &pdim, &orig_sdim, &coord_sys_mesh, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // printf("Finished creating mesh: %d\n", localrc); + + // Add nodes + ESMCI_meshaddnodes(out_mesh, &num_nodes, node_IDs, + nodeCoords, NULL, NULL, + &coord_sys_mesh, &orig_sdim, + &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // printf("Finished adding nodes: %d\n", localrc); + + // Add elements + // !!! None of the elements have shared edges. + int areaPresent = 0; + int centerCoordsPresent=0; + ESMCI_meshaddelements(out_mesh, + &num_elems, elem_IDs, numElemConn, //elementType, <- using numElemConn in place of elementType assumes 2D!! + NULL, // No mask + &areaPresent, NULL, // No areas + ¢erCoordsPresent, NULL, // No center coords + &totNumElemConn, elemConn, + &coord_sys_mesh, &orig_sdim, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // printf("Finished adding elements: %d\n", localrc); + + // Cleanup OGR_DS_Destroy( hDS ); - } - - localrc = 0; - printf("rc: %d localrc: %d\n", rc, localrc); + + delete [] elem_IDs; + delete [] elemConn; + delete [] node_IDs; + delete [] numElemConn; + delete [] nodeCoords; + + } else { + // Set return code +// if (rc!=NULL) *rc = ESMF_SUCCESS; + } // Return an error, because this isn't implemented yet // TODO: GET RID OF THE FOLLOWING LINE WHEN THIS SUBROUTINE IS CREATING A VALID MESH diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 5df6ceca0b..e265df576c 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -4583,8 +4583,8 @@ subroutine check_mesh_from_sph_3x3_UG_file(correct, rc) if (rc /= ESMF_SUCCESS) return ! DEBUG OUTPUT - !call ESMF_MeshWrite(mesh,"mesh_3x3_ugrid",rc=rc) - !if (rc .ne. ESMF_SUCCESS) rc=ESMF_FAILURE + call ESMF_MeshWrite(mesh,"mesh_3x3_ugrid",rc=rc) + if (rc .ne. ESMF_SUCCESS) rc=ESMF_FAILURE ! Init correct to true before looking for problems correct=.true. @@ -6913,19 +6913,18 @@ subroutine test_create_mesh_from_SH_file(correct, rc) if (rc /= ESMF_SUCCESS) return ! Create Mesh from shape file - mesh=ESMF_MeshCreate("data/test_shape.shp", & + mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & fileformat=ESMF_FILEFORMAT_SHAPEFILE, & rc=rc) if (rc /= ESMF_SUCCESS) return !! Write mesh for debugging - ! call ESMF_MeshWrite(mesh,"test_mesh",rc=rc) - ! if (rc /= ESMF_SUCCESS) return + call ESMF_MeshWrite(mesh,"cb_2018_us_county_500k",rc=rc) + if (rc /= ESMF_SUCCESS) return ! Get rid of Mesh - ! TODO: Uncomment when above is working - !call ESMF_MeshDestroy(mesh, rc=rc) + call ESMF_MeshDestroy(mesh, rc=rc) if (rc /= ESMF_SUCCESS) return ! Return success From aaa0cd1544496f59b1578d2ed01472d61a31e58d Mon Sep 17 00:00:00 2001 From: Michael Long Date: Thu, 15 Jun 2023 13:47:21 -0400 Subject: [PATCH 10/58] End initial parallel code developement. Transition to data/field read now. (ESMCI_IO_GDAL* files already created) - MSL --- .gitignore | 2 +- gisDev.org | 15 +- src/Infrastructure/IO/include/ESMCI_IO_GDAL.h | 148 ++++++++++++ src/Infrastructure/IO/src/ESMCI_IO_GDAL.C | 115 +++++++++ src/Infrastructure/IO/src/makefile | 4 +- .../Mesh/include/ESMCI_GDAL_Util.h | 19 +- src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C | 213 +++++++++++++++-- .../Mesh/src/ESMCI_Mesh_FileIO.C | 226 +++++++++--------- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 8 +- 9 files changed, 596 insertions(+), 154 deletions(-) create mode 100644 src/Infrastructure/IO/include/ESMCI_IO_GDAL.h create mode 100644 src/Infrastructure/IO/src/ESMCI_IO_GDAL.C diff --git a/.gitignore b/.gitignore index 138c7d0697..1a9386fd5a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,7 @@ PET*.ESMF_LogFile /examples/ /src/Infrastructure/IO/PIO/Build/ /src/Infrastructure/IO/PIO/Install/ - +/holding # protex generated files # ########################## *_ccapi.tex diff --git a/gisDev.org b/gisDev.org index f96558388d..8e7716c3fb 100644 --- a/gisDev.org +++ b/gisDev.org @@ -62,12 +62,15 @@ I know that’s a lot of information, so feel free to ask lots of questions. I t moving it shouldn’t be hard to bring this capability in, but there might be some back and forth at the beginning just to get both of us on the same page. -* Structure & Flow - get_elementconn_from... - get_nodecount_from... - get_coords_from... - - +* Parallelization +** Notes: +features and elements need to be defined separately, since a feature may be decomposed into several elements. +** Issues/Questions +*** geographic location of features not ordered. +*** Do we want to sync with a regular lat/lon grid so data are more likely to be on the PET where they're needed? +** get_DS_params +** divvy up feature/element IDs to PETS +** get features for ID bounds * Questions: ** What about CRS and projection to/from GEOS? Will area (spatial extent) be conserved? e.g. if the GIS CRS is curvilinear, is the mapping in ESMF able to handle that? diff --git a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h new file mode 100644 index 0000000000..7f03073e46 --- /dev/null +++ b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h @@ -0,0 +1,148 @@ +// $Id$ +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +// ESMF IO_NetCDF C++ definition include file +// +// (all lines below between the !BOP and !EOP markers will be included in +// the automated document processing.) +//------------------------------------------------------------------------- +// + // these lines prevent this file from being read more than once if it + // ends up being included multiple times + +#ifndef ESMCI_IO_GDAL_H +#define ESMCI_IO_GDAL_H + +//------------------------------------------------------------------------- + + // put any constants or macros which apply to the whole component in this file. + // anything public or esmf-wide should be up higher at the top level + // include files. +#include "ESMCI_Macros.h" + +//------------------------------------------------------------------------- +//BOP +// !CLASS: ESMCI::IO_GDAL - Handles low-level GDAL IO for ESMF internals and user API. +// +// !DESCRIPTION: +// TODO +//------------------------------------------------------------------------- +// +// !USES: +#include "ESMCI_Base.h" // inherited Base class +#include "ESMCI_State.h" + +#include + +#ifdef ESMF_GDAL +#include +#include +#include +#endif + +namespace ESMCI +{ + +// !PUBLIC TYPES: + class IO_GDAL; + +// !PRIVATE TYPES: + + // class definition type + class IO_GDAL : public ESMC_Base { // inherit ESMC_Base class + private: // corresponds to F90 module 'type ESMF_IO_GDAL' members + ESMC_Base *base; // associated object's base + std::string fileName; + State* theState; + +// !PUBLIC MEMBER FUNCTIONS: + + public: + // accessor methods + + // Get the State object + State* getState() { return theState; } + void setState(State* newState) { theState = newState; } + + // Read/Write to support the F90 optional arguments interface + int read(const std::string& fileName); + int write(const std::string& fileName); + + // internal validation + int validate(const char *options=0) const; + + // for testing/debugging + int print(const char *options=0) const; + + // native C++ constructors/destructors + IO_GDAL(void); + // IO_GDAL(const IO_GDAL &io_gdal); TODO + ~IO_GDAL(){destruct();} + private: + void destruct(); + + public: + // friend function to allocate and initialize IO_GDAL object from heap + friend IO_GDAL *ESMCI_IO_GDALCreate(const std::string&, ESMC_Base*, int*); + + // friend function to copy an io_gdal TODO ? + //friend IO_GDAL *ESMCI_IO_GDAL(IO_GDAL*, int*); + + // friend function to de-allocate IO_GDAL + friend int ESMCI_IO_GDALDestroy(IO_GDAL**); + +// !PRIVATE MEMBER FUNCTIONS: +// + private: +// + // < declare private interface methods here > + +#ifdef ESMF_GDAL +// int ncerrToEsmcRc (int ncerr); + ESMC_TypeKind_Flag gdalToEsmcType(OGRFieldType gdalTypeVal); +// nc_type esmcToNcType(ESMC_TypeKind_Flag esmcTypeVal); + +// Array* readArray(NcFile netCdfFile, +// int varIndex, +// int *rc); +// int writeArray(NcFile netCdfFile, +// Array* thisArray, +// int numDims, +// int* dimensions); +#endif + +// +//EOP +//------------------------------------------------------------------------- + +}; // end class IO_GDAL + + // Note: though seemingly redundant with the friend declarations within + // the class definition above, the following declarations are necessary + // to appease some compilers (most notably IBM), as well as ANSI C++. + // These also establish defaults to match F90 optional args. TODO ? + + // friend function to allocate and initialize io from heap + IO_GDAL *ESMCI_IO_GDALCreate(const std::string& name=0, + ESMC_Base* base=0, int* rc=0); + + // friend function to copy an io_netcdf TODO ? + //IO_GDAL *ESMCI_IO_GDALCreate(IO_GDAL *io_netcdf, int *rc=0); + + // friend function to de-allocate clock + int ESMCI_IO_GDALDestroy(IO_GDAL **io_netcdf); + + // friend to restore state TODO ? + //Clock *ESMCI_IO_GDALReadRestart(const std::string& name=0, + //int* rc=0); + +} // namespace ESMCI + +#endif // ESMC_IO_GDAL_H diff --git a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C new file mode 100644 index 0000000000..2605a5788a --- /dev/null +++ b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C @@ -0,0 +1,115 @@ +// $Id$ +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +// ESMC IO_NetCDF method code (body) file +// +//------------------------------------------------------------------------- +// +// !DESCRIPTION: +// +// The code in this file implements the C++ {\tt ESMC\_IO\_GDAL} methods declared +// in the companion file {\tt ESMCI\_IO\_GDAL.h} +// +//------------------------------------------------------------------------- +#define ESMC_FILENAME "ESMCI_IO_GDAL.C" + +// associated class definition file +#include "ESMCI_IO_GDAL.h" + +// higher level, 3rd party or system includes here +#include +#include +#include +#include +#include + +#include "ESMC_Util.h" +#include "ESMCI_LogErr.h" +#include "ESMCI_VM.h" +#include "ESMCI_ArraySpec.h" +#include "ESMCI_LocalArray.h" +#include "ESMCI_Array.h" + +using namespace std; + +//------------------------------------------------------------------------- +// leave the following line as-is; it will insert the cvs ident string +// into the object file for tracking purposes. +static const char *const version = "$Id$"; +//------------------------------------------------------------------------- + +namespace ESMCI +{ +//------------------------------------------------------------------------- + + ESMC_TypeKind_Flag IO_GDAL::gdalToEsmcType(OGRFieldType gdalTypeVal) + { + +#undef ESMC_METHOD +#define ESMC_METHOD "IO_GDAL::gdalToEsmcType" + + ESMC_TypeKind_Flag esmcTypeVal = ESMF_NOKIND; + + // Currently only integer and double (real*8) are implemented + + switch (gdalTypeVal) + { + case OFTInteger: + esmcTypeVal = ESMC_TYPEKIND_I4; + break; + case OFTIntegerList: + // TODO? + esmcTypeVal = ESMF_NOKIND; + break; + case OFTReal: + esmcTypeVal = ESMC_TYPEKIND_R8; + break; + case OFTRealList: + // TODO? + esmcTypeVal = ESMF_NOKIND; + break; + case OFTString: + // TODO? + esmcTypeVal = ESMF_NOKIND; + break; + case OFTStringList: + // TODO? + esmcTypeVal = ESMF_NOKIND; + break; + case OFTBinary: + // TODO? + esmcTypeVal = ESMF_NOKIND; + break; + case OFTDate: + esmcTypeVal = ESMF_NOKIND; + break; + case OFTTime: + esmcTypeVal = ESMF_NOKIND; + break; + case OFTDateTime: + esmcTypeVal = ESMF_NOKIND; + break; + case OFTInteger64: + esmcTypeVal = ESMF_NOKIND; + break; + case OFTInteger64List: + esmcTypeVal = ESMF_NOKIND; + break; + default: + break; + } + + return esmcTypeVal; + } + + +//------------------------------------------------------------------------- + +} // end namespace ESMCI diff --git a/src/Infrastructure/IO/src/makefile b/src/Infrastructure/IO/src/makefile index d66af0ee51..008b76c013 100644 --- a/src/Infrastructure/IO/src/makefile +++ b/src/Infrastructure/IO/src/makefile @@ -2,9 +2,9 @@ ALL: build_here -SOURCEC = ESMCI_IO_NetCDF.C ESMCI_IO.C ESMCI_IO_Handler.C ESMCI_IO_Gridspec.C ESMCI_IO_Scrip.C ESMCI_IO_YAML.C +SOURCEC = ESMCI_IO_NetCDF.C ESMCI_IO.C ESMCI_IO_Handler.C ESMCI_IO_Gridspec.C ESMCI_IO_Scrip.C ESMCI_IO_YAML.C ESMCI_IO_GDAL.C SOURCEF = -STOREH = ESMCI_IO_NetCDF.h ESMCI_IO.h ESMCI_IO_Handler.h ESMCI_IO_Gridspec.h ESMCI_IO_Scrip.h ESMCI_IO_YAML.h +STOREH = ESMCI_IO_NetCDF.h ESMCI_IO.h ESMCI_IO_Handler.h ESMCI_IO_Gridspec.h ESMCI_IO_Scrip.h ESMCI_IO_YAML.h ESMCI_IO_GDAL.h ifdef ESMF_PIO SOURCEC += ESMCI_PIO_Handler.C diff --git a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h index 95bab4f1b6..4b81bedb64 100644 --- a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h +++ b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h @@ -52,12 +52,23 @@ using namespace ESMCI; void open_(); // shapefile routines -void get_dim_from_SHP_file(OGRDataSourceH hDS, char *filename, int &dim); -void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, int *&nodeIDs, int *&elemIDs, - int *&elemConn, int *&numElemConn, - int *totNumElemConn, int *numNodes, int *numElems); +void ESMCI_GDAL_SHP_get_dim_from_file(OGRDataSourceH hDS, char *filename, int &dim); +void ESMCI_GDAL_process_shapefile_serial(OGRDataSourceH hDS, double *&nodeCoords, + int *&nodeIDs, int *&elemIDs, + int *&elemConn, int *&numElemConn, + int *totNumElemConn, int *numNodes, + int *numElems); +void ESMCI_GDAL_process_shapefile_distributed(OGRDataSourceH hDS, + int *nFeatures, int *&featureIDs, int *&globFeatureIDs, + double *&nodeCoords, + int *&nodeIDs, int *&elemIDs, + int *&elemConn, int *&numElemConn, + int *totNumElemConn, int *numNodes, + int *numElems); void ESMCI_mesh_create_from_SHP_file(); +void ESMCI_GDAL_SHP_get_feature_info(OGRDataSourceH hDS, int *nFeatures, int *&FeatureIDs); + #endif // ifdef ESMF_GDAL #endif // ESMCI_GDAL_UTIL_H diff --git a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C index 3ec94455f9..0e85619fcb 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C @@ -60,21 +60,19 @@ //----------------------------------------------------------------------------- using namespace ESMCI; -int i; - -int ftr = 0; +int elm = 0; int totpoints = 0; //int numNodes, numElems; //double *nodeXCoords,*nodeYCoords; -// Routines +// Local Routines int processPolygon(OGRGeometryH fGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn); int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn); // Get the dimension of the mesh in the SHP file // (This dimension is both the pdim and orig_sdim of the mesh) -void get_dim_from_SHP_file(OGRDataSourceH hDS, char *filename, int &dim) { +void ESMCI_GDAL_SHP_get_dim_from_file(OGRDataSourceH hDS, char *filename, int &dim) { #undef ESMC_METHOD #define ESMC_METHOD "get_dim_from_SHP_file()" @@ -86,9 +84,42 @@ void get_dim_from_SHP_file(OGRDataSourceH hDS, char *filename, int &dim) { return; } -void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, - int *&nodeIDs, int *&elemIDs, int *&elemConn, - int *&numElemConn, int *totNumElemConn, int *numNodes, int *numElems) { +void ESMCI_GDAL_SHP_get_feature_info(OGRDataSourceH hDS, int *nFeatures, int *&FeatureIDs) { + OGRLayerH hLayer; + OGRFeatureH hFeature; + + // Access the layer (associate the handle) + // Assume that index 0 is the layer we want. + hLayer = OGR_DS_GetLayer( hDS, 0 ); + + // Get the number of elements + *nFeatures = OGR_L_GetFeatureCount(hLayer,1); + + // -- elemIDs + FeatureIDs = (int *)malloc(*nFeatures*sizeof(int)); + + for (int i=0;i<*nFeatures;i++) { + hFeature = OGR_L_GetNextFeature(hLayer); + FeatureIDs[i] = OGR_F_GetFID(hFeature); + OGR_F_Destroy( hFeature ); + } + + + return; +} + +void ESMCI_GDAL_process_shapefile_serial( +// inputs + OGRDataSourceH hDS, +// outputs + double *&nodeCoords, + int *&nodeIDs, + int *&elemIDs, + int *&elemConn, + int *&numElemConn, + int *totNumElemConn, + int *numNodes, + int *numElems) { int nElements; // int *nodeIDs; // int *elemConn;//,*numElemConn; @@ -126,7 +157,7 @@ void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring - printf("Feature %d geom: %d (Polygon is %d)\n",ftr+1,wkbFlatten(OGR_G_GetGeometryType(hGeom)),wkbPolygon); + printf("Feature %d geom: %d (Polygon is %d)\n",elm+1,wkbFlatten(OGR_G_GetGeometryType(hGeom)),wkbPolygon); // ADD POLYGON if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { @@ -147,7 +178,7 @@ void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, *numNodes = totpoints; // At this point, un-trimmed. Points will repeat *totNumElemConn = totpoints; // -- numElems - *numElems = ftr; // This is an assumption! + *numElems = elm; // This is an assumption! // -- nodeIDs nodeIDs = new int[totpoints]; // nodeIDs = (int *)malloc(totpoints*sizeof(int)); @@ -162,7 +193,7 @@ void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, numElemConn = (int *)malloc(*numElems*sizeof(int)); // Reset counters - ftr = 0; // Zero features + elm = 0; // Zero features totpoints = 0; // Zero number of points // Rewind to the beginning, just in case @@ -189,30 +220,160 @@ void process_shapefile(OGRDataSourceH hDS, double *&nodeCoords, OGR_F_Destroy( hFeature ); } - printf("\n"); - printf("N Features: %d\n",ftr); - printf("N Points: %d\n",totpoints); - printf("numNodes: %d\n",numNodes); +// printf("\n"); +// printf("N Features: %d\n",elm); +// printf("N Points: %d\n",totpoints); +// printf("numNodes: %d\n",numNodes); nodeCoords= new double[2*totpoints]; // Pass OGR Values to Mesh arrays printf("Coords: \n"); int j = 0; - for (i=0;i=0; i--) { + for (int i = points-2; i >=0; i--) { nodeXCoords[totpoints+ii] = OGR_G_GetX(fGeom, i); nodeYCoords[totpoints+ii] = OGR_G_GetY(fGeom, i); nodeIDs[totpoints+ii] = totpoints+ii+1; // increment from 1, not 0 elemConn[totpoints+ii] = totpoints+ii+1; ii++; } - numElemConn[ftr] = points-1; - elemIDs[ftr] = ftr+1; + numElemConn[elm] = points-1; + elemIDs[elm] = elm+1; } // Successful query - ftr++; // Increment the number of features. + elm++; // Increment the number of features. totpoints = totpoints+points-1; // Increment total number of points return 0; diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index b8a68d1999..18476bd7e7 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -1318,128 +1318,132 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, int pet_count = vm->getPetCount(); // Bound all of this by local_pet == 0 for now (MSL) - if (local_pet == 0) { - // DEBUG OUTPUT filename - printf("In shapefile method filename=%s\n",filename); + // if (local_pet == 0) { + // // DEBUG OUTPUT filename + // printf("In shapefile method filename=%s\n",filename); + // } + + // Open file and create datasource (DS) + OGRDataSourceH hDS; + if (access(filename, F_OK) == 0) { + OGRRegisterAll(); // register all the drivers + hDS = OGROpen( filename, FALSE, NULL ); + if( hDS == NULL ) + { + printf( "Open failed on pet %d: %s, %d\n", local_pet, CPLGetLastErrorMsg(), CPLGetLastErrorNo() ); + Throw(); + } + } else if (local_pet == 0) { + printf("Cannot access shapefile\n"); + Throw(); + } - //// Fill in code getting things from shapefile and creating parts of the Mesh here - - // Open file - OGRDataSourceH hDS; - if (access(filename, F_OK) == 0) { - OGRRegisterAll(); // register all the drivers - hDS = OGROpen( filename, FALSE, NULL ); - if( hDS == NULL ) - { - printf( "Open failed: %s, %d\n", CPLGetLastErrorMsg(), CPLGetLastErrorNo() ); - Throw(); - } - } else { - printf("Cannot access shapefile\n"); - Throw(); - } + // Get DIM var - currently forced to 2D + int dim; + ESMCI_GDAL_SHP_get_dim_from_file(hDS, filename, dim); - // Get DIM var - currently forced to 2D - int dim; - get_dim_from_SHP_file(hDS, filename, dim); - - // Get shapefile params - int num_nodes; - int num_elems=0, totNumElemConn=0; - int *numElemConn=NULL, *elemConn=NULL; - double *nodeCoords=NULL; - int *node_IDs=NULL; - int *elem_IDs=NULL; - - // Processes polygons in hDS. Polygons are flattened to 2D - process_shapefile(hDS,nodeCoords,node_IDs,elem_IDs,elemConn,numElemConn, - &totNumElemConn, &num_nodes, &num_elems); - - // TBD: Coord system conversion - - /* At this point, we've read the shapfile and defined - - num_nodes - - num_elems - - nodeCoords - - numElemConn - - node_IDs - */ - -//\\ printf("totnumelemconn: %d\n", totNumElemConn); -//\\ printf("num_nodes: %d\n", num_nodes); -//\\ printf("num_elems: %d\n", num_elems); -//\\ int i; -//\\ for (i=0;i<2*num_nodes;i+=2) { -//\\ printf("nodeCoords %.2f, %.2f\n",nodeCoords[i],nodeCoords[i+1]); -//\\ } - - // Convert mesh dim from file into pdim and orig_sdim to use in mesh create - int pdim, orig_sdim; - if (dim == 2) { - pdim=orig_sdim=2; - } else if (dim == 3) { - pdim=orig_sdim=3; - } else { - Throw() << "Meshes can only be created with dim=2 or 3."; - } - - // Get coordsys from file - ESMC_CoordSys_Flag coord_sys_mesh=ESMC_COORDSYS_SPH_DEG; // Assume "degrees" for now. -// NOTE DEFINED YET get_coordsys_from_SHP_file(pioFileDesc, filename, dim, nodeCoord_ids, coord_sys_file); + // Get shapefile params + int num_nodes; + int num_elems=0; + int totNumElemConn=0; + int *numElemConn=NULL; + int *elemConn=NULL; + double *nodeCoords=NULL; + int *node_IDs=NULL; + int *elem_IDs=NULL; - // Create Mesh - ESMCI_meshcreate(out_mesh, &pdim, &orig_sdim, &coord_sys_mesh, &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - &localrc)) throw localrc; + // Processes polygons in hDS. Polygons are flattened to 2D +// process_shapefile_serial(hDS,nodeCoords,node_IDs,elem_IDs,elemConn,numElemConn, +// &totNumElemConn, &num_nodes, &num_elems); - // printf("Finished creating mesh: %d\n", localrc); + // 1) Get DS global params: number of features & feature IDs - // Add nodes - ESMCI_meshaddnodes(out_mesh, &num_nodes, node_IDs, - nodeCoords, NULL, NULL, - &coord_sys_mesh, &orig_sdim, - &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - &localrc)) throw localrc; - - // printf("Finished adding nodes: %d\n", localrc); - - // Add elements - // !!! None of the elements have shared edges. - int areaPresent = 0; - int centerCoordsPresent=0; - ESMCI_meshaddelements(out_mesh, - &num_elems, elem_IDs, numElemConn, //elementType, <- using numElemConn in place of elementType assumes 2D!! - NULL, // No mask - &areaPresent, NULL, // No areas - ¢erCoordsPresent, NULL, // No center coords - &totNumElemConn, elemConn, - &coord_sys_mesh, &orig_sdim, &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - &localrc)) throw localrc; + int nFeatures; + int *globalFeature_IDs=NULL; + ESMCI_GDAL_SHP_get_feature_info(hDS, &nFeatures, globalFeature_IDs); - // printf("Finished adding elements: %d\n", localrc); + // Get positions at which to read element information + std::vector feature_ids_vec; + get_ids_divided_evenly_across_pets(nFeatures, local_pet, pet_count, feature_ids_vec); - // Cleanup - OGR_DS_Destroy( hDS ); + // Assign vector info to pointer, because PIO and mesh calls don't accept vectors + int num_features=0; // local PET + int *feature_IDs=NULL; // local PET + if (!feature_ids_vec.empty()) { + num_features=feature_ids_vec.size(); // local to this pet + feature_IDs=&feature_ids_vec[0]; + } - delete [] elem_IDs; - delete [] elemConn; - delete [] node_IDs; - delete [] numElemConn; - delete [] nodeCoords; + // Processes polygons in hDS. Polygons are flattened to 2D + ESMCI_GDAL_process_shapefile_distributed(hDS,&num_features,feature_IDs,globalFeature_IDs, + nodeCoords,node_IDs,elem_IDs, + elemConn,numElemConn, + &totNumElemConn, &num_nodes, &num_elems); + // TBD: Coord system conversion + + /* At this point, we've read the shapfile and defined + - num_nodes + - num_elems + - nodeCoords + - numElemConn + - node_IDs + */ + // Convert mesh dim from file into pdim and orig_sdim to use in mesh create + int pdim, orig_sdim; + if (dim == 2) { + pdim=orig_sdim=2; + } else if (dim == 3) { + pdim=orig_sdim=3; } else { - // Set return code -// if (rc!=NULL) *rc = ESMF_SUCCESS; - } + Throw() << "Meshes can only be created with dim=2 or 3."; + } + + // Get coordsys from file + ESMC_CoordSys_Flag coord_sys_mesh=ESMC_COORDSYS_SPH_DEG; // Assume "degrees" for now. + // NOTE DEFINED YET get_coordsys_from_SHP_file(pioFileDesc, filename, dim, nodeCoord_ids, coord_sys_file); - // Return an error, because this isn't implemented yet - // TODO: GET RID OF THE FOLLOWING LINE WHEN THIS SUBROUTINE IS CREATING A VALID MESH - //if (ESMC_LogDefault.MsgFoundError(ESMC_RC_NOT_IMPL, - // "Creating a Mesh from a shapefile format file not finished yet.", - // ESMC_CONTEXT, &localrc)) throw localrc; - + // Create Mesh + ESMCI_meshcreate(out_mesh, &pdim, &orig_sdim, &coord_sys_mesh, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // printf("Finished creating mesh: %d\n", localrc); + + // Add nodes + ESMCI_meshaddnodes(out_mesh, &num_nodes, node_IDs, + nodeCoords, NULL, NULL, + &coord_sys_mesh, &orig_sdim, + &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // printf("Finished adding nodes: %d\n", localrc); + + // Add elements + // !!! None of the elements have shared edges. + int areaPresent = 0; + int centerCoordsPresent=0; + ESMCI_meshaddelements(out_mesh, + &num_elems, elem_IDs, numElemConn, //elementType, <- using numElemConn in place of elementType assumes 2D!! + NULL, // No mask + &areaPresent, NULL, // No areas + ¢erCoordsPresent, NULL, // No center coords + &totNumElemConn, elemConn, + &coord_sys_mesh, &orig_sdim, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) throw localrc; + + // printf("Finished adding elements: %d\n", localrc); + + // Cleanup + OGR_DS_Destroy( hDS ); + + delete [] elem_IDs; + delete [] elemConn; + delete [] node_IDs; + delete [] numElemConn; + delete [] nodeCoords; } catch(std::exception &x) { diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index e265df576c..4f720f4806 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -4564,7 +4564,7 @@ subroutine check_mesh_from_sph_3x3_UG_file(correct, rc) elemMask=(/1,0,1/) endif - endif + endif ! Create distgrid to ensure that elements are created on the @@ -6913,15 +6913,15 @@ subroutine test_create_mesh_from_SH_file(correct, rc) if (rc /= ESMF_SUCCESS) return ! Create Mesh from shape file - mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & + mesh=ESMF_MeshCreate("data/complex_3.shp", & fileformat=ESMF_FILEFORMAT_SHAPEFILE, & rc=rc) if (rc /= ESMF_SUCCESS) return !! Write mesh for debugging - call ESMF_MeshWrite(mesh,"cb_2018_us_county_500k",rc=rc) - if (rc /= ESMF_SUCCESS) return +! call ESMF_MeshWrite(mesh,"complex_3",rc=rc) +! if (rc /= ESMF_SUCCESS) return ! Get rid of Mesh call ESMF_MeshDestroy(mesh, rc=rc) From 4a8734f7cb1c1bc852e97168e934281469693f5d Mon Sep 17 00:00:00 2001 From: Michael Long Date: Tue, 11 Jul 2023 14:16:08 -0400 Subject: [PATCH 11/58] Safety commit while things are in major flux. Working on parallel data/field read from shapefile MSL --- gisDev.org | 9 + settings.sh | 2 + .../IO/include/ESMCI_GDAL_Handler.h | 193 + src/Infrastructure/IO/include/ESMCI_IO_GDAL.h | 28 +- .../IO/src/ESMCI_GDAL_Handler.C | 2360 ++++++++ src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 3 + src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 11 +- src/Infrastructure/IO/src/makefile | 5 + .../IO/tests/ESMF_IO_MultitileUTest.Log | 0 .../Mesh/tests/ESMCI_MeshCapGenUTest.C | 537 ++ .../Mesh/tests/ESMCI_MeshCapRegridGenUTest.C | 5091 +++++++++++++++++ .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 6 +- 12 files changed, 8227 insertions(+), 18 deletions(-) create mode 100644 src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h create mode 100644 src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C create mode 100644 src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.Log create mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C create mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C diff --git a/gisDev.org b/gisDev.org index 8e7716c3fb..bc4fc5fea8 100644 --- a/gisDev.org +++ b/gisDev.org @@ -71,6 +71,15 @@ features and elements need to be defined separately, since a feature may be deco ** get_DS_params ** divvy up feature/element IDs to PETS ** get features for ID bounds +* Field Read +ESMF_FieldRead() +-- ESMF_IORead() +-- -- c_ESMC_IORead() +-- -- -- (*ptr)->read() +-- -- -- -- IO::read() +-- -- -- -- -- IO_Handler::arrayRead() +-- -- -- -- -- -- PIO_Handler::arrayReadOneTileFile() +-- -- -- -- -- -- -- PIOc_Read_Array() * Questions: ** What about CRS and projection to/from GEOS? Will area (spatial extent) be conserved? e.g. if the GIS CRS is curvilinear, is the mapping in ESMF able to handle that? diff --git a/settings.sh b/settings.sh index 4af79aa5de..6e8a70475d 100755 --- a/settings.sh +++ b/settings.sh @@ -11,3 +11,5 @@ export ESMF_GDAL_INCLUDE=/usr/include/gdal export ESMF_GDAL_LIBPATH=/usr/lib64 #export ESMF_SHAPEFILE_LIBS=-lshp export ESMF_GDAL_LIBS=-lgdal +export ESMF_BOPT=g +export ESMF_CXXCOMPILEOPTS="-DESMFIO_DEBUG" diff --git a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h new file mode 100644 index 0000000000..f96df3c629 --- /dev/null +++ b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h @@ -0,0 +1,193 @@ +// $Id$ +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//------------------------------------------------------------------------- +// (all lines below between the !BOP and !EOP markers will be included in +// the automated document processing.) +//------------------------------------------------------------------------- +// these lines prevent this file from being read more than once if it +// ends up being included multiple times + +#ifndef __ESMCI_GDAL_HANDLER_H +#define __ESMCI_GDAL_HANDLER_H + +//------------------------------------------------------------------------- +//BOPI +// !CLASS: ESMCI::GDAL_Handler - IO +// +// !DESCRIPTION: +// +// The code in this file defines the C++ {\tt GDAL\_Handler} members and method +// signatures (prototypes). The companion file {\tt ESMCI\_GDAL\_Handler.C} +// contains the full code (bodies) for the {\tt GDAL\_Handler} methods. +// {\tt GDAL\_Handler} is derived from the {\tt IO\_Handler} +// base class. +// +//EOPI +//------------------------------------------------------------------------- + +#include "ESMCI_VM.h" +#include "ESMCI_Array.h" +#include "ESMC_Util.h" +#include "ESMCI_IO_Handler.h" // IO_Handler is superclass to GDAL_Handler +#include "mpi.h" + +#include + +// GDAL include files +#include +#include +#include + +//------------------------------------------------------------------------- + +namespace ESMCI { + + // classes and structs + + class GDAL_Handler; // The main class for implementing GDAL functionality + + // class definitions + + //=========================================================================== + + //=========================================================================== + + //=========================================================================== + class GDAL_Handler : public IO_Handler { // inherits from IO_Handler class + + private: + + // global information + static std::vector activeGdalInstances; + int gdalSystemDesc; // Descriptor for initialized GDAL inst. + int *gdalFileDesc; // Descriptor(s) for open GDAL file (typically just one, but multiple for I/O of multi-tile arrays) + MPI_Comm communicator; + int my_rank; + int num_iotasks; + int stride; + int rearr; + int base; + bool *new_file; // Typically just one value, but multiple for I/O of multi-tile arrays + + public: + // native constructor and destructor + GDAL_Handler(ESMC_IOFmt_Flag fmtArg, int ntilesArg, int *rc); + // Static initialize and finalize routines for GDAL + static void initialize(int comp_rank, MPI_Comm comp_comm, + int num_iotasks, + int stride, int rearr, int *base_p, int *rc = NULL); + static void finalize(int *rc = NULL); + // Be able to see if GDAL is initialized + static ESMC_Logical isGdalInitialized(void); + // Non-static member for default initialization + int initializeVM(void); + public: + ~GDAL_Handler() { destruct(); } + private: + void destruct(void); + public: + + // read() + // Non-atomic reads which are only successful on an open IO stream + void arrayReadOneTileFile(Array *arr_p, int tile, const char * const name, + int *timeslice = NULL, int *rc = NULL); + + // write() + // Non-atomic writes which are only successful on an open IO stream + void arrayWriteOneTileFile(Array *arr_p, int tile, const char * const name, + const std::vector &dimLabels, + int *timeslice = NULL, + const ESMCI::Info *varAttPack = NULL, + const ESMCI::Info *gblAttPack = NULL, + int *rc = NULL); + + // get() and set() + public: + + // match() + static bool match(GDAL_Handler const * const ioh1, + GDAL_Handler const * const ioh2, + int *rc = NULL) { + if (rc != (int *)NULL) { + *rc = ESMF_SUCCESS; + } + return (ioh1 == ioh2); + } + + // open() and close() + void openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); + ESMC_Logical isOpen(int tile); + ESMC_Logical isNewFile(int tile) { // note 1-based indexing for tile + return (new_file[tile-1] ? ESMF_TRUE : ESMF_FALSE); + } + void flushOneTileFile(int tile, int *rc = NULL); + void closeOneTileFile(int tile, int *rc = NULL); + + private: + int getIODesc(int iosys, Array *arr_p, int tile, + int ** iodims = (int **)NULL, + int *nioDims = (int *)NULL, + int ** arrdims = (int **)NULL, + int *narrDims = (int *)NULL, + int *basegdaltype = (int *)NULL, + int *rc = (int *)NULL); + void attPackPut (int vardesc, const ESMCI::Info *attPack, int tile, int *rc); + + public: + // Error recording routine + static bool CheckGDALError(int gdalRetCode, + int line, const char * const file, + const char * const method, + const std::string &fmtStr, + int rc_code, + int *rc, + bool warn = false); + +// Don't know yet if we will need these +#if 0 + private: + // Attribute writing + int writeStartElement(const std::string& name, + const std::string& value, + const int indentLevel, + const int nPairs, ...); // nPairs of + // (char *attrName, char *attrValue) + + int writeElement(const std::string& name, + const std::string& value, + const int indentLevel, + const int nPairs, ...); // nPairs of + // (char *attrName, char *attrValue) + + int writeEndElement(const std::string& name, + const int indentLevel); + + // write an XML comment + int writeComment(const std::string& comment, const int indentLevel=0); + + int write(int fileNameLen, const char* fileName, + const char* outChars, int flag); +#endif // 0 + }; // class IO_Handler + //=========================================================================== + +// Macros + +// For error checking +#define CHECKGDALERROR(_err, _str, _rc_code, _rc) \ + GDAL_Handler::CheckGDALError((_err), ESMC_CONTEXT, (_str), _rc_code, &(_rc)) +#define CHECKGDALWARN(_err, _str, _rc_code, _rc) \ + GDAL_Handler::CheckGDALError((_err), ESMC_CONTEXT, (_str), _rc_code, &(_rc), true) + + +} // namespace ESMCI + +#endif // __ESMCI_GDAL_HANDLER_H diff --git a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h index 7f03073e46..44274c2d69 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h @@ -50,6 +50,18 @@ namespace ESMCI { +/** + * These are the supported output data rearrangement methods. + */ +enum GDAL_REARRANGERS +{ + /** Box rearranger. */ + GDAL_REARR_BOX = 1, + + /** Subset rearranger. */ + GDAL_REARR_SUBSET = 2 +}; + // !PUBLIC TYPES: class IO_GDAL; @@ -105,17 +117,7 @@ namespace ESMCI // < declare private interface methods here > #ifdef ESMF_GDAL -// int ncerrToEsmcRc (int ncerr); ESMC_TypeKind_Flag gdalToEsmcType(OGRFieldType gdalTypeVal); -// nc_type esmcToNcType(ESMC_TypeKind_Flag esmcTypeVal); - -// Array* readArray(NcFile netCdfFile, -// int varIndex, -// int *rc); -// int writeArray(NcFile netCdfFile, -// Array* thisArray, -// int numDims, -// int* dimensions); #endif // @@ -143,6 +145,12 @@ namespace ESMCI //Clock *ESMCI_IO_GDALReadRestart(const std::string& name=0, //int* rc=0); + int GDALc_finalize(int instance); + int GDALc_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp); + + int GDALc_inq_varid(int ncid, const char *name, int *varidp); + int GDALc_inq_vardimid(int ncid, int varid, int *dimidsp); + } // namespace ESMCI #endif // ESMC_IO_GDAL_H diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C new file mode 100644 index 0000000000..7ebe79111d --- /dev/null +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -0,0 +1,2360 @@ +// $Id$ +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//============================================================================== +#define ESMC_FILENAME "ESMCI_GDAL_Handler.C" +//============================================================================== +// +// ESMC IO method code (body) file +// +//------------------------------------------------------------------------- +// +// !DESCRIPTION: +// +// The code in this file implements the C++ {\tt ESMC\_GDAL_Handler} methods +// declared in the companion file {\tt ESMCI\_GDAL_Handler.h} +// +//------------------------------------------------------------------------- +#define GDAL_DEBUG_LEVEL 0 +// include associated header file +#include "ESMCI_GDAL_Handler.h" + +// include generic services header file +#include "ESMCI_IO_GDAL.h" + +// higher level, 3rd party or system includes here +#include +#include +#include +#include +#include + +#include +#include + +// other ESMF include files here. +#include "ESMCI_Macros.h" +#include "ESMCI_LogErr.h" +#include "ESMCI_Info.h" +#include "json.hpp" +#include "ESMCI_TraceMacros.h" + +#include "esmf_io_debug.h" + +using json = nlohmann::json; // Convenience rename for JSON namespace. + +//------------------------------------------------------------------------- +// leave the following line as-is; it will insert the cvs ident string +// into the object file for tracking purposes. +static const char *const version = "$Id$"; +//------------------------------------------------------------------------- + +namespace ESMCI +{ + +// +//------------------------------------------------------------------------- +// +// private helper class for managing GDAL I/O Descriptors +// +//------------------------------------------------------------------------- +// + class GDAL_IODescHandler { + private: + static std::vector activeGdalIoDescriptors; + int ios; // GDAL IO system instance for this descriptor + int io_descriptor; // GDAL IO descriptor + int nDims; // The number of dimensions for Array IO + int *dims; // The shape of the Array IO + int basegdaltype; // GDAL version of Array data type + Array *array_p; // The array matched to this descriptor + int tile; // The tile number in the array for this descriptor (1-based indexing) + int arrayRank; // The rank of array_p + int *arrayShape; // The shape of array_p + public: + GDAL_IODescHandler(int iosArg, Array *arrayArg) { + ios = iosArg; + io_descriptor = (int)NULL; + array_p = arrayArg; + nDims = 0; + dims = (int *)NULL; + tile = 0; + arrayRank = 0; + arrayShape = (int *)NULL; + } + // These definitions are at the end of the file + public: + ~GDAL_IODescHandler(); + static void finalize(void); + static int constructGdalDecomp(int iosys, Array *arr_p, int tile, + int *newDecomp_p); + static int freeGdalDecomp(int *decomp_p); + static int getDims(const int &iodesc, + int * nioDims = (int *)NULL, + int ** ioDims = (int **)NULL, + int * narrDims = (int *)NULL, + int ** arrDims = (int **)NULL); + static int getIOType(const int &iodesc, int *rc = (int *)NULL); + static int getIODesc(int iosys, + Array *arrayArg, int tileArg, int *rc = (int *)NULL); + }; + +// +//------------------------------------------------------------------------- +// +// class variables +// +//------------------------------------------------------------------------- +// + + std::vector GDAL_Handler::activeGdalInstances; + std::vector GDAL_IODescHandler::activeGdalIoDescriptors; + +// +//------------------------------------------------------------------------- +// +// initialize and finalize +// +//------------------------------------------------------------------------- +// + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::initialize()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::initialize +// +// !INTERFACE: +void GDAL_Handler::initialize ( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + int comp_rank, // (in) - local PE rank + MPI_Comm comp_comm, // (in) - MPI communicator for IO + int num_iotasks, // (in) - Number of IO tasks + int stride, // (in) - IO task stride + int rearr, // (in) - rearrangement type + int *base_p, // (in) - base option (IO task offset) + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Create an active, initialized GDAL instance. +// GDAL is initialized based on the input arguments. However, if a +// compatible GDAL iosystem is already initialized, then nothing is done. +// This is a collective call. Input parameters are read on comp_rank=0, +// values on other tasks are ignored. ALL PEs which will be participating +// in future I/O calls with this instance must participate in the call. +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + int base; + bool instanceFound = false; // try to find a GDAL sys to reuse + int instance = 0; + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + PRINTPOS; + if (base_p != (int *)NULL) { + base = *base_p; + } else { + base = 1; + } + + try { + + if (!instanceFound) { + PRINTMSG("Before GDALc_Init_Intracomm, num_iotasks = " << num_iotasks); +// GDALc_Init_Intracomm(comp_comm, num_iotasks, +// stride, base, rearr, &instance); + PRINTMSG("After GDALc_Init_Intracomm, instance = " << instance); + // If we get here, hopefully everything is OK. + if (instance != 0) { +#ifdef ESMFIO_FILESYSTEM_LUSTRE + GDALc_set_hint(instance, "romio_ds_read", "disable"); + GDALc_set_hint(instance, "romio_ds_write", "disable"); +#endif +#ifdef ESMFIO_FILESYSTEM_GPFS + GDALc_set_hint(instance, "ibm_largeblock_io", "true"); +#endif + + // Set the error handling to return GDAL errors + // Just return error (error code may be different on different PEs). + // Broadcast the error to all PEs (consistant error handling) +// GDALc_Set_IOSystem_Error_Handling(instance, GDAL_BCAST_ERROR); + PRINTMSG("After GDALc_Set_IOSystem_Error_Handling"); + // Add the instance to the global list + GDAL_Handler::activeGdalInstances.push_back(instance); + PRINTMSG("push_back"); + localrc = ESMF_SUCCESS; + } else { + // Something went wrong (this really shouldn't happen) + ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, "Unknown error in GDALc_Init_Intracomm", + ESMC_CONTEXT, rc); + return; + } + } + } catch (int catchrc) { + // catch standard ESMF return code + PRINTMSG("Exception: " << catchrc); + ESMC_LogDefault.MsgFoundError(catchrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + rc); + return; + } catch (...) { + PRINTMSG("Unknown exception"); + ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, "- Caught exception", + ESMC_CONTEXT, rc); + return; + } + + // return successfully + if (rc != NULL) { + *rc = localrc; + } +} // GDAL_Handler::initialize() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::initializeVM()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::initializeVM +// +// !INTERFACE: +int GDAL_Handler::initializeVM (void +// +// !RETURN VALUE: +// +// int return code +// +// !ARGUMENTS: +// + ) { +// +// !DESCRIPTION: +// Create an active, initialized GDAL instance. +// GDAL is initialized based on defaults gleaned from the VM. However, if a +// compatible GDAL iosystem is already initialized, then nothing is done. +// This is a collective call. Input parameters are read on comp_rank=0, +// values on other tasks are ignored. ALL PEs which will be participating +// in future I/O calls with this instance must participate in the call. +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + int rc = ESMF_RC_NOT_IMPL; // return code + bool instanceFound = false; // try to find a GDAL sys to reuse + + try { + if (!instanceFound) { + int localrc; + VM *vm = VM::getCurrent(&localrc); + if (ESMC_LogDefault.MsgFoundError (localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &rc)) + return rc; + communicator = vm->getMpi_c(); + my_rank = vm->getLocalPet(); + + // Figure out the inputs for the initialize call + int numtasks = vm->getPetCount(); + stride = vm->getSsiMaxPetCount(); + base = 0; // IO tasks start with base and are every stride tasks until num_iotasks. + if (numtasks > stride){ + num_iotasks = int(numtasks/stride); + rearr = GDAL_REARR_BOX; + }else{ + num_iotasks = numtasks > 32 ? 32:numtasks; + stride = numtasks/num_iotasks; + rearr = GDAL_REARR_BOX; + } + + // Call the static function + GDAL_Handler::initialize(my_rank, communicator, num_iotasks, + stride, rearr, &base, &rc); + PRINTMSG("After initialize, rc = " << rc); + if (ESMF_SUCCESS == rc) { + PRINTMSG("Looking for active instance, size = " << activeGdalInstances.size()); + gdalSystemDesc = GDAL_Handler::activeGdalInstances.back(); + PRINTMSG("Fetched GDAL system descriptor, " << (void *)gdalSystemDesc); + } + } + } catch (int catchrc) { + // catch standard ESMF return code + PRINTMSG("Exception: " << catchrc); + ESMC_LogDefault.MsgFoundError(catchrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &rc); + return rc; + } catch (...) { + PRINTMSG("Unknown exception"); + ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, "- Caught exception", + ESMC_CONTEXT, &rc); + return rc; + } + + return rc; +} // GDAL_Handler::initializeVM() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::finalize()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::finalize +// +// !INTERFACE: +void GDAL_Handler::finalize ( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Tear down all active, initialized GDAL instances. +// +//EOPI +//----------------------------------------------------------------------------- + int gdalrc; + int localrc = ESMF_SUCCESS; // local return code + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTMSG(""); + try { + // Close any open IO descriptors before turning off the instances + GDAL_IODescHandler::finalize(); + } catch(int lrc) { + // catch standard ESMF return code + ESMC_LogDefault.MsgFoundError(lrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc); + return; + } catch(...) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, "- Caught exception", + ESMC_CONTEXT, rc); + return; + } + try { + // Now, close any open GDAL instances + while(!GDAL_Handler::activeGdalInstances.empty()) { + int instance = GDAL_Handler::activeGdalInstances.back(); + gdalrc = GDALc_finalize(instance); + // Even if we have an error but log and keep going to try and shut + // down other GDAL instances + CHECKGDALWARN(gdalrc, "Error shutting down GDAL instance", + ESMF_RC_FILE_UNEXPECTED, localrc); + + GDAL_Handler::activeGdalInstances.pop_back(); + } + } catch(int lrc) { + // catch standard ESMF return code + ESMC_LogDefault.MsgFoundError(lrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc); + return; + } catch(...) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, "- Caught exception", + ESMC_CONTEXT, rc); + return; + } + + // return successfully + if (rc != NULL) { + *rc = localrc; + } +} // GDAL_Handler::finalize() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::isGdalInitialized()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::isGdalInitialized +// +// !INTERFACE: +ESMC_Logical GDAL_Handler::isGdalInitialized (void +// +// !RETURN VALUE: +// +// ESMC_Logical ESMF_TRUE if GDAL is initialized, ESMF_FALSE otherwise +// +// !ARGUMENTS: +// + ) { +// +// !DESCRIPTION: +// Indicate whether or not GDAL has been initialized. +// NB: This does not guarantee that the initialization is appropriate +// for the desired I/O operations. +// +//EOPI +//----------------------------------------------------------------------------- + if(activeGdalInstances.empty()) { + return ESMF_FALSE; + } else { + return ESMF_TRUE; + } +} // GDAL_Handler::isGdalInitialized() +//----------------------------------------------------------------------------- + +// +//------------------------------------------------------------------------- +// +// constructors and destruct() +// +//------------------------------------------------------------------------- +// + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::GDAL_Handler()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::GDAL_Handler - constructor +// +// !INTERFACE: +GDAL_Handler::GDAL_Handler( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + ESMC_IOFmt_Flag fmtArg, // (in) - File format for GDAL to use + int ntilesArg, // (in) - Number of tiles in arrays handled by this object + int *rc // (out) - Error return code + ) : IO_Handler(fmtArg, ntilesArg) { +// +// !DESCRIPTION: +// Construct the internal information structure of an ESMCI::GDAL_Handler +// object. +// No error checking wrt consistency of input arguments is needed because +// the GDAL_Handler constructor is only to be called by IO_Handler::create() +// interfaces which are responsible for providing consistent arguments +// to this layer. +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + try { + + // fill in the GDAL_Handler object + gdalSystemDesc = 0; + gdalFileDesc = new int[ntilesArg]; + for (int i = 0; i < ntilesArg; ++i) { + gdalFileDesc[i] = 0; + } + localrc = ESMF_SUCCESS; + new_file = new bool[ntilesArg]; + for (int i = 0; i < ntilesArg; ++i) { + new_file[i] = false; + } + // Get the rest from initialize + localrc = initializeVM(); + + } catch (int lrc) { + // catch standard ESMF return code + ESMC_LogDefault.MsgFoundError(lrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc); + return; + } catch (...) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, "- Caught exception", + ESMC_CONTEXT, rc); + return; + } + + // return successfully + if (rc != NULL) { + *rc = localrc; + } +} // GDAL_Handler::GDAL_Handler() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::destruct()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::destruct - tear down GDAL handler +// +// !INTERFACE: +void GDAL_Handler::destruct (void +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + ) { +// +// !DESCRIPTION: +// Close any open files and recover resources. +// +//EOPI +//----------------------------------------------------------------------------- + int localrc; // Only for debug! + PRINTPOS; + // Make sure the file is closed (note that it's okay to call this even if the file is already closed) + PRINTMSG(" (" << my_rank << "): closing file"); + close((int *)NULL); // Don't care about an error, continue with cleanup + // kill the pointer to the GDAL_Handler object + // NB: This does not shutdown the GDAL instance, it may be reused. + gdalSystemDesc = 0; + // Deallocate some memory + delete[] gdalFileDesc; + delete[] new_file; +} // GDAL_Handler::destruct() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::arrayReadOneTileFile()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::arrayReadOneTileFile - Read an array from a file, for the given tile +// +// !INTERFACE: +void GDAL_Handler::arrayReadOneTileFile( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + Array *arr_p, // (inout) - Destination of read + int tile, // (in) - Tile we are reading (1-based indexing) + const char * const name, // (in) - Optional array name + int *timeslice, // (in) - Optional timeslice + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Read data from field from the open file for the given tile. +// For typical single-tile arrays, this will just be called once per arrayRead, with tile=1. +// If timeslice is not NULL, it should point to an integer representing the +// timeslice to read from the Array. +// +//EOPI +//----------------------------------------------------------------------------- + int localrc = ESMF_RC_NOT_IMPL; // local return code + int gdalrc; // GDAL error value + int * ioDims; // Array IO shape + int nioDims; // Array IO rank + int * arrDims; // Array shape + int narrDims; // Array rank + int iodesc; // GDAL IO descriptor + int filedesc; // GDAL file descriptor + int vardesc; // GDAL variable descriptor + int basegdaltype; // GDAL version of Array data type + void *baseAddress; // The address of the Array IO data + int localDE; // DE to use for IO + int nVar; // Number of variables in file + int nAtt; // Number of attributes in file + int unlim; // Unlimited dimension ID + std::string varname; // Default variable name + + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; + + // File open? + if (isOpen(tile) != ESMF_TRUE) + if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", + ESMC_CONTEXT, rc)) return; + + // Array compatible with this object? + localrc = checkArray(arr_p); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + + filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + + // Get a pointer to the array data + // Still have the one DE restriction so use localDE = 0 + localDE = 0; + int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDE, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + // arrlen will be the size owned locally (0 if this DE doesn't own the current tile) + // (though note that this value isn't actually used by GDAL) + int arrlen; + if (tileOfThisDe == tile) { + baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); + arrlen = 1; + } else { + baseAddress = NULL; + arrlen = 0; + } +#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) + int nDims; + + // If frame >= 0 then we need to not use the unlimited dim in the iodesc. + iodesc = getIODesc(gdalSystemDesc, arr_p, tile, &ioDims, &nioDims, + &arrDims, &narrDims, &basegdaltype, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) return; + + // This should work if it is a NetCDF file. + gdalrc = GDALc_inq(filedesc, &nDims, + &nVar, &nAtt, &unlim); + if (!CHECKGDALERROR(gdalrc, "File is not in NetCDF format", ESMF_RC_FILE_READ, (*rc))) { + return; + } + + if (((char *)NULL != name) && (strlen(name) > 0)) { + varname = name; + } else { + varname = arr_p->getName(); + } + + gdalrc = GDALc_inq_varid(filedesc, varname.c_str(), &vardesc); + // An error here means the variable is not in the file + const std::string errmsg = "variable " + varname + " not found in file"; + if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { + return; + } + + int frame; + if (((int *)NULL != timeslice) && (*timeslice > 0) && narrDims < nioDims) { + // + // Do not use the unlimited dim in iodesc calculation + // + int dimids[narrDims]; + gdalrc = GDALc_inq_vardimid(filedesc, vardesc, dimids); + // This should never happen + const std::string errmsg = "variable " + varname + " inq_dimid failed"; + if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { + return; + } + + if(unlim == dimids[narrDims-1]){ + narrDims = narrDims - 1; + } + for (int i=0; i time_len) { + PRINTMSG(" (" << my_rank << "): " << + "Timeframe is greater than that in file" << + getFilename(tile) << ", file time = " << time_len << + ", requested record = " << *timeslice); + if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, + "Timeframe is greater than max in file", + ESMC_CONTEXT, rc)) { + return; + } + } + frame = (*timeslice); + } else { + frame = -1; + for (int i=0; i= 0 && frame > 0) { + PRINTMSG("calling setframe for read_darray, frame = " << frame); + GDALc_setframe(filedesc, vardesc, frame-1); + } + +#endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) + + PRINTMSG("calling read_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); + // Read in the array + gdalrc = GDALc_read_darray(filedesc, vardesc, iodesc, + arrlen, (void *)baseAddress); + + if (!CHECKGDALERROR(gdalrc, "Error reading array data", ESMF_RC_FILE_READ, (*rc))) { + return; + } + + // return + if (rc != NULL) { + *rc = localrc; + } +} // GDAL_Handler::arrayReadOneTileFile() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::arrayWriteOneTileFile()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::arrayWriteOneTileFile - Write an Array to a file, for the given tile +// +// !INTERFACE: +void GDAL_Handler::arrayWriteOneTileFile( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: + Array *arr_p, // (in) Destination of write + int tile, // (in) Tile we are writing (1-based indexing) + const char * const name, // (in) Optional array name + const std::vector &dimLabels, // (in) Optional dimension labels + int *timeslice, // (in) Optional timeslice + const ESMCI::Info *varAttPack, // (in) Optional per-variable Attribute Package + const ESMCI::Info *gblAttPack, // (in) Optional global Attribute Package + int *rc // (out) - Error return code +// + ) { +// +// !DESCRIPTION: +// Write data to field to the open file, for the given tile. +// For typical single-tile arrays, this will just be called once per arrayWrite, with tile=1. +// Calls the appropriate GDAL write_darray__ function. +// It is an error if this handler object does not have an open +// GDAL file descriptor and a valid GDAL IO descriptor (these items should +// all be in place after a successful call to GDAL_Handler::open). +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + int gdalrc; // GDAL error value + int * ioDims; // Array IO shape + int nioDims; // Array IO rank + int * arrDims; // Array shape + int narrDims; // Array rank + int iodesc; // GDAL IO descriptor + int filedesc; // GDAL file descriptor + int vardesc = 0; // GDAL variable descriptor + int basegdaltype; // GDAL version of Array data type + void *baseAddress; // The address of the Array IO data + int localDE; // DE to use for IO + int ncDims[8]; // To hold NetCDF dimensions + int unlim = -1; // Unlimited dimension ID + int timeFrame = -1; // ID of time dimension (>0 if used) + int timesliceVal = -1; // Used time value (from timeslice) + bool varExists = false; // true if varname is defined in file + std::string varname; // Variable name + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; + + if ((int *)NULL != timeslice) { + timesliceVal = *timeslice; + } + // File open? + if (isOpen(tile) != ESMF_TRUE) + if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", + ESMC_CONTEXT, rc)) return; + + // Array compatible with this object? + localrc = checkArray(arr_p); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + + filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + iodesc = getIODesc(gdalSystemDesc, arr_p, tile, &ioDims, &nioDims, + &arrDims, &narrDims, &basegdaltype, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) return; + for (int i=0; i 0 && dimLabels.size() < (unsigned int)nioDims) { + std::stringstream errmsg; + errmsg << dimLabels.size() << " user dimension label(s) supplied, " << nioDims << " expected"; + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_SIZE, errmsg, + ESMC_CONTEXT, rc)) return; + } + + + // Get a pointer to the array data + // Still have the one DE restriction so use localDE = 0 + localDE = 0; + int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDE, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) return; + int arrlen; + if (tileOfThisDe == tile) { + baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); + PRINTMSG("baseAddress = 0x" << (void *)baseAddress); + // arrlen = arr_p->getLocalarrayList()[localDE]->getByteCount(); + arrlen = 1; + const int *counts = arr_p->getLocalarrayList()[localDE]->getCounts(); + for (int i=0; i= 0) { + if (varExists & !hasTimeDim) { + // It is an error to not have a time dimension if we are trying to + // write a timeslice and the variable already exists + // (it won't have time) + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, + "Field already exists without time dimension", + ESMC_CONTEXT, rc)) { + return; + } + } else { + timeFrame = timesliceVal; + } + } else if (timesliceVal < 0) { + // Special case for no timeslice input passed but time dimension exists + if (varExists && hasTimeDim) { + timeFrame = timeLen + 1; + PRINTMSG("timeslice not passed but set to " << timeFrame); + } + } + + PRINTMSG("ready to check var compat., timeFrame = " << timeFrame); + if (varExists) { + int nDims; + int nArrdims = nioDims + ((timeFrame > 0) ? 1 : 0); + + // Check compatibility between array to write and existing variable. + gdalrc = GDALc_inq_varndims(filedesc, vardesc, &nDims); + if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + + if (nDims != nArrdims) { + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, + "Variable rank in file does not match array", + ESMC_CONTEXT, rc)) { + PRINTMSG("Variable rank mismatch: nioDims = " << nioDims << + ", nArrdims = " << nArrdims << ", nDims = " << nDims); + return; + } + } + + PRINTMSG("Calling gdal_cpp_inq_vardimid_vdesc"); + std::vector dimIds(nDims); + gdalrc = GDALc_inq_vardimid(filedesc, vardesc, &dimIds.front()); + if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + + MPI_Offset dimLen; + int ioDimNum = 0; + for (int i = 0; i < nDims; i++) { + gdalrc = GDALc_inq_dimlen(filedesc, dimIds[i], &dimLen); + if (!CHECKGDALERROR(gdalrc, "Error retrieving dimension information", + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + PRINTMSG("GDALc_inq_dimlen for dim = " << i << " dimLen="< 0) + axis = dimLabels[i]; + else { + std::stringstream axis_tmp; + axis_tmp << varname << "_dim" << std::setfill('0') << std::setw(3) << i+1; + axis = axis_tmp.str(); + } + + // if dimension already exists, use it. + int dimid_existing; + gdalrc = GDALc_inq_dimid(filedesc, axis.c_str(), &dimid_existing); + if (GDAL_NOERR == gdalrc) { + MPI_Offset dim_len; + gdalrc = GDALc_inq_dimlen(filedesc, dimid_existing, &dim_len); + if (!CHECKGDALERROR(gdalrc, "Error finding existing dimension length", ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + if (ioDims[i] != dim_len) { + std::stringstream msg; + msg << "Existing dimension " << axis << " length " << dim_len << " != required " << ioDims[i]; + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, msg, + ESMC_CONTEXT, rc)) { + return; + } + } + ncDims[nioDims - i - 1] = dimid_existing; + } else { + PRINTMSG("Defining dimension " << i); + gdalrc = GDALc_def_dim(filedesc, axis.c_str(), + ioDims[i], &ncDims[nioDims - i - 1]); + if (!CHECKGDALERROR(gdalrc, std::string("Defining dimension: ") + axis, + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + } + } + PRINTMSG("finished defining space dims, timeFrame = " << timeFrame); + + if (timeFrame > -1) { + nioDims++; + for(int i=nioDims;i>0;i--) + ncDims[i] = ncDims[i-1]; + if (hasTimeDim) { + gdalrc = GDALc_inq_dimid (filedesc, "time", &ncDims[0]); + if (!CHECKGDALERROR(gdalrc, "Attempting to obtain 'time' dimension ID", + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + } else { + PRINTMSG("Defining time dimension"); + gdalrc = GDALc_def_dim(filedesc, "time", + GDAL_UNLIMITED, &ncDims[0]); + if (!CHECKGDALERROR(gdalrc, "Attempting to define 'time' dimension", + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + } + } + } + PRINTMSG("varExists = " << varExists); + if (!varExists) { + PRINTMSG("niodims = " << nioDims); + PRINTMSG("basegdaltype = " << basegdaltype); + + gdalrc = GDALc_def_var(filedesc, varname.c_str(), basegdaltype, + nioDims, ncDims, &vardesc); + if (!CHECKGDALERROR(gdalrc, "Attempting to define GDAL vardesc for: " + varname, + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + } + if (timeFrame >= 0) { +#ifdef ESMFIO_DEBUG + int nvdims; + GDALc_inq_varndims(filedesc, vardesc, &nvdims); + PRINTMSG("calling setframe, timeFrame = " << timeFrame); +#endif // ESMFIO_DEBUG + gdalrc = GDALc_setframe(filedesc, vardesc, timeFrame-1); + if (!CHECKGDALERROR(gdalrc, "Attempting to setframe for: " + varname, + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + } +#ifdef ESMFIO_DEBUG + else { + PRINTMSG("NOT calling setframe, timeFrame = " << timeFrame); + } + if (varExists) { + int varid; + int lrc; + lrc = GDALc_inq_varid(filedesc, varname.c_str(), &varid); + PRINTMSG("varid = " << varid); + } +#endif // ESMFIO_DEBUG + + // ESMF Attribute Package -> NetCDF variable and global attributes + if (varAttPack) { + attPackPut (vardesc, varAttPack, tile, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) { + return; + } + } + if (gblAttPack) { + attPackPut (NC_GLOBAL, gblAttPack, tile, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) { + return; + } + } + + + PRINTMSG("calling enddef, status = " << rc); + + gdalrc = GDALc_enddef(filedesc); + if (!CHECKGDALERROR(gdalrc, "Attempting to end definition of variable: " + varname, + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + +#endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) + PRINTMSG("calling write_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); + // Write the array + ESMCI_IOREGION_ENTER("GDALc_write_darray"); + gdalrc = GDALc_write_darray(filedesc, vardesc, iodesc, arrlen, + (void *)baseAddress, NULL); + if (!CHECKGDALERROR(gdalrc, "Attempting to write file", + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + new_file[tile-1] = false; + ESMCI_IOREGION_EXIT("GDALc_write_darray"); + + + // Cleanup & return + PRINTMSG("cleanup and return"); + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } +} // GDAL_Handler::arrayWriteOneTileFile() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::openOneTileFile()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::openOneTileFile - open a stream with stored filename, for the given tile +// +// !INTERFACE: +void GDAL_Handler::openOneTileFile( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + int tile, // (in) - tile for which we're opening the file (1-based indexing) + bool readonly, // (in) - if false, then read/write + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Open a file for reading and/or writing for the given tile. +// For typical single-tile arrays, this will just be called once per open, with tile=1. +// GDAL must be initialized for this routine to succeed (ESMF_RC_INTNRL_BAD) +// It is an error if a file is already open (ESMF_RC_FILE_OPEN) +// +//EOPI +//----------------------------------------------------------------------------- + int iotype; // GDAL I/O type + int mode; // GDAL file open mode + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + int gdalrc; // GDAL error value + VM *vm = VM::getCurrent(&localrc); + int numtasks = vm->getPetCount(); + int petspernode = vm->getSsiMaxPetCount(); + + + struct iofmt_map_t { + int esmf_iofmt; + int gdal_fmt; + } iofmt_map[] = { +#if defined (ESMF_PNETCDF) + { ESMF_IOFMT_NETCDF, GDAL_IOTYPE_PNETCDF } + ,{ ESMF_IOFMT_NETCDF_64BIT_OFFSET, GDAL_IOTYPE_PNETCDF } + ,{ ESMF_IOFMT_NETCDF_64BIT_DATA, GDAL_IOTYPE_PNETCDF } + ,{ ESMF_IOFMT_NETCDF4, GDAL_IOTYPE_NETCDF } + ,{ ESMF_IOFMT_NETCDF4C, GDAL_IOTYPE_NETCDF4C } + ,{ ESMF_IOFMT_NETCDF4P, GDAL_IOTYPE_NETCDF4P } +#elif defined (ESMF_NETCDF) + { ESMF_IOFMT_NETCDF, GDAL_IOTYPE_NETCDF } + ,{ ESMF_IOFMT_NETCDF_64BIT_OFFSET, GDAL_IOTYPE_NETCDF } + ,{ ESMF_IOFMT_NETCDF_64BIT_DATA, GDAL_IOTYPE_NETCDF } + ,{ ESMF_IOFMT_NETCDF4, GDAL_IOTYPE_NETCDF } + ,{ ESMF_IOFMT_NETCDF4C, GDAL_IOTYPE_NETCDF4C } + ,{ ESMF_IOFMT_NETCDF4P, GDAL_IOTYPE_NETCDF4P } +#endif + }; + + int iofmt_map_size = sizeof (iofmt_map)/sizeof (iofmt_map_t); + + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; + if (isGdalInitialized() != ESMF_TRUE) { + if (ESMC_LogDefault.MsgFoundError (ESMF_RC_INTNRL_BAD, + "GDAL not initialized", + ESMC_CONTEXT, rc)) return; + } else if (isOpen(tile) == ESMF_TRUE) { + if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_OPEN, + "File is already open", + ESMC_CONTEXT, rc)) return; + } else if (gdalSystemDesc <= 0 ) { + // Just grab last created GDAL instance for now (TBD: need way to choose) + gdalSystemDesc = GDAL_Handler::activeGdalInstances.back(); + } + + // Translate the I/O format from ESMF to GDAL +#if !defined(ESMF_NETCDF) && !defined (ESMF_PNETCDF) + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_LIB_NOT_PRESENT, + "Library for requested I/O format is not present", ESMC_CONTEXT, rc)) + return; +#endif + + int i_loop; + for (i_loop=0; i_loopgetStorageRef(); + for (json::const_iterator it=j.cbegin(); it!=j.cend(); it++) { + if (it.key().rfind("ESMF:", 0) == 0) { + continue; + } + json jcurr; + if (it.value().is_array()) { + jcurr = it.value(); + } else { + json arr = json::array(); + arr.push_back(it.value()); + jcurr = arr; + } + if (!(jcurr.is_array())) { + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_WRONGTYPE, "Only JSON arrays supported. Key is: " + it.key(), ESMC_CONTEXT, rc)) + return; + } + int size = (int)(jcurr.size()); + + // Determine if the target key is 32-bit + bool is_32bit = false; + try { + json::json_pointer jp = attPack->formatKey(it.key()); + is_32bit = ESMCI::retrieve_32bit_flag(attPack->getTypeStorage(), jp, true); + } + ESMC_CATCH_ERRPASSTHRU + + ESMC_TypeKind_Flag att_type = ESMCI::json_type_to_esmf_typekind(jcurr, true, is_32bit); + switch (att_type) { + case ESMC_TYPEKIND_CHARACTER: { + if (size > 1) { + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_WRONGTYPE, "JSON arrays with size > 1 not supported for strings. Key is: " + it.key(), ESMC_CONTEXT, rc)) + return; + } + const std::string value = jcurr[0]; + gdalrc = GDALc_put_att_text (filedesc, vardesc, + it.key().c_str(), strlen(value.c_str()), value.c_str()); + if (!CHECKGDALERROR(gdalrc, "Attempting to set string Attribute: " + it.key(), + ESMF_RC_FILE_WRITE, (*rc))) return; + break; + } + case ESMC_TYPEKIND_I8: { + const std::vector value = jcurr.get>(); + gdalrc = GDALc_put_att_long (filedesc, vardesc, + it.key().c_str(), att_type, size, value.data()); + if (!CHECKGDALERROR(gdalrc, "Attempting to set I8 Attribute: " + it.key(), + ESMF_RC_FILE_WRITE, (*rc))) return; + break; + } + case ESMC_TYPEKIND_R8: { + const std::vector value = jcurr.get>(); + gdalrc = GDALc_put_att_double (filedesc, vardesc, + it.key().c_str(), att_type, size, value.data()); + if (!CHECKGDALERROR(gdalrc, "Attempting to set R8 Attribute: " + it.key(), + ESMF_RC_FILE_WRITE, (*rc))) return; + break; + } + case ESMC_TYPEKIND_I4: { + const std::vector value = jcurr.get>(); + gdalrc = GDALc_put_att_int (filedesc, vardesc, + it.key().c_str(), att_type, size, value.data()); + if (!CHECKGDALERROR(gdalrc, "Attempting to set I4 Attribute: " + it.key(), + ESMF_RC_FILE_WRITE, (*rc))) return; + break; + } + case ESMC_TYPEKIND_R4: { + const std::vector value = jcurr.get>(); + gdalrc = GDALc_put_att_float (filedesc, vardesc, + it.key().c_str(), att_type, size, value.data()); + if (!CHECKGDALERROR(gdalrc, "Attempting to set R4 Attribute: " + it.key(), + ESMF_RC_FILE_WRITE, (*rc))) return; + break; + } + default: + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_NOTSET, + "Attribute " + it.key() + " has unsupported value type", + ESMC_CONTEXT, rc)) return; + } + } + + if (rc) {*rc = ESMF_SUCCESS;} + +} // GDAL_Handler::attPackPut() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::isOpen()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::isOpen - Determine is a file is open +// +// !INTERFACE: +ESMC_Logical GDAL_Handler::isOpen( +// +// !RETURN VALUE: +// +// ESMC_Logical ESMF_TRUE if a file is open, ESMF_FALSE otherwise +// +// !ARGUMENTS: +// + int tile // (in) - tile number for which we check if a file is open (relevant for + // multi-tile arrays with IO to a separate file for each array) (1-based indexing) + ) { +// +// !DESCRIPTION: +// Determine if a file is open returning ESMF_TRUE if a file is open, +// ESMF_FALSE otherwise +// +//EOPI +//----------------------------------------------------------------------------- + PRINTPOS; + int filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + if (filedesc == 0) { + PRINTMSG("gdalFileDesc is NULL"); + return ESMF_FALSE; + } else if (GDALc_File_is_Open(filedesc) != 0) { + PRINTMSG("File is open"); + return ESMF_TRUE; + } else { + // This really should not happen, warn and clean up just in case + std::string errmsg; + const std::string thisFilename = getFilename(tile); + errmsg = std::string ("File, ") + thisFilename + ", closed by GDAL"; + ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, ESMC_CONTEXT); + return ESMF_FALSE; + } +} // GDAL_Handler::isOpen() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::flushOneTileFile()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::flushOneTileFile - Flush any pending I/O operations for this tile's file +// +// !INTERFACE: +void GDAL_Handler::flushOneTileFile( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + int tile, // (in) - Tile for which we want to flush the file (1-based indexing) + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Flush any pending I/O operations for this tile's file. +// For typical single-tile arrays, this will just be called once per flush, with tile=1. +// It is safe to call this on a non-open file; in this case, nothing is done. +// +//EOPI +//----------------------------------------------------------------------------- + + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; + // Not open? No problem, just skip + if (isOpen(tile) == ESMF_TRUE) { + PRINTMSG("calling sync"); + ESMCI_IOREGION_ENTER("GDALc_sync"); + GDALc_sync(gdalFileDesc[tile-1]); + ESMCI_IOREGION_EXIT("GDALc_sync"); + } + // return successfully + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } +} // GDAL_Handler::flushOneTileFile() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::closeOneTileFile()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::closeOneTileFile - Close this tile's possibly-open file +// +// !INTERFACE: +void GDAL_Handler::closeOneTileFile( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + int tile, // (in) - Tile for which we want to close the file (1-based indexing) + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Close the open file associated with this tile (if any). +// For typical single-tile arrays, this will just be called once per close, with tile=1. +// It is NOT an error if no file is open +// +//EOPI +//----------------------------------------------------------------------------- + + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; + // Not open? No problem, just skip + if (isOpen(tile) == ESMF_TRUE) { + ESMCI_IOREGION_ENTER("GDALc_closefile"); + int gdalrc = GDALc_closefile(gdalFileDesc[tile-1]); + ESMCI_IOREGION_EXIT("GDALc_closefile"); + gdalFileDesc[tile-1] = 0; + new_file[tile-1] = false; + if (rc != NULL) *rc = gdalrc; + } + + // return successfully + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } +} // GDAL_Handler::closeOneTileFile() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::getIODesc()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::getIODesc - Find or create an IO descriptor +// +// !INTERFACE: + int GDAL_Handler::getIODesc( +// +// !RETURN VALUE: +// +// int GDAL IO descriptor +// +// !ARGUMENTS: +// + int iosys, // (in) - GDAL system handle to use + Array *arr_p, // (in) - Array for IO decompomposition + int tile, // (in) - Tile number in array (1-based indexing) + int ** ioDims, // (out) - Array shape for IO + int *nioDims, // (out) - Rank of Array IO + int ** arrDims, // (out) - Array shape for IO + int *narrDims, // (out) - Rank of Array IO + int *basegdaltype, // (out) - Data type for IO + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Find or create an appropriate GDAL I/O Descriptor and return it. +// +//EOPI +//----------------------------------------------------------------------------- + + int new_io_desc = (int)NULL; + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; + new_io_desc = GDAL_IODescHandler::getIODesc(iosys, arr_p, tile, &localrc); + if ((int)NULL == new_io_desc) { + PRINTMSG("calling constructGdalDecomp"); + localrc = GDAL_IODescHandler::constructGdalDecomp(iosys, + arr_p, tile, &new_io_desc); + PRINTMSG("constructGdalDecomp call complete" << ", localrc = " << localrc); + } + if ((ioDims != (int **)NULL) || (nioDims != (int *)NULL) || + (arrDims != (int **)NULL) || (narrDims != (int *)NULL)) { + int niodimArg; + int *iodimsArg; + int narrdimArg; + int *arrdimsArg; + + localrc = GDAL_IODescHandler::getDims(new_io_desc, &niodimArg, &iodimsArg, + &narrdimArg, &arrdimsArg); + if (!ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) { + if (ioDims != (int **)NULL) { + *ioDims = iodimsArg; + } + if (nioDims != (int *)NULL) { + *nioDims = niodimArg; + } + if (arrDims != (int **)NULL) { + *arrDims = arrdimsArg; + } + if (narrDims != (int *)NULL) { + *narrDims = narrdimArg; + } + } + } + PRINTMSG("getDims complete, calling getIOType"); + if (basegdaltype != (int *)NULL) { + *basegdaltype = GDAL_IODescHandler::getIOType(new_io_desc, &localrc); + ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + rc); + } + if (rc != NULL) { + *rc = localrc; + } + return new_io_desc; +} // GDAL_Handler::getIODesc() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_Handler::CheckGDALError()" +//BOPI +// !IROUTINE: ESMCI::GDAL_Handler::CheckGDALError +// +// !INTERFACE: +bool GDAL_Handler::CheckGDALError( +// +// !RETURN VALUE: +// +// bool true if it is OK to continue (false = error condition) +// +// !ARGUMENTS: +// + int gdalRetCode, // (in) - Return code to check + int line, // (in) - Line containing error + const char * const file, // (in) - File containing error + const char * const method, // (in) - ESMC_METHOD + const std::string &fmtStr, // (in) - Optional error string + int rc_code, // (in) - Default return code on error + int *rc, // (out) - Error return code + bool warn // (in) - warn instead of error + ) { +// +// !DESCRIPTION: +// Log an error (if an error condition is indicated by gdalRetCode) +// +//EOPI +//----------------------------------------------------------------------------- + int localrc = ESMF_SUCCESS;; + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + std::stringstream errmsg; + if (gdalRetCode != GDAL_NOERR) { +#if defined(ESMF_PNETCDF) + // Log the error, assuming the error code was passed through GDAL from PNetCDF + if (!fmtStr.empty()) { + errmsg << " " << fmtStr << ", (GDAL/PNetCDF error = " << ncmpi_strerror (gdalRetCode) << ")"; + } else { + errmsg << " (GDAL/PNetCDF error = " << ncmpi_strerror (gdalRetCode) << ")"; + } +#elif defined(ESMF_NETCDF) + // Log the error, assuming the error code was passed through GDAL from NetCDF + if (!fmtStr.empty()) { + errmsg << " " << fmtStr << ", (GDAL/NetCDF error = " << nc_strerror (gdalRetCode) << ")"; + } else { + errmsg << " (GDAL/NetCDF error = " << nc_strerror (gdalRetCode) << ")"; + } +#else + if (!fmtStr.empty()) { + errmsg << " " << fmtStr << ", (GDAL error = " << gdalRetCode << ")"; + } else { + errmsg << " (GDAL error = " << gdalRetCode << ")"; + } +#endif + // Attempt to find a corresponding ESMC error code + switch(gdalRetCode) { +#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) + case NC_EEXIST: + localrc = ESMF_RC_FILE_CREATE; + break; + case NC_ENOMEM: + localrc = ESMF_RC_MEM_ALLOCATE; + break; + case NC_EPERM: + localrc = ESMF_RC_FILE_OPEN; + break; + default: + localrc = ESMF_RC_NETCDF_ERROR; + break; +#else // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) + default: + localrc = ESMF_RC_FILE_UNEXPECTED; + break; +#endif + } + } else + localrc = ESMF_SUCCESS; + + if ((localrc != ESMF_SUCCESS) && warn) { + ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, + line, file, method); + // run through MsgFoundError in case Log tracing is enabled + ESMC_LogDefault.MsgFoundError(ESMF_SUCCESS, errmsg, + line, file, method, rc); + } else { + ESMC_LogDefault.MsgFoundError(localrc, errmsg, + line, file, method, rc); + } + + return (gdalRetCode == GDAL_NOERR); +} // GDAL_Handler::CheckGDALError() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_IODescHandler::~GDAL_IODescHandler()" +//BOPI +// !IROUTINE: ESMCI::GDAL_IODescHandler::~GDAL_IODescHandler +// +// !INTERFACE: +GDAL_IODescHandler::~GDAL_IODescHandler ( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + ) { +// +// !DESCRIPTION: +// Tear down active, initialized GDAL IO Descriptor and free memory +// +//EOPI +//----------------------------------------------------------------------------- + int localrc; + PRINTMSG("calling GDALc_freedecomp"); + ESMCI_IOREGION_ENTER("GDALc_freedecomp"); + GDALc_freedecomp(ios, io_descriptor); + ESMCI_IOREGION_EXIT("GDALc_freedecomp"); + if (dims != (int *)NULL) { + delete[] dims; + dims = (int *)NULL; + } + if (arrayShape != (int *)NULL) { + delete[] arrayShape; + arrayShape = (int *)NULL; + } + array_p = (Array *)NULL; +} // GDAL_IODescHandler::~GDAL_IODescHandler() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_IODescHandler::finalize()" +//BOPI +// !IROUTINE: ESMCI::GDAL_IODescHandler::finalize +// +// !INTERFACE: +void GDAL_IODescHandler::finalize ( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + ) { +// +// !DESCRIPTION: +// Tear down all active, initialized GDAL IO Descriptors. +// +//EOPI +//----------------------------------------------------------------------------- + GDAL_IODescHandler *handle; + + while(!GDAL_IODescHandler::activeGdalIoDescriptors.empty()) { + handle = GDAL_IODescHandler::activeGdalIoDescriptors.back(); + delete handle; // Shuts down descriptor + handle = (GDAL_IODescHandler *)NULL; + GDAL_IODescHandler::activeGdalIoDescriptors.pop_back(); + } +} // GDAL_IODescHandler::finalize() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_IODescHandler::constructGdalDecomp()" +//BOPI +// !IROUTINE: ESMCI::GDAL_IODescHandler::constructGdalDecomp - New Decomposition +// +// !INTERFACE: +int GDAL_IODescHandler::constructGdalDecomp( +// +// !RETURN VALUE: +// +// int return code +// +// !ARGUMENTS: +// + int iosys, // (in) - GDAL system handle to use + Array *arr_p, // (in) - Array for IO decompomposition + int tile, // (in) - Tile number in array (1-based indexing) + int *newDecomp_p // (out) - New decomposition descriptor + ) { +// +// !DESCRIPTION: +// Gather the necessary information the input array and call GDAL_initdecomp. +// The result is a new decomposition descriptor which is used in the +// GDAL read/write calls. +// +//EOPI +//----------------------------------------------------------------------------- + + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + int rc; + int localDe; // The DE being processed + int localDeCount; // The number of DEs on this PET + int gdalDofCount; // Number + MPI_Offset *gdalDofList; // Local to global array map + DistGrid *distGrid; // The Array's associated DistGrid + GDAL_IODescHandler *handle; // New handler object for this IO desc. + + PRINTPOS; + // check the inputs + if ((Array *)NULL == arr_p) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, "- arr_p cannot be NULL", + ESMC_CONTEXT, &localrc); + return ESMF_RC_ARG_BAD; + } + if (tile < 1) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "- tile must be >= 1", + ESMC_CONTEXT, &localrc); + return localrc; + } + if ((int *)NULL == newDecomp_p) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, + "- newDecomp_p cannot be NULL", ESMC_CONTEXT, &localrc); + return ESMF_RC_ARG_BAD; + } + + handle = new GDAL_IODescHandler(iosys, arr_p); + gdalDofList = (MPI_Offset *)NULL; + + localDeCount = arr_p->getDELayout()->getLocalDeCount(); + PRINTMSG("localDeCount = " << localDeCount); + //TODO: Remove this restriction (possibly with multiple IO descriptors) + if (localDeCount > 1) { + ESMC_LogDefault.Write("I/O does not support multiple DEs per PET", + ESMC_LOGMSG_WARN, ESMC_CONTEXT); + return ESMF_RC_NOT_IMPL; + } + + // TODO: To support multiple DEs per PE, we would need to extend this to be an array + bool thisDeIsThisTile = false; + + // We need the total number of elements + gdalDofCount = 0; + int const *localDeToDeMap = arr_p->getDistGrid()->getDELayout()->getLocalDeToDeMap(); + // NB: This loop is redundant for now, I wish I could lift the restriction. + for (localDe = 0; localDe < localDeCount; ++localDe) { + // consider the fact that replicated dimensions may lead to local elements in the + // Array, that are not accounted for by actual exclusive elements in the DistGrid + int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDe, &rc); + if (ESMC_LogDefault.MsgFoundError(rc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) + return localrc; + if (tileOfThisDe == tile) { + // TODO: As noted above, to support multiple DEs per PE, we would need to extend this to be an array + thisDeIsThisTile = true; + } + if (thisDeIsThisTile && arr_p->getDistGrid()->getElementCountPDe()[localDeToDeMap[localDe]]>0) + gdalDofCount += arr_p->getTotalElementCountPLocalDe()[localDe]; + } + + PRINTMSG("gdalDofCount = " << gdalDofCount); + try { + // Allocate space for the DOF list + gdalDofList = new MPI_Offset[gdalDofCount]; + + } catch(...) { + if ((MPI_Offset *)NULL != gdalDofList) { + // Free the DofList! + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + } + ESMC_LogDefault.AllocError(ESMC_CONTEXT, &localrc); + return localrc; + } + // Fill in the GDAL DOF list (local to global map) + // TODO: This is where we would need to make some magic to include multiple DEs. + // TODO: (Particular care may be needed in the multi-tile case, where some DEs on the + // TODO: current PE may be part of the current tile, while others are not. + // TODO: For now, with one DE, we can assume that, if gdalDofCount>0, then this DE + // TODO: corresponds to the current tile.) + localDe = 0; + if (gdalDofCount>0){ + // construct the mapping of the local elements + localrc = arr_p->constructFileMap((int64_t *) gdalDofList, gdalDofCount, localDe); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) { + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + return localrc; + } + } + +#if 0 + std::cout << " gdalDofList = ["; + for (int i = 0; i < gdalDofCount; i++) { + std::cout << " " << gdalDofList[i] + << ((i == (gdalDofCount - 1)) ? ' ' : ','); + } + std::cout << "]" << std::endl; +#endif // 0 + // Get TKR info + switch(arr_p->getTypekind()) { + case ESMC_TYPEKIND_I4: + handle->basegdaltype = GDAL_INT; + break; + case ESMC_TYPEKIND_R4: + handle->basegdaltype = GDAL_REAL; + break; + case ESMC_TYPEKIND_R8: + handle->basegdaltype = GDAL_DOUBLE; + break; + case ESMC_TYPEKIND_I1: + case ESMC_TYPEKIND_I2: + case ESMC_TYPEKIND_I8: + case ESMC_TYPEKIND_CHARACTER: + case ESMF_C8: + case ESMF_C16: + case ESMC_TYPEKIND_LOGICAL: + default: + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "Unsupported typekind", ESMC_CONTEXT, + &localrc)) { + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + return localrc; + } + } + + distGrid = arr_p->getDistGrid(); + const int *minIndexPDimPTile = distGrid->getMinIndexPDimPTile(); + const int *maxIndexPDimPTile = distGrid->getMaxIndexPDimPTile(); + + handle->tile = tile; +// NB: Is this part of the restrictions on Array I/O? +// nDims = arr_p->getRank(); + handle->nDims = distGrid->getDimCount(); + // Make sure dims is not used + if (handle->dims != (int *)NULL) { + delete handle->dims; + handle->dims = (int *)NULL; + } + handle->dims = new int[handle->nDims]; + // Step through the distGrid dimensions, getting the size of the dimension. (This is the + // size of the full array across all PEs.) + for (int i = 0; i < handle->nDims; i++) { + handle->dims[i] = (maxIndexPDimPTile[((tile - 1) * handle->nDims) + i] - + minIndexPDimPTile[((tile - 1) * handle->nDims) + i] + 1); + } + + handle->arrayRank = arr_p->getRank(); + if (handle->arrayShape != (int *)NULL) { + delete handle->arrayShape; + handle->arrayShape = (int *)NULL; + } + handle->arrayShape = new int[handle->arrayRank]; + // Get the size of each dimension owned locally. + if (thisDeIsThisTile) { + const int *totalLBound = arr_p->getTotalLBound(); + const int *totalUBound = arr_p->getTotalUBound(); + for (int i = 0; i < handle->arrayRank; ++i) { + // TODO: This is another place that would need to be generalized to handle more than + // one DE per PE: totalLBound and totalUBound are dimensioned + // [redDimCount*ssiLocalDeCount], so the below expression (which doesn't include the + // current DE count) would need to be adjusted to handle multiple DEs. + handle->arrayShape[i] = (totalUBound[i] - totalLBound[i] + 1); + } + } else { + // This DE is for some other tile, so as far as this tile is concerned, we own 0 elements + for (int i = 0; i < handle->arrayRank; ++i) { + handle->arrayShape[i] = 0; + } + } + +#ifdef ESMFIO_DEBUG + { + char shapestr[64]; + for (int i = 0; i < handle->arrayRank; i++) { + sprintf((shapestr + (5 * i)), " %03d%c", handle->arrayShape[i], + (((handle->arrayRank - 1) == i) ? ' ' : ',')); + } + PRINTMSG(", IODesc shape = [" << shapestr << "], calling gdal_initdecomp"); + + char dimstr[64]; + for (int i = 0; i < handle->nDims; i++) { + sprintf((dimstr + (5 * i)), " %03d%c", handle->dims[i], + (((handle->nDims - 1) == i) ? ' ' : ',')); + } + PRINTMSG(", IODesc dims = [" << dimstr << "]"); + } +#endif // ESMFIO_DEBUG + int ddims[handle->nDims]; + for(int i=0; inDims; i++) + ddims[i] = handle->dims[handle->nDims - i - 1]; + // Create the decomposition + ESMCI_IOREGION_ENTER("GDALc_InitDecomp"); + GDALc_InitDecomp(iosys, handle->basegdaltype, handle->nDims, + ddims, gdalDofCount, gdalDofList, + &(handle->io_descriptor), NULL, NULL, NULL); + ESMCI_IOREGION_EXIT("GDALc_InitDecomp"); + + PRINTMSG("after call to GDALc_initdecomp_dof"); + + // Add the handle into the master list + GDAL_IODescHandler::activeGdalIoDescriptors.push_back(handle); + // Finally, set the output handle + *newDecomp_p = handle->io_descriptor; + + // Free the DofList! + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + + // return successfully + return ESMF_SUCCESS; +} // GDAL_IODescHandler::constructGdalDecomp() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_IODescHandler::freeGdalDecomp()" +//BOPI +// !IROUTINE: ESMCI::GDAL_IODescHandler::freeGdalDecomp - Delete Decomposition +// +// !INTERFACE: +int GDAL_IODescHandler::freeGdalDecomp( +// +// !RETURN VALUE: +// +// int return code +// +// !ARGUMENTS: +// + int *decomp_p // (inout) - GDAL decomp desc to free + ) { +// +// !DESCRIPTION: +// Free a GDAL I/O decomposition structure and remove it from the +// active instances. +// +//EOPI +//----------------------------------------------------------------------------- + + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + GDAL_IODescHandler *handle; // Temp handler for finding descriptor + std::vector::iterator it; + bool foundHandle = false; + + // check the inputs + if (decomp_p == 0) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, + "- newDecomp_p cannot be NULL", ESMC_CONTEXT, &localrc); + return ESMF_RC_ARG_BAD; + } + + // Look for newDecomp_p in the active handle instances + for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); + it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); ++it) { + handle = *it; + if (*decomp_p == handle->io_descriptor) { + foundHandle = true; + delete handle; + handle = (GDAL_IODescHandler *)NULL; + *decomp_p = (int)NULL; + break; + } + } + + // If we didn't find the handle, that is bad + if (foundHandle) { + localrc = ESMF_SUCCESS; + } else { + ESMC_LogDefault.Write("GDAL IO descriptor not found or freed", + ESMC_LOGMSG_ERROR, ESMC_CONTEXT); + localrc = ESMF_RC_MEM_DEALLOCATE; + } + + return localrc; +} // GDAL_IODescHandler::freeGdalDecomp() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_IODescHandler::getDims()" +//BOPI +// !IROUTINE: ESMCI::GDAL_IODescHandler::getDims +// +// !INTERFACE: +int GDAL_IODescHandler::getDims( +// +// !RETURN VALUE: +// +// Return code +// +// !ARGUMENTS: +// + const int &iodesc, // (in) - The IO descriptor + int * nioDims, // (out) - The number of IO dimensions + int ** ioDims, // (out) - Array of dimensions (shape) for IO + int * narrDims, // (out) - The array's rank + int ** arrDims // (out) - The array's shape + ) { +// +// !DESCRIPTION: +// Return a pointer to the array of dimensions (shape) for the IO descriptor +// +//EOPI +//----------------------------------------------------------------------------- + int localrc = ESMF_RC_NOT_FOUND; // local return code + + std::vector::iterator it; + PRINTPOS; + for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); + it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); + it++) { + if (iodesc == (*it)->io_descriptor) { + PRINTMSG("getDims: found handler, nioDims = " << (*it)->nDims << + ", ioDims = " << (*it)->dims << ", narrDims = " << + (*it)->arrayRank); + if (nioDims != (int *)NULL) { + *nioDims = (*it)->nDims; + } + if (ioDims != (int **)NULL) { + *ioDims = (*it)->dims; + } + if (narrDims != (int *)NULL) { + *narrDims = (*it)->arrayRank; + } + if (arrDims != (int **)NULL) { + *arrDims = (*it)->arrayShape; + } + localrc = ESMF_SUCCESS; + break; + } + } + + // return success or not found + return localrc; + +} // GDAL_IODescHandler::getDims() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_IODescHandler::getIOType()" +//BOPI +// !IROUTINE: ESMCI::GDAL_IODescHandler::getIOType +// +// !INTERFACE: +int GDAL_IODescHandler::getIOType( +// +// !RETURN VALUE: +// +// int IO type (e.g., GDAL_int) +// +// !ARGUMENTS: +// + const int &iodesc, // (in) - The IO descriptor + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Return the IO type descriptor (e.g., GDAL_int) +// +//EOPI +//----------------------------------------------------------------------------- + int iotype = -1; + int localrc = ESMF_RC_NOT_FOUND; // local return code + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + std::vector::iterator it; + PRINTPOS; + for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); + it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); + it++) { + if (iodesc == (*it)->io_descriptor) { + iotype = (*it)->basegdaltype; + localrc = ESMF_SUCCESS; + } + } + + // return successfully + if (rc != NULL) { + *rc = localrc; + } + + return iotype; +} // GDAL_IODescHandler::getIOType() +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::GDAL_IODescHandler::getIODesc()" +//BOPI +// !IROUTINE: ESMCI::GDAL_IODescHandler::getIODesc +// +// !INTERFACE: +int GDAL_IODescHandler::getIODesc( +// +// !RETURN VALUE: +// +// int Pointer to the IODescHandler matching the IO system and +// array +// +// !ARGUMENTS: +// + int iosys, // (in) - The GDAL IO system + Array *arrayArg, // (in) - The IO descriptor + int tileArg, // (in) - Tile number in array (1-based indexing) + int *rc // (out) - Error return code + ) { +// +// !DESCRIPTION: +// Return a pointer to an appropriate GDAL IO descriptor +// +//EOPI +//----------------------------------------------------------------------------- + int iodesc = (int)NULL; // IO descriptor + int localrc = ESMF_RC_NOT_FOUND; // local return code + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + std::vector::iterator it; + for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); + it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); + ++it) { + if ((iosys == (*it)->ios) && (arrayArg == (*it)->array_p) && (tileArg == (*it)->tile)) { + iodesc = (*it)->io_descriptor; + localrc = ESMF_SUCCESS; + } + } + + // return successfully + if (rc != NULL) { + *rc = localrc; + } + + return iodesc; +} // GDAL_IODescHandler::getIODesc() +//----------------------------------------------------------------------------- + +} // end namespace ESMCI diff --git a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C index eb65d7e05f..a892d96942 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C @@ -35,6 +35,9 @@ #ifdef ESMF_PIO #include "ESMCI_PIO_Handler.h" #endif +#ifdef ESMF_GDAL +#include "ESMCI_GDAL_Handler.h" +#endif #define ROOT_PET (0) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 5925bcca86..fc7d5bd1cc 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -22,7 +22,8 @@ // declared in the companion file {\tt ESMCI\_PIO_Handler.h} // //------------------------------------------------------------------------- -#define PIO_DEBUG_LEVEL 0 +#define PIO_DEBUG_LEVEL 4 +#define ESMFIO_DEBUG 1 // include associated header file #include "ESMCI_PIO_Handler.h" @@ -738,7 +739,7 @@ void PIO_Handler::arrayReadOneTileFile( #endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) #ifdef ESMFIO_DEBUG - PIOc_set_log_level(0); + PIOc_set_log_level(4); #endif // ESMFIO_DEBUG PRINTMSG("calling read_darray, pio type = " << basepiotype << ", address = " << baseAddress); @@ -1189,7 +1190,7 @@ void PIO_Handler::arrayWriteOneTileFile( #endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) PRINTMSG("calling write_darray, pio type = " << basepiotype << ", address = " << baseAddress); #ifdef ESMFIO_DEBUG - PIOc_set_log_level(0); + PIOc_set_log_level(4); #endif // ESMFIO_DEBUG // Write the array ESMCI_IOREGION_ENTER("PIOc_write_darray"); @@ -1384,7 +1385,7 @@ void PIO_Handler::openOneTileFile( PRINTMSG("call to PIOc_createfile: success for " << thisFilename << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "< + +// ESMF header +#include "ESMC.h" + +// ESMF Test header +#include "ESMC_Test.h" + +#if defined ESMF_MOAB +#include "ESMCI_MBMesh.h" +#include "ESMCI_MBMesh_Glue.h" +#include "ESMCI_MCTGen.C" +#endif + +#include "ESMCI_MeshCap.h" +#include "ESMCI_Mesh.h" + +#include +#include +#include +#include +#include +#include +#include //find_if +#include + +struct FindPair { + FindPair (std::string first, std::string second) \ + : m_first_value(first), m_second_value(second) {} + + std::string m_first_value; + std::string m_second_value; + bool operator() (const std::pair &p) { + return (p.first == m_first_value && p.second == m_second_value); + } +}; + +void combine(const std::string &api, const std::string &mesh, + const std::string &nativeormb){ + int localrc; + int rc = ESMF_FAILURE; + + std::string failMsg = "FAIL"; + int result = 0; + +#if defined ESMF_MOAB + MCTGen *generate = new MCTGen(); +#endif + + int nvmb = 1; + if (nativeormb == "Native") nvmb = 0; + + int localPet, petCount; + ESMC_VM vm; + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + std::array buffer; + buffer.fill(0); + time_t rawtime; + time(&rawtime); + const auto timeinfo = localtime(&rawtime); + strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); + std::string timeStr(buffer.data()); + + std::string name = timeStr + " - " + "PET " + std::to_string(localPet) + " - " + + nativeormb + " Mesh - " + api + " - " + mesh; + +#if defined ESMF_MOAB + try { + std::shared_ptr test = generate->mesh_map[mesh](localrc); + + test->name = name; + test->nativeormb = nvmb; + // test->verbosity = 3; + // test->tol = 1.e-15; + // test->print(); + + if (localrc == ESMF_SUCCESS) localrc = test->build(); + if (localrc == ESMF_SUCCESS) rc = test->function_map[api](); + + // test is a shared_ptr so no need to delete + // delete test; + } + CATCH_MCT_FAIL(&rc) +#else + rc = ESMF_SUCCESS; +#endif + +#if defined ESMF_MOAB + delete generate; +#endif + + ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), + &result, __FILE__, __LINE__, 0); + +} + +int main(int argc, char *argv[]) { +#undef ESMC_METHOD +#define ESMC_METHOD "MeshCapUTest::main()" + + int rc; + int localPet, petCount; + ESMC_VM vm; + + std::string failMsg = "FAIL"; + // break this up so it doesn't count as an additional test + std::string nex_test_tag = "//NEX_"; + nex_test_tag.append("UTest\n"); + int result = 0; + + //---------------------------------------------------------------------------- + // Start the test with an alternate name for log and stdout files + ESMC_TestStart("ESMCI_MeshCapGenUTest.C", __LINE__, 0); + + //---------------------------------------------------------------------------- + rc=ESMC_LogSet(true); + + // Get parallel information + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + // output stream to write test tag to the generated source file + std::ofstream tagfile; + tagfile.open("ESMCI_MeshCapGenUTest.C", std::ios_base::app); + + // this is an easy way to comment a single line to toggle mbmesh/native + bool mbmesh = false; + mbmesh = true; + bool native = false; + native = true; + + // these are bound to MCT in constructor, must match! + std::vector test_apis; + test_apis.push_back("createget"); + test_apis.push_back("dual"); + test_apis.push_back("redist_elem"); + test_apis.push_back("redist_node"); + test_apis.push_back("redist_elno"); + test_apis.push_back("serialize"); + test_apis.push_back("to_pointlist_elem"); + test_apis.push_back("to_pointlist_node"); + test_apis.push_back("write_vtk"); + + // these are bound to MCTGen in constructor, must match! + std::vector test_meshes_native; + test_meshes_native.push_back("quad_2d_cart"); + test_meshes_native.push_back("quad_2d_sph_deg"); + test_meshes_native.push_back("quad_2d_sph_rad"); + test_meshes_native.push_back("tri_2d_cart"); + test_meshes_native.push_back("tri_2d_sph_deg"); + test_meshes_native.push_back("tri_2d_sph_rad"); + test_meshes_native.push_back("hex_3d_cart"); + test_meshes_native.push_back("hex_3d_sph_deg"); + test_meshes_native.push_back("hex_3d_sph_rad"); + test_meshes_native.push_back("mix_2d_cart"); + test_meshes_native.push_back("mix_2d_sph_deg"); + test_meshes_native.push_back("mix_2d_sph_rad"); + test_meshes_native.push_back("periodic_2d_sph_deg"); + test_meshes_native.push_back("periodic_2d_sph_rad"); + // cannot get info from ngons + // test_meshes_native.push_back("ngon_2d_cart"); + // test_meshes_native.push_back("ngon_2d_sph_deg"); + // test_meshes_native.push_back("ngon_2d_sph_rad"); + + // these are bound to MCTGen in constructor, must match! + std::vector test_meshes_mbmesh; + test_meshes_mbmesh.push_back("quad_2d_cart"); + test_meshes_mbmesh.push_back("quad_2d_sph_deg"); + test_meshes_mbmesh.push_back("quad_2d_sph_rad"); + test_meshes_mbmesh.push_back("tri_2d_cart"); + test_meshes_mbmesh.push_back("tri_2d_sph_deg"); + test_meshes_mbmesh.push_back("tri_2d_sph_rad"); + test_meshes_mbmesh.push_back("hex_3d_cart"); + test_meshes_mbmesh.push_back("hex_3d_sph_deg"); + test_meshes_mbmesh.push_back("hex_3d_sph_rad"); + test_meshes_mbmesh.push_back("mix_2d_cart"); + test_meshes_mbmesh.push_back("mix_2d_sph_deg"); + test_meshes_mbmesh.push_back("mix_2d_sph_rad"); + test_meshes_mbmesh.push_back("ngon_2d_cart"); + test_meshes_mbmesh.push_back("ngon_2d_sph_deg"); + test_meshes_mbmesh.push_back("ngon_2d_sph_rad"); + test_meshes_mbmesh.push_back("periodic_2d_sph_deg"); + test_meshes_mbmesh.push_back("periodic_2d_sph_rad"); + + // skip the following tests + std::vector> skip_test_mbmesh = {\ + // dual not implemented in 3d + {"dual", "hex_3d_cart"}, + {"dual", "hex_3d_sph_deg"}, + {"dual", "hex_3d_sph_rad"}, + // ESMCI_MBMesh_Redist.C, line:2336:Could not find a suitable processor for this element + {"redist_node", "tri_2d_cart"}, + {"redist_node", "tri_2d_sph_deg"}, + {"redist_node", "tri_2d_sph_rad"}, + + }; + + std::vector> skip_test_native = {\ + // dual not implemented in 3d + // Creation of a dual mesh isn't supported for Meshes of parametric dim greater than 3. + {"dual", "hex_3d_cart"}, + {"dual", "hex_3d_sph_deg"}, + {"dual", "hex_3d_sph_rad"}, + }; + + + if (mbmesh) { + for (const auto api: test_apis) { + for (const auto mesh: test_meshes_mbmesh) { + // don't run cases that hang + auto skip_itr = std::find_if(skip_test_mbmesh.begin(), skip_test_mbmesh.end(), + FindPair(api, mesh)); + + if (skip_itr != skip_test_mbmesh.end()) { + continue; + } else { + combine(api, mesh, "MBMesh"); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + + if (native) { + for (const auto api: test_apis) { + for (const auto mesh: test_meshes_native) { + // don't run cases that hang + auto skip_itr = std::find_if(skip_test_native.begin(), skip_test_native.end(), + FindPair(api, mesh)); + + if (skip_itr != skip_test_native.end()) { + continue; + } else { + combine(api, mesh, "Native"); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + + tagfile.close(); + + //---------------------------------------------------------------------------- + ESMC_TestEnd("ESMCI_MeshCapGenUTest.C", __LINE__, 0); + + return 0; +} +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest diff --git a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C new file mode 100644 index 0000000000..52f3cc146c --- /dev/null +++ b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C @@ -0,0 +1,5091 @@ +//============================================================================== +// +// Earth System Modeling Framework +// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +// Massachusetts Institute of Technology, Geophysical Fluid Dynamics +// Laboratory, University of Michigan, National Centers for Environmental +// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +// NASA Goddard Space Flight Center. +// Licensed under the University of Illinois-NCSA License. +// +//============================================================================== +#ifndef MPICH_IGNORE_CXX_SEEK +#define MPICH_IGNORE_CXX_SEEK +#endif +#include + +// ESMF header +#include "ESMC.h" + +// ESMF Test header +#include "ESMC_Test.h" + +#if defined ESMF_MOAB +#include "ESMCI_MBMesh.h" +#include "ESMCI_MBMesh_Glue.h" +#include "ESMCI_MCTGen.C" +#endif + +#include +#include +#include +#include +#include +#include +#include //find_if +#include +#include + +struct FindAnyPair { + FindAnyPair (std::string a, std::string b, std::string c, std::string d, + std::string e, std::string f, std::string g, std::string h) + : a_val(a), b_val(b), c_val(c), d_val(d), + e_val(e), f_val(f), g_val(g), h_val(h) {} + + std::string a_val; + std::string b_val; + std::string c_val; + std::string d_val; + std::string e_val; + std::string f_val; + std::string g_val; + std::string h_val; + bool operator() + ( const std::pair &p ) { + return (((p.first == a_val) || (p.first == b_val) || + (p.first == c_val) || (p.first == d_val) || + (p.first == e_val) || (p.first == f_val) || + (p.first == g_val) || (p.first == h_val)) && + ((p.second == a_val) || (p.second == b_val) || + (p.second == c_val) || (p.second == d_val) || + (p.second == e_val) || (p.second == f_val) || + (p.second == g_val) || (p.second == h_val))); + } +}; + +void combine(const std::string &api, const std::string &mesh, + const std::string &nativeormb, + const std::string &maptype, + const std::string &normtype, + const std::string &poletype, + const std::string &extrapmethod, + const std::string &unmappedaction, + const std::string &ignoredegenerate){ + int localrc; + int rc = ESMF_FAILURE; + + std::string failMsg = "FAIL"; + std::string dash = " - "; + int result = 0; + +#if defined ESMF_MOAB + MCTGen *generate = new MCTGen(); +#endif + + int nvmb = 1; + if (nativeormb == "Native") nvmb = 0; + + int localPet, petCount; + ESMC_VM vm; + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + std::array buffer; + buffer.fill(0); + time_t rawtime; + time(&rawtime); + const auto timeinfo = localtime(&rawtime); + strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); + std::string timeStr(buffer.data()); + + std::string name = timeStr + dash + "PET " + std::to_string(localPet) + dash + + nativeormb + " Mesh - " + api + dash + mesh + + dash + maptype + dash + normtype + dash + poletype + + dash + extrapmethod + dash + unmappedaction + + dash + ignoredegenerate; + +#if defined ESMF_MOAB + try { + std::shared_ptr test = generate->mesh_map[mesh](localrc); + + test->name = name; + test->nativeormb = nvmb; + // test->verbosity = 3; + // test->tol = 1.e-15; + // test->print(); + + // convert parameters to integers + int mt = test->MapType[maptype]; + int nt = test->NormType[normtype]; + int pt = test->PoleType[poletype]; + int em = test->ExtrapMethod[extrapmethod]; + int ua = test->UnmappedAction[unmappedaction]; + int id = test->IgnoreDegenerate[ignoredegenerate]; + + if (localrc == ESMF_SUCCESS) localrc = test->build(); + if (localrc == ESMF_SUCCESS) rc = test->regrid_map[api](mt, nt, pt, + em, ua, id); + + // test is a shared_ptr so no need to delete + // delete test; + } + CATCH_MCT_FAIL(&rc) +#else + rc = ESMF_SUCCESS; +#endif + +#if defined ESMF_MOAB + delete generate; +#endif + + ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), + &result, __FILE__, __LINE__, 0); +} + +int main(int argc, char *argv[]) { +#undef ESMC_METHOD +#define ESMC_METHOD "MBMeshRegidUTest::main()" + + int rc, localrc; + int localPet, petCount; + ESMC_VM vm; + + std::string failMsg = "FAIL"; + // break this up so it doesn't count as an additional test + std::string nex_test_tag = "//NEX_"; + nex_test_tag.append("UTest\n"); + int result = 0; + + //---------------------------------------------------------------------------- + // Start the test with an alternate name for log and stdout files + ESMC_TestStart("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); + + //---------------------------------------------------------------------------- + rc=ESMC_LogSet(true); + + // Get parallel information + vm=ESMC_VMGetGlobal(&rc); + rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, + (int *)NULL, (int *)NULL); + + // output stream to write test tag to the generated source file + std::ofstream tagfile; + tagfile.open("ESMCI_MeshCapRegridGenUTest.C", std::ios_base::app); + + // this is an easy way to comment a single line to toggle mbmesh/native + bool mbmesh = false; + mbmesh = true; + bool native = false; + native = true; + + std::vector test_apis_mbmesh; + test_apis_mbmesh.push_back("bilinear"); + test_apis_mbmesh.push_back("conservative"); + test_apis_mbmesh.push_back("nearest_d2s"); + test_apis_mbmesh.push_back("nearest_s2d"); + // Not yet available with MBMesh + // test_apis_mbmesh.push_back("conservative_2nd"); + // test_apis_mbmesh.push_back("patch"); + + std::vector test_apis_native; + test_apis_native.push_back("bilinear"); + test_apis_native.push_back("conservative"); + test_apis_native.push_back("conservative_2nd"); + test_apis_native.push_back("nearest_d2s"); + test_apis_native.push_back("nearest_s2d"); + test_apis_native.push_back("patch"); + + // these are bound to MCTGen in constructor, must match! + std::vector test_meshes; + test_meshes.push_back("quad_2d_cart"); + test_meshes.push_back("quad_2d_sph_deg"); + test_meshes.push_back("quad_2d_sph_rad"); + test_meshes.push_back("tri_2d_cart"); + test_meshes.push_back("tri_2d_sph_deg"); + test_meshes.push_back("tri_2d_sph_rad"); + test_meshes.push_back("hex_3d_cart"); + test_meshes.push_back("hex_3d_sph_deg"); + test_meshes.push_back("hex_3d_sph_rad"); + test_meshes.push_back("mix_2d_cart"); + test_meshes.push_back("mix_2d_sph_deg"); + test_meshes.push_back("mix_2d_sph_rad"); + test_meshes.push_back("ngon_2d_cart"); + test_meshes.push_back("ngon_2d_sph_deg"); + test_meshes.push_back("ngon_2d_sph_rad"); + test_meshes.push_back("periodic_2d_sph_deg"); + test_meshes.push_back("periodic_2d_sph_rad"); + + // method dependent, and mesh dependent + std::vector test_regrid_maptype; + test_regrid_maptype.push_back("MAP_CARTAPPROX"); + test_regrid_maptype.push_back("MAP_GREATCIRCLE"); + + // only conservative methods, all meshes + std::vector test_regrid_normtype; + test_regrid_normtype.push_back("NORM_DSTAREA"); + test_regrid_normtype.push_back("NORM_FRACAREA"); + + // all methods, but only for periodic grids + std::vector test_regrid_poletype; + test_regrid_poletype.push_back("POLE_NONE"); + test_regrid_poletype.push_back("POLE_ALL"); + test_regrid_poletype.push_back("POLE_NPNT"); + test_regrid_poletype.push_back("POLE_TEETH"); + + // all methods except nn, but only for meshes with destination larger than source + std::vector test_regrid_extrapmethod; + test_regrid_extrapmethod.push_back("EXTRAP_NONE"); + test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_STOD"); + test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_IDAVG"); + test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_D"); + test_regrid_extrapmethod.push_back("EXTRAP_CREEP"); + test_regrid_extrapmethod.push_back("EXTRAP_CREEP_NRST_D"); + + // all methods except nn, but only for meshes with destination larger than source + std::vector test_regrid_unmappedaction; + test_regrid_unmappedaction.push_back("UNMAPPED_THROWERROR"); + test_regrid_unmappedaction.push_back("UNMAPPED_IGNORE"); + + // all methods except nn, but only meshes with degenerate, clockwise or concave elements + std::vector test_regrid_ignoredegenerate; + test_regrid_ignoredegenerate.push_back("DONOT_IGNORE_DEGENERATE"); + test_regrid_ignoredegenerate.push_back("IGNORE_DEGENERATE"); + + + + std::vector> skip_test_mbmesh = {\ + // conservative not supported with ngons + {"conservative", "ngon_2d_cart"}, + {"conservative", "ngon_2d_sph_deg"}, + {"conservative", "ngon_2d_sph_rad"}, + // extrapolation methods not supported (why do EXTRAP_NEAREST_STOD, EXTRAP_NEAREST_IDAVG work?) + {"bilinear", "EXTRAP_NEAREST_D"}, + {"bilinear", "EXTRAP_CREEP"}, + {"bilinear", "EXTRAP_CREEP_NRST_D"}, + {"patch", "EXTRAP_NEAREST_D"}, + {"patch", "EXTRAP_CREEP"}, + {"patch", "EXTRAP_CREEP_NRST_D"}, + }; + + std::vector> skip_test_native = {\ + // meshes with ngons return incorrect element count with native + {"bilinear", "ngon_2d_cart"}, + {"bilinear", "ngon_2d_sph_deg"}, + {"bilinear", "ngon_2d_sph_rad"}, + {"patch", "ngon_2d_cart"}, + {"patch", "ngon_2d_sph_deg"}, + {"patch", "ngon_2d_sph_rad"}, + {"conservative", "ngon_2d_cart"}, + {"conservative", "ngon_2d_sph_deg"}, + {"conservative", "ngon_2d_sph_rad"}, + {"conservative_2nd", "ngon_2d_cart"}, + {"conservative_2nd", "ngon_2d_sph_deg"}, + {"conservative_2nd", "ngon_2d_sph_rad"}, + // Conservative not supported on 3D spherical meshes + {"conservative", "hex_3d_sph_deg"}, + {"conservative", "hex_3d_sph_rad"}, + }; + + std::vector> skip_test_common = {\ + // patch not supported in 3d + {"patch", "hex_3d_cart"}, + {"patch", "hex_3d_sph_deg"}, + {"patch", "hex_3d_sph_rad"}, + // conservative_2nd not supported in 3d + {"conservative_2nd", "hex_3d_cart"}, + {"conservative_2nd", "hex_3d_sph_deg"}, + {"conservative_2nd", "hex_3d_sph_rad"}, + // creep fill extrapolation not supported in 3D + {"hex_3d_cart", "EXTRAP_CREEP"}, + {"hex_3d_sph_deg", "EXTRAP_CREEP"}, + {"hex_3d_sph_rad", "EXTRAP_CREEP"}, + {"hex_3d_cart", "EXTRAP_CREEP_NRST_D"}, + {"hex_3d_sph_deg", "EXTRAP_CREEP_NRST_D"}, + {"hex_3d_sph_rad", "EXTRAP_CREEP_NRST_D"}, + // conservative is not supported with extrapolation + {"conservative", "EXTRAP_NEAREST_STOD"}, + {"conservative", "EXTRAP_NEAREST_IDAVG"}, + {"conservative", "EXTRAP_NEAREST_D"}, + {"conservative", "EXTRAP_CREEP"}, + {"conservative", "EXTRAP_CREEP_NRST_D"}, + {"conservative_2nd", "EXTRAP_NEAREST_STOD"}, + {"conservative_2nd", "EXTRAP_NEAREST_IDAVG"}, + {"conservative_2nd", "EXTRAP_NEAREST_D"}, + {"conservative_2nd", "EXTRAP_CREEP"}, + {"conservative_2nd", "EXTRAP_CREEP_NRST_D"}, + // the following are exceptions due to design, do not represent limitations per se + // conservative only works with great circles + {"conservative", "MAP_CARTAPPROX"}, + {"conservative_2nd", "MAP_CARTAPPROX"}, + // cartesian only works with straight lines + {"quad_2d_cart", "MAP_GREATCIRCLE"}, + {"tri_2d_cart", "MAP_GREATCIRCLE"}, + {"hex_3d_cart", "MAP_GREATCIRCLE"}, + {"mix_2d_cart", "MAP_GREATCIRCLE"}, + {"ngon_2d_cart", "MAP_GREATCIRCLE"}, + // nearest doesn't touch on any of the regrid options, only allow defaults + {"nearest_d2s", "MAP_GREATCIRCLE"}, + {"nearest_d2s", "POLE_ALL"}, + {"nearest_d2s", "POLE_NPNT"}, + {"nearest_d2s", "POLE_TEETH"}, + {"nearest_d2s", "EXTRAP_NEAREST_STOD"}, + {"nearest_d2s", "EXTRAP_NEAREST_IDAVG"}, + {"nearest_d2s", "EXTRAP_NEAREST_D"}, + {"nearest_d2s", "EXTRAP_CREEP"}, + {"nearest_d2s", "EXTRAP_CREEP_NRST_D"}, + {"nearest_d2s", "UNMAPPED_IGNORE"}, + {"nearest_d2s", "IGNORE_DEGENERATE"}, + {"nearest_s2d", "MAP_GREATCIRCLE"}, + {"nearest_s2d", "POLE_ALL"}, + {"nearest_s2d", "POLE_NPNT"}, + {"nearest_s2d", "POLE_TEETH"}, + {"nearest_s2d", "EXTRAP_NEAREST_STOD"}, + {"nearest_s2d", "EXTRAP_NEAREST_IDAVG"}, + {"nearest_s2d", "EXTRAP_NEAREST_D"}, + {"nearest_s2d", "EXTRAP_CREEP"}, + {"nearest_s2d", "EXTRAP_CREEP_NRST_D"}, + {"nearest_s2d", "UNMAPPED_IGNORE"}, + {"nearest_s2d", "IGNORE_DEGENERATE"}, + // only run pole options with periodic meshes + {"quad_2d_cart", "POLE_ALL"}, + {"quad_2d_sph_deg", "POLE_ALL"}, + {"quad_2d_sph_rad", "POLE_ALL"}, + {"tri_2d_cart", "POLE_ALL"}, + {"tri_2d_sph_deg", "POLE_ALL"}, + {"tri_2d_sph_rad", "POLE_ALL"}, + {"hex_3d_cart", "POLE_ALL"}, + {"hex_3d_sph_deg", "POLE_ALL"}, + {"hex_3d_sph_rad", "POLE_ALL"}, + {"mix_2d_cart", "POLE_ALL"}, + {"mix_2d_sph_deg", "POLE_ALL"}, + {"mix_2d_sph_rad", "POLE_ALL"}, + {"ngon_2d_cart", "POLE_ALL"}, + {"ngon_2d_sph_deg", "POLE_ALL"}, + {"ngon_2d_sph_rad", "POLE_ALL"}, + {"quad_2d_cart", "POLE_NPNT"}, + {"quad_2d_sph_deg", "POLE_NPNT"}, + {"quad_2d_sph_rad", "POLE_NPNT"}, + {"tri_2d_cart", "POLE_NPNT"}, + {"tri_2d_sph_deg", "POLE_NPNT"}, + {"tri_2d_sph_rad", "POLE_NPNT"}, + {"hex_3d_cart", "POLE_NPNT"}, + {"hex_3d_sph_deg", "POLE_NPNT"}, + {"hex_3d_sph_rad", "POLE_NPNT"}, + {"mix_2d_cart", "POLE_NPNT"}, + {"mix_2d_sph_deg", "POLE_NPNT"}, + {"mix_2d_sph_rad", "POLE_NPNT"}, + {"ngon_2d_cart", "POLE_NPNT"}, + {"ngon_2d_sph_deg", "POLE_NPNT"}, + {"ngon_2d_sph_rad", "POLE_NPNT"}, + {"quad_2d_cart", "POLE_TEETH"}, + {"quad_2d_sph_deg", "POLE_TEETH"}, + {"quad_2d_sph_rad", "POLE_TEETH"}, + {"tri_2d_cart", "POLE_TEETH"}, + {"tri_2d_sph_deg", "POLE_TEETH"}, + {"tri_2d_sph_rad", "POLE_TEETH"}, + {"hex_3d_cart", "POLE_TEETH"}, + {"hex_3d_sph_deg", "POLE_TEETH"}, + {"hex_3d_sph_rad", "POLE_TEETH"}, + {"mix_2d_cart", "POLE_TEETH"}, + {"mix_2d_sph_deg", "POLE_TEETH"}, + {"mix_2d_sph_rad", "POLE_TEETH"}, + {"ngon_2d_cart", "POLE_TEETH"}, + {"ngon_2d_sph_deg", "POLE_TEETH"}, + {"ngon_2d_sph_rad", "POLE_TEETH"}, + }; + + + if (mbmesh) { + for (const auto api: test_apis_mbmesh) { + for (const auto mesh: test_meshes) { + for (const auto mt: test_regrid_maptype) { + for (const auto nt: test_regrid_normtype) { + for (const auto pt: test_regrid_poletype) { + for (const auto em: test_regrid_extrapmethod) { + for (const auto ua: test_regrid_unmappedaction) { + for (const auto id: test_regrid_ignoredegenerate) { + auto skip_itr_common = std::find_if(skip_test_common.begin(), + skip_test_common.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + auto skip_itr_mbmesh = std::find_if(skip_test_mbmesh.begin(), + skip_test_mbmesh.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + if ((skip_itr_common != skip_test_common.end()) || + (skip_itr_mbmesh != skip_test_mbmesh.end())) { + continue; + } else { + combine(api, mesh, "MBMesh", mt, nt, pt, em, ua, id); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + } + } + } + } + } + } + + if (native) { + for (const auto api: test_apis_native) { + for (const auto mesh: test_meshes) { + for (const auto mt: test_regrid_maptype) { + for (const auto nt: test_regrid_normtype) { + for (const auto pt: test_regrid_poletype) { + for (const auto em: test_regrid_extrapmethod) { + for (const auto ua: test_regrid_unmappedaction) { + for (const auto id: test_regrid_ignoredegenerate) { + auto skip_itr_common = std::find_if(skip_test_common.begin(), + skip_test_common.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + auto skip_itr_native = std::find_if(skip_test_native.begin(), + skip_test_native.end(), + FindAnyPair(api, mesh, + mt, nt, pt, + em, ua, id)); + + if ((skip_itr_common != skip_test_common.end()) || + (skip_itr_native != skip_test_native.end())) { + continue; + } else { + combine(api, mesh, "Native", mt, nt, pt, em, ua, id); + // only print one tag per test (so only on root) + if (localPet == 0) tagfile << nex_test_tag; + } + } + } + } + } + } + } + } + } + } + + tagfile.close(); + + //---------------------------------------------------------------------------- + ESMC_TestEnd("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); + + return 0; +} +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest +//NEX_UTest diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 4f720f4806..859714dbbe 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -6913,15 +6913,15 @@ subroutine test_create_mesh_from_SH_file(correct, rc) if (rc /= ESMF_SUCCESS) return ! Create Mesh from shape file - mesh=ESMF_MeshCreate("data/complex_3.shp", & + mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & fileformat=ESMF_FILEFORMAT_SHAPEFILE, & rc=rc) if (rc /= ESMF_SUCCESS) return !! Write mesh for debugging -! call ESMF_MeshWrite(mesh,"complex_3",rc=rc) -! if (rc /= ESMF_SUCCESS) return + call ESMF_MeshWrite(mesh,"cb_2018_us_county_500k",rc=rc) + if (rc /= ESMF_SUCCESS) return ! Get rid of Mesh call ESMF_MeshDestroy(mesh, rc=rc) From 33af2100c622a5354ca5f4205d828d6e4d735dd1 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Mon, 17 Jul 2023 11:30:41 -0400 Subject: [PATCH 12/58] Compiles. Defined ESMF_IOFMT_SHP. Next: GDAL_Handler class MSL --- .../IO/include/ESMCI_GDAL_Handler.h | 2 +- .../IO/src/ESMCI_GDAL_Handler.C | 2224 ++++--- src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 8 + .../IO/tests/ESMF_IO_GDALUTest.F90 | 145 + .../IO/tests/ESMF_IO_MultitileUTest.Log | 0 .../Mesh/tests/ESMCI_MeshCapGenUTest.C | 537 -- .../Mesh/tests/ESMCI_MeshCapRegridGenUTest.C | 5091 ----------------- src/Infrastructure/Util/include/ESMC_Util.h | 3 +- .../Util/src/ESMF_UtilTypes.F90 | 6 +- 9 files changed, 1258 insertions(+), 6758 deletions(-) create mode 100644 src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 delete mode 100644 src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.Log delete mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C delete mode 100644 src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C diff --git a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h index f96df3c629..06753eead5 100644 --- a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h @@ -123,7 +123,7 @@ namespace ESMCI { } // open() and close() - void openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); + void GDAL_openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); ESMC_Logical isOpen(int tile); ESMC_Logical isNewFile(int tile) { // note 1-based indexing for tile return (new_file[tile-1] ? ESMF_TRUE : ESMF_FALSE); diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index 7ebe79111d..a1ba61c274 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -46,6 +46,8 @@ #include "json.hpp" #include "ESMCI_TraceMacros.h" +#include "pio.h" + #include "esmf_io_debug.h" using json = nlohmann::json; // Convenience rename for JSON namespace. @@ -178,8 +180,8 @@ void GDAL_Handler::initialize ( if (!instanceFound) { PRINTMSG("Before GDALc_Init_Intracomm, num_iotasks = " << num_iotasks); -// GDALc_Init_Intracomm(comp_comm, num_iotasks, -// stride, base, rearr, &instance); + PIOc_Init_Intracomm(comp_comm, num_iotasks, + stride, base, rearr, &instance); PRINTMSG("After GDALc_Init_Intracomm, instance = " << instance); // If we get here, hopefully everything is OK. if (instance != 0) { @@ -578,16 +580,13 @@ void GDAL_Handler::arrayReadOneTileFile( PRINTPOS; // File open? - if (isOpen(tile) != ESMF_TRUE) - if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", - ESMC_CONTEXT, rc)) return; // Array compatible with this object? - localrc = checkArray(arr_p); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) - return; +// localrc = checkArray(arr_p); +// if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) +// return; - filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based +// filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 @@ -605,7 +604,7 @@ void GDAL_Handler::arrayReadOneTileFile( baseAddress = NULL; arrlen = 0; } -#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) + int nDims; // If frame >= 0 then we need to not use the unlimited dim in the iodesc. @@ -615,11 +614,11 @@ void GDAL_Handler::arrayReadOneTileFile( ESMC_CONTEXT, rc)) return; // This should work if it is a NetCDF file. - gdalrc = GDALc_inq(filedesc, &nDims, - &nVar, &nAtt, &unlim); - if (!CHECKGDALERROR(gdalrc, "File is not in NetCDF format", ESMF_RC_FILE_READ, (*rc))) { - return; - } +// gdalrc = GDALc_inq(filedesc, &nDims, +// &nVar, &nAtt, &unlim); +// if (!CHECKGDALERROR(gdalrc, "File is not in NetCDF format", ESMF_RC_FILE_READ, (*rc))) { +// return; +// } if (((char *)NULL != name) && (strlen(name) > 0)) { varname = name; @@ -627,91 +626,89 @@ void GDAL_Handler::arrayReadOneTileFile( varname = arr_p->getName(); } - gdalrc = GDALc_inq_varid(filedesc, varname.c_str(), &vardesc); +// gdalrc = GDALc_inq_varid(filedesc, varname.c_str(), &vardesc); // An error here means the variable is not in the file - const std::string errmsg = "variable " + varname + " not found in file"; - if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { - return; - } - - int frame; - if (((int *)NULL != timeslice) && (*timeslice > 0) && narrDims < nioDims) { - // - // Do not use the unlimited dim in iodesc calculation - // - int dimids[narrDims]; - gdalrc = GDALc_inq_vardimid(filedesc, vardesc, dimids); - // This should never happen - const std::string errmsg = "variable " + varname + " inq_dimid failed"; - if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { - return; - } - - if(unlim == dimids[narrDims-1]){ - narrDims = narrDims - 1; - } - for (int i=0; i> int frame; +//>> if (((int *)NULL != timeslice) && (*timeslice > 0) && narrDims < nioDims) { +//>> // +//>> // Do not use the unlimited dim in iodesc calculation +//>> // +//>> int dimids[narrDims]; +// gdalrc = GDALc_inq_vardimid(filedesc, vardesc, dimids); +// // This should never happen +// const std::string errmsg = "variable " + varname + " inq_dimid failed"; +// if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { +// return; +// } + +// if(unlim == dimids[narrDims-1]){ +// narrDims = narrDims - 1; +// } +// for (int i=0; i time_len) { - PRINTMSG(" (" << my_rank << "): " << - "Timeframe is greater than that in file" << - getFilename(tile) << ", file time = " << time_len << - ", requested record = " << *timeslice); - if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, - "Timeframe is greater than max in file", - ESMC_CONTEXT, rc)) { - return; - } - } - frame = (*timeslice); - } else { - frame = -1; - for (int i=0; i= 0 && frame > 0) { - PRINTMSG("calling setframe for read_darray, frame = " << frame); - GDALc_setframe(filedesc, vardesc, frame-1); - } - -#endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) +// gdalrc = GDALc_inq_dimlen(filedesc, +// dimid_time, &time_len); +// if (!CHECKGDALERROR(gdalrc, "Error finding time length", ESMF_RC_FILE_READ, (*rc))) { +// return; +// } +// if (*timeslice > time_len) { +// PRINTMSG(" (" << my_rank << "): " << +// "Timeframe is greater than that in file" << +// getFilename(tile) << ", file time = " << time_len << +// ", requested record = " << *timeslice); +// if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, +// "Timeframe is greater than max in file", +// ESMC_CONTEXT, rc)) { +// return; +// } +// } +// frame = (*timeslice); +// } else { +// frame = -1; +// for (int i=0; i= 0 && frame > 0) { +// PRINTMSG("calling setframe for read_darray, frame = " << frame); +// GDALc_setframe(filedesc, vardesc, frame-1); +// } PRINTMSG("calling read_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); // Read in the array - gdalrc = GDALc_read_darray(filedesc, vardesc, iodesc, - arrlen, (void *)baseAddress); - - if (!CHECKGDALERROR(gdalrc, "Error reading array data", ESMF_RC_FILE_READ, (*rc))) { - return; - } +// gdalrc = GDALc_read_darray(filedesc, vardesc, iodesc, +// arrlen, (void *)baseAddress); +// +// if (!CHECKGDALERROR(gdalrc, "Error reading array data", ESMF_RC_FILE_READ, (*rc))) { +// return; +// } // return if (rc != NULL) { @@ -754,414 +751,413 @@ void GDAL_Handler::arrayWriteOneTileFile( // //EOPI //----------------------------------------------------------------------------- - // initialize return code; assume routine not implemented - int localrc = ESMF_RC_NOT_IMPL; // local return code - int gdalrc; // GDAL error value - int * ioDims; // Array IO shape - int nioDims; // Array IO rank - int * arrDims; // Array shape - int narrDims; // Array rank - int iodesc; // GDAL IO descriptor - int filedesc; // GDAL file descriptor - int vardesc = 0; // GDAL variable descriptor - int basegdaltype; // GDAL version of Array data type - void *baseAddress; // The address of the Array IO data - int localDE; // DE to use for IO - int ncDims[8]; // To hold NetCDF dimensions - int unlim = -1; // Unlimited dimension ID - int timeFrame = -1; // ID of time dimension (>0 if used) - int timesliceVal = -1; // Used time value (from timeslice) - bool varExists = false; // true if varname is defined in file - std::string varname; // Variable name - if (rc != NULL) { - *rc = ESMF_RC_NOT_IMPL; // final return code - } - - PRINTPOS; - - if ((int *)NULL != timeslice) { - timesliceVal = *timeslice; - } - // File open? - if (isOpen(tile) != ESMF_TRUE) - if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", - ESMC_CONTEXT, rc)) return; - - // Array compatible with this object? - localrc = checkArray(arr_p); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) - return; - - filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based - iodesc = getIODesc(gdalSystemDesc, arr_p, tile, &ioDims, &nioDims, - &arrDims, &narrDims, &basegdaltype, &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, - ESMC_CONTEXT, rc)) return; - for (int i=0; i 0 && dimLabels.size() < (unsigned int)nioDims) { - std::stringstream errmsg; - errmsg << dimLabels.size() << " user dimension label(s) supplied, " << nioDims << " expected"; - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_SIZE, errmsg, - ESMC_CONTEXT, rc)) return; - } - - - // Get a pointer to the array data - // Still have the one DE restriction so use localDE = 0 - localDE = 0; - int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDE, &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, - ESMC_CONTEXT, rc)) return; - int arrlen; - if (tileOfThisDe == tile) { - baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); - PRINTMSG("baseAddress = 0x" << (void *)baseAddress); - // arrlen = arr_p->getLocalarrayList()[localDE]->getByteCount(); - arrlen = 1; - const int *counts = arr_p->getLocalarrayList()[localDE]->getCounts(); - for (int i=0; i= 0) { - if (varExists & !hasTimeDim) { - // It is an error to not have a time dimension if we are trying to - // write a timeslice and the variable already exists - // (it won't have time) - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, - "Field already exists without time dimension", - ESMC_CONTEXT, rc)) { - return; - } - } else { - timeFrame = timesliceVal; - } - } else if (timesliceVal < 0) { - // Special case for no timeslice input passed but time dimension exists - if (varExists && hasTimeDim) { - timeFrame = timeLen + 1; - PRINTMSG("timeslice not passed but set to " << timeFrame); - } - } - - PRINTMSG("ready to check var compat., timeFrame = " << timeFrame); - if (varExists) { - int nDims; - int nArrdims = nioDims + ((timeFrame > 0) ? 1 : 0); - - // Check compatibility between array to write and existing variable. - gdalrc = GDALc_inq_varndims(filedesc, vardesc, &nDims); - if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - - if (nDims != nArrdims) { - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, - "Variable rank in file does not match array", - ESMC_CONTEXT, rc)) { - PRINTMSG("Variable rank mismatch: nioDims = " << nioDims << - ", nArrdims = " << nArrdims << ", nDims = " << nDims); - return; - } - } - - PRINTMSG("Calling gdal_cpp_inq_vardimid_vdesc"); - std::vector dimIds(nDims); - gdalrc = GDALc_inq_vardimid(filedesc, vardesc, &dimIds.front()); - if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - - MPI_Offset dimLen; - int ioDimNum = 0; - for (int i = 0; i < nDims; i++) { - gdalrc = GDALc_inq_dimlen(filedesc, dimIds[i], &dimLen); - if (!CHECKGDALERROR(gdalrc, "Error retrieving dimension information", - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - PRINTMSG("GDALc_inq_dimlen for dim = " << i << " dimLen="< 0) - axis = dimLabels[i]; - else { - std::stringstream axis_tmp; - axis_tmp << varname << "_dim" << std::setfill('0') << std::setw(3) << i+1; - axis = axis_tmp.str(); - } - - // if dimension already exists, use it. - int dimid_existing; - gdalrc = GDALc_inq_dimid(filedesc, axis.c_str(), &dimid_existing); - if (GDAL_NOERR == gdalrc) { - MPI_Offset dim_len; - gdalrc = GDALc_inq_dimlen(filedesc, dimid_existing, &dim_len); - if (!CHECKGDALERROR(gdalrc, "Error finding existing dimension length", ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - if (ioDims[i] != dim_len) { - std::stringstream msg; - msg << "Existing dimension " << axis << " length " << dim_len << " != required " << ioDims[i]; - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, msg, - ESMC_CONTEXT, rc)) { - return; - } - } - ncDims[nioDims - i - 1] = dimid_existing; - } else { - PRINTMSG("Defining dimension " << i); - gdalrc = GDALc_def_dim(filedesc, axis.c_str(), - ioDims[i], &ncDims[nioDims - i - 1]); - if (!CHECKGDALERROR(gdalrc, std::string("Defining dimension: ") + axis, - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - } - } - PRINTMSG("finished defining space dims, timeFrame = " << timeFrame); - - if (timeFrame > -1) { - nioDims++; - for(int i=nioDims;i>0;i--) - ncDims[i] = ncDims[i-1]; - if (hasTimeDim) { - gdalrc = GDALc_inq_dimid (filedesc, "time", &ncDims[0]); - if (!CHECKGDALERROR(gdalrc, "Attempting to obtain 'time' dimension ID", - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - } else { - PRINTMSG("Defining time dimension"); - gdalrc = GDALc_def_dim(filedesc, "time", - GDAL_UNLIMITED, &ncDims[0]); - if (!CHECKGDALERROR(gdalrc, "Attempting to define 'time' dimension", - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - } - } - } - PRINTMSG("varExists = " << varExists); - if (!varExists) { - PRINTMSG("niodims = " << nioDims); - PRINTMSG("basegdaltype = " << basegdaltype); - - gdalrc = GDALc_def_var(filedesc, varname.c_str(), basegdaltype, - nioDims, ncDims, &vardesc); - if (!CHECKGDALERROR(gdalrc, "Attempting to define GDAL vardesc for: " + varname, - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - } - if (timeFrame >= 0) { -#ifdef ESMFIO_DEBUG - int nvdims; - GDALc_inq_varndims(filedesc, vardesc, &nvdims); - PRINTMSG("calling setframe, timeFrame = " << timeFrame); -#endif // ESMFIO_DEBUG - gdalrc = GDALc_setframe(filedesc, vardesc, timeFrame-1); - if (!CHECKGDALERROR(gdalrc, "Attempting to setframe for: " + varname, - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - } -#ifdef ESMFIO_DEBUG - else { - PRINTMSG("NOT calling setframe, timeFrame = " << timeFrame); - } - if (varExists) { - int varid; - int lrc; - lrc = GDALc_inq_varid(filedesc, varname.c_str(), &varid); - PRINTMSG("varid = " << varid); - } -#endif // ESMFIO_DEBUG - - // ESMF Attribute Package -> NetCDF variable and global attributes - if (varAttPack) { - attPackPut (vardesc, varAttPack, tile, &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, - ESMC_CONTEXT, rc)) { - return; - } - } - if (gblAttPack) { - attPackPut (NC_GLOBAL, gblAttPack, tile, &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, - ESMC_CONTEXT, rc)) { - return; - } - } - - - PRINTMSG("calling enddef, status = " << rc); - - gdalrc = GDALc_enddef(filedesc); - if (!CHECKGDALERROR(gdalrc, "Attempting to end definition of variable: " + varname, - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - -#endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) - PRINTMSG("calling write_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); - // Write the array - ESMCI_IOREGION_ENTER("GDALc_write_darray"); - gdalrc = GDALc_write_darray(filedesc, vardesc, iodesc, arrlen, - (void *)baseAddress, NULL); - if (!CHECKGDALERROR(gdalrc, "Attempting to write file", - ESMF_RC_FILE_WRITE, (*rc))) { - return; - } - new_file[tile-1] = false; - ESMCI_IOREGION_EXIT("GDALc_write_darray"); - +//>> // initialize return code; assume routine not implemented +//>> int localrc = ESMF_RC_NOT_IMPL; // local return code +//>> int gdalrc; // GDAL error value +//>> int * ioDims; // Array IO shape +//>> int nioDims; // Array IO rank +//>> int * arrDims; // Array shape +//>> int narrDims; // Array rank +//>> int iodesc; // GDAL IO descriptor +//>> int filedesc; // GDAL file descriptor +//>> int vardesc = 0; // GDAL variable descriptor +//>> int basegdaltype; // GDAL version of Array data type +//>> void *baseAddress; // The address of the Array IO data +//>> int localDE; // DE to use for IO +//>> int ncDims[8]; // To hold NetCDF dimensions +//>> int unlim = -1; // Unlimited dimension ID +//>> int timeFrame = -1; // ID of time dimension (>0 if used) +//>> int timesliceVal = -1; // Used time value (from timeslice) +//>> bool varExists = false; // true if varname is defined in file +//>> std::string varname; // Variable name +//>> if (rc != NULL) { +//>> *rc = ESMF_RC_NOT_IMPL; // final return code +//>> } +//>> +//>> PRINTPOS; +//>> +//>> if ((int *)NULL != timeslice) { +//>> timesliceVal = *timeslice; +//>> } +//>> // File open? +//>> if (isOpen(tile) != ESMF_TRUE) +//>> if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", +//>> ESMC_CONTEXT, rc)) return; +//>> +//>> // Array compatible with this object? +//>> localrc = checkArray(arr_p); +//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) +//>> return; +//>> +//>> filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based +//>> iodesc = getIODesc(gdalSystemDesc, arr_p, tile, &ioDims, &nioDims, +//>> &arrDims, &narrDims, &basegdaltype, &localrc); +//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, +//>> ESMC_CONTEXT, rc)) return; +//>> for (int i=0; i> if (arrDims[i] < 0) { +//>> if (ESMC_LogDefault.MsgFoundError (ESMF_RC_INTNRL_BAD, "array dimension extent < 0", +//>> ESMC_CONTEXT, rc)) return; +//>> } +//>> } +//>> +//>> if (dimLabels.size() > 0 && dimLabels.size() < (unsigned int)nioDims) { +//>> std::stringstream errmsg; +//>> errmsg << dimLabels.size() << " user dimension label(s) supplied, " << nioDims << " expected"; +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_SIZE, errmsg, +//>> ESMC_CONTEXT, rc)) return; +//>> } +//>> +//>> +//>> // Get a pointer to the array data +//>> // Still have the one DE restriction so use localDE = 0 +//>> localDE = 0; +//>> int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDE, &localrc); +//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, +//>> ESMC_CONTEXT, rc)) return; +//>> int arrlen; +//>> if (tileOfThisDe == tile) { +//>> baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); +//>> PRINTMSG("baseAddress = 0x" << (void *)baseAddress); +//>> // arrlen = arr_p->getLocalarrayList()[localDE]->getByteCount(); +//>> arrlen = 1; +//>> const int *counts = arr_p->getLocalarrayList()[localDE]->getCounts(); +//>> for (int i=0; i> arrlen *= counts[i]; +//>> } else { +//>> baseAddress = NULL; +//>> arrlen = 0; +//>> } +//>> PRINTMSG("arrlen = " << arrlen); +//>> +//>>#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) +//>> // Define the variable name and check the file +//>> if (((char *)NULL != name) && (strlen(name) > 0)) { +//>> varname = name; +//>> } else { +//>> varname = arr_p->getName(); +//>> } +//>> PRINTMSG("varname = \"" << varname << "\""); +//>> if (ESMF_TRUE == isNewFile(tile)) { +//>> varExists = false; +//>> } else { +//>> int nVar; // Number of variables in file +//>> int nAtt; // Number of attributes in file +//>> int nfDims; // Number of dimensions in file +//>> PRINTMSG("Entering NetCDF define mode (redef)"); +//>> gdalrc = GDALc_redef(filedesc); +//>> // Not all NetCDF errors are really errors here so we need to check +//>> if ((GDAL_NOERR != gdalrc) && (NC_EINDEFINE != gdalrc)) { +//>> if (!CHECKGDALERROR(gdalrc, +//>> ((NC_EPERM == gdalrc) ? +//>> "File is read only" : +//>> "File is not in NetCDF format"), +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> } +//>> +//>> // This should work if it is a NetCDF file. +//>> PRINTMSG("Calling GDALc_inq"); +//>> gdalrc = GDALc_inq(filedesc, &nfDims, +//>> &nVar, &nAtt, &unlim); +//>> if (!CHECKGDALERROR(gdalrc, "File is not in NetCDF format", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> +//>> // We have a NetCDF file, see if the variable is in there +//>> PRINTMSG("Looking for variable in file"); +//>> gdalrc = GDALc_inq_varid(filedesc, varname.c_str(), &vardesc); +//>> // This should succeed if the variable exists +//>> varExists = (GDAL_NOERR == gdalrc); +//>> } +//>> +//>> // Check consistency of time dimension with timeslice +//>> bool hasTimeDim; +//>> +//>> int dimidTime; +//>> GDAL_Offset timeLen; +//>> PRINTMSG("Checking time dimension"); +//>> //gdalrc = GDALc_inq_dimid(filedesc, "time", &dimidTime); +//>> gdalrc = GDALc_inq_unlimdim(filedesc, &dimidTime); +//>> // NetCDF does not specify which error code goes with with +//>> // condition so we will guess that there is no time dimension +//>> // on any error condition (This may be an error depending on context). +//>> hasTimeDim = (GDAL_NOERR == gdalrc && dimidTime != -1); +//>> PRINTMSG("inq_dimid = " << gdalrc); +//>> PRINTMSG("hasTimeDim = " << hasTimeDim); +//>> PRINTMSG("unlim = " << unlim); +//>> if (hasTimeDim) { +//>> // Retrieve the max time field +//>> gdalrc = GDALc_inq_dimlen(filedesc, dimidTime, &timeLen); +//>> PRINTMSG("inq_dimlen = " << gdalrc); +//>> PRINTMSG("dimidTime = " << dimidTime); +//>> PRINTMSG("timeLen = " << timeLen); +//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving information about time", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> +//>> // Check to make sure that time is the unlimited dimension +//>> if (dimidTime != unlim) +//>> if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, +//>> "Time is not the file's unlimited dimension", +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } +//>> if (timesliceVal >= 0) { +//>> if (varExists & !hasTimeDim) { +//>> // It is an error to not have a time dimension if we are trying to +//>> // write a timeslice and the variable already exists +//>> // (it won't have time) +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, +//>> "Field already exists without time dimension", +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } else { +//>> timeFrame = timesliceVal; +//>> } +//>> } else if (timesliceVal < 0) { +//>> // Special case for no timeslice input passed but time dimension exists +//>> if (varExists && hasTimeDim) { +//>> timeFrame = timeLen + 1; +//>> PRINTMSG("timeslice not passed but set to " << timeFrame); +//>> } +//>> } +//>> +//>> PRINTMSG("ready to check var compat., timeFrame = " << timeFrame); +//>> if (varExists) { +//>> int nDims; +//>> int nArrdims = nioDims + ((timeFrame > 0) ? 1 : 0); +//>> +//>> // Check compatibility between array to write and existing variable. +//>> gdalrc = GDALc_inq_varndims(filedesc, vardesc, &nDims); +//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> +//>> if (nDims != nArrdims) { +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, +//>> "Variable rank in file does not match array", +//>> ESMC_CONTEXT, rc)) { +//>> PRINTMSG("Variable rank mismatch: nioDims = " << nioDims << +//>> ", nArrdims = " << nArrdims << ", nDims = " << nDims); +//>> return; +//>> } +//>> } +//>> +//>> PRINTMSG("Calling gdal_cpp_inq_vardimid_vdesc"); +//>> std::vector dimIds(nDims); +//>> gdalrc = GDALc_inq_vardimid(filedesc, vardesc, &dimIds.front()); +//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> +//>> MPI_Offset dimLen; +//>> int ioDimNum = 0; +//>> for (int i = 0; i < nDims; i++) { +//>> gdalrc = GDALc_inq_dimlen(filedesc, dimIds[i], &dimLen); +//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving dimension information", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> PRINTMSG("GDALc_inq_dimlen for dim = " << i << " dimLen="<> +//>> if (dimIds[i] == unlim) { +//>> if (timeFrame <= 0) { +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, +//>> "File variable requires time dimension", +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } else if ((timeFrame <= dimLen) && !overwriteFields()) { +//>> // This 'error' might be incorrect in that we can't figure +//>> // out the max frame of this variable, only for the whole file. +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, +//>> "Can't overwrite timeslice", +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } +//>> } else if (dimLen != ioDims[nDims - ioDimNum - 1 - int(hasTimeDim)]) { +//>> PRINTMSG("dimLen = "<> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } else { +//>> ioDimNum++; +//>> } +//>> } +//>> } +//>> +//>> if (varExists && !overwriteFields() && (timeFrame <= 0)) { +//>> // Check to see if we can overwrite an existing field or timeslice +//>> std::string errmsg = "Variable " + varname + " pre-exists, however overwrite flag is .false."; +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, errmsg, +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } +//>> +//>> if (!varExists) { +//>> // Ensure we are in define mode +//>> PRINTMSG("Going into NetCDF define mode (redef)"); +//>> gdalrc = GDALc_redef(filedesc); +//>> // Not all NetCDF errors are really errors here so we need to check +//>> if ((GDAL_NOERR != gdalrc) && (NC_EINDEFINE != gdalrc)) { +//>> if (!CHECKGDALERROR(gdalrc, +//>> ((NC_EPERM == gdalrc) ? +//>> "File is read only" : +//>> "File is not in NetCDF format"), +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> } +//>> } +//>> +//>> if (!varExists) { +//>> // Create the variable +//>> for (int i = 0; i < nioDims; i++) { +//>> std::string axis; +//>> if (dimLabels.size() > 0) +//>> axis = dimLabels[i]; +//>> else { +//>> std::stringstream axis_tmp; +//>> axis_tmp << varname << "_dim" << std::setfill('0') << std::setw(3) << i+1; +//>> axis = axis_tmp.str(); +//>> } +//>> +//>> // if dimension already exists, use it. +//>> int dimid_existing; +//>> gdalrc = GDALc_inq_dimid(filedesc, axis.c_str(), &dimid_existing); +//>> if (GDAL_NOERR == gdalrc) { +//>> MPI_Offset dim_len; +//>> gdalrc = GDALc_inq_dimlen(filedesc, dimid_existing, &dim_len); +//>> if (!CHECKGDALERROR(gdalrc, "Error finding existing dimension length", ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> if (ioDims[i] != dim_len) { +//>> std::stringstream msg; +//>> msg << "Existing dimension " << axis << " length " << dim_len << " != required " << ioDims[i]; +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, msg, +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } +//>> ncDims[nioDims - i - 1] = dimid_existing; +//>> } else { +//>> PRINTMSG("Defining dimension " << i); +//>> gdalrc = GDALc_def_dim(filedesc, axis.c_str(), +//>> ioDims[i], &ncDims[nioDims - i - 1]); +//>> if (!CHECKGDALERROR(gdalrc, std::string("Defining dimension: ") + axis, +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> } +//>> } +//>> PRINTMSG("finished defining space dims, timeFrame = " << timeFrame); +//>> +//>> if (timeFrame > -1) { +//>> nioDims++; +//>> for(int i=nioDims;i>0;i--) +//>> ncDims[i] = ncDims[i-1]; +//>> if (hasTimeDim) { +//>> gdalrc = GDALc_inq_dimid (filedesc, "time", &ncDims[0]); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to obtain 'time' dimension ID", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> } else { +//>> PRINTMSG("Defining time dimension"); +//>> gdalrc = GDALc_def_dim(filedesc, "time", +//>> GDAL_UNLIMITED, &ncDims[0]); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to define 'time' dimension", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> } +//>> } +//>> } +//>> PRINTMSG("varExists = " << varExists); +//>> if (!varExists) { +//>> PRINTMSG("niodims = " << nioDims); +//>> PRINTMSG("basegdaltype = " << basegdaltype); +//>> +//>> gdalrc = GDALc_def_var(filedesc, varname.c_str(), basegdaltype, +//>> nioDims, ncDims, &vardesc); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to define GDAL vardesc for: " + varname, +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> } +//>> if (timeFrame >= 0) { +//>>#ifdef ESMFIO_DEBUG +//>> int nvdims; +//>> GDALc_inq_varndims(filedesc, vardesc, &nvdims); +//>> PRINTMSG("calling setframe, timeFrame = " << timeFrame); +//>>#endif // ESMFIO_DEBUG +//>> gdalrc = GDALc_setframe(filedesc, vardesc, timeFrame-1); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to setframe for: " + varname, +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> } +//>>#ifdef ESMFIO_DEBUG +//>> else { +//>> PRINTMSG("NOT calling setframe, timeFrame = " << timeFrame); +//>> } +//>> if (varExists) { +//>> int varid; +//>> int lrc; +//>> lrc = GDALc_inq_varid(filedesc, varname.c_str(), &varid); +//>> PRINTMSG("varid = " << varid); +//>> } +//>>#endif // ESMFIO_DEBUG +//>> +//>> // ESMF Attribute Package -> NetCDF variable and global attributes +//>> if (varAttPack) { +//>> attPackPut (vardesc, varAttPack, tile, &localrc); +//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } +//>> if (gblAttPack) { +//>> attPackPut (NC_GLOBAL, gblAttPack, tile, &localrc); +//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } +//>> +//>> +//>> PRINTMSG("calling enddef, status = " << rc); +//>> +//>> gdalrc = GDALc_enddef(filedesc); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to end definition of variable: " + varname, +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> +//>>#endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) +//>> PRINTMSG("calling write_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); +//>> // Write the array +//>> ESMCI_IOREGION_ENTER("GDALc_write_darray"); +//>> gdalrc = GDALc_write_darray(filedesc, vardesc, iodesc, arrlen, +//>> (void *)baseAddress, NULL); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to write file", +//>> ESMF_RC_FILE_WRITE, (*rc))) { +//>> return; +//>> } +//>> new_file[tile-1] = false; +//>> ESMCI_IOREGION_EXIT("GDALc_write_darray"); // Cleanup & return PRINTMSG("cleanup and return"); @@ -1178,7 +1174,7 @@ void GDAL_Handler::arrayWriteOneTileFile( // !IROUTINE: ESMCI::GDAL_Handler::openOneTileFile - open a stream with stored filename, for the given tile // // !INTERFACE: -void GDAL_Handler::openOneTileFile( +void GDAL_Handler::GDAL_openOneTileFile( // // !RETURN VALUE: // @@ -1207,30 +1203,6 @@ void GDAL_Handler::openOneTileFile( int numtasks = vm->getPetCount(); int petspernode = vm->getSsiMaxPetCount(); - - struct iofmt_map_t { - int esmf_iofmt; - int gdal_fmt; - } iofmt_map[] = { -#if defined (ESMF_PNETCDF) - { ESMF_IOFMT_NETCDF, GDAL_IOTYPE_PNETCDF } - ,{ ESMF_IOFMT_NETCDF_64BIT_OFFSET, GDAL_IOTYPE_PNETCDF } - ,{ ESMF_IOFMT_NETCDF_64BIT_DATA, GDAL_IOTYPE_PNETCDF } - ,{ ESMF_IOFMT_NETCDF4, GDAL_IOTYPE_NETCDF } - ,{ ESMF_IOFMT_NETCDF4C, GDAL_IOTYPE_NETCDF4C } - ,{ ESMF_IOFMT_NETCDF4P, GDAL_IOTYPE_NETCDF4P } -#elif defined (ESMF_NETCDF) - { ESMF_IOFMT_NETCDF, GDAL_IOTYPE_NETCDF } - ,{ ESMF_IOFMT_NETCDF_64BIT_OFFSET, GDAL_IOTYPE_NETCDF } - ,{ ESMF_IOFMT_NETCDF_64BIT_DATA, GDAL_IOTYPE_NETCDF } - ,{ ESMF_IOFMT_NETCDF4, GDAL_IOTYPE_NETCDF } - ,{ ESMF_IOFMT_NETCDF4C, GDAL_IOTYPE_NETCDF4C } - ,{ ESMF_IOFMT_NETCDF4P, GDAL_IOTYPE_NETCDF4P } -#endif - }; - - int iofmt_map_size = sizeof (iofmt_map)/sizeof (iofmt_map_t); - if (rc != NULL) { *rc = ESMF_RC_NOT_IMPL; // final return code } @@ -1249,118 +1221,118 @@ void GDAL_Handler::openOneTileFile( gdalSystemDesc = GDAL_Handler::activeGdalInstances.back(); } - // Translate the I/O format from ESMF to GDAL -#if !defined(ESMF_NETCDF) && !defined (ESMF_PNETCDF) - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_LIB_NOT_PRESENT, - "Library for requested I/O format is not present", ESMC_CONTEXT, rc)) - return; -#endif - - int i_loop; - for (i_loop=0; i_loop> // Translate the I/O format from ESMF to GDAL +//>>#if !defined(ESMF_NETCDF) && !defined (ESMF_PNETCDF) +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_LIB_NOT_PRESENT, +//>> "Library for requested I/O format is not present", ESMC_CONTEXT, rc)) +//>> return; +//>>#endif +//>> +//>> int i_loop; +//>> for (i_loop=0; i_loop> if (getFormat() == iofmt_map[i_loop].esmf_iofmt) { +//>> iotype = iofmt_map[i_loop].gdal_fmt; +//>> break; +//>> } +//>> } +//>> if (i_loop == iofmt_map_size) { +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, +//>> "unsupported/unknown I/O format", ESMC_CONTEXT, rc)) +//>> return; +//>> } +//>> +//>> // Check to see if we are able to open file properly +//>> bool okToCreate = false; +//>> int clobberMode = GDAL_NOCLOBBER; +//>> if (readonly) { +//>> mode = GDAL_NOWRITE; +//>> } else { +//>> mode = GDAL_WRITE; +//>> } +//>> // Figure out if we need to call createfile or openfile +//>> new_file[tile-1] = false; +//>> const std::string thisFilename = getFilename(tile, &localrc); +//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) +//>> return; +//>> bool file_exists = IO_Handler::fileExists(thisFilename, !readonly); +//>> switch(getFileStatusFlag()) { +//>> case ESMC_FILESTATUS_UNKNOWN: +//>> if (file_exists) { +//>> // Treat like OLD +//>> okToCreate = false; +//>> } else { +//>> // Treat like NEW +//>> okToCreate = true; +//>> clobberMode = GDAL_NOCLOBBER; +//>> } +//>> break; +//>> case ESMC_FILESTATUS_OLD: +//>> okToCreate = false; +//>> break; +//>> case ESMC_FILESTATUS_NEW: +//>> okToCreate = true; +//>> clobberMode = GDAL_NOCLOBBER; +//>> break; +//>> case ESMC_FILESTATUS_REPLACE: +//>> okToCreate = true; +//>> clobberMode = GDAL_CLOBBER; +//>> break; +//>> default: +//>> localrc = ESMF_RC_ARG_BAD; +//>> if (ESMC_LogDefault.MsgFoundError(localrc, "unknown file status argument", ESMC_CONTEXT, rc)) +//>> return; +//>> } +//>> +//>> if (okToCreate) { +//>>#ifdef ESMFIO_DEBUG +//>> std::string errmsg = "Calling GDALc_createfile"; +//>> ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_INFO, ESMC_CONTEXT); +//>>#endif // ESMFIO_DEBUG +//>> // Looks like we are ready to try and create the file +//>> mode |= clobberMode; +//>> switch (getFormat()){ +//>> case ESMF_IOFMT_NETCDF_64BIT_OFFSET: +//>> { +//>> mode |= GDAL_64BIT_OFFSET; +//>> break; +//>> } +//>> case ESMF_IOFMT_NETCDF_64BIT_DATA: +//>> { +//>> mode |= GDAL_64BIT_DATA; +//>> break; +//>> } +//>> } +//>> ESMCI_IOREGION_ENTER("GDALc_createfile"); +//>> +//>> gdalrc = GDALc_createfile(gdalSystemDesc, &(gdalFileDesc[tile-1]), +//>> &iotype, thisFilename.c_str(), mode); +//>> ESMCI_IOREGION_EXIT("GDALc_createfile"); +//>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to create file: ") + thisFilename, +//>> ESMF_RC_FILE_OPEN, (*rc))) { +//>> return; +//>> } else { +//>> new_file[tile-1] = true; +//>> PRINTMSG("call to GDALc_createfile: success for " << thisFilename << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "<> } +//>> gdalrc = GDALc_set_fill(gdalFileDesc[tile-1], GDAL_NOFILL, NULL); +//>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to set fill on file: ") + thisFilename, +//>> ESMF_RC_FILE_OPEN, (*rc))) { +//>> return; +//>> } +//>> } else { +//>> PRINTMSG(" calling GDALc_openfile with mode = " << mode << +//>> ", file = \"" << thisFilename << "\""); +//>> // Looks like we are ready to go +//>> ESMCI_IOREGION_ENTER("GDALc_openfile"); +//>> gdalrc = GDALc_openfile(gdalSystemDesc, &(gdalFileDesc[tile-1]), +//>> &iotype, thisFilename.c_str(), mode); +//>> ESMCI_IOREGION_EXIT("GDALc_openfile"); +//>> PRINTMSG(", called GDALc_openfile on " << thisFilename); +//>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to open existing file: ") + thisFilename, +//>> ESMF_RC_FILE_OPEN, (*rc))) { +//>> return; +//>> } +//>> } // return successfully if (rc != NULL) { @@ -1398,85 +1370,85 @@ void GDAL_Handler::attPackPut ( int gdalrc; int filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based - const json &j = attPack->getStorageRef(); - for (json::const_iterator it=j.cbegin(); it!=j.cend(); it++) { - if (it.key().rfind("ESMF:", 0) == 0) { - continue; - } - json jcurr; - if (it.value().is_array()) { - jcurr = it.value(); - } else { - json arr = json::array(); - arr.push_back(it.value()); - jcurr = arr; - } - if (!(jcurr.is_array())) { - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_WRONGTYPE, "Only JSON arrays supported. Key is: " + it.key(), ESMC_CONTEXT, rc)) - return; - } - int size = (int)(jcurr.size()); - - // Determine if the target key is 32-bit - bool is_32bit = false; - try { - json::json_pointer jp = attPack->formatKey(it.key()); - is_32bit = ESMCI::retrieve_32bit_flag(attPack->getTypeStorage(), jp, true); - } - ESMC_CATCH_ERRPASSTHRU - - ESMC_TypeKind_Flag att_type = ESMCI::json_type_to_esmf_typekind(jcurr, true, is_32bit); - switch (att_type) { - case ESMC_TYPEKIND_CHARACTER: { - if (size > 1) { - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_WRONGTYPE, "JSON arrays with size > 1 not supported for strings. Key is: " + it.key(), ESMC_CONTEXT, rc)) - return; - } - const std::string value = jcurr[0]; - gdalrc = GDALc_put_att_text (filedesc, vardesc, - it.key().c_str(), strlen(value.c_str()), value.c_str()); - if (!CHECKGDALERROR(gdalrc, "Attempting to set string Attribute: " + it.key(), - ESMF_RC_FILE_WRITE, (*rc))) return; - break; - } - case ESMC_TYPEKIND_I8: { - const std::vector value = jcurr.get>(); - gdalrc = GDALc_put_att_long (filedesc, vardesc, - it.key().c_str(), att_type, size, value.data()); - if (!CHECKGDALERROR(gdalrc, "Attempting to set I8 Attribute: " + it.key(), - ESMF_RC_FILE_WRITE, (*rc))) return; - break; - } - case ESMC_TYPEKIND_R8: { - const std::vector value = jcurr.get>(); - gdalrc = GDALc_put_att_double (filedesc, vardesc, - it.key().c_str(), att_type, size, value.data()); - if (!CHECKGDALERROR(gdalrc, "Attempting to set R8 Attribute: " + it.key(), - ESMF_RC_FILE_WRITE, (*rc))) return; - break; - } - case ESMC_TYPEKIND_I4: { - const std::vector value = jcurr.get>(); - gdalrc = GDALc_put_att_int (filedesc, vardesc, - it.key().c_str(), att_type, size, value.data()); - if (!CHECKGDALERROR(gdalrc, "Attempting to set I4 Attribute: " + it.key(), - ESMF_RC_FILE_WRITE, (*rc))) return; - break; - } - case ESMC_TYPEKIND_R4: { - const std::vector value = jcurr.get>(); - gdalrc = GDALc_put_att_float (filedesc, vardesc, - it.key().c_str(), att_type, size, value.data()); - if (!CHECKGDALERROR(gdalrc, "Attempting to set R4 Attribute: " + it.key(), - ESMF_RC_FILE_WRITE, (*rc))) return; - break; - } - default: - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_NOTSET, - "Attribute " + it.key() + " has unsupported value type", - ESMC_CONTEXT, rc)) return; - } - } +//>> const json &j = attPack->getStorageRef(); +//>> for (json::const_iterator it=j.cbegin(); it!=j.cend(); it++) { +//>> if (it.key().rfind("ESMF:", 0) == 0) { +//>> continue; +//>> } +//>> json jcurr; +//>> if (it.value().is_array()) { +//>> jcurr = it.value(); +//>> } else { +//>> json arr = json::array(); +//>> arr.push_back(it.value()); +//>> jcurr = arr; +//>> } +//>> if (!(jcurr.is_array())) { +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_WRONGTYPE, "Only JSON arrays supported. Key is: " + it.key(), ESMC_CONTEXT, rc)) +//>> return; +//>> } +//>> int size = (int)(jcurr.size()); +//>> +//>> // Determine if the target key is 32-bit +//>> bool is_32bit = false; +//>> try { +//>> json::json_pointer jp = attPack->formatKey(it.key()); +//>> is_32bit = ESMCI::retrieve_32bit_flag(attPack->getTypeStorage(), jp, true); +//>> } +//>> ESMC_CATCH_ERRPASSTHRU +//>> +//>> ESMC_TypeKind_Flag att_type = ESMCI::json_type_to_esmf_typekind(jcurr, true, is_32bit); +//>> switch (att_type) { +//>> case ESMC_TYPEKIND_CHARACTER: { +//>> if (size > 1) { +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_WRONGTYPE, "JSON arrays with size > 1 not supported for strings. Key is: " + it.key(), ESMC_CONTEXT, rc)) +//>> return; +//>> } +//>> const std::string value = jcurr[0]; +//>> gdalrc = GDALc_put_att_text (filedesc, vardesc, +//>> it.key().c_str(), strlen(value.c_str()), value.c_str()); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to set string Attribute: " + it.key(), +//>> ESMF_RC_FILE_WRITE, (*rc))) return; +//>> break; +//>> } +//>> case ESMC_TYPEKIND_I8: { +//>> const std::vector value = jcurr.get>(); +//>> gdalrc = GDALc_put_att_long (filedesc, vardesc, +//>> it.key().c_str(), att_type, size, value.data()); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to set I8 Attribute: " + it.key(), +//>> ESMF_RC_FILE_WRITE, (*rc))) return; +//>> break; +//>> } +//>> case ESMC_TYPEKIND_R8: { +//>> const std::vector value = jcurr.get>(); +//>> gdalrc = GDALc_put_att_double (filedesc, vardesc, +//>> it.key().c_str(), att_type, size, value.data()); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to set R8 Attribute: " + it.key(), +//>> ESMF_RC_FILE_WRITE, (*rc))) return; +//>> break; +//>> } +//>> case ESMC_TYPEKIND_I4: { +//>> const std::vector value = jcurr.get>(); +//>> gdalrc = GDALc_put_att_int (filedesc, vardesc, +//>> it.key().c_str(), att_type, size, value.data()); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to set I4 Attribute: " + it.key(), +//>> ESMF_RC_FILE_WRITE, (*rc))) return; +//>> break; +//>> } +//>> case ESMC_TYPEKIND_R4: { +//>> const std::vector value = jcurr.get>(); +//>> gdalrc = GDALc_put_att_float (filedesc, vardesc, +//>> it.key().c_str(), att_type, size, value.data()); +//>> if (!CHECKGDALERROR(gdalrc, "Attempting to set R4 Attribute: " + it.key(), +//>> ESMF_RC_FILE_WRITE, (*rc))) return; +//>> break; +//>> } +//>> default: +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ATTR_NOTSET, +//>> "Attribute " + it.key() + " has unsupported value type", +//>> ESMC_CONTEXT, rc)) return; +//>> } +//>> } if (rc) {*rc = ESMF_SUCCESS;} @@ -1508,22 +1480,22 @@ ESMC_Logical GDAL_Handler::isOpen( // //EOPI //----------------------------------------------------------------------------- - PRINTPOS; - int filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based - if (filedesc == 0) { - PRINTMSG("gdalFileDesc is NULL"); - return ESMF_FALSE; - } else if (GDALc_File_is_Open(filedesc) != 0) { - PRINTMSG("File is open"); - return ESMF_TRUE; - } else { - // This really should not happen, warn and clean up just in case - std::string errmsg; - const std::string thisFilename = getFilename(tile); - errmsg = std::string ("File, ") + thisFilename + ", closed by GDAL"; - ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, ESMC_CONTEXT); - return ESMF_FALSE; - } +//>> PRINTPOS; +//>> int filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based +//>> if (filedesc == 0) { +//>> PRINTMSG("gdalFileDesc is NULL"); +//>> return ESMF_FALSE; +//>> } else if (GDALc_File_is_Open(filedesc) != 0) { +//>> PRINTMSG("File is open"); +//>> return ESMF_TRUE; +//>> } else { +//>> // This really should not happen, warn and clean up just in case +//>> std::string errmsg; +//>> const std::string thisFilename = getFilename(tile); +//>> errmsg = std::string ("File, ") + thisFilename + ", closed by GDAL"; +//>> ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, ESMC_CONTEXT); +//>> return ESMF_FALSE; +//>> } } // GDAL_Handler::isOpen() //----------------------------------------------------------------------------- @@ -1559,18 +1531,18 @@ void GDAL_Handler::flushOneTileFile( *rc = ESMF_RC_NOT_IMPL; // final return code } - PRINTPOS; - // Not open? No problem, just skip - if (isOpen(tile) == ESMF_TRUE) { - PRINTMSG("calling sync"); - ESMCI_IOREGION_ENTER("GDALc_sync"); - GDALc_sync(gdalFileDesc[tile-1]); - ESMCI_IOREGION_EXIT("GDALc_sync"); - } - // return successfully - if (rc != NULL) { - *rc = ESMF_SUCCESS; - } +//>> PRINTPOS; +//>> // Not open? No problem, just skip +//>> if (isOpen(tile) == ESMF_TRUE) { +//>> PRINTMSG("calling sync"); +//>> ESMCI_IOREGION_ENTER("GDALc_sync"); +//>> GDALc_sync(gdalFileDesc[tile-1]); +//>> ESMCI_IOREGION_EXIT("GDALc_sync"); +//>> } +//>> // return successfully +//>> if (rc != NULL) { +//>> *rc = ESMF_SUCCESS; +//>> } } // GDAL_Handler::flushOneTileFile() //----------------------------------------------------------------------------- @@ -1607,16 +1579,16 @@ void GDAL_Handler::closeOneTileFile( *rc = ESMF_RC_NOT_IMPL; // final return code } - PRINTPOS; - // Not open? No problem, just skip - if (isOpen(tile) == ESMF_TRUE) { - ESMCI_IOREGION_ENTER("GDALc_closefile"); - int gdalrc = GDALc_closefile(gdalFileDesc[tile-1]); - ESMCI_IOREGION_EXIT("GDALc_closefile"); - gdalFileDesc[tile-1] = 0; - new_file[tile-1] = false; - if (rc != NULL) *rc = gdalrc; - } +//>> PRINTPOS; +//>> // Not open? No problem, just skip +//>> if (isOpen(tile) == ESMF_TRUE) { +//>> ESMCI_IOREGION_ENTER("GDALc_closefile"); +//>> int gdalrc = GDALc_closefile(gdalFileDesc[tile-1]); +//>> ESMCI_IOREGION_EXIT("GDALc_closefile"); +//>> gdalFileDesc[tile-1] = 0; +//>> new_file[tile-1] = false; +//>> if (rc != NULL) *rc = gdalrc; +//>> } // return successfully if (rc != NULL) { @@ -1659,51 +1631,51 @@ void GDAL_Handler::closeOneTileFile( //----------------------------------------------------------------------------- int new_io_desc = (int)NULL; - // initialize return code; assume routine not implemented +//>> // initialize return code; assume routine not implemented int localrc = ESMF_RC_NOT_IMPL; // local return code - if (rc != NULL) { - *rc = ESMF_RC_NOT_IMPL; // final return code - } - - PRINTPOS; +//>> if (rc != NULL) { +//>> *rc = ESMF_RC_NOT_IMPL; // final return code +//>> } +//>> +//>> PRINTPOS; new_io_desc = GDAL_IODescHandler::getIODesc(iosys, arr_p, tile, &localrc); - if ((int)NULL == new_io_desc) { - PRINTMSG("calling constructGdalDecomp"); - localrc = GDAL_IODescHandler::constructGdalDecomp(iosys, - arr_p, tile, &new_io_desc); - PRINTMSG("constructGdalDecomp call complete" << ", localrc = " << localrc); - } - if ((ioDims != (int **)NULL) || (nioDims != (int *)NULL) || - (arrDims != (int **)NULL) || (narrDims != (int *)NULL)) { - int niodimArg; - int *iodimsArg; - int narrdimArg; - int *arrdimsArg; - - localrc = GDAL_IODescHandler::getDims(new_io_desc, &niodimArg, &iodimsArg, - &narrdimArg, &arrdimsArg); - if (!ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, - ESMC_CONTEXT, rc)) { - if (ioDims != (int **)NULL) { - *ioDims = iodimsArg; - } - if (nioDims != (int *)NULL) { - *nioDims = niodimArg; - } - if (arrDims != (int **)NULL) { - *arrDims = arrdimsArg; - } - if (narrDims != (int *)NULL) { - *narrDims = narrdimArg; - } - } - } - PRINTMSG("getDims complete, calling getIOType"); - if (basegdaltype != (int *)NULL) { - *basegdaltype = GDAL_IODescHandler::getIOType(new_io_desc, &localrc); - ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - rc); - } +//>> if ((int)NULL == new_io_desc) { +//>> PRINTMSG("calling constructGdalDecomp"); +//>> localrc = GDAL_IODescHandler::constructGdalDecomp(iosys, +//>> arr_p, tile, &new_io_desc); +//>> PRINTMSG("constructGdalDecomp call complete" << ", localrc = " << localrc); +//>> } +//>> if ((ioDims != (int **)NULL) || (nioDims != (int *)NULL) || +//>> (arrDims != (int **)NULL) || (narrDims != (int *)NULL)) { +//>> int niodimArg; +//>> int *iodimsArg; +//>> int narrdimArg; +//>> int *arrdimsArg; +//>> +//>> localrc = GDAL_IODescHandler::getDims(new_io_desc, &niodimArg, &iodimsArg, +//>> &narrdimArg, &arrdimsArg); +//>> if (!ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, +//>> ESMC_CONTEXT, rc)) { +//>> if (ioDims != (int **)NULL) { +//>> *ioDims = iodimsArg; +//>> } +//>> if (nioDims != (int *)NULL) { +//>> *nioDims = niodimArg; +//>> } +//>> if (arrDims != (int **)NULL) { +//>> *arrDims = arrdimsArg; +//>> } +//>> if (narrDims != (int *)NULL) { +//>> *narrDims = narrdimArg; +//>> } +//>> } +//>> } +//>> PRINTMSG("getDims complete, calling getIOType"); +//>> if (basegdaltype != (int *)NULL) { +//>> *basegdaltype = GDAL_IODescHandler::getIOType(new_io_desc, &localrc); +//>> ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, +//>> rc); +//>> } if (rc != NULL) { *rc = localrc; } @@ -1742,70 +1714,70 @@ bool GDAL_Handler::CheckGDALError( // //EOPI //----------------------------------------------------------------------------- - int localrc = ESMF_SUCCESS;; - if (rc != NULL) { - *rc = ESMF_RC_NOT_IMPL; // final return code - } - - std::stringstream errmsg; - if (gdalRetCode != GDAL_NOERR) { -#if defined(ESMF_PNETCDF) - // Log the error, assuming the error code was passed through GDAL from PNetCDF - if (!fmtStr.empty()) { - errmsg << " " << fmtStr << ", (GDAL/PNetCDF error = " << ncmpi_strerror (gdalRetCode) << ")"; - } else { - errmsg << " (GDAL/PNetCDF error = " << ncmpi_strerror (gdalRetCode) << ")"; - } -#elif defined(ESMF_NETCDF) - // Log the error, assuming the error code was passed through GDAL from NetCDF - if (!fmtStr.empty()) { - errmsg << " " << fmtStr << ", (GDAL/NetCDF error = " << nc_strerror (gdalRetCode) << ")"; - } else { - errmsg << " (GDAL/NetCDF error = " << nc_strerror (gdalRetCode) << ")"; - } -#else - if (!fmtStr.empty()) { - errmsg << " " << fmtStr << ", (GDAL error = " << gdalRetCode << ")"; - } else { - errmsg << " (GDAL error = " << gdalRetCode << ")"; - } -#endif - // Attempt to find a corresponding ESMC error code - switch(gdalRetCode) { -#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) - case NC_EEXIST: - localrc = ESMF_RC_FILE_CREATE; - break; - case NC_ENOMEM: - localrc = ESMF_RC_MEM_ALLOCATE; - break; - case NC_EPERM: - localrc = ESMF_RC_FILE_OPEN; - break; - default: - localrc = ESMF_RC_NETCDF_ERROR; - break; -#else // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) - default: - localrc = ESMF_RC_FILE_UNEXPECTED; - break; -#endif - } - } else - localrc = ESMF_SUCCESS; - - if ((localrc != ESMF_SUCCESS) && warn) { - ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, - line, file, method); - // run through MsgFoundError in case Log tracing is enabled - ESMC_LogDefault.MsgFoundError(ESMF_SUCCESS, errmsg, - line, file, method, rc); - } else { - ESMC_LogDefault.MsgFoundError(localrc, errmsg, - line, file, method, rc); - } - - return (gdalRetCode == GDAL_NOERR); +//>> int localrc = ESMF_SUCCESS;; +//>> if (rc != NULL) { +//>> *rc = ESMF_RC_NOT_IMPL; // final return code +//>> } +//>> +//>> std::stringstream errmsg; +//>> if (gdalRetCode != GDAL_NOERR) { +//>>#if defined(ESMF_PNETCDF) +//>> // Log the error, assuming the error code was passed through GDAL from PNetCDF +//>> if (!fmtStr.empty()) { +//>> errmsg << " " << fmtStr << ", (GDAL/PNetCDF error = " << ncmpi_strerror (gdalRetCode) << ")"; +//>> } else { +//>> errmsg << " (GDAL/PNetCDF error = " << ncmpi_strerror (gdalRetCode) << ")"; +//>> } +//>>#elif defined(ESMF_NETCDF) +//>> // Log the error, assuming the error code was passed through GDAL from NetCDF +//>> if (!fmtStr.empty()) { +//>> errmsg << " " << fmtStr << ", (GDAL/NetCDF error = " << nc_strerror (gdalRetCode) << ")"; +//>> } else { +//>> errmsg << " (GDAL/NetCDF error = " << nc_strerror (gdalRetCode) << ")"; +//>> } +//>>#else +//>> if (!fmtStr.empty()) { +//>> errmsg << " " << fmtStr << ", (GDAL error = " << gdalRetCode << ")"; +//>> } else { +//>> errmsg << " (GDAL error = " << gdalRetCode << ")"; +//>> } +//>>#endif +//>> // Attempt to find a corresponding ESMC error code +//>> switch(gdalRetCode) { +//>>#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) +//>> case NC_EEXIST: +//>> localrc = ESMF_RC_FILE_CREATE; +//>> break; +//>> case NC_ENOMEM: +//>> localrc = ESMF_RC_MEM_ALLOCATE; +//>> break; +//>> case NC_EPERM: +//>> localrc = ESMF_RC_FILE_OPEN; +//>> break; +//>> default: +//>> localrc = ESMF_RC_NETCDF_ERROR; +//>> break; +//>>#else // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) +//>> default: +//>> localrc = ESMF_RC_FILE_UNEXPECTED; +//>> break; +//>>#endif +//>> } +//>> } else +//>> localrc = ESMF_SUCCESS; +//>> +//>> if ((localrc != ESMF_SUCCESS) && warn) { +//>> ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, +//>> line, file, method); +//>> // run through MsgFoundError in case Log tracing is enabled +//>> ESMC_LogDefault.MsgFoundError(ESMF_SUCCESS, errmsg, +//>> line, file, method, rc); +//>> } else { +//>> ESMC_LogDefault.MsgFoundError(localrc, errmsg, +//>> line, file, method, rc); +//>> } +//>> +//>> return (gdalRetCode == GDAL_NOERR); } // GDAL_Handler::CheckGDALError() //----------------------------------------------------------------------------- @@ -1832,19 +1804,19 @@ GDAL_IODescHandler::~GDAL_IODescHandler ( //EOPI //----------------------------------------------------------------------------- int localrc; - PRINTMSG("calling GDALc_freedecomp"); - ESMCI_IOREGION_ENTER("GDALc_freedecomp"); - GDALc_freedecomp(ios, io_descriptor); - ESMCI_IOREGION_EXIT("GDALc_freedecomp"); - if (dims != (int *)NULL) { - delete[] dims; - dims = (int *)NULL; - } - if (arrayShape != (int *)NULL) { - delete[] arrayShape; - arrayShape = (int *)NULL; - } - array_p = (Array *)NULL; +//>> PRINTMSG("calling GDALc_freedecomp"); +//>> ESMCI_IOREGION_ENTER("GDALc_freedecomp"); +//>> GDALc_freedecomp(ios, io_descriptor); +//>> ESMCI_IOREGION_EXIT("GDALc_freedecomp"); +//>> if (dims != (int *)NULL) { +//>> delete[] dims; +//>> dims = (int *)NULL; +//>> } +//>> if (arrayShape != (int *)NULL) { +//>> delete[] arrayShape; +//>> arrayShape = (int *)NULL; +//>> } +//>> array_p = (Array *)NULL; } // GDAL_IODescHandler::~GDAL_IODescHandler() //----------------------------------------------------------------------------- @@ -1921,209 +1893,209 @@ int GDAL_IODescHandler::constructGdalDecomp( DistGrid *distGrid; // The Array's associated DistGrid GDAL_IODescHandler *handle; // New handler object for this IO desc. - PRINTPOS; - // check the inputs - if ((Array *)NULL == arr_p) { - ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, "- arr_p cannot be NULL", - ESMC_CONTEXT, &localrc); - return ESMF_RC_ARG_BAD; - } - if (tile < 1) { - ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "- tile must be >= 1", - ESMC_CONTEXT, &localrc); - return localrc; - } - if ((int *)NULL == newDecomp_p) { - ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, - "- newDecomp_p cannot be NULL", ESMC_CONTEXT, &localrc); - return ESMF_RC_ARG_BAD; - } - - handle = new GDAL_IODescHandler(iosys, arr_p); - gdalDofList = (MPI_Offset *)NULL; - - localDeCount = arr_p->getDELayout()->getLocalDeCount(); - PRINTMSG("localDeCount = " << localDeCount); - //TODO: Remove this restriction (possibly with multiple IO descriptors) - if (localDeCount > 1) { - ESMC_LogDefault.Write("I/O does not support multiple DEs per PET", - ESMC_LOGMSG_WARN, ESMC_CONTEXT); - return ESMF_RC_NOT_IMPL; - } - - // TODO: To support multiple DEs per PE, we would need to extend this to be an array - bool thisDeIsThisTile = false; - - // We need the total number of elements - gdalDofCount = 0; - int const *localDeToDeMap = arr_p->getDistGrid()->getDELayout()->getLocalDeToDeMap(); - // NB: This loop is redundant for now, I wish I could lift the restriction. - for (localDe = 0; localDe < localDeCount; ++localDe) { - // consider the fact that replicated dimensions may lead to local elements in the - // Array, that are not accounted for by actual exclusive elements in the DistGrid - int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDe, &rc); - if (ESMC_LogDefault.MsgFoundError(rc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) - return localrc; - if (tileOfThisDe == tile) { - // TODO: As noted above, to support multiple DEs per PE, we would need to extend this to be an array - thisDeIsThisTile = true; - } - if (thisDeIsThisTile && arr_p->getDistGrid()->getElementCountPDe()[localDeToDeMap[localDe]]>0) - gdalDofCount += arr_p->getTotalElementCountPLocalDe()[localDe]; - } - - PRINTMSG("gdalDofCount = " << gdalDofCount); - try { - // Allocate space for the DOF list - gdalDofList = new MPI_Offset[gdalDofCount]; - - } catch(...) { - if ((MPI_Offset *)NULL != gdalDofList) { - // Free the DofList! - delete[] gdalDofList; - gdalDofList = (MPI_Offset *)NULL; - } - ESMC_LogDefault.AllocError(ESMC_CONTEXT, &localrc); - return localrc; - } - // Fill in the GDAL DOF list (local to global map) - // TODO: This is where we would need to make some magic to include multiple DEs. - // TODO: (Particular care may be needed in the multi-tile case, where some DEs on the - // TODO: current PE may be part of the current tile, while others are not. - // TODO: For now, with one DE, we can assume that, if gdalDofCount>0, then this DE - // TODO: corresponds to the current tile.) - localDe = 0; - if (gdalDofCount>0){ - // construct the mapping of the local elements - localrc = arr_p->constructFileMap((int64_t *) gdalDofList, gdalDofCount, localDe); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - &localrc)) { - delete[] gdalDofList; - gdalDofList = (MPI_Offset *)NULL; - return localrc; - } - } - -#if 0 - std::cout << " gdalDofList = ["; - for (int i = 0; i < gdalDofCount; i++) { - std::cout << " " << gdalDofList[i] - << ((i == (gdalDofCount - 1)) ? ' ' : ','); - } - std::cout << "]" << std::endl; -#endif // 0 - // Get TKR info - switch(arr_p->getTypekind()) { - case ESMC_TYPEKIND_I4: - handle->basegdaltype = GDAL_INT; - break; - case ESMC_TYPEKIND_R4: - handle->basegdaltype = GDAL_REAL; - break; - case ESMC_TYPEKIND_R8: - handle->basegdaltype = GDAL_DOUBLE; - break; - case ESMC_TYPEKIND_I1: - case ESMC_TYPEKIND_I2: - case ESMC_TYPEKIND_I8: - case ESMC_TYPEKIND_CHARACTER: - case ESMF_C8: - case ESMF_C16: - case ESMC_TYPEKIND_LOGICAL: - default: - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "Unsupported typekind", ESMC_CONTEXT, - &localrc)) { - delete[] gdalDofList; - gdalDofList = (MPI_Offset *)NULL; - return localrc; - } - } - - distGrid = arr_p->getDistGrid(); - const int *minIndexPDimPTile = distGrid->getMinIndexPDimPTile(); - const int *maxIndexPDimPTile = distGrid->getMaxIndexPDimPTile(); - - handle->tile = tile; -// NB: Is this part of the restrictions on Array I/O? -// nDims = arr_p->getRank(); - handle->nDims = distGrid->getDimCount(); - // Make sure dims is not used - if (handle->dims != (int *)NULL) { - delete handle->dims; - handle->dims = (int *)NULL; - } - handle->dims = new int[handle->nDims]; - // Step through the distGrid dimensions, getting the size of the dimension. (This is the - // size of the full array across all PEs.) - for (int i = 0; i < handle->nDims; i++) { - handle->dims[i] = (maxIndexPDimPTile[((tile - 1) * handle->nDims) + i] - - minIndexPDimPTile[((tile - 1) * handle->nDims) + i] + 1); - } - - handle->arrayRank = arr_p->getRank(); - if (handle->arrayShape != (int *)NULL) { - delete handle->arrayShape; - handle->arrayShape = (int *)NULL; - } - handle->arrayShape = new int[handle->arrayRank]; - // Get the size of each dimension owned locally. - if (thisDeIsThisTile) { - const int *totalLBound = arr_p->getTotalLBound(); - const int *totalUBound = arr_p->getTotalUBound(); - for (int i = 0; i < handle->arrayRank; ++i) { - // TODO: This is another place that would need to be generalized to handle more than - // one DE per PE: totalLBound and totalUBound are dimensioned - // [redDimCount*ssiLocalDeCount], so the below expression (which doesn't include the - // current DE count) would need to be adjusted to handle multiple DEs. - handle->arrayShape[i] = (totalUBound[i] - totalLBound[i] + 1); - } - } else { - // This DE is for some other tile, so as far as this tile is concerned, we own 0 elements - for (int i = 0; i < handle->arrayRank; ++i) { - handle->arrayShape[i] = 0; - } - } - -#ifdef ESMFIO_DEBUG - { - char shapestr[64]; - for (int i = 0; i < handle->arrayRank; i++) { - sprintf((shapestr + (5 * i)), " %03d%c", handle->arrayShape[i], - (((handle->arrayRank - 1) == i) ? ' ' : ',')); - } - PRINTMSG(", IODesc shape = [" << shapestr << "], calling gdal_initdecomp"); - - char dimstr[64]; - for (int i = 0; i < handle->nDims; i++) { - sprintf((dimstr + (5 * i)), " %03d%c", handle->dims[i], - (((handle->nDims - 1) == i) ? ' ' : ',')); - } - PRINTMSG(", IODesc dims = [" << dimstr << "]"); - } -#endif // ESMFIO_DEBUG - int ddims[handle->nDims]; - for(int i=0; inDims; i++) - ddims[i] = handle->dims[handle->nDims - i - 1]; - // Create the decomposition - ESMCI_IOREGION_ENTER("GDALc_InitDecomp"); - GDALc_InitDecomp(iosys, handle->basegdaltype, handle->nDims, - ddims, gdalDofCount, gdalDofList, - &(handle->io_descriptor), NULL, NULL, NULL); - ESMCI_IOREGION_EXIT("GDALc_InitDecomp"); - - PRINTMSG("after call to GDALc_initdecomp_dof"); - - // Add the handle into the master list - GDAL_IODescHandler::activeGdalIoDescriptors.push_back(handle); - // Finally, set the output handle - *newDecomp_p = handle->io_descriptor; - - // Free the DofList! - delete[] gdalDofList; - gdalDofList = (MPI_Offset *)NULL; - - // return successfully - return ESMF_SUCCESS; +//>> PRINTPOS; +//>> // check the inputs +//>> if ((Array *)NULL == arr_p) { +//>> ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, "- arr_p cannot be NULL", +//>> ESMC_CONTEXT, &localrc); +//>> return ESMF_RC_ARG_BAD; +//>> } +//>> if (tile < 1) { +//>> ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "- tile must be >= 1", +//>> ESMC_CONTEXT, &localrc); +//>> return localrc; +//>> } +//>> if ((int *)NULL == newDecomp_p) { +//>> ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, +//>> "- newDecomp_p cannot be NULL", ESMC_CONTEXT, &localrc); +//>> return ESMF_RC_ARG_BAD; +//>> } +//>> +//>> handle = new GDAL_IODescHandler(iosys, arr_p); +//>> gdalDofList = (MPI_Offset *)NULL; +//>> +//>> localDeCount = arr_p->getDELayout()->getLocalDeCount(); +//>> PRINTMSG("localDeCount = " << localDeCount); +//>> //TODO: Remove this restriction (possibly with multiple IO descriptors) +//>> if (localDeCount > 1) { +//>> ESMC_LogDefault.Write("I/O does not support multiple DEs per PET", +//>> ESMC_LOGMSG_WARN, ESMC_CONTEXT); +//>> return ESMF_RC_NOT_IMPL; +//>> } +//>> +//>> // TODO: To support multiple DEs per PE, we would need to extend this to be an array +//>> bool thisDeIsThisTile = false; +//>> +//>> // We need the total number of elements +//>> gdalDofCount = 0; +//>> int const *localDeToDeMap = arr_p->getDistGrid()->getDELayout()->getLocalDeToDeMap(); +//>> // NB: This loop is redundant for now, I wish I could lift the restriction. +//>> for (localDe = 0; localDe < localDeCount; ++localDe) { +//>> // consider the fact that replicated dimensions may lead to local elements in the +//>> // Array, that are not accounted for by actual exclusive elements in the DistGrid +//>> int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDe, &rc); +//>> if (ESMC_LogDefault.MsgFoundError(rc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) +//>> return localrc; +//>> if (tileOfThisDe == tile) { +//>> // TODO: As noted above, to support multiple DEs per PE, we would need to extend this to be an array +//>> thisDeIsThisTile = true; +//>> } +//>> if (thisDeIsThisTile && arr_p->getDistGrid()->getElementCountPDe()[localDeToDeMap[localDe]]>0) +//>> gdalDofCount += arr_p->getTotalElementCountPLocalDe()[localDe]; +//>> } +//>> +//>> PRINTMSG("gdalDofCount = " << gdalDofCount); +//>> try { +//>> // Allocate space for the DOF list +//>> gdalDofList = new MPI_Offset[gdalDofCount]; +//>> +//>> } catch(...) { +//>> if ((MPI_Offset *)NULL != gdalDofList) { +//>> // Free the DofList! +//>> delete[] gdalDofList; +//>> gdalDofList = (MPI_Offset *)NULL; +//>> } +//>> ESMC_LogDefault.AllocError(ESMC_CONTEXT, &localrc); +//>> return localrc; +//>> } +//>> // Fill in the GDAL DOF list (local to global map) +//>> // TODO: This is where we would need to make some magic to include multiple DEs. +//>> // TODO: (Particular care may be needed in the multi-tile case, where some DEs on the +//>> // TODO: current PE may be part of the current tile, while others are not. +//>> // TODO: For now, with one DE, we can assume that, if gdalDofCount>0, then this DE +//>> // TODO: corresponds to the current tile.) +//>> localDe = 0; +//>> if (gdalDofCount>0){ +//>> // construct the mapping of the local elements +//>> localrc = arr_p->constructFileMap((int64_t *) gdalDofList, gdalDofCount, localDe); +//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, +//>> &localrc)) { +//>> delete[] gdalDofList; +//>> gdalDofList = (MPI_Offset *)NULL; +//>> return localrc; +//>> } +//>> } +//>> +//>>#if 0 +//>> std::cout << " gdalDofList = ["; +//>> for (int i = 0; i < gdalDofCount; i++) { +//>> std::cout << " " << gdalDofList[i] +//>> << ((i == (gdalDofCount - 1)) ? ' ' : ','); +//>> } +//>> std::cout << "]" << std::endl; +//>>#endif // 0 +//>> // Get TKR info +//>> switch(arr_p->getTypekind()) { +//>> case ESMC_TYPEKIND_I4: +//>> handle->basegdaltype = GDAL_INT; +//>> break; +//>> case ESMC_TYPEKIND_R4: +//>> handle->basegdaltype = GDAL_REAL; +//>> break; +//>> case ESMC_TYPEKIND_R8: +//>> handle->basegdaltype = GDAL_DOUBLE; +//>> break; +//>> case ESMC_TYPEKIND_I1: +//>> case ESMC_TYPEKIND_I2: +//>> case ESMC_TYPEKIND_I8: +//>> case ESMC_TYPEKIND_CHARACTER: +//>> case ESMF_C8: +//>> case ESMF_C16: +//>> case ESMC_TYPEKIND_LOGICAL: +//>> default: +//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "Unsupported typekind", ESMC_CONTEXT, +//>> &localrc)) { +//>> delete[] gdalDofList; +//>> gdalDofList = (MPI_Offset *)NULL; +//>> return localrc; +//>> } +//>> } +//>> +//>> distGrid = arr_p->getDistGrid(); +//>> const int *minIndexPDimPTile = distGrid->getMinIndexPDimPTile(); +//>> const int *maxIndexPDimPTile = distGrid->getMaxIndexPDimPTile(); +//>> +//>> handle->tile = tile; +//>>// NB: Is this part of the restrictions on Array I/O? +//>>// nDims = arr_p->getRank(); +//>> handle->nDims = distGrid->getDimCount(); +//>> // Make sure dims is not used +//>> if (handle->dims != (int *)NULL) { +//>> delete handle->dims; +//>> handle->dims = (int *)NULL; +//>> } +//>> handle->dims = new int[handle->nDims]; +//>> // Step through the distGrid dimensions, getting the size of the dimension. (This is the +//>> // size of the full array across all PEs.) +//>> for (int i = 0; i < handle->nDims; i++) { +//>> handle->dims[i] = (maxIndexPDimPTile[((tile - 1) * handle->nDims) + i] - +//>> minIndexPDimPTile[((tile - 1) * handle->nDims) + i] + 1); +//>> } +//>> +//>> handle->arrayRank = arr_p->getRank(); +//>> if (handle->arrayShape != (int *)NULL) { +//>> delete handle->arrayShape; +//>> handle->arrayShape = (int *)NULL; +//>> } +//>> handle->arrayShape = new int[handle->arrayRank]; +//>> // Get the size of each dimension owned locally. +//>> if (thisDeIsThisTile) { +//>> const int *totalLBound = arr_p->getTotalLBound(); +//>> const int *totalUBound = arr_p->getTotalUBound(); +//>> for (int i = 0; i < handle->arrayRank; ++i) { +//>> // TODO: This is another place that would need to be generalized to handle more than +//>> // one DE per PE: totalLBound and totalUBound are dimensioned +//>> // [redDimCount*ssiLocalDeCount], so the below expression (which doesn't include the +//>> // current DE count) would need to be adjusted to handle multiple DEs. +//>> handle->arrayShape[i] = (totalUBound[i] - totalLBound[i] + 1); +//>> } +//>> } else { +//>> // This DE is for some other tile, so as far as this tile is concerned, we own 0 elements +//>> for (int i = 0; i < handle->arrayRank; ++i) { +//>> handle->arrayShape[i] = 0; +//>> } +//>> } +//>> +//>>#ifdef ESMFIO_DEBUG +//>> { +//>> char shapestr[64]; +//>> for (int i = 0; i < handle->arrayRank; i++) { +//>> sprintf((shapestr + (5 * i)), " %03d%c", handle->arrayShape[i], +//>> (((handle->arrayRank - 1) == i) ? ' ' : ',')); +//>> } +//>> PRINTMSG(", IODesc shape = [" << shapestr << "], calling gdal_initdecomp"); +//>> +//>> char dimstr[64]; +//>> for (int i = 0; i < handle->nDims; i++) { +//>> sprintf((dimstr + (5 * i)), " %03d%c", handle->dims[i], +//>> (((handle->nDims - 1) == i) ? ' ' : ',')); +//>> } +//>> PRINTMSG(", IODesc dims = [" << dimstr << "]"); +//>> } +//>>#endif // ESMFIO_DEBUG +//>> int ddims[handle->nDims]; +//>> for(int i=0; inDims; i++) +//>> ddims[i] = handle->dims[handle->nDims - i - 1]; +//>> // Create the decomposition +//>> ESMCI_IOREGION_ENTER("GDALc_InitDecomp"); +//>> GDALc_InitDecomp(iosys, handle->basegdaltype, handle->nDims, +//>> ddims, gdalDofCount, gdalDofList, +//>> &(handle->io_descriptor), NULL, NULL, NULL); +//>> ESMCI_IOREGION_EXIT("GDALc_InitDecomp"); +//>> +//>> PRINTMSG("after call to GDALc_initdecomp_dof"); +//>> +//>> // Add the handle into the master list +//>> GDAL_IODescHandler::activeGdalIoDescriptors.push_back(handle); +//>> // Finally, set the output handle +//>> *newDecomp_p = handle->io_descriptor; +//>> +//>> // Free the DofList! +//>> delete[] gdalDofList; +//>> gdalDofList = (MPI_Offset *)NULL; +//>> +//>> // return successfully +//>> return ESMF_SUCCESS; } // GDAL_IODescHandler::constructGdalDecomp() //----------------------------------------------------------------------------- @@ -2166,27 +2138,27 @@ int GDAL_IODescHandler::freeGdalDecomp( return ESMF_RC_ARG_BAD; } - // Look for newDecomp_p in the active handle instances - for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); - it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); ++it) { - handle = *it; - if (*decomp_p == handle->io_descriptor) { - foundHandle = true; - delete handle; - handle = (GDAL_IODescHandler *)NULL; - *decomp_p = (int)NULL; - break; - } - } - - // If we didn't find the handle, that is bad - if (foundHandle) { - localrc = ESMF_SUCCESS; - } else { - ESMC_LogDefault.Write("GDAL IO descriptor not found or freed", - ESMC_LOGMSG_ERROR, ESMC_CONTEXT); - localrc = ESMF_RC_MEM_DEALLOCATE; - } +//>> // Look for newDecomp_p in the active handle instances +//>> for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); +//>> it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); ++it) { +//>> handle = *it; +//>> if (*decomp_p == handle->io_descriptor) { +//>> foundHandle = true; +//>> delete handle; +//>> handle = (GDAL_IODescHandler *)NULL; +//>> *decomp_p = (int)NULL; +//>> break; +//>> } +//>> } +//>> +//>> // If we didn't find the handle, that is bad +//>> if (foundHandle) { +//>> localrc = ESMF_SUCCESS; +//>> } else { +//>> ESMC_LogDefault.Write("GDAL IO descriptor not found or freed", +//>> ESMC_LOGMSG_ERROR, ESMC_CONTEXT); +//>> localrc = ESMF_RC_MEM_DEALLOCATE; +//>> } return localrc; } // GDAL_IODescHandler::freeGdalDecomp() @@ -2222,31 +2194,31 @@ int GDAL_IODescHandler::getDims( //----------------------------------------------------------------------------- int localrc = ESMF_RC_NOT_FOUND; // local return code - std::vector::iterator it; - PRINTPOS; - for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); - it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); - it++) { - if (iodesc == (*it)->io_descriptor) { - PRINTMSG("getDims: found handler, nioDims = " << (*it)->nDims << - ", ioDims = " << (*it)->dims << ", narrDims = " << - (*it)->arrayRank); - if (nioDims != (int *)NULL) { - *nioDims = (*it)->nDims; - } - if (ioDims != (int **)NULL) { - *ioDims = (*it)->dims; - } - if (narrDims != (int *)NULL) { - *narrDims = (*it)->arrayRank; - } - if (arrDims != (int **)NULL) { - *arrDims = (*it)->arrayShape; - } - localrc = ESMF_SUCCESS; - break; - } - } +//>> std::vector::iterator it; +//>> PRINTPOS; +//>> for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); +//>> it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); +//>> it++) { +//>> if (iodesc == (*it)->io_descriptor) { +//>> PRINTMSG("getDims: found handler, nioDims = " << (*it)->nDims << +//>> ", ioDims = " << (*it)->dims << ", narrDims = " << +//>> (*it)->arrayRank); +//>> if (nioDims != (int *)NULL) { +//>> *nioDims = (*it)->nDims; +//>> } +//>> if (ioDims != (int **)NULL) { +//>> *ioDims = (*it)->dims; +//>> } +//>> if (narrDims != (int *)NULL) { +//>> *narrDims = (*it)->arrayRank; +//>> } +//>> if (arrDims != (int **)NULL) { +//>> *arrDims = (*it)->arrayShape; +//>> } +//>> localrc = ESMF_SUCCESS; +//>> break; +//>> } +//>> } // return success or not found return localrc; diff --git a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C index a892d96942..7f3106df49 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C @@ -153,6 +153,14 @@ IO_Handler *IO_Handler::create ( localrc = ESMF_RC_LIB_NOT_PRESENT; #endif // defined(ESMF_PIO) && (defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)) break; + case ESMF_IOFMT_SHP: +#if defined(ESMF_PIO) && defined(ESMF_GDAL) + iohandler = new PIO_Handler(iofmt, ntiles, &localrc); +#else // defined(ESMF_PIO) && (defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)) + errmsg = "PIO & GDAL libraries required for GIS I/O operation"; + localrc = ESMF_RC_LIB_NOT_PRESENT; +#endif // defined(ESMF_PIO) && defined(ESMF_GDAL) + break; default: localrc = ESMF_RC_ARG_BAD; break; diff --git a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 new file mode 100644 index 0000000000..9591f91b46 --- /dev/null +++ b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 @@ -0,0 +1,145 @@ +! $Id$ +! +! Earth System Modeling Framework +! Copyright (c) 2002-2023, University Corporation for Atmospheric Research, +! Massachusetts Institute of Technology, Geophysical Fluid Dynamics +! Laboratory, University of Michigan, National Centers for Environmental +! Prediction, Los Alamos National Laboratory, Argonne National Laboratory, +! NASA Goddard Space Flight Center. +! Licensed under the University of Illinois-NCSA License. +! +!============================================================================== +! +program ESMF_IO_GDALUTest + +!------------------------------------------------------------------------------ + +#include "ESMF_Macros.inc" +#include "ESMF.h" + +!============================================================================== +!BOP +! !PROGRAM: ESMF_IO_MultitileUTest - Unit tests of IO on multi-tile fields / arrays +! !DESCRIPTION: +! +! The tests in this file target IO on multi-tile fields / arrays. These tests +! are designed to be run on 8 processors (due to the decompositions used in the +! tests). +! +!----------------------------------------------------------------------------- +! !USES: + use ESMF_TestMod ! test methods + use ESMF + + implicit none + +!------------------------------------------------------------------------------ +!------------------------------------------------------------------------------ + + ! cumulative result: count failures; no failures equals "all pass" + integer :: result = 0 + integer :: rc + + ! individual test failure message + character(ESMF_MAXSTR) :: failMsg + character(ESMF_MAXSTR) :: name + + type(ESMF_VM) :: vm + integer :: localPet + type(ESMF_Grid) :: grid6tile + type(ESMF_DistGrid) :: distgrid3tile + + ! Fields used for writing: + ! + ! The following fields make up the field bundle: + type(ESMF_Field) :: field1, field2, field1Copy, field4d + real(ESMF_KIND_R8), pointer :: field1Data(:,:), field2Data(:,:), field1CopyData(:,:), field4dData(:,:,:,:) + type(ESMF_FieldBundle) :: fieldBundle + ! This field is not in the field bundle: + type(ESMF_Field) :: field3 + real(ESMF_KIND_R8), pointer :: field3Data(:,:) + + ! Fields used for reading: + ! + ! The following fields make up the field bundle: + type(ESMF_Field) :: field1Read, field2Read, field1CopyRead, field4dRead + real(ESMF_KIND_R8), pointer :: field1ReadData(:,:), field2ReadData(:,:), field1CopyReadData(:,:), field4dReadData(:,:,:,:) + type(ESMF_FieldBundle) :: fieldBundleRead + ! This field is not in the field bundle: + type(ESMF_Field) :: field3Read + real(ESMF_KIND_R8), pointer :: field3ReadData(:,:) + + ! This is used for error testing: + type(ESMF_Grid) :: gridSingleTile + type(ESMF_Field) :: fieldSingleTile + type(ESMF_FieldBundle) :: fieldBundleMixedTileCounts + + ! Arrays used for writing: + ! + ! The following arrays make up the array bundle: + type(ESMF_Array) :: array1, array2 + real(ESMF_KIND_R8), pointer :: array1Data(:,:), array2Data(:,:) + type(ESMF_ArrayBundle) :: arrayBundle + ! This array is not in the array bundle: + type(ESMF_Array) :: array3 + real(ESMF_KIND_R8), pointer :: array3Data(:,:) + + ! Arrays used for reading: + ! + ! The following arrays make up the array bundle: + type(ESMF_Array) :: array1Read, array2Read + real(ESMF_KIND_R8), pointer :: array1ReadData(:,:), array2ReadData(:,:) + type(ESMF_ArrayBundle) :: arrayBundleRead + ! This array is not in the array bundle: + type(ESMF_Array) :: array3Read + real(ESMF_KIND_R8), pointer :: array3ReadData(:,:) + + logical :: allEqual + + character(len=*), parameter :: fileNameFields = "ESMF_IO_GDALUTestFields#.shp" + + !------------------------------------------------------------------------ + call ESMF_TestStart(ESMF_SRCLINE, rc=rc) ! calls ESMF_Initialize() internally + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_VMGetGlobal(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_VMGet(vm, localPet=localPet, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ + + ! --- + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + write(name, *) "Read a multi-tile Field" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldRead(field3Read, fileName=fileNameFields, iofmt=ESMF_IOFMT_SHP, rc=rc) +#if (defined ESMF_PIO && (defined ESMF_GDAL)) + call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) +#else + write(failMsg, *) "Did not return ESMF_RC_LIB_NOT_PRESENT" + call ESMF_Test((rc == ESMF_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) +#endif + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only +!>> write(name, *) "Confirm that Field-read field matches original" +!>> write(failMsg, *) "Read-in field differs from original" +!>> allEqual = all(field3ReadData == field3Data) +!>>#if (defined ESMF_PIO && (defined ESMF_GDAL)) +!>> call ESMF_Test(allEqual, name, failMsg, result, ESMF_SRCLINE) +!>>#else +!>> write(failMsg, *) "Comparison did not fail as expected" +!>> call ESMF_Test(.not. allEqual, name, failMsg, result, ESMF_SRCLINE) +!>>#endif + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + call ESMF_TestEnd(ESMF_SRCLINE) ! calls ESMF_Finalize() internally + !------------------------------------------------------------------------ + +contains + +end program ESMF_IO_GDALUTest diff --git a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.Log b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.Log deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C deleted file mode 100644 index 148b044587..0000000000 --- a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapGenUTest.C +++ /dev/null @@ -1,537 +0,0 @@ -//============================================================================== -// -// Earth System Modeling Framework -// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, -// Massachusetts Institute of Technology, Geophysical Fluid Dynamics -// Laboratory, University of Michigan, National Centers for Environmental -// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, -// NASA Goddard Space Flight Center. -// Licensed under the University of Illinois-NCSA License. -// -//============================================================================== -#ifndef MPICH_IGNORE_CXX_SEEK -#define MPICH_IGNORE_CXX_SEEK -#endif -#include - -// ESMF header -#include "ESMC.h" - -// ESMF Test header -#include "ESMC_Test.h" - -#if defined ESMF_MOAB -#include "ESMCI_MBMesh.h" -#include "ESMCI_MBMesh_Glue.h" -#include "ESMCI_MCTGen.C" -#endif - -#include "ESMCI_MeshCap.h" -#include "ESMCI_Mesh.h" - -#include -#include -#include -#include -#include -#include -#include //find_if -#include - -struct FindPair { - FindPair (std::string first, std::string second) \ - : m_first_value(first), m_second_value(second) {} - - std::string m_first_value; - std::string m_second_value; - bool operator() (const std::pair &p) { - return (p.first == m_first_value && p.second == m_second_value); - } -}; - -void combine(const std::string &api, const std::string &mesh, - const std::string &nativeormb){ - int localrc; - int rc = ESMF_FAILURE; - - std::string failMsg = "FAIL"; - int result = 0; - -#if defined ESMF_MOAB - MCTGen *generate = new MCTGen(); -#endif - - int nvmb = 1; - if (nativeormb == "Native") nvmb = 0; - - int localPet, petCount; - ESMC_VM vm; - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - std::array buffer; - buffer.fill(0); - time_t rawtime; - time(&rawtime); - const auto timeinfo = localtime(&rawtime); - strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); - std::string timeStr(buffer.data()); - - std::string name = timeStr + " - " + "PET " + std::to_string(localPet) + " - " + - nativeormb + " Mesh - " + api + " - " + mesh; - -#if defined ESMF_MOAB - try { - std::shared_ptr test = generate->mesh_map[mesh](localrc); - - test->name = name; - test->nativeormb = nvmb; - // test->verbosity = 3; - // test->tol = 1.e-15; - // test->print(); - - if (localrc == ESMF_SUCCESS) localrc = test->build(); - if (localrc == ESMF_SUCCESS) rc = test->function_map[api](); - - // test is a shared_ptr so no need to delete - // delete test; - } - CATCH_MCT_FAIL(&rc) -#else - rc = ESMF_SUCCESS; -#endif - -#if defined ESMF_MOAB - delete generate; -#endif - - ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), - &result, __FILE__, __LINE__, 0); - -} - -int main(int argc, char *argv[]) { -#undef ESMC_METHOD -#define ESMC_METHOD "MeshCapUTest::main()" - - int rc; - int localPet, petCount; - ESMC_VM vm; - - std::string failMsg = "FAIL"; - // break this up so it doesn't count as an additional test - std::string nex_test_tag = "//NEX_"; - nex_test_tag.append("UTest\n"); - int result = 0; - - //---------------------------------------------------------------------------- - // Start the test with an alternate name for log and stdout files - ESMC_TestStart("ESMCI_MeshCapGenUTest.C", __LINE__, 0); - - //---------------------------------------------------------------------------- - rc=ESMC_LogSet(true); - - // Get parallel information - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - // output stream to write test tag to the generated source file - std::ofstream tagfile; - tagfile.open("ESMCI_MeshCapGenUTest.C", std::ios_base::app); - - // this is an easy way to comment a single line to toggle mbmesh/native - bool mbmesh = false; - mbmesh = true; - bool native = false; - native = true; - - // these are bound to MCT in constructor, must match! - std::vector test_apis; - test_apis.push_back("createget"); - test_apis.push_back("dual"); - test_apis.push_back("redist_elem"); - test_apis.push_back("redist_node"); - test_apis.push_back("redist_elno"); - test_apis.push_back("serialize"); - test_apis.push_back("to_pointlist_elem"); - test_apis.push_back("to_pointlist_node"); - test_apis.push_back("write_vtk"); - - // these are bound to MCTGen in constructor, must match! - std::vector test_meshes_native; - test_meshes_native.push_back("quad_2d_cart"); - test_meshes_native.push_back("quad_2d_sph_deg"); - test_meshes_native.push_back("quad_2d_sph_rad"); - test_meshes_native.push_back("tri_2d_cart"); - test_meshes_native.push_back("tri_2d_sph_deg"); - test_meshes_native.push_back("tri_2d_sph_rad"); - test_meshes_native.push_back("hex_3d_cart"); - test_meshes_native.push_back("hex_3d_sph_deg"); - test_meshes_native.push_back("hex_3d_sph_rad"); - test_meshes_native.push_back("mix_2d_cart"); - test_meshes_native.push_back("mix_2d_sph_deg"); - test_meshes_native.push_back("mix_2d_sph_rad"); - test_meshes_native.push_back("periodic_2d_sph_deg"); - test_meshes_native.push_back("periodic_2d_sph_rad"); - // cannot get info from ngons - // test_meshes_native.push_back("ngon_2d_cart"); - // test_meshes_native.push_back("ngon_2d_sph_deg"); - // test_meshes_native.push_back("ngon_2d_sph_rad"); - - // these are bound to MCTGen in constructor, must match! - std::vector test_meshes_mbmesh; - test_meshes_mbmesh.push_back("quad_2d_cart"); - test_meshes_mbmesh.push_back("quad_2d_sph_deg"); - test_meshes_mbmesh.push_back("quad_2d_sph_rad"); - test_meshes_mbmesh.push_back("tri_2d_cart"); - test_meshes_mbmesh.push_back("tri_2d_sph_deg"); - test_meshes_mbmesh.push_back("tri_2d_sph_rad"); - test_meshes_mbmesh.push_back("hex_3d_cart"); - test_meshes_mbmesh.push_back("hex_3d_sph_deg"); - test_meshes_mbmesh.push_back("hex_3d_sph_rad"); - test_meshes_mbmesh.push_back("mix_2d_cart"); - test_meshes_mbmesh.push_back("mix_2d_sph_deg"); - test_meshes_mbmesh.push_back("mix_2d_sph_rad"); - test_meshes_mbmesh.push_back("ngon_2d_cart"); - test_meshes_mbmesh.push_back("ngon_2d_sph_deg"); - test_meshes_mbmesh.push_back("ngon_2d_sph_rad"); - test_meshes_mbmesh.push_back("periodic_2d_sph_deg"); - test_meshes_mbmesh.push_back("periodic_2d_sph_rad"); - - // skip the following tests - std::vector> skip_test_mbmesh = {\ - // dual not implemented in 3d - {"dual", "hex_3d_cart"}, - {"dual", "hex_3d_sph_deg"}, - {"dual", "hex_3d_sph_rad"}, - // ESMCI_MBMesh_Redist.C, line:2336:Could not find a suitable processor for this element - {"redist_node", "tri_2d_cart"}, - {"redist_node", "tri_2d_sph_deg"}, - {"redist_node", "tri_2d_sph_rad"}, - - }; - - std::vector> skip_test_native = {\ - // dual not implemented in 3d - // Creation of a dual mesh isn't supported for Meshes of parametric dim greater than 3. - {"dual", "hex_3d_cart"}, - {"dual", "hex_3d_sph_deg"}, - {"dual", "hex_3d_sph_rad"}, - }; - - - if (mbmesh) { - for (const auto api: test_apis) { - for (const auto mesh: test_meshes_mbmesh) { - // don't run cases that hang - auto skip_itr = std::find_if(skip_test_mbmesh.begin(), skip_test_mbmesh.end(), - FindPair(api, mesh)); - - if (skip_itr != skip_test_mbmesh.end()) { - continue; - } else { - combine(api, mesh, "MBMesh"); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - - if (native) { - for (const auto api: test_apis) { - for (const auto mesh: test_meshes_native) { - // don't run cases that hang - auto skip_itr = std::find_if(skip_test_native.begin(), skip_test_native.end(), - FindPair(api, mesh)); - - if (skip_itr != skip_test_native.end()) { - continue; - } else { - combine(api, mesh, "Native"); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - - tagfile.close(); - - //---------------------------------------------------------------------------- - ESMC_TestEnd("ESMCI_MeshCapGenUTest.C", __LINE__, 0); - - return 0; -} -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest diff --git a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C b/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C deleted file mode 100644 index 52f3cc146c..0000000000 --- a/src/Infrastructure/Mesh/tests/ESMCI_MeshCapRegridGenUTest.C +++ /dev/null @@ -1,5091 +0,0 @@ -//============================================================================== -// -// Earth System Modeling Framework -// Copyright (c) 2002-2023, University Corporation for Atmospheric Research, -// Massachusetts Institute of Technology, Geophysical Fluid Dynamics -// Laboratory, University of Michigan, National Centers for Environmental -// Prediction, Los Alamos National Laboratory, Argonne National Laboratory, -// NASA Goddard Space Flight Center. -// Licensed under the University of Illinois-NCSA License. -// -//============================================================================== -#ifndef MPICH_IGNORE_CXX_SEEK -#define MPICH_IGNORE_CXX_SEEK -#endif -#include - -// ESMF header -#include "ESMC.h" - -// ESMF Test header -#include "ESMC_Test.h" - -#if defined ESMF_MOAB -#include "ESMCI_MBMesh.h" -#include "ESMCI_MBMesh_Glue.h" -#include "ESMCI_MCTGen.C" -#endif - -#include -#include -#include -#include -#include -#include -#include //find_if -#include -#include - -struct FindAnyPair { - FindAnyPair (std::string a, std::string b, std::string c, std::string d, - std::string e, std::string f, std::string g, std::string h) - : a_val(a), b_val(b), c_val(c), d_val(d), - e_val(e), f_val(f), g_val(g), h_val(h) {} - - std::string a_val; - std::string b_val; - std::string c_val; - std::string d_val; - std::string e_val; - std::string f_val; - std::string g_val; - std::string h_val; - bool operator() - ( const std::pair &p ) { - return (((p.first == a_val) || (p.first == b_val) || - (p.first == c_val) || (p.first == d_val) || - (p.first == e_val) || (p.first == f_val) || - (p.first == g_val) || (p.first == h_val)) && - ((p.second == a_val) || (p.second == b_val) || - (p.second == c_val) || (p.second == d_val) || - (p.second == e_val) || (p.second == f_val) || - (p.second == g_val) || (p.second == h_val))); - } -}; - -void combine(const std::string &api, const std::string &mesh, - const std::string &nativeormb, - const std::string &maptype, - const std::string &normtype, - const std::string &poletype, - const std::string &extrapmethod, - const std::string &unmappedaction, - const std::string &ignoredegenerate){ - int localrc; - int rc = ESMF_FAILURE; - - std::string failMsg = "FAIL"; - std::string dash = " - "; - int result = 0; - -#if defined ESMF_MOAB - MCTGen *generate = new MCTGen(); -#endif - - int nvmb = 1; - if (nativeormb == "Native") nvmb = 0; - - int localPet, petCount; - ESMC_VM vm; - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - std::array buffer; - buffer.fill(0); - time_t rawtime; - time(&rawtime); - const auto timeinfo = localtime(&rawtime); - strftime(buffer.data(), sizeof(buffer), "%d-%m-%Y %H-%M-%S", timeinfo); - std::string timeStr(buffer.data()); - - std::string name = timeStr + dash + "PET " + std::to_string(localPet) + dash + - nativeormb + " Mesh - " + api + dash + mesh + - dash + maptype + dash + normtype + dash + poletype + - dash + extrapmethod + dash + unmappedaction + - dash + ignoredegenerate; - -#if defined ESMF_MOAB - try { - std::shared_ptr test = generate->mesh_map[mesh](localrc); - - test->name = name; - test->nativeormb = nvmb; - // test->verbosity = 3; - // test->tol = 1.e-15; - // test->print(); - - // convert parameters to integers - int mt = test->MapType[maptype]; - int nt = test->NormType[normtype]; - int pt = test->PoleType[poletype]; - int em = test->ExtrapMethod[extrapmethod]; - int ua = test->UnmappedAction[unmappedaction]; - int id = test->IgnoreDegenerate[ignoredegenerate]; - - if (localrc == ESMF_SUCCESS) localrc = test->build(); - if (localrc == ESMF_SUCCESS) rc = test->regrid_map[api](mt, nt, pt, - em, ua, id); - - // test is a shared_ptr so no need to delete - // delete test; - } - CATCH_MCT_FAIL(&rc) -#else - rc = ESMF_SUCCESS; -#endif - -#if defined ESMF_MOAB - delete generate; -#endif - - ESMC_Test(rc==ESMF_SUCCESS, name.c_str(), failMsg.c_str(), - &result, __FILE__, __LINE__, 0); -} - -int main(int argc, char *argv[]) { -#undef ESMC_METHOD -#define ESMC_METHOD "MBMeshRegidUTest::main()" - - int rc, localrc; - int localPet, petCount; - ESMC_VM vm; - - std::string failMsg = "FAIL"; - // break this up so it doesn't count as an additional test - std::string nex_test_tag = "//NEX_"; - nex_test_tag.append("UTest\n"); - int result = 0; - - //---------------------------------------------------------------------------- - // Start the test with an alternate name for log and stdout files - ESMC_TestStart("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); - - //---------------------------------------------------------------------------- - rc=ESMC_LogSet(true); - - // Get parallel information - vm=ESMC_VMGetGlobal(&rc); - rc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, - (int *)NULL, (int *)NULL); - - // output stream to write test tag to the generated source file - std::ofstream tagfile; - tagfile.open("ESMCI_MeshCapRegridGenUTest.C", std::ios_base::app); - - // this is an easy way to comment a single line to toggle mbmesh/native - bool mbmesh = false; - mbmesh = true; - bool native = false; - native = true; - - std::vector test_apis_mbmesh; - test_apis_mbmesh.push_back("bilinear"); - test_apis_mbmesh.push_back("conservative"); - test_apis_mbmesh.push_back("nearest_d2s"); - test_apis_mbmesh.push_back("nearest_s2d"); - // Not yet available with MBMesh - // test_apis_mbmesh.push_back("conservative_2nd"); - // test_apis_mbmesh.push_back("patch"); - - std::vector test_apis_native; - test_apis_native.push_back("bilinear"); - test_apis_native.push_back("conservative"); - test_apis_native.push_back("conservative_2nd"); - test_apis_native.push_back("nearest_d2s"); - test_apis_native.push_back("nearest_s2d"); - test_apis_native.push_back("patch"); - - // these are bound to MCTGen in constructor, must match! - std::vector test_meshes; - test_meshes.push_back("quad_2d_cart"); - test_meshes.push_back("quad_2d_sph_deg"); - test_meshes.push_back("quad_2d_sph_rad"); - test_meshes.push_back("tri_2d_cart"); - test_meshes.push_back("tri_2d_sph_deg"); - test_meshes.push_back("tri_2d_sph_rad"); - test_meshes.push_back("hex_3d_cart"); - test_meshes.push_back("hex_3d_sph_deg"); - test_meshes.push_back("hex_3d_sph_rad"); - test_meshes.push_back("mix_2d_cart"); - test_meshes.push_back("mix_2d_sph_deg"); - test_meshes.push_back("mix_2d_sph_rad"); - test_meshes.push_back("ngon_2d_cart"); - test_meshes.push_back("ngon_2d_sph_deg"); - test_meshes.push_back("ngon_2d_sph_rad"); - test_meshes.push_back("periodic_2d_sph_deg"); - test_meshes.push_back("periodic_2d_sph_rad"); - - // method dependent, and mesh dependent - std::vector test_regrid_maptype; - test_regrid_maptype.push_back("MAP_CARTAPPROX"); - test_regrid_maptype.push_back("MAP_GREATCIRCLE"); - - // only conservative methods, all meshes - std::vector test_regrid_normtype; - test_regrid_normtype.push_back("NORM_DSTAREA"); - test_regrid_normtype.push_back("NORM_FRACAREA"); - - // all methods, but only for periodic grids - std::vector test_regrid_poletype; - test_regrid_poletype.push_back("POLE_NONE"); - test_regrid_poletype.push_back("POLE_ALL"); - test_regrid_poletype.push_back("POLE_NPNT"); - test_regrid_poletype.push_back("POLE_TEETH"); - - // all methods except nn, but only for meshes with destination larger than source - std::vector test_regrid_extrapmethod; - test_regrid_extrapmethod.push_back("EXTRAP_NONE"); - test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_STOD"); - test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_IDAVG"); - test_regrid_extrapmethod.push_back("EXTRAP_NEAREST_D"); - test_regrid_extrapmethod.push_back("EXTRAP_CREEP"); - test_regrid_extrapmethod.push_back("EXTRAP_CREEP_NRST_D"); - - // all methods except nn, but only for meshes with destination larger than source - std::vector test_regrid_unmappedaction; - test_regrid_unmappedaction.push_back("UNMAPPED_THROWERROR"); - test_regrid_unmappedaction.push_back("UNMAPPED_IGNORE"); - - // all methods except nn, but only meshes with degenerate, clockwise or concave elements - std::vector test_regrid_ignoredegenerate; - test_regrid_ignoredegenerate.push_back("DONOT_IGNORE_DEGENERATE"); - test_regrid_ignoredegenerate.push_back("IGNORE_DEGENERATE"); - - - - std::vector> skip_test_mbmesh = {\ - // conservative not supported with ngons - {"conservative", "ngon_2d_cart"}, - {"conservative", "ngon_2d_sph_deg"}, - {"conservative", "ngon_2d_sph_rad"}, - // extrapolation methods not supported (why do EXTRAP_NEAREST_STOD, EXTRAP_NEAREST_IDAVG work?) - {"bilinear", "EXTRAP_NEAREST_D"}, - {"bilinear", "EXTRAP_CREEP"}, - {"bilinear", "EXTRAP_CREEP_NRST_D"}, - {"patch", "EXTRAP_NEAREST_D"}, - {"patch", "EXTRAP_CREEP"}, - {"patch", "EXTRAP_CREEP_NRST_D"}, - }; - - std::vector> skip_test_native = {\ - // meshes with ngons return incorrect element count with native - {"bilinear", "ngon_2d_cart"}, - {"bilinear", "ngon_2d_sph_deg"}, - {"bilinear", "ngon_2d_sph_rad"}, - {"patch", "ngon_2d_cart"}, - {"patch", "ngon_2d_sph_deg"}, - {"patch", "ngon_2d_sph_rad"}, - {"conservative", "ngon_2d_cart"}, - {"conservative", "ngon_2d_sph_deg"}, - {"conservative", "ngon_2d_sph_rad"}, - {"conservative_2nd", "ngon_2d_cart"}, - {"conservative_2nd", "ngon_2d_sph_deg"}, - {"conservative_2nd", "ngon_2d_sph_rad"}, - // Conservative not supported on 3D spherical meshes - {"conservative", "hex_3d_sph_deg"}, - {"conservative", "hex_3d_sph_rad"}, - }; - - std::vector> skip_test_common = {\ - // patch not supported in 3d - {"patch", "hex_3d_cart"}, - {"patch", "hex_3d_sph_deg"}, - {"patch", "hex_3d_sph_rad"}, - // conservative_2nd not supported in 3d - {"conservative_2nd", "hex_3d_cart"}, - {"conservative_2nd", "hex_3d_sph_deg"}, - {"conservative_2nd", "hex_3d_sph_rad"}, - // creep fill extrapolation not supported in 3D - {"hex_3d_cart", "EXTRAP_CREEP"}, - {"hex_3d_sph_deg", "EXTRAP_CREEP"}, - {"hex_3d_sph_rad", "EXTRAP_CREEP"}, - {"hex_3d_cart", "EXTRAP_CREEP_NRST_D"}, - {"hex_3d_sph_deg", "EXTRAP_CREEP_NRST_D"}, - {"hex_3d_sph_rad", "EXTRAP_CREEP_NRST_D"}, - // conservative is not supported with extrapolation - {"conservative", "EXTRAP_NEAREST_STOD"}, - {"conservative", "EXTRAP_NEAREST_IDAVG"}, - {"conservative", "EXTRAP_NEAREST_D"}, - {"conservative", "EXTRAP_CREEP"}, - {"conservative", "EXTRAP_CREEP_NRST_D"}, - {"conservative_2nd", "EXTRAP_NEAREST_STOD"}, - {"conservative_2nd", "EXTRAP_NEAREST_IDAVG"}, - {"conservative_2nd", "EXTRAP_NEAREST_D"}, - {"conservative_2nd", "EXTRAP_CREEP"}, - {"conservative_2nd", "EXTRAP_CREEP_NRST_D"}, - // the following are exceptions due to design, do not represent limitations per se - // conservative only works with great circles - {"conservative", "MAP_CARTAPPROX"}, - {"conservative_2nd", "MAP_CARTAPPROX"}, - // cartesian only works with straight lines - {"quad_2d_cart", "MAP_GREATCIRCLE"}, - {"tri_2d_cart", "MAP_GREATCIRCLE"}, - {"hex_3d_cart", "MAP_GREATCIRCLE"}, - {"mix_2d_cart", "MAP_GREATCIRCLE"}, - {"ngon_2d_cart", "MAP_GREATCIRCLE"}, - // nearest doesn't touch on any of the regrid options, only allow defaults - {"nearest_d2s", "MAP_GREATCIRCLE"}, - {"nearest_d2s", "POLE_ALL"}, - {"nearest_d2s", "POLE_NPNT"}, - {"nearest_d2s", "POLE_TEETH"}, - {"nearest_d2s", "EXTRAP_NEAREST_STOD"}, - {"nearest_d2s", "EXTRAP_NEAREST_IDAVG"}, - {"nearest_d2s", "EXTRAP_NEAREST_D"}, - {"nearest_d2s", "EXTRAP_CREEP"}, - {"nearest_d2s", "EXTRAP_CREEP_NRST_D"}, - {"nearest_d2s", "UNMAPPED_IGNORE"}, - {"nearest_d2s", "IGNORE_DEGENERATE"}, - {"nearest_s2d", "MAP_GREATCIRCLE"}, - {"nearest_s2d", "POLE_ALL"}, - {"nearest_s2d", "POLE_NPNT"}, - {"nearest_s2d", "POLE_TEETH"}, - {"nearest_s2d", "EXTRAP_NEAREST_STOD"}, - {"nearest_s2d", "EXTRAP_NEAREST_IDAVG"}, - {"nearest_s2d", "EXTRAP_NEAREST_D"}, - {"nearest_s2d", "EXTRAP_CREEP"}, - {"nearest_s2d", "EXTRAP_CREEP_NRST_D"}, - {"nearest_s2d", "UNMAPPED_IGNORE"}, - {"nearest_s2d", "IGNORE_DEGENERATE"}, - // only run pole options with periodic meshes - {"quad_2d_cart", "POLE_ALL"}, - {"quad_2d_sph_deg", "POLE_ALL"}, - {"quad_2d_sph_rad", "POLE_ALL"}, - {"tri_2d_cart", "POLE_ALL"}, - {"tri_2d_sph_deg", "POLE_ALL"}, - {"tri_2d_sph_rad", "POLE_ALL"}, - {"hex_3d_cart", "POLE_ALL"}, - {"hex_3d_sph_deg", "POLE_ALL"}, - {"hex_3d_sph_rad", "POLE_ALL"}, - {"mix_2d_cart", "POLE_ALL"}, - {"mix_2d_sph_deg", "POLE_ALL"}, - {"mix_2d_sph_rad", "POLE_ALL"}, - {"ngon_2d_cart", "POLE_ALL"}, - {"ngon_2d_sph_deg", "POLE_ALL"}, - {"ngon_2d_sph_rad", "POLE_ALL"}, - {"quad_2d_cart", "POLE_NPNT"}, - {"quad_2d_sph_deg", "POLE_NPNT"}, - {"quad_2d_sph_rad", "POLE_NPNT"}, - {"tri_2d_cart", "POLE_NPNT"}, - {"tri_2d_sph_deg", "POLE_NPNT"}, - {"tri_2d_sph_rad", "POLE_NPNT"}, - {"hex_3d_cart", "POLE_NPNT"}, - {"hex_3d_sph_deg", "POLE_NPNT"}, - {"hex_3d_sph_rad", "POLE_NPNT"}, - {"mix_2d_cart", "POLE_NPNT"}, - {"mix_2d_sph_deg", "POLE_NPNT"}, - {"mix_2d_sph_rad", "POLE_NPNT"}, - {"ngon_2d_cart", "POLE_NPNT"}, - {"ngon_2d_sph_deg", "POLE_NPNT"}, - {"ngon_2d_sph_rad", "POLE_NPNT"}, - {"quad_2d_cart", "POLE_TEETH"}, - {"quad_2d_sph_deg", "POLE_TEETH"}, - {"quad_2d_sph_rad", "POLE_TEETH"}, - {"tri_2d_cart", "POLE_TEETH"}, - {"tri_2d_sph_deg", "POLE_TEETH"}, - {"tri_2d_sph_rad", "POLE_TEETH"}, - {"hex_3d_cart", "POLE_TEETH"}, - {"hex_3d_sph_deg", "POLE_TEETH"}, - {"hex_3d_sph_rad", "POLE_TEETH"}, - {"mix_2d_cart", "POLE_TEETH"}, - {"mix_2d_sph_deg", "POLE_TEETH"}, - {"mix_2d_sph_rad", "POLE_TEETH"}, - {"ngon_2d_cart", "POLE_TEETH"}, - {"ngon_2d_sph_deg", "POLE_TEETH"}, - {"ngon_2d_sph_rad", "POLE_TEETH"}, - }; - - - if (mbmesh) { - for (const auto api: test_apis_mbmesh) { - for (const auto mesh: test_meshes) { - for (const auto mt: test_regrid_maptype) { - for (const auto nt: test_regrid_normtype) { - for (const auto pt: test_regrid_poletype) { - for (const auto em: test_regrid_extrapmethod) { - for (const auto ua: test_regrid_unmappedaction) { - for (const auto id: test_regrid_ignoredegenerate) { - auto skip_itr_common = std::find_if(skip_test_common.begin(), - skip_test_common.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - auto skip_itr_mbmesh = std::find_if(skip_test_mbmesh.begin(), - skip_test_mbmesh.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - if ((skip_itr_common != skip_test_common.end()) || - (skip_itr_mbmesh != skip_test_mbmesh.end())) { - continue; - } else { - combine(api, mesh, "MBMesh", mt, nt, pt, em, ua, id); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - } - } - } - } - } - } - - if (native) { - for (const auto api: test_apis_native) { - for (const auto mesh: test_meshes) { - for (const auto mt: test_regrid_maptype) { - for (const auto nt: test_regrid_normtype) { - for (const auto pt: test_regrid_poletype) { - for (const auto em: test_regrid_extrapmethod) { - for (const auto ua: test_regrid_unmappedaction) { - for (const auto id: test_regrid_ignoredegenerate) { - auto skip_itr_common = std::find_if(skip_test_common.begin(), - skip_test_common.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - auto skip_itr_native = std::find_if(skip_test_native.begin(), - skip_test_native.end(), - FindAnyPair(api, mesh, - mt, nt, pt, - em, ua, id)); - - if ((skip_itr_common != skip_test_common.end()) || - (skip_itr_native != skip_test_native.end())) { - continue; - } else { - combine(api, mesh, "Native", mt, nt, pt, em, ua, id); - // only print one tag per test (so only on root) - if (localPet == 0) tagfile << nex_test_tag; - } - } - } - } - } - } - } - } - } - } - - tagfile.close(); - - //---------------------------------------------------------------------------- - ESMC_TestEnd("ESMCI_MeshCapRegridGenUTest.C", __LINE__, 0); - - return 0; -} -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest -//NEX_UTest diff --git a/src/Infrastructure/Util/include/ESMC_Util.h b/src/Infrastructure/Util/include/ESMC_Util.h index ee5ae0c8f9..8a3ab60b50 100644 --- a/src/Infrastructure/Util/include/ESMC_Util.h +++ b/src/Infrastructure/Util/include/ESMC_Util.h @@ -109,7 +109,8 @@ typedef enum ESMC_IOFmt_Flag { //ESMF_IOFMT_BIN=0, ESMF_IOFMT_NETCDF4P, ESMF_IOFMT_NETCDF4C, ESMF_IOFMT_CONFIG, - ESMF_IOFMT_YAML} ESMC_IOFmt_Flag; + ESMF_IOFMT_YAML, + ESMF_IOFMT_SHP} ESMC_IOFmt_Flag; enum ESMC_LineType_Flag { ESMC_LINETYPE_CART=0, ESMC_LINETYPE_GREAT_CIRCLE}; diff --git a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 index 8d9c30c6b5..08fc09ba31 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 +++ b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 @@ -566,7 +566,8 @@ module ESMF_UtilTypesMod ESMF_IOFMT_NETCDF4P = ESMF_IOFmt_Flag(5), & ESMF_IOFMT_NETCDF4C = ESMF_IOFmt_Flag(6), & ESMF_IOFMT_CONFIG = ESMF_IOFmt_Flag(7), & - ESMF_IOFMT_YAML = ESMF_IOFmt_Flag(8) + ESMF_IOFMT_YAML = ESMF_IOFmt_Flag(8), & + ESMF_IOFMT_SHP = ESMF_IOFmt_Flag(9) ! GDAL/Shapefile format (MSL) !------------------------------------------------------------------------------ ! ! ESMF_Index_Flag @@ -1069,7 +1070,8 @@ module ESMF_UtilTypesMod ESMF_IOFMT_NETCDF4P, & ESMF_IOFMT_NETCDF4C, & ESMF_IOFMT_CONFIG, & - ESMF_IOFMT_YAML + ESMF_IOFMT_YAML, & + ESMF_IOFMT_SHP public ESMF_Index_Flag, & ESMF_INDEX_DELOCAL, & From 83dccf0ec8f20f67118736eaa0d9ff04e56683ff Mon Sep 17 00:00:00 2001 From: Michael Long Date: Mon, 17 Jul 2023 18:10:02 -0400 Subject: [PATCH 13/58] Added GDAL_Handler class. Compiles MSL --- src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h | 4 ++-- src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C | 2 +- src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h index 06753eead5..bfff4bc27c 100644 --- a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h @@ -53,7 +53,7 @@ namespace ESMCI { // classes and structs class GDAL_Handler; // The main class for implementing GDAL functionality - + class GDAL_SystemHandler; // class definitions //=========================================================================== @@ -123,7 +123,7 @@ namespace ESMCI { } // open() and close() - void GDAL_openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); + void openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); ESMC_Logical isOpen(int tile); ESMC_Logical isNewFile(int tile) { // note 1-based indexing for tile return (new_file[tile-1] ? ESMF_TRUE : ESMF_FALSE); diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index a1ba61c274..f13d68b1ad 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -1174,7 +1174,7 @@ void GDAL_Handler::arrayWriteOneTileFile( // !IROUTINE: ESMCI::GDAL_Handler::openOneTileFile - open a stream with stored filename, for the given tile // // !INTERFACE: -void GDAL_Handler::GDAL_openOneTileFile( +void GDAL_Handler::openOneTileFile( // // !RETURN VALUE: // diff --git a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C index 7f3106df49..e759d8c10a 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C @@ -155,7 +155,7 @@ IO_Handler *IO_Handler::create ( break; case ESMF_IOFMT_SHP: #if defined(ESMF_PIO) && defined(ESMF_GDAL) - iohandler = new PIO_Handler(iofmt, ntiles, &localrc); + iohandler = new GDAL_Handler(iofmt, ntiles, &localrc); #else // defined(ESMF_PIO) && (defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)) errmsg = "PIO & GDAL libraries required for GIS I/O operation"; localrc = ESMF_RC_LIB_NOT_PRESENT; From 981bb9702bd101e846680d4c632cff15a3a65bf4 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Thu, 7 Sep 2023 09:35:48 -0400 Subject: [PATCH 14/58] Using the IO GDAL multitile test. File opens and info is queried GDALClose still segfaults, because it's still done on all nodes. Close needs to happen only once. At this point, freezing this branch, and cloning into another for a restart. It looks like we need the PIO CPU topo and file handling types to manage the interface. So PIO will be cloned and GDAL built in in place of NETCDF. Lots to do! MSL --- settings.sh | 6 +- .../IO/include/ESMCI_GDAL_Handler.h | 2 +- src/Infrastructure/IO/include/ESMCI_IO_GDAL.h | 40 +- .../IO/src/ESMCI_GDAL_Handler.C | 912 +++++++++--------- src/Infrastructure/IO/src/ESMCI_IO_GDAL.C | 360 ++++++- src/Infrastructure/IO/src/makefile | 6 +- .../IO/tests/ESMF_IO_GDALUTest.F90 | 88 +- src/Infrastructure/IO/tests/makefile | 10 +- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 5 +- 9 files changed, 892 insertions(+), 537 deletions(-) diff --git a/settings.sh b/settings.sh index 6e8a70475d..1a1d3ba1e3 100755 --- a/settings.sh +++ b/settings.sh @@ -6,9 +6,11 @@ export ESMF_NETCDF=nc-config export ESMF_NETCDF_INCLUDE=/usr/lib64/gfortran/modules export ESMF_NETCDFF_INCLUDE=/usr/lib64/gfortran/modules export ESMF_GDAL=true -export ESMF_GDAL_INCLUDE=/usr/include/gdal +#export ESMF_GDAL_INCLUDE=/usr/include/gdal +export ESMF_GDAL_INCLUDE=/home/ilcentro/tools/gdal/include #export ESMF_SHAPEFILE_INCLUDE=/usr/include -export ESMF_GDAL_LIBPATH=/usr/lib64 +#export ESMF_GDAL_LIBPATH=/usr/lib64 +export ESMF_GDAL_LIBPATH=/home/ilcentro/tools/gdal/lib64 #export ESMF_SHAPEFILE_LIBS=-lshp export ESMF_GDAL_LIBS=-lgdal export ESMF_BOPT=g diff --git a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h index bfff4bc27c..9788cbac3d 100644 --- a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h @@ -68,7 +68,7 @@ namespace ESMCI { // global information static std::vector activeGdalInstances; int gdalSystemDesc; // Descriptor for initialized GDAL inst. - int *gdalFileDesc; // Descriptor(s) for open GDAL file (typically just one, but multiple for I/O of multi-tile arrays) + OGRDataSourceH *gdalFileDesc; // Descriptor(s) for open GDAL file (typically just one, but multiple for I/O of multi-tile arrays) MPI_Comm communicator; int my_rank; int num_iotasks; diff --git a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h index 44274c2d69..9f77c4ba17 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h @@ -132,24 +132,38 @@ enum GDAL_REARRANGERS // These also establish defaults to match F90 optional args. TODO ? // friend function to allocate and initialize io from heap - IO_GDAL *ESMCI_IO_GDALCreate(const std::string& name=0, - ESMC_Base* base=0, int* rc=0); + IO_GDAL *ESMCI_IO_GDALCreate(const std::string& name=0, + ESMC_Base* base=0, int* rc=0); - // friend function to copy an io_netcdf TODO ? - //IO_GDAL *ESMCI_IO_GDALCreate(IO_GDAL *io_netcdf, int *rc=0); + // friend function to copy an io_netcdf TODO ? + //IO_GDAL *ESMCI_IO_GDALCreate(IO_GDAL *io_netcdf, int *rc=0); - // friend function to de-allocate clock - int ESMCI_IO_GDALDestroy(IO_GDAL **io_netcdf); + // friend function to de-allocate clock + int ESMCI_IO_GDALDestroy(IO_GDAL **io_netcdf); - // friend to restore state TODO ? - //Clock *ESMCI_IO_GDALReadRestart(const std::string& name=0, - //int* rc=0); + // friend to restore state TODO ? + //Clock *ESMCI_IO_GDALReadRestart(const std::string& name=0, + //int* rc=0); - int GDALc_finalize(int instance); - int GDALc_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp); + int GDALc_finalize(int instance); + int GDALc_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp); - int GDALc_inq_varid(int ncid, const char *name, int *varidp); - int GDALc_inq_vardimid(int ncid, int varid, int *dimidsp); + int GDALc_inq_fieldid(OGRDataSourceH hDS, const char *name, int *varidp); + int GDALc_inq_field(int ncid, int varid, char *name, int *xtypep, int *ndimsp, int *dimidsp, + int *nattsp); + int GDALc_inq_vardimid(int ncid, int varid, int *dimidsp); + + int GDALc_deletefile(int iosysid, const char *filename); + int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char *fname, bool mode); + int GDALc_create(int iosysid, const char *path, int cmode, int *ncidp); + int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *fname, bool mode); + int GDALc_open(int iosysid, const char *path, int mode, int *ncidp); + int GDALc_closefile(int ncid); + + int GDALc_inq_timeid(OGRDataSourceH hDS, int *timeid); // Is there a field of type OFTDate, OFTTime, or OFTDateTime? + + // Read distributed array. + int GDALc_read_darray(OGRDataSourceH hDS, int fieldid, int ioid, MPI_Offset arraylen, void *array); } // namespace ESMCI diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index f13d68b1ad..ad8e85d00d 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -356,7 +356,7 @@ void GDAL_Handler::finalize ( // Now, close any open GDAL instances while(!GDAL_Handler::activeGdalInstances.empty()) { int instance = GDAL_Handler::activeGdalInstances.back(); - gdalrc = GDALc_finalize(instance); +// gdalrc = GDALc_finalize(instance); // Even if we have an error but log and keep going to try and shut // down other GDAL instances CHECKGDALWARN(gdalrc, "Error shutting down GDAL instance", @@ -461,9 +461,9 @@ GDAL_Handler::GDAL_Handler( // fill in the GDAL_Handler object gdalSystemDesc = 0; - gdalFileDesc = new int[ntilesArg]; + gdalFileDesc = new OGRDataSourceH[ntilesArg]; for (int i = 0; i < ntilesArg; ++i) { - gdalFileDesc[i] = 0; + gdalFileDesc[i] = NULL; } localrc = ESMF_SUCCESS; new_file = new bool[ntilesArg]; @@ -557,21 +557,21 @@ void GDAL_Handler::arrayReadOneTileFile( //EOPI //----------------------------------------------------------------------------- int localrc = ESMF_RC_NOT_IMPL; // local return code - int gdalrc; // GDAL error value + int gdalrc; // GDAL error value int * ioDims; // Array IO shape int nioDims; // Array IO rank int * arrDims; // Array shape int narrDims; // Array rank int iodesc; // GDAL IO descriptor - int filedesc; // GDAL file descriptor - int vardesc; // GDAL variable descriptor - int basegdaltype; // GDAL version of Array data type + OGRDataSourceH filedesc; // GDAL file descriptor + int fielddesc; // GDAL field descriptor + int basegdaltype; // GDAL version of Array data type void *baseAddress; // The address of the Array IO data int localDE; // DE to use for IO - int nVar; // Number of variables in file + int nField; // Number of field in file int nAtt; // Number of attributes in file int unlim; // Unlimited dimension ID - std::string varname; // Default variable name + std::string fieldname; // Default field name if (rc != NULL) { *rc = ESMF_RC_NOT_IMPL; // final return code @@ -582,11 +582,18 @@ void GDAL_Handler::arrayReadOneTileFile( // File open? // Array compatible with this object? -// localrc = checkArray(arr_p); -// if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) -// return; + localrc = checkArray(arr_p); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + + filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based -// filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + if (filedesc == NULL) { + PRINTMSG("DataSource is NULL X"); +// return; + } else{ + PRINTMSG("DataSource is GOOD X"); + } // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 @@ -613,25 +620,23 @@ void GDAL_Handler::arrayReadOneTileFile( if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; - // This should work if it is a NetCDF file. -// gdalrc = GDALc_inq(filedesc, &nDims, -// &nVar, &nAtt, &unlim); -// if (!CHECKGDALERROR(gdalrc, "File is not in NetCDF format", ESMF_RC_FILE_READ, (*rc))) { -// return; -// } + PRINTMSG("IODesc: iodims " << *ioDims << " nioDims " << nioDims << " arrDims " << *arrDims); if (((char *)NULL != name) && (strlen(name) > 0)) { - varname = name; + fieldname = name; } else { - varname = arr_p->getName(); + fieldname = arr_p->getName(); } -// gdalrc = GDALc_inq_varid(filedesc, varname.c_str(), &vardesc); + PRINTMSG("Field " << fieldname.c_str()); + PRINTMSG("NLayers 1: " << OGR_DS_GetLayerCount(filedesc)); + gdalrc = GDALc_inq_fieldid(filedesc, fieldname.c_str(), &fielddesc); // An error here means the variable is not in the file -// const std::string errmsg = "variable " + varname + " not found in file"; + if (gdalrc == -1) { + PRINTMSG("Field " << fieldname.c_str() << " not found in file"); // if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { -// return; -// } + return; + } //>> int frame; //>> if (((int *)NULL != timeslice) && (*timeslice > 0) && narrDims < nioDims) { @@ -639,37 +644,29 @@ void GDAL_Handler::arrayReadOneTileFile( //>> // Do not use the unlimited dim in iodesc calculation //>> // //>> int dimids[narrDims]; -// gdalrc = GDALc_inq_vardimid(filedesc, vardesc, dimids); -// // This should never happen -// const std::string errmsg = "variable " + varname + " inq_dimid failed"; -// if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { -// return; -// } +//>> gdalrc = GDALc_inq_vardimid(filedesc, vardesc, dimids); +//>> // This should never happen +//>> const std::string errmsg = "variable " + varname + " inq_dimid failed"; +//>> if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { +//>> return; +//>> } -// if(unlim == dimids[narrDims-1]){ -// narrDims = narrDims - 1; -// } -// for (int i=0; i> if(unlim == dimids[narrDims-1]){ +//>> narrDims = narrDims - 1; +//>> } +//>> for (int i=0; i> // Note that arrDims[i] will be 0 if this DE doesn't own the current tile +//>> arrlen *= arrDims[i]; +//>> } + +// TBD! THIS REQUIRES SOME DISCUSSION: HOW TO DEAL WITH FILES W/O DATE/TIME DEFS? + int dimid_time; + MPI_Offset time_len; + gdalrc = GDALc_inq_timeid(filedesc, &dimid_time); +//>> if (!CHECKGDALERROR(gdalrc, "No time dimension found in file", ESMF_RC_FILE_READ, (*rc))) { +//>> return; +//>> } -// int dimid_time; -// MPI_Offset time_len; -// gdalrc = GDALc_inq_dimid(filedesc, "time", &dimid_time); -// if (!CHECKGDALERROR(gdalrc, "No time dimension found in file", ESMF_RC_FILE_READ, (*rc))) { -// return; -// } -// // Check to see if time is the unlimited dimension -// if (dimid_time != unlim) { -// PRINTMSG(" Time dimension = " << dimid_time << -// ", unlimited dim = " << unlim); -// if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, -// " time is not the file's unlimited dimension", -// ESMC_CONTEXT, rc)) { -// return; -// } -// } // Check to make sure the requested record is in the file // gdalrc = GDALc_inq_dimlen(filedesc, // dimid_time, &time_len); @@ -700,11 +697,13 @@ void GDAL_Handler::arrayReadOneTileFile( // PRINTMSG("calling setframe for read_darray, frame = " << frame); // GDALc_setframe(filedesc, vardesc, frame-1); // } - - PRINTMSG("calling read_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); + PRINTPOS; + PRINTMSG("calling read_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); // Read in the array -// gdalrc = GDALc_read_darray(filedesc, vardesc, iodesc, -// arrlen, (void *)baseAddress); + + gdalrc = GDALc_read_darray(filedesc, fielddesc, iodesc, + arrlen, (void *)baseAddress); + // // if (!CHECKGDALERROR(gdalrc, "Error reading array data", ESMF_RC_FILE_READ, (*rc))) { // return; @@ -1194,11 +1193,11 @@ void GDAL_Handler::openOneTileFile( // //EOPI //----------------------------------------------------------------------------- - int iotype; // GDAL I/O type - int mode; // GDAL file open mode + int iotype=0; // GDAL I/O type + bool mode; // GDAL file open mode: write|nowrite // initialize return code; assume routine not implemented int localrc = ESMF_RC_NOT_IMPL; // local return code - int gdalrc; // GDAL error value + int gdalrc; // GDAL error value VM *vm = VM::getCurrent(&localrc); int numtasks = vm->getPetCount(); int petspernode = vm->getSsiMaxPetCount(); @@ -1221,13 +1220,13 @@ void GDAL_Handler::openOneTileFile( gdalSystemDesc = GDAL_Handler::activeGdalInstances.back(); } -//>> // Translate the I/O format from ESMF to GDAL -//>>#if !defined(ESMF_NETCDF) && !defined (ESMF_PNETCDF) -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_LIB_NOT_PRESENT, -//>> "Library for requested I/O format is not present", ESMC_CONTEXT, rc)) -//>> return; -//>>#endif -//>> + // Translate the I/O format from ESMF to GDAL +#if !defined(ESMF_GDAL) + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_LIB_NOT_PRESENT, + "Library for requested I/O format is not present", ESMC_CONTEXT, rc)) + return; +#endif + //>> int i_loop; //>> for (i_loop=0; i_loop> if (getFormat() == iofmt_map[i_loop].esmf_iofmt) { @@ -1240,99 +1239,87 @@ void GDAL_Handler::openOneTileFile( //>> "unsupported/unknown I/O format", ESMC_CONTEXT, rc)) //>> return; //>> } -//>> -//>> // Check to see if we are able to open file properly -//>> bool okToCreate = false; -//>> int clobberMode = GDAL_NOCLOBBER; -//>> if (readonly) { -//>> mode = GDAL_NOWRITE; -//>> } else { -//>> mode = GDAL_WRITE; -//>> } -//>> // Figure out if we need to call createfile or openfile -//>> new_file[tile-1] = false; -//>> const std::string thisFilename = getFilename(tile, &localrc); -//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) -//>> return; -//>> bool file_exists = IO_Handler::fileExists(thisFilename, !readonly); -//>> switch(getFileStatusFlag()) { -//>> case ESMC_FILESTATUS_UNKNOWN: -//>> if (file_exists) { -//>> // Treat like OLD -//>> okToCreate = false; -//>> } else { -//>> // Treat like NEW -//>> okToCreate = true; -//>> clobberMode = GDAL_NOCLOBBER; -//>> } -//>> break; -//>> case ESMC_FILESTATUS_OLD: -//>> okToCreate = false; -//>> break; -//>> case ESMC_FILESTATUS_NEW: -//>> okToCreate = true; -//>> clobberMode = GDAL_NOCLOBBER; -//>> break; -//>> case ESMC_FILESTATUS_REPLACE: -//>> okToCreate = true; -//>> clobberMode = GDAL_CLOBBER; -//>> break; -//>> default: -//>> localrc = ESMF_RC_ARG_BAD; -//>> if (ESMC_LogDefault.MsgFoundError(localrc, "unknown file status argument", ESMC_CONTEXT, rc)) -//>> return; -//>> } -//>> -//>> if (okToCreate) { -//>>#ifdef ESMFIO_DEBUG -//>> std::string errmsg = "Calling GDALc_createfile"; -//>> ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_INFO, ESMC_CONTEXT); -//>>#endif // ESMFIO_DEBUG -//>> // Looks like we are ready to try and create the file -//>> mode |= clobberMode; -//>> switch (getFormat()){ -//>> case ESMF_IOFMT_NETCDF_64BIT_OFFSET: -//>> { -//>> mode |= GDAL_64BIT_OFFSET; -//>> break; -//>> } -//>> case ESMF_IOFMT_NETCDF_64BIT_DATA: -//>> { -//>> mode |= GDAL_64BIT_DATA; -//>> break; -//>> } -//>> } -//>> ESMCI_IOREGION_ENTER("GDALc_createfile"); -//>> -//>> gdalrc = GDALc_createfile(gdalSystemDesc, &(gdalFileDesc[tile-1]), -//>> &iotype, thisFilename.c_str(), mode); -//>> ESMCI_IOREGION_EXIT("GDALc_createfile"); -//>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to create file: ") + thisFilename, -//>> ESMF_RC_FILE_OPEN, (*rc))) { -//>> return; -//>> } else { -//>> new_file[tile-1] = true; -//>> PRINTMSG("call to GDALc_createfile: success for " << thisFilename << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "<> } + + // Check to see if we are able to open file properly + bool okToCreate = false; + bool clobberMode = false; + if (readonly) { + mode = false; + } else { + mode = true; + } + // Figure out if we need to call createfile or openfile + new_file[tile-1] = false; + const std::string thisFilename = getFilename(tile, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + bool file_exists = IO_Handler::fileExists(thisFilename, !readonly); + switch(getFileStatusFlag()) { + case ESMC_FILESTATUS_UNKNOWN: + if (file_exists) { + // Treat like OLD + okToCreate = false; + } else { + // Treat like NEW + okToCreate = true; + clobberMode = false; + } + break; + case ESMC_FILESTATUS_OLD: + okToCreate = false; + break; + case ESMC_FILESTATUS_NEW: + okToCreate = true; + clobberMode = false; + break; + case ESMC_FILESTATUS_REPLACE: + okToCreate = true; + clobberMode = true; + break; + default: + localrc = ESMF_RC_ARG_BAD; + if (ESMC_LogDefault.MsgFoundError(localrc, "unknown file status argument", ESMC_CONTEXT, rc)) + return; + } + + if (okToCreate) { +#ifdef ESMFIO_DEBUG + std::string errmsg = "Calling GDALc_createfile"; + ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_INFO, ESMC_CONTEXT); +#endif // ESMFIO_DEBUG + // Looks like we are ready to try and create the file + ESMCI_IOREGION_ENTER("GDALc_createfile"); + + gdalrc = GDALc_createfile(gdalSystemDesc, &(gdalFileDesc[tile-1]), + &iotype, thisFilename.c_str(), mode); + ESMCI_IOREGION_EXIT("GDALc_createfile"); + if (!CHECKGDALWARN(gdalrc, std::string("Unable to create file: ") + thisFilename, + ESMF_RC_FILE_OPEN, (*rc))) { + return; + } else { + new_file[tile-1] = true; + PRINTMSG("call to GDALc_createfile: success for " << thisFilename << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "<> gdalrc = GDALc_set_fill(gdalFileDesc[tile-1], GDAL_NOFILL, NULL); //>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to set fill on file: ") + thisFilename, //>> ESMF_RC_FILE_OPEN, (*rc))) { //>> return; //>> } -//>> } else { -//>> PRINTMSG(" calling GDALc_openfile with mode = " << mode << -//>> ", file = \"" << thisFilename << "\""); -//>> // Looks like we are ready to go -//>> ESMCI_IOREGION_ENTER("GDALc_openfile"); -//>> gdalrc = GDALc_openfile(gdalSystemDesc, &(gdalFileDesc[tile-1]), -//>> &iotype, thisFilename.c_str(), mode); -//>> ESMCI_IOREGION_EXIT("GDALc_openfile"); -//>> PRINTMSG(", called GDALc_openfile on " << thisFilename); -//>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to open existing file: ") + thisFilename, -//>> ESMF_RC_FILE_OPEN, (*rc))) { -//>> return; -//>> } -//>> } + } else { + PRINTMSG(" calling GDALc_openfile with mode = " << mode << + ", file = \"" << thisFilename << "\""); + // Looks like we are ready to go + ESMCI_IOREGION_ENTER("GDALc_openfile"); + gdalrc = GDALc_openfile(gdalSystemDesc, (&gdalFileDesc[tile-1]), + &iotype, thisFilename.c_str(), mode); + ESMCI_IOREGION_EXIT("GDALc_openfile"); + PRINTMSG("NLayers 0: " << OGR_DS_GetLayerCount(gdalFileDesc[tile-1])); + PRINTMSG(", called GDALc_openfile on " << thisFilename); + if (!CHECKGDALWARN(gdalrc, std::string("Unable to open existing file: ") + thisFilename, + ESMF_RC_FILE_OPEN, (*rc))) { + return; + } + } // return successfully if (rc != NULL) { @@ -1368,7 +1355,7 @@ void GDAL_Handler::attPackPut ( //----------------------------------------------------------------------------- int localrc; int gdalrc; - int filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + OGRDataSourceH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based //>> const json &j = attPack->getStorageRef(); //>> for (json::const_iterator it=j.cbegin(); it!=j.cend(); it++) { @@ -1470,7 +1457,7 @@ ESMC_Logical GDAL_Handler::isOpen( // // !ARGUMENTS: // - int tile // (in) - tile number for which we check if a file is open (relevant for + int tile // (in) - tile number for which we check if a file is open (relevant for // multi-tile arrays with IO to a separate file for each array) (1-based indexing) ) { // @@ -1480,22 +1467,22 @@ ESMC_Logical GDAL_Handler::isOpen( // //EOPI //----------------------------------------------------------------------------- -//>> PRINTPOS; -//>> int filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based -//>> if (filedesc == 0) { -//>> PRINTMSG("gdalFileDesc is NULL"); -//>> return ESMF_FALSE; -//>> } else if (GDALc_File_is_Open(filedesc) != 0) { -//>> PRINTMSG("File is open"); -//>> return ESMF_TRUE; -//>> } else { -//>> // This really should not happen, warn and clean up just in case -//>> std::string errmsg; -//>> const std::string thisFilename = getFilename(tile); -//>> errmsg = std::string ("File, ") + thisFilename + ", closed by GDAL"; -//>> ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, ESMC_CONTEXT); -//>> return ESMF_FALSE; -//>> } + PRINTPOS; + OGRDataSourceH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + if (filedesc == NULL) { + PRINTMSG("gdalFileDesc is NULL"); + return ESMF_FALSE; + } else if (filedesc != NULL) { + PRINTMSG("File is open"); + return ESMF_TRUE; + } else { + // This really should not happen, warn and clean up just in case + std::string errmsg; + const std::string thisFilename = getFilename(tile); + errmsg = std::string ("File, ") + thisFilename + ", closed by GDAL"; + ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, ESMC_CONTEXT); + return ESMF_FALSE; + } } // GDAL_Handler::isOpen() //----------------------------------------------------------------------------- @@ -1525,24 +1512,32 @@ void GDAL_Handler::flushOneTileFile( //EOPI //----------------------------------------------------------------------------- + int gdalrc; + // initialize return code; assume routine not implemented int localrc = ESMF_RC_NOT_IMPL; // local return code if (rc != NULL) { *rc = ESMF_RC_NOT_IMPL; // final return code } -//>> PRINTPOS; -//>> // Not open? No problem, just skip -//>> if (isOpen(tile) == ESMF_TRUE) { -//>> PRINTMSG("calling sync"); + PRINTPOS; + // Not open? No problem, just skip + if (isOpen(tile) == ESMF_TRUE) { + PRINTMSG("calling sync"); //>> ESMCI_IOREGION_ENTER("GDALc_sync"); + if (gdalFileDesc[tile-1] != NULL) { +// OGR_DS_Destroy(gdalFileDesc[tile-1]); + printf("Closing tile %d, hDS %p\n", tile, (void *)gdalFileDesc[tile-1]); + gdalrc = GDALClose(gdalFileDesc[tile-1]); + printf("Close code: %d, tile %d\n",gdalrc, tile); + } //>> GDALc_sync(gdalFileDesc[tile-1]); //>> ESMCI_IOREGION_EXIT("GDALc_sync"); -//>> } -//>> // return successfully -//>> if (rc != NULL) { -//>> *rc = ESMF_SUCCESS; -//>> } + } + // return successfully + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } } // GDAL_Handler::flushOneTileFile() //----------------------------------------------------------------------------- @@ -1620,7 +1615,7 @@ void GDAL_Handler::closeOneTileFile( int *nioDims, // (out) - Rank of Array IO int ** arrDims, // (out) - Array shape for IO int *narrDims, // (out) - Rank of Array IO - int *basegdaltype, // (out) - Data type for IO + int *basegdaltype, // (out) - Data type for IO int *rc // (out) - Error return code ) { // @@ -1631,51 +1626,51 @@ void GDAL_Handler::closeOneTileFile( //----------------------------------------------------------------------------- int new_io_desc = (int)NULL; -//>> // initialize return code; assume routine not implemented + // initialize return code; assume routine not implemented int localrc = ESMF_RC_NOT_IMPL; // local return code -//>> if (rc != NULL) { -//>> *rc = ESMF_RC_NOT_IMPL; // final return code -//>> } -//>> -//>> PRINTPOS; + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; new_io_desc = GDAL_IODescHandler::getIODesc(iosys, arr_p, tile, &localrc); -//>> if ((int)NULL == new_io_desc) { -//>> PRINTMSG("calling constructGdalDecomp"); -//>> localrc = GDAL_IODescHandler::constructGdalDecomp(iosys, -//>> arr_p, tile, &new_io_desc); -//>> PRINTMSG("constructGdalDecomp call complete" << ", localrc = " << localrc); -//>> } -//>> if ((ioDims != (int **)NULL) || (nioDims != (int *)NULL) || -//>> (arrDims != (int **)NULL) || (narrDims != (int *)NULL)) { -//>> int niodimArg; -//>> int *iodimsArg; -//>> int narrdimArg; -//>> int *arrdimsArg; -//>> -//>> localrc = GDAL_IODescHandler::getDims(new_io_desc, &niodimArg, &iodimsArg, -//>> &narrdimArg, &arrdimsArg); -//>> if (!ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, -//>> ESMC_CONTEXT, rc)) { -//>> if (ioDims != (int **)NULL) { -//>> *ioDims = iodimsArg; -//>> } -//>> if (nioDims != (int *)NULL) { -//>> *nioDims = niodimArg; -//>> } -//>> if (arrDims != (int **)NULL) { -//>> *arrDims = arrdimsArg; -//>> } -//>> if (narrDims != (int *)NULL) { -//>> *narrDims = narrdimArg; -//>> } -//>> } -//>> } -//>> PRINTMSG("getDims complete, calling getIOType"); -//>> if (basegdaltype != (int *)NULL) { -//>> *basegdaltype = GDAL_IODescHandler::getIOType(new_io_desc, &localrc); -//>> ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, -//>> rc); -//>> } + if ((int)NULL == new_io_desc) { + PRINTMSG("calling constructGdalDecomp"); + localrc = GDAL_IODescHandler::constructGdalDecomp(iosys, + arr_p, tile, &new_io_desc); + PRINTMSG("constructGdalDecomp call complete" << ", localrc = " << localrc); + } + if ((ioDims != (int **)NULL) || (nioDims != (int *)NULL) || + (arrDims != (int **)NULL) || (narrDims != (int *)NULL)) { + int niodimArg; + int *iodimsArg; + int narrdimArg; + int *arrdimsArg; + + localrc = GDAL_IODescHandler::getDims(new_io_desc, &niodimArg, &iodimsArg, + &narrdimArg, &arrdimsArg); + if (!ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) { + if (ioDims != (int **)NULL) { + *ioDims = iodimsArg; + } + if (nioDims != (int *)NULL) { + *nioDims = niodimArg; + } + if (arrDims != (int **)NULL) { + *arrDims = arrdimsArg; + } + if (narrDims != (int *)NULL) { + *narrDims = narrdimArg; + } + } + } + PRINTMSG("getDims complete, calling getIOType"); + if (basegdaltype != (int *)NULL) { + *basegdaltype = GDAL_IODescHandler::getIOType(new_io_desc, &localrc); + ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + rc); + } if (rc != NULL) { *rc = localrc; } @@ -1699,7 +1694,7 @@ bool GDAL_Handler::CheckGDALError( // // !ARGUMENTS: // - int gdalRetCode, // (in) - Return code to check + int gdalRetCode, // (in) - Return code to check int line, // (in) - Line containing error const char * const file, // (in) - File containing error const char * const method, // (in) - ESMC_METHOD @@ -1777,7 +1772,7 @@ bool GDAL_Handler::CheckGDALError( //>> line, file, method, rc); //>> } //>> -//>> return (gdalRetCode == GDAL_NOERR); + return (gdalRetCode == PIO_NOERR); } // GDAL_Handler::CheckGDALError() //----------------------------------------------------------------------------- @@ -1893,209 +1888,209 @@ int GDAL_IODescHandler::constructGdalDecomp( DistGrid *distGrid; // The Array's associated DistGrid GDAL_IODescHandler *handle; // New handler object for this IO desc. -//>> PRINTPOS; -//>> // check the inputs -//>> if ((Array *)NULL == arr_p) { -//>> ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, "- arr_p cannot be NULL", -//>> ESMC_CONTEXT, &localrc); -//>> return ESMF_RC_ARG_BAD; -//>> } -//>> if (tile < 1) { -//>> ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "- tile must be >= 1", -//>> ESMC_CONTEXT, &localrc); -//>> return localrc; -//>> } -//>> if ((int *)NULL == newDecomp_p) { -//>> ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, -//>> "- newDecomp_p cannot be NULL", ESMC_CONTEXT, &localrc); -//>> return ESMF_RC_ARG_BAD; -//>> } -//>> -//>> handle = new GDAL_IODescHandler(iosys, arr_p); -//>> gdalDofList = (MPI_Offset *)NULL; -//>> -//>> localDeCount = arr_p->getDELayout()->getLocalDeCount(); -//>> PRINTMSG("localDeCount = " << localDeCount); -//>> //TODO: Remove this restriction (possibly with multiple IO descriptors) -//>> if (localDeCount > 1) { -//>> ESMC_LogDefault.Write("I/O does not support multiple DEs per PET", -//>> ESMC_LOGMSG_WARN, ESMC_CONTEXT); -//>> return ESMF_RC_NOT_IMPL; -//>> } -//>> -//>> // TODO: To support multiple DEs per PE, we would need to extend this to be an array -//>> bool thisDeIsThisTile = false; -//>> -//>> // We need the total number of elements -//>> gdalDofCount = 0; -//>> int const *localDeToDeMap = arr_p->getDistGrid()->getDELayout()->getLocalDeToDeMap(); -//>> // NB: This loop is redundant for now, I wish I could lift the restriction. -//>> for (localDe = 0; localDe < localDeCount; ++localDe) { -//>> // consider the fact that replicated dimensions may lead to local elements in the -//>> // Array, that are not accounted for by actual exclusive elements in the DistGrid -//>> int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDe, &rc); -//>> if (ESMC_LogDefault.MsgFoundError(rc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) -//>> return localrc; -//>> if (tileOfThisDe == tile) { -//>> // TODO: As noted above, to support multiple DEs per PE, we would need to extend this to be an array -//>> thisDeIsThisTile = true; -//>> } -//>> if (thisDeIsThisTile && arr_p->getDistGrid()->getElementCountPDe()[localDeToDeMap[localDe]]>0) -//>> gdalDofCount += arr_p->getTotalElementCountPLocalDe()[localDe]; -//>> } -//>> -//>> PRINTMSG("gdalDofCount = " << gdalDofCount); -//>> try { -//>> // Allocate space for the DOF list -//>> gdalDofList = new MPI_Offset[gdalDofCount]; -//>> -//>> } catch(...) { -//>> if ((MPI_Offset *)NULL != gdalDofList) { -//>> // Free the DofList! -//>> delete[] gdalDofList; -//>> gdalDofList = (MPI_Offset *)NULL; -//>> } -//>> ESMC_LogDefault.AllocError(ESMC_CONTEXT, &localrc); -//>> return localrc; -//>> } -//>> // Fill in the GDAL DOF list (local to global map) -//>> // TODO: This is where we would need to make some magic to include multiple DEs. -//>> // TODO: (Particular care may be needed in the multi-tile case, where some DEs on the -//>> // TODO: current PE may be part of the current tile, while others are not. -//>> // TODO: For now, with one DE, we can assume that, if gdalDofCount>0, then this DE -//>> // TODO: corresponds to the current tile.) -//>> localDe = 0; -//>> if (gdalDofCount>0){ -//>> // construct the mapping of the local elements -//>> localrc = arr_p->constructFileMap((int64_t *) gdalDofList, gdalDofCount, localDe); -//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, -//>> &localrc)) { -//>> delete[] gdalDofList; -//>> gdalDofList = (MPI_Offset *)NULL; -//>> return localrc; -//>> } -//>> } -//>> -//>>#if 0 -//>> std::cout << " gdalDofList = ["; -//>> for (int i = 0; i < gdalDofCount; i++) { -//>> std::cout << " " << gdalDofList[i] -//>> << ((i == (gdalDofCount - 1)) ? ' ' : ','); -//>> } -//>> std::cout << "]" << std::endl; -//>>#endif // 0 -//>> // Get TKR info -//>> switch(arr_p->getTypekind()) { -//>> case ESMC_TYPEKIND_I4: -//>> handle->basegdaltype = GDAL_INT; -//>> break; -//>> case ESMC_TYPEKIND_R4: -//>> handle->basegdaltype = GDAL_REAL; -//>> break; -//>> case ESMC_TYPEKIND_R8: -//>> handle->basegdaltype = GDAL_DOUBLE; -//>> break; -//>> case ESMC_TYPEKIND_I1: -//>> case ESMC_TYPEKIND_I2: -//>> case ESMC_TYPEKIND_I8: -//>> case ESMC_TYPEKIND_CHARACTER: -//>> case ESMF_C8: -//>> case ESMF_C16: -//>> case ESMC_TYPEKIND_LOGICAL: -//>> default: -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "Unsupported typekind", ESMC_CONTEXT, -//>> &localrc)) { -//>> delete[] gdalDofList; -//>> gdalDofList = (MPI_Offset *)NULL; -//>> return localrc; -//>> } -//>> } -//>> -//>> distGrid = arr_p->getDistGrid(); -//>> const int *minIndexPDimPTile = distGrid->getMinIndexPDimPTile(); -//>> const int *maxIndexPDimPTile = distGrid->getMaxIndexPDimPTile(); -//>> -//>> handle->tile = tile; -//>>// NB: Is this part of the restrictions on Array I/O? -//>>// nDims = arr_p->getRank(); -//>> handle->nDims = distGrid->getDimCount(); -//>> // Make sure dims is not used -//>> if (handle->dims != (int *)NULL) { -//>> delete handle->dims; -//>> handle->dims = (int *)NULL; -//>> } -//>> handle->dims = new int[handle->nDims]; -//>> // Step through the distGrid dimensions, getting the size of the dimension. (This is the -//>> // size of the full array across all PEs.) -//>> for (int i = 0; i < handle->nDims; i++) { -//>> handle->dims[i] = (maxIndexPDimPTile[((tile - 1) * handle->nDims) + i] - -//>> minIndexPDimPTile[((tile - 1) * handle->nDims) + i] + 1); -//>> } -//>> -//>> handle->arrayRank = arr_p->getRank(); -//>> if (handle->arrayShape != (int *)NULL) { -//>> delete handle->arrayShape; -//>> handle->arrayShape = (int *)NULL; -//>> } -//>> handle->arrayShape = new int[handle->arrayRank]; -//>> // Get the size of each dimension owned locally. -//>> if (thisDeIsThisTile) { -//>> const int *totalLBound = arr_p->getTotalLBound(); -//>> const int *totalUBound = arr_p->getTotalUBound(); -//>> for (int i = 0; i < handle->arrayRank; ++i) { -//>> // TODO: This is another place that would need to be generalized to handle more than -//>> // one DE per PE: totalLBound and totalUBound are dimensioned -//>> // [redDimCount*ssiLocalDeCount], so the below expression (which doesn't include the -//>> // current DE count) would need to be adjusted to handle multiple DEs. -//>> handle->arrayShape[i] = (totalUBound[i] - totalLBound[i] + 1); -//>> } -//>> } else { -//>> // This DE is for some other tile, so as far as this tile is concerned, we own 0 elements -//>> for (int i = 0; i < handle->arrayRank; ++i) { -//>> handle->arrayShape[i] = 0; -//>> } -//>> } -//>> -//>>#ifdef ESMFIO_DEBUG -//>> { -//>> char shapestr[64]; -//>> for (int i = 0; i < handle->arrayRank; i++) { -//>> sprintf((shapestr + (5 * i)), " %03d%c", handle->arrayShape[i], -//>> (((handle->arrayRank - 1) == i) ? ' ' : ',')); -//>> } -//>> PRINTMSG(", IODesc shape = [" << shapestr << "], calling gdal_initdecomp"); -//>> -//>> char dimstr[64]; -//>> for (int i = 0; i < handle->nDims; i++) { -//>> sprintf((dimstr + (5 * i)), " %03d%c", handle->dims[i], -//>> (((handle->nDims - 1) == i) ? ' ' : ',')); -//>> } -//>> PRINTMSG(", IODesc dims = [" << dimstr << "]"); -//>> } -//>>#endif // ESMFIO_DEBUG -//>> int ddims[handle->nDims]; -//>> for(int i=0; inDims; i++) -//>> ddims[i] = handle->dims[handle->nDims - i - 1]; -//>> // Create the decomposition -//>> ESMCI_IOREGION_ENTER("GDALc_InitDecomp"); -//>> GDALc_InitDecomp(iosys, handle->basegdaltype, handle->nDims, -//>> ddims, gdalDofCount, gdalDofList, -//>> &(handle->io_descriptor), NULL, NULL, NULL); -//>> ESMCI_IOREGION_EXIT("GDALc_InitDecomp"); -//>> -//>> PRINTMSG("after call to GDALc_initdecomp_dof"); -//>> -//>> // Add the handle into the master list -//>> GDAL_IODescHandler::activeGdalIoDescriptors.push_back(handle); -//>> // Finally, set the output handle -//>> *newDecomp_p = handle->io_descriptor; -//>> -//>> // Free the DofList! -//>> delete[] gdalDofList; -//>> gdalDofList = (MPI_Offset *)NULL; -//>> -//>> // return successfully -//>> return ESMF_SUCCESS; + PRINTPOS; + // check the inputs + if ((Array *)NULL == arr_p) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, "- arr_p cannot be NULL", + ESMC_CONTEXT, &localrc); + return ESMF_RC_ARG_BAD; + } + if (tile < 1) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "- tile must be >= 1", + ESMC_CONTEXT, &localrc); + return localrc; + } + if ((int *)NULL == newDecomp_p) { + ESMC_LogDefault.MsgFoundError(ESMF_RC_PTR_NULL, + "- newDecomp_p cannot be NULL", ESMC_CONTEXT, &localrc); + return ESMF_RC_ARG_BAD; + } + + handle = new GDAL_IODescHandler(iosys, arr_p); + gdalDofList = (MPI_Offset *)NULL; + + localDeCount = arr_p->getDELayout()->getLocalDeCount(); + PRINTMSG("localDeCount = " << localDeCount); + //TODO: Remove this restriction (possibly with multiple IO descriptors) + if (localDeCount > 1) { + ESMC_LogDefault.Write("I/O does not support multiple DEs per PET", + ESMC_LOGMSG_WARN, ESMC_CONTEXT); + return ESMF_RC_NOT_IMPL; + } + + // TODO: To support multiple DEs per PE, we would need to extend this to be an array + bool thisDeIsThisTile = false; + + // We need the total number of elements + gdalDofCount = 0; + int const *localDeToDeMap = arr_p->getDistGrid()->getDELayout()->getLocalDeToDeMap(); + // NB: This loop is redundant for now, I wish I could lift the restriction. + for (localDe = 0; localDe < localDeCount; ++localDe) { + // consider the fact that replicated dimensions may lead to local elements in the + // Array, that are not accounted for by actual exclusive elements in the DistGrid + int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDe, &rc); + if (ESMC_LogDefault.MsgFoundError(rc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) + return localrc; + if (tileOfThisDe == tile) { + // TODO: As noted above, to support multiple DEs per PE, we would need to extend this to be an array + thisDeIsThisTile = true; + } + if (thisDeIsThisTile && arr_p->getDistGrid()->getElementCountPDe()[localDeToDeMap[localDe]]>0) + gdalDofCount += arr_p->getTotalElementCountPLocalDe()[localDe]; + } + + PRINTMSG("gdalDofCount = " << gdalDofCount); + try { + // Allocate space for the DOF list + gdalDofList = new MPI_Offset[gdalDofCount]; + + } catch(...) { + if ((MPI_Offset *)NULL != gdalDofList) { + // Free the DofList! + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + } + ESMC_LogDefault.AllocError(ESMC_CONTEXT, &localrc); + return localrc; + } + // Fill in the GDAL DOF list (local to global map) + // TODO: This is where we would need to make some magic to include multiple DEs. + // TODO: (Particular care may be needed in the multi-tile case, where some DEs on the + // TODO: current PE may be part of the current tile, while others are not. + // TODO: For now, with one DE, we can assume that, if gdalDofCount>0, then this DE + // TODO: corresponds to the current tile.) + localDe = 0; + if (gdalDofCount>0){ + // construct the mapping of the local elements + localrc = arr_p->constructFileMap((int64_t *) gdalDofList, gdalDofCount, localDe); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &localrc)) { + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + return localrc; + } + } + +#if 0 + std::cout << " gdalDofList = ["; + for (int i = 0; i < gdalDofCount; i++) { + std::cout << " " << gdalDofList[i] + << ((i == (gdalDofCount - 1)) ? ' ' : ','); + } + std::cout << "]" << std::endl; +#endif // 0 + // Get TKR info + switch(arr_p->getTypekind()) { + case ESMC_TYPEKIND_I4: + handle->basegdaltype = OFTInteger; + break; + case ESMC_TYPEKIND_R4: +// handle->basegdaltype = OFTReal; +// break; + case ESMC_TYPEKIND_R8: + handle->basegdaltype = OFTReal; + break; + case ESMC_TYPEKIND_I1: + case ESMC_TYPEKIND_I2: + case ESMC_TYPEKIND_I8: + case ESMC_TYPEKIND_CHARACTER: + case ESMF_C8: + case ESMF_C16: + case ESMC_TYPEKIND_LOGICAL: + default: + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, "Unsupported typekind", ESMC_CONTEXT, + &localrc)) { + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + return localrc; + } + } + + distGrid = arr_p->getDistGrid(); + const int *minIndexPDimPTile = distGrid->getMinIndexPDimPTile(); + const int *maxIndexPDimPTile = distGrid->getMaxIndexPDimPTile(); + + handle->tile = tile; +// NB: Is this part of the restrictions on Array I/O? +// nDims = arr_p->getRank(); + handle->nDims = distGrid->getDimCount(); + // Make sure dims is not used + if (handle->dims != (int *)NULL) { + delete handle->dims; + handle->dims = (int *)NULL; + } + handle->dims = new int[handle->nDims]; + // Step through the distGrid dimensions, getting the size of the dimension. (This is the + // size of the full array across all PEs.) + for (int i = 0; i < handle->nDims; i++) { + handle->dims[i] = (maxIndexPDimPTile[((tile - 1) * handle->nDims) + i] - + minIndexPDimPTile[((tile - 1) * handle->nDims) + i] + 1); + } + + handle->arrayRank = arr_p->getRank(); + if (handle->arrayShape != (int *)NULL) { + delete handle->arrayShape; + handle->arrayShape = (int *)NULL; + } + handle->arrayShape = new int[handle->arrayRank]; + // Get the size of each dimension owned locally. + if (thisDeIsThisTile) { + const int *totalLBound = arr_p->getTotalLBound(); + const int *totalUBound = arr_p->getTotalUBound(); + for (int i = 0; i < handle->arrayRank; ++i) { + // TODO: This is another place that would need to be generalized to handle more than + // one DE per PE: totalLBound and totalUBound are dimensioned + // [redDimCount*ssiLocalDeCount], so the below expression (which doesn't include the + // current DE count) would need to be adjusted to handle multiple DEs. + handle->arrayShape[i] = (totalUBound[i] - totalLBound[i] + 1); + } + } else { + // This DE is for some other tile, so as far as this tile is concerned, we own 0 elements + for (int i = 0; i < handle->arrayRank; ++i) { + handle->arrayShape[i] = 0; + } + } + +#ifdef ESMFIO_DEBUG + { + char shapestr[64]; + for (int i = 0; i < handle->arrayRank; i++) { + sprintf((shapestr + (5 * i)), " %03d%c", handle->arrayShape[i], + (((handle->arrayRank - 1) == i) ? ' ' : ',')); + } + PRINTMSG(", IODesc shape = [" << shapestr << "], calling gdal_initdecomp"); + + char dimstr[64]; + for (int i = 0; i < handle->nDims; i++) { + sprintf((dimstr + (5 * i)), " %03d%c", handle->dims[i], + (((handle->nDims - 1) == i) ? ' ' : ',')); + } + PRINTMSG(", IODesc dims = [" << dimstr << "]"); + } +#endif // ESMFIO_DEBUG + int ddims[handle->nDims]; + for(int i=0; inDims; i++) + ddims[i] = handle->dims[handle->nDims - i - 1]; + // Create the decomposition + ESMCI_IOREGION_ENTER("GDALc_InitDecomp"); + PIOc_InitDecomp(iosys, handle->basegdaltype, handle->nDims, + ddims, gdalDofCount, gdalDofList, + &(handle->io_descriptor), NULL, NULL, NULL); + ESMCI_IOREGION_EXIT("GDALc_InitDecomp"); + + PRINTMSG("after call to GDALc_initdecomp_dof"); + + // Add the handle into the master list + GDAL_IODescHandler::activeGdalIoDescriptors.push_back(handle); + // Finally, set the output handle + *newDecomp_p = handle->io_descriptor; + + // Free the DofList! + delete[] gdalDofList; + gdalDofList = (MPI_Offset *)NULL; + + // return successfully + return ESMF_SUCCESS; } // GDAL_IODescHandler::constructGdalDecomp() //----------------------------------------------------------------------------- @@ -2194,31 +2189,34 @@ int GDAL_IODescHandler::getDims( //----------------------------------------------------------------------------- int localrc = ESMF_RC_NOT_FOUND; // local return code -//>> std::vector::iterator it; -//>> PRINTPOS; -//>> for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); -//>> it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); -//>> it++) { -//>> if (iodesc == (*it)->io_descriptor) { -//>> PRINTMSG("getDims: found handler, nioDims = " << (*it)->nDims << -//>> ", ioDims = " << (*it)->dims << ", narrDims = " << -//>> (*it)->arrayRank); -//>> if (nioDims != (int *)NULL) { -//>> *nioDims = (*it)->nDims; -//>> } -//>> if (ioDims != (int **)NULL) { -//>> *ioDims = (*it)->dims; -//>> } -//>> if (narrDims != (int *)NULL) { -//>> *narrDims = (*it)->arrayRank; -//>> } -//>> if (arrDims != (int **)NULL) { -//>> *arrDims = (*it)->arrayShape; -//>> } -//>> localrc = ESMF_SUCCESS; -//>> break; -//>> } -//>> } + std::vector::iterator it; + PRINTPOS; + PRINTMSG("iodesc " << iodesc ); + for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); + it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); + it++) { + + PRINTMSG("iodesc " << iodesc << ", io_desc " << (*it)->io_descriptor ); + if (iodesc == (*it)->io_descriptor) { + PRINTMSG("getDims: found handler, nioDims = " << (*it)->nDims << + ", ioDims = " << (*it)->dims << ", narrDims = " << + (*it)->arrayRank); + if (nioDims != (int *)NULL) { + *nioDims = (*it)->nDims; + } + if (ioDims != (int **)NULL) { + *ioDims = (*it)->dims; + } + if (narrDims != (int *)NULL) { + *narrDims = (*it)->arrayRank; + } + if (arrDims != (int **)NULL) { + *arrDims = (*it)->arrayShape; + } + localrc = ESMF_SUCCESS; + break; + } + } // return success or not found return localrc; diff --git a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C index 2605a5788a..393ea51132 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C @@ -37,6 +37,10 @@ #include "ESMCI_LocalArray.h" #include "ESMCI_Array.h" +#include "pio.h" + +#include "esmf_io_debug.h" + using namespace std; //------------------------------------------------------------------------- @@ -109,7 +113,361 @@ namespace ESMCI return esmcTypeVal; } - //------------------------------------------------------------------------- +int GDALc_inq_field(int ncid, int varid, char *name, int *xtypep, int *ndimsp, + int *dimidsp, int *nattsp) + { +//>> iosystem_desc_t *ios; +//>> file_desc_t *file; +//>> int ndims = 0; /* The number of dimensions for this variable. */ +//>> int ierr; +//>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//>> +//>> PLOG((1, "GDALc_inq_var ncid = %d varid = %d", ncid, varid)); +//>> +//>> /* Get the file info, based on the ncid. */ +//>> if ((ierr = pio_get_file(ncid, &file))) +//>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//>> ios = file->iosystem; +//>> +//>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//>> if (ios->async) +//>> { +//>> if (!ios->ioproc) +//>> { +//>> int msg = PIO_MSG_INQ_VAR; +//>> char name_present = name ? true : false; +//>> char xtype_present = xtypep ? true : false; +//>> char ndims_present = ndimsp ? true : false; +//>> char dimids_present = dimidsp ? true : false; +//>> char natts_present = nattsp ? true : false; +//>> +//>> if (ios->compmaster == MPI_ROOT) +//>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//>> +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&xtype_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&ndims_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&dimids_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&natts_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//>> PLOG((2, "PIOc_inq_var name_present = %d xtype_present = %d ndims_present = %d " +//>> "dimids_present = %d, natts_present = %d nattsp = %d", +//>> name_present, xtype_present, ndims_present, dimids_present, natts_present, nattsp)); +//>> } +//>> +//>> /* Handle MPI errors. */ +//>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//>> if (mpierr) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> } +//>> +//>> /* Call the netCDF layer. */ +//>> if (ios->ioproc) +//>> { +//>> PLOG((2, "Calling the netCDF layer")); +//>>#ifdef _PNETCDF +//>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//>> { +//>> ierr = ncmpi_inq_varndims(file->fh, varid, &ndims); +//>> PLOG((2, "from pnetcdf ndims = %d", ndims)); +//>> if (!ierr) +//>> ierr = ncmpi_inq_var(file->fh, varid, name, xtypep, ndimsp, dimidsp, nattsp); +//>> } +//>>#endif /* _PNETCDF */ +//>> +//>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//>> { +//>> ierr = nc_inq_varndims(file->fh, varid, &ndims); +//>> PLOG((3, "nc_inq_varndims called ndims = %d", ndims)); +//>> if (!ierr) +//>> { +//>> char my_name[NC_MAX_NAME + 1]; +//>> nc_type my_xtype; +//>> int my_ndims = 0, *my_dimids, my_natts = 0; +//>> if (ndims > 0) +//>> my_dimids = (int *) malloc(ndims * sizeof(int)); +//>> else +//>> my_dimids = NULL; +//>> ierr = nc_inq_var(file->fh, varid, my_name, &my_xtype, &my_ndims, my_dimids, +//>> &my_natts); +//>> PLOG((3, "my_name = %s my_xtype = %d my_ndims = %d my_natts = %d", my_name, +//>> my_xtype, my_ndims, my_natts)); +//>> if (!ierr) +//>> { +//>> if (name) +//>> strcpy(name, my_name); +//>> if (xtypep) +//>> *xtypep = my_xtype; +//>> if (ndimsp) +//>> *ndimsp = my_ndims; +//>> if (dimidsp) +//>> { +//>> for (int d = 0; d < ndims; d++) +//>> dimidsp[d] = my_dimids[d]; +//>> } +//>> if (my_dimids != NULL) +//>> free(my_dimids); +//>> if (nattsp) +//>> *nattsp = my_natts; +//>> } +//>> } +//>> } +//>> if (ndimsp) +//>> PLOG((2, "PIOc_inq_var ndims = %d ierr = %d", *ndimsp, ierr)); +//>> } +//>> +//>> /* Broadcast and check the return code. */ +//>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> if (ierr) +//>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//>> +//>> /* Broadcast the results for non-null pointers. */ +//>> if (name) +//>> { +//>> int slen; +//>> if (ios->iomaster == MPI_ROOT) +//>> slen = strlen(name); +//>> if ((mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> if ((mpierr = MPI_Bcast((void *)name, slen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> } +//>> if (xtypep) +//>> if ((mpierr = MPI_Bcast(xtypep, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> +//>> if (ndimsp) +//>> { +//>> PLOG((2, "PIOc_inq_var about to Bcast ndims = %d ios->ioroot = %d ios->my_comm = %d", +//>> *ndimsp, ios->ioroot, ios->my_comm)); +//>> if ((mpierr = MPI_Bcast(ndimsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> PLOG((2, "PIOc_inq_var Bcast ndims = %d", *ndimsp)); +//>> } +//>> if (dimidsp) +//>> { +//>> if ((mpierr = MPI_Bcast(&ndims, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> if ((mpierr = MPI_Bcast(dimidsp, ndims, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> } +//>> if (nattsp) +//>> if ((mpierr = MPI_Bcast(nattsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> +//>> return PIO_NOERR; + } + +int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char *filename, + bool mode) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + int ret; /* Return code from function calls. */ + +//>> /* Get the IO system info from the id. */ +//>> if (!(ios = pio_get_iosystem_from_id(iosysid))) +//>> return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); +//>> +//>> PLOG((1, "PIOc_createfile iosysid = %d iotype = %d filename = %s mode = %d", +//>> iosysid, *iotype, filename, mode)); +//>> +//>> /* Create the file. */ +//>> if ((ret = PIOc_createfile_int(iosysid, ncidp, iotype, filename, mode, 0))) +//>> return pio_err(ios, NULL, ret, __FILE__, __LINE__); +//>> +//>> /* Set the fill mode to NOFILL. */ +//>> if ((ret = PIOc_set_fill(*ncidp, NC_NOFILL, NULL))) +//>> return ret; + + return ret; +} + +int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filename, + bool mode) +{ +//>> PLOG((1, "PIOc_openfile iosysid %d *iotype %d filename %s mode %d", iosysid, +//>> iotype ? *iotype: 0, filename, mode)); + OGRRegisterAll(); + OGRDataSourceH hDx = OGROpen( filename, FALSE, NULL ); + PRINTMSG("NLayers -3: " << OGR_DS_GetLayerCount(hDx) << " file: " << filename ); + PRINTMSG("NLayers -2: " << GDALDatasetGetLayerCount(hDx)); + OGR_DS_Destroy(hDx); + *hDSp = OGROpen( filename, FALSE, NULL ); + PRINTMSG("NLayers -1: " << OGR_DS_GetLayerCount(*hDSp)); + if( hDSp == NULL ) + { + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_NOT_FOUND, "Open GDAL file failed", ESMC_CONTEXT, 0)) + return ESMF_RC_NOT_FOUND; + } +return 0; +} + +int GDALc_inq_fieldid(OGRDataSourceH hDS, const char *name, int *varidp) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int ierr; /* Return code from function calls. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ + +//>> PLOG((1, "PIOc_inq_varid ncid = %d name = %s", ncid, name)); + +#undef ESMC_METHOD +#define ESMC_METHOD "IO_GDAL::GDALc_inq_fieldid" + + if (hDS == NULL) { + PRINTMSG("DataSource is NULL"); + return -1; + } else { + PRINTMSG("DataSource is GOOD"); + printf("hDS %p\n",(void *)hDS); + } + + PRINTPOS; + PRINTMSG("NLayers: " << OGR_DS_GetLayerCount(hDS)); + OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); + PRINTPOS; + OGR_L_ResetReading(hLayer); + PRINTPOS; + if (hLayer == NULL) { + PRINTMSG("Layer is NULL"); + return -1; + } + *varidp = OGR_L_FindFieldIndex(hLayer,name,1); + + PRINTMSG("INQ_FIELDID FIELD " << name << " INDEX: " << *varidp); + + return *varidp; + +//>> /* Broadcast and check the return code. */ +//>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> if (ierr) +//>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//>> +//>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//>> if (varidp) +//>> if ((mpierr = MPI_Bcast(varidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + return PIO_NOERR; +} + + int GDALc_inq_timeid(OGRDataSourceH hDS, int *timeid) { // Is there a field of type OFTDate, OFTTime, or OFTDateTime? + + OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); + OGR_L_ResetReading(hLayer); + + OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); + int nFld = OGR_FD_GetFieldCount(hFD); + +// PRINTPOS; +// PRINTMSG("NFields: " << nFld); + + for (int i=0;iiosystem; + +// /* Get the iodesc. */ +// if (!(iodesc = pio_get_iodesc_from_id(ioid))) +// return pio_err(ios, file, PIO_EBADID, __FILE__, __LINE__); +// pioassert(iodesc->rearranger == PIO_REARR_BOX || iodesc->rearranger == PIO_REARR_SUBSET, +// "unknown rearranger", __FILE__, __LINE__); + +// /* iomaster needs max of buflen, others need local len */ +// if (ios->iomaster == MPI_ROOT) +// rlen = iodesc->maxiobuflen; +// else +// rlen = iodesc->llen; +// +// /* Allocate a buffer for one record. */ +// if (ios->ioproc && rlen > 0) +// if (!(iobuf = malloc(iodesc->mpitype_size * rlen))) +// return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); +// +// /* Call the correct darray read function based on iotype. */ +// switch (file->iotype) +// { +// case PIO_IOTYPE_NETCDF: +// case PIO_IOTYPE_NETCDF4C: +// if ((ierr = pio_read_darray_nc_serial(file, iodesc, varid, iobuf))) +// return pio_err(ios, file, ierr, __FILE__, __LINE__); +// break; +// case PIO_IOTYPE_PNETCDF: +// case PIO_IOTYPE_NETCDF4P: +// if ((ierr = pio_read_darray_nc(file, iodesc, varid, iobuf))) +// return pio_err(ios, file, ierr, __FILE__, __LINE__); +// break; +// default: +// return pio_err(NULL, NULL, PIO_EBADIOTYPE, __FILE__, __LINE__); +// } +// +// /* If the map is not monotonically increasing we will need to sort +// * it. */ +// PLOG((2, "iodesc->needssort %d", iodesc->needssort)); +// +// if (iodesc->needssort) +// { +// if (!(tmparray = calloc(iodesc->maplen, iodesc->piotype_size))) +// return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); +// } +// else +// tmparray = array; +// +// /* Rearrange the data. */ +// if ((ierr = rearrange_io2comp(ios, iodesc, iobuf, tmparray))) +// return pio_err(ios, file, ierr, __FILE__, __LINE__); +// +// /* Free the buffer. */ +// if (ios->ioproc && rlen > 0) +// free(iobuf); +// +// /* If we need to sort the map, do it. */ +// if (iodesc->needssort && ios->compproc) +// { +// pio_sorted_copy(tmparray, array, iodesc, 1, 1); +// free(tmparray); +// } + + PRINTMSG( "done with GDALc_read_darray()"); + + return PIO_NOERR; + } + } // end namespace ESMCI diff --git a/src/Infrastructure/IO/src/makefile b/src/Infrastructure/IO/src/makefile index 044d20cee8..2ad779b6a2 100644 --- a/src/Infrastructure/IO/src/makefile +++ b/src/Infrastructure/IO/src/makefile @@ -2,9 +2,9 @@ ALL: build_here -SOURCEC = ESMCI_IO_NetCDF.C ESMCI_IO.C ESMCI_IO_Handler.C ESMCI_IO_Gridspec.C ESMCI_IO_Scrip.C ESMCI_IO_YAML.C ESMCI_IO_GDAL.C +SOURCEC = ESMCI_IO_NetCDF.C ESMCI_IO.C ESMCI_IO_Handler.C ESMCI_IO_Gridspec.C ESMCI_IO_Scrip.C ESMCI_IO_YAML.C SOURCEF = -STOREH = ESMCI_IO_NetCDF.h ESMCI_IO.h ESMCI_IO_Handler.h ESMCI_IO_Gridspec.h ESMCI_IO_Scrip.h ESMCI_IO_YAML.h ESMCI_IO_GDAL.h +STOREH = ESMCI_IO_NetCDF.h ESMCI_IO.h ESMCI_IO_Handler.h ESMCI_IO_Gridspec.h ESMCI_IO_Scrip.h ESMCI_IO_YAML.h ifdef ESMF_PIO SOURCEC += ESMCI_PIO_Handler.C @@ -12,7 +12,7 @@ ifdef ESMF_PIO endif ifdef ESMF_GDAL - SOURCEC += ESMCI_GDAL_Handler.C + SOURCEC += ESMCI_GDAL_Handler.C ESMCI_IO_GDAL.C STOREH += ESMCI_GDAL_Handler.h ESMCI_IO_GDAL.h endif diff --git a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 index 9591f91b46..1e6cd3a0c8 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 @@ -46,18 +46,7 @@ program ESMF_IO_GDALUTest type(ESMF_VM) :: vm integer :: localPet - type(ESMF_Grid) :: grid6tile - type(ESMF_DistGrid) :: distgrid3tile - - ! Fields used for writing: - ! - ! The following fields make up the field bundle: - type(ESMF_Field) :: field1, field2, field1Copy, field4d - real(ESMF_KIND_R8), pointer :: field1Data(:,:), field2Data(:,:), field1CopyData(:,:), field4dData(:,:,:,:) - type(ESMF_FieldBundle) :: fieldBundle - ! This field is not in the field bundle: - type(ESMF_Field) :: field3 - real(ESMF_KIND_R8), pointer :: field3Data(:,:) + type(ESMF_Mesh) :: mesh ! Fields used for reading: ! @@ -66,37 +55,13 @@ program ESMF_IO_GDALUTest real(ESMF_KIND_R8), pointer :: field1ReadData(:,:), field2ReadData(:,:), field1CopyReadData(:,:), field4dReadData(:,:,:,:) type(ESMF_FieldBundle) :: fieldBundleRead ! This field is not in the field bundle: - type(ESMF_Field) :: field3Read - real(ESMF_KIND_R8), pointer :: field3ReadData(:,:) + type(ESMF_Field) :: field + real(ESMF_KIND_R8), pointer :: fieldReadData(:) - ! This is used for error testing: - type(ESMF_Grid) :: gridSingleTile - type(ESMF_Field) :: fieldSingleTile - type(ESMF_FieldBundle) :: fieldBundleMixedTileCounts + type(ESMF_ArraySpec) :: arraySpec - ! Arrays used for writing: - ! - ! The following arrays make up the array bundle: - type(ESMF_Array) :: array1, array2 - real(ESMF_KIND_R8), pointer :: array1Data(:,:), array2Data(:,:) - type(ESMF_ArrayBundle) :: arrayBundle - ! This array is not in the array bundle: - type(ESMF_Array) :: array3 - real(ESMF_KIND_R8), pointer :: array3Data(:,:) - - ! Arrays used for reading: - ! - ! The following arrays make up the array bundle: - type(ESMF_Array) :: array1Read, array2Read - real(ESMF_KIND_R8), pointer :: array1ReadData(:,:), array2ReadData(:,:) - type(ESMF_ArrayBundle) :: arrayBundleRead - ! This array is not in the array bundle: - type(ESMF_Array) :: array3Read - real(ESMF_KIND_R8), pointer :: array3ReadData(:,:) - - logical :: allEqual - - character(len=*), parameter :: fileNameFields = "ESMF_IO_GDALUTestFields#.shp" + character(len=*), parameter :: fileNameFields = "data/complex_3.shp" +! character(len=*), parameter :: fileNameFields = "cb_2018_us_county_20m.shp" !------------------------------------------------------------------------ call ESMF_TestStart(ESMF_SRCLINE, rc=rc) ! calls ESMF_Initialize() internally @@ -107,33 +72,44 @@ program ESMF_IO_GDALUTest if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ - ! --- - !------------------------------------------------------------------------ + ! Create Mesh from shape file + write(name, *) "Creating a Mesh to use in Field Tests" + mesh=ESMF_MeshCreate(fileNameFields, & + fileformat=ESMF_FILEFORMAT_SHAPEFILE, & + rc=rc) + if (rc /= ESMF_SUCCESS) return + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - !EX_UTest_Multi_Proc_Only - write(name, *) "Read a multi-tile Field" + + write(name, *) "Get a multi-tile Field" write(failMsg, *) "Did not return ESMF_SUCCESS" - call ESMF_FieldRead(field3Read, fileName=fileNameFields, iofmt=ESMF_IOFMT_SHP, rc=rc) + call ESMF_ArraySpecSet(arraySpec, 1, typekind=ESMF_TYPEKIND_R8, rc=rc) + if (rc /= ESMF_SUCCESS) return + field = ESMF_FieldCreate(mesh, arraySpec, name="DistFld", rc=rc) + if (rc /= ESMF_SUCCESS) return +! call ESMF_FieldPrint(field, rc=rc) +! if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field, farrayPtr=fieldReadData, rc=rc) #if (defined ESMF_PIO && (defined ESMF_GDAL)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else write(failMsg, *) "Did not return ESMF_RC_LIB_NOT_PRESENT" call ESMF_Test((rc == ESMF_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) #endif - !------------------------------------------------------------------------ !------------------------------------------------------------------------ !EX_UTest_Multi_Proc_Only -!>> write(name, *) "Confirm that Field-read field matches original" -!>> write(failMsg, *) "Read-in field differs from original" -!>> allEqual = all(field3ReadData == field3Data) -!>>#if (defined ESMF_PIO && (defined ESMF_GDAL)) -!>> call ESMF_Test(allEqual, name, failMsg, result, ESMF_SRCLINE) -!>>#else -!>> write(failMsg, *) "Comparison did not fail as expected" -!>> call ESMF_Test(.not. allEqual, name, failMsg, result, ESMF_SRCLINE) -!>>#endif + write(name, *) "Read a multi-tile Field" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldRead(field, fileName=fileNameFields, iofmt=ESMF_IOFMT_SHP, rc=rc) +#if (defined ESMF_PIO && (defined ESMF_GDAL)) + call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) +#else + write(failMsg, *) "Did not return ESMF_RC_LIB_NOT_PRESENT" + call ESMF_Test((rc == ESMF_RC_LIB_NOT_PRESENT), name, failMsg, result, ESMF_SRCLINE) +#endif !------------------------------------------------------------------------ !------------------------------------------------------------------------ diff --git a/src/Infrastructure/IO/tests/makefile b/src/Infrastructure/IO/tests/makefile index dd78d93ca8..ec99047da0 100644 --- a/src/Infrastructure/IO/tests/makefile +++ b/src/Infrastructure/IO/tests/makefile @@ -13,14 +13,16 @@ TESTS_BUILD = $(ESMF_TESTDIR)/ESMCI_IO_NetCDFUTest \ $(ESMF_TESTDIR)/ESMC_IO_InqUTest \ $(ESMF_TESTDIR)/ESMF_IO_YAMLUTest \ $(ESMF_TESTDIR)/ESMF_IOUTest \ - $(ESMF_TESTDIR)/ESMF_IO_MultitileUTest + $(ESMF_TESTDIR)/ESMF_IO_MultitileUTest \ + $(ESMF_TESTDIR)/ESMF_IO_GDALUTest TESTS_RUN = RUN_ESMCI_IO_NetCDFUTest \ RUN_ESMCI_IO_PIOUTest \ RUN_ESMC_IO_InqUTest \ RUN_ESMF_IO_YAMLUTest \ RUN_ESMF_IOUTest \ - RUN_ESMF_IO_MultitileUTest + RUN_ESMF_IO_MultitileUTest \ + RUN_ESMF_IO_GDALTest TESTS_RUN_UNI = RUN_ESMCI_IO_NetCDFUTestUNI \ RUN_ESMCI_IO_PIOUTestUNI \ @@ -81,3 +83,7 @@ RUN_ESMF_IO_YAMLUTestUNI: RUN_ESMF_IO_MultitileUTest: rm -f $(ESMF_TESTDIR)/ESMF_IO_MultitileUTest*.nc $(MAKE) TNAME=IO_Multitile NP=8 ftest + +RUN_ESMF_IO_GDALUTest: + rm -f $(ESMF_TESTDIR)/ESMF_IO_GDALUTest*.nc + $(MAKE) TNAME=IO_GDAL NP=4 ftest diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 859714dbbe..a1409e3e05 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -6913,14 +6913,15 @@ subroutine test_create_mesh_from_SH_file(correct, rc) if (rc /= ESMF_SUCCESS) return ! Create Mesh from shape file - mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & +! mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & + mesh=ESMF_MeshCreate("data/complex_3.shp", & fileformat=ESMF_FILEFORMAT_SHAPEFILE, & rc=rc) if (rc /= ESMF_SUCCESS) return !! Write mesh for debugging - call ESMF_MeshWrite(mesh,"cb_2018_us_county_500k",rc=rc) + call ESMF_MeshWrite(mesh,"complex_3",rc=rc) if (rc /= ESMF_SUCCESS) return ! Get rid of Mesh From 0410e278bfeb80bf0694a1ffc83de94daa64eb75 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Thu, 7 Sep 2023 09:42:21 -0400 Subject: [PATCH 15/58] Revert "Added GDAL_Handler class. Compiles" Going to clone PIO and convert from NETCDF to GDAL. This reverts commit 83dccf0ec8f20f67118736eaa0d9ff04e56683ff. --- src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h | 4 ++-- src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C | 2 +- src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h index 9788cbac3d..b27e6f24da 100644 --- a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h @@ -53,7 +53,7 @@ namespace ESMCI { // classes and structs class GDAL_Handler; // The main class for implementing GDAL functionality - class GDAL_SystemHandler; + // class definitions //=========================================================================== @@ -123,7 +123,7 @@ namespace ESMCI { } // open() and close() - void openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); + void GDAL_openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); ESMC_Logical isOpen(int tile); ESMC_Logical isNewFile(int tile) { // note 1-based indexing for tile return (new_file[tile-1] ? ESMF_TRUE : ESMF_FALSE); diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index ad8e85d00d..a25dd9a096 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -1173,7 +1173,7 @@ void GDAL_Handler::arrayWriteOneTileFile( // !IROUTINE: ESMCI::GDAL_Handler::openOneTileFile - open a stream with stored filename, for the given tile // // !INTERFACE: -void GDAL_Handler::openOneTileFile( +void GDAL_Handler::GDAL_openOneTileFile( // // !RETURN VALUE: // diff --git a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C index e759d8c10a..7f3106df49 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C @@ -155,7 +155,7 @@ IO_Handler *IO_Handler::create ( break; case ESMF_IOFMT_SHP: #if defined(ESMF_PIO) && defined(ESMF_GDAL) - iohandler = new GDAL_Handler(iofmt, ntiles, &localrc); + iohandler = new PIO_Handler(iofmt, ntiles, &localrc); #else // defined(ESMF_PIO) && (defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)) errmsg = "PIO & GDAL libraries required for GIS I/O operation"; localrc = ESMF_RC_LIB_NOT_PRESENT; From 10f6ee59d4452d3d6052a81c3d1f4d73450d7779 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Thu, 14 Sep 2023 14:06:27 -0400 Subject: [PATCH 16/58] PIO now compiles with GDAL libs and headers. Added pioc_gdal.c module which will hold the GDAL-specific routines -- likely all routines in one module. Maybe they'll split apart in the future. MSL --- .../IO/PIO/ParallelIO/src/clib/CMakeLists.txt | 11 + .../IO/PIO/ParallelIO/src/clib/pio.h | 11 +- .../IO/PIO/ParallelIO/src/clib/pio_gdal.XC | 3237 +++++++++++++++++ .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 308 ++ src/Infrastructure/IO/PIO/makefile | 4 + src/Infrastructure/IO/include/ESMCI_IO_GDAL.h | 4 +- .../IO/src/ESMCI_GDAL_Handler.C | 2 +- src/Infrastructure/IO/src/ESMCI_IO_GDAL.C | 138 +- 8 files changed, 3642 insertions(+), 73 deletions(-) create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt index e1f6a13bd7..86ed405895 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt @@ -28,6 +28,9 @@ set (src topology.c pio_file.c pioc_support.c pio_lists.c if (NETCDF_INTEGRATION) set (src ${src} ../ncint/nc_get_vard.c ../ncint/ncintdispatch.c ../ncint/ncint_pio.c ../ncint/nc_put_vard.c) endif () +#<> if (GDAL_INTEGRATION) +set (src ${src} pio_gdal.c) +#endif () add_library (pioc ${src}) @@ -173,6 +176,14 @@ if (PIO_USE_MPISERIAL) endif () endif () +#===== GDAL ===== +#if (GDAL_Found) + target_include_directories (pioc + PUBLIC ${GDAL_INCLUDE_DIR}) + target_link_libraries (pioc + PUBLIC ${GDAL_LIBRARY}) +#endif () + include(CheckTypeSize) check_type_size("size_t" SIZEOF_SIZE_T) CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG) diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h index 3e3c0d6b31..86bd41e042 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h @@ -18,6 +18,8 @@ #include +#include + /** PIO_OFFSET is an integer type of size sufficient to represent the * size (in bytes) of the largest file supported by MPI. This is not * actually used by the code. */ @@ -614,7 +616,10 @@ enum PIO_IOTYPE PIO_IOTYPE_NETCDF4C = 3, /** NetCDF4 (HDF5) parallel */ - PIO_IOTYPE_NETCDF4P = 4 + PIO_IOTYPE_NETCDF4P = 4, + + /** GDAL (serial only) */ + PIO_IOTYPE_GDAL = 5 }; /** @@ -1322,6 +1327,10 @@ extern "C" { int nc_put_vard_ulonglong(int ncid, int varid, int decompid, const size_t recnum, const unsigned long long *op); + /* These functions are for the GDAL integration layer. MSL - 9/7/2023 */ + int GDALc_inq_fieldid(int ncid, const char *name, int *varidp); + int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *fname, bool mode); + #if defined(__cplusplus) } #endif diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC new file mode 100644 index 0000000000..2ca08c73c4 --- /dev/null +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC @@ -0,0 +1,3237 @@ +/** + * @file + * PIO interfaces to + * [NetCDF](http://www.unidata.ucar.edu/software/netcdf/docs/modules.html) + * support functions + * + * This file provides an interface to the + * [NetCDF](http://www.unidata.ucar.edu/software/netcdf/docs/modules.html) + * support functions. Each subroutine calls the underlying netcdf or + * pnetcdf or netcdf4 functions from the appropriate subset of mpi + * tasks (io_comm). Each routine must be called collectively from + * union_comm. + * + * @author Jim Edwards (jedwards@ucar.edu), Ed Hartnett + * @date Feburary 2014, April 2016 + */ +#include +#include +#include +#include + +/** + * @defgroup PIO_inq_c Learn About File + * Learn the number of variables, dimensions, and global atts, and the + * unlimited dimension in C. + * + * @defgroup PIO_typelen_c Learn Aboue a Data Type + * Learn the length of a data type in C. + * + * @defgroup PIO_inq_format_c Learn About Binary Format + * Learn about the binary format in C. + * + * @defgroup PIO_inq_dim_c Learn About a Dimension + * Learn dimension name and length in C. + * + * @defgroup PIO_inq_var_c Learn About a Variable + * Learn variable name, dimensions, and type in C. + * + * @defgroup PIO_inq_att_c Learn About an Attribute + * Learn length, type, and name of an attribute in C. + * + * @defgroup PIO_rename_dim_c Rename a Dimension + * Rename a dimension in C. + * + * @defgroup PIO_rename_var_c Rename a Variable + * Rename a variable in C. + * + * @defgroup PIO_rename_att_c Rename an Attribute + * Rename an attribute in C. + * + * @defgroup PIO_del_att_c Delete an Attribute + * Delete an attribute in C. + * + * @defgroup PIO_set_fill_c Set Fill Value + * Set the fill value for a variable in C. + * + * @defgroup PIO_enddef_c End Define Mode + * End define mode in C. + * + * @defgroup PIO_redef_c Re-enter Define Mode + * Re-enter Define Mode in C. + * + * @defgroup PIO_def_dim_c Define a Dimension + * Define a new dimension in the file in C. + * + * @defgroup PIO_def_var_c Define a Variable + * Define a new variable in the file in C. + */ + +/** + * The PIO-C interface for the NetCDF function nc_inq. + * + * This routine is called collectively by all tasks in the + * communicator ios.union_comm. For more information on the underlying + * NetCDF commmand please read about this function in the NetCDF + * documentation at: + * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html + * + * @param ncid the ncid of the open file, obtained from + * GDALc_openfile() or GDALc_createfile(). + * @param ndimsp a pointer that will get the number of + * dimensions. Ignored if NULL. + * @param nvarsp a pointer that will get the number of + * variables. Ignored if NULL. + * @param ngattsp a pointer that will get the number of + * attributes. Ignored if NULL. + * @param unlimdimidp a pointer that will the ID of the unlimited + * dimension, or -1 if there is no unlimited dimension. Ignored if + * NULL. + * + * @return PIO_NOERR for success, error code otherwise. See + * GDALc_Set_File_Error_Handling(). + * @ingroup PIO_inq_c + * @author Jim Edwards, Ed Hartnett + */ +//<<>>int +//<<>>GDALc_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function calls. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq ncid = %d", ncid)); +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ; /* Message for async notification. */ +//<<>> char ndims_present = ndimsp ? true : false; +//<<>> char nvars_present = nvarsp ? true : false; +//<<>> char ngatts_present = ngattsp ? true : false; +//<<>> char unlimdimid_present = unlimdimidp ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ndims_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&nvars_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ngatts_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&unlimdimid_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_inq ncid = %d ndims_present = %d nvars_present = %d ngatts_present = %d unlimdimid_present = %d", +//<<>> ncid, ndims_present, nvars_present, ngatts_present, unlimdimid_present)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> { +//<<>> ierr = ncmpi_inq(file->fh, ndimsp, nvarsp, ngattsp, unlimdimidp); +//<<>> if (unlimdimidp) +//<<>> PLOG((2, "GDALc_inq returned from ncmpi_inq unlimdimid = %d", *unlimdimidp)); +//<<>> } +//<<>>#endif /* _PNETCDF */ +//<<>> if (file->iotype == PIO_IOTYPE_NETCDF && file->do_io) +//<<>> { +//<<>> PLOG((2, "GDALc_inq calling classic nc_inq")); +//<<>> /* Should not be necessary to do this - nc_inq should +//<<>> * handle null pointers. This has been reported as a bug +//<<>> * to netCDF developers. */ +//<<>> int tmp_ndims, tmp_nvars, tmp_ngatts, tmp_unlimdimid; +//<<>> PLOG((2, "GDALc_inq calling classic nc_inq")); +//<<>> ierr = nc_inq(file->fh, &tmp_ndims, &tmp_nvars, &tmp_ngatts, &tmp_unlimdimid); +//<<>> PLOG((2, "GDALc_inq calling classic nc_inq")); +//<<>> if (unlimdimidp) +//<<>> PLOG((2, "classic tmp_unlimdimid = %d", tmp_unlimdimid)); +//<<>> if (ndimsp) +//<<>> *ndimsp = tmp_ndims; +//<<>> if (nvarsp) +//<<>> *nvarsp = tmp_nvars; +//<<>> if (ngattsp) +//<<>> *ngattsp = tmp_ngatts; +//<<>> if (unlimdimidp) +//<<>> *unlimdimidp = tmp_unlimdimid; +//<<>> if (unlimdimidp) +//<<>> PLOG((2, "classic unlimdimid = %d", *unlimdimidp)); +//<<>> } +//<<>> else if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> { +//<<>> PLOG((2, "GDALc_inq calling netcdf-4 nc_inq")); +//<<>> ierr = nc_inq(file->fh, ndimsp, nvarsp, ngattsp, unlimdimidp); +//<<>> } +//<<>> +//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if (ndimsp) +//<<>> if ((mpierr = MPI_Bcast(ndimsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> if (nvarsp) +//<<>> if ((mpierr = MPI_Bcast(nvarsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> if (ngattsp) +//<<>> if ((mpierr = MPI_Bcast(ngattsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> if (unlimdimidp) +//<<>> if ((mpierr = MPI_Bcast(unlimdimidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find out how many dimensions are defined in the file. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param ndimsp a pointer that will get the number of +//<<>> * dimensions. Ignored if NULL. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_ndims(int ncid, int *ndimsp) +//<<>>{ +//<<>> PLOG((1, "GDALc_inq_ndims")); +//<<>> return GDALc_inq(ncid, ndimsp, NULL, NULL, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find out how many variables are defined in a file. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param nvarsp a pointer that will get the number of variables. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_nvars(int ncid, int *nvarsp) +//<<>>{ +//<<>> return GDALc_inq(ncid, NULL, nvarsp, NULL, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find out how many global attributes are defined in a file. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param ngattsp a pointer that will get the number of attributes. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_natts(int ncid, int *ngattsp) +//<<>>{ +//<<>> return GDALc_inq(ncid, NULL, NULL, ngattsp, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find out the dimension ids of the unlimited dimension. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param unlimdimidp a pointer that will the ID of the unlimited +//<<>> * dimension, or -1 if there is no unlimited dimension. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_unlimdim(int ncid, int *unlimdimidp) +//<<>>{ +//<<>> PLOG((1, "GDALc_inq_unlimdim ncid = %d", ncid)); +//<<>> return GDALc_inq(ncid, NULL, NULL, NULL, unlimdimidp); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find out the dimension ids of all unlimited dimensions. Note that +//<<>> * only netCDF-4 files can have more than 1 unlimited dimension. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param nunlimdimsp a pointer that gets the number of unlimited +//<<>> * dimensions. Ignored if NULL. +//<<>> * @param unlimdimidsp a pointer that will get an array of unlimited +//<<>> * dimension IDs. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_unlimdim_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int tmp_nunlimdims; /* The number of unlimited dims. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function calls. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq_unlimdims ncid = %d", ncid)); +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_UNLIMDIMS; /* Message for async notification. */ +//<<>> char nunlimdimsp_present = nunlimdimsp ? true : false; +//<<>> char unlimdimidsp_present = unlimdimidsp ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&nunlimdimsp_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&unlimdimidsp_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_inq_unlimdims ncid = %d nunlimdimsp_present = %d unlimdimidsp_present = %d", +//<<>> ncid, nunlimdimsp_present, unlimdimidsp_present)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> PLOG((2, "file->iotype = %d", file->iotype)); +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>> if (file->iotype == PIO_IOTYPE_NETCDF && file->do_io) +//<<>> { +//<<>> PLOG((2, "netcdf")); +//<<>> int tmp_unlimdimid; +//<<>> ierr = nc_inq_unlimdim(file->fh, &tmp_unlimdimid); +//<<>> PLOG((2, "classic tmp_unlimdimid = %d", tmp_unlimdimid)); +//<<>> tmp_nunlimdims = tmp_unlimdimid >= 0 ? 1 : 0; +//<<>> if (nunlimdimsp) +//<<>> *nunlimdimsp = tmp_unlimdimid >= 0 ? 1 : 0; +//<<>> if (unlimdimidsp) +//<<>> *unlimdimidsp = tmp_unlimdimid; +//<<>> } +//<<>>#ifdef _PNETCDF +//<<>> else if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> { +//<<>> PLOG((2, "pnetcdf")); +//<<>> int tmp_unlimdimid; +//<<>> ierr = ncmpi_inq_unlimdim(file->fh, &tmp_unlimdimid); +//<<>> PLOG((2, "pnetcdf tmp_unlimdimid = %d", tmp_unlimdimid)); +//<<>> tmp_nunlimdims = tmp_unlimdimid >= 0 ? 1 : 0; +//<<>> if (nunlimdimsp) +//<<>> *nunlimdimsp = tmp_nunlimdims; +//<<>> if (unlimdimidsp) +//<<>> *unlimdimidsp = tmp_unlimdimid; +//<<>> } +//<<>>#endif /* _PNETCDF */ +//<<>>#ifdef _NETCDF4 +//<<>> else if ((file->iotype == PIO_IOTYPE_NETCDF4C || file->iotype == PIO_IOTYPE_NETCDF4P) && +//<<>> file->do_io) +//<<>> { +//<<>> PLOG((2, "GDALc_inq calling netcdf-4 nc_inq_unlimdims")); +//<<>> int *tmp_unlimdimids; +//<<>> ierr = nc_inq_unlimdims(file->fh, &tmp_nunlimdims, NULL); +//<<>> if (!ierr) +//<<>> { +//<<>> if (nunlimdimsp) +//<<>> *nunlimdimsp = tmp_nunlimdims; +//<<>> PLOG((3, "tmp_nunlimdims = %d", tmp_nunlimdims)); +//<<>> if (!(tmp_unlimdimids = malloc(tmp_nunlimdims * sizeof(int)))) +//<<>> ierr = PIO_ENOMEM; +//<<>> if (!ierr) +//<<>> ierr = nc_inq_unlimdims(file->fh, &tmp_nunlimdims, tmp_unlimdimids); +//<<>> if (unlimdimidsp) +//<<>> for (int d = 0; d < tmp_nunlimdims; d++) +//<<>> { +//<<>> PLOG((3, "tmp_unlimdimids[%d] = %d", d, tmp_unlimdimids[d])); +//<<>> unlimdimidsp[d] = tmp_unlimdimids[d]; +//<<>> } +//<<>> free(tmp_unlimdimids); +//<<>> } +//<<>> } +//<<>>#endif /* _NETCDF4 */ +//<<>> +//<<>> PLOG((2, "GDALc_inq_unlimdims netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if ((mpierr = MPI_Bcast(&tmp_nunlimdims, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> if (nunlimdimsp) +//<<>> if ((mpierr = MPI_Bcast(nunlimdimsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> if (unlimdimidsp) +//<<>> if ((mpierr = MPI_Bcast(unlimdimidsp, tmp_nunlimdims, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * Learn the name and size of a type. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param xtype the type to learn about +//<<>> * @param name pointer that will get the name of the type. +//<<>> * @param sizep pointer that will get the size of the type in bytes. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_typelen_c +//<<>> * @author Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_type(int ncid, nc_type xtype, char *name, PIO_Offset *sizep) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq_type ncid = %d xtype = %d", ncid, xtype)); +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_TYPE; /* Message for async notification. */ +//<<>> char name_present = name ? true : false; +//<<>> char size_present = sizep ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&size_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = pioc_pnetcdf_inq_type(ncid, xtype, name, sizep); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_inq_type(file->fh, xtype, name, (size_t *)sizep); +//<<>> PLOG((2, "GDALc_inq_type netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if (name) +//<<>> { +//<<>> int slen; +//<<>> if (ios->iomaster == MPI_ROOT) +//<<>> slen = strlen(name); +//<<>> if ((mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (!mpierr) +//<<>> if ((mpierr = MPI_Bcast((void *)name, slen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> if (sizep) +//<<>> if ((mpierr = MPI_Bcast(sizep , 1, MPI_OFFSET, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * Learn the netCDF format of an open file. +//<<>> * +//<<>> * @param ncid the ncid of an open file. +//<<>> * @param formatp a pointer that will get the format. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_format_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_format(int ncid, int *formatp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq ncid = %d", ncid)); +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_FORMAT; +//<<>> char format_present = formatp ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&format_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_inq_format(file->fh, formatp); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_inq_format(file->fh, formatp); +//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if (formatp) +//<<>> if ((mpierr = MPI_Bcast(formatp , 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_dim. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param dimid the dimension ID. +//<<>> * @param name a pointer that gets the name of the dimension. Igorned +//<<>> * if NULL. Name will be PIO_MAX_NAME chars or fewer. +//<<>> * @param lenp a pointer that will get the number of values +//<<>> * @return PIO_NOERR for success, error code otherwise. See +//<<>> * @ingroup PIO_inq_dim_c +//<<>> * GDALc_Set_File_Error_Handling() +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_dim(int ncid, int dimid, char *name, PIO_Offset *lenp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq_dim ncid = %d dimid = %d", ncid, dimid)); +//<<>> +//<<>> /* Get the file info, based on the ncid. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_DIM; +//<<>> char name_present = name ? true : false; +//<<>> char len_present = lenp ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&dimid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_inq netcdf Bcast name_present = %d", name_present)); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&len_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_inq netcdf Bcast len_present = %d", len_present)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> { +//<<>> PLOG((2, "calling ncmpi_inq_dim")); +//<<>> ierr = ncmpi_inq_dim(file->fh, dimid, name, lenp);; +//<<>> } +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> { +//<<>> PLOG((2, "calling nc_inq_dim")); +//<<>> ierr = nc_inq_dim(file->fh, dimid, name, (size_t *)lenp);; +//<<>> } +//<<>> PLOG((2, "ierr = %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if (name) +//<<>> { +//<<>> int slen; +//<<>> PLOG((2, "bcasting results my_comm = %d", ios->my_comm)); +//<<>> if (ios->iomaster == MPI_ROOT) +//<<>> slen = strlen(name); +//<<>> if ((mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast((void *)name, slen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> if (lenp) +//<<>> if ((mpierr = MPI_Bcast(lenp , 1, MPI_OFFSET, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((2, "done with GDALc_inq_dim")); +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find the name of a dimension. +//<<>> * +//<<>> * @param ncid the ncid of an open file. +//<<>> * @param dimid the dimension ID. +//<<>> * @param name a pointer that gets the name of the dimension. Igorned +//<<>> * if NULL. Name will be PIO_MAX_NAME chars or fewer. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_dim_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_dimname(int ncid, int dimid, char *name) +//<<>>{ +//<<>> PLOG((1, "GDALc_inq_dimname ncid = %d dimid = %d", ncid, dimid)); +//<<>> return GDALc_inq_dim(ncid, dimid, name, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find the length of a dimension. +//<<>> * +//<<>> * @param ncid the ncid of an open file. +//<<>> * @param dimid the dimension ID. +//<<>> * @param lenp a pointer that gets the length of the dimension. Igorned +//<<>> * if NULL. +//<<>> * @returns 0 for success, error code otherwise. +//<<>> * @ingroup PIO_inq_dim_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_dimlen(int ncid, int dimid, PIO_Offset *lenp) +//<<>>{ +//<<>> return GDALc_inq_dim(ncid, dimid, NULL, lenp); +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_dimid. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param name pointer taht gets the name of the dimension. +//<<>> * @param idp a pointer that will get the id of the variable or attribute. +//<<>> * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling +//<<>> * @ingroup PIO_inq_dim_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_dimid(int ncid, const char *name, int *idp) +//<<>>{ +//<<>> iosystem_desc_t *ios; +//<<>> file_desc_t *file; +//<<>> int ierr; +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> /* Get the file info, based on the ncid. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> PLOG((2, "iosysid = %d", ios->iosysid)); +//<<>> +//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_inq_dimid ncid = %d name = %s", ncid, name)); +//<<>> +//<<>> /* If using async, and not an IO task, then send parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_DIMID; +//<<>> char id_present = idp ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> int namelen = strlen(name); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&id_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* IO tasks call the netCDF functions. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_inq_dimid(file->fh, name, idp); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_inq_dimid(file->fh, name, idp); +//<<>> } +//<<>> PLOG((3, "nc_inq_dimid call complete ierr = %d", ierr)); +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results. */ +//<<>> if (idp) +//<<>> if ((mpierr = MPI_Bcast(idp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_var. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name a pointer that gets the name of the dimension. Igorned +//<<>> * if NULL. Name will be PIO_MAX_NAME chars or fewer. +//<<>> * @param xtypep a pointer that will get the type of the +//<<>> * attribute. Ignored if NULL. +//<<>> * @param ndimsp a pointer that will get the number of +//<<>> * dimensions. Ignored if NULL. +//<<>> * @param dimidsp a pointer that will get an array of dimids. Ignored +//<<>> * if NULL. +//<<>> * @param nattsp a pointer that will get the number of +//<<>> * attributes. Ignored if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_var(int ncid, int varid, char *name, nc_type *xtypep, int *ndimsp, +//<<>> int *dimidsp, int *nattsp) +//<<>>{ +//<<>> iosystem_desc_t *ios; +//<<>> file_desc_t *file; +//<<>> int ndims = 0; /* The number of dimensions for this variable. */ +//<<>> int ierr; +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq_var ncid = %d varid = %d", ncid, varid)); +//<<>> +//<<>> /* Get the file info, based on the ncid. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_VAR; +//<<>> char name_present = name ? true : false; +//<<>> char xtype_present = xtypep ? true : false; +//<<>> char ndims_present = ndimsp ? true : false; +//<<>> char dimids_present = dimidsp ? true : false; +//<<>> char natts_present = nattsp ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&xtype_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ndims_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&dimids_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&natts_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_inq_var name_present = %d xtype_present = %d ndims_present = %d " +//<<>> "dimids_present = %d, natts_present = %d nattsp = %d", +//<<>> name_present, xtype_present, ndims_present, dimids_present, natts_present, nattsp)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* Call the netCDF layer. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>> PLOG((2, "Calling the netCDF layer")); +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> { +//<<>> ierr = ncmpi_inq_varndims(file->fh, varid, &ndims); +//<<>> PLOG((2, "from pnetcdf ndims = %d", ndims)); +//<<>> if (!ierr) +//<<>> ierr = ncmpi_inq_var(file->fh, varid, name, xtypep, ndimsp, dimidsp, nattsp); +//<<>> } +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> { +//<<>> ierr = nc_inq_varndims(file->fh, varid, &ndims); +//<<>> PLOG((3, "nc_inq_varndims called ndims = %d", ndims)); +//<<>> if (!ierr) +//<<>> { +//<<>> char my_name[NC_MAX_NAME + 1]; +//<<>> nc_type my_xtype; +//<<>> int my_ndims = 0, *my_dimids, my_natts = 0; +//<<>> if (ndims > 0) +//<<>> my_dimids = (int *) malloc(ndims * sizeof(int)); +//<<>> else +//<<>> my_dimids = NULL; +//<<>> ierr = nc_inq_var(file->fh, varid, my_name, &my_xtype, &my_ndims, my_dimids, +//<<>> &my_natts); +//<<>> PLOG((3, "my_name = %s my_xtype = %d my_ndims = %d my_natts = %d", my_name, +//<<>> my_xtype, my_ndims, my_natts)); +//<<>> if (!ierr) +//<<>> { +//<<>> if (name) +//<<>> strcpy(name, my_name); +//<<>> if (xtypep) +//<<>> *xtypep = my_xtype; +//<<>> if (ndimsp) +//<<>> *ndimsp = my_ndims; +//<<>> if (dimidsp) +//<<>> { +//<<>> for (int d = 0; d < ndims; d++) +//<<>> dimidsp[d] = my_dimids[d]; +//<<>> } +//<<>> if (my_dimids != NULL) +//<<>> free(my_dimids); +//<<>> if (nattsp) +//<<>> *nattsp = my_natts; +//<<>> } +//<<>> } +//<<>> } +//<<>> if (ndimsp) +//<<>> PLOG((2, "GDALc_inq_var ndims = %d ierr = %d", *ndimsp, ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast the results for non-null pointers. */ +//<<>> if (name) +//<<>> { +//<<>> int slen; +//<<>> if (ios->iomaster == MPI_ROOT) +//<<>> slen = strlen(name); +//<<>> if ((mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast((void *)name, slen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> if (xtypep) +//<<>> if ((mpierr = MPI_Bcast(xtypep, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> if (ndimsp) +//<<>> { +//<<>> PLOG((2, "GDALc_inq_var about to Bcast ndims = %d ios->ioroot = %d ios->my_comm = %d", +//<<>> *ndimsp, ios->ioroot, ios->my_comm)); +//<<>> if ((mpierr = MPI_Bcast(ndimsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> PLOG((2, "GDALc_inq_var Bcast ndims = %d", *ndimsp)); +//<<>> } +//<<>> if (dimidsp) +//<<>> { +//<<>> if ((mpierr = MPI_Bcast(&ndims, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast(dimidsp, ndims, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> if (nattsp) +//<<>> if ((mpierr = MPI_Bcast(nattsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the name of a variable. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param varid the variable ID. +//<<>> * @param name a pointer that will get the variable name. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_varname(int ncid, int varid, char *name) +//<<>>{ +//<<>> return GDALc_inq_var(ncid, varid, name, NULL, NULL, NULL, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find the type of a variable. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param varid the variable ID. +//<<>> * @param xtypep a pointer that will get the type of the +//<<>> * attribute. Ignored if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_vartype(int ncid, int varid, nc_type *xtypep) +//<<>>{ +//<<>> return GDALc_inq_var(ncid, varid, NULL, xtypep, NULL, NULL, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find the number of dimensions of a variable. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param varid the variable ID. +//<<>> * @param ndimsp a pointer that will get the number of +//<<>> * dimensions. Ignored if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_varndims(int ncid, int varid, int *ndimsp) +//<<>>{ +//<<>> return GDALc_inq_var(ncid, varid, NULL, NULL, ndimsp, NULL, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find the dimension IDs associated with a variable. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param varid the variable ID. +//<<>> * @param dimidsp a pointer that will get an array of dimids. Ignored +//<<>> * if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_vardimid(int ncid, int varid, int *dimidsp) +//<<>>{ +//<<>> return GDALc_inq_var(ncid, varid, NULL, NULL, NULL, dimidsp, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Find the number of attributes associated with a variable. +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param varid the variable ID. +//<<>> * @param nattsp a pointer that will get the number of attriburtes. Ignored +//<<>> * if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_varnatts(int ncid, int varid, int *nattsp) +//<<>>{ +//<<>> return GDALc_inq_var(ncid, varid, NULL, NULL, NULL, NULL, nattsp); +//<<>>} + +/** + * The PIO-C interface for the GDAL function OGR_L_FindFieldIndex() + * + * This routine is called collectively by all tasks in the communicator + * ios.union_comm. + * + * @param ncid the ncid of the open file, obtained from + * GDALc_openfile() or GDALc_createfile(). + * @param name the field name. + * @param varidp a pointer that will get the variable id + * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling + * @ingroup PIO_inq_var_c + * @author Jim Edwards, Ed Hartnett + */ +int +GDALc_inq_fieldid(int ncid, const char *name, int *varidp) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int ierr; /* Return code from function calls. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ + + /* Get file info based on ncid. */ + if ((ierr = pio_get_file(ncid, &file))) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + ios = file->iosystem; + + /* Caller must provide name. */ + if (!name || strlen(name) > NC_MAX_NAME) + return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); + + PLOG((1, "GDALc_inq_varid ncid = %d name = %s", ncid, name)); + + if (ios->async) + { + if (!ios->ioproc) + { + int msg = PIO_MSG_INQ_VARID; + + if (ios->compmaster == MPI_ROOT) + mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); + + if (!mpierr) + mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); + int namelen; + namelen = strlen(name); + if (!mpierr) + mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); + } + + /* Handle MPI errors. */ + if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) + check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); + if (mpierr) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + } + + /* If this is an IO task, then call the netCDF function. */ + if (ios->ioproc) + { +#ifdef _PNETCDF + if (file->iotype == PIO_IOTYPE_PNETCDF) + ierr = ncmpi_inq_varid(file->fh, name, varidp); +#endif /* _PNETCDF */ + + if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) + ierr = nc_inq_varid(file->fh, name, varidp); + } + + /* Broadcast and check the return code. */ + if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if (ierr) + return check_netcdf(file, ierr, __FILE__, __LINE__); + + /* Broadcast results to all tasks. Ignore NULL parameters. */ + if (varidp) + if ((mpierr = MPI_Bcast(varidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) + check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + return PIO_NOERR; +} + +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_att. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID or NC_GLOBAL. +//<<>> * @param name name of the attribute. +//<<>> * @param eh non-zero to handle errors in the function. This will +//<<>> * cause program to halt if PIO error handler is set to INTERNAL. +//<<>> * @param xtypep a pointer that will get the type of the attribute. +//<<>> * @param lenp a pointer that will get the number of values +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_att_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_att_eh(int ncid, int varid, const char *name, int eh, +//<<>> nc_type *xtypep, PIO_Offset *lenp) +//<<>>{ +//<<>> int msg = PIO_MSG_INQ_ATT; +//<<>> iosystem_desc_t *ios; +//<<>> file_desc_t *file; +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> int ierr; +//<<>> +//<<>> /* Find file based on ncid. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_inq_att ncid = %d varid = %d", ncid, varid)); +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> char xtype_present = xtypep ? true : false; +//<<>> char len_present = lenp ? true : false; +//<<>> int namelen = strlen(name); +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&xtype_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&len_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&eh, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_inq_att(file->fh, varid, name, xtypep, lenp); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_inq_att(file->fh, varid, name, xtypep, (size_t *)lenp); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> PLOG((2, "GDALc_inq_att netcdf call %s returned %d eh %d", name,ierr,eh)); +//<<>> if (eh && ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results if call succeeded. */ +//<<>> if (!ierr) +//<<>> { +//<<>> if (xtypep) +//<<>> if ((mpierr = MPI_Bcast(xtypep, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (lenp) +//<<>> if ((mpierr = MPI_Bcast(lenp, 1, MPI_OFFSET, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> return ierr; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_att. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID or NC_GLOBAL. +//<<>> * @param name name of the attribute. +//<<>> * @param xtypep a pointer that will get the type of the attribute. +//<<>> * @param lenp a pointer that will get the number of values +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_att_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_att(int ncid, int varid, const char *name, nc_type *xtypep, +//<<>> PIO_Offset *lenp) +//<<>>{ +//<<>> return GDALc_inq_att_eh(ncid, varid, name, 1, xtypep, lenp); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the length of an attribute. +//<<>> * +//<<>> * @param ncid the ID of an open file. +//<<>> * @param varid the variable ID, or NC_GLOBAL for global attributes. +//<<>> * @param name the name of the attribute. +//<<>> * @param lenp a pointer that gets the lenght of the attribute +//<<>> * array. Ignored if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_attlen_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_attlen(int ncid, int varid, const char *name, PIO_Offset *lenp) +//<<>>{ +//<<>> return GDALc_inq_att(ncid, varid, name, NULL, lenp); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the type of an attribute. +//<<>> * +//<<>> * @param ncid the ID of an open file. +//<<>> * @param varid the variable ID, or NC_GLOBAL for global attributes. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtypep a pointer that gets the type of the +//<<>> * attribute. Ignored if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_atttype_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep) +//<<>>{ +//<<>> return GDALc_inq_att(ncid, varid, name, xtypep, NULL); +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_attname. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param attnum the attribute ID. +//<<>> * @param name the name of the attribute. +//<<>> * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling +//<<>> * @ingroup PIO_inq_attname_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_attname(int ncid, int varid, int attnum, char *name) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq_attname ncid = %d varid = %d attnum = %d", ncid, varid, +//<<>> attnum)); +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_ATTNAME; +//<<>> char name_present = name ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&attnum, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_inq_attname(file->fh, varid, attnum, name); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_inq_attname(file->fh, varid, attnum, name); +//<<>> PLOG((2, "GDALc_inq_attname netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if (name) +//<<>> { +//<<>> int namelen = strlen(name); +//<<>> if ((mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> /* Casting to void to avoid warnings on some compilers. */ +//<<>> if ((mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_attid. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name a pointer that will get name of attribute. Ignored if +//<<>> * NULL. +//<<>> * @param idp a pointer that will get the id of the variable or +//<<>> * attribute. Ignored if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling +//<<>> * @ingroup PIO_inq_attid_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_attid(int ncid, int varid, const char *name, int *idp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_inq_attid ncid = %d varid = %d name = %s", ncid, varid, name)); +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_ATTID; +//<<>> int namelen = strlen(name); +//<<>> char id_present = idp ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((char *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&id_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_inq_attid(file->fh, varid, name, idp); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_inq_attid(file->fh, varid, name, idp); +//<<>> PLOG((2, "GDALc_inq_attname netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results. */ +//<<>> if (idp) +//<<>> if ((mpierr = MPI_Bcast(idp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_rename_dim. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param dimid the dimension ID. +//<<>> * @param name the new name for the dimension. +//<<>> * @return PIO_NOERR for success, error code otherwise. See +//<<>> * @ingroup PIO_rename_dim_c +//<<>> * GDALc_Set_File_Error_Handling(). +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_rename_dim(int ncid, int dimid, const char *name) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_rename_dim ncid = %d dimid = %d name = %s", ncid, dimid, name)); +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_RENAME_DIM; /* Message for async notification. */ +//<<>> int namelen = strlen(name); +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&dimid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_rename_dim Bcast file->fh = %d dimid = %d namelen = %d name = %s", +//<<>> file->fh, dimid, namelen, name)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_rename_dim(file->fh, dimid, name); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_rename_dim(file->fh, dimid, name); +//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_rename_var. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the new name for the variable. +//<<>> * @return PIO_NOERR for success, error code otherwise. See +//<<>> * @ingroup PIO_rename_var_c +//<<>> * GDALc_Set_File_Error_Handling(). +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_rename_var(int ncid, int varid, const char *name) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_rename_var ncid = %d varid = %d name = %s", ncid, varid, name)); +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_RENAME_VAR; /* Message for async notification. */ +//<<>> int namelen = strlen(name); +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_rename_var Bcast file->fh = %d varid = %d namelen = %d name = %s", +//<<>> file->fh, varid, namelen, name)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_rename_var(file->fh, varid, name); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_rename_var(file->fh, varid, name); +//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_rename_att. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param newname the new name for the attribute. +//<<>> * @return PIO_NOERR for success, error code otherwise. See +//<<>> * @ingroup PIO_rename_att_c +//<<>> * GDALc_Set_File_Error_Handling(). +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_rename_att(int ncid, int varid, const char *name, +//<<>> const char *newname) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI functions. */ +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide names of correct length. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME || +//<<>> !newname || strlen(newname) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_rename_att ncid = %d varid = %d name = %s newname = %s", +//<<>> ncid, varid, name, newname)); +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_RENAME_ATT; /* Message for async notification. */ +//<<>> int namelen = strlen(name); +//<<>> int newnamelen = strlen(newname); +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((char *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&newnamelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((char *)newname, newnamelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_rename_att(file->fh, varid, name, newname); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_rename_att(file->fh, varid, name, newname); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((2, "GDALc_rename_att succeeded")); +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_del_att. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name of the attribute to delete. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_del_att_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_del_att(int ncid, int varid, const char *name) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI functions. */ +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_del_att ncid = %d varid = %d name = %s", ncid, varid, name)); +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_DEL_ATT; +//<<>> int namelen = strlen(name); /* Length of name string. */ +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((char *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_del_att(file->fh, varid, name); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_del_att(file->fh, varid, name); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_set_fill. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param fillmode either NC_FILL or NC_NOFILL. +//<<>> * @param old_modep a pointer to an int that gets the old setting. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_set_fill_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_set_fill(int ncid, int fillmode, int *old_modep) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI functions. */ +//<<>> +//<<>> PLOG((1, "GDALc_set_fill ncid = %d fillmode = %d", ncid, fillmode)); +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_SET_FILL; +//<<>> int old_modep_present = old_modep ? 1 : 0; +//<<>> +//<<>> PLOG((3, "GDALc_set_fill about to send msg %d", msg)); +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&fillmode, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&old_modep_present, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_set_fill sent ncid = %d fillmode = %d old_modep_present = %d", ncid, fillmode, +//<<>> old_modep_present)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> { +//<<>> PLOG((3, "about to call ncmpi_set_fill() fillmode = %d", fillmode)); +//<<>> ierr = ncmpi_set_fill(file->fh, fillmode, old_modep); +//<<>> } +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_set_fill(file->fh, fillmode, old_modep); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results. */ +//<<>> if (old_modep) +//<<>> { +//<<>> PLOG((2, "old_mode = %d", *old_modep)); +//<<>> if ((mpierr = MPI_Bcast(old_modep, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> PLOG((2, "GDALc_set_fill succeeded")); +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_enddef. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_enddef_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_enddef(int ncid) +//<<>>{ +//<<>> return pioc_change_def(ncid, 1); +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_redef. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_redef_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_redef(int ncid) +//<<>>{ +//<<>> return pioc_change_def(ncid, 0); +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_def_dim. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param name name of the dimension. +//<<>> * @param len length of the dimension. +//<<>> * @param idp a pointer that will get the id of the variable or attribute. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_def_dim_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_def_dim(int ncid, const char *name, PIO_Offset len, int *idp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_def_dim ncid = %d name = %s len = %d", ncid, name, len)); +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_DEF_DIM; +//<<>> int namelen = strlen(name); +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&len, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_def_dim(file->fh, name, len, idp); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_def_dim(file->fh, name, (size_t)len, idp); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if (idp) +//<<>> if ((mpierr = MPI_Bcast(idp , 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((2, "def_dim ierr = %d", ierr)); +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_def_var +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param name the variable name. +//<<>> * @param xtype the PIO_TYPE of the variable. +//<<>> * @param ndims the number of dimensions. +//<<>> * @param dimidsp pointer to array of dimension IDs. +//<<>> * @param varidp a pointer that will get the variable ID. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_def_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_def_var(int ncid, const char *name, nc_type xtype, int ndims, +//<<>> const int *dimidsp, int *varidp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int invalid_unlim_dim = 0; /* True invalid dims are used. */ +//<<>> int varid; /* The varid of the created var. */ +//<<>> int rec_var = 0; /* Non-zero if this var uses unlimited dim. */ +//<<>> PIO_Offset pio_type_size; /* Size of pio type in bytes. */ +//<<>> MPI_Datatype mpi_type; /* The correspoding MPI type. */ +//<<>> int mpi_type_size; /* Size of mpi type. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> +//<<>> /* Get the file information. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide name. */ +//<<>> if (!name || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_def_var ncid = %d name = %s xtype = %d ndims = %d", ncid, name, +//<<>> xtype, ndims)); +//<<>> +//<<>> /* Run this on all tasks if async is not in use, but only on +//<<>> * non-IO tasks if async is in use. Learn whether each dimension +//<<>> * is unlimited. */ +//<<>> if (!ios->async || !ios->ioproc) +//<<>> { +//<<>> int nunlimdims; +//<<>> +//<<>> /* Get size of type. */ +//<<>> if ((ierr = GDALc_inq_type(ncid, xtype, NULL, &pio_type_size))) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Get the MPI type corresponding with the PIO type. */ +//<<>> if ((ierr = find_mpi_type(xtype, &mpi_type, NULL))) +//<<>> return pio_err(ios, NULL, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Get the size of the MPI type. */ +//<<>> if(mpi_type == MPI_DATATYPE_NULL) +//<<>> mpi_type_size = 0; +//<<>> else +//<<>> if ((mpierr = MPI_Type_size(mpi_type, &mpi_type_size))) +//<<>> return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> /* How many unlimited dims are present in the file? */ +//<<>> if ((ierr = GDALc_inq_unlimdims(ncid, &nunlimdims, NULL))) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> if (nunlimdims) +//<<>> { +//<<>> int unlimdimids[nunlimdims]; +//<<>> +//<<>> /* Find the IDs of the unlimited dimension(s). */ +//<<>> if ((ierr = GDALc_inq_unlimdims(ncid, NULL, unlimdimids))) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Check each dimid for this variable to see it it is an +//<<>> * unlimited dimension. */ +//<<>> for (int d = 0; d < ndims; d++) +//<<>> { +//<<>> int unlim_found = 0; +//<<>> +//<<>> /* Check against each unlimited dimid. */ +//<<>> for (int ud = 0; ud < nunlimdims; ud++) +//<<>> { +//<<>> if (dimidsp[d] == unlimdimids[ud]) +//<<>> { +//<<>> unlim_found++; +//<<>> break; +//<<>> } +//<<>> } +//<<>> +//<<>> /* Only first dim may be unlimited, for PIO. */ +//<<>> if (unlim_found) +//<<>> { +//<<>> if (d == 0) +//<<>> rec_var++; +//<<>> else +//<<>> invalid_unlim_dim++; +//<<>> } +//<<>> } +//<<>> } +//<<>> } +//<<>> +//<<>> /* If using async, and not an IO task, then send parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_DEF_VAR; +//<<>> int namelen = strlen(name); +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&(ncid), 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ndims, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast((void *)dimidsp, ndims, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast values currently only known on computation tasks to IO tasks. */ +//<<>> if ((mpierr = MPI_Bcast(&rec_var, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast(&invalid_unlim_dim, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast(&pio_type_size, 1, MPI_OFFSET, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast(&mpi_type, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast(&mpi_type_size, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* Check that only one unlimited dim is specified, and that it is +//<<>> * first. */ +//<<>> if (invalid_unlim_dim) +//<<>> return PIO_EINVAL; +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> ierr = ncmpi_def_var(file->fh, name, xtype, ndims, dimidsp, &varid); +//<<>>#endif /* _PNETCDF */ +//<<>> +//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +//<<>> ierr = nc_def_var(file->fh, name, xtype, ndims, dimidsp, &varid); +//<<>> PLOG((3, "defined var ierr %d file->iotype %d", ierr, file->iotype)); +//<<>> +//<<>>#ifdef _NETCDF4 +//<<>> /* For netCDF-4 parallel files, set parallel access to collective. */ +//<<>> if (!ierr && file->iotype == PIO_IOTYPE_NETCDF4P) +//<<>> ierr = nc_var_par_access(file->fh, varid, NC_COLLECTIVE); +//<<>>#endif /* _NETCDF4 */ +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results. */ +//<<>> if ((mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (varidp) +//<<>> *varidp = varid; +//<<>> +//<<>> /* Add to the list of var_desc_t structs for this file. */ +//<<>> if ((ierr = add_to_varlist(varid, rec_var, xtype, (int)pio_type_size, mpi_type, +//<<>> mpi_type_size, ndims, &file->varlist))) +//<<>> return pio_err(ios, NULL, ierr, __FILE__, __LINE__); +//<<>> file->nvars++; +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * Set the fill value for a variable. +//<<>> * +//<<>> * See the > * href="http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html">netCDF +//<<>> * variable documentation for details about the operation of this +//<<>> * function. +//<<>> * +//<<>> * When the fill mode for the file is NC_FILL, then fill values are +//<<>> * used for missing data. This function sets the fill value to be used +//<<>> * for a variable. If no specific fill value is set (as a _FillValue +//<<>> * attribute), then the default fill values from netcdf.h are used. +//<<>> * +//<<>> * NetCDF-4 and pnetcdf files allow setting fill_mode (to NC_FILL or +//<<>> * NC_NOFILL) on a per-variable basis. NetCDF classic only allows the +//<<>> * fill_mode setting to be set for the whole file. For this function, +//<<>> * the fill_mode parameter is ignored for classic files. Set the +//<<>> * file-level fill mode with GDALc_set_fill(). +//<<>> * +//<<>> * @param ncid the ncid of the open file. +//<<>> * @param varid the ID of the variable to set chunksizes for. +//<<>> * @param fill_mode fill mode for this variable (NC_FILL or NC_NOFILL) +//<<>> * @param fill_valuep pointer to the fill value to be used if fill_mode is set to NC_FILL. +//<<>> * @return PIO_NOERR for success, otherwise an error code. +//<<>> * @ingroup PIO_def_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_def_var_fill(int ncid, int varid, int fill_mode, const void *fill_valuep) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> nc_type xtype; /* The type of the variable (and fill value att). */ +//<<>> PIO_Offset type_size; /* Size in bytes of this variable's type. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>> PLOG((1, "GDALc_def_var_fill ncid = %d varid = %d fill_mode = %d\n", ncid, varid, +//<<>> fill_mode)); +//<<>> +//<<>> /* Get the file info. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* Caller must provide correct values. */ +//<<>> if ((fill_mode != NC_FILL && fill_mode != NC_NOFILL) || +//<<>> (fill_mode == NC_FILL && !fill_valuep)) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> /* Run this on all tasks if async is not in use, but only on +//<<>> * non-IO tasks if async is in use. Get the size of this vars +//<<>> * type. */ +//<<>> if (!ios->async || !ios->ioproc) +//<<>> { +//<<>> if ((ierr = GDALc_inq_vartype(ncid, varid, &xtype))) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> if ((ierr = GDALc_inq_type(ncid, xtype, NULL, &type_size))) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> PLOG((2, "GDALc_def_var_fill type_size = %d", type_size)); +//<<>> } +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_DEF_VAR_FILL; +//<<>> char fill_value_present = fill_valuep ? true : false; +//<<>> +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&fill_mode, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&fill_value_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr && fill_value_present) +//<<>> mpierr = MPI_Bcast((PIO_Offset *)fill_valuep, type_size, MPI_CHAR, ios->compmaster, +//<<>> ios->intercomm); +//<<>> PLOG((2, "GDALc_def_var_fill ncid = %d varid = %d fill_mode = %d type_size = %d fill_value_present = %d", +//<<>> ncid, varid, fill_mode, type_size, fill_value_present)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast values currently only known on computation tasks to IO tasks. */ +//<<>> if ((mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> if (ios->ioproc) +//<<>> { +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> ierr = ncmpi_def_var_fill(file->fh, varid, fill_mode, (void *)fill_valuep); +//<<>>#endif /* _PNETCDF */ +//<<>> } +//<<>> else if (file->iotype == PIO_IOTYPE_NETCDF) +//<<>> { +//<<>> PLOG((2, "defining fill value attribute for netCDF classic file")); +//<<>> if (file->do_io) +//<<>> { +//<<>> ierr = nc_set_fill(file->fh, NC_FILL, NULL); +//<<>> if (!ierr) +//<<>> ierr = nc_put_att(file->fh, varid, _FillValue, xtype, 1, fill_valuep); +//<<>> } +//<<>> } +//<<>> else +//<<>> { +//<<>>#ifdef _NETCDF4 +//<<>> if (file->do_io) +//<<>> ierr = nc_def_var_fill(file->fh, varid, fill_mode, fill_valuep); +//<<>>#endif +//<<>> } +//<<>> PLOG((2, "after def_var_fill ierr = %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * The PIO-C interface for the NetCDF function nc_inq_var_fill. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand +//<<>> * please read about this function in the NetCDF documentation at: +//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param no_fill a pointer to int that will get the fill +//<<>> * mode. Ignored if NULL (except with pnetcdf, which seg-faults with +//<<>> * NULL.) +//<<>> * @param fill_valuep pointer to space that gets the fill value for +//<<>> * this variable. Ignored if NULL. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @ingroup PIO_inq_var_c +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_inq_var_fill(int ncid, int varid, int *no_fill, void *fill_valuep) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> nc_type xtype; /* Type of variable and its _FillValue attribute. */ +//<<>> PIO_Offset type_size; /* Size in bytes of this variable's type. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> int ierr = PIO_NOERR; /* Return code from function calls. */ +//<<>> +//<<>> PLOG((1, "GDALc_inq_var_fill ncid = %d varid = %d", ncid, varid)); +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> PLOG((2, "found file")); +//<<>> +//<<>> /* Run this on all tasks if async is not in use, but only on +//<<>> * non-IO tasks if async is in use. Get the size of this vars +//<<>> * type. */ +//<<>> if (!ios->async || !ios->ioproc) +//<<>> { +//<<>> if ((ierr = GDALc_inq_vartype(ncid, varid, &xtype))) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> if ((ierr = GDALc_inq_type(ncid, xtype, NULL, &type_size))) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> PLOG((2, "GDALc_inq_var_fill type_size = %d", type_size)); +//<<>> } +//<<>> +//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ +//<<>> if (ios->async) +//<<>> { +//<<>> if (!ios->ioproc) +//<<>> { +//<<>> int msg = PIO_MSG_INQ_VAR_FILL; +//<<>> char no_fill_present = no_fill ? true : false; +//<<>> char fill_value_present = fill_valuep ? true : false; +//<<>> +//<<>> PLOG((2, "sending msg type_size = %d", type_size)); +//<<>> if (ios->compmaster == MPI_ROOT) +//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); +//<<>> +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&no_fill_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> if (!mpierr) +//<<>> mpierr = MPI_Bcast(&fill_value_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//<<>> PLOG((2, "GDALc_inq_var_fill ncid = %d varid = %d type_size = %lld no_fill_present = %d fill_value_present = %d", +//<<>> ncid, varid, type_size, no_fill_present, fill_value_present)); +//<<>> } +//<<>> +//<<>> /* Handle MPI errors. */ +//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//<<>> if (mpierr) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast values currently only known on computation tasks to IO tasks. */ +//<<>> if ((mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if ((mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->comproot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> } +//<<>> +//<<>> /* If this is an IO task, then call the netCDF function. */ +//<<>> if (ios->ioproc) +//<<>> { +//<<>> PLOG((2, "calling inq_var_fill file->iotype = %d file->fh = %d varid = %d", +//<<>> file->iotype, file->fh, varid)); +//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) +//<<>> { +//<<>>#ifdef _PNETCDF +//<<>> ierr = ncmpi_inq_var_fill(file->fh, varid, no_fill, fill_valuep); +//<<>>#endif /* _PNETCDF */ +//<<>> } +//<<>> else if (file->iotype == PIO_IOTYPE_NETCDF && file->do_io) +//<<>> { +//<<>> /* Get the file-level fill mode. */ +//<<>> if (no_fill) +//<<>> { +//<<>> if (file->writable) +//<<>> { +//<<>> ierr = nc_set_fill(file->fh, NC_NOFILL, no_fill); +//<<>> if (!ierr) +//<<>> ierr = nc_set_fill(file->fh, *no_fill, NULL); +//<<>> } +//<<>> else +//<<>> { +//<<>> /* pnetcdf and netCDF-4 return PIO_FILL for read-only +//<<>> * files. */ +//<<>> *no_fill = PIO_FILL; +//<<>> } +//<<>> } +//<<>> +//<<>> if (!ierr && fill_valuep) +//<<>> { +//<<>> ierr = nc_get_att(file->fh, varid, _FillValue, fill_valuep); +//<<>> if (ierr == NC_ENOTATT) +//<<>> { +//<<>> char char_fill_value = NC_FILL_CHAR; +//<<>> signed char byte_fill_value = NC_FILL_BYTE; +//<<>> short short_fill_value = NC_FILL_SHORT; +//<<>> int int_fill_value = NC_FILL_INT; +//<<>> float float_fill_value = NC_FILL_FLOAT; +//<<>> double double_fill_value = NC_FILL_DOUBLE; +//<<>> switch (xtype) +//<<>> { +//<<>> case NC_BYTE: +//<<>> memcpy(fill_valuep, &byte_fill_value, sizeof(signed char)); +//<<>> break; +//<<>> case NC_CHAR: +//<<>> memcpy(fill_valuep, &char_fill_value, sizeof(char)); +//<<>> break; +//<<>> case NC_SHORT: +//<<>> memcpy(fill_valuep, &short_fill_value, sizeof(short)); +//<<>> break; +//<<>> case NC_INT: +//<<>> memcpy(fill_valuep, &int_fill_value, sizeof(int)); +//<<>> break; +//<<>> case NC_FLOAT: +//<<>> memcpy(fill_valuep, &float_fill_value, sizeof(float)); +//<<>> break; +//<<>> case NC_DOUBLE: +//<<>> memcpy(fill_valuep, &double_fill_value, sizeof(double)); +//<<>> break; +//<<>> default: +//<<>> return pio_err(ios, file, NC_EBADTYPE, __FILE__, __LINE__); +//<<>> } +//<<>> ierr = PIO_NOERR; +//<<>> } +//<<>> } +//<<>> } +//<<>> else +//<<>> { +//<<>>#ifdef _NETCDF4 +//<<>> /* The inq_var_fill is not supported in classic-only builds. */ +//<<>> if (file->do_io) +//<<>> ierr = nc_inq_var_fill(file->fh, varid, no_fill, fill_valuep); +//<<>>#endif /* _NETCDF */ +//<<>> } +//<<>> PLOG((2, "after call to inq_var_fill, ierr = %d", ierr)); +//<<>> } +//<<>> +//<<>> /* Broadcast and check the return code. */ +//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (ierr) +//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>> +//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>> if (no_fill) +//<<>> if ((mpierr = MPI_Bcast(no_fill, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> if (fill_valuep) +//<<>> if ((mpierr = MPI_Bcast(fill_valuep, type_size, MPI_CHAR, ios->ioroot, ios->my_comm))) +//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} +//<<>> +//<<>>/** +//<<>> * @addtogroup PIO_get_att_c Get Attribute Values +//<<>> * Get the values stored in an attribute in C. +//<<>> * @{ +//<<>> */ +//<<>> +//<<>>/** +//<<>> * Get the value of an attribute of any type, with no type conversion. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att(int ncid, int varid, const char *name, void *ip) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> nc_type atttype; /* The type of the attribute. */ +//<<>> +//<<>> /* Find the info about this file. */ +//<<>> if ((ierr = pio_get_file(ncid, &file))) +//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); +//<<>> ios = file->iosystem; +//<<>> +//<<>> /* User must provide a name and destination pointer. */ +//<<>> if (!name || !ip || strlen(name) > NC_MAX_NAME) +//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); +//<<>> +//<<>> PLOG((1, "GDALc_get_att ncid %d varid %d name %s", ncid, varid, name)); +//<<>> +//<<>> /* Get the type of the attribute. */ +//<<>> if ((ierr = GDALc_inq_att(ncid, varid, name, &atttype, NULL))) +//<<>> return ierr; +//<<>> PLOG((2, "atttype = %d", atttype)); +//<<>> +//<<>> return GDALc_get_att_tc(ncid, varid, name, atttype, ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 64-bit floating point array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_double(int ncid, int varid, const char *name, double *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_DOUBLE, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 8-bit unsigned char array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_uchar(int ncid, int varid, const char *name, unsigned char *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_UBYTE, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 16-bit unsigned integer array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_ushort(int ncid, int varid, const char *name, unsigned short *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_USHORT, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 32-bit unsigned integer array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_uint(int ncid, int varid, const char *name, unsigned int *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_UINT, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 32-bit ingeger array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_long(int ncid, int varid, const char *name, long *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_LONG_INTERNAL, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an text attribute. There is no type conversion +//<<>> * with this call. If the attribute is not of type NC_CHAR, then an +//<<>> * error will be returned. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_text(int ncid, int varid, const char *name, char *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_CHAR, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 8-bit signed char array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_schar(int ncid, int varid, const char *name, signed char *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_BYTE, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 64-bit unsigned integer array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_ulonglong(int ncid, int varid, const char *name, unsigned long long *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_UINT64, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 16-bit integer array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_short(int ncid, int varid, const char *name, short *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_SHORT, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 32-bit integer array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_int(int ncid, int varid, const char *name, int *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_INT, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 64-bit integer array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_longlong(int ncid, int varid, const char *name, long long *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_INT64, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Get the value of an 32-bit floating point array attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute to get +//<<>> * @param ip a pointer that will get the attribute value. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_get_att_float(int ncid, int varid, const char *name, float *ip) +//<<>>{ +//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_FLOAT, (void *)ip); +//<<>>} +//<<>> +//<<>>/** +//<<>> * @} +//<<>> */ +//<<>> +//<<>>/** +//<<>> * @addtogroup PIO_put_att_c Write an Attribute +//<<>> * Create an attribute in C. +//<<>> * @{ +//<<>> */ +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute of any type. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const void *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, xtype, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 8-bit signed chars. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_schar(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const signed char *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_BYTE, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 32-bit signed integers. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_long(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const long *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_LONG_INTERNAL, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 32-bit signed integers. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_int(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const int *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_INT, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 8-bit unsigned chars. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_uchar(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const unsigned char *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_UBYTE, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 64-bit signed integers. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_longlong(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const long long *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_INT64, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 32-bit unsigned integers. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_uint(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const unsigned int *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_UINT, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 32-bit floating points. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_float(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const float *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_FLOAT, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 64-bit unsigned integers. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_ulonglong(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const unsigned long long *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_UINT64, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 16-bit unsigned integers. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_ushort(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const unsigned short *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_USHORT, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF text attribute. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_text(int ncid, int varid, const char *name, +//<<>> PIO_Offset len, const char *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, NC_CHAR, len, NC_CHAR, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 16-bit integers. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_short(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const short *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_SHORT, op); +//<<>>} +//<<>> +//<<>>/** +//<<>> * Write a netCDF attribute array of 64-bit floating points. +//<<>> * +//<<>> * This routine is called collectively by all tasks in the communicator +//<<>> * ios.union_comm. +//<<>> * +//<<>> * @param ncid the ncid of the open file, obtained from +//<<>> * GDALc_openfile() or GDALc_createfile(). +//<<>> * @param varid the variable ID. +//<<>> * @param name the name of the attribute. +//<<>> * @param xtype the nc_type of the attribute. +//<<>> * @param len the length of the attribute array. +//<<>> * @param op a pointer with the attribute data. +//<<>> * @return PIO_NOERR for success, error code otherwise. +//<<>> * @author Jim Edwards, Ed Hartnett +//<<>> */ +//<<>>int +//<<>>GDALc_put_att_double(int ncid, int varid, const char *name, nc_type xtype, +//<<>> PIO_Offset len, const double *op) +//<<>>{ +//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_DOUBLE, op); +//<<>>} +/** + * @} + */ diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c new file mode 100644 index 0000000000..cc5d25b7f8 --- /dev/null +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c @@ -0,0 +1,308 @@ +#include +#include +#include +#include + +/** + * The PIO-C interface for the GDAL function OGR_L_FindFieldIndex() + * + * This routine is called collectively by all tasks in the communicator + * ios.union_comm. + * + * @param ncid the ncid of the open file, obtained from + * GDALc_openfile() or GDALc_createfile(). + * @param name the field name. + * @param varidp a pointer that will get the variable id + * @return PIO_NOERR for success, error code otherwise. <> + * @ingroup PIO_inq_var_c + * @author Michael Long (adapted from Jim Edwards, Ed Hartnett) + */ +int +GDALc_inq_fieldid(int ncid, const char *name, int *varidp) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int ierr; /* Return code from function calls. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ + + /* Get file info based on ncid. */ + if ((ierr = pio_get_file(ncid, &file))) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + ios = file->iosystem; + + /* Caller must provide name. */ + if (!name || strlen(name) > NC_MAX_NAME) + return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); + + PLOG((1, "GDALc_inq_varid ncid = %d name = %s", ncid, name)); + + if (ios->async) + { + if (!ios->ioproc) + { + int msg = PIO_MSG_INQ_VARID; + + if (ios->compmaster == MPI_ROOT) + mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); + + if (!mpierr) + mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); + int namelen; + namelen = strlen(name); + if (!mpierr) + mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); + } + + /* Handle MPI errors. */ + if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) + check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); + if (mpierr) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + } + + /* If this is an IO task, then call the netCDF function. */ + if (ios->ioproc) + { +#ifdef _PNETCDF + if (file->iotype == PIO_IOTYPE_PNETCDF) + ierr = ncmpi_inq_varid(file->fh, name, varidp); +#endif /* _PNETCDF */ + + if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) + ierr = nc_inq_varid(file->fh, name, varidp); + } + + /* Broadcast and check the return code. */ + if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if (ierr) + return check_netcdf(file, ierr, __FILE__, __LINE__); + + /* Broadcast results to all tasks. Ignore NULL parameters. */ + if (varidp) + if ((mpierr = MPI_Bcast(varidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) + check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + return PIO_NOERR; +} + +int +GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filename, bool mode) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int imode; /* Internal mode val for netcdf4 file open. */ + int nvars = 0; + int *rec_var = NULL; + int *pio_type = NULL; + int *pio_type_size = NULL; + MPI_Datatype *mpi_type = NULL; + int *mpi_type_size = NULL; + int *ndims = NULL; + int mpierr = MPI_SUCCESS, mpierr2; /** Return code from MPI function codes. */ + int ierr = PIO_NOERR; /* Return code from function calls. */ + +#ifdef USE_MPE + pio_start_mpe_log(OPEN); +#endif /* USE_MPE */ + + /* Get the IO system info from the iosysid. */ + if (!(ios = pio_get_iosystem_from_id(iosysid))) + return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); + + /* User must provide valid input for these parameters. */ + if (!hDSp || !iotype || !filename) + return pio_err(ios, NULL, PIO_EINVAL, __FILE__, __LINE__); + if (*iotype != PIO_IOTYPE_GDAL ) + return pio_err(ios, NULL, PIO_EINVAL, __FILE__, __LINE__); + +// PLOG((2, "PIOc_openfile_retry iosysid = %d iotype = %d filename = %s mode = %d retry = %d", +// iosysid, *iotype, filename, mode, retry)); + + /* Allocate space for the file info. */ + if (!(file = calloc(sizeof(*file), 1))) + return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); + + /* Fill in some file values. */ + file->fh = -1; + file->iotype = *iotype; + file->iosystem = ios; + file->writable = (mode & PIO_WRITE) ? 1 : 0; + + /* Set to true if this task should participate in IO (only true + * for one task with netcdf serial files. */ + if (file->iotype == PIO_IOTYPE_GDAL || + ios->io_rank == 0) + file->do_io = 1; + + /* If async is in use, and this is not an IO task, bcast the parameters. */ + if (ios->async) + { + int msg = PIO_MSG_OPEN_FILE; + size_t len = strlen(filename); + + if (!ios->ioproc) + { + /* Send the message to the message handler. */ + if (ios->compmaster == MPI_ROOT) + mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); + + /* Send the parameters of the function call. */ + if (!mpierr) + mpierr = MPI_Bcast(&len, 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast((void *)filename, len + 1, MPI_CHAR, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast(&file->iotype, 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast(&mode, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&use_ext_ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); + } + + /* Handle MPI errors. */ + if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) + return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); + if (mpierr) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + } + + /* If this is an IO task, then call the netCDF function. */ + if (ios->ioproc) + { + switch (file->iotype) + { + case PIO_IOTYPE_NETCDF: + if (ios->io_rank == 0) + { +//>> if ((ierr = nc_open(filename, mode, &file->fh))) + break; + ierr = inq_file_metadata(file, file->fh, PIO_IOTYPE_NETCDF, + &nvars, &rec_var, &pio_type, + &pio_type_size, &mpi_type, + &mpi_type_size, &ndims); + PLOG((2, "PIOc_openfile_retry:nc_open for classic filename = %s mode = %d " + "ierr = %d", filename, mode, ierr)); + } + break; + + default: + return pio_err(ios, file, PIO_EBADIOTYPE, __FILE__, __LINE__); + } + + } + + /* Broadcast and check the return code. */ + if (ios->ioroot == ios->union_rank) + PLOG((2, "Bcasting error code ierr %d ios->ioroot %d ios->my_comm %d", + ierr, ios->ioroot, ios->my_comm)); + if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + PLOG((2, "Bcast openfile_retry error code ierr = %d", ierr)); + + /* If there was an error, free allocated memory and deal with the error. */ + if (ierr) + { + free(file); + return check_netcdf2(ios, NULL, ierr, __FILE__, __LINE__); + } + + /* Broadcast writability to all tasks. */ + if ((mpierr = MPI_Bcast(&file->writable, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + /* Broadcast some values to all tasks from io root. */ +//>> if (ios->async) +//>> { +//>> PLOG((3, "open bcasting pio_next_ncid %d ios->ioroot %d", pio_next_ncid, ios->ioroot)); +//>> if ((mpierr = MPI_Bcast(&pio_next_ncid, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> } + + if ((mpierr = MPI_Bcast(&nvars, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + /* Non io tasks need to allocate to store info about variables. */ + if (nvars && !rec_var) + { + if (!(rec_var = malloc(nvars * sizeof(int)))) + return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); + if (!(pio_type = malloc(nvars * sizeof(int)))) + return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); + if (!(pio_type_size = malloc(nvars * sizeof(int)))) + return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); + if (!(mpi_type = malloc(nvars * sizeof(MPI_Datatype)))) + return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); + if (!(mpi_type_size = malloc(nvars * sizeof(int)))) + return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); + if (!(ndims = malloc(nvars * sizeof(int)))) + return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); + } + if (nvars) + { + if ((mpierr = MPI_Bcast(rec_var, nvars, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Bcast(pio_type, nvars, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Bcast(pio_type_size, nvars, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Bcast(mpi_type, nvars*(int)(sizeof(MPI_Datatype)/sizeof(int)), MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Bcast(mpi_type_size, nvars, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Bcast(ndims, nvars, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + } + + { + /* Create the ncid that the user will see. This is necessary + * because otherwise ncids will be reused if files are opened + * on multiple iosystems. */ +//>>>>>>>>>> file->pio_ncid = pio_next_ncid++; + + /* Return the PIO ncid to the user. */ +//>>>>>>>>>> *ncidp = file->pio_ncid; + } + + /* Add this file to the list of currently open files. */ + pio_add_to_file_list(file); + + /* Add info about the variables to the file_desc_t struct. */ + for (int v = 0; v < nvars; v++) + if ((ierr = add_to_varlist(v, rec_var[v], pio_type[v], pio_type_size[v], + mpi_type[v], mpi_type_size[v], ndims[v], + &file->varlist))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + file->nvars = nvars; + + /* Free resources. */ + if (nvars) + { + if (rec_var) + free(rec_var); + if (pio_type) + free(pio_type); + if (pio_type_size) + free(pio_type_size); + if (mpi_type) + free(mpi_type); + if (mpi_type_size) + free(mpi_type_size); + if (ndims) + free(ndims); + } + +#ifdef USE_MPE + pio_stop_mpe_log(OPEN, __func__); +#endif /* USE_MPE */ + PLOG((2, "Opened file %s file->pio_ncid = %d file->fh = %d ierr = %d", + filename, file->pio_ncid, file->fh, ierr)); + + return ierr; +} + +/** + * @} + */ diff --git a/src/Infrastructure/IO/PIO/makefile b/src/Infrastructure/IO/PIO/makefile index de0b38fb8d..4f7d64a002 100644 --- a/src/Infrastructure/IO/PIO/makefile +++ b/src/Infrastructure/IO/PIO/makefile @@ -34,6 +34,10 @@ else PIO_CONF_OPTS += --disable-pnetcdf endif +ifdef ESMF_GDAL_LIBPATH + GDAL_Found=true + PIO_CMAKE_OPTS += -DGDAL_INCLUDE_DIR=$(ESMF_GDAL_INCLUDE) -DGDAL_LIBRARY=$(ESMF_GDAL_LIBPATH)/libgdal.so +endif ifndef PIO_AUTOTOOLS_BUILD # Use the PIO native cmake build system to build and install diff --git a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h index 9f77c4ba17..bcda660935 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h @@ -148,7 +148,7 @@ enum GDAL_REARRANGERS int GDALc_finalize(int instance); int GDALc_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp); - int GDALc_inq_fieldid(OGRDataSourceH hDS, const char *name, int *varidp); +//<<>> int GDALc_inq_fieldid(OGRDataSourceH hDS, const char *name, int *varidp); int GDALc_inq_field(int ncid, int varid, char *name, int *xtypep, int *ndimsp, int *dimidsp, int *nattsp); int GDALc_inq_vardimid(int ncid, int varid, int *dimidsp); @@ -156,7 +156,7 @@ enum GDAL_REARRANGERS int GDALc_deletefile(int iosysid, const char *filename); int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char *fname, bool mode); int GDALc_create(int iosysid, const char *path, int cmode, int *ncidp); - int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *fname, bool mode); +// int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *fname, bool mode); int GDALc_open(int iosysid, const char *path, int mode, int *ncidp); int GDALc_closefile(int ncid); diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index a25dd9a096..2fcf78d57f 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -630,7 +630,7 @@ void GDAL_Handler::arrayReadOneTileFile( PRINTMSG("Field " << fieldname.c_str()); PRINTMSG("NLayers 1: " << OGR_DS_GetLayerCount(filedesc)); - gdalrc = GDALc_inq_fieldid(filedesc, fieldname.c_str(), &fielddesc); +//<<>> gdalrc = GDALc_inq_fieldid(filedesc, fieldname.c_str(), &fielddesc); // An error here means the variable is not in the file if (gdalrc == -1) { PRINTMSG("Field " << fieldname.c_str() << " not found in file"); diff --git a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C index 393ea51132..0922fe9edd 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C @@ -294,75 +294,75 @@ int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char return ret; } -int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filename, - bool mode) -{ -//>> PLOG((1, "PIOc_openfile iosysid %d *iotype %d filename %s mode %d", iosysid, -//>> iotype ? *iotype: 0, filename, mode)); - OGRRegisterAll(); - OGRDataSourceH hDx = OGROpen( filename, FALSE, NULL ); - PRINTMSG("NLayers -3: " << OGR_DS_GetLayerCount(hDx) << " file: " << filename ); - PRINTMSG("NLayers -2: " << GDALDatasetGetLayerCount(hDx)); - OGR_DS_Destroy(hDx); - *hDSp = OGROpen( filename, FALSE, NULL ); - PRINTMSG("NLayers -1: " << OGR_DS_GetLayerCount(*hDSp)); - if( hDSp == NULL ) - { - if (ESMC_LogDefault.MsgFoundError(ESMF_RC_NOT_FOUND, "Open GDAL file failed", ESMC_CONTEXT, 0)) - return ESMF_RC_NOT_FOUND; - } -return 0; -} - -int GDALc_inq_fieldid(OGRDataSourceH hDS, const char *name, int *varidp) -{ - iosystem_desc_t *ios; /* Pointer to io system information. */ - file_desc_t *file; /* Pointer to file information. */ - int ierr; /* Return code from function calls. */ - int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ - -//>> PLOG((1, "PIOc_inq_varid ncid = %d name = %s", ncid, name)); - -#undef ESMC_METHOD -#define ESMC_METHOD "IO_GDAL::GDALc_inq_fieldid" - - if (hDS == NULL) { - PRINTMSG("DataSource is NULL"); - return -1; - } else { - PRINTMSG("DataSource is GOOD"); - printf("hDS %p\n",(void *)hDS); - } - - PRINTPOS; - PRINTMSG("NLayers: " << OGR_DS_GetLayerCount(hDS)); - OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); - PRINTPOS; - OGR_L_ResetReading(hLayer); - PRINTPOS; - if (hLayer == NULL) { - PRINTMSG("Layer is NULL"); - return -1; - } - *varidp = OGR_L_FindFieldIndex(hLayer,name,1); - - PRINTMSG("INQ_FIELDID FIELD " << name << " INDEX: " << *varidp); - - return *varidp; - -//>> /* Broadcast and check the return code. */ -//>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//>> if (ierr) -//>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//>> -//>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//>> if (varidp) -//>> if ((mpierr = MPI_Bcast(varidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); - - return PIO_NOERR; -} +//<<>>int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filename, +//<<>> bool mode) +//<<>>{ +//<<>>//>> PLOG((1, "PIOc_openfile iosysid %d *iotype %d filename %s mode %d", iosysid, +//<<>>//>> iotype ? *iotype: 0, filename, mode)); +//<<>> OGRRegisterAll(); +//<<>> OGRDataSourceH hDx = OGROpen( filename, FALSE, NULL ); +//<<>> PRINTMSG("NLayers -3: " << OGR_DS_GetLayerCount(hDx) << " file: " << filename ); +//<<>> PRINTMSG("NLayers -2: " << GDALDatasetGetLayerCount(hDx)); +//<<>> OGR_DS_Destroy(hDx); +//<<>> *hDSp = OGROpen( filename, FALSE, NULL ); +//<<>> PRINTMSG("NLayers -1: " << OGR_DS_GetLayerCount(*hDSp)); +//<<>> if( hDSp == NULL ) +//<<>> { +//<<>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_NOT_FOUND, "Open GDAL file failed", ESMC_CONTEXT, 0)) +//<<>> return ESMF_RC_NOT_FOUND; +//<<>> } +//<<>>return 0; +//<<>>} + +//<<>>int GDALc_inq_fieldid(OGRDataSourceH hDS, const char *name, int *varidp) +//<<>>{ +//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//<<>> file_desc_t *file; /* Pointer to file information. */ +//<<>> int ierr; /* Return code from function calls. */ +//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ +//<<>> +//<<>>//>> PLOG((1, "PIOc_inq_varid ncid = %d name = %s", ncid, name)); +//<<>> +//<<>>#undef ESMC_METHOD +//<<>>#define ESMC_METHOD "IO_GDAL::GDALc_inq_fieldid" +//<<>> +//<<>> if (hDS == NULL) { +//<<>> PRINTMSG("DataSource is NULL"); +//<<>> return -1; +//<<>> } else { +//<<>> PRINTMSG("DataSource is GOOD"); +//<<>> printf("hDS %p\n",(void *)hDS); +//<<>> } +//<<>> +//<<>> PRINTPOS; +//<<>> PRINTMSG("NLayers: " << OGR_DS_GetLayerCount(hDS)); +//<<>> OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); +//<<>> PRINTPOS; +//<<>> OGR_L_ResetReading(hLayer); +//<<>> PRINTPOS; +//<<>> if (hLayer == NULL) { +//<<>> PRINTMSG("Layer is NULL"); +//<<>> return -1; +//<<>> } +//<<>> *varidp = OGR_L_FindFieldIndex(hLayer,name,1); +//<<>> +//<<>> PRINTMSG("INQ_FIELDID FIELD " << name << " INDEX: " << *varidp); +//<<>> +//<<>> return *varidp; +//<<>> +//<<>>//>> /* Broadcast and check the return code. */ +//<<>>//>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>>//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>>//>> if (ierr) +//<<>>//>> return check_netcdf(file, ierr, __FILE__, __LINE__); +//<<>>//>> +//<<>>//>> /* Broadcast results to all tasks. Ignore NULL parameters. */ +//<<>>//>> if (varidp) +//<<>>//>> if ((mpierr = MPI_Bcast(varidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//<<>>//>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//<<>> +//<<>> return PIO_NOERR; +//<<>>} int GDALc_inq_timeid(OGRDataSourceH hDS, int *timeid) { // Is there a field of type OFTDate, OFTTime, or OFTDateTime? From bf3670b84cc2f855db26a1bd47a354fe7b757280 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Tue, 26 Sep 2023 20:52:41 -0400 Subject: [PATCH 17/58] Continuted development. To the point where we want to start reading the data directly. -- Need to map from Shapefile features to Mesh elements when features < elements (as in the case with Multipolygons) -- What is going on with start/count in PIOc_InitDecomp()? --- gisDev.org | 12 + .../IO/PIO/ParallelIO/src/clib/pio.h | 19 +- .../IO/PIO/ParallelIO/src/clib/pio_darray.c | 4 + .../IO/PIO/ParallelIO/src/clib/pio_file.c | 4 + .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 552 +++++++++++++++++- .../IO/PIO/ParallelIO/src/clib/pioc_support.c | 3 + .../IO/include/ESMCI_GDAL_Handler.h | 6 +- src/Infrastructure/IO/include/ESMCI_IO_GDAL.h | 1 - .../IO/src/ESMCI_GDAL_Handler.C | 115 ++-- src/Infrastructure/IO/src/ESMCI_IO_GDAL.C | 22 - src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 2 +- .../IO/tests/ESMCI_IO_PIOUTest.C | 2 + .../IO/tests/ESMF_IO_GDALUTest.F90 | 4 +- src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C | 1 + .../Mesh/src/ESMCI_Mesh_FileIO.C | 2 + .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 4 +- 16 files changed, 641 insertions(+), 112 deletions(-) diff --git a/gisDev.org b/gisDev.org index bc4fc5fea8..a5baf139ba 100644 --- a/gisDev.org +++ b/gisDev.org @@ -85,3 +85,15 @@ ESMF_FieldRead() Will area (spatial extent) be conserved? e.g. if the GIS CRS is curvilinear, is the mapping in ESMF able to handle that? i.e. is ESMF mapping only planar? *** Solution: add a transformation routine from->to. e.g. from ESMF planar to GIS curvilear, or vice versa +* Sept 21, 2023 +** MeshCreate: +*** Need to create an index that identifies which multipolygon feature ID + is associated with a given subdivided polygon. The point is to allow + for a data read/write to know what data to use when reading a field. + e.g. if a multipolyon with index 20 has a field value of 10, an the + multipolygon is broken into several polygons, each sub-polygon would + have a reference index to multipolygon 20 so it could be given a field + value of 10 (or otherwise scaled proportionally). + + - the index needs to be a handle of type OGRFeatureH <- NOPE. Get Feature Index of type GBigInt + - It needs to happen in the meshgrid processing step diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h index 86bd41e042..7f819b02ce 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h @@ -18,7 +18,8 @@ #include -#include +#include +//#include /** PIO_OFFSET is an integer type of size sufficient to represent the * size (in bytes) of the largest file supported by MPI. This is not @@ -598,6 +599,13 @@ typedef struct file_desc_t * feature. One consequence is that PIO_IOTYPE_NETCDF4C files will * not have deflate automatically turned on for each var. */ int ncint_file; + + /** GDAL specific vars - M.Long */ + GDALDatasetH *hDS; + int dateVarID; // Index of field with type OFTDate + int timeVarID; // Index of field with type OFTTime + int datetimeVarID; // Index of field with type OFTDatetime + } file_desc_t; /** @@ -1328,8 +1336,13 @@ extern "C" { const unsigned long long *op); /* These functions are for the GDAL integration layer. MSL - 9/7/2023 */ - int GDALc_inq_fieldid(int ncid, const char *name, int *varidp); - int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *fname, bool mode); + int GDALc_inq_fieldid(int fileid, const char *name, int *varidp); + int GDALc_inq_timeid(int fileid, int *timeid); // Is there a field of type OFTDate, OFTTime, or OFTDateTime? +// int GDALc_openfile(int iosysid, GDALDatasetH *hDSp, int *iotype, const char *fname, bool mode); + int GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp, int *iotype, const char *fname, bool mode); + int GDALc_sync(int fileid); + int GDALc_shp_get_int_field(int fileid); + int GDALc_shp_get_double_field(int fileid); #if defined(__cplusplus) } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c index eb3066e01a..46b7e47b2f 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c @@ -949,6 +949,10 @@ PIOc_read_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, if ((ierr = pio_read_darray_nc(file, iodesc, varid, iobuf))) return pio_err(ios, file, ierr, __FILE__, __LINE__); break; + case PIO_IOTYPE_GDAL: + if ((ierr = pio_read_darray_shp(file, iodesc, varid, iobuf))) + return pio_err(ios, file, ierr, __FILE__, __LINE__); + break; default: return pio_err(NULL, NULL, PIO_EBADIOTYPE, __FILE__, __LINE__); } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c index 1edf4f42ec..03052a5c7a 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c @@ -281,6 +281,10 @@ PIOc_closefile(int ncid) ierr = ncmpi_close(file->fh); break; #endif + case PIO_IOTYPE_GDAL: + ierr = GDALClose((void*)file->hDS); + printf("GDALClose ierr: %d\n",ierr); + break; default: return pio_err(ios, file, PIO_EBADIOTYPE, __FILE__, __LINE__); } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c index cc5d25b7f8..16e6829160 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c @@ -3,6 +3,133 @@ #include #include +/** + * The PIO library maintains its own set of ncids. This is the next + * ncid number that will be assigned. + */ +extern int pio_next_ncid; + +static int +GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nvars, + int **rec_var, int **pio_type, int **pio_type_size, + MPI_Datatype **mpi_type, int **mpi_type_size, int **ndims) +{ + int mpierr; + int ret; + + /* Check inputs. */ + pioassert(rec_var && pio_type && pio_type_size && mpi_type && mpi_type_size, + "pointers must be provided", __FILE__, __LINE__); + + if (hDS == NULL) { + return pio_err(file->iosystem, file, -999, __FILE__, __LINE__); + } + /* How many vars in the file? */ + if (iotype == PIO_IOTYPE_GDAL) + { + OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); + OGR_L_ResetReading(hLayer); + + OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); + *nvars = OGR_FD_GetFieldCount(hFD); + printf(">>>>> NVARS: %d\n",*nvars); + if (nvars == 0) // empty file + return pio_err(NULL, file, PIO_ENOMEM, __FILE__, __LINE__); + + /* Allocate storage for info about each var. */ + if (*nvars) + { + if (!(*rec_var = malloc(*nvars * sizeof(int)))) + return PIO_ENOMEM; + if (!(*pio_type = malloc(*nvars * sizeof(int)))) + return PIO_ENOMEM; + if (!(*pio_type_size = malloc(*nvars * sizeof(int)))) + return PIO_ENOMEM; + if (!(*mpi_type = malloc(*nvars * sizeof(MPI_Datatype)))) + return PIO_ENOMEM; + if (!(*mpi_type_size = malloc(*nvars * sizeof(int)))) + return PIO_ENOMEM; + if (!(*ndims = malloc(*nvars * sizeof(int)))) + return PIO_ENOMEM; + } + + /* Learn about each variable in the file. */ + for (int v = 0; v < *nvars; v++) + { + int var_ndims; /* Number of dims for this var. */ + nc_type my_type; + + /* Find type of the var and number of dims in this var. Also + * learn about type. */ + size_t type_size; + + // + var_ndims = 2; // FIXED FOR NOW ... OGR_G_GetCoordinateDimension(OGRGeometryH); + (*ndims)[v] = var_ndims; + //>> if ((ret = nc_inq_var(ncid, v, NULL, &my_type, &var_ndims, NULL, NULL))) + //>> return pio_err(NULL, file, ret, __FILE__, __LINE__); + OGRFieldType Fld = OGR_Fld_GetType(OGR_FD_GetFieldDefn(hFD,v)); + printf(">>>>> FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,v)),Fld); + bool typeOK = true; // assume we're good + switch (Fld) { + case OFTReal: + (*pio_type)[v] = (int)PIO_DOUBLE; + break; + case OFTInteger: + (*pio_type)[v] = (int)PIO_INT; + break; + // This needs to be done. How do we deal with timestamps etc in GDAL vector fields? + //>>case OFTDate: + //>> break; + //>> case OFTTime: + //>> break; + //>> case OFTDate: + //>> break; + //>> case OFTDateTime: + default: + printf(">>>> Fld Type: %d\n",Fld); + typeOK = false; + break; +// return pio_err(file->iosystem, file, PIO_EBADIOTYPE, __FILE__, __LINE__); + } + //>> if ((ret = nc_inq_type(ncid, (*pio_type)[v], NULL, &type_size))) + //>> return check_netcdf(file, ret, __FILE__, __LINE__); + //>> (*pio_type_size)[v] = type_size; + + printf(">>>>> TEST: hDS %p, hFD %p\n", (void *)hDS, (void *)hFD); + + if (!typeOK) // Not a usable type + continue; + + /* Get the MPI type corresponding with the PIO type. */ + if ((ret = find_mpi_type((*pio_type)[v], &(*mpi_type)[v], NULL))) + return pio_err(NULL, file, ret, __FILE__, __LINE__); + + /* Get the size of the MPI type. */ + if ((*mpi_type)[v] == MPI_DATATYPE_NULL) + (*mpi_type_size)[v] = 0; + else + if ((mpierr = MPI_Type_size((*mpi_type)[v], &(*mpi_type_size)[v]))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + +//>> /* What are the dimids associated with this var? */ +//>> if (var_ndims) +//>> { +//>> int var_dimids[var_ndims]; +//>> if (iotype == PIO_IOTYPE_GDAL) +//>> { +//>>//>> if ((ret = nc_inq_vardimid(ncid, v, var_dimids))) +//>>//>> return pio_err(NULL, file, ret, __FILE__, __LINE__); +//>> } +//>> +//>> } + +// OGR_FD_Destroy(hFD); + } /* next var */ + } /* If PIO_TYPE_GDAL */ + return PIO_NOERR; +} + /** * The PIO-C interface for the GDAL function OGR_L_FindFieldIndex() * @@ -18,15 +145,15 @@ * @author Michael Long (adapted from Jim Edwards, Ed Hartnett) */ int -GDALc_inq_fieldid(int ncid, const char *name, int *varidp) +GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) { iosystem_desc_t *ios; /* Pointer to io system information. */ file_desc_t *file; /* Pointer to file information. */ int ierr; /* Return code from function calls. */ int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ - /* Get file info based on ncid. */ - if ((ierr = pio_get_file(ncid, &file))) + /* Get file info based on fileid. */ + if ((ierr = pio_get_file(fileid, &file))) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); ios = file->iosystem; @@ -34,7 +161,7 @@ GDALc_inq_fieldid(int ncid, const char *name, int *varidp) if (!name || strlen(name) > NC_MAX_NAME) return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); - PLOG((1, "GDALc_inq_varid ncid = %d name = %s", ncid, name)); + PLOG((1, "GDALc_inq_fieldid fileid = %d name = %s", fileid, name)); if (ios->async) { @@ -46,7 +173,7 @@ GDALc_inq_fieldid(int ncid, const char *name, int *varidp) mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); if (!mpierr) - mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); + mpierr = MPI_Bcast(&fileid, 1, MPI_INT, ios->compmaster, ios->intercomm); int namelen; namelen = strlen(name); if (!mpierr) @@ -62,16 +189,24 @@ GDALc_inq_fieldid(int ncid, const char *name, int *varidp) return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); } - /* If this is an IO task, then call the netCDF function. */ + /* If this is an IO task, then call the GDAL function. */ if (ios->ioproc) { -#ifdef _PNETCDF - if (file->iotype == PIO_IOTYPE_PNETCDF) - ierr = ncmpi_inq_varid(file->fh, name, varidp); -#endif /* _PNETCDF */ - - if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) - ierr = nc_inq_varid(file->fh, name, varidp); + GDALDatasetH *hDS = file->hDS; + if (file->do_io) { // We assume that its a GDAL file +// printf("NLayers: %d\n", OGR_DS_GetLayerCount(hDS)); + OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); + OGR_L_ResetReading(hLayer); + if (hLayer == NULL) { + printf("Layer is NULL"); + return -1; + } + *fieldidp = OGR_L_FindFieldIndex(hLayer,name,1); + + pioassert(*fieldidp > 0, "variable not found", __FILE__, __LINE__); +// printf("INQ_FIELDID FIELD %s INDEX: %d\n", name, *fieldidp); + + } } /* Broadcast and check the return code. */ @@ -81,15 +216,16 @@ GDALc_inq_fieldid(int ncid, const char *name, int *varidp) return check_netcdf(file, ierr, __FILE__, __LINE__); /* Broadcast results to all tasks. Ignore NULL parameters. */ - if (varidp) - if ((mpierr = MPI_Bcast(varidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) + if (fieldidp) + if ((mpierr = MPI_Bcast(fieldidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) check_mpi(NULL, file, mpierr, __FILE__, __LINE__); return PIO_NOERR; } int -GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filename, bool mode) +GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const char *filename, bool mode) +//GDALc_openfile(int iosysid, GDALDatasetH *hDSp, int *iotype, const char *filename, bool mode) { iosystem_desc_t *ios; /* Pointer to io system information. */ file_desc_t *file; /* Pointer to file information. */ @@ -103,6 +239,7 @@ GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filen int *ndims = NULL; int mpierr = MPI_SUCCESS, mpierr2; /** Return code from MPI function codes. */ int ierr = PIO_NOERR; /* Return code from function calls. */ + GDALDatasetH hDS; #ifdef USE_MPE pio_start_mpe_log(OPEN); @@ -174,16 +311,17 @@ GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filen { switch (file->iotype) { - case PIO_IOTYPE_NETCDF: - if (ios->io_rank == 0) + case PIO_IOTYPE_GDAL: +// if (ios->io_rank == 0) { -//>> if ((ierr = nc_open(filename, mode, &file->fh))) - break; - ierr = inq_file_metadata(file, file->fh, PIO_IOTYPE_NETCDF, + *hDSp = OGROpen( filename, FALSE, NULL ); + if( hDSp != NULL ) + + ierr = GDALc_inq_file_metadata(file, *hDSp, PIO_IOTYPE_GDAL, &nvars, &rec_var, &pio_type, &pio_type_size, &mpi_type, &mpi_type_size, &ndims); - PLOG((2, "PIOc_openfile_retry:nc_open for classic filename = %s mode = %d " + PLOG((2, "GDALc_openfile:OGROpen for filename = %s mode = %d " "ierr = %d", filename, mode, ierr)); } break; @@ -206,7 +344,7 @@ GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filen if (ierr) { free(file); - return check_netcdf2(ios, NULL, ierr, __FILE__, __LINE__); + return PIO_NOERR;// check_netcdf2(ios, NULL, ierr, __FILE__, __LINE__); } /* Broadcast writability to all tasks. */ @@ -256,15 +394,13 @@ GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filen return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); } - { - /* Create the ncid that the user will see. This is necessary - * because otherwise ncids will be reused if files are opened - * on multiple iosystems. */ -//>>>>>>>>>> file->pio_ncid = pio_next_ncid++; - - /* Return the PIO ncid to the user. */ -//>>>>>>>>>> *ncidp = file->pio_ncid; - } + file->hDS = *hDSp; + + /* Create the ncid/fileid that the user will see. This is necessary + * because otherwise ids will be reused if files are opened + * on multiple iosystems. */ + file->pio_ncid = pio_next_ncid++; + *fileIDp=file->pio_ncid; /* Add this file to the list of currently open files. */ pio_add_to_file_list(file); @@ -303,6 +439,358 @@ GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filen return ierr; } +int +GDALc_sync(int fileid) { + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ + int ierr = PIO_NOERR; /* Return code from function calls. */ +} + +int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTDate, OFTTime, or OFTDateTime? + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int ierr = PIO_NOERR; /* Return code from function calls. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ + + /* Get file info based on ncid. */ + if ((ierr = pio_get_file(fileid, &file))) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + ios = file->iosystem; + if (file->hDS == NULL) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + + GDALDatasetH *hDS = file->hDS; + OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); + if (hLayer == NULL) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + OGR_L_ResetReading(hLayer); + + OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); + if (hFD == NULL) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + printf("XXXXX NFLDS: %d, FID %d, hDS %p, hFD %p\n", file->nvars, fileid, (void *)file->hDS, (void *)hFD); + int nFld = OGR_FD_GetFieldCount(hFD); + OGRFieldDefnH hTMP = OGR_FD_GetFieldDefn(hFD,1); + hTMP = OGR_FD_GetFieldDefn(hFD,0); + + for (int i=0;i<(file->nvars)-1;i++) { + printf("XXXXX i: %d\n", i); + OGRFieldDefnH hFlD = OGR_FD_GetFieldDefn(hFD,i); + OGRFieldType Fld = OGR_Fld_GetType(hFlD); + if (Fld == NULL) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + printf("XXXXX FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,i)),Fld); + +// const char* FldTyp = OGR_GetFieldTypeName(Fld); +// PRINTMSG("Field type: " << FldTyp); + } + +// OGR_FD_Destroy(hFD); + + return 0; + } + +/** + * Read an array of data from a file to the (serial) IO library. This + * function is only used with netCDF classic and netCDF-4 serial + * iotypes. + * + * @param file a pointer to the open file descriptor for the file + * that will be written to + * @param iodesc a pointer to the defined iodescriptor for the buffer + * @param vid the variable id to be read. + * @param iobuf the buffer to be written from this mpi task. May be + * null. for example we have 8 ionodes and a distributed array with + * global size 4, then at least 4 nodes will have a null iobuf. In + * practice the box rearranger trys to have at least blocksize bytes + * on each io task and so if the total number of bytes to write is + * less than blocksize * numiotasks then some iotasks will have a NULL + * iobuf. + * @returns 0 for success, error code otherwise. + * @ingroup PIO_read_darray_c + * @author Jim Edwards, Ed Hartnett + */ +int +pio_read_darray_shp(file_desc_t *file, io_desc_t *iodesc, int vid, + void *iobuf) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + var_desc_t *vdesc; /* Information about the variable. */ + int ndims; /* Number of dims in decomposition. */ + int fndims; /* Number of dims for this var in file. */ + MPI_Status status; + int mpierr; /* Return code from MPI functions. */ + int ierr; + + /* Check inputs. */ + pioassert(file && file->iosystem && iodesc && vid >= 0 && vid <= PIO_MAX_VARS, + "invalid input", __FILE__, __LINE__); + + PLOG((2, "pio_read_darray_shp vid = %d", vid)); + ios = file->iosystem; + +#ifdef TIMING + /* Start timer if desired. */ + if ((ierr = pio_start_timer("PIO:read_darray_shp"))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); +#endif /* TIMING */ + + /* Get var info for this var. */ + if ((ierr = get_var_desc(vid, &file->varlist, &vdesc))) + return pio_err(NULL, file, ierr, __FILE__, __LINE__); + + /* Get the number of dims in our decomposition. */ + ndims = iodesc->ndims; + + /* Get number of dims for this var. */ + fndims = vdesc->ndims; + + /* If setframe was not called, use a default value of 0. This is + * required for backward compatibility. */ + if (fndims == ndims + 1 && vdesc->record < 0) + vdesc->record = 0; + PLOG((3, "fndims %d ndims %d vdesc->record %d vdesc->ndims %d", fndims, + ndims, vdesc->record, vdesc->ndims)); + + /* Confirm that we are being called with the correct ndims. */ + pioassert((fndims == ndims && vdesc->record < 0) || + (fndims == ndims + 1 && vdesc->record >= 0), + "unexpected record", __FILE__, __LINE__); + + if (ios->ioproc) + { + io_region *region; + size_t start[fndims]; + size_t count[fndims]; + size_t tmp_start[fndims * iodesc->maxregions]; + size_t tmp_count[fndims * iodesc->maxregions]; + size_t tmp_bufsize; + void *bufptr; + + /* buffer is incremented by byte and loffset is in terms of + the iodessc->mpitype so we need to multiply by the size of + the mpitype. */ + region = iodesc->firstregion; + + /* If setframe was not set before this call, assume a value of + * 0. This is required for backward compatibility. */ + if (fndims > ndims) + if (vdesc->record < 0) + vdesc->record = 0; + + /* Put together start/count arrays for all regions. */ + for (int regioncnt = 0; regioncnt < iodesc->maxregions; regioncnt++) + { + if (!region || iodesc->llen == 0) + { + /* Nothing to write for this region. */ + for (int i = 0; i < fndims; i++) + { + tmp_start[i + regioncnt * fndims] = 0; + tmp_count[i + regioncnt * fndims] = 0; + } + bufptr = NULL; + } + else + { + if (vdesc->record >= 0 && fndims > 1) + { + /* This is a record var. Find start for record dims. */ + tmp_start[regioncnt * fndims] = vdesc->record; + + /* Find start/count for all non-record dims. */ + for (int i = 1; i < fndims; i++) + { + tmp_start[i + regioncnt * fndims] = region->start[i - 1]; + tmp_count[i + regioncnt * fndims] = region->count[i - 1]; + } + + /* Set count for record dimension. */ + if (tmp_count[1 + regioncnt * fndims] > 0) + tmp_count[regioncnt * fndims] = 1; + } + else + { + /* Non-time dependent array */ + for (int i = 0; i < fndims; i++) + { + tmp_start[i + regioncnt * fndims] = region->start[i]; + tmp_count[i + regioncnt * fndims] = region->count[i]; + } + } + } + +#if PIO_ENABLE_LOGGING + /* Log arrays for debug purposes. */ + PLOG((3, "region = %d", region)); + for (int i = 0; i < fndims; i++) + PLOG((3, "tmp_start[%d] = %d tmp_count[%d] = %d", i + regioncnt * fndims, tmp_start[i + regioncnt * fndims], + i + regioncnt * fndims, tmp_count[i + regioncnt * fndims])); +#endif /* PIO_ENABLE_LOGGING */ + + /* Move to next region. */ + if (region) + region = region->next; + } /* next regioncnt */ + + /* IO tasks other than 0 send their starts/counts and data to + * IO task 0. */ + if (ios->io_rank > 0) + { + if ((mpierr = MPI_Send(&iodesc->llen, 1, MPI_OFFSET, 0, ios->io_rank, ios->io_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + PLOG((3, "sent iodesc->llen = %d", iodesc->llen)); + + if (iodesc->llen > 0) + { + if ((mpierr = MPI_Send(&(iodesc->maxregions), 1, MPI_INT, 0, + ios->num_iotasks + ios->io_rank, ios->io_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Send(tmp_count, iodesc->maxregions * fndims, MPI_OFFSET, 0, + 2 * ios->num_iotasks + ios->io_rank, ios->io_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Send(tmp_start, iodesc->maxregions * fndims, MPI_OFFSET, 0, + 3 * ios->num_iotasks + ios->io_rank, ios->io_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + PLOG((3, "sent iodesc->maxregions = %d tmp_count and tmp_start arrays", iodesc->maxregions)); + + if ((mpierr = MPI_Recv(iobuf, iodesc->llen, iodesc->mpitype, 0, + 4 * ios->num_iotasks + ios->io_rank, ios->io_comm, &status))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + PLOG((3, "received %d elements of data", iodesc->llen)); + } + } + else if (ios->io_rank == 0) + { + /* This is IO task 0. Get starts/counts and data from + * other IO tasks. */ + int maxregions = 0; + size_t loffset, regionsize; + size_t this_start[fndims * iodesc->maxregions]; + size_t this_count[fndims * iodesc->maxregions]; + + for (int rtask = 1; rtask <= ios->num_iotasks; rtask++) + { + if (rtask < ios->num_iotasks) + { + if ((mpierr = MPI_Recv(&tmp_bufsize, 1, MPI_OFFSET, rtask, rtask, ios->io_comm, &status))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + PLOG((3, "received tmp_bufsize = %d", tmp_bufsize)); + + if (tmp_bufsize > 0) + { + if ((mpierr = MPI_Recv(&maxregions, 1, MPI_INT, rtask, ios->num_iotasks + rtask, + ios->io_comm, &status))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Recv(this_count, maxregions * fndims, MPI_OFFSET, rtask, + 2 * ios->num_iotasks + rtask, ios->io_comm, &status))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Recv(this_start, maxregions * fndims, MPI_OFFSET, rtask, + 3 * ios->num_iotasks + rtask, ios->io_comm, &status))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + PLOG((3, "received maxregions = %d this_count, this_start arrays ", maxregions)); + } + } + else + { + maxregions = iodesc->maxregions; + tmp_bufsize = iodesc->llen; + } + PLOG((3, "maxregions = %d tmp_bufsize = %d", maxregions, tmp_bufsize)); + + /* Now get each region of data. */ + loffset = 0; + for (int regioncnt = 0; regioncnt < maxregions; regioncnt++) + { + /* Get pointer where data should go. */ + bufptr = (void *)((char *)iobuf + iodesc->mpitype_size * loffset); + regionsize = 1; + + /* ??? */ + if (rtask < ios->num_iotasks) + { + for (int m = 0; m < fndims; m++) + { + start[m] = this_start[m + regioncnt * fndims]; + count[m] = this_count[m + regioncnt * fndims]; + regionsize *= count[m]; + } + } + else + { + for (int m = 0; m < fndims; m++) + { + start[m] = tmp_start[m + regioncnt * fndims]; + count[m] = tmp_count[m + regioncnt * fndims]; + regionsize *= count[m]; + } + } + loffset += regionsize; + + /* Read the data. */ + /* ierr = nc_get_vara(file->fh, vid, start, count, bufptr); */ + switch (iodesc->piotype) + { + case PIO_BYTE: + return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); + case PIO_CHAR: + return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); + case PIO_SHORT: + return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); + case PIO_INT: + printf("Int: Start %d, Count %d\n", start, count); + ierr = GDALc_shp_get_int_field(file->pio_ncid); + break; + case PIO_FLOAT: + return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); + case PIO_DOUBLE: + printf("Double 1: Start %d, Count %d\n", start[0], count[0]); + printf("Double 2: Start %d, Count %d\n", start[fndims-1], count[fndims-1]); + ierr = GDALc_shp_get_double_field(file->pio_ncid); + break; + default: + return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); + } + + /* Check error code of netCDF call. */ + if (ierr) + return check_netcdf(file, ierr, __FILE__, __LINE__); + } + + /* The decomposition may not use all of the active io + * tasks. rtask here is the io task rank and + * ios->num_iotasks is the number of iotasks actually + * used in this decomposition. */ + if (rtask < ios->num_iotasks && tmp_bufsize > 0){ + + if ((mpierr = MPI_Send(iobuf, tmp_bufsize, iodesc->mpitype, rtask, + 4 * ios->num_iotasks + rtask, ios->io_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + } + } + } + } + +#ifdef TIMING + if ((ierr = pio_stop_timer("PIO:read_darray_nc_serial"))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); +#endif /* TIMING */ + + PLOG((2, "pio_read_darray_nc_serial complete ierr %d", ierr)); + return PIO_NOERR; +} + +int +GDALc_shp_get_int_field(int fileid) +{ + return PIO_NOERR; +} +int +GDALc_shp_get_double_field(int fileid) +{ + return PIO_NOERR; +} /** * @} */ diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c index c3d670450b..f39656b64f 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c @@ -3111,6 +3111,9 @@ iotype_is_valid(int iotype) #ifdef _PNETCDF #endif /* _PNETCDF */ + if (iotype == PIO_IOTYPE_GDAL) + ret++; + return ret; } diff --git a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h index b27e6f24da..96d93094ee 100644 --- a/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_GDAL_Handler.h @@ -69,6 +69,7 @@ namespace ESMCI { static std::vector activeGdalInstances; int gdalSystemDesc; // Descriptor for initialized GDAL inst. OGRDataSourceH *gdalFileDesc; // Descriptor(s) for open GDAL file (typically just one, but multiple for I/O of multi-tile arrays) + int *gdalFileID; MPI_Comm communicator; int my_rank; int num_iotasks; @@ -123,7 +124,7 @@ namespace ESMCI { } // open() and close() - void GDAL_openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); + void openOneTileFile(int tile, bool readonly_arg, int *rc = NULL); ESMC_Logical isOpen(int tile); ESMC_Logical isNewFile(int tile) { // note 1-based indexing for tile return (new_file[tile-1] ? ESMF_TRUE : ESMF_FALSE); @@ -137,7 +138,8 @@ namespace ESMCI { int *nioDims = (int *)NULL, int ** arrdims = (int **)NULL, int *narrDims = (int *)NULL, - int *basegdaltype = (int *)NULL, +// int *basegdaltype = (int *)NULL, + int *basepiotype = (int *)NULL, int *rc = (int *)NULL); void attPackPut (int vardesc, const ESMCI::Info *attPack, int tile, int *rc); diff --git a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h index bcda660935..c582d4eb94 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h @@ -160,7 +160,6 @@ enum GDAL_REARRANGERS int GDALc_open(int iosysid, const char *path, int mode, int *ncidp); int GDALc_closefile(int ncid); - int GDALc_inq_timeid(OGRDataSourceH hDS, int *timeid); // Is there a field of type OFTDate, OFTTime, or OFTDateTime? // Read distributed array. int GDALc_read_darray(OGRDataSourceH hDS, int fieldid, int ioid, MPI_Offset arraylen, void *array); diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index 2fcf78d57f..4c7c17f36f 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -22,7 +22,7 @@ // declared in the companion file {\tt ESMCI\_GDAL_Handler.h} // //------------------------------------------------------------------------- -#define GDAL_DEBUG_LEVEL 0 +#define GDAL_DEBUG_LEVEL 4 // include associated header file #include "ESMCI_GDAL_Handler.h" @@ -76,6 +76,7 @@ namespace ESMCI int nDims; // The number of dimensions for Array IO int *dims; // The shape of the Array IO int basegdaltype; // GDAL version of Array data type + int basepiotype; // PIO version of Array data type Array *array_p; // The array matched to this descriptor int tile; // The tile number in the array for this descriptor (1-based indexing) int arrayRank; // The rank of array_p @@ -178,6 +179,9 @@ void GDAL_Handler::initialize ( try { +#ifdef ESMFIO_DEBUG + PIOc_set_log_level(GDAL_DEBUG_LEVEL); +#endif // ESMFIO_DEBUG if (!instanceFound) { PRINTMSG("Before GDALc_Init_Intracomm, num_iotasks = " << num_iotasks); PIOc_Init_Intracomm(comp_comm, num_iotasks, @@ -461,10 +465,14 @@ GDAL_Handler::GDAL_Handler( // fill in the GDAL_Handler object gdalSystemDesc = 0; - gdalFileDesc = new OGRDataSourceH[ntilesArg]; + gdalFileDesc = new GDALDatasetH[ntilesArg]; for (int i = 0; i < ntilesArg; ++i) { gdalFileDesc[i] = NULL; } + gdalFileID = new int[ntilesArg]; + for (int i = 0; i < ntilesArg; ++i) { + gdalFileID[i] = NULL; + } localrc = ESMF_SUCCESS; new_file = new bool[ntilesArg]; for (int i = 0; i < ntilesArg; ++i) { @@ -563,9 +571,11 @@ void GDAL_Handler::arrayReadOneTileFile( int * arrDims; // Array shape int narrDims; // Array rank int iodesc; // GDAL IO descriptor - OGRDataSourceH filedesc; // GDAL file descriptor + GDALDatasetH filedesc; // GDAL file descriptor + int fileID; int fielddesc; // GDAL field descriptor int basegdaltype; // GDAL version of Array data type + int basepiotype; // PIO version of Array data type void *baseAddress; // The address of the Array IO data int localDE; // DE to use for IO int nField; // Number of field in file @@ -587,6 +597,7 @@ void GDAL_Handler::arrayReadOneTileFile( return; filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + fileID = gdalFileID[tile-1]; // note that tile indices are 1-based if (filedesc == NULL) { PRINTMSG("DataSource is NULL X"); @@ -614,9 +625,8 @@ void GDAL_Handler::arrayReadOneTileFile( int nDims; - // If frame >= 0 then we need to not use the unlimited dim in the iodesc. iodesc = getIODesc(gdalSystemDesc, arr_p, tile, &ioDims, &nioDims, - &arrDims, &narrDims, &basegdaltype, &localrc); + &arrDims, &narrDims, &basepiotype, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; @@ -628,11 +638,10 @@ void GDAL_Handler::arrayReadOneTileFile( fieldname = arr_p->getName(); } - PRINTMSG("Field " << fieldname.c_str()); - PRINTMSG("NLayers 1: " << OGR_DS_GetLayerCount(filedesc)); -//<<>> gdalrc = GDALc_inq_fieldid(filedesc, fieldname.c_str(), &fielddesc); + gdalrc = GDALc_inq_fieldid(fileID, fieldname.c_str(), &fielddesc); + PRINTMSG("Field " << fieldname.c_str() << " FieldDesc " << fielddesc << " gdalrc " << gdalrc); // An error here means the variable is not in the file - if (gdalrc == -1) { + if (gdalrc != PIO_NOERR) { PRINTMSG("Field " << fieldname.c_str() << " not found in file"); // if (!CHECKGDALERROR(gdalrc, errmsg, ESMF_RC_FILE_READ, (*rc))) { return; @@ -662,7 +671,7 @@ void GDAL_Handler::arrayReadOneTileFile( // TBD! THIS REQUIRES SOME DISCUSSION: HOW TO DEAL WITH FILES W/O DATE/TIME DEFS? int dimid_time; MPI_Offset time_len; - gdalrc = GDALc_inq_timeid(filedesc, &dimid_time); + gdalrc = GDALc_inq_timeid(fileID, &dimid_time); //>> if (!CHECKGDALERROR(gdalrc, "No time dimension found in file", ESMF_RC_FILE_READ, (*rc))) { //>> return; //>> } @@ -698,10 +707,10 @@ void GDAL_Handler::arrayReadOneTileFile( // GDALc_setframe(filedesc, vardesc, frame-1); // } PRINTPOS; - PRINTMSG("calling read_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); + PRINTMSG("calling read_darray, gdal type = " << basepiotype << ", address = " << baseAddress); // Read in the array - gdalrc = GDALc_read_darray(filedesc, fielddesc, iodesc, + gdalrc = PIOc_read_darray(fileID, fielddesc, iodesc, arrlen, (void *)baseAddress); // @@ -1173,7 +1182,7 @@ void GDAL_Handler::arrayWriteOneTileFile( // !IROUTINE: ESMCI::GDAL_Handler::openOneTileFile - open a stream with stored filename, for the given tile // // !INTERFACE: -void GDAL_Handler::GDAL_openOneTileFile( +void GDAL_Handler::openOneTileFile( // // !RETURN VALUE: // @@ -1202,6 +1211,16 @@ void GDAL_Handler::GDAL_openOneTileFile( int numtasks = vm->getPetCount(); int petspernode = vm->getSsiMaxPetCount(); + + struct iofmt_map_t { + int esmf_iofmt; + int gdal_fmt; + } iofmt_map[] = { + { ESMF_IOFMT_SHP, PIO_IOTYPE_GDAL } // This needs mods for different GIS types soon <> + }; + + int iofmt_map_size = sizeof (iofmt_map)/sizeof (iofmt_map_t); + if (rc != NULL) { *rc = ESMF_RC_NOT_IMPL; // final return code } @@ -1227,18 +1246,18 @@ void GDAL_Handler::GDAL_openOneTileFile( return; #endif -//>> int i_loop; -//>> for (i_loop=0; i_loop> if (getFormat() == iofmt_map[i_loop].esmf_iofmt) { -//>> iotype = iofmt_map[i_loop].gdal_fmt; -//>> break; -//>> } -//>> } -//>> if (i_loop == iofmt_map_size) { -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_BAD, -//>> "unsupported/unknown I/O format", ESMC_CONTEXT, rc)) -//>> return; -//>> } + int i_loop; + for (i_loop=0; i_loop> return; //>> } } else { - PRINTMSG(" calling GDALc_openfile with mode = " << mode << - ", file = \"" << thisFilename << "\""); + PRINTMSG(" calling GDALc_openfile with mode = " << mode << ", file = \"" << thisFilename << "\""); // Looks like we are ready to go ESMCI_IOREGION_ENTER("GDALc_openfile"); - gdalrc = GDALc_openfile(gdalSystemDesc, (&gdalFileDesc[tile-1]), + gdalrc = GDALc_openfile(gdalSystemDesc, (&gdalFileID[tile-1]), (&gdalFileDesc[tile-1]), &iotype, thisFilename.c_str(), mode); ESMCI_IOREGION_EXIT("GDALc_openfile"); - PRINTMSG("NLayers 0: " << OGR_DS_GetLayerCount(gdalFileDesc[tile-1])); +// PRINTMSG("NLayers 0: " << OGR_DS_GetLayerCount(gdalFileDesc[tile-1])); PRINTMSG(", called GDALc_openfile on " << thisFilename); if (!CHECKGDALWARN(gdalrc, std::string("Unable to open existing file: ") + thisFilename, ESMF_RC_FILE_OPEN, (*rc))) { @@ -1355,7 +1373,7 @@ void GDAL_Handler::attPackPut ( //----------------------------------------------------------------------------- int localrc; int gdalrc; - OGRDataSourceH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + GDALDatasetH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based //>> const json &j = attPack->getStorageRef(); //>> for (json::const_iterator it=j.cbegin(); it!=j.cend(); it++) { @@ -1468,7 +1486,7 @@ ESMC_Logical GDAL_Handler::isOpen( //EOPI //----------------------------------------------------------------------------- PRINTPOS; - OGRDataSourceH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + GDALDatasetH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based if (filedesc == NULL) { PRINTMSG("gdalFileDesc is NULL"); return ESMF_FALSE; @@ -1527,9 +1545,9 @@ void GDAL_Handler::flushOneTileFile( //>> ESMCI_IOREGION_ENTER("GDALc_sync"); if (gdalFileDesc[tile-1] != NULL) { // OGR_DS_Destroy(gdalFileDesc[tile-1]); - printf("Closing tile %d, hDS %p\n", tile, (void *)gdalFileDesc[tile-1]); - gdalrc = GDALClose(gdalFileDesc[tile-1]); - printf("Close code: %d, tile %d\n",gdalrc, tile); + printf("Flushing tile %d, hDS %p\n", tile, (void *)gdalFileDesc[tile-1]); + gdalrc = PIOc_sync(gdalFileID[tile-1]); + printf("Flush code: %d, tile %d\n",gdalrc, tile); } //>> GDALc_sync(gdalFileDesc[tile-1]); //>> ESMCI_IOREGION_EXIT("GDALc_sync"); @@ -1576,14 +1594,15 @@ void GDAL_Handler::closeOneTileFile( //>> PRINTPOS; //>> // Not open? No problem, just skip -//>> if (isOpen(tile) == ESMF_TRUE) { -//>> ESMCI_IOREGION_ENTER("GDALc_closefile"); -//>> int gdalrc = GDALc_closefile(gdalFileDesc[tile-1]); -//>> ESMCI_IOREGION_EXIT("GDALc_closefile"); -//>> gdalFileDesc[tile-1] = 0; -//>> new_file[tile-1] = false; -//>> if (rc != NULL) *rc = gdalrc; -//>> } + if (isOpen(tile) == ESMF_TRUE) { + ESMCI_IOREGION_ENTER("GDALc_closefile"); + int gdalrc = PIOc_closefile(gdalFileID[tile-1]); + ESMCI_IOREGION_EXIT("GDALc_closefile"); + gdalFileID[tile-1] = 0; + gdalFileDesc[tile-1] = NULL; + new_file[tile-1] = false; + if (rc != NULL) *rc = gdalrc; + } // return successfully if (rc != NULL) { @@ -1615,7 +1634,7 @@ void GDAL_Handler::closeOneTileFile( int *nioDims, // (out) - Rank of Array IO int ** arrDims, // (out) - Array shape for IO int *narrDims, // (out) - Rank of Array IO - int *basegdaltype, // (out) - Data type for IO + int *basepiotype, // (out) - Data type for IO int *rc // (out) - Error return code ) { // @@ -1666,8 +1685,8 @@ void GDAL_Handler::closeOneTileFile( } } PRINTMSG("getDims complete, calling getIOType"); - if (basegdaltype != (int *)NULL) { - *basegdaltype = GDAL_IODescHandler::getIOType(new_io_desc, &localrc); + if (basepiotype != (int *)NULL) { + *basepiotype = GDAL_IODescHandler::getIOType(new_io_desc, &localrc); ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc); } @@ -1983,12 +2002,14 @@ int GDAL_IODescHandler::constructGdalDecomp( switch(arr_p->getTypekind()) { case ESMC_TYPEKIND_I4: handle->basegdaltype = OFTInteger; + handle->basepiotype = PIO_INT; break; case ESMC_TYPEKIND_R4: // handle->basegdaltype = OFTReal; // break; case ESMC_TYPEKIND_R8: handle->basegdaltype = OFTReal; + handle->basepiotype = PIO_DOUBLE; break; case ESMC_TYPEKIND_I1: case ESMC_TYPEKIND_I2: @@ -2073,7 +2094,7 @@ int GDAL_IODescHandler::constructGdalDecomp( ddims[i] = handle->dims[handle->nDims - i - 1]; // Create the decomposition ESMCI_IOREGION_ENTER("GDALc_InitDecomp"); - PIOc_InitDecomp(iosys, handle->basegdaltype, handle->nDims, + PIOc_InitDecomp(iosys, handle->basepiotype, handle->nDims, ddims, gdalDofCount, gdalDofList, &(handle->io_descriptor), NULL, NULL, NULL); ESMCI_IOREGION_EXIT("GDALc_InitDecomp"); @@ -2260,7 +2281,7 @@ int GDAL_IODescHandler::getIOType( it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); it++) { if (iodesc == (*it)->io_descriptor) { - iotype = (*it)->basegdaltype; + iotype = (*it)->basepiotype; localrc = ESMF_SUCCESS; } } diff --git a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C index 0922fe9edd..e270e7daf4 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C @@ -364,28 +364,6 @@ int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char //<<>> return PIO_NOERR; //<<>>} - int GDALc_inq_timeid(OGRDataSourceH hDS, int *timeid) { // Is there a field of type OFTDate, OFTTime, or OFTDateTime? - - OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); - OGR_L_ResetReading(hLayer); - - OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); - int nFld = OGR_FD_GetFieldCount(hFD); - -// PRINTPOS; -// PRINTMSG("NFields: " << nFld); - - for (int i=0;i>>>> nElems, %d, nFeatures, %d\n", num_elems, num_features); + // TBD: Coord system conversion /* At this point, we've read the shapfile and defined diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index a1409e3e05..3935bf0a37 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -6913,8 +6913,8 @@ subroutine test_create_mesh_from_SH_file(correct, rc) if (rc /= ESMF_SUCCESS) return ! Create Mesh from shape file -! mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & - mesh=ESMF_MeshCreate("data/complex_3.shp", & + mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & +! mesh=ESMF_MeshCreate("data/complex_3.shp", & fileformat=ESMF_FILEFORMAT_SHAPEFILE, & rc=rc) if (rc /= ESMF_SUCCESS) return From 7fea943cfbae39b3ec1040e0faaebb9d55c32037 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Wed, 11 Oct 2023 14:52:59 -0400 Subject: [PATCH 18/58] Quick cleanup --- src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C index e16d18b226..5741efc4ed 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C @@ -403,12 +403,6 @@ int processPolygon(OGRGeometryH fGeom, int runtyp, double *nodeXCoords, double * // If populating, (i.e. if runtyp = 1), then populate if ( runtyp == 1 ) { // Set nodeIDs & nodeCoords -// for (i = 0; i < points-1; i++) { -// nodeXCoords[totpoints+i] = OGR_G_GetX(fGeom, i); -// nodeYCoords[totpoints+i] = OGR_G_GetY(fGeom, i); -// nodeIDs[totpoints+i] = totpoints+i+1; // increment from 1, not 0 -// elemConn[totpoints+i] = totpoints+i+1; -// } // assumes OGR reads a clockwise ring. This loop reverses it. int ii=0; for (int i = points-2; i >=0; i--) { From 248ab02af3a72615b648fb1a5a96ad2cf3096fcb Mon Sep 17 00:00:00 2001 From: Michael Long Date: Thu, 12 Oct 2023 13:32:45 -0400 Subject: [PATCH 19/58] Revision to make multipolygons be a single element in ESMF. The process of reading a SHP file in ESMF broke multipolygons apart into individual elements. This revision preserves the multipolygons as a whole element. This facilitates data reading/writing on a Mesh. -- rewrote the GDAL Util routines. -- Made extensive use of std::vectors -- Now, no longer strictly a C project. Now C++ too MSL --- .../Mesh/include/ESMCI_GDAL_Util.h | 22 +- src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C | 561 ++++++++++-------- .../Mesh/src/ESMCI_Mesh_FileIO.C | 47 +- .../Mesh/tests/ESMF_MeshFileIOUTest.F90 | 2 +- 4 files changed, 368 insertions(+), 264 deletions(-) diff --git a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h index 4b81bedb64..8d54262254 100644 --- a/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h +++ b/src/Infrastructure/Mesh/include/ESMCI_GDAL_Util.h @@ -58,13 +58,21 @@ void ESMCI_GDAL_process_shapefile_serial(OGRDataSourceH hDS, double *&nodeCoords int *&elemConn, int *&numElemConn, int *totNumElemConn, int *numNodes, int *numElems); -void ESMCI_GDAL_process_shapefile_distributed(OGRDataSourceH hDS, - int *nFeatures, int *&featureIDs, int *&globFeatureIDs, - double *&nodeCoords, - int *&nodeIDs, int *&elemIDs, - int *&elemConn, int *&numElemConn, - int *totNumElemConn, int *numNodes, - int *numElems); +void ESMCI_GDAL_process_shapefile_distributed( +// inputs + OGRDataSourceH hDS, + int *nFeatures, + int *&featureIDs, + int *&globFeatureIDs, +// outputs + double *&nodeCoords, + std::vector &nodeIDs, + std::vector &elemIDs, + std::vector &elemConn, + std::vector &numElemConn, + int *totNumElemConn, + int *nNodes, + int *nElems); void ESMCI_mesh_create_from_SHP_file(); void ESMCI_GDAL_SHP_get_feature_info(OGRDataSourceH hDS, int *nFeatures, int *&FeatureIDs); diff --git a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C index 5741efc4ed..92b0d9fc6e 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -67,8 +68,11 @@ int totpoints = 0; //double *nodeXCoords,*nodeYCoords; // Local Routines -int processPolygon(OGRGeometryH fGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn); -int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn); +int processPolygon(OGRGeometryH fGeom, std::vector &polyXCoords, std::vector &polyYCoords, std::vector + &polyConn, std::vector &numPolyConn, std::vector &polyNodeIDs, int *nPpoints); +int processMultiPolygon(OGRGeometryH hGeom, std::vector &mpolyXCoords, std::vector &mpolyYCoords, std::vector &mpolyConn, + std::vector &nPolyConn, std::vector &polyNodeIDs, int *nMPpoints, int *nMPconn); +int getLayerInfo( OGRLayerH hL, int *nPoints, int *nGeom); // Get the dimension of the mesh in the SHP file // (This dimension is both the pdim and orig_sdim of the mesh) @@ -101,7 +105,7 @@ void ESMCI_GDAL_SHP_get_feature_info(OGRDataSourceH hDS, int *nFeatures, int *&F for (int i=0;i<*nFeatures;i++) { hFeature = OGR_L_GetNextFeature(hLayer); FeatureIDs[i] = OGR_F_GetFID(hFeature); - printf("FEATURE ID %d\n", FeatureIDs[i]); +// printf("FEATURE ID %d\n", FeatureIDs[i]); OGR_F_Destroy( hFeature ); } @@ -121,135 +125,135 @@ void ESMCI_GDAL_process_shapefile_serial( int *totNumElemConn, int *numNodes, int *numElems) { - int nElements; -// int *nodeIDs; -// int *elemConn;//,*numElemConn; - double *nodeXCoords,*nodeYCoords; - -// OGRRegisterAll(); // register all the drivers - -// OGRDataSourceH hDS; - OGRLayerH hLayer; - OGRFeatureH hFeature; - - char filename[200]; - - // Step 1 - - // Access the layer (associate the handle) - // Assume that index 0 is the layer we want. - hLayer = OGR_DS_GetLayer( hDS, 0 ); - - // Get the number of elements - nElements = OGR_L_GetFeatureCount(hLayer,1); - - printf("Number of shapefile elements: %d\n\n",nElements); - - // Step 2: - - // Rewind to the beginning, just in case - OGR_L_ResetReading(hLayer); - - // Loop through features in layer and establish extents for allocation - while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) { - OGRGeometryH hGeom,fGeom; - - // Get geometry handles - hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon - fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring - - printf("Feature %d geom: %d (Polygon is %d)\n",elm+1,wkbFlatten(OGR_G_GetGeometryType(hGeom)),wkbPolygon); - - // ADD POLYGON - if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { - processPolygon(fGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); - } - // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS - else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ - processMultiPolygon(hGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); - } - - // Cleanup - OGR_F_Destroy( hFeature ); - } - - // Step 3: - // Allocate vars - // -- numNodes - there are as many connections as nodes - *numNodes = totpoints; // At this point, un-trimmed. Points will repeat - *totNumElemConn = totpoints; - // -- numElems - *numElems = elm; // This is an assumption! - // -- nodeIDs - nodeIDs = new int[totpoints]; -// nodeIDs = (int *)malloc(totpoints*sizeof(int)); - // -- node[X,Y]Coords - nodeXCoords = (double *)malloc(*numNodes*sizeof(double)); - nodeYCoords = (double *)malloc(*numNodes*sizeof(double)); - // -- elemConn - elemConn = (int *)malloc(*numNodes*sizeof(int)); //<- nodeIDs is already this, right? - // -- elemIDs - elemIDs = (int *)malloc(*numElems*sizeof(int)); - // -- numElemConn - numElemConn = (int *)malloc(*numElems*sizeof(int)); - - // Reset counters - elm = 0; // Zero features - totpoints = 0; // Zero number of points - - // Rewind to the beginning, just in case - OGR_L_ResetReading(hLayer); - - // Loop through features in layer and establish extents for allocation - while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) { - OGRGeometryH hGeom,fGeom; - - // Get geometry handles - hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon - fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring - - // ADD POLYGON - if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { - processPolygon(fGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); - } - // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS - else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ - processMultiPolygon(hGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); - } - - // Cleanup - OGR_F_Destroy( hFeature ); - } - -// printf("\n"); -// printf("N Features: %d\n",elm); -// printf("N Points: %d\n",totpoints); -// printf("numNodes: %d\n",numNodes); - - nodeCoords= new double[2*totpoints]; - - // Pass OGR Values to Mesh arrays - printf("Coords: \n"); - int j = 0; - for (int i=0;i>>> int nElements; +//>>>>// int *nodeIDs; +//>>>>// int *elemConn;//,*numElemConn; +//>>>> double *nodeXCoords,*nodeYCoords; +//>>>> +//>>>>// OGRRegisterAll(); // register all the drivers +//>>>> +//>>>>// OGRDataSourceH hDS; +//>>>> OGRLayerH hLayer; +//>>>> OGRFeatureH hFeature; +//>>>> +//>>>> char filename[200]; +//>>>> +//>>>> // Step 1 +//>>>> +//>>>> // Access the layer (associate the handle) +//>>>> // Assume that index 0 is the layer we want. +//>>>> hLayer = OGR_DS_GetLayer( hDS, 0 ); +//>>>> +//>>>> // Get the number of elements +//>>>> nElements = OGR_L_GetFeatureCount(hLayer,1); +//>>>> +//>>>> printf("Number of shapefile elements: %d\n\n",nElements); +//>>>> +//>>>> // Step 2: +//>>>> +//>>>> // Rewind to the beginning, just in case +//>>>> OGR_L_ResetReading(hLayer); +//>>>> +//>>>> // Loop through features in layer and establish extents for allocation +//>>>> while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) { +//>>>> OGRGeometryH hGeom,fGeom; +//>>>> +//>>>> // Get geometry handles +//>>>> hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon +//>>>> fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring +//>>>> +//>>>> printf("Feature %d geom: %d (Polygon is %d)\n",elm+1,wkbFlatten(OGR_G_GetGeometryType(hGeom)),wkbPolygon); +//>>>> +//>>>> // ADD POLYGON +//>>>> if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { +//>>>> processPolygon(fGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); +//>>>> } +//>>>> // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS +//>>>> else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ +//>>>> processMultiPolygon(hGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); +//>>>> } +//>>>> +//>>>> // Cleanup +//>>>> OGR_F_Destroy( hFeature ); +//>>>> } +//>>>> +//>>>> // Step 3: +//>>>> // Allocate vars +//>>>> // -- numNodes - there are as many connections as nodes +//>>>> *numNodes = totpoints; // At this point, un-trimmed. Points will repeat +//>>>> *totNumElemConn = totpoints; +//>>>> // -- numElems +//>>>> *numElems = elm; // This is an assumption! +//>>>> // -- nodeIDs +//>>>> nodeIDs = new int[totpoints]; +//>>>>// nodeIDs = (int *)malloc(totpoints*sizeof(int)); +//>>>> // -- node[X,Y]Coords +//>>>> nodeXCoords = (double *)malloc(*numNodes*sizeof(double)); +//>>>> nodeYCoords = (double *)malloc(*numNodes*sizeof(double)); +//>>>> // -- elemConn +//>>>> elemConn = (int *)malloc(*numNodes*sizeof(int)); //<- nodeIDs is already this, right? +//>>>> // -- elemIDs +//>>>> elemIDs = (int *)malloc(*numElems*sizeof(int)); +//>>>> // -- numElemConn +//>>>> numElemConn = (int *)malloc(*numElems*sizeof(int)); +//>>>> +//>>>> // Reset counters +//>>>> elm = 0; // Zero features +//>>>> totpoints = 0; // Zero number of points +//>>>> +//>>>> // Rewind to the beginning, just in case +//>>>> OGR_L_ResetReading(hLayer); +//>>>> +//>>>> // Loop through features in layer and establish extents for allocation +//>>>> while( (hFeature = OGR_L_GetNextFeature(hLayer)) != NULL ) { +//>>>> OGRGeometryH hGeom,fGeom; +//>>>> +//>>>> // Get geometry handles +//>>>> hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon +//>>>> fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring +//>>>> +//>>>> // ADD POLYGON +//>>>> if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { +//>>>> processPolygon(fGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); +//>>>> } +//>>>> // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS +//>>>> else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ +//>>>> processMultiPolygon(hGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); +//>>>> } +//>>>> +//>>>> // Cleanup +//>>>> OGR_F_Destroy( hFeature ); +//>>>> } +//>>>> +//>>>>// printf("\n"); +//>>>>// printf("N Features: %d\n",elm); +//>>>>// printf("N Points: %d\n",totpoints); +//>>>>// printf("numNodes: %d\n",numNodes); +//>>>> +//>>>> nodeCoords= new double[2*totpoints]; +//>>>> +//>>>> // Pass OGR Values to Mesh arrays +//>>>> printf("Coords: \n"); +//>>>> int j = 0; +//>>>> for (int i=0;i>>>// printf("%d: %.2f, %.2f\n",nodeIDs[i],nodeXCoords[i],nodeYCoords[i]); +//>>>> nodeCoords[j] = nodeXCoords[i]; +//>>>> nodeCoords[j+1] = nodeYCoords[i]; +//>>>> j+=2; +//>>>> } +//>>>> +//>>>>// printf("--\n"); +//>>>>// printf("elemID: numElemConn\n"); +//>>>>// +//>>>>// for (i=0;i>>>// printf("%d: %d\n", elemIDs[i],numElemConn[i]); +//>>>>// } +//>>>>// printf("--\n"); +//>>>> +//>>>> free(nodeXCoords); +//>>>> free(nodeYCoords); +//>>>> +//>>>> return ; } void ESMCI_GDAL_process_shapefile_distributed( // inputs @@ -259,108 +263,72 @@ void ESMCI_GDAL_process_shapefile_distributed( int *&globFeatureIDs, // outputs double *&nodeCoords, - int *&nodeIDs, - int *&elemIDs, - int *&elemConn, - int *&numElemConn, + std::vector &nodeIDs, + std::vector &elemIDs, + std::vector &elemConn, + std::vector &numElemConn, int *totNumElemConn, - int *numNodes, - int *numElems) { - double *nodeXCoords,*nodeYCoords; + int *nNodes, + int *nElems) { + + std::vector XCoords; + std::vector YCoords; + + OGRRegisterAll(); // register all the drivers + OGRLayerH hLayer; OGRFeatureH hFeature; - char filename[200]; - // Step 1 - // Access the layer (associate the handle) // Assume that index 0 is the layer we want. hLayer = OGR_DS_GetLayer( hDS, 0 ); - // Step 2: + // Step 2: Get layer extends (number of elements, points & geometries) - // Rewind to the beginning, just in case - OGR_L_ResetReading(hLayer); + // Get the number of elements + *nElems = OGR_L_GetFeatureCount(hLayer,1); - // Loop through features in layer and establish extents for allocation - for (int i = 0; i < *nFeatures; i++) { + int nPoints = 0; + int nGeom = 0; + int ierr = getLayerInfo(hLayer, &nPoints, &nGeom); - OGRGeometryH hGeom,fGeom; - -// printf("Feature %d, ID %d, i %d\n", globFeatureIDs[featureIDs[i]-1],featureIDs[i]-1,i); - hFeature = OGR_L_GetFeature(hLayer, globFeatureIDs[featureIDs[i]-1]); +// printf("Number of shapefile elements/points/geometries: %d/%d/%d\n\n",nElements,nPoints,nGeom); - // Get geometry handles - hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon - fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring - - // ADD POLYGON - if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { - processPolygon(fGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); - } - // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS - else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ - processMultiPolygon(hGeom,0, NULL, NULL, NULL, NULL, NULL, NULL); - } - - // Cleanup - OGR_F_Destroy( hFeature ); - } + // Rewind to the beginning, just in case + OGR_L_ResetReading(hLayer); // Step 3: - // Allocate vars - // -- numNodes - there are as many connections as nodes - *numNodes = totpoints; // At this point, un-trimmed. Points will repeat - *totNumElemConn = totpoints; - // -- numElems - *numElems = elm; // This is an assumption! - // -- nodeIDs - nodeIDs = new int[totpoints]; - // -- node[X,Y]Coords - nodeXCoords = (double *)malloc(*numNodes*sizeof(double)); - nodeYCoords = (double *)malloc(*numNodes*sizeof(double)); - // -- elemConn - elemConn = (int *)malloc(*numNodes*sizeof(int)); //<- nodeIDs is already this, right? - // -- elemIDs - elemIDs = (int *)malloc(*numElems*sizeof(int)); - // -- numElemConn - numElemConn = (int *)malloc(*numElems*sizeof(int)); - - // Reset counters - elm = 0; // Zero features totpoints = 0; // Zero number of points // Rewind to the beginning, just in case OGR_L_ResetReading(hLayer); - // Loop through features in layer and establish extents for allocation - for (int i = 0; i < *nFeatures; i++) { + // Loop through features in layer to build grid structures and establish coords & connectivity + std::vector FTRconn, nFTRconn;//, nodeIDs; + for (int i = 0; i < *nFeatures; i++) { // Distributed OGRGeometryH hGeom,fGeom; + int nFTRpoints; - hFeature = OGR_L_GetFeature(hLayer, globFeatureIDs[featureIDs[i]-1]); - - if ( hFeature == NULL) { - printf("NULL feature %d\n", i); - } + hFeature = OGR_L_GetFeature(hLayer, globFeatureIDs[featureIDs[i]-1]); // Distributed // Get geometry handles hGeom = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon fGeom = OGR_G_GetGeometryRef(hGeom,0); // and this should be linestring - - if ( hGeom == NULL || fGeom == NULL ) { - printf("NULL Geometry %d\n", i); - } // ADD POLYGON if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPolygon) { - processPolygon(fGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); + processPolygon(fGeom, XCoords, YCoords, elemConn, numElemConn, nodeIDs, &nFTRpoints); } // BREAK DOWN MULTIPOLYGON AND ADD SUB-POLYGONS else if (wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbMultiPolygon){ - processMultiPolygon(hGeom,1, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); + processMultiPolygon(hGeom, XCoords, YCoords, elemConn, numElemConn, nodeIDs, &nFTRpoints, NULL); } + totpoints += nFTRpoints; + + // Checks + //printf("Xcoords: %d (%d/%d) %d\n",polyXCoords.size(),nPpoints,nMPp,mpolyXCoords.size()); // Cleanup OGR_F_Destroy( hFeature ); @@ -368,90 +336,199 @@ void ESMCI_GDAL_process_shapefile_distributed( nodeCoords= new double[2*totpoints]; + // Pass data to output variables // Pass OGR Values to Mesh arrays int j = 0; for (int i=0;i &polyXCoords, // X coords in this polygon/linestring. + std::vector &polyYCoords, // X coords in this polygon/linestring. + std::vector &polyConn, + std::vector &numPolyConn, + std::vector &polyNodeIDs, + int *nPpoints) // Number of points in this polygon/linestring +{ + + *nPpoints = OGR_G_GetPointCount(fGeom)-1; + // Points of a polygon should start and end the same. // This will determine the element params and serve // as a check. - if( OGR_G_GetX(fGeom,0) != OGR_G_GetX(fGeom,points-1) && - OGR_G_GetY(fGeom,0) != OGR_G_GetY(fGeom,points-1) ) + if( OGR_G_GetX(fGeom,0) != OGR_G_GetX(fGeom,*nPpoints) && + OGR_G_GetY(fGeom,0) != OGR_G_GetY(fGeom,*nPpoints) ) { printf( "Incomplete polygon. (X,Y)i != (X,Y)e\n" ); return 1; } - // If populating, (i.e. if runtyp = 1), then populate - if ( runtyp == 1 ) { - // Set nodeIDs & nodeCoords - // assumes OGR reads a clockwise ring. This loop reverses it. - int ii=0; - for (int i = points-2; i >=0; i--) { - nodeXCoords[totpoints+ii] = OGR_G_GetX(fGeom, i); - nodeYCoords[totpoints+ii] = OGR_G_GetY(fGeom, i); - nodeIDs[totpoints+ii] = totpoints+ii+1; // increment from 1, not 0 - elemConn[totpoints+ii] = totpoints+ii+1; - ii++; - } - numElemConn[elm] = points-1; - elemIDs[elm] = elm+1; + // Set polyConns & polyCoords + for (int i = 0; i < *nPpoints; i++) { + polyConn.push_back(polyXCoords.size()+i+1); + polyNodeIDs.push_back(polyXCoords.size()+i+1); + } + numPolyConn.push_back(*nPpoints); + + //for (int n : polyNodeIDs) + // printf(" %d",n); + //printf("\n"); + + // -- Set coords: + // this is done this way because it appears GDAL reads these clockwise + // and we need it to be counterclockwise. So the loop is reversed. + // Haven't found a way to test for this using GDAL, so this is + // a hardwire + for (int i = *nPpoints-1; i >=0; i--) { + polyXCoords.push_back( OGR_G_GetX(fGeom, i) ); + polyYCoords.push_back( OGR_G_GetY(fGeom, i) ); } - - // Successful query - elm++; // Increment the number of features. - totpoints = totpoints+points-1; // Increment total number of points +// Success (currently, there's no error checking) return 0; } -int processMultiPolygon(OGRGeometryH hGeom, int runtyp, double *nodeXCoords, double *nodeYCoords, - int *nodeIDs, int *elemIDs, int *numElemConn, int *elemConn) { - // runtyp: if 0, just counting things. - // if 1, populating arrays +int processMultiPolygon( + OGRGeometryH hGeom, + std::vector &mpolyXCoords, + std::vector &mpolyYCoords, + std::vector &polyConn, + std::vector &nPolyConn, + std::vector &polyNodeIDs, + int *nMPpoints, + int *nMPconn) +{ int j; int nGeom; + int nPpoints, nPconn; + int nMPp = 0; + +// double *polyXCoords, *polyYCoords; + std::vector polyXCoords; + std::vector polyYCoords; + OGRGeometryH fGeom,mGeom; +// nMPpoints = 0; + // get number of geometries in MP nGeom = OGR_G_GetGeometryCount(hGeom); -// printf( "MultiPolygon: %d\n", nGeom ); - // Loop over nGeom + // Loop over nGeom in the multipolygon for (j = 0; j < nGeom; j++) { fGeom = OGR_G_GetGeometryRef(hGeom,j); mGeom = OGR_G_GetGeometryRef(fGeom,0); // ADD POLYGON if (wkbFlatten(OGR_G_GetGeometryType(fGeom)) == wkbPolygon) { - processPolygon(mGeom,runtyp, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); + processPolygon(mGeom, mpolyXCoords, mpolyYCoords, polyConn, nPolyConn, polyNodeIDs, &nPpoints); + nMPp += nPpoints; // Updated number of total points in MP } // Or RECURSE INTO SUB MULTIPOLYGON else if(wkbFlatten(OGR_G_GetGeometryType(fGeom)) == wkbMultiPolygon) { - processMultiPolygon(fGeom,runtyp, nodeXCoords, nodeYCoords, nodeIDs, elemIDs, numElemConn, elemConn); + // To be done. For multiPolygons made of multiPolygons. + printf("MPMP!!"); + exit(1); + // processMultiPolygon(fGeom,runtyp, mpolyXCoords, mpolyYCoords); } + + // Now, we need to expand the arrays to fit the new polygon info, and + // include a polybreak. + // + // -- append a polybreak to the element connectivity vectors + if (j < nGeom-1) { + polyConn.push_back(MESH_POLYBREAK_IND); // THIS SHOULD BE MESH_POLYBREAK_END + nPolyConn.back() = nPolyConn.back()+1; + } + + // Need to collapse the number of connectivity entries, since this is a multipolygon. + // processPolygon() treats them like individual entries. + if ( j > 0 ) { + nPolyConn[nPolyConn.size()-2] += nPolyConn.back(); + nPolyConn.pop_back(); + } + + // printf("nPolyConn: %d/%d, %d\n", nPolyConn.back(),nPpoints,polyConn.back()); + + // -- append the coordinate vectors + //mpolyXCoords.insert(mpolyXCoords.end(),polyXCoords.begin(),polyXCoords.end()); + //mpolyYCoords.insert(mpolyYCoords.end(),polyYCoords.begin(),polyYCoords.end()); + + // printf("Xcoords: %d (%d/%d) %d\n",polyXCoords.size(),nPpoints,nMPp,mpolyXCoords.size()); + // The above print statement and nMPp are just for checking that sizes are correct. + + polyXCoords.clear(); + polyYCoords.clear(); + } -// printf("\n"); + *nMPpoints = nMPp; + + return 0; +} + +int getLayerInfo( OGRLayerH hL, int *nPoints, int *nGeom) +{ + int nGeom_tmp = 0; + int nPnts_tmp = 0; + OGRFeatureH hFeature; + // Rewind to the beginning, just in case + OGR_L_ResetReading(hL); + + // Loop through features in layer and establish extents for allocation + while( (hFeature = OGR_L_GetNextFeature(hL)) != NULL ) { + OGRGeometryH hGeom1,hGeom2,hGeom3; + + // Get geometry handles + hGeom1 = OGR_F_GetGeometryRef(hFeature); // looks like this should be a polygon + + // Process POLYGON + if (wkbFlatten(OGR_G_GetGeometryType(hGeom1)) == wkbPolygon) { + hGeom2 = OGR_G_GetGeometryRef(hGeom1,0); // and this should be linestring + nGeom_tmp++; + *nGeom=nGeom_tmp; + nPnts_tmp = OGR_G_GetPointCount(hGeom2); + *nPoints += nPnts_tmp-1; + } // or process a MULTIPOLYGON + else if(wkbFlatten(OGR_G_GetGeometryType(hGeom1)) == wkbMultiPolygon) { + int nGeomMP = OGR_G_GetGeometryCount(hGeom1); + for (int j = 0; j < nGeomMP; j++) { + hGeom2 = OGR_G_GetGeometryRef(hGeom1,j); // this should be a polygon + // Process sub-polygon + if (wkbFlatten(OGR_G_GetGeometryType(hGeom2)) == wkbPolygon) { + hGeom3 = OGR_G_GetGeometryRef(hGeom2,0); // and this should be linestring + nGeom_tmp++; + *nGeom=nGeom_tmp; + nPnts_tmp = OGR_G_GetPointCount(hGeom3); + *nPoints += nPnts_tmp-1; // subtract one so we don't repeat the point that closes the ring + } // Or RECURSE INTO SUB MULTIPOLYGON + else if(wkbFlatten(OGR_G_GetGeometryType(hGeom2)) == wkbMultiPolygon) { + // To be done. For multiPolygons made of multiPolygons. + printf("MPMP!!"); + exit(1); + } + } + } + OGR_F_Destroy(hFeature); + } return 0; } + #endif // ifdef ESMF_GDAL diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index 673b66e98e..4461f0b9a2 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -1346,11 +1346,12 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, int num_nodes; int num_elems=0; int totNumElemConn=0; - int *numElemConn=NULL; - int *elemConn=NULL; double *nodeCoords=NULL; - int *node_IDs=NULL; - int *elem_IDs=NULL; + std::vector nodeIDs, elemIDs, elemConn, numElemConn; + int *num_ElemConn=NULL; + int *elem_Conn=NULL; + int *node_IDs=NULL; // Pointer. Will point to vector. + int *elem_IDs; // Processes polygons in hDS. Polygons are flattened to 2D // process_shapefile_serial(hDS,nodeCoords,node_IDs,elem_IDs,elemConn,numElemConn, @@ -1376,10 +1377,28 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, // Processes polygons in hDS. Polygons are flattened to 2D ESMCI_GDAL_process_shapefile_distributed(hDS,&num_features,feature_IDs,globalFeature_IDs, - nodeCoords,node_IDs,elem_IDs, + nodeCoords,nodeIDs,elemIDs, elemConn,numElemConn, &totNumElemConn, &num_nodes, &num_elems); - printf(">>>>> nElems, %d, nFeatures, %d\n", num_elems, num_features); +// printf(">>>>> nElems, %d, nFeatures, %d\n", num_elems, num_features); + + node_IDs=&nodeIDs[0]; + elem_Conn=&elemConn[0]; + num_ElemConn=&numElemConn[0]; + num_elems = num_features; + + int sumElemConn=0; + for(std::vector::iterator it = numElemConn.begin(); it != numElemConn.end(); ++it) + sumElemConn += *it; + +// printf("dim: %d\n",dim); +// printf("numElemConn: %d\n",numElemConn.size()); +// printf("elemConn: %d\n",elemConn.size()); +// printf("num_elems: %d\n",num_elems); +// printf("num_ftrs: %d\n",num_features); +// printf("num_nodes: %d\n",num_nodes); +// printf("totNumElmCon: %d\n",totNumElemConn); +// printf("sum_of_elems: %d\n",sumElemConn); // TBD: Coord system conversion @@ -1427,11 +1446,11 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, int areaPresent = 0; int centerCoordsPresent=0; ESMCI_meshaddelements(out_mesh, - &num_elems, elem_IDs, numElemConn, //elementType, <- using numElemConn in place of elementType assumes 2D!! + &num_elems, feature_IDs, num_ElemConn, //elementType, <- using numElemConn in place of elementType assumes 2D!! NULL, // No mask &areaPresent, NULL, // No areas ¢erCoordsPresent, NULL, // No center coords - &totNumElemConn, elemConn, + &sumElemConn, elem_Conn, &coord_sys_mesh, &orig_sdim, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) throw localrc; @@ -1439,13 +1458,13 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, // printf("Finished adding elements: %d\n", localrc); // Cleanup - OGR_DS_Destroy( hDS ); + GDALClose( hDS ); - delete [] elem_IDs; - delete [] elemConn; - delete [] node_IDs; - delete [] numElemConn; - delete [] nodeCoords; +// delete [] elem_IDs; +// delete [] elem_Conn; +// delete [] node_IDs; +// delete [] num_ElemConn; +// delete [] nodeCoords; } catch(std::exception &x) { diff --git a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 index 3935bf0a37..5daa2ac929 100644 --- a/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 +++ b/src/Infrastructure/Mesh/tests/ESMF_MeshFileIOUTest.F90 @@ -6913,7 +6913,7 @@ subroutine test_create_mesh_from_SH_file(correct, rc) if (rc /= ESMF_SUCCESS) return ! Create Mesh from shape file - mesh=ESMF_MeshCreate("data/cb_2018_us_county_500k.shp", & + mesh=ESMF_MeshCreate("data/cb_2018_us_county_20m.shp", & ! mesh=ESMF_MeshCreate("data/complex_3.shp", & fileformat=ESMF_FILEFORMAT_SHAPEFILE, & rc=rc) From 76bf40d15fad07b07b2f76bc9d379550f8c4c4a5 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Fri, 13 Oct 2023 15:18:46 -0400 Subject: [PATCH 20/58] Successful ESMF_FieldRead() of a variable in a shapefile, onto a mesh created from that shapefile. -- serial read, mpi broadcast. -- Only OFTReal is possible at the moment. It seems that OFTString is interpreted as a real by GDAL/ESMF, so that a string field with an integer in it is read as a double. Weird MSL --- .../IO/PIO/ParallelIO/src/clib/pio.h | 3 +- .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 47 ++++++++++++++----- .../IO/tests/ESMF_IO_GDALUTest.F90 | 8 ++-- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h index 7f819b02ce..abbdddd78e 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h @@ -1342,7 +1342,8 @@ extern "C" { int GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp, int *iotype, const char *fname, bool mode); int GDALc_sync(int fileid); int GDALc_shp_get_int_field(int fileid); - int GDALc_shp_get_double_field(int fileid); + int GDALc_shp_get_double_field(int fileid, int varid, const size_t *startp, + const size_t *countp, double *ip); #if defined(__cplusplus) } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c index 16e6829160..6bfbcca3ee 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c @@ -32,7 +32,7 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); *nvars = OGR_FD_GetFieldCount(hFD); - printf(">>>>> NVARS: %d\n",*nvars); +// printf(">>>>> NVARS: %d\n",*nvars); if (nvars == 0) // empty file return pio_err(NULL, file, PIO_ENOMEM, __FILE__, __LINE__); @@ -64,12 +64,13 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv size_t type_size; // - var_ndims = 2; // FIXED FOR NOW ... OGR_G_GetCoordinateDimension(OGRGeometryH); + var_ndims = 1; // FIXED FOR NOW. For data-read purposes, it's a 1D stream across the number of + // elements. (*ndims)[v] = var_ndims; //>> if ((ret = nc_inq_var(ncid, v, NULL, &my_type, &var_ndims, NULL, NULL))) //>> return pio_err(NULL, file, ret, __FILE__, __LINE__); OGRFieldType Fld = OGR_Fld_GetType(OGR_FD_GetFieldDefn(hFD,v)); - printf(">>>>> FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,v)),Fld); +// printf(">>>>> FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,v)),Fld); bool typeOK = true; // assume we're good switch (Fld) { case OFTReal: @@ -87,7 +88,7 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv //>> break; //>> case OFTDateTime: default: - printf(">>>> Fld Type: %d\n",Fld); +// printf(">>>> Fld Type: %d\n",Fld); typeOK = false; break; // return pio_err(file->iosystem, file, PIO_EBADIOTYPE, __FILE__, __LINE__); @@ -96,7 +97,7 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv //>> return check_netcdf(file, ret, __FILE__, __LINE__); //>> (*pio_type_size)[v] = type_size; - printf(">>>>> TEST: hDS %p, hFD %p\n", (void *)hDS, (void *)hFD); +// printf(">>>>> TEST: hDS %p, hFD %p\n", (void *)hDS, (void *)hFD); if (!typeOK) // Not a usable type continue; @@ -469,7 +470,7 @@ int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTD OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); if (hFD == NULL) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); - printf("XXXXX NFLDS: %d, FID %d, hDS %p, hFD %p\n", file->nvars, fileid, (void *)file->hDS, (void *)hFD); +// printf("XXXXX NFLDS: %d, FID %d, hDS %p, hFD %p\n", file->nvars, fileid, (void *)file->hDS, (void *)hFD); int nFld = OGR_FD_GetFieldCount(hFD); OGRFieldDefnH hTMP = OGR_FD_GetFieldDefn(hFD,1); hTMP = OGR_FD_GetFieldDefn(hFD,0); @@ -480,7 +481,7 @@ int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTD OGRFieldType Fld = OGR_Fld_GetType(hFlD); if (Fld == NULL) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); - printf("XXXXX FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,i)),Fld); +// printf("XXXXX FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,i)),Fld); // const char* FldTyp = OGR_GetFieldTypeName(Fld); // PRINTMSG("Field type: " << FldTyp); @@ -739,15 +740,14 @@ pio_read_darray_shp(file_desc_t *file, io_desc_t *iodesc, int vid, case PIO_SHORT: return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); case PIO_INT: - printf("Int: Start %d, Count %d\n", start, count); + printf("Int 1: Start %d, Count %d, fndims %d\n", start[0], count[0],fndims); + printf("Int 2: Start %d, Count %d\n", start[fndims-1], count[fndims-1]); ierr = GDALc_shp_get_int_field(file->pio_ncid); break; case PIO_FLOAT: return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); case PIO_DOUBLE: - printf("Double 1: Start %d, Count %d\n", start[0], count[0]); - printf("Double 2: Start %d, Count %d\n", start[fndims-1], count[fndims-1]); - ierr = GDALc_shp_get_double_field(file->pio_ncid); + ierr = GDALc_shp_get_double_field(file->pio_ncid, vid, start, count, (double *)bufptr); break; default: return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); @@ -763,7 +763,6 @@ pio_read_darray_shp(file_desc_t *file, io_desc_t *iodesc, int vid, * ios->num_iotasks is the number of iotasks actually * used in this decomposition. */ if (rtask < ios->num_iotasks && tmp_bufsize > 0){ - if ((mpierr = MPI_Send(iobuf, tmp_bufsize, iodesc->mpitype, rtask, 4 * ios->num_iotasks + rtask, ios->io_comm))) return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); @@ -787,8 +786,30 @@ GDALc_shp_get_int_field(int fileid) return PIO_NOERR; } int -GDALc_shp_get_double_field(int fileid) +GDALc_shp_get_double_field(int fileid, int varid, const size_t *startp, + const size_t *countp, double *ip) { + OGRFeatureH hF; + file_desc_t *file; /* Pointer to file information. */ + int ierr; + + /* Get file info based on fileid. */ + if ((ierr = pio_get_file(fileid, &file))) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + if (file->hDS == NULL) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + + OGRLayerH hL = OGR_DS_GetLayer( file->hDS, 0 ); + + // here, we have to assume start and count are only one dimension, and have + // only one assigned value. + for (size_t i = startp[0]; i Date: Wed, 1 Nov 2023 23:26:48 -0400 Subject: [PATCH 21/58] OK. We can create a file, open it, add layer & field. Not yet writing data yet. -- MSL --- gisDev.org | 29 + .../IO/PIO/ParallelIO/src/clib/pio.h | 3 + .../IO/PIO/ParallelIO/src/clib/pio_darray.c | 17 +- .../IO/PIO/ParallelIO/src/clib/pio_file.c | 3 + .../IO/PIO/ParallelIO/src/clib/pio_gdal.XC | 3237 ----------------- .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 655 +++- .../IO/PIO/ParallelIO/src/clib/pioc_support.c | 2 +- src/Infrastructure/IO/include/ESMCI_IO_GDAL.h | 2 +- .../IO/src/ESMCI_GDAL_Handler.C | 563 +-- src/Infrastructure/IO/src/ESMCI_IO_GDAL.C | 42 +- .../IO/tests/ESMF_IO_GDALUTest.F90 | 11 +- 11 files changed, 870 insertions(+), 3694 deletions(-) delete mode 100644 src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC diff --git a/gisDev.org b/gisDev.org index a5baf139ba..e89e455ed0 100644 --- a/gisDev.org +++ b/gisDev.org @@ -80,11 +80,21 @@ ESMF_FieldRead() -- -- -- -- -- IO_Handler::arrayRead() -- -- -- -- -- -- PIO_Handler::arrayReadOneTileFile() -- -- -- -- -- -- -- PIOc_Read_Array() +* Field Write +ESMF_FieldWrite() +-- ESMF_IOWrite() +-- -- c_ESMC_IOWrite() +-- -- -- (*ptr)->write() +-- -- -- -- IO::write() +-- -- -- -- -- IO_Handler::arrayWrite() +-- -- -- -- -- -- PIO_Handler::arrayWriteOneTileFile() +-- -- -- -- -- -- -- PIOc_write_darray() * Questions: ** What about CRS and projection to/from GEOS? Will area (spatial extent) be conserved? e.g. if the GIS CRS is curvilinear, is the mapping in ESMF able to handle that? i.e. is ESMF mapping only planar? *** Solution: add a transformation routine from->to. e.g. from ESMF planar to GIS curvilear, or vice versa +** How to deal with time slices? Can we use '%' tags like in ExtData? * Sept 21, 2023 ** MeshCreate: *** Need to create an index that identifies which multipolygon feature ID @@ -97,3 +107,22 @@ i.e. is ESMF mapping only planar? - the index needs to be a handle of type OGRFeatureH <- NOPE. Get Feature Index of type GBigInt - It needs to happen in the meshgrid processing step + +* Oct 16, 2023 - file write +1) Create a new file (if needed) +2) add variable +3) add data + +Right now, we have to assume: +- CRS +- Layer name + +Proposed workflow: +- Call PIO all the way down to PIOc_write_darray_multi +- Use file->iodesc & file->hDS to determine if its GDAL +- If GDAL, call GDAL specific write routine (in pioc_gdal.c) + +* Oct 26, 2023 - filw write, cont'd +1) Determine file type +2) Get driver +3) Define spatial reference w/ CRS diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h index abbdddd78e..f81f9b2576 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h @@ -1344,6 +1344,9 @@ extern "C" { int GDALc_shp_get_int_field(int fileid); int GDALc_shp_get_double_field(int fileid, int varid, const size_t *startp, const size_t *countp, double *ip); + int GDALc_createfile(int iosysid, int *fileidp, int *iotype, const char *fname, bool mode); + int GDALc_createfile_shp(int iosysid, int *fileidp, int *iotype, const char *filename, bool mode); + int GDALc_def_field(int fileid, const char *name, int xtype, int *varidp); #if defined(__cplusplus) } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c index 46b7e47b2f..6ea308a5c6 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray.c @@ -181,7 +181,7 @@ PIOc_write_darray_multi(int ncid, const int *varids, int ioid, int nvars, /* Run these on all tasks if async is not in use, but only on * non-IO tasks if async is in use. */ - if (!ios->async || !ios->ioproc) + if ((!ios->async || !ios->ioproc) && (file->iotype != PIO_IOTYPE_GDAL)) { /* Get the number of dims for this var. */ PLOG((3, "about to call PIOc_inq_varndims varids[0] = %d", varids[0])); @@ -333,6 +333,12 @@ PIOc_write_darray_multi(int ncid, const int *varids, int ioid, int nvars, return pio_err(ios, file, ierr, __FILE__, __LINE__); break; + case PIO_IOTYPE_GDAL: +// if ((ierr = gdal_write_darray_multi_serial(file, nvars, fndims, varids, iodesc, + if ((ierr = gdal_write_darray_multi_serial(file, nvars, 1, varids, iodesc, + DARRAY_DATA, frame))) + return pio_err(ios, file, ierr, __FILE__, __LINE__); + break; default: return pio_err(NULL, NULL, PIO_EBADIOTYPE, __FILE__, __LINE__); } @@ -661,6 +667,7 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra #endif /* USE_MPE */ /* Get the file info. */ + printf(">>>> getting file %d\n",ncid); if ((ierr = pio_get_file(ncid, &file))) return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); ios = file->iosystem; @@ -686,9 +693,12 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra arraylen, iodesc->ndof)); /* Get var description. */ + PLOG((3, "here1")); + printf(">>>> NCID: %d, %d\n",file->pio_ncid, file->fh); if ((ierr = get_var_desc(varid, &file->varlist, &vdesc))) return pio_err(ios, file, ierr, __FILE__, __LINE__); + PLOG((3, "here2")); /* If the type of the var doesn't match the type of the * decomposition, return an error. */ /* if (iodesc->piotype != vdesc->pio_type) */ @@ -697,13 +707,14 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra /* __FILE__, __LINE__); */ /* If we don't know the fill value for this var, get it. */ - if (!vdesc->fillvalue) + if (!vdesc->fillvalue && file->iotype != PIO_IOTYPE_GDAL) if ((ierr = find_var_fillvalue(file, varid, vdesc))) return pio_err(ios, file, PIO_EBADID, __FILE__, __LINE__); /* Check that if the user passed a fill value, it is correct. If * use_fill is false, then find_var_fillvalue will not end up * getting a fill value. */ + PLOG((3, "here3")); if (fillvalue && vdesc->use_fill) if (memcmp(fillvalue, vdesc->fillvalue, vdesc->pio_type_size)) return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); @@ -950,7 +961,7 @@ PIOc_read_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, return pio_err(ios, file, ierr, __FILE__, __LINE__); break; case PIO_IOTYPE_GDAL: - if ((ierr = pio_read_darray_shp(file, iodesc, varid, iobuf))) + if ((ierr = gdal_read_darray_shp(file, iodesc, varid, iobuf))) return pio_err(ios, file, ierr, __FILE__, __LINE__); break; default: diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c index 03052a5c7a..f16de9b01e 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c @@ -473,6 +473,9 @@ PIOc_sync(int ncid) flush_output_buffer(file, true, 0); break; #endif + case PIO_IOTYPE_GDAL: + ierr = OGR_DS_SyncToDisk(file->hDS); + break; default: return pio_err(ios, file, PIO_EBADIOTYPE, __FILE__, __LINE__); } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC deleted file mode 100644 index 2ca08c73c4..0000000000 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.XC +++ /dev/null @@ -1,3237 +0,0 @@ -/** - * @file - * PIO interfaces to - * [NetCDF](http://www.unidata.ucar.edu/software/netcdf/docs/modules.html) - * support functions - * - * This file provides an interface to the - * [NetCDF](http://www.unidata.ucar.edu/software/netcdf/docs/modules.html) - * support functions. Each subroutine calls the underlying netcdf or - * pnetcdf or netcdf4 functions from the appropriate subset of mpi - * tasks (io_comm). Each routine must be called collectively from - * union_comm. - * - * @author Jim Edwards (jedwards@ucar.edu), Ed Hartnett - * @date Feburary 2014, April 2016 - */ -#include -#include -#include -#include - -/** - * @defgroup PIO_inq_c Learn About File - * Learn the number of variables, dimensions, and global atts, and the - * unlimited dimension in C. - * - * @defgroup PIO_typelen_c Learn Aboue a Data Type - * Learn the length of a data type in C. - * - * @defgroup PIO_inq_format_c Learn About Binary Format - * Learn about the binary format in C. - * - * @defgroup PIO_inq_dim_c Learn About a Dimension - * Learn dimension name and length in C. - * - * @defgroup PIO_inq_var_c Learn About a Variable - * Learn variable name, dimensions, and type in C. - * - * @defgroup PIO_inq_att_c Learn About an Attribute - * Learn length, type, and name of an attribute in C. - * - * @defgroup PIO_rename_dim_c Rename a Dimension - * Rename a dimension in C. - * - * @defgroup PIO_rename_var_c Rename a Variable - * Rename a variable in C. - * - * @defgroup PIO_rename_att_c Rename an Attribute - * Rename an attribute in C. - * - * @defgroup PIO_del_att_c Delete an Attribute - * Delete an attribute in C. - * - * @defgroup PIO_set_fill_c Set Fill Value - * Set the fill value for a variable in C. - * - * @defgroup PIO_enddef_c End Define Mode - * End define mode in C. - * - * @defgroup PIO_redef_c Re-enter Define Mode - * Re-enter Define Mode in C. - * - * @defgroup PIO_def_dim_c Define a Dimension - * Define a new dimension in the file in C. - * - * @defgroup PIO_def_var_c Define a Variable - * Define a new variable in the file in C. - */ - -/** - * The PIO-C interface for the NetCDF function nc_inq. - * - * This routine is called collectively by all tasks in the - * communicator ios.union_comm. For more information on the underlying - * NetCDF commmand please read about this function in the NetCDF - * documentation at: - * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html - * - * @param ncid the ncid of the open file, obtained from - * GDALc_openfile() or GDALc_createfile(). - * @param ndimsp a pointer that will get the number of - * dimensions. Ignored if NULL. - * @param nvarsp a pointer that will get the number of - * variables. Ignored if NULL. - * @param ngattsp a pointer that will get the number of - * attributes. Ignored if NULL. - * @param unlimdimidp a pointer that will the ID of the unlimited - * dimension, or -1 if there is no unlimited dimension. Ignored if - * NULL. - * - * @return PIO_NOERR for success, error code otherwise. See - * GDALc_Set_File_Error_Handling(). - * @ingroup PIO_inq_c - * @author Jim Edwards, Ed Hartnett - */ -//<<>>int -//<<>>GDALc_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function calls. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq ncid = %d", ncid)); -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ; /* Message for async notification. */ -//<<>> char ndims_present = ndimsp ? true : false; -//<<>> char nvars_present = nvarsp ? true : false; -//<<>> char ngatts_present = ngattsp ? true : false; -//<<>> char unlimdimid_present = unlimdimidp ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ndims_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&nvars_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ngatts_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&unlimdimid_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_inq ncid = %d ndims_present = %d nvars_present = %d ngatts_present = %d unlimdimid_present = %d", -//<<>> ncid, ndims_present, nvars_present, ngatts_present, unlimdimid_present)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> { -//<<>> ierr = ncmpi_inq(file->fh, ndimsp, nvarsp, ngattsp, unlimdimidp); -//<<>> if (unlimdimidp) -//<<>> PLOG((2, "GDALc_inq returned from ncmpi_inq unlimdimid = %d", *unlimdimidp)); -//<<>> } -//<<>>#endif /* _PNETCDF */ -//<<>> if (file->iotype == PIO_IOTYPE_NETCDF && file->do_io) -//<<>> { -//<<>> PLOG((2, "GDALc_inq calling classic nc_inq")); -//<<>> /* Should not be necessary to do this - nc_inq should -//<<>> * handle null pointers. This has been reported as a bug -//<<>> * to netCDF developers. */ -//<<>> int tmp_ndims, tmp_nvars, tmp_ngatts, tmp_unlimdimid; -//<<>> PLOG((2, "GDALc_inq calling classic nc_inq")); -//<<>> ierr = nc_inq(file->fh, &tmp_ndims, &tmp_nvars, &tmp_ngatts, &tmp_unlimdimid); -//<<>> PLOG((2, "GDALc_inq calling classic nc_inq")); -//<<>> if (unlimdimidp) -//<<>> PLOG((2, "classic tmp_unlimdimid = %d", tmp_unlimdimid)); -//<<>> if (ndimsp) -//<<>> *ndimsp = tmp_ndims; -//<<>> if (nvarsp) -//<<>> *nvarsp = tmp_nvars; -//<<>> if (ngattsp) -//<<>> *ngattsp = tmp_ngatts; -//<<>> if (unlimdimidp) -//<<>> *unlimdimidp = tmp_unlimdimid; -//<<>> if (unlimdimidp) -//<<>> PLOG((2, "classic unlimdimid = %d", *unlimdimidp)); -//<<>> } -//<<>> else if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> { -//<<>> PLOG((2, "GDALc_inq calling netcdf-4 nc_inq")); -//<<>> ierr = nc_inq(file->fh, ndimsp, nvarsp, ngattsp, unlimdimidp); -//<<>> } -//<<>> -//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if (ndimsp) -//<<>> if ((mpierr = MPI_Bcast(ndimsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> if (nvarsp) -//<<>> if ((mpierr = MPI_Bcast(nvarsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> if (ngattsp) -//<<>> if ((mpierr = MPI_Bcast(ngattsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> if (unlimdimidp) -//<<>> if ((mpierr = MPI_Bcast(unlimdimidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find out how many dimensions are defined in the file. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param ndimsp a pointer that will get the number of -//<<>> * dimensions. Ignored if NULL. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_ndims(int ncid, int *ndimsp) -//<<>>{ -//<<>> PLOG((1, "GDALc_inq_ndims")); -//<<>> return GDALc_inq(ncid, ndimsp, NULL, NULL, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find out how many variables are defined in a file. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param nvarsp a pointer that will get the number of variables. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_nvars(int ncid, int *nvarsp) -//<<>>{ -//<<>> return GDALc_inq(ncid, NULL, nvarsp, NULL, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find out how many global attributes are defined in a file. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param ngattsp a pointer that will get the number of attributes. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_natts(int ncid, int *ngattsp) -//<<>>{ -//<<>> return GDALc_inq(ncid, NULL, NULL, ngattsp, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find out the dimension ids of the unlimited dimension. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param unlimdimidp a pointer that will the ID of the unlimited -//<<>> * dimension, or -1 if there is no unlimited dimension. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_unlimdim(int ncid, int *unlimdimidp) -//<<>>{ -//<<>> PLOG((1, "GDALc_inq_unlimdim ncid = %d", ncid)); -//<<>> return GDALc_inq(ncid, NULL, NULL, NULL, unlimdimidp); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find out the dimension ids of all unlimited dimensions. Note that -//<<>> * only netCDF-4 files can have more than 1 unlimited dimension. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param nunlimdimsp a pointer that gets the number of unlimited -//<<>> * dimensions. Ignored if NULL. -//<<>> * @param unlimdimidsp a pointer that will get an array of unlimited -//<<>> * dimension IDs. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_unlimdim_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int tmp_nunlimdims; /* The number of unlimited dims. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function calls. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq_unlimdims ncid = %d", ncid)); -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_UNLIMDIMS; /* Message for async notification. */ -//<<>> char nunlimdimsp_present = nunlimdimsp ? true : false; -//<<>> char unlimdimidsp_present = unlimdimidsp ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&nunlimdimsp_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&unlimdimidsp_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_inq_unlimdims ncid = %d nunlimdimsp_present = %d unlimdimidsp_present = %d", -//<<>> ncid, nunlimdimsp_present, unlimdimidsp_present)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> PLOG((2, "file->iotype = %d", file->iotype)); -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>> if (file->iotype == PIO_IOTYPE_NETCDF && file->do_io) -//<<>> { -//<<>> PLOG((2, "netcdf")); -//<<>> int tmp_unlimdimid; -//<<>> ierr = nc_inq_unlimdim(file->fh, &tmp_unlimdimid); -//<<>> PLOG((2, "classic tmp_unlimdimid = %d", tmp_unlimdimid)); -//<<>> tmp_nunlimdims = tmp_unlimdimid >= 0 ? 1 : 0; -//<<>> if (nunlimdimsp) -//<<>> *nunlimdimsp = tmp_unlimdimid >= 0 ? 1 : 0; -//<<>> if (unlimdimidsp) -//<<>> *unlimdimidsp = tmp_unlimdimid; -//<<>> } -//<<>>#ifdef _PNETCDF -//<<>> else if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> { -//<<>> PLOG((2, "pnetcdf")); -//<<>> int tmp_unlimdimid; -//<<>> ierr = ncmpi_inq_unlimdim(file->fh, &tmp_unlimdimid); -//<<>> PLOG((2, "pnetcdf tmp_unlimdimid = %d", tmp_unlimdimid)); -//<<>> tmp_nunlimdims = tmp_unlimdimid >= 0 ? 1 : 0; -//<<>> if (nunlimdimsp) -//<<>> *nunlimdimsp = tmp_nunlimdims; -//<<>> if (unlimdimidsp) -//<<>> *unlimdimidsp = tmp_unlimdimid; -//<<>> } -//<<>>#endif /* _PNETCDF */ -//<<>>#ifdef _NETCDF4 -//<<>> else if ((file->iotype == PIO_IOTYPE_NETCDF4C || file->iotype == PIO_IOTYPE_NETCDF4P) && -//<<>> file->do_io) -//<<>> { -//<<>> PLOG((2, "GDALc_inq calling netcdf-4 nc_inq_unlimdims")); -//<<>> int *tmp_unlimdimids; -//<<>> ierr = nc_inq_unlimdims(file->fh, &tmp_nunlimdims, NULL); -//<<>> if (!ierr) -//<<>> { -//<<>> if (nunlimdimsp) -//<<>> *nunlimdimsp = tmp_nunlimdims; -//<<>> PLOG((3, "tmp_nunlimdims = %d", tmp_nunlimdims)); -//<<>> if (!(tmp_unlimdimids = malloc(tmp_nunlimdims * sizeof(int)))) -//<<>> ierr = PIO_ENOMEM; -//<<>> if (!ierr) -//<<>> ierr = nc_inq_unlimdims(file->fh, &tmp_nunlimdims, tmp_unlimdimids); -//<<>> if (unlimdimidsp) -//<<>> for (int d = 0; d < tmp_nunlimdims; d++) -//<<>> { -//<<>> PLOG((3, "tmp_unlimdimids[%d] = %d", d, tmp_unlimdimids[d])); -//<<>> unlimdimidsp[d] = tmp_unlimdimids[d]; -//<<>> } -//<<>> free(tmp_unlimdimids); -//<<>> } -//<<>> } -//<<>>#endif /* _NETCDF4 */ -//<<>> -//<<>> PLOG((2, "GDALc_inq_unlimdims netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if ((mpierr = MPI_Bcast(&tmp_nunlimdims, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> if (nunlimdimsp) -//<<>> if ((mpierr = MPI_Bcast(nunlimdimsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> if (unlimdimidsp) -//<<>> if ((mpierr = MPI_Bcast(unlimdimidsp, tmp_nunlimdims, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * Learn the name and size of a type. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param xtype the type to learn about -//<<>> * @param name pointer that will get the name of the type. -//<<>> * @param sizep pointer that will get the size of the type in bytes. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_typelen_c -//<<>> * @author Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_type(int ncid, nc_type xtype, char *name, PIO_Offset *sizep) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq_type ncid = %d xtype = %d", ncid, xtype)); -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_TYPE; /* Message for async notification. */ -//<<>> char name_present = name ? true : false; -//<<>> char size_present = sizep ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&size_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = pioc_pnetcdf_inq_type(ncid, xtype, name, sizep); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_inq_type(file->fh, xtype, name, (size_t *)sizep); -//<<>> PLOG((2, "GDALc_inq_type netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if (name) -//<<>> { -//<<>> int slen; -//<<>> if (ios->iomaster == MPI_ROOT) -//<<>> slen = strlen(name); -//<<>> if ((mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (!mpierr) -//<<>> if ((mpierr = MPI_Bcast((void *)name, slen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> if (sizep) -//<<>> if ((mpierr = MPI_Bcast(sizep , 1, MPI_OFFSET, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * Learn the netCDF format of an open file. -//<<>> * -//<<>> * @param ncid the ncid of an open file. -//<<>> * @param formatp a pointer that will get the format. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_format_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_format(int ncid, int *formatp) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq ncid = %d", ncid)); -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_FORMAT; -//<<>> char format_present = formatp ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&format_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_inq_format(file->fh, formatp); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_inq_format(file->fh, formatp); -//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if (formatp) -//<<>> if ((mpierr = MPI_Bcast(formatp , 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_dim. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param dimid the dimension ID. -//<<>> * @param name a pointer that gets the name of the dimension. Igorned -//<<>> * if NULL. Name will be PIO_MAX_NAME chars or fewer. -//<<>> * @param lenp a pointer that will get the number of values -//<<>> * @return PIO_NOERR for success, error code otherwise. See -//<<>> * @ingroup PIO_inq_dim_c -//<<>> * GDALc_Set_File_Error_Handling() -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_dim(int ncid, int dimid, char *name, PIO_Offset *lenp) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq_dim ncid = %d dimid = %d", ncid, dimid)); -//<<>> -//<<>> /* Get the file info, based on the ncid. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_DIM; -//<<>> char name_present = name ? true : false; -//<<>> char len_present = lenp ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&dimid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_inq netcdf Bcast name_present = %d", name_present)); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&len_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_inq netcdf Bcast len_present = %d", len_present)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> { -//<<>> PLOG((2, "calling ncmpi_inq_dim")); -//<<>> ierr = ncmpi_inq_dim(file->fh, dimid, name, lenp);; -//<<>> } -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> { -//<<>> PLOG((2, "calling nc_inq_dim")); -//<<>> ierr = nc_inq_dim(file->fh, dimid, name, (size_t *)lenp);; -//<<>> } -//<<>> PLOG((2, "ierr = %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if (name) -//<<>> { -//<<>> int slen; -//<<>> PLOG((2, "bcasting results my_comm = %d", ios->my_comm)); -//<<>> if (ios->iomaster == MPI_ROOT) -//<<>> slen = strlen(name); -//<<>> if ((mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast((void *)name, slen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> if (lenp) -//<<>> if ((mpierr = MPI_Bcast(lenp , 1, MPI_OFFSET, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((2, "done with GDALc_inq_dim")); -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find the name of a dimension. -//<<>> * -//<<>> * @param ncid the ncid of an open file. -//<<>> * @param dimid the dimension ID. -//<<>> * @param name a pointer that gets the name of the dimension. Igorned -//<<>> * if NULL. Name will be PIO_MAX_NAME chars or fewer. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_dim_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_dimname(int ncid, int dimid, char *name) -//<<>>{ -//<<>> PLOG((1, "GDALc_inq_dimname ncid = %d dimid = %d", ncid, dimid)); -//<<>> return GDALc_inq_dim(ncid, dimid, name, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find the length of a dimension. -//<<>> * -//<<>> * @param ncid the ncid of an open file. -//<<>> * @param dimid the dimension ID. -//<<>> * @param lenp a pointer that gets the length of the dimension. Igorned -//<<>> * if NULL. -//<<>> * @returns 0 for success, error code otherwise. -//<<>> * @ingroup PIO_inq_dim_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_dimlen(int ncid, int dimid, PIO_Offset *lenp) -//<<>>{ -//<<>> return GDALc_inq_dim(ncid, dimid, NULL, lenp); -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_dimid. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param name pointer taht gets the name of the dimension. -//<<>> * @param idp a pointer that will get the id of the variable or attribute. -//<<>> * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling -//<<>> * @ingroup PIO_inq_dim_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_dimid(int ncid, const char *name, int *idp) -//<<>>{ -//<<>> iosystem_desc_t *ios; -//<<>> file_desc_t *file; -//<<>> int ierr; -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> /* Get the file info, based on the ncid. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> PLOG((2, "iosysid = %d", ios->iosysid)); -//<<>> -//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_inq_dimid ncid = %d name = %s", ncid, name)); -//<<>> -//<<>> /* If using async, and not an IO task, then send parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_DIMID; -//<<>> char id_present = idp ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> int namelen = strlen(name); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&id_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* IO tasks call the netCDF functions. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_inq_dimid(file->fh, name, idp); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_inq_dimid(file->fh, name, idp); -//<<>> } -//<<>> PLOG((3, "nc_inq_dimid call complete ierr = %d", ierr)); -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results. */ -//<<>> if (idp) -//<<>> if ((mpierr = MPI_Bcast(idp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_var. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name a pointer that gets the name of the dimension. Igorned -//<<>> * if NULL. Name will be PIO_MAX_NAME chars or fewer. -//<<>> * @param xtypep a pointer that will get the type of the -//<<>> * attribute. Ignored if NULL. -//<<>> * @param ndimsp a pointer that will get the number of -//<<>> * dimensions. Ignored if NULL. -//<<>> * @param dimidsp a pointer that will get an array of dimids. Ignored -//<<>> * if NULL. -//<<>> * @param nattsp a pointer that will get the number of -//<<>> * attributes. Ignored if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_var(int ncid, int varid, char *name, nc_type *xtypep, int *ndimsp, -//<<>> int *dimidsp, int *nattsp) -//<<>>{ -//<<>> iosystem_desc_t *ios; -//<<>> file_desc_t *file; -//<<>> int ndims = 0; /* The number of dimensions for this variable. */ -//<<>> int ierr; -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq_var ncid = %d varid = %d", ncid, varid)); -//<<>> -//<<>> /* Get the file info, based on the ncid. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_VAR; -//<<>> char name_present = name ? true : false; -//<<>> char xtype_present = xtypep ? true : false; -//<<>> char ndims_present = ndimsp ? true : false; -//<<>> char dimids_present = dimidsp ? true : false; -//<<>> char natts_present = nattsp ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&xtype_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ndims_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&dimids_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&natts_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_inq_var name_present = %d xtype_present = %d ndims_present = %d " -//<<>> "dimids_present = %d, natts_present = %d nattsp = %d", -//<<>> name_present, xtype_present, ndims_present, dimids_present, natts_present, nattsp)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* Call the netCDF layer. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>> PLOG((2, "Calling the netCDF layer")); -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> { -//<<>> ierr = ncmpi_inq_varndims(file->fh, varid, &ndims); -//<<>> PLOG((2, "from pnetcdf ndims = %d", ndims)); -//<<>> if (!ierr) -//<<>> ierr = ncmpi_inq_var(file->fh, varid, name, xtypep, ndimsp, dimidsp, nattsp); -//<<>> } -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> { -//<<>> ierr = nc_inq_varndims(file->fh, varid, &ndims); -//<<>> PLOG((3, "nc_inq_varndims called ndims = %d", ndims)); -//<<>> if (!ierr) -//<<>> { -//<<>> char my_name[NC_MAX_NAME + 1]; -//<<>> nc_type my_xtype; -//<<>> int my_ndims = 0, *my_dimids, my_natts = 0; -//<<>> if (ndims > 0) -//<<>> my_dimids = (int *) malloc(ndims * sizeof(int)); -//<<>> else -//<<>> my_dimids = NULL; -//<<>> ierr = nc_inq_var(file->fh, varid, my_name, &my_xtype, &my_ndims, my_dimids, -//<<>> &my_natts); -//<<>> PLOG((3, "my_name = %s my_xtype = %d my_ndims = %d my_natts = %d", my_name, -//<<>> my_xtype, my_ndims, my_natts)); -//<<>> if (!ierr) -//<<>> { -//<<>> if (name) -//<<>> strcpy(name, my_name); -//<<>> if (xtypep) -//<<>> *xtypep = my_xtype; -//<<>> if (ndimsp) -//<<>> *ndimsp = my_ndims; -//<<>> if (dimidsp) -//<<>> { -//<<>> for (int d = 0; d < ndims; d++) -//<<>> dimidsp[d] = my_dimids[d]; -//<<>> } -//<<>> if (my_dimids != NULL) -//<<>> free(my_dimids); -//<<>> if (nattsp) -//<<>> *nattsp = my_natts; -//<<>> } -//<<>> } -//<<>> } -//<<>> if (ndimsp) -//<<>> PLOG((2, "GDALc_inq_var ndims = %d ierr = %d", *ndimsp, ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast the results for non-null pointers. */ -//<<>> if (name) -//<<>> { -//<<>> int slen; -//<<>> if (ios->iomaster == MPI_ROOT) -//<<>> slen = strlen(name); -//<<>> if ((mpierr = MPI_Bcast(&slen, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast((void *)name, slen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> if (xtypep) -//<<>> if ((mpierr = MPI_Bcast(xtypep, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> if (ndimsp) -//<<>> { -//<<>> PLOG((2, "GDALc_inq_var about to Bcast ndims = %d ios->ioroot = %d ios->my_comm = %d", -//<<>> *ndimsp, ios->ioroot, ios->my_comm)); -//<<>> if ((mpierr = MPI_Bcast(ndimsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> PLOG((2, "GDALc_inq_var Bcast ndims = %d", *ndimsp)); -//<<>> } -//<<>> if (dimidsp) -//<<>> { -//<<>> if ((mpierr = MPI_Bcast(&ndims, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast(dimidsp, ndims, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> if (nattsp) -//<<>> if ((mpierr = MPI_Bcast(nattsp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the name of a variable. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param varid the variable ID. -//<<>> * @param name a pointer that will get the variable name. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_varname(int ncid, int varid, char *name) -//<<>>{ -//<<>> return GDALc_inq_var(ncid, varid, name, NULL, NULL, NULL, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find the type of a variable. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param varid the variable ID. -//<<>> * @param xtypep a pointer that will get the type of the -//<<>> * attribute. Ignored if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_vartype(int ncid, int varid, nc_type *xtypep) -//<<>>{ -//<<>> return GDALc_inq_var(ncid, varid, NULL, xtypep, NULL, NULL, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find the number of dimensions of a variable. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param varid the variable ID. -//<<>> * @param ndimsp a pointer that will get the number of -//<<>> * dimensions. Ignored if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_varndims(int ncid, int varid, int *ndimsp) -//<<>>{ -//<<>> return GDALc_inq_var(ncid, varid, NULL, NULL, ndimsp, NULL, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find the dimension IDs associated with a variable. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param varid the variable ID. -//<<>> * @param dimidsp a pointer that will get an array of dimids. Ignored -//<<>> * if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_vardimid(int ncid, int varid, int *dimidsp) -//<<>>{ -//<<>> return GDALc_inq_var(ncid, varid, NULL, NULL, NULL, dimidsp, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Find the number of attributes associated with a variable. -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param varid the variable ID. -//<<>> * @param nattsp a pointer that will get the number of attriburtes. Ignored -//<<>> * if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_varnatts(int ncid, int varid, int *nattsp) -//<<>>{ -//<<>> return GDALc_inq_var(ncid, varid, NULL, NULL, NULL, NULL, nattsp); -//<<>>} - -/** - * The PIO-C interface for the GDAL function OGR_L_FindFieldIndex() - * - * This routine is called collectively by all tasks in the communicator - * ios.union_comm. - * - * @param ncid the ncid of the open file, obtained from - * GDALc_openfile() or GDALc_createfile(). - * @param name the field name. - * @param varidp a pointer that will get the variable id - * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling - * @ingroup PIO_inq_var_c - * @author Jim Edwards, Ed Hartnett - */ -int -GDALc_inq_fieldid(int ncid, const char *name, int *varidp) -{ - iosystem_desc_t *ios; /* Pointer to io system information. */ - file_desc_t *file; /* Pointer to file information. */ - int ierr; /* Return code from function calls. */ - int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ - - /* Get file info based on ncid. */ - if ((ierr = pio_get_file(ncid, &file))) - return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); - ios = file->iosystem; - - /* Caller must provide name. */ - if (!name || strlen(name) > NC_MAX_NAME) - return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); - - PLOG((1, "GDALc_inq_varid ncid = %d name = %s", ncid, name)); - - if (ios->async) - { - if (!ios->ioproc) - { - int msg = PIO_MSG_INQ_VARID; - - if (ios->compmaster == MPI_ROOT) - mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); - - if (!mpierr) - mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); - int namelen; - namelen = strlen(name); - if (!mpierr) - mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); - if (!mpierr) - mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); - } - - /* Handle MPI errors. */ - if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) - check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); - if (mpierr) - return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); - } - - /* If this is an IO task, then call the netCDF function. */ - if (ios->ioproc) - { -#ifdef _PNETCDF - if (file->iotype == PIO_IOTYPE_PNETCDF) - ierr = ncmpi_inq_varid(file->fh, name, varidp); -#endif /* _PNETCDF */ - - if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) - ierr = nc_inq_varid(file->fh, name, varidp); - } - - /* Broadcast and check the return code. */ - if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) - return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); - if (ierr) - return check_netcdf(file, ierr, __FILE__, __LINE__); - - /* Broadcast results to all tasks. Ignore NULL parameters. */ - if (varidp) - if ((mpierr = MPI_Bcast(varidp, 1, MPI_INT, ios->ioroot, ios->my_comm))) - check_mpi(NULL, file, mpierr, __FILE__, __LINE__); - - return PIO_NOERR; -} - -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_att. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID or NC_GLOBAL. -//<<>> * @param name name of the attribute. -//<<>> * @param eh non-zero to handle errors in the function. This will -//<<>> * cause program to halt if PIO error handler is set to INTERNAL. -//<<>> * @param xtypep a pointer that will get the type of the attribute. -//<<>> * @param lenp a pointer that will get the number of values -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_att_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_att_eh(int ncid, int varid, const char *name, int eh, -//<<>> nc_type *xtypep, PIO_Offset *lenp) -//<<>>{ -//<<>> int msg = PIO_MSG_INQ_ATT; -//<<>> iosystem_desc_t *ios; -//<<>> file_desc_t *file; -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> int ierr; -//<<>> -//<<>> /* Find file based on ncid. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_inq_att ncid = %d varid = %d", ncid, varid)); -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> char xtype_present = xtypep ? true : false; -//<<>> char len_present = lenp ? true : false; -//<<>> int namelen = strlen(name); -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&xtype_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&len_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&eh, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_inq_att(file->fh, varid, name, xtypep, lenp); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_inq_att(file->fh, varid, name, xtypep, (size_t *)lenp); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> PLOG((2, "GDALc_inq_att netcdf call %s returned %d eh %d", name,ierr,eh)); -//<<>> if (eh && ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results if call succeeded. */ -//<<>> if (!ierr) -//<<>> { -//<<>> if (xtypep) -//<<>> if ((mpierr = MPI_Bcast(xtypep, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (lenp) -//<<>> if ((mpierr = MPI_Bcast(lenp, 1, MPI_OFFSET, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> return ierr; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_att. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID or NC_GLOBAL. -//<<>> * @param name name of the attribute. -//<<>> * @param xtypep a pointer that will get the type of the attribute. -//<<>> * @param lenp a pointer that will get the number of values -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_att_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_att(int ncid, int varid, const char *name, nc_type *xtypep, -//<<>> PIO_Offset *lenp) -//<<>>{ -//<<>> return GDALc_inq_att_eh(ncid, varid, name, 1, xtypep, lenp); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the length of an attribute. -//<<>> * -//<<>> * @param ncid the ID of an open file. -//<<>> * @param varid the variable ID, or NC_GLOBAL for global attributes. -//<<>> * @param name the name of the attribute. -//<<>> * @param lenp a pointer that gets the lenght of the attribute -//<<>> * array. Ignored if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_attlen_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_attlen(int ncid, int varid, const char *name, PIO_Offset *lenp) -//<<>>{ -//<<>> return GDALc_inq_att(ncid, varid, name, NULL, lenp); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the type of an attribute. -//<<>> * -//<<>> * @param ncid the ID of an open file. -//<<>> * @param varid the variable ID, or NC_GLOBAL for global attributes. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtypep a pointer that gets the type of the -//<<>> * attribute. Ignored if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_atttype_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep) -//<<>>{ -//<<>> return GDALc_inq_att(ncid, varid, name, xtypep, NULL); -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_attname. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param attnum the attribute ID. -//<<>> * @param name the name of the attribute. -//<<>> * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling -//<<>> * @ingroup PIO_inq_attname_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_attname(int ncid, int varid, int attnum, char *name) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq_attname ncid = %d varid = %d attnum = %d", ncid, varid, -//<<>> attnum)); -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_ATTNAME; -//<<>> char name_present = name ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&attnum, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&name_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_inq_attname(file->fh, varid, attnum, name); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_inq_attname(file->fh, varid, attnum, name); -//<<>> PLOG((2, "GDALc_inq_attname netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if (name) -//<<>> { -//<<>> int namelen = strlen(name); -//<<>> if ((mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> /* Casting to void to avoid warnings on some compilers. */ -//<<>> if ((mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_attid. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name a pointer that will get name of attribute. Ignored if -//<<>> * NULL. -//<<>> * @param idp a pointer that will get the id of the variable or -//<<>> * attribute. Ignored if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. See GDALc_Set_File_Error_Handling -//<<>> * @ingroup PIO_inq_attid_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_attid(int ncid, int varid, const char *name, int *idp) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_inq_attid ncid = %d varid = %d name = %s", ncid, varid, name)); -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_ATTID; -//<<>> int namelen = strlen(name); -//<<>> char id_present = idp ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((char *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&id_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_inq_attid(file->fh, varid, name, idp); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_inq_attid(file->fh, varid, name, idp); -//<<>> PLOG((2, "GDALc_inq_attname netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results. */ -//<<>> if (idp) -//<<>> if ((mpierr = MPI_Bcast(idp, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_rename_dim. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param dimid the dimension ID. -//<<>> * @param name the new name for the dimension. -//<<>> * @return PIO_NOERR for success, error code otherwise. See -//<<>> * @ingroup PIO_rename_dim_c -//<<>> * GDALc_Set_File_Error_Handling(). -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_rename_dim(int ncid, int dimid, const char *name) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_rename_dim ncid = %d dimid = %d name = %s", ncid, dimid, name)); -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_RENAME_DIM; /* Message for async notification. */ -//<<>> int namelen = strlen(name); -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&dimid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_rename_dim Bcast file->fh = %d dimid = %d namelen = %d name = %s", -//<<>> file->fh, dimid, namelen, name)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_rename_dim(file->fh, dimid, name); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_rename_dim(file->fh, dimid, name); -//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_rename_var. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the new name for the variable. -//<<>> * @return PIO_NOERR for success, error code otherwise. See -//<<>> * @ingroup PIO_rename_var_c -//<<>> * GDALc_Set_File_Error_Handling(). -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_rename_var(int ncid, int varid, const char *name) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_rename_var ncid = %d varid = %d name = %s", ncid, varid, name)); -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_RENAME_VAR; /* Message for async notification. */ -//<<>> int namelen = strlen(name); -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_rename_var Bcast file->fh = %d varid = %d namelen = %d name = %s", -//<<>> file->fh, varid, namelen, name)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_rename_var(file->fh, varid, name); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_rename_var(file->fh, varid, name); -//<<>> PLOG((2, "GDALc_inq netcdf call returned %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_rename_att. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param newname the new name for the attribute. -//<<>> * @return PIO_NOERR for success, error code otherwise. See -//<<>> * @ingroup PIO_rename_att_c -//<<>> * GDALc_Set_File_Error_Handling(). -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_rename_att(int ncid, int varid, const char *name, -//<<>> const char *newname) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI functions. */ -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide names of correct length. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME || -//<<>> !newname || strlen(newname) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_rename_att ncid = %d varid = %d name = %s newname = %s", -//<<>> ncid, varid, name, newname)); -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_RENAME_ATT; /* Message for async notification. */ -//<<>> int namelen = strlen(name); -//<<>> int newnamelen = strlen(newname); -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((char *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&newnamelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((char *)newname, newnamelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_rename_att(file->fh, varid, name, newname); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_rename_att(file->fh, varid, name, newname); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((2, "GDALc_rename_att succeeded")); -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_del_att. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__attributes.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name of the attribute to delete. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_del_att_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_del_att(int ncid, int varid, const char *name) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI functions. */ -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_del_att ncid = %d varid = %d name = %s", ncid, varid, name)); -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_DEL_ATT; -//<<>> int namelen = strlen(name); /* Length of name string. */ -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((char *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_del_att(file->fh, varid, name); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_del_att(file->fh, varid, name); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_set_fill. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param fillmode either NC_FILL or NC_NOFILL. -//<<>> * @param old_modep a pointer to an int that gets the old setting. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_set_fill_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_set_fill(int ncid, int fillmode, int *old_modep) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI functions. */ -//<<>> -//<<>> PLOG((1, "GDALc_set_fill ncid = %d fillmode = %d", ncid, fillmode)); -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_SET_FILL; -//<<>> int old_modep_present = old_modep ? 1 : 0; -//<<>> -//<<>> PLOG((3, "GDALc_set_fill about to send msg %d", msg)); -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&fillmode, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&old_modep_present, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_set_fill sent ncid = %d fillmode = %d old_modep_present = %d", ncid, fillmode, -//<<>> old_modep_present)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> { -//<<>> PLOG((3, "about to call ncmpi_set_fill() fillmode = %d", fillmode)); -//<<>> ierr = ncmpi_set_fill(file->fh, fillmode, old_modep); -//<<>> } -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_set_fill(file->fh, fillmode, old_modep); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results. */ -//<<>> if (old_modep) -//<<>> { -//<<>> PLOG((2, "old_mode = %d", *old_modep)); -//<<>> if ((mpierr = MPI_Bcast(old_modep, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> PLOG((2, "GDALc_set_fill succeeded")); -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_enddef. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_enddef_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_enddef(int ncid) -//<<>>{ -//<<>> return pioc_change_def(ncid, 1); -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_redef. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__datasets.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_redef_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_redef(int ncid) -//<<>>{ -//<<>> return pioc_change_def(ncid, 0); -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_def_dim. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__dimensions.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param name name of the dimension. -//<<>> * @param len length of the dimension. -//<<>> * @param idp a pointer that will get the id of the variable or attribute. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_def_dim_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_def_dim(int ncid, const char *name, PIO_Offset len, int *idp) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide name shorter than NC_MAX_NAME +1. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_def_dim ncid = %d name = %s len = %d", ncid, name, len)); -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_DEF_DIM; -//<<>> int namelen = strlen(name); -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&len, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_def_dim(file->fh, name, len, idp); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_def_dim(file->fh, name, (size_t)len, idp); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if (idp) -//<<>> if ((mpierr = MPI_Bcast(idp , 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((2, "def_dim ierr = %d", ierr)); -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_def_var -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param name the variable name. -//<<>> * @param xtype the PIO_TYPE of the variable. -//<<>> * @param ndims the number of dimensions. -//<<>> * @param dimidsp pointer to array of dimension IDs. -//<<>> * @param varidp a pointer that will get the variable ID. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_def_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_def_var(int ncid, const char *name, nc_type xtype, int ndims, -//<<>> const int *dimidsp, int *varidp) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int invalid_unlim_dim = 0; /* True invalid dims are used. */ -//<<>> int varid; /* The varid of the created var. */ -//<<>> int rec_var = 0; /* Non-zero if this var uses unlimited dim. */ -//<<>> PIO_Offset pio_type_size; /* Size of pio type in bytes. */ -//<<>> MPI_Datatype mpi_type; /* The correspoding MPI type. */ -//<<>> int mpi_type_size; /* Size of mpi type. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> -//<<>> /* Get the file information. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide name. */ -//<<>> if (!name || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_def_var ncid = %d name = %s xtype = %d ndims = %d", ncid, name, -//<<>> xtype, ndims)); -//<<>> -//<<>> /* Run this on all tasks if async is not in use, but only on -//<<>> * non-IO tasks if async is in use. Learn whether each dimension -//<<>> * is unlimited. */ -//<<>> if (!ios->async || !ios->ioproc) -//<<>> { -//<<>> int nunlimdims; -//<<>> -//<<>> /* Get size of type. */ -//<<>> if ((ierr = GDALc_inq_type(ncid, xtype, NULL, &pio_type_size))) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Get the MPI type corresponding with the PIO type. */ -//<<>> if ((ierr = find_mpi_type(xtype, &mpi_type, NULL))) -//<<>> return pio_err(ios, NULL, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Get the size of the MPI type. */ -//<<>> if(mpi_type == MPI_DATATYPE_NULL) -//<<>> mpi_type_size = 0; -//<<>> else -//<<>> if ((mpierr = MPI_Type_size(mpi_type, &mpi_type_size))) -//<<>> return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> /* How many unlimited dims are present in the file? */ -//<<>> if ((ierr = GDALc_inq_unlimdims(ncid, &nunlimdims, NULL))) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> if (nunlimdims) -//<<>> { -//<<>> int unlimdimids[nunlimdims]; -//<<>> -//<<>> /* Find the IDs of the unlimited dimension(s). */ -//<<>> if ((ierr = GDALc_inq_unlimdims(ncid, NULL, unlimdimids))) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Check each dimid for this variable to see it it is an -//<<>> * unlimited dimension. */ -//<<>> for (int d = 0; d < ndims; d++) -//<<>> { -//<<>> int unlim_found = 0; -//<<>> -//<<>> /* Check against each unlimited dimid. */ -//<<>> for (int ud = 0; ud < nunlimdims; ud++) -//<<>> { -//<<>> if (dimidsp[d] == unlimdimids[ud]) -//<<>> { -//<<>> unlim_found++; -//<<>> break; -//<<>> } -//<<>> } -//<<>> -//<<>> /* Only first dim may be unlimited, for PIO. */ -//<<>> if (unlim_found) -//<<>> { -//<<>> if (d == 0) -//<<>> rec_var++; -//<<>> else -//<<>> invalid_unlim_dim++; -//<<>> } -//<<>> } -//<<>> } -//<<>> } -//<<>> -//<<>> /* If using async, and not an IO task, then send parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_DEF_VAR; -//<<>> int namelen = strlen(name); -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&(ncid), 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ndims, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast((void *)dimidsp, ndims, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast values currently only known on computation tasks to IO tasks. */ -//<<>> if ((mpierr = MPI_Bcast(&rec_var, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast(&invalid_unlim_dim, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast(&pio_type_size, 1, MPI_OFFSET, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast(&mpi_type, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast(&mpi_type_size, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* Check that only one unlimited dim is specified, and that it is -//<<>> * first. */ -//<<>> if (invalid_unlim_dim) -//<<>> return PIO_EINVAL; -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> ierr = ncmpi_def_var(file->fh, name, xtype, ndims, dimidsp, &varid); -//<<>>#endif /* _PNETCDF */ -//<<>> -//<<>> if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -//<<>> ierr = nc_def_var(file->fh, name, xtype, ndims, dimidsp, &varid); -//<<>> PLOG((3, "defined var ierr %d file->iotype %d", ierr, file->iotype)); -//<<>> -//<<>>#ifdef _NETCDF4 -//<<>> /* For netCDF-4 parallel files, set parallel access to collective. */ -//<<>> if (!ierr && file->iotype == PIO_IOTYPE_NETCDF4P) -//<<>> ierr = nc_var_par_access(file->fh, varid, NC_COLLECTIVE); -//<<>>#endif /* _NETCDF4 */ -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results. */ -//<<>> if ((mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (varidp) -//<<>> *varidp = varid; -//<<>> -//<<>> /* Add to the list of var_desc_t structs for this file. */ -//<<>> if ((ierr = add_to_varlist(varid, rec_var, xtype, (int)pio_type_size, mpi_type, -//<<>> mpi_type_size, ndims, &file->varlist))) -//<<>> return pio_err(ios, NULL, ierr, __FILE__, __LINE__); -//<<>> file->nvars++; -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * Set the fill value for a variable. -//<<>> * -//<<>> * See the > * href="http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html">netCDF -//<<>> * variable documentation for details about the operation of this -//<<>> * function. -//<<>> * -//<<>> * When the fill mode for the file is NC_FILL, then fill values are -//<<>> * used for missing data. This function sets the fill value to be used -//<<>> * for a variable. If no specific fill value is set (as a _FillValue -//<<>> * attribute), then the default fill values from netcdf.h are used. -//<<>> * -//<<>> * NetCDF-4 and pnetcdf files allow setting fill_mode (to NC_FILL or -//<<>> * NC_NOFILL) on a per-variable basis. NetCDF classic only allows the -//<<>> * fill_mode setting to be set for the whole file. For this function, -//<<>> * the fill_mode parameter is ignored for classic files. Set the -//<<>> * file-level fill mode with GDALc_set_fill(). -//<<>> * -//<<>> * @param ncid the ncid of the open file. -//<<>> * @param varid the ID of the variable to set chunksizes for. -//<<>> * @param fill_mode fill mode for this variable (NC_FILL or NC_NOFILL) -//<<>> * @param fill_valuep pointer to the fill value to be used if fill_mode is set to NC_FILL. -//<<>> * @return PIO_NOERR for success, otherwise an error code. -//<<>> * @ingroup PIO_def_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_def_var_fill(int ncid, int varid, int fill_mode, const void *fill_valuep) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> nc_type xtype; /* The type of the variable (and fill value att). */ -//<<>> PIO_Offset type_size; /* Size in bytes of this variable's type. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> -//<<>> PLOG((1, "GDALc_def_var_fill ncid = %d varid = %d fill_mode = %d\n", ncid, varid, -//<<>> fill_mode)); -//<<>> -//<<>> /* Get the file info. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* Caller must provide correct values. */ -//<<>> if ((fill_mode != NC_FILL && fill_mode != NC_NOFILL) || -//<<>> (fill_mode == NC_FILL && !fill_valuep)) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> /* Run this on all tasks if async is not in use, but only on -//<<>> * non-IO tasks if async is in use. Get the size of this vars -//<<>> * type. */ -//<<>> if (!ios->async || !ios->ioproc) -//<<>> { -//<<>> if ((ierr = GDALc_inq_vartype(ncid, varid, &xtype))) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> if ((ierr = GDALc_inq_type(ncid, xtype, NULL, &type_size))) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> PLOG((2, "GDALc_def_var_fill type_size = %d", type_size)); -//<<>> } -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_DEF_VAR_FILL; -//<<>> char fill_value_present = fill_valuep ? true : false; -//<<>> -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&fill_mode, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&fill_value_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr && fill_value_present) -//<<>> mpierr = MPI_Bcast((PIO_Offset *)fill_valuep, type_size, MPI_CHAR, ios->compmaster, -//<<>> ios->intercomm); -//<<>> PLOG((2, "GDALc_def_var_fill ncid = %d varid = %d fill_mode = %d type_size = %d fill_value_present = %d", -//<<>> ncid, varid, fill_mode, type_size, fill_value_present)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast values currently only known on computation tasks to IO tasks. */ -//<<>> if ((mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> if (ios->ioproc) -//<<>> { -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> ierr = ncmpi_def_var_fill(file->fh, varid, fill_mode, (void *)fill_valuep); -//<<>>#endif /* _PNETCDF */ -//<<>> } -//<<>> else if (file->iotype == PIO_IOTYPE_NETCDF) -//<<>> { -//<<>> PLOG((2, "defining fill value attribute for netCDF classic file")); -//<<>> if (file->do_io) -//<<>> { -//<<>> ierr = nc_set_fill(file->fh, NC_FILL, NULL); -//<<>> if (!ierr) -//<<>> ierr = nc_put_att(file->fh, varid, _FillValue, xtype, 1, fill_valuep); -//<<>> } -//<<>> } -//<<>> else -//<<>> { -//<<>>#ifdef _NETCDF4 -//<<>> if (file->do_io) -//<<>> ierr = nc_def_var_fill(file->fh, varid, fill_mode, fill_valuep); -//<<>>#endif -//<<>> } -//<<>> PLOG((2, "after def_var_fill ierr = %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * The PIO-C interface for the NetCDF function nc_inq_var_fill. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. For more information on the underlying NetCDF commmand -//<<>> * please read about this function in the NetCDF documentation at: -//<<>> * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param no_fill a pointer to int that will get the fill -//<<>> * mode. Ignored if NULL (except with pnetcdf, which seg-faults with -//<<>> * NULL.) -//<<>> * @param fill_valuep pointer to space that gets the fill value for -//<<>> * this variable. Ignored if NULL. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @ingroup PIO_inq_var_c -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_inq_var_fill(int ncid, int varid, int *no_fill, void *fill_valuep) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> nc_type xtype; /* Type of variable and its _FillValue attribute. */ -//<<>> PIO_Offset type_size; /* Size in bytes of this variable's type. */ -//<<>> int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ -//<<>> int ierr = PIO_NOERR; /* Return code from function calls. */ -//<<>> -//<<>> PLOG((1, "GDALc_inq_var_fill ncid = %d varid = %d", ncid, varid)); -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> PLOG((2, "found file")); -//<<>> -//<<>> /* Run this on all tasks if async is not in use, but only on -//<<>> * non-IO tasks if async is in use. Get the size of this vars -//<<>> * type. */ -//<<>> if (!ios->async || !ios->ioproc) -//<<>> { -//<<>> if ((ierr = GDALc_inq_vartype(ncid, varid, &xtype))) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> if ((ierr = GDALc_inq_type(ncid, xtype, NULL, &type_size))) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> PLOG((2, "GDALc_inq_var_fill type_size = %d", type_size)); -//<<>> } -//<<>> -//<<>> /* If async is in use, and this is not an IO task, bcast the parameters. */ -//<<>> if (ios->async) -//<<>> { -//<<>> if (!ios->ioproc) -//<<>> { -//<<>> int msg = PIO_MSG_INQ_VAR_FILL; -//<<>> char no_fill_present = no_fill ? true : false; -//<<>> char fill_value_present = fill_valuep ? true : false; -//<<>> -//<<>> PLOG((2, "sending msg type_size = %d", type_size)); -//<<>> if (ios->compmaster == MPI_ROOT) -//<<>> mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); -//<<>> -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&no_fill_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> if (!mpierr) -//<<>> mpierr = MPI_Bcast(&fill_value_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//<<>> PLOG((2, "GDALc_inq_var_fill ncid = %d varid = %d type_size = %lld no_fill_present = %d fill_value_present = %d", -//<<>> ncid, varid, type_size, no_fill_present, fill_value_present)); -//<<>> } -//<<>> -//<<>> /* Handle MPI errors. */ -//<<>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//<<>> if (mpierr) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast values currently only known on computation tasks to IO tasks. */ -//<<>> if ((mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if ((mpierr = MPI_Bcast(&type_size, 1, MPI_OFFSET, ios->comproot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> } -//<<>> -//<<>> /* If this is an IO task, then call the netCDF function. */ -//<<>> if (ios->ioproc) -//<<>> { -//<<>> PLOG((2, "calling inq_var_fill file->iotype = %d file->fh = %d varid = %d", -//<<>> file->iotype, file->fh, varid)); -//<<>> if (file->iotype == PIO_IOTYPE_PNETCDF) -//<<>> { -//<<>>#ifdef _PNETCDF -//<<>> ierr = ncmpi_inq_var_fill(file->fh, varid, no_fill, fill_valuep); -//<<>>#endif /* _PNETCDF */ -//<<>> } -//<<>> else if (file->iotype == PIO_IOTYPE_NETCDF && file->do_io) -//<<>> { -//<<>> /* Get the file-level fill mode. */ -//<<>> if (no_fill) -//<<>> { -//<<>> if (file->writable) -//<<>> { -//<<>> ierr = nc_set_fill(file->fh, NC_NOFILL, no_fill); -//<<>> if (!ierr) -//<<>> ierr = nc_set_fill(file->fh, *no_fill, NULL); -//<<>> } -//<<>> else -//<<>> { -//<<>> /* pnetcdf and netCDF-4 return PIO_FILL for read-only -//<<>> * files. */ -//<<>> *no_fill = PIO_FILL; -//<<>> } -//<<>> } -//<<>> -//<<>> if (!ierr && fill_valuep) -//<<>> { -//<<>> ierr = nc_get_att(file->fh, varid, _FillValue, fill_valuep); -//<<>> if (ierr == NC_ENOTATT) -//<<>> { -//<<>> char char_fill_value = NC_FILL_CHAR; -//<<>> signed char byte_fill_value = NC_FILL_BYTE; -//<<>> short short_fill_value = NC_FILL_SHORT; -//<<>> int int_fill_value = NC_FILL_INT; -//<<>> float float_fill_value = NC_FILL_FLOAT; -//<<>> double double_fill_value = NC_FILL_DOUBLE; -//<<>> switch (xtype) -//<<>> { -//<<>> case NC_BYTE: -//<<>> memcpy(fill_valuep, &byte_fill_value, sizeof(signed char)); -//<<>> break; -//<<>> case NC_CHAR: -//<<>> memcpy(fill_valuep, &char_fill_value, sizeof(char)); -//<<>> break; -//<<>> case NC_SHORT: -//<<>> memcpy(fill_valuep, &short_fill_value, sizeof(short)); -//<<>> break; -//<<>> case NC_INT: -//<<>> memcpy(fill_valuep, &int_fill_value, sizeof(int)); -//<<>> break; -//<<>> case NC_FLOAT: -//<<>> memcpy(fill_valuep, &float_fill_value, sizeof(float)); -//<<>> break; -//<<>> case NC_DOUBLE: -//<<>> memcpy(fill_valuep, &double_fill_value, sizeof(double)); -//<<>> break; -//<<>> default: -//<<>> return pio_err(ios, file, NC_EBADTYPE, __FILE__, __LINE__); -//<<>> } -//<<>> ierr = PIO_NOERR; -//<<>> } -//<<>> } -//<<>> } -//<<>> else -//<<>> { -//<<>>#ifdef _NETCDF4 -//<<>> /* The inq_var_fill is not supported in classic-only builds. */ -//<<>> if (file->do_io) -//<<>> ierr = nc_inq_var_fill(file->fh, varid, no_fill, fill_valuep); -//<<>>#endif /* _NETCDF */ -//<<>> } -//<<>> PLOG((2, "after call to inq_var_fill, ierr = %d", ierr)); -//<<>> } -//<<>> -//<<>> /* Broadcast and check the return code. */ -//<<>> if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (ierr) -//<<>> return check_netcdf(file, ierr, __FILE__, __LINE__); -//<<>> -//<<>> /* Broadcast results to all tasks. Ignore NULL parameters. */ -//<<>> if (no_fill) -//<<>> if ((mpierr = MPI_Bcast(no_fill, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> if (fill_valuep) -//<<>> if ((mpierr = MPI_Bcast(fill_valuep, type_size, MPI_CHAR, ios->ioroot, ios->my_comm))) -//<<>> check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//<<>> -//<<>> return PIO_NOERR; -//<<>>} -//<<>> -//<<>>/** -//<<>> * @addtogroup PIO_get_att_c Get Attribute Values -//<<>> * Get the values stored in an attribute in C. -//<<>> * @{ -//<<>> */ -//<<>> -//<<>>/** -//<<>> * Get the value of an attribute of any type, with no type conversion. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att(int ncid, int varid, const char *name, void *ip) -//<<>>{ -//<<>> iosystem_desc_t *ios; /* Pointer to io system information. */ -//<<>> file_desc_t *file; /* Pointer to file information. */ -//<<>> int ierr; /* Return code from function calls. */ -//<<>> nc_type atttype; /* The type of the attribute. */ -//<<>> -//<<>> /* Find the info about this file. */ -//<<>> if ((ierr = pio_get_file(ncid, &file))) -//<<>> return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -//<<>> ios = file->iosystem; -//<<>> -//<<>> /* User must provide a name and destination pointer. */ -//<<>> if (!name || !ip || strlen(name) > NC_MAX_NAME) -//<<>> return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); -//<<>> -//<<>> PLOG((1, "GDALc_get_att ncid %d varid %d name %s", ncid, varid, name)); -//<<>> -//<<>> /* Get the type of the attribute. */ -//<<>> if ((ierr = GDALc_inq_att(ncid, varid, name, &atttype, NULL))) -//<<>> return ierr; -//<<>> PLOG((2, "atttype = %d", atttype)); -//<<>> -//<<>> return GDALc_get_att_tc(ncid, varid, name, atttype, ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 64-bit floating point array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_double(int ncid, int varid, const char *name, double *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_DOUBLE, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 8-bit unsigned char array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_uchar(int ncid, int varid, const char *name, unsigned char *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_UBYTE, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 16-bit unsigned integer array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_ushort(int ncid, int varid, const char *name, unsigned short *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_USHORT, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 32-bit unsigned integer array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_uint(int ncid, int varid, const char *name, unsigned int *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_UINT, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 32-bit ingeger array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_long(int ncid, int varid, const char *name, long *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_LONG_INTERNAL, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an text attribute. There is no type conversion -//<<>> * with this call. If the attribute is not of type NC_CHAR, then an -//<<>> * error will be returned. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_text(int ncid, int varid, const char *name, char *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_CHAR, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 8-bit signed char array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_schar(int ncid, int varid, const char *name, signed char *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_BYTE, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 64-bit unsigned integer array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_ulonglong(int ncid, int varid, const char *name, unsigned long long *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_UINT64, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 16-bit integer array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_short(int ncid, int varid, const char *name, short *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_SHORT, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 32-bit integer array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_int(int ncid, int varid, const char *name, int *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_INT, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 64-bit integer array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_longlong(int ncid, int varid, const char *name, long long *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_INT64, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Get the value of an 32-bit floating point array attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute to get -//<<>> * @param ip a pointer that will get the attribute value. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_get_att_float(int ncid, int varid, const char *name, float *ip) -//<<>>{ -//<<>> return GDALc_get_att_tc(ncid, varid, name, PIO_FLOAT, (void *)ip); -//<<>>} -//<<>> -//<<>>/** -//<<>> * @} -//<<>> */ -//<<>> -//<<>>/** -//<<>> * @addtogroup PIO_put_att_c Write an Attribute -//<<>> * Create an attribute in C. -//<<>> * @{ -//<<>> */ -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute of any type. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const void *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, xtype, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 8-bit signed chars. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_schar(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const signed char *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_BYTE, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 32-bit signed integers. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_long(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const long *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_LONG_INTERNAL, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 32-bit signed integers. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_int(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const int *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_INT, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 8-bit unsigned chars. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_uchar(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const unsigned char *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_UBYTE, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 64-bit signed integers. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_longlong(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const long long *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_INT64, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 32-bit unsigned integers. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_uint(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const unsigned int *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_UINT, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 32-bit floating points. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_float(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const float *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_FLOAT, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 64-bit unsigned integers. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_ulonglong(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const unsigned long long *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_UINT64, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 16-bit unsigned integers. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_ushort(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const unsigned short *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_USHORT, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF text attribute. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_text(int ncid, int varid, const char *name, -//<<>> PIO_Offset len, const char *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, NC_CHAR, len, NC_CHAR, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 16-bit integers. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_short(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const short *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_SHORT, op); -//<<>>} -//<<>> -//<<>>/** -//<<>> * Write a netCDF attribute array of 64-bit floating points. -//<<>> * -//<<>> * This routine is called collectively by all tasks in the communicator -//<<>> * ios.union_comm. -//<<>> * -//<<>> * @param ncid the ncid of the open file, obtained from -//<<>> * GDALc_openfile() or GDALc_createfile(). -//<<>> * @param varid the variable ID. -//<<>> * @param name the name of the attribute. -//<<>> * @param xtype the nc_type of the attribute. -//<<>> * @param len the length of the attribute array. -//<<>> * @param op a pointer with the attribute data. -//<<>> * @return PIO_NOERR for success, error code otherwise. -//<<>> * @author Jim Edwards, Ed Hartnett -//<<>> */ -//<<>>int -//<<>>GDALc_put_att_double(int ncid, int varid, const char *name, nc_type xtype, -//<<>> PIO_Offset len, const double *op) -//<<>>{ -//<<>> return GDALc_put_att_tc(ncid, varid, name, xtype, len, PIO_DOUBLE, op); -//<<>>} -/** - * @} - */ diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c index 6bfbcca3ee..ce9d771011 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c @@ -70,14 +70,20 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv //>> if ((ret = nc_inq_var(ncid, v, NULL, &my_type, &var_ndims, NULL, NULL))) //>> return pio_err(NULL, file, ret, __FILE__, __LINE__); OGRFieldType Fld = OGR_Fld_GetType(OGR_FD_GetFieldDefn(hFD,v)); -// printf(">>>>> FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,v)),Fld); + printf(">>>>> FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,v)),Fld); bool typeOK = true; // assume we're good switch (Fld) { case OFTReal: (*pio_type)[v] = (int)PIO_DOUBLE; + (*pio_type_size)[v] = sizeof(double); break; case OFTInteger: (*pio_type)[v] = (int)PIO_INT; + (*pio_type_size)[v] = sizeof(int); + break; + case OFTString: + (*pio_type)[v] = (int)PIO_STRING; + (*pio_type_size)[v] = -1; break; // This needs to be done. How do we deal with timestamps etc in GDAL vector fields? //>>case OFTDate: @@ -88,7 +94,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv //>> break; //>> case OFTDateTime: default: -// printf(">>>> Fld Type: %d\n",Fld); typeOK = false; break; // return pio_err(file->iosystem, file, PIO_EBADIOTYPE, __FILE__, __LINE__); @@ -99,6 +104,8 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv // printf(">>>>> TEST: hDS %p, hFD %p\n", (void *)hDS, (void *)hFD); + printf(">>>> Fld Type: %d %d\n",(*pio_type)[v],PIO_STRING); + if (!typeOK) // Not a usable type continue; @@ -204,8 +211,8 @@ GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) } *fieldidp = OGR_L_FindFieldIndex(hLayer,name,1); - pioassert(*fieldidp > 0, "variable not found", __FILE__, __LINE__); -// printf("INQ_FIELDID FIELD %s INDEX: %d\n", name, *fieldidp); +// pioassert(*fieldidp > 0, "variable not found", __FILE__, __LINE__); + printf("INQ_FIELDID FIELD %s INDEX: %d\n", name, *fieldidp); } } @@ -315,7 +322,7 @@ GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const case PIO_IOTYPE_GDAL: // if (ios->io_rank == 0) { - *hDSp = OGROpen( filename, FALSE, NULL ); + *hDSp = OGROpen( filename, mode, NULL ); if( hDSp != NULL ) ierr = GDALc_inq_file_metadata(file, *hDSp, PIO_IOTYPE_GDAL, @@ -323,7 +330,7 @@ GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const &pio_type_size, &mpi_type, &mpi_type_size, &ndims); PLOG((2, "GDALc_openfile:OGROpen for filename = %s mode = %d " - "ierr = %d", filename, mode, ierr)); + "ierr = %d nvars = %d", filename, mode, ierr, nvars)); } break; @@ -407,11 +414,11 @@ GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const pio_add_to_file_list(file); /* Add info about the variables to the file_desc_t struct. */ - for (int v = 0; v < nvars; v++) + for (int v = 0; v < nvars; v++) { if ((ierr = add_to_varlist(v, rec_var[v], pio_type[v], pio_type_size[v], mpi_type[v], mpi_type_size[v], ndims[v], &file->varlist))) - return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + return pio_err(ios, NULL, ierr, __FILE__, __LINE__);} file->nvars = nvars; /* Free resources. */ @@ -513,7 +520,7 @@ int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTD * @author Jim Edwards, Ed Hartnett */ int -pio_read_darray_shp(file_desc_t *file, io_desc_t *iodesc, int vid, +gdal_read_darray_shp(file_desc_t *file, io_desc_t *iodesc, int vid, void *iobuf) { iosystem_desc_t *ios; /* Pointer to io system information. */ @@ -812,6 +819,636 @@ GDALc_shp_get_double_field(int fileid, int varid, const size_t *startp, return PIO_NOERR; } + +/** + * Create a new file GDAL using pio. Input parameters are read on comp task + * 0 and ignored elsewhere. NOFILL mode will be turned on in all + * cases. + * + * @param iosysid A defined pio system ID, obtained from + * PIOc_InitIntercomm() or PIOc_InitAsync(). + * @param fileidp A pointer that gets the fileid of the newly created + * file. + * @param iotype A pointer to a pio output format. Must be of type + * PIO_IOTYPE_GDAL + * @param filename The filename to create. + * @param mode The mode for the create operation. + * @returns 0 for success, error code otherwise. + * @ingroup PIO_create_file_c + * @author Michael Long. Adapted from work by Jim Edwards, Ed Hartnett + */ +int +GDALc_createfile(int iosysid, int *ncidp, int *iotype, const char *filename, + bool mode) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + int ret; /* Return code from function calls. */ + + /* Get the IO system info from the id. */ + if (!(ios = pio_get_iosystem_from_id(iosysid))) + return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); + + PLOG((1, "GDALc_createfile iosysid = %d iotype = %d filename = %s mode = %d", + iosysid, *iotype, filename, mode)); + + /* Create the file. */ + if ((ret = GDALc_createfile_shp(iosysid, ncidp, iotype, filename, mode))) + return pio_err(ios, NULL, ret, __FILE__, __LINE__); + + /* Set the fill mode to NOFILL. */ +// if ((ret = PIOc_set_fill(*ncidp, NC_NOFILL, NULL))) +// return ret; + + return ret; +} +/** + * Create a new file using pio. This is an internal function that is + * called by GDALc_createfile(). Input + * parameters are read on comp task 0 and ignored elsewhere. + * + * @param iosysid A defined pio system ID, obtained from + * PIOc_Init_Intracomm() or PIOc_InitAsync(). + * @param fileidp A pointer that gets the fileid of the newly created + * file. This is the PIO fileid. Within PIO, the file will have a + * different ID, the file->fh. + * @param iotype A pointer to a pio output format. Must be of type + * PIO_IOTYPE_GDAL. + * @param filename The filename to create. + * @param mode The mode for the create operation. + * + * @returns 0 for success, error code otherwise. + * @ingroup PIO_createfile_c + * @author Michael Long. Adapted from work by Ed Hartnett + */ +int +GDALc_createfile_shp(int iosysid, int *fileidp, int *iotype, const char *filename, bool mode) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ + int ierr; /* Return code from function calls. */ + +#ifdef USE_MPE + pio_start_mpe_log(CREATE); +#endif /* USE_MPE */ + + /* Get the IO system info from the iosysid. */ + if (!(ios = pio_get_iosystem_from_id(iosysid))) + return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); + + /* User must provide valid input for these parameters. */ + if (!fileidp || !iotype || !filename || strlen(filename) > PIO_MAX_NAME) + return pio_err(ios, NULL, PIO_EINVAL, __FILE__, __LINE__); + + /* A valid iotype must be specified. */ + if (!iotype_is_valid(*iotype)) + return pio_err(ios, NULL, PIO_EINVAL, __FILE__, __LINE__); + + PLOG((1, "GDALc_createfile_int iosysid %d iotype %d filename %s mode %d " + , iosysid, *iotype, filename, mode)); + + /* Allocate space for the file info. */ + if (!(file = calloc(sizeof(file_desc_t), 1))) + return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); + + /* Fill in some file values. */ + file->fh = -1; + file->iosystem = ios; + file->iotype = *iotype; + file->buffer = NULL; + file->writable = 1; + + /* Set to true if this task should participate in IO (only true for + * one task with netcdf serial files. */ + if (ios->io_rank == 0) + file->do_io = 1; + + PLOG((2, "file->do_io = %d ios->async = %d", file->do_io, ios->async)); + + /* If async is in use, and this is not an IO task, bcast the + * parameters. */ +//>> if (ios->async) +//>> { +//>> if (!ios->ioproc) +//>> { +//>> int msg = PIO_MSG_CREATE_FILE; +//>> size_t len = strlen(filename); +//>> char fileidp_present = fileidp ? 1 : 0; +//>> +//>> /* Send the message to the message handler. */ +//>> PLOG((3, "msg %d ios->union_comm %d MPI_COMM_NULL %d", msg, ios->union_comm, MPI_COMM_NULL)); +//>> if (ios->compmaster == MPI_ROOT) +//>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); +//>> +//>> /* Send the parameters of the function call. */ +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&len, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast((void *)filename, len + 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&file->iotype, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&mode, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&use_ext_fileid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&fileidp_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); +//>> if (fileidp_present) +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(fileidp, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>>#ifdef NETCDF_INTEGRATION +//>> if (!mpierr) +//>> mpierr = MPI_Bcast(&diosysid, 1, MPI_INT, ios->compmaster, ios->intercomm); +//>>#endif /* NETCDF_INTEGRATION */ +//>> PLOG((2, "len %d filename %s iotype %d mode %d use_ext_fileid %d " +//>> "fileidp_present %d", len, filename, file->iotype, mode, +//>> use_ext_fileid, fileidp_present)); +//>> } +//>> +//>> /* Handle MPI errors. */ +//>> PLOG((2, "handling mpi errors mpierr = %d", mpierr)); +//>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); +//>> if (mpierr) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> } + + /* If this task is in the IO component, do the IO. */ + if (ios->ioproc) + { + switch (file->iotype) + { + case PIO_IOTYPE_GDAL: + PLOG((2, "Calling GDALCreate io_comm = %d mode = %d fh = %d", + ios->io_comm, mode, file->fh)); +// ierr = nc_create_par(filename, mode, ios->io_comm, ios->info, &file->fh); + OGRSpatialReferenceH hSpatial=OSRNewSpatialReference( NULL ); + int err = OSRSetWellKnownGeogCS( hSpatial, "WGS84"); + if (err != OGRERR_NONE ) { + printf("Error setting CRS. %d\n", err); + } + + const char *pszDriverName = "ESRI Shapefile"; + GDALDriverH hDriver = GDALGetDriverByName( pszDriverName ); + if( hDriver == NULL ) + { + printf( "%s driver not available.\n", pszDriverName ); + exit( 1 ); + } + + file->hDS = GDALCreate( hDriver, filename, 0, 0, 0, GDT_Unknown, NULL ); + if( file->hDS == NULL ) + { + printf( "Creation of output file failed.\n" ); + exit( 1 ); + } + PLOG((2, "GDALCreate returned %d file->fh = %d", ierr, file->fh)); + OGRLayerH hLayer = OGR_DS_CreateLayer( file->hDS, "test_", hSpatial, wkbMultiPolygon, NULL ); + if( hLayer == NULL ) + { + printf( "Layer creation failed.\n" ); + exit( 1 ); + } + break; + } + PLOG((3, "create call complete file->fh %d", file->fh)); + } + + /* Broadcast and check the return code. */ + if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + /* If there was an error, free the memory we allocated and handle error. */ + if (ierr) + { + free(file); + return check_netcdf2(ios, NULL, ierr, __FILE__, __LINE__); + } + + /* Broadcast writablility to all tasks. */ + if ((mpierr = MPI_Bcast(&file->writable, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + /* Broadcast next fileid to all tasks from io root, necessary + * because files may be opened on mutilple iosystems, causing the + * underlying library to reuse fileids. Hilarious confusion + * ensues. */ +//>> if (ios->async) +//>> { +//>> PLOG((3, "createfile bcasting pio_next_fileid %d", pio_next_ncid)); +//>> if ((mpierr = MPI_Bcast(&pio_next_ncid, 1, MPI_INT, ios->ioroot, ios->my_comm))) +//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); +//>> PLOG((3, "createfile bcast pio_next_ncid %d", pio_next_ncid)); +//>> } + + /* Assign the PIO ncid. */ + file->pio_ncid = pio_next_ncid++; + + PLOG((2, "file->fh = %d file->pio_ncid = %d", file->fh, file->pio_ncid)); + + /* Return the ncid to the caller. */ + *fileidp = file->pio_ncid; + + /* Add the struct with this files info to the global list of + * open files. */ + pio_add_to_file_list(file); + +#ifdef USE_MPE + pio_stop_mpe_log(CREATE, __func__); +#endif /* USE_MPE */ + PLOG((2, "Created file %s file->fh = %d file->pio_ncid = %d", filename, + file->fh, file->pio_ncid)); + + return ierr; +} + +/** + * The PIO-C interface for the NetCDF function nc_def_var + * + * This routine is called collectively by all tasks in the communicator + * ios.union_comm. For more information on the underlying NetCDF commmand + * please read about this function in the NetCDF documentation at: + * http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html + * + * @param ncid the ncid of the open file, obtained from + * PIOc_openfile() or PIOc_createfile(). + * @param name the variable name. + * @param xtype the PIO_TYPE of the variable. + * @param ndims the number of dimensions. + * @param dimidsp pointer to array of dimension IDs. + * @param varidp a pointer that will get the variable ID. + * @return PIO_NOERR for success, error code otherwise. + * @ingroup PIO_def_var_c + * @author Jim Edwards, Ed Hartnett + */ +int +GDALc_def_field(int fileid, const char *name, int xtype, int *varidp) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + file_desc_t *file; /* Pointer to file information. */ + int invalid_unlim_dim = 0; /* True invalid dims are used. */ + int varid; /* The varid of the created var. */ + int rec_var = 0; /* Non-zero if this var uses unlimited dim. */ + PIO_Offset pio_type_size; /* Size of pio type in bytes. */ + MPI_Datatype mpi_type; /* The correspoding MPI type. */ + int mpi_type_size; /* Size of mpi type. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function codes. */ + int ierr; /* Return code from function calls. */ + + int ndims = 1; // fixed for the moment + + /* Get the file information. */ + if ((ierr = pio_get_file(fileid, &file))) + return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); + ios = file->iosystem; + + /* User must provide name. */ + if (!name || strlen(name) > NC_MAX_NAME) + return pio_err(ios, file, PIO_EINVAL, __FILE__, __LINE__); + +// PLOG((1, "GDALc_def_var ncid = %d name = %s xtype = %d ndims = %d", ncid, name, +// xtype, ndims)); + + /* Run this on all tasks if async is not in use, but only on + * non-IO tasks if async is in use. Learn whether each dimension + * is unlimited. */ + if (!ios->async || !ios->ioproc) + { + int nunlimdims; + + /* Get size of type. */ + switch (xtype) { + case PIO_DOUBLE: + pio_type_size = sizeof(double); + break; + case PIO_REAL: + pio_type_size = sizeof(double); + break; + case PIO_INT: + pio_type_size = sizeof(int); + break; + // This needs to be done. How do we deal with timestamps etc in GDAL vector fields? + //>>case OFTDate: + //>> break; + //>> case OFTTime: + //>> break; + //>> case OFTDate: + //>> break; + //>> case OFTDateTime: + default: + break; + } + /* Get the MPI type corresponding with the PIO type. */ + if ((ierr = find_mpi_type(xtype, &mpi_type, NULL))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + + /* Get the size of the MPI type. */ + if(mpi_type == MPI_DATATYPE_NULL) + mpi_type_size = 0; + else + if ((mpierr = MPI_Type_size(mpi_type, &mpi_type_size))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + } + + /* If using async, and not an IO task, then send parameters. */ + if (ios->async) + { + if (!ios->ioproc) + { + int msg = PIO_MSG_DEF_VAR; + int namelen = strlen(name); + + if (ios->compmaster == MPI_ROOT) + mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); + + if (!mpierr) + mpierr = MPI_Bcast(&(fileid), 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast(&namelen, 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast((void *)name, namelen + 1, MPI_CHAR, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast(&xtype, 1, MPI_INT, ios->compmaster, ios->intercomm); + } + + /* Handle MPI errors. */ + if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) + check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); + if (mpierr) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + + /* Broadcast values currently only known on computation tasks to IO tasks. */ + if ((mpierr = MPI_Bcast(&pio_type_size, 1, MPI_OFFSET, ios->comproot, ios->my_comm))) + check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Bcast(&mpi_type, 1, MPI_INT, ios->comproot, ios->my_comm))) + check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Bcast(&mpi_type_size, 1, MPI_INT, ios->comproot, ios->my_comm))) + check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + } + + /* If this is an IO task, then call the GDAL function. */ + if (ios->ioproc) + { +// if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) +// ierr = nc_def_var(file->fh, name, xtype, ndims, dimidsp, &varid); +// PLOG((3, "defined var ierr %d file->iotype %d", ierr, file->iotype)); + OGRLayerH hL = OGR_DS_GetLayer( file->hDS, 0 ); + OGRFieldDefnH hFD = OGR_Fld_Create( name, OFTReal ); + if( OGR_L_CreateField( hL, hFD, TRUE ) != OGRERR_NONE ) + { + printf( "Creating field failed.\n" ); + exit( 1 ); + } + varid = OGR_L_FindFieldIndex(hL,name,1); + OGR_Fld_Destroy(hFD); + } + + /* Broadcast and check the return code. */ + if ((mpierr = MPI_Bcast(&ierr, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if (ierr) + return check_netcdf(file, ierr, __FILE__, __LINE__); + + /* Broadcast results. */ + if ((mpierr = MPI_Bcast(&varid, 1, MPI_INT, ios->ioroot, ios->my_comm))) + check_mpi(NULL, file, mpierr, __FILE__, __LINE__); + if (varidp) + *varidp = varid; + + /* Add to the list of var_desc_t structs for this file. */ + if ((ierr = add_to_varlist(varid, rec_var, xtype, (int)pio_type_size, mpi_type, + mpi_type_size, ndims, &file->varlist))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + file->nvars++; + + return PIO_NOERR; +} + +/* */ +int +gdal_write_darray_multi_serial(file_desc_t *file, int nvars, int fndims, const int *varids, + io_desc_t *iodesc, int fill, const int *frame) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + var_desc_t *vdesc; /* Contains info about the variable. */ + int ierr; /* Return code. */ + + PLOG((1, "nvars = %d fndims = %d varids[0] = %d maxvars = %d", nvars, fndims, varids[0], PIO_MAX_VARS)); + + /* Check inputs. */ + pioassert(file && file->iosystem && varids && varids[0] >= 0 && + varids[0] <= PIO_MAX_VARS && iodesc, "invalid input", __FILE__, __LINE__); + + PLOG((1, "write_darray_multi_serial nvars = %d fndims = %d iodesc->ndims = %d " + "iodesc->mpitype = %d", nvars, fndims, iodesc->ndims, iodesc->mpitype)); + + /* Get the iosystem info. */ + ios = file->iosystem; + + /* Get the var info. */ + if ((ierr = get_var_desc(varids[0], &file->varlist, &vdesc))) + return pio_err(NULL, file, ierr, __FILE__, __LINE__); + + /* Set these differently for data and fill writing. iobuf may be + * null if array size < number of nodes. */ + int num_regions = fill ? iodesc->maxfillregions: iodesc->maxregions; + io_region *region = fill ? iodesc->fillregion : iodesc->firstregion; + PIO_Offset llen = fill ? iodesc->holegridsize : iodesc->llen; + void *iobuf = fill ? vdesc->fillbuf : file->iobuf; + +#ifdef TIMING + /* Start timer if desired. */ + if ((ierr = pio_start_timer("PIO:write_darray_multi_serial"))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); +#endif /* TIMING */ + + /* Only IO tasks participate in this code. */ + if (ios->ioproc) + { + size_t tmp_start[fndims * num_regions]; /* A start array for each region. */ + size_t tmp_count[fndims * num_regions]; /* A count array for each region. */ + + PLOG((3, "num_regions = %d", num_regions)); + + /* Fill the tmp_start and tmp_count arrays, which contain the + * start and count arrays for all regions. */ + if ((ierr = find_all_start_count(region, num_regions, fndims, iodesc->ndims, vdesc, + tmp_start, tmp_count))) + return pio_err(ios, file, ierr, __FILE__, __LINE__); + + /* Tasks other than 0 will send their data to task 0. */ + if (ios->io_rank > 0) + { + /* Send the tmp_start and tmp_count arrays from this IO task + * to task 0. */ + if ((ierr = send_all_start_count(ios, iodesc, llen, num_regions, nvars, fndims, + tmp_start, tmp_count, iobuf))) + return pio_err(ios, file, ierr, __FILE__, __LINE__); + } + else + { + /* Task 0 will receive data from all other IO tasks. */ + + if ((ierr = recv_and_write_shp(file, varids, frame, iodesc, llen, num_regions, nvars, fndims, + tmp_start, tmp_count, iobuf))) + return pio_err(ios, file, ierr, __FILE__, __LINE__); + } + } + +#ifdef TIMING + if ((ierr = pio_stop_timer("PIO:write_darray_multi_serial"))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); +#endif /* TIMING */ + + return PIO_NOERR; +} + +int +recv_and_write_shp(file_desc_t *file, const int *varids, const int *frame, + io_desc_t *iodesc, PIO_Offset llen, int maxregions, int nvars, + int fndims, size_t *tmp_start, size_t *tmp_count, void *iobuf) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + size_t rlen; /* Length of IO buffer on this task. */ + int rregions; /* Number of regions in buffer for this task. */ + size_t start[fndims], count[fndims]; + size_t loffset; + void *bufptr; + var_desc_t *vdesc; /* Contains info about the variable. */ + MPI_Status status; /* Recv status for MPI. */ + int mpierr; /* Return code from MPI function codes. */ + int ierr; /* Return code. */ + + /* Check inputs. */ + pioassert(file && varids && iodesc && tmp_start && tmp_count, "invalid input", + __FILE__, __LINE__); + + PLOG((2, "recv_and_write_data llen = %d maxregions = %d nvars = %d fndims = %d", + llen, maxregions, nvars, fndims)); + + /* Get pointer to IO system. */ + ios = file->iosystem; + + /* For each of the other tasks that are using this task + * for IO. */ + for (int rtask = 0; rtask < ios->num_iotasks; rtask++) + { + /* From the remote tasks, we send information about + * the data regions. and also the data. */ + if (rtask) + { + /* handshake - tell the sending task I'm ready */ + if ((mpierr = MPI_Send(&ierr, 1, MPI_INT, rtask, 0, ios->io_comm))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + + /* Get length of iobuffer for each field on this + * task (all fields are the same length). */ + if ((mpierr = MPI_Recv(&rlen, 1, MPI_OFFSET, rtask, rtask, ios->io_comm, + &status))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + PLOG((3, "received rlen = %d", rlen)); + + /* Get the number of regions, the start/count + * values for all regions, and the data buffer. */ + if (rlen > 0) + { + if ((mpierr = MPI_Recv(&rregions, 1, MPI_INT, rtask, rtask + ios->num_iotasks, + ios->io_comm, &status))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Recv(tmp_start, rregions * fndims, MPI_OFFSET, rtask, + rtask + 2 * ios->num_iotasks, ios->io_comm, &status))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Recv(tmp_count, rregions * fndims, MPI_OFFSET, rtask, + rtask + 3 * ios->num_iotasks, ios->io_comm, &status))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + if ((mpierr = MPI_Recv(iobuf, nvars * rlen, iodesc->mpitype, rtask, + rtask + 4 * ios->num_iotasks, ios->io_comm, &status))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + PLOG((3, "received data rregions = %d fndims = %d", rregions, fndims)); + } + } + else /* task 0 */ + { + rlen = llen; + rregions = maxregions; + } + PLOG((3, "rtask = %d rlen = %d rregions = %d", rtask, rlen, rregions)); + + /* If there is data from this task, write it. */ + if (rlen > 0) + { + loffset = 0; + for (int regioncnt = 0; regioncnt < rregions; regioncnt++) + { + PLOG((3, "writing data for region with regioncnt = %d", regioncnt)); + bool needtowrite = true; + + if ((ierr = get_var_desc(varids[0], &file->varlist, &vdesc))) + return pio_err(NULL, file, ierr, __FILE__, __LINE__); + + /* Get the start/count arrays for this region. */ + for (int i = 0; i < fndims; i++) + { + start[i] = tmp_start[i + regioncnt * fndims]; + count[i] = tmp_count[i + regioncnt * fndims]; + PLOG((3, "needtowrite %d count[%d] %d\n",needtowrite, i, count[i])); + if(i>0 || vdesc->record <0) + needtowrite = (count[i] > 0 && needtowrite); + } + + /* Process each variable in the buffer. */ + for (int nv = 0; nv < nvars; nv++) + { + PLOG((3, "writing buffer var %d", nv)); + + /* Get a pointer to the correct part of the buffer. */ + bufptr = (void *)((char *)iobuf + iodesc->mpitype_size * (nv * rlen + loffset)); + + /* If this var has an unlimited dim, set + * the start on that dim to the frame + * value for this variable. */ + if (vdesc->record >= 0) + { + if (fndims > 1 && iodesc->ndims < fndims && count[1] > 0) + { + count[0] = 1; + start[0] = frame[nv]; + } + else if (fndims == iodesc->ndims) + { + start[0] += vdesc->record; + } + } + +#ifdef LOGGING + if(needtowrite) + for (int i = 1; i < fndims; i++) + PLOG((3, "(serial) start[%d] %d count[%d] %d needtowrite %d", i, start[i], i, count[i], needtowrite)); +#endif /* LOGGING */ + + /* Call the netCDF functions to write the data. */ +// if (needtowrite) +// if ((ierr = nc_put_vara(file->fh, varids[nv], start, count, bufptr))) +// return check_netcdf2(ios, NULL, ierr, __FILE__, __LINE__); + + } /* next var */ + + /* Calculate the total size. */ + size_t tsize = 1; + for (int i = 0; i < fndims; i++) + tsize *= count[i]; + + /* Keep track of where we are in the buffer. */ + loffset += tsize; + + PLOG((3, " at bottom of loop regioncnt = %d tsize = %d loffset = %d", regioncnt, + tsize, loffset)); + } /* next regioncnt */ + } /* endif (rlen > 0) */ + } /* next rtask */ + + return PIO_NOERR; +} /** * @} */ diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c index f39656b64f..2da40df7b1 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c @@ -873,11 +873,11 @@ find_mpi_type(int pio_type, MPI_Datatype *mpi_type, int *type_size) my_mpi_type = MPI_UNSIGNED_LONG_LONG; my_type_size = NETCDF_DOUBLE_INT64_SIZE; break; +#endif /* _NETCDF4 */ case PIO_STRING: my_mpi_type = MPI_CHAR; my_type_size = NETCDF_CHAR_SIZE; break; -#endif /* _NETCDF4 */ default: return PIO_EBADTYPE; } diff --git a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h index c582d4eb94..0a74838138 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_GDAL.h @@ -154,7 +154,7 @@ enum GDAL_REARRANGERS int GDALc_inq_vardimid(int ncid, int varid, int *dimidsp); int GDALc_deletefile(int iosysid, const char *filename); - int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char *fname, bool mode); +// int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char *fname, bool mode); int GDALc_create(int iosysid, const char *path, int cmode, int *ncidp); // int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *fname, bool mode); int GDALc_open(int iosysid, const char *path, int mode, int *ncidp); diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index 4c7c17f36f..f13bbd9b33 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -571,7 +571,7 @@ void GDAL_Handler::arrayReadOneTileFile( int * arrDims; // Array shape int narrDims; // Array rank int iodesc; // GDAL IO descriptor - GDALDatasetH filedesc; // GDAL file descriptor + GDALDatasetH filedesc; // GDAL file descriptor int fileID; int fielddesc; // GDAL field descriptor int basegdaltype; // GDAL version of Array data type @@ -759,413 +759,147 @@ void GDAL_Handler::arrayWriteOneTileFile( // //EOPI //----------------------------------------------------------------------------- -//>> // initialize return code; assume routine not implemented -//>> int localrc = ESMF_RC_NOT_IMPL; // local return code -//>> int gdalrc; // GDAL error value -//>> int * ioDims; // Array IO shape -//>> int nioDims; // Array IO rank -//>> int * arrDims; // Array shape -//>> int narrDims; // Array rank -//>> int iodesc; // GDAL IO descriptor -//>> int filedesc; // GDAL file descriptor -//>> int vardesc = 0; // GDAL variable descriptor -//>> int basegdaltype; // GDAL version of Array data type -//>> void *baseAddress; // The address of the Array IO data -//>> int localDE; // DE to use for IO -//>> int ncDims[8]; // To hold NetCDF dimensions -//>> int unlim = -1; // Unlimited dimension ID -//>> int timeFrame = -1; // ID of time dimension (>0 if used) -//>> int timesliceVal = -1; // Used time value (from timeslice) -//>> bool varExists = false; // true if varname is defined in file -//>> std::string varname; // Variable name -//>> if (rc != NULL) { -//>> *rc = ESMF_RC_NOT_IMPL; // final return code -//>> } -//>> -//>> PRINTPOS; -//>> -//>> if ((int *)NULL != timeslice) { -//>> timesliceVal = *timeslice; -//>> } -//>> // File open? -//>> if (isOpen(tile) != ESMF_TRUE) -//>> if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", -//>> ESMC_CONTEXT, rc)) return; -//>> -//>> // Array compatible with this object? -//>> localrc = checkArray(arr_p); -//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) -//>> return; -//>> -//>> filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based -//>> iodesc = getIODesc(gdalSystemDesc, arr_p, tile, &ioDims, &nioDims, -//>> &arrDims, &narrDims, &basegdaltype, &localrc); -//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, -//>> ESMC_CONTEXT, rc)) return; -//>> for (int i=0; i> if (arrDims[i] < 0) { -//>> if (ESMC_LogDefault.MsgFoundError (ESMF_RC_INTNRL_BAD, "array dimension extent < 0", -//>> ESMC_CONTEXT, rc)) return; -//>> } -//>> } -//>> -//>> if (dimLabels.size() > 0 && dimLabels.size() < (unsigned int)nioDims) { -//>> std::stringstream errmsg; -//>> errmsg << dimLabels.size() << " user dimension label(s) supplied, " << nioDims << " expected"; -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_SIZE, errmsg, -//>> ESMC_CONTEXT, rc)) return; -//>> } -//>> -//>> -//>> // Get a pointer to the array data -//>> // Still have the one DE restriction so use localDE = 0 -//>> localDE = 0; -//>> int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDE, &localrc); -//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, -//>> ESMC_CONTEXT, rc)) return; -//>> int arrlen; -//>> if (tileOfThisDe == tile) { -//>> baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); -//>> PRINTMSG("baseAddress = 0x" << (void *)baseAddress); -//>> // arrlen = arr_p->getLocalarrayList()[localDE]->getByteCount(); -//>> arrlen = 1; -//>> const int *counts = arr_p->getLocalarrayList()[localDE]->getCounts(); -//>> for (int i=0; i> arrlen *= counts[i]; -//>> } else { -//>> baseAddress = NULL; -//>> arrlen = 0; -//>> } -//>> PRINTMSG("arrlen = " << arrlen); -//>> -//>>#if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) -//>> // Define the variable name and check the file -//>> if (((char *)NULL != name) && (strlen(name) > 0)) { -//>> varname = name; -//>> } else { -//>> varname = arr_p->getName(); -//>> } -//>> PRINTMSG("varname = \"" << varname << "\""); -//>> if (ESMF_TRUE == isNewFile(tile)) { -//>> varExists = false; -//>> } else { -//>> int nVar; // Number of variables in file -//>> int nAtt; // Number of attributes in file -//>> int nfDims; // Number of dimensions in file -//>> PRINTMSG("Entering NetCDF define mode (redef)"); -//>> gdalrc = GDALc_redef(filedesc); -//>> // Not all NetCDF errors are really errors here so we need to check -//>> if ((GDAL_NOERR != gdalrc) && (NC_EINDEFINE != gdalrc)) { -//>> if (!CHECKGDALERROR(gdalrc, -//>> ((NC_EPERM == gdalrc) ? -//>> "File is read only" : -//>> "File is not in NetCDF format"), -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> } -//>> -//>> // This should work if it is a NetCDF file. -//>> PRINTMSG("Calling GDALc_inq"); -//>> gdalrc = GDALc_inq(filedesc, &nfDims, -//>> &nVar, &nAtt, &unlim); -//>> if (!CHECKGDALERROR(gdalrc, "File is not in NetCDF format", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> -//>> // We have a NetCDF file, see if the variable is in there -//>> PRINTMSG("Looking for variable in file"); -//>> gdalrc = GDALc_inq_varid(filedesc, varname.c_str(), &vardesc); -//>> // This should succeed if the variable exists -//>> varExists = (GDAL_NOERR == gdalrc); -//>> } -//>> -//>> // Check consistency of time dimension with timeslice -//>> bool hasTimeDim; -//>> -//>> int dimidTime; -//>> GDAL_Offset timeLen; -//>> PRINTMSG("Checking time dimension"); -//>> //gdalrc = GDALc_inq_dimid(filedesc, "time", &dimidTime); -//>> gdalrc = GDALc_inq_unlimdim(filedesc, &dimidTime); -//>> // NetCDF does not specify which error code goes with with -//>> // condition so we will guess that there is no time dimension -//>> // on any error condition (This may be an error depending on context). -//>> hasTimeDim = (GDAL_NOERR == gdalrc && dimidTime != -1); -//>> PRINTMSG("inq_dimid = " << gdalrc); -//>> PRINTMSG("hasTimeDim = " << hasTimeDim); -//>> PRINTMSG("unlim = " << unlim); -//>> if (hasTimeDim) { -//>> // Retrieve the max time field -//>> gdalrc = GDALc_inq_dimlen(filedesc, dimidTime, &timeLen); -//>> PRINTMSG("inq_dimlen = " << gdalrc); -//>> PRINTMSG("dimidTime = " << dimidTime); -//>> PRINTMSG("timeLen = " << timeLen); -//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving information about time", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> -//>> // Check to make sure that time is the unlimited dimension -//>> if (dimidTime != unlim) -//>> if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, -//>> "Time is not the file's unlimited dimension", -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } -//>> if (timesliceVal >= 0) { -//>> if (varExists & !hasTimeDim) { -//>> // It is an error to not have a time dimension if we are trying to -//>> // write a timeslice and the variable already exists -//>> // (it won't have time) -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, -//>> "Field already exists without time dimension", -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } else { -//>> timeFrame = timesliceVal; -//>> } -//>> } else if (timesliceVal < 0) { -//>> // Special case for no timeslice input passed but time dimension exists -//>> if (varExists && hasTimeDim) { -//>> timeFrame = timeLen + 1; -//>> PRINTMSG("timeslice not passed but set to " << timeFrame); -//>> } -//>> } -//>> -//>> PRINTMSG("ready to check var compat., timeFrame = " << timeFrame); -//>> if (varExists) { -//>> int nDims; -//>> int nArrdims = nioDims + ((timeFrame > 0) ? 1 : 0); -//>> -//>> // Check compatibility between array to write and existing variable. -//>> gdalrc = GDALc_inq_varndims(filedesc, vardesc, &nDims); -//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> -//>> if (nDims != nArrdims) { -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, -//>> "Variable rank in file does not match array", -//>> ESMC_CONTEXT, rc)) { -//>> PRINTMSG("Variable rank mismatch: nioDims = " << nioDims << -//>> ", nArrdims = " << nArrdims << ", nDims = " << nDims); -//>> return; -//>> } -//>> } -//>> -//>> PRINTMSG("Calling gdal_cpp_inq_vardimid_vdesc"); -//>> std::vector dimIds(nDims); -//>> gdalrc = GDALc_inq_vardimid(filedesc, vardesc, &dimIds.front()); -//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving information about variable", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> -//>> MPI_Offset dimLen; -//>> int ioDimNum = 0; -//>> for (int i = 0; i < nDims; i++) { -//>> gdalrc = GDALc_inq_dimlen(filedesc, dimIds[i], &dimLen); -//>> if (!CHECKGDALERROR(gdalrc, "Error retrieving dimension information", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> PRINTMSG("GDALc_inq_dimlen for dim = " << i << " dimLen="<> -//>> if (dimIds[i] == unlim) { -//>> if (timeFrame <= 0) { -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, -//>> "File variable requires time dimension", -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } else if ((timeFrame <= dimLen) && !overwriteFields()) { -//>> // This 'error' might be incorrect in that we can't figure -//>> // out the max frame of this variable, only for the whole file. -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_UNEXPECTED, -//>> "Can't overwrite timeslice", -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } -//>> } else if (dimLen != ioDims[nDims - ioDimNum - 1 - int(hasTimeDim)]) { -//>> PRINTMSG("dimLen = "<> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } else { -//>> ioDimNum++; -//>> } -//>> } -//>> } -//>> -//>> if (varExists && !overwriteFields() && (timeFrame <= 0)) { -//>> // Check to see if we can overwrite an existing field or timeslice -//>> std::string errmsg = "Variable " + varname + " pre-exists, however overwrite flag is .false."; -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, errmsg, -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } -//>> -//>> if (!varExists) { -//>> // Ensure we are in define mode -//>> PRINTMSG("Going into NetCDF define mode (redef)"); -//>> gdalrc = GDALc_redef(filedesc); -//>> // Not all NetCDF errors are really errors here so we need to check -//>> if ((GDAL_NOERR != gdalrc) && (NC_EINDEFINE != gdalrc)) { -//>> if (!CHECKGDALERROR(gdalrc, -//>> ((NC_EPERM == gdalrc) ? -//>> "File is read only" : -//>> "File is not in NetCDF format"), -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> } -//>> } -//>> -//>> if (!varExists) { -//>> // Create the variable -//>> for (int i = 0; i < nioDims; i++) { -//>> std::string axis; -//>> if (dimLabels.size() > 0) -//>> axis = dimLabels[i]; -//>> else { -//>> std::stringstream axis_tmp; -//>> axis_tmp << varname << "_dim" << std::setfill('0') << std::setw(3) << i+1; -//>> axis = axis_tmp.str(); -//>> } -//>> -//>> // if dimension already exists, use it. -//>> int dimid_existing; -//>> gdalrc = GDALc_inq_dimid(filedesc, axis.c_str(), &dimid_existing); -//>> if (GDAL_NOERR == gdalrc) { -//>> MPI_Offset dim_len; -//>> gdalrc = GDALc_inq_dimlen(filedesc, dimid_existing, &dim_len); -//>> if (!CHECKGDALERROR(gdalrc, "Error finding existing dimension length", ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> if (ioDims[i] != dim_len) { -//>> std::stringstream msg; -//>> msg << "Existing dimension " << axis << " length " << dim_len << " != required " << ioDims[i]; -//>> if (ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_WRITE, msg, -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } -//>> ncDims[nioDims - i - 1] = dimid_existing; -//>> } else { -//>> PRINTMSG("Defining dimension " << i); -//>> gdalrc = GDALc_def_dim(filedesc, axis.c_str(), -//>> ioDims[i], &ncDims[nioDims - i - 1]); -//>> if (!CHECKGDALERROR(gdalrc, std::string("Defining dimension: ") + axis, -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> } -//>> } -//>> PRINTMSG("finished defining space dims, timeFrame = " << timeFrame); -//>> -//>> if (timeFrame > -1) { -//>> nioDims++; -//>> for(int i=nioDims;i>0;i--) -//>> ncDims[i] = ncDims[i-1]; -//>> if (hasTimeDim) { -//>> gdalrc = GDALc_inq_dimid (filedesc, "time", &ncDims[0]); -//>> if (!CHECKGDALERROR(gdalrc, "Attempting to obtain 'time' dimension ID", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> } else { -//>> PRINTMSG("Defining time dimension"); -//>> gdalrc = GDALc_def_dim(filedesc, "time", -//>> GDAL_UNLIMITED, &ncDims[0]); -//>> if (!CHECKGDALERROR(gdalrc, "Attempting to define 'time' dimension", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> } -//>> } -//>> } -//>> PRINTMSG("varExists = " << varExists); -//>> if (!varExists) { -//>> PRINTMSG("niodims = " << nioDims); -//>> PRINTMSG("basegdaltype = " << basegdaltype); -//>> -//>> gdalrc = GDALc_def_var(filedesc, varname.c_str(), basegdaltype, -//>> nioDims, ncDims, &vardesc); -//>> if (!CHECKGDALERROR(gdalrc, "Attempting to define GDAL vardesc for: " + varname, -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> } -//>> if (timeFrame >= 0) { -//>>#ifdef ESMFIO_DEBUG -//>> int nvdims; -//>> GDALc_inq_varndims(filedesc, vardesc, &nvdims); -//>> PRINTMSG("calling setframe, timeFrame = " << timeFrame); -//>>#endif // ESMFIO_DEBUG -//>> gdalrc = GDALc_setframe(filedesc, vardesc, timeFrame-1); -//>> if (!CHECKGDALERROR(gdalrc, "Attempting to setframe for: " + varname, -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> } -//>>#ifdef ESMFIO_DEBUG -//>> else { -//>> PRINTMSG("NOT calling setframe, timeFrame = " << timeFrame); -//>> } -//>> if (varExists) { -//>> int varid; -//>> int lrc; -//>> lrc = GDALc_inq_varid(filedesc, varname.c_str(), &varid); -//>> PRINTMSG("varid = " << varid); -//>> } -//>>#endif // ESMFIO_DEBUG -//>> -//>> // ESMF Attribute Package -> NetCDF variable and global attributes -//>> if (varAttPack) { -//>> attPackPut (vardesc, varAttPack, tile, &localrc); -//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } -//>> if (gblAttPack) { -//>> attPackPut (NC_GLOBAL, gblAttPack, tile, &localrc); -//>> if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, -//>> ESMC_CONTEXT, rc)) { -//>> return; -//>> } -//>> } -//>> -//>> -//>> PRINTMSG("calling enddef, status = " << rc); -//>> -//>> gdalrc = GDALc_enddef(filedesc); -//>> if (!CHECKGDALERROR(gdalrc, "Attempting to end definition of variable: " + varname, -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> -//>>#endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) -//>> PRINTMSG("calling write_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); -//>> // Write the array -//>> ESMCI_IOREGION_ENTER("GDALc_write_darray"); -//>> gdalrc = GDALc_write_darray(filedesc, vardesc, iodesc, arrlen, -//>> (void *)baseAddress, NULL); -//>> if (!CHECKGDALERROR(gdalrc, "Attempting to write file", -//>> ESMF_RC_FILE_WRITE, (*rc))) { -//>> return; -//>> } -//>> new_file[tile-1] = false; -//>> ESMCI_IOREGION_EXIT("GDALc_write_darray"); + // initialize return code; assume routine not implemented + int localrc = ESMF_RC_NOT_IMPL; // local return code + int gdalrc; // GDAL error value + int * ioDims; // Array IO shape + int nioDims; // Array IO rank + int * arrDims; // Array shape + int narrDims; // Array rank + int iodesc; // GDAL IO descriptor + GDALDatasetH filedesc; // GDAL file descriptor + int fileID; + int vardesc = 0; // GDAL variable descriptor + int basegdaltype; // GDAL version of Array data type + void *baseAddress; // The address of the Array IO data + int localDE; // DE to use for IO + int ncDims[8]; // To hold NetCDF dimensions + int unlim = -1; // Unlimited dimension ID + int timeFrame = -1; // ID of time dimension (>0 if used) + int timesliceVal = -1; // Used time value (from timeslice) + bool varExists = false; // true if varname is defined in file + std::string varname; // Variable name + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; // final return code + } + + PRINTPOS; + + if ((int *)NULL != timeslice) { + timesliceVal = *timeslice; + } + // File open? + if (isOpen(tile) != ESMF_TRUE) + if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", + ESMC_CONTEXT, rc)) return; + + // Array compatible with this object? + localrc = checkArray(arr_p); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + + filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based + fileID = gdalFileID[tile-1]; // note that tile indices are 1-based + iodesc = getIODesc(gdalSystemDesc, arr_p, tile, &ioDims, &nioDims, + &arrDims, &narrDims, &basegdaltype, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) return; + for (int i=0; i 0 && dimLabels.size() < (unsigned int)nioDims) { + std::stringstream errmsg; + errmsg << dimLabels.size() << " user dimension label(s) supplied, " << nioDims << " expected"; + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_ARG_SIZE, errmsg, + ESMC_CONTEXT, rc)) return; + } + + + // Get a pointer to the array data + // Still have the one DE restriction so use localDE = 0 + localDE = 0; + int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDE, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, rc)) return; + int arrlen; + if (tileOfThisDe == tile) { + baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); + PRINTMSG("baseAddress = 0x" << (void *)baseAddress); + // arrlen = arr_p->getLocalarrayList()[localDE]->getByteCount(); + arrlen = 1; + const int *counts = arr_p->getLocalarrayList()[localDE]->getCounts(); + for (int i=0; i= 0 ); + } + + // Check consistency of time dimension with timeslice + bool hasTimeDim; + + int dimidTime; +// GDAL_Offset timeLen; + PRINTMSG("Checking time dimension"); + + // NetCDF does not specify which error code goes with with + // condition so we will guess that there is no time dimension + // on any error condition (This may be an error depending on context). + hasTimeDim = (PIO_NOERR == gdalrc && dimidTime != -1); + PRINTMSG("inq_dimid = " << gdalrc); + PRINTMSG("hasTimeDim = " << hasTimeDim); + PRINTMSG("unlim = " << unlim); + +// 1) Create the datasource and file. <-- Should be created by openOneFile() +// 2) Define the layer +// 3) Define the field + if (!varExists) { + ESMCI_IOREGION_ENTER("GDALc_write_darray"); + gdalrc = GDALc_def_field(fileID, varname.c_str(), basegdaltype, &vardesc); + if (!CHECKGDALERROR(gdalrc, "Attempting to define GDAL/PIO vardesc for: " + varname, + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + } + + PRINTMSG("calling write_darray, gdal type = " << basegdaltype << ", address = " << baseAddress); + // Write the array + ESMCI_IOREGION_ENTER("GDALc_write_darray"); + gdalrc = PIOc_write_darray(fileID, vardesc, iodesc, arrlen, + (void *)baseAddress, NULL); + if (!CHECKGDALERROR(gdalrc, "Attempting to write file", + ESMF_RC_FILE_WRITE, (*rc))) { + return; + } + new_file[tile-1] = false; + ESMCI_IOREGION_EXIT("GDALc_write_darray"); // Cleanup & return PRINTMSG("cleanup and return"); @@ -1309,7 +1043,7 @@ void GDAL_Handler::openOneTileFile( // Looks like we are ready to try and create the file ESMCI_IOREGION_ENTER("GDALc_createfile"); - gdalrc = GDALc_createfile(gdalSystemDesc, &(gdalFileDesc[tile-1]), + gdalrc = GDALc_createfile(gdalSystemDesc, &(gdalFileID[tile-1]), &iotype, thisFilename.c_str(), mode); ESMCI_IOREGION_EXIT("GDALc_createfile"); if (!CHECKGDALWARN(gdalrc, std::string("Unable to create file: ") + thisFilename, @@ -1319,11 +1053,6 @@ void GDAL_Handler::openOneTileFile( new_file[tile-1] = true; PRINTMSG("call to GDALc_createfile: success for " << thisFilename << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "<> gdalrc = GDALc_set_fill(gdalFileDesc[tile-1], GDAL_NOFILL, NULL); -//>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to set fill on file: ") + thisFilename, -//>> ESMF_RC_FILE_OPEN, (*rc))) { -//>> return; -//>> } } else { PRINTMSG(" calling GDALc_openfile with mode = " << mode << ", file = \"" << thisFilename << "\""); // Looks like we are ready to go @@ -1486,11 +1215,11 @@ ESMC_Logical GDAL_Handler::isOpen( //EOPI //----------------------------------------------------------------------------- PRINTPOS; - GDALDatasetH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based - if (filedesc == NULL) { + int fileid = gdalFileID[tile-1]; // note that tile indices are 1-based + if (fileid == NULL) { PRINTMSG("gdalFileDesc is NULL"); return ESMF_FALSE; - } else if (filedesc != NULL) { + } else if (fileid != NULL) { PRINTMSG("File is open"); return ESMF_TRUE; } else { diff --git a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C index e270e7daf4..f8d5550b89 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_GDAL.C @@ -270,29 +270,29 @@ int GDALc_inq_field(int ncid, int varid, char *name, int *xtypep, int *ndimsp, //>> return PIO_NOERR; } -int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char *filename, - bool mode) -{ - iosystem_desc_t *ios; /* Pointer to io system information. */ - int ret; /* Return code from function calls. */ - -//>> /* Get the IO system info from the id. */ -//>> if (!(ios = pio_get_iosystem_from_id(iosysid))) -//>> return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); +//>>int GDALc_createfile(int iosysid, OGRDataSourceH *ncidp, int *iotype, const char *filename, +//>> bool mode) +//>>{ +//>> iosystem_desc_t *ios; /* Pointer to io system information. */ +//>> int ret; /* Return code from function calls. */ //>> -//>> PLOG((1, "PIOc_createfile iosysid = %d iotype = %d filename = %s mode = %d", -//>> iosysid, *iotype, filename, mode)); +//>>//>> /* Get the IO system info from the id. */ +//>>//>> if (!(ios = pio_get_iosystem_from_id(iosysid))) +//>>//>> return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); +//>>//>> +//>>//>> PLOG((1, "PIOc_createfile iosysid = %d iotype = %d filename = %s mode = %d", +//>>//>> iosysid, *iotype, filename, mode)); +//>>//>> +//>>//>> /* Create the file. */ +//>>//>> if ((ret = PIOc_createfile_int(iosysid, ncidp, iotype, filename, mode, 0))) +//>>//>> return pio_err(ios, NULL, ret, __FILE__, __LINE__); +//>>//>> +//>>//>> /* Set the fill mode to NOFILL. */ +//>>//>> if ((ret = PIOc_set_fill(*ncidp, NC_NOFILL, NULL))) +//>>//>> return ret; //>> -//>> /* Create the file. */ -//>> if ((ret = PIOc_createfile_int(iosysid, ncidp, iotype, filename, mode, 0))) -//>> return pio_err(ios, NULL, ret, __FILE__, __LINE__); -//>> -//>> /* Set the fill mode to NOFILL. */ -//>> if ((ret = PIOc_set_fill(*ncidp, NC_NOFILL, NULL))) -//>> return ret; - - return ret; -} +//>> return ret; +//>>} //<<>>int GDALc_openfile(int iosysid, OGRDataSourceH *hDSp, int *iotype, const char *filename, //<<>> bool mode) diff --git a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 index 4e25db04a5..1531cbacf4 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 @@ -60,8 +60,8 @@ program ESMF_IO_GDALUTest type(ESMF_ArraySpec) :: arraySpec -! character(len=*), parameter :: fileNameFields = "data/complex_3.shp" - character(len=*), parameter :: fileNameFields = "data/cb_2018_us_county_20m.shp" + character(len=*), parameter :: fileNameFields = "data/complex_3.shp" +! character(len=*), parameter :: fileNameFields = "data/cb_2018_us_county_20m.shp" !------------------------------------------------------------------------ call ESMF_TestStart(ESMF_SRCLINE, rc=rc) ! calls ESMF_Initialize() internally @@ -87,8 +87,8 @@ program ESMF_IO_GDALUTest write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_ArraySpecSet(arraySpec, 1, typekind=ESMF_TYPEKIND_R8, rc=rc) if (rc /= ESMF_SUCCESS) return - field = ESMF_FieldCreate(mesh, arraySpec, name="GEOID", meshLoc=ESMF_MESHLOC_ELEMENT, rc=rc) -! field = ESMF_FieldCreate(mesh, arraySpec, name="DistFld", meshLoc=ESMF_MESHLOC_ELEMENT, rc=rc) +! field = ESMF_FieldCreate(mesh, arraySpec, name="GEOID", meshLoc=ESMF_MESHLOC_ELEMENT, rc=rc) + field = ESMF_FieldCreate(mesh, arraySpec, name="DistFld", meshLoc=ESMF_MESHLOC_ELEMENT, rc=rc) if (rc /= ESMF_SUCCESS) return ! call ESMF_FieldPrint(field, rc=rc) ! if (rc /= ESMF_SUCCESS) return @@ -105,7 +105,8 @@ program ESMF_IO_GDALUTest write(name, *) "Read a multi-tile Field" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_FieldRead(field, fileName=fileNameFields, iofmt=ESMF_IOFMT_SHP, rc=rc) - call ESMF_FieldWrite(field, "test.nc",overwrite=.true.,rc=rc) + call ESMF_FieldWrite(field, "test.shp", iofmt=ESMF_IOFMT_SHP, overwrite=.true.,rc=rc) +! call ESMF_FieldWrite(field, "test.nc", rc=rc) #if (defined ESMF_PIO && (defined ESMF_GDAL)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else From 659d603c78c1e8bbb5c267aed844930b4621a03a Mon Sep 17 00:00:00 2001 From: Michael Long Date: Fri, 24 Nov 2023 09:40:37 -0500 Subject: [PATCH 22/58] Stopping here to wait for a proper MeshWrite() capability from on high -- MSL --- gisDev.org | 3 + .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 111 +----------------- .../IO/tests/ESMF_IO_GDALUTest.F90 | 6 +- 3 files changed, 12 insertions(+), 108 deletions(-) diff --git a/gisDev.org b/gisDev.org index e89e455ed0..71a95011d9 100644 --- a/gisDev.org +++ b/gisDev.org @@ -126,3 +126,6 @@ Proposed workflow: 1) Determine file type 2) Get driver 3) Define spatial reference w/ CRS + +* Nov 16, 2023 - WriteMesh +Legacy/ESMCI_MeshRead.C -> call to WriteVTKMesh() in ESMCI_VTKMesh.C diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c index ce9d771011..11e9059a63 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c @@ -32,7 +32,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); *nvars = OGR_FD_GetFieldCount(hFD); -// printf(">>>>> NVARS: %d\n",*nvars); if (nvars == 0) // empty file return pio_err(NULL, file, PIO_ENOMEM, __FILE__, __LINE__); @@ -63,12 +62,9 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv * learn about type. */ size_t type_size; - // var_ndims = 1; // FIXED FOR NOW. For data-read purposes, it's a 1D stream across the number of // elements. (*ndims)[v] = var_ndims; - //>> if ((ret = nc_inq_var(ncid, v, NULL, &my_type, &var_ndims, NULL, NULL))) - //>> return pio_err(NULL, file, ret, __FILE__, __LINE__); OGRFieldType Fld = OGR_Fld_GetType(OGR_FD_GetFieldDefn(hFD,v)); printf(">>>>> FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,v)),Fld); bool typeOK = true; // assume we're good @@ -96,14 +92,7 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv default: typeOK = false; break; -// return pio_err(file->iosystem, file, PIO_EBADIOTYPE, __FILE__, __LINE__); } - //>> if ((ret = nc_inq_type(ncid, (*pio_type)[v], NULL, &type_size))) - //>> return check_netcdf(file, ret, __FILE__, __LINE__); - //>> (*pio_type_size)[v] = type_size; - -// printf(">>>>> TEST: hDS %p, hFD %p\n", (void *)hDS, (void *)hFD); - printf(">>>> Fld Type: %d %d\n",(*pio_type)[v],PIO_STRING); if (!typeOK) // Not a usable type @@ -120,19 +109,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv if ((mpierr = MPI_Type_size((*mpi_type)[v], &(*mpi_type_size)[v]))) return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//>> /* What are the dimids associated with this var? */ -//>> if (var_ndims) -//>> { -//>> int var_dimids[var_ndims]; -//>> if (iotype == PIO_IOTYPE_GDAL) -//>> { -//>>//>> if ((ret = nc_inq_vardimid(ncid, v, var_dimids))) -//>>//>> return pio_err(NULL, file, ret, __FILE__, __LINE__); -//>> } -//>> -//>> } - -// OGR_FD_Destroy(hFD); } /* next var */ } /* If PIO_TYPE_GDAL */ return PIO_NOERR; @@ -202,7 +178,6 @@ GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) { GDALDatasetH *hDS = file->hDS; if (file->do_io) { // We assume that its a GDAL file -// printf("NLayers: %d\n", OGR_DS_GetLayerCount(hDS)); OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); OGR_L_ResetReading(hLayer); if (hLayer == NULL) { @@ -211,7 +186,6 @@ GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) } *fieldidp = OGR_L_FindFieldIndex(hLayer,name,1); -// pioassert(*fieldidp > 0, "variable not found", __FILE__, __LINE__); printf("INQ_FIELDID FIELD %s INDEX: %d\n", name, *fieldidp); } @@ -233,7 +207,6 @@ GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) int GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const char *filename, bool mode) -//GDALc_openfile(int iosysid, GDALDatasetH *hDSp, int *iotype, const char *filename, bool mode) { iosystem_desc_t *ios; /* Pointer to io system information. */ file_desc_t *file; /* Pointer to file information. */ @@ -263,9 +236,6 @@ GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const if (*iotype != PIO_IOTYPE_GDAL ) return pio_err(ios, NULL, PIO_EINVAL, __FILE__, __LINE__); -// PLOG((2, "PIOc_openfile_retry iosysid = %d iotype = %d filename = %s mode = %d retry = %d", -// iosysid, *iotype, filename, mode, retry)); - /* Allocate space for the file info. */ if (!(file = calloc(sizeof(*file), 1))) return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); @@ -303,8 +273,6 @@ GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const mpierr = MPI_Bcast(&file->iotype, 1, MPI_INT, ios->compmaster, ios->intercomm); if (!mpierr) mpierr = MPI_Bcast(&mode, 1, MPI_INT, ios->compmaster, ios->intercomm); -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(&use_ext_ncid, 1, MPI_INT, ios->compmaster, ios->intercomm); } /* Handle MPI errors. */ @@ -359,14 +327,6 @@ GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp,int *iotype, const if ((mpierr = MPI_Bcast(&file->writable, 1, MPI_INT, ios->ioroot, ios->my_comm))) return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); - /* Broadcast some values to all tasks from io root. */ -//>> if (ios->async) -//>> { -//>> PLOG((3, "open bcasting pio_next_ncid %d ios->ioroot %d", pio_next_ncid, ios->ioroot)); -//>> if ((mpierr = MPI_Bcast(&pio_next_ncid, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//>> } - if ((mpierr = MPI_Bcast(&nvars, 1, MPI_INT, ios->ioroot, ios->my_comm))) return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); @@ -477,7 +437,6 @@ int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTD OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); if (hFD == NULL) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -// printf("XXXXX NFLDS: %d, FID %d, hDS %p, hFD %p\n", file->nvars, fileid, (void *)file->hDS, (void *)hFD); int nFld = OGR_FD_GetFieldCount(hFD); OGRFieldDefnH hTMP = OGR_FD_GetFieldDefn(hFD,1); hTMP = OGR_FD_GetFieldDefn(hFD,0); @@ -488,14 +447,8 @@ int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTD OGRFieldType Fld = OGR_Fld_GetType(hFlD); if (Fld == NULL) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -// printf("XXXXX FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,i)),Fld); - -// const char* FldTyp = OGR_GetFieldTypeName(Fld); -// PRINTMSG("Field type: " << FldTyp); } -// OGR_FD_Destroy(hFD); - return 0; } @@ -531,6 +484,8 @@ gdal_read_darray_shp(file_desc_t *file, io_desc_t *iodesc, int vid, int mpierr; /* Return code from MPI functions. */ int ierr; + PLOG((1, "XXX fndims = %d vid = %d maxvars = %d", fndims, vid, PIO_MAX_VARS)); + /* Check inputs. */ pioassert(file && file->iosystem && iodesc && vid >= 0 && vid <= PIO_MAX_VARS, "invalid input", __FILE__, __LINE__); @@ -925,54 +880,6 @@ GDALc_createfile_shp(int iosysid, int *fileidp, int *iotype, const char *filenam PLOG((2, "file->do_io = %d ios->async = %d", file->do_io, ios->async)); - /* If async is in use, and this is not an IO task, bcast the - * parameters. */ -//>> if (ios->async) -//>> { -//>> if (!ios->ioproc) -//>> { -//>> int msg = PIO_MSG_CREATE_FILE; -//>> size_t len = strlen(filename); -//>> char fileidp_present = fileidp ? 1 : 0; -//>> -//>> /* Send the message to the message handler. */ -//>> PLOG((3, "msg %d ios->union_comm %d MPI_COMM_NULL %d", msg, ios->union_comm, MPI_COMM_NULL)); -//>> if (ios->compmaster == MPI_ROOT) -//>> mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); -//>> -//>> /* Send the parameters of the function call. */ -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(&len, 1, MPI_INT, ios->compmaster, ios->intercomm); -//>> if (!mpierr) -//>> mpierr = MPI_Bcast((void *)filename, len + 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(&file->iotype, 1, MPI_INT, ios->compmaster, ios->intercomm); -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(&mode, 1, MPI_INT, ios->compmaster, ios->intercomm); -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(&use_ext_fileid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(&fileidp_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); -//>> if (fileidp_present) -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(fileidp, 1, MPI_INT, ios->compmaster, ios->intercomm); -//>>#ifdef NETCDF_INTEGRATION -//>> if (!mpierr) -//>> mpierr = MPI_Bcast(&diosysid, 1, MPI_INT, ios->compmaster, ios->intercomm); -//>>#endif /* NETCDF_INTEGRATION */ -//>> PLOG((2, "len %d filename %s iotype %d mode %d use_ext_fileid %d " -//>> "fileidp_present %d", len, filename, file->iotype, mode, -//>> use_ext_fileid, fileidp_present)); -//>> } -//>> -//>> /* Handle MPI errors. */ -//>> PLOG((2, "handling mpi errors mpierr = %d", mpierr)); -//>> if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) -//>> return check_mpi(NULL, file, mpierr2, __FILE__, __LINE__); -//>> if (mpierr) -//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//>> } - /* If this task is in the IO component, do the IO. */ if (ios->ioproc) { @@ -981,7 +888,7 @@ GDALc_createfile_shp(int iosysid, int *fileidp, int *iotype, const char *filenam case PIO_IOTYPE_GDAL: PLOG((2, "Calling GDALCreate io_comm = %d mode = %d fh = %d", ios->io_comm, mode, file->fh)); -// ierr = nc_create_par(filename, mode, ios->io_comm, ios->info, &file->fh); + OGRSpatialReferenceH hSpatial=OSRNewSpatialReference( NULL ); int err = OSRSetWellKnownGeogCS( hSpatial, "WGS84"); if (err != OGRERR_NONE ) { @@ -1033,13 +940,6 @@ GDALc_createfile_shp(int iosysid, int *fileidp, int *iotype, const char *filenam * because files may be opened on mutilple iosystems, causing the * underlying library to reuse fileids. Hilarious confusion * ensues. */ -//>> if (ios->async) -//>> { -//>> PLOG((3, "createfile bcasting pio_next_fileid %d", pio_next_ncid)); -//>> if ((mpierr = MPI_Bcast(&pio_next_ncid, 1, MPI_INT, ios->ioroot, ios->my_comm))) -//>> return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//>> PLOG((3, "createfile bcast pio_next_ncid %d", pio_next_ncid)); -//>> } /* Assign the PIO ncid. */ file->pio_ncid = pio_next_ncid++; @@ -1189,9 +1089,6 @@ GDALc_def_field(int fileid, const char *name, int xtype, int *varidp) /* If this is an IO task, then call the GDAL function. */ if (ios->ioproc) { -// if (file->iotype != PIO_IOTYPE_PNETCDF && file->do_io) -// ierr = nc_def_var(file->fh, name, xtype, ndims, dimidsp, &varid); -// PLOG((3, "defined var ierr %d file->iotype %d", ierr, file->iotype)); OGRLayerH hL = OGR_DS_GetLayer( file->hDS, 0 ); OGRFieldDefnH hFD = OGR_Fld_Create( name, OFTReal ); if( OGR_L_CreateField( hL, hFD, TRUE ) != OGRERR_NONE ) @@ -1428,6 +1325,8 @@ recv_and_write_shp(file_desc_t *file, const int *varids, const int *frame, /* Call the netCDF functions to write the data. */ // if (needtowrite) + // ADD POLYGONS + // ADD DATA // if ((ierr = nc_put_vara(file->fh, varids[nv], start, count, bufptr))) // return check_netcdf2(ios, NULL, ierr, __FILE__, __LINE__); diff --git a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 index 1531cbacf4..7728926e24 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 @@ -105,8 +105,10 @@ program ESMF_IO_GDALUTest write(name, *) "Read a multi-tile Field" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_FieldRead(field, fileName=fileNameFields, iofmt=ESMF_IOFMT_SHP, rc=rc) - call ESMF_FieldWrite(field, "test.shp", iofmt=ESMF_IOFMT_SHP, overwrite=.true.,rc=rc) -! call ESMF_FieldWrite(field, "test.nc", rc=rc) +! call ESMF_FieldWrite(field, "test.shp", iofmt=ESMF_IOFMT_SHP, overwrite=.true.,rc=rc) + call ESMF_FieldWrite(field, "test.nc", rc=rc) + !! Write mesh for debugging + call ESMF_MeshWrite(mesh,"complex_3",rc=rc) #if (defined ESMF_PIO && (defined ESMF_GDAL)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else From 7f042948e1c6a403c799a089729ab2914b428b49 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Tue, 28 Nov 2023 16:41:14 -0500 Subject: [PATCH 23/58] This should be the up-to-date Mesh Create & Read capability. It has been cleaned up for merging with the main repository I expect a lot of feedback and edits. There is much more work to be done. -- MSL --- .../IO/PIO/ParallelIO/src/clib/pio.h | 3 +- .../IO/PIO/ParallelIO/src/clib/pio_file.c | 5 + .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 26 ---- .../IO/src/ESMCI_GDAL_Handler.C | 130 +++++++++--------- .../IO/tests/ESMF_IO_GDALUTest.F90 | 7 +- src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C | 14 +- .../Mesh/src/ESMCI_Mesh_FileIO.C | 28 ---- 7 files changed, 72 insertions(+), 141 deletions(-) diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h index abbdddd78e..b66ef11f06 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h @@ -1342,8 +1342,7 @@ extern "C" { int GDALc_openfile(int iosysid, int *fileIDp, GDALDatasetH *hDSp, int *iotype, const char *fname, bool mode); int GDALc_sync(int fileid); int GDALc_shp_get_int_field(int fileid); - int GDALc_shp_get_double_field(int fileid, int varid, const size_t *startp, - const size_t *countp, double *ip); + int GDALc_shp_get_double_field(int fileid, int varid, const size_t *startp, const size_t *countp, double *ip); #if defined(__cplusplus) } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c index 03052a5c7a..d50c916409 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c @@ -473,6 +473,11 @@ PIOc_sync(int ncid) flush_output_buffer(file, true, 0); break; #endif +//#ifdef _GDAL + case PIO_IOTYPE_GDAL: + printf("<<>> PIOc_sync() TEST <<>>"); + break; +//#endif default: return pio_err(ios, file, PIO_EBADIOTYPE, __FILE__, __LINE__); } diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c index 6bfbcca3ee..3e3f305844 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c @@ -32,7 +32,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); *nvars = OGR_FD_GetFieldCount(hFD); -// printf(">>>>> NVARS: %d\n",*nvars); if (nvars == 0) // empty file return pio_err(NULL, file, PIO_ENOMEM, __FILE__, __LINE__); @@ -70,7 +69,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv //>> if ((ret = nc_inq_var(ncid, v, NULL, &my_type, &var_ndims, NULL, NULL))) //>> return pio_err(NULL, file, ret, __FILE__, __LINE__); OGRFieldType Fld = OGR_Fld_GetType(OGR_FD_GetFieldDefn(hFD,v)); -// printf(">>>>> FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,v)),Fld); bool typeOK = true; // assume we're good switch (Fld) { case OFTReal: @@ -88,7 +86,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv //>> break; //>> case OFTDateTime: default: -// printf(">>>> Fld Type: %d\n",Fld); typeOK = false; break; // return pio_err(file->iosystem, file, PIO_EBADIOTYPE, __FILE__, __LINE__); @@ -97,8 +94,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv //>> return check_netcdf(file, ret, __FILE__, __LINE__); //>> (*pio_type_size)[v] = type_size; -// printf(">>>>> TEST: hDS %p, hFD %p\n", (void *)hDS, (void *)hFD); - if (!typeOK) // Not a usable type continue; @@ -113,19 +108,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv if ((mpierr = MPI_Type_size((*mpi_type)[v], &(*mpi_type_size)[v]))) return check_mpi(NULL, file, mpierr, __FILE__, __LINE__); -//>> /* What are the dimids associated with this var? */ -//>> if (var_ndims) -//>> { -//>> int var_dimids[var_ndims]; -//>> if (iotype == PIO_IOTYPE_GDAL) -//>> { -//>>//>> if ((ret = nc_inq_vardimid(ncid, v, var_dimids))) -//>>//>> return pio_err(NULL, file, ret, __FILE__, __LINE__); -//>> } -//>> -//>> } - -// OGR_FD_Destroy(hFD); } /* next var */ } /* If PIO_TYPE_GDAL */ return PIO_NOERR; @@ -195,7 +177,6 @@ GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) { GDALDatasetH *hDS = file->hDS; if (file->do_io) { // We assume that its a GDAL file -// printf("NLayers: %d\n", OGR_DS_GetLayerCount(hDS)); OGRLayerH hLayer = OGR_DS_GetLayer( hDS, 0 ); OGR_L_ResetReading(hLayer); if (hLayer == NULL) { @@ -205,7 +186,6 @@ GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) *fieldidp = OGR_L_FindFieldIndex(hLayer,name,1); pioassert(*fieldidp > 0, "variable not found", __FILE__, __LINE__); -// printf("INQ_FIELDID FIELD %s INDEX: %d\n", name, *fieldidp); } } @@ -470,18 +450,15 @@ int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTD OGRFeatureDefnH hFD = OGR_L_GetLayerDefn(hLayer); if (hFD == NULL) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -// printf("XXXXX NFLDS: %d, FID %d, hDS %p, hFD %p\n", file->nvars, fileid, (void *)file->hDS, (void *)hFD); int nFld = OGR_FD_GetFieldCount(hFD); OGRFieldDefnH hTMP = OGR_FD_GetFieldDefn(hFD,1); hTMP = OGR_FD_GetFieldDefn(hFD,0); for (int i=0;i<(file->nvars)-1;i++) { - printf("XXXXX i: %d\n", i); OGRFieldDefnH hFlD = OGR_FD_GetFieldDefn(hFD,i); OGRFieldType Fld = OGR_Fld_GetType(hFlD); if (Fld == NULL) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -// printf("XXXXX FIELDNAME: %s, TYPE: %d\n",OGR_Fld_GetNameRef(OGR_FD_GetFieldDefn(hFD,i)),Fld); // const char* FldTyp = OGR_GetFieldTypeName(Fld); // PRINTMSG("Field type: " << FldTyp); @@ -740,8 +717,6 @@ pio_read_darray_shp(file_desc_t *file, io_desc_t *iodesc, int vid, case PIO_SHORT: return pio_err(ios, file, PIO_EBADTYPE, __FILE__, __LINE__); case PIO_INT: - printf("Int 1: Start %d, Count %d, fndims %d\n", start[0], count[0],fndims); - printf("Int 2: Start %d, Count %d\n", start[fndims-1], count[fndims-1]); ierr = GDALc_shp_get_int_field(file->pio_ncid); break; case PIO_FLOAT: @@ -807,7 +782,6 @@ GDALc_shp_get_double_field(int fileid, int varid, const size_t *startp, hF = OGR_L_GetFeature(hL,i); ip[i] = OGR_F_GetFieldAsDouble(hF,varid); -// printf("Data %d: %0.2f\n",i,ip[i]); } return PIO_NOERR; diff --git a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C index 4c7c17f36f..707c8a4ab1 100644 --- a/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_GDAL_Handler.C @@ -21,6 +21,7 @@ // The code in this file implements the C++ {\tt ESMC\_GDAL_Handler} methods // declared in the companion file {\tt ESMCI\_GDAL_Handler.h} // +// This was adapted from the module ESMCI_PIO_Handler.C -- MSL //------------------------------------------------------------------------- #define GDAL_DEBUG_LEVEL 4 // include associated header file @@ -201,7 +202,7 @@ void GDAL_Handler::initialize ( // Just return error (error code may be different on different PEs). // Broadcast the error to all PEs (consistant error handling) // GDALc_Set_IOSystem_Error_Handling(instance, GDAL_BCAST_ERROR); - PRINTMSG("After GDALc_Set_IOSystem_Error_Handling"); +// PRINTMSG("After GDALc_Set_IOSystem_Error_Handling"); // Add the instance to the global list GDAL_Handler::activeGdalInstances.push_back(instance); PRINTMSG("push_back"); @@ -668,7 +669,7 @@ void GDAL_Handler::arrayReadOneTileFile( //>> arrlen *= arrDims[i]; //>> } -// TBD! THIS REQUIRES SOME DISCUSSION: HOW TO DEAL WITH FILES W/O DATE/TIME DEFS? +//>> TBD! THIS REQUIRES SOME DISCUSSION: HOW TO DEAL WITH FILES W/O DATE/TIME DEFS? -- MSL int dimid_time; MPI_Offset time_len; gdalrc = GDALc_inq_timeid(fileID, &dimid_time); @@ -677,35 +678,35 @@ void GDAL_Handler::arrayReadOneTileFile( //>> } // Check to make sure the requested record is in the file -// gdalrc = GDALc_inq_dimlen(filedesc, -// dimid_time, &time_len); -// if (!CHECKGDALERROR(gdalrc, "Error finding time length", ESMF_RC_FILE_READ, (*rc))) { -// return; -// } -// if (*timeslice > time_len) { -// PRINTMSG(" (" << my_rank << "): " << -// "Timeframe is greater than that in file" << -// getFilename(tile) << ", file time = " << time_len << -// ", requested record = " << *timeslice); -// if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, -// "Timeframe is greater than max in file", -// ESMC_CONTEXT, rc)) { -// return; -// } -// } -// frame = (*timeslice); -// } else { -// frame = -1; -// for (int i=0; i= 0 && frame > 0) { -// PRINTMSG("calling setframe for read_darray, frame = " << frame); -// GDALc_setframe(filedesc, vardesc, frame-1); -// } +//>> gdalrc = GDALc_inq_dimlen(filedesc, +//>> dimid_time, &time_len); +//>> if (!CHECKGDALERROR(gdalrc, "Error finding time length", ESMF_RC_FILE_READ, (*rc))) { +//>> return; +//>> } +//>> if (*timeslice > time_len) { +//>> PRINTMSG(" (" << my_rank << "): " << +//>> "Timeframe is greater than that in file" << +//>> getFilename(tile) << ", file time = " << time_len << +//>> ", requested record = " << *timeslice); +//>> if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, +//>> "Timeframe is greater than max in file", +//>> ESMC_CONTEXT, rc)) { +//>> return; +//>> } +//>> } +//>> frame = (*timeslice); +//>> } else { +//>> frame = -1; +//>> for (int i=0; i> // Note that arrDims[i] will be 0 if this DE doesn't own the current tile +//>> arrlen *= arrDims[i]; +//>> } +//>> +//>> } +//>> if (unlim >= 0 && frame > 0) { +//>> PRINTMSG("calling setframe for read_darray, frame = " << frame); +//>> GDALc_setframe(filedesc, vardesc, frame-1); +//>> } PRINTPOS; PRINTMSG("calling read_darray, gdal type = " << basepiotype << ", address = " << baseAddress); // Read in the array @@ -713,10 +714,10 @@ void GDAL_Handler::arrayReadOneTileFile( gdalrc = PIOc_read_darray(fileID, fielddesc, iodesc, arrlen, (void *)baseAddress); -// -// if (!CHECKGDALERROR(gdalrc, "Error reading array data", ESMF_RC_FILE_READ, (*rc))) { -// return; -// } + + if (!CHECKGDALERROR(gdalrc, "Error reading array data", ESMF_RC_FILE_READ, (*rc))) { + return; + } // return if (rc != NULL) { @@ -1319,11 +1320,6 @@ void GDAL_Handler::openOneTileFile( new_file[tile-1] = true; PRINTMSG("call to GDALc_createfile: success for " << thisFilename << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "<> gdalrc = GDALc_set_fill(gdalFileDesc[tile-1], GDAL_NOFILL, NULL); -//>> if (!CHECKGDALWARN(gdalrc, std::string("Unable to set fill on file: ") + thisFilename, -//>> ESMF_RC_FILE_OPEN, (*rc))) { -//>> return; -//>> } } else { PRINTMSG(" calling GDALc_openfile with mode = " << mode << ", file = \"" << thisFilename << "\""); // Looks like we are ready to go @@ -1331,7 +1327,7 @@ void GDAL_Handler::openOneTileFile( gdalrc = GDALc_openfile(gdalSystemDesc, (&gdalFileID[tile-1]), (&gdalFileDesc[tile-1]), &iotype, thisFilename.c_str(), mode); ESMCI_IOREGION_EXIT("GDALc_openfile"); -// PRINTMSG("NLayers 0: " << OGR_DS_GetLayerCount(gdalFileDesc[tile-1])); +//>> DEBUG: PRINTMSG("NLayers 0: " << OGR_DS_GetLayerCount(gdalFileDesc[tile-1])); PRINTMSG(", called GDALc_openfile on " << thisFilename); if (!CHECKGDALWARN(gdalrc, std::string("Unable to open existing file: ") + thisFilename, ESMF_RC_FILE_OPEN, (*rc))) { @@ -1366,7 +1362,7 @@ void GDAL_Handler::attPackPut ( ) { // // !DESCRIPTION: -// Puts the Attributes and their values into the NetCDF file. If vardesc is 0, the +// Puts the Attributes and their values into the GDAL file. If vardesc is 0, the // attribute will be considered a global attribute. // //EOPI @@ -1488,10 +1484,10 @@ ESMC_Logical GDAL_Handler::isOpen( PRINTPOS; GDALDatasetH filedesc = gdalFileDesc[tile-1]; // note that tile indices are 1-based if (filedesc == NULL) { - PRINTMSG("gdalFileDesc is NULL"); +//>> PRINTMSG("gdalFileDesc is NULL"); return ESMF_FALSE; } else if (filedesc != NULL) { - PRINTMSG("File is open"); +//>> PRINTMSG("File is open"); return ESMF_TRUE; } else { // This really should not happen, warn and clean up just in case @@ -1544,10 +1540,8 @@ void GDAL_Handler::flushOneTileFile( PRINTMSG("calling sync"); //>> ESMCI_IOREGION_ENTER("GDALc_sync"); if (gdalFileDesc[tile-1] != NULL) { -// OGR_DS_Destroy(gdalFileDesc[tile-1]); - printf("Flushing tile %d, hDS %p\n", tile, (void *)gdalFileDesc[tile-1]); +//>> OGR_DS_Destroy(gdalFileDesc[tile-1]); gdalrc = PIOc_sync(gdalFileID[tile-1]); - printf("Flush code: %d, tile %d\n",gdalrc, tile); } //>> GDALc_sync(gdalFileDesc[tile-1]); //>> ESMCI_IOREGION_EXIT("GDALc_sync"); @@ -2154,27 +2148,27 @@ int GDAL_IODescHandler::freeGdalDecomp( return ESMF_RC_ARG_BAD; } -//>> // Look for newDecomp_p in the active handle instances -//>> for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); -//>> it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); ++it) { -//>> handle = *it; -//>> if (*decomp_p == handle->io_descriptor) { -//>> foundHandle = true; -//>> delete handle; -//>> handle = (GDAL_IODescHandler *)NULL; -//>> *decomp_p = (int)NULL; -//>> break; -//>> } -//>> } -//>> -//>> // If we didn't find the handle, that is bad -//>> if (foundHandle) { -//>> localrc = ESMF_SUCCESS; -//>> } else { -//>> ESMC_LogDefault.Write("GDAL IO descriptor not found or freed", -//>> ESMC_LOGMSG_ERROR, ESMC_CONTEXT); -//>> localrc = ESMF_RC_MEM_DEALLOCATE; -//>> } + // Look for newDecomp_p in the active handle instances + for (it = GDAL_IODescHandler::activeGdalIoDescriptors.begin(); + it < GDAL_IODescHandler::activeGdalIoDescriptors.end(); ++it) { + handle = *it; + if (*decomp_p == handle->io_descriptor) { + foundHandle = true; + delete handle; + handle = (GDAL_IODescHandler *)NULL; + *decomp_p = (int)NULL; + break; + } + } + + // If we didn't find the handle, that is bad + if (foundHandle) { + localrc = ESMF_SUCCESS; + } else { + ESMC_LogDefault.Write("GDAL IO descriptor not found or freed", + ESMC_LOGMSG_ERROR, ESMC_CONTEXT); + localrc = ESMF_RC_MEM_DEALLOCATE; + } return localrc; } // GDAL_IODescHandler::freeGdalDecomp() diff --git a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 index 4e25db04a5..37291d1575 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_GDALUTest.F90 @@ -60,8 +60,7 @@ program ESMF_IO_GDALUTest type(ESMF_ArraySpec) :: arraySpec -! character(len=*), parameter :: fileNameFields = "data/complex_3.shp" - character(len=*), parameter :: fileNameFields = "data/cb_2018_us_county_20m.shp" + character(len=*), parameter :: fileNameFields = "data/complex_3.shp" !------------------------------------------------------------------------ call ESMF_TestStart(ESMF_SRCLINE, rc=rc) ! calls ESMF_Initialize() internally @@ -87,8 +86,7 @@ program ESMF_IO_GDALUTest write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_ArraySpecSet(arraySpec, 1, typekind=ESMF_TYPEKIND_R8, rc=rc) if (rc /= ESMF_SUCCESS) return - field = ESMF_FieldCreate(mesh, arraySpec, name="GEOID", meshLoc=ESMF_MESHLOC_ELEMENT, rc=rc) -! field = ESMF_FieldCreate(mesh, arraySpec, name="DistFld", meshLoc=ESMF_MESHLOC_ELEMENT, rc=rc) + field = ESMF_FieldCreate(mesh, arraySpec, name="DistFld", meshLoc=ESMF_MESHLOC_ELEMENT, rc=rc) if (rc /= ESMF_SUCCESS) return ! call ESMF_FieldPrint(field, rc=rc) ! if (rc /= ESMF_SUCCESS) return @@ -105,7 +103,6 @@ program ESMF_IO_GDALUTest write(name, *) "Read a multi-tile Field" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_FieldRead(field, fileName=fileNameFields, iofmt=ESMF_IOFMT_SHP, rc=rc) - call ESMF_FieldWrite(field, "test.nc",overwrite=.true.,rc=rc) #if (defined ESMF_PIO && (defined ESMF_GDAL)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else diff --git a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C index 92b0d9fc6e..de36e3966c 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_GDAL_Util.C @@ -105,7 +105,6 @@ void ESMCI_GDAL_SHP_get_feature_info(OGRDataSourceH hDS, int *nFeatures, int *&F for (int i=0;i<*nFeatures;i++) { hFeature = OGR_L_GetNextFeature(hLayer); FeatureIDs[i] = OGR_F_GetFID(hFeature); -// printf("FEATURE ID %d\n", FeatureIDs[i]); OGR_F_Destroy( hFeature ); } @@ -293,8 +292,6 @@ void ESMCI_GDAL_process_shapefile_distributed( int nGeom = 0; int ierr = getLayerInfo(hLayer, &nPoints, &nGeom); -// printf("Number of shapefile elements/points/geometries: %d/%d/%d\n\n",nElements,nPoints,nGeom); - // Rewind to the beginning, just in case OGR_L_ResetReading(hLayer); @@ -340,7 +337,6 @@ void ESMCI_GDAL_process_shapefile_distributed( // Pass OGR Values to Mesh arrays int j = 0; for (int i=0;i>>>> nElems, %d, nFeatures, %d\n", num_elems, num_features); node_IDs=&nodeIDs[0]; elem_Conn=&elemConn[0]; @@ -1391,15 +1384,6 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, for(std::vector::iterator it = numElemConn.begin(); it != numElemConn.end(); ++it) sumElemConn += *it; -// printf("dim: %d\n",dim); -// printf("numElemConn: %d\n",numElemConn.size()); -// printf("elemConn: %d\n",elemConn.size()); -// printf("num_elems: %d\n",num_elems); -// printf("num_ftrs: %d\n",num_features); -// printf("num_nodes: %d\n",num_nodes); -// printf("totNumElmCon: %d\n",totNumElemConn); -// printf("sum_of_elems: %d\n",sumElemConn); - // TBD: Coord system conversion /* At this point, we've read the shapfile and defined @@ -1429,8 +1413,6 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) throw localrc; - // printf("Finished creating mesh: %d\n", localrc); - // Add nodes ESMCI_meshaddnodes(out_mesh, &num_nodes, node_IDs, nodeCoords, NULL, NULL, @@ -1439,8 +1421,6 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) throw localrc; - // printf("Finished adding nodes: %d\n", localrc); - // Add elements // !!! None of the elements have shared edges. int areaPresent = 0; @@ -1455,17 +1435,9 @@ void ESMCI_mesh_create_from_SHAPEFILE_file(char *filename, if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &localrc)) throw localrc; - // printf("Finished adding elements: %d\n", localrc); - // Cleanup GDALClose( hDS ); -// delete [] elem_IDs; -// delete [] elem_Conn; -// delete [] node_IDs; -// delete [] num_ElemConn; -// delete [] nodeCoords; - } catch(std::exception &x) { // catch Mesh exception return code From 4a492cfcabd59d5d0c73cf60ddf36343ffffb420 Mon Sep 17 00:00:00 2001 From: Michael Long Date: Tue, 5 Dec 2023 07:30:37 -0500 Subject: [PATCH 24/58] Fixed some incomplete merges. MSL --- .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c index b44f9aaa94..cd00eed5c1 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_gdal.c @@ -92,15 +92,6 @@ GDALc_inq_file_metadata(file_desc_t *file, GDALDatasetH hDS, int iotype, int *nv typeOK = false; break; } -<<<<<<< HEAD - printf(">>>> Fld Type: %d %d\n",(*pio_type)[v],PIO_STRING); - -======= - //>> if ((ret = nc_inq_type(ncid, (*pio_type)[v], NULL, &type_size))) - //>> return check_netcdf(file, ret, __FILE__, __LINE__); - //>> (*pio_type_size)[v] = type_size; - ->>>>>>> msl/shapefile_io_v1.0.1 if (!typeOK) // Not a usable type continue; @@ -191,13 +182,6 @@ GDALc_inq_fieldid(int fileid, const char *name, int *fieldidp) return -1; } *fieldidp = OGR_L_FindFieldIndex(hLayer,name,1); - -<<<<<<< HEAD - printf("INQ_FIELDID FIELD %s INDEX: %d\n", name, *fieldidp); -======= - pioassert(*fieldidp > 0, "variable not found", __FILE__, __LINE__); ->>>>>>> msl/shapefile_io_v1.0.1 - } } @@ -456,12 +440,6 @@ int GDALc_inq_timeid(int fileid, int *timeid) { // Is there a field of type OFTD OGRFieldType Fld = OGR_Fld_GetType(hFlD); if (Fld == NULL) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); -<<<<<<< HEAD -======= - -// const char* FldTyp = OGR_GetFieldTypeName(Fld); -// PRINTMSG("Field type: " << FldTyp); ->>>>>>> msl/shapefile_io_v1.0.1 } return 0; From 34b551e1d03e5a3a357e8425ddd5a28ed0faffce Mon Sep 17 00:00:00 2001 From: Michael Long Date: Thu, 4 Jan 2024 10:48:32 -0500 Subject: [PATCH 25/58] OK. Brought NCAR/ParallelIO into ESMF as a git subrepo. in prep for a PR to diagnose the GDAL read issues. MSL --- ParallelIO/.github/workflows/autotools.yml | 66 + ParallelIO/.github/workflows/cmake.yml | 64 + .../.github/workflows/cmake_ubuntu_latest.yml | 68 + .../netcdf_hdf5_no_pnetcdf_ncint_mpich.yml | 119 + .../netcdf_hdf5_pnetcdf_ncint_mpich_asan.yml | 162 + .../workflows/netcdf_pnetcdf_openmpi.yml | 156 + .../strict_autotools_ubuntu_latest.yml | 62 + ParallelIO/.gitignore | 32 + ParallelIO/CMakeLists.txt | 494 ++ ParallelIO/CTestConfig.cmake | 23 + ParallelIO/CTestScript.cmake | 195 + ParallelIO/LICENSE | 201 + ParallelIO/Makefile.am | 18 + ParallelIO/README.md | 117 + ParallelIO/cmake/FindGPTL.cmake | 72 + ParallelIO/cmake/FindHDF5.cmake | 118 + ParallelIO/cmake/FindLIBRT.cmake | 28 + ParallelIO/cmake/FindLIBZ.cmake | 37 + ParallelIO/cmake/FindMPE.cmake | 50 + ParallelIO/cmake/FindMPISERIAL.cmake | 44 + ParallelIO/cmake/FindNetCDF.cmake | 143 + ParallelIO/cmake/FindPAPI.cmake | 28 + ParallelIO/cmake/FindPnetCDF.cmake | 68 + ParallelIO/cmake/FindSZIP.cmake | 37 + ParallelIO/cmake/LibCheck.cmake | 104 + ParallelIO/cmake/LibFind.cmake | 333 ++ ParallelIO/cmake/LibMPI.cmake | 124 + ParallelIO/cmake/Makefile.am | 13 + ParallelIO/cmake/TryHDF5_HAS_SZIP.c | 13 + ParallelIO/cmake/TryNetCDF_DAP.c | 13 + ParallelIO/cmake/TryNetCDF_PARALLEL.c | 13 + ParallelIO/cmake/TryNetCDF_PNETCDF.c | 13 + ParallelIO/cmake/mpiexec.alcf | 16 + ParallelIO/cmake/mpiexec.ncsa | 12 + ParallelIO/cmake/mpiexec.nersc | 12 + ParallelIO/cmake/mpiexec.nwscla | 11 + ParallelIO/cmake/mpiexec.olcf | 12 + ParallelIO/cmake_config.h.in | 48 + ParallelIO/configure.ac | 502 ++ ParallelIO/ctest/CTestEnvironment-alcf.cmake | 14 + .../CTestEnvironment-anlworkstation.cmake | 26 + ParallelIO/ctest/CTestEnvironment-cgd.cmake | 17 + ParallelIO/ctest/CTestEnvironment-ncsa.cmake | 22 + ParallelIO/ctest/CTestEnvironment-nersc.cmake | 22 + .../ctest/CTestEnvironment-nwscla.cmake | 18 + .../ctest/CTestEnvironment-unknown.cmake | 12 + ParallelIO/ctest/CTestScript-Test.cmake | 29 + ParallelIO/ctest/runcdash-alcf-ibm.sh | 37 + ParallelIO/ctest/runcdash-anlworkstation.sh | 45 + ParallelIO/ctest/runcdash-cgd-gnu-openmpi.sh | 38 + ParallelIO/ctest/runcdash-cgd-nag.sh | 38 + ParallelIO/ctest/runcdash-nersc-cray.sh | 74 + ParallelIO/ctest/runcdash-nersc-intel.sh | 73 + .../ctest/runcdash-nwsc-intel-mpiserial.sh | 37 + ParallelIO/ctest/runcdash-nwsc-intel.sh | 36 + ParallelIO/ctest/runcdash-nwscla-gnu.sh | 37 + ParallelIO/ctest/runcdash-nwscla-intel.sh | 40 + ParallelIO/ctest/runcdash-nwscla-pgi.sh | 37 + ParallelIO/ctest/runctest-alcf.sh | 42 + ParallelIO/ctest/runctest-anlworkstation.sh | 18 + ParallelIO/ctest/runctest-cgd.sh | 45 + ParallelIO/ctest/runctest-ncsa.sh | 39 + ParallelIO/ctest/runctest-nersc.sh | 57 + ParallelIO/ctest/runctest-nwscla.sh | 44 + ParallelIO/ctest/runctest-unknown.sh | 18 + .../doc/CMakeFiles/3.2.3/CMakeSystem.cmake | 15 + ParallelIO/doc/CMakeFiles/cmake.check_cache | 1 + ParallelIO/doc/CMakeLists.txt | 43 + ParallelIO/doc/Doxyfile.in | 2389 +++++++++ ParallelIO/doc/DoxygenLayout.xml | 180 + ParallelIO/doc/Makefile.am | 20 + ParallelIO/doc/customdoxygen.css | 1184 +++++ ParallelIO/doc/doxygen.sty | 350 ++ ParallelIO/doc/images/I_O_on_Few.png | Bin 0 -> 51147 bytes ParallelIO/doc/images/I_O_on_Many_Async.png | Bin 0 -> 106413 bytes .../doc/images/I_O_on_Many_Intracomm.png | Bin 0 -> 86263 bytes .../doc/images/I_O_on_many_async_small.png | Bin 0 -> 167170 bytes ParallelIO/doc/images/Makefile.am | 9 + ParallelIO/doc/images/PIO_Async.png | Bin 0 -> 59591 bytes ParallelIO/doc/images/PIO_Decomposition.png | Bin 0 -> 86877 bytes ParallelIO/doc/images/PIO_Intracomm1.png | Bin 0 -> 62702 bytes .../doc/images/PIO_Library_Architecture1.jpg | Bin 0 -> 53536 bytes ParallelIO/doc/images/baseimage.graffle | 1128 +++++ ParallelIO/doc/images/block-cyclic-rearr.eps | 3315 +++++++++++++ .../doc/images/block-cyclic-rearr.graffle | 2928 +++++++++++ ParallelIO/doc/images/block-cyclic-rearr.png | Bin 0 -> 30602 bytes ParallelIO/doc/images/block-cyclic.eps | 1219 +++++ ParallelIO/doc/images/block-cyclic.graffle | 2054 ++++++++ ParallelIO/doc/images/block-cyclic.png | Bin 0 -> 21257 bytes ParallelIO/doc/images/dof-rearr.eps | 3366 +++++++++++++ ParallelIO/doc/images/dof-rearr.graffle | 2758 +++++++++++ ParallelIO/doc/images/dof-rearr.png | Bin 0 -> 29798 bytes ParallelIO/doc/images/dof.eps | 1283 +++++ ParallelIO/doc/images/dof.graffle | 1953 ++++++++ ParallelIO/doc/images/dof.png | Bin 0 -> 21545 bytes ParallelIO/doc/source/CAMexample.txt | 139 + ParallelIO/doc/source/Decomp.txt | 86 + ParallelIO/doc/source/Error.txt | 16 + ParallelIO/doc/source/Examples.txt | 39 + ParallelIO/doc/source/Installing.txt | 219 + ParallelIO/doc/source/Introduction.txt | 89 + ParallelIO/doc/source/Makefile.am | 8 + ParallelIO/doc/source/Testing.txt | 203 + ParallelIO/doc/source/api.txt | 42 + ParallelIO/doc/source/base.txt | 33 + ParallelIO/doc/source/c_api.txt | 51 + ParallelIO/doc/source/contributing_code.txt | 137 + ParallelIO/doc/source/example/errorhandle | 9 + ParallelIO/doc/source/example/simple-bc | 14 + ParallelIO/doc/source/example/simple-bc-rearr | 17 + .../doc/source/example/simple-bc-rearr-pe1 | 14 + .../doc/source/example/simple-bc-rearr-pe2 | 17 + ParallelIO/doc/source/example/simple-dof | 13 + .../doc/source/example/simple-dof-rearr | 17 + ParallelIO/doc/source/faq.txt | 42 + ParallelIO/doc/source/iosystem.txt | 24 + ParallelIO/doc/source/mach_walkthrough.txt | 511 ++ ParallelIO/doc/source/netcdf_integration.txt | 168 + ParallelIO/doc/source/testpio_example.txt | 374 ++ ParallelIO/doc/source/users_guide.txt | 21 + ParallelIO/examples/CMakeLists.txt | 10 + ParallelIO/examples/Makefile.am | 11 + ParallelIO/examples/basic/CAM05.csh | 11 + ParallelIO/examples/basic/CMakeLists.txt | 32 + ParallelIO/examples/basic/MPASA30km.csh | 10 + ParallelIO/examples/basic/MPASA60km.csh | 10 + ParallelIO/examples/basic/POPB.csh | 10 + ParallelIO/examples/basic/POPC.csh | 13 + ParallelIO/examples/basic/POPD.csh | 14 + ParallelIO/examples/basic/POPDv0.csh | 20 + ParallelIO/examples/basic/POPDv1.csh | 20 + ParallelIO/examples/basic/POPDv2.csh | 39 + ParallelIO/examples/basic/POPDv3.csh | 16 + ParallelIO/examples/basic/POPDv4.csh | 17 + ParallelIO/examples/basic/POPDv5.csh | 17 + ParallelIO/examples/basic/README.testpio | 288 ++ ParallelIO/examples/basic/WRFB.csh | 13 + ParallelIO/examples/basic/alloc_mod.F90.in | 328 ++ ParallelIO/examples/basic/build_defaults.xml | 491 ++ ParallelIO/examples/basic/check_mod.F90 | 252 + ParallelIO/examples/basic/config_bench.xml | 315 ++ ParallelIO/examples/basic/fdepends.awk | 56 + ParallelIO/examples/basic/gdecomp_mod.F90 | 1346 +++++ ParallelIO/examples/basic/kinds_mod.F90 | 41 + ParallelIO/examples/basic/kraken.128.csh | 10 + ParallelIO/examples/basic/kraken.1K.csh | 8 + ParallelIO/examples/basic/kraken.256.csh | 9 + ParallelIO/examples/basic/kraken.512.csh | 10 + ParallelIO/examples/basic/kraken.64.csh | 7 + ParallelIO/examples/basic/namelist_mod.F90 | 547 +++ .../examples/basic/namelists/testpio_in.apb05 | 31 + .../examples/basic/namelists/testpio_in.asb01 | 31 + .../examples/basic/namelists/testpio_in.asb04 | 31 + .../examples/basic/namelists/testpio_in.n4b01 | 30 + .../examples/basic/namelists/testpio_in.n4b02 | 30 + .../examples/basic/namelists/testpio_in.n4b03 | 30 + .../examples/basic/namelists/testpio_in.n4b04 | 30 + .../examples/basic/namelists/testpio_in.n4b05 | 30 + .../examples/basic/namelists/testpio_in.n4b06 | 31 + .../examples/basic/namelists/testpio_in.n4b07 | 31 + .../examples/basic/namelists/testpio_in.n4b08 | 31 + .../examples/basic/namelists/testpio_in.n4n01 | 30 + .../examples/basic/namelists/testpio_in.n4n02 | 30 + .../examples/basic/namelists/testpio_in.n4n03 | 30 + .../examples/basic/namelists/testpio_in.pb01 | 30 + .../examples/basic/namelists/testpio_in.pb02 | 30 + .../examples/basic/namelists/testpio_in.pb03 | 30 + .../examples/basic/namelists/testpio_in.pb04 | 30 + .../examples/basic/namelists/testpio_in.pb05 | 30 + .../examples/basic/namelists/testpio_in.pb06 | 31 + .../examples/basic/namelists/testpio_in.pb07 | 31 + .../examples/basic/namelists/testpio_in.pb08 | 31 + .../examples/basic/namelists/testpio_in.pn01 | 30 + .../examples/basic/namelists/testpio_in.pn02 | 30 + .../examples/basic/namelists/testpio_in.pn03 | 30 + .../examples/basic/namelists/testpio_in.ps01 | 30 + .../examples/basic/namelists/testpio_in.ps02 | 30 + .../examples/basic/namelists/testpio_in.ps03 | 30 + .../examples/basic/namelists/testpio_in.ps04 | 30 + .../examples/basic/namelists/testpio_in.ps05 | 30 + .../examples/basic/namelists/testpio_in.ps06 | 31 + .../examples/basic/namelists/testpio_in.ps07 | 31 + .../examples/basic/namelists/testpio_in.ps08 | 31 + .../examples/basic/namelists/testpio_in.sb01 | 30 + .../examples/basic/namelists/testpio_in.sb02 | 30 + .../examples/basic/namelists/testpio_in.sb03 | 30 + .../examples/basic/namelists/testpio_in.sb04 | 30 + .../examples/basic/namelists/testpio_in.sb05 | 30 + .../examples/basic/namelists/testpio_in.sb06 | 31 + .../examples/basic/namelists/testpio_in.sb07 | 31 + .../examples/basic/namelists/testpio_in.sb08 | 31 + .../examples/basic/namelists/testpio_in.sn01 | 30 + .../examples/basic/namelists/testpio_in.sn02 | 30 + .../examples/basic/namelists/testpio_in.sn03 | 30 + .../examples/basic/namelists/testpio_in.wr01 | 30 + .../examples/basic/namelists/testpio_in.wr02 | 16 + ParallelIO/examples/basic/perl5lib/ChangeLog | 276 ++ ParallelIO/examples/basic/perl5lib/README | 10 + .../examples/basic/perl5lib/XML/Changes | 27 + .../examples/basic/perl5lib/XML/Lite.pm | 550 +++ .../basic/perl5lib/XML/Lite/Element.pm | 491 ++ ParallelIO/examples/basic/perl5lib/XML/README | 20 + .../basic/perl5lib/XML/man3/XML_Lite.3 | 213 + .../perl5lib/XML/man3/XML_Lite_Element.3 | 206 + ParallelIO/examples/basic/test.csh | 10 + ParallelIO/examples/basic/testdecomp.F90 | 45 + .../examples/basic/testdecomp.bluefire.run | 32 + ParallelIO/examples/basic/testdecomp_in | 36 + ParallelIO/examples/basic/testpio.F90 | 1663 +++++++ ParallelIO/examples/basic/testpio_bench.pl | 823 ++++ ParallelIO/examples/basic/testpio_build.pl | 73 + ParallelIO/examples/basic/testpio_run.pl | 358 ++ ParallelIO/examples/basic/utils_mod.F90 | 115 + ParallelIO/examples/basic/wstest.c | 71 + ParallelIO/examples/basic/ystest.sh | 13 + ParallelIO/examples/c/CMakeLists.txt | 68 + ParallelIO/examples/c/Makefile.am | 24 + ParallelIO/examples/c/darray_async.c | 367 ++ ParallelIO/examples/c/darray_no_async.c | 376 ++ ParallelIO/examples/c/example1.c | 442 ++ ParallelIO/examples/c/example2.c | 695 +++ ParallelIO/examples/c/examplePio.c | 630 +++ ParallelIO/examples/c/run_tests.sh.in | 42 + ParallelIO/examples/c/valsupp_example1.supp | 15 + ParallelIO/examples/cxx/CMakeLists.txt | 12 + ParallelIO/examples/cxx/examplePio.cxx | 38 + ParallelIO/examples/f03/CMakeLists.txt | 23 + ParallelIO/examples/f03/Makefile.am | 31 + ParallelIO/examples/f03/exampleAsyncPio.F90 | 413 ++ ParallelIO/examples/f03/examplePio.F90 | 385 ++ ParallelIO/examples/f03/run_tests.sh.in | 31 + ParallelIO/libpio.settings.in | 38 + ParallelIO/scripts/Makefile.am | 6 + ParallelIO/scripts/genf90.pl | 393 ++ ParallelIO/scripts/prune_decomps.pl | 162 + ParallelIO/src/CMakeLists.txt | 47 + ParallelIO/src/Makefile.am | 23 + ParallelIO/src/clib/CMakeLists.txt | 205 + ParallelIO/src/clib/Makefile.am | 28 + ParallelIO/src/clib/parallel_sort.c | 251 + ParallelIO/src/clib/parallel_sort.h | 35 + ParallelIO/src/clib/pio.h | 1352 +++++ ParallelIO/src/clib/pio_darray.c | 1018 ++++ ParallelIO/src/clib/pio_darray_int.c | 2191 +++++++++ ParallelIO/src/clib/pio_error.c | 23 + ParallelIO/src/clib/pio_error.h | 108 + ParallelIO/src/clib/pio_file.c | 490 ++ ParallelIO/src/clib/pio_gdal.XC | 3237 ++++++++++++ ParallelIO/src/clib/pio_gdal.c | 824 ++++ ParallelIO/src/clib/pio_get_nc.c | 1211 +++++ ParallelIO/src/clib/pio_get_vard.c | 269 + ParallelIO/src/clib/pio_getput_int.c | 1543 ++++++ ParallelIO/src/clib/pio_internal.h | 644 +++ ParallelIO/src/clib/pio_lists.c | 408 ++ ParallelIO/src/clib/pio_meta.h.in | 34 + ParallelIO/src/clib/pio_msg.c | 2900 +++++++++++ ParallelIO/src/clib/pio_nc.c | 3238 ++++++++++++ ParallelIO/src/clib/pio_nc4.c | 1054 ++++ ParallelIO/src/clib/pio_put_nc.c | 1259 +++++ ParallelIO/src/clib/pio_put_vard.c | 299 ++ ParallelIO/src/clib/pio_rearrange.c | 2605 ++++++++++ ParallelIO/src/clib/pio_spmd.c | 519 ++ ParallelIO/src/clib/pioc.c | 1715 +++++++ ParallelIO/src/clib/pioc_async.c | 843 ++++ ParallelIO/src/clib/pioc_sc.c | 367 ++ ParallelIO/src/clib/pioc_support.c | 3372 +++++++++++++ ParallelIO/src/clib/topology.c | 363 ++ ParallelIO/src/clib/uthash.h | 1230 +++++ ParallelIO/src/flib/CMakeLists.txt | 268 + ParallelIO/src/flib/Makefile.am | 190 + ParallelIO/src/flib/ncint_mod.F90 | 237 + ParallelIO/src/flib/pio.F90 | 174 + ParallelIO/src/flib/pio_kinds.F90 | 38 + ParallelIO/src/flib/pio_nf.F90 | 2109 ++++++++ ParallelIO/src/flib/pio_support.F90 | 335 ++ ParallelIO/src/flib/pio_types.F90 | 212 + ParallelIO/src/flib/piodarray.F90.in | 353 ++ ParallelIO/src/flib/piolib_mod.F90 | 1644 +++++++ ParallelIO/src/flib/pionfatt_mod.F90.in | 475 ++ ParallelIO/src/flib/pionfget_mod.F90.in | 432 ++ ParallelIO/src/flib/pionfput_mod.F90.in | 563 +++ ParallelIO/src/gptl/CMakeLists.txt | 154 + ParallelIO/src/gptl/COPYING | 674 +++ ParallelIO/src/gptl/ChangeLog | 141 + ParallelIO/src/gptl/GPTLget_memusage.c | 160 + ParallelIO/src/gptl/GPTLprint_memusage.c | 120 + ParallelIO/src/gptl/GPTLutil.c | 82 + ParallelIO/src/gptl/Makefile.am | 25 + ParallelIO/src/gptl/README | 143 + ParallelIO/src/gptl/f_wrappers.c | 538 ++ ParallelIO/src/gptl/f_wrappers_2.c | 185 + ParallelIO/src/gptl/gptl.c | 4371 +++++++++++++++++ ParallelIO/src/gptl/gptl.h | 158 + ParallelIO/src/gptl/gptl.inc | 158 + ParallelIO/src/gptl/gptl_papi.c | 1326 +++++ ParallelIO/src/gptl/perf_mod.F90 | 1430 ++++++ ParallelIO/src/gptl/perf_utils.F90 | 528 ++ ParallelIO/src/gptl/private.h | 156 + ParallelIO/src/gptl/threadutil.c | 380 ++ ParallelIO/src/ncint/Makefile.am | 13 + ParallelIO/src/ncint/nc_get_vard.c | 269 + ParallelIO/src/ncint/nc_put_vard.c | 299 ++ ParallelIO/src/ncint/ncint_pio.c | 179 + ParallelIO/src/ncint/ncintdispatch.c | 1049 ++++ ParallelIO/src/ncint/ncintdispatch.h | 163 + ParallelIO/tests/CMakeLists.txt | 34 + ParallelIO/tests/Makefile.am | 28 + ParallelIO/tests/cperf/CMakeLists.txt | 42 + ParallelIO/tests/cperf/mpi_argp.c | 78 + ParallelIO/tests/cperf/piodecomptest.c | 330 ++ ParallelIO/tests/cunit/CMakeLists.txt | 331 ++ ParallelIO/tests/cunit/Makefile.am | 77 + ParallelIO/tests/cunit/pio_tests.h | 126 + ParallelIO/tests/cunit/run_tests.sh.in | 50 + ParallelIO/tests/cunit/test_async_1d.c | 155 + ParallelIO/tests/cunit/test_async_3proc.c | 116 + ParallelIO/tests/cunit/test_async_4proc.c | 120 + ParallelIO/tests/cunit/test_async_manyproc.c | 111 + ParallelIO/tests/cunit/test_async_mpi.c | 467 ++ ParallelIO/tests/cunit/test_async_multi2.c | 117 + ParallelIO/tests/cunit/test_async_multicomp.c | 135 + ParallelIO/tests/cunit/test_async_perf.c | 412 ++ ParallelIO/tests/cunit/test_async_simple.c | 125 + ParallelIO/tests/cunit/test_common.c | 1530 ++++++ ParallelIO/tests/cunit/test_darray.c | 430 ++ ParallelIO/tests/cunit/test_darray_1d.c | 880 ++++ ParallelIO/tests/cunit/test_darray_2sync.c | 597 +++ ParallelIO/tests/cunit/test_darray_3d.c | 416 ++ ParallelIO/tests/cunit/test_darray_append.c | 406 ++ ParallelIO/tests/cunit/test_darray_async.c | 568 +++ .../tests/cunit/test_darray_async_from_comm.c | 599 +++ .../tests/cunit/test_darray_async_many.c | 677 +++ .../tests/cunit/test_darray_async_simple.c | 219 + ParallelIO/tests/cunit/test_darray_fill.c | 376 ++ ParallelIO/tests/cunit/test_darray_frame.c | 240 + ParallelIO/tests/cunit/test_darray_multi.c | 478 ++ ParallelIO/tests/cunit/test_darray_multivar.c | 604 +++ .../tests/cunit/test_darray_multivar2.c | 289 ++ .../tests/cunit/test_darray_multivar3.c | 351 ++ ParallelIO/tests/cunit/test_darray_vard.c | 523 ++ ParallelIO/tests/cunit/test_decomp_frame.c | 378 ++ ParallelIO/tests/cunit/test_decomp_uneven.c | 369 ++ ParallelIO/tests/cunit/test_decomps.c | 436 ++ ParallelIO/tests/cunit/test_intercomm2.c | 536 ++ ParallelIO/tests/cunit/test_iosystem2.c | 219 + .../tests/cunit/test_iosystem2_simple.c | 240 + .../tests/cunit/test_iosystem2_simple2.c | 141 + ParallelIO/tests/cunit/test_iosystem3.c | 353 ++ .../tests/cunit/test_iosystem3_simple.c | 111 + .../tests/cunit/test_iosystem3_simple2.c | 100 + ParallelIO/tests/cunit/test_perf2.c | 587 +++ ParallelIO/tests/cunit/test_pioc.c | 2418 +++++++++ ParallelIO/tests/cunit/test_pioc_fill.c | 812 +++ ParallelIO/tests/cunit/test_pioc_putget.c | 2063 ++++++++ ParallelIO/tests/cunit/test_pioc_unlim.c | 301 ++ ParallelIO/tests/cunit/test_rearr.c | 1598 ++++++ ParallelIO/tests/cunit/test_shared.c | 187 + ParallelIO/tests/cunit/test_simple.c | 167 + ParallelIO/tests/cunit/test_spmd.c | 796 +++ ParallelIO/tests/doftests/CMakeLists.txt | 19 + ParallelIO/tests/doftests/dofcopy.F90 | 83 + ParallelIO/tests/fncint/Makefile.am | 37 + ParallelIO/tests/fncint/ftst_pio.f90 | 111 + ParallelIO/tests/fncint/ftst_pio_orig.f90 | 114 + ParallelIO/tests/fncint/run_tests.sh.in | 29 + ParallelIO/tests/fncint/tst_c_pio.c | 118 + ParallelIO/tests/general/CMakeLists.txt | 853 ++++ ParallelIO/tests/general/Makefile.am | 110 + ParallelIO/tests/general/README.md | 142 + ParallelIO/tests/general/ncdf_fail.F90.in | 102 + ParallelIO/tests/general/ncdf_get_put.F90.in | 606 +++ ParallelIO/tests/general/ncdf_inq.F90.in | 192 + .../tests/general/ncdf_simple_tests.F90.in | 198 + .../tests/general/pio_decomp_fillval.F90.in | 392 ++ .../general/pio_decomp_frame_tests.F90.in | 2567 ++++++++++ .../tests/general/pio_decomp_tests.F90.in | 306 ++ .../tests/general/pio_decomp_tests_1d.F90.in | 429 ++ .../tests/general/pio_decomp_tests_2d.F90.in | 368 ++ .../general/pio_decomp_tests_2d_async.F90.in | 377 ++ .../general/pio_decomp_tests_2d_halo.F90.in | 249 + .../tests/general/pio_decomp_tests_3d.F90.in | 210 + .../general/pio_decomphalo_tests_2d.F90.in | 271 + ParallelIO/tests/general/pio_fail.F90.in | 26 + ParallelIO/tests/general/pio_file_fail.F90.in | 52 + .../general/pio_file_simple_tests.F90.in | 69 + .../tests/general/pio_init_finalize.F90.in | 7 + .../general/pio_iosystem_async_tests.F90.in | 257 + .../tests/general/pio_iosystem_tests.F90.in | 307 ++ .../tests/general/pio_iosystem_tests2.F90.in | 237 + .../tests/general/pio_iosystem_tests3.F90.in | 283 ++ ParallelIO/tests/general/pio_rearr.F90.in | 251 + .../tests/general/pio_rearr_opts.F90.in | 479 ++ .../tests/general/pio_rearr_opts2.F90.in | 418 ++ ParallelIO/tests/general/run_tests.sh.in | 36 + ParallelIO/tests/general/test_memleak.c | 348 ++ ParallelIO/tests/general/util/Makefile.am | 6 + .../tests/general/util/pio_tf_f90gen.pl | 917 ++++ ParallelIO/tests/general/util/pio_tutil.F90 | 1203 +++++ ParallelIO/tests/ncint/CMakeLists.txt | 31 + ParallelIO/tests/ncint/Makefile.am | 31 + ParallelIO/tests/ncint/pio_err_macros.h | 79 + ParallelIO/tests/ncint/run_perf.sh.in | 33 + ParallelIO/tests/ncint/run_tests.sh.in | 43 + ParallelIO/tests/ncint/tst_async_multi.c | 182 + ParallelIO/tests/ncint/tst_ncint_async_perf.c | 179 + ParallelIO/tests/ncint/tst_ncint_perf.c | 172 + ParallelIO/tests/ncint/tst_pio_async.c | 160 + ParallelIO/tests/ncint/tst_pio_udf.c | 129 + ParallelIO/tests/ncint/tst_var_compress.c | 157 + ParallelIO/tests/performance/CMakeLists.txt | 24 + ParallelIO/tests/performance/Makefile.am | 41 + .../tests/performance/Pioperformance.md | 62 + ParallelIO/tests/performance/gensimple.pl | 27 + .../tests/performance/kt.PIO1.perfmakefile | 19 + ParallelIO/tests/performance/pioperf.nl | 9 + .../tests/performance/pioperformance.F90 | 637 +++ ParallelIO/tests/performance/run_tests.sh.in | 30 + ParallelIO/tests/unit/CMakeLists.txt | 75 + ParallelIO/tests/unit/Levy_Notes | 64 + ParallelIO/tests/unit/Makefile.am | 45 + ParallelIO/tests/unit/basic_tests.F90 | 326 ++ ParallelIO/tests/unit/driver.F90 | 229 + ParallelIO/tests/unit/ftst_vars_chunking.F90 | 98 + ParallelIO/tests/unit/global_vars.F90 | 57 + ParallelIO/tests/unit/input.nl | 7 + ParallelIO/tests/unit/nc_set_log_level2.c | 10 + ParallelIO/tests/unit/ncdf_tests.F90 | 624 +++ ParallelIO/tests/unit/not_netcdf.ieee | Bin 0 -> 300 bytes ParallelIO/tests/unit/run_tests.sh.in | 30 + .../.github/actions/buildhdf5/action.yml | 56 + .../.github/actions/buildmpich/action.yml | 30 + .../.github/actions/buildnetcdf/action.yml | 67 + .../.github/actions/buildnetcdff/action.yml | 35 + .../.github/actions/buildopenmpi/action.yml | 30 + .../.github/actions/buildpnetcdf/action.yml | 52 + .../.github/actions/intelcompilers/action.yml | 23 + .../actions/parallelio_autotools/action.yml | 131 + .../actions/parallelio_cmake/action.yml | 141 + .../.github/workflows/autotools.yml | 65 +- .../ParallelIO/.github/workflows/cmake.yml | 64 +- .../.github/workflows/cmake_ubuntu_latest.yml | 47 +- .../ParallelIO/.github/workflows/intel.yml | 131 + .../netcdf_hdf5_no_pnetcdf_ncint_mpich.yml | 139 +- .../netcdf_hdf5_pnetcdf_ncint_mpich_asan.yml | 146 +- .../workflows/netcdf_pnetcdf_openmpi.yml | 198 +- .../strict_autotools_ubuntu_latest.yml | 55 +- .../.github/workflows/withspack.yml | 77 + .../IO/PIO/ParallelIO/.gitignore | 2 +- .../IO/PIO/ParallelIO/CMakeLists.txt | 58 +- .../IO/PIO/ParallelIO/README.md | 4 +- .../IO/PIO/ParallelIO/cmake/FindGPTL.cmake | 6 +- .../IO/PIO/ParallelIO/cmake/FindHDF5.cmake | 16 +- .../IO/PIO/ParallelIO/cmake/FindLIBRT.cmake | 4 +- .../IO/PIO/ParallelIO/cmake/FindLIBZ.cmake | 4 +- .../IO/PIO/ParallelIO/cmake/FindMPE.cmake | 4 +- .../PIO/ParallelIO/cmake/FindMPISERIAL.cmake | 4 +- .../IO/PIO/ParallelIO/cmake/FindPAPI.cmake | 2 +- .../IO/PIO/ParallelIO/cmake/FindPnetCDF.cmake | 8 +- .../IO/PIO/ParallelIO/cmake/FindSZIP.cmake | 4 +- .../IO/PIO/ParallelIO/cmake/LibCheck.cmake | 2 +- .../IO/PIO/ParallelIO/cmake/LibFind.cmake | 55 +- .../IO/PIO/ParallelIO/cmake/mpiexec.alcf | 2 +- .../IO/PIO/ParallelIO/cmake_config.h.in | 1 + .../IO/PIO/ParallelIO/configure.ac | 102 +- .../ctest/CTestEnvironment-alcf.cmake | 2 +- .../CTestEnvironment-anlworkstation.cmake | 1 - .../ctest/CTestEnvironment-ncsa.cmake | 2 +- .../ctest/CTestEnvironment-nersc.cmake | 2 +- .../ParallelIO/ctest/runcdash-nwscla-gnu.sh | 4 +- .../ParallelIO/ctest/runcdash-nwscla-intel.sh | 4 +- .../ParallelIO/ctest/runcdash-nwscla-pgi.sh | 4 +- .../IO/PIO/ParallelIO/ctest/runctest-ncsa.sh | 2 +- .../IO/PIO/ParallelIO/ctest/runctest-nersc.sh | 2 +- .../ParallelIO/doc/CMakeFiles/CMakeOutput.log | 28 +- .../IO/PIO/ParallelIO/doc/Doxyfile.in | 4 +- .../IO/PIO/ParallelIO/doc/DoxygenLayout.xml | 2 +- .../IO/PIO/ParallelIO/doc/customdoxygen.css | 55 +- .../PIO/ParallelIO/doc/source/CAMexample.txt | 6 +- .../IO/PIO/ParallelIO/doc/source/Decomp.txt | 17 +- .../IO/PIO/ParallelIO/doc/source/Error.txt | 2 +- .../IO/PIO/ParallelIO/doc/source/Examples.txt | 10 +- .../PIO/ParallelIO/doc/source/Installing.txt | 16 +- .../IO/PIO/ParallelIO/doc/source/Testing.txt | 12 +- .../IO/PIO/ParallelIO/doc/source/api.txt | 2 +- .../IO/PIO/ParallelIO/doc/source/base.txt | 2 +- .../doc/source/contributing_code.txt | 12 +- .../ParallelIO/doc/source/example/simple-bc | 3 +- .../doc/source/example/simple-bc-rearr | 3 +- .../doc/source/example/simple-bc-rearr-pe1 | 3 +- .../doc/source/example/simple-bc-rearr-pe2 | 3 +- .../ParallelIO/doc/source/example/simple-dof | 3 +- .../doc/source/example/simple-dof-rearr | 3 +- .../IO/PIO/ParallelIO/doc/source/faq.txt | 8 +- .../IO/PIO/ParallelIO/doc/source/iosystem.txt | 1 - .../doc/source/mach_walkthrough.txt | 18 +- .../ParallelIO/doc/source/testpio_example.txt | 64 +- .../PIO/ParallelIO/doc/source/users_guide.txt | 2 +- .../ParallelIO/examples/basic/CMakeLists.txt | 9 +- .../ParallelIO/examples/basic/MPASA30km.csh | 3 +- .../ParallelIO/examples/basic/MPASA60km.csh | 1 - .../IO/PIO/ParallelIO/examples/basic/POPB.csh | 1 - .../IO/PIO/ParallelIO/examples/basic/POPD.csh | 1 - .../PIO/ParallelIO/examples/basic/POPDv0.csh | 1 - .../PIO/ParallelIO/examples/basic/POPDv1.csh | 1 - .../PIO/ParallelIO/examples/basic/POPDv2.csh | 2 - .../PIO/ParallelIO/examples/basic/POPDv3.csh | 1 - .../PIO/ParallelIO/examples/basic/POPDv4.csh | 1 - .../PIO/ParallelIO/examples/basic/POPDv5.csh | 1 - .../ParallelIO/examples/basic/README.testpio | 65 +- .../examples/basic/alloc_mod.F90.in | 22 +- .../examples/basic/build_defaults.xml | 40 +- .../ParallelIO/examples/basic/check_mod.F90 | 58 +- .../examples/basic/config_bench.xml | 31 +- .../ParallelIO/examples/basic/fdepends.awk | 12 +- .../ParallelIO/examples/basic/gdecomp_mod.F90 | 52 +- .../ParallelIO/examples/basic/kinds_mod.F90 | 8 +- .../examples/basic/namelist_mod.F90 | 24 +- .../examples/basic/perl5lib/ChangeLog | 14 +- .../examples/basic/perl5lib/XML/Changes | 1 - .../examples/basic/perl5lib/XML/Lite.pm | 109 +- .../basic/perl5lib/XML/Lite/Element.pm | 89 +- .../examples/basic/perl5lib/XML/README | 4 +- .../basic/perl5lib/XML/man3/XML_Lite.3 | 26 +- .../perl5lib/XML/man3/XML_Lite_Element.3 | 16 +- .../ParallelIO/examples/basic/testdecomp.F90 | 4 +- .../examples/basic/testdecomp.bluefire.run | 3 - .../PIO/ParallelIO/examples/basic/testpio.F90 | 237 +- .../examples/basic/testpio_bench.pl | 16 +- .../examples/basic/testpio_build.pl | 5 +- .../ParallelIO/examples/basic/testpio_run.pl | 18 +- .../ParallelIO/examples/basic/utils_mod.F90 | 2 +- .../IO/PIO/ParallelIO/examples/basic/wstest.c | 10 +- .../PIO/ParallelIO/examples/c/CMakeLists.txt | 5 + .../PIO/ParallelIO/examples/c/darray_async.c | 14 +- .../IO/PIO/ParallelIO/examples/c/examplePio.c | 104 +- .../IO/PIO/ParallelIO/examples/c/piorcw.c | 245 + .../examples/c/valsupp_example1.supp | 2 +- .../ParallelIO/examples/cxx/examplePio.cxx | 18 +- .../examples/f03/exampleAsyncPio.F90 | 1 - .../IO/PIO/ParallelIO/libpio.settings.in | 3 +- .../PIO/ParallelIO/scripts/prune_decomps.pl | 10 +- .../IO/PIO/ParallelIO/src/clib/pio_gdal.c | 7 + .../PIO/ParallelIO/tests/cperf/CMakeLists.txt | 9 +- .../ParallelIO/tests/cperf/piodecomptest.c | 32 +- .../PIO/ParallelIO/tests/cunit/CMakeLists.txt | 14 + .../IO/PIO/ParallelIO/tests/cunit/Makefile.am | 4 +- .../ParallelIO/tests/cunit/test_async_mpi.c | 38 +- .../PIO/ParallelIO/tests/cunit/test_common.c | 34 +- .../tests/cunit/test_darray_2sync.c | 12 +- .../ParallelIO/tests/cunit/test_darray_3d.c | 2 +- .../ParallelIO/tests/cunit/test_darray_fill.c | 2 +- .../tests/cunit/test_darray_lossycompress.c | 499 ++ .../tests/cunit/test_darray_multivar3.c | 2 +- .../tests/cunit/test_decomp_frame.c | 2 +- .../tests/cunit/test_decomp_uneven.c | 4 +- .../ParallelIO/tests/cunit/test_intercomm2.c | 5 +- .../tests/cunit/test_iosystem2_simple2.c | 2 +- .../PIO/ParallelIO/tests/cunit/test_perf2.c | 8 +- .../IO/PIO/ParallelIO/tests/cunit/test_pioc.c | 27 +- .../ParallelIO/tests/cunit/test_pioc_putget.c | 3 +- .../ParallelIO/tests/cunit/test_pioc_unlim.c | 26 +- .../PIO/ParallelIO/tests/derecho_testsuite.py | 135 + .../ParallelIO/tests/doftests/CMakeLists.txt | 1 - .../PIO/ParallelIO/tests/doftests/dofcopy.F90 | 6 +- .../ParallelIO/tests/general/CMakeLists.txt | 55 +- .../IO/PIO/ParallelIO/tests/general/README.md | 8 +- .../ParallelIO/tests/general/ncdf_fail.F90.in | 12 +- .../ParallelIO/tests/general/ncdf_inq.F90.in | 6 +- .../tests/general/ncdf_simple_tests.F90.in | 5 +- .../general/pio_decomp_frame_tests.F90.in | 2 +- .../tests/general/pio_decomp_tests.F90.in | 8 +- .../tests/general/pio_decomp_tests_3d.F90.in | 10 +- .../tests/general/pio_file_fail.F90.in | 3 +- .../tests/general/pio_filter_tests.F90.in | 417 ++ .../tests/general/pio_init_finalize.F90.in | 2 - .../general/pio_iosystem_async_tests.F90.in | 25 +- .../ParallelIO/tests/general/pio_rearr.F90.in | 3 +- .../tests/general/pio_rearr_opts.F90.in | 8 +- .../tests/general/pio_rearr_opts2.F90.in | 8 +- .../tests/general/util/pio_tf_f90gen.pl | 12 +- .../tests/general/util/pio_tutil.F90 | 62 +- .../PIO/ParallelIO/tests/ncint/CMakeLists.txt | 3 +- .../IO/PIO/ParallelIO/tests/ncint/ncint.h | 86 + .../ParallelIO/tests/ncint/pio_err_macros.h | 2 +- .../ParallelIO/tests/ncint/tst_async_multi.c | 2 +- .../tests/ncint/tst_ncint_async_perf.c | 5 +- .../ParallelIO/tests/ncint/tst_ncint_open.c | 99 + .../ParallelIO/tests/ncint/tst_ncint_perf.c | 49 +- .../ParallelIO/tests/ncint/tst_pio_async.c | 12 +- .../PIO/ParallelIO/tests/ncint/tst_pio_udf.c | 84 +- .../ParallelIO/tests/ncint/tst_var_compress.c | 12 +- .../tests/performance/CMakeLists.txt | 23 +- .../tests/performance/Pioperformance.md | 20 +- .../tests/performance/kt.PIO1.perfmakefile | 4 +- .../tests/performance/pioperformance.F90 | 58 +- .../IO/PIO/ParallelIO/tests/unit/Levy_Notes | 4 +- .../PIO/ParallelIO/tests/unit/basic_tests.F90 | 10 +- .../IO/PIO/ParallelIO/tests/unit/driver.F90 | 30 +- .../tests/unit/ftst_vars_chunking.F90 | 34 +- .../PIO/ParallelIO/tests/unit/global_vars.F90 | 2 +- .../PIO/ParallelIO/tests/unit/ncdf_tests.F90 | 8 +- .../IO/tests/ESMF_IO_GDALUTest.F90 | 276 +- 602 files changed, 143425 insertions(+), 1578 deletions(-) create mode 100644 ParallelIO/.github/workflows/autotools.yml create mode 100644 ParallelIO/.github/workflows/cmake.yml create mode 100644 ParallelIO/.github/workflows/cmake_ubuntu_latest.yml create mode 100644 ParallelIO/.github/workflows/netcdf_hdf5_no_pnetcdf_ncint_mpich.yml create mode 100644 ParallelIO/.github/workflows/netcdf_hdf5_pnetcdf_ncint_mpich_asan.yml create mode 100644 ParallelIO/.github/workflows/netcdf_pnetcdf_openmpi.yml create mode 100644 ParallelIO/.github/workflows/strict_autotools_ubuntu_latest.yml create mode 100644 ParallelIO/.gitignore create mode 100644 ParallelIO/CMakeLists.txt create mode 100644 ParallelIO/CTestConfig.cmake create mode 100644 ParallelIO/CTestScript.cmake create mode 100644 ParallelIO/LICENSE create mode 100644 ParallelIO/Makefile.am create mode 100644 ParallelIO/README.md create mode 100644 ParallelIO/cmake/FindGPTL.cmake create mode 100644 ParallelIO/cmake/FindHDF5.cmake create mode 100644 ParallelIO/cmake/FindLIBRT.cmake create mode 100644 ParallelIO/cmake/FindLIBZ.cmake create mode 100644 ParallelIO/cmake/FindMPE.cmake create mode 100644 ParallelIO/cmake/FindMPISERIAL.cmake create mode 100644 ParallelIO/cmake/FindNetCDF.cmake create mode 100644 ParallelIO/cmake/FindPAPI.cmake create mode 100644 ParallelIO/cmake/FindPnetCDF.cmake create mode 100644 ParallelIO/cmake/FindSZIP.cmake create mode 100644 ParallelIO/cmake/LibCheck.cmake create mode 100644 ParallelIO/cmake/LibFind.cmake create mode 100644 ParallelIO/cmake/LibMPI.cmake create mode 100644 ParallelIO/cmake/Makefile.am create mode 100644 ParallelIO/cmake/TryHDF5_HAS_SZIP.c create mode 100644 ParallelIO/cmake/TryNetCDF_DAP.c create mode 100644 ParallelIO/cmake/TryNetCDF_PARALLEL.c create mode 100644 ParallelIO/cmake/TryNetCDF_PNETCDF.c create mode 100755 ParallelIO/cmake/mpiexec.alcf create mode 100755 ParallelIO/cmake/mpiexec.ncsa create mode 100755 ParallelIO/cmake/mpiexec.nersc create mode 100755 ParallelIO/cmake/mpiexec.nwscla create mode 100755 ParallelIO/cmake/mpiexec.olcf create mode 100644 ParallelIO/cmake_config.h.in create mode 100644 ParallelIO/configure.ac create mode 100644 ParallelIO/ctest/CTestEnvironment-alcf.cmake create mode 100644 ParallelIO/ctest/CTestEnvironment-anlworkstation.cmake create mode 100644 ParallelIO/ctest/CTestEnvironment-cgd.cmake create mode 100644 ParallelIO/ctest/CTestEnvironment-ncsa.cmake create mode 100644 ParallelIO/ctest/CTestEnvironment-nersc.cmake create mode 100644 ParallelIO/ctest/CTestEnvironment-nwscla.cmake create mode 100644 ParallelIO/ctest/CTestEnvironment-unknown.cmake create mode 100644 ParallelIO/ctest/CTestScript-Test.cmake create mode 100755 ParallelIO/ctest/runcdash-alcf-ibm.sh create mode 100755 ParallelIO/ctest/runcdash-anlworkstation.sh create mode 100755 ParallelIO/ctest/runcdash-cgd-gnu-openmpi.sh create mode 100755 ParallelIO/ctest/runcdash-cgd-nag.sh create mode 100755 ParallelIO/ctest/runcdash-nersc-cray.sh create mode 100755 ParallelIO/ctest/runcdash-nersc-intel.sh create mode 100755 ParallelIO/ctest/runcdash-nwsc-intel-mpiserial.sh create mode 100755 ParallelIO/ctest/runcdash-nwsc-intel.sh create mode 100755 ParallelIO/ctest/runcdash-nwscla-gnu.sh create mode 100755 ParallelIO/ctest/runcdash-nwscla-intel.sh create mode 100755 ParallelIO/ctest/runcdash-nwscla-pgi.sh create mode 100755 ParallelIO/ctest/runctest-alcf.sh create mode 100755 ParallelIO/ctest/runctest-anlworkstation.sh create mode 100755 ParallelIO/ctest/runctest-cgd.sh create mode 100755 ParallelIO/ctest/runctest-ncsa.sh create mode 100755 ParallelIO/ctest/runctest-nersc.sh create mode 100755 ParallelIO/ctest/runctest-nwscla.sh create mode 100755 ParallelIO/ctest/runctest-unknown.sh create mode 100644 ParallelIO/doc/CMakeFiles/3.2.3/CMakeSystem.cmake create mode 100644 ParallelIO/doc/CMakeFiles/cmake.check_cache create mode 100644 ParallelIO/doc/CMakeLists.txt create mode 100644 ParallelIO/doc/Doxyfile.in create mode 100644 ParallelIO/doc/DoxygenLayout.xml create mode 100644 ParallelIO/doc/Makefile.am create mode 100644 ParallelIO/doc/customdoxygen.css create mode 100644 ParallelIO/doc/doxygen.sty create mode 100644 ParallelIO/doc/images/I_O_on_Few.png create mode 100644 ParallelIO/doc/images/I_O_on_Many_Async.png create mode 100644 ParallelIO/doc/images/I_O_on_Many_Intracomm.png create mode 100644 ParallelIO/doc/images/I_O_on_many_async_small.png create mode 100644 ParallelIO/doc/images/Makefile.am create mode 100644 ParallelIO/doc/images/PIO_Async.png create mode 100644 ParallelIO/doc/images/PIO_Decomposition.png create mode 100644 ParallelIO/doc/images/PIO_Intracomm1.png create mode 100644 ParallelIO/doc/images/PIO_Library_Architecture1.jpg create mode 100644 ParallelIO/doc/images/baseimage.graffle create mode 100644 ParallelIO/doc/images/block-cyclic-rearr.eps create mode 100644 ParallelIO/doc/images/block-cyclic-rearr.graffle create mode 100644 ParallelIO/doc/images/block-cyclic-rearr.png create mode 100644 ParallelIO/doc/images/block-cyclic.eps create mode 100644 ParallelIO/doc/images/block-cyclic.graffle create mode 100644 ParallelIO/doc/images/block-cyclic.png create mode 100644 ParallelIO/doc/images/dof-rearr.eps create mode 100644 ParallelIO/doc/images/dof-rearr.graffle create mode 100644 ParallelIO/doc/images/dof-rearr.png create mode 100644 ParallelIO/doc/images/dof.eps create mode 100644 ParallelIO/doc/images/dof.graffle create mode 100644 ParallelIO/doc/images/dof.png create mode 100644 ParallelIO/doc/source/CAMexample.txt create mode 100644 ParallelIO/doc/source/Decomp.txt create mode 100644 ParallelIO/doc/source/Error.txt create mode 100644 ParallelIO/doc/source/Examples.txt create mode 100644 ParallelIO/doc/source/Installing.txt create mode 100644 ParallelIO/doc/source/Introduction.txt create mode 100644 ParallelIO/doc/source/Makefile.am create mode 100644 ParallelIO/doc/source/Testing.txt create mode 100644 ParallelIO/doc/source/api.txt create mode 100644 ParallelIO/doc/source/base.txt create mode 100644 ParallelIO/doc/source/c_api.txt create mode 100644 ParallelIO/doc/source/contributing_code.txt create mode 100644 ParallelIO/doc/source/example/errorhandle create mode 100644 ParallelIO/doc/source/example/simple-bc create mode 100644 ParallelIO/doc/source/example/simple-bc-rearr create mode 100644 ParallelIO/doc/source/example/simple-bc-rearr-pe1 create mode 100644 ParallelIO/doc/source/example/simple-bc-rearr-pe2 create mode 100644 ParallelIO/doc/source/example/simple-dof create mode 100644 ParallelIO/doc/source/example/simple-dof-rearr create mode 100644 ParallelIO/doc/source/faq.txt create mode 100644 ParallelIO/doc/source/iosystem.txt create mode 100644 ParallelIO/doc/source/mach_walkthrough.txt create mode 100644 ParallelIO/doc/source/netcdf_integration.txt create mode 100644 ParallelIO/doc/source/testpio_example.txt create mode 100644 ParallelIO/doc/source/users_guide.txt create mode 100644 ParallelIO/examples/CMakeLists.txt create mode 100644 ParallelIO/examples/Makefile.am create mode 100644 ParallelIO/examples/basic/CAM05.csh create mode 100644 ParallelIO/examples/basic/CMakeLists.txt create mode 100755 ParallelIO/examples/basic/MPASA30km.csh create mode 100755 ParallelIO/examples/basic/MPASA60km.csh create mode 100755 ParallelIO/examples/basic/POPB.csh create mode 100644 ParallelIO/examples/basic/POPC.csh create mode 100644 ParallelIO/examples/basic/POPD.csh create mode 100755 ParallelIO/examples/basic/POPDv0.csh create mode 100755 ParallelIO/examples/basic/POPDv1.csh create mode 100755 ParallelIO/examples/basic/POPDv2.csh create mode 100755 ParallelIO/examples/basic/POPDv3.csh create mode 100755 ParallelIO/examples/basic/POPDv4.csh create mode 100755 ParallelIO/examples/basic/POPDv5.csh create mode 100644 ParallelIO/examples/basic/README.testpio create mode 100644 ParallelIO/examples/basic/WRFB.csh create mode 100644 ParallelIO/examples/basic/alloc_mod.F90.in create mode 100644 ParallelIO/examples/basic/build_defaults.xml create mode 100644 ParallelIO/examples/basic/check_mod.F90 create mode 100644 ParallelIO/examples/basic/config_bench.xml create mode 100644 ParallelIO/examples/basic/fdepends.awk create mode 100644 ParallelIO/examples/basic/gdecomp_mod.F90 create mode 100644 ParallelIO/examples/basic/kinds_mod.F90 create mode 100755 ParallelIO/examples/basic/kraken.128.csh create mode 100755 ParallelIO/examples/basic/kraken.1K.csh create mode 100755 ParallelIO/examples/basic/kraken.256.csh create mode 100755 ParallelIO/examples/basic/kraken.512.csh create mode 100755 ParallelIO/examples/basic/kraken.64.csh create mode 100644 ParallelIO/examples/basic/namelist_mod.F90 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.apb05 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.asb01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.asb04 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b02 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b03 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b04 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b05 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b06 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b07 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4b08 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4n01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4n02 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.n4n03 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb02 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb03 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb04 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb05 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb06 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb07 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pb08 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pn01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pn02 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.pn03 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps02 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps03 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps04 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps05 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps06 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps07 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.ps08 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb02 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb03 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb04 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb05 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb06 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb07 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sb08 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sn01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sn02 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.sn03 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.wr01 create mode 100644 ParallelIO/examples/basic/namelists/testpio_in.wr02 create mode 100644 ParallelIO/examples/basic/perl5lib/ChangeLog create mode 100644 ParallelIO/examples/basic/perl5lib/README create mode 100644 ParallelIO/examples/basic/perl5lib/XML/Changes create mode 100644 ParallelIO/examples/basic/perl5lib/XML/Lite.pm create mode 100644 ParallelIO/examples/basic/perl5lib/XML/Lite/Element.pm create mode 100644 ParallelIO/examples/basic/perl5lib/XML/README create mode 100644 ParallelIO/examples/basic/perl5lib/XML/man3/XML_Lite.3 create mode 100644 ParallelIO/examples/basic/perl5lib/XML/man3/XML_Lite_Element.3 create mode 100755 ParallelIO/examples/basic/test.csh create mode 100644 ParallelIO/examples/basic/testdecomp.F90 create mode 100644 ParallelIO/examples/basic/testdecomp.bluefire.run create mode 100644 ParallelIO/examples/basic/testdecomp_in create mode 100644 ParallelIO/examples/basic/testpio.F90 create mode 100755 ParallelIO/examples/basic/testpio_bench.pl create mode 100644 ParallelIO/examples/basic/testpio_build.pl create mode 100755 ParallelIO/examples/basic/testpio_run.pl create mode 100644 ParallelIO/examples/basic/utils_mod.F90 create mode 100644 ParallelIO/examples/basic/wstest.c create mode 100644 ParallelIO/examples/basic/ystest.sh create mode 100644 ParallelIO/examples/c/CMakeLists.txt create mode 100644 ParallelIO/examples/c/Makefile.am create mode 100644 ParallelIO/examples/c/darray_async.c create mode 100644 ParallelIO/examples/c/darray_no_async.c create mode 100644 ParallelIO/examples/c/example1.c create mode 100644 ParallelIO/examples/c/example2.c create mode 100644 ParallelIO/examples/c/examplePio.c create mode 100755 ParallelIO/examples/c/run_tests.sh.in create mode 100644 ParallelIO/examples/c/valsupp_example1.supp create mode 100644 ParallelIO/examples/cxx/CMakeLists.txt create mode 100644 ParallelIO/examples/cxx/examplePio.cxx create mode 100644 ParallelIO/examples/f03/CMakeLists.txt create mode 100644 ParallelIO/examples/f03/Makefile.am create mode 100644 ParallelIO/examples/f03/exampleAsyncPio.F90 create mode 100644 ParallelIO/examples/f03/examplePio.F90 create mode 100755 ParallelIO/examples/f03/run_tests.sh.in create mode 100644 ParallelIO/libpio.settings.in create mode 100644 ParallelIO/scripts/Makefile.am create mode 100755 ParallelIO/scripts/genf90.pl create mode 100644 ParallelIO/scripts/prune_decomps.pl create mode 100644 ParallelIO/src/CMakeLists.txt create mode 100644 ParallelIO/src/Makefile.am create mode 100644 ParallelIO/src/clib/CMakeLists.txt create mode 100644 ParallelIO/src/clib/Makefile.am create mode 100644 ParallelIO/src/clib/parallel_sort.c create mode 100644 ParallelIO/src/clib/parallel_sort.h create mode 100644 ParallelIO/src/clib/pio.h create mode 100644 ParallelIO/src/clib/pio_darray.c create mode 100644 ParallelIO/src/clib/pio_darray_int.c create mode 100644 ParallelIO/src/clib/pio_error.c create mode 100644 ParallelIO/src/clib/pio_error.h create mode 100644 ParallelIO/src/clib/pio_file.c create mode 100644 ParallelIO/src/clib/pio_gdal.XC create mode 100644 ParallelIO/src/clib/pio_gdal.c create mode 100644 ParallelIO/src/clib/pio_get_nc.c create mode 100644 ParallelIO/src/clib/pio_get_vard.c create mode 100644 ParallelIO/src/clib/pio_getput_int.c create mode 100644 ParallelIO/src/clib/pio_internal.h create mode 100644 ParallelIO/src/clib/pio_lists.c create mode 100644 ParallelIO/src/clib/pio_meta.h.in create mode 100644 ParallelIO/src/clib/pio_msg.c create mode 100644 ParallelIO/src/clib/pio_nc.c create mode 100644 ParallelIO/src/clib/pio_nc4.c create mode 100644 ParallelIO/src/clib/pio_put_nc.c create mode 100644 ParallelIO/src/clib/pio_put_vard.c create mode 100644 ParallelIO/src/clib/pio_rearrange.c create mode 100644 ParallelIO/src/clib/pio_spmd.c create mode 100644 ParallelIO/src/clib/pioc.c create mode 100644 ParallelIO/src/clib/pioc_async.c create mode 100644 ParallelIO/src/clib/pioc_sc.c create mode 100644 ParallelIO/src/clib/pioc_support.c create mode 100644 ParallelIO/src/clib/topology.c create mode 100644 ParallelIO/src/clib/uthash.h create mode 100644 ParallelIO/src/flib/CMakeLists.txt create mode 100644 ParallelIO/src/flib/Makefile.am create mode 100644 ParallelIO/src/flib/ncint_mod.F90 create mode 100644 ParallelIO/src/flib/pio.F90 create mode 100644 ParallelIO/src/flib/pio_kinds.F90 create mode 100644 ParallelIO/src/flib/pio_nf.F90 create mode 100644 ParallelIO/src/flib/pio_support.F90 create mode 100644 ParallelIO/src/flib/pio_types.F90 create mode 100644 ParallelIO/src/flib/piodarray.F90.in create mode 100644 ParallelIO/src/flib/piolib_mod.F90 create mode 100644 ParallelIO/src/flib/pionfatt_mod.F90.in create mode 100644 ParallelIO/src/flib/pionfget_mod.F90.in create mode 100644 ParallelIO/src/flib/pionfput_mod.F90.in create mode 100644 ParallelIO/src/gptl/CMakeLists.txt create mode 100644 ParallelIO/src/gptl/COPYING create mode 100644 ParallelIO/src/gptl/ChangeLog create mode 100644 ParallelIO/src/gptl/GPTLget_memusage.c create mode 100644 ParallelIO/src/gptl/GPTLprint_memusage.c create mode 100644 ParallelIO/src/gptl/GPTLutil.c create mode 100644 ParallelIO/src/gptl/Makefile.am create mode 100644 ParallelIO/src/gptl/README create mode 100644 ParallelIO/src/gptl/f_wrappers.c create mode 100644 ParallelIO/src/gptl/f_wrappers_2.c create mode 100644 ParallelIO/src/gptl/gptl.c create mode 100644 ParallelIO/src/gptl/gptl.h create mode 100644 ParallelIO/src/gptl/gptl.inc create mode 100644 ParallelIO/src/gptl/gptl_papi.c create mode 100644 ParallelIO/src/gptl/perf_mod.F90 create mode 100644 ParallelIO/src/gptl/perf_utils.F90 create mode 100644 ParallelIO/src/gptl/private.h create mode 100644 ParallelIO/src/gptl/threadutil.c create mode 100644 ParallelIO/src/ncint/Makefile.am create mode 100644 ParallelIO/src/ncint/nc_get_vard.c create mode 100644 ParallelIO/src/ncint/nc_put_vard.c create mode 100644 ParallelIO/src/ncint/ncint_pio.c create mode 100644 ParallelIO/src/ncint/ncintdispatch.c create mode 100644 ParallelIO/src/ncint/ncintdispatch.h create mode 100644 ParallelIO/tests/CMakeLists.txt create mode 100644 ParallelIO/tests/Makefile.am create mode 100644 ParallelIO/tests/cperf/CMakeLists.txt create mode 100644 ParallelIO/tests/cperf/mpi_argp.c create mode 100644 ParallelIO/tests/cperf/piodecomptest.c create mode 100644 ParallelIO/tests/cunit/CMakeLists.txt create mode 100644 ParallelIO/tests/cunit/Makefile.am create mode 100644 ParallelIO/tests/cunit/pio_tests.h create mode 100644 ParallelIO/tests/cunit/run_tests.sh.in create mode 100644 ParallelIO/tests/cunit/test_async_1d.c create mode 100644 ParallelIO/tests/cunit/test_async_3proc.c create mode 100644 ParallelIO/tests/cunit/test_async_4proc.c create mode 100644 ParallelIO/tests/cunit/test_async_manyproc.c create mode 100644 ParallelIO/tests/cunit/test_async_mpi.c create mode 100644 ParallelIO/tests/cunit/test_async_multi2.c create mode 100644 ParallelIO/tests/cunit/test_async_multicomp.c create mode 100644 ParallelIO/tests/cunit/test_async_perf.c create mode 100644 ParallelIO/tests/cunit/test_async_simple.c create mode 100644 ParallelIO/tests/cunit/test_common.c create mode 100644 ParallelIO/tests/cunit/test_darray.c create mode 100644 ParallelIO/tests/cunit/test_darray_1d.c create mode 100644 ParallelIO/tests/cunit/test_darray_2sync.c create mode 100644 ParallelIO/tests/cunit/test_darray_3d.c create mode 100644 ParallelIO/tests/cunit/test_darray_append.c create mode 100644 ParallelIO/tests/cunit/test_darray_async.c create mode 100644 ParallelIO/tests/cunit/test_darray_async_from_comm.c create mode 100644 ParallelIO/tests/cunit/test_darray_async_many.c create mode 100644 ParallelIO/tests/cunit/test_darray_async_simple.c create mode 100644 ParallelIO/tests/cunit/test_darray_fill.c create mode 100644 ParallelIO/tests/cunit/test_darray_frame.c create mode 100644 ParallelIO/tests/cunit/test_darray_multi.c create mode 100644 ParallelIO/tests/cunit/test_darray_multivar.c create mode 100644 ParallelIO/tests/cunit/test_darray_multivar2.c create mode 100644 ParallelIO/tests/cunit/test_darray_multivar3.c create mode 100644 ParallelIO/tests/cunit/test_darray_vard.c create mode 100644 ParallelIO/tests/cunit/test_decomp_frame.c create mode 100644 ParallelIO/tests/cunit/test_decomp_uneven.c create mode 100644 ParallelIO/tests/cunit/test_decomps.c create mode 100644 ParallelIO/tests/cunit/test_intercomm2.c create mode 100644 ParallelIO/tests/cunit/test_iosystem2.c create mode 100644 ParallelIO/tests/cunit/test_iosystem2_simple.c create mode 100644 ParallelIO/tests/cunit/test_iosystem2_simple2.c create mode 100644 ParallelIO/tests/cunit/test_iosystem3.c create mode 100644 ParallelIO/tests/cunit/test_iosystem3_simple.c create mode 100644 ParallelIO/tests/cunit/test_iosystem3_simple2.c create mode 100644 ParallelIO/tests/cunit/test_perf2.c create mode 100644 ParallelIO/tests/cunit/test_pioc.c create mode 100644 ParallelIO/tests/cunit/test_pioc_fill.c create mode 100644 ParallelIO/tests/cunit/test_pioc_putget.c create mode 100644 ParallelIO/tests/cunit/test_pioc_unlim.c create mode 100644 ParallelIO/tests/cunit/test_rearr.c create mode 100644 ParallelIO/tests/cunit/test_shared.c create mode 100644 ParallelIO/tests/cunit/test_simple.c create mode 100644 ParallelIO/tests/cunit/test_spmd.c create mode 100644 ParallelIO/tests/doftests/CMakeLists.txt create mode 100644 ParallelIO/tests/doftests/dofcopy.F90 create mode 100644 ParallelIO/tests/fncint/Makefile.am create mode 100644 ParallelIO/tests/fncint/ftst_pio.f90 create mode 100644 ParallelIO/tests/fncint/ftst_pio_orig.f90 create mode 100755 ParallelIO/tests/fncint/run_tests.sh.in create mode 100644 ParallelIO/tests/fncint/tst_c_pio.c create mode 100644 ParallelIO/tests/general/CMakeLists.txt create mode 100644 ParallelIO/tests/general/Makefile.am create mode 100644 ParallelIO/tests/general/README.md create mode 100644 ParallelIO/tests/general/ncdf_fail.F90.in create mode 100644 ParallelIO/tests/general/ncdf_get_put.F90.in create mode 100644 ParallelIO/tests/general/ncdf_inq.F90.in create mode 100644 ParallelIO/tests/general/ncdf_simple_tests.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_fillval.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_frame_tests.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_tests.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_tests_1d.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_tests_2d.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_tests_2d_async.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_tests_2d_halo.F90.in create mode 100644 ParallelIO/tests/general/pio_decomp_tests_3d.F90.in create mode 100644 ParallelIO/tests/general/pio_decomphalo_tests_2d.F90.in create mode 100644 ParallelIO/tests/general/pio_fail.F90.in create mode 100644 ParallelIO/tests/general/pio_file_fail.F90.in create mode 100644 ParallelIO/tests/general/pio_file_simple_tests.F90.in create mode 100644 ParallelIO/tests/general/pio_init_finalize.F90.in create mode 100644 ParallelIO/tests/general/pio_iosystem_async_tests.F90.in create mode 100644 ParallelIO/tests/general/pio_iosystem_tests.F90.in create mode 100644 ParallelIO/tests/general/pio_iosystem_tests2.F90.in create mode 100644 ParallelIO/tests/general/pio_iosystem_tests3.F90.in create mode 100644 ParallelIO/tests/general/pio_rearr.F90.in create mode 100644 ParallelIO/tests/general/pio_rearr_opts.F90.in create mode 100644 ParallelIO/tests/general/pio_rearr_opts2.F90.in create mode 100755 ParallelIO/tests/general/run_tests.sh.in create mode 100644 ParallelIO/tests/general/test_memleak.c create mode 100644 ParallelIO/tests/general/util/Makefile.am create mode 100755 ParallelIO/tests/general/util/pio_tf_f90gen.pl create mode 100644 ParallelIO/tests/general/util/pio_tutil.F90 create mode 100644 ParallelIO/tests/ncint/CMakeLists.txt create mode 100644 ParallelIO/tests/ncint/Makefile.am create mode 100644 ParallelIO/tests/ncint/pio_err_macros.h create mode 100755 ParallelIO/tests/ncint/run_perf.sh.in create mode 100755 ParallelIO/tests/ncint/run_tests.sh.in create mode 100644 ParallelIO/tests/ncint/tst_async_multi.c create mode 100644 ParallelIO/tests/ncint/tst_ncint_async_perf.c create mode 100644 ParallelIO/tests/ncint/tst_ncint_perf.c create mode 100644 ParallelIO/tests/ncint/tst_pio_async.c create mode 100644 ParallelIO/tests/ncint/tst_pio_udf.c create mode 100644 ParallelIO/tests/ncint/tst_var_compress.c create mode 100644 ParallelIO/tests/performance/CMakeLists.txt create mode 100644 ParallelIO/tests/performance/Makefile.am create mode 100644 ParallelIO/tests/performance/Pioperformance.md create mode 100644 ParallelIO/tests/performance/gensimple.pl create mode 100644 ParallelIO/tests/performance/kt.PIO1.perfmakefile create mode 100644 ParallelIO/tests/performance/pioperf.nl create mode 100644 ParallelIO/tests/performance/pioperformance.F90 create mode 100755 ParallelIO/tests/performance/run_tests.sh.in create mode 100644 ParallelIO/tests/unit/CMakeLists.txt create mode 100644 ParallelIO/tests/unit/Levy_Notes create mode 100644 ParallelIO/tests/unit/Makefile.am create mode 100644 ParallelIO/tests/unit/basic_tests.F90 create mode 100644 ParallelIO/tests/unit/driver.F90 create mode 100644 ParallelIO/tests/unit/ftst_vars_chunking.F90 create mode 100644 ParallelIO/tests/unit/global_vars.F90 create mode 100644 ParallelIO/tests/unit/input.nl create mode 100644 ParallelIO/tests/unit/nc_set_log_level2.c create mode 100644 ParallelIO/tests/unit/ncdf_tests.F90 create mode 100644 ParallelIO/tests/unit/not_netcdf.ieee create mode 100755 ParallelIO/tests/unit/run_tests.sh.in create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/buildhdf5/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/buildmpich/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/buildnetcdf/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/buildnetcdff/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/buildopenmpi/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/buildpnetcdf/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/intelcompilers/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/parallelio_autotools/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/actions/parallelio_cmake/action.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/workflows/intel.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/.github/workflows/withspack.yml create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/examples/c/piorcw.c create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/tests/cunit/test_darray_lossycompress.c create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/tests/derecho_testsuite.py create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/tests/general/pio_filter_tests.F90.in create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/tests/ncint/ncint.h create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/tests/ncint/tst_ncint_open.c diff --git a/ParallelIO/.github/workflows/autotools.yml b/ParallelIO/.github/workflows/autotools.yml new file mode 100644 index 0000000000..8708fed114 --- /dev/null +++ b/ParallelIO/.github/workflows/autotools.yml @@ -0,0 +1,66 @@ +name: autotools_ubuntu_latest + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CC: mpicc + FC: mpifort + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" + PNETCDF_VERSION: 1.12.3 + FCFLAGS: "-fallow-argument-mismatch" + steps: + - uses: actions/checkout@v3 + - name: Installs + run: | + set -x + # sudo gem install apt-spy2 + # sudo apt-spy2 check + # sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update + sudo apt-get install netcdf-bin + sudo apt-get install libnetcdf-dev + sudo apt-get install doxygen + sudo apt-get install graphviz + sudo apt-get install wget + sudo apt-get install gfortran + sudo apt-get install libjpeg-dev + sudo apt-get install libz-dev + sudo apt-get install openmpi-bin + sudo apt-get install libopenmpi-dev + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v3 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-${{ env.PNETCDF_VERSION }} + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz &> /dev/null + tar -xzvf pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz + pushd pnetcdf-${{ env.PNETCDF_VERSION }} + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + + - name: autoreconf + run: autoreconf -i + - name: configure + run: ./configure --enable-fortran --with-mpiexec='mpiexec --oversubscribe' + #run: ./configure --enable-fortran --enable-docs --with-mpiexec='mpiexec --oversubscribe' + - name: make check + run: make -j check diff --git a/ParallelIO/.github/workflows/cmake.yml b/ParallelIO/.github/workflows/cmake.yml new file mode 100644 index 0000000000..8d7443c2c6 --- /dev/null +++ b/ParallelIO/.github/workflows/cmake.yml @@ -0,0 +1,64 @@ +name: cmake + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CC: mpicc + FC: mpifort + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" + LD_LIBRARY_PATH: "/home/runner/pnetcdf/lib" + PNETCDF_VERSION: 1.12.3 + FCFLAGS: "-fallow-argument-mismatch" + steps: + - uses: actions/checkout@v3 + - name: Installs + run: | + set -x + #sudo gem install apt-spy2 + #sudo apt-spy2 check + #sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update + sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev cmake + + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v3 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-${{ env.PNETCDF_VERSION }} + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz &> /dev/null + tar -xzvf pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz + pushd pnetcdf-${{ env.PNETCDF_VERSION }} + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + + - name: cmake build + run: | + set -x + mkdir build + cd build + cmake -Wno-dev -DNetCDF_C_LIBRARY=/usr/lib/x86_64-linux-gnu/libnetcdf.so \ + -DNetCDF_C_INCLUDE_DIR=/usr/include -DPnetCDF_PATH='/home/runner/pnetcdf' \ + -DPIO_ENABLE_FORTRAN=Off \ + -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off -DMPIEXEC_PREFLAGS="--oversubscribe" .. + make VERBOSE=1 + make tests VERBOSE=1 + ctest -VV diff --git a/ParallelIO/.github/workflows/cmake_ubuntu_latest.yml b/ParallelIO/.github/workflows/cmake_ubuntu_latest.yml new file mode 100644 index 0000000000..d998aae307 --- /dev/null +++ b/ParallelIO/.github/workflows/cmake_ubuntu_latest.yml @@ -0,0 +1,68 @@ +--- # cmake build without netcdf integration +name: cmake_ubuntu-latest + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CC: mpicc + FC: mpifort + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" + LD_LIBRARY_PATH: "/home/runner/pnetcdf/lib" + PNETCDF_VERSION: 1.12.3 + FCFLAGS: "-fallow-argument-mismatch" + steps: + - uses: actions/checkout@v3 + - name: Installs + run: | + set -x + #sudo gem install apt-spy2 + #sudo apt-spy2 check + #sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update + sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev + + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v3 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-${{ env.PNETCDF_VERSION }} + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz &> /dev/null + tar -xzvf pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz + pushd pnetcdf-${{ env.PNETCDF_VERSION }} + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + + - name: cmake build + run: | + set -x + mkdir build + cd build + cmake -Wno-dev -DPIO_ENABLE_NETCDF_INTEGRATION=OFF \ + -DNetCDF_C_LIBRARY=/usr/lib/x86_64-linux-gnu/libnetcdf.so \ + -DNetCDF_C_INCLUDE_DIR=/usr/include -DPnetCDF_PATH='/home/runner/pnetcdf' \ + -DPIO_ENABLE_FORTRAN=OFF \ + -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off -DMPIEXEC_PREFLAGS="--oversubscribe" .. + make VERBOSE=1 + make tests VERBOSE=1 + ctest -VV diff --git a/ParallelIO/.github/workflows/netcdf_hdf5_no_pnetcdf_ncint_mpich.yml b/ParallelIO/.github/workflows/netcdf_hdf5_no_pnetcdf_ncint_mpich.yml new file mode 100644 index 0000000000..6a8fb24f05 --- /dev/null +++ b/ParallelIO/.github/workflows/netcdf_hdf5_no_pnetcdf_ncint_mpich.yml @@ -0,0 +1,119 @@ +name: netcdf_hdf5_no_pnetcdf_ncint_mpich +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CPPFLAGS: "-I/home/runner/mpich/include -I/home/runner/hdf5/include -I/home/runner/netcdf-c/include -I/home/runner/netcdf-fortran/include" + LDFLAGS: "-L/home/runner/mpich/lib -L/home/runner/hdf5/lib -L/home/runner/netcdf-c/lib -L/home/runner/netcdf-fortran/lib" + # Note issue https://github.com/NCAR/ParallelIO/issues/1889 netcdf integration currently only works with netcdf 4.7.4 + NETCDF_C_VERSION: 4.7.4 + NETCDF_F_VERSION: 4.5.4 + MPICH_VERSION: 4.0.3 + HDF5_VERSION_MAJOR: 1.12 + HDF5_VERSION_PATCH: 2 + FFLAGS: "-fallow-argument-mismatch" + FCFLAGS: "-fallow-argument-mismatch" + steps: + - uses: actions/checkout@v3 + - name: Installs + run: | + sudo apt-get install doxygen graphviz wget gfortran libjpeg-dev libz-dev + - name: cache-mpich + id: cache-mpich + uses: actions/cache@v3 + with: + path: ~/mpich + key: mpich-${{ runner.os }}-${{ env.MPICH_VERSION }} + + - name: build-mpich + if: steps.cache-mpich.outputs.cache-hit != 'true' + run: | + wget http://www.mpich.org/static/downloads/${{ env.MPICH_VERSION }}/mpich-${{ env.MPICH_VERSION }}.tar.gz &> /dev/null + tar -xzf mpich-${{ env.MPICH_VERSION }}.tar.gz + pushd mpich-${{ env.MPICH_VERSION }} + ./configure --prefix=/home/runner/mpich + make + sudo make install + popd + - name: cache-hdf5 + id: cache-hdf5 + uses: actions/cache@v3 + with: + path: ~/hdf5 + key: hdf5-${{ runner.os }}-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}-mpich-${{ env.MPICH_VERSION }} + + - name: build-hdf5 + if: steps.cache-hdf5.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-${{ env.HDF5_VERSION_MAJOR }}/hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}/src/hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}.tar.gz &> /dev/null + tar -xzf hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}.tar.gz + pushd hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + ./configure --prefix=/home/runner/hdf5 --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + make + sudo make install + popd + - name: cache-netcdf-c + id: cache-netcdf-c + uses: actions/cache@v3 + with: + path: ~/netcdf-c + key: netcdf-c-${{ runner.os }}-${{ env.NETCDF_C_VERSION }}-mpich-${{ env.MPICH_VERSION }}-hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + + - name: build-netcdf-c + if: steps.cache-netcdf-c.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v${{ env.NETCDF_C_VERSION }}.tar.gz + tar -xzf v${{ env.NETCDF_C_VERSION }}.tar.gz &> /dev/null + pushd netcdf-c-${{ env.NETCDF_C_VERSION }} + ./configure --prefix=/home/runner/netcdf-c --disable-dap --disable-utilities + make -j + sudo make install + popd + + - name: cache-netcdf-fortran + id: cache-netcdf-fortran + uses: actions/cache@v3 + with: + path: ~/netcdf-fortran + key: netcdf-fortran-${{ runner.os }}-${{ env.NETCDF_F_VERSION }}-mpich-${{ env.MPICH_VERSION }}-hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + + - name: build-netcdf-fortran + if: steps.cache-netcdf-fortran.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://github.com/Unidata/netcdf-fortran/archive/refs/tags/v${{ env.NETCDF_F_VERSION }}.tar.gz + tar -zxf v${{ env.NETCDF_F_VERSION }}.tar.gz &> /dev/null + pushd netcdf-fortran-${{ env.NETCDF_F_VERSION }} + ./configure --prefix=/home/runner/netcdf-fortran + make -j + sudo make install + popd + + - name: autotools build + run: | + set -x + gcc --version + export PATH=/home/runner/mpich/bin:/home/runner/netcdf-c/bin:$PATH + export CC=/home/runner/mpich/bin/mpicc + export FC=/home/runner/mpich/bin/mpifort + autoreconf -i + ./configure --enable-fortran --enable-netcdf-integration --disable-pnetcdf + make -j check + + diff --git a/ParallelIO/.github/workflows/netcdf_hdf5_pnetcdf_ncint_mpich_asan.yml b/ParallelIO/.github/workflows/netcdf_hdf5_pnetcdf_ncint_mpich_asan.yml new file mode 100644 index 0000000000..7ee67f90f2 --- /dev/null +++ b/ParallelIO/.github/workflows/netcdf_hdf5_pnetcdf_ncint_mpich_asan.yml @@ -0,0 +1,162 @@ +name: netcdf_hdf5_pnetcdf_ncint_mpich_asan +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CPPFLAGS: "-I/home/runner/mpich/include -I/home/runner/hdf5/include -I/home/runner/netcdf-c/include -I/home/runner/netcdf-fortran/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/mpich/lib -L/home/runner/hdf5/lib -L/home/runner/netcdf-c/lib -L/home/runner/netcdf-fortran/lib -L/home/runner/pnetcdf/lib" + # Note issue https://github.com/NCAR/ParallelIO/issues/1889 netcdf integration only currently works with netcdf-c 4.7.4 + NETCDF_C_VERSION: 4.7.4 + NETCDF_F_VERSION: 4.5.4 + PNETCDF_VERSION: 1.12.3 + MPICH_VERSION: 4.0.3 + HDF5_VERSION_MAJOR: 1.12 + HDF5_VERSION_PATCH: 2 + FCFLAGS: "-fallow-argument-mismatch" + FFLAGS: "-fallow-argument-mismatch" + steps: + - uses: actions/checkout@v3 + - name: Installs + run: | + sudo apt-get install doxygen graphviz wget gfortran libjpeg-dev libz-dev + - name: cache-mpich + id: cache-mpich + uses: actions/cache@v3 + with: + path: ~/mpich + key: mpich-${{ runner.os }}-${{ env.MPICH_VERSION }} + + - name: build-mpich + if: steps.cache-mpich.outputs.cache-hit != 'true' + run: | + wget http://www.mpich.org/static/downloads/${{ env.MPICH_VERSION }}/mpich-${{ env.MPICH_VERSION }}.tar.gz &> /dev/null + tar -xzf mpich-${{ env.MPICH_VERSION }}.tar.gz + pushd mpich-${{ env.MPICH_VERSION }} + ./configure --prefix=/home/runner/mpich + make + sudo make install + popd + - name: cache-hdf5 + id: cache-hdf5 + uses: actions/cache@v3 + with: + path: ~/hdf5 + key: hdf5-${{ runner.os }}-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}-mpich-${{ env.MPICH_VERSION }} + + - name: build-hdf5 + if: steps.cache-hdf5.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-${{ env.HDF5_VERSION_MAJOR }}/hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}/src/hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}.tar.gz &> /dev/null + tar -xzf hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}.tar.gz + pushd hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + ./configure --prefix=/home/runner/hdf5 --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + make + sudo make install + popd + - name: cache-netcdf-c + id: cache-netcdf-c + uses: actions/cache@v3 + with: + path: ~/netcdf-c + key: netcdf-c-${{ runner.os }}-${{ env.NETCDF_C_VERSION }}-mpich-${{ env.MPICH_VERSION }}-hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + + - name: build-netcdf-c + if: steps.cache-netcdf-c.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v${{ env.NETCDF_C_VERSION }}.tar.gz + tar -xzf v${{ env.NETCDF_C_VERSION }}.tar.gz + pushd netcdf-c-${{ env.NETCDF_C_VERSION }} + ./configure --prefix=/home/runner/netcdf-c --disable-dap --disable-utilities + make -j + sudo make install + popd + - name: cache-netcdf-fortran + id: cache-netcdf-fortran + uses: actions/cache@v3 + with: + path: ~/netcdf-fortran + key: netcdf-fortran-${{ runner.os }}-${{ env.NETCDF_F_VERSION }}-mpich-${{ env.MPICH_VERSION }}-hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + + - name: build-netcdf-fortran + if: steps.cache-netcdf-fortran.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://github.com/Unidata/netcdf-fortran/archive/refs/tags/v${{ env.NETCDF_F_VERSION }}.tar.gz + tar -xzf v${{ env.NETCDF_F_VERSION }}.tar.gz + pushd netcdf-fortran-${{ env.NETCDF_F_VERSION }} + ./configure --prefix=/home/runner/netcdf-fortran + make -j + sudo make install + popd + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v3 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-${{ env.PNETCDF_VERSION }}-mpich-${{ env.MPICH_VERSION }} + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://parallel-netcdf.github.io/Release/pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz &> /dev/null + tar -xzf pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz + pushd pnetcdf-${{ env.PNETCDF_VERSION }} + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + - name: cmake build + run: | + set -x + gcc --version + echo 'export PATH=/home/runner/mpich/bin:$PATH' > .bashrc + source .bashrc + export CC=/home/runner/mpich/bin/mpicc + export FC=/home/runner/mpich/bin/mpifort + export CFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer -static-libasan" + export FCFLAGS="$FCFLAGS -g -O0 -fsanitize=address -fno-omit-frame-pointer -static-libasan" + export LDFLAGS="$LDFLAGS -static-libasan" + export LD_LIBRARY_PATH="/home/runner/netcdf-c/lib:/home/runner/mpich/lib:/home/runner/hdf5/lib:/home/runner/netcdf-fortran/lib:/home/runner/pnetcdf/lib:$LD_LIBRARY_PATH" + export ASAN_OPTIONS="detect_odr_violation=0" + mkdir build + cd build + cmake -Wno-dev -DNetCDF_C_LIBRARY=/home/runner/netcdf-c/lib/libnetcdf.so -DNetCDF_C_INCLUDE_DIR=/home/runner/netcdf-c/include -DPnetCDF_PATH='/home/runner/pnetcdf' -DPIO_ENABLE_FORTRAN=Off -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off .. || (cat CMakeFiles/CMakeOutput.log && cat CMakeFiles/CMakeError.log) + make VERBOSE=1 + make tests VERBOSE=1 +# ctest -VV + - name: autotools build + run: | + set -x + gcc --version + echo 'export PATH=/home/runner/mpich/bin:$PATH' > .bashrc + source .bashrc + export CC=/home/runner/mpich/bin/mpicc + export FC=/home/runner/mpich/bin/mpifort + export CFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer -static-libasan" + export FCFLAGS="$FCFLAGS -g -O0 -fsanitize=address -fno-omit-frame-pointer -static-libasan" + export LDFLAGS="$LDFLAGS -static-libasan" + export ASAN_OPTIONS="detect_odr_violation=0" + autoreconf -i + ./configure --enable-fortran --enable-netcdf-integration + make -j check + + diff --git a/ParallelIO/.github/workflows/netcdf_pnetcdf_openmpi.yml b/ParallelIO/.github/workflows/netcdf_pnetcdf_openmpi.yml new file mode 100644 index 0000000000..4ab12970de --- /dev/null +++ b/ParallelIO/.github/workflows/netcdf_pnetcdf_openmpi.yml @@ -0,0 +1,156 @@ +name: netcdf_pnetcdf_openmpi + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CPPFLAGS: "-I/home/runner/openmpi/include -I/home/runner/hdf5/include -I/home/runner/netcdf-c/include -I/home/runner/netcdf-fortran/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/openmpi/lib -L/home/runner/hdf5/lib -L/home/runner/netcdf-c/lib -L/home/runner/netcdf-fortran/lib -L/home/runner/pnetcdf/lib" + NETCDF_C_VERSION: 4.9.0 + NETCDF_F_VERSION: 4.6.0 + OPENMPI_VERSION_MAJOR: 4.1 + OPENMPI_VERSION_PATCH: 4 + PNETCDF_VERSION: 1.12.3 + HDF5_VERSION_PATCH: 2 + HDF5_VERSION_MAJOR: 1.12 + FCFLAGS: "-fallow-argument-mismatch" + FFLAGS: "-fallow-argument-mismatch" + steps: + - uses: actions/checkout@v3 + - name: Installs + run: | + sudo apt-get install doxygen graphviz wget gfortran libjpeg-dev libz-dev + - name: cache-openmpi + id: cache-openmpi + uses: actions/cache@v3 + with: + path: ~/openmpi + key: openmpi-${{ runner.os }}-${{ env.OPENMPI_VERSION }} + + - name: build-openmpi + if: steps.cache-openmpi.outputs.cache-hit != 'true' + run: | + wget https://download.open-mpi.org/release/open-mpi/v${{ env.OPENMPI_VERSION_MAJOR }}/openmpi-${{ env.OPENMPI_VERSION_MAJOR }}.${{ env.OPENMPI_VERSION_PATCH}}.tar.gz &> /dev/null + tar -xzf openmpi-${{ env.OPENMPI_VERSION_MAJOR }}.${{ env.OPENMPI_VERSION_PATCH }}.tar.gz + pushd openmpi-${{ env.OPENMPI_VERSION_MAJOR }}.${{ env.OPENMPI_VERSION_PATCH }} + ./configure --prefix=/home/runner/openmpi + make + sudo make install + popd + - name: cache-hdf5 + id: cache-hdf5 + uses: actions/cache@v3 + with: + path: ~/hdf5 + key: hdf5-${{ runner.os }}-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}-openmpi-${{ env.OPENMPI_VERSION_MAJOR }}.${{ env.OPENMPI_VERSION_PATCH }} + + - name: build-hdf5 + if: steps.cache-hdf5.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-${{ env.HDF5_VERSION_MAJOR }}/hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}/src/hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}.tar.gz &> /dev/null + tar -xzf hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }}.tar.gz + pushd hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + ./configure --prefix=/home/runner/hdf5 --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + make + sudo make install + popd + - name: cache-netcdf-c + id: cache-netcdf-c + uses: actions/cache@v3 + with: + path: ~/netcdf-c + key: netcdf-c-${{ runner.os }}-${{ env.NETCDF_C_VERSION }}-openmpi-${{ env.OPENMPI_VERSION_MAJOR }}.${{ env.OPENMPI_VERSION_PATCH }}-hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + + - name: build-netcdf-c + if: steps.cache-netcdf-c.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v${{ env.NETCDF_C_VERSION }}.tar.gz + tar -xzf v${{ env.NETCDF_C_VERSION }}.tar.gz &> /dev/null + pushd netcdf-c-${{ env.NETCDF_C_VERSION }} + ./configure --prefix=/home/runner/netcdf-c --disable-dap --disable-utilities + make -j + sudo make install + popd + - name: cache-netcdf-fortran + id: cache-netcdf-fortran + uses: actions/cache@v3 + with: + path: ~/netcdf-fortran + key: netcdf-fortran-${{ runner.os }}-${{ env.NETCDF_F_VERSION }}-openmpi-${{ env.OPENMPI_VERSION_MAJOR }}.${{ env.OPENMPI_VERSION_PATCH }}-hdf5-${{ env.HDF5_VERSION_MAJOR }}.${{ env.HDF5_VERSION_PATCH }} + + - name: build-netcdf-fortran + if: steps.cache-netcdf-fortran.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://github.com/Unidata/netcdf-fortran/archive/refs/tags/v${{ env.NETCDF_F_VERSION }}.tar.gz + tar -zxf v${{ env.NETCDF_F_VERSION }}.tar.gz &> /dev/null + pushd netcdf-fortran-${{ env.NETCDF_F_VERSION }} + ./configure --prefix=/home/runner/netcdf-fortran + make -j + sudo make install + popd + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v3 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-${{ env.PNETCDF_VERSION }}-openmpi-${{ env.OPENMPI_VERSION_MAJOR }}.${{ env.OPENMPI_VERSION_PATCH }} + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://parallel-netcdf.github.io/Release/pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz &> /dev/null + tar -xzf pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz + pushd pnetcdf-${{ env.PNETCDF_VERSION }} + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + - name: autotools build + run: | + set -x + echo 'export PATH=/home/runner/openmpi/bin:$PATH' > .bashrc + source .bashrc + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + autoreconf -i + ./configure --with-mpiexec='mpiexec --oversubscribe' + cat config.h + make check + - name: cmake build + run: | + set -x + echo 'export PATH=/home/runner/openmpi/bin:$PATH' > .bashrc + source .bashrc + export CC=mpicc + mkdir build + cd build + export LD_LIBRARY_PATH="/home/runner/netcdf-c/lib:/home/runner/pnetcdf/lib:/home/runner/hdf5/lib:/home/runner/openmpi/lib:$LD_LIBRARY_PATH" + cmake -Wno-dev -DWITH_MPIEXEC='/home/runner/openmpi/bin/mpiexec;--oversubscribe' \ + -DNetCDF_C_LIBRARY=/home/runner/netcdf-c/lib/libnetcdf.so \ + -DNetCDF_C_INCLUDE_DIR=/home/runner/netcdf-c/include -DPnetCDF_PATH='/home/runner/pnetcdf' \ + -DPIO_ENABLE_FORTRAN=Off -DPIO_HDF5_LOGGING=On -DPIO_USE_MALLOC=On -DPIO_ENABLE_LOGGING=On \ + -DPIO_ENABLE_TIMING=Off .. || (cat CMakeFiles/CMakeOutput.log && cat CMakeFiles/CMakeError.log) + cat config.h + make VERBOSE=1 + make tests VERBOSE=1 + ctest -VV diff --git a/ParallelIO/.github/workflows/strict_autotools_ubuntu_latest.yml b/ParallelIO/.github/workflows/strict_autotools_ubuntu_latest.yml new file mode 100644 index 0000000000..faf74ce40b --- /dev/null +++ b/ParallelIO/.github/workflows/strict_autotools_ubuntu_latest.yml @@ -0,0 +1,62 @@ +name: strict_autotools_ubuntu_latest + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CC: mpicc + FC: mpifort + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" + FCFLAGS: "-fallow-argument-mismatch" + PNETCDF_VERSION: 1.12.3 + steps: + - uses: actions/checkout@v3 + - name: Installs + run: | + set -x + #sudo gem install apt-spy2 + #sudo apt-spy2 check + #sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update + sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev + + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v3 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-${{ env.PNETCDF_VERSION }} + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz &> /dev/null + tar -xzvf pnetcdf-${{ env.PNETCDF_VERSION }}.tar.gz + pushd pnetcdf-${{ env.PNETCDF_VERSION }} + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + + - name: autoreconf + run: autoreconf -i + - name: build + run: | + set -x + export CFLAGS="-std=c99 -Wall" + export FFLAGS="-Wall" + export FCFLAGS="$FCFLAGS -Wall" + export DISTCHECK_CONFIGURE_FLAGS="--enable-fortran --with-mpiexec='/usr/bin/mpiexec --oversubscribe'" + ./configure + make -j distcheck diff --git a/ParallelIO/.gitignore b/ParallelIO/.gitignore new file mode 100644 index 0000000000..5055b0c6a8 --- /dev/null +++ b/ParallelIO/.gitignore @@ -0,0 +1,32 @@ +.project +html/ +*~ +\#*\# +*.o +Makefile.in +*.lo +*.la +Makefile +acinclude.m4 +aclocal.m4 +atconfig +autom4te.cache +config-h.in +config.* +configure +stamp-h1 +conftest* +missing +libtool +install-sh +ltmain.sh +compile +depcomp +build/ +.deps/ +.libs/ +m4/ +*.nc +*.log +*.gz +!/decomps/*/*.nc \ No newline at end of file diff --git a/ParallelIO/CMakeLists.txt b/ParallelIO/CMakeLists.txt new file mode 100644 index 0000000000..5abb33a588 --- /dev/null +++ b/ParallelIO/CMakeLists.txt @@ -0,0 +1,494 @@ +# This is part of the PIO library. + +# This is the CMake build file for the main directory. + +# Jim Edwards + +cmake_minimum_required (VERSION 3.5.2) +project (PIO C) + +# The project version number. +set(VERSION_MAJOR 2 CACHE STRING "Project major version number.") +set(VERSION_MINOR 5 CACHE STRING "Project minor version number.") +set(VERSION_PATCH 10 CACHE STRING "Project patch version number.") + +mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH) + +# Create version info in autotools parlance for pio_meta.h. +set(PIO_VERSION_MAJOR ${VERSION_MAJOR}) +set(PIO_VERSION_MINOR ${VERSION_MINOR}) +set(PIO_VERSION_PATCH ${VERSION_PATCH}) + +# This is needed for the libpio.settings file. +SET(PACKAGE_VERSION ${PIO_VERSION_MAJOR}.${PIO_VERSION_MINOR}.${PIO_VERSION_PATCH}) + +# This provides cmake_print_variables() function for debugging. +include(CMakePrintHelpers) + +# Determine the configure date. +IF(DEFINED ENV{SOURCE_DATE_EPOCH}) + EXECUTE_PROCESS( + COMMAND "date" "-u" "-d" "@$ENV{SOURCE_DATE_EPOCH}" + OUTPUT_VARIABLE CONFIG_DATE + ) +ELSE() + EXECUTE_PROCESS( + COMMAND date + OUTPUT_VARIABLE CONFIG_DATE + ) +ENDIF() +IF(CONFIG_DATE) + string(STRIP ${CONFIG_DATE} CONFIG_DATE) +ENDIF() + +# A function used to create autotools-style 'yes/no' definitions. +# If a variable is set, it 'yes' is returned. Otherwise, 'no' is +# returned. +# +# Also creates a version of the ret_val prepended with 'NC', +# when feature is true, which is used to generate netcdf_meta.h. +FUNCTION(is_enabled feature ret_val) + IF(${feature}) + SET(${ret_val} "yes" PARENT_SCOPE) + SET("PIO_${ret_val}" 1 PARENT_SCOPE) + ELSE() + SET(${ret_val} "no" PARENT_SCOPE) + SET("PIO_${ret_val}" 0 PARENT_SCOPE) + ENDIF(${feature}) +ENDFUNCTION() + +# A function used to create autotools-style 'yes/no' definitions. +# If a variable is set, it 'yes' is returned. Otherwise, 'no' is +# returned. +# +# Also creates a version of the ret_val prepended with 'NC', +# when feature is true, which is used to generate netcdf_meta.h. +FUNCTION(is_disabled feature ret_val) + IF(${feature}) + SET(${ret_val} "no" PARENT_SCOPE) + ELSE() + SET(${ret_val} "yes" PARENT_SCOPE) + SET("PIO_${ret_val}" 1 PARENT_SCOPE) + ENDIF(${feature}) +ENDFUNCTION() + +# The size of the data buffer for write/read_darray(). +set(PIO_BUFFER_SIZE 134217728) + +#============================================================================== +# USER-DEFINED OPTIONS (set with "-DOPT=VAL" from command line) +#============================================================================== + +#===== Library Options ===== +option (PIO_ENABLE_FORTRAN "Enable the Fortran library builds" ON) +option (PIO_ENABLE_TIMING "Enable the use of the GPTL timing library" ON) +option (PIO_ENABLE_LOGGING "Enable debug logging (large output possible)" OFF) +option (PIO_ENABLE_DOC "Enable building PIO documentation" ON) +option (PIO_ENABLE_COVERAGE "Enable code coverage" OFF) +option (PIO_ENABLE_EXAMPLES "Enable PIO examples" ON) +option (PIO_ENABLE_NETCDF_INTEGRATION "Enable netCDF integration" OFF) +option (PIO_INTERNAL_DOC "Enable PIO developer documentation" OFF) +option (PIO_TEST_BIG_ENDIAN "Enable test to see if machine is big endian" ON) +option (PIO_USE_MPIIO "Enable support for MPI-IO auto detect" ON) +option (PIO_USE_MPISERIAL "Enable mpi-serial support (instead of MPI)" OFF) +option (PIO_USE_PNETCDF_VARD "Use pnetcdf put_vard " OFF) +option (WITH_PNETCDF "Require the use of PnetCDF" ON) +option (BUILD_SHARED_LIBS "Build shared libraries" OFF) + +if(APPLE) + # The linker on macOS does not include `common symbols` by default + # Passing the -c flag includes them and fixes an error with undefined symbols (err_buffer, resultlen) + set(CMAKE_C_ARCHIVE_FINISH " -c ") +endif() + +# Set a variable that appears in the config.h.in file. +if(PIO_USE_PNETCDF_VARD) + set(USE_VARD 1) +else() + set(USE_VARD 0) +endif() + +# Set a variable that appears in the config.h.in file. +if(PIO_ENABLE_LOGGING) + set(ENABLE_LOGGING 1) + set(HAS_LOGGING "yes") +else() + set(ENABLE_LOGGING 0) + set(HAS_LOGGING "no") +endif() + +# Set a variable that appears in the config.h.in file. +if(PIO_ENABLE_NETCDF_INTEGRATION) + set(NETCDF_INTEGRATION 1) +else() + set(NETCDF_INTEGRATION 0) +endif() + +if(PIO_USE_MPISERIAL) + set(USE_MPI_SERIAL 1) +else() + set(USE_MPI_SERIAL 0) +endif() + +#============================================================================== +# PREPEND TO CMAKE MODULE PATH +#============================================================================== + +#===== Local modules ===== +list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +#===== External modules ===== +if (PIO_ENABLE_FORTRAN) + enable_language(Fortran) + if (NOT DEFINED USER_CMAKE_MODULE_PATH) + message (STATUS "Importing CMake_Fortran_utils") + execute_process( + COMMAND git clone https://github.com/CESM-Development/CMake_Fortran_utils + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + OUTPUT_QUIET + ERROR_QUIET) + find_path (USER_CMAKE_MODULE_PATH + NAMES mpiexec.cmake + HINTS ${CMAKE_BINARY_DIR}/CMake_Fortran_utils) + if (USER_CMAKE_MODULE_PATH) + message (STATUS "Importing CMake_Fortran_utils - success") + else () + message (FATAL_ERROR "Failed to import CMake_Fortran_utils") + endif () + endif () + set (USER_CMAKE_MODULE_PATH ${USER_CMAKE_MODULE_PATH} + CACHE STRING "Location of the CMake_Fortran_utils") + list (APPEND CMAKE_MODULE_PATH ${USER_CMAKE_MODULE_PATH}) +endif () + +INCLUDE (CheckTypeSize) + +#===== MPI ===== +if (PIO_USE_MPISERIAL) + find_package (MPISERIAL COMPONENTS C REQUIRED) + if (MPISERIAL_C_FOUND) + set (CMAKE_REQUIRED_INCLUDES ${MPISERIAL_C_INCLUDE_DIRS}) + endif () +else () + find_package (MPI REQUIRED) + set (CMAKE_REQUIRED_INCLUDES ${MPI_INCLUDE_PATH}) +endif () + +#SET(CMAKE_EXTRA_INCLUDE_FILES "mpi.h") +#check_type_size("MPI_Offset" SIZEOF_MPI_OFFSET) +#SET(CMAKE_EXTRA_INCLUDE_FILES) + +#===== Library Variables ===== +set (PIO_FILESYSTEM_HINTS IGNORE CACHE STRING "Filesystem hints (lustre or gpfs)") + +#===== Testing Options ===== +option (PIO_ENABLE_TESTS "Enable the testing builds" ON) +option (PIO_VALGRIND_CHECK "Enable memory leak check using valgrind" OFF) + +#============================================================================== +# BACKWARDS COMPATIBILITY +#============================================================================== + +# Old NETCDF_DIR variable --> NetCDF_PATH +if (DEFINED NETCDF_DIR) + set (NetCDF_PATH ${NETCDF_DIR} + CACHE STRING "Location of the NetCDF library installation") +endif () + +# Old PNETCDF_DIR variable --> PnetCDF_PATH +if (DEFINED PNETCDF_DIR) + set (PnetCDF_PATH ${PNETCDF_DIR} + CACHE STRING "Location of the PnetCDF library installation") +endif () + +#============================================================================== +# HELPFUL GLOBAL VARIABLES +#============================================================================== + +# System Name +string (TOUPPER "${CMAKE_SYSTEM_NAME}" CMAKE_SYSTEM_NAME_CAPS) +set (CMAKE_SYSTEM_DIRECTIVE "${CMAKE_SYSTEM_NAME_CAPS}" + CACHE STRING "System name preprocessor directive") + +# C Compiler Name +string (TOUPPER "${CMAKE_C_COMPILER_ID}" CMAKE_C_COMPILER_NAME) +if (CMAKE_C_COMPILER_NAME STREQUAL "XL") + set (CMAKE_C_COMPILER_NAME "IBM") +endif () +set (CMAKE_C_COMPILER_DIRECTIVE "CPR${CMAKE_C_COMPILER_NAME}" + CACHE STRING "C compiler name preprocessor directive") + +# Fortran Compiler Name +if (PIO_ENABLE_FORTRAN) + string (TOUPPER "${CMAKE_Fortran_COMPILER_ID}" CMAKE_Fortran_COMPILER_NAME) + if (CMAKE_Fortran_COMPILER_NAME STREQUAL "XL") + set (CMAKE_Fortran_COMPILER_NAME "IBM") + endif () + set (CMAKE_Fortran_COMPILER_DIRECTIVE "CPR${CMAKE_Fortran_COMPILER_NAME}" + CACHE STRING "Fortran compiler name preprocessor directive") +endif() +#============================================================================== +# SET CODE COVERAGE COMPILER FLAGS +#============================================================================== + +# Only support GNU compilers at this time +if (PIO_ENABLE_COVERAGE) + if (CMAKE_C_COMPILER_NAME STREQUAL "GNU") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") + else () + message (WARNING "The C compiler is non-GNU: coverage of C code could NOT be enabled") + endif () + if (CMAKE_Fortran_COMPILER_NAME STREQUAL "GNU") + set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fprofile-arcs -ftest-coverage") + else () + message (WARNING "The Fortran compiler is non-GNU: coverage of Fortran code could NOT be enabled") + endif () +endif () + +# Allow argument mismatch in gfortran versions > 10 for mpi library compatibility +if (CMAKE_C_COMPILER_NAME STREQUAL "GNU") + if ("${CMAKE_Fortran_COMPILER_VERSION}" VERSION_LESS 10) + else() + set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") + endif() +endif() +# Include this so we can check values in netcdf_meta.h. +INCLUDE(CheckCSourceCompiles) +INCLUDE(FindNetCDF) +message("Fortran Library build is ${PIO_ENABLE_FORTRAN}") +if (PIO_ENABLE_FORTRAN) + find_package (NetCDF COMPONENTS C Fortran) + if (NOT NetCDF_Fortran_FOUND) + include(FindPkgConfig) + pkg_check_modules(NetCDF_Fortran REQUIRED IMPORTED_TARGET "netcdf-fortran") + endif() + if (WITH_PNETCDF) + find_package (PnetCDF COMPONENTS C Fortran) + endif() +else() + find_package (NetCDF REQUIRED COMPONENTS C) + if (WITH_PNETCDF) + find_package (PnetCDF COMPONENTS C) + endif() +endif() + +# Did we find pnetCDF? If so, set _PNETCDF in config.h. +if (PnetCDF_C_FOUND) + set(_PNETCDF 1) +endif () + +#============================================================================== +# INCLUDE SOURCE DIRECTORIES +#============================================================================== + +# Libraries +add_subdirectory (src) + +#============================================================================== +# TESTING TARGET +#============================================================================== + +# Custom "piotests" target (builds the test executables) +add_custom_target (tests) +if (PIO_ENABLE_FORTRAN) + add_dependencies (tests pioc piof) +else() + add_dependencies (tests pioc) +endif() + +# Custom "check" target that depends upon "tests" +add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND}) +add_dependencies (check tests) + +# Tests +if (PIO_ENABLE_TESTS) + enable_testing() + include (CTest) + add_subdirectory (tests) + if (PIO_ENABLE_EXAMPLES) + add_subdirectory (examples) + endif () +endif () + +# Documentation +if (PIO_ENABLE_DOC) + add_subdirectory (doc) +endif () + +SET(STATUS_PNETCDF ${PnetCDF_C_FOUND}) + +### +# Check to see if netcdf-4 capability is present in netcdf-c. +### +CHECK_C_SOURCE_COMPILES(" +#include +#if !NC_HAS_NC4 + choke me +#endif +int main() {return 0;}" HAVE_NETCDF4) + +### +# Check to see if netcdf-4 parallel I/O capability is present in +# netcdf-c. (Really we should be checking NC_HAS_PARALLEL4, but that +# was only recently introduced, so we will go with NC_HAS_PARALLEL.) +### +CHECK_C_SOURCE_COMPILES(" +#include +#if !NC_HAS_PARALLEL + choke me +#endif +int main() {return 0;}" HAVE_NETCDF_PAR) + +# Set this synonym for HAVE_NETCDF_PAR. It is defined in config.h. +if (HAVE_NETCDF_PAR) + set(_NETCDF4 1) +endif () + +### +# Check to see if szip write capability is present in netcdf-c. +### +SET(CMAKE_REQUIRED_INCLUDES ${NetCDF_C_INCLUDE_DIR}) +CHECK_C_SOURCE_COMPILES(" +#include +#if !NC_HAS_SZIP_WRITE + choke me +#endif +int main() {return 0;}" HAVE_SZIP_WRITE) + +### +# Check to see if parallel filters are supported by HDF5/netcdf-c. +### +CHECK_C_SOURCE_COMPILES(" +#include +#if !NC_HAS_PAR_FILTERS + choke me +#endif +int main() {return 0;}" HDF5_HAS_PAR_FILTERS) +if(HDF5_HAS_PAR_FILTERS) + set(HAVE_PAR_FILTERS 1) +else() + set(HAVE_PAR_FILTERS 0) +endif() + +### +# Check to see if this is netcdf-c-4.7.2, which won't work. +### +CHECK_C_SOURCE_COMPILES(" +#include +#if NC_VERSION_MAJOR == 4 && NC_VERSION_MINOR == 7 && NC_VERSION_PATCH == 2 +#else + choke me +#endif +int main() {return 0;}" HAVE_472) +if (HAVE_472) + message (FATAL_ERROR "PIO cannot build with netcdf-c-4.7.2, please upgrade your netCDF library") +endif () + +### +# Check to see if dispatch table version 2 is supported for netcdf integration. +### +CHECK_C_SOURCE_COMPILES(" +#include +#if NC_DISPATCH_VERSION != 2 + choke me +#endif +int main() {return 0;}" HAVE_DISPATCH2) + +if (NETCDF_INTEGRATION) + if (NOT HAVE_DISPATCH2) + message (FATAL_ERROR "Need newer version of netcdf-c for netcdf integration feature, please upgrade your netCDF library") + endif () + set(HAVE_NETCDF_INTEGRATION 1) +else () + set(HAVE_NETCDF_INTEGRATION 0) +endif () + +# Configure testing with MPIEXEC. +if (NOT WITH_MPIEXEC) + set(WITH_MPIEXEC mpiexec) +endif() +#set(MPIEXEC "${WITH_MPIEXEC}" CACHE INTERNAL "") +set(MPIEXEC "${WITH_MPIEXEC}") +set_property(GLOBAL PROPERTY WITH_MPIEXEC "${WITH_MPIEXEC}") + +##### +# Configure and print the libpio.settings file. +##### + +# Get system configuration, Use it to determine osname, os release, cpu. These +# will be used when committing to CDash. +find_program(UNAME NAMES uname) +IF(UNAME) + macro(getuname name flag) + exec_program("${UNAME}" ARGS "${flag}" OUTPUT_VARIABLE "${name}") + endmacro(getuname) + getuname(osname -s) + getuname(osrel -r) + getuname(cpu -m) + set(TMP_BUILDNAME "${osname}-${osrel}-${cpu}") +ENDIF() + +# Set +SET(prefix ${CMAKE_INSTALL_PREFIX}) +SET(exec_prefix ${CMAKE_INSTALL_PREFIX}) +SET(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) +SET(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) +SET(CC ${CMAKE_C_COMPILER}) + +# Set variables to mirror those used by autoconf. +# This way we don't need to maintain two separate template +# files. +SET(host_cpu "${cpu}") +SET(host_vendor "${osname}") +SET(host_os "${osrel}") +SET(abs_top_builddir "${CMAKE_CURRENT_BINARY_DIR}") +SET(abs_top_srcdir "${CMAKE_CURRENT_SOURCE_DIR}") + +SET(CC_VERSION "${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}") +SET(FC_VERSION "${CMAKE_Fortran_COMPILER_ID} ${CMAKE_Fortran_COMPILER_VERSION}") +# Build *FLAGS for libpio.settings. (CFLAGS, CPPFLAGS, FFLAGS promoted from src) +SET(LDFLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE}}") + +is_disabled(BUILD_SHARED_LIBS enable_static) +is_enabled(BUILD_SHARED_LIBS enable_shared) + +is_enabled(USE_SZIP HAS_SZIP_WRITE) +is_enabled(STATUS_PNETCDF HAS_PNETCDF) +is_enabled(HAVE_H5Z_SZIP HAS_SZLIB) +is_enabled(HDF5_HAS_PAR_FILTERS HAS_PAR_FILTERS) +is_enabled(HAVE_NETCDF4 HAS_NETCDF4) +is_enabled(HAVE_NETCDF_PAR HAS_NETCDF4_PAR) +is_enabled(HAVE_NETCDF_INTEGRATION HAS_NETCDF_INTEGRATION) +is_enabled(PIO_ENABLE_FORTRAN HAS_PIO_FORTRAN) + +# Generate file from template. +CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/libpio.settings.in" + "${CMAKE_CURRENT_BINARY_DIR}/libpio.settings" + @ONLY) + +# Read in settings file, print out. +# Avoid using system-specific calls so that this +# might also work on Windows. +FILE(READ "${CMAKE_CURRENT_BINARY_DIR}/libpio.settings" + LIBPIO_SETTINGS) +MESSAGE(STATUS ${LIBPIO_SETTINGS}) + +# Install libpio.settings file into same location +# as the libraries. +INSTALL(FILES "${PIO_BINARY_DIR}/libpio.settings" + DESTINATION lib + COMPONENT libraries) + +##### +# Create pio_meta.h include file. +##### +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/clib/pio_meta.h.in + ${CMAKE_CURRENT_BINARY_DIR}/src/clib/pio_meta.h @ONLY) + +# configure a header file to pass some of the CMake settings +# to the source code +configure_file ( + "${PROJECT_SOURCE_DIR}/cmake_config.h.in" + "${PROJECT_BINARY_DIR}/config.h" + ) diff --git a/ParallelIO/CTestConfig.cmake b/ParallelIO/CTestConfig.cmake new file mode 100644 index 0000000000..cd7099ae6b --- /dev/null +++ b/ParallelIO/CTestConfig.cmake @@ -0,0 +1,23 @@ +## This file should be placed in the root directory of your project. +## Then modify the CMakeLists.txt file in the root directory of your +## project to incorporate the testing dashboard. +## +## # The following are required to submit to the CDash dashboard: +## ENABLE_TESTING() +## INCLUDE(CTest) + +set (CTEST_PROJECT_NAME "PIO") +set (CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set (CTEST_DROP_METHOD "http") +if (DEFINED ENV{PIO_DASHBOARD_DROP_SITE}) + set (CTEST_DROP_SITE "$ENV{PIO_DASHBOARD_DROP_SITE}") +else () + set (CTEST_DROP_SITE "my.cdash.org") +endif () +if (DEFINED ENV{PIO_DASHBOARD_PROJECT_NAME}) + set (CTEST_DROP_LOCATION "/submit.php?project=$ENV{PIO_DASHBOARD_PROJECT_NAME}") +else () + set (CTEST_DROP_LOCATION "/submit.php?project=PIO") +endif () +set (CTEST_DROP_SITE_CDASH TRUE) diff --git a/ParallelIO/CTestScript.cmake b/ParallelIO/CTestScript.cmake new file mode 100644 index 0000000000..a8cd24d76c --- /dev/null +++ b/ParallelIO/CTestScript.cmake @@ -0,0 +1,195 @@ +#============================================================================== +# +# This is the CTest script for PIO builds and submission to the CTest +# Dashboard site: my.cdash.org. +# +# Example originally stolen from: +# http://www.vtk.org/Wiki/CTest:Using_CTEST_and_CDASH_without_CMAKE +#============================================================================== + +#--------------------------------------- +#-- User-defined setup from environment +#--------------------------------------- + +## -- CTest Dashboard Root Directory +if (DEFINED ENV{PIO_DASHBOARD_ROOT}) + set (CTEST_DASHBOARD_ROOT "$ENV{PIO_DASHBOARD_ROOT}") +else () + set (CTEST_DASHBOARD_ROOT "$ENV{HOME}/pio-dashboard") +endif () + +## -- Compiler ID +if (DEFINED ENV{PIO_COMPILER_ID}) + set (compid "$ENV{PIO_COMPILER_ID}") +else () + set (compid "?") +endif () + +## -- CTest Dashboard Build Group +set (CTEST_BUILD_GROUP "${CTEST_SCRIPT_ARG}") + +#--------------------------------------- +#-- Get the machine environment +#--------------------------------------- + +## -- Set hostname + +find_program (HOSTNAME_CMD NAMES hostname) +execute_process (COMMAND ${HOSTNAME_CMD} + OUTPUT_VARIABLE HOSTNAME + OUTPUT_STRIP_TRAILING_WHITESPACE) + +## -- Set hostname ID (e.g., alcf, nwsc, nersc, ...) +message ("hostname is ${HOSTNAME}") + +if (DEFINED HOSTNAME_ID) +else() +# UCAR/NWSC Machines +if (HOSTNAME MATCHES "^yslogin" OR + HOSTNAME MATCHES "^geyser" OR + HOSTNAME MATCHES "^caldera" OR + HOSTNAME MATCHES "^pronghorn") + set (HOSTNAME_ID "nwsc") +# New UCAR/NWSC SGI Machines +elseif (HOSTNAME MATCHES "^laramie" OR + HOSTNAME MATCHES "^chadmin" OR + HOSTNAME MATCHES "^cheyenne") + set (HOSTNAME_ID "nwscla") +# ALCF/Argonne Machines +elseif (HOSTNAME MATCHES "^mira" OR + HOSTNAME MATCHES "^cetus" OR + HOSTNAME MATCHES "^vesta" OR + HOSTNAME MATCHES "^cooley") + set (HOSTNAME_ID "alcf") +# NERSC Machines +elseif (HOSTNAME MATCHES "^edison" OR + HOSTNAME MATCHES "^cori" OR + HOSTNAME MATCHES "^nid") + set (HOSTNAME_ID "nersc") +# Blue Waters at NCSA +elseif (HOSTNAME MATCHES "^h2ologin" ) + set (HOSTNAME_ID "ncsa") +# CGD local linux cluster +elseif (HOSTNAME MATCHES "^hobart") + set (HOSTNAME_ID "cgd") +# Argonne Linux workstations +elseif (HOSTNAME MATCHES "^compute001" OR + HOSTNAME MATCHES "^thwomp" OR + HOSTNAME MATCHES "^stomp" OR + HOSTNAME MATCHES "^crush" OR + HOSTNAME MATCHES "^crank" OR + HOSTNAME MATCHES "^steamroller" OR + HOSTNAME MATCHES "^grind" OR + HOSTNAME MATCHES "^churn" OR + HOSTNAME MATCHES "^trounce" OR + HOSTNAME MATCHES "^thrash" OR + HOSTNAME MATCHES "^vanquish") + set (HOSTNAME_ID "anlworkstation") +else () + if (CMAKE_SYSTEM_NAME MATCHES "Catamount") + set (HOSTNAME_ID "ncsa") + else () + set (HOSTNAME_ID "unknown") + endif () +endif () +endif() +## -- Get system info + +find_program (UNAME NAMES uname) +function (getuname name flag) + execute_process (COMMAND ${UNAME} ${flag} + OUTPUT_VARIABLE res + OUTPUT_STRIP_TRAILING_WHITESPACE) + set (${name} ${res} PARENT_SCOPE) +endfunction () + +getuname (osname -s) +getuname (osrel -r) +getuname (cpu -m) + +## -- Git command +find_program (CTEST_GIT_COMMAND NAMES git) + +## -- make command +find_program (MAKE NAMES make) + +#----------------------------------------------------------- +#-- Generate build-specific information +#----------------------------------------------------------- + +## -- CTest Site Name + +set (CTEST_SITE "${HOSTNAME_ID}-${HOSTNAME}") + +## -- CTest Build Name + +set (CTEST_BUILD_NAME "${osname}-${osrel}-${cpu}-${compid}") + +## -- SRC Dir (where this script exists) +set (CTEST_SOURCE_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}") + +## -- BIN Dir +set (CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/build-${CTEST_BUILD_NAME}-${CTEST_BUILD_GROUP}") + +## -- Add the CTest script directory to the module path +set (CTEST_EXTRA_SCRIPT_PATH "${CTEST_SOURCE_DIRECTORY}/ctest") +list (APPEND CMAKE_MODULE_PATH ${CTEST_EXTRA_SCRIPT_PATH}) + +# ----------------------------------------------------------- +# -- Store Build-Specific Info (environment variables) +# ----------------------------------------------------------- + +set (ENV{PIO_DASHBOARD_SITE} ${CTEST_SITE}) +set (ENV{PIO_DASHBOARD_BUILD_NAME} ${CTEST_BUILD_NAME}) +set (ENV{PIO_DASHBOARD_SOURCE_DIR} ${CTEST_SOURCE_DIRECTORY}) +set (ENV{PIO_DASHBOARD_BINARY_DIR} ${CTEST_BINARY_DIRECTORY}) + +# ----------------------------------------------------------- +# -- Run CTest +# ----------------------------------------------------------- + +## -- Empty the binary directory +ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) + +## -- Start +message (" -- Hostname_id = ${HOSTNAME_ID}") +message (" -- Start dashboard - ${CTEST_BUILD_NAME} --") +ctest_start("${CTEST_SCRIPT_ARG}") + +## -- Update +message (" -- Update source - ${CTEST_BUILD_NAME} --") +set (CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}") +ctest_update () + +## -- Configure +message (" -- Configure build - ${CTEST_BUILD_NAME} -- with options ${CTEST_CONFIGURE_OPTIONS}") +include (CTestEnvironment-${HOSTNAME_ID}) +set (CTEST_CONFIGURE_COMMAND "${CMAKE_COMMAND} ${CTEST_CONFIGURE_OPTIONS} ${CTEST_SOURCE_DIRECTORY}") +ctest_configure () + +## -- BUILD +message (" -- Build - ${CTEST_BUILD_NAME} --") +set (CTEST_BUILD_COMMAND "${MAKE} tests") +ctest_build () + +## -- TEST +message (" -- Test - ${CTEST_BUILD_NAME} --") +execute_process (COMMAND ${CTEST_EXTRA_SCRIPT_PATH}/runctest-${HOSTNAME_ID}.sh + ${CTEST_EXTRA_SCRIPT_PATH} ${CTEST_SCRIPT_ARG} + WORKING_DIRECTORY ${CTEST_BINARY_DIRECTORY}) + +## -- SUBMIT +message (" -- Submit to dashboard - ${CTEST_BUILD_NAME} --") +message ("** -- PIO_DASHBOARD_SITE=$ENV{PIO_DASHBOARD_SITE}") +ctest_submit () + +# ----------------------------------------------------------- +# -- Clear environment +# ----------------------------------------------------------- + +unset (ENV{PIO_DASHBOARD_SITE}) +unset (ENV{PIO_DASHBOARD_BUILD_NAME}) +unset (ENV{PIO_DASHBOARD_SOURCE_DIR}) +unset (ENV{PIO_DASHBOARD_BINARY_DIR}) + +message (" -- Finished - ${CTEST_BUILD_NAME} --") diff --git a/ParallelIO/LICENSE b/ParallelIO/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/ParallelIO/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/ParallelIO/Makefile.am b/ParallelIO/Makefile.am new file mode 100644 index 0000000000..41d1265c1f --- /dev/null +++ b/ParallelIO/Makefile.am @@ -0,0 +1,18 @@ +# This is part of PIO. It creates the main Makefile. + +# Ed Hartnett + +# Look in the m4 directory for autotools stuff. +ACLOCAL_AMFLAGS= -I m4 + +# Does the user want to build doxygen documentation? +if BUILD_DOCS +DOC = doc +endif + +# Build in each of these subdirs. +SUBDIRS = src tests examples ${DOC} scripts cmake + +# Add these files to the distribution. +EXTRA_DIST = CMakeLists.txt LICENSE cmake_config.h.in \ +libpio.settings.in diff --git a/ParallelIO/README.md b/ParallelIO/README.md new file mode 100644 index 0000000000..3ecaaa6a05 --- /dev/null +++ b/ParallelIO/README.md @@ -0,0 +1,117 @@ +# ParallelIO + +The Parallel IO libraries (PIO) are high-level parallel I/O C and +Fortran libraries for applications that need to do netCDF I/O from +large numbers of processors on a HPC system. + +PIO provides a netCDF-like API, and allows users to designate some +subset of processors to perform IO. Computational code calls +netCDF-like functions to read and write data, and PIO uses the IO +processors to perform all necessary IO. + +## Intracomm Mode + +In Intracomm mode, PIO allows the user to designate some subset of +processors to do all I/O. The I/O processors also participate in +computational work. + +![I/O on Many Processors with Async + Mode](./doc/images/I_O_on_Many_Intracomm.png) + +## Async Mode + +PIO also supports the creation of multiple computation components, +each containing many processors, and one shared set of IO +processors. The computational components can perform write operation +asynchronously, and the IO processors will take care of all storage +interaction. + +![I/O on Many Processors with Async + Mode](./doc/images/I_O_on_Many_Async.png) + +## Website + +For complete documentation, see our website at +[http://ncar.github.io/ParallelIO/](http://ncar.github.io/ParallelIO/). + +## Mailing List + +The (low-traffic) PIO mailing list is at +https://groups.google.com/forum/#!forum/parallelio, send email to the +list at parallelio@googlegroups.com. + +## Testing + +The results of our continuous integration testing with GitHub actions +can be found on any of the Pull Requests on the GitHub site: +https://github.com/NCAR/ParallelIO. + +The results of our nightly tests on multiple platforms can be found on +our cdash site at +[http://my.cdash.org/index.php?project=PIO](http://my.cdash.org/index.php?project=PIO). + +## Dependencies + +PIO can use NetCDF (version 4.6.1+) and/or PnetCDF (version 1.9.0+) +for I/O. NetCDF may be built with or without netCDF-4 features. NetCDF +is required for PIO, PnetCDF is optional. + +The NetCDF C library must be built with MPI, which requires that it be +linked with an MPI-enabled version of HDF5. Optionally, NetCDF can be +built with DAP support, which introduces a dependency on CURL. HDF5, +itself, introduces dependencies on LIBZ and (optionally) SZIP. + +## Building PIO + +To build PIO, unpack the distribution tarball and do: + +``` +CC=mpicc FC=mpif90 ./configure --enable-fortran && make check install +``` + +For a full description of the available options and flags, try: +``` +./configure --help +``` + +Note that environment variables CC and FC may need to be set to the +MPI versions of the C and Fortran compiler. Also CPPFLAGS and LDFLAGS +may need to be set to indicate the locations of one or more of the +dependent libraries. (If using MPI compilers, the entire set of +dependent libraries should be built with the same compilers.) For +example: + +``` +export CC=mpicc +export FC=mpifort +export CPPFLAGS='-I/usr/local/netcdf-fortran-4.4.5_c_4.6.3_mpich-3.2/include -I/usr/local/netcdf-c-4.6.3_hdf5-1.10.5/include -I/usr/local/pnetcdf-1.11.0_shared/include' +export LDFLAGS='-L/usr/local/netcdf-c-4.6.3_hdf5-1.10.5/lib -L/usr/local/pnetcdf-1.11.0_shared/lib' +./configure --prefix=/usr/local/pio-2.4.2 --enable-fortran +make check +make install +``` + +## Building with CMake + +The typical configuration with CMake can be done as follows: + +``` +CC=mpicc FC=mpif90 cmake [-DOPTION1=value1 -DOPTION2=value2 ...] /path/to/pio/source +``` + +Full instructions for the cmake build can be found in the installation +documentation. + +# References + +Hartnett, E., Edwards, J., "THE PARALLELIO (PIO) C/FORTRAN LIBRARIES +FOR SCALABLE HPC PERFORMANCE", 37th Conference on Environmental +Information Processing Technologies, American Meteorological Society +Annual Meeting, January, 2021. Retrieved on Feb 3, 2021, from +[https://www.researchgate.net/publication/348169990_THE_PARALLELIO_PIO_CFORTRAN_LIBRARIES_FOR_SCALABLE_HPC_PERFORMANCE]. + +Hartnett, E., Edwards, J., "POSTER: THE PARALLELIO (PIO) C/FORTRAN LIBRARIES +FOR SCALABLE HPC PERFORMANCE", 37th Conference on Environmental +Information Processing Technologies, American Meteorological Society +Annual Meeting, January, 2021. Retrieved on Feb 3, 2021, from +[https://www.researchgate.net/publication/348170136_THE_PARALLELIO_PIO_CFORTRAN_LIBRARIES_FOR_SCALABLE_HPC_PERFORMANCE]. diff --git a/ParallelIO/cmake/FindGPTL.cmake b/ParallelIO/cmake/FindGPTL.cmake new file mode 100644 index 0000000000..c223c1b346 --- /dev/null +++ b/ParallelIO/cmake/FindGPTL.cmake @@ -0,0 +1,72 @@ +# - Try to find GPTL +# +# This can be controlled by setting the GPTL_DIR (or, equivalently, the +# GPTL environment variable), or GPTL__DIR CMake variables, where +# is the COMPONENT language one needs. +# +# Once done, this will define: +# +# GPTL__FOUND (BOOL) - system has GPTL +# GPTL__IS_SHARED (BOOL) - whether library is shared/dynamic +# GPTL__INCLUDE_DIR (PATH) - Location of the C header file +# GPTL__INCLUDE_DIRS (LIST) - the GPTL include directories +# GPTL__LIBRARY (FILE) - Path to the C library file +# GPTL__LIBRARIES (LIST) - link these to use GPTL +# +# The available COMPONENTS are: C Fortran Perfmod +# If no components are specified, it assumes only C +include (LibFind) + +# Define GPTL C Component +define_package_component (GPTL DEFAULT + COMPONENT C + INCLUDE_NAMES gptl.h + LIBRARY_NAMES gptl) + +# Define GPTL Fortran Component +define_package_component (GPTL + COMPONENT Fortran + INCLUDE_NAMES gptl.mod + LIBRARY_NAMES gptl) + +# Define GPTL Fortran_Perf Component +define_package_component (GPTL + COMPONENT Fortran_Perf + INCLUDE_NAMES perf_mod.mod + LIBRARY_NAMES gptl) + +# Search for list of valid components requested +find_valid_components (GPTL) + +#============================================================================== +# SEARCH FOR VALIDATED COMPONENTS +foreach (GPTL_comp IN LISTS GPTL_FIND_VALID_COMPONENTS) + + # If not found already, search... + if (NOT GPTL_${GPTL_comp}_FOUND) + + # Manually add the MPI include and library dirs to search paths + if (GPTL_comp STREQUAL C AND MPI_C_FOUND) + set (mpiincs ${MPI_C_INCLUDE_PATH}) + set (mpilibs ${MPI_C_LIBRARIES}) + set (mpifound ${MPI_C_FOUND}) + elseif (MPI_Fortran_FOUND) + set (mpiincs ${MPI_Fortran_INCLUDE_PATH}) + set (mpilibs ${MPI_Fortran_LIBRARIES}) + set (mpifound ${MPI_Fortran_FOUND}) + endif () + + # Search for the package component + if (mpifound) + initialize_paths (GPTL_${GPTL_comp}_PATHS + INCLUDE_DIRECTORIES ${mpiincs} + LIBRARIES ${mpilibs}) + find_package_component(GPTL COMPONENT ${GPTL_comp} + PATHS ${GPTL_${GPTL_comp}_PATHS}) + else () + find_package_component(GPTL COMPONENT ${GPTL_comp}) + endif () + + endif () + +endforeach () diff --git a/ParallelIO/cmake/FindHDF5.cmake b/ParallelIO/cmake/FindHDF5.cmake new file mode 100644 index 0000000000..e918277b1a --- /dev/null +++ b/ParallelIO/cmake/FindHDF5.cmake @@ -0,0 +1,118 @@ +# - Try to find HDF5 +# +# This can be controlled by setting the HDF5_DIR (or, equivalently, the +# HDF5 environment variable), or HDF5__DIR CMake variables, where +# is the COMPONENT language one needs. +# +# Once done, this will define: +# +# HDF5__FOUND (BOOL) - system has HDF5 +# HDF5__IS_SHARED (BOOL) - whether library is shared/dynamic +# HDF5__INCLUDE_DIR (PATH) - Location of the C header file +# HDF5__INCLUDE_DIRS (LIST) - the HDF5 include directories +# HDF5__LIBRARY (FILE) - Path to the C library file +# HDF5__LIBRARIES (LIST) - link these to use HDF5 +# +# The available COMPONENTS are: C HL Fortran Fortran_HL +# If no components are specified, it assumes only C +include (LibFind) + +# Define HDF5 C Component +define_package_component (HDF5 DEFAULT + COMPONENT C + INCLUDE_NAMES hdf5.h + LIBRARY_NAMES hdf5) + +# Define HDF5 HL Component +define_package_component (HDF5 + COMPONENT HL + INCLUDE_NAMES hdf5_hl.h + LIBRARY_NAMES hdf5_hl) + +# Define HDF5 Fortran Component +define_package_component (HDF5 + COMPONENT Fortran + INCLUDE_NAMES hdf5.mod + LIBRARY_NAMES hdf5_fortran) + +# Define HDF5 Fortran_HL Component +define_package_component (HDF5 + COMPONENT Fortran_HL + INCLUDE_NAMES hdf5.mod + LIBRARY_NAMES hdf5hl_fortran) + +# Search for list of valid components requested +find_valid_components (HDF5) + +#============================================================================== +# SEARCH FOR VALIDATED COMPONENTS +foreach (HDF5_comp IN LISTS HDF5_FIND_VALID_COMPONENTS) + + # If not found already, search... + if (NOT HDF5_${HDF5_comp}_FOUND) + + # Manually add the MPI include and library dirs to search paths + if ( (HDF5_comp STREQUAL C OR HDF5_comp STREQUAL HL) AND MPI_C_FOUND) + set (mpiincs ${MPI_C_INCLUDE_PATH}) + set (mpilibs ${MPI_C_LIBRARIES}) + set (mpifound ${MPI_C_FOUND}) + elseif (MPI_Fortran_FOUND) + set (mpiincs ${MPI_Fortran_INCLUDE_PATH}) + set (mpilibs ${MPI_Fortran_LIBRARIES}) + set (mpifound ${MPI_Fortran_FOUND}) + endif () + + # Search for the package component + if (mpifound) + initialize_paths (HDF5_${HDF5_comp}_PATHS + INCLUDE_DIRECTORIES ${mpiincs} + LIBRARIES ${mpilibs}) + find_package_component(HDF5 COMPONENT ${HDF5_comp} + PATHS ${HDF5_${HDF5_comp}_PATHS}) + else () + find_package_component(HDF5 COMPONENT ${HDF5_comp}) + endif () + + # Continue only if found + if (HDF5_${HDF5_comp}_FOUND) + + # Dependencies + if (HDF5_comp STREQUAL C AND NOT HDF5_C_IS_SHARED) + + # DEPENDENCY: LIBZ + find_package (LIBZ) + if (LIBZ_FOUND) + list (APPEND HDF5_C_INCLUDE_DIRS ${LIBZ_INCLUDE_DIRS}) + list (APPEND HDF5_C_LIBRARIES ${LIBZ_LIBRARIES}) + endif () + + # DEPENDENCY: SZIP (Optional) + check_macro (HDF5_C_HAS_SZIP + NAME TryHDF5_HAS_SZIP.c + HINTS ${CMAKE_MODULE_PATH} + DEFINITIONS -I${HDF5_C_INCLUDE_DIRS} + COMMENT "whether HDF5 has SZIP support") + if (HDF5_C_HAS_SZIP) + find_package (SZIP) + if (SZIP_FOUND) + list (APPEND HDF5_C_INCLUDE_DIRS ${SZIP_INCLUDE_DIRS}) + list (APPEND HDF5_C_LIBRARIES ${SZIP_LIBRARIES}) + endif () + endif () + + elseif (NOT HDF5_${HDF5_comp}_IS_SHARED) + + # DEPENDENCY: HDF5 + find_package (HDF5 COMPONENTS C) + if (HDF5_C_FOUND) + list (APPEND HDF5_${HDF5_comp}_INCLUDE_DIRS ${HDF5_C_INCLUDE_DIRS}) + list (APPEND HDF5_${HDF5_comp}_LIBRARIES ${HDF5_C_LIBRARIES}) + endif () + + endif () + + endif () + + endif () + +endforeach () diff --git a/ParallelIO/cmake/FindLIBRT.cmake b/ParallelIO/cmake/FindLIBRT.cmake new file mode 100644 index 0000000000..1f55f9f3f1 --- /dev/null +++ b/ParallelIO/cmake/FindLIBRT.cmake @@ -0,0 +1,28 @@ +# - Try to find LIBRT +# +# This can be controlled by setting the LIBRT_DIR (or, equivalently, the +# LIBRT environment variable). +# +# Once done, this will define: +# +# LIBRT_FOUND (BOOL) - system has LIBRT +# LIBRT_IS_SHARED (BOOL) - whether library is shared/dynamic +# LIBRT_INCLUDE_DIR (PATH) - Location of the C header file +# LIBRT_INCLUDE_DIRS (LIST) - the LIBRT include directories +# LIBRT_LIBRARY (FILE) - Path to the C library file +# LIBRT_LIBRARIES (LIST) - link these to use LIBRT +# +include (LibFind) + +# Define LIBRT package +define_package_component (LIBRT + INCLUDE_NAMES time.h + LIBRARY_NAMES rt) + +# SEARCH FOR PACKAGE +if (NOT LIBRT_FOUND) + + # Search for the package + find_package_component(LIBRT) + +endif () diff --git a/ParallelIO/cmake/FindLIBZ.cmake b/ParallelIO/cmake/FindLIBZ.cmake new file mode 100644 index 0000000000..8ebbaefeed --- /dev/null +++ b/ParallelIO/cmake/FindLIBZ.cmake @@ -0,0 +1,37 @@ +# - Try to find LIBZ +# +# This can be controlled by setting the LIBZ_DIR (or, equivalently, the +# LIBZ environment variable). +# +# Once done, this will define: +# +# LIBZ_FOUND (BOOL) - system has LIBZ +# LIBZ_IS_SHARED (BOOL) - whether library is shared/dynamic +# LIBZ_INCLUDE_DIR (PATH) - Location of the C header file +# LIBZ_INCLUDE_DIRS (LIST) - the LIBZ include directories +# LIBZ_LIBRARY (FILE) - Path to the C library file +# LIBZ_LIBRARIES (LIST) - link these to use LIBZ +# +include (LibFind) + +# Define LIBZ package +define_package_component (LIBZ + INCLUDE_NAMES zlib.h + LIBRARY_NAMES z) + +# SEARCH FOR PACKAGE +if (NOT LIBZ_FOUND) + + # Manually add the MPI include and library dirs to search paths + # and search for the package component + if (MPI_C_FOUND) + initialize_paths (LIBZ_PATHS + INCLUDE_DIRECTORIES ${MPI_C_INCLUDE_PATH} + LIBRARIES ${MPI_C_LIBRARIES}) + find_package_component(LIBZ + PATHS ${LIBZ_PATHS}) + else () + find_package_component(LIBZ) + endif () + +endif () diff --git a/ParallelIO/cmake/FindMPE.cmake b/ParallelIO/cmake/FindMPE.cmake new file mode 100644 index 0000000000..5a964172da --- /dev/null +++ b/ParallelIO/cmake/FindMPE.cmake @@ -0,0 +1,50 @@ +# - Try to find MPE +# +# This can be controlled by setting the MPE_PATH (or, equivalently, +# the MPE environment variable), or MPE__PATH CMake variables, +# where is the COMPONENT language one needs. +# +# Once done, this will define: +# +# MPE__FOUND (BOOL) - system has MPE +# MPE__IS_SHARED (BOOL) - whether library is shared/dynamic +# MPE__INCLUDE_DIR (PATH) - Location of the C header file +# MPE__INCLUDE_DIRS (LIST) - the MPE include directories +# MPE__LIBRARY (FILE) - Path to the C library file +# MPE__LIBRARIES (LIST) - link these to use MPE +# +# The available COMPONENTS are: C +include (LibFind) +include (LibCheck) + +# Define MPE C Component +define_package_component (MPE DEFAULT + COMPONENT C + INCLUDE_NAMES mpe.h + LIBRARY_NAMES mpe) + +# Search for list of valid components requested +find_valid_components (MPE) + +#============================================================================== +# SEARCH FOR VALIDATED COMPONENTS +foreach (NCDFcomp IN LISTS MPE_FIND_VALID_COMPONENTS) + + # If not found already, search... + if (NOT MPE_${NCDFcomp}_FOUND) + + # Manually add the MPI include and library dirs to search paths + # and search for the package component + if (MPI_${NCDFcomp}_FOUND) + initialize_paths (MPE_${NCDFcomp}_PATHS + INCLUDE_DIRECTORIES ${MPI_${NCDFcomp}_INCLUDE_PATH} + LIBRARIES ${MPI_${NCDFcomp}_LIBRARIES}) + find_package_component(MPE COMPONENT ${NCDFcomp} + PATHS ${MPE_${NCDFcomp}_PATHS}) + else () + find_package_component(MPE COMPONENT ${NCDFcomp}) + endif () + + endif () + +endforeach () diff --git a/ParallelIO/cmake/FindMPISERIAL.cmake b/ParallelIO/cmake/FindMPISERIAL.cmake new file mode 100644 index 0000000000..09906eb7a2 --- /dev/null +++ b/ParallelIO/cmake/FindMPISERIAL.cmake @@ -0,0 +1,44 @@ +# - Try to find MPISERIAL +# +# This can be controlled by setting the MPISERIAL_PATH (or, equivalently, the +# MPISERIAL environment variable). +# +# Once done, this will define: +# +# MPISERIAL_FOUND (BOOL) - system has MPISERIAL +# MPISERIAL_IS_SHARED (BOOL) - whether library is shared/dynamic +# MPISERIAL_INCLUDE_DIR (PATH) - Location of the C header file +# MPISERIAL_INCLUDE_DIRS (LIST) - the MPISERIAL include directories +# MPISERIAL_LIBRARY (FILE) - Path to the C library file +# MPISERIAL_LIBRARIES (LIST) - link these to use MPISERIAL +# +include (LibFind) + +# Define MPISERIAL C component +define_package_component (MPISERIAL DEFAULT + COMPONENT C + INCLUDE_NAMES mpi.h + LIBRARY_NAMES mpi-serial) + +# Define MPISERIAL Fortran component +define_package_component (MPISERIAL + COMPONENT Fortran + INCLUDE_NAMES mpi.mod mpif.h + LIBRARY_NAMES mpi-serial) + +# Search for list of valid components requested +find_valid_components (MPISERIAL) + +#============================================================================== +# SEARCH FOR VALIDATED COMPONENTS +foreach (MPISERIAL_comp IN LISTS MPISERIAL_FIND_VALID_COMPONENTS) + + # If not found already, search... + if (NOT MPISERIAL_${MPISERIAL_comp}_FOUND) + + # Search for the package + find_package_component(MPISERIAL COMPONENT ${MPISERIAL_comp}) + + endif () + +endforeach () diff --git a/ParallelIO/cmake/FindNetCDF.cmake b/ParallelIO/cmake/FindNetCDF.cmake new file mode 100644 index 0000000000..344714b18a --- /dev/null +++ b/ParallelIO/cmake/FindNetCDF.cmake @@ -0,0 +1,143 @@ +# - Try to find NetCDF +# +# This can be controlled by setting the NetCDF_PATH (or, equivalently, the +# NETCDF environment variable), or NetCDF__PATH CMake variables, where +# is the COMPONENT language one needs. +# +# Once done, this will define: +# +# NetCDF__FOUND (BOOL) - system has NetCDF +# NetCDF__IS_SHARED (BOOL) - whether library is shared/dynamic +# NetCDF__INCLUDE_DIR (PATH) - Location of the C header file +# NetCDF__INCLUDE_DIRS (LIST) - the NetCDF include directories +# NetCDF__LIBRARY (FILE) - Path to the C library file +# NetCDF__LIBRARIES (LIST) - link these to use NetCDF +# +# The available COMPONENTS are: C Fortran +# If no components are specified, it assumes only C +include (LibFind) +include (LibCheck) + +# Define NetCDF C Component +define_package_component (NetCDF DEFAULT + COMPONENT C + INCLUDE_NAMES netcdf.h + LIBRARY_NAMES netcdf) + +# Define NetCDF Fortran Component +define_package_component (NetCDF + COMPONENT Fortran + INCLUDE_NAMES netcdf.mod netcdf.inc + LIBRARY_NAMES netcdff) + +# Search for list of valid components requested +find_valid_components (NetCDF) + +#============================================================================== +# SEARCH FOR VALIDATED COMPONENTS +foreach (NCDFcomp IN LISTS NetCDF_FIND_VALID_COMPONENTS) + + # If not found already, search... + if (NOT NetCDF_${NCDFcomp}_FOUND) + + # Manually add the MPI include and library dirs to search paths + # and search for the package component + if (MPI_${NCDFcomp}_FOUND) + initialize_paths (NetCDF_${NCDFcomp}_PATHS + INCLUDE_DIRECTORIES ${MPI_${NCDFcomp}_INCLUDE_PATH} + LIBRARIES ${MPI_${NCDFcomp}_LIBRARIES}) + find_package_component(NetCDF COMPONENT ${NCDFcomp} + PATHS ${NetCDF_${NCDFcomp}_PATHS}) + else () + find_package_component(NetCDF COMPONENT ${NCDFcomp}) + endif () + + # Continue only if component found + if (NetCDF_${NCDFcomp}_FOUND) + + # Checks + if (NCDFcomp STREQUAL C) + + # Check version + check_version (NetCDF + NAME "netcdf_meta.h" + HINTS ${NetCDF_C_INCLUDE_DIRS} + MACRO_REGEX "NC_VERSION_") + + # Check for parallel support + check_macro (NetCDF_C_HAS_PARALLEL + NAME TryNetCDF_PARALLEL.c + HINTS ${CMAKE_MODULE_PATH} + DEFINITIONS -I${NetCDF_C_INCLUDE_DIR} + COMMENT "whether NetCDF has parallel support") + + # Check if logging enabled + set(CMAKE_REQUIRED_INCLUDES ${NetCDF_C_INCLUDE_DIR}) + set(CMAKE_REQUIRED_LIBRARIES ${NetCDF_C_LIBRARIES}) + CHECK_FUNCTION_EXISTS(nc_set_log_level NetCDF_C_LOGGING_ENABLED) + + endif () + + # Dependencies + if (NCDFcomp STREQUAL C AND NOT NetCDF_C_IS_SHARED) + + # DEPENDENCY: PnetCDF (if PnetCDF enabled) + check_macro (NetCDF_C_HAS_PNETCDF + NAME TryNetCDF_PNETCDF.c + HINTS ${CMAKE_MODULE_PATH} + DEFINITIONS -I${NetCDF_C_INCLUDE_DIR} + COMMENT "whether NetCDF has PnetCDF support") + if (NetCDF_C_HAS_PNETCDF) + find_package (PnetCDF COMPONENTS C) + if (CURL_FOUND) + list (APPEND NetCDF_C_INCLUDE_DIRS ${PnetCDF_C_INCLUDE_DIRS}) + list (APPEND NetCDF_C_LIBRARIES ${PnetCDF_C_LIBRARIES}) + endif () + endif () + + # DEPENDENCY: CURL (If DAP enabled) + check_macro (NetCDF_C_HAS_DAP + NAME TryNetCDF_DAP.c + HINTS ${CMAKE_MODULE_PATH} + DEFINITIONS -I${NetCDF_C_INCLUDE_DIR} + COMMENT "whether NetCDF has DAP support") + if (NetCDF_C_HAS_DAP) + find_package (CURL) + if (CURL_FOUND) + list (APPEND NetCDF_C_INCLUDE_DIRS ${CURL_INCLUDE_DIRS}) + list (APPEND NetCDF_C_LIBRARIES ${CURL_LIBRARIES}) + endif () + endif () + + # DEPENDENCY: HDF5 + find_package (HDF5 COMPONENTS HL C) + if (HDF5_C_FOUND) + list (APPEND NetCDF_C_INCLUDE_DIRS ${HDF5_C_INCLUDE_DIRS} + ${HDF5_HL_INCLUDE_DIRS}) + list (APPEND NetCDF_C_LIBRARIES ${HDF5_C_LIBRARIES} + ${HDF5_HL_LIBRARIES}) + endif () + + # DEPENDENCY: LIBDL Math + list (APPEND NetCDF_C_LIBRARIES -ldl -lm) + + elseif (NCDFcomp STREQUAL Fortran AND NOT NetCDF_Fortran_IS_SHARED) + + # DEPENDENCY: NetCDF + set (orig_comp ${NCDFcomp}) + set (orig_comps ${NetCDF_FIND_VALID_COMPONENTS}) + find_package (NetCDF COMPONENTS C) + set (NetCDF_FIND_VALID_COMPONENTS ${orig_comps}) + set (NCDFcomp ${orig_comp}) + if (NetCDF_C_FOUND) + list (APPEND NetCDF_Fortran_INCLUDE_DIRS ${NetCDF_C_INCLUDE_DIRS}) + list (APPEND NetCDF_Fortran_LIBRARIES ${NetCDF_C_LIBRARIES}) + endif () + + endif () + + endif () + + endif () + +endforeach () diff --git a/ParallelIO/cmake/FindPAPI.cmake b/ParallelIO/cmake/FindPAPI.cmake new file mode 100644 index 0000000000..dcf1445bc7 --- /dev/null +++ b/ParallelIO/cmake/FindPAPI.cmake @@ -0,0 +1,28 @@ +# - Try to find PAPI +# +# This can be controlled by setting the PAPI_DIR (or, equivalently, the +# PAPI environment variable). +# +# Once done, this will define: +# +# PAPI_FOUND (BOOL) - system has PAPI +# PAPI_IS_SHARED (BOOL) - whether library is shared/dynamic +# PAPI_INCLUDE_DIR (PATH) - Location of the C header file +# PAPI_INCLUDE_DIRS (LIST) - the PAPI include directories +# PAPI_LIBRARY (FILE) - Path to the C library file +# PAPI_LIBRARIES (LIST) - link these to use PAPI +# +include (LibFind) + +# Define PAPI package +define_package_component (PAPI + INCLUDE_NAMES papi.h + LIBRARY_NAMES papi) + +# SEARCH FOR PACKAGE +if (NOT PAPI_FOUND) + + # Search for the package + find_package_component(PAPI) + +endif () diff --git a/ParallelIO/cmake/FindPnetCDF.cmake b/ParallelIO/cmake/FindPnetCDF.cmake new file mode 100644 index 0000000000..b87d245cd1 --- /dev/null +++ b/ParallelIO/cmake/FindPnetCDF.cmake @@ -0,0 +1,68 @@ +# - Try to find PnetCDF +# +# This can be controlled by setting the PnetCDF_PATH (or, equivalently, the +# PNETCDF environment variable), or PnetCDF__PATH CMake variables, where +# is the COMPONENT language one needs. +# +# Once done, this will define: +# +# PnetCDF__FOUND (BOOL) - system has PnetCDF +# PnetCDF__IS_SHARED (BOOL) - whether library is shared/dynamic +# PnetCDF__INCLUDE_DIR (PATH) - Location of the C header file +# PnetCDF__INCLUDE_DIRS (LIST) - the PnetCDF include directories +# PnetCDF__LIBRARY (FILE) - Path to the C library file +# PnetCDF__LIBRARIES (LIST) - link these to use PnetCDF +# +# The available COMPONENTS are: C, Fortran +# If no components are specified, it assumes only C +include (LibFind) +include (LibCheck) + +# Define PnetCDF C Component +define_package_component (PnetCDF DEFAULT + COMPONENT C + INCLUDE_NAMES pnetcdf.h + LIBRARY_NAMES pnetcdf) + +# Define PnetCDF Fortran Component +define_package_component (PnetCDF + COMPONENT Fortran + INCLUDE_NAMES pnetcdf.mod pnetcdf.inc + LIBRARY_NAMES pnetcdf) + +# Search for list of valid components requested +find_valid_components (PnetCDF) + +#============================================================================== +# SEARCH FOR VALIDATED COMPONENTS +foreach (PNCDFcomp IN LISTS PnetCDF_FIND_VALID_COMPONENTS) + + # If not found already, search... + if (NOT PnetCDF_${PNCDFcomp}_FOUND) + + # Manually add the MPI include and library dirs to search paths + # and search for the package component + if (MPI_${PNCDFcomp}_FOUND) + initialize_paths (PnetCDF_${PNCDFcomp}_PATHS + INCLUDE_DIRECTORIES ${MPI_${PNCDFcomp}_INCLUDE_PATH} + LIBRARIES ${MPI_${PNCDFcomp}_LIBRARIES}) + find_package_component(PnetCDF COMPONENT ${PNCDFcomp} + PATHS ${PnetCDF_${PNCDFcomp}_PATHS}) + else () + find_package_component(PnetCDF COMPONENT ${PNCDFcomp}) + endif () + + # Continue only if component found + if (PnetCDF_${PNCDFcomp}_FOUND) + + # Check version + check_version (PnetCDF + NAME "pnetcdf.h" + HINTS ${PnetCDF_${PNCDFcomp}_INCLUDE_DIR} + MACRO_REGEX "PNETCDF_VERSION_") + + endif () + + endif () + +endforeach () diff --git a/ParallelIO/cmake/FindSZIP.cmake b/ParallelIO/cmake/FindSZIP.cmake new file mode 100644 index 0000000000..e65cfe5fd6 --- /dev/null +++ b/ParallelIO/cmake/FindSZIP.cmake @@ -0,0 +1,37 @@ +# - Try to find SZIP +# +# This can be controlled by setting the SZIP_DIR (or, equivalently, the +# SZIP environment variable). +# +# Once done, this will define: +# +# SZIP_FOUND (BOOL) - system has SZIP +# SZIP_IS_SHARED (BOOL) - whether library is shared/dynamic +# SZIP_INCLUDE_DIR (PATH) - Location of the C header file +# SZIP_INCLUDE_DIRS (LIST) - the SZIP include directories +# SZIP_LIBRARY (FILE) - Path to the C library file +# SZIP_LIBRARIES (LIST) - link these to use SZIP +# +include (LibFind) + +# Define SZIP package +define_package_component (SZIP + INCLUDE_NAMES szlib.h + LIBRARY_NAMES sz) + +# SEARCH FOR PACKAGE +if (NOT SZIP_FOUND) + + # Manually add the MPI include and library dirs to search paths + # and search for the package component + if (MPI_C_FOUND) + initialize_paths (SZIP_PATHS + INCLUDE_DIRECTORIES ${MPI_C_INCLUDE_PATH} + LIBRARIES ${MPI_C_LIBRARIES}) + find_package_component(SZIP + PATHS ${SZIP_PATHS}) + else () + find_package_component(SZIP) + endif () + +endif () diff --git a/ParallelIO/cmake/LibCheck.cmake b/ParallelIO/cmake/LibCheck.cmake new file mode 100644 index 0000000000..3f12bdf796 --- /dev/null +++ b/ParallelIO/cmake/LibCheck.cmake @@ -0,0 +1,104 @@ +include (CMakeParseArguments) +include (CheckFunctionExists) +#============================================================================== +# +# FUNCTIONS TO HELP WITH Check* MODULES +# +#============================================================================== + +#______________________________________________________________________________ +# - Basic function to check a property of a package using a try_compile step +# +# SYNTAX: check_macro ( +# NAME +# HINTS ... +# DEFINITIONS ... +# COMMENT ) +# +function (check_macro VARIABLE) + + # Parse the input arguments + set (oneValueArgs COMMENT NAME) + set (multiValueArgs HINTS DEFINITIONS) + cmake_parse_arguments (${VARIABLE} "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # If the return variable is defined, already, don't continue + if (NOT DEFINED ${VARIABLE}) + + message (STATUS "Checking ${${VARIABLE}_COMMENT}") + find_file (${VARIABLE}_TRY_FILE + NAMES ${${VARIABLE}_NAME} + HINTS ${${VARIABLE}_HINTS}) + if (${VARIABLE}_TRY_FILE) + try_compile (COMPILE_RESULT + ${CMAKE_CURRENT_BINARY_DIR}/try${VARIABLE} + SOURCES ${${VARIABLE}_TRY_FILE} + COMPILE_DEFINITIONS ${${VARIABLE}_DEFINITIONS} + OUTPUT_VARIABLE TryOUT) + if (COMPILE_RESULT) + message (STATUS "Checking ${${VARIABLE}_COMMENT} - yes") + else () + message (STATUS "Checking ${${VARIABLE}_COMMENT} - no") + endif () + + set (${VARIABLE} ${COMPILE_RESULT} + CACHE BOOL "${${VARIABLE}_COMMENT}") + + else () + message (STATUS "Checking ${${VARIABLE}_COMMENT} - failed") + endif () + + unset (${VARIABLE}_TRY_FILE CACHE) + endif () + +endfunction () + +#______________________________________________________________________________ +# - Basic function to check the version of a package using a try_run step +# +# SYNTAX: check_version ( +# NAME +# HINTS ... +# DEFINITIONS ...) +# +function (check_version PKG) + + # Parse the input arguments + set (oneValueArgs NAME MACRO_REGEX) + set (multiValueArgs HINTS) + cmake_parse_arguments (${PKG} "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # If the return variable is defined, already, don't continue + if (NOT DEFINED ${PKG}_VERSION) + + message (STATUS "Checking ${PKG} version") + find_file (${PKG}_VERSION_HEADER + NAMES ${${PKG}_NAME} + HINTS ${${PKG}_HINTS}) + if (${PKG}_VERSION_HEADER) + set (def) + file (STRINGS ${${PKG}_VERSION_HEADER} deflines + REGEX "^#define[ \\t]+${${PKG}_MACRO_REGEX}") + foreach (defline IN LISTS deflines) + string (REPLACE "\"" "" defline "${defline}") + string (REPLACE "." "" defline "${defline}") + string (REGEX REPLACE "[ \\t]+" ";" deflist "${defline}") + list (GET deflist 2 arg) + list (APPEND def ${arg}) + endforeach () + string (REPLACE ";" "." vers "${def}") + message (STATUS "Checking ${PKG} version - ${vers}") + set (${PKG}_VERSION ${vers} + CACHE STRING "${PKG} version string") + if (${PKG}_VERSION VERSION_LESS ${PKG}_FIND_VERSION}) + message (FATAL_ERROR "${PKG} version insufficient") + endif () + else () + message (STATUS "Checking ${PKG} version - failed") + endif () + + unset (${PKG}_VERSION_HEADER CACHE) + + endif () + +endfunction () \ No newline at end of file diff --git a/ParallelIO/cmake/LibFind.cmake b/ParallelIO/cmake/LibFind.cmake new file mode 100644 index 0000000000..61cd93aa37 --- /dev/null +++ b/ParallelIO/cmake/LibFind.cmake @@ -0,0 +1,333 @@ +include (CMakeParseArguments) +include(FindPackageHandleStandardArgs) + +#============================================================================== +# +# FUNCTIONS TO HELP WITH Find* MODULES +# +#============================================================================== + +#______________________________________________________________________________ +# - Wrapper for finding static libraries ONLY +# +macro (find_static_library) + set (_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + find_library(${ARGN}) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${_CMAKE_FIND_LIBRARY_SUFFIXES}) + unset (_CMAKE_FIND_LIBRARY_SUFFIXES) +endmacro () + + +#______________________________________________________________________________ +# - Wrapper for finding shared/dynamic libraries ONLY +# +macro (find_shared_library) + set (_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + find_library(${ARGN}) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${_CMAKE_FIND_LIBRARY_SUFFIXES}) + unset (_CMAKE_FIND_LIBRARY_SUFFIXES) +endmacro () + + +#______________________________________________________________________________ +# - Function to determine type (SHARED or STATIC) of library +# +# Input: +# LIB (FILE) +# +# Returns: +# RETURN_VAR (BOOL) +# +function (is_shared_library RETURN_VAR LIB) + get_filename_component(libext ${LIB} EXT) + if (libext MATCHES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + set (${RETURN_VAR} TRUE PARENT_SCOPE) + else () + set (${RETURN_VAR} FALSE PARENT_SCOPE) + endif () +endfunction () + + +#______________________________________________________________________________ +# - Function to define a valid package component +# +# Input: +# ${PKG}_DEFAULT (BOOL) +# ${PKG}_COMPONENT (STRING) +# ${PKG}_INCLUDE_NAMES (LIST) +# ${PKG}_LIBRARY_NAMES (LIST) +# +# Returns: +# ${PKG}_DEFAULT_COMPONENT (STRING) +# ${PKG}_VALID_COMPONENTS (LIST) +# ${PKG}_${COMPONENT}_INCLUDE_NAMES (LIST) +# ${PKG}_${COMPONENT}_LIBRARY_NAMES (LIST) +# +function (define_package_component PKG) + + # Parse the input arguments + set (options DEFAULT) + set (oneValueArgs COMPONENT) + set (multiValueArgs INCLUDE_NAMES LIBRARY_NAMES) + cmake_parse_arguments (${PKG} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if (${PKG}_COMPONENT) + set (PKGCOMP ${PKG}_${${PKG}_COMPONENT}) + else () + set (PKGCOMP ${PKG}) + endif () + + # Set return values + if (${PKG}_COMPONENT) + if (${PKG}_DEFAULT) + set (${PKG}_DEFAULT_COMPONENT ${${PKG}_COMPONENT} PARENT_SCOPE) + endif () + set (VALID_COMPONENTS ${${PKG}_VALID_COMPONENTS}) + list (APPEND VALID_COMPONENTS ${${PKG}_COMPONENT}) + set (${PKG}_VALID_COMPONENTS ${VALID_COMPONENTS} PARENT_SCOPE) + endif () + set (${PKGCOMP}_INCLUDE_NAMES ${${PKG}_INCLUDE_NAMES} PARENT_SCOPE) + set (${PKGCOMP}_LIBRARY_NAMES ${${PKG}_LIBRARY_NAMES} PARENT_SCOPE) + +endfunction () + + +#______________________________________________________________________________ +# - Function to find valid package components +# +# Assumes pre-defined variables: +# ${PKG}_FIND_COMPONENTS (LIST) +# ${PKG}_DEFAULT_COMPONENT (STRING) +# ${PKG}_VALID_COMPONENTS (LIST) +# +# Returns: +# ${PKG}_FIND_VALID_COMPONENTS (LIST) +# +function (find_valid_components PKG) + + if (NOT ${PKG}_FIND_COMPONENTS) + set (${PKG}_FIND_COMPONENTS ${${PKG}_DEFAULT_COMPONENT}) + endif () + + set (FIND_VALID_COMPONENTS) + foreach (comp IN LISTS ${PKG}_FIND_COMPONENTS) + if (";${${PKG}_VALID_COMPONENTS};" MATCHES ";${comp};") + list (APPEND FIND_VALID_COMPONENTS ${comp}) + endif () + endforeach () + + set (${PKG}_FIND_VALID_COMPONENTS ${FIND_VALID_COMPONENTS} PARENT_SCOPE) + +endfunction () + + +#______________________________________________________________________________ +# - Initialize a list of paths from a list of includes and libraries +# +# Input: +# INCLUDE_DIRECTORIES +# LIBRARIES +# +# Ouput: +# ${PATHLIST} +# +function (initialize_paths PATHLIST) + + # Parse the input arguments + set (multiValueArgs INCLUDE_DIRECTORIES LIBRARIES) + cmake_parse_arguments (INIT "" "" "${multiValueArgs}" ${ARGN}) + + set (paths) + foreach (inc IN LISTS INIT_INCLUDE_DIRECTORIES) + list (APPEND paths ${inc}) + get_filename_component (dname ${inc} NAME) + if (dname MATCHES "include") + get_filename_component (prefx ${inc} PATH) + list (APPEND paths ${prefx}) + endif () + endforeach () + foreach (lib IN LISTS INIT_LIBRARIES) + get_filename_component (libdir ${lib} PATH) + list (APPEND paths ${libdir}) + get_filename_component (dname ${libdir} PATH) + if (dname MATCHES "lib") + get_filename_component (prefx ${libdir} PATH) + list (APPEND paths ${prefx}) + endif () + endforeach () + + set (${PATHLIST} ${paths} PARENT_SCOPE) + +endfunction () + + +#______________________________________________________________________________ +# - Basic find package macro for a specific component +# +# Assumes pre-defined variables: +# ${PKG}_${COMP}_INCLUDE_NAMES or ${PKG}_INCLUDE_NAMES +# ${PKG}_${COMP}_LIBRARY_NAMES or ${PKG}_LIBRARY_NAMES +# +# Input: +# ${PKG}_COMPONENT +# ${PKG}_HINTS +# ${PKG}_PATHS +# +function (find_package_component PKG) + + # Parse the input arguments + set (options) + set (oneValueArgs COMPONENT) + set (multiValueArgs HINTS PATHS) + cmake_parse_arguments (${PKG} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set (COMP ${${PKG}_COMPONENT}) + if (COMP) + set (PKGCOMP ${PKG}_${COMP}) + else () + set (PKGCOMP ${PKG}) + endif () + string (TOUPPER ${PKG} PKGUP) + string (TOUPPER ${PKGCOMP} PKGCOMPUP) + + # Only continue if package not found already + if (NOT ${PKGCOMP}_FOUND) + + # Handle QUIET and REQUIRED arguments + if (${${PKG}_FIND_QUIETLY}) + set (${PKGCOMP}_FIND_QUIETLY TRUE) + endif () + if (${${PKG}_FIND_REQUIRED}) + set (${PKGCOMP}_FIND_REQUIRED TRUE) + endif () + + # Determine search order + set (SEARCH_DIRS) + if (${PKG}_HINTS) + list (APPEND SEARCH_DIRS ${${PKG}_HINTS}) + endif () + if (${PKGCOMP}_PATH) + list (APPEND SEARCH_DIRS ${${PKGCOMP}_PATH}) + endif () + if (${PKG}_PATH) + list (APPEND SEARCH_DIRS ${${PKG}_PATH}) + endif () + if (DEFINED ENV{${PKGCOMPUP}}) + list (APPEND SEARCH_DIRS $ENV{${PKGCOMPUP}}) + endif () + if (DEFINED ENV{${PKGUP}}) + list (APPEND SEARCH_DIRS $ENV{${PKGUP}}) + endif () + if (CMAKE_SYSTEM_PREFIX_PATH) + list (APPEND SEARCH_DIRS ${CMAKE_SYSTEM_PREFIX_PATH}) + endif () + if (${PKG}_PATHS) + list (APPEND SEARCH_DIRS ${${PKG}_PATHS}) + endif () + + # Start the search for the include file and library file. Only overload + # if the variable is not defined. + foreach (suffix PREFIX LIBRARY INCLUDE_DIR) + if (NOT DEFINED ${PKGCOMP}_${suffix}) + set (${PKGCOMP}_${suffix} ${PKGCOMP}_${suffix}-NOTFOUND) + endif () + endforeach () + + foreach (dir IN LISTS SEARCH_DIRS) + + # Search for include file names in current dirrectory + foreach (iname IN LISTS ${PKGCOMP}_INCLUDE_NAMES) + if (EXISTS ${dir}/${iname}) + set (${PKGCOMP}_PREFIX ${dir}) + set (${PKGCOMP}_INCLUDE_DIR ${dir}) + break () + endif () + if (EXISTS ${dir}/include/${iname}) + set (${PKGCOMP}_PREFIX ${dir}) + set (${PKGCOMP}_INCLUDE_DIR ${dir}/include) + break () + endif () + endforeach () + + # Search for library file names in the found prefix only! + if (${PKGCOMP}_PREFIX) + find_library (${PKGCOMP}_LIBRARY + NAMES ${${PKGCOMP}_LIBRARY_NAMES} + PATHS ${${PKGCOMP}_PREFIX} + PATH_SUFFIXES lib + NO_DEFAULT_PATH) + + # If found, check if library is static or dynamic + if (${PKGCOMP}_LIBRARY) + is_shared_library (${PKGCOMP}_IS_SHARED ${${PKGCOMP}_LIBRARY}) + + # If we want only shared libraries, and it isn't shared... + if (PREFER_SHARED AND NOT ${PKGCOMP}_IS_SHARED) + find_shared_library (${PKGCOMP}_SHARED_LIBRARY + NAMES ${${PKGCOMP}_LIBRARY_NAMES} + PATHS ${${PKGCOMP}_PREFIX} + PATH_SUFFIXES lib + NO_DEFAULT_PATH) + if (${PKGCOMP}_SHARED_LIBRARY) + set (${PKGCOMP}_LIBRARY ${${PKGCOMP}_SHARED_LIBRARY}) + set (${PKGCOMP}_IS_SHARED TRUE) + endif () + + # If we want only static libraries, and it is shared... + elseif (PREFER_STATIC AND ${PKGCOMP}_IS_SHARED) + find_static_library (${PKGCOMP}_STATIC_LIBRARY + NAMES ${${PKGCOMP}_LIBRARY_NAMES} + PATHS ${${PKGCOMP}_PREFIX} + PATH_SUFFIXES lib + NO_DEFAULT_PATH) + if (${PKGCOMP}_STATIC_LIBRARY) + set (${PKGCOMP}_LIBRARY ${${PKGCOMP}_STATIC_LIBRARY}) + set (${PKGCOMP}_IS_SHARED FALSE) + endif () + endif () + endif () + + # If include dir and library both found, then we're done + if (${PKGCOMP}_INCLUDE_DIR AND ${PKGCOMP}_LIBRARY) + break () + + # Otherwise, reset the search variables and continue + else () + set (${PKGCOMP}_PREFIX ${PKGCOMP}_PREFIX-NOTFOUND) + set (${PKGCOMP}_INCLUDE_DIR ${PKGCOMP}_INCLUDE_DIR-NOTFOUND) + set (${PKGCOMP}_LIBRARY ${PKGCOMP}_LIBRARY-NOTFOUND) + endif () + endif () + + endforeach () + + # handle the QUIETLY and REQUIRED arguments and + # set NetCDF_C_FOUND to TRUE if all listed variables are TRUE + find_package_handle_standard_args (${PKGCOMP} DEFAULT_MSG + ${PKGCOMP}_LIBRARY + ${PKGCOMP}_INCLUDE_DIR) + mark_as_advanced (${PKGCOMP}_INCLUDE_DIR ${PKGCOMP}_LIBRARY) + + # HACK For bug in CMake v3.0: + set (${PKGCOMP}_FOUND ${${PKGCOMPUP}_FOUND}) + + # Set return variables + if (${PKGCOMP}_FOUND) + set (${PKGCOMP}_INCLUDE_DIRS ${${PKGCOMP}_INCLUDE_DIR}) + set (${PKGCOMP}_LIBRARIES ${${PKGCOMP}_LIBRARY}) + endif () + + # Set variables in parent scope + set (${PKGCOMP}_FOUND ${${PKGCOMP}_FOUND} PARENT_SCOPE) + set (${PKGCOMP}_INCLUDE_DIR ${${PKGCOMP}_INCLUDE_DIR} PARENT_SCOPE) + set (${PKGCOMP}_INCLUDE_DIRS ${${PKGCOMP}_INCLUDE_DIRS} PARENT_SCOPE) + set (${PKGCOMP}_LIBRARY ${${PKGCOMP}_LIBRARY} PARENT_SCOPE) + set (${PKGCOMP}_LIBRARIES ${${PKGCOMP}_LIBRARIES} PARENT_SCOPE) + set (${PKGCOMP}_IS_SHARED ${${PKGCOMP}_IS_SHARED} PARENT_SCOPE) + + endif () + +endfunction () + + + diff --git a/ParallelIO/cmake/LibMPI.cmake b/ParallelIO/cmake/LibMPI.cmake new file mode 100644 index 0000000000..48efe976a9 --- /dev/null +++ b/ParallelIO/cmake/LibMPI.cmake @@ -0,0 +1,124 @@ +# This is part of the PIO library. + +# THis file contains CMake code related to MPI. + +# Jim Edwards +include (CMakeParseArguments) + +# Find Valgrind to perform memory leak check +if (PIO_VALGRIND_CHECK) + find_program (VALGRIND_COMMAND NAMES valgrind) + if (VALGRIND_COMMAND) + set (VALGRIND_COMMAND_OPTIONS --leak-check=full --show-reachable=yes) + else () + message (WARNING "Valgrind not found: memory leak check could not be performed") + set (VALGRIND_COMMAND "") + endif () +endif () + +# +# - Functions for parallel testing with CTest +# + +#============================================================================== +# - Get the machine platform-specific +# +# Syntax: platform_name (RETURN_VARIABLE) +# +function (platform_name RETURN_VARIABLE) + + # Determine platform name from site name... + site_name (SITENAME) + + + if (SITENAME MATCHES "^laramie" OR + SITENAME MATCHES "^cheyenne" OR + SITENAME MATCHES "^chadmin") + + set (${RETURN_VARIABLE} "nwscla" PARENT_SCOPE) + + # ALCF/Argonne Machines + elseif (SITENAME MATCHES "^mira" OR + SITENAME MATCHES "^cetus" OR + SITENAME MATCHES "^vesta" OR + SITENAME MATCHES "^cooley") + + set (${RETURN_VARIABLE} "alcf" PARENT_SCOPE) + + # NERSC Machines + elseif (SITENAME MATCHES "^edison" OR + SITENAME MATCHES "^cori") + + set (${RETURN_VARIABLE} "nersc" PARENT_SCOPE) + + # NCSA Machine (Blue Waters) + elseif (SITENAME MATCHES "^h2ologin") + + set (${RETURN_VARIABLE} "ncsa" PARENT_SCOPE) + + # OLCF/Oak Ridge Machines + elseif (SITENAME MATCHES "^eos" OR + SITENAME MATCHES "^titan") + + set (${RETURN_VARIABLE} "olcf" PARENT_SCOPE) + + else () + + set (${RETURN_VARIABLE} "unknown" PARENT_SCOPE) + + endif () +endfunction () + +#============================================================================== +# - Add a new parallel test +# +# Syntax: add_mpi_test ( +# EXECUTABLE +# ARGUMENTS ... +# NUMPROCS +# TIMEOUT ) +function (add_mpi_test TESTNAME) + + # Parse the input arguments + set (options) + set (oneValueArgs NUMPROCS TIMEOUT EXECUTABLE) + set (multiValueArgs ARGUMENTS) + cmake_parse_arguments (${TESTNAME} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # Store parsed arguments for convenience + set (exec_file ${${TESTNAME}_EXECUTABLE}) + set (exec_args ${${TESTNAME}_ARGUMENTS}) + set (num_procs ${${TESTNAME}_NUMPROCS}) + set (timeout ${${TESTNAME}_TIMEOUT}) + + # Get the platform name + platform_name (PLATFORM) + + get_property(WITH_MPIEXEC GLOBAL PROPERTY WITH_MPIEXEC) + if (WITH_MPIEXEC) + set(MPIEXEC "${WITH_MPIEXEC}") + endif () + + # Default ("unknown" platform) execution + if (PLATFORM STREQUAL "unknown") + + # Run tests directly from the command line + set(EXE_CMD ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${num_procs} + ${MPIEXEC_PREFLAGS} ${VALGRIND_COMMAND} ${VALGRIND_COMMAND_OPTIONS} ${exec_file} + ${MPIEXEC_POSTFLAGS} ${exec_args}) + + else () + + # Run tests from the platform-specific executable + set (EXE_CMD ${CMAKE_SOURCE_DIR}/cmake/mpiexec.${PLATFORM} + ${num_procs} ${VALGRIND_COMMAND} ${VALGRIND_COMMAND_OPTIONS} ${exec_file} ${exec_args}) + + endif () + + # Add the test to CTest + add_test(NAME ${TESTNAME} COMMAND ${EXE_CMD}) + + # Adjust the test timeout + set_tests_properties(${TESTNAME} PROPERTIES TIMEOUT ${timeout}) + +endfunction() diff --git a/ParallelIO/cmake/Makefile.am b/ParallelIO/cmake/Makefile.am new file mode 100644 index 0000000000..9b2ea30f96 --- /dev/null +++ b/ParallelIO/cmake/Makefile.am @@ -0,0 +1,13 @@ +## This is the automake file for the cmake directory of the PIO +## libraries. This directory holds files needed for the CMake build, +## but not the autotools build. + +# Ed Hartnett 8/19/19 + +# Cmake needs all these extra files to build. +EXTRA_DIST = FindGPTL.cmake FindHDF5.cmake FindLIBRT.cmake \ +FindLIBZ.cmake FindMPE.cmake FindMPISERIAL.cmake FindNetCDF.cmake \ +FindPAPI.cmake FindPnetCDF.cmake FindSZIP.cmake LibCheck.cmake \ +LibFind.cmake LibMPI.cmake Makefile.am mpiexec.alcf mpiexec.ncsa \ +mpiexec.nersc mpiexec.nwscla mpiexec.olcf TryHDF5_HAS_SZIP.c \ +TryNetCDF_DAP.c TryNetCDF_PARALLEL.c TryNetCDF_PNETCDF.c diff --git a/ParallelIO/cmake/TryHDF5_HAS_SZIP.c b/ParallelIO/cmake/TryHDF5_HAS_SZIP.c new file mode 100644 index 0000000000..c4013455c2 --- /dev/null +++ b/ParallelIO/cmake/TryHDF5_HAS_SZIP.c @@ -0,0 +1,13 @@ +/* + * HDF5 C Test for szip filter + */ +#include "H5pubconf.h" + +int main() +{ +#if H5_HAVE_FILTER_SZIP==1 + return 0; +#else + XXX; +#endif +} diff --git a/ParallelIO/cmake/TryNetCDF_DAP.c b/ParallelIO/cmake/TryNetCDF_DAP.c new file mode 100644 index 0000000000..4d2f77fd98 --- /dev/null +++ b/ParallelIO/cmake/TryNetCDF_DAP.c @@ -0,0 +1,13 @@ +/* + * NetCDF C Test for DAP Support + */ +#include "netcdf_meta.h" + +int main() +{ +#if NC_HAS_DAP==1 || NC_HAS_DAP2==1 || NC_HAS_DAP4==1 + return 0; +#else + XXX; +#endif +} diff --git a/ParallelIO/cmake/TryNetCDF_PARALLEL.c b/ParallelIO/cmake/TryNetCDF_PARALLEL.c new file mode 100644 index 0000000000..7b041f6371 --- /dev/null +++ b/ParallelIO/cmake/TryNetCDF_PARALLEL.c @@ -0,0 +1,13 @@ +/* + * NetCDF C Test for parallel Support + */ +#include "netcdf_meta.h" + +int main() +{ +#if NC_HAS_PARALLEL==1 + return 0; +#else + XXX; +#endif +} diff --git a/ParallelIO/cmake/TryNetCDF_PNETCDF.c b/ParallelIO/cmake/TryNetCDF_PNETCDF.c new file mode 100644 index 0000000000..60a0c08864 --- /dev/null +++ b/ParallelIO/cmake/TryNetCDF_PNETCDF.c @@ -0,0 +1,13 @@ +/* + * NetCDF C Test for PnetCDF Support + */ +#include "netcdf_meta.h" + +int main() +{ +#if NC_HAS_PNETCDF==1 + return 0; +#else + XXX; +#endif +} diff --git a/ParallelIO/cmake/mpiexec.alcf b/ParallelIO/cmake/mpiexec.alcf new file mode 100755 index 0000000000..48765fd022 --- /dev/null +++ b/ParallelIO/cmake/mpiexec.alcf @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Arguments: +# +# $1 - Number of MPI Tasks +# $2+ - Executable and its arguments +# + +NP=$1 +shift + +${BGQ_RUNJOB:-runjob} --np $NP --block $COBALT_PARTNAME \ + --envs GPFSMPIO_NAGG_PSET=16 GPFSMPIO_ONESIDED_ALWAYS_RMW=1 \ + GPFSMPIO_BALANCECONTIG=1 GPFSMPIO_WRITE_AGGMETHOD=2 \ + GPFSMPIO_READ_AGGMETHOD=2 PAMID_TYPED_ONESIDED=1 \ + PAMID_RMA_PENDING=1M GPFSMPIO_BRIDGERINGAGG=1 : $@ diff --git a/ParallelIO/cmake/mpiexec.ncsa b/ParallelIO/cmake/mpiexec.ncsa new file mode 100755 index 0000000000..2bb0d1c846 --- /dev/null +++ b/ParallelIO/cmake/mpiexec.ncsa @@ -0,0 +1,12 @@ +#!/bin/bash +# +# Arguments: +# +# $1 - Number of MPI Tasks +# $2+ - Executable and its arguments +# + +NP=$1 +shift + +aprun -n $NP $@ diff --git a/ParallelIO/cmake/mpiexec.nersc b/ParallelIO/cmake/mpiexec.nersc new file mode 100755 index 0000000000..e8774b0e98 --- /dev/null +++ b/ParallelIO/cmake/mpiexec.nersc @@ -0,0 +1,12 @@ +#!/bin/bash +# +# Arguments: +# +# $1 - Number of MPI Tasks +# $2+ - Executable and its arguments +# + +NP=$1 +shift + +srun -n $NP $@ diff --git a/ParallelIO/cmake/mpiexec.nwscla b/ParallelIO/cmake/mpiexec.nwscla new file mode 100755 index 0000000000..9aea7be13e --- /dev/null +++ b/ParallelIO/cmake/mpiexec.nwscla @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Arguments: +# +# $1 - Number of MPI Tasks +# $2+ - Executable and its arguments +# + +NP=$1 +shift +mpirun -np $NP $@ diff --git a/ParallelIO/cmake/mpiexec.olcf b/ParallelIO/cmake/mpiexec.olcf new file mode 100755 index 0000000000..2bb0d1c846 --- /dev/null +++ b/ParallelIO/cmake/mpiexec.olcf @@ -0,0 +1,12 @@ +#!/bin/bash +# +# Arguments: +# +# $1 - Number of MPI Tasks +# $2+ - Executable and its arguments +# + +NP=$1 +shift + +aprun -n $NP $@ diff --git a/ParallelIO/cmake_config.h.in b/ParallelIO/cmake_config.h.in new file mode 100644 index 0000000000..586030c202 --- /dev/null +++ b/ParallelIO/cmake_config.h.in @@ -0,0 +1,48 @@ +/** @file + * + * This is the template for the config.h file, which is created at + * build-time by cmake. + */ +#ifndef _PIO_CONFIG_ +#define _PIO_CONFIG_ + +/** The major part of the version number. */ +#define PIO_VERSION_MAJOR @VERSION_MAJOR@ + +/** The minor part of the version number. */ +#define PIO_VERSION_MINOR @VERSION_MINOR@ + +/** The patch part of the version number. */ +#define PIO_VERSION_PATCH @VERSION_PATCH@ + +/** Set to non-zero to turn on logging. Output may be large. */ +#define PIO_ENABLE_LOGGING @ENABLE_LOGGING@ + +/** Size of MPI_Offset type. */ +#define SIZEOF_MPI_OFFSET @SIZEOF_MPI_OFFSET@ + +/* buffer size for darray data. */ +#define PIO_BUFFER_SIZE @PIO_BUFFER_SIZE@ + +#define USE_VARD @USE_VARD@ + +/* Does netCDF support netCDF/HDF5 files? */ +#cmakedefine HAVE_NETCDF4 + +/* Does netCDF support parallel I/O for netCDF/HDF5 files? */ +#cmakedefine HAVE_NETCDF_PAR + +/* Does PIO support netCDF/HDF5 files? (Will be same as + * HAVE_NETCDF_PAR). */ +#cmakedefine _NETCDF4 + +/* Does netCDF and HDF5 support parallel I/O filters? */ +#cmakedefine HAVE_PAR_FILTERS + +/* Was PIO built with netCDF integration? */ +#cmakedefine NETCDF_INTEGRATION + +/* Does PIO support using pnetcdf for I/O? */ +#cmakedefine _PNETCDF + +#endif /* _PIO_CONFIG_ */ diff --git a/ParallelIO/configure.ac b/ParallelIO/configure.ac new file mode 100644 index 0000000000..007b1fdedc --- /dev/null +++ b/ParallelIO/configure.ac @@ -0,0 +1,502 @@ +## This is the autoconf file for the PIO library. +## Ed Hartnett 8/16/17 + +# Initialize autoconf and automake. +AC_INIT(pio, 2.5.10) +AC_CONFIG_SRCDIR(src/clib/pio_darray.c) +AM_INIT_AUTOMAKE([foreign serial-tests]) + + +# The PIO version, again. Use AC_SUBST for pio_meta.h and +# AC_DEFINE_UNQUOTED for config.h. +AC_SUBST([PIO_VERSION_MAJOR]) PIO_VERSION_MAJOR=2 +AC_SUBST([PIO_VERSION_MINOR]) PIO_VERSION_MINOR=5 +AC_SUBST([PIO_VERSION_PATCH]) PIO_VERSION_PATCH=10 + +AC_DEFINE_UNQUOTED([PIO_VERSION_MAJOR], [$PIO_VERSION_MAJOR], [PIO major version]) +AC_DEFINE_UNQUOTED([PIO_VERSION_MINOR], [$PIO_VERSION_MINOR], [PIO minor version]) +AC_DEFINE_UNQUOTED([PIO_VERSION_PATCH], [$PIO_VERSION_PATCH], [PIO patch version]) + +# Once more for the documentation. +AC_SUBST([VERSION_MAJOR], [2]) +AC_SUBST([VERSION_MINOR], [5]) +AC_SUBST([VERSION_PATCH], [10]) + +# The m4 directory holds macros for autoconf. +AC_CONFIG_MACRO_DIR([m4]) + +# Configuration date. This follows convention of allowing +# SOURCE_DATE_EPOCH to be used to specify a timestamp, to allow +# byte-for-byte reproducable software builds. +if test "x$SOURCE_DATE_EPOCH" != "x" ; then + AC_SUBST([CONFIG_DATE]) CONFIG_DATE="`date -u -d "${SOURCE_DATE_EPOCH}"`" +else + AC_SUBST([CONFIG_DATE]) CONFIG_DATE="`date`" +fi + +# Libtool initialisation. +LD=ld # Required for MPE to work. +LT_INIT + +# Find and learn about install and ranlib. +AC_PROG_INSTALL +AC_PROG_RANLIB + +# Find and learn about the C compiler. +AC_PROG_CC +AC_PROG_CC_C99 + +# Compiler with version information. This consists of the full path +# name of the compiler and the reported version number. +AC_SUBST([CC_VERSION]) +# Strip anything that looks like a flag off of $CC +CC_NOFLAGS=`echo $CC | sed 's/ -.*//'` + +if `echo $CC_NOFLAGS | grep ^/ >/dev/null 2>&1`; then + CC_VERSION="$CC" +else + CC_VERSION="$CC"; + for x in `echo $PATH | sed -e 's/:/ /g'`; do + if test -x $x/$CC_NOFLAGS; then + CC_VERSION="$x/$CC" + break + fi + done +fi + +if test -n "$cc_version_info"; then + CC_VERSION="$CC_VERSION ( $cc_version_info)" +fi + +# Find and learn about the Fortran compiler. +AC_PROG_FC + +# Compiler with version information. This consists of the full path +# name of the compiler and the reported version number. +AC_SUBST([FC_VERSION]) +# Strip anything that looks like a flag off of $FC +FC_NOFLAGS=`echo $FC | sed 's/ -.*//'` + +if `echo $FC_NOFLAGS | grep ^/ >/dev/null 2>&1`; then + FC_VERSION="$FC" +else + FC_VERSION="$FC"; + for x in `echo $PATH | sed -e 's/:/ /g'`; do + if test -x $x/$FC_NOFLAGS; then + FC_VERSION="$x/$FC" + break + fi + done +fi +if test -n "$fc_version_info"; then + FC_VERSION="$FC_VERSION ( $fc_version_info)" +fi + +AC_MSG_CHECKING([whether a PIO_BUFFER_SIZE was specified]) +AC_ARG_WITH([piobuffersize], + [AS_HELP_STRING([--with-piobuffersize=], + [Specify buffer size for PIO.])], + [PIO_BUFFER_SIZE=$with_piobuffersize], [PIO_BUFFER_SIZE=134217728]) +AC_MSG_RESULT([$PIO_BUFFER_SIZE]) +AC_DEFINE_UNQUOTED([PIO_BUFFER_SIZE], [$PIO_BUFFER_SIZE], [buffer size for darray data.]) + +# Does the user want to enable logging? +AC_MSG_CHECKING([whether debug logging is enabled]) +AC_ARG_ENABLE([logging], + [AS_HELP_STRING([--enable-logging], + [enable debug logging capability (will negatively impact performance). \ + This debugging feature is probably only of interest to PIO developers.])]) +test "x$enable_logging" = xyes || enable_logging=no +AC_MSG_RESULT([$enable_logging]) +if test "x$enable_logging" = xyes; then + AC_DEFINE([PIO_ENABLE_LOGGING], 1, [If true, turn on logging.]) +fi + +# Does the user want to enable timing? +AC_MSG_CHECKING([whether GPTL timing library is used]) +AC_ARG_ENABLE([timing], + [AS_HELP_STRING([--enable-timing], + [enable use of the GPTL timing library.])]) +test "x$enable_timing" = xyes || enable_timing=no +AC_MSG_RESULT([$enable_timing]) +if test "x$enable_timing" = xyes; then + AC_DEFINE([TIMING], 1, [If true, use GPTL timing library.]) + AC_DEFINE([HAVE_MPI], [1], [required by GPTL timing library]) +fi +AM_CONDITIONAL(USE_GPTL, [test "x$enable_timing" = xyes]) + +# Does the user want to disable papi? +AC_MSG_CHECKING([whether PAPI should be enabled (if enable-timing is used)]) +AC_ARG_ENABLE([papi], [AS_HELP_STRING([--disable-papi], + [disable PAPI library use])]) +test "x$enable_papi" = xno || enable_papi=yes +AC_MSG_RESULT($enable_papi) + +# Does the user want to disable test runs? +AC_MSG_CHECKING([whether test runs should be enabled for make check]) +AC_ARG_ENABLE([test-runs], [AS_HELP_STRING([--disable-test-runs], + [disable running run_test.sh test scripts for make check. Tests will still be built.])]) +test "x$enable_test_runs" = xno || enable_test_runs=yes +AC_MSG_RESULT($enable_test_runs) +AM_CONDITIONAL(RUN_TESTS, [test "x$enable_test_runs" = xyes]) + +# Does the user want to enable Fortran library? +AC_MSG_CHECKING([whether Fortran library should be built]) +AC_ARG_ENABLE([fortran], + [AS_HELP_STRING([--enable-fortran], + [build the PIO Fortran library.])]) +test "x$enable_fortran" = xyes || enable_fortran=no +AC_MSG_RESULT([$enable_fortran]) +AM_CONDITIONAL(BUILD_FORTRAN, [test "x$enable_fortran" = xyes]) + +# Does the user want to use MPE library? +AC_MSG_CHECKING([whether use of MPE library is enabled]) +AC_ARG_ENABLE([mpe], + [AS_HELP_STRING([--enable-mpe], + [enable use of MPE library for timing and diagnostic info (may negatively impact performance).])]) +test "x$enable_mpe" = xyes || enable_mpe=no +AC_MSG_RESULT([$enable_mpe]) +if test "x$enable_mpe" = xyes; then + + AC_SEARCH_LIBS([pthread_setspecific], [pthread], [], [], []) + AC_SEARCH_LIBS([MPE_Log_get_event_number], [mpe], [HAVE_LIBMPE=yes], [HAVE_LIBMPE=no], []) + AC_SEARCH_LIBS([MPE_Init_mpi_core], [lmpe], [HAVE_LIBLMPE=yes], [HAVE_LIBLMPE=no], []) + AC_CHECK_HEADERS([mpe.h], [HAVE_MPE=yes], [HAVE_MPE=no]) + if test "x$HAVE_LIBMPE" != xyes; then + AC_MSG_ERROR([-lmpe not found but --enable-mpe used.]) + fi + if test "x$HAVE_LIBLMPE" != xyes; then + AC_MSG_ERROR([-llmpe not found but --enable-mpe used.]) + fi + if test $enable_fortran = yes; then + AC_MSG_ERROR([MPE not implemented in Fortran tests and examples. Build without --enable-fortran]) + fi + AC_DEFINE([USE_MPE], 1, [If true, use MPE timing library.]) + +fi + +# Does the user want to disable pnetcdf? +AC_MSG_CHECKING([whether pnetcdf is to be used]) +AC_ARG_ENABLE([pnetcdf], + [AS_HELP_STRING([--disable-pnetcdf], + [Disable pnetcdf use.])]) +test "x$enable_pnetcdf" = xno || enable_pnetcdf=yes +AC_MSG_RESULT([$enable_pnetcdf]) +AM_CONDITIONAL(BUILD_PNETCDF, [test "x$enable_pnetcdf" = xyes]) + +# Does the user want to build documentation? +AC_MSG_CHECKING([whether documentation should be build (requires doxygen)]) +AC_ARG_ENABLE([docs], + [AS_HELP_STRING([--enable-docs], + [enable building of documentation with doxygen.])]) +test "x$enable_docs" = xyes || enable_docs=no +AC_MSG_RESULT([$enable_docs]) + +# Does the user want to developer documentation? +AC_MSG_CHECKING([whether PIO developer documentation should be build (only for PIO developers)]) +AC_ARG_ENABLE([developer-docs], + [AS_HELP_STRING([--enable-developer-docs], + [enable building of PIO developer documentation with doxygen.])]) +test "x$enable_developer_docs" = xyes || enable_developer_docs=no +AC_MSG_RESULT([$enable_developer_docs]) + +# Developer docs enables docs. +if test "x$enable_developer_docs" = xyes; then + enable_docs=yes +fi +AM_CONDITIONAL(BUILD_DOCS, [test "x$enable_docs" = xyes]) + +# Did the user specify an MPI launcher other than mpiexec? +AC_MSG_CHECKING([whether a user specified program to run mpi programs]) +AC_ARG_WITH([mpiexec], + [AS_HELP_STRING([--with-mpiexec=], + [Specify command to launch MPI parallel tests.])], + [WITH_MPIEXEC=$with_mpiexec], [WITH_MPIEXEC=mpiexec]) +AC_MSG_RESULT([$WITH_MPIEXEC]) +AC_SUBST([WITH_MPIEXEC], [$WITH_MPIEXEC]) + +# Is doxygen installed? +AC_CHECK_PROGS([DOXYGEN], [doxygen]) +if test -z "$DOXYGEN" -a "x$enable_docs" = xyes; then + AC_MSG_ERROR([Doxygen not found but --enable-docs used.]) +fi + +AC_MSG_NOTICE([processing doxyfile]) +# If building docs, process Doxyfile.in into Doxyfile. +if test "x$enable_docs" = xyes; then + AC_SUBST([CMAKE_CURRENT_SOURCE_DIR], ["."]) + AC_SUBST([CMAKE_BINARY_DIR], [".."]) + if test "x$enable_fortran" = xno; then + AC_MSG_ERROR([--enable-fortran is required for documentation builds.]) + fi + AC_SUBST([FORTRAN_SRC_FILES], ["../src/flib/piodarray.f90 ../src/flib/pio.F90 ../src/flib/pio_kinds.F90 ../src/flib/piolib_mod.f90 ../src/flib/pionfatt_mod_2.f90 ../src/flib/pio_nf.F90 ../src/flib/pionfget_mod_2.f90 ../src/flib/pionfput_mod.f90 ../src/flib/pio_support.F90 ../src/flib/pio_types.F90"]) + if test "x$enable_developer_docs" = xyes; then + AC_SUBST([C_SRC_FILES], ["../src/clib ../src/ncint"]) + else + AC_SUBST([C_SRC_FILES], ["../src/clib/pio_nc.c ../src/clib/pio_nc4.c ../src/clib/pio_darray.c ../src/clib/pio_get_nc.c ../src/clib/pio_put_nc.c ../src/clib/pioc_support.c ../src/clib/pioc.c ../src/clib/pio_file.c ../src/clib/pio.h ../src/clib/pio_get_vard.c ../src/clib/pio_put_vard.c ../src/ncint/ncint_pio.c ../src/ncint/nc_put_vard.c ../src/ncint/nc_get_vard.c"]) + fi + AC_CONFIG_FILES([doc/Doxyfile]) +fi + +AC_MSG_NOTICE([finding libraries]) + +# Ensure we have MPI. +AC_CHECK_FUNCS([MPI_Init]) +if test "x$ac_cv_func_MPI_Init" != "xyes"; then + AC_MSG_ERROR([Can't link to MPI library. MPI is required.]) +fi + +# Check for netCDF library. +AC_CHECK_LIB([netcdf], [nc_create], [], [AC_MSG_ERROR([Can't find or link to the netcdf library.])]) +AC_CHECK_HEADERS([netcdf.h netcdf_meta.h]) + +# Check for pnetcdf library. +AC_CHECK_LIB([pnetcdf], [ncmpi_create], [], []) +if test "x$ac_cv_lib_pnetcdf_ncmpi_create" = xno -a $enable_pnetcdf = yes; then + AC_MSG_ERROR([Pnetcdf not found. Set CPPFLAGS/LDFLAGS or use --disable-pnetcdf.]) +fi + +# If we have parallel-netcdf, then set these as well. +if test x$ac_cv_lib_pnetcdf_ncmpi_create = xyes; then + AC_DEFINE([_PNETCDF], [1], [parallel-netcdf library available]) +fi + +# Do we have netCDF-4? +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if !NC_HAS_NC4 +# error +#endif] +])], [have_netcdf4=yes], [have_netcdf4=no]) +AC_MSG_CHECKING([whether netCDF provides netCDF/HDF5]) +AC_MSG_RESULT([${have_netcdf4}]) + +# Do we have a parallel build of netCDF-4? (Really we should be +# checking NC_HAS_PARALLEL4, but that was only recently introduced, so +# we will go with NC_HAS_PARALLEL.) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if !NC_HAS_PARALLEL +# error +#endif] +])], [have_netcdf_par=yes], [have_netcdf_par=no]) +AC_MSG_CHECKING([whether netCDF provides parallel I/O for netCDF/HDF5]) +AC_MSG_RESULT([${have_netcdf_par}]) + +# Do we have szip? +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if !NC_HAS_SZIP_WRITE +# error +#endif] +])], [have_szip_write=yes], [have_szip_write=no]) +AC_MSG_CHECKING([whether netCDF provides szip write capability]) +AC_MSG_RESULT([${have_szip_write}]) + +# Do we have parallel filter support? Parallel filters are required +# for iotype NETCDF4P to use compression. +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if !NC_HAS_PAR_FILTERS +# error +#endif] +])], [have_par_filters=yes], [have_par_filters=no]) +AC_MSG_CHECKING([whether netCDF provides parallel filter support]) +AC_MSG_RESULT([${have_par_filters}]) +if test "x$have_par_filters" = xyes ; then + AC_DEFINE([HAVE_PAR_FILTERS], [1], [if true, netcdf-c supports filters with parallel I/O]) +fi + +# Is this version 4.7.2, which does not work? +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if NC_VERSION_MAJOR == 4 && NC_VERSION_MINOR == 7 && NC_VERSION_PATCH == 2 +#else +# error +#endif] +])], [have_472=yes], [have_472=no]) +AC_MSG_CHECKING([whether this is netcdf-c-4.7.2]) +AC_MSG_RESULT([${have_472}]) +if test "x$have_472" = xyes; then + AC_MSG_ERROR([PIO cannot build with netcdf-c-4.7.2, please upgrade your netCDF version.]) +fi + +# Do we have the correct dispatch table version in netcdf-c for netcdf +# integration? +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if NC_DISPATCH_VERSION != 2 +# error +#endif] +])], [have_dispatch2=yes], [have_dispatch2=no]) +AC_MSG_CHECKING([whether netcdf-c supports version 2 of dispatch table for netcdf integration]) +AC_MSG_RESULT([${have_dispatch2}]) +if test "x$enable_netcdf_integration" = xyes -a "x$have_dispatch2" = xno; then + AC_MSG_ERROR([NetCDF integration cannot be used with this version of netcdf-c, please upgrade your netCDF version.]) +fi + +# Set some build settings for when netcdf-4 is supported. +if test x$have_netcdf_par = xyes; then + AC_DEFINE([_NETCDF4],[1],[Does netCDF library provide netCDF-4 with parallel access]) +fi +AM_CONDITIONAL(BUILD_NETCDF4, [test "x$have_netcdf_par" = xyes]) + +# Not working for some reason, so I will just set it... +#AC_CHECK_TYPE([MPI_Offset], [], [], [#include ]) +#if test "x${ac_cv_type_MPI_Offset}" = xyes; then +# AC_CHECK_SIZEOF([MPI_Offset], [], [#include ]) +#else +# AC_MSG_ERROR([Unable to find type MPI_Offset in mpi.h]) +#fi + +# If we want the timing library, we must find it. +if test "x$enable_timing" = xyes; then + AC_CHECK_HEADERS([gptl.h]) + AC_CHECK_LIB([gptl], [GPTLinitialize], [], + [AC_MSG_ERROR([Can't find or link to the GPTL library.])]) + if test "x$enable_fortran" = xyes; then + AC_LANG_PUSH([Fortran]) +# AC_CHECK_HEADERS([gptl.inc]) + AC_CHECK_LIB([gptlf], [gptlstart], [], + [AC_MSG_ERROR([Can't find or link to the GPTL Fortran library.])]) + AC_LANG_POP([Fortran]) + fi + + # Check for papi library. + AC_CHECK_LIB([papi], [PAPI_library_init]) + AC_MSG_CHECKING([whether system can support PAPI]) + have_papi=no + if test $enable_papi = yes; then + if test "x$ac_cv_lib_papi_PAPI_library_init" = xyes; then + # If we have PAPI library, check /proc/sys/kernel/perf_event_paranoid + # to see if we have permissions. + if test -f /proc/sys/kernel/perf_event_paranoid; then + if test `cat /proc/sys/kernel/perf_event_paranoid` != 1; then + AC_MSG_ERROR([PAPI library found, but /proc/sys/kernel/perf_event_paranoid != 1 + try sudo sh -c 'echo 1 >/proc/sys/kernel/perf_event_paranoid']) + fi + fi + AC_DEFINE([HAVE_PAPI], [1], [PAPI library is present and usable]) + have_papi=yes + fi + fi + AC_MSG_RESULT($have_papi) +fi +AM_CONDITIONAL([HAVE_PAPI], [test "x$have_papi" = xyes]) + +# Does the user want to build netcdf-c integration layer? +AC_MSG_CHECKING([whether netcdf-c integration layer should be build]) +AC_ARG_ENABLE([netcdf-integration], + [AS_HELP_STRING([--enable-netcdf-integration], + [enable building of netCDF C API integration.])]) +test "x$enable_netcdf_integration" = xyes || enable_netcdf_integration=no +AC_MSG_RESULT([$enable_netcdf_integration]) +if test "x$enable_netcdf_integration" = xyes -a "x$enable_timing" = xyes; then + AC_MSG_ERROR([Cannot use GPTL timing library with netCDF interation.]) +fi +if test "x$enable_netcdf_integration" = xyes -a "x$have_netcdf_par" = xno; then + AC_MSG_ERROR([Cannot use netCDF integration unless netCDF library was built for parallel I/O.]) +fi + +# If netCDF integration is used, set this preprocessor symbol. +if test "x$enable_netcdf_integration" = xyes; then + AC_DEFINE([NETCDF_INTEGRATION],[1],[Are we building with netCDF integration]) +fi +AM_CONDITIONAL(BUILD_NCINT, [test "x$enable_netcdf_integration" = xyes]) + +# If we are building netCDF integration and also then PIO Fortran +# library, then we also need netcdf-fortran. +if test "x$enable_netcdf_integration" = xyes -a "x$enable_fortran" = xyes; then + AC_LANG_PUSH([Fortran]) + AC_CHECK_LIB([netcdff], [nf_inq_libvers], [], [AC_MSG_ERROR([Can't find or link to the netcdf-fortran library, required because both --enable-fortran and --enable-netcdf-integration are specified.])]) + AC_LANG_POP([Fortran]) +fi + +AC_CONFIG_FILES([tests/general/pio_tutil.F90:tests/general/util/pio_tutil.F90]) + +# The user may have changed the MPIEXEC for these test scripts. +AC_CONFIG_FILES([tests/cunit/run_tests.sh], [chmod ugo+x tests/cunit/run_tests.sh]) +AC_CONFIG_FILES([tests/ncint/run_tests.sh], [chmod ugo+x tests/ncint/run_tests.sh]) +AC_CONFIG_FILES([tests/ncint/run_perf.sh], [chmod ugo+x tests/ncint/run_perf.sh]) +AC_CONFIG_FILES([tests/fncint/run_tests.sh], [chmod ugo+x tests/fncint/run_tests.sh]) +AC_CONFIG_FILES([tests/general/run_tests.sh], [chmod ugo+x tests/general/run_tests.sh]) +AC_CONFIG_FILES([tests/performance/run_tests.sh], [chmod ugo+x tests/performance/run_tests.sh]) +AC_CONFIG_FILES([tests/unit/run_tests.sh], [chmod ugo+x tests/unit/run_tests.sh]) +AC_CONFIG_FILES([examples/c/run_tests.sh], [chmod ugo+x examples/c/run_tests.sh]) +AC_CONFIG_FILES([examples/f03/run_tests.sh], [chmod ugo+x examples/f03/run_tests.sh]) + +# Args: +# 1. netcdf_meta.h variable +# 2. conditional variable that is yes or no. +# 3. default condition +# +# example: AX_SET_META([NC_HAS_NC2],[$nc_build_v2],[]) # Because it checks for no. +# AX_SET_META([NC_HAS_HDF4],[$enable_hdf4],[yes]) +AC_DEFUN([AX_SET_META],[ + if [ test "x$2" = x$3 ]; then + AC_SUBST([$1]) $1=1 + else + AC_SUBST([$1]) $1=0 + fi +]) + +##### +# Define values used in include/pio_meta.h +##### +AX_SET_META([PIO_HAS_SZIP_WRITE],[$have_szip_write],[yes]) +AX_SET_META([PIO_HAS_PNETCDF],[$enable_pnetcdf],[yes]) +AX_SET_META([PIO_HAS_PAR_FILTERS], [$have_par_filters],[yes]) +AX_SET_META([PIO_HAS_NETCDF4], [$have_netcdf4],[yes]) +AX_SET_META([PIO_HAS_NETCDF4_PAR], [$have_netcdf_par],[yes]) +AX_SET_META([PIO_HAS_NETCDF_INTEGRATION], [$enable_netcdf_integration],[yes]) + +# Create output variables from various shell variables, for use in +# generating libpio.settings. +AC_SUBST([enable_shared]) +AC_SUBST([enable_static]) +AC_SUBST([CFLAGS]) +AC_SUBST([CPPFLAGS]) +AC_SUBST([FFLAGS]) +AC_SUBST([FCFLAGS]) +AC_SUBST([LDFLAGS]) +AC_SUBST([FPPFLAGS]) # ignored by autotools +AC_SUBST(HAS_PNETCDF,[$enable_pnetcdf]) +AC_SUBST(HAS_LOGGING, [$enable_logging]) +AC_SUBST(HAS_SZIP_WRITE, [$have_szip_write]) +AC_SUBST([HAS_PAR_FILTERS], [$have_par_filters]) +AC_SUBST([HAS_NETCDF4], [$have_netcdf4]) +AC_SUBST([HAS_NETCDF4_PAR], [$have_netcdf_par]) +AC_SUBST([HAS_NETCDF_INTEGRATION], [$enable_netcdf_integration]) +AC_SUBST([HAS_PIO_FORTRAN], [$enable_fortran]) + +# Create the build summary file. +AC_CONFIG_FILES([libpio.settings + src/clib/pio_meta.h + ]) +AC_CONFIG_LINKS([tests/unit/input.nl:tests/unit/input.nl]) + +# Create the config.h file. +AC_CONFIG_HEADERS([config.h]) + +# Create the makefiles. +AC_OUTPUT(Makefile + src/Makefile + src/clib/Makefile + src/ncint/Makefile + src/flib/Makefile + src/gptl/Makefile + tests/Makefile + tests/cunit/Makefile + tests/ncint/Makefile + tests/fncint/Makefile + tests/unit/Makefile + tests/general/Makefile + tests/general/util/Makefile + tests/performance/Makefile + doc/Makefile + doc/source/Makefile + doc/images/Makefile + examples/Makefile + examples/c/Makefile + examples/f03/Makefile + cmake/Makefile + scripts/Makefile) + +# Show the build summary. +cat libpio.settings + + diff --git a/ParallelIO/ctest/CTestEnvironment-alcf.cmake b/ParallelIO/ctest/CTestEnvironment-alcf.cmake new file mode 100644 index 0000000000..607076479d --- /dev/null +++ b/ParallelIO/ctest/CTestEnvironment-alcf.cmake @@ -0,0 +1,14 @@ +#============================================================================== +# +# This file sets the environment variables needed to configure and build +# on the Argonne Leadership Computing Facility systems +# (mira/cetus/vesta/cooley). +# +#============================================================================== + +# Assume all package locations (NetCDF, PnetCDF, HDF5, etc) are already +# set with existing environment variables: NETCDF, PNETCDF, HDF5, etc. + +# Define the extra CMake configure options +set (CTEST_CONFIGURE_OPTIONS "-DCMAKE_VERBOSE_MAKEFILE=TRUE") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPREFER_STATIC=TRUE") diff --git a/ParallelIO/ctest/CTestEnvironment-anlworkstation.cmake b/ParallelIO/ctest/CTestEnvironment-anlworkstation.cmake new file mode 100644 index 0000000000..38e5b4b0a9 --- /dev/null +++ b/ParallelIO/ctest/CTestEnvironment-anlworkstation.cmake @@ -0,0 +1,26 @@ +#============================================================================== +# +# This file sets the environment variables needed to configure and build +# on Argonne Linux workstations +# +#============================================================================== + +# Assume all package locations (NetCDF, PnetCDF, HDF5, etc) are already +# set with existing environment variables: NETCDF, PNETCDF, HDF5, etc. + +# Define the extra CMake configure options +set (CTEST_CONFIGURE_OPTIONS "-DCMAKE_VERBOSE_MAKEFILE=TRUE") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DNetCDF_PATH=$ENV{NETCDFROOT}") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPnetCDF_PATH=$ENV{PNETCDFROOT}") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DHDF5_PATH=$ENV{HDF5ROOT}") + +# If ENABLE_COVERAGE environment variable is set, then enable code coverage +if (DEFINED ENV{ENABLE_COVERAGE}) + set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPIO_ENABLE_COVERAGE=ON") +endif () + +# If VALGRIND_CHECK environment variable is set, then enable memory leak check using Valgrind +if (DEFINED ENV{VALGRIND_CHECK}) + set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPIO_VALGRIND_CHECK=ON") +endif () + diff --git a/ParallelIO/ctest/CTestEnvironment-cgd.cmake b/ParallelIO/ctest/CTestEnvironment-cgd.cmake new file mode 100644 index 0000000000..eb8606e46d --- /dev/null +++ b/ParallelIO/ctest/CTestEnvironment-cgd.cmake @@ -0,0 +1,17 @@ +#============================================================================== +# +# This file sets the environment variables needed to configure and build +# on the NCAR CGD cluster Hobart +# +#============================================================================== + +# Assume all package locations (NetCDF, PnetCDF, HDF5, etc) are already +# set with existing environment variables: NETCDF, PNETCDF, HDF5, etc. + +# Define the extra CMake configure options +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=TRUE -DPNETCDF_DIR=$ENV{PNETCDF_PATH} -DNETCDF_DIR=$ENV{NETCDF_PATH}") + +# If MPISERIAL environment variable is set, then enable MPISERIAL +if (DEFINED ENV{MPISERIAL}) + set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPIO_USE_MPISERIAL=ON") +endif () diff --git a/ParallelIO/ctest/CTestEnvironment-ncsa.cmake b/ParallelIO/ctest/CTestEnvironment-ncsa.cmake new file mode 100644 index 0000000000..706946ec2b --- /dev/null +++ b/ParallelIO/ctest/CTestEnvironment-ncsa.cmake @@ -0,0 +1,22 @@ +#============================================================================== +# +# This file sets the environment variables needed to configure and build +# on the NCSA systems +# (Blue Waters). +# +#============================================================================== + +# Assume all package locations (NetCDF, PnetCDF, HDF5, etc) are already +# set with existing environment variables: NETCDF, PNETCDF, HDF5, etc. + +# Define the extra CMake configure options +set (CTEST_CONFIGURE_OPTIONS "-DCMAKE_VERBOSE_MAKEFILE=TRUE") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPREFER_STATIC=TRUE") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DNetCDF_PATH=$ENV{NETCDF_DIR}") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPnetCDF_PATH=$ENV{PARALLEL_NETCDF_DIR}") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DHDF5_PATH=$ENV{HDF5_DIR}") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_C_INCLUDE_PATH=$ENV{MPICH_DIR}/include") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_Fortran_INCLUDE_PATH=$ENV{MPICH_DIR}/include") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_C_LIBRARIES=$ENV{MPICH_DIR}/lib/libmpich.a") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_Fortran_LIBRARIES=$ENV{MPICH_DIR}/lib/libmpichf90.a") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DCMAKE_SYSTEM_NAME=Catamount") diff --git a/ParallelIO/ctest/CTestEnvironment-nersc.cmake b/ParallelIO/ctest/CTestEnvironment-nersc.cmake new file mode 100644 index 0000000000..6b1ac8fa79 --- /dev/null +++ b/ParallelIO/ctest/CTestEnvironment-nersc.cmake @@ -0,0 +1,22 @@ +#============================================================================== +# +# This file sets the environment variables needed to configure and build +# on the NERSC systems +# (edison/ corip1). +# +#============================================================================== + +# Assume all package locations (NetCDF, PnetCDF, HDF5, etc) are already +# set with existing environment variables: NETCDF, PNETCDF, HDF5, etc. + +# Define the extra CMake configure options +set (CTEST_CONFIGURE_OPTIONS "-DCMAKE_VERBOSE_MAKEFILE=TRUE") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPREFER_STATIC=TRUE") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DNETCDF_DIR=$ENV{NETCDF_DIR}") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPNETCDF_DIR=$ENV{PARALLEL_NETCDF_DIR}") +#set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DHDF5_PATH=$ENV{HDF5_DIR}") +#set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_C_INCLUDE_PATH=$ENV{MPICH_DIR}/include") +#set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_Fortran_INCLUDE_PATH=$ENV{MPICH_DIR}/include") +#set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_C_LIBRARIES=$ENV{MPICH_DIR}/lib/libmpich.a") +#set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DMPI_Fortran_LIBRARIES=$ENV{MPICH_DIR}/lib/libmpichf90.a") +set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DCMAKE_SYSTEM_NAME=Catamount") diff --git a/ParallelIO/ctest/CTestEnvironment-nwscla.cmake b/ParallelIO/ctest/CTestEnvironment-nwscla.cmake new file mode 100644 index 0000000000..efee6bf659 --- /dev/null +++ b/ParallelIO/ctest/CTestEnvironment-nwscla.cmake @@ -0,0 +1,18 @@ +#============================================================================== +# +# This file sets the environment variables needed to configure and build +# on the new NCAR Wyoming Supercomputing Center systems +# (laramie/cheyenne). +# +#============================================================================== + +# Assume all package locations (NetCDF, PnetCDF, HDF5, etc) are already +# set with existing environment variables: NETCDF, PNETCDF, HDF5, etc. + +# Define the extra CMake configure options +set (CTEST_CONFIGURE_OPTIONS "-DCMAKE_VERBOSE_MAKEFILE=TRUE ") + +# If MPISERIAL environment variable is set, then enable MPISERIAL +if (DEFINED ENV{MPISERIAL}) + set (CTEST_CONFIGURE_OPTIONS "${CTEST_CONFIGURE_OPTIONS} -DPIO_USE_MPISERIAL=ON") +endif () diff --git a/ParallelIO/ctest/CTestEnvironment-unknown.cmake b/ParallelIO/ctest/CTestEnvironment-unknown.cmake new file mode 100644 index 0000000000..8d51f15fff --- /dev/null +++ b/ParallelIO/ctest/CTestEnvironment-unknown.cmake @@ -0,0 +1,12 @@ +#============================================================================== +# +# This file sets the CMake variables needed to configure and build +# on the default ("unknown") system. +# +#============================================================================== + +# Assume all package locations (NetCDF, PnetCDF, HDF5, etc) are already +# set with existing environment variables: NETCDF, PNETCDF, HDF5, etc. + +# Define the extra CMake configure options +set (CTEST_CONFIGURE_OPTIONS "-DCMAKE_VERBOSE_MAKEFILE=TRUE") diff --git a/ParallelIO/ctest/CTestScript-Test.cmake b/ParallelIO/ctest/CTestScript-Test.cmake new file mode 100644 index 0000000000..cf50195a25 --- /dev/null +++ b/ParallelIO/ctest/CTestScript-Test.cmake @@ -0,0 +1,29 @@ +#============================================================================== +# +# This is the CTest script for generating test results for submission to the +# CTest Dashboard site: my.cdash.org. +# +# Example originally stolen from: +# http://www.vtk.org/Wiki/CTest:Using_CTEST_and_CDASH_without_CMAKE +#============================================================================== + +#------------------------------------------- +#-- Get the common build information +#------------------------------------------- + +set (CTEST_SITE $ENV{PIO_DASHBOARD_SITE}-$ENV{PIO_COMPILER_ID}) +set (CTEST_BUILD_NAME $ENV{PIO_DASHBOARD_BUILD_NAME}) +set (CTEST_SOURCE_DIRECTORY $ENV{PIO_DASHBOARD_SOURCE_DIR}) +set (CTEST_BINARY_DIRECTORY $ENV{PIO_DASHBOARD_BINARY_DIR}) + +# ----------------------------------------------------------- +# -- Run CTest- TESTING ONLY (Appended to existing TAG) +# ----------------------------------------------------------- + +## -- Start +ctest_start("${CTEST_SCRIPT_ARG}" APPEND) + +## -- TEST +ctest_test() + +## Don't submit! Submission handled by main CTestScript diff --git a/ParallelIO/ctest/runcdash-alcf-ibm.sh b/ParallelIO/ctest/runcdash-alcf-ibm.sh new file mode 100755 index 0000000000..9f36996bda --- /dev/null +++ b/ParallelIO/ctest/runcdash-alcf-ibm.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +# Manually set environment variables for CTest run/build +GIT=/soft/versioning/git/2.3.0/bin/git +CTEST=/soft/buildtools/cmake/3.3.0/bin/ctest + +export LIBZ=/soft/libraries/alcf/current/xl/ZLIB +export HDF5=/soft/libraries/hdf5/1.8.14/cnk-xl/V1R2M2-20150213 +export NETCDF=/soft/libraries/netcdf/4.3.3-f4.4.1/cnk-xl/V1R2M2-20150213 +export PNETCDF=/soft/libraries/pnetcdf/1.6.0/cnk-xl/V1R2M2-20150213 + +export CC=/soft/compilers/wrappers/xl/mpixlc_r +export FC=/soft/compilers/wrappers/xl/mpixlf90_r + +export PIO_DASHBOARD_ROOT=`pwd`/dashboard +export PIO_COMPILER_ID=Cray-`$CC -qversion | head -n 2 | tail -n 1 | cut -d' ' -f2` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + $GIT clone https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + +$CTEST -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-anlworkstation.sh b/ParallelIO/ctest/runcdash-anlworkstation.sh new file mode 100755 index 0000000000..44651b2f3e --- /dev/null +++ b/ParallelIO/ctest/runcdash-anlworkstation.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +source /software/common/adm/packages/softenv-1.6.2/etc/softenv-load.sh +source /software/common/adm/packages/softenv-1.6.2/etc/softenv-aliases.sh + +soft add +gcc-6.2.0 +soft add +mpich-3.2-gcc-6.2.0 +soft add +cmake-3.5.1 + +export NETCDFROOT=/soft/apps/packages/climate/netcdf/4.4.1c-4.2cxx-4.4.4f-parallel/gcc-6.2.0 +export PNETCDFROOT=/soft/apps/packages/climate/pnetcdf/1.7.0/gcc-6.2.0 +export HDF5ROOT=/soft/apps/packages/climate/hdf5/1.8.16-parallel/gcc-6.2.0 + +export CC=mpicc +export FC=mpifort + +export PIO_DASHBOARD_SITE=anlworkstation-`hostname` +export PIO_DASHBOARD_ROOT=/sandbox/dashboard +export CTEST_SCRIPT_DIRECTORY=${PIO_DASHBOARD_ROOT}/src +export PIO_DASHBOARD_SOURCE_DIR=${CTEST_SCRIPT_DIRECTORY} +export PIO_COMPILER_ID=gcc-`gcc --version | head -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +echo "CTEST_SCRIPT_DIRECTORY="${CTEST_SCRIPT_DIRECTORY} +echo "PIO_DASHBOARD_SOURCE_DIR="${PIO_DASHBOARD_SOURCE_DIR} + +if [ ! -d src ]; then + git clone --branch develop https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-cgd-gnu-openmpi.sh b/ParallelIO/ctest/runcdash-cgd-gnu-openmpi.sh new file mode 100755 index 0000000000..57cad94053 --- /dev/null +++ b/ParallelIO/ctest/runcdash-cgd-gnu-openmpi.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module purge +module load compiler/gnu/5.4.0 +module load tool/parallel-netcdf/1.8.1/gnu-5.4.0/openmpi + +export CC=mpicc +export FC=mpif90 +export PIO_DASHBOARD_SITE="cgd" +export PIO_DASHBOARD_ROOT=/scratch/cluster/jedwards/dashboard +export CTEST_SCRIPT_DIRECTORY=${PIO_DASHBOARD_ROOT}/src +export PIO_DASHBOARD_SOURCE_DIR=${CTEST_SCRIPT_DIRECTORY} +export PIO_COMPILER_ID=gcc-`gcc --version | head -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +echo "CTEST_SCRIPT_DIRECTORY="${CTEST_SCRIPT_DIRECTORY} +echo "PIO_DASHBOARD_SOURCE_DIR="${PIO_DASHBOARD_SOURCE_DIR} + +if [ ! -d src ]; then + git clone --branch develop https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + + +ctest -S CTestScript.cmake,${model} -VV -DCTEST_CONFIGURE_OPTIONS="-DCMAKE_EXE_LINKER_FLAGS=-ldl" diff --git a/ParallelIO/ctest/runcdash-cgd-nag.sh b/ParallelIO/ctest/runcdash-cgd-nag.sh new file mode 100755 index 0000000000..e413186131 --- /dev/null +++ b/ParallelIO/ctest/runcdash-cgd-nag.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module purge +module load compiler/nag/6.1 +module load tool/parallel-netcdf/1.7.0/nag/mvapich2 + +export CC=mpicc +export FC=mpif90 +export PIO_DASHBOARD_SITE="cgd" +export PIO_DASHBOARD_ROOT=/scratch/cluster/jedwards/dashboard +export CTEST_SCRIPT_DIRECTORY=${PIO_DASHBOARD_ROOT}/src +export PIO_DASHBOARD_SOURCE_DIR=${CTEST_SCRIPT_DIRECTORY} +export PIO_COMPILER_ID=Nag-6.1-gcc-`gcc --version | head -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +echo "CTEST_SCRIPT_DIRECTORY="${CTEST_SCRIPT_DIRECTORY} +echo "PIO_DASHBOARD_SOURCE_DIR="${PIO_DASHBOARD_SOURCE_DIR} + +if [ ! -d src ]; then + git clone --branch develop https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-nersc-cray.sh b/ParallelIO/ctest/runcdash-nersc-cray.sh new file mode 100755 index 0000000000..d3516cea7d --- /dev/null +++ b/ParallelIO/ctest/runcdash-nersc-cray.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module rm PrgEnv-intel +module rm PrgEnv-cray +module rm PrgEnv-gnu +module rm intel +module rm cce +module rm cray-parallel-netcdf +module rm cray-parallel-hdf5 +module rm pmi +module rm cray-libsci +module rm cray-mpich2 +module rm cray-mpich +module rm cray-netcdf +module rm cray-hdf5 +module rm cray-netcdf-hdf5parallel +module rm craype-sandybridge +module rm craype-ivybridge +module rm craype-haswell +module rm craype +module load PrgEnv-cray + +case "$NERSC_HOST" in + edison) + cd $CSCRATCH/dashboard + module switch cce cce/8.5.1 + module load craype-ivybridge + module load git/2.4.6 + module load cmake/3.3.2 + module load cray-hdf5-parallel/1.8.16 + module load cray-netcdf-hdf5parallel/4.3.3.1 + module load cray-parallel-netcdf/1.7.0 + ;; + cori) + cd $SCRATCH/dashboard + module switch cce cce/8.5.4 + module load craype-mic-knl + module load git/2.9.1 + module load cmake/3.3.2 + module load cray-hdf5-parallel/1.8.16 + module load cray-netcdf-hdf5parallel/4.3.3.1 + module load cray-parallel-netcdf/1.7.0 + ;; + +esac + +export CC=cc +export FC=ftn + +export PIO_DASHBOARD_ROOT=`pwd`/dashboard +export PIO_COMPILER_ID=Cray-`$CC -V 2>&1 | cut -d' ' -f5` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + git clone --branch develop https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + +export HDF5_DISABLE_VERSION_CHECK=2 + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-nersc-intel.sh b/ParallelIO/ctest/runcdash-nersc-intel.sh new file mode 100755 index 0000000000..55c80559b6 --- /dev/null +++ b/ParallelIO/ctest/runcdash-nersc-intel.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module rm PrgEnv-intel +module rm PrgEnv-cray +module rm PrgEnv-gnu +module rm intel +module rm cce +module rm cray-parallel-netcdf +module rm cray-parallel-hdf5 +module rm pmi +module rm cray-libsci +module rm cray-mpich2 +module rm cray-mpich +module rm cray-netcdf +module rm cray-hdf5 +module rm cray-netcdf-hdf5parallel +module rm craype-sandybridge +module rm craype-ivybridge +module rm craype-haswell +module rm craype +module load PrgEnv-intel + +case "$NERSC_HOST" in + edison) + cd $CSCRATCH/dashboard + module switch intel intel/16.0.0.109 + module load craype-ivybridge + module load git/2.4.6 + module load cmake/3.3.2 + module load cray-hdf5-parallel/1.8.16 + module load cray-netcdf-hdf5parallel/4.3.3.1 + module load cray-parallel-netcdf/1.7.0 + ;; + cori) + cd $SCRATCH/dashboard + module switch intel intel/17.0.1.132 + module load craype-mic-knl + module load git/2.9.1 + module load cmake/3.3.2 + module load cray-hdf5-parallel/1.8.16 + module load cray-netcdf-hdf5parallel/4.3.3.1 + module load cray-parallel-netcdf/1.7.0 + ;; + +esac + +export CC=cc +export FC=ftn + +export PIO_DASHBOARD_ROOT=`pwd`/dashboard +export PIO_COMPILER_ID=Intel-`$CC --version | head -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + git clone --branch develop https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + +export HDF5_DISABLE_VERSION_CHECK=2 +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-nwsc-intel-mpiserial.sh b/ParallelIO/ctest/runcdash-nwsc-intel-mpiserial.sh new file mode 100755 index 0000000000..68ac5826be --- /dev/null +++ b/ParallelIO/ctest/runcdash-nwsc-intel-mpiserial.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module reset +module unload netcdf +module swap intel intel/15.0.3 +module load git/2.3.0 +module load cmake/3.0.2 +module load netcdf/4.3.3.1 + +export MPISERIAL=/glade/u/home/jedwards/mpi-serial/intel15.0.3/ + +export CC=icc +export FC=ifort + +export PIO_DASHBOARD_ROOT=`pwd`/dashboard +export PIO_COMPILER_ID=Serial-Intel-`$CC --version | head -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + git clone --branch develop https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-nwsc-intel.sh b/ParallelIO/ctest/runcdash-nwsc-intel.sh new file mode 100755 index 0000000000..1e72e9a1b3 --- /dev/null +++ b/ParallelIO/ctest/runcdash-nwsc-intel.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module reset +module unload netcdf +module swap intel intel/16.0.3 +module load git/2.3.0 +module load cmake/3.0.2 +module load netcdf-mpi/4.4.1 +module load pnetcdf/1.7.0 + +export CC=mpicc +export FC=mpif90 + +export PIO_DASHBOARD_ROOT=`pwd`/dashboard +export PIO_COMPILER_ID=Intel-`$CC --version | head -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + git clone --branch develop https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout develop +git pull origin develop + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-nwscla-gnu.sh b/ParallelIO/ctest/runcdash-nwscla-gnu.sh new file mode 100755 index 0000000000..ba6b60a5d8 --- /dev/null +++ b/ParallelIO/ctest/runcdash-nwscla-gnu.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module reset +module unload netcdf +module swap intel gnu/10.1.0 +module swap mpt openmpi/4.0.3 +module load git +module load cmake +module load netcdf-mpi/4.7.3 +module load pnetcdf/1.12.1 + +export CC=mpicc +export FC=mpif90 + +export PIO_DASHBOARD_ROOT=/glade/u/home/jedwards/sandboxes/dashboard +export PIO_COMPILER_ID=GNU-`$CC --version | head -n 1 | tail -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + git clone https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout master +git pull origin master + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-nwscla-intel.sh b/ParallelIO/ctest/runcdash-nwscla-intel.sh new file mode 100755 index 0000000000..e85d5760c0 --- /dev/null +++ b/ParallelIO/ctest/runcdash-nwscla-intel.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +source /etc/profile.d/modules.sh + +module reset +module unload netcdf +module swap intel intel/19.1.1 +module switch mpt mpt/2.22 +module load cmake/3.18.2 +module load netcdf-mpi/4.7.3 +module load pnetcdf/1.12.1 +echo "MODULE LIST..." +module list + +export CC=mpicc +export FC=mpif90 +export MPI_TYPE_DEPTH=24 +export PIO_DASHBOARD_ROOT=/glade/scratch/jedwards/dashboard +export PIO_COMPILER_ID=Intel-`$CC --version | head -n 1 | cut -d' ' -f3` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + git clone https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout master +git pull origin master + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runcdash-nwscla-pgi.sh b/ParallelIO/ctest/runcdash-nwscla-pgi.sh new file mode 100755 index 0000000000..8d9c0cde8b --- /dev/null +++ b/ParallelIO/ctest/runcdash-nwscla-pgi.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# Get/Generate the Dashboard Model +if [ $# -eq 0 ]; then + model=Experimental +else + model=$1 +fi + +module reset +module unload netcdf +module swap intel pgi/20.4 +module swap mpt mpt/2.22 +module load git/2.22.0 +module load cmake/3.18.2 +module load netcdf-mpi/4.7.3 +module load pnetcdf/1.12.1 + +export CC=mpicc +export FC=mpif90 +export MPI_TYPE_DEPTH=24 +export PIO_DASHBOARD_ROOT=/glade/u/home/jedwards/sandboxes/dashboard +export PIO_COMPILER_ID=PGI-`$CC --version | head -n 2 | tail -n 1 | cut -d' ' -f4` + +if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then + mkdir "$PIO_DASHBOARD_ROOT" +fi +cd "$PIO_DASHBOARD_ROOT" + +if [ ! -d src ]; then + git clone https://github.com/PARALLELIO/ParallelIO src +fi +cd src +git checkout master +git pull origin master + +ctest -S CTestScript.cmake,${model} -VV diff --git a/ParallelIO/ctest/runctest-alcf.sh b/ParallelIO/ctest/runctest-alcf.sh new file mode 100755 index 0000000000..6b5fa20f1c --- /dev/null +++ b/ParallelIO/ctest/runctest-alcf.sh @@ -0,0 +1,42 @@ +#!/bin/sh +#============================================================================== +# +# This script defines how to run CTest on the Argonne Leadership Computing +# Facility systems (mira/cetus/vesta/cooley). +# +# This assumes the CTest model name (e.g., "Nightly") is passed to it when +# run. +# +#============================================================================== + +# Get the CTest script directory +scrdir=$1 + +# Get the CTest model name +model=$2 + +# Write QSUB submission script with the test execution command +echo "#!/bin/sh" > runctest.sh +echo "CTESTCMD=`which ctest`" >> runctest.sh +echo "\$CTESTCMD -S ${scrdir}/CTestScript-Test.cmake,${model} -V" >> runctest.sh + +# Make the QSUB script executable +chmod +x runctest.sh + +# Submit the job to the queue +jobid=`qsub -t 20 -n 4 --proccount 4 \ + --env PIO_DASHBOARD_SITE=$PIO_DASHBOARD_SITE \ + --env PIO_DASHBOARD_BUILD_NAME=$PIO_DASHBOARD_BUILD_NAME \ + --env PIO_DASHBOARD_SOURCE_DIR=$PIO_DASHBOARD_SOURCE_DIR \ + --env PIO_DASHBOARD_BINARY_DIR=$PIO_DASHBOARD_BINARY_DIR \ + --mode script runctest.sh` + +# Wait for the job to complete before exiting +while true; do + status=`qstat $jobid` + if [ "$status" == "" ]; then + break + else + sleep 10 + fi +done diff --git a/ParallelIO/ctest/runctest-anlworkstation.sh b/ParallelIO/ctest/runctest-anlworkstation.sh new file mode 100755 index 0000000000..9718a83480 --- /dev/null +++ b/ParallelIO/ctest/runctest-anlworkstation.sh @@ -0,0 +1,18 @@ +#!/bin/sh +#============================================================================== +# +# This script defines how to run CTest on the Argonne Linux workstations. +# +# This assumes the CTest model name (e.g., "Nightly") is passed to it when +# run. +# +#============================================================================== + +# Get the CTest script directory +scrdir=$1 + +# Get the CTest model name +model=$2 + +# Run the "ctest" command in another process +ctest -S ${scrdir}/CTestScript-Test.cmake,${model} -V diff --git a/ParallelIO/ctest/runctest-cgd.sh b/ParallelIO/ctest/runctest-cgd.sh new file mode 100755 index 0000000000..bbd31ccf5d --- /dev/null +++ b/ParallelIO/ctest/runctest-cgd.sh @@ -0,0 +1,45 @@ +#!/bin/sh +#============================================================================== +# +# This script defines how to run CTest on the NCAR CGD local cluster +# Hobart. +# +# This assumes the CTest model name (e.g., "Nightly") is passed to it when +# run. +# +#============================================================================== + +# Get the CTest script directory +scrdir=$1 + +# Get the CTest model name +model=$2 + +# Write QSUB submission script with the test execution command +echo "#!/bin/sh" > runctest.sh +echo "export PIO_DASHBOARD_BUILD_NAME=${PIO_DASHBOARD_BUILD_NAME}" >> runctest.sh +echo "export PIO_DASHBOARD_SOURCE_DIR=${PIO_DASHBOARD_BINARY_DIR}/../src/" >> runctest.sh +echo "export PIO_DASHBOARD_BINARY_DIR=${PIO_DASHBOARD_BINARY_DIR}" >> runctest.sh +echo "export PIO_DASHBOARD_SITE=cgd-${HOSTNAME}" >> runctest.sh + +echo "CTESTCMD=`which ctest`" >> runctest.sh +echo "\$CTESTCMD -S ${scrdir}/CTestScript-Test.cmake,${model} -V" >> runctest.sh + +# Make the QSUB script executable +chmod +x runctest.sh + +# Submit the job to the queue +jobid=`/usr/local/bin/qsub -l nodes=1:ppn=8 runctest.sh -q short` + +# Wait for the job to complete before exiting +while true; do + status=`/usr/local/bin/qstat $jobid` + echo $status + if [ "$status" == "" ]; then + break + else + sleep 10 + fi +done + +exit 0 diff --git a/ParallelIO/ctest/runctest-ncsa.sh b/ParallelIO/ctest/runctest-ncsa.sh new file mode 100755 index 0000000000..c3cd75e300 --- /dev/null +++ b/ParallelIO/ctest/runctest-ncsa.sh @@ -0,0 +1,39 @@ +#!/bin/sh +#============================================================================== +# +# This script defines how to run CTest on the National Center for +# Supercomputing Applications system (blue waters). +# +# This assumes the CTest model name (e.g., "Nightly") is passed to it when +# run. +# +#============================================================================== + +# Get the CTest script directory +scrdir=$1 + +# Get the CTest model name +model=$2 + +# Write QSUB submission script with the test execution command +echo "#!/bin/sh" > runctest.pbs +echo "#PBS -q debug" >> runctest.pbs +echo "#PBS -l mppwidth=24" >> runctest.pbs +echo "#PBS -l walltime=00:20:00" >> runctest.pbs +echo "#PBS -v PIO_DASHBOARD_SITE,PIO_DASHBOARD_BUILD_NAME,PIO_DASHBOARD_SOURCE_DIR,PIO_DASHBOARD_BINARY_DIR" >> runctest.pbs +echo "cd \$PBS_O_WORKDIR" >> runctest.pbs +echo "CTEST_CMD=`which ctest`" >> runctest.pbs +echo "\$CTEST_CMD -S ${scrdir}/CTestScript-Test.cmake,${model} -V" >> runctest.pbs + +# Submit the job to the queue +jobid=`qsub runctest.pbs` + +# Wait for the job to complete before exiting +while true; do + status=`qstat $jobid` + if [ "$status" == "" ]; then + break + else + sleep 10 + fi +done diff --git a/ParallelIO/ctest/runctest-nersc.sh b/ParallelIO/ctest/runctest-nersc.sh new file mode 100755 index 0000000000..a84d26bbeb --- /dev/null +++ b/ParallelIO/ctest/runctest-nersc.sh @@ -0,0 +1,57 @@ +#!/bin/sh +#============================================================================== +# +# This script defines how to run CTest on the National Energy Research +# Scientific Computing Center systems (edison/cori). +# +# This assumes the CTest model name (e.g., "Nightly") is passed to it when +# run. +# +#============================================================================== + +# Get the CTest script directory +scrdir=$1 + +# Get the CTest model name +model=$2 + +# Write QSUB submission script with the test execution command +echo "#!/bin/sh" > runctest.slurm +echo "#SBATCH --partition debug" >> runctest.slurm +echo "#SBATCH --nodes=1" >> runctest.slurm +case "$NERSC_HOST" in + edison) + echo "#SBATCH --ntasks-per-node=32" >> runctest.slurm + ;; + cori) + echo "#SBATCH --ntasks-per-node=68" >> runctest.slurm + echo "#SBATCH -C knl" >> runctest.slurm + ;; +esac + +echo "#SBATCH --time=01:00:00" >> runctest.slurm + +echo "#SBATCH --export PIO_DASHBOARD_SITE,PIO_DASHBOARD_BUILD_NAME,PIO_DASHBOARD_SOURCE_DIR,PIO_DASHBOARD_BINARY_DIR" >> runctest.slurm +#echo "cd \$PBS_O_WORKDIR" >> runctest.pbs +echo "CTEST_CMD=`which ctest`" >> runctest.slurm +echo "\$CTEST_CMD -S ${scrdir}/CTestScript-Test.cmake,${model} -V" >> runctest.slurm +chmod +x runctest.slurm +# Submit the job to the queue +#jobid=`sbatch runctest.slurm| egrep -o -e "\b[0-9]+$"` +case "$NERSC_HOST" in + edison) + salloc -N 1 ./runctest.slurm + ;; + cori) + salloc -N 1 -C knl ./runctest.slurm + ;; +esac +# Wait for the job to complete before exiting +#while true; do +# status=`squeue -j $jobid` +# if [ "$status" == "" ]; then +# break +# else +# sleep 10 +# fi +#done diff --git a/ParallelIO/ctest/runctest-nwscla.sh b/ParallelIO/ctest/runctest-nwscla.sh new file mode 100755 index 0000000000..d3e252317d --- /dev/null +++ b/ParallelIO/ctest/runctest-nwscla.sh @@ -0,0 +1,44 @@ +#!/bin/sh +#============================================================================== +# +# This script defines how to run CTest on the NCAR Wyoming Supercomputing +# Center systems (cheyenne/laramie). +# +# This assumes the CTest model name (e.g., "Nightly") is passed to it when +# run. +# +#============================================================================== + +# Get the CTest script directory +scrdir=$1 + +# Get the CTest model name +model=$2 + +# Write QSUB submission script with the test execution command +echo "#!/bin/sh" > runctest.sh +echo "#PBS -l walltime=01:00:00" >> runctest.sh +echo "#PBS -l select=1:ncpus=8:mpiprocs=8" >> runctest.sh +echo "#PBS -A P93300606" >> runctest.sh +echo "#PBS -q regular" >> runctest.sh +echo "export PIO_DASHBOARD_SITE=nwscla-${HOSTNAME}" >> runctest.sh +echo "CTESTCMD=`which ctest`" >> runctest.sh +echo "\$CTESTCMD -S ${scrdir}/CTestScript-Test.cmake,${model} -V" >> runctest.sh + +# Make the QSUB script executable +chmod +x runctest.sh + +# Submit the job to the queue +jobid=`qsub -l walltime=01:00:00 runctest.sh` + +# Wait for the job to complete before exiting +while true; do + qstat $jobid + if [ $? -eq 0 ]; then + sleep 30 + else + break; + fi +done + +exit 0 diff --git a/ParallelIO/ctest/runctest-unknown.sh b/ParallelIO/ctest/runctest-unknown.sh new file mode 100755 index 0000000000..01ba66403c --- /dev/null +++ b/ParallelIO/ctest/runctest-unknown.sh @@ -0,0 +1,18 @@ +#!/bin/sh +#============================================================================== +# +# This script defines how to run CTest on the default ("unknown") machine. +# +# This assumes the CTest model name (e.g., "Nightly") is passed to it when +# run. +# +#============================================================================== + +# Get the CTest script directory +scrdir=$1 + +# Get the dashboard model name +model=$2 + +# Run the "ctest" command in another process +ctest -S ${scrdir}/CTestScript-Test.cmake,${model} -V diff --git a/ParallelIO/doc/CMakeFiles/3.2.3/CMakeSystem.cmake b/ParallelIO/doc/CMakeFiles/3.2.3/CMakeSystem.cmake new file mode 100644 index 0000000000..c94e370e1b --- /dev/null +++ b/ParallelIO/doc/CMakeFiles/3.2.3/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-3.10.0-123.el7.x86_64") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "3.10.0-123.el7.x86_64") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-3.10.0-123.el7.x86_64") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "3.10.0-123.el7.x86_64") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/ParallelIO/doc/CMakeFiles/cmake.check_cache b/ParallelIO/doc/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000000..3dccd73172 --- /dev/null +++ b/ParallelIO/doc/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/ParallelIO/doc/CMakeLists.txt b/ParallelIO/doc/CMakeLists.txt new file mode 100644 index 0000000000..5c7894b599 --- /dev/null +++ b/ParallelIO/doc/CMakeLists.txt @@ -0,0 +1,43 @@ +#============================================================================== +# +# API documentation with Doxygen +# +#============================================================================== + +find_package(Doxygen) + +if(DOXYGEN_FOUND) + # This supports the build with/witout internal documentation. + if (PIO_INTERNAL_DOC) + SET(C_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/../src/clib") + else () + SET(C_SRC_FILES + "${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pioc.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pio_nc4.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pio_darray.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pio_get_nc.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pio_put_nc.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pioc_async.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pio_file.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pio.h \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pio_nc.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/topology.c \\ +${CMAKE_CURRENT_SOURCE_DIR}/../src/clib/pioc_sc.c" ) + endif () + + # Process the Doxyfile using options set during configure. + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in + ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + + # Copy necessary files. + add_custom_target(doc + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/customdoxygen.css + ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/DoxygenLayout.xml + ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.sty + ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM) +endif(DOXYGEN_FOUND) diff --git a/ParallelIO/doc/Doxyfile.in b/ParallelIO/doc/Doxyfile.in new file mode 100644 index 0000000000..713d3b56aa --- /dev/null +++ b/ParallelIO/doc/Doxyfile.in @@ -0,0 +1,2389 @@ +# Doxyfile 1.8.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = PIO + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = .. + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = YES + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = f90=Fortran + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = @CMAKE_CURRENT_SOURCE_DIR@/DoxygenLayout.xml + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = NO + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = doxywarn.log + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../doc/source \ + @CMAKE_CURRENT_SOURCE_DIR@/../examples/c \ + @CMAKE_CURRENT_SOURCE_DIR@/../examples/f03 \ + @FORTRAN_SRC_FILES@ \ + @C_SRC_FILES@ + + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.h \ + *.inc \ + *.dox \ + *.f90 \ + *.F90 \ + *.txt + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = gptl \ + @CMAKE_BINARY_DIR@/src/flib/*.dir \ + @CMAKE_BINARY_DIR@/src/flib/genf90 \ + ../src/clib/uthash.h \ + _UNUSED_ + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = ./source/example \ + ../examples/basic + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = ./images + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: NO. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = docs + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +#HTML_EXTRA_STYLESHEET = ../../docs/customdoxygen.css +HTML_EXTRA_STYLESHEET = customdoxygen.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /