From e90ffebadb0f9c5a11b7a76cc4ad1a098552c068 Mon Sep 17 00:00:00 2001 From: Chris Marsh Date: Fri, 30 Oct 2020 15:34:13 -0600 Subject: [PATCH 001/266] use std::inf and std::isnan for gcc5.4 compatibility --- src/Infrastructure/Mesh/src/Moab/moab/Util.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/Mesh/src/Moab/moab/Util.hpp b/src/Infrastructure/Mesh/src/Moab/moab/Util.hpp index 4540068df0..b7823e10bd 100644 --- a/src/Infrastructure/Mesh/src/Moab/moab/Util.hpp +++ b/src/Infrastructure/Mesh/src/Moab/moab/Util.hpp @@ -29,7 +29,7 @@ #elif defined MOAB_HAVE_FINITE #define moab_isfinite(f) finite(f) #else -#define moab_isfinite(f) (!isinf(f) && !isnan(f)) +#define moab_isfinite(f) (!std::isinf(f) && !std::isnan(f)) #endif namespace moab { From 9c36a95ffb84a6ee9f37ee0f1233512b23777502 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 22 Feb 2021 08:47:06 -0800 Subject: [PATCH 002/266] Align with intelclang configuration - mostly dealing with correct Clang runtime lib selection. --- .../build_rules.mk | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/build_config/Darwin.gfortranclang.default/build_rules.mk b/build_config/Darwin.gfortranclang.default/build_rules.mk index b8eccde15c..81add887f8 100644 --- a/build_config/Darwin.gfortranclang.default/build_rules.mk +++ b/build_config/Darwin.gfortranclang.default/build_rules.mk @@ -10,7 +10,7 @@ ESMF_F90DEFAULT = gfortran ESMF_CXXDEFAULT = clang ESMF_CPPDEFAULT = clang -E -P -x c -ESMF_CXXCOMPILECPPFLAGS += -x c++ +ESMF_CXXCOMPILEOPTS += -x c++ -mmacosx-version-min=10.7 -stdlib=libc++ ############################################################ # Default MPI setting. @@ -208,22 +208,6 @@ ESMF_F90COMPILEOPTS += -ffree-line-length-none ESMF_F90RPATHPREFIX = -Wl,-rpath, ESMF_CXXRPATHPREFIX = -Wl,-rpath, -############################################################ -# Determine where clang's libraries are located -# -# TODO: The -print-file-name option doesn't seem to work properly yet. -#ESMF_LIBSTDCXX := $(shell $(ESMF_CXXCOMPILER) -print-file-name=libstdc++.dylib) -#ifeq ($(ESMF_LIBSTDCXX),libstdc++.dylib) -#ESMF_LIBSTDCXX := $(shell $(ESMF_CXXCOMPILER) -print-file-name=libstdc++.a) -#endif -#ESMF_F90LINKPATHS += -L$(dir $(ESMF_LIBSTDCXX)) - -#ESMF_LIBCXX := $(shell $(ESMF_CXXCOMPILER) -print-file-name=libc++.dylib) -#ifeq ($(ESMF_LIBCXX),libc++.dylib) -#ESMF_LIBCXX := $(shell $(ESMF_CXXCOMPILER) -print-file-name=libc++.a) -#endif -#ESMF_F90LINKPATHS += -L$(dir $(ESMF_LIBCXX)) - ############################################################ # Determine where gfortran's libraries are located # @@ -234,15 +218,25 @@ endif ESMF_CXXLINKPATHS += -L$(dir $(ESMF_LIBGFORTRAN)) ESMF_CXXLINKRPATHS += $(ESMF_CXXRPATHPREFIX)$(dir $(ESMF_LIBGFORTRAN)) +############################################################ +# Link against the c++ library +# +ESMF_LIBSTDCXX := $(shell $(ESMF_CXXCOMPILER) -print-file-name=libc++.dylib) +ifeq ($(ESMF_LIBSTDCXX),libc++.dylib) +ESMF_LIBSTDCXX := $(shell $(ESMF_CXXCOMPILER) -print-file-name=libc++.a) +endif +ESMF_F90LINKPATHS += -L$(dir $(ESMF_LIBSTDCXX)) +ESMF_F90LINKLIBS += -lc++ + ############################################################ # Link against libesmf.a using the F90 linker front-end # -ESMF_F90LINKLIBS += -lstdc++ -lc++ +ESMF_F90LINKLIBS += -lm ############################################################ # Link against libesmf.a using the C++ linker front-end # -ESMF_CXXLINKLIBS += -lgfortran -lstdc++ -lc++ +ESMF_CXXLINKLIBS += -lgfortran -lc++ ############################################################ # Shared library options From 237317cfb101ec7a274188420611994063374a80 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 25 Mar 2022 08:15:18 -0700 Subject: [PATCH 003/266] Low level changes to support messages larger than 2^31 going into MPI layer. Have blocking calls covered. Non-blocking, including VMEpoch handling outstanding. Also XXE layer outstanding. --- .../VM/include/ESMCI_VMKernel.h | 11 +- src/Infrastructure/VM/interface/ESMCI_VM_F.C | 16 +-- src/Infrastructure/VM/interface/ESMF_VM.F90 | 126 ++++++++++-------- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 94 +++++++++++-- 4 files changed, 163 insertions(+), 84 deletions(-) diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index 5edae9e106..8e383cae7b 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -63,6 +63,9 @@ enum vmEpoch { epochNone=0, epochBuffer}; #define VM_ANY_SRC (-2) #define VM_ANY_TAG (-2) +// MPI size limit +#define VM_MPI_SIZE_LIMIT (2147483647) + // define the communication preferences #define PREF_INTRA_PROCESS_SHMHACK (0) // default #define PREF_INTRA_PROCESS_PTHREAD (1) @@ -473,12 +476,12 @@ class VMK{ static std::string getEsmfComm(){return std::string(XSTR(ESMF_COMM));} // p2p communication calls - int send(const void *message, int size, int dest, int tag=-1); - int send(const void *message, int size, int dest, commhandle **commh, + int send(const void *message, unsigned long long int size, int dest, int tag=-1); + int send(const void *message, unsigned long long int size, int dest, commhandle **commh, int tag=-1); - int recv(void *message, int size, int source, int tag=-1, + int recv(void *message, unsigned long long int size, int source, int tag=-1, status *status=NULL); - int recv(void *message, int size, int source, commhandle **commh, + int recv(void *message, unsigned long long int size, int source, commhandle **commh, int tag=-1); int sendrecv(void *sendData, int sendSize, int dst, void *recvData, diff --git a/src/Infrastructure/VM/interface/ESMCI_VM_F.C b/src/Infrastructure/VM/interface/ESMCI_VM_F.C index 7bfccb30be..c0ef74b499 100644 --- a/src/Infrastructure/VM/interface/ESMCI_VM_F.C +++ b/src/Infrastructure/VM/interface/ESMCI_VM_F.C @@ -734,8 +734,8 @@ extern "C" { if (rc!=NULL) *rc = ESMF_SUCCESS; } - void FTN_X(c_esmc_vmrecv)(ESMCI::VM **vm, void *message, int *size, - int *source, int *rc){ + void FTN_X(c_esmc_vmrecv)(ESMCI::VM **vm, void *message, + unsigned long long int *size, int *source, int *rc){ #undef ESMC_METHOD #define ESMC_METHOD "c_esmc_vmrecv()" // Initialize return code; assume routine not implemented @@ -757,8 +757,8 @@ extern "C" { if (rc!=NULL) *rc = ESMF_SUCCESS; } - void FTN_X(c_esmc_vmrecvnb)(ESMCI::VM **vm, void *message, int *size, - int *source, void **commhandle, int *rc){ + void FTN_X(c_esmc_vmrecvnb)(ESMCI::VM **vm, void *message, + unsigned long long int *size, int *source, void **commhandle, int *rc){ #undef ESMC_METHOD #define ESMC_METHOD "c_esmc_vmrecvnb()" // Initialize return code; assume routine not implemented @@ -922,8 +922,8 @@ extern "C" { if (rc!=NULL) *rc = ESMF_SUCCESS; } - void FTN_X(c_esmc_vmsend)(ESMCI::VM **vm, void *message, int *size, int *dest, - int *rc){ + void FTN_X(c_esmc_vmsend)(ESMCI::VM **vm, void *message, + unsigned long long int *size, int *dest, int *rc){ #undef ESMC_METHOD #define ESMC_METHOD "c_esmc_vmsend()" // Initialize return code; assume routine not implemented @@ -945,8 +945,8 @@ extern "C" { if (rc!=NULL) *rc = ESMF_SUCCESS; } - void FTN_X(c_esmc_vmsendnb)(ESMCI::VM **vm, void *message, int *size, - int *dest, void **commhandle, int *rc){ + void FTN_X(c_esmc_vmsendnb)(ESMCI::VM **vm, void *message, + unsigned long long int *size, int *dest, void **commhandle, int *rc){ #undef ESMC_METHOD #define ESMC_METHOD "c_esmc_vmsendnb()" // Initialize return code; assume routine not implemented diff --git a/src/Infrastructure/VM/interface/ESMF_VM.F90 b/src/Infrastructure/VM/interface/ESMF_VM.F90 index 2ba1887be1..d942ae44c8 100644 --- a/src/Infrastructure/VM/interface/ESMF_VM.F90 +++ b/src/Infrastructure/VM/interface/ESMF_VM.F90 @@ -238,19 +238,19 @@ subroutine c_ESMC_VMGatherV(vm, sendData, sendCount, recvData, recvCounts, & end subroutine subroutine c_ESMC_VMRecv(vm, recvData, recvSize, src, rc) - import :: ESMF_VM + import :: ESMF_VM, ESMF_KIND_I8 type(ESMF_VM) :: vm type(*) :: recvData(*) - integer :: recvSize + integer(ESMF_KIND_I8) :: recvSize integer :: src integer :: rc end subroutine subroutine c_ESMC_VMRecvNB(vm, recvData, recvSize, src, comm, rc) - import :: ESMF_VM, ESMF_CommHandle + import :: ESMF_VM, ESMF_CommHandle, ESMF_KIND_I8 type(ESMF_VM) :: vm type(*) :: recvData(*) - integer :: recvSize + integer(ESMF_KIND_I8) :: recvSize integer :: src type(ESMF_CommHandle) :: comm integer :: rc @@ -303,19 +303,19 @@ subroutine c_ESMC_VMScatterV(vm, sendData, sendCounts, sendOffsets, & end subroutine subroutine c_ESMC_VMSend(vm, sendData, sendSize, dst, rc) - import :: ESMF_VM + import :: ESMF_VM, ESMF_KIND_I8 type(ESMF_VM) :: vm type(*) :: sendData(*) - integer :: sendSize + integer(ESMF_KIND_I8) :: sendSize integer :: dst integer :: rc end subroutine subroutine c_ESMC_VMSendNB(vm, sendData, sendSize, dst, comm, rc) - import :: ESMF_VM, ESMF_CommHandle + import :: ESMF_VM, ESMF_CommHandle, ESMF_KIND_I8 type(ESMF_VM) :: vm type(*) :: sendData(*) - integer :: sendSize + integer(ESMF_KIND_I8) :: sendSize integer :: dst type(ESMF_CommHandle) :: comm integer :: rc @@ -6226,7 +6226,7 @@ end subroutine ESMF_VMPrint ! ! !ARGUMENTS: ! type(ESMF_VM), intent(in) :: vm -! (ESMF_KIND_), target, intent(out) :: recvData(:) +! (ESMF_KIND_), target, intent(out) :: recvData(:) ! integer, intent(in) :: count ! integer, intent(in) :: srcPet !type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -6292,7 +6292,7 @@ subroutine ESMF_VMRecvI4(vm, recvData, count, srcPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - integer(ESMF_KIND_I4), target, intent(out) :: recvData(:) + integer(ESMF_KIND_I4), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -6303,7 +6303,7 @@ subroutine ESMF_VMRecvI4(vm, recvData, count, srcPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -6325,7 +6325,8 @@ subroutine ESMF_VMRecvI4(vm, recvData, count, srcPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 4 ! 4 bytes + size = count + size = size * 4 ! 4 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMRecv(vm, recvData, size, srcPet, localrc) @@ -6365,7 +6366,7 @@ subroutine ESMF_VMRecvI8(vm, recvData, count, srcPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - integer(ESMF_KIND_I8), target, intent(out) :: recvData(:) + integer(ESMF_KIND_I8), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -6376,7 +6377,7 @@ subroutine ESMF_VMRecvI8(vm, recvData, count, srcPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -6398,7 +6399,8 @@ subroutine ESMF_VMRecvI8(vm, recvData, count, srcPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 8 ! 8 bytes + size = count + size = size * 8 ! 8 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMRecv(vm, recvData, size, srcPet, localrc) @@ -6438,7 +6440,7 @@ subroutine ESMF_VMRecvR4(vm, recvData, count, srcPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - real(ESMF_KIND_R4), target, intent(out) :: recvData(:) + real(ESMF_KIND_R4), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -6449,7 +6451,7 @@ subroutine ESMF_VMRecvR4(vm, recvData, count, srcPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -6471,7 +6473,8 @@ subroutine ESMF_VMRecvR4(vm, recvData, count, srcPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 4 ! 4 bytes + size = count + size = size * 4 ! 4 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMRecv(vm, recvData, size, srcPet, localrc) @@ -6511,7 +6514,7 @@ subroutine ESMF_VMRecvR8(vm, recvData, count, srcPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - real(ESMF_KIND_R8), target, intent(out) :: recvData(:) + real(ESMF_KIND_R8), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -6522,7 +6525,7 @@ subroutine ESMF_VMRecvR8(vm, recvData, count, srcPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -6544,7 +6547,8 @@ subroutine ESMF_VMRecvR8(vm, recvData, count, srcPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 8 ! 8 bytes + size = count + size = size * 8 ! 8 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMRecv(vm, recvData, size, srcPet, localrc) @@ -6584,7 +6588,7 @@ subroutine ESMF_VMRecvLogical(vm, recvData, count, srcPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - type(ESMF_Logical), target, intent(out) :: recvData(:) + type(ESMF_Logical), target, intent(out) :: recvData(:) integer, intent(in) :: count integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -6595,7 +6599,7 @@ subroutine ESMF_VMRecvLogical(vm, recvData, count, srcPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -6617,7 +6621,8 @@ subroutine ESMF_VMRecvLogical(vm, recvData, count, srcPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 4 ! 4 bytes + size = count + size = size * 4 ! 4 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMRecv(vm, recvData, size, srcPet, localrc) @@ -6668,7 +6673,7 @@ subroutine ESMF_VMRecvChar(vm, recvData, count, srcPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -6690,7 +6695,7 @@ subroutine ESMF_VMRecvChar(vm, recvData, count, srcPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 1 ! 1 byte + size = count ! 1 byte ! Call into the C++ interface. if (blocking) then call c_ESMC_VMRecv(vm, recvData, size, srcPet, localrc) @@ -6741,7 +6746,7 @@ subroutine ESMF_VMRecvCharArray(vm, recvData, count, srcPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -6763,7 +6768,7 @@ subroutine ESMF_VMRecvCharArray(vm, recvData, count, srcPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 1 ! 1 byte + size = count ! 1 byte ! Call into the C++ interface. if (blocking) then call c_ESMC_VMRecv(vm, recvData, size, srcPet, localrc) @@ -7806,7 +7811,7 @@ end subroutine ESMF_VMScatterVR8 ! ! !ARGUMENTS: ! type(ESMF_VM), intent(in) :: vm -! (ESMF_KIND_), target, intent(in) :: sendData(:) +! (ESMF_KIND_), target, intent(in) :: sendData(:) ! integer, intent(in) :: count ! integer, intent(in) :: dstPet !type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -7871,7 +7876,7 @@ subroutine ESMF_VMSendI4(vm, sendData, count, dstPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - integer(ESMF_KIND_I4), target, intent(in) :: sendData(:) + integer(ESMF_KIND_I4), target, intent(in) :: sendData(:) integer, intent(in) :: count integer, intent(in) :: dstPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -7881,7 +7886,7 @@ subroutine ESMF_VMSendI4(vm, sendData, count, dstPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -7903,7 +7908,8 @@ subroutine ESMF_VMSendI4(vm, sendData, count, dstPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 4 ! 4 bytes + size = count + size = size * 4 ! 4 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMSend(vm, sendData, size, dstPet, localrc) @@ -7943,7 +7949,7 @@ subroutine ESMF_VMSendI8(vm, sendData, count, dstPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - integer(ESMF_KIND_I8), target, intent(in) :: sendData(:) + integer(ESMF_KIND_I8), target, intent(in) :: sendData(:) integer, intent(in) :: count integer, intent(in) :: dstPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -7953,7 +7959,7 @@ subroutine ESMF_VMSendI8(vm, sendData, count, dstPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -7975,7 +7981,8 @@ subroutine ESMF_VMSendI8(vm, sendData, count, dstPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 8 ! 8 bytes + size = count + size = size * 8 ! 8 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMSend(vm, sendData, size, dstPet, localrc) @@ -8015,7 +8022,7 @@ subroutine ESMF_VMSendR4(vm, sendData, count, dstPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - real(ESMF_KIND_R4), target, intent(in) :: sendData(:) + real(ESMF_KIND_R4), target, intent(in) :: sendData(:) integer, intent(in) :: count integer, intent(in) :: dstPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8026,7 +8033,7 @@ subroutine ESMF_VMSendR4(vm, sendData, count, dstPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -8048,7 +8055,8 @@ subroutine ESMF_VMSendR4(vm, sendData, count, dstPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 4 ! 4 bytes + size = count + size = size * 4 ! 4 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMSend(vm, sendData, size, dstPet, localrc) @@ -8088,7 +8096,7 @@ subroutine ESMF_VMSendR8(vm, sendData, count, dstPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - real(ESMF_KIND_R8), target, intent(in) :: sendData(:) + real(ESMF_KIND_R8), target, intent(in) :: sendData(:) integer, intent(in) :: count integer, intent(in) :: dstPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8099,7 +8107,7 @@ subroutine ESMF_VMSendR8(vm, sendData, count, dstPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -8121,7 +8129,8 @@ subroutine ESMF_VMSendR8(vm, sendData, count, dstPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 8 ! 8 bytes + size = count + size = size * 8 ! 8 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMSend(vm, sendData, size, dstPet, localrc) @@ -8161,7 +8170,7 @@ subroutine ESMF_VMSendLogical(vm, sendData, count, dstPet, keywordEnforcer, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - type(ESMF_Logical), target, intent(in) :: sendData(:) + type(ESMF_Logical), target, intent(in) :: sendData(:) integer, intent(in) :: count integer, intent(in) :: dstPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8172,7 +8181,7 @@ subroutine ESMF_VMSendLogical(vm, sendData, count, dstPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -8194,7 +8203,8 @@ subroutine ESMF_VMSendLogical(vm, sendData, count, dstPet, keywordEnforcer, & if (count > 0) then ! There is data to be received - size = count * 4 ! 4 bytes + size = count + size = size * 4 ! 4 bytes ! Call into the C++ interface. if (blocking) then call c_ESMC_VMSend(vm, sendData, size, dstPet, localrc) @@ -8245,7 +8255,7 @@ subroutine ESMF_VMSendChar(vm, sendData, count, dstPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -8318,7 +8328,7 @@ subroutine ESMF_VMSendCharArray(vm, sendData, count, dstPet, keywordEnforcer, & !EOPI !------------------------------------------------------------------------------ integer :: localrc ! local return code - integer :: size + integer(ESMF_KIND_I8) :: size logical :: blocking type(ESMF_CommHandle) :: localcommhandle @@ -8377,10 +8387,10 @@ end subroutine ESMF_VMSendCharArray ! ! !ARGUMENTS: ! type(ESMF_VM), intent(in) :: vm -! (ESMF_KIND_), target, intent(in) :: sendData(:) +! (ESMF_KIND_), target, intent(in) :: sendData(:) ! integer, intent(in) :: sendCount ! integer, intent(in) :: dstPet -! (ESMF_KIND_), target, intent(out) :: recvData(:) +! (ESMF_KIND_), target, intent(out) :: recvData(:) ! integer, intent(in) :: recvCount ! integer, intent(in) :: srcPet !type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8454,10 +8464,10 @@ subroutine ESMF_VMSendRecvI4(vm, sendData, sendCount, dstPet, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - integer(ESMF_KIND_I4), target, intent(in) :: sendData(:) + integer(ESMF_KIND_I4), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount integer, intent(in) :: dstPet - integer(ESMF_KIND_I4), target, intent(out) :: recvData(:) + integer(ESMF_KIND_I4), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8530,10 +8540,10 @@ subroutine ESMF_VMSendRecvI8(vm, sendData, sendCount, dstPet, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - integer(ESMF_KIND_I8), target, intent(in) :: sendData(:) + integer(ESMF_KIND_I8), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount integer, intent(in) :: dstPet - integer(ESMF_KIND_I8), target, intent(out) :: recvData(:) + integer(ESMF_KIND_I8), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8606,10 +8616,10 @@ subroutine ESMF_VMSendRecvR4(vm, sendData, sendCount, dstPet, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - real(ESMF_KIND_R4), target, intent(in) :: sendData(:) + real(ESMF_KIND_R4), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount integer, intent(in) :: dstPet - real(ESMF_KIND_R4), target, intent(out) :: recvData(:) + real(ESMF_KIND_R4), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8682,10 +8692,10 @@ subroutine ESMF_VMSendRecvR8(vm, sendData, sendCount, dstPet, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - real(ESMF_KIND_R8), target, intent(in) :: sendData(:) + real(ESMF_KIND_R8), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount integer, intent(in) :: dstPet - real(ESMF_KIND_R8), target, intent(out) :: recvData(:) + real(ESMF_KIND_R8), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below @@ -8758,10 +8768,10 @@ subroutine ESMF_VMSendRecvLogical(vm, sendData, sendCount, dstPet, & ! ! !ARGUMENTS: type(ESMF_VM), intent(in) :: vm - type(ESMF_Logical), target, intent(in) :: sendData(:) + type(ESMF_Logical), target, intent(in) :: sendData(:) integer, intent(in) :: sendCount integer, intent(in) :: dstPet - type(ESMF_Logical), target, intent(out) :: recvData(:) + type(ESMF_Logical), target, intent(out) :: recvData(:) integer, intent(in) :: recvCount integer, intent(in) :: srcPet type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index f4e8a29709..c2a5d9fc87 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -21,6 +21,7 @@ #define VM_COMMQUEUELOG_off #define VM_EPOCHLOG_off #define VM_SSISHMLOG_off +#define VM_SIZELOG_on // On SunOS systems there are a couple of macros that need to be set // in order to get POSIX compliant functions IPC, pthreads, gethostid @@ -3873,7 +3874,7 @@ void VMK::epochExit(bool keepAlloc){ void *buffer = (void *)sm->stream.str(); // access the buffer -> freeze int size = sm->stream.pcount(); // bytes in stream buffer if (size > 0){ -#ifdef VM_EPOCHLOG_on +#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " ready to post non-blocking send:" << " dst=" << getVas(lpid[its->first]) << " size=" << size @@ -3898,7 +3899,7 @@ void VMK::epochExit(bool keepAlloc){ sm->streamBuffer = sm->stream.str(); // copy data into persistent buffer sm->stream.str(""); // clear out stream if (sm->streamBuffer.size() > 0){ -#ifdef VM_EPOCHLOG_on +#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " ready to post non-blocking send:" << " dst=" << getVas(lpid[its->first]) @@ -4070,7 +4071,8 @@ int VMK::getDefaultTag(int src, int dst){ } -int VMK::send(const void *message, int size, int dest, int tag){ +int VMK::send(const void *message, unsigned long long int size, int dest, + int tag){ // p2p send #if (VERBOSITY > 9) printf("sending to: %d, %d\n", dest, lpid[dest]); @@ -4094,7 +4096,29 @@ int VMK::send(const void *message, int size, int dest, int tag){ if (mpi_mutex_flag) pthread_mutex_lock(pth_mutex); #endif if (tag == -1) tag = getDefaultTag(mypet,dest); - localrc = MPI_Send(messageC, size, MPI_BYTE, lpid[dest], tag, mpi_c); +#ifdef VM_SIZELOG_on + { + std::stringstream msg; + msg << "VMK::send():" << __LINE__ << ", size=" << size; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + } +#endif + if (size < VM_MPI_SIZE_LIMIT) + localrc = MPI_Send(messageC, size, MPI_BYTE, lpid[dest], tag, mpi_c); + else{ + // must send in multiple stages + unsigned long long _size = size; + i=0; + while(_size > VM_MPI_SIZE_LIMIT){ + localrc = MPI_Send(messageC, VM_MPI_SIZE_LIMIT, MPI_BYTE, lpid[dest], + tag+i, mpi_c); + i += 1; + _size -= VM_MPI_SIZE_LIMIT; + } + if (_size > 0) + localrc = MPI_Send(messageC, _size, MPI_BYTE, lpid[dest], tag+i, + mpi_c); + } #ifndef ESMF_NO_PTHREADS if (mpi_mutex_flag) pthread_mutex_unlock(pth_mutex); #endif @@ -4217,8 +4241,8 @@ int VMK::send(const void *message, int size, int dest, int tag){ } -int VMK::send(const void *message, int size, int dest, commhandle **ch, - int tag){ +int VMK::send(const void *message, unsigned long long int size, int dest, + commhandle **ch, int tag){ // p2p send non-blocking //fprintf(stderr, "VMK::send: ch=%p\n", *ch); #if (VERBOSITY > 9) @@ -4288,7 +4312,14 @@ int VMK::send(const void *message, int size, int dest, commhandle **ch, #ifdef VM_MEMLOG_on VM::logMemInfo(std::string("VM::send():1.0")); #endif - localrc = MPI_Isend(messageC, size, MPI_BYTE, lpid[dest], tag, mpi_c, +#ifdef VM_SIZELOG_on + { + std::stringstream msg; + msg << "VMK::send():" << __LINE__ << ", size=" << size; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + } +#endif + localrc = MPI_Isend(messageC, size, MPI_BYTE, lpid[dest], tag, mpi_c, (*ch)->mpireq); #ifdef VM_MEMLOG_on VM::logMemInfo(std::string("VM::send():2.0")); @@ -4364,7 +4395,8 @@ int VMK::send(const void *message, int size, int dest, commhandle **ch, } -int VMK::recv(void *message, int size, int source, int tag, status *status){ +int VMK::recv(void *message, unsigned long long int size, int source, int tag, + status *status){ // p2p recv #if (VERBOSITY > 9) printf("receiving from: %d, %d\n", source, lpid[source]); @@ -4406,7 +4438,30 @@ int VMK::recv(void *message, int size, int source, int tag, status *status){ mpi_s = &(status->mpi_s); else mpi_s = MPI_STATUS_IGNORE; - localrc = MPI_Recv(message, size, MPI_BYTE, mpiSource, tag, mpi_c, mpi_s); +#ifdef VM_SIZELOG_on + { + std::stringstream msg; + msg << "VMK::recv():" << __LINE__ << ", size=" << size; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + } +#endif + if (size < VM_MPI_SIZE_LIMIT) + localrc = MPI_Recv(message, size, MPI_BYTE, mpiSource, tag, mpi_c, mpi_s); + else{ + // must receive in multiple stages + unsigned long long _size = size; + i=0; + while(_size > VM_MPI_SIZE_LIMIT){ + localrc = MPI_Recv(message, VM_MPI_SIZE_LIMIT, MPI_BYTE, mpiSource, + tag+i, mpi_c, mpi_s); + i += 1; + _size -= VM_MPI_SIZE_LIMIT; + } + if (_size > 0) + localrc = MPI_Recv(message, _size, MPI_BYTE, mpiSource, tag+i, mpi_c, + mpi_s); + } + #ifndef ESMF_NO_PTHREADS if (mpi_mutex_flag) pthread_mutex_unlock(pth_mutex); #endif @@ -4546,7 +4601,8 @@ int VMK::recv(void *message, int size, int source, int tag, status *status){ } -int VMK::recv(void *message, int size, int source, commhandle **ch, int tag){ +int VMK::recv(void *message, unsigned long long int size, int source, + commhandle **ch, int tag){ #undef ESMC_METHOD #define ESMC_METHOD "ESMCI::VMK::recv()" // p2p recv non-blocking @@ -4594,8 +4650,10 @@ int VMK::recv(void *message, int size, int source, commhandle **ch, int tag){ // deal with the first actions here rm->firstFlag = false; // reset the flag // query the message size with probe -#ifdef VM_EPOCHLOG_on +#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) std::stringstream msg; +#endif +#ifdef VM_EPOCHLOG_on msg << "epochBuffer:" << __LINE__ << " ready to probe:" << " src=" << getVas(lpid[source]); ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); @@ -4616,7 +4674,7 @@ int VMK::recv(void *message, int size, int source, commhandle **ch, int tag){ mpi_c); // post blocking recv of the entire epoch buffer -#ifdef VM_EPOCHLOG_on +#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) msg.str(""); // clear msg << "epochBuffer:" << __LINE__ << " ready to post blocking recv:" << " src=" << getVas(lpid[source]) @@ -4636,8 +4694,9 @@ int VMK::recv(void *message, int size, int source, commhandle **ch, int tag){ #endif } // now service the specific receive call with chunk of data from buffer - int *ip = (int *)rm->buffer; - int chunkSize = *ip++; + unsigned long long int *ipl = (unsigned long long int *)rm->buffer; + unsigned long long int chunkSize = *ipl++; + int *ip = (int *)ipl; int chunkTag = *ip++; char *cp = (char *)ip; @@ -4674,6 +4733,13 @@ int VMK::recv(void *message, int size, int source, commhandle **ch, int tag){ int mpiSource; if (source == VM_ANY_SRC) mpiSource = MPI_ANY_SOURCE; else mpiSource = lpid[source]; +#ifdef VM_SIZELOG_on + { + std::stringstream msg; + msg << "VMK::recv():" << __LINE__ << ", size=" << size; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + } +#endif localrc = MPI_Irecv(message, size, MPI_BYTE, mpiSource, tag, mpi_c, (*ch)->mpireq); #ifndef ESMF_NO_PTHREADS From a696c55c53b2d976fc439e8a9a6545540bdd634b Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 1 Jun 2022 06:43:22 -0700 Subject: [PATCH 004/266] Bump versioning into the 8.4.0 beta snapshot phase. --- src/Infrastructure/Util/include/ESMC_Macros.h | 4 ++-- src/Infrastructure/Util/src/ESMF_UtilTypes.F90 | 4 ++-- src/addon/ESMPy/setup.py | 2 +- src/addon/NUOPC/doc/NUOPC_howtodoc.ctex | 2 +- src/addon/NUOPC/doc/NUOPC_refdoc.ctex | 2 +- src/doc/ESMC_crefdoc.ctex | 2 +- src/doc/ESMF_refdoc.ctex | 2 +- src/doc/ESMF_usrdoc.ctex | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Infrastructure/Util/include/ESMC_Macros.h b/src/Infrastructure/Util/include/ESMC_Macros.h index da10b6b2de..673447ba6b 100644 --- a/src/Infrastructure/Util/include/ESMC_Macros.h +++ b/src/Infrastructure/Util/include/ESMC_Macros.h @@ -51,13 +51,13 @@ #define ESMF_VERSION_MAJOR 8 -#define ESMF_VERSION_MINOR 3 +#define ESMF_VERSION_MINOR 4 #define ESMF_VERSION_REVISION 0 #define ESMF_VERSION_PATCHLEVEL 0 #define ESMF_VERSION_PUBLIC 'F' #define ESMF_VERSION_BETASNAPSHOT 'T' -#define ESMF_VERSION_STRING "8.3.0 beta snapshot" +#define ESMF_VERSION_STRING "8.4.0 beta snapshot" #endif // ESMC_MACROS_H diff --git a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 index 4cbbc5253b..900d316542 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 +++ b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 @@ -82,13 +82,13 @@ module ESMF_UtilTypesMod !EOPI integer, parameter :: ESMF_VERSION_MAJOR = 8 - integer, parameter :: ESMF_VERSION_MINOR = 3 + integer, parameter :: ESMF_VERSION_MINOR = 4 integer, parameter :: ESMF_VERSION_REVISION = 0 integer, parameter :: ESMF_VERSION_PATCHLEVEL = 0 logical, parameter :: ESMF_VERSION_PUBLIC = .false. logical, parameter :: ESMF_VERSION_BETASNAPSHOT = .true. - character(*), parameter :: ESMF_VERSION_STRING = "8.3.0 beta snapshot" + character(*), parameter :: ESMF_VERSION_STRING = "8.4.0 beta snapshot" #if defined (ESMF_NETCDF) logical, parameter :: ESMF_IO_NETCDF_PRESENT = .true. diff --git a/src/addon/ESMPy/setup.py b/src/addon/ESMPy/setup.py index 2772e7e351..d4f53c3191 100644 --- a/src/addon/ESMPy/setup.py +++ b/src/addon/ESMPy/setup.py @@ -247,7 +247,7 @@ def _get_dot_(path, root='src'): # TODO: build doc command # TODO: remove duplicated metadata: here and src/ESMF/__init__.py setup(name="ESMPy", - version="8.3.0", + version="8.4.0", description="ESMF Python interface", author="University Corporation for Atmospheric Research, \ Massachusetts Institute of Technology, \ diff --git a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex index dfb98691f1..63d3fcc410 100644 --- a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf Building a NUOPC Model}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.3.0 beta snapshot} +\newcommand{\myversion}{ESMF 8.4.0 beta snapshot} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex index ab93cea2ce..5c7d62fded 100644 --- a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf NUOPC Layer Reference}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.3.0 beta snapshot} +\newcommand{\myversion}{ESMF 8.4.0 beta snapshot} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/doc/ESMC_crefdoc.ctex b/src/doc/ESMC_crefdoc.ctex index 335760281d..11d9089813 100644 --- a/src/doc/ESMC_crefdoc.ctex +++ b/src/doc/ESMC_crefdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.3.0 beta snapshot} +\newcommand{\myversion}{Version 8.4.0 beta snapshot} \newenvironment {reqlist} diff --git a/src/doc/ESMF_refdoc.ctex b/src/doc/ESMF_refdoc.ctex index 720769f712..cdd784cc98 100644 --- a/src/doc/ESMF_refdoc.ctex +++ b/src/doc/ESMF_refdoc.ctex @@ -15,7 +15,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.3.0 beta snapshot} +\newcommand{\myversion}{Version 8.4.0 beta snapshot} \input{common_commands} diff --git a/src/doc/ESMF_usrdoc.ctex b/src/doc/ESMF_usrdoc.ctex index be35e07754..a427cf0ec8 100644 --- a/src/doc/ESMF_usrdoc.ctex +++ b/src/doc/ESMF_usrdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.3.0 beta snapshot} +\newcommand{\myversion}{Version 8.4.0 beta snapshot} \newenvironment {reqlist} From 41a31625b87f4532acfc89b663ae1e2f4727dbfa Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 1 Jun 2022 07:06:26 -0700 Subject: [PATCH 005/266] Adjust TAG1 for API change checking. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 58467039fe..ba5b565e96 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -247,7 +247,7 @@ jobs: command: git clone --branch $CIRCLE_BRANCH https://github.com/esmf-org/esmf.git - run: name: Docker Run API Changes - command: docker build -t "esmf/api-change:${CIRCLE_BRANCH_NEW}" --file "ESCOMP-Containers/ESMF/API_changes/Dockerfile" --build-arg DOCKER_NAMESPACE="esmf" --build-arg TAG1="ESMF_8_2_0" --build-arg TAG2="${CIRCLE_BRANCH}" --no-cache . + command: docker build -t "esmf/api-change:${CIRCLE_BRANCH_NEW}" --file "ESCOMP-Containers/ESMF/API_changes/Dockerfile" --build-arg DOCKER_NAMESPACE="esmf" --build-arg TAG1="v8.3.0" --build-arg TAG2="${CIRCLE_BRANCH}" --no-cache . - run: name: Extract API Changes command: bash esmf/.circleci/sh/extract-artifacts.sh "/tmp/artifacts" "/artifacts/api_change-artifacts.zip" "esmf/api-change:${CIRCLE_BRANCH_NEW}" From 3c875a5b0161efdd01bfb230fc4a78ab4b2ef065 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 6 Jun 2022 09:47:29 -0700 Subject: [PATCH 006/266] Move ESMPy copyright range to 2011-2022. --- src/addon/ESMPy/doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/doc/conf.py b/src/addon/ESMPy/doc/conf.py index d7d47fdc57..f14df17791 100644 --- a/src/addon/ESMPy/doc/conf.py +++ b/src/addon/ESMPy/doc/conf.py @@ -51,7 +51,7 @@ # General information about the project. project = u'ESMPy' -copyright = u'2011-2020, 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' +copyright = u'2011-2022, 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' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the From f0d4ab211d8d69ddf7fbccc52e0a4c33deabd66b Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 7 Jun 2022 09:24:46 -0700 Subject: [PATCH 007/266] Bring back the table of all possible os/compiler/comm/abi options. I think it is still useful. --- build/doc/user_arch.tex | 85 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/build/doc/user_arch.tex b/build/doc/user_arch.tex index eddb154377..4bed5cda99 100644 --- a/build/doc/user_arch.tex +++ b/build/doc/user_arch.tex @@ -8,6 +8,91 @@ click the {\em Supported Platforms} link under one of the releases on the \htmladdnormallink{ESMF releases page}{http://earthsystemmodeling.org/static/releases.html}. +All possible combinations of {\tt ESMF\_OS}, {\tt ESMF\_COMPILER}, {\tt ESMF\_COMM}, +and {\tt ESMF\_ABI} build environment variables are listed in the following table. +Where multiple options exist, and the default is independent +of {\tt ESMF\_MACHINE}, the default value is in {\bf bold}. +A {\tt default} value in the compiler column indicates +the vendor compiler. A {\tt mpi} value in the comm column indicates +the vendor MPI implementation. + +\begin{longtable}{lllll} + {\bfseries\footnotesize ESMF\_OS} &{\bfseries\footnotesize ESMF\_COMPILER} & {\bfseries\footnotesize ESMF\_COMM} & {\bfseries\footnotesize ESMF\_ABI} \\ + +AIX &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 32, {\bf 64} \\ +Cygwin &\tt g95 &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32, 64 \\ +Cygwin &\tt gfortran &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,lam,msmpi,openmpi,user &\tt 32, 64 \\ +Darwin &\tt absoft &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt g95 &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt gfortran &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt gfortranclang &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt intel &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,intelmpi,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt intelclang &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,intelmpi,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt intelgcc &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,intelmpi,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt nag &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt pgi &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Darwin &\tt xlf &\footnotesize \tt mpiuni,{\bf mpi},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32 \\ +Darwin &\tt xlfgcc &\footnotesize \tt mpiuni,{\bf mpi},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32 \\ +IRIX64 &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 32, {\bf 64} \\ +Linux &\tt absoft &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Linux &\tt absoftintel &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32, 64 \\ +Linux &\tt g95 &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64, \\ + & & &\tt ia64\_64, \\ + & & &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium \\ +Linux &\tt gfortran &\footnotesize \tt {\bf mpiuni},mpi,mpt,mpich,mpich1,mpich2,mpich3,mvapich2, &\tt 32, 64, \\ + & &\footnotesize \tt intelmpi,lam,openmpi,user &\tt ia64\_64, \\ + & & &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium \\ +Linux &\tt gfortranclang &\footnotesize \tt {\bf mpiuni},mpi,mpt,mpich,mpich1,mpich2,mpich3,mvapich2, &\tt 32, 64, \\ + & & \footnotesize \tt lam,openmpi,user &\tt ia64\_64, \\ + & & &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium \\ +Linux &\tt intel &\footnotesize \tt {\bf mpiuni},mpi,mpt,mpich,mpich1,mpich2,mpich3,mvapich2, &\tt 32, 64, \\ + & &\footnotesize \tt intelmpi,scalimpi,lam,openmpi,user &\tt ia64\_64, \\ + & & &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium, \\ + & & &\tt mic \\ +Linux &\tt intelgcc &\footnotesize \tt {\bf mpiuni},mpi,mpt,mpich,mpich1,mpich2,mpich3,mvapich2, &\tt 32, 64, \\ + & &\footnotesize \tt intelmpi,lam,openmpi,user &\tt ia64\_64, \\ + & & &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium \\ +Linux &\tt lahey &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Linux &\tt nag &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ +Linux &\tt nagintel &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32, 64 \\ +Linux &\tt nvhpc &\footnotesize \tt {\bf mpiuni},mpi,mpt,mpich,mpich1,mpich2,mpich3,mvapich,mvapich2 &\tt 32, 64, \\ + & &\footnotesize \tt intelmpi,openmpi,user &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium \\ +Linux &\tt pathscale &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32, 64, \\ + & & &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium \\ +Linux &\tt pgi &\footnotesize \tt {\bf mpiuni},mpi,mpt,mpich,mpich1,mpich2,mpich3,mvapich,mvapich2 &\tt 32, 64, \\ + & &\footnotesize \tt intelmpi,scalimpi,lam,openmpi,user &\tt x86\_64\_32, \\ + & & &\tt x86\_64\_small, \\ + & & &\tt x86\_64\_medium \\ +Linux &\tt pgigcc &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32 \\ +Linux &\tt sxcross &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 32 \\ +Linux &\tt xlf &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 32 \\ +MinGW &\tt gfortran &\footnotesize \tt {\bf mpiuni},msmpi,user &\tt 32, 64 \\ +MinGW &\tt intel &\footnotesize \tt {\bf mpiuni},msmpi,user &\tt 32, 64 \\ +MinGW &\tt intelcl &\footnotesize \tt {\bf mpiuni},msmpi,user &\tt 32, 64 \\ +OSF1 &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +SunOS &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 32, {\bf 64} \\ +Unicos &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +Unicos &\tt cce &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +Unicos &\tt gfortran &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +Unicos &\tt intel &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +Unicos &\tt pathscale &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +Unicos &\tt pgi &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 + +\end{longtable} \vspace{1ex} From 8caeab2b040f56348ec8b3570685905c8a303634 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 15 Jun 2022 20:28:58 +0000 Subject: [PATCH 008/266] Hierarchical profiling of nested loop structures. --- src/addon/NUOPC/src/NUOPC_Driver.F90 | 31 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index 22cf53d6c8..edeb915555 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -3463,6 +3463,7 @@ recursive subroutine ExecuteRunSequence(driver, rc) integer :: loopLevel, loopLevelPrev integer :: levelMember, levelMemberPrev integer :: loopIteration, loopIterationPrev + logical :: enterCurrent, exitPrevious rc = ESMF_SUCCESS @@ -3549,9 +3550,21 @@ recursive subroutine ExecuteRunSequence(driver, rc) (loopIteration/=loopIterationPrev)) then ! found a time loop event if (btest(profiling,12)) then + enterCurrent = .true. + exitPrevious = .false. if ((loopLevelPrev/=0).and.(levelMemberPrev/=0).and. & (loopIterationPrev/=0)) then - ! an actual previous iteration does exist -> exit trace region + ! an actual previous event does exist + exitPrevious = .true. + if (loopLevel > loopLevelPrev) then + ! going down another level in the loop nesting hierarchy + exitPrevious = .false. + else if (loopLevel > loopLevelPrev) then + ! coming back up a level in the loop nesting hierarchy + enterCurrent = .false. + endif + endif + if (exitPrevious) then write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & loopLevelPrev, levelMemberPrev, loopIterationPrev call ESMF_TraceRegionExit(trim(traceString), rc=rc) @@ -3559,13 +3572,15 @@ recursive subroutine ExecuteRunSequence(driver, rc) line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out endif - ! enter new trace region - write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & - loopLevel, levelMember, loopIteration - call ESMF_TraceRegionEnter(trim(traceString), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & - return ! bail out + if (enterCurrent) then + ! enter new trace region + write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & + loopLevel, levelMember, loopIteration + call ESMF_TraceRegionEnter(trim(traceString), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif endif ! update the "Prev' variables loopLevelPrev = loopLevel From 04d9eea7955d171aaff638d526d6d95c93b8cc45 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 21 Jun 2022 17:53:32 -0700 Subject: [PATCH 009/266] Implement InitializeDataResolution driver attribute. --- .../doc/NUOPC_DriverComponent_metadata.tex | 1 + src/addon/NUOPC/src/NUOPC_Comp.F90 | 14 ++- src/addon/NUOPC/src/NUOPC_Driver.F90 | 101 +++++++++++------- 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/src/addon/NUOPC/doc/NUOPC_DriverComponent_metadata.tex b/src/addon/NUOPC/doc/NUOPC_DriverComponent_metadata.tex index 32b06cb4e9..4b447dfca3 100644 --- a/src/addon/NUOPC/doc/NUOPC_DriverComponent_metadata.tex +++ b/src/addon/NUOPC/doc/NUOPC_DriverComponent_metadata.tex @@ -63,6 +63,7 @@ {\tt Internal\-InitializePhaseMap} & List of string values, mapping the logical NUOPC initialize phases, of a specific Initialize Phase Definition (IPD) version, to the actual ESMF initialize phase number under which the entry point is registered.& IPDvXXpY=Z, where XX = two-digit revision number, e.g. 01, Y = logical NUOPC phase number, Z = actual ESMF phase number, with Y, Z > 0 and Y, Z < 10 \\ \hline {\tt NestingGeneration} & Integer value enumerating nesting level.& 0, 1, 2, ...\\ \hline {\tt Nestling} & Integer value enumerating siblings within the same generation.& 0, 1, 2, ...\\ \hline + {\tt Initialize\-DataResolution} & String value indicating whether the resolution loop is disabled or enabled.& false, true\\ \hline {\tt Initialize\-DataComplete} & String value indicating whether all initialize data dependencies have been satisfied.& false, true\\ \hline {\tt Initialize\-DataProgress} & String value indicating whether progress is being made resolving initialize data dependencies.& false, true\\ \hline {\tt HierarchyProtocol} & String value specifying the hierarchy protocol.& "PushUpAllExportsAndUnsatisfiedImports" - activates field mirroring of all exports and unsatisfied imports. By default use reference sharing for the mirrored fields and geom objects. This is the default behavior without having {\tt HierarchyProtocol} set. "ConnectProvidedFields"- no field mirroring, only connect to externally provided fields in the import- and exportStates. "Explorer" - like the default, but do not use reference sharing. {\em All other values currently disable the hierarchy protocol.}\\ \hline diff --git a/src/addon/NUOPC/src/NUOPC_Comp.F90 b/src/addon/NUOPC/src/NUOPC_Comp.F90 index 2ca1315565..82307a66a5 100644 --- a/src/addon/NUOPC/src/NUOPC_Comp.F90 +++ b/src/addon/NUOPC/src/NUOPC_Comp.F90 @@ -1822,15 +1822,16 @@ subroutine NUOPC_GridCompAttributeInit(comp, kind, rc) endif ! Add NUOPC/Driver, NUOPC/Model, NUOPC/Mediator Attributes - allocate(attrList(8)) + allocate(attrList(9)) attrList(1) = "InternalInitializePhaseMap" ! list of strings to map str to phase # attrList(2) = "InternalRunPhaseMap" ! list of strings to map str to phase # attrList(3) = "InternalFinalizePhaseMap" ! list of strings to map str to phase # attrList(4) = "NestingGeneration" ! values: integer starting 0 for parent attrList(5) = "Nestling" ! values: integer starting 0 for first nestling - attrList(6) = "InitializeDataComplete" ! values: strings "false"/"true" - attrList(7) = "InitializeDataProgress" ! values: strings "false"/"true" - attrList(8) = "HierarchyProtocol" ! strings + attrList(6) = "InitializeDataResolution"! values: strings "false"/"true" + attrList(7) = "InitializeDataComplete" ! values: strings "false"/"true" + attrList(8) = "InitializeDataProgress" ! values: strings "false"/"true" + attrList(9) = "HierarchyProtocol" ! strings ! add Attribute packages call ESMF_AttributeAdd(comp, convention="NUOPC", purpose="Instance", & attrList=attrList, rc=localrc) @@ -1878,6 +1879,11 @@ subroutine NUOPC_GridCompAttributeInit(comp, kind, rc) rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=FILENAME, rcToReturn=rc)) return ! bail out + call NUOPC_CompAttributeSet(comp, & + name="InitializeDataResolution", value="true", & + rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=FILENAME, rcToReturn=rc)) return ! bail out call NUOPC_CompAttributeSet(comp, & name="InitializeDataComplete", value="false", & rc=localrc) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index 3ea8242515..3f59189d87 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -191,7 +191,7 @@ recursive subroutine SetServices(driver, rc) ! Explicitly claim initialize phase 1 to be able to call into Driver ! simply via a single ESMF_GridCompInitialize() from the application level. call ESMF_GridCompSetEntryPoint(driver, ESMF_METHOD_INITIALIZE, & - userRoutine=InitializeP1, phase=1, rc=rc) + userRoutine=InitializeGeneric, phase=1, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out @@ -300,9 +300,9 @@ recursive subroutine SetServices(driver, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out - + ! Set IPDvX attribute - call NUOPC_CompAttributeSet(driver, name="IPDvX", value="true", rc=rc) + call NUOPC_CompAttributeSet(driver, name="IPDvX", value="false", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out @@ -389,14 +389,14 @@ recursive subroutine InitializeP0(driver, importState, exportState, clock, rc) !----------------------------------------------------------------------------- - recursive subroutine InitializeP1(driver, importState, exportState, clock, rc) + recursive subroutine InitializeGeneric(driver, importState, exportState, clock, rc) type(ESMF_GridComp) :: driver type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables - character(*), parameter :: rName="InitializeP1" + character(*), parameter :: rName="InitializeGeneric" character(ESMF_MAXSTR) :: name integer :: verbosity, profiling type(type_InternalState) :: is @@ -452,6 +452,9 @@ recursive subroutine InitializeP1(driver, importState, exportState, clock, rc) endif ! call the actual initialize routines + call InitializeP0(driver, importState, exportState, clock, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out call InitializeIPDv02p1(driver, importState, exportState, clock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out @@ -564,10 +567,13 @@ recursive subroutine InitializeExternalAdvertise(driver, importState, & endif ! call the actual initialize routine + call InitializeP0(driver, importState, exportState, clock, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out call InitializeIPDv02p1(driver, importState, exportState, clock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out - + ! extro call NUOPC_LogExtro(name, rName, verbosity, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & @@ -2427,49 +2433,68 @@ recursive subroutine InitializeIPDv02p5Data(driver, importState, exportState,& return ! bail out execFlagCollect = execFlagCollect.or.execFlag - ! deal with the fact that the executing component may not be across all PETs - execFlagInt = 0 - if (execFlagCollect) execFlagInt = 1 - - call ESMF_VMAllFullReduce(vm, sendData=(/execFlagInt/), & - recvData=execFlagIntReduced, count=1, reduceflag=ESMF_REDUCE_SUM, rc=rc) + ! determine whether to enter initialize data resolution loop + call NUOPC_CompAttributeGet(driver, name="InitializeDataResolution", & + value=valueString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME)) & + return ! bail out +#if 0 + call ESMF_LogWrite("InitializeDataResolution: "//trim(valueString), & + ESMF_LOGMSG_DEBUG, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) & return ! bail out +#endif - if (execFlagIntReduced>0) execFlag = .true. - - ! now all PETs have the same execFlag setting for a consistent decision - if (execFlag) then - ! there were model components with IPDv02p5, IPDv03p7, IPDv04p7, - ! IPDv05p8, or IPDvXp08 -->> resolve data dependencies by entering loop - if (btest(verbosity,11)) then - call ESMF_LogWrite(trim(name)//& - ": components present that trigger loopDataDependentInitialize().", & - ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out - endif - - call loopDataDependentInitialize(driver, is%wrap%dataDepAllComplete, rc=rc) + if (trim(valueString)=="true") then + ! deal with the fact that the executing component may not be across all PETs + execFlagInt = 0 + if (execFlagCollect) execFlagInt = 1 + + call ESMF_VMAllFullReduce(vm, sendData=(/execFlagInt/), & + recvData=execFlagIntReduced, count=1, reduceflag=ESMF_REDUCE_SUM, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) & return ! bail out - if (btest(verbosity,11)) then - write(msgString, "(A,l)") trim(name)//& - ": loopDataDependentInitialize() returned with dataDepAllComplete: ",& - is%wrap%dataDepAllComplete - call ESMF_LogWrite(msgString, ESMF_LOGMSG_INFO, rc=rc) + if (execFlagIntReduced>0) execFlag = .true. + + ! now all PETs have the same execFlag setting for a consistent decision + if (execFlag) then + ! there were model components with IPDv02p5, IPDv03p7, IPDv04p7, + ! IPDv05p8, or IPDvXp08 -->> resolve data dependencies by entering loop + if (btest(verbosity,11)) then + call ESMF_LogWrite(trim(name)//& + ": components present that trigger loopDataDependentInitialize().", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out + endif + + call loopDataDependentInitialize(driver, is%wrap%dataDepAllComplete, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out + line=__LINE__, file=trim(name)//":"//FILENAME)) & + return ! bail out + + if (btest(verbosity,11)) then + write(msgString, "(A,l)") trim(name)//& + ": loopDataDependentInitialize() returned with dataDepAllComplete: ",& + is%wrap%dataDepAllComplete + call ESMF_LogWrite(msgString, ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out + endif endif + + ! set the InitializeDataComplete attribute + valueString="false" + if (is%wrap%dataDepAllComplete) valueString="true" + + else + valueString="true" endif - - ! set the InitializeDataComplete attribute - valueString="false" - if (is%wrap%dataDepAllComplete) valueString="true" - + call NUOPC_CompAttributeSet(driver, & name="InitializeDataComplete", value=valueString, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & From 46f666e7dfc22625c24430b1513745271ae51ff5 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Sun, 26 Jun 2022 16:04:35 -0700 Subject: [PATCH 010/266] remove setup.py in favor of setup.cfg and pyproject.toml --- src/addon/ESMPy/.gitignore | 2 ++ src/addon/ESMPy/pyproject.toml | 24 ++++++++++++++ src/addon/ESMPy/setup.cfg | 32 +++++++++++++++++++ src/addon/ESMPy/{setup.py => setup.py.old} | 0 .../ESMPy/src/ESMF/interface/loadESMF.py | 32 ++++++++++++++----- 5 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 src/addon/ESMPy/pyproject.toml create mode 100644 src/addon/ESMPy/setup.cfg rename src/addon/ESMPy/{setup.py => setup.py.old} (100%) diff --git a/src/addon/ESMPy/.gitignore b/src/addon/ESMPy/.gitignore index 238fdcd5b7..15e6c72411 100644 --- a/src/addon/ESMPy/.gitignore +++ b/src/addon/ESMPy/.gitignore @@ -28,8 +28,10 @@ PET* # ESMPy build and docs # ######################## build +dist doc/esmpy_doc src/ESMF/interface/esmfmkfile.py +src/ESMPy.egg-info examples/data src/ESMF/test/data examples/notebooks/ESMPy-data diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml new file mode 100644 index 0000000000..894c1b3a35 --- /dev/null +++ b/src/addon/ESMPy/pyproject.toml @@ -0,0 +1,24 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +# [project] +# name = "ESMPy" +# description = "ESMF Python interface" +# license = {text = "University of Illinois-NCSA"} +# readme = "README.md" +# # dynamic = ["version"] +# dependencies = [ +# "numpy", +# ] +# +# [tool.setuptools.packages.find] +# where = ["src"] +# exclude = [ +# "ESMPy.doc*", +# "ESMPy.example*", +# "ESMPy.test*", +# ] +# +# [tool.setuptools.dynamic] +# version = {attr = "ESMPy.VERSION"} diff --git a/src/addon/ESMPy/setup.cfg b/src/addon/ESMPy/setup.cfg new file mode 100644 index 0000000000..ccbdd01a94 --- /dev/null +++ b/src/addon/ESMPy/setup.cfg @@ -0,0 +1,32 @@ +[metadata] +name = ESMPy +version = 8.4.0 +description = ESMF Python interface +long_description = file: README.md, LICENSE +license = University of Illinois-NCSA +author = 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 +author_email = "esmf_support@ucar.edu", +url="http://earthsystemmodeling.org/esmpy/", + + +[options] +zip_safe = False +include_package_data = True +packages = find: +install_requires = + numpy + + +[options.packages.find] +where=src +exclude = + doc* + examples* + test* diff --git a/src/addon/ESMPy/setup.py b/src/addon/ESMPy/setup.py.old similarity index 100% rename from src/addon/ESMPy/setup.py rename to src/addon/ESMPy/setup.py.old diff --git a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py b/src/addon/ESMPy/src/ESMF/interface/loadESMF.py index c10bd60fbc..ca5395f4a3 100644 --- a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py +++ b/src/addon/ESMPy/src/ESMF/interface/loadESMF.py @@ -8,21 +8,37 @@ import ESMF.api.constants as constants -try: - from ESMF.interface.esmfmkfile import ESMFMKFILE as esmfmk -except: - raise ImportError('The ESMFMKFILE cannot be found!') - try: import numpy as np except: - raise ImportError('The Numpy library cannot be found!') + raise ImportError('The Numpy library cannot be found.') # this library is loaded here so that it can be pulled back up without sys try: import ctypes as ct except: - raise ImportError('The CTypes library cannot be found!') + raise ImportError('The CTypes library cannot be found.') + +esmfmk = None +mked = False +esmfmkfile_local = os.path.join(os.getcwd(),"src/ESMF/interface/esmfmkfile.py") +try: + + if os.path.isfile(esmfmkfile_local): + from ESMF.interface.esmfmkfile import ESMFMKFILE as esmfmk + mked = True +except: + raise ImportError('The esmf.mk file could not be loaded.') +else: + if not mked: + esmfmk = os.getenv("ESMFMKFILE") + if not esmfmk: + raise ImportError('The ESMFMKFILE was not set in the build, nor is it available as an environment variable.') + else: + with open(esmfmkfile_local, 'w') as emfl: + emfl.write('ESMFMKFILE = "'+esmfmk+'"') + emfl.close() + #### INVESTIGATE esmf.mk ###################################################### @@ -134,4 +150,4 @@ mode=ct.RTLD_GLOBAL) except: traceback.print_exc(file=sys.stdout) - raise ImportError('The ESMF shared library did not load properly.') \ No newline at end of file + raise ImportError('The ESMF shared library did not load properly.') From 9c6ea6096a19683eaa2a7a8f267cfb6135e70015 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Sun, 26 Jun 2022 16:04:49 -0700 Subject: [PATCH 011/266] remove setup.py in favor of setup.cfg and pyproject.toml --- src/addon/ESMPy/setup.cfg | 3 +++ src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py | 1 - src/addon/ESMPy/src/ESMF/util/decorators.py | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/addon/ESMPy/setup.cfg b/src/addon/ESMPy/setup.cfg index ccbdd01a94..f6e962c30e 100644 --- a/src/addon/ESMPy/setup.cfg +++ b/src/addon/ESMPy/setup.cfg @@ -30,3 +30,6 @@ exclude = doc* examples* test* + +[nosetests] +attr=!slow,!data diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py index d70e8f6a9f..0c6fff2995 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py @@ -862,4 +862,3 @@ def test_grid_create_from_file_scrip_decomp_cyclic_cyclic(self): reg_decomp=reg_decomp, decompflag=decompflag) except: raise NameError('grid_create_from_file_scrip_cyclic_cyclic failed!') - diff --git a/src/addon/ESMPy/src/ESMF/util/decorators.py b/src/addon/ESMPy/src/ESMF/util/decorators.py index 8d1b351e4e..2c98ad8cd2 100644 --- a/src/addon/ESMPy/src/ESMF/util/decorators.py +++ b/src/addon/ESMPy/src/ESMF/util/decorators.py @@ -95,4 +95,3 @@ def new_func(*args, **kwargs): raise NetCDFMissing("This function requires ESMF to have been built with NetCDF.") return new_func - From d6f20437943abdb08e9611bae6948e723f4d1825 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 27 Jun 2022 16:18:09 +0000 Subject: [PATCH 012/266] Fix a typo. --- src/addon/NUOPC/src/NUOPC_Driver.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index edeb915555..e2ea2e7d55 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -3559,7 +3559,7 @@ recursive subroutine ExecuteRunSequence(driver, rc) if (loopLevel > loopLevelPrev) then ! going down another level in the loop nesting hierarchy exitPrevious = .false. - else if (loopLevel > loopLevelPrev) then + else if (loopLevel < loopLevelPrev) then ! coming back up a level in the loop nesting hierarchy enterCurrent = .false. endif From 992fafaac4299b426b8e74e664db6e90b38c8eb5 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 29 Jun 2022 11:01:38 -0700 Subject: [PATCH 013/266] Update the API doc to reflect current AttributeSet() behavior. --- src/addon/NUOPC/src/NUOPC_Comp.F90 | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/addon/NUOPC/src/NUOPC_Comp.F90 b/src/addon/NUOPC/src/NUOPC_Comp.F90 index 82307a66a5..6fa79cbbd9 100644 --- a/src/addon/NUOPC/src/NUOPC_Comp.F90 +++ b/src/addon/NUOPC/src/NUOPC_Comp.F90 @@ -2065,8 +2065,6 @@ subroutine NUOPC_GridCompAttributeSetS(comp, name, value, rc) ! Set the Attribute {\tt name} inside of {\tt comp} on the highest level ! of the standard NUOPC AttPack hierarchy (convention="NUOPC", ! purpose="Instance"). -! -! Return with error if the Attribute is not present or not set. !EOP !----------------------------------------------------------------------------- ! local variables @@ -2108,8 +2106,6 @@ subroutine NUOPC_CplCompAttributeSetS(comp, name, value, rc) ! Set the Attribute {\tt name} inside of {\tt comp} on the highest level ! of the standard NUOPC AttPack hierarchy (convention="NUOPC", ! purpose="Instance"). -! -! Return with error if the Attribute is not present or not set. !EOP !----------------------------------------------------------------------------- ! local variables @@ -2151,8 +2147,6 @@ subroutine NUOPC_GridCompAttributeSetI(comp, name, value, rc) ! Set the Attribute {\tt name} inside of {\tt comp} on the highest level ! of the standard NUOPC AttPack hierarchy (convention="NUOPC", ! purpose="Instance"). -! -! Return with error if the Attribute is not present or not set. !EOP !----------------------------------------------------------------------------- ! local variables @@ -2194,8 +2188,6 @@ subroutine NUOPC_CplCompAttributeSetI(comp, name, value, rc) ! Set the Attribute {\tt name} inside of {\tt comp} on the highest level ! of the standard NUOPC AttPack hierarchy (convention="NUOPC", ! purpose="Instance"). -! -! Return with error if the Attribute is not present or not set. !EOP !----------------------------------------------------------------------------- ! local variables @@ -2238,8 +2230,6 @@ subroutine NUOPC_GridCompAttributeSetSL(comp, name, valueList, rc) ! Set the Attribute {\tt name} inside of {\tt comp} on the highest level ! of the standard NUOPC AttPack hierarchy (convention="NUOPC", ! purpose="Instance"). -! -! Return with error if the Attribute is not present or not set. !EOP !----------------------------------------------------------------------------- ! local variables @@ -2281,8 +2271,6 @@ subroutine NUOPC_CplCompAttributeSetSL(comp, name, valueList, rc) ! Set the Attribute {\tt name} inside of {\tt comp} on the highest level ! of the standard NUOPC AttPack hierarchy (convention="NUOPC", ! purpose="Instance"). -! -! Return with error if the Attribute is not present or not set. !EOP !----------------------------------------------------------------------------- ! local variables From 4b01140741b0533a08d215aceca67ac30ce51e2c Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 1 Jul 2022 12:12:35 -0700 Subject: [PATCH 014/266] Pushing run sequence event handling (for verbosity and profiling) down into recursive NUOPC_RunSequenceCtrl(). Functionality working, but need cleanup. --- src/addon/NUOPC/src/NUOPC_Driver.F90 | 21 +++- src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 | 119 +++++++++++++++++-- 2 files changed, 126 insertions(+), 14 deletions(-) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index e2ea2e7d55..b9ca0d92a9 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -3464,6 +3464,7 @@ recursive subroutine ExecuteRunSequence(driver, rc) integer :: levelMember, levelMemberPrev integer :: loopIteration, loopIterationPrev logical :: enterCurrent, exitPrevious + type(NUOPC_RunSeqEventHandler) :: eventHandler rc = ESMF_SUCCESS @@ -3529,10 +3530,17 @@ recursive subroutine ExecuteRunSequence(driver, rc) levelMemberPrev = 0 loopIterationPrev = 0 + ! initialize eventHandler + eventHandler%vFlag = btest(verbosity,12) + eventHandler%pFlag = btest(profiling,12) + eventHandler%loopLevelPrev = 0 + eventHandler%levelMemberPrev = 0 + eventHandler%loopIterationPrev = 0 + ! use RunSequence iterator to execute the actual time stepping loop nullify(runElement) ! prepare runElement for iterator use do while (NUOPC_RunSequenceIterate(is%wrap%runSeq, runSeqIndex, & - runElement, rc=rc)) + runElement, eventHandler, rc=rc)) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out @@ -3567,7 +3575,8 @@ recursive subroutine ExecuteRunSequence(driver, rc) if (exitPrevious) then write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & loopLevelPrev, levelMemberPrev, loopIterationPrev - call ESMF_TraceRegionExit(trim(traceString), rc=rc) +call ESMF_LogWrite("TRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) +! call ESMF_TraceRegionExit(trim(traceString), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out @@ -3576,13 +3585,14 @@ recursive subroutine ExecuteRunSequence(driver, rc) ! enter new trace region write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & loopLevel, levelMember, loopIteration - call ESMF_TraceRegionEnter(trim(traceString), rc=rc) +call ESMF_LogWrite("TREntr: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) +! call ESMF_TraceRegionEnter(trim(traceString), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out endif endif - ! update the "Prev' variables + ! update the "Prev" variables loopLevelPrev = loopLevel levelMemberPrev = levelMember loopIterationPrev = loopIteration @@ -3658,7 +3668,8 @@ recursive subroutine ExecuteRunSequence(driver, rc) ! an actual previous iteration does exist -> exit trace region write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & loopLevelPrev, levelMemberPrev, loopIterationPrev - call ESMF_TraceRegionExit(trim(traceString), rc=rc) +call ESMF_LogWrite("TRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) +! call ESMF_TraceRegionExit(trim(traceString), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out diff --git a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 index 2a9f240e77..a3b68bf31d 100644 --- a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 +++ b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 @@ -28,7 +28,8 @@ module NUOPC_RunSequenceDef public NUOPC_RunSequenceAdd, NUOPC_RunSequenceSet, NUOPC_RunSequencePrint public NUOPC_RunSequenceDeallocate public NUOPC_RunSequenceIterate - + public NUOPC_RunSeqEventHandler + !============================================================================== ! ! DERIVED TYPES @@ -64,6 +65,14 @@ module NUOPC_RunSequenceDef type(ESMF_Alarm) :: alarm end type + type NUOPC_RunSeqEventHandler + logical :: vFlag ! verbosity bit-12 + logical :: pFlag ! profiling bit-12 + integer :: loopLevelPrev + integer :: levelMemberPrev + integer :: loopIterationPrev + end type + !============================================================================== ! ! INTERFACE BLOCKS @@ -429,13 +438,15 @@ subroutine NUOPC_RunSequenceSingleDeall(runSeq, rc) !BOPI ! !IROUTINE: NUOPC_RunSequenceIterate - Iterate through a RunSequence ! !INTERFACE: - function NUOPC_RunSequenceIterate(runSeq, runSeqIndex, runElement, rc) + function NUOPC_RunSequenceIterate(runSeq, runSeqIndex, runElement, & + eventHandler, rc) ! !RETURN VALUE: logical :: NUOPC_RunSequenceIterate ! !ARGUMENTS: type(NUOPC_RunSequence), pointer :: runSeq(:) integer, intent(in) :: runSeqIndex type(NUOPC_RunElement), pointer :: runElement + type(NUOPC_RunSeqEventHandler) :: eventHandler integer, optional, intent(out) :: rc ! !DESCRIPTION: ! Iterate through the RunSequence that is in position {\tt runSeqIndex} in the @@ -522,7 +533,8 @@ function NUOPC_RunSequenceIterate(runSeq, runSeqIndex, runElement, rc) endif ! runElement may be a control element (either LINK or ENDDO) - NUOPC_RunSequenceIterate = NUOPC_RunSequenceCtrl(runSeq, runElement, rc=localrc) + NUOPC_RunSequenceIterate = NUOPC_RunSequenceCtrl(runSeq, runElement, & + eventHandler, rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=FILENAME, rcToReturn=rc)) return ! bail out @@ -680,11 +692,14 @@ subroutine NUOPC_RunSequenceSet(runSeq, clock, alarm, rc) !BOPI ! !IROUTINE: NUOPC_RunSequenceCtrl - Recursive iterator through a RunSequence ! !INTERFACE: - recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, rc) & + recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & + eventHandler, rc) & ! !ARGUMENTS: result(NUOPC_RunSequenceCtrlResult) + type(NUOPC_RunSeqEventHandler) :: eventHandler type(NUOPC_RunSequence), pointer :: runSeq(:) type(NUOPC_RunElement), pointer :: runElement + integer, optional, intent(out) :: rc ! !DESCRIPTION: !EOP @@ -715,6 +730,7 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, rc) & if (associated(runElement%next)) then ! simple component element NUOPC_RunSequenceCtrlResult = .true. +call NUOPC_RunSequenceHandleEvent(runElement%runSeq, eventHandler, rc=localrc) return else ! invalid element @@ -739,8 +755,8 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, rc) & if (.not.associated(runElement%next)) then ! "ENDDO" element -#if 0 - print *, "found ENDDO element" +#if 1 + call ESMF_LogWrite("Found ENDDO element", ESMF_LOGMSG_DEBUG, rc=localrc) #endif if (runElement%runSeq%alarmBlock) then ! end of alarm block -> advance the clock @@ -762,6 +778,8 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, rc) & if (clockIsStopTime) then if (.not.associated(runSeq(i)%stack)) then ! reached the end of top level loop +call ESMF_LogWrite("AT THE END", ESMF_LOGMSG_DEBUG, rc=localrc) +call NUOPC_RunSequenceHandleEvent(runSeq(i), eventHandler, endFlag=.true., rc=localrc) return ! break out else ! reached the end of a nested run sequence loop -> move up the stack @@ -779,8 +797,8 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, rc) & endif else ! "LINK" element -#if 0 - print *, "found LINK element" +#if 1 + call ESMF_LogWrite("Found LINK element", ESMF_LOGMSG_DEBUG, rc=localrc) #endif if (associated(runSeq(i)%stack)) then ! detected recursive link @@ -848,13 +866,96 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, rc) & endif endif +call NUOPC_RunSequenceHandleEvent(runElement%runSeq, eventHandler, rc=localrc) + ! recursive call... NUOPC_RunSequenceCtrlResult = NUOPC_RunSequenceCtrl(runSeq, runElement, & - rc=localrc) + eventHandler, rc=localrc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=FILENAME, rcToReturn=rc)) return ! bail out end function !----------------------------------------------------------------------------- + subroutine NUOPC_RunSequenceHandleEvent(runSeq, eh, endFlag, rc) + type(NUOPC_RunSequence) :: runSeq + type(NUOPC_RunSeqEventHandler) :: eh + logical, optional, intent(in) :: endFlag + integer, intent(out) :: rc + + integer :: loopLevel + integer :: levelMember + integer :: loopIteration + logical :: enterCurrent, exitPrevious + character(ESMF_MAXSTR) :: traceString + logical :: endFlagInternal + integer :: profiling = 4096 + + loopLevel = runSeq%loopLevel + levelMember = runSeq%levelMember + loopIteration = runSeq%loopIteration + + endFlagInternal = .false. ! default + if (present(endFlag)) endFlagInternal = endFlag + + if (endFlagInternal) then + if ((eh%loopLevelPrev/=0).and.(eh%levelMemberPrev/=0).and. & + (eh%loopIterationPrev/=0)) then + ! an actual previous iteration does exist -> exit trace region + write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & + eh%loopLevelPrev, eh%levelMemberPrev, eh%loopIterationPrev +call ESMF_LogWrite("xxxTRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) + call ESMF_TraceRegionExit(trim(traceString), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=FILENAME, rcToReturn=rc)) & + return ! bail out + endif + else + if ((loopLevel/=eh%loopLevelPrev).or.(levelMember/=eh%levelMemberPrev).or.& + (loopIteration/=eh%loopIterationPrev)) then + ! found a time loop event + if (btest(profiling,12)) then + enterCurrent = .true. + exitPrevious = .false. + if ((eh%loopLevelPrev/=0).and.(eh%levelMemberPrev/=0).and. & + (eh%loopIterationPrev/=0)) then + ! an actual previous event does exist + exitPrevious = .true. + if (loopLevel > eh%loopLevelPrev) then + ! going down another level in the loop nesting hierarchy + exitPrevious = .false. + else if (loopLevel < eh%loopLevelPrev) then + ! coming back up a level in the loop nesting hierarchy + enterCurrent = .false. + endif + endif + if (exitPrevious) then + write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & + eh%loopLevelPrev, eh%levelMemberPrev, eh%loopIterationPrev +call ESMF_LogWrite("xxxTRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) + call ESMF_TraceRegionExit(trim(traceString), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=FILENAME, rcToReturn=rc)) & + return ! bail out + endif + if (enterCurrent) then + ! enter new trace region + write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & + loopLevel, levelMember, loopIteration +call ESMF_LogWrite("xxxTREntr: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) + call ESMF_TraceRegionEnter(trim(traceString), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=FILENAME, rcToReturn=rc)) & + return ! bail out + endif + endif + ! update the "Prev" variables + eh%loopLevelPrev = loopLevel + eh%levelMemberPrev = levelMember + eh%loopIterationPrev = loopIteration + endif + endif + end subroutine + + end module NUOPC_RunSequenceDef From 986fc6a529fdaa6d8cd95cfc8655df5cb2d64e1d Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 1 Jul 2022 12:50:52 -0700 Subject: [PATCH 015/266] Complete the event handling to consider verbosity and profiling attributes correctly. --- src/addon/NUOPC/src/NUOPC_Driver.F90 | 90 +----------- src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 | 139 ++++++++++++------- 2 files changed, 90 insertions(+), 139 deletions(-) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index b9ca0d92a9..2faa58fa32 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -3454,16 +3454,12 @@ recursive subroutine ExecuteRunSequence(driver, rc) integer :: userrc type(type_InternalState) :: is character(ESMF_MAXSTR) :: name - character(ESMF_MAXSTR) :: msgString, traceString, timeString + character(ESMF_MAXSTR) :: msgString type(NUOPC_RunElement), pointer :: runElement type(ESMF_Clock) :: internalClock, activeClock integer :: i, j, phase, runPhase, runSeqIndex integer :: verbosity, profiling integer :: indentCount - integer :: loopLevel, loopLevelPrev - integer :: levelMember, levelMemberPrev - integer :: loopIteration, loopIterationPrev - logical :: enterCurrent, exitPrevious type(NUOPC_RunSeqEventHandler) :: eventHandler rc = ESMF_SUCCESS @@ -3525,17 +3521,13 @@ recursive subroutine ExecuteRunSequence(driver, rc) line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out endif - ! initialize "Prev" variables - loopLevelPrev = 0 - levelMemberPrev = 0 - loopIterationPrev = 0 - ! initialize eventHandler eventHandler%vFlag = btest(verbosity,12) eventHandler%pFlag = btest(profiling,12) eventHandler%loopLevelPrev = 0 eventHandler%levelMemberPrev = 0 eventHandler%loopIterationPrev = 0 + eventHandler%name = trim(name) ! use RunSequence iterator to execute the actual time stepping loop nullify(runElement) ! prepare runElement for iterator use @@ -3550,70 +3542,6 @@ recursive subroutine ExecuteRunSequence(driver, rc) activeClock = runElement%runSeq%clock endif - if (btest(verbosity,12).or.btest(profiling,12)) then - loopLevel = runElement%runSeq%loopLevel - levelMember = runElement%runSeq%levelMember - loopIteration = runElement%runSeq%loopIteration - if ((loopLevel/=loopLevelPrev).or.(levelMember/=levelMemberPrev).or.& - (loopIteration/=loopIterationPrev)) then - ! found a time loop event - if (btest(profiling,12)) then - enterCurrent = .true. - exitPrevious = .false. - if ((loopLevelPrev/=0).and.(levelMemberPrev/=0).and. & - (loopIterationPrev/=0)) then - ! an actual previous event does exist - exitPrevious = .true. - if (loopLevel > loopLevelPrev) then - ! going down another level in the loop nesting hierarchy - exitPrevious = .false. - else if (loopLevel < loopLevelPrev) then - ! coming back up a level in the loop nesting hierarchy - enterCurrent = .false. - endif - endif - if (exitPrevious) then - write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & - loopLevelPrev, levelMemberPrev, loopIterationPrev -call ESMF_LogWrite("TRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) -! call ESMF_TraceRegionExit(trim(traceString), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & - return ! bail out - endif - if (enterCurrent) then - ! enter new trace region - write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & - loopLevel, levelMember, loopIteration -call ESMF_LogWrite("TREntr: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) -! call ESMF_TraceRegionEnter(trim(traceString), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & - return ! bail out - endif - endif - ! update the "Prev" variables - loopLevelPrev = loopLevel - levelMemberPrev = levelMember - loopIterationPrev = loopIteration - if (btest(verbosity,12)) then - ! write iteration info to Log - write(msgString,"(A,I4,A,I4,A,I4)") & - trim(name)//": RunSequence event loopLevel=", loopLevel, & - " levelMember=", levelMember, " loopIteration=", loopIteration - call ESMF_ClockPrint(activeClock, options="currTime", & - preString=trim(msgString)//", current time: ", & - unit=timeString, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out - call ESMF_LogWrite(timeString, ESMF_LOGMSG_INFO, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & - return ! bail out - endif - endif - endif - ! now interpret and act on the current runElement i = runElement%i phase = runElement%phase @@ -3662,20 +3590,6 @@ recursive subroutine ExecuteRunSequence(driver, rc) line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out - if (btest(profiling,12)) then - if ((loopLevelPrev/=0).and.(levelMemberPrev/=0).and. & - (loopIterationPrev/=0)) then - ! an actual previous iteration does exist -> exit trace region - write(traceString,"('RunSequenceEvent.',I4.4,'.',I4.4,'.',I4.4)") & - loopLevelPrev, levelMemberPrev, loopIterationPrev -call ESMF_LogWrite("TRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) -! call ESMF_TraceRegionExit(trim(traceString), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & - return ! bail out - endif - endif - if (btest(verbosity,12)) then call ESMF_LogGet(indentCount=indentCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & diff --git a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 index a3b68bf31d..4315a17b2a 100644 --- a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 +++ b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 @@ -71,6 +71,7 @@ module NUOPC_RunSequenceDef integer :: loopLevelPrev integer :: levelMemberPrev integer :: loopIterationPrev + character(ESMF_MAXSTR) :: name end type !============================================================================== @@ -709,10 +710,14 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & logical :: clockIsStopTime, ringing integer :: i type(ESMF_Time) :: currTime + logical :: needHandler if (present(rc)) rc = ESMF_SUCCESS NUOPC_RunSequenceCtrlResult = .false. ! initialize to safe return value + ! determine if event handler is needed + needHandler = (eventHandler%vFlag .or. eventHandler%pFlag) + ! sanity checks if (.not.associated(runSeq)) then call ESMF_LogSetError(ESMF_RC_ARG_BAD, msg="runSeq must be associated.", & @@ -730,7 +735,12 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & if (associated(runElement%next)) then ! simple component element NUOPC_RunSequenceCtrlResult = .true. -call NUOPC_RunSequenceHandleEvent(runElement%runSeq, eventHandler, rc=localrc) + if (needHandler) then + call NUOPC_RunSequenceHandleEvent(runElement%runSeq, eventHandler, & + rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=FILENAME, rcToReturn=rc)) return ! bail out + endif return else ! invalid element @@ -755,7 +765,7 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & if (.not.associated(runElement%next)) then ! "ENDDO" element -#if 1 +#if 0 call ESMF_LogWrite("Found ENDDO element", ESMF_LOGMSG_DEBUG, rc=localrc) #endif if (runElement%runSeq%alarmBlock) then @@ -778,8 +788,13 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & if (clockIsStopTime) then if (.not.associated(runSeq(i)%stack)) then ! reached the end of top level loop -call ESMF_LogWrite("AT THE END", ESMF_LOGMSG_DEBUG, rc=localrc) -call NUOPC_RunSequenceHandleEvent(runSeq(i), eventHandler, endFlag=.true., rc=localrc) + if (needHandler) then + call NUOPC_RunSequenceHandleEvent(runSeq(i), eventHandler, & + endFlag=.true., rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, & + msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=FILENAME, & + rcToReturn=rc)) return ! bail out + endif return ! break out else ! reached the end of a nested run sequence loop -> move up the stack @@ -797,7 +812,7 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & endif else ! "LINK" element -#if 1 +#if 0 call ESMF_LogWrite("Found LINK element", ESMF_LOGMSG_DEBUG, rc=localrc) #endif if (associated(runSeq(i)%stack)) then @@ -866,7 +881,12 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & endif endif -call NUOPC_RunSequenceHandleEvent(runElement%runSeq, eventHandler, rc=localrc) + if (needHandler) then + call NUOPC_RunSequenceHandleEvent(runElement%runSeq, eventHandler, & + rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=FILENAME, rcToReturn=rc)) return ! bail out + endif ! recursive call... NUOPC_RunSequenceCtrlResult = NUOPC_RunSequenceCtrl(runSeq, runElement, & @@ -877,6 +897,7 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & end function !----------------------------------------------------------------------------- + !----------------------------------------------------------------------------- subroutine NUOPC_RunSequenceHandleEvent(runSeq, eh, endFlag, rc) type(NUOPC_RunSequence) :: runSeq type(NUOPC_RunSeqEventHandler) :: eh @@ -887,9 +908,10 @@ subroutine NUOPC_RunSequenceHandleEvent(runSeq, eh, endFlag, rc) integer :: levelMember integer :: loopIteration logical :: enterCurrent, exitPrevious - character(ESMF_MAXSTR) :: traceString + character(ESMF_MAXSTR) :: traceString, msgString, timeString logical :: endFlagInternal - integer :: profiling = 4096 + + rc = ESMF_SUCCESS loopLevel = runSeq%loopLevel levelMember = runSeq%levelMember @@ -904,58 +926,73 @@ subroutine NUOPC_RunSequenceHandleEvent(runSeq, eh, endFlag, rc) ! an actual previous iteration does exist -> exit trace region write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & eh%loopLevelPrev, eh%levelMemberPrev, eh%loopIterationPrev -call ESMF_LogWrite("xxxTRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) +!call ESMF_LogWrite("TRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) call ESMF_TraceRegionExit(trim(traceString), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=FILENAME, rcToReturn=rc)) & + line=__LINE__, file=trim(eh%name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out endif else - if ((loopLevel/=eh%loopLevelPrev).or.(levelMember/=eh%levelMemberPrev).or.& - (loopIteration/=eh%loopIterationPrev)) then - ! found a time loop event - if (btest(profiling,12)) then - enterCurrent = .true. - exitPrevious = .false. - if ((eh%loopLevelPrev/=0).and.(eh%levelMemberPrev/=0).and. & - (eh%loopIterationPrev/=0)) then - ! an actual previous event does exist - exitPrevious = .true. - if (loopLevel > eh%loopLevelPrev) then - ! going down another level in the loop nesting hierarchy - exitPrevious = .false. - else if (loopLevel < eh%loopLevelPrev) then - ! coming back up a level in the loop nesting hierarchy - enterCurrent = .false. - endif - endif - if (exitPrevious) then - write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & - eh%loopLevelPrev, eh%levelMemberPrev, eh%loopIterationPrev -call ESMF_LogWrite("xxxTRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) - call ESMF_TraceRegionExit(trim(traceString), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=FILENAME, rcToReturn=rc)) & - return ! bail out - endif - if (enterCurrent) then - ! enter new trace region - write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & - loopLevel, levelMember, loopIteration -call ESMF_LogWrite("xxxTREntr: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) - call ESMF_TraceRegionEnter(trim(traceString), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=FILENAME, rcToReturn=rc)) & - return ! bail out + if ((loopLevel/=eh%loopLevelPrev).or.(levelMember/=eh%levelMemberPrev).or.& + (loopIteration/=eh%loopIterationPrev)) then + ! found a time loop event + if (eh%pFlag) then + enterCurrent = .true. + exitPrevious = .false. + if ((eh%loopLevelPrev/=0).and.(eh%levelMemberPrev/=0).and. & + (eh%loopIterationPrev/=0)) then + ! an actual previous event does exist + exitPrevious = .true. + if (loopLevel > eh%loopLevelPrev) then + ! going down another level in the loop nesting hierarchy + exitPrevious = .false. + else if (loopLevel < eh%loopLevelPrev) then + ! coming back up a level in the loop nesting hierarchy + enterCurrent = .false. endif endif - ! update the "Prev" variables - eh%loopLevelPrev = loopLevel - eh%levelMemberPrev = levelMember - eh%loopIterationPrev = loopIteration + if (exitPrevious) then + write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & + eh%loopLevelPrev, eh%levelMemberPrev, eh%loopIterationPrev +!call ESMF_LogWrite("TRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) + call ESMF_TraceRegionExit(trim(traceString), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(eh%name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif + if (enterCurrent) then + ! enter new trace region + write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & + loopLevel, levelMember, loopIteration +!call ESMF_LogWrite("TREntr: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) + call ESMF_TraceRegionEnter(trim(traceString), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(eh%name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif endif + ! update the "Prev" variables + eh%loopLevelPrev = loopLevel + eh%levelMemberPrev = levelMember + eh%loopIterationPrev = loopIteration + if (eh%vFlag) then + ! write iteration info to Log + write(msgString,"(A,I4,A,I4,A,I4)") & + trim(eh%name)//": RunSequence event loopLevel=", loopLevel, & + " levelMember=", levelMember, " loopIteration=", loopIteration + call ESMF_ClockPrint(runSeq%clock, options="currTime", & + preString=trim(msgString)//", current time: ", & + unit=timeString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(eh%name)//":"//FILENAME)) return ! bail out + call ESMF_LogWrite(timeString, ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(eh%name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif + endif endif end subroutine - + !----------------------------------------------------------------------------- end module NUOPC_RunSequenceDef From 673053e8069b2c50cd4ab2fc1549bf438e2e11f7 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 1 Jul 2022 14:23:09 -0700 Subject: [PATCH 016/266] Finish handling of Alarm events. --- src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 index 4315a17b2a..17c441775a 100644 --- a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 +++ b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 @@ -835,6 +835,16 @@ recursive logical function NUOPC_RunSequenceCtrl(runSeq, runElement, & line=__LINE__, file=FILENAME, rcToReturn=rc)) return ! bail out ! set the linked RunSequence level index one higher than current one runSeq(i)%loopLevel = runElement%runSeq%loopLevel + 1 + if (runElement%runSeq%loopIteration==1) then + ! first time into this alarm again during loop + runElement%runSeq%levelChildren = runElement%runSeq%levelChildren + 1 + runSeq(i)%levelMember = runElement%runSeq%levelChildren + runSeq(i)%loopIteration = 1 + runSeq(i)%levelChildren = 0 + else + ! coming in subsequent times + runSeq(i)%loopIteration = runSeq(i)%loopIteration + 1 + endif ! put the next element in the current level onto the new levels stack runSeq(i)%stack => runElement%next ! set stack pointer for return ! follow the link: start at the top of linked sequence From ae3e8ef37fb4512ad0cb9b810585df4fde142bb7 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 1 Jul 2022 16:09:20 -0700 Subject: [PATCH 017/266] Consider Profile bit in all cases. --- src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 index 17c441775a..c4dab80ee5 100644 --- a/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 +++ b/src/addon/NUOPC/src/NUOPC_RunSequenceDef.F90 @@ -933,14 +933,16 @@ subroutine NUOPC_RunSequenceHandleEvent(runSeq, eh, endFlag, rc) if (endFlagInternal) then if ((eh%loopLevelPrev/=0).and.(eh%levelMemberPrev/=0).and. & (eh%loopIterationPrev/=0)) then - ! an actual previous iteration does exist -> exit trace region - write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & - eh%loopLevelPrev, eh%levelMemberPrev, eh%loopIterationPrev + if (eh%pFlag) then + ! an actual previous iteration does exist -> exit trace region + write(traceString,"('RunSequenceRegion.',I4.4,'.',I4.4,'.',I4.4)") & + eh%loopLevelPrev, eh%levelMemberPrev, eh%loopIterationPrev !call ESMF_LogWrite("TRExit: "//trim(traceString), ESMF_LOGMSG_DEBUG, rc=rc) - call ESMF_TraceRegionExit(trim(traceString), rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, file=trim(eh%name)//":"//FILENAME, rcToReturn=rc)) & - return ! bail out + call ESMF_TraceRegionExit(trim(traceString), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(eh%name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif endif else if ((loopLevel/=eh%loopLevelPrev).or.(levelMember/=eh%levelMemberPrev).or.& From f13c778697f13d86174f0e4ed39af5842db0d87c Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 5 Jul 2022 10:56:48 -0700 Subject: [PATCH 018/266] Introduce new specialization points assist hierarchical architectures: label_PreChildrenAdvertise, label_PostChildrenAdvertise, label_PreChildrenRealize, label_PostChildrenRealize, label_PreChildrenDataInitialize, label_PostChildrenDataInitialize. --- src/addon/NUOPC/src/NUOPC_Driver.F90 | 127 ++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 2 deletions(-) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index bd6faaadfd..91e0eaf3ee 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -34,6 +34,12 @@ module NUOPC_Driver routine_Run public & + label_PreChildrenAdvertise, & + label_PostChildrenAdvertise, & + label_PreChildrenRealize, & + label_PostChildrenRealize, & + label_PreChildrenDataInitialize, & + label_PostChildrenDataInitialize, & label_ModifyInitializePhaseMap, & label_ModifyCplLists, & label_SetModelServices, & @@ -46,6 +52,18 @@ module NUOPC_Driver label_InternalState = "Driver_InternalState" character(*), parameter :: & label_SetModelServices = "Driver_SetModelServices" + character(*), parameter :: & + label_PreChildrenAdvertise = "Driver_PreChildrenAdvertise" + character(*), parameter :: & + label_PostChildrenAdvertise = "Driver_PostChildrenAdvertise" + character(*), parameter :: & + label_PreChildrenRealize = "Driver_PreChildrenRealize" + character(*), parameter :: & + label_PostChildrenRealize = "Driver_PostChildrenRealize" + character(*), parameter :: & + label_PreChildrenDataInitialize = "Driver_PreChildrenDataInitialize" + character(*), parameter :: & + label_PostChildrenDataInitialize = "Driver_PostChildrenDataInitialize" character(*), parameter :: & label_SetRunSequence = "Driver_SetRunSequence" character(*), parameter :: & @@ -1229,7 +1247,7 @@ recursive subroutine InitializeIPDv02p1(driver, importState, exportState, & if (btest(profiling,1)) then call ESMF_TraceRegionExit("label_ModifyInitializePhaseMap") endif - + ! Ingest the InitializePhaseMap do i=0, is%wrap%modelCount areServicesSet = & @@ -1260,6 +1278,23 @@ recursive subroutine InitializeIPDv02p1(driver, importState, exportState, & enddo enddo + ! SPECIALIZE by calling into optional attached method + ! before children advertise + if (btest(profiling,1)) then + call ESMF_TraceRegionEnter("label_PreChildrenAdvertise") + endif + call ESMF_MethodExecute(driver, label=label_PreChildrenAdvertise, & + existflag=existflag, userRc=userrc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (ESMF_LogFoundError(rcToCheck=userrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (btest(profiling,1)) then + call ESMF_TraceRegionExit("label_PreChildrenAdvertise") + endif + ! -> Encode the NUOPC IPDv00, IPDv01, IPDv02, IPDv03, IPDv04, IPDv05, IPDvX ! modelComps @@ -1413,7 +1448,7 @@ recursive subroutine InitializeIPDv02p1(driver, importState, exportState, & if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) & return ! bail out - + ! Before returning the driver must clean up its own importState, which ! may have Fields advertised that do not have a ConsumerConnection set. ! These are Fields that during the negotiation between driver children @@ -1433,6 +1468,23 @@ recursive subroutine InitializeIPDv02p1(driver, importState, exportState, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out endif + ! SPECIALIZE by calling into optional attached method + ! after children advertise + if (btest(profiling,1)) then + call ESMF_TraceRegionEnter("label_PostChildrenAdvertise") + endif + call ESMF_MethodExecute(driver, label=label_PostChildrenAdvertise, & + existflag=existflag, userRc=userrc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (ESMF_LogFoundError(rcToCheck=userrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (btest(profiling,1)) then + call ESMF_TraceRegionExit("label_PostChildrenAdvertise") + endif + ! handle verbosity if (btest(verbosity,8)) then call ESMF_GridCompGet(driver, clockIsPresent=clockIsPresent, rc=rc) @@ -1725,12 +1777,14 @@ recursive subroutine InitializeIPDv02p3(driver, importState, exportState, & ! local variables character(*), parameter :: rName="InitializeIPDv02p3" + integer :: userrc character(ESMF_MAXSTR) :: name integer :: verbosity, profiling type(ESMF_Clock) :: internalClock logical :: clockIsPresent character(ESMF_MAXSTR) :: msgString, pLabel integer :: phase + logical :: existflag rc = ESMF_SUCCESS @@ -1804,6 +1858,23 @@ recursive subroutine InitializeIPDv02p3(driver, importState, exportState, & return ! bail out endif + ! SPECIALIZE by calling into optional attached method + ! before children realize + if (btest(profiling,1)) then + call ESMF_TraceRegionEnter("label_PreChildrenRealize") + endif + call ESMF_MethodExecute(driver, label=label_PreChildrenRealize, & + existflag=existflag, userRc=userrc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (ESMF_LogFoundError(rcToCheck=userrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (btest(profiling,1)) then + call ESMF_TraceRegionExit("label_PreChildrenRealize") + endif + ! connectorComps call loopConnectorCompsS(driver, phaseString="IPDv00p2b", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & @@ -1991,6 +2062,23 @@ recursive subroutine InitializeIPDv02p3(driver, importState, exportState, & ! connectorComps ! nothing to do + ! SPECIALIZE by calling into optional attached method + ! after children realize + if (btest(profiling,1)) then + call ESMF_TraceRegionEnter("label_PostChildrenRealize") + endif + call ESMF_MethodExecute(driver, label=label_PostChildrenRealize, & + existflag=existflag, userRc=userrc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (ESMF_LogFoundError(rcToCheck=userrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (btest(profiling,1)) then + call ESMF_TraceRegionExit("label_PostChildrenRealize") + endif + ! handle verbosity if (btest(verbosity,8)) then call ESMF_GridCompGet(driver, clockIsPresent=clockIsPresent, rc=rc) @@ -2058,6 +2146,7 @@ recursive subroutine InitializeIPDv02p5(driver, importState, exportState, & integer :: verbosity, profiling character(ESMF_MAXSTR) :: msgString, pLabel integer :: phase + logical :: existflag rc = ESMF_SUCCESS @@ -2131,6 +2220,23 @@ recursive subroutine InitializeIPDv02p5(driver, importState, exportState, & return ! bail out endif + ! SPECIALIZE by calling into optional attached method + ! before children data initialize + if (btest(profiling,1)) then + call ESMF_TraceRegionEnter("label_PreChildrenDataInitialize") + endif + call ESMF_MethodExecute(driver, label=label_PreChildrenDataInitialize, & + existflag=existflag, userRc=userrc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (ESMF_LogFoundError(rcToCheck=userrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (btest(profiling,1)) then + call ESMF_TraceRegionExit("label_PreChildrenDataInitialize") + endif + ! if the incoming clock is valid, then use to set currTime on internalClock clockIsCreated = ESMF_ClockIsCreated(clock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & @@ -2274,6 +2380,23 @@ recursive subroutine InitializeIPDv02p5(driver, importState, exportState, & endif endif + ! SPECIALIZE by calling into optional attached method + ! after children data initialize + if (btest(profiling,1)) then + call ESMF_TraceRegionEnter("label_PostChildrenDataInitialize") + endif + call ESMF_MethodExecute(driver, label=label_PostChildrenDataInitialize, & + existflag=existflag, userRc=userrc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (ESMF_LogFoundError(rcToCheck=userrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (btest(profiling,1)) then + call ESMF_TraceRegionExit("label_PostChildrenDataInitialize") + endif + ! handle verbosity if (btest(verbosity,8)) then call ESMF_GridCompGet(driver, clockIsPresent=clockIsPresent, rc=rc) From eefff66b4fd1436919234593b256a3e0e11d2218 Mon Sep 17 00:00:00 2001 From: uturuncoglu Date: Tue, 5 Jul 2022 23:44:50 -0600 Subject: [PATCH 019/266] fix options for direction argument --- src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 b/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 index 5bbe071586..55f7e32324 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 +++ b/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 @@ -132,8 +132,8 @@ contains ! Array of data to be sorted. The sorted data is returned @\ ! in the list. @\ ! \item [direction] @\ -! Direction of sorting. Legal values are {\tt ESMF_SORT_ASCENDING} @\ -! and {\tt ESMF_SORT_DESCENDING}. @\ +! Direction of sorting. Legal values are {\tt ESMF_SORTFLAG_ASCENDING} @\ +! and {\tt ESMF_SORTFLAG_DESCENDING}. @\ ! \item [{[rc]}] @\ ! Return code; equals {\tt ESMF_SUCCESS} if the sorting is successful. @\ ! \end{description} @\ From 2210accc4b8b072a93f4d49c1b5f7258d279d18f Mon Sep 17 00:00:00 2001 From: uturuncoglu Date: Tue, 5 Jul 2022 23:53:51 -0600 Subject: [PATCH 020/266] more fix in doc --- src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 b/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 index 55f7e32324..ab125a4b2d 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 +++ b/src/Infrastructure/Util/src/ESMF_UtilSort.cppF90 @@ -97,8 +97,8 @@ contains ! Array of data to be sorted. The original data is overwritten by the @\ ! sorted data. @\ ! \item [direction] @\ -! Direction of sorting. Legal values are {\tt ESMF\_SORT\_ASCENDING} @\ -! and {\tt ESMF\_SORT\_DESCENDING}. @\ +! Direction of sorting. Legal values are {\tt ESMF\_SORTFLAG\_ASCENDING} @\ +! and {\tt ESMF\_SORTFLAG\_DESCENDING}. @\ ! \item [{[rc]}] @\ ! Return code; equals {\tt ESMF\_SUCCESS} if the sorting is successful. @\ ! \end{description} @\ From 9f530a9fb30f8e06fe4e5c2dabb0ef3b5c63a368 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Wed, 6 Jul 2022 07:11:47 -0600 Subject: [PATCH 021/266] update to readonly decomp --- .../IO/PIO/ParallelIO/src/clib/CMakeLists.txt | 25 +- .../IO/PIO/ParallelIO/src/clib/pio.h | 3 + .../PIO/ParallelIO/src/clib/pio_darray_int.c | 6 +- .../IO/PIO/ParallelIO/src/clib/pio_file.c | 1 + .../PIO/ParallelIO/src/clib/pio_rearrange.c | 68 +- .../IO/PIO/ParallelIO/src/clib/pioc.c | 1209 +++++------------ .../IO/PIO/ParallelIO/src/clib/pioc_async.c | 836 ++++++++++++ .../IO/PIO/ParallelIO/src/clib/pioc_support.c | 10 +- .../Mesh/src/ESMCI_ESMFMesh_Util.C | 18 +- .../Mesh/src/ESMCI_UGRID_Util.C | 6 +- 10 files changed, 1279 insertions(+), 903 deletions(-) create mode 100644 src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_async.c diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt index 448f45dcda..7919ba6662 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/CMakeLists.txt @@ -6,8 +6,23 @@ project (PIOC C) # DEFINE THE TARGET #============================================================================== +if (CMAKE_BUILD_TYPE) + define_property( + SOURCE + PROPERTY COMPILE_FLAGS + INHERITED + BRIEF_DOCS "brief-doc" + FULL_DOCS "full-doc" + ) + string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type) + set_directory_properties(PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_${_build_type}}") + set(CMAKE_CXX_FLAGS_${_build_type} "") +endif() + + + set (src topology.c pio_file.c pioc_support.c pio_lists.c - pioc.c pioc_sc.c pio_spmd.c pio_rearrange.c pio_nc4.c + pioc.c pioc_sc.c pio_spmd.c pio_rearrange.c pio_nc4.c pioc_async.c pio_nc.c pio_put_nc.c pio_get_nc.c pio_getput_int.c pio_msg.c pio_darray.c pio_darray_int.c pio_get_vard.c pio_put_vard.c pio_error.c parallel_sort.c) if (NETCDF_INTEGRATION) @@ -16,6 +31,13 @@ endif () add_library (pioc ${src}) +set_source_files_properties( + pioc_async.c + PROPERTIES + COMPILE_FLAGS -O0 +) + + # set up include-directories include_directories( "${CMAKE_BINARY_DIR}" @@ -161,7 +183,6 @@ get_target_property(includes pioc INCLUDE_DIRECTORIES) foreach(x IN LISTS cppdefs) string(APPEND CPPFLAGS " -D${x}") endforeach() - foreach(x IN LISTS includes) if (x) string(APPEND CPPFLAGS " -I${x}") diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h index b8fb3cb20e..3e3c0d6b31 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio.h @@ -785,6 +785,9 @@ extern "C" { /* Decomposition. */ /* Init decomposition with 1-based compmap array. */ + int PIOc_InitDecomp_ReadOnly(int iosysid, int pio_type, int ndims, const int *gdimlen, int maplen, + const PIO_Offset *compmap, int *ioidp, const int *rearr, + const PIO_Offset *iostart, const PIO_Offset *iocount); int PIOc_InitDecomp(int iosysid, int pio_type, int ndims, const int *gdimlen, int maplen, const PIO_Offset *compmap, int *ioidp, const int *rearr, const PIO_Offset *iostart, const PIO_Offset *iocount); diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray_int.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray_int.c index f99b4e9959..39ff5c8f65 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray_int.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_darray_int.c @@ -803,10 +803,9 @@ send_all_start_count(iosystem_desc_t *ios, io_desc_t *iodesc, PIO_Offset llen, "invalid inputs", __FILE__, __LINE__); /* Do a handshake. */ -#ifdef DO_HANDSHAKE if ((mpierr = MPI_Recv(&ierr, 1, MPI_INT, 0, 0, ios->io_comm, &status))) return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); -#endif + /* Send local length of iobuffer for each field (all * fields are the same length). */ if ((mpierr = MPI_Send((void *)&llen, 1, MPI_OFFSET, 0, ios->io_rank, ios->io_comm))) @@ -905,10 +904,9 @@ recv_and_write_data(file_desc_t *file, const int *varids, const int *frame, if (rtask) { /* handshake - tell the sending task I'm ready */ -#ifdef DO_HANDSHAKE if ((mpierr = MPI_Send(&ierr, 1, MPI_INT, rtask, 0, ios->io_comm))) return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); -#endif + /* 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, 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 06de1f4c00..1edf4f42ec 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_file.c @@ -398,6 +398,7 @@ PIOc_sync(int ncid) int ierr = PIO_NOERR; /* Return code from function calls. */ PLOG((1, "PIOc_sync ncid = %d", ncid)); + /* Get the file info from the ncid. */ if ((ierr = pio_get_file(ncid, &file))) return pio_err(NULL, NULL, ierr, __FILE__, __LINE__); diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_rearrange.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_rearrange.c index 02c11ec5b6..7f8bb5cc12 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_rearrange.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pio_rearrange.c @@ -89,6 +89,7 @@ expand_region(int dim, const int *gdimlen, int maplen, const PIO_Offset *map, "invalid input", __FILE__, __LINE__); /* Expand no greater than max_size along this dimension. */ + PLOG((3,"expand_region: max_size[%d]=%d region_size=%d",dim, max_size[dim], region_size)); for (int i = 1; i <= max_size[dim]; ++i) { /* Count so far is at least i. */ @@ -107,6 +108,7 @@ expand_region(int dim, const int *gdimlen, int maplen, const PIO_Offset *map, /* If we have exhausted the map, or the map no longer matches, we are done, break out of both loops. */ + PLOG((3,"dim=%d maplen = %d map[%d]=%d map[%d]=%d i=%d region_stride=%d",dim, maplen, test_idx, map[test_idx], j, map[j],i,region_stride)); if (test_idx >= maplen || map[test_idx] != map[j] + i * region_stride) { expansion_done = 1; @@ -117,7 +119,7 @@ expand_region(int dim, const int *gdimlen, int maplen, const PIO_Offset *map, break; } - + PLOG((3,"expansion_done = %d count[%d]=%ld",expansion_done, dim, count[dim])); /* Move on to next outermost dimension if there are more left, * else return. */ if (dim > 0) @@ -390,16 +392,8 @@ create_mpi_datatypes(MPI_Datatype mpitype, int msgcnt, displace[j] = ((lindex + pos)[j * blocksize] - 1); } -#if PIO_ENABLE_LOGGING - int cnt=0; - for (int j = 1; j < len; j++){ - PLOG((4, "displace[%d] = %d blocksize=%d mfrom %x", j, displace[j], blocksize, mfrom)); - } - -#endif /* PIO_ENABLE_LOGGING */ - PLOG((2, "calling MPI_Type_create_indexed_block len = %d blocksize = %d " - "mpitype = %d", len, blocksize, mpitype)); + "mpitype = %d displace[0]=%d", len, blocksize, mpitype, displace[0])); /* Create an indexed datatype with constant-sized blocks. */ mpierr = MPI_Type_create_indexed_block(len, blocksize, displace, mpitype, &mtype[i]); @@ -417,13 +411,6 @@ create_mpi_datatypes(MPI_Datatype mpitype, int msgcnt, return check_mpi(NULL, NULL, mpierr, __FILE__, __LINE__); pos += mcount[i]; -// MPI_Aint ext, lb; -// int tsize; -// MPI_Type_get_extent(mtype[i], &lb, &ext); -// MPI_Type_size(mtype[i], &tsize); -// printf("%d lb %d extent %d tsize %d\n",__LINE__, lb, ext, tsize); - - } } @@ -889,8 +876,6 @@ rearrange_comp2io(iosystem_desc_t *ios, io_desc_t *iodesc, void *sbuf, recvtypes[i] = PIO_DATATYPE_NULL; sendtypes[i] = PIO_DATATYPE_NULL; } -// PLOG((3, "ntasks = %d iodesc->mpitype_size = %d niotasks = %d", ntasks, -// iodesc->mpitype_size, niotasks)); /* If it has not already been done, define the MPI data types that * will be used for this io_desc_t. */ @@ -1128,11 +1113,10 @@ rearrange_io2comp(iosystem_desc_t *ios, io_desc_t *iodesc, void *sbuf, /* Data in sbuf on the ionodes is sent to rbuf on the compute * nodes. */ - + if ((ret = pio_swapm(sbuf, sendcounts, sdispls, sendtypes, rbuf, recvcounts, rdispls, recvtypes, mycomm, &iodesc->rearr_opts.io2comp))) return pio_err(ios, NULL, ret, __FILE__, __LINE__); - #ifdef TIMING if ((ret = pio_stop_timer("PIO:rearrange_io2comp"))) return pio_err(ios, NULL, ret, __FILE__, __LINE__); @@ -1859,7 +1843,7 @@ compare_offsets(const void *a, const void *b) * @param gdimlen an array length ndims with the sizes of the global * dimensions. * @param maplen the length of the map - * @param map may be NULL (when ???). + * @param map may be NULL (when maplen==0). * @param maxregions * @param firstregion pointer to the first region. * @returns 0 on success, error code otherwise. @@ -1911,7 +1895,8 @@ get_regions(int ndims, const int *gdimlen, int maplen, const PIO_Offset *map, nmaplen = nmaplen + regionlen; PLOG((2, "regionlen = %d nmaplen = %d", regionlen, nmaplen)); - + for (int i = 0; i < ndims; i++) + PLOG((3,"region start[%d]=%ld count[%d]=%ld",i,region->start[i], i, region->count[i])); /* If we need to, allocate the next region. */ if (region->next == NULL && nmaplen < maplen) { @@ -2135,7 +2120,7 @@ subset_rearrange_create(iosystem_desc_t *ios, int maplen, PIO_Offset *compmap, PLOG((4,"compmap[%d] = %d ",i, compmap[i])); if (compmap[i] > 0){ PLOG((4,"sindex[%d] = %d ",j, i)); - iodesc->sindex[j++] = i; + iodesc->sindex[j++] = i; } } @@ -2266,6 +2251,9 @@ subset_rearrange_create(iosystem_desc_t *ios, int maplen, PIO_Offset *compmap, cnt[i] = rdispls[i]; } + for (i=0; i< iodesc->llen; i++) + iomap[i] = 0; + /* For IO tasks init rfrom and rindex arrays (compute tasks have * llen of 0). */ int rllen; @@ -2273,24 +2261,36 @@ subset_rearrange_create(iosystem_desc_t *ios, int maplen, PIO_Offset *compmap, /* we only want a single copy of each source point in the iobuffer but it may be sent to multiple destinations in a read operation */ int k=0; - PIO_Offset previomap[ntasks]; - for (i = 0; i < ntasks; i++) - previomap[i] = -1; +// PIO_Offset previomap[ntasks]; +// for (i = 0; i < ntasks; i++) +// previomap[i] = -1; + if(iodesc->llen > 0){ + mapsort *mptr = &map[0]; + iomap[0] = mptr->iomap; + soffset = mptr->soffset; + int increment; + for (i = 0, rllen=0; i < iodesc->llen; i++) { - mapsort *mptr = &map[i]; + mptr = &map[i]; + increment = 0; iodesc->rfrom[i] = mptr->rfrom; - if(mptr->iomap > previomap[mptr->rfrom]) - { +// if(mptr->iomap > previomap[mptr->rfrom]) +// { + if(i==iodesc->llen-1 || mptr->iomap < map[i+1].iomap){ iomap[rllen] = mptr->iomap; - soffset = mptr->soffset; + increment = 1; } - previomap[mptr->rfrom]=iomap[rllen]; + soffset = mptr->soffset; + +// } +// previomap[mptr->rfrom]=iomap[rllen]; srcindex[(cnt[mptr->rfrom])++] = soffset; - iodesc->rindex[i] = rllen++; + iodesc->rindex[i] = rllen; + rllen = rllen + increment; iodesc->rllen = rllen; } - + } /* Handle fill values if needed. */ PLOG((3, "ios->ioproc %d iodesc->needsfill %d iodesc->rllen %d", ios->ioproc, iodesc->needsfill, iodesc->rllen)); diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc.c index 2ea700c52c..dc5a6eb051 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc.c @@ -660,17 +660,19 @@ PIOc_InitDecomp(int iosysid, int pio_type, int ndims, const int *gdimlen, int ma if (iodesc->rearranger == PIO_REARR_SUBSET) { /* check if the decomp is valid for write or is read-only */ - if(ios->compproc){ + iodesc->readonly = false; +/* if(ios->compproc){ // It should be okay to use compmap here but test_darray_fill shows // the compmap array modified by this call, TODO - investigate this. PIO_Offset *tmpmap; - if (!(tmpmap = malloc(sizeof(PIO_Offset) * maplen))) - return PIO_ENOMEM; + if (!(tmpmap = malloc(sizeof(PIO_Offset) * maplen))) + return PIO_ENOMEM; memcpy(tmpmap, compmap, maplen*sizeof(PIO_Offset)); if((ierr = run_unique_check(ios->comp_comm, (size_t) maplen, tmpmap, &iodesc->readonly))) return pio_err(ios, NULL, ierr, __FILE__, __LINE__); - free(tmpmap); + free(tmpmap); } +*/ /* printf("readonly: %d\n",iodesc->readonly); for(int i=0;imap, gdimlen, ndims, iodesc))) return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + + } + else /* box rearranger */ + { + if (ios->ioproc) + { + /* Unless the user specifies the start and count for each + * IO task compute it. */ + if (iostart && iocount) + { + PLOG((3, "iostart and iocount provided")); + for (int i = 0; i < ndims; i++) + { + iodesc->firstregion->start[i] = iostart[i]; + iodesc->firstregion->count[i] = iocount[i]; + } + iodesc->num_aiotasks = ios->num_iotasks; + } + else + { + /* Compute start and count values for each io task. */ + PLOG((2, "about to call CalcStartandCount pio_type = %d ndims = %d", pio_type, ndims)); + if ((ierr = CalcStartandCount(pio_type, ndims, gdimlen, ios->num_iotasks, + ios->io_rank, iodesc->firstregion->start, + iodesc->firstregion->count, &iodesc->num_aiotasks))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + } + + /* Compute the max io buffer size needed for an iodesc. */ + if ((ierr = compute_maxIObuffersize(ios->io_comm, iodesc))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + PLOG((3, "compute_maxIObuffersize called iodesc->maxiobuflen = %d", + iodesc->maxiobuflen)); + } + + /* Depending on array size and io-blocksize the actual number + * of io tasks used may vary. */ + if ((mpierr = MPI_Bcast(&(iodesc->num_aiotasks), 1, MPI_INT, ios->ioroot, + ios->my_comm))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + PLOG((3, "iodesc->num_aiotasks = %d", iodesc->num_aiotasks)); + + /* Compute the communications pattern for this decomposition. */ + if (iodesc->rearranger == PIO_REARR_BOX) + if ((ierr = box_rearrange_create(ios, maplen, iodesc->map, gdimlen, ndims, iodesc))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + } + + /* Broadcast next ioid to all tasks from io root.*/ + if (ios->async) + { + PLOG((3, "initdecomp bcasting pio_next_ioid %d", pio_next_ioid)); + if ((mpierr = MPI_Bcast(&pio_next_ioid, 1, MPI_INT, ios->ioroot, ios->my_comm))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + PLOG((3, "initdecomp bcast pio_next_ioid %d", pio_next_ioid)); + } + + /* Set the decomposition ID. */ + iodesc->ioid = pio_next_ioid++; + if (ioidp) + *ioidp = iodesc->ioid; + + /* Add this IO description to the list. */ + if ((ierr = pio_add_to_iodesc_list(iodesc))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + +#if PIO_ENABLE_LOGGING + /* Log results. */ + PLOG((2, "iodesc ioid = %d nrecvs = %d ndof = %d ndims = %d num_aiotasks = %d " + "rearranger = %d maxregions = %d needsfill = %d llen = %d maxiobuflen = %d", + iodesc->ioid, iodesc->nrecvs, iodesc->ndof, iodesc->ndims, iodesc->num_aiotasks, + iodesc->rearranger, iodesc->maxregions, iodesc->needsfill, iodesc->llen, + iodesc->maxiobuflen)); + if (iodesc->rindex) + for (int j = 0; j < iodesc->llen; j++) + PLOG((3, "rindex[%d] = %lld", j, iodesc->rindex[j])); +#endif /* PIO_ENABLE_LOGGING */ + + /* This function only does something if pre-processor macro + * PERFTUNE is set. */ + performance_tune_rearranger(ios, iodesc); + +#ifdef USE_MPE + pio_stop_mpe_log(DECOMP, __func__); +#endif /* USE_MPE */ + + return PIO_NOERR; +} + +/** + * Initialize the decomposition used with distributed arrays. The + * decomposition describes how the data will be distributed between + * tasks. + * + * Internally, this function will: + *
    + *
  • Allocate and initialize an iodesc struct for this + * decomposition. (This also allocates an io_region struct for the + * first region.) + *
  • (Box rearranger only) If iostart or iocount are NULL, call + * CalcStartandCount() to determine starts/counts. Then call + * compute_maxIObuffersize() to compute the max IO buffer size needed. + *
  • Create the rearranger. + *
  • Assign an ioid and add this decomposition to the list of open + * decompositions. + *
+ * + * @param iosysid the IO system ID. + * @param pio_type the basic PIO data type used. + * @param ndims the number of dimensions in the variable, not + * including the unlimited dimension. + * @param gdimlen an array length ndims with the sizes of the global + * dimensions. + * @param maplen the local length of the compmap array. + * @param compmap a 1 based array of offsets into the array record on + * file. A 0 in this array indicates a value which should not be + * transfered. + * @param ioidp pointer that will get the io description ID. Ignored + * if NULL. + * @param rearranger pointer to the rearranger to be used for this + * decomp or NULL to use the default. + * @param iostart An array of start values for block cyclic + * decompositions for the SUBSET rearranger. Ignored if block + * rearranger is used. If NULL and SUBSET rearranger is used, the + * iostarts are generated. + * @param iocount An array of count values for block cyclic + * decompositions for the SUBSET rearranger. Ignored if block + * rearranger is used. If NULL and SUBSET rearranger is used, the + * iostarts are generated. + * @returns 0 on success, error code otherwise + * @ingroup PIO_initdecomp_c + * @author Jim Edwards, Ed Hartnett + */ +int +PIOc_InitDecomp_ReadOnly(int iosysid, int pio_type, int ndims, const int *gdimlen, int maplen, + const PIO_Offset *compmap, int *ioidp, const int *rearranger, + const PIO_Offset *iostart, const PIO_Offset *iocount) +{ + iosystem_desc_t *ios; /* Pointer to io system information. */ + io_desc_t *iodesc; /* The IO description. */ + int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function calls. */ + int ierr; /* Return code. */ + + PLOG((1, "PIOc_InitDecomp iosysid = %d pio_type = %d ndims = %d maplen = %d", + iosysid, pio_type, ndims, maplen)); + +#ifdef USE_MPE + pio_start_mpe_log(DECOMP); +#endif /* USE_MPE */ + + /* Get IO system info. */ + if (!(ios = pio_get_iosystem_from_id(iosysid))) + return pio_err(NULL, NULL, PIO_EBADID, __FILE__, __LINE__); + + /* Caller must provide these. */ + if (!gdimlen || !compmap || !ioidp) + return pio_err(ios, NULL, PIO_EINVAL, __FILE__, __LINE__); + + /* Check the dim lengths. */ + for (int i = 0; i < ndims; i++) + if (gdimlen[i] <= 0) + return pio_err(ios, NULL, PIO_EINVAL, __FILE__, __LINE__); + + /* 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_INITDECOMP_DOF; /* Message for async notification. */ + char rearranger_present = rearranger ? true : false; + char iostart_present = iostart ? true : false; + char iocount_present = iocount ? true : false; + if (ios->compmaster == MPI_ROOT){ + PLOG((1, "about to sent msg %d union_comm %d",msg,ios->union_comm)); + mpierr = MPI_Send(&msg, 1, MPI_INT, ios->ioroot, 1, ios->union_comm); + } + if (!mpierr) + mpierr = MPI_Bcast(&iosysid, 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast(&pio_type, 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((int *)gdimlen, ndims, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast(&maplen, 1, MPI_INT, ios->compmaster, ios->intercomm); + if (!mpierr) + mpierr = MPI_Bcast((PIO_Offset *)compmap, maplen, MPI_OFFSET, ios->compmaster, ios->intercomm); + + if (!mpierr) + mpierr = MPI_Bcast(&rearranger_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); + if (rearranger_present && !mpierr) + mpierr = MPI_Bcast((int *)rearranger, 1, MPI_INT, ios->compmaster, ios->intercomm); + + if (!mpierr) + mpierr = MPI_Bcast(&iostart_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); + if (iostart_present && !mpierr) + mpierr = MPI_Bcast((PIO_Offset *)iostart, ndims, MPI_OFFSET, ios->compmaster, ios->intercomm); + + if (!mpierr) + mpierr = MPI_Bcast(&iocount_present, 1, MPI_CHAR, ios->compmaster, ios->intercomm); + if (iocount_present && !mpierr) + mpierr = MPI_Bcast((PIO_Offset *)iocount, ndims, MPI_OFFSET, ios->compmaster, ios->intercomm); + PLOG((2, "PIOc_InitDecomp iosysid = %d pio_type = %d ndims = %d maplen = %d rearranger_present = %d iostart_present = %d " + "iocount_present = %d ", iosysid, pio_type, ndims, maplen, rearranger_present, iostart_present, iocount_present)); + } + + /* Handle MPI errors. */ + if ((mpierr2 = MPI_Bcast(&mpierr, 1, MPI_INT, ios->comproot, ios->my_comm))) + return check_mpi(ios, NULL, mpierr2, __FILE__, __LINE__); + if (mpierr) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); + + if(rearranger && (*rearranger != ios->default_rearranger)) + return pio_err(ios, NULL, PIO_EBADREARR, __FILE__,__LINE__); + + } + + /* Allocate space for the iodesc info. This also allocates the + * first region and copies the rearranger opts into this + * iodesc. */ + PLOG((2, "allocating iodesc pio_type %d ndims %d", pio_type, ndims)); + if ((ierr = malloc_iodesc(ios, pio_type, ndims, &iodesc))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + + /* Remember the maplen. */ + iodesc->maplen = maplen; + + /* Remember the map. */ + if (!(iodesc->map = malloc(sizeof(PIO_Offset) * maplen))) + return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); + iodesc->needssort = false; + iodesc->remap = NULL; + for (int m = 0; m < maplen; m++) + { + if(m > 0 && compmap[m] > 0 && compmap[m] < compmap[m-1]) + { + iodesc->needssort = true; + PLOG((2, "compmap[%d] = %ld compmap[%d]= %ld", m, compmap[m], m-1, compmap[m-1])); + break; + } + } + if (iodesc->needssort) + { + struct sort_map *tmpsort; + + if (!(tmpsort = malloc(sizeof(struct sort_map) * maplen))) + return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); + if (!(iodesc->remap = malloc(sizeof(int) * maplen))) + { + free(tmpsort); + return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); + } + for (int m=0; m < maplen; m++) + { + tmpsort[m].remap = m; + tmpsort[m].map = compmap[m]; + } + qsort( tmpsort, maplen, sizeof(struct sort_map), compare ); + for (int m=0; m < maplen; m++) + { + iodesc->map[m] = compmap[tmpsort[m].remap]; + iodesc->remap[m] = tmpsort[m].remap; + } + free(tmpsort); + } + else + { + for (int m=0; m < maplen; m++) + { + iodesc->map[m] = compmap[m]; + } + } + + /* Remember the dim sizes. */ + if (!(iodesc->dimlen = malloc(sizeof(int) * ndims))) + return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); + for (int d = 0; d < ndims; d++) + iodesc->dimlen[d] = gdimlen[d]; + + /* Set the rearranger. */ + if (!rearranger) + iodesc->rearranger = ios->default_rearranger; + else + iodesc->rearranger = *rearranger; + PLOG((2, "iodesc->rearranger = %d", iodesc->rearranger)); + + /* Is this the subset rearranger? */ + if (iodesc->rearranger == PIO_REARR_SUBSET) + { + iodesc->readonly = true; + /* check if the decomp is valid for write or is read-only */ +/* if(ios->compproc){ + // It should be okay to use compmap here but test_darray_fill shows + // the compmap array modified by this call, TODO - investigate this. + PIO_Offset *tmpmap; + if (!(tmpmap = malloc(sizeof(PIO_Offset) * maplen))) + return PIO_ENOMEM; + memcpy(tmpmap, compmap, maplen*sizeof(PIO_Offset)); + if((ierr = run_unique_check(ios->comp_comm, (size_t) maplen, tmpmap, &iodesc->readonly))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); + free(tmpmap); + } +*/ /* printf("readonly: %d\n",iodesc->readonly); + for(int i=0;inum_aiotasks = ios->num_iotasks; + PLOG((2, "creating subset rearranger iodesc->num_aiotasks = %d readonly = %d", + iodesc->num_aiotasks, iodesc->readonly)); + if ((ierr = subset_rearrange_create(ios, maplen, (PIO_Offset *)iodesc->map, gdimlen, + ndims, iodesc))) + return pio_err(ios, NULL, ierr, __FILE__, __LINE__); } else /* box rearranger */ { @@ -1071,219 +1385,72 @@ PIOc_Init_Intracomm(MPI_Comm comp_comm, int num_iotasks, int stride, int base, return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); /* Create an MPI communicator for the IO tasks. */ - if ((mpierr = MPI_Comm_create(ios->comp_comm, iogroup, &ios->io_comm))) - return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); - - /* Free the MPI groups. */ - if (compgroup != MPI_GROUP_NULL) - MPI_Group_free(&compgroup); - - if (iogroup != MPI_GROUP_NULL) - MPI_Group_free(&iogroup); - - /* For the tasks that are doing IO, get their rank within the IO - * communicator. If they are not doing IO, set their io_rank to - * -1. */ - if (ios->ioproc) - { - if ((mpierr = MPI_Comm_rank(ios->io_comm, &ios->io_rank))) - return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); - } - else - ios->io_rank = -1; - PLOG((3, "ios->io_comm = %d ios->io_rank = %d", ios->io_comm, ios->io_rank)); - - /* Rank in the union comm is the same as rank in the comp comm. */ - ios->union_rank = ios->comp_rank; - - /* Add this ios struct to the list in the PIO library. */ - *iosysidp = pio_add_to_iosystem_list(ios); - -#ifdef USE_MPE - pio_stop_mpe_log(INIT, __func__); -#endif /* USE_MPE */ - PLOG((2, "Init_Intracomm complete iosysid = %d", *iosysidp)); - - return PIO_NOERR; -} - -/** - * Interface to call from pio_init from fortran. - * - * @param f90_comp_comm - * @param num_iotasks the number of IO tasks - * @param stride the stride to use assigning tasks - * @param base the starting point when assigning tasks - * @param rearr the rearranger - * @param rearr_opts the rearranger options - * @param iosysidp a pointer that gets the IO system ID - * @returns 0 for success, error code otherwise - * @ingroup PIO_init_c - * @author Jim Edwards - */ -int -PIOc_Init_Intracomm_from_F90(int f90_comp_comm, - const int num_iotasks, const int stride, - const int base, const int rearr, - rearr_opt_t *rearr_opts, int *iosysidp) -{ - int ret = PIO_NOERR; - ret = PIOc_Init_Intracomm(MPI_Comm_f2c(f90_comp_comm), num_iotasks, - stride, base, rearr, - iosysidp); - if (ret != PIO_NOERR) - { - PLOG((1, "PIOc_Init_Intracomm failed")); - return ret; - } - - if (rearr_opts) - { - PLOG((1, "Setting rearranger options, iosys=%d", *iosysidp)); - return PIOc_set_rearr_opts(*iosysidp, rearr_opts->comm_type, - rearr_opts->fcd, - rearr_opts->comp2io.hs, - rearr_opts->comp2io.isend, - rearr_opts->comp2io.max_pend_req, - rearr_opts->io2comp.hs, - rearr_opts->io2comp.isend, - rearr_opts->io2comp.max_pend_req); - } - return ret; -} - -/** - * Interface to call from pio_init from fortran. - * - * @param f90_world_comm the incoming communicator which includes all tasks - * @param num_io_procs the number of IO tasks - * @param io_proc_list the rank of io tasks in f90_world_comm - * @param component_count the number of computational components - * used an iosysid will be generated for each - * @param procs_per_component the number of procs in each computational component - * @param flat_proc_list a 1D array of size - * component_count*maxprocs_per_component with rank in f90_world_comm - * @param f90_io_comm the io_comm handle to be returned to fortran - * @param f90_comp_comm the comp_comm handle to be returned to fortran - * @param rearranger currently only PIO_REARRANGE_BOX is supported - * @param iosysidp pointer to array of length component_count that - * gets the iosysid for each component. - * @returns 0 for success, error code otherwise - * @ingroup PIO_init_c - * @author Jim Edwards - */ -int -PIOc_init_async_from_F90(int f90_world_comm, - int num_io_procs, - int *io_proc_list, - int component_count, - int *procs_per_component, - int *flat_proc_list, - int *f90_io_comm, - int *f90_comp_comm, - int rearranger, - int *iosysidp) - -{ - int ret = PIO_NOERR; - MPI_Comm io_comm, comp_comm; - int maxprocs_per_component=0; + if ((mpierr = MPI_Comm_create(ios->comp_comm, iogroup, &ios->io_comm))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); - for(int i=0; i< component_count; i++) - maxprocs_per_component = (procs_per_component[i] > maxprocs_per_component) ? procs_per_component[i] : maxprocs_per_component; + /* Free the MPI groups. */ + if (compgroup != MPI_GROUP_NULL) + MPI_Group_free(&compgroup); - int **proc_list = (int **) malloc(sizeof(int *) *component_count); + if (iogroup != MPI_GROUP_NULL) + MPI_Group_free(&iogroup); - for(int i=0; i< component_count; i++){ - proc_list[i] = (int *) malloc(sizeof(int) * maxprocs_per_component); - for(int j=0;jioproc) + { + if ((mpierr = MPI_Comm_rank(ios->io_comm, &ios->io_rank))) + return check_mpi(ios, NULL, mpierr, __FILE__, __LINE__); } - - ret = PIOc_init_async(MPI_Comm_f2c(f90_world_comm), num_io_procs, io_proc_list, - component_count, procs_per_component, proc_list, &io_comm, - &comp_comm, rearranger, iosysidp); - if(comp_comm) - *f90_comp_comm = MPI_Comm_c2f(comp_comm); - else - *f90_comp_comm = 0; - if(io_comm) - *f90_io_comm = MPI_Comm_c2f(io_comm); else - *f90_io_comm = 0; + ios->io_rank = -1; + PLOG((3, "ios->io_comm = %d ios->io_rank = %d", ios->io_comm, ios->io_rank)); - if (ret != PIO_NOERR) - { - PLOG((1, "PIOc_Init_Intercomm failed")); - return ret; - } -/* - if (rearr_opts) - { - PLOG((1, "Setting rearranger options, iosys=%d", *iosysidp)); - return PIOc_set_rearr_opts(*iosysidp, rearr_opts->comm_type, - rearr_opts->fcd, - rearr_opts->comp2io.hs, - rearr_opts->comp2io.isend, - rearr_opts->comp2io.max_pend_req, - rearr_opts->io2comp.hs, - rearr_opts->io2comp.isend, - rearr_opts->io2comp.max_pend_req); - } -*/ - return ret; + /* Rank in the union comm is the same as rank in the comp comm. */ + ios->union_rank = ios->comp_rank; + + /* Add this ios struct to the list in the PIO library. */ + *iosysidp = pio_add_to_iosystem_list(ios); + +#ifdef USE_MPE + pio_stop_mpe_log(INIT, __func__); +#endif /* USE_MPE */ + PLOG((2, "Init_Intracomm complete iosysid = %d", *iosysidp)); + + return PIO_NOERR; } /** * Interface to call from pio_init from fortran. * - * @param f90_world_comm the incoming communicator which includes all tasks - * @param component_count the number of computational components - * used an iosysid will be generated for each and a comp_comm is expected - * for each - * @param f90_comp_comms the comp_comm handles passed from fortran - * @param f90_io_comm the io_comm passed from fortran - * @param rearranger currently only PIO_REARRANGE_BOX is supported - * @param iosysidp pointer to array of length component_count that - * gets the iosysid for each component. + * @param f90_comp_comm + * @param num_iotasks the number of IO tasks + * @param stride the stride to use assigning tasks + * @param base the starting point when assigning tasks + * @param rearr the rearranger + * @param rearr_opts the rearranger options + * @param iosysidp a pointer that gets the IO system ID * @returns 0 for success, error code otherwise * @ingroup PIO_init_c * @author Jim Edwards */ int -PIOc_init_async_comms_from_F90(int f90_world_comm, - int component_count, - int *f90_comp_comms, - int f90_io_comm, - int rearranger, - int *iosysidp) - +PIOc_Init_Intracomm_from_F90(int f90_comp_comm, + const int num_iotasks, const int stride, + const int base, const int rearr, + rearr_opt_t *rearr_opts, int *iosysidp) { int ret = PIO_NOERR; - MPI_Comm comp_comm[component_count]; - MPI_Comm io_comm; - - for(int i=0; iio2comp.isend, rearr_opts->io2comp.max_pend_req); } -*/ return ret; } @@ -1524,657 +1690,6 @@ PIOc_iotype_available(int iotype) } } -/** - * Library initialization used when IO tasks are distinct from compute - * tasks. - * - * This is a collective call. Input parameters are read on - * comp_rank=0 values on other tasks are ignored. This variation of - * PIO_init sets up a distinct set of tasks to handle IO, these tasks - * do not return from this call. Instead they go to an internal loop - * and wait to receive further instructions from the computational - * tasks. - * - * Sequence of Events to do Asynch I/O - * ----------------------------------- - * - * Here is the sequence of events that needs to occur when an IO - * operation is called from the collection of compute tasks. I'm - * going to use pio_put_var because write_darray has some special - * characteristics that make it a bit more complicated... - * - * Compute tasks call pio_put_var with an integer argument - * - * The MPI_Send sends a message from comp_rank=0 to io_rank=0 on - * union_comm (a comm defined as the union of io and compute tasks) - * msg is an integer which indicates the function being called, in - * this case the msg is PIO_MSG_PUT_VAR_INT - * - * The iotasks now know what additional arguments they should expect - * to receive from the compute tasks, in this case a file handle, a - * variable id, the length of the array and the array itself. - * - * The iotasks now have the information they need to complete the - * operation and they call the pio_put_var routine. (In pio1 this bit - * of code is in pio_get_put_callbacks.F90.in) - * - * After the netcdf operation is completed (in the case of an inq or - * get operation) the result is communicated back to the compute - * tasks. - * - * @param world the communicator containing all the available tasks. - * - * @param num_io_procs the number of processes for the IO component. - * - * @param io_proc_list an array of lenth num_io_procs with the - * processor number for each IO processor. If NULL then the IO - * processes are assigned starting at processes 0. - * - * @param component_count number of computational components - * - * @param num_procs_per_comp an array of int, of length - * component_count, with the number of processors in each computation - * component. - * - * @param proc_list an array of arrays containing the processor - * numbers for each computation component. If NULL then the - * computation components are assigned processors sequentially - * starting with processor num_io_procs. - * - * @param user_io_comm pointer to an MPI_Comm. If not NULL, it will - * get an MPI duplicate of the IO communicator. (It is a full - * duplicate and later must be freed with MPI_Free() by the caller.) - * - * @param user_comp_comm pointer to an array of pointers to MPI_Comm; - * the array is of length component_count. If not NULL, it will get an - * MPI duplicate of each computation communicator. (These are full - * duplicates and each must later be freed with MPI_Free() by the - * caller.) - * - * @param rearranger the default rearranger to use for decompositions - * in this IO system. Only PIO_REARR_BOX is supported for - * async. Support for PIO_REARR_SUBSET will be provided in a future - * version. - * - * @param iosysidp pointer to array of length component_count that - * gets the iosysid for each component. - * - * @return PIO_NOERR on success, error code otherwise. - * @ingroup PIO_init_c - * @author Ed Hartnett - */ -int -PIOc_init_async(MPI_Comm world, int num_io_procs, int *io_proc_list, - int component_count, int *num_procs_per_comp, int **proc_list, - MPI_Comm *user_io_comm, MPI_Comm *user_comp_comm, int rearranger, - int *iosysidp) -{ - int my_rank; /* Rank of this task. */ - int **my_proc_list; /* Array of arrays of procs for comp components. */ - int my_io_proc_list[num_io_procs]; /* List of processors in IO component. */ - int mpierr; /* Return code from MPI functions. */ - int ret; /* Return code. */ -// int world_size; - - /* Check input parameters. Only allow box rearranger for now. */ - if (num_io_procs < 1 || component_count < 1 || !num_procs_per_comp || !iosysidp || - (rearranger != PIO_REARR_BOX && rearranger != PIO_REARR_SUBSET)) - return pio_err(NULL, NULL, PIO_EINVAL, __FILE__, __LINE__); - - my_proc_list = (int**) malloc(component_count * sizeof(int*)); - - /* Turn on the logging system for PIO. */ - if ((ret = pio_init_logging())) - return pio_err(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((1, "PIOc_init_async num_io_procs = %d component_count = %d", num_io_procs, - component_count)); - -#ifdef USE_MPE - pio_start_mpe_log(INIT); -#endif /* USE_MPE */ - - /* Determine which tasks to use for IO. */ - for (int p = 0; p < num_io_procs; p++) - my_io_proc_list[p] = io_proc_list ? io_proc_list[p] : p; - - /* Determine which tasks to use for each computational component. */ - if ((ret = determine_procs(num_io_procs, component_count, num_procs_per_comp, - proc_list, my_proc_list))) - return pio_err(NULL, NULL, ret, __FILE__, __LINE__); - - /* Get rank of this task in world. */ - if ((ret = MPI_Comm_rank(world, &my_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - /* Get size of world. */ -// if ((ret = MPI_Comm_size(world, &world_size))) -// return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - /* Is this process in the IO component? */ - int pidx; - for (pidx = 0; pidx < num_io_procs; pidx++) - if (my_rank == my_io_proc_list[pidx]) - break; - int in_io = (pidx == num_io_procs) ? 0 : 1; - PLOG((3, "in_io = %d", in_io)); - - /* Allocate struct to hold io system info for each computation component. */ - iosystem_desc_t *iosys[component_count], *my_iosys; - for (int cmp1 = 0; cmp1 < component_count; cmp1++) - if (!(iosys[cmp1] = (iosystem_desc_t *)calloc(1, sizeof(iosystem_desc_t)))) - return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); - - /* Create group for world. */ - MPI_Group world_group; - if ((ret = MPI_Comm_group(world, &world_group))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "world group created")); - - /* We will create a group for the IO component. */ - MPI_Group io_group; - - /* The shared IO communicator. */ - MPI_Comm io_comm; - - /* Rank of current process in IO communicator. */ - int io_rank = -1; - - /* Set to MPI_ROOT on master process, MPI_PROC_NULL on other - * processes. */ - int iomaster; - - /* Create a group for the IO component. */ - if ((ret = MPI_Group_incl(world_group, num_io_procs, my_io_proc_list, &io_group))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "created IO group - io_group = %d MPI_GROUP_EMPTY = %d", io_group, MPI_GROUP_EMPTY)); - - /* There is one shared IO comm. Create it. */ - if ((ret = MPI_Comm_create(world, io_group, &io_comm))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "created io comm io_comm = %d", io_comm)); - - /* Does the user want a copy of the IO communicator? */ - if (user_io_comm) - { - *user_io_comm = MPI_COMM_NULL; - if (in_io) - if ((mpierr = MPI_Comm_dup(io_comm, user_io_comm))) - return check_mpi(NULL, NULL, mpierr, __FILE__, __LINE__); - } - - /* For processes in the IO component, get their rank within the IO - * communicator. */ - if (in_io) - { - PLOG((3, "about to get io rank")); - if ((ret = MPI_Comm_rank(io_comm, &io_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - iomaster = !io_rank ? MPI_ROOT : MPI_PROC_NULL; - PLOG((3, "intracomm created for io_comm = %d io_rank = %d IO %s", - io_comm, io_rank, iomaster == MPI_ROOT ? "MASTER" : "SERVANT")); - } - - /* We will create a group for each computational component. */ - MPI_Group group[component_count]; - - /* We will also create a group for each component and the IO - * component processes (i.e. a union of computation and IO - * processes. */ - MPI_Group union_group[component_count]; - - /* For each computation component. */ - for (int cmp = 0; cmp < component_count; cmp++) - { - PLOG((3, "processing component %d", cmp)); - - /* Get pointer to current iosys. */ - my_iosys = iosys[cmp]; - - /* The rank of the computation leader in the union comm. */ - my_iosys->comproot = num_io_procs; - - /* Initialize some values. */ - my_iosys->io_comm = MPI_COMM_NULL; - my_iosys->comp_comm = MPI_COMM_NULL; - my_iosys->union_comm = MPI_COMM_NULL; - my_iosys->intercomm = MPI_COMM_NULL; - my_iosys->my_comm = MPI_COMM_NULL; - my_iosys->async = 1; - my_iosys->error_handler = default_error_handler; - my_iosys->num_comptasks = num_procs_per_comp[cmp]; - my_iosys->num_iotasks = num_io_procs; - my_iosys->num_uniontasks = my_iosys->num_comptasks + my_iosys->num_iotasks; - my_iosys->default_rearranger = rearranger; - - /* Initialize the rearranger options. */ - my_iosys->rearr_opts.comm_type = PIO_REARR_COMM_COLL; - my_iosys->rearr_opts.fcd = PIO_REARR_COMM_FC_2D_DISABLE; - - /* We are not providing an info object. */ - my_iosys->info = MPI_INFO_NULL; - - /* Create a group for this component. */ - if ((ret = MPI_Group_incl(world_group, num_procs_per_comp[cmp], my_proc_list[cmp], - &group[cmp]))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "created component MPI group - group[%d] = %d", cmp, group[cmp])); - - /* For all the computation components create a union group - * with their processors and the processors of the (shared) IO - * component. */ - - /* How many processors in the union comm? */ - int nprocs_union = num_io_procs + num_procs_per_comp[cmp]; - - /* This will hold proc numbers from both computation and IO - * components. */ - int proc_list_union[nprocs_union]; - - /* Add proc numbers from IO. */ - for (int p = 0; p < num_io_procs; p++) - proc_list_union[p] = my_io_proc_list[p]; - - /* Add proc numbers from computation component. */ - for (int p = 0; p < num_procs_per_comp[cmp]; p++) - proc_list_union[p + num_io_procs] = my_proc_list[cmp][p]; - -// qsort(proc_list_union, num_procs_per_comp[cmp] + num_io_procs, sizeof(int), compare_ints); - for (int p = 0; p < num_procs_per_comp[cmp] + num_io_procs; p++) - PLOG((3, "p %d num_io_procs %d proc_list_union[p + num_io_procs] %d ", - p, num_io_procs, proc_list_union[p])); - - /* The rank of the computation leader in the union comm. First task which is not an io task */ - my_iosys->ioroot = 0; -/* - my_iosys->comproot = -1; - my_iosys->ioroot = -1; - for (int p = 0; p < num_procs_per_comp[cmp] + num_io_procs; p++) - { - bool ioproc = false; - for (int q = 0; q < num_io_procs; q++) - { - if (proc_list_union[p] == my_io_proc_list[q]) - { - ioproc = true; - my_iosys->ioroot = proc_list_union[p]; - break; - } - } - if ( !ioproc && my_iosys->comproot < 0) - { - my_iosys->comproot = proc_list_union[p]; - } - } -*/ - - PLOG((3, "my_iosys->comproot = %d ioroot = %d", my_iosys->comproot, my_iosys->ioroot)); - - - - /* Allocate space for computation task ranks. */ - if (!(my_iosys->compranks = calloc(my_iosys->num_comptasks, sizeof(int)))) - return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); - - /* Remember computation task ranks. We need the ranks within - * the union_comm. */ - for (int p = 0; p < num_procs_per_comp[cmp]; p++) - my_iosys->compranks[p] = num_io_procs + p; - - /* Remember whether this process is in the IO component. */ - my_iosys->ioproc = in_io; - - /* With async, tasks are either in a computation component or - * the IO component. */ - my_iosys->compproc = !in_io; - - /* Is this process in this computation component? */ - int in_cmp = 0; - for (pidx = 0; pidx < num_procs_per_comp[cmp]; pidx++) - if (my_rank == my_proc_list[cmp][pidx]) - break; - in_cmp = (pidx == num_procs_per_comp[cmp]) ? 0 : 1; - PLOG((3, "pidx = %d num_procs_per_comp[%d] = %d in_cmp = %d", - pidx, cmp, num_procs_per_comp[cmp], in_cmp)); - - /* Create the union group. */ - if ((ret = MPI_Group_incl(world_group, nprocs_union, proc_list_union, &union_group[cmp]))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "created union MPI_group - union_group[%d] = %d with %d procs", cmp, - union_group[cmp], nprocs_union)); - - /* Create an intracomm for this component. Only processes in - * the component need to participate in the intracomm create - * call. */ - PLOG((3, "creating intracomm cmp = %d from group[%d] = %d", cmp, cmp, group[cmp])); - if ((ret = MPI_Comm_create(world, group[cmp], &my_iosys->comp_comm))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - if (in_cmp) - { - /* Does the user want a copy? */ - if (user_comp_comm) - if ((mpierr = MPI_Comm_dup(my_iosys->comp_comm, &user_comp_comm[cmp]))) - return check_mpi(NULL, NULL, mpierr, __FILE__, __LINE__); - - /* Get the rank in this comp comm. */ - if ((ret = MPI_Comm_rank(my_iosys->comp_comm, &my_iosys->comp_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - /* Set comp_rank 0 to be the compmaster. It will have a - * setting of MPI_ROOT, all other tasks will have a - * setting of MPI_PROC_NULL. */ - my_iosys->compmaster = my_iosys->comp_rank ? MPI_PROC_NULL : MPI_ROOT; - - PLOG((3, "intracomm created for cmp = %d comp_comm = %d comp_rank = %d comp %s", - cmp, my_iosys->comp_comm, my_iosys->comp_rank, - my_iosys->compmaster == MPI_ROOT ? "MASTER" : "SERVANT")); - } - - /* If this is the IO component, make a copy of the IO comm for - * each computational component. */ - if (in_io) - { - PLOG((3, "making a dup of io_comm = %d io_rank = %d", io_comm, io_rank)); - if ((ret = MPI_Comm_dup(io_comm, &my_iosys->io_comm))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "dup of io_comm = %d io_rank = %d", my_iosys->io_comm, io_rank)); - my_iosys->iomaster = iomaster; - my_iosys->io_rank = io_rank; - my_iosys->ioroot = 0; - my_iosys->comp_idx = cmp; - } - - /* Create an array that holds the ranks of the tasks to be used - * for IO. */ - if (!(my_iosys->ioranks = calloc(my_iosys->num_iotasks, sizeof(int)))) - return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); - for (int i = 0; i < my_iosys->num_iotasks; i++) - my_iosys->ioranks[i] = i; - - /* All the processes in this component, and the IO component, - * are part of the union_comm. */ - PLOG((3, "before creating union_comm my_iosys->io_comm = %d group = %d", my_iosys->io_comm, union_group[cmp])); - if ((ret = MPI_Comm_create(world, union_group[cmp], &my_iosys->union_comm))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "created union comm for cmp %d my_iosys->union_comm %d", cmp, my_iosys->union_comm)); - - - if (in_io || in_cmp) - { - if ((ret = MPI_Comm_rank(my_iosys->union_comm, &my_iosys->union_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((3, "my_iosys->union_rank %d", my_iosys->union_rank)); - - /* Set my_comm to union_comm for async. */ - my_iosys->my_comm = my_iosys->union_comm; - PLOG((3, "intracomm created for union cmp = %d union_rank = %d union_comm = %d", - cmp, my_iosys->union_rank, my_iosys->union_comm)); - - if (in_io) - { - PLOG((3, "my_iosys->io_comm = %d", my_iosys->io_comm)); - /* Create the intercomm from IO to computation component. */ - PLOG((3, "about to create intercomm for IO component to cmp = %d " - "my_iosys->io_comm = %d comproot %d", cmp, my_iosys->io_comm, my_iosys->comproot)); - if ((ret = MPI_Intercomm_create(my_iosys->io_comm, 0, my_iosys->union_comm, - my_iosys->comproot, cmp, &my_iosys->intercomm))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - } - else - { - /* Create the intercomm from computation component to IO component. */ - PLOG((3, "about to create intercomm for cmp = %d my_iosys->comp_comm = %d ioroot %d", cmp, - my_iosys->comp_comm, my_iosys->ioroot)); - if ((ret = MPI_Intercomm_create(my_iosys->comp_comm, 0, my_iosys->union_comm, - my_iosys->ioroot, cmp, &my_iosys->intercomm))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - } - PLOG((3, "intercomm created for cmp = %d", cmp)); - } - - /* Add this id to the list of PIO iosystem ids. */ - iosysidp[cmp] = pio_add_to_iosystem_list(my_iosys); - PLOG((2, "new iosys ID added to iosystem_list iosysidp[%d] = %d", cmp, iosysidp[cmp])); - -#ifdef NETCDF_INTEGRATION - if (in_io || in_cmp) - { - /* Remember the io system id. */ - diosysid = iosysidp[cmp]; - PLOG((3, "diosysid = %d", iosysidp[cmp])); - } -#endif /* NETCDF_INTEGRATION */ - - } /* next computational component */ - - /* Now call the function from which the IO tasks will not return - * until the PIO_MSG_EXIT message is sent. This will handle - * messages from all computation components. */ - if (in_io) - { - PLOG((2, "Starting message handler io_rank = %d component_count = %d", - io_rank, component_count)); -#ifdef USE_MPE - pio_stop_mpe_log(INIT, __func__); -#endif /* USE_MPE */ - - /* Start the message handler loop. This will not return until - * an exit message is sent, or an error occurs. */ - if ((ret = pio_msg_handler2(io_rank, component_count, iosys, io_comm))) - return pio_err(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((2, "Returned from pio_msg_handler2() ret = %d", ret)); - } - - /* Free resources if needed. */ - if (in_io) - if ((mpierr = MPI_Comm_free(&io_comm))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - /* Free the arrays of processor numbers. */ - for (int cmp = 0; cmp < component_count; cmp++) - free(my_proc_list[cmp]); - - free(my_proc_list); - - /* Free MPI groups. */ - if ((ret = MPI_Group_free(&io_group))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - for (int cmp = 0; cmp < component_count; cmp++) - { - if ((ret = MPI_Group_free(&group[cmp]))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - if ((ret = MPI_Group_free(&union_group[cmp]))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - } - - if ((ret = MPI_Group_free(&world_group))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - -#ifdef USE_MPE - if (!in_io) - pio_stop_mpe_log(INIT, __func__); -#endif /* USE_MPE */ - - PLOG((2, "successfully done with PIOc_init_async")); - return PIO_NOERR; -} - -/** - * Library initialization used when IO tasks are distinct from compute - * tasks. - * - * This is a collective call. Input parameters are read on - * each comp_rank=0 and on io_rank=0, values on other tasks are ignored. - * This variation of PIO_init uses tasks in io_comm to handle IO, - * these tasks do not return from this call. Instead they go to an internal loop - * and wait to receive further instructions from the computational - * tasks. - * - * Sequence of Events to do Asynch I/O - * ----------------------------------- - * - * Here is the sequence of events that needs to occur when an IO - * operation is called from the collection of compute tasks. I'm - * going to use pio_put_var because write_darray has some special - * characteristics that make it a bit more complicated... - * - * Compute tasks call pio_put_var with an integer argument - * - * The MPI_Send sends a message from comp_rank=0 to io_rank=0 on - * union_comm (a comm defined as the union of io and compute tasks) - * msg is an integer which indicates the function being called, in - * this case the msg is PIO_MSG_PUT_VAR_INT - * - * The iotasks now know what additional arguments they should expect - * to receive from the compute tasks, in this case a file handle, a - * variable id, the length of the array and the array itself. - * - * The iotasks now have the information they need to complete the - * operation and they call the pio_put_var routine. (In pio1 this bit - * of code is in pio_get_put_callbacks.F90.in) - * - * After the netcdf operation is completed (in the case of an inq or - * get operation) the result is communicated back to the compute - * tasks. - * - * @param world the communicator containing all the available tasks. - * - * @param component_count number of computational components - * - * @param comp_comm an array of size component_count which are the defined - * comms of each component - comp_comm should be MPI_COMM_NULL on tasks outside - * the tasks of each comm these comms may overlap - * - * @param io_comm a communicator for the IO group, tasks in this comm do not - * return from this call. - * - * @param rearranger the default rearranger to use for decompositions - * in this IO system. Only PIO_REARR_BOX is supported for - * async. Support for PIO_REARR_SUBSET will be provided in a future - * version. - * - * @param iosysidp pointer to array of length component_count that - * gets the iosysid for each component. - * - * @return PIO_NOERR on success, error code otherwise. - * @ingroup PIO_init_c - * @author Jim Edwards - */ -int -PIOc_init_async_from_comms(MPI_Comm world, int component_count, MPI_Comm *comp_comm, - MPI_Comm io_comm, int rearranger, int *iosysidp) -{ - int my_rank; /* Rank of this task. */ - int **my_proc_list; /* Array of arrays of procs for comp components. */ - int *io_proc_list; /* List of processors in IO component. */ - int *num_procs_per_comp; /* List of number of tasks in each component */ - int num_io_procs = 0; - int ret; /* Return code. */ -#ifdef USE_MPE - bool in_io = false; -#endif /* USE_MPE */ - -#ifdef USE_MPE - pio_start_mpe_log(INIT); -#endif /* USE_MPE */ - - /* Check input parameters. Only allow box rearranger for now. */ - if (component_count < 1 || !comp_comm || !iosysidp || - (rearranger != PIO_REARR_BOX && rearranger != PIO_REARR_SUBSET)) - return pio_err(NULL, NULL, PIO_EINVAL, __FILE__, __LINE__); - - /* Turn on the logging system for PIO. */ - if ((ret = pio_init_logging())) - return pio_err(NULL, NULL, ret, __FILE__, __LINE__); - PLOG((1, "PIOc_init_async_from_comms component_count = %d", component_count)); - - /* Get num_io_procs from io_comm, share with world */ - if (io_comm != MPI_COMM_NULL) - { -#ifdef USE_MPE - in_io = true; -#endif /* USE_MPE */ - if ((ret = MPI_Comm_size(io_comm, &num_io_procs))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - } - if ((ret = MPI_Allreduce(MPI_IN_PLACE, &num_io_procs, 1, MPI_INT, MPI_MAX, world))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - /* Get io_proc_list from io_comm, share with world */ - io_proc_list = (int*) calloc(num_io_procs, sizeof(int)); - if (io_comm != MPI_COMM_NULL) - { - int my_io_rank; - if ((ret = MPI_Comm_rank(io_comm, &my_io_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - if ((ret = MPI_Comm_rank(world, &my_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - io_proc_list[my_io_rank] = my_rank; - component_count = 0; - } - if ((ret = MPI_Allreduce(MPI_IN_PLACE, io_proc_list, num_io_procs, MPI_INT, MPI_MAX, world))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - /* Get num_procs_per_comp for each comp and share with world */ - if ((ret = MPI_Allreduce(MPI_IN_PLACE, &(component_count), 1, MPI_INT, MPI_MAX, world))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - num_procs_per_comp = (int *) malloc(component_count * sizeof(int)); - - for(int cmp=0; cmp < component_count; cmp++) - { - num_procs_per_comp[cmp] = 0; - if(comp_comm[cmp] != MPI_COMM_NULL) - if ((ret = MPI_Comm_size(comp_comm[cmp], &(num_procs_per_comp[cmp])))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - if ((ret = MPI_Allreduce(MPI_IN_PLACE, &(num_procs_per_comp[cmp]), 1, MPI_INT, MPI_MAX, world))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - - } - - /* Get proc list for each comp and share with world */ - my_proc_list = (int**) malloc(component_count * sizeof(int*)); - - for(int cmp=0; cmp < component_count; cmp++) - { - if (!(my_proc_list[cmp] = (int *) malloc(num_procs_per_comp[cmp] * sizeof(int)))) - return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); - for(int i = 0; i < num_procs_per_comp[cmp]; i++) - my_proc_list[cmp][i] = 0; - if(comp_comm[cmp] != MPI_COMM_NULL){ - int my_comp_rank; - if ((ret = MPI_Comm_rank(comp_comm[cmp], &my_comp_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - if ((ret = MPI_Comm_rank(world, &my_rank))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - my_proc_list[cmp][my_comp_rank] = my_rank; - } - if ((ret = MPI_Allreduce(MPI_IN_PLACE, my_proc_list[cmp], num_procs_per_comp[cmp], - MPI_INT, MPI_MAX, world))) - return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); - } - - if((ret = PIOc_init_async(world, num_io_procs, io_proc_list, component_count, - num_procs_per_comp, my_proc_list, NULL, NULL, rearranger, - iosysidp))) - return pio_err(NULL, NULL, ret, __FILE__, __LINE__); - - for(int cmp=0; cmp < component_count; cmp++) - free(my_proc_list[cmp]); - free(my_proc_list); - free(io_proc_list); - free(num_procs_per_comp); - -#ifdef USE_MPE - if (!in_io) - pio_stop_mpe_log(INIT, __func__); -#endif /* USE_MPE */ - - PLOG((2, "successfully done with PIOc_init_async_from_comms")); - return PIO_NOERR; -} - /** * Set the target blocksize for the box rearranger. * diff --git a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_async.c b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_async.c new file mode 100644 index 0000000000..7676f1e2d1 --- /dev/null +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_async.c @@ -0,0 +1,836 @@ +/** + * @file + * Some initialization and support functions. + * @author Jim Edwards + * @date 2014 + * + * @see https://github.com/NCAR/ParallelIO + */ +#include +#include +#include +#include + +#ifdef NETCDF_INTEGRATION +#include "ncintdispatch.h" +#endif /* NETCDF_INTEGRATION */ + +#ifdef USE_MPE +/* The event numbers for MPE logging. */ +extern int event_num[2][NUM_EVENTS]; +#endif /* USE_MPE */ + +#ifdef NETCDF_INTEGRATION +/* Have we initialized the netcdf integration code? */ +extern int ncint_initialized; + +/* This is used as the default iosysid for the netcdf integration + * code. */ +extern int diosysid; +#endif /* NETCDF_INTEGRATION */ + +extern int default_error_handler; /* defined in pioc.c */ + +/** + * Library initialization used when IO tasks are distinct from compute + * tasks. + * + * This is a collective call. Input parameters are read on + * comp_rank=0 values on other tasks are ignored. This variation of + * PIO_init sets up a distinct set of tasks to handle IO, these tasks + * do not return from this call. Instead they go to an internal loop + * and wait to receive further instructions from the computational + * tasks. + * + * Sequence of Events to do Asynch I/O + * ----------------------------------- + * + * Here is the sequence of events that needs to occur when an IO + * operation is called from the collection of compute tasks. I'm + * going to use pio_put_var because write_darray has some special + * characteristics that make it a bit more complicated... + * + * Compute tasks call pio_put_var with an integer argument + * + * The MPI_Send sends a message from comp_rank=0 to io_rank=0 on + * union_comm (a comm defined as the union of io and compute tasks) + * msg is an integer which indicates the function being called, in + * this case the msg is PIO_MSG_PUT_VAR_INT + * + * The iotasks now know what additional arguments they should expect + * to receive from the compute tasks, in this case a file handle, a + * variable id, the length of the array and the array itself. + * + * The iotasks now have the information they need to complete the + * operation and they call the pio_put_var routine. (In pio1 this bit + * of code is in pio_get_put_callbacks.F90.in) + * + * After the netcdf operation is completed (in the case of an inq or + * get operation) the result is communicated back to the compute + * tasks. + * + * @param world the communicator containing all the available tasks. + * + * @param num_io_procs the number of processes for the IO component. + * + * @param io_proc_list an array of lenth num_io_procs with the + * processor number for each IO processor. If NULL then the IO + * processes are assigned starting at processes 0. + * + * @param component_count number of computational components + * + * @param num_procs_per_comp an array of int, of length + * component_count, with the number of processors in each computation + * component. + * + * @param proc_list an array of arrays containing the processor + * numbers for each computation component. If NULL then the + * computation components are assigned processors sequentially + * starting with processor num_io_procs. + * + * @param user_io_comm pointer to an MPI_Comm. If not NULL, it will + * get an MPI duplicate of the IO communicator. (It is a full + * duplicate and later must be freed with MPI_Free() by the caller.) + * + * @param user_comp_comm pointer to an array of pointers to MPI_Comm; + * the array is of length component_count. If not NULL, it will get an + * MPI duplicate of each computation communicator. (These are full + * duplicates and each must later be freed with MPI_Free() by the + * caller.) + * + * @param rearranger the default rearranger to use for decompositions + * in this IO system. Only PIO_REARR_BOX is supported for + * async. Support for PIO_REARR_SUBSET will be provided in a future + * version. + * + * @param iosysidp pointer to array of length component_count that + * gets the iosysid for each component. + * + * @return PIO_NOERR on success, error code otherwise. + * @ingroup PIO_init_c + * @author Ed Hartnett + */ +int +PIOc_init_async(MPI_Comm world, int num_io_procs, int *io_proc_list, + int component_count, int *num_procs_per_comp, int **proc_list, + MPI_Comm *user_io_comm, MPI_Comm *user_comp_comm, int rearranger, + int *iosysidp) +{ + int my_rank; /* Rank of this task. */ + int **my_proc_list; /* Array of arrays of procs for comp components. */ + int my_io_proc_list[num_io_procs]; /* List of processors in IO component. */ + int mpierr; /* Return code from MPI functions. */ + int ret; /* Return code. */ +// int world_size; + + /* Check input parameters. Only allow box rearranger for now. */ + if (num_io_procs < 1 || component_count < 1 || !num_procs_per_comp || !iosysidp || + (rearranger != PIO_REARR_BOX && rearranger != PIO_REARR_SUBSET)) + return pio_err(NULL, NULL, PIO_EINVAL, __FILE__, __LINE__); + + my_proc_list = (int**) malloc(component_count * sizeof(int*)); + + /* Turn on the logging system for PIO. */ + if ((ret = pio_init_logging())) + return pio_err(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((1, "PIOc_init_async num_io_procs = %d component_count = %d", num_io_procs, + component_count)); + +#ifdef USE_MPE + pio_start_mpe_log(INIT); +#endif /* USE_MPE */ + + /* Determine which tasks to use for IO. */ + for (int p = 0; p < num_io_procs; p++) + my_io_proc_list[p] = io_proc_list ? io_proc_list[p] : p; + + PLOG((1, "PIOc_init_async call determine_procs")); + /* Determine which tasks to use for each computational component. */ + if ((ret = determine_procs(num_io_procs, component_count, num_procs_per_comp, + proc_list, my_proc_list))) + return pio_err(NULL, NULL, ret, __FILE__, __LINE__); + + PLOG((1, "PIOc_init_async determine_procs done world=%d",world)); + /* Get rank of this task in world. */ + if ((ret = MPI_Comm_rank(world, &my_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + /* Get size of world. */ +// if ((ret = MPI_Comm_size(world, &world_size))) +// return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + PLOG((1, "%d: num_io_procs = %d", my_rank, num_io_procs)); + + /* Is this process in the IO component? */ + int pidx; + for (pidx = 0; pidx < num_io_procs; pidx++) + if (my_rank == my_io_proc_list[pidx]) + break; + int in_io = (pidx == num_io_procs) ? 0 : 1; + PLOG((1, "in_io = %d", in_io)); + + /* Allocate struct to hold io system info for each computation component. */ + iosystem_desc_t *iosys[component_count], *my_iosys; + for (int cmp1 = 0; cmp1 < component_count; cmp1++) + if (!(iosys[cmp1] = (iosystem_desc_t *)calloc(1, sizeof(iosystem_desc_t)))) + return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); + + PLOG((1, "create world group ")); + /* Create group for world. */ + MPI_Group world_group; + if ((ret = MPI_Comm_group(world, &world_group))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((1, "world group created")); + + /* We will create a group for the IO component. */ + MPI_Group io_group; + + /* The shared IO communicator. */ + MPI_Comm io_comm; + + /* Rank of current process in IO communicator. */ + int io_rank = -1; + + /* Set to MPI_ROOT on master process, MPI_PROC_NULL on other + * processes. */ + int iomaster; + + /* Create a group for the IO component. */ + if ((ret = MPI_Group_incl(world_group, num_io_procs, my_io_proc_list, &io_group))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((1, "created IO group - io_group = %d MPI_GROUP_EMPTY = %d", io_group, MPI_GROUP_EMPTY)); + + /* There is one shared IO comm. Create it. */ + if ((ret = MPI_Comm_create(world, io_group, &io_comm))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((1, "created io comm io_comm = %d", io_comm)); + + /* Does the user want a copy of the IO communicator? */ + if (user_io_comm) + { + *user_io_comm = MPI_COMM_NULL; + if (in_io) + if ((mpierr = MPI_Comm_dup(io_comm, user_io_comm))) + return check_mpi(NULL, NULL, mpierr, __FILE__, __LINE__); + } + + /* For processes in the IO component, get their rank within the IO + * communicator. */ + if (in_io) + { + PLOG((3, "about to get io rank")); + if ((ret = MPI_Comm_rank(io_comm, &io_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + iomaster = !io_rank ? MPI_ROOT : MPI_PROC_NULL; + PLOG((3, "intracomm created for io_comm = %d io_rank = %d IO %s", + io_comm, io_rank, iomaster == MPI_ROOT ? "MASTER" : "SERVANT")); + } + + /* We will create a group for each computational component. */ + MPI_Group group[component_count]; + + /* We will also create a group for each component and the IO + * component processes (i.e. a union of computation and IO + * processes. */ + MPI_Group union_group[component_count]; + + /* For each computation component. */ + for (int cmp = 0; cmp < component_count; cmp++) + { + PLOG((2, "processing component %d", cmp)); + + /* Get pointer to current iosys. */ + my_iosys = iosys[cmp]; + + /* The rank of the computation leader in the union comm. */ + my_iosys->comproot = num_io_procs; + + /* Initialize some values. */ + my_iosys->io_comm = MPI_COMM_NULL; + my_iosys->comp_comm = MPI_COMM_NULL; + my_iosys->union_comm = MPI_COMM_NULL; + my_iosys->intercomm = MPI_COMM_NULL; + my_iosys->my_comm = MPI_COMM_NULL; + my_iosys->async = 1; + my_iosys->error_handler = default_error_handler; + my_iosys->num_comptasks = num_procs_per_comp[cmp]; + my_iosys->num_iotasks = num_io_procs; + my_iosys->num_uniontasks = my_iosys->num_comptasks + my_iosys->num_iotasks; + my_iosys->default_rearranger = rearranger; + + /* Initialize the rearranger options. */ + my_iosys->rearr_opts.comm_type = PIO_REARR_COMM_COLL; + my_iosys->rearr_opts.fcd = PIO_REARR_COMM_FC_2D_DISABLE; + + /* We are not providing an info object. */ + my_iosys->info = MPI_INFO_NULL; + + /* Create a group for this component. */ + if ((ret = MPI_Group_incl(world_group, num_procs_per_comp[cmp], my_proc_list[cmp], + &group[cmp]))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((2, "created component MPI group - group[%d] = %d", cmp, group[cmp])); + + /* For all the computation components create a union group + * with their processors and the processors of the (shared) IO + * component. */ + + /* How many processors in the union comm? */ + int nprocs_union = num_io_procs + num_procs_per_comp[cmp]; + + /* This will hold proc numbers from both computation and IO + * components. */ + int proc_list_union[nprocs_union]; + + /* Add proc numbers from IO. */ + for (int p = 0; p < num_io_procs; p++) + proc_list_union[p] = my_io_proc_list[p]; + + /* Add proc numbers from computation component. */ + for (int p = 0; p < num_procs_per_comp[cmp]; p++) + proc_list_union[p + num_io_procs] = my_proc_list[cmp][p]; + +// qsort(proc_list_union, num_procs_per_comp[cmp] + num_io_procs, sizeof(int), compare_ints); + for (int p = 0; p < num_procs_per_comp[cmp] + num_io_procs; p++) + PLOG((3, "p %d num_io_procs %d proc_list_union[p + num_io_procs] %d ", + p, num_io_procs, proc_list_union[p])); + + /* The rank of the computation leader in the union comm. First task which is not an io task */ + my_iosys->ioroot = 0; +/* + my_iosys->comproot = -1; + my_iosys->ioroot = -1; + for (int p = 0; p < num_procs_per_comp[cmp] + num_io_procs; p++) + { + bool ioproc = false; + for (int q = 0; q < num_io_procs; q++) + { + if (proc_list_union[p] == my_io_proc_list[q]) + { + ioproc = true; + my_iosys->ioroot = proc_list_union[p]; + break; + } + } + if ( !ioproc && my_iosys->comproot < 0) + { + my_iosys->comproot = proc_list_union[p]; + } + } +*/ + + PLOG((3, "my_iosys->comproot = %d ioroot = %d", my_iosys->comproot, my_iosys->ioroot)); + + + + /* Allocate space for computation task ranks. */ + if (!(my_iosys->compranks = calloc(my_iosys->num_comptasks, sizeof(int)))) + return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); + + /* Remember computation task ranks. We need the ranks within + * the union_comm. */ + for (int p = 0; p < num_procs_per_comp[cmp]; p++) + my_iosys->compranks[p] = num_io_procs + p; + + /* Remember whether this process is in the IO component. */ + my_iosys->ioproc = in_io; + + /* With async, tasks are either in a computation component or + * the IO component. */ + my_iosys->compproc = !in_io; + + /* Is this process in this computation component? */ + int in_cmp = 0; + for (pidx = 0; pidx < num_procs_per_comp[cmp]; pidx++) + if (my_rank == my_proc_list[cmp][pidx]) + break; + in_cmp = (pidx == num_procs_per_comp[cmp]) ? 0 : 1; + PLOG((3, "pidx = %d num_procs_per_comp[%d] = %d in_cmp = %d", + pidx, cmp, num_procs_per_comp[cmp], in_cmp)); + + /* Create the union group. */ + if ((ret = MPI_Group_incl(world_group, nprocs_union, proc_list_union, &union_group[cmp]))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((3, "created union MPI_group - union_group[%d] = %d with %d procs", cmp, + union_group[cmp], nprocs_union)); + + /* Create an intracomm for this component. Only processes in + * the component need to participate in the intracomm create + * call. */ + PLOG((3, "creating intracomm cmp = %d from group[%d] = %d", cmp, cmp, group[cmp])); + if ((ret = MPI_Comm_create(world, group[cmp], &my_iosys->comp_comm))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + if (in_cmp) + { + /* Does the user want a copy? */ + if (user_comp_comm) + if ((mpierr = MPI_Comm_dup(my_iosys->comp_comm, &user_comp_comm[cmp]))) + return check_mpi(NULL, NULL, mpierr, __FILE__, __LINE__); + + /* Get the rank in this comp comm. */ + if ((ret = MPI_Comm_rank(my_iosys->comp_comm, &my_iosys->comp_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + /* Set comp_rank 0 to be the compmaster. It will have a + * setting of MPI_ROOT, all other tasks will have a + * setting of MPI_PROC_NULL. */ + my_iosys->compmaster = my_iosys->comp_rank ? MPI_PROC_NULL : MPI_ROOT; + + PLOG((3, "intracomm created for cmp = %d comp_comm = %d comp_rank = %d comp %s", + cmp, my_iosys->comp_comm, my_iosys->comp_rank, + my_iosys->compmaster == MPI_ROOT ? "MASTER" : "SERVANT")); + } + + /* If this is the IO component, make a copy of the IO comm for + * each computational component. */ + if (in_io) + { + PLOG((3, "making a dup of io_comm = %d io_rank = %d", io_comm, io_rank)); + if ((ret = MPI_Comm_dup(io_comm, &my_iosys->io_comm))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((3, "dup of io_comm = %d io_rank = %d", my_iosys->io_comm, io_rank)); + my_iosys->iomaster = iomaster; + my_iosys->io_rank = io_rank; + my_iosys->ioroot = 0; + my_iosys->comp_idx = cmp; + } + + /* Create an array that holds the ranks of the tasks to be used + * for IO. */ + if (!(my_iosys->ioranks = calloc(my_iosys->num_iotasks, sizeof(int)))) + return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); + for (int i = 0; i < my_iosys->num_iotasks; i++) + my_iosys->ioranks[i] = i; + + /* All the processes in this component, and the IO component, + * are part of the union_comm. */ + PLOG((3, "before creating union_comm my_iosys->io_comm = %d group = %d", my_iosys->io_comm, union_group[cmp])); + if ((ret = MPI_Comm_create(world, union_group[cmp], &my_iosys->union_comm))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((3, "created union comm for cmp %d my_iosys->union_comm %d", cmp, my_iosys->union_comm)); + + + if (in_io || in_cmp) + { + if ((ret = MPI_Comm_rank(my_iosys->union_comm, &my_iosys->union_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((3, "my_iosys->union_rank %d", my_iosys->union_rank)); + + /* Set my_comm to union_comm for async. */ + my_iosys->my_comm = my_iosys->union_comm; + PLOG((3, "intracomm created for union cmp = %d union_rank = %d union_comm = %d", + cmp, my_iosys->union_rank, my_iosys->union_comm)); + + if (in_io) + { + PLOG((3, "my_iosys->io_comm = %d", my_iosys->io_comm)); + /* Create the intercomm from IO to computation component. */ + PLOG((3, "about to create intercomm for IO component to cmp = %d " + "my_iosys->io_comm = %d comproot %d", cmp, my_iosys->io_comm, my_iosys->comproot)); + if ((ret = MPI_Intercomm_create(my_iosys->io_comm, 0, my_iosys->union_comm, + my_iosys->comproot, cmp, &my_iosys->intercomm))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + } + else + { + /* Create the intercomm from computation component to IO component. */ + PLOG((3, "about to create intercomm for cmp = %d my_iosys->comp_comm = %d ioroot %d", cmp, + my_iosys->comp_comm, my_iosys->ioroot)); + if ((ret = MPI_Intercomm_create(my_iosys->comp_comm, 0, my_iosys->union_comm, + my_iosys->ioroot, cmp, &my_iosys->intercomm))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + } + PLOG((3, "intercomm created for cmp = %d", cmp)); + } + + /* Add this id to the list of PIO iosystem ids. */ + iosysidp[cmp] = pio_add_to_iosystem_list(my_iosys); + PLOG((2, "new iosys ID added to iosystem_list iosysidp[%d] = %d", cmp, iosysidp[cmp])); + +#ifdef NETCDF_INTEGRATION + if (in_io || in_cmp) + { + /* Remember the io system id. */ + diosysid = iosysidp[cmp]; + PLOG((3, "diosysid = %d", iosysidp[cmp])); + } +#endif /* NETCDF_INTEGRATION */ + + } /* next computational component */ + + /* Now call the function from which the IO tasks will not return + * until the PIO_MSG_EXIT message is sent. This will handle + * messages from all computation components. */ + if (in_io) + { + PLOG((2, "Starting message handler io_rank = %d component_count = %d", + io_rank, component_count)); +#ifdef USE_MPE + pio_stop_mpe_log(INIT, __func__); +#endif /* USE_MPE */ + + /* Start the message handler loop. This will not return until + * an exit message is sent, or an error occurs. */ + if ((ret = pio_msg_handler2(io_rank, component_count, iosys, io_comm))) + return pio_err(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((2, "Returned from pio_msg_handler2() ret = %d", ret)); + } + + /* Free resources if needed. */ + if (in_io) + if ((mpierr = MPI_Comm_free(&io_comm))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + /* Free the arrays of processor numbers. */ + for (int cmp = 0; cmp < component_count; cmp++) + free(my_proc_list[cmp]); + + free(my_proc_list); + + /* Free MPI groups. */ + if ((ret = MPI_Group_free(&io_group))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + for (int cmp = 0; cmp < component_count; cmp++) + { + if ((ret = MPI_Group_free(&group[cmp]))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + if ((ret = MPI_Group_free(&union_group[cmp]))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + } + + if ((ret = MPI_Group_free(&world_group))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + +#ifdef USE_MPE + if (!in_io) + pio_stop_mpe_log(INIT, __func__); +#endif /* USE_MPE */ + + PLOG((2, "successfully done with PIOc_init_async")); + return PIO_NOERR; +} + +/** + * Library initialization used when IO tasks are distinct from compute + * tasks. + * + * This is a collective call. Input parameters are read on + * each comp_rank=0 and on io_rank=0, values on other tasks are ignored. + * This variation of PIO_init uses tasks in io_comm to handle IO, + * these tasks do not return from this call. Instead they go to an internal loop + * and wait to receive further instructions from the computational + * tasks. + * + * Sequence of Events to do Asynch I/O + * ----------------------------------- + * + * Here is the sequence of events that needs to occur when an IO + * operation is called from the collection of compute tasks. I'm + * going to use pio_put_var because write_darray has some special + * characteristics that make it a bit more complicated... + * + * Compute tasks call pio_put_var with an integer argument + * + * The MPI_Send sends a message from comp_rank=0 to io_rank=0 on + * union_comm (a comm defined as the union of io and compute tasks) + * msg is an integer which indicates the function being called, in + * this case the msg is PIO_MSG_PUT_VAR_INT + * + * The iotasks now know what additional arguments they should expect + * to receive from the compute tasks, in this case a file handle, a + * variable id, the length of the array and the array itself. + * + * The iotasks now have the information they need to complete the + * operation and they call the pio_put_var routine. (In pio1 this bit + * of code is in pio_get_put_callbacks.F90.in) + * + * After the netcdf operation is completed (in the case of an inq or + * get operation) the result is communicated back to the compute + * tasks. + * + * @param world the communicator containing all the available tasks. + * + * @param component_count number of computational components + * + * @param comp_comm an array of size component_count which are the defined + * comms of each component - comp_comm should be MPI_COMM_NULL on tasks outside + * the tasks of each comm these comms may overlap + * + * @param io_comm a communicator for the IO group, tasks in this comm do not + * return from this call. + * + * @param rearranger the default rearranger to use for decompositions + * in this IO system. Only PIO_REARR_BOX is supported for + * async. Support for PIO_REARR_SUBSET will be provided in a future + * version. + * + * @param iosysidp pointer to array of length component_count that + * gets the iosysid for each component. + * + * @return PIO_NOERR on success, error code otherwise. + * @ingroup PIO_init_c + * @author Jim Edwards + */ +int +PIOc_init_async_from_comms(MPI_Comm world, int component_count, MPI_Comm *comp_comm, + MPI_Comm io_comm, int rearranger, int *iosysidp) +{ + int my_rank; /* Rank of this task. */ + int **my_proc_list; /* Array of arrays of procs for comp components. */ + int *io_proc_list; /* List of processors in IO component. */ + int *num_procs_per_comp; /* List of number of tasks in each component */ + int num_io_procs = 0; + int ret; /* Return code. */ +#ifdef USE_MPE + bool in_io = false; +#endif /* USE_MPE */ + +#ifdef USE_MPE + pio_start_mpe_log(INIT); +#endif /* USE_MPE */ + + /* Check input parameters. Only allow box rearranger for now. */ + if (component_count < 1 || !comp_comm || !iosysidp || + (rearranger != PIO_REARR_BOX && rearranger != PIO_REARR_SUBSET)) + return pio_err(NULL, NULL, PIO_EINVAL, __FILE__, __LINE__); + + /* Turn on the logging system for PIO. */ + if ((ret = pio_init_logging())) + return pio_err(NULL, NULL, ret, __FILE__, __LINE__); + PLOG((1, "PIOc_init_async_from_comms component_count = %d", component_count)); + + /* Get num_io_procs from io_comm, share with world */ + if (io_comm != MPI_COMM_NULL) + { +#ifdef USE_MPE + in_io = true; +#endif /* USE_MPE */ + if ((ret = MPI_Comm_size(io_comm, &num_io_procs))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + } + if ((ret = MPI_Allreduce(MPI_IN_PLACE, &num_io_procs, 1, MPI_INT, MPI_MAX, world))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + /* Get io_proc_list from io_comm, share with world */ + io_proc_list = (int*) calloc(num_io_procs, sizeof(int)); + if (io_comm != MPI_COMM_NULL) + { + int my_io_rank; + if ((ret = MPI_Comm_rank(io_comm, &my_io_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + if ((ret = MPI_Comm_rank(world, &my_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + io_proc_list[my_io_rank] = my_rank; + component_count = 0; + } + if ((ret = MPI_Allreduce(MPI_IN_PLACE, io_proc_list, num_io_procs, MPI_INT, MPI_MAX, world))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + /* Get num_procs_per_comp for each comp and share with world */ + if ((ret = MPI_Allreduce(MPI_IN_PLACE, &(component_count), 1, MPI_INT, MPI_MAX, world))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + num_procs_per_comp = (int *) malloc(component_count * sizeof(int)); + + for(int cmp=0; cmp < component_count; cmp++) + { + num_procs_per_comp[cmp] = 0; + if(comp_comm[cmp] != MPI_COMM_NULL) + if ((ret = MPI_Comm_size(comp_comm[cmp], &(num_procs_per_comp[cmp])))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + if ((ret = MPI_Allreduce(MPI_IN_PLACE, &(num_procs_per_comp[cmp]), 1, MPI_INT, MPI_MAX, world))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + + } + + /* Get proc list for each comp and share with world */ + my_proc_list = (int**) malloc(component_count * sizeof(int*)); + + for(int cmp=0; cmp < component_count; cmp++) + { + if (!(my_proc_list[cmp] = (int *) malloc(num_procs_per_comp[cmp] * sizeof(int)))) + return pio_err(NULL, NULL, PIO_ENOMEM, __FILE__, __LINE__); + for(int i = 0; i < num_procs_per_comp[cmp]; i++) + my_proc_list[cmp][i] = 0; + if(comp_comm[cmp] != MPI_COMM_NULL){ + int my_comp_rank; + if ((ret = MPI_Comm_rank(comp_comm[cmp], &my_comp_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + if ((ret = MPI_Comm_rank(world, &my_rank))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + my_proc_list[cmp][my_comp_rank] = my_rank; + } + if ((ret = MPI_Allreduce(MPI_IN_PLACE, my_proc_list[cmp], num_procs_per_comp[cmp], + MPI_INT, MPI_MAX, world))) + return check_mpi(NULL, NULL, ret, __FILE__, __LINE__); + } + + if((ret = PIOc_init_async(world, num_io_procs, io_proc_list, component_count, + num_procs_per_comp, my_proc_list, NULL, NULL, rearranger, + iosysidp))) + return pio_err(NULL, NULL, ret, __FILE__, __LINE__); + + for(int cmp=0; cmp < component_count; cmp++) + free(my_proc_list[cmp]); + free(my_proc_list); + free(io_proc_list); + free(num_procs_per_comp); + +#ifdef USE_MPE + if (!in_io) + pio_stop_mpe_log(INIT, __func__); +#endif /* USE_MPE */ + + PLOG((2, "successfully done with PIOc_init_async_from_comms")); + return PIO_NOERR; +} + +/** + * Interface to call from pio_init from fortran. + * + * @param f90_world_comm the incoming communicator which includes all tasks + * @param num_io_procs the number of IO tasks + * @param io_proc_list the rank of io tasks in f90_world_comm + * @param component_count the number of computational components + * used an iosysid will be generated for each + * @param procs_per_component the number of procs in each computational component + * @param flat_proc_list a 1D array of size + * component_count*maxprocs_per_component with rank in f90_world_comm + * @param f90_io_comm the io_comm handle to be returned to fortran + * @param f90_comp_comm the comp_comm handle to be returned to fortran + * @param rearranger currently only PIO_REARRANGE_BOX is supported + * @param iosysidp pointer to array of length component_count that + * gets the iosysid for each component. + * @returns 0 for success, error code otherwise + * @ingroup PIO_init_c + * @author Jim Edwards + */ +int +PIOc_init_async_from_F90(int f90_world_comm, + int num_io_procs, + int *io_proc_list, + int component_count, + int *procs_per_component, + int *flat_proc_list, + int *f90_io_comm, + int *f90_comp_comm, + int rearranger, + int *iosysidp) + +{ + int ret = PIO_NOERR; + MPI_Comm io_comm, comp_comm; + int maxprocs_per_component=0; + + for(int i=0; i< component_count; i++) + maxprocs_per_component = (procs_per_component[i] > maxprocs_per_component) ? procs_per_component[i] : maxprocs_per_component; + + int **proc_list = (int **) malloc(sizeof(int *) *component_count); + + for(int i=0; i< component_count; i++){ + proc_list[i] = (int *) malloc(sizeof(int) * maxprocs_per_component); + for(int j=0;jcomm_type, + rearr_opts->fcd, + rearr_opts->comp2io.hs, + rearr_opts->comp2io.isend, + rearr_opts->comp2io.max_pend_req, + rearr_opts->io2comp.hs, + rearr_opts->io2comp.isend, + rearr_opts->io2comp.max_pend_req); + } +*/ + return ret; +} + +/** + * Interface to call from pio_init from fortran. + * + * @param f90_world_comm the incoming communicator which includes all tasks + * @param component_count the number of computational components + * used an iosysid will be generated for each and a comp_comm is expected + * for each + * @param f90_comp_comms the comp_comm handles passed from fortran + * @param f90_io_comm the io_comm passed from fortran + * @param rearranger currently only PIO_REARRANGE_BOX is supported + * @param iosysidp pointer to array of length component_count that + * gets the iosysid for each component. + * @returns 0 for success, error code otherwise + * @ingroup PIO_init_c + * @author Jim Edwards + */ +int +PIOc_init_async_comms_from_F90(int f90_world_comm, + int component_count, + int *f90_comp_comms, + int f90_io_comm, + int rearranger, + int *iosysidp) + +{ + int ret = PIO_NOERR; + MPI_Comm comp_comm[component_count]; + MPI_Comm io_comm; + + for(int i=0; icomm_type, + rearr_opts->fcd, + rearr_opts->comp2io.hs, + rearr_opts->comp2io.isend, + rearr_opts->comp2io.max_pend_req, + rearr_opts->io2comp.hs, + rearr_opts->io2comp.isend, + rearr_opts->io2comp.max_pend_req); + } +*/ + return ret; +} 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 8b2ddf1689..c3d670450b 100644 --- a/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c +++ b/src/Infrastructure/IO/PIO/ParallelIO/src/clib/pioc_support.c @@ -1042,13 +1042,15 @@ PIOc_freedecomp(int iosysid, int ioid) /* Free the dimlens. */ free(iodesc->dimlen); - if (iodesc->remap) + if (iodesc->remap){ free(iodesc->remap); - + iodesc->remap = NULL; + } PLOG((3, "freeing rfrom, rtype")); - if (iodesc->rfrom) + if (iodesc->rfrom){ free(iodesc->rfrom); - + iodesc->rfrom = NULL; + } if (iodesc->rtype) { for (int i = 0; i < iodesc->nrecvs; i++) diff --git a/src/Infrastructure/Mesh/src/ESMCI_ESMFMesh_Util.C b/src/Infrastructure/Mesh/src/ESMCI_ESMFMesh_Util.C index 6c8add74b7..09397f5e98 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_ESMFMesh_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_ESMFMesh_Util.C @@ -237,7 +237,7 @@ void get_numElementConn_from_ESMFMesh_file(int pioSystemDesc, int pioFileDesc, c // Init numElementConn decomp int nec_iodesc; int gdimlen = (int) elementCount; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_BYTE, 1, &gdimlen, num_elems, nec_offsets, &nec_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_BYTE, 1, &gdimlen, num_elems, nec_offsets, &nec_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -271,7 +271,7 @@ void get_numElementConn_from_ESMFMesh_file(int pioSystemDesc, int pioFileDesc, c // Init numElementConn decomp int nec_iodesc; int gdimlen = (int) elementCount; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_INT, 1, &gdimlen, num_elems, nec_offsets, &nec_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_INT, 1, &gdimlen, num_elems, nec_offsets, &nec_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -505,7 +505,7 @@ void get_elemConn_info_1Dvar_from_ESMFMesh_file(int pioSystemDesc, int pioFileDe // Init elementConn decomp int ec_iodesc; int ec_gdimlen=connectionCount; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_INT, 1, &ec_gdimlen, totNumElementConn, ec_offsets, &ec_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_INT, 1, &ec_gdimlen, totNumElementConn, ec_offsets, &ec_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -597,7 +597,7 @@ void get_elemConn_info_2Dvar_from_ESMFMesh_file(int pioSystemDesc, int pioFileDe // Init elementConn decomp int ec_iodesc; int gdimlen2D[2]={(int)elementCount,(int)maxNodePElement}; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_INT, 2, gdimlen2D, totNumElementConn, ec_offsets, &ec_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_INT, 2, gdimlen2D, totNumElementConn, ec_offsets, &ec_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -731,7 +731,7 @@ void get_nodeCoords_from_ESMFMesh_file(int pioSystemDesc, int pioFileDesc, char // Init nodeCoords decomp int node_iodesc; int node_gdimlen2D[2]={(int)nodeCount, (int)coordDim}; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_DOUBLE, 2, node_gdimlen2D, num_nodes*coordDim, node_offsets, &node_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_DOUBLE, 2, node_gdimlen2D, num_nodes*coordDim, node_offsets, &node_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -797,7 +797,7 @@ void get_nodeMask_from_ESMFMesh_file(int pioSystemDesc, int pioFileDesc, char *f // Init nodeMask decomp int nm_iodesc; int nm_gdimlen = (int) nodeCount; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_INT, 1, &nm_gdimlen, num_nodes, nm_offsets, &nm_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_INT, 1, &nm_gdimlen, num_nodes, nm_offsets, &nm_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for nodeMask ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -861,7 +861,7 @@ void get_elementMask_from_ESMFMesh_file(int pioSystemDesc, int pioFileDesc, char // Init elementMask decomp int em_iodesc; int em_gdimlen = (int) elementCount; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_INT, 1, &em_gdimlen, num_elems, em_offsets, &em_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_INT, 1, &em_gdimlen, num_elems, em_offsets, &em_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for elementMask ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -930,7 +930,7 @@ void get_elementArea_from_ESMFMesh_file(int pioSystemDesc, int pioFileDesc, char // Init elementArea decomp int ea_iodesc; int ea_gdimlen = (int) elementCount; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_DOUBLE, 1, &ea_gdimlen, num_elems, ea_offsets, &ea_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_DOUBLE, 1, &ea_gdimlen, num_elems, ea_offsets, &ea_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for elementMask ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -1006,7 +1006,7 @@ void get_centerCoords_from_ESMFMesh_file(int pioSystemDesc, int pioFileDesc, cha // Init elementConn decomp int cc_iodesc; int cc_gdimlen2D[2]={(int)elementCount,(int)coordDim}; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_DOUBLE, 2, cc_gdimlen2D, num_elems*coordDim, cc_offsets, &cc_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_DOUBLE, 2, cc_gdimlen2D, num_elems*coordDim, cc_offsets, &cc_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for centerCoords ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; diff --git a/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C b/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C index 372e8075f3..735df9e73f 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C +++ b/src/Infrastructure/Mesh/src/ESMCI_UGRID_Util.C @@ -354,7 +354,7 @@ void get_elementConn_info_from_UGRID_file(int pioSystemDesc, int pioFileDesc, ch // Init elementConn decomp int ec_iodesc; int gdimlen2D[2]={(int)elementCount,(int)max_num_conns_per_elem}; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_INT, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_INT, 2, gdimlen2D, totNumRectElementConn, ec_offsets, &ec_iodesc, &rearr, NULL, NULL); @@ -650,7 +650,7 @@ void get_coords_from_UGRID_file(int pioSystemDesc, int pioFileDesc, char *filena // Init coords decomp int iodesc; int gdimlen=global_count; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_DOUBLE, 1, &gdimlen, num_ids, offsets, &iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_DOUBLE, 1, &gdimlen, num_ids, offsets, &iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; @@ -1070,7 +1070,7 @@ void get_mask_from_UGRID_file(int pioSystemDesc, int pioFileDesc, char *filename // Init elem mask decomp int em_iodesc; - piorc = PIOc_InitDecomp(pioSystemDesc, PIO_DOUBLE, num_dims, dim_sizes, num_ids, em_offsets, &em_iodesc, + piorc = PIOc_InitDecomp_ReadOnly(pioSystemDesc, PIO_DOUBLE, num_dims, dim_sizes, num_ids, em_offsets, &em_iodesc, &rearr, NULL, NULL); if (!CHECKPIOERROR(piorc, std::string("Error initializing PIO decomp for element mask from file ") + filename, ESMF_RC_FILE_OPEN, localrc)) throw localrc;; From 9ccdf456d4f900532e30383cb23811fd36bb0a46 Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Wed, 6 Jul 2022 12:48:59 -0600 Subject: [PATCH 022/266] use vm->getSsiMaxPetCount() instead of vm->getSsiLocalPetCount() for consistancy across pets --- src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C index ff07679f77..5e48148e89 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_FileIO.C @@ -168,13 +168,14 @@ void ESMCI_mesh_create_from_file(char *filename, int local_pet = vm->getLocalPet(); MPI_Comm mpi_comm = vm->getMpi_c(); int pet_count = vm->getPetCount(); - int pets_per_Ssi = vm->getSsiLocalPetCount(); + 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; From 83ecf338b7f511eef7eb229bccc0316301c98b9a Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 6 Jul 2022 12:59:55 -0700 Subject: [PATCH 023/266] Call SetVM from within the shared object support of DriverAddComp(). Implement the supporting infrastructure to robustly handle Fortran name mangling as for SetServices. --- .../Component/src/ESMCI_FTable.C | 16 +- .../Component/src/ESMF_GridComp.F90 | 30 +++- src/addon/NUOPC/src/NUOPC.F90 | 1 + src/addon/NUOPC/src/NUOPC_Comp.F90 | 162 ++++++++++++++++-- src/addon/NUOPC/src/NUOPC_Driver.F90 | 10 ++ 5 files changed, 195 insertions(+), 24 deletions(-) diff --git a/src/Superstructure/Component/src/ESMCI_FTable.C b/src/Superstructure/Component/src/ESMCI_FTable.C index f205967198..83586ba2b1 100644 --- a/src/Superstructure/Component/src/ESMCI_FTable.C +++ b/src/Superstructure/Component/src/ESMCI_FTable.C @@ -232,7 +232,7 @@ extern "C" { #undef ESMC_METHOD #define ESMC_METHOD "c_esmc_setvmshobj" void FTN_X(c_esmc_setvmshobj)(void *ptr, char const *routineArg, - char const *sharedObjArg, int *userRc, int *rc, + char const *sharedObjArg, ESMC_Logical *foundRoutine, int *userRc, int *rc, ESMCI_FortranStrLenArg rlen, ESMCI_FortranStrLenArg llen){ int localrc = ESMC_RC_NOT_IMPL; if (rc) *rc = ESMC_RC_NOT_IMPL; @@ -241,6 +241,7 @@ extern "C" { "- System does not support dynamic loading.", ESMC_CONTEXT, rc); return; #else + *foundRoutine = ESMF_FALSE; // initialize void *lib; if (llen>0){ string sharedObj(sharedObjArg, llen); @@ -256,14 +257,13 @@ extern "C" { string routine(routineArg, rlen); routine.resize(routine.find_last_not_of(" ")+1); void (*func)() = (void (*)())dlsym(lib, routine.c_str()); - if ((void *)func == NULL){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, - "routine not found", ESMC_CONTEXT, rc); - return; + if ((void *)func != NULL){ + // Routine was found + *foundRoutine = ESMF_TRUE; + ESMCI::FTable::setVM(ptr, func, userRc, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + rc)) return; } - ESMCI::FTable::setVM(ptr, func, userRc, &localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - rc)) return; // return successfully if (rc) *rc = ESMF_SUCCESS; #endif diff --git a/src/Superstructure/Component/src/ESMF_GridComp.F90 b/src/Superstructure/Component/src/ESMF_GridComp.F90 index 1048018b36..ba4930e0c0 100644 --- a/src/Superstructure/Component/src/ESMF_GridComp.F90 +++ b/src/Superstructure/Component/src/ESMF_GridComp.F90 @@ -2905,19 +2905,26 @@ end subroutine ESMF_GridCompSetVM ! !INTERFACE: ! Private name; call using ESMF_GridCompSetVM() recursive subroutine ESMF_GridCompSetVMShObj(gridcomp, userRoutine, & - keywordEnforcer, sharedObj, userRc, rc) + keywordEnforcer, sharedObj, userRoutineFound, userRc, rc) ! ! !ARGUMENTS: type(ESMF_GridComp), intent(inout) :: gridcomp character(len=*), intent(in) :: userRoutine type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below character(len=*), intent(in), optional :: sharedObj + logical, intent(out), optional :: userRoutineFound integer, intent(out), optional :: userRc integer, intent(out), optional :: rc ! ! !STATUS: ! \begin{itemize} ! \item\apiStatusCompatibleVersion{5.2.0r} +! \item\apiStatusModifiedSinceVersion{5.2.0r} +! \begin{description} +! \item[8.4.0] Added argument {\tt userRoutineFound}. +! The new argument provides a way to test availability without +! causing error conditions. +! \end{description} ! \end{itemize} ! ! !DESCRIPTION: @@ -2959,6 +2966,11 @@ recursive subroutine ESMF_GridCompSetVMShObj(gridcomp, userRoutine, & ! Name of shared object that contains {\tt userRoutine}. If the ! {\tt sharedObj} argument is not provided the executable itself will be ! searched for {\tt userRoutine}. +! \item[{[userRoutineFound]}] +! Report back whether the specified {\tt userRoutine} was found and executed, +! or was not available. If this argument is present, not finding the +! {\tt userRoutine} will not result in returning an error in {\tt rc}. +! The default is to return an error if the {\tt userRoutine} cannot be found. ! \item[{[userRc]}] ! Return code set by {\tt userRoutine} before returning. ! \item[{[rc]}] @@ -2970,6 +2982,8 @@ recursive subroutine ESMF_GridCompSetVMShObj(gridcomp, userRoutine, & integer :: localrc ! local error status integer :: localUserRc character(len=0) :: emptyString + type(ESMF_Logical) :: userRoutineFoundHelp + logical :: userRoutineFoundHelpHelp ! initialize return code; assume routine not implemented if (present(rc)) rc = ESMF_RC_NOT_IMPL @@ -2978,16 +2992,22 @@ recursive subroutine ESMF_GridCompSetVMShObj(gridcomp, userRoutine, & ESMF_INIT_CHECK_DEEP(ESMF_GridCompGetInit, gridcomp, rc) if (present(sharedObj)) then - call c_ESMC_SetVMShObj(gridcomp, userRoutine, sharedObj, localUserRc, & - localrc) + call c_ESMC_SetVMShObj(gridcomp, userRoutine, sharedObj, & + userRoutineFoundHelp, localUserRc, localrc) else - call c_ESMC_SetVMShObj(gridcomp, userRoutine, emptyString, localUserRc, & - localrc) + call c_ESMC_SetVMShObj(gridcomp, userRoutine, emptyString, & + userRoutineFoundHelp, localUserRc, localrc) endif if (ESMF_LogFoundError(localrc, & ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return + ! translate ESMF_Logical -> logical + userRoutineFoundHelpHelp = userRoutineFoundHelp + + ! report back + if (present(userRoutineFound)) userRoutineFound = userRoutineFoundHelpHelp + ! pass back userRc if (present(userRc)) userRc = localUserRc diff --git a/src/addon/NUOPC/src/NUOPC.F90 b/src/addon/NUOPC/src/NUOPC.F90 index 5fd0dff795..4e0bef5da3 100644 --- a/src/addon/NUOPC/src/NUOPC.F90 +++ b/src/addon/NUOPC/src/NUOPC.F90 @@ -72,6 +72,7 @@ module NUOPC public NUOPC_CompSetEntryPoint ! method public NUOPC_CompSetInternalEntryPoint ! method public NUOPC_CompSetServices ! method + public NUOPC_CompSetVM ! method public NUOPC_CompSpecialize ! method public & label_ExternalAdvertise, & diff --git a/src/addon/NUOPC/src/NUOPC_Comp.F90 b/src/addon/NUOPC/src/NUOPC_Comp.F90 index 6fa79cbbd9..5f85533413 100644 --- a/src/addon/NUOPC/src/NUOPC_Comp.F90 +++ b/src/addon/NUOPC/src/NUOPC_Comp.F90 @@ -41,6 +41,7 @@ module NUOPC_Comp public NUOPC_CompSetEntryPoint public NUOPC_CompSetInternalEntryPoint public NUOPC_CompSetServices + public NUOPC_CompSetVM public NUOPC_CompSpecialize ! public labels @@ -147,6 +148,10 @@ module NUOPC_Comp module procedure NUOPC_GridCompSetServices end interface !--------------------------------------------- + interface NUOPC_CompSetVM + module procedure NUOPC_GridCompSetVM + end interface + !--------------------------------------------- interface NUOPC_CompSpecialize module procedure NUOPC_GridCompSpecialize module procedure NUOPC_CplCompSpecialize @@ -3838,10 +3843,10 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) logical :: userRoutineFound if (present(rc)) rc = ESMF_SUCCESS - + ! attempt to find something called SetServices, allowing variations ! caused by compiler name mangling - + call ESMF_GridCompSetServices(comp, userRoutine="setservices", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3851,7 +3856,7 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) rcToReturn=rc)) & return ! bail out if (userRoutineFound) return ! bail out successfully - + call ESMF_GridCompSetServices(comp, userRoutine="setservices_", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3861,7 +3866,7 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) rcToReturn=rc)) & return ! bail out if (userRoutineFound) return ! bail out successfully - + call ESMF_GridCompSetServices(comp, userRoutine="setservices__", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3871,7 +3876,7 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) rcToReturn=rc)) & return ! bail out if (userRoutineFound) return ! bail out successfully - + call ESMF_GridCompSetServices(comp, userRoutine="SETSERVICES", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3881,7 +3886,7 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) rcToReturn=rc)) & return ! bail out if (userRoutineFound) return ! bail out successfully - + call ESMF_GridCompSetServices(comp, userRoutine="SETSERVICES_", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3891,7 +3896,7 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) rcToReturn=rc)) & return ! bail out if (userRoutineFound) return ! bail out successfully - + call ESMF_GridCompSetServices(comp, userRoutine="SETSERVICES__", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3901,7 +3906,7 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) rcToReturn=rc)) & return ! bail out if (userRoutineFound) return ! bail out successfully - + call ESMF_GridCompSetServices(comp, userRoutine="SetServices", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3911,7 +3916,7 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) rcToReturn=rc)) & return ! bail out if (userRoutineFound) return ! bail out successfully - + call ESMF_GridCompSetServices(comp, userRoutine="SetServices_", & sharedObj=sharedObj, userRoutineFound=userRoutineFound, & userRc=userRc, rc=localrc) @@ -3946,10 +3951,145 @@ recursive subroutine NUOPC_GridCompSetServices(comp, sharedObj, userRc, rc) file=FILENAME, & rcToReturn=rc) endif - + end subroutine !----------------------------------------------------------------------------- - + + !----------------------------------------------------------------------------- +!BOP +! !IROUTINE: NUOPC_CompSetVM - Try to find and call SetVM in a shared object +! !INTERFACE: + ! Private name; call using NUOPC_CompSetVM() + recursive subroutine NUOPC_GridCompSetVM(comp, sharedObj, userRc, rc) +! !ARGUMENTS: + type(ESMF_GridComp), intent(inout) :: comp + character(len=*), intent(in), optional :: sharedObj + integer, intent(out), optional :: userRc + integer, intent(out), optional :: rc +! !DESCRIPTION: +! Try to find a routine called "{\tt SetVM}" in the {\tt sharedObj} file +! and execute the routine. An attempt is made to find a routine that +! is close in name to "{\tt SetVM}", allowing for compiler name +! mangling, i.e. upper and lower case, as well as trailing underscores. +!EOP + !----------------------------------------------------------------------------- + ! local variables + integer :: localrc + logical :: userRoutineFound + + if (present(rc)) rc = ESMF_SUCCESS + + ! attempt to find something called SetVM, allowing variations + ! caused by compiler name mangling + + call ESMF_GridCompSetVM(comp, userRoutine="setvm", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="setvm_", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="setvm__", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="SETVM", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="SETVM_", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="SETVM__", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="SetVM", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="SetVM_", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + call ESMF_GridCompSetVM(comp, userRoutine="SetVM__", & + sharedObj=sharedObj, userRoutineFound=userRoutineFound, & + userRc=userRc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc)) & + return ! bail out + if (userRoutineFound) return ! bail out successfully + + ! getting down to here means that none of the attempts were successful + if (present(sharedObj)) then + call ESMF_LogSetError(ESMF_RC_ARG_BAD, & + msg="Could not find a matching SetVM routine in "//trim(sharedObj),& + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc) + else + call ESMF_LogSetError(ESMF_RC_ARG_BAD, & + msg="Could not find a matching SetVM routine in the executable.", & + line=__LINE__, & + file=FILENAME, & + rcToReturn=rc) + endif + + end subroutine + !----------------------------------------------------------------------------- + !----------------------------------------------------------------------------- !BOP ! !IROUTINE: NUOPC_CompSpecialize - Specialize a derived GridComp diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index bd6faaadfd..58333f4d39 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -4512,6 +4512,16 @@ recursive subroutine NUOPC_DriverAddGridCompSO(driver, compLabel, & return ! bail out endif + ! Call the SetVM on the added component + call NUOPC_CompSetVM(cmEntry%wrap%component, & + sharedObj=sharedObj, userRc=userrc, rc=localrc) + if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + if (ESMF_LogFoundError(rcToCheck=userrc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + ! Call the SetServices on the added component call NUOPC_CompSetServices(cmEntry%wrap%component, & sharedObj=sharedObj, userRc=userrc, rc=localrc) From 89566eed513d2f7c8c11f3341537910e0a57d0c1 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 8 Jul 2022 10:13:50 -0600 Subject: [PATCH 024/266] fix pip build for ESMPy on Cheyenne --- src/addon/ESMPy/setup.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/addon/ESMPy/setup.cfg b/src/addon/ESMPy/setup.cfg index f6e962c30e..b15f9fb68c 100644 --- a/src/addon/ESMPy/setup.cfg +++ b/src/addon/ESMPy/setup.cfg @@ -19,6 +19,8 @@ url="http://earthsystemmodeling.org/esmpy/", [options] zip_safe = False include_package_data = True +package_dir= + =src packages = find: install_requires = numpy From 59d62d39d8ac4646807256e1cbe1af676015b092 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 12 Jul 2022 15:19:17 -0700 Subject: [PATCH 025/266] Finish extending the ESMF_CplCompSetVMShObj() entry point for ESMF_CplCompSetVM() overload to provide 'userRoutineFound' argument. --- .../Component/src/ESMF_CplComp.F90 | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Superstructure/Component/src/ESMF_CplComp.F90 b/src/Superstructure/Component/src/ESMF_CplComp.F90 index 97a5733a26..4d5933f442 100644 --- a/src/Superstructure/Component/src/ESMF_CplComp.F90 +++ b/src/Superstructure/Component/src/ESMF_CplComp.F90 @@ -2547,19 +2547,26 @@ end subroutine ESMF_CplCompSetVM ! !INTERFACE: ! Private name; call using ESMF_CplCompSetVM() recursive subroutine ESMF_CplCompSetVMShObj(cplcomp, userRoutine, & - keywordEnforcer, sharedObj, userRc, rc) + keywordEnforcer, sharedObj, userRoutineFound, userRc, rc) ! ! !ARGUMENTS: type(ESMF_CplComp), intent(inout) :: cplcomp character(len=*), intent(in) :: userRoutine type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below character(len=*), intent(in), optional :: sharedObj + logical, intent(out), optional :: userRoutineFound integer, intent(out), optional :: userRc integer, intent(out), optional :: rc ! ! !STATUS: ! \begin{itemize} ! \item\apiStatusCompatibleVersion{5.2.0r} +! \item\apiStatusModifiedSinceVersion{5.2.0r} +! \begin{description} +! \item[8.4.0] Added argument {\tt userRoutineFound}. +! The new argument provides a way to test availability without +! causing error conditions. +! \end{description} ! \end{itemize} ! ! !DESCRIPTION: @@ -2601,6 +2608,11 @@ recursive subroutine ESMF_CplCompSetVMShObj(cplcomp, userRoutine, & ! Name of shared object that contains {\tt userRoutine}. If the ! {\tt sharedObj} argument is not provided the executable itself will be ! searched for {\tt userRoutine}. +! \item[{[userRoutineFound]}] +! Report back whether the specified {\tt userRoutine} was found and executed, +! or was not available. If this argument is present, not finding the +! {\tt userRoutine} will not result in returning an error in {\tt rc}. +! The default is to return an error if the {\tt userRoutine} cannot be found. ! \item[{[userRc]}] ! Return code set by {\tt userRoutine} before returning. ! \item[{[rc]}] @@ -2612,6 +2624,8 @@ recursive subroutine ESMF_CplCompSetVMShObj(cplcomp, userRoutine, & integer :: localrc ! local error status integer :: localUserRc character(len=0) :: emptyString + type(ESMF_Logical) :: userRoutineFoundHelp + logical :: userRoutineFoundHelpHelp ! initialize return code; assume routine not implemented if (present(rc)) rc = ESMF_RC_NOT_IMPL @@ -2620,16 +2634,22 @@ recursive subroutine ESMF_CplCompSetVMShObj(cplcomp, userRoutine, & ESMF_INIT_CHECK_DEEP(ESMF_CplCompGetInit, cplcomp, rc) if (present(sharedObj)) then - call c_ESMC_SetVMShObj(cplcomp, userRoutine, sharedObj, localUserRc, & - localrc) + call c_ESMC_SetVMShObj(cplcomp, userRoutine, sharedObj, & + userRoutineFoundHelp, localUserRc, localrc) else - call c_ESMC_SetVMShObj(cplcomp, userRoutine, emptyString, localUserRc, & - localrc) + call c_ESMC_SetVMShObj(cplcomp, userRoutine, emptyString, & + userRoutineFoundHelp, localUserRc, localrc) endif if (ESMF_LogFoundError(localrc, & ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return + ! translate ESMF_Logical -> logical + userRoutineFoundHelpHelp = userRoutineFoundHelp + + ! report back + if (present(userRoutineFound)) userRoutineFound = userRoutineFoundHelpHelp + ! pass back userRc if (present(userRc)) userRc = localUserRc From ddf2219c8c7e0100e53edfd3c7f398d90d3174ea Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 14 Jul 2022 13:18:40 -0700 Subject: [PATCH 026/266] Add plumbing for NamedAlias implementation. Add section to refdoc. --- src/Superstructure/NamedAlias/doc/makefile | 49 +++++++ src/Superstructure/NamedAlias/makefile | 16 ++ .../NamedAlias/src/ESMF_NamedAlias.F90 | 137 ++++++++++++++++++ src/Superstructure/NamedAlias/src/makefile | 24 +++ src/Superstructure/NamedAlias/tests/makefile | 32 ++++ src/Superstructure/makefile | 4 +- src/doc/ESMC_api.tex | 36 ++++- src/doc/ESMF_api.tex | 61 +++++++- 8 files changed, 342 insertions(+), 17 deletions(-) create mode 100644 src/Superstructure/NamedAlias/doc/makefile create mode 100644 src/Superstructure/NamedAlias/makefile create mode 100644 src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 create mode 100644 src/Superstructure/NamedAlias/src/makefile create mode 100644 src/Superstructure/NamedAlias/tests/makefile diff --git a/src/Superstructure/NamedAlias/doc/makefile b/src/Superstructure/NamedAlias/doc/makefile new file mode 100644 index 0000000000..c360f78b15 --- /dev/null +++ b/src/Superstructure/NamedAlias/doc/makefile @@ -0,0 +1,49 @@ +# $Id$ + +ALL: onedoc + +LOCDIR = src/Superstructure/NamedAlias/doc + +DVIFILES = +PDFFILES = +HTMLFILES = + +# +# Tex Files to make +# +TEXFILES_TO_MAKE = $(addsuffix _ccapi.tex, $(basename $(notdir $(wildcard ../src/*.C)))) +TEXFILES_TO_MAKE += $(addsuffix _chapi.tex, $(basename $(notdir $(wildcard ../include/*.h)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../src/*.F)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../src/*.F90)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../src/*.f)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../src/*.f90)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../src/*.cppF90)))) + +TEXFILES_TO_MAKE += $(addsuffix _ccapi.tex, $(basename $(notdir $(wildcard ../interface/*.C)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../interface/*.F)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../interface/*.F90)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../interface/*.f)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../interface/*.f90)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../interface/*.cppF90)))) + +TEXFILES_TO_MAKE += $(addsuffix _ccapi.tex, $(basename $(notdir $(wildcard ../examples/*.C)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../examples/*.F)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../examples/*.F90)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../examples/*.f)))) +TEXFILES_TO_MAKE += $(addsuffix _fapi.tex, $(basename $(notdir $(wildcard ../examples/*.f90)))) + + +# Files that a doc depends on. Do not list the the ctex file ! +# The ctex file is listed in the rule found in the build/common file. +# These lists almost certainly will not be an exhaustive list of +# all of the dependent files, but even a partial listing will be helpfull. +# +REFDOC_DEP_FILES = $(TEXFILES_TO_MAKE) + +include $(ESMF_DIR)/makefile + +DIRS = +CLEANDIRS = +CLEANFILES = $(TEXFILES_TO_MAKE) $(CLEAN_TEXFILES) +CLOBBERDIRS = + diff --git a/src/Superstructure/NamedAlias/makefile b/src/Superstructure/NamedAlias/makefile new file mode 100644 index 0000000000..7736f3acae --- /dev/null +++ b/src/Superstructure/NamedAlias/makefile @@ -0,0 +1,16 @@ +# $Id$ + +ALL: build_here + +# this needs to be the path of this directory relative to the +# top level esmf directory. +LOCDIR = src/Superstructure/NamedAlias/ + +# leave this line alone. +include ${ESMF_DIR}/makefile + + +# the DIRS line needs to contain all subdirectories which exist +# directly below this directory, and have either library, +# example/test code, or documents which need to be generated. +DIRS = src doc tests diff --git a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 new file mode 100644 index 0000000000..e87c49256c --- /dev/null +++ b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 @@ -0,0 +1,137 @@ +! $Id$ +! +! Earth System Modeling Framework +! Copyright 2002-2022, 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 ESMF_FILENAME "ESMF_NamedAlias.F90" +!============================================================================== + +#include "ESMF_Macros.inc" +#include "ESMF.h" + +!============================================================================== +!============================================================================== + +module ESMF_NamedAliasMod + +use ESMF_UtilTypesMod ! ESMF utility types +use ESMF_InitMacrosMod ! ESMF initializer macros +use ESMF_BaseMod ! ESMF base class +use ESMF_LogErrMod ! ESMF error handling + +use ESMF_VMMod +use ESMF_StateMod +use ESMF_StateItemMod +use ESMF_DistGridMod +use ESMF_FieldMod +use ESMF_FieldGetMod +use ESMF_FieldBundleMod +use ESMF_CompMod +use ESMF_GridCompMod +use ESMF_CplCompMod +use ESMF_SciCompMod +use ESMF_ArrayMod +use ESMF_ArrayBundleMod +use ESMF_InfoMod +use ESMF_UtilTypesMod +use ESMF_GeomBaseMod +use ESMF_MeshMod +use ESMF_GridMod +use ESMF_XGridMod +use ESMF_XGridGetMod +use ESMF_LocStreamMod +use ESMF_RHandleMod +use ESMF_InfoDescribeMod + +implicit none + +!============================================================================== +!============================================================================== + +private +public ESMF_NamedAlias + +!============================================================================== +!============================================================================== + +interface ESMF_NamedAlias + module procedure ESMF_NamedAliasArray +#if 0 + module procedure ESMF_NamedAliasArrayBundle + module procedure ESMF_NamedAliasCplComp + module procedure ESMF_NamedAliasGridComp + module procedure ESMF_NamedAliasSciComp + module procedure ESMF_NamedAliasDistGrid + module procedure ESMF_NamedAliasField + module procedure ESMF_NamedAliasFieldBundle + module procedure ESMF_NamedAliasGrid + module procedure ESMF_NamedAliasState + module procedure ESMF_NamedAliasLocStream + module procedure ESMF_NamedAliasMesh +#endif +end interface + +contains !===================================================================== + +! -------------------------- ESMF-public method ------------------------------- +!BOP +! !IROUTINE: ESMF_NamedAlias - Named Alias +! +! !INTERFACE: +! function ESMF_NamedAlias(object, name, rc) +! +! !ARGUMENTS: +! type(ESMF_*), intent(in) :: object +! character(len = *), intent(in), optional :: name +! integer, intent(out), optional :: rc +! +! !DESCRIPTION: +! Generate a named alias to {\tt object}. +! +! The arguments are: +! \begin{description} +! \item[object] +! The incoming object for which a named alias is generated. +! \item [{[name]}] +! The name of the named alias. By default use the name of {\tt object}. +! \item [{[rc]}] +! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. +! \end{description} +! +!EOP +!------------------------------------------------------------------------------ + +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasArray()" +!BOPI +! !IROUTINE: ESMF_NamedAliasArray - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasArray(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_Array) :: ESMF_NamedAliasArray +! +! !ARGUMENTS: + type(ESMF_Array), intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + + ESMF_NamedAliasArray = object + + end function ESMF_NamedAliasArray +!------------------------------------------------------------------------------ + + +end module ESMF_NamedAliasMod diff --git a/src/Superstructure/NamedAlias/src/makefile b/src/Superstructure/NamedAlias/src/makefile new file mode 100644 index 0000000000..7cd8d57367 --- /dev/null +++ b/src/Superstructure/NamedAlias/src/makefile @@ -0,0 +1,24 @@ +# $Id$ + +ALL: build_here + +SOURCEC = +SOURCEF = ESMF_NamedAlias.F90 + +# list all .h files which should be copied to common include dir +STOREH = + +OBJSC = $(addsuffix .o, $(basename $(SOURCEC))) +OBJSF = $(addsuffix .o, $(basename $(SOURCEF))) + +LIBBASE = libesmf +LOCDIR = src/Superstructure/NamedAlias/src + +CLEANDIRS = +CLEANFILES = +CLOBBERDIS = + +include ${ESMF_DIR}/makefile + +DIRS = + diff --git a/src/Superstructure/NamedAlias/tests/makefile b/src/Superstructure/NamedAlias/tests/makefile new file mode 100644 index 0000000000..b2a780ba6d --- /dev/null +++ b/src/Superstructure/NamedAlias/tests/makefile @@ -0,0 +1,32 @@ +# $Id$ + +ALL: build_unit_tests +run: run_unit_tests +run_uni: run_unit_tests_uni + +LOCDIR = src/Superstructure/NamedAlias/tests + +.NOTPARALLEL: +TESTS_BUILD = $(ESMF_TESTDIR)/ESMF_NamedAliasUTest + +TESTS_RUN = RUN_ESMF_NamedAliasUTest + +TESTS_RUN_UNI = RUN_ESMF_NamedAliasUTestUNI + +include ${ESMF_DIR}/makefile + +CLEANDIRS = +CLEANFILES = $(TESTS_BUILD) +CLOBBERDIRS = + +DIRS = + +# +# unit test targets +# + +RUN_ESMF_DistGridCreateGetUTest: + $(MAKE) TNAME=NamedAlias NP=4 ftest + +RUN_ESMF_DistGridCreateGetUTestUNI: + $(MAKE) TNAME=NamedAlias NP=1 ftest diff --git a/src/Superstructure/makefile b/src/Superstructure/makefile index 14d23c6843..df5f09e026 100644 --- a/src/Superstructure/makefile +++ b/src/Superstructure/makefile @@ -7,9 +7,9 @@ LOCDIR = src/Superstructure include $(ESMF_DIR)/makefile ifeq ($(ESMF_MAPPER_BUILD),ON) -DIRS = State Component Mapper AttachMethods InfoAPI StateReconcile AttributeAPI TraceAPI WebServices IOAPI PreESMFMod ESMFMod AppDriver +DIRS = State Component Mapper AttachMethods InfoAPI NamedAlias StateReconcile AttributeAPI TraceAPI WebServices IOAPI PreESMFMod ESMFMod AppDriver else -DIRS = State Component AttachMethods InfoAPI StateReconcile AttributeAPI TraceAPI WebServices IOAPI PreESMFMod ESMFMod AppDriver +DIRS = State Component AttachMethods InfoAPI NamedAlias StateReconcile AttributeAPI TraceAPI WebServices IOAPI PreESMFMod ESMFMod AppDriver endif CLEANDIRS = diff --git a/src/doc/ESMC_api.tex b/src/doc/ESMC_api.tex index cde535b3e5..0eb6a58788 100644 --- a/src/doc/ESMC_api.tex +++ b/src/doc/ESMC_api.tex @@ -89,7 +89,7 @@ \subsection{Standard Methods and Interface Rules} \subsection{Deep and Shallow Classes} \label{sec:deepshallow} -The ESMF contains two types of classes. +ESMF contains two types of classes. {\bf Deep} classes require {\tt ESMC\_Create()} and {\tt ESMC\_Destroy()} calls. @@ -101,14 +101,15 @@ \subsection{Deep and Shallow Classes} {\bf Shallow} classes do not possess {\tt ESMC\_Create()} and {\tt ESMC\_Destroy()} calls. They are simply declared and their values set using an {\tt ESMC\_Set()} call. -Examples of shallow classes are Time, TimeInterval, and ArraySpec. Shallow classes do not take long to set up and can be declared and set within -a time-critical code segment. Shallow objects stop existing when -the method in which they were declared has returned. +Examples of shallow classes are Time, TimeInterval, and ArraySpec. +Shallow classes do not take long to set up and can be declared and set within +a time-critical code segment. Shallow objects stop existing when execution +goes out of the declaring scope. An exception to this is when a shallow object, such as a Time, -is stored in a deep object such as a Clock. The Clock then -carries a copy of the Time in persistent memory. The Time is -deallocated with the {\tt ESMC\_ClockDestroy()} call. +is stored in a deep object such as a Clock. The deep Clock object then +becomes the declaring scope of the Time object, persisting in memory. +The Time object is deallocated with the {\tt ESMC\_ClockDestroy()} call. See Section \ref{sec:overallimpl}, Overall Design and Implementation Notes, for a brief discussion of deep and shallow classes from @@ -116,6 +117,27 @@ \subsection{Deep and Shallow Classes} and inter-language issues related to deep and shallow classes, see the \htmladdnormallink{{\it ESMF Implementation Report}}{http://www.earthsystemmodeling.org/documents/IMPL\_repdoc/}. +\subsection{Aliases} +\label{sec:aliases} + +Deep objects, i.e. instances of ESMF deep classes created by the appropriate +{\tt ESMC\_Create()}, can be used with the standard assignment (=) +operator. + +The assignment +\begin{verbatim} +deep2 = deep1 +\end{verbatim} +makes {\tt deep2} an {\bf alias} of {\tt deep1}, meaning that both variables +reference the same deep allocation in memory. Many aliases of the same deep +object can be created. + +All the aliases of a deep object are equivalent. In particular, there is no +distinction between the variable on the left hand side of the actual +{\tt ESMC\_Create()} call, and any aliases created from it. All actions +taken on any of the aliases of a deep object affect the deep object, and thus +all other aliases. + \subsection{Special Methods} The following are special methods which, in one case, diff --git a/src/doc/ESMF_api.tex b/src/doc/ESMF_api.tex index 4536707196..7c0e8f9dc7 100644 --- a/src/doc/ESMF_api.tex +++ b/src/doc/ESMF_api.tex @@ -91,26 +91,28 @@ \subsection{Standard Methods and Interface Rules} \subsection{Deep and Shallow Classes} \label{sec:deepshallow} -The ESMF contains two types of classes. +ESMF contains two types of classes. {\bf Deep} classes require {\tt ESMF\_Create()} and {\tt ESMF\_Destroy()} calls. They involve memory allocation, take significant time to set up (due to memory management) and should not be created in a time-critical portion of code. Deep objects persist even after the method in which they were created has -returned. Most classes in ESMF, including GridComp, CplComp, State, Fields, FieldBundles, Arrays, ArrayBundles, Grids, and Clocks, fall into this category. +returned. Most classes in ESMF, including GridComp, CplComp, State, Fields, +FieldBundles, Arrays, ArrayBundles, Grids, and Clocks, fall into this category. {\bf Shallow} classes do not possess {\tt ESMF\_Create()} and {\tt ESMF\_Destroy()} calls. They are simply declared and their values set using an {\tt ESMF\_Set()} call. -Examples of shallow classes are Time, TimeInterval, and ArraySpec. Shallow classes do not take long to set up and can be declared and set within -a time-critical code segment. Shallow objects stop existing when -the method in which they were declared has returned. +Examples of shallow classes are Time, TimeInterval, and ArraySpec. +Shallow classes do not take long to set up and can be declared and set within +a time-critical code segment. Shallow objects stop existing when execution +goes out of the declaring scope. An exception to this is when a shallow object, such as a Time, -is stored in a deep object such as a Clock. The Clock then -carries a copy of the Time in persistent memory. The Time is -deallocated with the {\tt ESMF\_ClockDestroy()} call. +is stored in a deep object such as a Clock. The deep Clock object then +becomes the declaring scope of the Time object, persisting in memory. +The Time object is deallocated with the {\tt ESMF\_ClockDestroy()} call. See Section \ref{sec:overallimpl}, Overall Design and Implementation Notes, for a brief discussion of deep and shallow classes from @@ -118,6 +120,49 @@ \subsection{Deep and Shallow Classes} and inter-language issues related to deep and shallow classes, see the \htmladdnormallink{{\it ESMF Implementation Report}}{http://www.earthsystemmodeling.org/documents/IMPL\_repdoc/}. +\subsection{Aliases and Named Aliases} +\label{sec:aliases} + +Deep objects, i.e. instances of ESMF deep classes created by the appropriate +{\tt ESMF\_Create()}, can be used with the standard assignment (=), +equality (==), and not equal (/=) operators. + +The assignment +\begin{verbatim} +deep2 = deep1 +\end{verbatim} +makes {\tt deep2} an {\bf alias} of {\tt deep1}, meaning that both variables +reference the same deep allocation in memory. Many aliases of the same deep +object can be created. + +All the aliases of a deep object are equivalent. In particular, there is no +distinction between the variable on the left hand side of the actual +{\tt ESMF\_Create()} call, and any aliases created from it. All actions +taken on any of the aliases of a deep object affect the deep object, and thus +all other aliases. + +The equality and not equal operators for deep objects are implemented as simple +alias checks. For a more general comparison of two distinct deep objects, a +deep class might provide the {\tt ESMF\_Match()} method. + +ESMF provides the concept of a {\bf named alias}. A named alias behaves just +like an alias in all aspects, except when it comes to setting and getting the +{\em name} of the deep object it is associated with. While regular aliases +all access the same name string in the actual deep object, a named alias keeps +its private name string. This allows the same deep object to be known under a +different name in different contexts. + +The assignment +\begin{verbatim} +deep2 = ESMF_NamedAlias(deep1) +\end{verbatim} +makes {\tt deep2} a {\bf named alias} of {\tt deep1}. Any {\em name} changes on +{\tt deep2} only affect {\tt deep2}, and any regular aliases created from +{\tt deep2}. However, the {\em name} retrieved from {\tt deep1}, or from any +regular aliases created from {\tt deep1}, is unaffected. + +\input{../Superstructure/NamedAlias/doc/ESMF_NamedAlias_fapi} + \subsection{Special Methods} The following are special methods which, in one case, From bb33bd205265a47be991ef93f868a26f6b8c9943 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 14 Jul 2022 13:51:59 -0700 Subject: [PATCH 027/266] Fix up the hook-up of ESMF_NamedAlias() and add a first unit test. --- src/Superstructure/ESMFMod/src/ESMF.F90 | 2 + .../NamedAlias/src/ESMF_NamedAlias.F90 | 28 ++++++- .../NamedAlias/tests/ESMF_NamedAliasUTest.F90 | 84 +++++++++++++++++++ src/Superstructure/NamedAlias/tests/makefile | 4 +- 4 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 diff --git a/src/Superstructure/ESMFMod/src/ESMF.F90 b/src/Superstructure/ESMFMod/src/ESMF.F90 index da7ad44a8e..e5d3914665 100644 --- a/src/Superstructure/ESMFMod/src/ESMF.F90 +++ b/src/Superstructure/ESMFMod/src/ESMF.F90 @@ -125,6 +125,8 @@ module ESMF use ESMF_InfoDescribeMod use ESMF_InfoSyncMod + use ESMF_NamedAliasMod + use ESMF_RegridWeightGenMod end module ESMF diff --git a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 index e87c49256c..d370d019c5 100644 --- a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 +++ b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 @@ -61,13 +61,13 @@ module ESMF_NamedAliasMod !============================================================================== interface ESMF_NamedAlias + module procedure ESMF_NamedAliasDistGrid module procedure ESMF_NamedAliasArray #if 0 module procedure ESMF_NamedAliasArrayBundle module procedure ESMF_NamedAliasCplComp module procedure ESMF_NamedAliasGridComp module procedure ESMF_NamedAliasSciComp - module procedure ESMF_NamedAliasDistGrid module procedure ESMF_NamedAliasField module procedure ESMF_NamedAliasFieldBundle module procedure ESMF_NamedAliasGrid @@ -107,6 +107,32 @@ module ESMF_NamedAliasMod !EOP !------------------------------------------------------------------------------ +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasDistGrid()" +!BOPI +! !IROUTINE: ESMF_NamedAliasDistGrid - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasDistGrid(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_DistGrid) :: ESMF_NamedAliasDistGrid +! +! !ARGUMENTS: + type(ESMF_DistGrid),intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + + ESMF_NamedAliasDistGrid = object + + end function ESMF_NamedAliasDistGrid +!------------------------------------------------------------------------------ + ! -------------------------- ESMF-public method ------------------------------- #undef ESMF_METHOD #define ESMF_METHOD "ESMF_NamedAliasArray()" diff --git a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 new file mode 100644 index 0000000000..b38c583fbb --- /dev/null +++ b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 @@ -0,0 +1,84 @@ +! $Id$ +! +! Earth System Modeling Framework +! Copyright 2002-2022, 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_NamedAliasUTest + +!------------------------------------------------------------------------------ + +#include "ESMF_Macros.inc" +#include "ESMF.h" + +!============================================================================== +!BOP +! !PROGRAM: ESMF_NamedAliasUTest - This unit test file tests ESMF_NamedAlias(). +! !DESCRIPTION: +! +! The code in this file drives F90 NamedAlias() unit tests. +! +!----------------------------------------------------------------------------- +! !USES: + use ESMF_TestMod ! test methods + use ESMF + + implicit none + +!------------------------------------------------------------------------------ +! The following line turns the CVS identifier string into a printable variable. + character(*), parameter :: version = & + '$Id$' +!------------------------------------------------------------------------------ + + ! cumulative result: count failures; no failures equals "all pass" + integer :: result = 0 + + ! individual test result code + integer :: rc + + ! individual test failure message + character(ESMF_MAXSTR) :: failMsg + character(ESMF_MAXSTR) :: name + + !LOCAL VARIABLES: + type(ESMF_DistGrid):: distgrid1, distgrid2 + +!------------------------------------------------------------------------------- +! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are +! always run. When the environment variable, EXHAUSTIVE, is set to ON then +! the EXHAUSTIVE and sanity tests both run. If the EXHAUSTIVE variable is set +! to OFF, then only the sanity unit tests. +! Special strings (Non-exhaustive and exhaustive) have been +! added to allow a script to count the number and types of unit tests. +!------------------------------------------------------------------------------- + + !------------------------------------------------------------------------ + call ESMF_TestStart(ESMF_SRCLINE, rc=rc) ! calls ESMF_Initialize() internally + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ + + distgrid1 = ESMF_DistGridCreate(minIndex=(/1/), maxIndex=(/1000/), rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Testing NamedAlias for DistGrid" + write(failMsg, *) "Did not return ESMF_SUCCESS" + distgrid2 = ESMF_NamedAlias(distgrid1, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + + !------------------------------------------------------------------------ +10 continue + call ESMF_TestEnd(ESMF_SRCLINE) ! calls ESMF_Finalize() internally + !------------------------------------------------------------------------ + +end program ESMF_NamedAliasUTest diff --git a/src/Superstructure/NamedAlias/tests/makefile b/src/Superstructure/NamedAlias/tests/makefile index b2a780ba6d..95e0f1af1c 100644 --- a/src/Superstructure/NamedAlias/tests/makefile +++ b/src/Superstructure/NamedAlias/tests/makefile @@ -25,8 +25,8 @@ DIRS = # unit test targets # -RUN_ESMF_DistGridCreateGetUTest: +RUN_ESMF_NamedAliasUTest: $(MAKE) TNAME=NamedAlias NP=4 ftest -RUN_ESMF_DistGridCreateGetUTestUNI: +RUN_ESMF_NamedAliasUTestUNI: $(MAKE) TNAME=NamedAlias NP=1 ftest From d798b950cabf5f5a6a25c3cc9b1a7392d9f81710 Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Thu, 14 Jul 2022 15:30:19 -0600 Subject: [PATCH 028/266] Fix XGrid creation to allow it to work with Meshes created with >4 sided elements. --- .../include/Regridding/ESMCI_MeshRegrid.h | 5 + .../Mesh/src/ESMCI_Mesh_Regrid_Glue.C | 120 ------ .../Mesh/src/ESMCI_Mesh_XGrid_Glue.C | 8 + .../Mesh/src/Regridding/ESMCI_MeshRegrid.C | 124 ++++++ .../XGrid/tests/ESMF_XGridUTest.F90 | 365 +++++++++++++++++- 5 files changed, 500 insertions(+), 122 deletions(-) diff --git a/src/Infrastructure/Mesh/include/Regridding/ESMCI_MeshRegrid.h b/src/Infrastructure/Mesh/include/Regridding/ESMCI_MeshRegrid.h index 3d1bb9a07c..6bcfbd99aa 100644 --- a/src/Infrastructure/Mesh/include/Regridding/ESMCI_MeshRegrid.h +++ b/src/Infrastructure/Mesh/include/Regridding/ESMCI_MeshRegrid.h @@ -40,6 +40,11 @@ namespace ESMCI { int *unmappedaction, bool set_dst_status, WMat &dst_status, bool checkFlag); + void translate_split_src_elems_in_wts(Mesh *srcmesh, int num_entries, + int *iientries); + void translate_split_dst_elems_in_wts(Mesh *dstmesh, int num_entries, + int *iientries, double *factors); + int get_iwts(Mesh &mesh, MEField<> *iwts); } // namespace diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_Regrid_Glue.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_Regrid_Glue.C index 86368aaf63..ba0500af79 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_Regrid_Glue.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_Regrid_Glue.C @@ -65,10 +65,6 @@ static bool all_mesh_elem_ids_in_wmat(Mesh *mesh, WMat &wts, int *missing_id); static bool any_cells_in_mesh_degenerate(Mesh *mesh); static void get_mesh_node_ids_not_in_wmat(PointList *pointlist, WMat &wts, std::vector *missing_ids); static void get_mesh_elem_ids_not_in_wmat(Mesh *mesh, WMat &wts, std::vector *missing_ids); -static void translate_split_src_elems_in_wts(Mesh *srcmesh, int num_entries, - int *iientries); -static void translate_split_dst_elems_in_wts(Mesh *dstmesh, int num_entries, - int *iientries, double *factors); static void change_wts_to_be_fracarea(Mesh *mesh, int num_entries, int *iientries, double *factors); @@ -1579,122 +1575,6 @@ static void noncnsrv_check_for_mesh_errors(Mesh *mesh, bool ignore_degenerate, b #endif -static void translate_split_src_elems_in_wts(Mesh *srcmesh, int num_entries, - int *iientries) { - - - // Get a list of split ids that we own - UInt num_gids=0; - UInt *gids_split=NULL; - UInt *gids_orig=NULL; - - // Get number of split points - num_gids=srcmesh->split_to_orig_id.size(); - - // Allocate space - if (num_gids>0) { - gids_split= new UInt[num_gids]; - gids_orig= new UInt[num_gids]; - - // Loop and get split-orig id pairs - std::map::iterator mi=srcmesh->split_to_orig_id.begin(); - std::map::iterator me=srcmesh->split_to_orig_id.end(); - - int pos=0; - for ( ; mi != me; mi++) { - gids_split[pos]=mi->first; - gids_orig[pos]=mi->second; - pos++; - } - - // for (int i=0; i id_map_dir; - id_map_dir.Create(num_gids,gids_split,gids_orig); - - // Clean up - if (num_gids>0) { - if (gids_split!= NULL) delete [] gids_split; - if (gids_orig != NULL) delete [] gids_orig; - } - - - // Gather list of spit src ids - //// TODO: Maybe use a std::set instead to reduce the amount of communication?? - std::vector src_split_gids; - std::vector src_split_gids_idx; - - // Loop through weights modifying split dst elements - for (int i=0; i srcmesh->max_non_split_id) { - src_split_gids.push_back(src_id); - src_split_gids_idx.push_back(2*i); - } - - } - - // Do remote lookup to translate - UInt num_src_split_gids=src_split_gids.size(); - UInt *src_split_gids_proc=NULL; - UInt *src_split_gids_orig=NULL; - - if (num_src_split_gids > 0) { - src_split_gids_proc = new UInt[num_src_split_gids]; - src_split_gids_orig = new UInt[num_src_split_gids]; - } - - // Get mapping of split ids to original ids - id_map_dir.RemoteGID(num_src_split_gids, &src_split_gids[0], src_split_gids_proc, src_split_gids_orig); - - // Loop setting new ids - for (int i=0; i 0) { - if (src_split_gids_proc != NULL) delete [] src_split_gids_proc; - if (src_split_gids_orig != NULL) delete [] src_split_gids_orig; - } -} - - - -static void translate_split_dst_elems_in_wts(Mesh *dstmesh, int num_entries, - int *iientries, double *factors) { - - // Loop through weights modifying split dst elements - for (int i=0; i::iterator mi = dstmesh->split_id_to_frac.find(dst_id); - - // It is part of a larger polygon, so process - if (mi != dstmesh->split_id_to_frac.end()) { - - // Modify weight by fraction of orig polygon - factors[i] *= mi->second; - - // See if the id needs to be translated, if so then translate - std::map::iterator soi = dstmesh->split_to_orig_id.find(dst_id); - if (soi != dstmesh->split_to_orig_id.end()) { - iientries[2*i+1]=soi->second; - } - } - } - -} - static void change_wts_to_be_fracarea(Mesh *mesh, int num_entries, int *iientries, double *factors) { diff --git a/src/Infrastructure/Mesh/src/ESMCI_Mesh_XGrid_Glue.C b/src/Infrastructure/Mesh/src/ESMCI_Mesh_XGrid_Glue.C index 785075dc16..0ecc1decb9 100644 --- a/src/Infrastructure/Mesh/src/ESMCI_Mesh_XGrid_Glue.C +++ b/src/Infrastructure/Mesh/src/ESMCI_Mesh_XGrid_Glue.C @@ -260,6 +260,10 @@ void ESMCI_Mesh_XGrid_calc_wgts_from_side_mesh(Mesh *src_side_mesh, Mesh *dst_xg } // for j } // for wi + // If meshes are split, then translate indices and factorss + if (src_side_mesh->is_split) translate_split_src_elems_in_wts(src_side_mesh, num_entries, iientries); + if (dst_xgrid_mesh->is_split) translate_split_dst_elems_in_wts(dst_xgrid_mesh, num_entries, iientries, factors); + *nentries = num_entries; // Clean up. If has_iw, then we will use the arrays to // fill out the users pointers. These will be deleted following a copy. @@ -345,6 +349,10 @@ void ESMCI_Mesh_XGrid_calc_wgts_to_side_mesh(Mesh *src_xgrid_mesh, Mesh *dst_sid } // for j } // for wi + // If meshes are split, then translate indices and factorss + if (src_xgrid_mesh->is_split) translate_split_src_elems_in_wts(src_xgrid_mesh, num_entries, iientries); + if (dst_side_mesh->is_split) translate_split_dst_elems_in_wts(dst_side_mesh, num_entries, iientries, factors); + *nentries = num_entries; // Clean up. If has_iw, then we will use the arrays to // fill out the users pointers. These will be deleted following a copy. diff --git a/src/Infrastructure/Mesh/src/Regridding/ESMCI_MeshRegrid.C b/src/Infrastructure/Mesh/src/Regridding/ESMCI_MeshRegrid.C index c9f8317fa2..fb8e7dbdc7 100644 --- a/src/Infrastructure/Mesh/src/Regridding/ESMCI_MeshRegrid.C +++ b/src/Infrastructure/Mesh/src/Regridding/ESMCI_MeshRegrid.C @@ -231,6 +231,128 @@ namespace ESMCI { } + + // This should only be used where srcmesh->is_split is true. This function translates + // the src indices in iientires to their original (before splitting) versions. + void translate_split_src_elems_in_wts(Mesh *srcmesh, int num_entries, + int *iientries) { + + + // Get a list of split ids that we own + UInt num_gids=0; + UInt *gids_split=NULL; + UInt *gids_orig=NULL; + + // Get number of split points + num_gids=srcmesh->split_to_orig_id.size(); + + // Allocate space + if (num_gids>0) { + gids_split= new UInt[num_gids]; + gids_orig= new UInt[num_gids]; + + // Loop and get split-orig id pairs + std::map::iterator mi=srcmesh->split_to_orig_id.begin(); + std::map::iterator me=srcmesh->split_to_orig_id.end(); + + int pos=0; + for ( ; mi != me; mi++) { + gids_split[pos]=mi->first; + gids_orig[pos]=mi->second; + pos++; + } + + // for (int i=0; i id_map_dir; + id_map_dir.Create(num_gids,gids_split,gids_orig); + + // Clean up + if (num_gids>0) { + if (gids_split!= NULL) delete [] gids_split; + if (gids_orig != NULL) delete [] gids_orig; + } + + + // Gather list of spit src ids + //// TODO: Maybe use a std::set instead to reduce the amount of communication?? + std::vector src_split_gids; + std::vector src_split_gids_idx; + + // Loop through weights modifying split dst elements + for (int i=0; i srcmesh->max_non_split_id) { + src_split_gids.push_back(src_id); + src_split_gids_idx.push_back(2*i); + } + + } + + // Do remote lookup to translate + UInt num_src_split_gids=src_split_gids.size(); + UInt *src_split_gids_proc=NULL; + UInt *src_split_gids_orig=NULL; + + if (num_src_split_gids > 0) { + src_split_gids_proc = new UInt[num_src_split_gids]; + src_split_gids_orig = new UInt[num_src_split_gids]; + } + + // Get mapping of split ids to original ids + id_map_dir.RemoteGID(num_src_split_gids, &src_split_gids[0], src_split_gids_proc, src_split_gids_orig); + + // Loop setting new ids + for (int i=0; i 0) { + if (src_split_gids_proc != NULL) delete [] src_split_gids_proc; + if (src_split_gids_orig != NULL) delete [] src_split_gids_orig; + } + } + + + // This should only be used where dstmesh->is_split is true. This function translates + // the dst indices in iientires and the corresponding factors to what they should be + // without splitting + void translate_split_dst_elems_in_wts(Mesh *dstmesh, int num_entries, + int *iientries, double *factors) { + + // Loop through weights modifying split dst elements + for (int i=0; i::iterator mi = dstmesh->split_id_to_frac.find(dst_id); + + // It is part of a larger polygon, so process + if (mi != dstmesh->split_id_to_frac.end()) { + + // Modify weight by fraction of orig polygon + factors[i] *= mi->second; + + // See if the id needs to be translated, if so then translate + std::map::iterator soi = dstmesh->split_to_orig_id.find(dst_id); + if (soi != dstmesh->split_to_orig_id.end()) { + iientries[2*i+1]=soi->second; + } + } + } + + } + + // to generate the iwts again, and return to Fortran int get_iwts(Mesh &mesh, MEField<> *iwts) { @@ -256,4 +378,6 @@ namespace ESMCI { } + + } diff --git a/src/Infrastructure/XGrid/tests/ESMF_XGridUTest.F90 b/src/Infrastructure/XGrid/tests/ESMF_XGridUTest.F90 index 5f059aa706..57b12488ac 100644 --- a/src/Infrastructure/XGrid/tests/ESMF_XGridUTest.F90 +++ b/src/Infrastructure/XGrid/tests/ESMF_XGridUTest.F90 @@ -168,6 +168,14 @@ program ESMF_XGridUTest write(name, *) "Creating an XGrid in 2D with Mesh merging" call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + !NEX_UTest + ! Create an XGrid in 2D from Meshes + call test_xgrid_w_ngon_mesh(rc) + write(failMsg, *) "" + write(name, *) "Creating an XGrid in 2D from Meshes contain elements with >4 sides" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !NEX_UTest ! Create an XGrid in 2D from Meshes with user supplied area @@ -1352,7 +1360,355 @@ subroutine test7(rc) end subroutine test7 - + ! Create a spherical mesh containing >4 sided elements + ! on 1 or 2 PETS + + ! + ! 2.5 8 10 --------11 + ! / \ / | + ! 2.1 7 9 12 + ! | | 5 / + ! | 4 | / + ! | | / + ! 1.0 4 ------- 5 ------- 6 + ! | | \ 3 | + ! | 1 | \ | + ! | | 2 \ | + ! -0.1 1 ------- 2 ------- 3 + ! + ! -0.1 1.0 2.1 2.5 + ! + ! Node Id labels at corners + ! Element Id labels in centers + subroutine createTestMeshPH(mesh, rc) + type(ESMF_Mesh), intent(out) :: mesh + integer :: rc + + integer, pointer :: nodeIds(:),nodeOwners(:) + real(ESMF_KIND_R8), pointer :: nodeCoords(:) + real(ESMF_KIND_R8), pointer :: ownedNodeCoords(:) + integer :: numNodes, numOwnedNodes, numOwnedNodesTst + integer :: numElems,numOwnedElemsTst + integer, pointer :: elemIds(:),elemTypes(:),elemConn(:) + real(ESMF_KIND_R8), pointer :: elemCoords(:) + integer :: petCount, localPet + type(ESMF_VM) :: vm + integer :: numQuadElems,numTriElems + integer :: numPentElems,numHexElems,numTotElems + integer :: numElemConn + + ! 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 + + ! return with an error if not 1 or 2 PETs + if ((petCount /= 1) .and. (petCount /=2)) then + rc=ESMF_FAILURE + return + endif + + if (petCount .eq. 1) then + ! Set number of nodes + numNodes=12 + + ! Allocate and fill the node id array. + allocate(nodeIds(numNodes)) + nodeIds=(/1,2,3,4,5,6,7,8,9,10,11,12/) + + ! Allocate and fill node coordinate array. + ! Since this is a 2D Mesh the size is 2x the + ! number of nodes. + allocate(nodeCoords(2*numNodes)) + nodeCoords=(/0.0,0.0, & ! node id 1 + 1.0,0.0, & ! node id 2 + 2.1,0.0, & ! node id 3 + 0.0, 1.0, & ! node id 4 + 1.0, 1.0, & ! node id 5 + 2.1, 1.0, & ! node id 6 + 0.0, 2.1, & ! node id 7 + 0.5, 2.5, & ! node id 8 + 1.0, 2.1, & ! node id 9 + 1.5, 2.5, & ! node id 10 + 2.5, 2.5, & ! node id 11 + 2.5, 2.1/) ! node id 12 + + ! Allocate and fill the node owner array. + ! Since this Mesh is all on PET 0, it's just set to all 0. + allocate(nodeOwners(numNodes)) + nodeOwners=0 ! everything on PET 0 + + ! Set the number of each type of element, plus tot and num conn. + numQuadElems=1 + numTriElems=2 + numPentElems=1 + numHexElems=1 + numTotElems=numTriElems+numQuadElems+numPentElems+numHexElems + numElemConn=3*numTriElems+4*numQuadElems+ & + 5*numPentElems+6*numHexElems + + ! Allocate and fill the element id array. + allocate(elemIds(numTotElems)) + elemIds=(/1,2,3,4,5/) + + + ! Allocate and fill the element topology type array. + allocate(elemTypes(numTotElems)) + elemTypes=(/ESMF_MESHELEMTYPE_QUAD, & ! elem id 1 + ESMF_MESHELEMTYPE_TRI, & ! elem id 2 + ESMF_MESHELEMTYPE_TRI, & ! elem id 3 + 5, & ! elem id 4 + 6/) ! elem id 5 + + + ! Allocate and fill elem coordinate array. + ! Since this is a 2D Mesh the size is 2x the + ! number of nodes. + allocate(elemCoords(2*numTotElems)) + elemCoords=(/ 0.45, 0.45, & ! elem id 1 + 1.37, 0.27, & ! elem id 2 + 1.73, 0.63, & ! elem id 3 + 0.46, 1.74, & ! elem id 4 + 1.76, 1.87/) ! elem id 5 + + + + ! Allocate and fill the element connection type array. + ! Note that entries in this array refer to the + ! positions in the nodeIds, etc. arrays and that + ! the order and number of entries for each element + ! reflects that given in the Mesh options + ! section for the corresponding entry + ! in the elemTypes array. + allocate(elemConn(numElemConn)) + elemConn=(/1,2,5,4, & ! elem id 1 + 2,3,5, & ! elem id 2 + 3,6,5, & ! elem id 3 + 4,5,9,8,7, & ! elem id 4 + 5,6,12,11,10,9/) ! elem id 5 + + + else if (petCount .eq. 2) then + ! Setup mesh data depending on PET + if (localPET .eq. 0) then !!! This part only for PET 0 + ! Set number of nodes + numNodes=6 + + ! Allocate and fill the node id array. + allocate(nodeIds(numNodes)) + nodeIds=(/1,2,3,4,5,6/) + + ! Allocate and fill node coordinate array. + ! Since this is a 2D Mesh the size is 2x the + ! number of nodes. + allocate(nodeCoords(2*numNodes)) + nodeCoords=(/0.0, 0.0, & ! node id 1 + 1.0, 0.0, & ! node id 2 + 2.1, 0.0, & ! node id 3 + 0.0, 1.0, & ! node id 4 + 1.0, 1.0, & ! node id 5 + 2.1, 1.0/) ! node id 6 + + ! Allocate and fill the node owner array. + allocate(nodeOwners(numNodes)) + nodeOwners=(/0, & ! node id 1 + 0, & ! node id 2 + 0, & ! node id 3 + 0, & ! node id 4 + 0, & ! node id 5 + 0/) ! node id 6 + + ! Set the number of each type of element, plus tot and num conn. + numQuadElems=1 + numTriElems=2 + numPentElems=0 + numHexElems=0 + numTotElems=numTriElems+numQuadElems+numPentElems+numHexElems + numElemConn=3*numTriElems+4*numQuadElems+ & + 5*numPentElems+6*numHexElems + + ! Allocate and fill the element id array. + allocate(elemIds(numTotElems)) + elemIds=(/1,2,3/) + + ! Allocate and fill the element topology type array. + allocate(elemTypes(numTotElems)) + elemTypes=(/ESMF_MESHELEMTYPE_QUAD, & ! elem id 1 + ESMF_MESHELEMTYPE_TRI, & ! elem id 2 + ESMF_MESHELEMTYPE_TRI/) ! elem id 3 + + ! Allocate and fill elem coordinate array. + ! Since this is a 2D Mesh the size is 2x the + ! number of nodes. + allocate(elemCoords(2*numTotElems)) + elemCoords=(/0.45, 0.45, & ! elem id 1 + 1.37, 0.27, & ! elem id 2 + 1.73, 0.63/) ! elem id 3 + + ! Allocate and fill the element connection type array. + ! Note that entry are local indices + allocate(elemConn(numElemConn)) + elemConn=(/1,2,5,4, & ! elem id 1 + 2,3,5, & ! elem id 2 + 3,6,5/) ! elem id 3 + + else if (localPET .eq. 1) then !!! This part only for PET 1 + ! Set number of nodes + numNodes=9 + + ! Allocate and fill the node id array. + allocate(nodeIds(numNodes)) + nodeIds=(/4,5,6,7,8,9,10,11,12/) + + ! Allocate and fill node coordinate array. + ! Since this is a 2D Mesh the size is 2x the + ! number of nodes. + allocate(nodeCoords(2*numNodes)) + nodeCoords=(/0.0, 1.0, & ! node id 4 + 1.0, 1.0, & ! node id 5 + 2.1, 1.0, & ! node id 6 + 0.0, 2.1, & ! node id 7 + 0.5, 2.5, & ! node id 8 + 1.0, 2.1, & ! node id 9 + 1.5, 2.5, & ! node id 10 + 2.5, 2.5, & ! node id 11 + 2.5, 2.1/) ! node id 12 + + + ! Allocate and fill the node owner array. + allocate(nodeOwners(numNodes)) + nodeOwners=(/0, & ! node id 4 + 0, & ! node id 5 + 0, & ! node id 6 + 1, & ! node id 7 + 1, & ! node id 8 + 1, & ! node id 9 + 1, & ! node id 10 + 1, & ! node id 11 + 1/) ! node id 12 + + ! Set the number of each type of element, plus tot and num conn. + numQuadElems=0 + numTriElems=0 + numPentElems=1 + numHexElems=1 + numTotElems=numTriElems+numQuadElems+numPentElems+numHexElems + numElemConn=3*numTriElems+4*numQuadElems+ & + 5*numPentElems+6*numHexElems + + ! Allocate and fill the element id array. + allocate(elemIds(numTotElems)) + elemIds=(/4,5/) + + ! Allocate and fill the element topology type array. + allocate(elemTypes(numTotElems)) + elemTypes=(/5, & ! elem id 4 + 6/) ! elem id 5 + + ! Allocate and fill elem coordinate array. + ! Since this is a 2D Mesh the size is 2x the + ! number of nodes. + allocate(elemCoords(2*numTotElems)) + elemCoords=(/0.46, 1.74, & ! elem id 4 + 1.76, 1.87/) ! elem id 5 + + ! Allocate and fill the element connection type array. + allocate(elemConn(numElemConn)) + elemConn=(/1,2,6,5,4, & ! elem id 4 + 2,3,9,8,7,6/) ! elem id 5 + + endif + endif + + ! Create Mesh structure in 1 step + mesh=ESMF_MeshCreate(parametricDim=2,spatialDim=2, & + coordSys=ESMF_COORDSYS_SPH_DEG, & + nodeIds=nodeIds, nodeCoords=nodeCoords, & + nodeOwners=nodeOwners, elementIds=elemIds,& + elementTypes=elemTypes, elementConn=elemConn, & + elementCoords=elemCoords, & + rc=rc) + if (rc /= ESMF_SUCCESS) return + + ! deallocate node data + deallocate(nodeIds) + deallocate(nodeCoords) + deallocate(nodeOwners) + + ! deallocate elem data + deallocate(elemIds) + deallocate(elemTypes) + deallocate(elemConn) + +end subroutine createTestMeshPH + + +! Test XGrid when created from a mesh containing +! an elem with >4 sides + subroutine test_xgrid_w_ngon_mesh(rc) + integer, intent(out) :: rc + integer :: localrc, i, npet + type(ESMF_XGrid) :: xgrid + type(ESMF_Mesh) :: mesh_ngon, mesh_qt + type(ESMF_VM) :: vm + real(ESMF_KIND_R8) :: xgrid_area(12), B_area(2,2) + + rc = ESMF_SUCCESS + localrc = ESMF_SUCCESS + + call ESMF_VMGetCurrent(vm=vm, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_VMGet(vm, petcount=npet, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + ! Create ngon mesh + call createTestMeshPH(mesh_ngon, localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + ! Create mesh containing quads and triangles + call CreateTestMesh2x2_1(mesh_qt, localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + ! Create XGrid from meshes + xgrid = ESMF_XGridCreate(sideAMesh=(/mesh_ngon/), & + sideBMesh=(/mesh_qt/), & + storeOverlay = .true., & + rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + ! Test flux exchange through xgrid + call flux_exchange_sph_mesh(xgrid, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + ! Get rid of meshes + call ESMF_MeshDestroy(mesh_ngon, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_MeshDestroy(mesh_qt, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + end subroutine test_xgrid_w_ngon_mesh + + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! Creates the following mesh on @@ -5276,8 +5632,13 @@ subroutine flux_exchange_sph_mesh(xgrid, scheme, rc) deallocate(s2x_rh, x2s_rh) deallocate(d2x_rh, x2d_rh) + ! Destroy xgrid call ESMF_XGridDestroy(xgrid,rc=localrc) - + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + ! If rc present, return success if(present(rc)) rc = ESMF_SUCCESS end subroutine flux_exchange_sph_mesh From 5df84c1d557f2c1a873dd94541e4887c0c2fabe3 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 14 Jul 2022 16:38:10 -0700 Subject: [PATCH 029/266] Implement the generic NamedAlias behavior within the InteMacros. Use it on the State level for now, including unit testing. --- .../Util/include/ESMF_InitMacros.inc | 2 +- .../Component/src/ESMF_Comp.F90 | 4 +- .../NamedAlias/src/ESMF_NamedAlias.F90 | 49 +++++-- .../NamedAlias/tests/ESMF_NamedAliasUTest.F90 | 130 +++++++++++++++++- .../State/src/ESMF_StateAPI.cppF90 | 22 ++- .../State/src/ESMF_StateSet.F90 | 18 ++- src/doc/ESMF_api.tex | 11 +- 7 files changed, 207 insertions(+), 29 deletions(-) diff --git a/src/Infrastructure/Util/include/ESMF_InitMacros.inc b/src/Infrastructure/Util/include/ESMF_InitMacros.inc index bc7e34e849..1e2c1dd07b 100644 --- a/src/Infrastructure/Util/include/ESMF_InitMacros.inc +++ b/src/Infrastructure/Util/include/ESMF_InitMacros.inc @@ -62,7 +62,7 @@ automatic initialization of types. if (fget(var) .ne. ESMF_INIT_DEFINED) call \ finit(var) #else -#define ESMF_INIT_DECLARE ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED +#define ESMF_INIT_DECLARE ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED ; logical :: namedAlias = .false. ; character(ESMF_MAXSTR) :: name #define ESMF_INIT_CHECK_SET_SHALLOW(fget,finit,var) #endif diff --git a/src/Superstructure/Component/src/ESMF_Comp.F90 b/src/Superstructure/Component/src/ESMF_Comp.F90 index ebd785b924..2be399eb6a 100644 --- a/src/Superstructure/Component/src/ESMF_Comp.F90 +++ b/src/Superstructure/Component/src/ESMF_Comp.F90 @@ -140,7 +140,7 @@ module ESMF_CompMod .true., & ! vmIsPresent .true., & ! isIsPresent .true., & ! esIsPresent - ESMF_INIT_DEFINED), & + ESMF_INIT_DEFINED, .false., ""), & ESMF_COMPSTATUS_ALL_NOTPRESENT = ESMF_CompStatus(& .false., & ! configIsPresent .false., & ! clockIsPresent @@ -152,7 +152,7 @@ module ESMF_CompMod .false., & ! vmIsPresent .false., & ! isIsPresent .false., & ! esIsPresent - ESMF_INIT_DEFINED) + ESMF_INIT_DEFINED, .false., "") !------------------------------------------------------------------------------ ! ! ESMF_CompTunnel diff --git a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 index d370d019c5..fa8adf192b 100644 --- a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 +++ b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 @@ -25,8 +25,12 @@ module ESMF_NamedAliasMod use ESMF_BaseMod ! ESMF base class use ESMF_LogErrMod ! ESMF error handling -use ESMF_VMMod + use ESMF_StateMod +use ESMF_ArrayMod + +#if 0 +use ESMF_VMMod use ESMF_StateItemMod use ESMF_DistGridMod use ESMF_FieldMod @@ -36,7 +40,6 @@ module ESMF_NamedAliasMod use ESMF_GridCompMod use ESMF_CplCompMod use ESMF_SciCompMod -use ESMF_ArrayMod use ESMF_ArrayBundleMod use ESMF_InfoMod use ESMF_UtilTypesMod @@ -48,6 +51,7 @@ module ESMF_NamedAliasMod use ESMF_LocStreamMod use ESMF_RHandleMod use ESMF_InfoDescribeMod +#endif implicit none @@ -61,7 +65,7 @@ module ESMF_NamedAliasMod !============================================================================== interface ESMF_NamedAlias - module procedure ESMF_NamedAliasDistGrid + module procedure ESMF_NamedAliasState module procedure ESMF_NamedAliasArray #if 0 module procedure ESMF_NamedAliasArrayBundle @@ -71,7 +75,6 @@ module ESMF_NamedAliasMod module procedure ESMF_NamedAliasField module procedure ESMF_NamedAliasFieldBundle module procedure ESMF_NamedAliasGrid - module procedure ESMF_NamedAliasState module procedure ESMF_NamedAliasLocStream module procedure ESMF_NamedAliasMesh #endif @@ -92,7 +95,11 @@ module ESMF_NamedAliasMod ! integer, intent(out), optional :: rc ! ! !DESCRIPTION: -! Generate a named alias to {\tt object}. +! Generate a named alias to {\tt object}. The supported classes are: +! \begin{itemize} +! \item {\tt ESMF\_State} +! \item {\tt ESMF\_Array} +! \end{itemize} ! ! The arguments are: ! \begin{description} @@ -109,28 +116,46 @@ module ESMF_NamedAliasMod ! -------------------------- ESMF-public method ------------------------------- #undef ESMF_METHOD -#define ESMF_METHOD "ESMF_NamedAliasDistGrid()" +#define ESMF_METHOD "ESMF_NamedAliasState()" !BOPI -! !IROUTINE: ESMF_NamedAliasDistGrid - Named Alias +! !IROUTINE: ESMF_NamedAliasState - Named Alias ! ! !INTERFACE: ! Private name; call using ESMF_NamedAlias() - function ESMF_NamedAliasDistGrid(object, keywordEnforcer, name, rc) + function ESMF_NamedAliasState(object, keywordEnforcer, name, rc) ! ! !RETURN VALUE: - type(ESMF_DistGrid) :: ESMF_NamedAliasDistGrid + type(ESMF_State) :: ESMF_NamedAliasState ! ! !ARGUMENTS: - type(ESMF_DistGrid),intent(in) :: object + type(ESMF_State),intent(in) :: object type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below character(len = *), intent(in), optional :: name integer, intent(out), optional :: rc !EOPI !------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + + ! first create regular alias + ESMF_NamedAliasState = object + + ! next mark as namedAlias + ESMF_NamedAliasState%namedAlias = .true. - ESMF_NamedAliasDistGrid = object + ! finally set name + if (present(name)) then + ESMF_NamedAliasState%name = trim(name) + else + call ESMF_StateGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasState%name = trim(nameDefault) + endif - end function ESMF_NamedAliasDistGrid + end function ESMF_NamedAliasState !------------------------------------------------------------------------------ ! -------------------------- ESMF-public method ------------------------------- diff --git a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 index b38c583fbb..a9f579c6bd 100644 --- a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 +++ b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 @@ -48,7 +48,9 @@ program ESMF_NamedAliasUTest character(ESMF_MAXSTR) :: name !LOCAL VARIABLES: - type(ESMF_DistGrid):: distgrid1, distgrid2 + logical :: testFlag + character(ESMF_MAXSTR) :: name1, name2 + type(ESMF_State) :: state1, state2 !------------------------------------------------------------------------------- ! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are @@ -64,17 +66,135 @@ program ESMF_NamedAliasUTest if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ - distgrid1 = ESMF_DistGridCreate(minIndex=(/1/), maxIndex=(/1000/), rc=rc) + state1 = ESMF_StateCreate(name="Test Name 1", rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Testing NamedAlias for DistGrid" + write(name, *) "NamedAlias() with default name for State Test" write(failMsg, *) "Did not return ESMF_SUCCESS" - distgrid2 = ESMF_NamedAlias(distgrid1, rc=rc) - call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + state2 = ESMF_NamedAlias(state1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias State Test" + write(failMsg, *) "Incorrect result" + testFlag = (state1 == state2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateGet(state1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_StateGet(state2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for State Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateSet(state2, name="Test Name 2", rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_StateGet(state1, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for State not affecting Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateGet(state2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for State correct setting Test" + write(failMsg, *) "Incorrect result" + testFlag = (trim(name2) == "Test Name 2") + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is still an Alias State Test" + write(failMsg, *) "Incorrect result" + testFlag = (state1 == state2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateDestroy(state2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object State Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_StateGet(state1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + state1 = ESMF_StateCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + state2 = ESMF_NamedAlias(state1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias State Test" + write(failMsg, *) "Incorrect result" + testFlag = (state1 == state2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateGet(state1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_StateGet(state2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for State Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateDestroy(state2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object State Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_StateGet(state1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ 10 continue diff --git a/src/Superstructure/State/src/ESMF_StateAPI.cppF90 b/src/Superstructure/State/src/ESMF_StateAPI.cppF90 index de70e2d209..048005e0ad 100644 --- a/src/Superstructure/State/src/ESMF_StateAPI.cppF90 +++ b/src/Superstructure/State/src/ESMF_StateAPI.cppF90 @@ -1216,13 +1216,15 @@ ESMF_INIT_CHECK_DEEP(ESMF_RouteHandleGetInit,routehandleList(i),rc) type(ESMF_ItemOrder_Flag) :: itemorderflagArg type(ESMF_StateClass), pointer :: stypep + localrc = ESMF_SUCCESS + if (present(rc)) rc = ESMF_SUCCESS + ! check input variables ESMF_INIT_CHECK_DEEP(ESMF_StateGetInit,state,rc) call ESMF_StateValidate(state, rc=localrc) - if (ESMF_LogFoundError(localrc, & - ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return localnestedflag = .false. if (present (nestedFlag)) then @@ -1235,10 +1237,22 @@ ESMF_INIT_CHECK_DEEP(ESMF_RouteHandleGetInit,routehandleList(i),rc) stypep => state%statep - if (present(name)) call ESMF_GetName(stypep%base, name=name, rc=localrc) + if (present(name)) then + if (state%namedAlias) then + name = trim(state%name) + else + call ESMF_GetName(stypep%base, name=name, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif + endif + if (present(stateintent)) stateintent = stypep%st localitemcount = infoCountWorker (stypep) + ! infoCountWorker can set localrc -> must check on return + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return if (present(itemCount)) & itemCount = localitemcount diff --git a/src/Superstructure/State/src/ESMF_StateSet.F90 b/src/Superstructure/State/src/ESMF_StateSet.F90 index 4a01fb7654..adaa6b4e6b 100644 --- a/src/Superstructure/State/src/ESMF_StateSet.F90 +++ b/src/Superstructure/State/src/ESMF_StateSet.F90 @@ -34,6 +34,7 @@ module ESMF_StateSetMod ! ! !USES: use ESMF_UtilTypesMod + use ESMF_BaseMod use ESMF_LogErrMod use ESMF_StateTypesMod use ESMF_StateVaMod @@ -80,13 +81,14 @@ module ESMF_StateSetMod ! !IROUTINE: ESMF_StateSet - Set State aspects ! ! !INTERFACE: - subroutine ESMF_StateSet(state, keywordEnforcer, stateIntent, rc) + subroutine ESMF_StateSet(state, keywordEnforcer, stateIntent, name, rc) ! ! !ARGUMENTS: type(ESMF_State), intent(inout) :: state type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below type(ESMF_StateIntent_Flag), intent(in), optional :: stateIntent - integer, intent(out), optional :: rc + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc ! ! !DESCRIPTION: @@ -99,16 +101,28 @@ subroutine ESMF_StateSet(state, keywordEnforcer, stateIntent, rc) ! \item[stateIntent] ! Intent, e.g. Import or Export, of this {\tt ESMF\_State}. ! Possible values are listed in Section~\ref{const:stateintent}. +! \item [{[name]}] +! The State name. ! \item[{[rc]}] ! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors. ! \end{description} ! !EOP !------------------------------------------------------------------------------ + integer :: localrc ! local return code type(ESMF_StateClass), pointer :: stypep if (present(rc)) rc = ESMF_RC_NOT_IMPL stypep => state%statep if (present(stateIntent)) stypep%st = stateintent + if (present(name)) then + if (state%namedAlias) then + state%name = trim(name) + else + call ESMF_SetName(stypep%base, name=name, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif + endif ! return successfully if (present(rc)) rc = ESMF_SUCCESS end subroutine ESMF_StateSet diff --git a/src/doc/ESMF_api.tex b/src/doc/ESMF_api.tex index 7c0e8f9dc7..e2929d1059 100644 --- a/src/doc/ESMF_api.tex +++ b/src/doc/ESMF_api.tex @@ -157,9 +157,14 @@ \subsection{Aliases and Named Aliases} deep2 = ESMF_NamedAlias(deep1) \end{verbatim} makes {\tt deep2} a {\bf named alias} of {\tt deep1}. Any {\em name} changes on -{\tt deep2} only affect {\tt deep2}, and any regular aliases created from -{\tt deep2}. However, the {\em name} retrieved from {\tt deep1}, or from any -regular aliases created from {\tt deep1}, is unaffected. +{\tt deep2} only affect {\tt deep2}. However, the {\em name} retrieved from +{\tt deep1}, or from any regular aliases created from {\tt deep1}, is +unaffected. + +Notice that aliases generated from a named alias are again named aliases. This +is true even when using the regular assignment operator with a named alias on +the right hand side. Named aliases own their unique name string that cannot +be accessed or altered through any other alias. \input{../Superstructure/NamedAlias/doc/ESMF_NamedAlias_fapi} From 9f3bc1a57327dc921c86f323e72a901b08b13848 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 15 Jul 2022 06:58:38 -0700 Subject: [PATCH 030/266] Fix ESMCI:Test() to output failMsg when falure detected. --- src/epilogue/src/ESMCI_Test.C | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/epilogue/src/ESMCI_Test.C b/src/epilogue/src/ESMCI_Test.C index bdc202d106..e63709bae6 100644 --- a/src/epilogue/src/ESMCI_Test.C +++ b/src/epilogue/src/ESMCI_Test.C @@ -102,7 +102,8 @@ int Test( if (!only) fprintf(stderr, "%s\n", msgbuf.str().c_str()); }else { - msgbuf << "FAIL " << name << ", " << file << ", line " << line; + msgbuf << "FAIL " << name << ", " << file << ", line " << line << ": " + << failMsg; whichLog->Write(msgbuf, ESMC_LOGMSG_INFO); if (!only) fprintf(stderr, "%s\n", msgbuf.str().c_str()); From 00d32489d7e2cd3ab7a28f5a2566870326ae5094 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 15 Jul 2022 10:07:59 -0700 Subject: [PATCH 031/266] Fix things up. All regression tests passing again. --- src/Infrastructure/Util/include/ESMCI_F90Interface.h | 5 ++++- src/Infrastructure/Util/include/ESMF_InitMacros.inc | 3 ++- src/Superstructure/Component/src/ESMF_Comp.F90 | 4 ++-- src/Superstructure/State/src/ESMF_StateTypes.F90 | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure/Util/include/ESMCI_F90Interface.h b/src/Infrastructure/Util/include/ESMCI_F90Interface.h index 684de20944..0e19498479 100644 --- a/src/Infrastructure/Util/include/ESMCI_F90Interface.h +++ b/src/Infrastructure/Util/include/ESMCI_F90Interface.h @@ -42,9 +42,12 @@ namespace ESMCI { class F90ClassHolder{ - void *memoryHolder[16]; // Reserves 16 times the space of a void pointer. + void *memoryHolder[48]; // Reserves 48 times the space of a void pointer. // This value has been determined empirically to // work on all the supported platforms. + // Increased this from the previous value of 16 + // when ESMF_INIT_DECLARE_NAMED_ALIAS was + // introduced. This now depends on ESMF_MAXSTR. friend std::ostream& operator<<(std::ostream& out, const F90ClassHolder& f90p){ out << f90p.memoryHolder[0]; diff --git a/src/Infrastructure/Util/include/ESMF_InitMacros.inc b/src/Infrastructure/Util/include/ESMF_InitMacros.inc index 1e2c1dd07b..75293cd622 100644 --- a/src/Infrastructure/Util/include/ESMF_InitMacros.inc +++ b/src/Infrastructure/Util/include/ESMF_InitMacros.inc @@ -62,7 +62,8 @@ automatic initialization of types. if (fget(var) .ne. ESMF_INIT_DEFINED) call \ finit(var) #else -#define ESMF_INIT_DECLARE ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED ; logical :: namedAlias = .false. ; character(ESMF_MAXSTR) :: name +#define ESMF_INIT_DECLARE ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED +#define ESMF_INIT_DECLARE_NAMED_ALIAS ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED ; logical :: namedAlias = .false. ; character(ESMF_MAXSTR) :: name #define ESMF_INIT_CHECK_SET_SHALLOW(fget,finit,var) #endif diff --git a/src/Superstructure/Component/src/ESMF_Comp.F90 b/src/Superstructure/Component/src/ESMF_Comp.F90 index 2be399eb6a..ebd785b924 100644 --- a/src/Superstructure/Component/src/ESMF_Comp.F90 +++ b/src/Superstructure/Component/src/ESMF_Comp.F90 @@ -140,7 +140,7 @@ module ESMF_CompMod .true., & ! vmIsPresent .true., & ! isIsPresent .true., & ! esIsPresent - ESMF_INIT_DEFINED, .false., ""), & + ESMF_INIT_DEFINED), & ESMF_COMPSTATUS_ALL_NOTPRESENT = ESMF_CompStatus(& .false., & ! configIsPresent .false., & ! clockIsPresent @@ -152,7 +152,7 @@ module ESMF_CompMod .false., & ! vmIsPresent .false., & ! isIsPresent .false., & ! esIsPresent - ESMF_INIT_DEFINED, .false., "") + ESMF_INIT_DEFINED) !------------------------------------------------------------------------------ ! ! ESMF_CompTunnel diff --git a/src/Superstructure/State/src/ESMF_StateTypes.F90 b/src/Superstructure/State/src/ESMF_StateTypes.F90 index 97a4195861..b415ffd286 100644 --- a/src/Superstructure/State/src/ESMF_StateTypes.F90 +++ b/src/Superstructure/State/src/ESMF_StateTypes.F90 @@ -65,7 +65,7 @@ module ESMF_StateTypesMod #endif !private type(ESMF_StateClass), pointer :: statep - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ From 593844ae88c49ccd187bd68ad3dbe73234f5723b Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 15 Jul 2022 11:57:40 -0700 Subject: [PATCH 032/266] Implement NamedAlias for GridComp, CplComp, SciComp. Also some cleanup. --- .../Util/include/ESMF_InitMacros.inc | 2 +- .../Component/src/ESMF_Comp.F90 | 6 +- .../Component/src/ESMF_CplComp.F90 | 28 +- .../Component/src/ESMF_GridComp.F90 | 37 +- .../Component/src/ESMF_SciComp.F90 | 26 +- .../NamedAlias/src/ESMF_NamedAlias.F90 | 156 +++- .../NamedAlias/tests/ESMF_NamedAliasUTest.F90 | 685 ++++++++++++++---- .../State/src/ESMF_StateAPI.cppF90 | 2 +- .../State/src/ESMF_StateSet.F90 | 2 +- .../State/src/ESMF_StateTypes.F90 | 2 +- 10 files changed, 786 insertions(+), 160 deletions(-) diff --git a/src/Infrastructure/Util/include/ESMF_InitMacros.inc b/src/Infrastructure/Util/include/ESMF_InitMacros.inc index 75293cd622..94bce59f0c 100644 --- a/src/Infrastructure/Util/include/ESMF_InitMacros.inc +++ b/src/Infrastructure/Util/include/ESMF_InitMacros.inc @@ -63,7 +63,7 @@ automatic initialization of types. finit(var) #else #define ESMF_INIT_DECLARE ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED -#define ESMF_INIT_DECLARE_NAMED_ALIAS ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED ; logical :: namedAlias = .false. ; character(ESMF_MAXSTR) :: name +#define ESMF_INIT_DECLARE_NAMED_ALIAS ESMF_INIT_TYPE :: isInit = ESMF_INIT_UNDEFINED ; logical :: isNamedAlias = .false. ; character(ESMF_MAXSTR) :: name #define ESMF_INIT_CHECK_SET_SHALLOW(fget,finit,var) #endif diff --git a/src/Superstructure/Component/src/ESMF_Comp.F90 b/src/Superstructure/Component/src/ESMF_Comp.F90 index ebd785b924..64ee1562fd 100644 --- a/src/Superstructure/Component/src/ESMF_Comp.F90 +++ b/src/Superstructure/Component/src/ESMF_Comp.F90 @@ -249,7 +249,7 @@ module ESMF_CompMod #endif !private type(ESMF_CompClass), pointer :: compp - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ @@ -265,7 +265,7 @@ module ESMF_CompMod #endif !private type(ESMF_CompClass), pointer :: compp - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ @@ -281,7 +281,7 @@ module ESMF_CompMod #endif !private type(ESMF_CompClass), pointer :: compp - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ diff --git a/src/Superstructure/Component/src/ESMF_CplComp.F90 b/src/Superstructure/Component/src/ESMF_CplComp.F90 index 97a5733a26..60f3f45412 100644 --- a/src/Superstructure/Component/src/ESMF_CplComp.F90 +++ b/src/Superstructure/Component/src/ESMF_CplComp.F90 @@ -886,6 +886,11 @@ subroutine ESMF_CplCompGet(cplcomp, keywordEnforcer, configIsPresent, config, & ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return + if (cplcomp%isNamedAlias .and. present(name)) then + ! access NamedAlias name + name = trim(cplcomp%name) + endif + ! call Comp method call ESMF_CompStatusGet(compStatus, & clockIsPresent = clockIsPresent, & @@ -1900,12 +1905,23 @@ subroutine ESMF_CplCompSet(cplcomp, keywordEnforcer, config, configFile, & ESMF_INIT_CHECK_DEEP(ESMF_ConfigGetInit,config,rc) ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc) - ! call Comp method - call ESMF_CompSet(cplcomp%compp, name, clock=clock, configFile=configFile, & - config=config, rc=localrc) - if (ESMF_LogFoundError(localrc, & - ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (cplcomp%isNamedAlias .and. present(name)) then + ! set NamedAlias name + cplcomp%name = trim(name) + ! call Comp method (without name) + call ESMF_CompSet(cplcomp%compp, clock=clock, & + configFile=configFile, config=config, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + else + ! call Comp method + call ESMF_CompSet(cplcomp%compp, name=name, clock=clock, & + configFile=configFile, config=config, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif ! return successfully if (present(rc)) rc = ESMF_SUCCESS diff --git a/src/Superstructure/Component/src/ESMF_GridComp.F90 b/src/Superstructure/Component/src/ESMF_GridComp.F90 index 1048018b36..98c3635ab2 100644 --- a/src/Superstructure/Component/src/ESMF_GridComp.F90 +++ b/src/Superstructure/Component/src/ESMF_GridComp.F90 @@ -1128,6 +1128,11 @@ recursive subroutine ESMF_GridCompGet(gridcomp, keywordEnforcer, & ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return + if (gridcomp%isNamedAlias .and. present(name)) then + ! access NamedAlias name + name = trim(gridcomp%name) + endif + ! call Comp method call ESMF_CompStatusGet(compStatus, & clockIsPresent = clockIsPresent, & @@ -2254,15 +2259,29 @@ subroutine ESMF_GridCompSet(gridcomp, keywordEnforcer, grid, gridList, & ESMF_INIT_CHECK_DEEP(ESMF_ConfigGetInit,config,rc) ESMF_INIT_CHECK_DEEP(ESMF_ClockGetInit,clock,rc) - ! call Comp method - call ESMF_CompSet(gridcomp%compp, name=name, & - grid=grid, gridList=gridList, mesh=mesh, meshList=meshList, & - locstream=locstream, locstreamList=locstreamList, xgrid=xgrid, & - xgridList=xgridList, clock=clock, configFile=configFile, config=config, & - rc=localrc) - if (ESMF_LogFoundError(localrc, & - ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (gridcomp%isNamedAlias .and. present(name)) then + ! set NamedAlias name + gridcomp%name = trim(name) + ! call Comp method (without name) + call ESMF_CompSet(gridcomp%compp, & + grid=grid, gridList=gridList, mesh=mesh, meshList=meshList, & + locstream=locstream, locstreamList=locstreamList, xgrid=xgrid, & + xgridList=xgridList, clock=clock, configFile=configFile, config=config, & + rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + else + ! call Comp method + call ESMF_CompSet(gridcomp%compp, name=name, & + grid=grid, gridList=gridList, mesh=mesh, meshList=meshList, & + locstream=locstream, locstreamList=locstreamList, xgrid=xgrid, & + xgridList=xgridList, clock=clock, configFile=configFile, config=config, & + rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif ! return successfully if (present(rc)) rc = ESMF_SUCCESS diff --git a/src/Superstructure/Component/src/ESMF_SciComp.F90 b/src/Superstructure/Component/src/ESMF_SciComp.F90 index ddce1ec24c..9a452de43f 100644 --- a/src/Superstructure/Component/src/ESMF_SciComp.F90 +++ b/src/Superstructure/Component/src/ESMF_SciComp.F90 @@ -476,11 +476,15 @@ subroutine ESMF_SciCompGet(scicomp, keywordEnforcer, name, rc) ! call Comp method call ESMF_CompGet(scicomp%compp, name=name, compStatus=compStatus, & rc=localrc) -print *, "Name: ", name if (ESMF_LogFoundError(localrc, & ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=localrc)) return + if (scicomp%isNamedAlias .and. present(name)) then + ! access NamedAlias name + name = trim(scicomp%name) + endif + ! call Comp method call ESMF_CompStatusGet(compStatus, rc = localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & @@ -616,11 +620,21 @@ subroutine ESMF_SciCompSet(scicomp, keywordEnforcer, name, rc) ESMF_INIT_CHECK_DEEP(ESMF_SciCompGetInit,scicomp,rc) - ! call Comp method - call ESMF_CompSet(scicomp%compp, name=name, rc=localrc) - if (ESMF_LogFoundError(localrc, & - ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (scicomp%isNamedAlias .and. present(name)) then + ! set NamedAlias name + scicomp%name = trim(name) + ! call Comp method (without name) + call ESMF_CompSet(scicomp%compp, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + else + ! call Comp method + call ESMF_CompSet(scicomp%compp, name=name, rc=localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif ! return successfully if (present(rc)) rc = ESMF_SUCCESS diff --git a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 index fa8adf192b..658e7e74ce 100644 --- a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 +++ b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 @@ -27,6 +27,12 @@ module ESMF_NamedAliasMod use ESMF_StateMod +use ESMF_CompMod +use ESMF_GridCompMod +use ESMF_CplCompMod +use ESMF_SciCompMod + + use ESMF_ArrayMod #if 0 @@ -36,10 +42,6 @@ module ESMF_NamedAliasMod use ESMF_FieldMod use ESMF_FieldGetMod use ESMF_FieldBundleMod -use ESMF_CompMod -use ESMF_GridCompMod -use ESMF_CplCompMod -use ESMF_SciCompMod use ESMF_ArrayBundleMod use ESMF_InfoMod use ESMF_UtilTypesMod @@ -66,12 +68,13 @@ module ESMF_NamedAliasMod interface ESMF_NamedAlias module procedure ESMF_NamedAliasState + module procedure ESMF_NamedAliasGridComp + module procedure ESMF_NamedAliasCplComp + module procedure ESMF_NamedAliasSciComp + module procedure ESMF_NamedAliasArray #if 0 module procedure ESMF_NamedAliasArrayBundle - module procedure ESMF_NamedAliasCplComp - module procedure ESMF_NamedAliasGridComp - module procedure ESMF_NamedAliasSciComp module procedure ESMF_NamedAliasField module procedure ESMF_NamedAliasFieldBundle module procedure ESMF_NamedAliasGrid @@ -84,7 +87,7 @@ module ESMF_NamedAliasMod ! -------------------------- ESMF-public method ------------------------------- !BOP -! !IROUTINE: ESMF_NamedAlias - Named Alias +! !IROUTINE: ESMF_NamedAlias - Generate a Named Alias ! ! !INTERFACE: ! function ESMF_NamedAlias(object, name, rc) @@ -98,6 +101,9 @@ module ESMF_NamedAliasMod ! Generate a named alias to {\tt object}. The supported classes are: ! \begin{itemize} ! \item {\tt ESMF\_State} +! \item {\tt ESMF\_GridComp} +! \item {\tt ESMF\_CplComp} +! \item {\tt ESMF\_SciComp} ! \item {\tt ESMF\_Array} ! \end{itemize} ! @@ -143,7 +149,7 @@ function ESMF_NamedAliasState(object, keywordEnforcer, name, rc) ESMF_NamedAliasState = object ! next mark as namedAlias - ESMF_NamedAliasState%namedAlias = .true. + ESMF_NamedAliasState%isNamedAlias = .true. ! finally set name if (present(name)) then @@ -158,6 +164,138 @@ function ESMF_NamedAliasState(object, keywordEnforcer, name, rc) end function ESMF_NamedAliasState !------------------------------------------------------------------------------ +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasGridComp()" +!BOPI +! !IROUTINE: ESMF_NamedAliasGridComp - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasGridComp(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_GridComp) :: ESMF_NamedAliasGridComp +! +! !ARGUMENTS: + type(ESMF_GridComp),intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + + ! first create regular alias + ESMF_NamedAliasGridComp = object + + ! next mark as namedAlias + ESMF_NamedAliasGridComp%isNamedAlias = .true. + + ! finally set name + if (present(name)) then + ESMF_NamedAliasGridComp%name = trim(name) + else + call ESMF_GridCompGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasGridComp%name = trim(nameDefault) + endif + + end function ESMF_NamedAliasGridComp +!------------------------------------------------------------------------------ + +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasCplComp()" +!BOPI +! !IROUTINE: ESMF_NamedAliasCplComp - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasCplComp(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_CplComp) :: ESMF_NamedAliasCplComp +! +! !ARGUMENTS: + type(ESMF_CplComp),intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + + ! first create regular alias + ESMF_NamedAliasCplComp = object + + ! next mark as namedAlias + ESMF_NamedAliasCplComp%isNamedAlias = .true. + + ! finally set name + if (present(name)) then + ESMF_NamedAliasCplComp%name = trim(name) + else + call ESMF_CplCompGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasCplComp%name = trim(nameDefault) + endif + + end function ESMF_NamedAliasCplComp +!------------------------------------------------------------------------------ + +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasSciComp()" +!BOPI +! !IROUTINE: ESMF_NamedAliasSciComp - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasSciComp(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_SciComp) :: ESMF_NamedAliasSciComp +! +! !ARGUMENTS: + type(ESMF_SciComp),intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + + ! first create regular alias + ESMF_NamedAliasSciComp = object + + ! next mark as namedAlias + ESMF_NamedAliasSciComp%isNamedAlias = .true. + + ! finally set name + if (present(name)) then + ESMF_NamedAliasSciComp%name = trim(name) + else + call ESMF_SciCompGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasSciComp%name = trim(nameDefault) + endif + + end function ESMF_NamedAliasSciComp +!------------------------------------------------------------------------------ + ! -------------------------- ESMF-public method ------------------------------- #undef ESMF_METHOD #define ESMF_METHOD "ESMF_NamedAliasArray()" diff --git a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 index a9f579c6bd..528e54103a 100644 --- a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 +++ b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 @@ -50,7 +50,6 @@ program ESMF_NamedAliasUTest !LOCAL VARIABLES: logical :: testFlag character(ESMF_MAXSTR) :: name1, name2 - type(ESMF_State) :: state1, state2 !------------------------------------------------------------------------------- ! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are @@ -66,139 +65,579 @@ program ESMF_NamedAliasUTest if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ - state1 = ESMF_StateCreate(name="Test Name 1", rc=rc) + call TestStateNamedAlias(rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "NamedAlias() with default name for State Test" - write(failMsg, *) "Did not return ESMF_SUCCESS" - state2 = ESMF_NamedAlias(state1, rc=rc) - call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "NamedAlias is an Alias State Test" - write(failMsg, *) "Incorrect result" - testFlag = (state1 == state2) - call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - call ESMF_StateGet(state1, name=name1, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_StateGet(state2, name=name2, rc=rc) + call TestGridCompNamedAlias(rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Same default name for NamedAlias for State Test" - write(failMsg, *) "Incorrect result" - testFlag = (name1 == name2) - call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - call ESMF_StateSet(state2, name="Test Name 2", rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_StateGet(state1, name=name2, rc=rc) + call TestCplCompNamedAlias(rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Name change on NamedAlias for State not affecting Test" - write(failMsg, *) "Incorrect result" - testFlag = (name1 == name2) - call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - call ESMF_StateGet(state2, name=name2, rc=rc) + call TestSciCompNamedAlias(rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Name change on NamedAlias for State correct setting Test" - write(failMsg, *) "Incorrect result" - testFlag = (trim(name2) == "Test Name 2") - call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "NamedAlias is still an Alias State Test" - write(failMsg, *) "Incorrect result" - testFlag = (state1 == state2) - call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Destroy object through NamedAlias State Test" - write(failMsg, *) "Did not return ESMF_SUCCESS" - call ESMF_StateDestroy(state2, rc=rc) - call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Destroying NamedAlias destroys object State Test" - write(failMsg, *) "Returns ESMF_SUCCESS, but should not" - call ESMF_StateGet(state1, name=name1, rc=rc) - call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - state1 = ESMF_StateCreate(name="Test Name 1", rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "NamedAlias() with new name for State Test" - write(failMsg, *) "Did not return ESMF_SUCCESS" - state2 = ESMF_NamedAlias(state1, name="Test Name 2", rc=rc) - call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "NamedAlias is an Alias State Test" - write(failMsg, *) "Incorrect result" - testFlag = (state1 == state2) - call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - call ESMF_StateGet(state1, name=name1, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_StateGet(state2, name=name2, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Different name for NamedAlias for State Test" - write(failMsg, *) "Incorrect result" - testFlag = (name1 /= name2) - call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Destroy object through NamedAlias State Test" - write(failMsg, *) "Did not return ESMF_SUCCESS" - call ESMF_StateDestroy(state2, rc=rc) - call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - !------------------------------------------------------------------------ - !NEX_UTest - write(name, *) "Destroying NamedAlias destroys object State Test" - write(failMsg, *) "Returns ESMF_SUCCESS, but should not" - call ESMF_StateGet(state1, name=name1, rc=rc) - call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - - - !------------------------------------------------------------------------ 10 continue call ESMF_TestEnd(ESMF_SRCLINE) ! calls ESMF_Finalize() internally !------------------------------------------------------------------------ +contains !====================================================================== + + subroutine TestStateNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_State) :: object1, object2 + + object1 = ESMF_StateCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias State Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_StateGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for State Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateSet(object2, name="Test Name 2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_StateGet(object1, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for State not affecting Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for State correct setting Test" + write(failMsg, *) "Incorrect result" + testFlag = (trim(name2) == "Test Name 2") + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is still an Alias State Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object State Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_StateGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_StateCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias State Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_StateGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for State Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object State Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_StateGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + + subroutine TestGridCompNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_GridComp) :: object1, object2 + + object1 = ESMF_GridCompCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for GridComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias GridComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_GridCompGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_GridCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for GridComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_GridCompSet(object2, name="Test Name 2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_GridCompGet(object1, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for GridComp not affecting Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_GridCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for GridComp correct setting Test" + write(failMsg, *) "Incorrect result" + testFlag = (trim(name2) == "Test Name 2") + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is still an Alias GridComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias GridComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_GridCompDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object GridComp Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_GridCompGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_GridCompCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for GridComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias GridComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_GridCompGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_GridCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for GridComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias GridComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_GridCompDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object GridComp Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_GridCompGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + + subroutine TestCplCompNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_CplComp) :: object1, object2 + + object1 = ESMF_CplCompCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for CplComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias CplComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_CplCompGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_CplCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for CplComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_CplCompSet(object2, name="Test Name 2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_CplCompGet(object1, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for CplComp not affecting Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_CplCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for CplComp correct setting Test" + write(failMsg, *) "Incorrect result" + testFlag = (trim(name2) == "Test Name 2") + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is still an Alias CplComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias CplComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_CplCompDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object CplComp Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_CplCompGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_CplCompCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for CplComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias CplComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_CplCompGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_CplCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for CplComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias CplComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_CplCompDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object CplComp Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_CplCompGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + + subroutine TestSciCompNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_SciComp) :: object1, object2 + + object1 = ESMF_SciCompCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for SciComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias SciComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_SciCompGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_SciCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for SciComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_SciCompSet(object2, name="Test Name 2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_SciCompGet(object1, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for SciComp not affecting Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_SciCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for SciComp correct setting Test" + write(failMsg, *) "Incorrect result" + testFlag = (trim(name2) == "Test Name 2") + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is still an Alias SciComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias SciComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_SciCompDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object SciComp Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_SciCompGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_SciCompCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for SciComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias SciComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_SciCompGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_SciCompGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for SciComp Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias SciComp Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_SciCompDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object SciComp Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_SciCompGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + end program ESMF_NamedAliasUTest diff --git a/src/Superstructure/State/src/ESMF_StateAPI.cppF90 b/src/Superstructure/State/src/ESMF_StateAPI.cppF90 index 048005e0ad..5f11993a57 100644 --- a/src/Superstructure/State/src/ESMF_StateAPI.cppF90 +++ b/src/Superstructure/State/src/ESMF_StateAPI.cppF90 @@ -1238,7 +1238,7 @@ ESMF_INIT_CHECK_DEEP(ESMF_RouteHandleGetInit,routehandleList(i),rc) stypep => state%statep if (present(name)) then - if (state%namedAlias) then + if (state%isNamedAlias) then name = trim(state%name) else call ESMF_GetName(stypep%base, name=name, rc=localrc) diff --git a/src/Superstructure/State/src/ESMF_StateSet.F90 b/src/Superstructure/State/src/ESMF_StateSet.F90 index adaa6b4e6b..2427f63732 100644 --- a/src/Superstructure/State/src/ESMF_StateSet.F90 +++ b/src/Superstructure/State/src/ESMF_StateSet.F90 @@ -115,7 +115,7 @@ subroutine ESMF_StateSet(state, keywordEnforcer, stateIntent, name, rc) stypep => state%statep if (present(stateIntent)) stypep%st = stateintent if (present(name)) then - if (state%namedAlias) then + if (state%isNamedAlias) then state%name = trim(name) else call ESMF_SetName(stypep%base, name=name, rc=localrc) diff --git a/src/Superstructure/State/src/ESMF_StateTypes.F90 b/src/Superstructure/State/src/ESMF_StateTypes.F90 index b415ffd286..b8bcb7808d 100644 --- a/src/Superstructure/State/src/ESMF_StateTypes.F90 +++ b/src/Superstructure/State/src/ESMF_StateTypes.F90 @@ -65,7 +65,7 @@ module ESMF_StateTypesMod #endif !private type(ESMF_StateClass), pointer :: statep - ESMF_INIT_DECLARE_NAMED_ALIAS + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ From 7edf2e073d04e8dd7c523cf0feed11ea83865e7e Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 15 Jul 2022 14:08:34 -0700 Subject: [PATCH 033/266] Add NamedAlias support to FieldBundle and ArrayBundle. --- .../interface/ESMCI_ArrayBundle_F.C | 36 +-- .../interface/ESMF_ArrayBundle.F90 | 21 +- .../FieldBundle/src/ESMF_FieldBundle.cppF90 | 13 +- .../NamedAlias/src/ESMF_NamedAlias.F90 | 115 +++++++-- .../NamedAlias/tests/ESMF_NamedAliasUTest.F90 | 220 ++++++++++++++++++ 5 files changed, 355 insertions(+), 50 deletions(-) diff --git a/src/Infrastructure/ArrayBundle/interface/ESMCI_ArrayBundle_F.C b/src/Infrastructure/ArrayBundle/interface/ESMCI_ArrayBundle_F.C index 1eea8c89b8..31ebde237e 100644 --- a/src/Infrastructure/ArrayBundle/interface/ESMCI_ArrayBundle_F.C +++ b/src/Infrastructure/ArrayBundle/interface/ESMCI_ArrayBundle_F.C @@ -84,7 +84,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } @@ -117,7 +117,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } @@ -160,7 +160,7 @@ extern "C" { delete [] cname; }else if(*len_name){ ESMC_LogDefault.MsgFoundError(ESMC_RC_PTR_NULL, - "- Not a valid string", ESMC_CONTEXT, ESMC_NOT_PRESENT_FILTER(rc)); + "Not a valid string", ESMC_CONTEXT, ESMC_NOT_PRESENT_FILTER(rc)); return; } // return successfully @@ -202,7 +202,7 @@ extern "C" { // opt_arrayList was provided if (*len_arrayList < *arrayCount){ ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_SIZE, - "- opt_arrayList must provide arrayCount elements", ESMC_CONTEXT, rc); + "opt_arrayList must provide arrayCount elements", ESMC_CONTEXT, rc); return; } // opt_arrayList has correct number of elements @@ -223,6 +223,12 @@ extern "C" { // Initialize return code; assume routine not implemented if (rc!=NULL) *rc = ESMC_RC_NOT_IMPL; int localrc = ESMC_RC_NOT_IMPL; + // test if this is a valid ArrayBundle + if ((*ptr)->ESMC_BaseGetStatus()!=ESMF_STATUS_READY){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "not a valid object", ESMC_CONTEXT, rc); + return; + } // fill simple return values if (ESMC_NOT_PRESENT_FILTER(arrayCount) != ESMC_NULL_POINTER) *arrayCount = (*ptr)->getCount(); @@ -231,7 +237,7 @@ extern "C" { // opt_arrayList was provided if (*len_arrayList < (*ptr)->getCount()){ ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_SIZE, - "- opt_arrayList must provide arrayCount elements", ESMC_CONTEXT, rc); + "opt_arrayList must provide arrayCount elements", ESMC_CONTEXT, rc); return; } // opt_arrayList has correct number of elements @@ -266,7 +272,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } @@ -300,7 +306,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } @@ -330,7 +336,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } @@ -555,7 +561,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } @@ -602,7 +608,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } @@ -628,24 +634,24 @@ extern "C" { // must provide valid factorList and factorIndexList args if (!present(factorIndexList)){ ESMC_LogDefault.MsgFoundError(ESMC_RC_PTR_NULL, - "- Not a valid pointer to factorIndexList array", ESMC_CONTEXT, rc); + "Not a valid pointer to factorIndexList array", ESMC_CONTEXT, rc); return; } if ((factorIndexList)->dimCount != 2){ ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_RANK, - "- factorIndexList array must be of rank 2", ESMC_CONTEXT, rc); + "factorIndexList array must be of rank 2", ESMC_CONTEXT, rc); return; } if ((factorIndexList)->extent[0] != 2 && (factorIndexList)->extent[0] != 4){ ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_SIZE, - "- 1st dimension of factorIndexList array must be of size 2 or 4", + "1st dimension of factorIndexList array must be of size 2 or 4", ESMC_CONTEXT, rc); return; } if ((factorIndexList)->extent[1] != *factorListCount){ ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_SIZE, - "- 2nd dimension of factorIndexList does not match factorListCount", + "2nd dimension of factorIndexList does not match factorListCount", ESMC_CONTEXT, rc); return; } @@ -674,7 +680,7 @@ extern "C" { rc); return; }catch(...){ - ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "- Caught exception", + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, "Caught exception", ESMC_CONTEXT, rc); return; } diff --git a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 index 53f62d9320..1504b56cf0 100644 --- a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 +++ b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 @@ -61,9 +61,8 @@ module ESMF_ArrayBundleMod #ifndef ESMF_NO_SEQUENCE sequence #endif - private type(ESMF_Pointer) :: this - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ @@ -991,7 +990,7 @@ subroutine ESMF_ArrayBundleGetListAll(arraybundle, keywordEnforcer, & ESMF_CONTEXT, rcToReturn=rc)) return enddo endif - + ! Fill arrayNameList if (present(arrayNameList)) then do i=1, min(size(arrayNameList), opt_arrayCount) @@ -1000,20 +999,24 @@ subroutine ESMF_ArrayBundleGetListAll(arraybundle, keywordEnforcer, & ESMF_CONTEXT, rcToReturn=rc)) return enddo endif - + ! Garbage collection deallocate(opt_arrayPtrList) ! Special call to get name out of Base class if (present(name)) then - call c_ESMC_GetName(arraybundle, name, localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (arraybundle%isNamedAlias) then + name = trim(arraybundle%name) + else + call c_ESMC_GetName(arraybundle, name, localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif endif - + ! Return successfully if (present(rc)) rc = ESMF_SUCCESS - + end subroutine ESMF_ArrayBundleGetListAll !------------------------------------------------------------------------------ diff --git a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 index 9014f55076..0397edd558 100644 --- a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 +++ b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 @@ -109,7 +109,7 @@ module ESMF_FieldBundleMod sequence ^endif type(ESMF_FieldBundleType), pointer :: this - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ @@ -1600,7 +1600,7 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below ! Destroy all the internal Fields if this is a proxy fieldBundle #if 0 -!gjt: don't do this, Fields do their own garbage collection under their VM +!gjt: dont do this, Fields do their own garbage collection under their VM if(this%is_proxy) then nullify(flist) call ESMF_ContainerGet(this%container, itemCount=fcount, & @@ -1895,10 +1895,13 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below endif if (present(name)) then + if (fieldbundle%isNamedAlias) then + name = trim(fieldbundle%name) + else call ESMF_GetName(fieldbundle%this%base, name, localrc) - if (ESMF_LogFoundError(localrc, & - ESMF_ERR_PASSTHRU, & + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & ESMF_CONTEXT, rcToReturn=rc)) return + endif endif ! Return successfully @@ -6277,7 +6280,7 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! \begin{sloppypar} ! A logical flag, the default is .false., i.e., existing field data may ! {\em not} be overwritten. If .true., only the -! data corresponding to the field's name will be +! data corresponding to the fields name will be ! be overwritten. If the {\tt timeslice} option is given, only data for ! the given timeslice will be overwritten. ! Note that it is always an error to attempt to overwrite a NetCDF diff --git a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 index 658e7e74ce..88b4dc8089 100644 --- a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 +++ b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 @@ -31,28 +31,15 @@ module ESMF_NamedAliasMod use ESMF_GridCompMod use ESMF_CplCompMod use ESMF_SciCompMod +use ESMF_FieldBundleMod +use ESMF_ArrayBundleMod use ESMF_ArrayMod #if 0 -use ESMF_VMMod -use ESMF_StateItemMod -use ESMF_DistGridMod use ESMF_FieldMod use ESMF_FieldGetMod -use ESMF_FieldBundleMod -use ESMF_ArrayBundleMod -use ESMF_InfoMod -use ESMF_UtilTypesMod -use ESMF_GeomBaseMod -use ESMF_MeshMod -use ESMF_GridMod -use ESMF_XGridMod -use ESMF_XGridGetMod -use ESMF_LocStreamMod -use ESMF_RHandleMod -use ESMF_InfoDescribeMod #endif implicit none @@ -71,15 +58,12 @@ module ESMF_NamedAliasMod module procedure ESMF_NamedAliasGridComp module procedure ESMF_NamedAliasCplComp module procedure ESMF_NamedAliasSciComp + module procedure ESMF_NamedAliasFieldBundle + module procedure ESMF_NamedAliasArrayBundle module procedure ESMF_NamedAliasArray #if 0 - module procedure ESMF_NamedAliasArrayBundle module procedure ESMF_NamedAliasField - module procedure ESMF_NamedAliasFieldBundle - module procedure ESMF_NamedAliasGrid - module procedure ESMF_NamedAliasLocStream - module procedure ESMF_NamedAliasMesh #endif end interface @@ -104,7 +88,8 @@ module ESMF_NamedAliasMod ! \item {\tt ESMF\_GridComp} ! \item {\tt ESMF\_CplComp} ! \item {\tt ESMF\_SciComp} -! \item {\tt ESMF\_Array} +! \item {\tt ESMF\_FieldBundle} +! \item {\tt ESMF\_ArrayBundle} ! \end{itemize} ! ! The arguments are: @@ -296,6 +281,94 @@ function ESMF_NamedAliasSciComp(object, keywordEnforcer, name, rc) end function ESMF_NamedAliasSciComp !------------------------------------------------------------------------------ +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasFieldBundle()" +!BOPI +! !IROUTINE: ESMF_NamedAliasFieldBundle - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasFieldBundle(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_FieldBundle) :: ESMF_NamedAliasFieldBundle +! +! !ARGUMENTS: + type(ESMF_FieldBundle),intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + + ! first create regular alias + ESMF_NamedAliasFieldBundle = object + + ! next mark as namedAlias + ESMF_NamedAliasFieldBundle%isNamedAlias = .true. + + ! finally set name + if (present(name)) then + ESMF_NamedAliasFieldBundle%name = trim(name) + else + call ESMF_FieldBundleGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasFieldBundle%name = trim(nameDefault) + endif + + end function ESMF_NamedAliasFieldBundle +!------------------------------------------------------------------------------ + +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasArrayBundle()" +!BOPI +! !IROUTINE: ESMF_NamedAliasArrayBundle - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasArrayBundle(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_ArrayBundle) :: ESMF_NamedAliasArrayBundle +! +! !ARGUMENTS: + type(ESMF_ArrayBundle),intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + + ! first create regular alias + ESMF_NamedAliasArrayBundle = object + + ! next mark as namedAlias + ESMF_NamedAliasArrayBundle%isNamedAlias = .true. + + ! finally set name + if (present(name)) then + ESMF_NamedAliasArrayBundle%name = trim(name) + else + call ESMF_ArrayBundleGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasArrayBundle%name = trim(nameDefault) + endif + + end function ESMF_NamedAliasArrayBundle +!------------------------------------------------------------------------------ + ! -------------------------- ESMF-public method ------------------------------- #undef ESMF_METHOD #define ESMF_METHOD "ESMF_NamedAliasArray()" diff --git a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 index 528e54103a..78a1cca5f8 100644 --- a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 +++ b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 @@ -77,6 +77,12 @@ program ESMF_NamedAliasUTest call TestSciCompNamedAlias(rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call TestFieldBundleNamedAlias(rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call TestArrayBundleNamedAlias(rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ 10 continue call ESMF_TestEnd(ESMF_SRCLINE) ! calls ESMF_Finalize() internally @@ -640,4 +646,218 @@ subroutine TestSciCompNamedAlias(rc) !============================================================================ + subroutine TestFieldBundleNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_FieldBundle):: object1, object2 + + object1 = ESMF_FieldBundleCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias FieldBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_FieldBundleGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldBundleGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for FieldBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldBundleDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object FieldBundle Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_FieldBundleGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_FieldBundleCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias FieldBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_FieldBundleGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldBundleGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for FieldBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldBundleDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object FieldBundle Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_FieldBundleGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + + subroutine TestArrayBundleNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_ArrayBundle):: object1, object2 + + object1 = ESMF_ArrayBundleCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for ArrayBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias ArrayBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_ArrayBundleGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayBundleGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for ArrayBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias ArrayBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayBundleDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object ArrayBundle Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_ArrayBundleGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_ArrayBundleCreate(name="Test Name 1", rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for ArrayBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias ArrayBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_ArrayBundleGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayBundleGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for ArrayBundle Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias ArrayBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayBundleDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object ArrayBundle Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_ArrayBundleGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + end program ESMF_NamedAliasUTest From 9865973e1f8dde838cf9a28e91bc6308bb49fc8c Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 15 Jul 2022 15:32:20 -0700 Subject: [PATCH 034/266] Add NamedAlias support to Field and Array. --- .../Array/interface/ESMF_Array.F90 | 10 +- .../Array/interface/ESMF_ArrayCreate.cppF90 | 4 +- .../Array/interface/ESMF_ArrayGet.cppF90 | 10 +- .../Base/interface/ESMCI_Base_F.C | 12 + src/Infrastructure/Field/src/ESMF_Field.F90 | 2 +- .../Field/src/ESMF_FieldGet.cppF90 | 13 +- .../Field/src/ESMF_FieldSet.F90 | 10 +- .../NamedAlias/src/ESMF_NamedAlias.F90 | 81 ++++- .../NamedAlias/tests/ESMF_NamedAliasUTest.F90 | 294 ++++++++++++++++++ 9 files changed, 406 insertions(+), 30 deletions(-) diff --git a/src/Infrastructure/Array/interface/ESMF_Array.F90 b/src/Infrastructure/Array/interface/ESMF_Array.F90 index 0401b94442..2cbd37e9ff 100644 --- a/src/Infrastructure/Array/interface/ESMF_Array.F90 +++ b/src/Infrastructure/Array/interface/ESMF_Array.F90 @@ -459,9 +459,13 @@ subroutine ESMF_ArraySetDefault(array, keywordEnforcer, computationalLWidth, & ! Set the name in Base object if (present(name)) then - call c_ESMC_SetName(array, "Array", name, localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (array%isNamedAlias) then + array%name = trim(name) + else + call c_ESMC_SetName(array, "Array", name, localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif endif ! Deal with (optional) array arguments diff --git a/src/Infrastructure/Array/interface/ESMF_ArrayCreate.cppF90 b/src/Infrastructure/Array/interface/ESMF_ArrayCreate.cppF90 index 62842f9f62..917a872fc8 100644 --- a/src/Infrastructure/Array/interface/ESMF_ArrayCreate.cppF90 +++ b/src/Infrastructure/Array/interface/ESMF_ArrayCreate.cppF90 @@ -69,9 +69,9 @@ module ESMF_ArrayCreateMod ^ifndef ESMF_NO_SEQUENCE sequence ^endif - private +! private type(ESMF_Pointer) :: this - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ diff --git a/src/Infrastructure/Array/interface/ESMF_ArrayGet.cppF90 b/src/Infrastructure/Array/interface/ESMF_ArrayGet.cppF90 index c039ecdd4c..1e3eb0a98a 100644 --- a/src/Infrastructure/Array/interface/ESMF_ArrayGet.cppF90 +++ b/src/Infrastructure/Array/interface/ESMF_ArrayGet.cppF90 @@ -543,9 +543,13 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below ! Special call to get name out of Base class if (present(name)) then - call c_ESMC_GetName(array, name, localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (array%isNamedAlias) then + name = trim(array%name) + else + call c_ESMC_GetName(array, name, localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif endif ! Special call to get vm out of Base class diff --git a/src/Infrastructure/Base/interface/ESMCI_Base_F.C b/src/Infrastructure/Base/interface/ESMCI_Base_F.C index 444b264f1c..4cc1158b2b 100644 --- a/src/Infrastructure/Base/interface/ESMCI_Base_F.C +++ b/src/Infrastructure/Base/interface/ESMCI_Base_F.C @@ -456,6 +456,12 @@ extern "C" { return; } + if ((*base)->ESMC_BaseGetStatus()!=ESMF_STATUS_READY){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "not a valid object", ESMC_CONTEXT, rc); + return; + } + string copts = string (opts, ESMC_F90lentrim (opts, nlen)); *rc = (*base)->ESMC_Validate(copts.c_str()); @@ -492,6 +498,12 @@ extern "C" { return; } + if ((*base)->ESMC_BaseGetStatus()!=ESMF_STATUS_READY){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "not a valid object", ESMC_CONTEXT, rc); + return; + } + if (ESMF_MAXSTR < nlen){ strncpy(name, (*base)->ESMC_BaseGetF90Name(), ESMF_MAXSTR); memset(name+ESMF_MAXSTR, ' ', nlen-ESMF_MAXSTR); // fill rest with spaces diff --git a/src/Infrastructure/Field/src/ESMF_Field.F90 b/src/Infrastructure/Field/src/ESMF_Field.F90 index dd8539ecbd..226147a419 100644 --- a/src/Infrastructure/Field/src/ESMF_Field.F90 +++ b/src/Infrastructure/Field/src/ESMF_Field.F90 @@ -123,7 +123,7 @@ module ESMF_FieldMod #endif !private type (ESMF_FieldType), pointer :: ftypep - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ diff --git a/src/Infrastructure/Field/src/ESMF_FieldGet.cppF90 b/src/Infrastructure/Field/src/ESMF_FieldGet.cppF90 index e01da09dd2..4aa8fe59c1 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldGet.cppF90 +++ b/src/Infrastructure/Field/src/ESMF_FieldGet.cppF90 @@ -906,11 +906,14 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below deallocate(ll_min, ll_max, ll_elecount) endif ! present(index and elementCount) - if (present(name)) then - call ESMF_GetName(ftype%base, name, localrc) - if (ESMF_LogFoundError(localrc, & - ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (present(name) .and. field%isNamedAlias) then + ! access NamedAlias name + name = trim(field%name) + else + call ESMF_GetName(ftype%base, name, localrc) + if (ESMF_LogFoundError(localrc, & + ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return endif if (present(vm)) then diff --git a/src/Infrastructure/Field/src/ESMF_FieldSet.F90 b/src/Infrastructure/Field/src/ESMF_FieldSet.F90 index d29c87e920..24cfb9fa3f 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldSet.F90 +++ b/src/Infrastructure/Field/src/ESMF_FieldSet.F90 @@ -128,9 +128,13 @@ subroutine ESMF_FieldSet(field, keywordEnforcer, name, rc) ! Set the name in Base object if (present(name)) then - call ESMF_SetName(field%ftypep%base, name=name, rc=localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + if (field%isNamedAlias) then + field%name = trim(name) + else + call ESMF_SetName(field%ftypep%base, name=name, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + endif endif ! return successfully diff --git a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 index 88b4dc8089..59d93fc9d2 100644 --- a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 +++ b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 @@ -32,15 +32,10 @@ module ESMF_NamedAliasMod use ESMF_CplCompMod use ESMF_SciCompMod use ESMF_FieldBundleMod -use ESMF_ArrayBundleMod - - -use ESMF_ArrayMod - -#if 0 use ESMF_FieldMod use ESMF_FieldGetMod -#endif +use ESMF_ArrayBundleMod +use ESMF_ArrayMod implicit none @@ -59,12 +54,9 @@ module ESMF_NamedAliasMod module procedure ESMF_NamedAliasCplComp module procedure ESMF_NamedAliasSciComp module procedure ESMF_NamedAliasFieldBundle + module procedure ESMF_NamedAliasField module procedure ESMF_NamedAliasArrayBundle - module procedure ESMF_NamedAliasArray -#if 0 - module procedure ESMF_NamedAliasField -#endif end interface contains !===================================================================== @@ -89,7 +81,9 @@ module ESMF_NamedAliasMod ! \item {\tt ESMF\_CplComp} ! \item {\tt ESMF\_SciComp} ! \item {\tt ESMF\_FieldBundle} +! \item {\tt ESMF\_Field} ! \item {\tt ESMF\_ArrayBundle} +! \item {\tt ESMF\_Array} ! \end{itemize} ! ! The arguments are: @@ -325,6 +319,50 @@ function ESMF_NamedAliasFieldBundle(object, keywordEnforcer, name, rc) end function ESMF_NamedAliasFieldBundle !------------------------------------------------------------------------------ +! -------------------------- ESMF-public method ------------------------------- +#undef ESMF_METHOD +#define ESMF_METHOD "ESMF_NamedAliasField()" +!BOPI +! !IROUTINE: ESMF_NamedAliasField - Named Alias +! +! !INTERFACE: + ! Private name; call using ESMF_NamedAlias() + function ESMF_NamedAliasField(object, keywordEnforcer, name, rc) +! +! !RETURN VALUE: + type(ESMF_Field) :: ESMF_NamedAliasField +! +! !ARGUMENTS: + type(ESMF_Field),intent(in) :: object +type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below + character(len = *), intent(in), optional :: name + integer, intent(out), optional :: rc +!EOPI +!------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + + ! first create regular alias + ESMF_NamedAliasField = object + + ! next mark as namedAlias + ESMF_NamedAliasField%isNamedAlias = .true. + + ! finally set name + if (present(name)) then + ESMF_NamedAliasField%name = trim(name) + else + call ESMF_FieldGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasField%name = trim(nameDefault) + endif + + end function ESMF_NamedAliasField +!------------------------------------------------------------------------------ + ! -------------------------- ESMF-public method ------------------------------- #undef ESMF_METHOD #define ESMF_METHOD "ESMF_NamedAliasArrayBundle()" @@ -383,17 +421,34 @@ function ESMF_NamedAliasArray(object, keywordEnforcer, name, rc) type(ESMF_Array) :: ESMF_NamedAliasArray ! ! !ARGUMENTS: - type(ESMF_Array), intent(in) :: object + type(ESMF_Array),intent(in) :: object type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below character(len = *), intent(in), optional :: name integer, intent(out), optional :: rc !EOPI !------------------------------------------------------------------------------ + integer :: localrc + character(ESMF_MAXSTR) :: nameDefault + + if (present(rc)) rc = ESMF_SUCCESS + ! first create regular alias ESMF_NamedAliasArray = object + ! next mark as namedAlias + ESMF_NamedAliasArray%isNamedAlias = .true. + + ! finally set name + if (present(name)) then + ESMF_NamedAliasArray%name = trim(name) + else + call ESMF_ArrayGet(object, name=nameDefault, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ESMF_NamedAliasArray%name = trim(nameDefault) + endif + end function ESMF_NamedAliasArray !------------------------------------------------------------------------------ - end module ESMF_NamedAliasMod diff --git a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 index 78a1cca5f8..aeaaaa9539 100644 --- a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 +++ b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 @@ -80,9 +80,15 @@ program ESMF_NamedAliasUTest call TestFieldBundleNamedAlias(rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call TestFieldNamedAlias(rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call TestArrayBundleNamedAlias(rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call TestArrayNamedAlias(rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ 10 continue call ESMF_TestEnd(ESMF_SRCLINE) ! calls ESMF_Finalize() internally @@ -753,6 +759,150 @@ subroutine TestFieldBundleNamedAlias(rc) !============================================================================ + subroutine TestFieldNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_Field) :: object1, object2 + type(ESMF_Grid) :: grid + + grid = ESMF_GridCreateNoPeriDim(minIndex=(/1,1/), maxIndex=(/16,20/), rc=rc) + if (rc /= ESMF_SUCCESS) return + object1 = ESMF_FieldCreate(name="Test Name 1", typekind=ESMF_TYPEKIND_R8, & + grid=grid, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for Field Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias Field Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_FieldGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for Field Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_FieldSet(object2, name="Test Name 2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(object1, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for Field not affecting Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_FieldGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for Field correct setting Test" + write(failMsg, *) "Incorrect result" + testFlag = (trim(name2) == "Test Name 2") + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is still an Alias Field Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias Field Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object Field Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_FieldGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_FieldCreate(name="Test Name 1", typekind=ESMF_TYPEKIND_R8, & + grid=grid, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for Field Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias Field Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_FieldGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for Field Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias Field Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object Field Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_FieldGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + subroutine TestArrayBundleNamedAlias(rc) integer, intent(out) :: rc type(ESMF_ArrayBundle):: object1, object2 @@ -860,4 +1010,148 @@ subroutine TestArrayBundleNamedAlias(rc) !============================================================================ + subroutine TestArrayNamedAlias(rc) + integer, intent(out) :: rc + type(ESMF_Array) :: object1, object2 + type(ESMF_DistGrid) :: distgrid + + distgrid = ESMF_DistGridCreate(minIndex=(/1,1/), maxIndex=(/16,20/), rc=rc) + if (rc /= ESMF_SUCCESS) return + object1 = ESMF_ArrayCreate(name="Test Name 1", typekind=ESMF_TYPEKIND_R8, & + distgrid=distgrid, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with default name for Array Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias Array Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_ArrayGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Same default name for NamedAlias for Array Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_ArraySet(object2, name="Test Name 2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(object1, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for Array not affecting Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 == name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_ArrayGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Name change on NamedAlias for Array correct setting Test" + write(failMsg, *) "Incorrect result" + testFlag = (trim(name2) == "Test Name 2") + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is still an Alias Array Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias Array Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object Array Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_ArrayGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + object1 = ESMF_ArrayCreate(name="Test Name 1", typekind=ESMF_TYPEKIND_R8, & + distgrid=distgrid, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias() with new name for Array Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + object2 = ESMF_NamedAlias(object1, name="Test Name 2", rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "NamedAlias is an Alias Array Test" + write(failMsg, *) "Incorrect result" + testFlag = (object1 == object2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_ArrayGet(object1, name=name1, rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(object2, name=name2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Different name for NamedAlias for Array Test" + write(failMsg, *) "Incorrect result" + testFlag = (name1 /= name2) + call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroy object through NamedAlias Array Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayDestroy(object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Destroying NamedAlias destroys object Array Test" + write(failMsg, *) "Returns ESMF_SUCCESS, but should not" + call ESMF_ArrayGet(object1, name=name1, rc=rc) + call ESMF_Test((rc/=ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + ! return successfully + rc = ESMF_SUCCESS + + end subroutine + + !============================================================================ + end program ESMF_NamedAliasUTest From 4da4a8320aef313379de55ea5e13cbdbc562fa16 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Sat, 16 Jul 2022 12:04:52 -0700 Subject: [PATCH 035/266] Make sure to pass component variables as regular aliases through CompExecute(). --- src/Superstructure/Component/src/ESMF_Comp.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Superstructure/Component/src/ESMF_Comp.F90 b/src/Superstructure/Component/src/ESMF_Comp.F90 index 64ee1562fd..195c065b95 100644 --- a/src/Superstructure/Component/src/ESMF_Comp.F90 +++ b/src/Superstructure/Component/src/ESMF_Comp.F90 @@ -176,7 +176,7 @@ module ESMF_CompMod #endif !private type(ESMF_CompClass), pointer :: compp - ESMF_INIT_DECLARE + ESMF_INIT_DECLARE_NAMED_ALIAS end type !------------------------------------------------------------------------------ @@ -1190,6 +1190,7 @@ recursive subroutine ESMF_CompExecute(compp, method, & ! Wrap comp so it's passed to C++ correctly. compp%compw%compp => compp ESMF_INIT_SET_CREATED(compp%compw) + compp%compw%isNamedAlias = .false. ! Set up the arguments if (compp%iAmParticipant) then @@ -2631,9 +2632,10 @@ recursive subroutine ESMF_CWrapSetInitCreated(cw, rc) !------------------------------------------------------------------------------ ! Assume failure until success if (present(rc)) rc = ESMF_RC_NOT_IMPL - + ! Set init code ESMF_INIT_SET_CREATED(cw) + cw%isNamedAlias = .false. ! Return success if (present(rc)) rc = ESMF_SUCCESS From d31fe30cb1f5d70aef159519f90db9634b439f6e Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 19 Jul 2022 08:50:28 -0700 Subject: [PATCH 036/266] Add the return type specification to ESMF_NamedAlias() API doc. --- src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 index 59d93fc9d2..210999dd18 100644 --- a/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 +++ b/src/Superstructure/NamedAlias/src/ESMF_NamedAlias.F90 @@ -68,6 +68,8 @@ module ESMF_NamedAliasMod ! !INTERFACE: ! function ESMF_NamedAlias(object, name, rc) ! +! !RETURN VALUE: +! type(ESMF_*) :: ESMF_NamedAlias ! !ARGUMENTS: ! type(ESMF_*), intent(in) :: object ! character(len = *), intent(in), optional :: name From 79f77aa83033b2fbaab1754b0e1c2968acf4ac48 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 19 Jul 2022 13:32:32 -0700 Subject: [PATCH 037/266] Add testing for NamedAliases (and Aliases simultanously) added to and retrieved from State. --- .../NamedAlias/tests/ESMF_NamedAliasUTest.F90 | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) diff --git a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 index aeaaaa9539..6532376dd4 100644 --- a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 +++ b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 @@ -655,6 +655,7 @@ subroutine TestSciCompNamedAlias(rc) subroutine TestFieldBundleNamedAlias(rc) integer, intent(out) :: rc type(ESMF_FieldBundle):: object1, object2 + type(ESMF_State) :: state object1 = ESMF_FieldBundleCreate(name="Test Name 1", rc=rc) if (rc /= ESMF_SUCCESS) return @@ -736,6 +737,36 @@ subroutine TestFieldBundleNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias FieldBundle Test" @@ -763,6 +794,7 @@ subroutine TestFieldNamedAlias(rc) integer, intent(out) :: rc type(ESMF_Field) :: object1, object2 type(ESMF_Grid) :: grid + type(ESMF_State) :: state grid = ESMF_GridCreateNoPeriDim(minIndex=(/1,1/), maxIndex=(/16,20/), rc=rc) if (rc /= ESMF_SUCCESS) return @@ -831,6 +863,36 @@ subroutine TestFieldNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias Field Test" @@ -880,6 +942,36 @@ subroutine TestFieldNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias Field Test" @@ -906,6 +998,7 @@ subroutine TestFieldNamedAlias(rc) subroutine TestArrayBundleNamedAlias(rc) integer, intent(out) :: rc type(ESMF_ArrayBundle):: object1, object2 + type(ESMF_State) :: state object1 = ESMF_ArrayBundleCreate(name="Test Name 1", rc=rc) if (rc /= ESMF_SUCCESS) return @@ -987,6 +1080,36 @@ subroutine TestArrayBundleNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias ArrayBundle Test" @@ -1014,6 +1137,7 @@ subroutine TestArrayNamedAlias(rc) integer, intent(out) :: rc type(ESMF_Array) :: object1, object2 type(ESMF_DistGrid) :: distgrid + type(ESMF_State) :: state distgrid = ESMF_DistGridCreate(minIndex=(/1,1/), maxIndex=(/16,20/), rc=rc) if (rc /= ESMF_SUCCESS) return @@ -1082,6 +1206,36 @@ subroutine TestArrayNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias Array Test" @@ -1131,6 +1285,36 @@ subroutine TestArrayNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias Array Test" From 2ab925b909e3ff26d4a83cda5a078666f7e105c2 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 19 Jul 2022 15:02:54 -0600 Subject: [PATCH 038/266] Fix some documentation It looks like some parts of the documentation for ESMF_GridCreateMosaicReg were copied from the documentation for ESMF_GridCreateCubedSphereReg. Thus, the former had some references to a fixed tile count of 6 when in fact that routine supports an arbitrary tile count. In addition, fix some minor typos. --- .../Grid/interface/ESMF_Grid.F90 | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Infrastructure/Grid/interface/ESMF_Grid.F90 b/src/Infrastructure/Grid/interface/ESMF_Grid.F90 index 592205fd6d..e45e612381 100644 --- a/src/Infrastructure/Grid/interface/ESMF_Grid.F90 +++ b/src/Infrastructure/Grid/interface/ESMF_Grid.F90 @@ -14655,11 +14655,11 @@ function ESMF_GridCreateCubedSphereReg(tileSize,keywordEnforcer, & ! By default every tile is decomposed in the same way. If the total ! PET count is less than 6, one tile will be assigned to one DE and the DEs ! will be assigned to PETs sequentially, therefore, some PETs may have -! more than one DEs. If the total PET count is greater than 6, the total +! more than one DE. If the total PET count is greater than 6, the total ! number of DEs will be a multiple of 6 and less than or equal to the total ! PET count. For instance, if the total PET count is 16, the total DE count ! will be 12 with each tile decomposed into 1x2 blocks. The 12 DEs are mapped -! to the first 12 PETs and the remainding 4 PETs have no DEs locally, unless +! to the first 12 PETs and the remaining 4 PETs have no DEs locally, unless ! an optional {\tt delayout} is provided. ! \item[{[decompflagPTile]}] ! List of decomposition flags indicating how each dimension of each @@ -15790,16 +15790,16 @@ function ESMF_GridCreateMosaicReg(filename,keywordEnforcer, regDecompPTile, deco ! The name of the GRIDSPEC Mosaic file. ! \item[{[regDecompPTile]}] ! List of DE counts for each dimension. The second index steps through -! the tiles. The total {\tt deCount} is determined as th sum over +! the tiles. The total {\tt deCount} is determined as the sum over ! the products of {\tt regDecompPTile} elements for each tile. ! By default every tile is decomposed in the same way. If the total -! PET count is less than 6, one tile will be assigned to one DE and the DEs +! PET count is less than the tile count, one tile will be assigned to one DE and the DEs ! will be assigned to PETs sequentially, therefore, some PETs may have -! more than one DEs. If the total PET count is greater than 6, the total -! number of DEs will be multiple of 6 and less than or equal to the total -! PET count. For instance, if the total PET count is 16, the total DE count +! more than one DE. If the total PET count is greater than the tile count, the total +! number of DEs will be a multiple of the tile count and less than or equal to the total +! PET count. For instance, if the total PET count is 16 and the tile count is 6, the total DE count ! will be 12 with each tile decomposed into 1x2 blocks. The 12 DEs are mapped -! to the first 12 PETs and the remainding 4 PETs have no DEs locally, unless +! to the first 12 PETs and the remaining 4 PETs have no DEs locally, unless ! an optional {\tt delayout} is provided. ! \item[{[decompflagPTile]}] ! List of decomposition flags indicating how each dimension of each @@ -15956,8 +15956,8 @@ function ESMF_GridCreateMosaicReg(filename,keywordEnforcer, regDecompPTile, deco enddo !------------------------------------------------------------------------ - ! default decomposition. The number of DEs has to be multiple of 6. - ! If the total PET count is less than 6, some PETs will get more than one DE. + ! default decomposition. The number of DEs has to be multiple of the tile count. + ! If the total PET count is less than the tile count, some PETs will get more than one DE. ! Otherwise, total DEs is always less than or equal to total PETs. if (PetCnt < tileCount) then From 9bb996860de9a771e7a463496bf01ab1c2af77af Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 19 Jul 2022 17:27:50 -0600 Subject: [PATCH 039/266] Do not abort a write for tilecount > 1 This won't work yet, but we want it to get further --- src/Infrastructure/IO/src/ESMCI_IO.C | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_IO.C b/src/Infrastructure/IO/src/ESMCI_IO.C index 10fe76c098..340b5d056a 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO.C +++ b/src/Infrastructure/IO/src/ESMCI_IO.C @@ -544,19 +544,6 @@ int IO::write( for (it = objects.begin(); it < objects.end(); ++it) { Array *temp_array_p = (*it)->getArray(); // default to caller-provided Array - DistGrid *dg = temp_array_p->getDistGrid (); - - int tilecount = dg->getTileCount (); - if (tilecount != 1) { - localrc = ESMF_RC_NOT_IMPL; - std::stringstream errmsg; - errmsg << "tile count of " << tilecount << " != 1 - not supported yet"; - if (ESMC_LogDefault.MsgFoundError(localrc, errmsg.str(), ESMC_CONTEXT, &rc)) { - // Close the file but return original error even if close fails. - localrc = close(); - return rc; - } - } std::vector dimLabels; // Grid-level dimension labels From ad18f1ab75b16baadbd496e4401405b660abf68f Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 20 Jul 2022 14:25:57 -0700 Subject: [PATCH 040/266] Support NamedAlias feature for nested states (States being added to States). Also test this under NamedAliasUTest. --- .../NamedAlias/tests/ESMF_NamedAliasUTest.F90 | 91 ++++++++++++++++--- .../State/src/ESMF_StateInternals.cppF90 | 25 +++-- .../State/src/ESMF_StateItem.F90 | 6 +- 3 files changed, 96 insertions(+), 26 deletions(-) diff --git a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 index 6532376dd4..208e06e370 100644 --- a/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 +++ b/src/Superstructure/NamedAlias/tests/ESMF_NamedAliasUTest.F90 @@ -99,6 +99,7 @@ program ESMF_NamedAliasUTest subroutine TestStateNamedAlias(rc) integer, intent(out) :: rc type(ESMF_State) :: object1, object2 + type(ESMF_State) :: state object1 = ESMF_StateCreate(name="Test Name 1", rc=rc) if (rc /= ESMF_SUCCESS) return @@ -164,6 +165,36 @@ subroutine TestStateNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias State Test" @@ -212,6 +243,36 @@ subroutine TestStateNamedAlias(rc) call ESMF_Test(testFlag, name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ + state = ESMF_StateCreate(rc=rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Add Alias and NamedAlias to State State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_StateAdd(state, (/object1, object2/), rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve Alias from State State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name1, object1, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Retrieve NamedAlias from State State Test" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_Stateget(state, name2, object2, rc=rc) + call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_StateDestroy(state, rc=rc) + if (rc /= ESMF_SUCCESS) return + !------------------------------------------------------------------------ !NEX_UTest write(name, *) "Destroy object through NamedAlias State Test" @@ -868,7 +929,7 @@ subroutine TestFieldNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(name, *) "Add Alias and NamedAlias to State Field Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_StateAdd(state, (/object1, object2/), rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -876,7 +937,7 @@ subroutine TestFieldNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve Alias from State FieldBundle Test" + write(name, *) "Retrieve Alias from State Field Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name1, object1, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -884,7 +945,7 @@ subroutine TestFieldNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(name, *) "Retrieve NamedAlias from State Field Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name2, object2, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -947,7 +1008,7 @@ subroutine TestFieldNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(name, *) "Add Alias and NamedAlias to State Field Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_StateAdd(state, (/object1, object2/), rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -955,7 +1016,7 @@ subroutine TestFieldNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve Alias from State FieldBundle Test" + write(name, *) "Retrieve Alias from State Field Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name1, object1, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -963,7 +1024,7 @@ subroutine TestFieldNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(name, *) "Retrieve NamedAlias from State Field Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name2, object2, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1085,7 +1146,7 @@ subroutine TestArrayBundleNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(name, *) "Add Alias and NamedAlias to State ArrayBundle Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_StateAdd(state, (/object1, object2/), rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1093,7 +1154,7 @@ subroutine TestArrayBundleNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve Alias from State FieldBundle Test" + write(name, *) "Retrieve Alias from State ArrayBundle Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name1, object1, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1101,7 +1162,7 @@ subroutine TestArrayBundleNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(name, *) "Retrieve NamedAlias from State ArrayBundle Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name2, object2, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1211,7 +1272,7 @@ subroutine TestArrayNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(name, *) "Add Alias and NamedAlias to State Array Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_StateAdd(state, (/object1, object2/), rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1219,7 +1280,7 @@ subroutine TestArrayNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve Alias from State FieldBundle Test" + write(name, *) "Retrieve Alias from State Array Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name1, object1, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1227,7 +1288,7 @@ subroutine TestArrayNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(name, *) "Retrieve NamedAlias from State Array Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name2, object2, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1290,7 +1351,7 @@ subroutine TestArrayNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Add Alias and NamedAlias to State FieldBundle Test" + write(name, *) "Add Alias and NamedAlias to State Array Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_StateAdd(state, (/object1, object2/), rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1298,7 +1359,7 @@ subroutine TestArrayNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve Alias from State FieldBundle Test" + write(name, *) "Retrieve Alias from State Array Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name1, object1, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -1306,7 +1367,7 @@ subroutine TestArrayNamedAlias(rc) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "Retrieve NamedAlias from State FieldBundle Test" + write(name, *) "Retrieve NamedAlias from State Array Test" write(failMsg, *) "Did not return ESMF_SUCCESS" call ESMF_Stateget(state, name2, object2, rc=rc) call ESMF_Test((rc==ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) diff --git a/src/Superstructure/State/src/ESMF_StateInternals.cppF90 b/src/Superstructure/State/src/ESMF_StateInternals.cppF90 index 7cf3c1bdda..cd30a264cf 100644 --- a/src/Superstructure/State/src/ESMF_StateInternals.cppF90 +++ b/src/Superstructure/State/src/ESMF_StateInternals.cppF90 @@ -628,13 +628,20 @@ ESMF_INIT_CHECK_DEEP(ESMF_RouteHandleGetInit,routehandles(i),rc) return @\ endif @\ @\ - call ESMF_GetName (mname(i)%statep%base, name=itemname, rc=localrc) @\ + if (mname(i)%isNamedAlias) then @\ + itemname = trim(mname(i)%name) @\ + else @\ + call ESMF_GetName (mname(i)%statep%base, name=itemname, rc=localrc) @\ + if (ESMF_LogFoundError(localrc, & @\ + ESMF_ERR_PASSTHRU, & @\ + ESMF_CONTEXT, rcToReturn=rc)) return @\ + endif @\ ^else @\ call mtype##Get(mname(i), name=itemname, rc=localrc) @\ -^endif @\ if (ESMF_LogFoundError(localrc, & @\ - ESMF_ERR_PASSTHRU, & @\ - ESMF_CONTEXT, rcToReturn=rc)) return @\ + ESMF_ERR_PASSTHRU, & @\ + ESMF_CONTEXT, rcToReturn=rc)) return @\ +^endif @\ @\ ! See if this name is already in the state @\ exists = ESMF_StateClassFindData (stypep, itemname, expected=.false., & @\ @@ -700,16 +707,22 @@ ESMF_INIT_CHECK_DEEP(ESMF_RouteHandleGetInit,routehandles(i),rc) if (localaddflag .and. localrepflag) then @\ call ESMF_ContainerAddReplace (stypep%stateContainer, & @\ itemList=siwrap, rc=localrc) @\ + if (ESMF_LogFoundError (localrc, & @\ + ESMF_ERR_PASSTHRU, & @\ + ESMF_CONTEXT, rcToReturn=rc)) return @\ else if (localaddflag) then @\ call ESMF_ContainerAdd (stypep%stateContainer, & @\ itemList=siwrap, rc=localrc) @\ + if (ESMF_LogFoundError (localrc, & @\ + ESMF_ERR_PASSTHRU, & @\ + ESMF_CONTEXT, rcToReturn=rc)) return @\ else @\ call ESMF_ContainerReplace (stypep%stateContainer, & @\ itemList=siwrap, rc=localrc) @\ - end if @\ - if (ESMF_LogFoundError (localrc, & @\ + if (ESMF_LogFoundError (localrc, & @\ ESMF_ERR_PASSTHRU, & @\ ESMF_CONTEXT, rcToReturn=rc)) return @\ + end if @\ @\ end do @\ @\ diff --git a/src/Superstructure/State/src/ESMF_StateItem.F90 b/src/Superstructure/State/src/ESMF_StateItem.F90 index 5eef0a66e0..b27980ed59 100644 --- a/src/Superstructure/State/src/ESMF_StateItem.F90 +++ b/src/Superstructure/State/src/ESMF_StateItem.F90 @@ -445,11 +445,7 @@ subroutine ESMF_StateItemGet(stateItem, name, rc) return case (ESMF_STATEITEM_STATE%ot) if (present(name)) then - call ESMF_GetName(stateItem%datap%spp%base, name, localrc) - if (ESMF_LogFoundError(localrc, & - ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) & - return + name = stateItem%namep endif case default call ESMF_LogSetError(rcToCheck=ESMF_RC_INTNRL_BAD, & From 12fcb3f7a81d72dd6e6b80ca6884521a637ecdc1 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 21 Jul 2022 10:12:22 -0700 Subject: [PATCH 041/266] modify doc to reflect pip installation process --- src/addon/ESMPy/doc/install.rst | 34 ++++++++------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/src/addon/ESMPy/doc/install.rst b/src/addon/ESMPy/doc/install.rst index 7c767bcccd..aec7b904b6 100644 --- a/src/addon/ESMPy/doc/install.rst +++ b/src/addon/ESMPy/doc/install.rst @@ -17,7 +17,7 @@ The following packages are *optional*: * ESMF installation with NetCDF - required to create :class:`Grids ` and :class:`Meshes ` from file - NetCDF must be built as a shared library for ESMPy installation to succeed * `mpi4py `_- python bindings to MPI, needed to run some of the parallel regridding examples -* `nose `_ - for nose testing +* `nose2 `_ - for nose testing ---------------- Getting the code @@ -59,40 +59,24 @@ Development versions can be found in the ``esmpy_dev`` channel: Installing ESMPy from Source ---------------------------- -When installing from source, ESMPy requires a pointer to a file named esmf.mk -that is generated during an ESMF installation. The path of this file is: +When installing from source, ESMPy uses `pip `_ +to build and install the package. This requires setting an environment variable +pointing to a file named esmf.mk that is generated during an ESMF installation. +The path of this file is: .. code:: /lib/libO>//esmf.mk -If the ``ESMFMKFILE`` flag is set when building ESMPy then it will not need to be -referenced again. If not, an environment variable of the same name must be set -with the path to the esmf.mk file every time a new shell is initiated. - -ESMPy can be installed in a custom location using the -``--prefix``, ``--home``, or ``--install-base`` flags to the install command. If this -is done, then this location needs to be added to the ``PYTHONPATH`` environment -variable every time a new shell is initiated. If a -custom install location is not specified, ESMPy will be installed in the -standard Python package installation directory on that particular machine. +If ``ESMFMKFILE`` is set when building ESMPy then it will not need to be +referenced again. An installation of ESMPy in the default location for Python packages can be done with the following command issued from the top level ESMPy directory: .. code:: - python setup.py build --ESMFMKFILE=/esmf.mk install - -- custom install location: - -.. code:: - - python setup.py build --ESMFMKFILE=/esmf.mk - - python setup.py install --prefix= - - setenv PYTHONPATH /lib/\*/site_packages + pip install . Please contact esmf_support@ucar.edu with any questions. @@ -172,5 +156,3 @@ Testing related: - Nightly regression testing is limited to a small subset of the ESMF test platforms, including Darwin and Linux running gfortran with openMPI. - - From 1bd8b61908321b7966a7018ca9ea3609851fed2d Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 21 Jul 2022 10:13:27 -0700 Subject: [PATCH 042/266] temporarily remove slow tests and add unittest.expected_failure tags --- src/addon/ESMPy/examples/exampletest.py | 2 +- src/addon/ESMPy/setup.cfg | 2 +- .../src/ESMF/test/test_api/test_field.py | 6 +++--- .../ESMPy/src/ESMF/test/test_api/test_grid.py | 19 ++++++++++--------- .../src/ESMF/test/test_api/test_locstream.py | 6 ++++-- .../ESMPy/src/ESMF/test/test_api/test_mesh.py | 4 +++- .../ESMPy/src/ESMF/test/test_cbindings.py | 5 +++-- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/exampletest.py index 5bfbf8d32f..a6f57047a6 100644 --- a/src/addon/ESMPy/examples/exampletest.py +++ b/src/addon/ESMPy/examples/exampletest.py @@ -60,7 +60,7 @@ def test_regrid_from_file(self): # only example, not in documentation @attr('slow') - def test_tripole_regrid(self): + def _tripole_regrid(self): from . import tripole_regrid # only example, not in documentation diff --git a/src/addon/ESMPy/setup.cfg b/src/addon/ESMPy/setup.cfg index b15f9fb68c..c492282869 100644 --- a/src/addon/ESMPy/setup.cfg +++ b/src/addon/ESMPy/setup.cfg @@ -24,7 +24,7 @@ package_dir= packages = find: install_requires = numpy - + nose2 [options.packages.find] where=src diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py index e69d2baa5f..e06c28c1f6 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py @@ -100,7 +100,7 @@ def test_numpy_funcs(self): @attr('serial') @attr('slow') #nosetests src/ESMF/test/test_api/test_field.py:TestField.test_field_create_2d_grid - def test_field_create_2d_grid(self): + def _field_create_2d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] periodic=[[None, None, None], [None, None, 0], [None, None, 1], @@ -150,7 +150,7 @@ def test_field_create_2d_grid(self): @attr('serial') @attr('slow') - def test_field_create_3d_grid(self): + def _field_create_3d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] periodic=[[None, None, None], [None, None, 0], [None, None, 1], [None, None, 2], @@ -201,7 +201,7 @@ def test_field_create_3d_grid(self): "The following combinations of parameters failed to create a proper Field: " + str(len(fail))) @attr('slow') - def test_field_create_2d_mesh(self): + def _field_create_2d_mesh(self): parallel = False if pet_count() > 1: parallel = True diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py index 0c6fff2995..11cca7fe5d 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py @@ -11,6 +11,7 @@ import numpy as np import os import inspect +import unittest class TestGrid(TestBase): @@ -179,7 +180,7 @@ def test_grid_periodic(self): @attr('serial') @attr('slow') - def test_grid_create_2d(self): + def _grid_create_2d(self): keywords = dict( # periodic specifies all valid combos of [pole_kind, num_peri_dims, periodic_dim, pole_dim] pole_kind=[[PoleKind.NONE, PoleKind.NONE], @@ -225,7 +226,7 @@ def test_grid_create_2d(self): @attr('serial') @attr('slow') - def test_grid_create_3d(self): + def _grid_create_3d(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] periodic=[[None, None, None], [None, None, 0], [None, None, 1], [None, None, 2], @@ -688,7 +689,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): raise NameError('grid_create_from_file_scrip_balanced_restlast failed!') @attr('data') - @expected_failure + @unittest.expectedFailure def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.CYCLIC], @@ -741,7 +742,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): raise NameError('grid_create_from_file_scrip_restfirst_restlast failed!') @attr('data') - @expected_failure + @unittest.expectedFailure def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.CYCLIC], @@ -794,7 +795,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): raise NameError('grid_create_from_file_scrip_restlast_restlast failed!') @attr('data') - @expected_failure + @unittest.expectedFailure def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.CYCLIC], @@ -808,7 +809,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): raise NameError('grid_create_from_file_scrip_restlast_cyclic failed!') @attr('data') - @expected_failure + @unittest.expectedFailure def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.BALANCED], @@ -822,7 +823,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): raise NameError('grid_create_from_file_scrip_cyclic_balanced failed!') @attr('data') - @expected_failure + @unittest.expectedFailure def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTFIRST], @@ -836,7 +837,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): raise NameError('grid_create_from_file_scrip_cyclic_restfirst failed!') @attr('data') - @expected_failure + @unittest.expectedFailure def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTLAST], @@ -850,7 +851,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): raise NameError('grid_create_from_file_scrip_cyclic_restlast failed!') @attr('data') - @expected_failure + @unittest.expectedFailure def test_grid_create_from_file_scrip_decomp_cyclic_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.CYCLIC], diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py index 2df9f027a9..03c799b19d 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py @@ -7,6 +7,8 @@ from ESMF.interface.cbindings import * from ESMF.test.base import TestBase, attr +import unittest + class TestLocStream(TestBase): def test_create(self): @@ -67,7 +69,7 @@ def test_slice(self): assert(np.all(locstream["ESMF:X"] == np.array([0, 1, 2, 3, 4]))) - @expected_failure + @unittest.expectedFailure def test_pickle(self): locstream = LocStream(10, name="Test LocStream") @@ -75,7 +77,7 @@ def test_pickle(self): pickle.dumps(locstream) - @expected_failure + @unittest.expectedFailure def test_properties(self): locstream = LocStream(10, name="Test LocStream") locstream["ESMF:X"] = (1, 2, 3, 4, 5) diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py index 590ea363ab..18204e71e0 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py @@ -8,6 +8,8 @@ except ImportError: from nose import SkipTest +import unittest + import os import inspect @@ -304,7 +306,7 @@ def test_slice_mesh_created_from_file_esmfmesh(self): @attr('data') @attr('serial') - @expected_failure + @unittest.expectedFailure #TODO: remove expected failure once we have a smaller data file with mesh element coordinates to use # TODO: have to define slicing for mesh element coordinates as well.. def test_slice_mesh_created_from_file_elem_coords(self): diff --git a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py b/src/addon/ESMPy/src/ESMF/test/test_cbindings.py index f6dcca5022..a7369977d5 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py +++ b/src/addon/ESMPy/src/ESMF/test/test_cbindings.py @@ -10,6 +10,7 @@ import numpy as np +import unittest class TestCbindings(TestBase): @@ -33,7 +34,7 @@ def test_interfaceint(self): interfaceint = ESMP_InterfaceInt(Narray) - @expected_failure + @unittest.expectedFailure def test_interfaceint2(self): # This test should fail try: @@ -43,7 +44,7 @@ def test_interfaceint2(self): except: raise TypeError('FAIL: tuples cannot be used in place of numpy.array') - @expected_failure + @unittest.expectedFailure def test_interfaceint3(self): # This test should fail try: From d9bfc8af2c731e26e6eeaf11233691ca776ed77f Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 22 Jul 2022 12:28:56 -0600 Subject: [PATCH 043/266] Start generalizing constructPioDecomp to handle multiple tiles For now it still just handles a single tile, but I have put in place some generality to start moving towards handling multiple tiles. And it correctly handles the decomposition for a single tile of a multi-tile array now, which it didn't do before. Note that I changed the calculation of arrayShape in PIO_IODescHandler::constructPioDecomp: I'm pretty sure it is incorrect to have tile in here: this is documented as having dimension [redDimCount*ssiLocalDeCount]. So in principle we should have the DE number in here, but we can leave that out as long as we assume no more than one DE per PE. --- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 67 ++++++++++++++----- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 6fdbf0c48f..6cf10c5707 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -1917,6 +1917,12 @@ int PIO_IODescHandler::constructPioDecomp( return ESMF_RC_NOT_IMPL; } + // FIXME(wjs, 2022-07-20) Do we need a tile argument to this function (replacing the + // local tile variable)? Otherwise, need to have a loop over tiles. + int tile = 1; + // 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 pioDofCount = 0; int const *localDeToDeMap = arr_p->getDistGrid()->getDELayout()->getLocalDeToDeMap(); @@ -1924,11 +1930,17 @@ int PIO_IODescHandler::constructPioDecomp( 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 - if (arr_p->getDistGrid()->getElementCountPDe()[localDeToDeMap[localDe]]>0) + int globalDe = localDeToDeMap[localDe]; + int tileOfThisDe = arr_p->getDistGrid()->getTileListPDe()[globalDe]; + 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()[globalDe]>0) pioDofCount += arr_p->getTotalElementCountPLocalDe()[localDe]; } - // PRINTMSG("(" << my_rank << "): pioDofCount = " << pioDofCount); + PRINTMSG("pioDofCount = " << pioDofCount); try { // Allocate space for the DOF list pioDofList = new MPI_Offset[pioDofCount]; @@ -1943,8 +1955,11 @@ int PIO_IODescHandler::constructPioDecomp( return localrc; } // Fill in the PIO DOF list (local to global map) - // TODO: This is where we would need to make some magic to include - // TODO: multiple DEs. + // 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 pioDofCount>0, then this DE + // TODO: corresponds to the current tile.) localDe = 0; if (pioDofCount>0){ // construct the mapping of the local elements @@ -1992,12 +2007,9 @@ int PIO_IODescHandler::constructPioDecomp( } } - int tile = 0; distGrid = arr_p->getDistGrid(); const int *minIndexPDimPTile = distGrid->getMinIndexPDimPTile(); const int *maxIndexPDimPTile = distGrid->getMaxIndexPDimPTile(); - const int *totalLBound = arr_p->getTotalLBound(); - const int *totalUBound = arr_p->getTotalUBound(); // NB: Is this part of the restrictions on Array I/O? // nDims = arr_p->getRank(); @@ -2008,11 +2020,11 @@ int PIO_IODescHandler::constructPioDecomp( handle->dims = (int *)NULL; } handle->dims = new int[handle->nDims]; - // Step through the distGrid dimensions, getting the size of the - // dimension. + // 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 * handle->nDims) + i] - - minIndexPDimPTile[(tile * handle->nDims) + i] + 1); + handle->dims[i] = (maxIndexPDimPTile[((tile - 1) * handle->nDims) + i] - + minIndexPDimPTile[((tile - 1) * handle->nDims) + i] + 1); } handle->arrayRank = arr_p->getRank(); @@ -2021,20 +2033,39 @@ int PIO_IODescHandler::constructPioDecomp( handle->arrayShape = (int *)NULL; } handle->arrayShape = new int[handle->arrayRank]; - for (int i = 0; i < handle->arrayRank; ++i) { - handle->arrayShape[i] = (totalUBound[(tile * handle->arrayRank) + i] - - totalLBound[(tile * handle->arrayRank) + i] + - 1); + // 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 dimstr[64]; + char shapestr[64]; for (int i = 0; i < handle->arrayRank; i++) { - sprintf((dimstr + (5 * i)), " %03d%c", handle->arrayShape[i], + sprintf((shapestr + (5 * i)), " %03d%c", handle->arrayShape[i], (((handle->arrayRank - 1) == i) ? ' ' : ',')); } - PRINTMSG(", IODesc shape = [" << dimstr << "], calling pio_initdecomp"); + PRINTMSG(", IODesc shape = [" << shapestr << "], calling pio_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 << "]"); } PIOc_set_log_level(PIO_DEBUG_LEVEL); #endif // ESMFIO_DEBUG From ae427b6c83855d250f9ea657ed46807b88041fde Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 22 Jul 2022 14:36:09 -0600 Subject: [PATCH 044/266] Add a getTilePLocalDe function and apply it in some places I didn't replace all possible uses: I focused on uses of the old pattern where we wouldn't otherwise need to do the local to global DE conversion, because that's where the simplification is greatest. --- .../DistGrid/include/ESMCI_DistGrid.h | 1 + .../DistGrid/src/ESMCI_DistGrid.C | 51 ++++++++++++++++++- .../Grid/interface/ESMCI_Grid_F.C | 10 ++-- src/Infrastructure/Grid/src/ESMCI_Grid.C | 18 +++---- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 9 ++-- 5 files changed, 64 insertions(+), 25 deletions(-) diff --git a/src/Infrastructure/DistGrid/include/ESMCI_DistGrid.h b/src/Infrastructure/DistGrid/include/ESMCI_DistGrid.h index 6a068ee102..adf52079d1 100644 --- a/src/Infrastructure/DistGrid/include/ESMCI_DistGrid.h +++ b/src/Infrastructure/DistGrid/include/ESMCI_DistGrid.h @@ -242,6 +242,7 @@ namespace ESMCI { if (ESMC_BaseGetStatus()!=ESMF_STATUS_READY) throw ESMC_RC_OBJ_DELETED; return tileListPDe; } + int getTilePLocalDe(int localDe, int *rc) const; int const *getContigFlagPDimPDe() const { if (ESMC_BaseGetStatus()!=ESMF_STATUS_READY) throw ESMC_RC_OBJ_DELETED; return contigFlagPDimPDe; diff --git a/src/Infrastructure/DistGrid/src/ESMCI_DistGrid.C b/src/Infrastructure/DistGrid/src/ESMCI_DistGrid.C index a9c45bb5c6..ef38f03f75 100644 --- a/src/Infrastructure/DistGrid/src/ESMCI_DistGrid.C +++ b/src/Infrastructure/DistGrid/src/ESMCI_DistGrid.C @@ -4962,6 +4962,52 @@ ESMC_I8 DistGrid::getElementCountPDe( } //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::DistGrid::getTilePLocalDe()" +//BOPI +// !IROUTINE: ESMCI::DistGrid::getTilePLocalDe +// +// !INTERFACE: +int DistGrid::getTilePLocalDe( +// +// !RETURN VALUE: +// int tile number for local de +// +// !ARGUMENTS: +// + int localDe, // in - local DE = {0, ..., localDeCount-1} + int *rc // out - return code + )const{ +// +// !DESCRIPTION: +// Get the tile number for the given local de. Note that tiles are basis 1. +// +//EOPI +//----------------------------------------------------------------------------- + if (ESMC_BaseGetStatus()!=ESMF_STATUS_READY) throw ESMC_RC_OBJ_DELETED; + + // initialize return code; assume routine not implemented + if (rc!=NULL) *rc = ESMC_RC_NOT_IMPL; // final return code + + // check input + const int localDeCount = delayout->getLocalDeCount(); + if (localDe < 0 || localDe > localDeCount-1){ + ESMC_LogDefault.MsgFoundError(ESMC_RC_ARG_BAD, + "Specified local DE out of bounds", ESMC_CONTEXT, rc); + return -1; // bail out + } + + // calculate result + const int *localDeToDeMap = delayout->getLocalDeToDeMap(); + int tile = tileListPDe[localDeToDeMap[localDe]]; + + // return successfully + if (rc!=NULL) *rc = ESMF_SUCCESS; + return tile; +} +//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- #undef ESMC_METHOD @@ -5099,8 +5145,9 @@ template int DistGrid::tGetSequenceIndexLocalDe( tArbSeqIndexListPCollPLocalDe[0][localDe][linExclusiveIndex]); }else{ // determine the sequentialized index by construction of default tile rule - const int *localDeToDeMap = delayout->getLocalDeToDeMap(); - int tile = tileListPDe[localDeToDeMap[localDe]]; // tiles are basis 1 !!!! + int tile = getTilePLocalDe(localDe, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, &rc)) return rc; if (tile == 0){ // means that the localDe does not have any elements thus not on tile }else{ diff --git a/src/Infrastructure/Grid/interface/ESMCI_Grid_F.C b/src/Infrastructure/Grid/interface/ESMCI_Grid_F.C index 7ae3b31790..f91f58b720 100644 --- a/src/Infrastructure/Grid/interface/ESMCI_Grid_F.C +++ b/src/Infrastructure/Grid/interface/ESMCI_Grid_F.C @@ -2574,13 +2574,9 @@ void c_esmc_grid_get_from_proto(ESMCI::Grid **_grid, // Get tile number if (_tile != NULL) { - // Get de - const int *localDEList=grid->getDistGrid()->getDELayout()->getLocalDeToDeMap(); - int de=localDEList[localDE]; - - // Get tile - const int *DETileList = grid->getDistGrid()->getTileListPDe(); - *_tile=DETileList[de]; + *_tile = grid->getDistGrid()->getTilePLocalDe(localDE, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, ESMC_NOT_PRESENT_FILTER(_rc))) return; } diff --git a/src/Infrastructure/Grid/src/ESMCI_Grid.C b/src/Infrastructure/Grid/src/ESMCI_Grid.C index f3b3a38004..9a280d3242 100644 --- a/src/Infrastructure/Grid/src/ESMCI_Grid.C +++ b/src/Infrastructure/Grid/src/ESMCI_Grid.C @@ -7719,10 +7719,7 @@ void GridIter::setDEBnds( // Temporarily set min/max int localrc; - const int *localDEList= staggerDistgrid->getDELayout()->getLocalDeToDeMap(); - const int *DETileList = staggerDistgrid->getTileListPDe(); - int tile=DETileList[localDEList[localDE]]; - + int tile=staggerDistgrid->getTilePLocalDe(localDE, &localrc); const int *tileMin=staggerDistgrid->getMinIndexPDimPTile(tile, &localrc); const int *tileMax=staggerDistgrid->getMaxIndexPDimPTile(tile, &localrc); @@ -8771,10 +8768,10 @@ void GridCellIter::getDEBnds( } else { // Get tile min/max int localrc,rc; - const int *localDEList= staggerDistgrid->getDELayout()->getLocalDeToDeMap(); - const int *DETileList = staggerDistgrid->getTileListPDe(); - int tile=DETileList[localDEList[localDE]]; - + int tile=staggerDistgrid->getTilePLocalDe(localDE, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &rc)) throw rc; + const int *tileMin=staggerDistgrid->getMinIndexPDimPTile(tile, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &rc)) throw rc; @@ -8851,10 +8848,7 @@ void GridCellIter::setDEBnds( // Temporarily set min/max int localrc; - const int *localDEList= staggerDistgrid->getDELayout()->getLocalDeToDeMap(); - const int *DETileList = staggerDistgrid->getTileListPDe(); - int tile=DETileList[localDEList[localDE]]; - + int tile=staggerDistgrid->getTilePLocalDe(localDE, &localrc); const int *tileMin=staggerDistgrid->getMinIndexPDimPTile(tile, &localrc); const int *tileMax=staggerDistgrid->getMaxIndexPDimPTile(tile, &localrc); diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 6cf10c5707..1e74ff73ed 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -1885,6 +1885,7 @@ int PIO_IODescHandler::constructPioDecomp( // 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 pioDofCount; // Number @@ -1930,13 +1931,14 @@ int PIO_IODescHandler::constructPioDecomp( 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 globalDe = localDeToDeMap[localDe]; - int tileOfThisDe = arr_p->getDistGrid()->getTileListPDe()[globalDe]; + 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()[globalDe]>0) + if (thisDeIsThisTile && arr_p->getDistGrid()->getElementCountPDe()[localDeToDeMap[localDe]]>0) pioDofCount += arr_p->getTotalElementCountPLocalDe()[localDe]; } @@ -2073,7 +2075,6 @@ int PIO_IODescHandler::constructPioDecomp( for(int i=0; inDims; i++) ddims[i] = handle->dims[handle->nDims - i - 1]; // Create the decomposition - int *rc; ESMCI_IOREGION_ENTER("PIOc_InitDecomp"); PIOc_InitDecomp(iosys, handle->basepiotype, handle->nDims, ddims, pioDofCount, pioDofList, From 01938799a9ea9b3c139f295619c39aeaf2d1309f Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Fri, 22 Jul 2022 16:53:52 -0600 Subject: [PATCH 045/266] Make sure distance is initialized for is_in() functions. --- .../Mesh/src/Regridding/ESMCI_Mapping.C | 8 +- .../Mesh/src/Regridding/ESMCI_ShapeFunc.C | 108 ++++++++++-------- 2 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/Infrastructure/Mesh/src/Regridding/ESMCI_Mapping.C b/src/Infrastructure/Mesh/src/Regridding/ESMCI_Mapping.C index d65de06c3f..ae44c932c3 100644 --- a/src/Infrastructure/Mesh/src/Regridding/ESMCI_Mapping.C +++ b/src/Infrastructure/Mesh/src/Regridding/ESMCI_Mapping.C @@ -218,7 +218,7 @@ bool POLY_Mapping::is_in_cell(const double *mdata, } // do is in - double sdist; + double sdist=0.0; bool in_tri = tri_shape_func::is_in(p, &sdist); // Don't need to transform tri parametric coords because tri shape func seems to use [0,1], but @@ -250,7 +250,7 @@ bool POLY_Mapping::is_in_cell(const double *mdata, pcoord[1]=2*p[1]-1.0; // do is in - double sdist; + double sdist=0.0; bool in_quad = quad_shape_func::is_in(pcoord, &sdist); // Distance to quad @@ -284,7 +284,7 @@ bool POLY_Mapping::is_in_cell(const double *mdata, pcoord[1]=p2; // do is in - double sdist; + double sdist=0.0; bool in_tri = tri_shape_func::is_in(pcoord, &sdist); // Distance to tri @@ -307,7 +307,7 @@ bool POLY_Mapping::is_in_cell(const double *mdata, pcoord[1]=2*p2-1.0; // do is in - double sdist; + double sdist=0.0; bool in_quad = quad_shape_func::is_in(pcoord, &sdist); // Distance to quad diff --git a/src/Infrastructure/Mesh/src/Regridding/ESMCI_ShapeFunc.C b/src/Infrastructure/Mesh/src/Regridding/ESMCI_ShapeFunc.C index b4bf0b4614..87113e4f4b 100644 --- a/src/Infrastructure/Mesh/src/Regridding/ESMCI_ShapeFunc.C +++ b/src/Infrastructure/Mesh/src/Regridding/ESMCI_ShapeFunc.C @@ -54,6 +54,13 @@ void dg0_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[] template bool dg0_shape_func::is_in(const double pcoord[], double *dist) { + // WARNING: + // This method isn't used right now, but + // init dist to 0.0, just so something consistent is + // returned. However, this will be WRONG if is_in=false. + // TODO: If this is used, fix dist value to be correct when is_in=false + if (dist) *dist=0.0; + return false; } @@ -94,8 +101,17 @@ void bar_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[], Scal } // for j } + bool bar_shape_func::is_in(const double pcoord[], double *dist) { const double in_tol = 1e-10; + + // WARNING: + // This method isn't used right now, but + // init dist to 0.0, just so something consistent is + // returned. However, this will be WRONG if is_in=false. + // TODO: If this is used, fix dist value to be correct when is_in=false + if (dist) *dist=0.0; // Init to 0.0 + if (pcoord[0] < -1.0-in_tol || pcoord[0] > 1.0+in_tol) return false; return true; } @@ -144,6 +160,14 @@ void bar3_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[], Sca bool bar3_shape_func::is_in(const double pcoord[], double *dist) { const double in_tol = 1e-10; + + // WARNING: + // This method isn't used right now, but + // init dist to 0.0, just so something consistent is + // returned. However, this will be WRONG if is_in=false. + // TODO: If this is used, fix dist value to be correct when is_in=false + if (dist) *dist=0.0; // Init to 0.0 + if (pcoord[0] < -1.0-in_tol || pcoord[0] > 1.0+in_tol) return false; return true; } @@ -191,27 +215,15 @@ void tri_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[], Scal } -#if 0 -bool tri_shape_func::is_in(const double pcoord[], double *dist) { - const double in_tol = 1e-10; - if (pcoord[0] < -in_tol) { - if (dist) *dist = -pcoord[0]; - return false; - } else if (pcoord[1] < -in_tol) { - if (dist) *dist = -pcoord[1]; - return false; - } else if ((pcoord[0] + pcoord[1]) > 1.0+in_tol) { - if (dist) *dist = std::abs((pcoord[0] + pcoord[1]) - 1.0); - return false; - } - return true; -} -#endif bool tri_shape_func::is_in(const double pcoord[], double *dist) { const double in_tol = 1e-10; + + // Init to is_in = true case bool in=true; + if (dist) *dist=0.0; + // Figure out if it's actually not in if ((pcoord[0] <-in_tol) || (pcoord[1] <-in_tol)) { double out_dist[2]={0.0,0.0}; @@ -320,29 +332,16 @@ void quad_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[], Sca } // for j } -#if 0 + bool quad_shape_func::is_in(const double pcoord[], double *dist) { const double in_tol = 1e-10; - if (pcoord[0] < -1.0-in_tol) { - if(dist) *dist = -1.0 - pcoord[0]; - return false; - } else if (pcoord[0] > 1.0+in_tol) { - return false; - } else if (pcoord[1] < -1.0-in_tol) { - return false; - } else if(pcoord[1] > 1.0+in_tol) { - return false; - } - return true; -} -#endif - -bool quad_shape_func::is_in(const double pcoord[], double *dist) { - const double in_tol = 1e-10; + // Init to is_in = true case bool in=true; double max_out[2]={0.0,0.0}; + if (dist) *dist=0.0; + // Figure out if it's actually not in if (pcoord[0] < -1.0-in_tol) { max_out[0]=-1.0 - pcoord[0]; in= false; @@ -461,6 +460,14 @@ void quad9_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[], Sc bool quad9_shape_func::is_in(const double pcoord[], double *dist) { const double in_tol = 1e-10; + + // WARNING: + // This method isn't used right now, but + // init dist to 0.0, just so something consistent is + // returned. However, this will be WRONG if is_in=false. + // TODO: If this is used, fix dist value to be correct when is_in=false + if (dist) *dist=0.0; // Init to 0.0 + if (pcoord[0] < -1.0-in_tol || pcoord[0] > 1.0+in_tol || pcoord[1] < -1.0-in_tol || pcoord[1] > 1.0+in_tol) return false; return true; } @@ -556,12 +563,16 @@ void hex_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[], Scal } // for j } -#if 1 + bool hex_shape_func::is_in(const double pcoord[], double *dist) { const double in_tol = 1e-10; + + // Init to is_in = true case bool in=true; double max_out[3]={0.0,0.0,0.0}; + if (dist) *dist=0.0; + // Figure out if it's actually not in if (pcoord[0] < -1.0-in_tol) { max_out[0]=-1.0 - pcoord[0]; in= false; @@ -592,17 +603,6 @@ bool hex_shape_func::is_in(const double pcoord[], double *dist) { return in; } -#else - -bool hex_shape_func::is_in(const double pcoord[], double *dist) { - const double in_tol = 1e-10; - if (pcoord[0] < -1.0-in_tol || pcoord[0] > 1.0+in_tol || pcoord[1] < -1.0-in_tol || pcoord[1] > 1.0+in_tol - || pcoord[2] < -1.0-in_tol || pcoord[2] > 1.0+in_tol) return false; - return true; -} - -#endif - const double hex_shape_func::ipoints[ndofs*pdim] = { @@ -666,9 +666,17 @@ void tet_shape_func::shape_grads(unsigned int npts, const ScalarT pcoord[], Scal bool tet_shape_func::is_in(const double pcoord[],double *dist) { const double in_tol = 1e-10; - if (pcoord[0] < 0-in_tol || pcoord[1] < -in_tol || pcoord[2] < -in_tol) return false; + // WARNING: + // This method isn't used right now, but + // init dist to 0.0, just so something consistent is + // returned. However, this will be WRONG if is_in=false. + // TODO: If this is used, fix dist value to be correct when is_in=false + if (dist) *dist=0.0; // Init to 0.0 + + if (pcoord[0] < 0-in_tol || pcoord[1] < -in_tol || pcoord[2] < -in_tol) return false; if ((pcoord[0] + pcoord[1] + pcoord[2]) > 1+in_tol) return false; + return true; } @@ -706,6 +714,14 @@ void quad_zeroderiv_shape_func::shape_grads(unsigned int npts, const ScalarT pco bool quad_zeroderiv_shape_func::is_in(const double pcoord[], double *dist) { const double in_tol = 1e-10; + + // WARNING: + // This method isn't used right now, but + // init dist to 0.0, just so something consistent is + // returned. However, this will be WRONG if is_in=false. + // TODO: If this is used, fix dist value to be correct when is_in=false + if (dist) *dist=0.0; // Init to 0.0 + if (pcoord[0] < -1.0-in_tol || pcoord[0] > 1.0+in_tol || pcoord[1] < -1.0-in_tol || pcoord[1] > 1.0+in_tol) return false; return true; } From e09d87fe9e76057e7c62e7b27aaa148061ac431b Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Mon, 25 Jul 2022 10:13:43 -0600 Subject: [PATCH 046/266] PIO arrayWrite: fix baseAddress and arrlen for DE not on this tile --- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 1e74ff73ed..1aed5a7476 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -606,6 +606,10 @@ void PIO_Handler::arrayRead( // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 localDE = 0; + // FIXME(wjs, 2022-07-21) Should this be something special (like NULL) if this DE + // doesn't belong to the tile of interest? Or is it okay for it to be set like this + // anyway? + // - (2022-07-22) I think I should set it to NULL baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); int arrlen = 1; #if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) @@ -808,13 +812,24 @@ void PIO_Handler::arrayWrite( // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 localDE = 0; - baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); - PRINTMSG("baseAddress = 0x" << (void *)baseAddress); -// int arrlen = arr_p->getLocalarrayList()[localDE]->getByteCount(); - int arrlen = 1; - const int *counts = arr_p->getLocalarrayList()[localDE]->getCounts(); - for (int i=0; igetDistGrid()->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> $(MKINFO) -@echo "ESMF_VERSION_STRING=$(ESMF_VERSION_STRING)" >> $(MKINFO) ifeq ($(shell $(ESMF_DIR)/scripts/available git),git) - @if [ -d $(ESMF_DIR)/.git ] ; then \ + @if [ "$(ESMF_VERSION_STRING_GIT)" != "" ] ; then \ echo "ESMF_VERSION_STRING_GIT=$(ESMF_VERSION_STRING_GIT)" >> $(MKINFO) ; \ else \ echo "# Not a Git repository" >> $(MKINFO) ; \ diff --git a/scripts/esmfversiongit b/scripts/esmfversiongit index 83beadea61..5ba3cc4b83 100755 --- a/scripts/esmfversiongit +++ b/scripts/esmfversiongit @@ -1,5 +1,6 @@ #!/bin/sh # return the ESMF version from Git if available, or empty string otherwise -if [ -d $ESMF_DIR/.git ] ; then \ +# test looks for .git directory or .git file (when esmf is a submodule) +if [ -d $ESMF_DIR/.git ] || [ -s $ESMF_DIR/.git ] ; then \ git describe --tags 2>&1 | grep -v fatal fi From ef8d7e992915dc8012b84be0a79d8e89713c6893 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 27 Jul 2022 14:13:56 -0600 Subject: [PATCH 049/266] Handle multi-tile file naming The convention is that there should be exactly one '#' in the file name; this will be replaced by the tile number. I have *not* documented this in the API documentation yet. --- .../IO/include/ESMCI_IO_Handler.h | 9 ++- src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 67 +++++++++++++++++++ src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 34 +++++++--- 3 files changed, 97 insertions(+), 13 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_IO_Handler.h b/src/Infrastructure/IO/include/ESMCI_IO_Handler.h index 828efb49af..3769716445 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_Handler.h @@ -68,9 +68,11 @@ namespace ESMCI { int localPet; ESMC_IndexFlag indexflag; ESMC_IOFmt_Flag iofmtFlag; - std::string filename; // The filename for this object + std::string filename; // The filename for this object (for multi-tile IO, + // this will contain a placeholder to be replaced by tile number) ESMC_FileStatus_Flag fileStatusFlag; // Store file status bool overwrite; // OK to overwrite fields if true + int ntiles; // Number of tiles in arrays handled by this object protected: IO_Handler(ESMC_IOFmt_Flag fmtArg); // native constructor private: @@ -106,11 +108,11 @@ namespace ESMCI { public: const char *getName(void) const { return "ESMCI::IO_Handler"; } ESMC_IOFmt_Flag getFormat(void) { return iofmtFlag; } + const int getNtiles(void) const { return ntiles; } virtual bool formatOk(ESMC_IOFmt_Flag *newIofmt) { return (((ESMC_IOFmt_Flag *)NULL != newIofmt) && (*newIofmt == iofmtFlag)); } - const char *getFilename(void) const { return filename.c_str(); } bool overwriteFields(void) { return overwrite; } ESMC_FileStatus_Flag getFileStatusFlag(void) { return fileStatusFlag; } protected: @@ -122,6 +124,9 @@ namespace ESMCI { int setFilename(const std::string& name); public: + // get filename; if multi-tile IO, tile placeholder will be replaced by the given tile number + const std::string getFilename(int tile, int *rc = NULL) const; + // file exists is needed to implement status codes static bool fileExists(const std::string& filename, bool needWrite); // match() diff --git a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C index 4f3513d997..729f968491 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C @@ -25,6 +25,8 @@ // higher level, 3rd party or system includes here #include +#include +#include #include // other ESMF include files here. @@ -83,6 +85,10 @@ IO_Handler::IO_Handler ( fileStatusFlag = ESMC_FILESTATUS_UNKNOWN; overwrite = false; filename[0] = '\0'; + // FIXME(wjs, 2022-07-25) Determine ntiles dynamically, here or later; for now we'll fix + // at 6 for testing. If we end up setting it dynamically elsewhere, then it should be + // initialized to 1 here. + ntiles = 6; } //----------------------------------------------------------------------------- @@ -410,6 +416,67 @@ int IO_Handler::setFilename( } // end IO_Handler::setFilename //------------------------------------------------------------------------- +//------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO_Handler::getFilename()" +//BOPI +// !IROUTINE: IO_Handler::getFilename - get filename for this object, possibly tile-specific +// +// !INTERFACE: +const std::string IO_Handler::getFilename( +// +// !RETURN VALUE: +// filename associated with this IO_Handler object, possibly tile-specific +// +// !ARGUMENTS: + int tile, // (in) - tile number for which filename is requested + int *rc // (out) - return code + )const{ +// +// !DESCRIPTION: +// Return the filename for this IO_Handler object. +// If doing multi-tile IO, then the tile placeholder in the originally-specified +// filename will be replaced by the current tile number. +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + if (rc != NULL) { + *rc = ESMF_RC_NOT_IMPL; + } + + if (ntiles > 1) { + const char tilePlaceholder = '#'; // the character that will get replaced by the tile number + int numOccurrences = std::count(filename.begin(), filename.end(), tilePlaceholder); + if (numOccurrences != 1) { + std::stringstream errmsg; + errmsg << "For multi-tile IO, the specified file name must have exactly " + << "one occurrence of '" << tilePlaceholder << "', which will be " + << "replaced by the tile number. Filename <" << filename + << "> has " << numOccurrences << " occurrences."; + if (ESMC_LogDefault.MsgFoundError(ESMF_RC_VAL_WRONG, errmsg, ESMC_CONTEXT, rc)) { + return ""; + } + } + + size_t pos = filename.find(tilePlaceholder); + std::string tileStr = std::to_string(tile); + std::string actualFilename = filename; + actualFilename.replace(pos, 1, tileStr); + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } + return actualFilename; + + } else { + // Single tile; no need to do any replacement of template character + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } + return filename; + } +} // end IO_Handler::getFilename +//------------------------------------------------------------------------- //----------------------------------------------------------------------------- #undef ESMC_METHOD diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 1aed5a7476..f0224a215b 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -684,9 +684,12 @@ void PIO_Handler::arrayRead( return; } if (*timeslice > time_len) { + // FIXME(wjs, 2022-07-26) Hard-coding tile here for now because it's needed for + // the interface. Eventually we'll get it as an argument or in a loop. + int tile = 1; PRINTMSG(" (" << my_rank << "): " << "Timeframe is greater than that in file" << - getFilename() << ", file time = " << time_len << + getFilename(tile) << ", file time = " << time_len << ", requested record = " << *timeslice); if (ESMC_LogDefault.MsgFoundError(ESMC_RC_FILE_UNEXPECTED, "Timeframe is greater than max in file", @@ -1231,6 +1234,9 @@ void PIO_Handler::open( int iofmt_map_size = sizeof (iofmt_map)/sizeof (iofmt_map_t); + // FIXME(wjs, 2022-07-26) Get tile as an argument or loop over tiles + int tile = 1; + if (rc != NULL) { *rc = ESMF_RC_NOT_IMPL; // final return code } @@ -1279,7 +1285,10 @@ void PIO_Handler::open( } // Figure out if we need to call createfile or openfile new_file = false; - bool file_exists = IO_Handler::fileExists(getFilename(), !readonly); + 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) { @@ -1331,33 +1340,33 @@ void PIO_Handler::open( ESMCI_IOREGION_ENTER("PIOc_createfile"); piorc = PIOc_createfile(pioSystemDesc, &pioFileDesc, - &iotype, getFilename(), mode); + &iotype, thisFilename.c_str(), mode); ESMCI_IOREGION_EXIT("PIOc_createfile"); - if (!CHECKPIOWARN(piorc, std::string("Unable to create file: ") + getFilename(), + if (!CHECKPIOWARN(piorc, std::string("Unable to create file: ") + thisFilename, ESMF_RC_FILE_OPEN, (*rc))) { return; } else { new_file = true; - PRINTMSG("call to PIOc_createfile: success for " << getFilename() << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "< Date: Thu, 28 Jul 2022 14:50:41 -0600 Subject: [PATCH 050/266] Add better error checking to GRIDSPEC mosaic read method. --- .../IO/interface/ESMF_IOGridmosaic.F90 | 118 ++++++++++++++---- 1 file changed, 93 insertions(+), 25 deletions(-) diff --git a/src/Infrastructure/IO/interface/ESMF_IOGridmosaic.F90 b/src/Infrastructure/IO/interface/ESMF_IOGridmosaic.F90 index 9ac12530ab..3241d2c644 100644 --- a/src/Infrastructure/IO/interface/ESMF_IOGridmosaic.F90 +++ b/src/Infrastructure/IO/interface/ESMF_IOGridmosaic.F90 @@ -930,7 +930,9 @@ subroutine ESMF_GridspecReadStaggerR8(filename, nx, ny, lon, lat, staggerLoc, st integer :: start1(2), count1(2) real(ESMF_KIND_R8), allocatable :: supercoord(:,:) integer :: localrc - logical :: foundit + logical :: found_grid_tile_spec + logical :: found_geo_lon + logical :: found_geo_lat if (present(rc)) rc=ESMF_SUCCESS @@ -946,7 +948,12 @@ subroutine ESMF_GridspecReadStaggerR8(filename, nx, ny, lon, lat, staggerLoc, st ESMF_CONTEXT, rcToReturn=rc)) return #ifdef ESMF_NETCDF - foundit = .false. + ! Init variables to ensure that we find the correct things in file + found_grid_tile_spec = .false. + found_geo_lon=.false. + found_geo_lat=.false. + + ! Open file ncStatus = nf90_open(path=filename, mode=nf90_nowrite, ncid=ncid) if (CDFCheckError (ncStatus, & ESMF_METHOD, & @@ -967,7 +974,7 @@ subroutine ESMF_GridspecReadStaggerR8(filename, nx, ny, lon, lat, staggerLoc, st if (attstr(1:attlen) .eq. 'grid_tile_spec') then ! skip checking the attributes -- not sure which one should be set to what ! but makesure this dummy variable exists - foundit = .true. + found_grid_tile_spec = .true. #if 0 ! check the projection attribute ncStatus = nf90_inquire_attribute(ncid, i, 'projection', len=attlen) @@ -1052,8 +1059,10 @@ subroutine ESMF_GridspecReadStaggerR8(filename, nx, ny, lon, lat, staggerLoc, st endif if (attstr(1:attlen) .eq. 'geographic_latitude') then ncStatus = nf90_get_var(ncid, i, lat, start=start1, count=count1, stride=(/2,2/)) + found_geo_lat=.true. else ncStatus = nf90_get_var(ncid, i, lon, start=start1, count=count1, stride=(/2,2/)) + found_geo_lon=.true. endif if (CDFCheckError (ncStatus, & ESMF_METHOD, & @@ -1062,15 +1071,40 @@ subroutine ESMF_GridspecReadStaggerR8(filename, nx, ny, lon, lat, staggerLoc, st rc)) return endif endif - enddo - ncStatus = nf90_close(ncid) - if (CDFCheckError (ncStatus, & - ESMF_METHOD, & - ESMF_SRCLINE, & - "close tile file", & - rc)) return - if (.not. foundit .and. present(rc)) rc=ESMF_FAILURE - return + enddo + + ! Close file + ncStatus = nf90_close(ncid) + if (CDFCheckError (ncStatus, & + ESMF_METHOD, & + ESMF_SRCLINE, & + "close tile file", & + rc)) return + + ! Error check that the correct variables were in file + if (.not. found_grid_tile_spec) then + call ESMF_LogSetError(rcToCheck=ESMF_RC_NOT_FOUND, & + msg="No variable with a standard_name attribute set to grid_tile_spec found in file "//trim(filename), & + ESMF_CONTEXT, rcToReturn=rc) + return + endif + + if (.not. found_geo_lat) then + call ESMF_LogSetError(rcToCheck=ESMF_RC_NOT_FOUND, & + msg="No variable with a standard_name attribute set to geographic_latitude found in file "//trim(filename), & + ESMF_CONTEXT, rcToReturn=rc) + return + endif + + if (.not. found_geo_lon) then + call ESMF_LogSetError(rcToCheck=ESMF_RC_NOT_FOUND, & + msg="No variable with a standard_name attribute set to geographic_longitude found in file "//trim(filename), & + ESMF_CONTEXT, rcToReturn=rc) + return + endif + + ! Leave + return #else call ESMF_LogSetError(ESMF_RC_LIB_NOT_PRESENT, & @@ -1117,8 +1151,10 @@ subroutine ESMF_GridspecReadStaggerR4(filename, nx, ny, lon, lat, staggerLoc, st integer :: start1(2), count1(2) real(ESMF_KIND_R8), allocatable :: supercoord(:,:) integer :: localrc - logical :: foundit - + logical :: found_grid_tile_spec + logical :: found_geo_lon + logical :: found_geo_lat + if (present(rc)) rc=ESMF_SUCCESS call ESMF_VMGetCurrent(vm, rc=localrc) @@ -1133,7 +1169,12 @@ subroutine ESMF_GridspecReadStaggerR4(filename, nx, ny, lon, lat, staggerLoc, st ESMF_CONTEXT, rcToReturn=rc)) return #ifdef ESMF_NETCDF - foundit = .false. + ! Init variables to ensure that we find the correct things in file + found_grid_tile_spec = .false. + found_geo_lon=.false. + found_geo_lat=.false. + + ! Open file ncStatus = nf90_open(path=filename, mode=nf90_nowrite, ncid=ncid) if (CDFCheckError (ncStatus, & ESMF_METHOD, & @@ -1154,7 +1195,7 @@ subroutine ESMF_GridspecReadStaggerR4(filename, nx, ny, lon, lat, staggerLoc, st if (attstr(1:attlen) .eq. 'grid_tile_spec') then ! skip checking the attributes -- not sure which one should be set to what ! but makesure this dummy variable exists - foundit = .true. + found_grid_tile_spec = .true. #if 0 ! check the projection attribute ncStatus = nf90_inquire_attribute(ncid, i, 'projection', len=attlen) @@ -1239,8 +1280,10 @@ subroutine ESMF_GridspecReadStaggerR4(filename, nx, ny, lon, lat, staggerLoc, st endif if (attstr(1:attlen) .eq. 'geographic_latitude') then ncStatus = nf90_get_var(ncid, i, lat, start=start1, count=count1, stride=(/2,2/)) + found_geo_lat=.true. else ncStatus = nf90_get_var(ncid, i, lon, start=start1, count=count1, stride=(/2,2/)) + found_geo_lon=.true. endif if (CDFCheckError (ncStatus, & ESMF_METHOD, & @@ -1249,15 +1292,40 @@ subroutine ESMF_GridspecReadStaggerR4(filename, nx, ny, lon, lat, staggerLoc, st rc)) return endif endif - enddo - ncStatus = nf90_close(ncid) - if (CDFCheckError (ncStatus, & - ESMF_METHOD, & - ESMF_SRCLINE, & - "close tile file", & - rc)) return - if (.not. foundit .and. present(rc)) rc=ESMF_FAILURE - return + enddo + + ! Close file + ncStatus = nf90_close(ncid) + if (CDFCheckError (ncStatus, & + ESMF_METHOD, & + ESMF_SRCLINE, & + "close tile file", & + rc)) return + + ! Error check that the correct variables were in file + if (.not. found_grid_tile_spec) then + call ESMF_LogSetError(rcToCheck=ESMF_RC_NOT_FOUND, & + msg="No variable with standard_name attribute set to grid_tile_spec found in file "//trim(filename), & + ESMF_CONTEXT, rcToReturn=rc) + return + endif + + if (.not. found_geo_lat) then + call ESMF_LogSetError(rcToCheck=ESMF_RC_NOT_FOUND, & + msg="No variable with standard_name attribute set to geographic_latitude found in file "//trim(filename), & + ESMF_CONTEXT, rcToReturn=rc) + return + endif + + if (.not. found_geo_lon) then + call ESMF_LogSetError(rcToCheck=ESMF_RC_NOT_FOUND, & + msg="No variable with standard_name attribute set to geographic_longitude found in file "//trim(filename), & + ESMF_CONTEXT, rcToReturn=rc) + return + endif + + ! Leave + return #else call ESMF_LogSetError(ESMF_RC_LIB_NOT_PRESENT, & From aa4054816c5770502f7e23a584b923753b87081e Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Thu, 28 Jul 2022 16:27:49 -0600 Subject: [PATCH 051/266] Fix problem when attribute string len is 0. --- src/Infrastructure/IO/interface/ESMF_IOFileTypeCheck.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/IO/interface/ESMF_IOFileTypeCheck.F90 b/src/Infrastructure/IO/interface/ESMF_IOFileTypeCheck.F90 index 7e8c60aa5b..db5734385b 100644 --- a/src/Infrastructure/IO/interface/ESMF_IOFileTypeCheck.F90 +++ b/src/Infrastructure/IO/interface/ESMF_IOFileTypeCheck.F90 @@ -134,7 +134,7 @@ subroutine ESMF_FileTypeCheck(filename, filetype, varname, rc) ncStatus = nf90_inquire_attribute(gridid, i, 'standard_name', len=len) endif endif - if (ncStatus == nf90_noerror) then + if ((ncStatus == nf90_noerror) .and. (len .ge. 1)) then if (attvalue(len:len) .eq. achar(0)) len = len-1 if (attvalue(1:len) .eq. 'mesh_topology') then fileType=ESMF_FILEFORMAT_UGRID @@ -165,8 +165,8 @@ subroutine ESMF_FileTypeCheck(filename, filetype, varname, rc) endif ! check if it is CFGRID ! check if the coordinate variables exist or not - ncStatus = nf90_inquire_attribute(gridid, i, "units", len=len) - if (ncStatus == nf90_noerror) then + ncStatus = nf90_inquire_attribute(gridid, i, "units", len=len) + if ((ncStatus == nf90_noerror) .and. (len .ge. 1)) then ncStatus=nf90_get_att(gridid, i, 'units', attvalue) if (ncStatus /= nf90_noerror) then print '("NetCDF error: ", A)', trim(nf90_strerror(ncStatus)) From 4812f463b2d0e92fd41c0e8e6afbcd470e77d9af Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Thu, 28 Jul 2022 16:46:07 -0600 Subject: [PATCH 052/266] Add correct key names when LocStream is created from Cartesian ESMF Mesh file. --- .../LocStream/src/ESMF_LocStream.F90 | 74 +++++++++++++------ 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/src/Infrastructure/LocStream/src/ESMF_LocStream.F90 b/src/Infrastructure/LocStream/src/ESMF_LocStream.F90 index 107a115772..9e4b7d14ed 100644 --- a/src/Infrastructure/LocStream/src/ESMF_LocStream.F90 +++ b/src/Infrastructure/LocStream/src/ESMF_LocStream.F90 @@ -2467,30 +2467,62 @@ function ESMF_LocStreamCreateFromFile(filename, keywordEnforcer, & ESMF_CONTEXT, rcToReturn=rc)) return !print *, PetNo, starti, localcount, coordX(1), coordY(1) - ! Add coordinate keys - call ESMF_LocStreamAddKey(locStream, 'ESMF:Lon',coordX, keyUnits=units, & - keyLongName='Longitude', & - datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return - - call ESMF_LocStreamAddKey(locStream, 'ESMF:Lat',coordY, keyUnits=units, & - keyLongName='Latitude', & - datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return + + ! Add coordinate keys based on coordSys + if ((coordSys == ESMF_COORDSYS_SPH_DEG) .or. (coordSys == ESMF_COORDSYS_SPH_RAD)) then - !If 3D grid, add the height coordinates - if (totaldims == 3) then - if (localcount == 0) allocate(coordZ(localcount)) - call ESMF_LocStreamAddKey(locStream, 'ESMF:Radius',coordZ, & - keyUnits='radius', & - keyLongName='Height', & - datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) + call ESMF_LocStreamAddKey(locStream, 'ESMF:Lon',coordX, keyUnits=units, & + keyLongName='Longitude', & + datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return - deallocate(coordZ) + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_LocStreamAddKey(locStream, 'ESMF:Lat',coordY, keyUnits=units, & + keyLongName='Latitude', & + datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + !If 3D grid, add the height coordinates + if (totaldims == 3) then + if (localcount == 0) allocate(coordZ(localcount)) + call ESMF_LocStreamAddKey(locStream, 'ESMF:Radius',coordZ, & + keyUnits='radius', & + keyLongName='Height', & + datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + deallocate(coordZ) + endif + + else if (coordSys == ESMF_COORDSYS_CART) then + + call ESMF_LocStreamAddKey(locStream, 'ESMF:X',coordX, keyUnits=units, & + datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + call ESMF_LocStreamAddKey(locStream, 'ESMF:Y',coordY, keyUnits=units, & + datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + + !If 3D grid, add the height coordinates + if (totaldims == 3) then + if (localcount == 0) allocate(coordZ(localcount)) + call ESMF_LocStreamAddKey(locStream, 'ESMF:Z',coordZ, & + datacopyflag=ESMF_DATACOPY_VALUE, rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + deallocate(coordZ) + endif + else + call ESMF_LogSetError(rcToCheck=ESMF_RC_ARG_BAD, & + msg="Unrecognized coordinate system.", & + ESMF_CONTEXT, rcToReturn=rc) + return endif + !Add mask key call ESMF_LocStreamAddKey(locStream, 'ESMF:Mask',imask, & keyLongName='Mask', & From 6906b7b22641cfd46c42c1388f30f31feaf45280 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 29 Jul 2022 12:33:35 -0600 Subject: [PATCH 053/266] Fix to propagate ESMF_Info types (#55) * Fix Info::get() function in ESMCI_Info.C * Fix writing global attributes * Do not copy storage type JSON during Info::get() if null * Fix reference to Info storage type * Use explicit kind parameter for _FillValue in FieldIOUTest * Fix typo in debug output statement Co-authored-by: Dusan Jovic --- src/Infrastructure/Base/src/ESMCI_Info.C | 15 +++++++++++++-- .../Field/tests/ESMF_FieldIOUTest.F90 | 4 ++-- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure/Base/src/ESMCI_Info.C b/src/Infrastructure/Base/src/ESMCI_Info.C index 8f9d996f07..7ccdcf8cee 100644 --- a/src/Infrastructure/Base/src/ESMCI_Info.C +++ b/src/Infrastructure/Base/src/ESMCI_Info.C @@ -858,18 +858,29 @@ void Info::get(ESMCI::Info &info, key_t &key) const { #endif json j; + json const *ts = nullptr; try { j = this->get(key); + check_init_from_json(j); + const json &type_storage = this->getTypeStorage(); + if (!type_storage.is_null() && type_storage.size() > 0) { + json::json_pointer jpath = this->formatKey(key); + update_json_pointer(this->getTypeStorage(), &ts, jpath, true); + check_init_from_json(*ts); + } + #if 0 std::string msg2 = std::string(ESMC_METHOD) + ": j dump=" + j.dump(); ESMC_LogWrite(msg2.c_str(), ESMC_LOGMSG_DEBUG); #endif - - check_init_from_json(j); + } ESMF_CATCH_INFO info.getStorageRefWritable() = std::move(j); + if (!type_storage.is_null() && type_storage.size() > 0) { + info.getTypeStorageWritable() = std::move(*ts); + } #if 0 std::string msg3 = std::string(ESMC_METHOD) + ": info dump=" + info.dump(0); diff --git a/src/Infrastructure/Field/tests/ESMF_FieldIOUTest.F90 b/src/Infrastructure/Field/tests/ESMF_FieldIOUTest.F90 index 12a25c7f97..75b4e1583b 100644 --- a/src/Infrastructure/Field/tests/ESMF_FieldIOUTest.F90 +++ b/src/Infrastructure/Field/tests/ESMF_FieldIOUTest.F90 @@ -1330,7 +1330,7 @@ program ESMF_FieldIOUTest #if !defined (ESMF_PNETCDF) case ("_FillValue") call ESMF_AttributeSet (field_att, & - attrNames(i), valueList=(/ -1.e+10 /), & + attrNames(i), valueList=(/ -1.e+10_ESMF_KIND_R8 /), & convention=apConv, purpose=apPurp, & rc=rc) if (rc /= ESMF_SUCCESS) exit @@ -1563,7 +1563,7 @@ program ESMF_FieldIOUTest #if !defined (ESMF_PNETCDF) case ("_FillValue") call ESMF_AttributeSet (field_ugd_att, & - attrNames(i), valueList=(/ -1.e+10 /), & + attrNames(i), valueList=(/ -1.e+10_ESMF_KIND_R8 /), & convention=apConv, purpose=apPurp, & rc=rc) if (rc /= ESMF_SUCCESS) exit diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 6fdbf0c48f..27ebe1c5d1 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -1117,7 +1117,7 @@ void PIO_Handler::arrayWrite( } } if (gblAttPack) { - attPackPut (NULL, gblAttPack, &localrc); + attPackPut (NC_GLOBAL, gblAttPack, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) { return; From 6ad0adbd45b1bc1bdbe8ad549690c8053c4e027c Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 1 Aug 2022 13:56:24 -0700 Subject: [PATCH 054/266] Clean-up. --- .../VM/tests/ESMF_VMSendVMRecvUTest.F90 | 285 +++++++++++------- 1 file changed, 177 insertions(+), 108 deletions(-) diff --git a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 index ec18cd36fd..6fa78e0e2b 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 @@ -10,10 +10,10 @@ ! !============================================================================== ! - program ESMF_VMSendVMRecvUTest +program ESMF_VMSendVMRecvUTest !------------------------------------------------------------------------------ - + #include "ESMF_Macros.inc" !============================================================================== @@ -44,6 +44,7 @@ program ESMF_VMSendVMRecvUTest ! individual test failure message character(ESMF_MAXSTR) :: failMsg character(ESMF_MAXSTR) :: name + character(ESMF_MAXSTR) :: msgStr character(len=8) :: strvalue ! local variables @@ -51,18 +52,20 @@ program ESMF_VMSendVMRecvUTest type(ESMF_VM):: vm integer:: localPet, petCount integer:: count, src, dst - integer, allocatable:: localData(:),soln(:) - real(ESMF_KIND_R8), allocatable:: r8_localData(:),r8_soln(:) - real(ESMF_KIND_R4), allocatable:: r4_localData(:),r4_soln(:) + integer(ESMF_KIND_I4), allocatable :: i4_localData(:),i4_soln(:) + integer(ESMF_KIND_I8), allocatable :: i8_localData(:),i8_soln(:) + real(ESMF_KIND_R4), allocatable :: r4_localData(:),r4_soln(:) + real(ESMF_KIND_R8), allocatable :: r8_localData(:),r8_soln(:) type(ESMF_logical), allocatable:: local_logical(:),logical_soln(:) character(10), allocatable :: local_chars(:), char_soln(:) character(10) :: lchars - - integer :: isum - real(ESMF_KIND_R8) :: R8Sum - real(ESMF_KIND_R4) :: R4Sum + + integer(ESMF_KIND_I4) :: I4Sum + integer(ESMF_KIND_I8) :: I8Sum + real(ESMF_KIND_R4) :: R4Sum + real(ESMF_KIND_R8) :: R8Sum !------------------------------------------------------------------------------ ! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are @@ -85,30 +88,33 @@ program ESMF_VMSendVMRecvUTest !------------------------------------------------------------------------------ ! IMPORTANT NOTE: -! The correct operation of this unit test depends on sufficient internal -! buffering within VMSend and VMRecv! There will be an implementation +! The correct operation of this unit test depends on sufficient internal +! buffering within VMSend and VMRecv! There will be an implementation ! specific threshold for count above which this unit test will start to hang! !------------------------------------------------------------------------------ - allocate(localData(count)) - allocate(r8_localData(count)) + allocate(i4_localData(count)) + allocate(i8_localData(count)) allocate(r4_localData(count)) + allocate(r8_localData(count)) allocate(local_logical(count)) allocate(local_chars(count)) ! Allocate the solution arrays - Allocate(soln(count)) - Allocate(r8_soln(count)) - Allocate(r4_soln(count)) + allocate(i4_soln(count)) + allocate(i8_soln(count)) + allocate(r4_soln(count)) + allocate(r8_soln(count)) allocate(logical_soln(count)) allocate(char_soln(count)) !Assign values do i=1,count - localData(i) = localPet*100+i - r4_localData(i) = real( localData(i) , ESMF_KIND_R4 ) - r8_localData(i) = real( localData(i) , ESMF_KIND_R8 ) - if (mod(localData(i)+localPet,2).eq.0) then + i4_localData(i) = int(localPet*100+i, ESMF_KIND_I4) + i8_localData(i) = int(i4_localData(i), ESMF_KIND_I8) + r4_localData(i) = real(i4_localData(i), ESMF_KIND_R4 ) + r8_localData(i) = real(i4_localData(i), ESMF_KIND_R8 ) + if (mod(i4_localData(i)+localPet,2).eq.0) then local_logical(i)= ESMF_TRUE else local_logical(i)= ESMF_FALSE @@ -118,71 +124,114 @@ program ESMF_VMSendVMRecvUTest src = localPet - 1 if (src < 0) src = petCount - 1 - + dst = localPet + 1 if (dst > petCount -1) dst = 0 !The solution to test against is.. do i=1,count - soln(i) = src*100+i - r8_soln(i) = real(soln(i), ESMF_KIND_R8) - r4_soln(i) = real(r8_soln(i), ESMF_KIND_R4) - if ( mod(soln(i)+src,2) .eq. 0 ) then + i4_soln(i) = int(src*100+i, ESMF_KIND_I4) + i8_soln(i) = int(i4_soln(i), ESMF_KIND_I8) + r4_soln(i) = real(i4_soln(i), ESMF_KIND_R4) + r8_soln(i) = real(i4_soln(i), ESMF_KIND_R8) + if ( mod(i4_soln(i)+src,2) .eq. 0 ) then logical_soln(i)= ESMF_TRUE else logical_soln(i)= ESMF_FALSE endif write (char_soln(i), '(i2.2,i3)') src, i - end do + end do + + !Test with ESMF_KIND_I4 arguments + !================================ - - !Test with integer arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Send local data to dst + write(name, *) "Sending local data I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local data Test" - call ESMF_VMSend(vm, sendData=localData, count=count, dstPet=dst, rc=rc) + call ESMF_VMSend(vm, sendData=i4_localData, count=count, dstPet=dst, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - print *, localPet," Before recv LocalData is ", localData(1),localData(2) + write (msgStr,*) "Before recv LocalData is ", i4_localData(1),i4_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! dst receives local data from src + write(name, *) "Receiving local data I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local data Test" - call ESMF_VMRecv(vm, recvData=localData, count=count, srcPet=src, rc=rc) + call ESMF_VMRecv(vm, recvData=i4_localData, count=count, srcPet=src, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - isum=0 + I4Sum=0 + write(name, *) "Verify local data after receive I4 Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local data after receive Test" - print *,localPet, " After rcv LocalData is ", localData(1),localData(2) - isum=isum+ (localData(1) - soln(1)) + (localData(2) - soln(2)) - call ESMF_Test( (isum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + write (msgStr,*) "After rcv LocalData is ", i4_localData(1),i4_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + I4Sum=I4Sum+ (i4_localData(1) - i4_soln(1)) + (i4_localData(2) - i4_soln(2)) + call ESMF_Test( (I4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + + !Test with ESMF_KIND_I8 arguments + !================================ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + ! Send local data to dst + write(name, *) "Sending local data I8 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMSend(vm, sendData=i8_localData, count=count, dstPet=dst, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + + !------------------------------------------------------------------------ + write (msgStr,*) "Before recv LocalData is ", i8_localData(1),i8_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + ! dst receives local data from src + write(name, *) "Receiving local data I8 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=i8_localData, count=count, srcPet=src, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + ! Verify localData after VM Receive + I8Sum=0 + write(name, *) "Verify local data after receive I8 Test" + write(failMsg, *) "Wrong Local Data" + write (msgStr,*) "After rcv LocalData is ", i8_localData(1),i8_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + I8Sum=I8Sum+ (i8_localData(1) - i8_soln(1)) + (i8_localData(2) - i8_soln(2)) + call ESMF_Test( (I8Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + + !Test with ESMF_KIND_R4 arguments + !================================ - !Test with REAL_KIND_R4 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Send local data to dst + write(name, *) "Sending local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local data Test" call ESMF_VMSend(vm, sendData=r4_localData, count=count, dstPet=dst, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - print *, localPet,"Before recv: R4_LocalData is ", r4_localData(1),r4_localData(2) + write (msgStr,*) "Before recv: R4_LocalData is ", r4_localData(1),r4_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! dst receives local data from src + write(name, *) "Receiving local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local data Test" call ESMF_VMRecv(vm, recvData=r4_localData, count=count, srcPet=src, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -190,30 +239,35 @@ program ESMF_VMSendVMRecvUTest !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive R4Sum=0. + write(name, *) "Verify local data after receive R4 Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local data after receive Test" - print *,localPet, "After recv LocalData is ", localData(1),localData(2) + write (msgStr,*) "After recv LocalData is ", r4_localData(1),r4_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) R4Sum=(r4_localData(1) - r4_soln(1)) + & (r4_localData(2) - r4_soln(2)) call ESMF_Test( (R4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) - !Test with ESMF_KIND_R8 arguments - !================================ + !Test with ESMF_KIND_R8 arguments + !================================ + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Send local data to dst + write(name, *) "Sending local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local data Test" call ESMF_VMSend(vm, sendData=r8_localData, count=count, dstPet=dst, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - print *, localPet,"Before recv: R8_LocalData is ", r8_localData(1),r8_localData(2) + write (msgStr,*) "Before recv: R8_LocalData is ", r8_localData(1),r8_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! dst receives local data from src + write(name, *) "Receiving local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local data Test" call ESMF_VMRecv(vm, recvData=r8_localData, count=count, srcPet=src, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -221,153 +275,168 @@ program ESMF_VMSendVMRecvUTest !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive R8Sum=0. + write(name, *) "Verify local data after receive R8 Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local data after receive Test" - print *,localPet, "After recv LocalData is ", localData(1),localData(2) + write (msgStr,*) "After recv LocalData is ", r8_localData(1),r8_localData(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) R8Sum=(r8_localData(1) - r8_soln(1)) + & (r8_localData(2) - r8_soln(2)) call ESMF_Test( (R8Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) - !Test with logical arguments - !=========================== + !Test with logical arguments + !=========================== + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Send local data to dst + write(name, *) "Sending local data Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local data Test" call ESMF_VMSend(vm, sendData=local_logical, count=count, dstPet=dst, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ call ESMF_LogicalString(local_logical(1), strvalue, rc) - print *, localPet, "before recv: Local_Logical(1) is ", trim(strvalue) + write (msgStr,*) "before recv: Local_Logical(1) is ", trim(strvalue) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogicalString(local_logical(2), strvalue, rc) - print *, localPet, "before recv: Local_Logical(2) is ", trim(strvalue) + write (msgStr,*) "before recv: Local_Logical(2) is ", trim(strvalue) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! dst receives local data from src + write(name, *) "Receiving local data Logica Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local data Test" call ESMF_VMRecv(vm, recvData=local_logical, count=count, srcPet=src, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - ISum=0 + I4Sum=0 + write(name, *) "Verify local data after receive Logical Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local data after receive Test" call ESMF_LogicalString(local_logical(1), strvalue, rc) - print *, localPet, "After recv: Local_Logical(1) is ", trim(strvalue) + write (msgStr,*) "After recv: Local_Logical(1) is ", trim(strvalue) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogicalString(local_logical(2), strvalue, rc) - print *, localPet, "After recv: Local_Logical(2) is ", trim(strvalue) + write (msgStr,*) "After recv: Local_Logical(2) is ", trim(strvalue) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogicalString(logical_soln(1), strvalue, rc) - print *, localPet, "After recv: Logical_soln(1) is ", trim(strvalue) + write (msgStr,*) "After recv: Logical_soln(1) is ", trim(strvalue) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogicalString(logical_soln(2), strvalue, rc) - print *, localPet, "After recv: logical_soln(2) is ", trim(strvalue) + write (msgStr,*) "After recv: logical_soln(2) is ", trim(strvalue) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) do i=1,count - if (local_logical(i).ne. logical_soln(i)) ISum= ISum + 1 + if (local_logical(i).ne. logical_soln(i)) I4Sum= I4Sum + 1 end do - call ESMF_Test( (ISum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (I4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) -call ESMF_UtilIOUnitFlush (6) -call ESMF_VMBarrier (vm) + !Test with scalar character string arguments + !=========================================== - !Test with scalar character string arguments - !=========================================== !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Send local data to dst - write(failMsg, *) "Did not RETURN ESMF_SUCCESS" write(name, *) "Sending local character string data Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" lchars = local_chars(1) call ESMF_VMSend(vm, sendData=lchars, count=len(lchars), dstPet=dst, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) -call ESMF_UtilIOUnitFlush (6) -call ESMF_VMBarrier (vm) - !------------------------------------------------------------------------ - print *, localPet, "before recv: Local_chars is ", local_chars + write (msgStr,*) "before recv: Local_chars is ", local_chars + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! dst receives local data from src + write(name, *) "Receiving local character string data Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local data Test" call ESMF_VMRecv(vm, recvData=lchars, count=len(lchars), srcPet=src, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) -call ESMF_UtilIOUnitFlush (6) -call ESMF_VMBarrier (vm) - !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive + write(name, *) "Verify local character string data after receive Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local data after receive Test" call ESMF_Test (lchars == char_soln(1), & name, failMsg, result, ESMF_SRCLINE) -call ESMF_UtilIOUnitFlush (6) -call ESMF_VMBarrier (vm) + !Test with character string array arguments + !========================================== - !Test with character string array arguments - !========================================== !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Send local data to dst - write(failMsg, *) "Did not RETURN ESMF_SUCCESS" write(name, *) "Sending local character array data Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMSend(vm, sendData=local_chars, count=count*len(local_chars), & dstPet=dst, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - print *, localPet, "before recv: Local_chars(1) is ", local_chars(1) - print *, localPet, "before recv: Local_chars(2) is ", local_chars(2) + write (msgStr,*) "before recv: Local_chars(1) is ", local_chars(1) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + write (msgStr,*) "before recv: Local_chars(2) is ", local_chars(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ -call ESMF_UtilIOUnitFlush (6) -call ESMF_VMBarrier (vm) - !NEX_UTest_Multi_Proc_Only ! dst receives local data from src + write(name, *) "Receiving local character array data Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local data Test" call ESMF_VMRecv(vm, recvData=local_chars, count=count*len(local_chars), & srcPet=src, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) -call ESMF_UtilIOUnitFlush (6) -call ESMF_VMBarrier (vm) - !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - ISum=0 + I4Sum=0 + write(name, *) "Verify local character array data after receive Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local data after receive Test" - print *, localPet, "After recv: Local_chars(1) is ", local_chars(1) - print *, localPet, "After recv: Local_chars(2) is ", local_chars(2) - print *, localPet, "After recv: char_soln(1) is ", char_soln(1) - print *, localPet, "After recv: char_soln(2) is ", char_soln(2) + write (msgStr,*) "After recv: Local_chars(1) is ", local_chars(1) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + write (msgStr,*) "After recv: Local_chars(2) is ", local_chars(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + write (msgStr,*) "After recv: char_soln(1) is ", char_soln(1) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + write (msgStr,*) "After recv: char_soln(2) is ", char_soln(2) + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) do i=1,count - if (local_chars(i) /= char_soln(i)) ISum= ISum + 1 + if (local_chars(i) /= char_soln(i)) I4Sum= I4Sum + 1 end do - call ESMF_Test( (ISum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (I4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) - deallocate(localData) - deallocate(r8_localData) + deallocate(i4_localData) + deallocate(i8_localData) deallocate(r4_localData) + deallocate(r8_localData) deallocate(local_logical) deallocate(local_chars) - deallocate(soln) - deallocate(r8_soln) + deallocate(i4_soln) + deallocate(i8_soln) deallocate(r4_soln) + deallocate(r8_soln) deallocate(logical_soln) deallocate(char_soln) call ESMF_TestEnd(ESMF_SRCLINE) - end program ESMF_VMSendVMRecvUTest +end program ESMF_VMSendVMRecvUTest From 417e44618c5f8e0b5f017fffc5efe869f756d0be Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 1 Aug 2022 15:00:08 -0700 Subject: [PATCH 055/266] Better error handling for uni-proc blocking send/recv. --- src/Infrastructure/VM/include/ESMCI_VMKernel.h | 2 +- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index 4ac4c2020e..037e4b3d85 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -64,7 +64,7 @@ enum vmEpoch { epochNone=0, epochBuffer}; #define VM_ANY_TAG (-2) // MPI size limit -#define VM_MPI_SIZE_LIMIT (2147483647) +#define VM_MPI_SIZE_LIMIT (2147483647) // 2^31 (signed int) // define the communication preferences #define PREF_INTRA_PROCESS_SHMHACK (0) // default diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index e6e8fa6062..d52926fed3 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -4073,6 +4073,8 @@ int VMK::getDefaultTag(int src, int dst){ int VMK::send(const void *message, unsigned long long int size, int dest, int tag){ +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::VMK::send()" // p2p send #if (VERBOSITY > 9) printf("sending to: %d, %d\n", dest, lpid[dest]); @@ -4230,7 +4232,9 @@ int VMK::send(const void *message, unsigned long long int size, int dest, sync_buffer_flag_fill(&shmp->shms, 0); }else{ // buffer is insufficient - // todo: need to throw error + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, + "buffer insufficient!", ESMC_CONTEXT, &localrc); + return localrc; } break; default: @@ -4243,6 +4247,8 @@ int VMK::send(const void *message, unsigned long long int size, int dest, int VMK::send(const void *message, unsigned long long int size, int dest, commhandle **ch, int tag){ +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::VMK::send()" // p2p send non-blocking //fprintf(stderr, "VMK::send: ch=%p\n", *ch); #if (VERBOSITY > 9) @@ -4397,6 +4403,8 @@ int VMK::send(const void *message, unsigned long long int size, int dest, int VMK::recv(void *message, unsigned long long int size, int source, int tag, status *status){ +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::VMK::recv()" // p2p recv #if (VERBOSITY > 9) printf("receiving from: %d, %d\n", source, lpid[source]); @@ -4590,7 +4598,9 @@ int VMK::recv(void *message, unsigned long long int size, int source, int tag, sync_buffer_flag_empty(&shmp->shms, 0); }else{ // buffer is insufficient - // todo: need to throw error + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, + "buffer insufficient!", ESMC_CONTEXT, &localrc); + return localrc; } break; default: From 8b1ade7db15b0fdf2d6ecbbf4940bae970a4887f Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 1 Aug 2022 15:27:22 -0700 Subject: [PATCH 056/266] Fix blocking send/recv for large message > VM_MPI_SIZE_LIMIT, i.e. 2GiB. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index d52926fed3..d2930a04c9 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -4110,15 +4110,17 @@ int VMK::send(const void *message, unsigned long long int size, int dest, else{ // must send in multiple stages unsigned long long _size = size; + char *messageCC = (char *)messageC; i=0; while(_size > VM_MPI_SIZE_LIMIT){ - localrc = MPI_Send(messageC, VM_MPI_SIZE_LIMIT, MPI_BYTE, lpid[dest], + localrc = MPI_Send(messageCC, VM_MPI_SIZE_LIMIT, MPI_BYTE, lpid[dest], tag+i, mpi_c); i += 1; _size -= VM_MPI_SIZE_LIMIT; + messageCC += VM_MPI_SIZE_LIMIT; } if (_size > 0) - localrc = MPI_Send(messageC, _size, MPI_BYTE, lpid[dest], tag+i, + localrc = MPI_Send(messageCC, _size, MPI_BYTE, lpid[dest], tag+i, mpi_c); } #ifndef ESMF_NO_PTHREADS @@ -4458,15 +4460,17 @@ int VMK::recv(void *message, unsigned long long int size, int source, int tag, else{ // must receive in multiple stages unsigned long long _size = size; + char *messageCC = (char *)message; i=0; while(_size > VM_MPI_SIZE_LIMIT){ - localrc = MPI_Recv(message, VM_MPI_SIZE_LIMIT, MPI_BYTE, mpiSource, + localrc = MPI_Recv(messageCC, VM_MPI_SIZE_LIMIT, MPI_BYTE, mpiSource, tag+i, mpi_c, mpi_s); i += 1; _size -= VM_MPI_SIZE_LIMIT; + messageCC += VM_MPI_SIZE_LIMIT; } if (_size > 0) - localrc = MPI_Recv(message, _size, MPI_BYTE, mpiSource, tag+i, mpi_c, + localrc = MPI_Recv(messageCC, _size, MPI_BYTE, mpiSource, tag+i, mpi_c, mpi_s); } From 0f594dda9be816e6a59bf5cedf253c267c7ddee3 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 1 Aug 2022 15:29:33 -0700 Subject: [PATCH 057/266] =?UTF-8?q?Use=20explicit=20braces=20to=20avoid=20?= =?UTF-8?q?ambiguous=20=E2=80=98else=E2=80=99=20as=20per=20compiler=20warn?= =?UTF-8?q?ing.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index d2930a04c9..8431e2631d 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -3968,9 +3968,9 @@ void VMK::epochSetFirst(bool testAndClearBuffers){ sendMap[key].firstFlag = true; } its->second.firstFlag=true; - if(testAndClearBuffers) + if(testAndClearBuffers){ if (its->second.clear(true)) itErase = its; - else + }else itErase = sendMap.end(); } // handle case where the very last element needs to be erased From e3b41e6a980504926924f85d511f3f4c16e75380 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 1 Aug 2022 18:24:23 -0700 Subject: [PATCH 058/266] No affinity setting of threads under Cygwin. Replace deprecated PARCH_ macros with ESMF_OS_ macros. --- src/Infrastructure/Array/include/ESMCI_Array.h | 4 ++-- src/Infrastructure/Util/include/ESMF_LogErr.inc | 2 +- src/Infrastructure/VM/include/ESMCI_VMKernel.h | 4 ++-- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Infrastructure/Array/include/ESMCI_Array.h b/src/Infrastructure/Array/include/ESMCI_Array.h index 450f08e11e..3ea6fb62f0 100644 --- a/src/Infrastructure/Array/include/ESMCI_Array.h +++ b/src/Infrastructure/Array/include/ESMCI_Array.h @@ -273,7 +273,7 @@ namespace ESMCI { totalElementCountPLocalDe = NULL; sizeSuperUndist = NULL; sizeDist = NULL; -#if !defined (PARCH_IRIX64) +#if !defined (ESMF_OS_IRIX64) rimSeqIndexI4.resize(0); rimSeqIndexI8.resize(0); #endif @@ -311,7 +311,7 @@ namespace ESMCI { totalElementCountPLocalDe = NULL; sizeSuperUndist = NULL; sizeDist = NULL; -#if !defined (PARCH_IRIX64) +#if !defined (ESMF_OS_IRIX64) rimSeqIndexI4.resize(0); rimSeqIndexI8.resize(0); #endif diff --git a/src/Infrastructure/Util/include/ESMF_LogErr.inc b/src/Infrastructure/Util/include/ESMF_LogErr.inc index 7dce4fea7e..d9b199cc69 100644 --- a/src/Infrastructure/Util/include/ESMF_LogErr.inc +++ b/src/Infrastructure/Util/include/ESMF_LogErr.inc @@ -20,7 +20,7 @@ #include "ESMF_ErrReturnCodes.inc" #include "ESMF_LogConstants.inc" -#ifndef PARCH_IRIX64 +#ifndef ESMF_OS_IRIX64 #define ESMF_LogWrite() ESMF_LogWrite() diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index 1bfbb2ed62..e216292b27 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -257,7 +257,7 @@ class VMK{ struct Affinities{ esmf_pthread_t mypthid; #ifndef ESMF_NO_PTHREADS -#ifndef PARCH_darwin +#if !defined(ESMF_OS_Darwin) && !defined(ESMF_OS_Cygwin) cpu_set_t cpuset; #ifndef ESMF_NO_OPENMP int omp_num_threads; @@ -267,7 +267,7 @@ class VMK{ public: void reset(){ #ifndef ESMF_NO_PTHREADS -#ifndef PARCH_darwin +#if !defined(ESMF_OS_Darwin) && !defined(ESMF_OS_Cygwin) pthread_setaffinity_np(mypthid, sizeof(cpu_set_t), &cpuset); #ifndef ESMF_NO_OPENMP omp_set_num_threads(omp_num_threads); diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 516c6dc439..d9015659b2 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -356,7 +356,7 @@ void VMK::InitPreMPI(){ void VMK::set(bool globalResourceControl){ #ifndef ESMF_NO_GETHOSTID #ifndef ESMF_NO_PTHREADS -#ifndef PARCH_darwin +#if !defined(ESMF_OS_Darwin) && !defined(ESMF_OS_Cygwin) if (globalResourceControl){ // setting affinity on this level might interfer with user level pinning // therefore only do it by user request @@ -753,7 +753,7 @@ VMK::Affinities VMK::setAffinities(void *ssarg){ Affinities affs; affs.mypthid = mypthid; #ifndef ESMF_NO_PTHREADS -#ifndef PARCH_darwin +#if !defined(ESMF_OS_Darwin) && !defined(ESMF_OS_Cygwin) // get the current thread affinity pthread_getaffinity_np(mypthid, sizeof(cpu_set_t), &(affs.cpuset)); // set thread affinity @@ -2648,7 +2648,7 @@ void VMK::log(std::string prefix, ESMC_LogMsgType_Flag msgType)const{ ESMC_LogDefault.Write(msg.str(), msgType); msg.str(""); // clear #ifndef ESMF_NO_PTHREADS -#ifndef PARCH_darwin +#if !defined(ESMF_OS_Darwin) && !defined(ESMF_OS_Cygwin) // output thread affinity cpu_set_t cpuset; pthread_getaffinity_np(mypthid, sizeof(cpu_set_t), &cpuset); From 57b553107dd0bfb6abb7c5c7c1434fd3452cab61 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 1 Aug 2022 18:44:44 -0700 Subject: [PATCH 059/266] Rework blocking Send/Recv Unit test to support arbitrary size 'count'. Only test between two PETs for now. --- .../VM/tests/ESMF_VMSendVMRecvUTest.F90 | 501 ++++++++++-------- src/Infrastructure/VM/tests/makefile | 2 +- 2 files changed, 274 insertions(+), 229 deletions(-) diff --git a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 index 6fa78e0e2b..b19683ea6b 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 @@ -15,6 +15,7 @@ program ESMF_VMSendVMRecvUTest !------------------------------------------------------------------------------ #include "ESMF_Macros.inc" +#define DEBUG_LOG_OFF !============================================================================== !BOP @@ -44,28 +45,29 @@ program ESMF_VMSendVMRecvUTest ! individual test failure message character(ESMF_MAXSTR) :: failMsg character(ESMF_MAXSTR) :: name - character(ESMF_MAXSTR) :: msgStr character(len=8) :: strvalue + character(ESMF_MAXSTR) :: msgStr + ! local variables integer:: i, rc type(ESMF_VM):: vm integer:: localPet, petCount integer:: count, src, dst - integer(ESMF_KIND_I4), allocatable :: i4_localData(:),i4_soln(:) - integer(ESMF_KIND_I8), allocatable :: i8_localData(:),i8_soln(:) - real(ESMF_KIND_R4), allocatable :: r4_localData(:),r4_soln(:) - real(ESMF_KIND_R8), allocatable :: r8_localData(:),r8_soln(:) - type(ESMF_logical), allocatable:: local_logical(:),logical_soln(:) - - character(10), allocatable :: local_chars(:), char_soln(:) - character(10) :: lchars + integer(ESMF_KIND_I4), allocatable :: i4_data(:) + integer(ESMF_KIND_I8), allocatable :: i8_data(:) + real(ESMF_KIND_R4), allocatable :: r4_data(:) + real(ESMF_KIND_R8), allocatable :: r8_data(:) + type(ESMF_Logical), allocatable :: lg_data(:) + character(10) :: char_data, char_soln + character(10), allocatable :: ch_data(:) integer(ESMF_KIND_I4) :: I4Sum integer(ESMF_KIND_I8) :: I8Sum real(ESMF_KIND_R4) :: R4Sum real(ESMF_KIND_R8) :: R8Sum + integer :: LGSum, CHSum !------------------------------------------------------------------------------ ! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are @@ -75,52 +77,17 @@ program ESMF_VMSendVMRecvUTest ! added to allow a script to count the number and types of unit tests. !------------------------------------------------------------------------------ - call ESMF_TestStart(ESMF_SRCLINE, rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Get count of PETs and which PET number we are call ESMF_VMGetGlobal(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_VMGet(vm, localPet=localPet, petCount=petCount, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Allocate localData - count = 2 - -!------------------------------------------------------------------------------ -! IMPORTANT NOTE: -! The correct operation of this unit test depends on sufficient internal -! buffering within VMSend and VMRecv! There will be an implementation -! specific threshold for count above which this unit test will start to hang! -!------------------------------------------------------------------------------ - - allocate(i4_localData(count)) - allocate(i8_localData(count)) - allocate(r4_localData(count)) - allocate(r8_localData(count)) - allocate(local_logical(count)) - allocate(local_chars(count)) - - ! Allocate the solution arrays - allocate(i4_soln(count)) - allocate(i8_soln(count)) - allocate(r4_soln(count)) - allocate(r8_soln(count)) - allocate(logical_soln(count)) - allocate(char_soln(count)) - - !Assign values - do i=1,count - i4_localData(i) = int(localPet*100+i, ESMF_KIND_I4) - i8_localData(i) = int(i4_localData(i), ESMF_KIND_I8) - r4_localData(i) = real(i4_localData(i), ESMF_KIND_R4 ) - r8_localData(i) = real(i4_localData(i), ESMF_KIND_R8 ) - if (mod(i4_localData(i)+localPet,2).eq.0) then - local_logical(i)= ESMF_TRUE - else - local_logical(i)= ESMF_FALSE - endif - write (local_chars(i), '(i2.2,i3)') localPet, i - end do + count = 280000000 src = localPet - 1 if (src < 0) src = petCount - 1 @@ -128,314 +95,392 @@ program ESMF_VMSendVMRecvUTest dst = localPet + 1 if (dst > petCount -1) dst = 0 - !The solution to test against is.. - do i=1,count - i4_soln(i) = int(src*100+i, ESMF_KIND_I4) - i8_soln(i) = int(i4_soln(i), ESMF_KIND_I8) - r4_soln(i) = real(i4_soln(i), ESMF_KIND_R4) - r8_soln(i) = real(i4_soln(i), ESMF_KIND_R8) - if ( mod(i4_soln(i)+src,2) .eq. 0 ) then - logical_soln(i)= ESMF_TRUE - else - logical_soln(i)= ESMF_FALSE - endif - write (char_soln(i), '(i2.2,i3)') src, i - end do + write(msgStr, *) "src=",src," dst=",dst + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !Test with ESMF_KIND_I4 arguments !================================ + allocate(i4_data(count)) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! Send local data to dst - write(name, *) "Sending local data I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMSend(vm, sendData=i4_localData, count=count, dstPet=dst, rc=rc) + if (localPet==0) then + write(name, *) "Sending local data I4 Test" + do i=1, count + i4_data(i) = int(localPet*100+i, ESMF_KIND_I4) + enddo + call ESMF_VMSend(vm, sendData=i4_data, count=count, dstPet=dst, rc=rc) + else + write(name, *) "Receiving local data I4 Test" + call ESMF_VMRecv(vm, recvData=i4_data, count=count, srcPet=src, rc=rc) + I4Sum=0 + do i=1, count + I4Sum = I4Sum + (i4_data(i) - int(src*100+i, ESMF_KIND_I4)) + enddo + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - write (msgStr,*) "Before recv LocalData is ", i4_localData(1),i4_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! dst receives local data from src - write(name, *) "Receiving local data I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=i4_localData, count=count, srcPet=src, rc=rc) + if (localPet==0) then + write(name, *) "Receiving local data I4 Test" + call ESMF_VMRecv(vm, recvData=i4_data, count=count, srcPet=src, rc=rc) + I4Sum=0 + do i=1, count + I4Sum = I4Sum + (i4_data(i) - int(src*100+i, ESMF_KIND_I4)) + enddo + else + write(name, *) "Sending local data I4 Test" + do i=1, count + i4_data(i) = int(localPet*100+i, ESMF_KIND_I4) + enddo + call ESMF_VMSend(vm, sendData=i4_data, count=count, dstPet=dst, rc=rc) + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - I4Sum=0 write(name, *) "Verify local data after receive I4 Test" write(failMsg, *) "Wrong Local Data" - write (msgStr,*) "After rcv LocalData is ", i4_localData(1),i4_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - I4Sum=I4Sum+ (i4_localData(1) - i4_soln(1)) + (i4_localData(2) - i4_soln(2)) - call ESMF_Test( (I4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (I4Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(i4_data) !Test with ESMF_KIND_I8 arguments !================================ + allocate(i8_data(count)) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! Send local data to dst - write(name, *) "Sending local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMSend(vm, sendData=i8_localData, count=count, dstPet=dst, rc=rc) + if (localPet==0) then + write(name, *) "Sending local data I8 Test" + do i=1, count + i8_data(i) = int(localPet*100+i, ESMF_KIND_I8) + enddo + call ESMF_VMSend(vm, sendData=i8_data, count=count, dstPet=dst, rc=rc) + else + write(name, *) "Receiving local data I8 Test" + call ESMF_VMRecv(vm, recvData=i8_data, count=count, srcPet=src, rc=rc) + I8Sum=0 + do i=1, count + I8Sum = I8Sum + (i8_data(i) - int(src*100+i, ESMF_KIND_I8)) + enddo + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - write (msgStr,*) "Before recv LocalData is ", i8_localData(1),i8_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! dst receives local data from src - write(name, *) "Receiving local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=i8_localData, count=count, srcPet=src, rc=rc) + if (localPet==0) then + write(name, *) "Receiving local data I8 Test" + call ESMF_VMRecv(vm, recvData=i8_data, count=count, srcPet=src, rc=rc) + I8Sum=0 + do i=1, count + I8Sum = I8Sum + (i8_data(i) - int(src*100+i, ESMF_KIND_I8)) + enddo + else + write(name, *) "Sending local data I8 Test" + do i=1, count + i8_data(i) = int(localPet*100+i, ESMF_KIND_I8) + enddo + call ESMF_VMSend(vm, sendData=i8_data, count=count, dstPet=dst, rc=rc) + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - I8Sum=0 write(name, *) "Verify local data after receive I8 Test" write(failMsg, *) "Wrong Local Data" - write (msgStr,*) "After rcv LocalData is ", i8_localData(1),i8_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - I8Sum=I8Sum+ (i8_localData(1) - i8_soln(1)) + (i8_localData(2) - i8_soln(2)) - call ESMF_Test( (I8Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (I8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(i8_data) !Test with ESMF_KIND_R4 arguments !================================ + allocate(r4_data(count)) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! Send local data to dst - write(name, *) "Sending local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMSend(vm, sendData=r4_localData, count=count, dstPet=dst, rc=rc) + if (localPet==0) then + write(name, *) "Sending local data R4 Test" + do i=1, count + r4_data(i) = real(localPet*100+i, ESMF_KIND_R4) + enddo + call ESMF_VMSend(vm, sendData=r4_data, count=count, dstPet=dst, rc=rc) + else + write(name, *) "Receiving local data R4 Test" + call ESMF_VMRecv(vm, recvData=r4_data, count=count, srcPet=src, rc=rc) + R4Sum=0 + do i=1, count + R4Sum = R4Sum + (r4_data(i) - real(src*100+i, ESMF_KIND_R4)) + enddo + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - write (msgStr,*) "Before recv: R4_LocalData is ", r4_localData(1),r4_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! dst receives local data from src - write(name, *) "Receiving local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=r4_localData, count=count, srcPet=src, rc=rc) + if (localPet==0) then + write(name, *) "Receiving local data R4 Test" + call ESMF_VMRecv(vm, recvData=r4_data, count=count, srcPet=src, rc=rc) + R4Sum=0 + do i=1, count + R4Sum = R4Sum + (r4_data(i) - real(src*100+i, ESMF_KIND_R4)) + enddo + else + write(name, *) "Sending local data R4 Test" + do i=1, count + r4_data(i) = real(localPet*100+i, ESMF_KIND_R4) + enddo + call ESMF_VMSend(vm, sendData=r4_data, count=count, dstPet=dst, rc=rc) + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - R4Sum=0. write(name, *) "Verify local data after receive R4 Test" write(failMsg, *) "Wrong Local Data" - write (msgStr,*) "After recv LocalData is ", r4_localData(1),r4_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - R4Sum=(r4_localData(1) - r4_soln(1)) + & - (r4_localData(2) - r4_soln(2)) - call ESMF_Test( (R4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (R4Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(r4_data) !Test with ESMF_KIND_R8 arguments !================================ + allocate(r8_data(count)) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! Send local data to dst - write(name, *) "Sending local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMSend(vm, sendData=r8_localData, count=count, dstPet=dst, rc=rc) + if (localPet==0) then + write(name, *) "Sending local data R8 Test" + do i=1, count + r8_data(i) = real(localPet*100+i, ESMF_KIND_R8) + enddo + call ESMF_VMSend(vm, sendData=r8_data, count=count, dstPet=dst, rc=rc) + else + write(name, *) "Receiving local data R8 Test" + call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, rc=rc) + R8Sum=0 + do i=1, count + R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + enddo + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - write (msgStr,*) "Before recv: R8_LocalData is ", r8_localData(1),r8_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! dst receives local data from src - write(name, *) "Receiving local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=r8_localData, count=count, srcPet=src, rc=rc) + if (localPet==0) then + write(name, *) "Receiving local data R8 Test" + call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, rc=rc) + R8Sum=0 + do i=1, count + R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + enddo + else + write(name, *) "Sending local data R8 Test" + do i=1, count + r8_data(i) = real(localPet*100+i, ESMF_KIND_R8) + enddo + call ESMF_VMSend(vm, sendData=r8_data, count=count, dstPet=dst, rc=rc) + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - R8Sum=0. write(name, *) "Verify local data after receive R8 Test" write(failMsg, *) "Wrong Local Data" - write (msgStr,*) "After recv LocalData is ", r8_localData(1),r8_localData(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - R8Sum=(r8_localData(1) - r8_soln(1)) + & - (r8_localData(2) - r8_soln(2)) - call ESMF_Test( (R8Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with logical arguments - !=========================== + deallocate(r8_data) + + !Test with ESMF_Logical arguments + !================================ + allocate(lg_data(count)) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! Send local data to dst - write(name, *) "Sending local data Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMSend(vm, sendData=local_logical, count=count, dstPet=dst, rc=rc) + if (localPet==0) then + write(name, *) "Sending local data Logical Test" + do i=1, count + lg_data(i) = (mod(localPet*100+i,2) == 0) + enddo + call ESMF_VMSend(vm, sendData=lg_data, count=count, dstPet=dst, rc=rc) + else + write(name, *) "Receiving local data Logical Test" + call ESMF_VMRecv(vm, recvData=lg_data, count=count, srcPet=src, rc=rc) + LGSum=0 + do i=1, count + if ((lg_data(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & + LGSum = LGSum + 1 + enddo + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - call ESMF_LogicalString(local_logical(1), strvalue, rc) - write (msgStr,*) "before recv: Local_Logical(1) is ", trim(strvalue) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_LogicalString(local_logical(2), strvalue, rc) - write (msgStr,*) "before recv: Local_Logical(2) is ", trim(strvalue) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! dst receives local data from src - write(name, *) "Receiving local data Logica Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=local_logical, count=count, srcPet=src, rc=rc) + if (localPet==0) then + write(name, *) "Receiving local data Logical Test" + call ESMF_VMRecv(vm, recvData=lg_data, count=count, srcPet=src, rc=rc) + LGSum=0 + do i=1, count + if ((lg_data(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & + LGSum = LGSum + 1 + enddo + else + write(name, *) "Sending local data Logical Test" + do i=1, count + lg_data(i) = (mod(localPet*100+i,2) == 0) + enddo + call ESMF_VMSend(vm, sendData=lg_data, count=count, dstPet=dst, rc=rc) + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - I4Sum=0 write(name, *) "Verify local data after receive Logical Test" write(failMsg, *) "Wrong Local Data" - call ESMF_LogicalString(local_logical(1), strvalue, rc) - write (msgStr,*) "After recv: Local_Logical(1) is ", trim(strvalue) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_LogicalString(local_logical(2), strvalue, rc) - write (msgStr,*) "After recv: Local_Logical(2) is ", trim(strvalue) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_LogicalString(logical_soln(1), strvalue, rc) - write (msgStr,*) "After recv: Logical_soln(1) is ", trim(strvalue) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - call ESMF_LogicalString(logical_soln(2), strvalue, rc) - write (msgStr,*) "After recv: logical_soln(2) is ", trim(strvalue) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - do i=1,count - if (local_logical(i).ne. logical_soln(i)) I4Sum= I4Sum + 1 - end do - call ESMF_Test( (I4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (LGSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with scalar character string arguments - !=========================================== + deallocate(lg_data) + + !Test with character string arguments + !==================================== !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! Send local data to dst - write(name, *) "Sending local character string data Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - lchars = local_chars(1) - call ESMF_VMSend(vm, sendData=lchars, count=len(lchars), dstPet=dst, rc=rc) + if (localPet==0) then + write(name, *) "Sending local data Character String Test" + write (char_data, "(i2.2,i3)") localPet, 1 + call ESMF_VMSend(vm, sendData=char_data, count=len(char_data), & + dstPet=dst, rc=rc) + else + write(name, *) "Receiving local data Character String Test" + call ESMF_VMRecv(vm, recvData=char_data, count=len(char_data), & + srcPet=src, rc=rc) + CHSum=0 + write (char_soln, "(i2.2,i3)") src, 1 + if (char_data /= char_soln) CHSum = CHSum + 1 + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - write (msgStr,*) "before recv: Local_chars is ", local_chars - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! dst receives local data from src - write(name, *) "Receiving local character string data Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=lchars, count=len(lchars), srcPet=src, rc=rc) + if (localPet==0) then + write(name, *) "Receiving local data Character String Test" + call ESMF_VMRecv(vm, recvData=char_data, count=len(char_data), & + srcPet=src, rc=rc) + CHSum=0 + write (char_soln, "(i2.2,i3)") src, 1 + if (char_data /= char_soln) CHSum = CHSum + 1 + else + write(name, *) "Sending local data Character String Test" + write (char_data, "(i2.2,i3)") localPet, 1 + call ESMF_VMSend(vm, sendData=char_data, count=len(char_data), & + dstPet=dst, rc=rc) + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - write(name, *) "Verify local character string data after receive Test" + write(name, *) "Verify local data after receive Character String Test" write(failMsg, *) "Wrong Local Data" - call ESMF_Test (lchars == char_soln(1), & - name, failMsg, result, ESMF_SRCLINE) + call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !Test with character string array arguments !========================================== + count = 100 + allocate(ch_data(count)) !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! Send local data to dst - write(name, *) "Sending local character array data Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMSend(vm, sendData=local_chars, count=count*len(local_chars), & - dstPet=dst, rc=rc) + if (localPet==0) then + write(name, *) "Sending local data Character String array Test" + do i=1, count + write (ch_data(i), "(i2.2,i3)") localPet, i + enddo + call ESMF_VMSend(vm, sendData=ch_data, count=count*len(ch_data), & + dstPet=dst, rc=rc) + else + write(name, *) "Receiving local data Character String array Test" + call ESMF_VMRecv(vm, recvData=ch_data, count=count*len(ch_data), & + srcPet=src, rc=rc) + CHSum=0 + do i=1, count + write (char_soln, "(i2.2,i3)") src, i + if (ch_data(i) /= char_soln) CHSum = CHSum + 1 + enddo + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - - !------------------------------------------------------------------------ - write (msgStr,*) "before recv: Local_chars(1) is ", local_chars(1) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - write (msgStr,*) "before recv: Local_chars(2) is ", local_chars(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !------------------------------------------------------------------------ + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only - ! dst receives local data from src - write(name, *) "Receiving local character array data Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=local_chars, count=count*len(local_chars), & - srcPet=src, rc=rc) + if (localPet==0) then + write(name, *) "Receiving local data Character String array Test" + call ESMF_VMRecv(vm, recvData=ch_data, count=count*len(ch_data), & + srcPet=src, rc=rc) + CHSum=0 + do i=1, count + write (char_soln, "(i2.2,i3)") src, i + if (ch_data(i) /= char_soln) CHSum = CHSum + 1 + enddo + else + write(name, *) "Sending local data Character String array Test" + do i=1, count + write (ch_data(i), "(i2.2,i3)") localPet, i + enddo + call ESMF_VMSend(vm, sendData=ch_data, count=count*len(ch_data), & + dstPet=dst, rc=rc) + endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only ! Verify localData after VM Receive - I4Sum=0 - write(name, *) "Verify local character array data after receive Test" + write(name, *) "Verify local data after receive Character String array Test" write(failMsg, *) "Wrong Local Data" - write (msgStr,*) "After recv: Local_chars(1) is ", local_chars(1) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - write (msgStr,*) "After recv: Local_chars(2) is ", local_chars(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - write (msgStr,*) "After recv: char_soln(1) is ", char_soln(1) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - write (msgStr,*) "After recv: char_soln(2) is ", char_soln(2) - call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) - if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - do i=1,count - if (local_chars(i) /= char_soln(i)) I4Sum= I4Sum + 1 - end do - call ESMF_Test( (I4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) - - deallocate(i4_localData) - deallocate(i8_localData) - deallocate(r4_localData) - deallocate(r8_localData) - deallocate(local_logical) - deallocate(local_chars) - - deallocate(i4_soln) - deallocate(i8_soln) - deallocate(r4_soln) - deallocate(r8_soln) - deallocate(logical_soln) - deallocate(char_soln) + call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(ch_data) call ESMF_TestEnd(ESMF_SRCLINE) diff --git a/src/Infrastructure/VM/tests/makefile b/src/Infrastructure/VM/tests/makefile index 812282fd53..1cb4e00aee 100644 --- a/src/Infrastructure/VM/tests/makefile +++ b/src/Infrastructure/VM/tests/makefile @@ -127,7 +127,7 @@ RUN_ESMF_VMUserMpiInitUTestUNI: # VM Send VM Recv # RUN_ESMF_VMSendVMRecvUTest: - $(MAKE) TNAME=VMSendVMRecv NP=4 ftest + $(MAKE) TNAME=VMSendVMRecv NP=2 ftest # # VM SendNb VM RecvNb From 088794159d95a5326f7340783daa4a331dc91024 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 11:56:18 -0700 Subject: [PATCH 060/266] Clean-up. --- src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 index b19683ea6b..9711be3655 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 @@ -15,17 +15,15 @@ program ESMF_VMSendVMRecvUTest !------------------------------------------------------------------------------ #include "ESMF_Macros.inc" -#define DEBUG_LOG_OFF !============================================================================== !BOP -! !PROGRAM: ESMF_VMSendVMRecvUTest - Unit test for VM Send and Receive Functions +! !PROGRAM: ESMF_VMSendVMRecvUTest - Unit test for blocking VM Send and Receive +! Functions ! ! !DESCRIPTION: ! -! The code in this file drives the F90 VM Send Receive tests. The VM -! Send Receive function is complex enough to require a separate test file. -! It runs on multiple processors. +! The code in this file drives the F90 blocking VM Send Receive tests. ! !----------------------------------------------------------------------------- ! !USES: @@ -45,8 +43,6 @@ program ESMF_VMSendVMRecvUTest ! individual test failure message character(ESMF_MAXSTR) :: failMsg character(ESMF_MAXSTR) :: name - character(len=8) :: strvalue - character(ESMF_MAXSTR) :: msgStr ! local variables From ab10689e588d3a4396650f93dad06179ece83ef1 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 11:56:50 -0700 Subject: [PATCH 061/266] More complete use of VM_SIZELOG_on. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 8431e2631d..52b4535fe0 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -4276,7 +4276,7 @@ int VMK::send(const void *message, unsigned long long int size, int dest, if (tag == -1) tag = getDefaultTag(mypet,dest); if (epoch==epochBuffer){ sendBuffer *sm = &(sendMap[dest]); -#ifdef VM_EPOCHLOG_on +#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " non-blocking send to" << " dst=" << dest << @@ -4293,7 +4293,7 @@ int VMK::send(const void *message, unsigned long long int size, int dest, append(sm->stream, size); append(sm->stream, tag); sm->stream.write((const char*)message, size); -#ifdef VM_EPOCHLOG_on +#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) msg.str(""); // clear msg << "epochBuffer:" << __LINE__ << " non-blocking send write complete"<< ", current stream size=" << @@ -4378,6 +4378,13 @@ int VMK::send(const void *message, unsigned long long int size, int dest, // Shared memory hack for mpiuni // This shared memory implementation is naturally non-blocking. // Limited to SHARED_NONBLOCK_CHANNELS per src/dst pair +#ifdef VM_SIZELOG_on + { + std::stringstream msg; + msg << "VMK::send():" << __LINE__ << ", size=" << size; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + } +#endif (*ch)->type=-1; // indicate that this is a dummy commhandle shmp = sendChannel[dest].shmp; // shared memory mp channel sendCount = shmp->sendCount; @@ -4653,7 +4660,7 @@ int VMK::recv(void *message, unsigned long long int size, int source, else if (tag == VM_ANY_TAG) tag = MPI_ANY_TAG; if (epoch==epochBuffer){ recvBuffer *rm = &(recvMap[source]); -#ifdef VM_EPOCHLOG_on +#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " non-blocking recv" << " firstFlag=" << rm->firstFlag << @@ -4802,6 +4809,13 @@ int VMK::recv(void *message, unsigned long long int size, int source, // Shared memory hack for mpiuni // This shared memory implementation is naturally non-blocking. // Limited to SHARED_NONBLOCK_CHANNELS per src/dst pair +#ifdef VM_SIZELOG_on + { + std::stringstream msg; + msg << "VMK::recv():" << __LINE__ << ", size=" << size; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + } +#endif (*ch)->type=-1; // indicate that this is a dummy commhandle shmp = recvChannel[source].shmp; // shared memory mp channel recvCount = shmp->recvCount; From 0c12f6dffd62a95335b880b3bc37fff06188aef6 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 11:58:09 -0700 Subject: [PATCH 062/266] Rework test approach to be better suitable for general testing: Large messages and VMEpoch. --- .../VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 | 813 +++++++++++------- 1 file changed, 517 insertions(+), 296 deletions(-) diff --git a/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 index 91cfe7e236..cae7c4bc23 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 @@ -10,10 +10,10 @@ ! !============================================================================== ! - program ESMF_VMSendNbVMRecvNbUTest +program ESMF_VMSendNbVMRecvNbUTest !------------------------------------------------------------------------------ - + #include "ESMF_Macros.inc" !============================================================================== @@ -23,9 +23,7 @@ program ESMF_VMSendNbVMRecvNbUTest ! ! !DESCRIPTION: ! -! The code in this file drives the F90 non-blocking VM Send Receive tests. The -! VM Send Receive function is complex enough to require a separate test file. -! It runs on multiple processors. +! The code in this file drives the F90 non-blocking VM Send Receive tests. ! !----------------------------------------------------------------------------- ! !USES: @@ -45,35 +43,29 @@ program ESMF_VMSendNbVMRecvNbUTest ! individual test failure message character(ESMF_MAXSTR) :: failMsg character(ESMF_MAXSTR) :: name - character(len=8) :: strvalue - character(ESMF_MAXSTR) :: infostring + character(ESMF_MAXSTR) :: msgStr ! local variables integer:: i, rc type(ESMF_VM):: vm integer:: localPet, petCount integer:: count, src, dst - integer, allocatable:: localData(:),soln(:) - real(ESMF_KIND_R8), allocatable:: r8_localData(:),r8_soln(:) - real(ESMF_KIND_R4), allocatable:: r4_localData(:),r4_soln(:) - - type(ESMF_logical), allocatable:: local_logical(:),logical_soln(:) - - integer, allocatable:: i_recvData(:) - real(ESMF_KIND_R8), allocatable:: r8_recvData(:) - real(ESMF_KIND_R4), allocatable:: r4_recvData(:) - - type(ESMF_logical), allocatable:: recv_logical(:) - integer :: isum - real(ESMF_KIND_R8) :: R8Sum - real(ESMF_KIND_R4) :: R4Sum + integer(ESMF_KIND_I4), allocatable :: i4_data(:) + integer(ESMF_KIND_I8), allocatable :: i8_data(:) + real(ESMF_KIND_R4), allocatable :: r4_data(:) + real(ESMF_KIND_R8), allocatable :: r8_data(:) + type(ESMF_Logical), allocatable :: lg_data(:) + character(10) :: char_data, char_soln + character(10), allocatable :: ch_data(:) - type(ESMF_CommHandle):: commhandleI4s, commhandleR4s, commhandleR8s - type(ESMF_CommHandle):: commhandleLOGICALs + integer(ESMF_KIND_I4) :: I4Sum + integer(ESMF_KIND_I8) :: I8Sum + real(ESMF_KIND_R4) :: R4Sum + real(ESMF_KIND_R8) :: R8Sum + integer :: LGSum, CHSum - type(ESMF_CommHandle):: commhandleI4r, commhandleR4r, commhandleR8r - type(ESMF_CommHandle):: commhandleLOGICALr + type(ESMF_CommHandle):: commhandle !------------------------------------------------------------------------------ ! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are @@ -83,461 +75,690 @@ program ESMF_VMSendNbVMRecvNbUTest ! added to allow a script to count the number and types of unit tests. !------------------------------------------------------------------------------ - call ESMF_TestStart(ESMF_SRCLINE, rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Get count of PETs and which PET number we are call ESMF_VMGetGlobal(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_VMGet(vm, localPet=localPet, petCount=petCount, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Allocate localData - count = 2 +! count = 280000000 + count = 2800 -!------------------------------------------------------------------------------ -! IMPORTANT NOTE: -! The correct operation of this unit test depends on sufficient internal -! buffering within VMSend and VMRecv! There will be an implementation -! specific threshold for count above which this unit test will start to hang! -!------------------------------------------------------------------------------ + src = localPet - 1 + if (src < 0) src = petCount - 1 - allocate(localData(count)) - allocate(r8_localData(count)) - allocate(r4_localData(count)) - allocate(local_logical(count)) - - allocate(i_recvData(count)) - allocate(r8_recvData(count)) - allocate(r4_recvData(count)) - allocate(recv_logical(count)) - - ! Allocate the solution arrays - Allocate(soln(count)) - Allocate(r8_soln(count)) - Allocate(r4_soln(count)) - allocate(logical_soln(count)) - - !Assign values - do i=1,count - localData(i) = localPet*100+i - r4_localData(i) = real( localData(i), ESMF_KIND_R4 ) - r8_localData(i) = real( localData(i), ESMF_KIND_R8 ) - if (mod(localData(i)+localPet,2).eq.0) then - local_logical(i)= ESMF_TRUE - else - local_logical(i)= ESMF_FALSE - endif - end do + dst = localPet + 1 + if (dst > petCount -1) dst = 0 + + write(msgStr, *) "src=",src," dst=",dst + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) !=============================================================================== -! First round of tests use explicit commhandles and wait on each recv call -! individually. +! First round of tests use explicit commhandles and wait on each recv call. !=============================================================================== - ! Set src and dst for the first round - src = localPet - 1 - do while (src < 0) - src = src + petCount - enddo - dst = localPet + 1 - do while (dst > petCount - 1) - dst = dst - petCount + !Test with ESMF_KIND_I4 arguments + !================================ + allocate(i4_data(count)) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Sending local data I4 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + do i=1, count + i4_data(i) = int(localPet*100+i, ESMF_KIND_I4) enddo - - write(infostring, *) "First round: src=",src," dst=",dst - call ESMF_LogWrite(infostring, ESMF_LOGMSG_INFO) + call ESMF_VMSend(vm, sendData=i4_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !The solution to test against is.. - do i=1,count - soln(i) = src*100+i - r8_soln(i) = real(soln(i), ESMF_KIND_R8) - r4_soln(i) = real(r8_soln(i), ESMF_KIND_R4) - if ( mod(soln(i)+src,2) .eq. 0 ) then - logical_soln(i)= ESMF_TRUE - else - logical_soln(i)= ESMF_FALSE - endif - end do + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Receiving local data I4 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=i4_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with integer arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "Waiting for received local data I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local I4 data Test" - call ESMF_VMSend(vm, sendData=localData, count=count, dstPet=dst, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleI4s, rc=rc) + call ESMF_VMCommWait(vm, commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ - print *, localPet," Before recv LocalData is ", i_recvData(1),i_recvData(2) + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive I4 Test" + write(failMsg, *) "Wrong Local Data" + I4Sum=0 + do i=1, count + I4Sum = I4Sum + (i4_data(i) - int(src*100+i, ESMF_KIND_I4)) + enddo + call ESMF_Test( (I4Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(i4_data) + + !Test with ESMF_KIND_I8 arguments + !================================ + allocate(i8_data(count)) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Sending local data I8 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + do i=1, count + i8_data(i) = int(localPet*100+i, ESMF_KIND_I8) + enddo + call ESMF_VMSend(vm, sendData=i8_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Receiving local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local I4 data Test" - call ESMF_VMRecv(vm, recvData=i_recvData, count=count, srcPet=src, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleI4r, rc=rc) + call ESMF_VMRecv(vm, recvData=i8_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with REAL_KIND_R4 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "Waiting for received local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local R4 data Test" - call ESMF_VMSend(vm, sendData=r4_localData, count=count, dstPet=dst, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleR4s, rc=rc) + call ESMF_VMCommWait(vm, commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ - print *, localPet,"Before recv: R4_LocalData is ", r4_recvData(1),r4_recvData(2) + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive I8 Test" + write(failMsg, *) "Wrong Local Data" + I8Sum=0 + do i=1, count + I8Sum = I8Sum + (i8_data(i) - int(src*100+i, ESMF_KIND_I8)) + enddo + call ESMF_Test( (I8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(i8_data) + + !Test with ESMF_KIND_R4 arguments + !================================ + allocate(r4_data(count)) + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Sending local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local R4 data Test" - call ESMF_VMRecv(vm, recvData=r4_recvData, count=count, srcPet=src, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleR4r, rc=rc) + do i=1, count + r4_data(i) = real(localPet*100+i, ESMF_KIND_R4) + enddo + call ESMF_VMSend(vm, sendData=r4_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with ESMF_KIND_R8 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "Receiving local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local R8 data Test" - call ESMF_VMSend(vm, sendData=r8_localData, count=count, dstPet=dst, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleR8s, rc=rc) + call ESMF_VMRecv(vm, recvData=r4_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !NEX_UTest + write(name, *) "Waiting for received local data R4 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMCommWait(vm, commhandle, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive R4 Test" + write(failMsg, *) "Wrong Local Data" + R4Sum=0 + do i=1, count + R4Sum = R4Sum + (r4_data(i) - real(src*100+i, ESMF_KIND_R4)) + enddo + call ESMF_Test( (R4Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(r4_data) + + !Test with ESMF_KIND_R8 arguments + !================================ + allocate(r8_data(count)) !------------------------------------------------------------------------ - print *, localPet,"Before recv: R8_LocalData is ", r8_recvData(1),r8_recvData(2) + !NEX_UTest + write(name, *) "Sending local data R8 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + do i=1, count + r8_data(i) = real(localPet*100+i, ESMF_KIND_R8) + enddo + call ESMF_VMSend(vm, sendData=r8_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Receiving local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local R8 data Test" - call ESMF_VMRecv(vm, recvData=r8_recvData, count=count, srcPet=src, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleR8r, rc=rc) + call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with logical arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "Waiting for received local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local LOGICAL data Test" - call ESMF_VMSend(vm, sendData=local_logical, count=count, dstPet=dst, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleLOGICALs, rc=rc) + call ESMF_VMCommWait(vm, commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ - call ESMF_LogicalString(recv_logical(1), strvalue, rc) - print *, localPet, "before recv: recv_logical(1) is ", trim(strvalue) - call ESMF_LogicalString(recv_logical(2), strvalue, rc) - print *, localPet, "before recv: recv_logical(2) is ", trim(strvalue) + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive R8 Test" + write(failMsg, *) "Wrong Local Data" + R8Sum=0 + do i=1, count + R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + enddo + call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(r8_data) + + !Test with ESMF_Logical arguments + !================================ + allocate(lg_data(count)) + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Sending local data Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local LOGICAL data Test" - call ESMF_VMRecv(vm, recvData=recv_logical, count=count, srcPet=src, & - syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandleLOGICALr, rc=rc) + do i=1, count + lg_data(i) = (mod(localPet*100+i,2) == 0) + enddo + call ESMF_VMSend(vm, sendData=lg_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Receiving local data Logical Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=lg_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with integer arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest - ! Wait on integer recv + write(name, *) "Waiting for received local data Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Waiting for I4 RecvNb" - call ESMF_VMCommWait(vm, commhandleI4r, rc=rc) + call ESMF_VMCommWait(vm, commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest ! Verify localData after VM Receive - isum=0 + write(name, *) "Verify local data after receive Logical Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local I4 data after receive Test" - print *,localPet, " After rcv LocalData is ", i_recvData(1),i_recvData(2) - isum=isum+ (i_recvData(1) - soln(1)) + (i_recvData(2) - soln(2)) - call ESMF_Test( (isum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + LGSum=0 + do i=1, count + if ((lg_data(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & + LGSum = LGSum + 1 + enddo + call ESMF_Test( (LGSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(lg_data) + + !Test with character string arguments + !==================================== - !Test with REAL_KIND_R4 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest - ! Wait on R4 recv + write(name, *) "Sending local data Character String Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Waiting for R4 RecvNb" - call ESMF_VMCommWait(vm, commhandleR4r, rc=rc) + write (char_data, "(i2.2,i3)") localPet, 1 + call ESMF_VMSend(vm, sendData=char_data, count=len(char_data), & + dstPet=dst, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest - ! Verify localData after VM Receive - R4Sum=0. - write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local R4 data after receive Test" - print *,localPet, "After recv LocalData is ", r4_recvData(1),r4_recvData(2) - R4Sum=(r4_recvData(1) - r4_soln(1)) + & - (r4_recvData(2) - r4_soln(2)) - call ESMF_Test( (R4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + write(name, *) "Receiving local data Character String Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=char_data, count=len(char_data), & + srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, & + rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with ESMF_KIND_R8 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest - ! Wait on R8 recv + write(name, *) "Waiting for received local data Character String Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Waiting for R8 RecvNb" - call ESMF_VMCommWait(vm, commhandleR8r, rc=rc) + call ESMF_VMCommWait(vm, commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest ! Verify localData after VM Receive - R8Sum=0. + write(name, *) "Verify local data after receive Character String Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local R8 data after receive Test" - print *,localPet, "After recv LocalData is ", r8_recvData(1),r8_recvData(2) - R8Sum=(r8_recvData(1) - r8_soln(1)) + & - (r8_recvData(2) - r8_soln(2)) - call ESMF_Test( (R8Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + CHSum=0 + write (char_soln, "(i2.2,i3)") src, 1 + if (char_data /= char_soln) CHSum = CHSum + 1 + call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !Test with character string array arguments + !========================================== + count = 100 + allocate(ch_data(count)) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Sending local data Character String array Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + do i=1, count + write (ch_data(i), "(i2.2,i3)") localPet, i + enddo + call ESMF_VMSend(vm, sendData=ch_data, count=count*len(ch_data), & + dstPet=dst, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Receiving local data Character String array Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=ch_data, count=count*len(ch_data), & + srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, & + rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with logical arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest - ! Wait on LOGICAL recv + write(name, *) "Waiting for received local data Character String array Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Waiting for LOGICAL RecvNb" - call ESMF_VMCommWait(vm, commhandleLOGICALr, rc=rc) + call ESMF_VMCommWait(vm, commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest ! Verify localData after VM Receive - ISum=0. + write(name, *) "Verify local data after receive Character String array Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local LOGICAL data after receive Test" - call ESMF_LogicalString(recv_logical(1), strvalue, rc) - print *, localPet, "After recv: recv_logical(1) is ", trim(strvalue) - call ESMF_LogicalString(recv_logical(2), strvalue, rc) - print *, localPet, "After recv: recv_logical(2) is ", trim(strvalue) - call ESMF_LogicalString(logical_soln(1), strvalue, rc) - print *, localPet, "After recv: Logical_soln(1) is ", trim(strvalue) - call ESMF_LogicalString(logical_soln(2), strvalue, rc) - print *, localPet, "After recv: logical_soln(2) is ", trim(strvalue) - do i=1,count - if (recv_logical(i).ne. logical_soln(i)) ISum= ISum + 1 - end do - call ESMF_Test( (ISum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + CHSum=0 + do i=1, count + write (char_soln, "(i2.2,i3)") src, i + if (ch_data(i) /= char_soln) CHSum = CHSum + 1 + enddo + call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + deallocate(ch_data) !=============================================================================== -! Second round of tests don't use commhandles but rely on ESMF's internal -! request queue. After all of the non-blocking calls are queued and before -! testing the received values a call to ESMF_VMCommWaitAll() waits on _all_ -! outstanding non-blocking communication calls for the current VM. +! Second round of tests use ESMF's internal request queue to wait on outstanding +! comms. !=============================================================================== - ! Set src and dst for the second round - src = localPet - 2 - do while (src < 0) - src = src + petCount + !Test with ESMF_KIND_I4 arguments + !================================ + allocate(i4_data(count)) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Sending local data I4 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + do i=1, count + i4_data(i) = int(localPet*100+i, ESMF_KIND_I4) enddo - dst = localPet + 2 - do while (dst > petCount - 1) - dst = dst - petCount + call ESMF_VMSend(vm, sendData=i4_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Receiving local data I4 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=i4_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "waiting for all outstanding comms for I4 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMCommWaitAll(vm, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive I4 Test" + write(failMsg, *) "Wrong Local Data" + I4Sum=0 + do i=1, count + I4Sum = I4Sum + (i4_data(i) - int(src*100+i, ESMF_KIND_I4)) enddo + call ESMF_Test( (I4Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - write(infostring, *) "Second round: src=",src," dst=",dst - call ESMF_LogWrite(infostring, ESMF_LOGMSG_INFO) + deallocate(i4_data) - !The solution to test against is.. - do i=1,count - soln(i) = src*100+i - r8_soln(i) = real(soln(i), ESMF_KIND_R8) - r4_soln(i) = real(r8_soln(i), ESMF_KIND_R4) - if ( mod(soln(i)+src,2) .eq. 0 ) then - logical_soln(i)= ESMF_TRUE - else - logical_soln(i)= ESMF_FALSE - endif - end do + !Test with ESMF_KIND_I8 arguments + !================================ + allocate(i8_data(count)) - !Test with integer arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "Sending local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local I4 data Test" - call ESMF_VMSend(vm, sendData=localData, count=count, dstPet=dst, & + do i=1, count + i8_data(i) = int(localPet*100+i, ESMF_KIND_I8) + enddo + call ESMF_VMSend(vm, sendData=i8_data, count=count, dstPet=dst, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) - !------------------------------------------------------------------------ - print *, localPet," Before recv i_recvData is ", i_recvData(1),i_recvData(2) + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Receiving local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local I4 data Test" - call ESMF_VMRecv(vm, recvData=i_recvData, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=i8_data, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with REAL_KIND_R4 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "waiting for all outstanding comms for I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local R4 data Test" - call ESMF_VMSend(vm, sendData=r4_localData, count=count, dstPet=dst, & - syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ - print *, localPet,"Before recv: r4_recvData is ", r4_recvData(1),r4_recvData(2) + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive I8 Test" + write(failMsg, *) "Wrong Local Data" + I8Sum=0 + do i=1, count + I8Sum = I8Sum + (i8_data(i) - int(src*100+i, ESMF_KIND_I8)) + enddo + call ESMF_Test( (I8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(i8_data) + + !Test with ESMF_KIND_R4 arguments + !================================ + allocate(r4_data(count)) + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Sending local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local R4 data Test" - call ESMF_VMRecv(vm, recvData=r4_recvData, count=count, srcPet=src, & + do i=1, count + r4_data(i) = real(localPet*100+i, ESMF_KIND_R4) + enddo + call ESMF_VMSend(vm, sendData=r4_data, count=count, dstPet=dst, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with ESMF_KIND_R8 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "Receiving local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local R8 data Test" - call ESMF_VMSend(vm, sendData=r8_localData, count=count, dstPet=dst, & + call ESMF_VMRecv(vm, recvData=r4_data, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !NEX_UTest + write(name, *) "waiting for all outstanding comms for R4 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMCommWaitAll(vm, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ - print *, localPet,"Before recv: r8_recvData is ", r8_recvData(1),r8_recvData(2) + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive R4 Test" + write(failMsg, *) "Wrong Local Data" + R4Sum=0 + do i=1, count + R4Sum = R4Sum + (r4_data(i) - real(src*100+i, ESMF_KIND_R4)) + enddo + call ESMF_Test( (R4Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(r4_data) + + !Test with ESMF_KIND_R8 arguments + !================================ + allocate(r8_data(count)) + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Sending local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local R8 data Test" - call ESMF_VMRecv(vm, recvData=r8_recvData, count=count, srcPet=src, & + do i=1, count + r8_data(i) = real(localPet*100+i, ESMF_KIND_R8) + enddo + call ESMF_VMSend(vm, sendData=r8_data, count=count, dstPet=dst, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with logical arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest - ! Send local data to dst + write(name, *) "Receiving local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Sending local LOGICAL data Test" - call ESMF_VMSend(vm, sendData=local_logical, count=count, dstPet=dst, & + call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "waiting for all outstanding comms for R8 Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMCommWaitAll(vm, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ - call ESMF_LogicalString(recv_logical(1), strvalue, rc) - print *, localPet, "before recv: recv_logical(1) is ", trim(strvalue) - call ESMF_LogicalString(recv_logical(2), strvalue, rc) - print *, localPet, "before recv: recv_logical(2) is ", trim(strvalue) + !NEX_UTest + ! Verify localData after VM Receive + write(name, *) "Verify local data after receive R8 Test" + write(failMsg, *) "Wrong Local Data" + R8Sum=0 + do i=1, count + R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + enddo + call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(r8_data) + + !Test with ESMF_Logical arguments + !================================ + allocate(lg_data(count)) + !------------------------------------------------------------------------ !NEX_UTest - ! dst receives local data from src + write(name, *) "Sending local data Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Receiving local LOGICAL data Test" - call ESMF_VMRecv(vm, recvData=recv_logical, count=count, srcPet=src, & + do i=1, count + lg_data(i) = (mod(localPet*100+i,2) == 0) + enddo + call ESMF_VMSend(vm, sendData=lg_data, count=count, dstPet=dst, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Receiving local data Logical Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=lg_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test the VMCommWaitAll function to wait on all outstanding nb comms for VM - !=========================== !------------------------------------------------------------------------ !NEX_UTest - ! Wait on integer sendrecv + write(name, *) "waiting for all outstanding comms for Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - write(name, *) "Waiting for all queued non-blocking comms in VM" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - - !Test with integer arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest ! Verify localData after VM Receive - isum=0 + write(name, *) "Verify local data after receive Logical Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local I4 data after receive Test" - print *,localPet, " After rcv LocalData is ", i_recvData(1),i_recvData(2) - isum=isum+ (i_recvData(1) - soln(1)) + (i_recvData(2) - soln(2)) - call ESMF_Test( (isum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + LGSum=0 + do i=1, count + if ((lg_data(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & + LGSum = LGSum + 1 + enddo + call ESMF_Test( (LGSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + deallocate(lg_data) + + !Test with character string arguments + !==================================== - !Test with REAL_KIND_R4 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest - ! Verify localData after VM Receive - R4Sum=0. - write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local R4 data after receive Test" - print *,localPet, "After recv LocalData is ", r4_recvData(1),r4_recvData(2) - R4Sum=(r4_recvData(1) - r4_soln(1)) + & - (r4_recvData(2) - r4_soln(2)) - call ESMF_Test( (R4Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + write(name, *) "Sending local data Character String Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + write (char_data, "(i2.2,i3)") localPet, 1 + call ESMF_VMSend(vm, sendData=char_data, count=len(char_data), & + dstPet=dst, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Receiving local data Character String Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=char_data, count=len(char_data), & + srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "waiting for all outstanding comms for Character String Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMCommWaitAll(vm, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with ESMF_KIND_R8 arguments - !================================ !------------------------------------------------------------------------ !NEX_UTest ! Verify localData after VM Receive - R8Sum=0. + write(name, *) "Verify local data after receive Character String Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local R8 data after receive Test" - print *,localPet, "After recv LocalData is ", r8_recvData(1),r8_recvData(2) - R8Sum=(r8_recvData(1) - r8_soln(1)) + & - (r8_recvData(2) - r8_soln(2)) - call ESMF_Test( (R8Sum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + CHSum=0 + write (char_soln, "(i2.2,i3)") src, 1 + if (char_data /= char_soln) CHSum = CHSum + 1 + call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !Test with character string array arguments + !========================================== + count = 100 + allocate(ch_data(count)) + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Sending local data Character String array Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + do i=1, count + write (ch_data(i), "(i2.2,i3)") localPet, i + enddo + call ESMF_VMSend(vm, sendData=ch_data, count=count*len(ch_data), & + dstPet=dst, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "Receiving local data Character String array Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMRecv(vm, recvData=ch_data, count=count*len(ch_data), & + srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest + write(name, *) "waiting for all outstanding comms for Character String array Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMCommWaitAll(vm, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ - !Test with logical arguments - !=========================== !------------------------------------------------------------------------ !NEX_UTest ! Verify localData after VM Receive - ISum=0. + write(name, *) "Verify local data after receive Character String array Test" write(failMsg, *) "Wrong Local Data" - write(name, *) "Verify local LOGICAL data after receive Test" - call ESMF_LogicalString(recv_logical(1), strvalue, rc) - print *, localPet, "After recv: recv_logical(1) is ", trim(strvalue) - call ESMF_LogicalString(recv_logical(2), strvalue, rc) - print *, localPet, "After recv: recv_logical(2) is ", trim(strvalue) - call ESMF_LogicalString(logical_soln(1), strvalue, rc) - print *, localPet, "After recv: Logical_soln(1) is ", trim(strvalue) - call ESMF_LogicalString(logical_soln(2), strvalue, rc) - print *, localPet, "After recv: logical_soln(2) is ", trim(strvalue) - do i=1,count - if (recv_logical(i).ne. logical_soln(i)) ISum= ISum + 1 - end do - call ESMF_Test( (ISum .eq. 0), name, failMsg, result, ESMF_SRCLINE) + CHSum=0 + do i=1, count + write (char_soln, "(i2.2,i3)") src, i + if (ch_data(i) /= char_soln) CHSum = CHSum + 1 + enddo + call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + deallocate(ch_data) call ESMF_TestEnd(ESMF_SRCLINE) - end program ESMF_VMSendNbVMRecvNbUTest +end program ESMF_VMSendNbVMRecvNbUTest From 8206469ffd94ebaa3180702cb668818fc071b7ec Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 12:06:34 -0700 Subject: [PATCH 063/266] Fix a typo. --- src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 b/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 index cd69c64227..8a739926cf 100644 --- a/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 +++ b/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 @@ -126,7 +126,7 @@ program ESMF_VMNonBlockingEx ! started, let along completed. For this reason it is unsafe to overwrite ! the data in the {\tt localData} array on {\tt src} PET, or to access ! the {\tt localData} array on {\tt dst} PET. However both PETs are free -! to engage in other work while the data transfer my proceed concurrently. +! to engage in other work while the data transfer may proceed concurrently. !EOE !BOC From c03680d4356672cc31e7eeeade8afbb6415e5568 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 12:15:05 -0700 Subject: [PATCH 064/266] Fix text. --- .../VM/examples/ESMF_VMNonBlockingEx.F90 | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 b/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 index 8a739926cf..07b5db0c3c 100644 --- a/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 +++ b/src/Infrastructure/VM/examples/ESMF_VMNonBlockingEx.F90 @@ -277,20 +277,19 @@ program ESMF_VMNonBlockingEx !BOE ! For cases where multiple messages are being sent between the same -! {\tt src}-{\tt dst} -! pairs using non-blocking communications, performance can often -! be improved by aggregating individual messages. An extra buffer -! is needed to hold the collected messages, resulting in only a single data +! {\tt src}-{\tt dst} pairs using non-blocking communications, performance +! can often be improved by aggregating individual messages. An extra buffer +! is needed to hold the collected messages. The result is a single data ! transfer for each PET pair. In many cases this can significantly reduce the ! time spent in communications. The ESMF VM class provides access to such a -! buffer technique through the {\tt ESMF\_VMEpoch} API. +! buffering technique through the {\tt ESMF\_VMEpoch} API. ! ! The {\tt ESMF\_VMEpoch} API consists of two interfaces: ! {\tt ESMF\_VMEpochEnter()} and {\tt ESMF\_VMEpochExit()}. When entering an ! epoch, the user specifies the type of epoch that is to be entered. Currently ! only {\tt ESMF\_VMEPOCH\_BUFFER} is available. Inside this epoch, ! non-blocking communication calls are aggregated and data transfers on the -! {\tt src} side are not issued until the epoch is exited. On the {\tt dst side} +! {\tt src} side are not issued until the epoch is exited. On the {\tt dst} side ! a single data transfer is received, and then divided over the actual ! non-blocking receive calls. ! From 0a794a226cadbbce041f456a2ba5fc579ce6df93 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 16:27:09 -0700 Subject: [PATCH 065/266] Implement large message (>2GiB) support for standard non-blocking path (not for VMEpoch yet), via message chunking. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 74 +++++++++++++++------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 52b4535fe0..152f984c75 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -4105,7 +4105,7 @@ int VMK::send(const void *message, unsigned long long int size, int dest, ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif - if (size < VM_MPI_SIZE_LIMIT) + if (size <= VM_MPI_SIZE_LIMIT) localrc = MPI_Send(messageC, size, MPI_BYTE, lpid[dest], tag, mpi_c); else{ // must send in multiple stages @@ -4115,7 +4115,7 @@ int VMK::send(const void *message, unsigned long long int size, int dest, while(_size > VM_MPI_SIZE_LIMIT){ localrc = MPI_Send(messageCC, VM_MPI_SIZE_LIMIT, MPI_BYTE, lpid[dest], tag+i, mpi_c); - i += 1; + i++; _size -= VM_MPI_SIZE_LIMIT; messageCC += VM_MPI_SIZE_LIMIT; } @@ -4261,9 +4261,6 @@ int VMK::send(const void *message, unsigned long long int size, int dest, pipc_mp *pipcmp; int scpsize; char *pdest; - char *psrc; - int i; - char *mess; int sendCount; // check if this needs a new entry in the request queue if (*ch==NULL){ @@ -4305,10 +4302,12 @@ int VMK::send(const void *message, unsigned long long int size, int dest, ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif }else{ - (*ch)->nelements=1; + int nelements = size/VM_MPI_SIZE_LIMIT; + if (size%VM_MPI_SIZE_LIMIT) nelements++; + (*ch)->nelements=nelements; (*ch)->type=1; // MPI (*ch)->sendFlag=true; // send request - (*ch)->mpireq = new MPI_Request[1]; + (*ch)->mpireq = new MPI_Request[nelements]; // MPI-1 implementation void *messageC; // for MPI C interface convert (const void *) -> (void *) memcpy(&messageC, &message, sizeof(void *)); @@ -4316,19 +4315,35 @@ int VMK::send(const void *message, unsigned long long int size, int dest, #ifndef ESMF_NO_PTHREADS if (mpi_mutex_flag) pthread_mutex_lock(pth_mutex); #endif -//fprintf(stderr, "MPI_Isend: ch=%p\n", (*ch)->mpireq); #ifdef VM_MEMLOG_on VM::logMemInfo(std::string("VM::send():1.0")); #endif #ifdef VM_SIZELOG_on { std::stringstream msg; - msg << "VMK::send():" << __LINE__ << ", size=" << size; + msg << "VMK::send():" << __LINE__ << ", size=" << size + << " in " << nelements << " chunks"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif - localrc = MPI_Isend(messageC, size, MPI_BYTE, lpid[dest], tag, mpi_c, - (*ch)->mpireq); + if (size <= VM_MPI_SIZE_LIMIT) + localrc = MPI_Isend(messageC, size, MPI_BYTE, lpid[dest], tag, mpi_c, + (*ch)->mpireq); + else{ + unsigned long long _size = size; + char *messageCC = (char *)messageC; + int i=0; + while(_size > VM_MPI_SIZE_LIMIT){ + localrc = MPI_Isend(messageCC, VM_MPI_SIZE_LIMIT, MPI_BYTE, + lpid[dest], tag+i, mpi_c, &((*ch)->mpireq[i])); + i++; + _size -= VM_MPI_SIZE_LIMIT; + messageCC += VM_MPI_SIZE_LIMIT; + } + if (_size > 0) + localrc = MPI_Isend(messageCC, _size, MPI_BYTE, + lpid[dest], tag+i, mpi_c, &((*ch)->mpireq[i])); + } #ifdef VM_MEMLOG_on VM::logMemInfo(std::string("VM::send():2.0")); #endif @@ -4462,7 +4477,7 @@ int VMK::recv(void *message, unsigned long long int size, int source, int tag, ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif - if (size < VM_MPI_SIZE_LIMIT) + if (size <= VM_MPI_SIZE_LIMIT) localrc = MPI_Recv(message, size, MPI_BYTE, mpiSource, tag, mpi_c, mpi_s); else{ // must receive in multiple stages @@ -4472,7 +4487,7 @@ int VMK::recv(void *message, unsigned long long int size, int source, int tag, while(_size > VM_MPI_SIZE_LIMIT){ localrc = MPI_Recv(messageCC, VM_MPI_SIZE_LIMIT, MPI_BYTE, mpiSource, tag+i, mpi_c, mpi_s); - i += 1; + i++; _size -= VM_MPI_SIZE_LIMIT; messageCC += VM_MPI_SIZE_LIMIT; } @@ -4635,10 +4650,7 @@ int VMK::recv(void *message, unsigned long long int size, int source, pipc_mp *pipcmp; shared_mp *shmp; int scpsize, rcpsize; - char *pdest; char *psrc; - int i; - char *mess; int recvCount; // check if this needs a new entry in the request queue if (*ch==NULL){ @@ -4741,28 +4753,46 @@ int VMK::recv(void *message, unsigned long long int size, int source, memcpy(message, cp, size); rm->buffer = (void *)(cp+chunkSize); // next chunk in buffer }else{ - (*ch)->nelements=1; + int nelements = size/VM_MPI_SIZE_LIMIT; + if (size%VM_MPI_SIZE_LIMIT) nelements++; + (*ch)->nelements=nelements; (*ch)->type=1; // MPI (*ch)->sendFlag=false; // not a send request - (*ch)->mpireq = new MPI_Request[1]; + (*ch)->mpireq = new MPI_Request[nelements]; // MPI-1 implementation // use mutex to serialize mpi comm calls if mpi thread support requires it #ifndef ESMF_NO_PTHREADS if (mpi_mutex_flag) pthread_mutex_lock(pth_mutex); #endif -//fprintf(stderr, "MPI_Irecv: ch=%p\n", (*ch)->mpireq); int mpiSource; if (source == VM_ANY_SRC) mpiSource = MPI_ANY_SOURCE; else mpiSource = lpid[source]; #ifdef VM_SIZELOG_on { std::stringstream msg; - msg << "VMK::recv():" << __LINE__ << ", size=" << size; + msg << "VMK::recv():" << __LINE__ << ", size=" << size + << " in " << nelements << " chunks"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif - localrc = MPI_Irecv(message, size, MPI_BYTE, mpiSource, tag, mpi_c, - (*ch)->mpireq); + if (size <= VM_MPI_SIZE_LIMIT) + localrc = MPI_Irecv(message, size, MPI_BYTE, mpiSource, tag, mpi_c, + (*ch)->mpireq); + else{ + unsigned long long _size = size; + char *messageCC = (char *)message; + int i=0; + while(_size > VM_MPI_SIZE_LIMIT){ + localrc = MPI_Irecv(messageCC, VM_MPI_SIZE_LIMIT, MPI_BYTE, mpiSource, + tag+i, mpi_c, &((*ch)->mpireq[i])); + i++; + _size -= VM_MPI_SIZE_LIMIT; + messageCC += VM_MPI_SIZE_LIMIT; + } + if (_size > 0) + localrc = MPI_Irecv(messageCC, _size, MPI_BYTE, mpiSource, + tag+i, mpi_c, &((*ch)->mpireq[i])); + } #ifndef ESMF_NO_PTHREADS if (mpi_mutex_flag) pthread_mutex_unlock(pth_mutex); #endif From 3fc52e921a7745b4011e2248535590e9ccb90691 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 16:35:11 -0700 Subject: [PATCH 066/266] Fix up test implementation. --- .../VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 | 164 ++++++++++-------- 1 file changed, 92 insertions(+), 72 deletions(-) diff --git a/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 index cae7c4bc23..88ba37730e 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMSendNbVMRecvNbUTest.F90 @@ -51,13 +51,15 @@ program ESMF_VMSendNbVMRecvNbUTest integer:: localPet, petCount integer:: count, src, dst - integer(ESMF_KIND_I4), allocatable :: i4_data(:) - integer(ESMF_KIND_I8), allocatable :: i8_data(:) - real(ESMF_KIND_R4), allocatable :: r4_data(:) - real(ESMF_KIND_R8), allocatable :: r8_data(:) - type(ESMF_Logical), allocatable :: lg_data(:) - character(10) :: char_data, char_soln - character(10), allocatable :: ch_data(:) + integer, parameter:: countParameter = 2800000 + + integer(ESMF_KIND_I4), allocatable :: i4_data(:), i4_test(:) + integer(ESMF_KIND_I8), allocatable :: i8_data(:), i8_test(:) + real(ESMF_KIND_R4), allocatable :: r4_data(:), r4_test(:) + real(ESMF_KIND_R8), allocatable :: r8_data(:), r8_test(:) + type(ESMF_Logical), allocatable :: lg_data(:), lg_test(:) + character(10) :: char_data, char_test, char_soln + character(10), allocatable :: ch_data(:), ch_test(:) integer(ESMF_KIND_I4) :: I4Sum integer(ESMF_KIND_I8) :: I8Sum @@ -84,10 +86,6 @@ program ESMF_VMSendNbVMRecvNbUTest call ESMF_VMGet(vm, localPet=localPet, petCount=petCount, rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - ! Allocate localData -! count = 280000000 - count = 2800 - src = localPet - 1 if (src < 0) src = petCount - 1 @@ -104,7 +102,8 @@ program ESMF_VMSendNbVMRecvNbUTest !Test with ESMF_KIND_I4 arguments !================================ - allocate(i4_data(count)) + count = countParameter + allocate(i4_data(count), i4_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -122,7 +121,7 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=i4_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=i4_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ @@ -142,16 +141,19 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" I4Sum=0 do i=1, count - I4Sum = I4Sum + (i4_data(i) - int(src*100+i, ESMF_KIND_I4)) + I4Sum = I4Sum + (i4_test(i) - int(src*100+i, ESMF_KIND_I4)) enddo call ESMF_Test( (I4Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(i4_data) + call ESMF_VMCommWaitAll(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + deallocate(i4_data, i4_test) !Test with ESMF_KIND_I8 arguments !================================ - allocate(i8_data(count)) + count = countParameter + allocate(i8_data(count), i8_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -169,7 +171,7 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=i8_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=i8_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ @@ -189,16 +191,19 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" I8Sum=0 do i=1, count - I8Sum = I8Sum + (i8_data(i) - int(src*100+i, ESMF_KIND_I8)) + I8Sum = I8Sum + (i8_test(i) - int(src*100+i, ESMF_KIND_I8)) enddo call ESMF_Test( (I8Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(i8_data) + call ESMF_VMCommWaitAll(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + deallocate(i8_data, i8_test) !Test with ESMF_KIND_R4 arguments !================================ - allocate(r4_data(count)) + count = countParameter + allocate(r4_data(count), r4_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -216,7 +221,7 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=r4_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=r4_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ @@ -235,16 +240,19 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" R4Sum=0 do i=1, count - R4Sum = R4Sum + (r4_data(i) - real(src*100+i, ESMF_KIND_R4)) + R4Sum = R4Sum + (r4_test(i) - real(src*100+i, ESMF_KIND_R4)) enddo call ESMF_Test( (R4Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(r4_data) + call ESMF_VMCommWaitAll(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + deallocate(r4_data, r4_test) !Test with ESMF_KIND_R8 arguments !================================ - allocate(r8_data(count)) + count = countParameter + allocate(r8_data(count), r8_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -262,7 +270,7 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=r8_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ @@ -282,16 +290,19 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" R8Sum=0 do i=1, count - R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + R8Sum = R8Sum + (r8_test(i) - real(src*100+i, ESMF_KIND_R8)) enddo call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(r8_data) + call ESMF_VMCommWaitAll(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + deallocate(r8_data, r8_test) !Test with ESMF_Logical arguments !================================ - allocate(lg_data(count)) + count = countParameter + allocate(lg_data(count), lg_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -309,7 +320,7 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=lg_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=lg_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ @@ -329,13 +340,15 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" LGSum=0 do i=1, count - if ((lg_data(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & + if ((lg_test(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & LGSum = LGSum + 1 enddo call ESMF_Test( (LGSum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(lg_data) + call ESMF_VMCommWaitAll(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + deallocate(lg_data, lg_test) !Test with character string arguments !==================================== @@ -354,7 +367,7 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data Character String Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=char_data, count=len(char_data), & + call ESMF_VMRecv(vm, recvData=char_test, count=len(char_test), & srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, & rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -375,14 +388,14 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" CHSum=0 write (char_soln, "(i2.2,i3)") src, 1 - if (char_data /= char_soln) CHSum = CHSum + 1 + if (char_test /= char_soln) CHSum = CHSum + 1 call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !Test with character string array arguments !========================================== - count = 100 - allocate(ch_data(count)) + count = min(1000,countParameter) ! performance issue for too large + allocate(ch_data(count), ch_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -400,7 +413,7 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data Character String array Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=ch_data, count=count*len(ch_data), & + call ESMF_VMRecv(vm, recvData=ch_test, count=count*len(ch_test), & srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, commhandle=commhandle, & rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -422,12 +435,14 @@ program ESMF_VMSendNbVMRecvNbUTest CHSum=0 do i=1, count write (char_soln, "(i2.2,i3)") src, i - if (ch_data(i) /= char_soln) CHSum = CHSum + 1 + if (ch_test(i) /= char_soln) CHSum = CHSum + 1 enddo call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(ch_data) + call ESMF_VMCommWaitAll(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + deallocate(ch_data, ch_test) !=============================================================================== ! Second round of tests use ESMF's internal request queue to wait on outstanding @@ -436,7 +451,8 @@ program ESMF_VMSendNbVMRecvNbUTest !Test with ESMF_KIND_I4 arguments !================================ - allocate(i4_data(count)) + count = countParameter + allocate(i4_data(count), i4_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -454,14 +470,14 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=i4_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=i4_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "waiting for all outstanding comms for I4 Test" + write(name, *) "Waiting for all outstanding comms for I4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -474,16 +490,17 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" I4Sum=0 do i=1, count - I4Sum = I4Sum + (i4_data(i) - int(src*100+i, ESMF_KIND_I4)) + I4Sum = I4Sum + (i4_test(i) - int(src*100+i, ESMF_KIND_I4)) enddo call ESMF_Test( (I4Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(i4_data) + deallocate(i4_data, i4_test) !Test with ESMF_KIND_I8 arguments !================================ - allocate(i8_data(count)) + count = countParameter + allocate(i8_data(count), i8_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -501,14 +518,14 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=i8_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=i8_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "waiting for all outstanding comms for I8 Test" + write(name, *) "Waiting for all outstanding comms for I8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -521,16 +538,17 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" I8Sum=0 do i=1, count - I8Sum = I8Sum + (i8_data(i) - int(src*100+i, ESMF_KIND_I8)) + I8Sum = I8Sum + (i8_test(i) - int(src*100+i, ESMF_KIND_I8)) enddo call ESMF_Test( (I8Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(i8_data) + deallocate(i8_data, i8_test) !Test with ESMF_KIND_R4 arguments !================================ - allocate(r4_data(count)) + count = countParameter + allocate(r4_data(count), r4_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -548,13 +566,13 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=r4_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=r4_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "waiting for all outstanding comms for R4 Test" + write(name, *) "Waiting for all outstanding comms for R4 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -567,16 +585,17 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" R4Sum=0 do i=1, count - R4Sum = R4Sum + (r4_data(i) - real(src*100+i, ESMF_KIND_R4)) + R4Sum = R4Sum + (r4_test(i) - real(src*100+i, ESMF_KIND_R4)) enddo call ESMF_Test( (R4Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(r4_data) + deallocate(r4_data, r4_test) !Test with ESMF_KIND_R8 arguments !================================ - allocate(r8_data(count)) + count = countParameter + allocate(r8_data(count), r8_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -594,14 +613,14 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=r8_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "waiting for all outstanding comms for R8 Test" + write(name, *) "Waiting for all outstanding comms for R8 Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -614,16 +633,17 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" R8Sum=0 do i=1, count - R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + R8Sum = R8Sum + (r8_test(i) - real(src*100+i, ESMF_KIND_R8)) enddo call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(r8_data) + deallocate(r8_data, r8_test) !Test with ESMF_Logical arguments !================================ - allocate(lg_data(count)) + count = countParameter + allocate(lg_data(count), lg_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -641,14 +661,14 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=lg_data, count=count, srcPet=src, & + call ESMF_VMRecv(vm, recvData=lg_test, count=count, srcPet=src, & syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "waiting for all outstanding comms for Logical Test" + write(name, *) "Waiting for all outstanding comms for Logical Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -661,13 +681,13 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" LGSum=0 do i=1, count - if ((lg_data(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & + if ((lg_test(i)==ESMF_TRUE) .neqv. (mod(src*100+i,2)==0)) & LGSum = LGSum + 1 enddo call ESMF_Test( (LGSum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(lg_data) + deallocate(lg_data, lg_test) !Test with character string arguments !==================================== @@ -686,14 +706,14 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data Character String Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=char_data, count=len(char_data), & + call ESMF_VMRecv(vm, recvData=char_test, count=len(char_test), & srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "waiting for all outstanding comms for Character String Test" + write(name, *) "Waiting for all outstanding comms for Character String Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -706,14 +726,14 @@ program ESMF_VMSendNbVMRecvNbUTest write(failMsg, *) "Wrong Local Data" CHSum=0 write (char_soln, "(i2.2,i3)") src, 1 - if (char_data /= char_soln) CHSum = CHSum + 1 + if (char_test /= char_soln) CHSum = CHSum + 1 call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !Test with character string array arguments !========================================== - count = 100 - allocate(ch_data(count)) + count = min(1000,countParameter) ! performance issue for too large + allocate(ch_data(count), ch_test(count)) !------------------------------------------------------------------------ !NEX_UTest @@ -731,14 +751,14 @@ program ESMF_VMSendNbVMRecvNbUTest !NEX_UTest write(name, *) "Receiving local data Character String array Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" - call ESMF_VMRecv(vm, recvData=ch_data, count=count*len(ch_data), & + call ESMF_VMRecv(vm, recvData=ch_test, count=count*len(ch_test), & srcPet=src, syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest - write(name, *) "waiting for all outstanding comms for Character String array Test" + write(name, *) "Waiting for all outstanding comms for Character String array Test" write(failMsg, *) "Did not RETURN ESMF_SUCCESS" call ESMF_VMCommWaitAll(vm, rc=rc) call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -752,12 +772,12 @@ program ESMF_VMSendNbVMRecvNbUTest CHSum=0 do i=1, count write (char_soln, "(i2.2,i3)") src, i - if (ch_data(i) /= char_soln) CHSum = CHSum + 1 + if (ch_test(i) /= char_soln) CHSum = CHSum + 1 enddo call ESMF_Test( (CHSum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - deallocate(ch_data) + deallocate(ch_data, ch_test) call ESMF_TestEnd(ESMF_SRCLINE) From 0477f43eb9dbf00c9b8ac6041ec073079c6e007e Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 2 Aug 2022 16:40:01 -0700 Subject: [PATCH 067/266] Add unit testing for large message sizes in blocking and non-blocking comms, also eventually with VMEpoch. --- .../VM/tests/ESMF_VMEpochLargeMsgUTest.F90 | 223 ++++++++++++++++++ .../VM/tests/ESMF_VMSendVMRecvUTest.F90 | 17 +- src/Infrastructure/VM/tests/makefile | 9 +- 3 files changed, 245 insertions(+), 4 deletions(-) create mode 100644 src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 diff --git a/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 new file mode 100644 index 0000000000..d80eab3d09 --- /dev/null +++ b/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 @@ -0,0 +1,223 @@ +! $Id$ +! +! Earth System Modeling Framework +! Copyright 2002-2022, 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_VMEpochLargeMsgUTest + +!------------------------------------------------------------------------------ + +#include "ESMF_Macros.inc" + +!============================================================================== +!BOP +! !PROGRAM: ESMF_VMSendNbVMRecvNbUTest - Unit test for non-blocking VM Send +! and Receive Functions +! +! !DESCRIPTION: +! +! The code in this file drives the F90 non-blocking VM Send Receive tests. +! +!----------------------------------------------------------------------------- +! !USES: + use ESMF_TestMod ! test methods + use ESMF + + implicit none + +!------------------------------------------------------------------------------ +! The following line turns the CVS identifier string into a printable variable. + character(*), parameter :: version = & + '$Id$' +!------------------------------------------------------------------------------ + ! cumulative result: count failures; no failures equals "all pass" + integer :: result = 0 + + ! individual test failure message + character(ESMF_MAXSTR) :: failMsg + character(ESMF_MAXSTR) :: name + character(ESMF_MAXSTR) :: msgStr + + ! local variables + integer:: i, rc + type(ESMF_VM):: vm + integer:: localPet, petCount + integer:: count, src, dst + + real(ESMF_KIND_R8), allocatable :: r8_data(:) + real(ESMF_KIND_R8) :: R8Sum + +!------------------------------------------------------------------------------ +! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are +! always run. When the environment variable, EXHAUSTIVE, is set to ON then +! the EXHAUSTIVE and sanity tests both run. If the EXHAUSTIVE variable is set +! Special strings (Non-exhaustive and exhaustive) have been +! added to allow a script to count the number and types of unit tests. +!------------------------------------------------------------------------------ + + call ESMF_TestStart(ESMF_SRCLINE, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Get count of PETs and which PET number we are + call ESMF_VMGetGlobal(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_VMGet(vm, localPet=localPet, petCount=petCount, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! check petCount + if (petCount < 2) then + call ESMF_LogWrite("Must run test with at least 2 PETs", & + ESMF_LOGMSG_ERROR, rc=rc) + call ESMF_Finalize(endflag=ESMF_END_ABORT) + endif + + ! single src PET, single dst PET + src = 0 + dst = petCount-1 + + write(msgStr, *) "src=",src," dst=",dst + call ESMF_LogWrite(msgStr, ESMF_LOGMSG_INFO, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + +!=============================================================================== +! Blocking src -> dst +!=============================================================================== + + !Test with ESMF_KIND_R8 arguments + !================================ + count = 280000000 + if (localPet==src .or. localPet==dst) allocate(r8_data(count)) + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==src) then + write(name, *) "Sending local data R8 Blocking Test" + do i=1, count + r8_data(i) = real(localPet*100+i, ESMF_KIND_R8) + enddo + call ESMF_VMSend(vm, sendData=r8_data, count=count, dstPet=dst, rc=rc) + else + write(name, *) "Dummy Sending R8 Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==dst) then + write(name, *) "Receiving local data R8 Blocking Test" + call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, rc=rc) + else + write(name, *) "Dummy Receiving R8 Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + ! Verify localData after VM Receive + write(failMsg, *) "Wrong Local Data" + R8Sum=0 + if (localPet==dst) then + write(name, *) "Verify local data after receive R8 Blocking Test" + do i=1, count + R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + enddo + else + write(name, *) "Dummy verify local data after receive R8 Blocking Test" + endif + call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + if (localPet==src .or. localPet==dst) deallocate(r8_data) + +!=============================================================================== +! Non-Blocking src -> dst +!=============================================================================== + + + !Test with ESMF_KIND_R8 arguments + !================================ + count = 280000000 +! count = 250000000 + if (localPet==src .or. localPet==dst) allocate(r8_data(count)) + +!call ESMF_VMEpochEnter(epoch=ESMF_VMEPOCH_BUFFER, rc=rc) + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==src) then + write(name, *) "Sending local data R8 Non-Blocking Test" + do i=1, count + r8_data(i) = real(localPet*100+i, ESMF_KIND_R8) + enddo + call ESMF_VMSend(vm, sendData=r8_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + else + write(name, *) "Dummy Sending R8 Non-Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==dst) then + write(name, *) "Receiving local data R8 Non-Blocking Test" + call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + else + write(name, *) "Dummy Receiving R8 Non-Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==dst) then + write(name, *) "Waiting for all outstanding comms for R8 Non-Blocking Test" + call ESMF_VMCommWaitAll(vm, rc=rc) + else + write(name, *) "Dummy Waiting for all outstanding comms for R8 Non-Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ +!call ESMF_VMEpochExit(rc=rc) + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + ! Verify localData after VM Receive + write(failMsg, *) "Wrong Local Data" + R8Sum=0 + if (localPet==dst) then + write(name, *) "Verify local data after receive R8 Non-Blocking Test" + do i=1, count + R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + enddo + else + write(name, *) "Dummy verify local data after receive R8 Non-Blocking Test" + endif + call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + if (localPet==src) call ESMF_VMCommWaitAll(vm, rc=rc) + if (localPet==src .or. localPet==dst) deallocate(r8_data) + + call ESMF_TestEnd(ESMF_SRCLINE) + +end program ESMF_VMEpochLargeMsgUTest diff --git a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 index 9711be3655..8872e1ab05 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMSendVMRecvUTest.F90 @@ -51,6 +51,8 @@ program ESMF_VMSendVMRecvUTest integer:: localPet, petCount integer:: count, src, dst + integer, parameter:: countParameter = 2800000 + integer(ESMF_KIND_I4), allocatable :: i4_data(:) integer(ESMF_KIND_I8), allocatable :: i8_data(:) real(ESMF_KIND_R4), allocatable :: r4_data(:) @@ -82,8 +84,12 @@ program ESMF_VMSendVMRecvUTest call ESMF_VMGet(vm, localPet=localPet, petCount=petCount, rc=rc) if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) - ! Allocate localData - count = 280000000 + ! check petCount + if (petCount < 2) then + call ESMF_LogWrite("Must run test with at least 2 PETs", & + ESMF_LOGMSG_ERROR, rc=rc) + call ESMF_Finalize(endflag=ESMF_END_ABORT) + endif src = localPet - 1 if (src < 0) src = petCount - 1 @@ -98,6 +104,7 @@ program ESMF_VMSendVMRecvUTest !Test with ESMF_KIND_I4 arguments !================================ + count = countParameter allocate(i4_data(count)) !------------------------------------------------------------------------ @@ -152,6 +159,7 @@ program ESMF_VMSendVMRecvUTest !Test with ESMF_KIND_I8 arguments !================================ + count = countParameter allocate(i8_data(count)) !------------------------------------------------------------------------ @@ -206,6 +214,7 @@ program ESMF_VMSendVMRecvUTest !Test with ESMF_KIND_R4 arguments !================================ + count = countParameter allocate(r4_data(count)) !------------------------------------------------------------------------ @@ -260,6 +269,7 @@ program ESMF_VMSendVMRecvUTest !Test with ESMF_KIND_R8 arguments !================================ + count = countParameter allocate(r8_data(count)) !------------------------------------------------------------------------ @@ -314,6 +324,7 @@ program ESMF_VMSendVMRecvUTest !Test with ESMF_Logical arguments !================================ + count = countParameter allocate(lg_data(count)) !------------------------------------------------------------------------ @@ -419,7 +430,7 @@ program ESMF_VMSendVMRecvUTest !Test with character string array arguments !========================================== - count = 100 + count = min(1000,countParameter) ! performance issue for too large allocate(ch_data(count)) !------------------------------------------------------------------------ diff --git a/src/Infrastructure/VM/tests/makefile b/src/Infrastructure/VM/tests/makefile index 1cb4e00aee..ddb78c8fc2 100644 --- a/src/Infrastructure/VM/tests/makefile +++ b/src/Infrastructure/VM/tests/makefile @@ -32,6 +32,7 @@ TESTS_BUILD = $(ESMF_TESTDIR)/ESMC_VMUTest \ $(ESMF_TESTDIR)/ESMF_VMAllToAllUTest \ $(ESMF_TESTDIR)/ESMF_VMAllToAllVUTest \ $(ESMF_TESTDIR)/ESMF_VMBarrierUTest \ + $(ESMF_TESTDIR)/ESMF_VMEpochLargeMsgUTest \ $(ESMF_TESTDIR)/ESMF_VMComponentUTest TESTS_RUN = RUN_ESMC_VMUTest \ @@ -51,6 +52,7 @@ TESTS_RUN = RUN_ESMC_VMUTest \ RUN_ESMF_VMAllToAllUTest \ RUN_ESMF_VMAllToAllVUTest \ RUN_ESMF_VMBarrierUTest \ + RUN_ESMF_VMEpochLargeMsgUTest \ RUN_ESMF_VMComponentUTest TESTS_RUN_UNI = RUN_ESMC_VMUTestUNI \ @@ -127,7 +129,7 @@ RUN_ESMF_VMUserMpiInitUTestUNI: # VM Send VM Recv # RUN_ESMF_VMSendVMRecvUTest: - $(MAKE) TNAME=VMSendVMRecv NP=2 ftest + $(MAKE) TNAME=VMSendVMRecv NP=4 ftest # # VM SendNb VM RecvNb @@ -233,6 +235,11 @@ RUN_ESMF_VMBarrierUTestUNI: $(MAKE) TNAME=VMBarrier NP=1 ftest # +# VM Epoch and Large Messages +# +RUN_ESMF_VMEpochLargeMsgUTest: + $(MAKE) TNAME=VMEpochLargeMsg NP=2 ftest +# # VM Component # RUN_ESMF_VMComponentUTest: From 6907157f3bbe5c35c0881ec108ee88aa5876f8fe Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 3 Aug 2022 12:23:02 -0700 Subject: [PATCH 068/266] More complete messages under VM_SIZELOG_on in all cases. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 152f984c75..6b9c5db038 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -4102,6 +4102,10 @@ int VMK::send(const void *message, unsigned long long int size, int dest, { std::stringstream msg; msg << "VMK::send():" << __LINE__ << ", size=" << size; + if (size <= VM_MPI_SIZE_LIMIT) + msg << " in one chunk"; + else + msg << " in multiple chunks"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif @@ -4396,7 +4400,8 @@ int VMK::send(const void *message, unsigned long long int size, int dest, #ifdef VM_SIZELOG_on { std::stringstream msg; - msg << "VMK::send():" << __LINE__ << ", size=" << size; + msg << "VMK::send():" << __LINE__ << ", size=" << size + << " using MPIUNI channel via memcpy() in one chunk"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif @@ -4474,6 +4479,10 @@ int VMK::recv(void *message, unsigned long long int size, int source, int tag, { std::stringstream msg; msg << "VMK::recv():" << __LINE__ << ", size=" << size; + if (size <= VM_MPI_SIZE_LIMIT) + msg << " in one chunk"; + else + msg << " in multiple chunks"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif @@ -4842,7 +4851,8 @@ int VMK::recv(void *message, unsigned long long int size, int source, #ifdef VM_SIZELOG_on { std::stringstream msg; - msg << "VMK::recv():" << __LINE__ << ", size=" << size; + msg << "VMK::recv():" << __LINE__ << ", size=" << size + << " using MPIUNI channel via memcpy() in one chunk"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } #endif From 7763500de0dd98b973064b6bf2d31489a9895a40 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 3 Aug 2022 13:11:32 -0700 Subject: [PATCH 069/266] Improved debugging/development logging. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 53 +++++++++++++++------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 6b9c5db038..e862599961 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -19,7 +19,7 @@ #define VM_PETMANAGEMENTLOG_off #define VM_MEMLOG_off #define VM_COMMQUEUELOG_off -#define VM_EPOCHLOG_off +#define VM_EPOCHLOG_on #define VM_SSISHMLOG_off #define VM_SIZELOG_on @@ -3530,7 +3530,10 @@ int VMK::commtest(commhandle **ch, int *completeFlag, status *status){ // ... but set localCompleteFlag localCompleteFlag = 1; }else{ - printf("VMK: only MPI non-blocking implemented\n"); + std::stringstream msg; + msg << "VMK::commtest():" << __LINE__ + << " only MPI non-blocking implemented"; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); localrc = VMK_ERROR; } // if this *ch is in the request queue x-> unlink and delete @@ -3683,7 +3686,10 @@ int VMK::commwait(commhandle **ch, status *status, int nanopause){ }else if ((*ch)->type==-1){ // this is a dummy commhandle and there is nothing to wait for... }else{ - printf("VMK: only MPI non-blocking implemented\n"); + std::stringstream msg; + msg << "VMK::commwait():" << __LINE__ + << " only MPI non-blocking implemented"; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); localrc = VMK_ERROR; } } @@ -3735,7 +3741,10 @@ void VMK::commcancel(commhandle **commh){ #endif } }else{ - printf("VMK: only MPI non-blocking implemented\n"); + std::stringstream msg; + msg << "VMK::commwait():" << __LINE__ + << " only MPI non-blocking implemented"; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); } } } @@ -3889,7 +3898,7 @@ void VMK::epochExit(bool keepAlloc){ #ifdef VM_EPOCHLOG_on double t1; wtime(&t1); msg.str(""); // clear - msg << "epochBuffer:" << __LINE__ << " cost of non-blocking send: " + msg << "epochBuffer:" << __LINE__ << " time in non-blocking send: " << t1 - t0 << " seconds"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif @@ -3914,7 +3923,7 @@ void VMK::epochExit(bool keepAlloc){ #ifdef VM_EPOCHLOG_on double t1; wtime(&t1); msg.str(""); // clear - msg << "epochBuffer:" << __LINE__ << " cost of non-blocking send: " + msg << "epochBuffer:" << __LINE__ << " time in non-blocking send: " << t1 - t0 << " seconds"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif @@ -4035,7 +4044,7 @@ bool VMK::sendBuffer::clear(bool justTest){ #ifdef VM_EPOCHLOG_on double t1; wtime(&t1); msg.str(""); // clear - msg << "epochBuffer:" << __LINE__ << " returned from MPI_Wait(), cost: " + msg << "epochBuffer:" << __LINE__ << " time in MPI_Wait(): " << t1 - t0 << " seconds"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif @@ -4699,22 +4708,34 @@ int VMK::recv(void *message, unsigned long long int size, int source, msg << "epochBuffer:" << __LINE__ << " ready to probe:" << " src=" << getVas(lpid[source]); ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + double t0; wtime(&t0); #endif int defaultTag = getDefaultTag(source,mypet); MPI_Status mpistat; MPI_Probe(lpid[source], defaultTag, mpi_c, &mpistat); - + int bytecount; MPI_Get_count(&mpistat, MPI_BYTE, &bytecount); - + rm->streamBuffer.resize(bytecount); rm->buffer = (void *)rm->streamBuffer.data(); - +#ifdef VM_EPOCHLOG_on + double t1; wtime(&t1); + msg.str(""); // clear + msg << "epochBuffer:" << __LINE__ << " time in blocking probe: " + << t1 - t0 << " seconds"; + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); + msg.str(""); // clear + msg << "epochBuffer:" << __LINE__ << " incoming message of size=" + << rm->streamBuffer.size(); + ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); +#endif + // send the acknowledge message to sender for throttle int ackDummy=1; MPI_Send(&ackDummy, sizeof(int), MPI_BYTE, lpid[source], defaultTag, mpi_c); - + // post blocking recv of the entire epoch buffer #if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) msg.str(""); // clear @@ -4723,15 +4744,15 @@ int VMK::recv(void *message, unsigned long long int size, int source, << " size=" << rm->streamBuffer.size() << " streamBuffer=" << (void *)rm->streamBuffer.data(); ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); - double t0; wtime(&t0); + double t2; wtime(&t2); #endif MPI_Recv(rm->buffer, bytecount, MPI_BYTE, lpid[source], defaultTag, mpi_c, MPI_STATUS_IGNORE); #ifdef VM_EPOCHLOG_on - double t1; wtime(&t1); + double t3; wtime(&t3); msg.str(""); // clear - msg << "epochBuffer:" << __LINE__ << " cost of blocking recv: " - << t1 - t0 << " seconds"; + msg << "epochBuffer:" << __LINE__ << " time in blocking recv: " + << t3 - t2 << " seconds"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif } @@ -4741,7 +4762,7 @@ int VMK::recv(void *message, unsigned long long int size, int source, int *ip = (int *)ipl; int chunkTag = *ip++; char *cp = (char *)ip; - + #ifdef VM_EPOCHLOG_on msg.str(""); // clear msg << "epochBuffer:" << __LINE__ << " processing recv chunk:" From 5b14232a3458e450ceadb7a3a27c75e0e4847218 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 3 Aug 2022 14:22:50 -0700 Subject: [PATCH 070/266] Attempt to capture compiler, etc. version requirements in the User's Guide. --- src/doc/ESMF_systemreq.tex | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/doc/ESMF_systemreq.tex b/src/doc/ESMF_systemreq.tex index f3a103f61a..72ce3f2dd1 100644 --- a/src/doc/ESMF_systemreq.tex +++ b/src/doc/ESMF_systemreq.tex @@ -2,17 +2,37 @@ The following compilers and utilities are required for compiling, linking and -testing the ESMF software: +testing the ESMF software. Some combinations of Fortran and C++ compilers, +e.g. Intel ifort with GNU g++, are supported. \begin{itemize} -\item Fortran90 (or later) compiler; -\item C++ compiler; -\item MPI implementation compatible with the above compilers (but see below); +\item Fortran compiler: + \begin{itemize} + \item GNU's gfortran v7.0 and newer, or + \item Intel's ifort v18.0 and newer. + \end{itemize} +\item C++ compiler: + \begin{itemize} + \item GNU's g++ v7.0 and newer, or + \item Intel's icpc v18.0 and newer. + \end{itemize} +\item C compiler: + \begin{itemize} + \item GNU's gcc v7.0 and newer, or + \item Intel's icc v18.0 and newer. + \end{itemize} +\item MPI implementation compatible with the above compilers (but also see below +for the MPI-bypass build option): + \begin{itemize} + \item OpenMPI v3.0 and newer, or + \item MPICH v2.1 and newer, or + \item IntelMPI v18.0 and newer. + \end{itemize} \item GNU's \htmladdnormallink{gcc compiler}{http://gcc.gnu.org} - -for a standard cpp preprocessor implementation; -\item \htmladdnormallink{GNU Make}{http://www.gnu.org/software/make/make.html}; +for a standard cpp preprocessor implementation. +\item \htmladdnormallink{GNU Make}{http://www.gnu.org/software/make/make.html}. \item \htmladdnormallink{Perl}{http://www.perl.com/download.csp} - for running test scripts. -\end{itemize} +\end{itemize} Internal packages that can optionally reference external libraries: \begin{itemize} From 4a27d56dff96be97850ac5baef2fb4d732c01b46 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 3 Aug 2022 17:43:54 -0700 Subject: [PATCH 071/266] add PGI and MPT --- src/doc/ESMF_systemreq.tex | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/doc/ESMF_systemreq.tex b/src/doc/ESMF_systemreq.tex index 72ce3f2dd1..0eda06a06d 100644 --- a/src/doc/ESMF_systemreq.tex +++ b/src/doc/ESMF_systemreq.tex @@ -8,24 +8,28 @@ \item Fortran compiler: \begin{itemize} \item GNU's gfortran v7.0 and newer, or - \item Intel's ifort v18.0 and newer. + \item Intel's ifort v18.0 and newer, or + \item PGI v18.1 and newer. \end{itemize} \item C++ compiler: \begin{itemize} \item GNU's g++ v7.0 and newer, or - \item Intel's icpc v18.0 and newer. + \item Intel's icpc v18.0 and newer, or + \item PGI v18.1 and newer. \end{itemize} \item C compiler: \begin{itemize} \item GNU's gcc v7.0 and newer, or - \item Intel's icc v18.0 and newer. + \item Intel's icc v18.0 and newer, or + \item PGI v18.1 and newer. \end{itemize} \item MPI implementation compatible with the above compilers (but also see below for the MPI-bypass build option): \begin{itemize} \item OpenMPI v3.0 and newer, or \item MPICH v2.1 and newer, or - \item IntelMPI v18.0 and newer. + \item IntelMPI v18.0 and newer, or + \item MPT 2.17 and newer. \end{itemize} \item GNU's \htmladdnormallink{gcc compiler}{http://gcc.gnu.org} - for a standard cpp preprocessor implementation. From bdd4bc73b0c2148fee6c3314637052d5dd2ff085 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 07:42:50 -0700 Subject: [PATCH 072/266] Update system requirements list. --- src/doc/ESMF_systemreq.tex | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/doc/ESMF_systemreq.tex b/src/doc/ESMF_systemreq.tex index 0eda06a06d..267c0ca81d 100644 --- a/src/doc/ESMF_systemreq.tex +++ b/src/doc/ESMF_systemreq.tex @@ -9,20 +9,30 @@ \begin{itemize} \item GNU's gfortran v7.0 and newer, or \item Intel's ifort v18.0 and newer, or - \item PGI v18.1 and newer. - \end{itemize} + \item PGI's pgf90 v18.1 and newer, or + \item NVHPC's nvfortran, or + \item NAG's nagfor, or + \item IBM's xlf, or + \item CCE's ftn. + \end{itemize} \item C++ compiler: \begin{itemize} \item GNU's g++ v7.0 and newer, or \item Intel's icpc v18.0 and newer, or - \item PGI v18.1 and newer. - \end{itemize} + \item PGI's pgCC v18.1 and newer, or + \item NVHPC's nvc++, or + \item IBM's xlC, or + \item CCE's CC. + \end{itemize} \item C compiler: \begin{itemize} \item GNU's gcc v7.0 and newer, or \item Intel's icc v18.0 and newer, or - \item PGI v18.1 and newer. - \end{itemize} + \item PGI pgcc v18.1 and newer, or + \item NVHPC's nvcc, or + \item IBM's xlc, or + \item CCE's cc. + \end{itemize} \item MPI implementation compatible with the above compilers (but also see below for the MPI-bypass build option): \begin{itemize} @@ -30,7 +40,7 @@ \item MPICH v2.1 and newer, or \item IntelMPI v18.0 and newer, or \item MPT 2.17 and newer. - \end{itemize} + \end{itemize} \item GNU's \htmladdnormallink{gcc compiler}{http://gcc.gnu.org} - for a standard cpp preprocessor implementation. \item \htmladdnormallink{GNU Make}{http://www.gnu.org/software/make/make.html}. @@ -50,7 +60,7 @@ \item NetCDF - version 3.6.x or newer (version 4.4 or newer required by PIO) \item parallel-NetCDF - version 1.2.0 or newer (version 1.12 or newer required by PIO) \item Xerces - version 3.1.0 or newer -\end{itemize} +\end{itemize} ESMF can be built using a single-processor MPI-bypass library that comes with ESMF by setting {\tt ESMF\_COMM=mpiuni}. This allows ESMF applications From 6420390a490e0a217556e0794596942c394b6ae7 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 07:47:08 -0700 Subject: [PATCH 073/266] Update MPI implementations in requirement list. --- src/doc/ESMF_systemreq.tex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/ESMF_systemreq.tex b/src/doc/ESMF_systemreq.tex index 267c0ca81d..4cc19954ff 100644 --- a/src/doc/ESMF_systemreq.tex +++ b/src/doc/ESMF_systemreq.tex @@ -38,8 +38,10 @@ \begin{itemize} \item OpenMPI v3.0 and newer, or \item MPICH v2.1 and newer, or + \item MVAPICH2 v2.0 and newer, or \item IntelMPI v18.0 and newer, or - \item MPT 2.17 and newer. + \item MPT 2.17 and newer, or + \item CRAY-MPICH v7.7 and newer. \end{itemize} \item GNU's \htmladdnormallink{gcc compiler}{http://gcc.gnu.org} - for a standard cpp preprocessor implementation. From 05a4cc398200c2e3fae58d97f7610dbfb25009ff Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 08:34:22 -0700 Subject: [PATCH 074/266] Add testing with VMEpoch as its own section. --- .../VM/tests/ESMF_VMEpochLargeMsgUTest.F90 | 95 ++++++++++++++++++- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 index d80eab3d09..d1d92ea0a2 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 @@ -146,14 +146,92 @@ program ESMF_VMEpochLargeMsgUTest ! Non-Blocking src -> dst !=============================================================================== + !Test with ESMF_KIND_R8 arguments + !================================ + count = 280000000 + if (localPet==src .or. localPet==dst) allocate(r8_data(count)) + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==src) then + write(name, *) "Sending local data R8 Non-Blocking Test" + do i=1, count + r8_data(i) = real(localPet*100+i, ESMF_KIND_R8) + enddo + call ESMF_VMSend(vm, sendData=r8_data, count=count, dstPet=dst, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + else + write(name, *) "Dummy Sending R8 Non-Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==dst) then + write(name, *) "Receiving local data R8 Non-Blocking Test" + call ESMF_VMRecv(vm, recvData=r8_data, count=count, srcPet=src, & + syncflag=ESMF_SYNC_NONBLOCKING, rc=rc) + else + write(name, *) "Dummy Receiving R8 Non-Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + if (localPet==dst) then + write(name, *) "Waiting for all outstanding comms for R8 Non-Blocking Test" + call ESMF_VMCommWaitAll(vm, rc=rc) + else + write(name, *) "Dummy Waiting for all outstanding comms for R8 Non-Blocking Test" + rc = ESMF_SUCCESS + endif + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + ! Verify localData after VM Receive + write(failMsg, *) "Wrong Local Data" + R8Sum=0 + if (localPet==dst) then + write(name, *) "Verify local data after receive R8 Non-Blocking Test" + do i=1, count + R8Sum = R8Sum + (r8_data(i) - real(src*100+i, ESMF_KIND_R8)) + enddo + else + write(name, *) "Dummy verify local data after receive R8 Non-Blocking Test" + endif + call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + call ESMF_VMCommWaitAll(vm, rc=rc) + if (localPet==src .or. localPet==dst) deallocate(r8_data) + +!=============================================================================== +! Non-Blocking with VMEpoch src -> dst +!=============================================================================== !Test with ESMF_KIND_R8 arguments !================================ - count = 280000000 -! count = 250000000 +! count = 280000000 + count = 250000000 if (localPet==src .or. localPet==dst) allocate(r8_data(count)) -!call ESMF_VMEpochEnter(epoch=ESMF_VMEPOCH_BUFFER, rc=rc) + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(name, *) "ESMF_VMEpochEnter() Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMEpochEnter(epoch=ESMF_VMEPOCH_BUFFER, rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only write(failMsg, *) "Did not RETURN ESMF_SUCCESS" @@ -197,7 +275,14 @@ program ESMF_VMEpochLargeMsgUTest endif call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ -!call ESMF_VMEpochExit(rc=rc) + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(name, *) "ESMF_VMEpochExit() Test" + write(failMsg, *) "Did not RETURN ESMF_SUCCESS" + call ESMF_VMEpochExit(rc=rc) + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ !------------------------------------------------------------------------ !NEX_UTest_Multi_Proc_Only @@ -215,9 +300,9 @@ program ESMF_VMEpochLargeMsgUTest call ESMF_Test( (R8Sum == 0), name, failMsg, result, ESMF_SRCLINE) !------------------------------------------------------------------------ - if (localPet==src) call ESMF_VMCommWaitAll(vm, rc=rc) if (localPet==src .or. localPet==dst) deallocate(r8_data) + !------------------------------------------------------------------------ call ESMF_TestEnd(ESMF_SRCLINE) end program ESMF_VMEpochLargeMsgUTest From df7e07e796356d6de6ec6ee59b21b0565e817954 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 09:10:11 -0700 Subject: [PATCH 075/266] Add VM_EPOCHMEMLOG_on, and code simplification wrt std::strstream vs std::stringstream option. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 57 ++++++++++------------ 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index e862599961..6b17e0aba9 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -20,6 +20,7 @@ #define VM_MEMLOG_off #define VM_COMMQUEUELOG_off #define VM_EPOCHLOG_on +#define VM_EPOCHMEMLOG_on #define VM_SSISHMLOG_off #define VM_SIZELOG_on @@ -3794,11 +3795,11 @@ void VMK::epochFinal(){ #ifdef USE_STRSTREAM // use strstream void *buffer = (void *)sm->stream.str(); // access the buffer -> freeze - int size = sm->stream.pcount(); // bytes in stream buffer + unsigned long long int size = sm->stream.pcount(); // bytes in stream buffer #else // use stringstream - void *buffer = (void *)sm->streamBuffer.data(); - int size = sm->streamBuffer.size(); // bytes in stream buffer + void *buffer = (void *)sm->streamBuffer.data(); // access contig. buffer + unsigned long long int size = sm->streamBuffer.size(); // bytes in stream buffer #endif std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " ready to clear outstanding comm:" @@ -3878,47 +3879,36 @@ void VMK::epochExit(bool keepAlloc){ #endif } bool needAck = false; +#ifdef VM_EPOCHMEMLOG_on + VM::logMemInfo(std::string("VMK::epochExit:1.0")); +#endif #ifdef USE_STRSTREAM // use strstream void *buffer = (void *)sm->stream.str(); // access the buffer -> freeze - int size = sm->stream.pcount(); // bytes in stream buffer + unsigned long long size = sm->stream.pcount(); // bytes in stream buffer + sm->stream.seekp(0); // reset stream to the beginning (not affect buff) +#else + // use stringstream + sm->streamBuffer = sm->stream.str(); // copy data into contiguous buffer + sm->stream.str(""); // clear out stream + void *buffer = (void *)sm->streamBuffer.data(); // access contig. buffer + unsigned long long size = sm->streamBuffer.size(); +#endif +#ifdef VM_EPOCHMEMLOG_on + VM::logMemInfo(std::string("VMK::epochExit:2.0")); +#endif if (size > 0){ #if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " ready to post non-blocking send:" - << " dst=" << getVas(lpid[its->first]) << " size=" << size + << " dst=" << getVas(lpid[its->first]) + << " size=" << size << " buffer=" << buffer; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); double t0; wtime(&t0); #endif MPI_Isend(buffer, size, MPI_BYTE, lpid[its->first], tag, mpi_c, &sm->mpireq); - sm->stream.seekp(0); // reset stream to the beginning (not affect buff) - needAck = true; -#ifdef VM_EPOCHLOG_on - double t1; wtime(&t1); - msg.str(""); // clear - msg << "epochBuffer:" << __LINE__ << " time in non-blocking send: " - << t1 - t0 << " seconds"; - ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); -#endif - } -#else - // use stringstream - sm->streamBuffer = sm->stream.str(); // copy data into persistent buffer - sm->stream.str(""); // clear out stream - if (sm->streamBuffer.size() > 0){ -#if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) - std::stringstream msg; - msg << "epochBuffer:" << __LINE__ << " ready to post non-blocking send:" - << " dst=" << getVas(lpid[its->first]) - << " size=" << sm->streamBuffer.size() - << " buffer=" << (void *)sm->streamBuffer.data(); - ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); - double t0; wtime(&t0); -#endif - MPI_Isend((void *)sm->streamBuffer.data(), sm->streamBuffer.size(), - MPI_BYTE, lpid[its->first], tag, mpi_c, &sm->mpireq); needAck = true; #ifdef VM_EPOCHLOG_on double t1; wtime(&t1); @@ -3928,6 +3918,8 @@ void VMK::epochExit(bool keepAlloc){ ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif } +#ifdef VM_EPOCHMEMLOG_on + VM::logMemInfo(std::string("VMK::epochExit:3.0")); #endif if (needAck){ // post the receive of the acknowledge message from receiver for throttle @@ -3943,6 +3935,9 @@ void VMK::epochExit(bool keepAlloc){ ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif } +#ifdef VM_EPOCHMEMLOG_on + VM::logMemInfo(std::string("VMK::epochExit:4.0")); +#endif } if (!keepAlloc){ // clear the recvMap, freeing all receive buffers held From 4bd1015690647c8f3289eea0cd55922b504805ef Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 09:19:20 -0700 Subject: [PATCH 076/266] Replace USE_STRSTREAM macro with EPOCH_BUFFER_OPTION to allow more choices. --- src/Infrastructure/VM/include/ESMCI_VMKernel.h | 11 ++++++----- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 16 ++++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index 037e4b3d85..9b9da1ade7 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -17,14 +17,15 @@ #define MPICH_IGNORE_CXX_SEEK #endif -#define USE_STRSTREAM +#define EPOCH_BUFFER_OPTION (1) // 0: std:strstream + // 1: std:stringstream #include #include #include #include #include -#ifdef USE_STRSTREAM +#if (EPOCH_BUFFER_OPTION == 0) #include #endif #include @@ -124,7 +125,7 @@ namespace ESMCI { template void append(std::stringstream &streami, T value){ streami.write((char*)&value, sizeof(T)); } -#ifdef USE_STRSTREAM +#if (EPOCH_BUFFER_OPTION == 0) template void append(std::strstream &streami, T value){ streami.write((char*)&value, sizeof(T)); } @@ -230,9 +231,9 @@ class VMK{ }; struct sendBuffer{ -#ifdef USE_STRSTREAM +#if (EPOCH_BUFFER_OPTION == 0) std::strstream stream; -#else +#elif (EPOCH_BUFFER_OPTION == 1) std::stringstream stream; std::string streamBuffer; #endif diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 6b17e0aba9..a4a93af5a0 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -3792,11 +3792,11 @@ void VMK::epochFinal(){ for (its=sendMap.begin(); its!=sendMap.end(); ++its){ sendBuffer *sm = &(its->second); #ifdef VM_EPOCHLOG_on -#ifdef USE_STRSTREAM +#if (EPOCH_BUFFER_OPTION == 0) // use strstream void *buffer = (void *)sm->stream.str(); // access the buffer -> freeze unsigned long long int size = sm->stream.pcount(); // bytes in stream buffer -#else +#elif (EPOCH_BUFFER_OPTION == 1) // use stringstream void *buffer = (void *)sm->streamBuffer.data(); // access contig. buffer unsigned long long int size = sm->streamBuffer.size(); // bytes in stream buffer @@ -3882,12 +3882,12 @@ void VMK::epochExit(bool keepAlloc){ #ifdef VM_EPOCHMEMLOG_on VM::logMemInfo(std::string("VMK::epochExit:1.0")); #endif -#ifdef USE_STRSTREAM +#if (EPOCH_BUFFER_OPTION == 0) // use strstream void *buffer = (void *)sm->stream.str(); // access the buffer -> freeze unsigned long long size = sm->stream.pcount(); // bytes in stream buffer sm->stream.seekp(0); // reset stream to the beginning (not affect buff) -#else +#elif (EPOCH_BUFFER_OPTION == 1) // use stringstream sm->streamBuffer = sm->stream.str(); // copy data into contiguous buffer sm->stream.str(""); // clear out stream @@ -4046,10 +4046,10 @@ bool VMK::sendBuffer::clear(bool justTest){ } } -#ifdef USE_STRSTREAM +#if (EPOCH_BUFFER_OPTION == 0) // use strstream stream.freeze(false); // unfreeze the persistent buffer for deallocation -#else +#elif (EPOCH_BUFFER_OPTION == 1) // use stringstream streamBuffer.clear(); // done with buffer #endif @@ -4302,9 +4302,9 @@ int VMK::send(const void *message, unsigned long long int size, int dest, msg.str(""); // clear msg << "epochBuffer:" << __LINE__ << " non-blocking send write complete"<< ", current stream size=" << -#ifdef USE_STRSTREAM +#if (EPOCH_BUFFER_OPTION == 0) sm->stream.pcount(); -#else +#elif (EPOCH_BUFFER_OPTION == 1) sm->stream.tellp(); #endif ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); From ccbc20071b893d2a2db469f31d69b39c64188fa0 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 10:35:04 -0700 Subject: [PATCH 077/266] Implement EPOCH_BUFFER_OPTION == 2, std:vector. --- .../VM/include/ESMCI_VMKernel.h | 18 +++++++++++- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 29 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index 9b9da1ade7..ea70763738 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -17,8 +17,9 @@ #define MPICH_IGNORE_CXX_SEEK #endif -#define EPOCH_BUFFER_OPTION (1) // 0: std:strstream +#define EPOCH_BUFFER_OPTION (2) // 0: std:strstream // 1: std:stringstream + // 2: std:vector #include #include @@ -27,6 +28,8 @@ #include #if (EPOCH_BUFFER_OPTION == 0) #include +#elif (EPOCH_BUFFER_OPTION == 2) +#include #endif #include @@ -129,6 +132,17 @@ template void append(std::stringstream &streami, T value){ template void append(std::strstream &streami, T value){ streami.write((char*)&value, sizeof(T)); } +#elif (EPOCH_BUFFER_OPTION == 2) +template void append(std::vector &charBuffer, T value){ + unsigned long long int size = charBuffer.size(); + charBuffer.resize(size+sizeof(T)); + memcpy(&(charBuffer[size]), (char*)&value, sizeof(T)); +} +template void append(std::vector &charBuffer, const char* message, T _size){ + unsigned long long int size = charBuffer.size(); + charBuffer.resize(size+_size); + memcpy(&(charBuffer[size]), message, _size); +} #endif //----------------------------------------------------------------------------- @@ -236,6 +250,8 @@ class VMK{ #elif (EPOCH_BUFFER_OPTION == 1) std::stringstream stream; std::string streamBuffer; +#elif (EPOCH_BUFFER_OPTION == 2) + std::vector charBuffer; #endif MPI_Request mpireq; bool firstFlag; diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index a4a93af5a0..9b56c8388b 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -3800,6 +3800,10 @@ void VMK::epochFinal(){ // use stringstream void *buffer = (void *)sm->streamBuffer.data(); // access contig. buffer unsigned long long int size = sm->streamBuffer.size(); // bytes in stream buffer +#elif (EPOCH_BUFFER_OPTION == 2) + // use vector + void *buffer = (void *)&(sm->charBuffer[0]); // access the buffer + unsigned long long int size = sm->charBuffer.size(); // bytes in buffer #endif std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " ready to clear outstanding comm:" @@ -3893,6 +3897,11 @@ void VMK::epochExit(bool keepAlloc){ sm->stream.str(""); // clear out stream void *buffer = (void *)sm->streamBuffer.data(); // access contig. buffer unsigned long long size = sm->streamBuffer.size(); +#elif (EPOCH_BUFFER_OPTION == 2) + // use vector + void *buffer = (void *)&(sm->charBuffer[0]); // access the buffer + unsigned long long int size = sm->charBuffer.size(); // bytes in buffer + sm->charBuffer.resize(0); // reset buffer, without affecting allocation #endif #ifdef VM_EPOCHMEMLOG_on VM::logMemInfo(std::string("VMK::epochExit:2.0")); @@ -4007,6 +4016,9 @@ bool VMK::sendBuffer::clear(bool justTest){ std::stringstream msg; msg << "epochBuffer:" << __LINE__ << " ready to clear outstanding comm"; ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); +#endif +#ifdef VM_EPOCHMEMLOG_on + VM::logMemInfo(std::string("VMK::sendBuffer::clear():1.0")); #endif bool done = false; if (mpireq != MPI_REQUEST_NULL){ @@ -4046,12 +4058,21 @@ bool VMK::sendBuffer::clear(bool justTest){ } } +#ifdef VM_EPOCHMEMLOG_on + VM::logMemInfo(std::string("VMK::sendBuffer::clear():2.0")); +#endif #if (EPOCH_BUFFER_OPTION == 0) // use strstream stream.freeze(false); // unfreeze the persistent buffer for deallocation #elif (EPOCH_BUFFER_OPTION == 1) // use stringstream streamBuffer.clear(); // done with buffer +#elif (EPOCH_BUFFER_OPTION == 2) + // use vector + std::vector().swap(charBuffer); // done with buffer swap out of scope +#endif +#ifdef VM_EPOCHMEMLOG_on + VM::logMemInfo(std::string("VMK::sendBuffer::clear():3.0")); #endif return done; } @@ -4295,9 +4316,15 @@ int VMK::send(const void *message, unsigned long long int size, int dest, sm->clear(); // wait for outstanding comm and clear out. } // append the message into the epoch buffer stream +#if (EPOCH_BUFFER_OPTION == 0 || EPOCH_BUFFER_OPTION == 1) append(sm->stream, size); append(sm->stream, tag); sm->stream.write((const char*)message, size); +#elif (EPOCH_BUFFER_OPTION == 2) + append(sm->charBuffer, size); + append(sm->charBuffer, tag); + append(sm->charBuffer, (const char*)message, size); +#endif #if (defined VM_EPOCHLOG_on || defined VM_SIZELOG_on) msg.str(""); // clear msg << "epochBuffer:" << __LINE__ << " non-blocking send write complete"<< @@ -4306,6 +4333,8 @@ int VMK::send(const void *message, unsigned long long int size, int dest, sm->stream.pcount(); #elif (EPOCH_BUFFER_OPTION == 1) sm->stream.tellp(); +#elif (EPOCH_BUFFER_OPTION == 2) + sm->charBuffer.size(); #endif ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); #endif From d768e4185505dbe60121e192d41726ac93220c0b Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 4 Aug 2022 12:04:27 -0700 Subject: [PATCH 078/266] remove version information from pgi and gfortran READMEs --- build_config/Darwin.gfortran.default/README | 7 +++---- build_config/Darwin.gfortranclang.default/README | 3 +-- build_config/Linux.gfortran.default/README | 4 +--- build_config/Linux.gfortranclang.default/README | 4 +--- build_config/Linux.pgi.default/README | 3 --- build_config/Linux.pgigcc.default/README | 3 --- build_config/MinGW.gfortran.default/README | 3 +-- build_config/Unicos.gfortran.default/README | 3 +-- build_config/Unicos.pgi.default/README | 3 --- 9 files changed, 8 insertions(+), 25 deletions(-) diff --git a/build_config/Darwin.gfortran.default/README b/build_config/Darwin.gfortran.default/README index 95d6be165a..5a7c2859b5 100644 --- a/build_config/Darwin.gfortran.default/README +++ b/build_config/Darwin.gfortran.default/README @@ -1,10 +1,9 @@ -Settings for Darwin (Mac OS X), using the GNU gfortran compiler -(part of the GCC 4.0 release) and GNU C++ compiler (g++). Due to bugs -in early versions of gfortran, ESMF requires gfortran version 4.3 or newer. +Settings for Darwin (Mac OS X), using the GNU gfortran compiler +and GNU C++ compiler (g++). On some Darwin systems, the clang compiler is provided as an alias to g++. This is detected and properly supported. On systems where both g++ and clang -exist, ensure that the PATH environement variable is set correctly such that +exist, ensure that the PATH environment variable is set correctly such that the desired c++ environment is used. For example, if clang is the desired compiler, the path to it should be prior to the path to the gcc bin directory. diff --git a/build_config/Darwin.gfortranclang.default/README b/build_config/Darwin.gfortranclang.default/README index c75fffcbc1..8fe16fb8e1 100644 --- a/build_config/Darwin.gfortranclang.default/README +++ b/build_config/Darwin.gfortranclang.default/README @@ -1,6 +1,5 @@ Settings for Darwin (Mac OS X), using the GNU gfortran compiler -(part of the GCC 4.0 release) and the clang C++ compiler (g++). Due to bugs -in early versions of gfortran, ESMF requires gfortran version 4.3 or newer. + and the clang C++ compiler (g++). Requires the following environment settings: diff --git a/build_config/Linux.gfortran.default/README b/build_config/Linux.gfortran.default/README index fd176606a0..e694b5fc52 100644 --- a/build_config/Linux.gfortran.default/README +++ b/build_config/Linux.gfortran.default/README @@ -1,6 +1,4 @@ -Settings for Linux, using the gfortran compiler that comes with the GCC of -version 4.0.0 and up. Due to bugs in early versions of gfortran, ESMF -requires gfortran version 4.3 or newer. +Settings for Linux, using the GNU gfortran compiler and GNU C++ compiler (g++). Requires the following environment settings: diff --git a/build_config/Linux.gfortranclang.default/README b/build_config/Linux.gfortranclang.default/README index 8386deb4ae..d619483db5 100644 --- a/build_config/Linux.gfortranclang.default/README +++ b/build_config/Linux.gfortranclang.default/README @@ -1,6 +1,4 @@ -Settings for Linux, using the clang C++ compiler and gfortran compiler. -Due to bugs in early versions of gfortran, ESMF requires gfortran version 4.3 -or newer. +Settings for Linux, using the clang C++ compiler and GNU gfortran compiler. Requires the following environment settings: diff --git a/build_config/Linux.pgi.default/README b/build_config/Linux.pgi.default/README index 5ad4c8069d..dfb33083ba 100644 --- a/build_config/Linux.pgi.default/README +++ b/build_config/Linux.pgi.default/README @@ -3,6 +3,3 @@ Settings for Linux, using the commercial Portland Group PGI Fortran and C++ comp Requires the following environment settings: ESMF_COMPILER pgi - -For pre-7.1 compilers, please see the ESMF_Conf.inc file for several -macros that must be enabled for proper operation. diff --git a/build_config/Linux.pgigcc.default/README b/build_config/Linux.pgigcc.default/README index 14f0331861..c85882cf86 100644 --- a/build_config/Linux.pgigcc.default/README +++ b/build_config/Linux.pgigcc.default/README @@ -4,6 +4,3 @@ and the GNU C++ compiler (g++). Requires the following environment settings: ESMF_COMPILER pgigcc - -For pre-7.1 compilers, please see the ESMF_Conf.inc file for several -macros that must be enabled for proper operation. diff --git a/build_config/MinGW.gfortran.default/README b/build_config/MinGW.gfortran.default/README index fbe024801a..6ff0e2caaa 100644 --- a/build_config/MinGW.gfortran.default/README +++ b/build_config/MinGW.gfortran.default/README @@ -1,4 +1,4 @@ -Settings for MinGW/MSYS, using gfortran 4.3 or later. +Settings for MinGW/MSYS using the GNU gfortran compiler. Supports the following environment settings: @@ -11,4 +11,3 @@ using MinGW 6.1 and MSYS 1.0.11. MinGW and MSYS are available from http://www.mingw.org. 2.) The MinGW version of gcc is required for preprocessing. - diff --git a/build_config/Unicos.gfortran.default/README b/build_config/Unicos.gfortran.default/README index 2f8a9df2db..2a49b57d48 100644 --- a/build_config/Unicos.gfortran.default/README +++ b/build_config/Unicos.gfortran.default/README @@ -1,5 +1,4 @@ -Settings for Unicos/lc on Cray XT/XE/XK, using gfortran and g++ out of the GNU Compiler Collection. Due to bugs in early versions of gfortran, ESMF -requires gfortran version 4.3 or newer. +Settings for Unicos/lc on Cray XT/XE/XK, using gfortran and g++ out of the GNU Compiler Collection. Requires the following environment settings: diff --git a/build_config/Unicos.pgi.default/README b/build_config/Unicos.pgi.default/README index 53ca84d63d..536bea8f7e 100644 --- a/build_config/Unicos.pgi.default/README +++ b/build_config/Unicos.pgi.default/README @@ -3,6 +3,3 @@ Settings for Unicos/lc on Cray XT, using the Portland Group PGI Fortran and C++ Requires the following environment settings: ESMF_COMPILER pgi - -For pre-7.1 compilers, please see the ESMF_Conf.inc file for several -macros that must be enabled for proper operation. From 57d8fdeef343e51f4249ef2f65382d7caaebebc9 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 15:49:57 -0700 Subject: [PATCH 079/266] Large message support working under VMEpoch for EPOCH_BUFFER_OPTION 2 (vector buffer). --- .../VM/include/ESMCI_VMKernel.h | 16 ++-- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 87 +++++++++++++++++-- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index ea70763738..e22a38f15d 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -17,9 +17,9 @@ #define MPICH_IGNORE_CXX_SEEK #endif -#define EPOCH_BUFFER_OPTION (2) // 0: std:strstream - // 1: std:stringstream - // 2: std:vector +#define EPOCH_BUFFER_OPTION (2) // 0: std::strstream + // 1: std::stringstream + // 2: std::vector #include #include @@ -148,10 +148,14 @@ template void append(std::vector &charBuffer, const char* mess class VMK{ - - // structs + public: - + + // custom MPI types for large message support + static std::vector customType; + + // structs + struct commhandle{ commhandle *prev_handle;// previous handle in the queue commhandle *next_handle;// next handle in the queue diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 9b56c8388b..0425ebf42c 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -121,6 +121,7 @@ typedef DWORD pid_t; namespace ESMCI { // Definition of class static data members +std::vector VMK::customType(10); // up to 2^10 = 1024 byte MPI_Comm VMK::default_mpi_c; int VMK::mpi_thread_level; int VMK::mpi_init_outside_esmf; @@ -623,6 +624,13 @@ void VMK::init(MPI_Comm mpiCommunicator, bool globalResourceControl){ MPI_Allgather(&num_adevices, 1, MPI_INTEGER, nadevs, 1, MPI_INTEGER, mpi_c); #endif + // Creating large contiguous MPI data types + int byteCount=1; + for (auto i=0; i<(signed)customType.size(); i++){ + byteCount *= 2; + MPI_Type_contiguous(byteCount, MPI_BYTE, &(customType[i])); + MPI_Type_commit(&(customType[i])); + } // Start epoch support in the global VM epochInit(); } @@ -3916,8 +3924,46 @@ void VMK::epochExit(bool keepAlloc){ ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); double t0; wtime(&t0); #endif - MPI_Isend(buffer, size, MPI_BYTE, lpid[its->first], tag, mpi_c, - &sm->mpireq); + if (size <= VM_MPI_SIZE_LIMIT) + // small message + MPI_Isend(buffer, size, MPI_BYTE, lpid[its->first], tag, mpi_c, + &sm->mpireq); + else{ +#if (EPOCH_BUFFER_OPTION == 2) + // large message + // - determine smallest customType to keep count < VM_MPI_SIZE_LIMIT + int byteCount = 1; + int i; + for (i=0; i<(signed)customType.size(); i++){ + byteCount *= 2; + if (size / byteCount < VM_MPI_SIZE_LIMIT) break; + } + if (i>=(signed)customType.size()){ + int localrc; + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, + "Message too large to be supported", + ESMC_CONTEXT, &localrc); + throw localrc; // bail out with exception + } + // - might need to pad the buffer to be a multiple of the customType + int extra = size%byteCount; + if (extra){ + size += byteCount - extra; + sm->charBuffer.resize(size); + } + // - use the determined customType to send the message + int count = size/byteCount; + MPI_Isend(buffer, count, customType[i], lpid[its->first], tag, mpi_c, + &sm->mpireq); +#else + // large messages not supported + int localrc; + ESMC_LogDefault.MsgFoundError(ESMC_RC_INTNRL_BAD, + "Message larger than 2GiB only supported for EPOCH_BUFFER_OPTION 2.", + ESMC_CONTEXT, &localrc); + throw localrc; // bail out with exception +#endif + } needAck = true; #ifdef VM_EPOCHLOG_on double t1; wtime(&t1); @@ -4738,11 +4784,29 @@ int VMK::recv(void *message, unsigned long long int size, int source, MPI_Status mpistat; MPI_Probe(lpid[source], defaultTag, mpi_c, &mpistat); - int bytecount; - MPI_Get_count(&mpistat, MPI_BYTE, &bytecount); - - rm->streamBuffer.resize(bytecount); + // - determine smallest customType to keep count < VM_MPI_SIZE_LIMIT + int count; + int i; + for (i=(signed)customType.size()-1; i>=0; i--){ + MPI_Get_count(&mpistat, customType[i], &count); + if (count > VM_MPI_SIZE_LIMIT/2) break; + } + unsigned long long int byteCount; + if (i<0){ + // small message + MPI_Get_count(&mpistat, MPI_BYTE, &count); + byteCount = count; + }else{ + // large message + byteCount = 2; + for (int j=0; jstreamBuffer.resize(byteCount); rm->buffer = (void *)rm->streamBuffer.data(); + #ifdef VM_EPOCHLOG_on double t1; wtime(&t1); msg.str(""); // clear @@ -4770,8 +4834,15 @@ int VMK::recv(void *message, unsigned long long int size, int source, ESMC_LogDefault.Write(msg.str(), ESMC_LOGMSG_DEBUG); double t2; wtime(&t2); #endif - MPI_Recv(rm->buffer, bytecount, MPI_BYTE, - lpid[source], defaultTag, mpi_c, MPI_STATUS_IGNORE); + if (i<0){ + // small message + MPI_Recv(rm->buffer, count, MPI_BYTE, + lpid[source], defaultTag, mpi_c, MPI_STATUS_IGNORE); + }else{ + // large message + MPI_Recv(rm->buffer, count, customType[i], + lpid[source], defaultTag, mpi_c, MPI_STATUS_IGNORE); + } #ifdef VM_EPOCHLOG_on double t3; wtime(&t3); msg.str(""); // clear From c1262976a278aef97b122f60e0f0398c6d17e5cb Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 16:07:02 -0700 Subject: [PATCH 080/266] Consistently test above the 2GiB limit in this unit test. --- .../VM/tests/ESMF_VMEpochLargeMsgUTest.F90 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 index d1d92ea0a2..72a1c4c62b 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMEpochLargeMsgUTest.F90 @@ -92,7 +92,8 @@ program ESMF_VMEpochLargeMsgUTest !Test with ESMF_KIND_R8 arguments !================================ - count = 280000000 +! count = 250000000 ! just below 2GiB limit + count = 280000000 ! just above 2GiB limit if (localPet==src .or. localPet==dst) allocate(r8_data(count)) !------------------------------------------------------------------------ @@ -148,7 +149,8 @@ program ESMF_VMEpochLargeMsgUTest !Test with ESMF_KIND_R8 arguments !================================ - count = 280000000 +! count = 250000000 ! just below 2GiB limit + count = 280000000 ! just above 2GiB limit if (localPet==src .or. localPet==dst) allocate(r8_data(count)) !------------------------------------------------------------------------ @@ -220,8 +222,8 @@ program ESMF_VMEpochLargeMsgUTest !Test with ESMF_KIND_R8 arguments !================================ -! count = 280000000 - count = 250000000 +! count = 250000000 ! just below 2GiB limit + count = 280000000 ! just above 2GiB limit if (localPet==src .or. localPet==dst) allocate(r8_data(count)) !------------------------------------------------------------------------ From 8ebc19a897788fcbf9d7de25b417a9eb27bbaced Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 16:51:28 -0700 Subject: [PATCH 081/266] Remove undesired line end characters from string. --- src/Infrastructure/VM/interface/ESMCI_VM_F.C | 50 ++++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Infrastructure/VM/interface/ESMCI_VM_F.C b/src/Infrastructure/VM/interface/ESMCI_VM_F.C index dcb1d25d1a..165891f731 100644 --- a/src/Infrastructure/VM/interface/ESMCI_VM_F.C +++ b/src/Infrastructure/VM/interface/ESMCI_VM_F.C @@ -80,7 +80,7 @@ extern "C" { localrc = (*vm)->allfullreduce(input, output, *count, vmt, (vmOp)(*op)); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -103,7 +103,7 @@ extern "C" { localrc = (*vm)->allgather(input, output, *size); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -128,7 +128,7 @@ extern "C" { (ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -178,7 +178,7 @@ extern "C" { recvOffsets, vmt); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -222,7 +222,7 @@ extern "C" { localrc = (*vm)->allreduce(input, output, *count, vmt, (vmOp)(*op)); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -269,7 +269,7 @@ extern "C" { recvData, *recvCount, vmt); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -322,7 +322,7 @@ extern "C" { recvCounts, recvOffsets, vmt); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -344,7 +344,7 @@ extern "C" { localrc = (*vm)->barrier(); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -367,7 +367,7 @@ extern "C" { localrc = (*vm)->broadcast(data, *size, *root); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -392,7 +392,7 @@ extern "C" { (ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -486,7 +486,7 @@ extern "C" { localrc = (*vm)->gather(input, output, *size, *root); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -511,7 +511,7 @@ extern "C" { (ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -557,7 +557,7 @@ extern "C" { recvOffsets, vmt, *root); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -747,7 +747,7 @@ extern "C" { localrc = (*vm)->recv(message, *size, *source); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -773,7 +773,7 @@ extern "C" { (ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -817,7 +817,7 @@ extern "C" { localrc = (*vm)->reduce(input, output, *count, vmt, (vmOp)(*op), *root); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -840,7 +840,7 @@ extern "C" { localrc = (*vm)->scatter(input, output, *size, *root); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -866,7 +866,7 @@ extern "C" { (ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -912,7 +912,7 @@ extern "C" { *recvCount, vmt, *root); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -935,7 +935,7 @@ extern "C" { localrc = (*vm)->send(message, *size, *dest); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -961,7 +961,7 @@ extern "C" { (ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -985,7 +985,7 @@ extern "C" { *recvSize, *src); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -1012,7 +1012,7 @@ extern "C" { *recvSize, *src, (ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -1035,7 +1035,7 @@ extern "C" { localrc = (*vm)->commwait((ESMCI::VMK::commhandle **)commhandle); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; @@ -1087,7 +1087,7 @@ extern "C" { localrc = (*vm)->threadbarrier(); if (localrc){ char *message = new char[160]; - sprintf(message, "VMKernel/MPI error #%d\n", localrc); + sprintf(message, "VMKernel/MPI error #%d", localrc); ESMC_LogDefault.MsgFoundError(ESMF_RC_INTNRL_BAD, message, ESMC_CONTEXT, rc); delete [] message; From 5b5163fc0a85de49e1e6f96b9a04ba9cf8ed2cc4 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 4 Aug 2022 16:57:35 -0700 Subject: [PATCH 082/266] Increase the SHARED_BUFFER to 256 bytes to have VM examples pass now that there is better error checking. --- src/Infrastructure/VM/include/ESMCI_VMKernel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index e22a38f15d..6c599cbe76 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -91,7 +91,7 @@ enum vmEpoch { epochNone=0, epochBuffer}; // - buffer lenghts in bytes #define PIPC_BUFFER (4096) -#define SHARED_BUFFER (64) +#define SHARED_BUFFER (256) // - number of shared memory non-blocking channels #define SHARED_NONBLOCK_CHANNELS (16) From 99a2dab4675455f29efa5c2eaf1768c922f45a6b Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 5 Aug 2022 08:30:28 -0700 Subject: [PATCH 083/266] Formatting. --- .../VM/include/ESMCI_VMKernel.h | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Infrastructure/VM/include/ESMCI_VMKernel.h b/src/Infrastructure/VM/include/ESMCI_VMKernel.h index 6c599cbe76..8fbe32b0c4 100644 --- a/src/Infrastructure/VM/include/ESMCI_VMKernel.h +++ b/src/Infrastructure/VM/include/ESMCI_VMKernel.h @@ -422,13 +422,13 @@ class VMK{ void exit(class VMKPlan *vmp, void *arg); void shutdown(class VMKPlan *vmp, void *arg); // exit a vm derived from current vm according to the VMKPlan - + void print() const; void log(std::string prefix, ESMC_LogMsgType_Flag msgType=ESMC_LOGMSG_INFO)const; static void logSystem(std::string prefix, ESMC_LogMsgType_Flag msgType=ESMC_LOGMSG_INFO); - + // get() calls <-- to be replaced by following new inlined section int getNpets(); // return npets int getMypet(); // return mypet @@ -441,13 +441,13 @@ class VMK{ int getTid(int i); // return tid for PET int getVas(int i); // return vas for PET int getLpid(int i); // return lpid for PET - + int getDefaultTag(int src, int dst); // return default tag int getMaxTag(); // return maximum value of tag - + const int *getSsipe() const {return ssipe;} int **getCid() const {return cid;} - + // get() calls int getLocalPet() const {return mypet;} int getCurrentSsiPe() const; @@ -497,14 +497,15 @@ class VMK{ static std::string getEsmfComm(){return std::string(XSTR(ESMF_COMM));} // p2p communication calls - int send(const void *message, unsigned long long int size, int dest, int tag=-1); - int send(const void *message, unsigned long long int size, int dest, commhandle **commh, + int send(const void *message, unsigned long long int size, int dest, int tag=-1); - int recv(void *message, unsigned long long int size, int source, int tag=-1, - status *status=NULL); - int recv(void *message, unsigned long long int size, int source, commhandle **commh, - int tag=-1); - + int send(const void *message, unsigned long long int size, int dest, + commhandle **commh, int tag=-1); + int recv(void *message, unsigned long long int size, int source, + int tag=-1, status *status=NULL); + int recv(void *message, unsigned long long int size, int source, + commhandle **commh, int tag=-1); + int sendrecv(void *sendData, int sendSize, int dst, void *recvData, int recvSize, int src, int dstTag=-1, int srcTag=-1); int sendrecv(void *sendData, int sendSize, int dst, void *recvData, @@ -525,7 +526,7 @@ class VMK{ int allreduce(void *in, void *out, int len, vmType type, vmOp op); int allfullreduce(void *in, void *out, int len, vmType type, vmOp op); - + int reduce_scatter(void *in, void *out, int *outCounts, vmType type, vmOp op); @@ -533,7 +534,7 @@ class VMK{ int scatter(void *in, void *out, int len, int root, commhandle **commh); int scatterv(void *in, int *inCounts, int *inOffsets, void *out, int outCount, vmType type, int root); - + int gather(void *in, void *out, int len, int root); int gather(void *in, void *out, int len, int root, commhandle **commh); int gatherv(void *in, int inCount, void *out, int *outCounts, @@ -550,14 +551,14 @@ class VMK{ int broadcast(void *data, int len, int root); int broadcast(void *data, int len, int root, commhandle **commh); - + // non-blocking service calls int commtest(commhandle **commh, int *completeFlag, status *status=NULL); int commwait(commhandle **commh, status *status=NULL, int nanopause=0); void commqueuewait(); void commcancel(commhandle **commh); bool cancelled(status *status); - + // SSI shared memory methods int ssishmAllocate(std::vector&bytes, memhandle *memh, bool contigFlag=false); @@ -567,7 +568,7 @@ class VMK{ int ssishmGetLocalPet(memhandle memh){return memh.localPet;} int ssishmGetLocalPetCount(memhandle memh){return memh.localPetCount;} int ssishmSync(memhandle memh); - + // IntraProcessSharedMemoryAllocation Table Methods void *ipshmallocate(int bytes, int *firstFlag=NULL); void ipshmdeallocate(void *); @@ -577,7 +578,7 @@ class VMK{ void ipmutexdeallocate(ipmutex *ipmutex); int ipmutexlock(ipmutex *ipmutex); int ipmutexunlock(ipmutex *ipmutex); - + // Simple thread-safety lock/unlock using internal pth_mutex int lock(); int unlock(); @@ -589,7 +590,7 @@ class VMK{ void epochEnter(vmEpoch epoch, bool keepAlloc=true, int throttle=10); void epochExit(bool keepAlloc=true); vmEpoch getEpoch() const {return epoch;} - + // Timer methods static void wtime(double *time); static void wtimeprec(double *prec); From 348f23dc5b6bca2163498b092940c924849a7027 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 5 Aug 2022 11:23:06 -0600 Subject: [PATCH 084/266] Use a more standard error handling pattern for addArray This will support some upcoming changes. Thanks to @theurich for guidance on this. --- src/Infrastructure/IO/src/ESMCI_IO.C | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_IO.C b/src/Infrastructure/IO/src/ESMCI_IO.C index 340b5d056a..24f98c0f80 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO.C +++ b/src/Infrastructure/IO/src/ESMCI_IO.C @@ -1006,7 +1006,7 @@ int IO::addArray( //EOP //----------------------------------------------------------------------------- // initialize return code; assume routine not implemented - int localrc = ESMF_SUCCESS; // local return code + int localrc = ESMC_RC_NOT_IMPL; // local return code int rc = ESMC_RC_NOT_IMPL; // final return code PRINTPOS; @@ -1024,23 +1024,22 @@ int IO::addArray( variableName, dimAttPack, varAttPack, gblAttPack); if ((IO_ObjectContainer *)NULL == newObj) { - localrc = ESMC_RC_MEM_ALLOCATE; ESMC_LogDefault.AllocError(ESMC_CONTEXT, &rc); ESMC_LogDefault.Write("Unable to allocate storage for IO object", ESMC_LOGMSG_ERROR, ESMC_CONTEXT); + return rc; } else { objects.push_back(newObj); } } catch(...) { PRINTMSG("CATCH: Alloc error!!"); ESMC_LogDefault.AllocError(ESMC_CONTEXT, &rc); + return rc; } - // return - if (ESMC_RC_NOT_IMPL == rc) { - rc = localrc; - } - return (rc); + // return successfully + rc = ESMF_SUCCESS; + return rc; } // end IO::addArray //------------------------------------------------------------------------- From f0a95ac78bf54876180445e2aca42587d2109930 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 5 Aug 2022 11:29:44 -0700 Subject: [PATCH 085/266] XXE to use "unsigned long long int" for size, supporting message messages (>32-bit limit) on this layer. --- .../DELayout/include/ESMCI_DELayout.h | 66 ++++++----- .../DELayout/src/ESMCI_DELayout.C | 104 ++++++++++-------- 2 files changed, 96 insertions(+), 74 deletions(-) diff --git a/src/Infrastructure/DELayout/include/ESMCI_DELayout.h b/src/Infrastructure/DELayout/include/ESMCI_DELayout.h index 9d10001fca..76be29b6d0 100644 --- a/src/Infrastructure/DELayout/include/ESMCI_DELayout.h +++ b/src/Infrastructure/DELayout/include/ESMCI_DELayout.h @@ -524,12 +524,15 @@ class XXE{ int vectorLengthShift); int appendWtimer(int predicateBitField, char *string, int id, int actualId, int relativeId=0, XXE *relativeXXE=NULL); - int appendRecv(int predicateBitField, void *buffer, int size, int srcPet, + int appendRecv(int predicateBitField, void *buffer, + unsigned long long int size, int srcPet, int tag=-1, bool vectorFlag=false, bool indirectionFlag=false); - int appendSend(int predicateBitField, void *buffer, int size, int dstPet, + int appendSend(int predicateBitField, void *buffer, + unsigned long long int size, int dstPet, int tag=-1, bool vectorFlag=false, bool indirectionFlag=false); - int appendSendRRA(int predicateBitField, int rraOffset, int size, - int dstPet, int rraIndex, int tag=-1, bool vectorFlag=false); + int appendSendRRA(int predicateBitField, int rraOffset, + unsigned long long int size, int dstPet, int rraIndex, + int tag=-1, bool vectorFlag=false); int appendSendRecv(int predicateBitField, void *srcBuffer, void *dstBuffer, int srcSize, int dstSize, int srcPet, int dstPet, int srcTag, int dstTag, bool vectorFlag=false, bool srcIndirectionFlag=false, @@ -538,14 +541,17 @@ class XXE{ int srcSize, int dstSize, int srcPet, int dstPet, int rraIndex, int srcTag, int dstTag, bool vectorFlag=false, bool dstIndirectionFlag=false); - int appendRecvnb(int predicateBitField, void *buffer, int size, int srcPet, + int appendRecvnb(int predicateBitField, void *buffer, + unsigned long long int size, int srcPet, int tag=-1, bool vectorFlag=false, bool indirectionFlag=false); - int appendSendnb(int predicateBitField, void *buffer, int size, int dstPet, + int appendSendnb(int predicateBitField, void *buffer, + unsigned long long int size, int dstPet, int tag=-1, bool vectorFlag=false, bool indirectionFlag=false); - int appendSendnbRRA(int predicateBitField, int rraOffset, int size, - int dstPet, int rraIndex, int tag=-1, bool vectorFlag=false); - int appendMemCpySrcRRA(int predicateBitField, int rraOffset, int size, - void *dstMem, int rraIndex); + int appendSendnbRRA(int predicateBitField, int rraOffset, + unsigned long long int size, int dstPet, int rraIndex, + int tag=-1, bool vectorFlag=false); + int appendMemCpySrcRRA(int predicateBitField, int rraOffset, + unsigned long long int size, void *dstMem, int rraIndex); int appendMemGatherSrcRRA(int predicateBitField, void *dstBase, TKId dstBaseTK, int rraIndex, int chunkCount, bool vectorFlag=false, bool indirectionFlag=false); @@ -553,9 +559,11 @@ class XXE{ int rraOffset, int rraIndex); int appendZeroSuperScalarRRA(int predicateBitField, TKId elementTK, int rraIndex, int termCount, bool vectorFlag=false); - int appendZeroMemset(int predicateBitField, void *buffer, int byteCount, - bool vectorFlag=false, bool indirectionFlag=false); - int appendZeroMemsetRRA(int predicateBitField, int byteCount, int rraIndex, + int appendZeroMemset(int predicateBitField, void *buffer, + unsigned long long int byteCount, bool vectorFlag=false, + bool indirectionFlag=false); + int appendZeroMemsetRRA(int predicateBitField, + unsigned long long int byteCount, int rraIndex, bool vectorFlag=false); int appendProductSumScalarRRA(int predicateBitField, TKId elementTK, TKId valueTK, TKId factorTK, int rraOffset, void *factor, void *value, @@ -617,7 +625,7 @@ class XXE{ bool vectorFlag; bool indirectionFlag; void *buffer; - int size; + unsigned long long int size; int tag; }SendInfo; @@ -630,7 +638,7 @@ class XXE{ bool vectorFlag; bool indirectionFlag; void *buffer; - int size; + unsigned long long int size; int tag; }RecvInfo; @@ -642,7 +650,7 @@ class XXE{ int dstPet; bool vectorFlag; int rraOffset; - int size; + unsigned long long int size; int rraIndex; int tag; }SendRRAInfo; @@ -655,7 +663,7 @@ class XXE{ int srcPet; bool vectorFlag; int rraOffset; - int size; + unsigned long long int size; int rraIndex; int tag; }RecvRRAInfo; @@ -706,7 +714,7 @@ class XXE{ bool vectorFlag; bool indirectionFlag; void *buffer; - int size; + unsigned long long int size; int tag; }SendnbInfo; @@ -720,7 +728,7 @@ class XXE{ bool vectorFlag; bool indirectionFlag; void *buffer; - int size; + unsigned long long int size; int tag; }RecvnbInfo; @@ -733,7 +741,7 @@ class XXE{ int dstPet; bool vectorFlag; int rraOffset; - int size; + unsigned long long int size; int rraIndex; int tag; }SendnbRRAInfo; @@ -747,7 +755,7 @@ class XXE{ int srcPet; bool vectorFlag; int rraOffset; - int size; + unsigned long long int size; int rraIndex; int tag; }RecvnbRRAInfo; @@ -960,13 +968,13 @@ class XXE{ bool vectorFlag; bool indirectionFlag; void *buffer; - int byteCount; + unsigned long long int byteCount; }ZeroMemsetInfo; typedef struct{ OpId opId; int predicateBitField; - int byteCount; + unsigned long long int byteCount; int rraIndex; bool vectorFlag; }ZeroMemsetRRAInfo; @@ -976,7 +984,7 @@ class XXE{ int predicateBitField; void *dstMem; void *srcMem; - int size; + unsigned long long int size; }MemCpyInfo; typedef struct{ @@ -984,7 +992,7 @@ class XXE{ int predicateBitField; void *dstMem; int rraOffset; - int size; + unsigned long long int size; int rraIndex; }MemCpySrcRRAInfo; @@ -1070,8 +1078,8 @@ class XXE{ bool vectorFlag; bool indirectionFlag; void *buffer; - int size; - }BuffInfo; + unsigned long long int size; + }BuffInfo; // meta for: SendInfo and RecvInfo typedef struct{ OpId opId; @@ -1083,8 +1091,8 @@ class XXE{ bool vectorFlag; bool indirectionFlag; void *buffer; - int size; - }BuffnbInfo; + unsigned long long int size; + }BuffnbInfo; // meta for: SendnbInfo and RecvnbInfo typedef struct{ OpId opId; diff --git a/src/Infrastructure/DELayout/src/ESMCI_DELayout.C b/src/Infrastructure/DELayout/src/ESMCI_DELayout.C index c12cb14dea..d8c2984538 100644 --- a/src/Infrastructure/DELayout/src/ESMCI_DELayout.C +++ b/src/Infrastructure/DELayout/src/ESMCI_DELayout.C @@ -3902,17 +3902,18 @@ int XXE::exec( char *buffer = (char *)xxeSendInfo->buffer; if (xxeSendInfo->indirectionFlag) buffer = *(char **)xxeSendInfo->buffer; - int size = xxeSendInfo->size; + unsigned long long int size = xxeSendInfo->size; if (xxeSendInfo->vectorFlag) size *= *vectorLength; #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::send: buffer=%p, size=%d, dst=%d, " + sprintf(msg, "XXE::send: buffer=%p, size=%Ld, dst=%d, " "tag=%d, vectorFlag=%d, indirectionFlag=%d", xxeSendInfo->buffer, xxeSendInfo->size, xxeSendInfo->dstPet, xxeSendInfo->tag, xxeSendInfo->vectorFlag, xxeSendInfo->indirectionFlag); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit vm->send(buffer, size, xxeSendInfo->dstPet, xxeSendInfo->tag); xxeSendInfo->activeFlag = true; // set xxeSendInfo->cancelledFlag = false; // set @@ -3924,17 +3925,18 @@ int XXE::exec( char *buffer = (char *)xxeRecvInfo->buffer; if (xxeRecvInfo->indirectionFlag) buffer = *(char **)xxeRecvInfo->buffer; - int size = xxeRecvInfo->size; + unsigned long long int size = xxeRecvInfo->size; if (xxeRecvInfo->vectorFlag) size *= *vectorLength; #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::recv: buffer=%p, size=%d, src=%d, " + sprintf(msg, "XXE::recv: buffer=%p, size=%Ld, src=%d, " "tag=%d, vectorFlag=%d, indirectionFlag=%d", xxeRecvInfo->buffer, xxeRecvInfo->size, xxeRecvInfo->srcPet, xxeRecvInfo->tag, xxeRecvInfo->vectorFlag, xxeRecvInfo->indirectionFlag); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit vm->recv(buffer, size, xxeRecvInfo->srcPet, xxeRecvInfo->tag); xxeRecvInfo->activeFlag = true; // set xxeRecvInfo->cancelledFlag = false; // set @@ -3943,16 +3945,17 @@ int XXE::exec( case sendRRA: { xxeSendRRAInfo = (SendRRAInfo *)xxeElement; - int size = xxeSendRRAInfo->size; + unsigned long long int size = xxeSendRRAInfo->size; int rraOffset = xxeSendRRAInfo->rraOffset; if (xxeSendRRAInfo->vectorFlag){ size *= *vectorLength; rraOffset *= *vectorLength; } #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::sendRRA: size=%d", xxeSendRRAInfo->size); + sprintf(msg, "XXE::sendRRA: size=%Ld", xxeSendRRAInfo->size); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit vm->send(rraList[xxeSendRRAInfo->rraIndex] + rraOffset, size, xxeSendRRAInfo->dstPet, xxeSendRRAInfo->tag); xxeSendRRAInfo->activeFlag = true; // set @@ -3962,16 +3965,17 @@ int XXE::exec( case recvRRA: { xxeRecvRRAInfo = (RecvRRAInfo *)xxeElement; - int size = xxeRecvRRAInfo->size; + unsigned long long int size = xxeRecvRRAInfo->size; int rraOffset = xxeRecvRRAInfo->rraOffset; if (xxeRecvRRAInfo->vectorFlag){ size *= *vectorLength; rraOffset *= *vectorLength; } #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::recvRRA: size=%d", xxeRecvRRAInfo->size); + sprintf(msg, "XXE::recvRRA: size=%Ld", xxeRecvRRAInfo->size); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit vm->recv(rraList[xxeRecvRRAInfo->rraIndex] + rraOffset, size, xxeRecvRRAInfo->srcPet, xxeRecvRRAInfo->tag); xxeRecvRRAInfo->activeFlag = true; // set @@ -4041,16 +4045,16 @@ int XXE::exec( char *buffer = (char *)xxeSendnbInfo->buffer; if (xxeSendnbInfo->indirectionFlag) buffer = *(char **)xxeSendnbInfo->buffer; - int size = xxeSendnbInfo->size; + unsigned long long int size = xxeSendnbInfo->size; if (xxeSendnbInfo->vectorFlag) size *= *vectorLength; #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::sendnb: dst=%d, size=%d, buffer=%p", + sprintf(msg, "XXE::sendnb: dst=%d, size=%Ld, buffer=%p", xxeSendnbInfo->dstPet, size, buffer); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif #ifdef XXE_EXEC_OPSLOG_on - for (int k=0; ksend(buffer, size, xxeSendnbInfo->dstPet, xxeSendnbInfo->commhandle, xxeSendnbInfo->tag); #ifdef XXE_EXEC_MEMLOG_on @@ -4074,14 +4079,15 @@ int XXE::exec( char *buffer = (char *)xxeRecvnbInfo->buffer; if (xxeRecvnbInfo->indirectionFlag) buffer = *(char **)xxeRecvnbInfo->buffer; - int size = xxeRecvnbInfo->size; + unsigned long long int size = xxeRecvnbInfo->size; if (xxeRecvnbInfo->vectorFlag) size *= *vectorLength; #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::recvnb: src=%d, size=%d, buffer=%p", + sprintf(msg, "XXE::recvnb: src=%d, size=%Ld, buffer=%p", xxeRecvnbInfo->srcPet, size, buffer); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit vm->recv(buffer, size, xxeRecvnbInfo->srcPet, xxeRecvnbInfo->commhandle, xxeRecvnbInfo->tag); xxeRecvnbInfo->activeFlag = true; // set @@ -4091,17 +4097,18 @@ int XXE::exec( case sendnbRRA: { xxeSendnbRRAInfo = (SendnbRRAInfo *)xxeElement; - int size = xxeSendnbRRAInfo->size; + unsigned long long int size = xxeSendnbRRAInfo->size; int rraOffset = xxeSendnbRRAInfo->rraOffset; if (xxeSendnbRRAInfo->vectorFlag){ size *= *vectorLength; rraOffset *= *vectorLength; } #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::sendnbRRA: dst=%d, size=%d", + sprintf(msg, "XXE::sendnbRRA: dst=%d, size=%Ld", xxeSendnbRRAInfo->dstPet, size); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit vm->send(rraList[xxeSendnbRRAInfo->rraIndex] + rraOffset, size, xxeSendnbRRAInfo->dstPet, xxeSendnbRRAInfo->commhandle, xxeSendnbRRAInfo->tag); @@ -4112,17 +4119,18 @@ int XXE::exec( case recvnbRRA: { xxeRecvnbRRAInfo = (RecvnbRRAInfo *)xxeElement; - int size = xxeRecvnbRRAInfo->size; + unsigned long long int size = xxeRecvnbRRAInfo->size; int rraOffset = xxeRecvnbRRAInfo->rraOffset; if (xxeRecvnbRRAInfo->vectorFlag){ size *= *vectorLength; rraOffset *= *vectorLength; } #ifdef XXE_EXEC_LOG_on - sprintf(msg, "XXE::recvnbRRA: src=%d, size=%d", + sprintf(msg, "XXE::recvnbRRA: src=%d, size=%Ld", xxeRecvnbRRAInfo->srcPet, size); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit vm->recv(rraList[xxeRecvnbRRAInfo->rraIndex] + rraOffset, size, xxeRecvnbRRAInfo->srcPet, xxeRecvnbRRAInfo->commhandle, xxeRecvnbRRAInfo->tag); @@ -5229,15 +5237,16 @@ printf("gjt - DID NOT CANCEL commhandle\n"); char *buffer = (char *)xxeZeroMemsetInfo->buffer; if (xxeZeroMemsetInfo->indirectionFlag) buffer = *(char **)xxeZeroMemsetInfo->buffer; - int byteCount = xxeZeroMemsetInfo->byteCount; + unsigned long long int byteCount = xxeZeroMemsetInfo->byteCount; if(xxeZeroMemsetInfo->vectorFlag) byteCount *= *vectorLength; #ifdef XXE_EXEC_LOG_on sprintf(msg, "XXE::zeroMemset: indirectionFlag=%d, buffer=%p, " - "vectorFlag=%d, byteCount=%d", xxeZeroMemsetInfo->indirectionFlag, + "vectorFlag=%d, byteCount=%Ld", xxeZeroMemsetInfo->indirectionFlag, buffer, xxeZeroMemsetInfo->vectorFlag, byteCount); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit memset(buffer, 0, byteCount); } break; @@ -5246,21 +5255,23 @@ printf("gjt - DID NOT CANCEL commhandle\n"); xxeZeroMemsetRRAInfo = (ZeroMemsetRRAInfo *)xxeElement; char *rraBase = rraList[xxeZeroMemsetRRAInfo->rraIndex]; - int byteCount = xxeZeroMemsetRRAInfo->byteCount; + unsigned long long int byteCount = xxeZeroMemsetRRAInfo->byteCount; if(xxeZeroMemsetRRAInfo->vectorFlag) byteCount *= *vectorLength; #ifdef XXE_EXEC_LOG_on sprintf(msg, "XXE::zeroMemsetRRA: rraBase=%p, " - "vectorFlag=%d, byteCount=%d", rraBase, + "vectorFlag=%d, byteCount=%Ld", rraBase, xxeZeroMemsetRRAInfo->vectorFlag, byteCount); ESMC_LogDefault.Write(msg, ESMC_LOGMSG_DEBUG); #endif +//TODO: 32-bit limit memset(rraBase, 0, byteCount); } break; case memCpy: { xxeMemCpyInfo = (MemCpyInfo *)xxeElement; +//TODO: 32-bit limit memcpy(xxeMemCpyInfo->dstMem, xxeMemCpyInfo->srcMem, xxeMemCpyInfo->size); } @@ -5268,6 +5279,7 @@ printf("gjt - DID NOT CANCEL commhandle\n"); case memCpySrcRRA: { xxeMemCpySrcRRAInfo = (MemCpySrcRRAInfo *)xxeElement; +//TODO: 32-bit limit memcpy(xxeMemCpySrcRRAInfo->dstMem, rraList[xxeMemCpySrcRRAInfo->rraIndex] + xxeMemCpySrcRRAInfo->rraOffset, @@ -5283,7 +5295,7 @@ printf("gjt - DID NOT CANCEL commhandle\n"); char *rraBase = rraList[xxeMemGatherSrcRRAInfo->rraIndex]; int *rraOffsetList = xxeMemGatherSrcRRAInfo->rraOffsetList; int *countList = xxeMemGatherSrcRRAInfo->countList; - int vectorL = 1; // initialize + unsigned long long int vectorL = 1; // initialize if (xxeMemGatherSrcRRAInfo->vectorFlag) vectorL = *vectorLength; bool superVector = (xxeMemGatherSrcRRAInfo->vectorFlag @@ -5304,7 +5316,7 @@ printf("gjt - DID NOT CANCEL commhandle\n"); } #ifdef XXE_EXEC_LOG_on sprintf(msg, "XXE::memGatherSrcRRA: dstBaseTK=%d, vectorFlag=%d, " - "vectorL=%d, srcSuperVecSize_r=%d, superVectorOkay=%d", + "vectorL=%Ld, srcSuperVecSize_r=%d, superVectorOkay=%d", xxeMemGatherSrcRRAInfo->dstBaseTK, xxeMemGatherSrcRRAInfo->vectorFlag, vectorL, srcSuperVecSize_r, @@ -5366,9 +5378,11 @@ printf("gjt - DID NOT CANCEL commhandle\n"); { char *dstPointer = dstBase; for (int k=0; kchunkCount; k++){ - memcpy(dstPointer, rraBase + rraOffsetList[k] * vectorL, - countList[k] * vectorL); - dstPointer += countList[k] * vectorL; +//TODO: 32-bit limit + unsigned long long int size = vectorL; + size *= countList[k]; + memcpy(dstPointer, rraBase + rraOffsetList[k] * vectorL, size); + dstPointer += size; } } break; @@ -7738,7 +7752,7 @@ int XXE::print( case send: { xxeSendInfo = (SendInfo *)xxeElement; - fprintf(fp, " XXE::send: buffer=%p, size=%d, dst=%d, " + fprintf(fp, " XXE::send: buffer=%p, size=%Ld, dst=%d, " "tag=%d, vectorFlag=%d, indirectionFlag=%d\n", xxeSendInfo->buffer, xxeSendInfo->size, xxeSendInfo->dstPet, xxeSendInfo->tag, xxeSendInfo->vectorFlag, @@ -7748,7 +7762,7 @@ int XXE::print( case recv: { xxeRecvInfo = (RecvInfo *)xxeElement; - fprintf(fp, " XXE::recv: buffer=%p, size=%d, src=%d, " + fprintf(fp, " XXE::recv: buffer=%p, size=%Ld, src=%d, " "tag=%d, vectorFlag=%d, indirectionFlag=%d\n", xxeRecvInfo->buffer, xxeRecvInfo->size, xxeRecvInfo->srcPet, xxeRecvInfo->tag, xxeRecvInfo->vectorFlag, @@ -7758,7 +7772,7 @@ int XXE::print( case sendRRA: { xxeSendRRAInfo = (SendRRAInfo *)xxeElement; - fprintf(fp, " XXE::sendRRA: rraOffset=%d, size=%d, " + fprintf(fp, " XXE::sendRRA: rraOffset=%d, size=%Ld, " "dst=%d, rraIndex=%d, tag=%d, vectorFlag=%d\n", xxeSendRRAInfo->rraOffset, xxeSendRRAInfo->size, xxeSendRRAInfo->dstPet, xxeSendRRAInfo->rraIndex, @@ -7768,7 +7782,7 @@ int XXE::print( case recvRRA: { xxeRecvRRAInfo = (RecvRRAInfo *)xxeElement; - fprintf(fp, " XXE::recvRRA: rraOffset=%d, size=%d, " + fprintf(fp, " XXE::recvRRA: rraOffset=%d, size=%Ld, " "src=%d, rraIndex=%d, tag=%d, vectorFlag=%d\n", xxeRecvRRAInfo->rraOffset, xxeRecvRRAInfo->size, xxeRecvRRAInfo->srcPet, xxeRecvRRAInfo->rraIndex, @@ -7778,7 +7792,7 @@ int XXE::print( case sendnb: { xxeSendnbInfo = (SendnbInfo *)xxeElement; - fprintf(fp, " XXE::sendnb: buffer=%p, size=%d, dst=%d, " + fprintf(fp, " XXE::sendnb: buffer=%p, size=%Ld, dst=%d, " "tag=%d, vectorFlag=%d, indirectionFlag=%d, commhandle=%p\n", xxeSendnbInfo->buffer, xxeSendnbInfo->size, xxeSendnbInfo->dstPet, xxeSendnbInfo->tag, xxeSendnbInfo->vectorFlag, @@ -7788,7 +7802,7 @@ int XXE::print( case recvnb: { xxeRecvnbInfo = (RecvnbInfo *)xxeElement; - fprintf(fp, " XXE::recvnb: buffer=%p, size=%d, src=%d, " + fprintf(fp, " XXE::recvnb: buffer=%p, size=%Ld, src=%d, " "tag=%d, vectorFlag=%d, indirectionFlag=%d, commhandle=%p\n", xxeRecvnbInfo->buffer, xxeRecvnbInfo->size, xxeRecvnbInfo->srcPet, xxeRecvnbInfo->tag, xxeRecvnbInfo->vectorFlag, @@ -7798,7 +7812,7 @@ int XXE::print( case sendnbRRA: { xxeSendnbRRAInfo = (SendnbRRAInfo *)xxeElement; - fprintf(fp, " XXE::sendnbRRA: rraOffset=%d, size=%d, " + fprintf(fp, " XXE::sendnbRRA: rraOffset=%d, size=%Ld, " "dst=%d, rraIndex=%d, tag=%d, vectorFlag=%d, commhandle=%p\n", xxeSendnbRRAInfo->rraOffset, xxeSendnbRRAInfo->size, xxeSendnbRRAInfo->dstPet, xxeSendnbRRAInfo->rraIndex, @@ -7809,7 +7823,7 @@ int XXE::print( case recvnbRRA: { xxeRecvnbRRAInfo = (RecvnbRRAInfo *)xxeElement; - fprintf(fp, " XXE::recvnbRRA: rraOffset=%d, size=%d, " + fprintf(fp, " XXE::recvnbRRA: rraOffset=%d, size=%Ld, " "src=%d, rraIndex=%d, tag=%d, vectorFlag=%d, commhandle=%p\n", xxeRecvnbRRAInfo->rraOffset, xxeRecvnbRRAInfo->size, xxeRecvnbRRAInfo->srcPet, xxeRecvnbRRAInfo->rraIndex, @@ -7980,7 +7994,7 @@ int XXE::print( case zeroMemset: { xxeZeroMemsetInfo = (ZeroMemsetInfo *)xxeElement; - fprintf(fp, " XXE::zeroMemset buffer=%p, byteCount=%d, " + fprintf(fp, " XXE::zeroMemset buffer=%p, byteCount=%Ld, " "vectorFlag=%d, indirectionFlag=%d\n", xxeZeroMemsetInfo->buffer, xxeZeroMemsetInfo->byteCount, xxeZeroMemsetInfo->vectorFlag, @@ -7990,7 +8004,7 @@ int XXE::print( case zeroMemsetRRA: { xxeZeroMemsetRRAInfo = (ZeroMemsetRRAInfo *)xxeElement; - fprintf(fp, " XXE::zeroMemsetRRA byteCount=%d, " + fprintf(fp, " XXE::zeroMemsetRRA byteCount=%Ld, " "rraIndex=%d, vectorFlag=%d\n", xxeZeroMemsetRRAInfo->byteCount, xxeZeroMemsetRRAInfo->rraIndex, xxeZeroMemsetRRAInfo->vectorFlag); @@ -9711,7 +9725,7 @@ int XXE::appendRecv( // int predicateBitField, void *buffer, - int size, + unsigned long long int size, int srcPet, int tag, bool vectorFlag, @@ -9766,7 +9780,7 @@ int XXE::appendSend( // int predicateBitField, void *buffer, - int size, + unsigned long long int size, int dstPet, int tag, bool vectorFlag, @@ -9821,7 +9835,7 @@ int XXE::appendSendRRA( // int predicateBitField, int rraOffset, - int size, + unsigned long long int size, int dstPet, int rraIndex, int tag, @@ -10006,7 +10020,7 @@ int XXE::appendRecvnb( // int predicateBitField, void *buffer, - int size, + unsigned long long int size, int srcPet, int tag, bool vectorFlag, @@ -10068,7 +10082,7 @@ int XXE::appendSendnb( // int predicateBitField, void *buffer, - int size, + unsigned long long int size, int dstPet, int tag, bool vectorFlag, @@ -10130,7 +10144,7 @@ int XXE::appendSendnbRRA( // int predicateBitField, int rraOffset, - int size, + unsigned long long int size, int dstPet, int rraIndex, int tag, @@ -10192,7 +10206,7 @@ int XXE::appendMemCpySrcRRA( // int predicateBitField, int rraOffset, - int size, + unsigned long long int size, void *dstMem, int rraIndex ){ @@ -10412,7 +10426,7 @@ int XXE::appendZeroMemset( // int predicateBitField, void *buffer, - int byteCount, + unsigned long long int byteCount, bool vectorFlag, bool indirectionFlag ){ @@ -10461,7 +10475,7 @@ int XXE::appendZeroMemsetRRA( // !ARGUMENTS: // int predicateBitField, - int byteCount, + unsigned long long int byteCount, int rraIndex, bool vectorFlag ){ From 9aa622e484614ad790e11e2eca4829f85d0417b2 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 5 Aug 2022 12:07:06 -0700 Subject: [PATCH 086/266] Additional guidance on compiler combinations. Add Clang to the list. --- src/doc/ESMF_systemreq.tex | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/doc/ESMF_systemreq.tex b/src/doc/ESMF_systemreq.tex index 4cc19954ff..f5880f2cd3 100644 --- a/src/doc/ESMF_systemreq.tex +++ b/src/doc/ESMF_systemreq.tex @@ -2,8 +2,10 @@ The following compilers and utilities are required for compiling, linking and -testing the ESMF software. Some combinations of Fortran and C++ compilers, -e.g. Intel ifort with GNU g++, are supported. +testing the ESMF software. It is good common practice to use a consistent set +of Fortran/C++/C compilers from the same vendor, e.g. GNU, Intel, etc. +However, some vendor {\em combinations} of Fortran, C++, and C compilers, +e.g. Intel ifort with GNU g++, are also supported. \begin{itemize} \item Fortran compiler: \begin{itemize} @@ -23,6 +25,7 @@ \item NVHPC's nvc++, or \item IBM's xlC, or \item CCE's CC. + \item LLVM's clang \end{itemize} \item C compiler: \begin{itemize} @@ -32,6 +35,7 @@ \item NVHPC's nvcc, or \item IBM's xlc, or \item CCE's cc. + \item LLVM's clang \end{itemize} \item MPI implementation compatible with the above compilers (but also see below for the MPI-bypass build option): From 0de4558e1e11e31382976ee8a41dd37f22d7f2f2 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 5 Aug 2022 12:11:03 -0700 Subject: [PATCH 087/266] Set VM_EPOCHMEMLOG_off. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 0425ebf42c..5f33248600 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -20,7 +20,7 @@ #define VM_MEMLOG_off #define VM_COMMQUEUELOG_off #define VM_EPOCHLOG_on -#define VM_EPOCHMEMLOG_on +#define VM_EPOCHMEMLOG_off #define VM_SSISHMLOG_off #define VM_SIZELOG_on From 81d571218b114d1f13781870b251ea00f1b4a428 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 7 Aug 2022 07:16:47 -0600 Subject: [PATCH 088/266] Detect number of tiles in arrays for I/O Auto-detect the number of tiles in arrays being written or read, and check to confirm that all arrays handled by a given IO object have the same number of tiles (which is a requirement for now that could possibly be relaxed later). --- src/Infrastructure/IO/include/ESMCI_IO.h | 58 ++++++++- .../IO/include/ESMCI_IO_Handler.h | 11 +- .../IO/include/ESMCI_PIO_Handler.h | 2 +- src/Infrastructure/IO/src/ESMCI_IO.C | 120 +++++++++++++++++- src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 59 +++++++-- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 13 +- 6 files changed, 242 insertions(+), 21 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_IO.h b/src/Infrastructure/IO/include/ESMCI_IO.h index de62e41fb4..7a84395753 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO.h +++ b/src/Infrastructure/IO/include/ESMCI_IO.h @@ -132,12 +132,38 @@ namespace ESMCI { // global information IO_Handler *ioHandler; std::vector objects; + + // All of the arrays handled by a given IO_Handler must have the same number + // of tiles. Since an IO object only contains a single IO_Handler, this + // implies that a given IO object is associated with a specific number of + // tiles in the arrays it can read and write. We could relax that + // restriction in the future by having multiple IO_Handlers, each handling a + // different number of tiles. + int ntiles; // Number of tiles in arrays handled by this object + // (should only be accessed via getNtiles(), even + // internally) + bool ntilesIsLocked; // Once ntiles has been set explicitly or queried for + // any purpose, it cannot be changed further; + // ntilesIsLocked indicates that state. public: // native constructor and destructor IO(int *rc = NULL) { ioHandler = (IO_Handler *)NULL; // No constructor call for objects -- use default Allocator + + // Start by assuming ntiles = 1. Typically we expect this to be set + // explicitly via a call to setOrCheckNtiles before it is accessed. + // However, there are some theoretical cases where setOrCheckNtiles may + // not be called, such as writing a file that doesn't contain any arrays + // (just attributes / metadata). In these cases, we want to default to the + // single-tile case. However, we want to ensure that a given IO object + // always uses the same value of ntiles - so once we have explicitly set + // ntiles or have done any operations that depend on ntiles (such as + // opening a file), the ntiles value becomes locked and cannot be changed. + // The ntilesIsLocked variable tracks this state. + ntiles = 1; + ntilesIsLocked = false; // return successfully if (rc != NULL) { *rc = ESMF_SUCCESS; @@ -238,9 +264,39 @@ namespace ESMCI { const ESMC_AttReconcileFlag &attreconflag); #endif // TBI + private: + const int getNtiles(void) { + // Once ntiles has been queried for any reason, it becomes locked and cannot be + // changed. (See comment in the constructor for more details.) + ntilesIsLocked = true; + return ntiles; + } + + // If ntiles has not yet been set (i.e., this function has not yet been + // called), then set ntiles to the given value. If ntiles has already been + // set, then verify that ntiles matches the already-set value; if it + // doesn't, return an error via the return value. Note that all arrays + // handled by this IO object must have the same number of tiles; to confirm + // that this is the case, this function should be called for each array, + // specifying the number of tiles for that array. + // + // If this IO object will be handling multi-tile arrays, then this function + // must be called before calling open or any other function that depends on + // the number of tiles. + int setOrCheckNtiles(int ntiles_arg); + + // Verify that the given value of ntiles matches the already-set ntiles (set + // via a prior call to setOrCheckNtiles); if it doesn't, return an error via + // the return value. (Note that all arrays handled by this IO object must + // have the same number tiles.) + // + // It is often better to use setOrCheckNtiles, since that version will set + // ntiles if it hasn't already been set; this version is meant only for the + // situation where ntiles should already have been set previously. + int checkNtiles(int ntiles_arg) const; + // Don't know yet if we will need these #if 0 - private: // Attribute writing int writeStartElement(const std::string& name, const std::string& value, diff --git a/src/Infrastructure/IO/include/ESMCI_IO_Handler.h b/src/Infrastructure/IO/include/ESMCI_IO_Handler.h index 3769716445..2af7a2b67b 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_Handler.h @@ -74,16 +74,16 @@ namespace ESMCI { bool overwrite; // OK to overwrite fields if true int ntiles; // Number of tiles in arrays handled by this object protected: - IO_Handler(ESMC_IOFmt_Flag fmtArg); // native constructor + IO_Handler(ESMC_IOFmt_Flag fmtArg, int ntilesArg); // native constructor private: // IO(ESMC_IOFmt_Flag fmtArg, int rank, int *rc); protected: ~IO_Handler() { destruct(); } // create() and destroy() public: - static IO_Handler *create(ESMC_IOFmt_Flag iofmt, int *rc = NULL); + static IO_Handler *create(ESMC_IOFmt_Flag iofmt, int ntiles, int *rc = NULL); static IO_Handler *create(const std::string& file, - ESMC_IOFmt_Flag iofmt, int *rc = NULL); + ESMC_IOFmt_Flag iofmt, int ntiles, int *rc = NULL); static int destroy(IO_Handler **io); static void finalize(int *rc = NULL); private: @@ -139,9 +139,12 @@ namespace ESMCI { return (ioh1 == ioh2); } - // open() and close() + // open(), close() and helper functions protected: virtual void open(bool readonly_arg, int *rc = NULL) = 0; + + // Check compatibility of an array with this IO Handler object; return error if incompatible + int checkArray(const Array *arr_p) const; public: void open(const std::string &file, ESMC_FileStatus_Flag filestatusflag_arg, diff --git a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h index d46f096749..cec44fe3a5 100644 --- a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h @@ -83,7 +83,7 @@ namespace ESMCI { public: // native constructor and destructor - PIO_Handler(ESMC_IOFmt_Flag fmtArg, int *rc); + PIO_Handler(ESMC_IOFmt_Flag fmtArg, int ntilesArg, int *rc); // Static initialize and finalize routines for PIO static void initialize(int comp_rank, MPI_Comm comp_comm, int num_iotasks, diff --git a/src/Infrastructure/IO/src/ESMCI_IO.C b/src/Infrastructure/IO/src/ESMCI_IO.C index 24f98c0f80..1157397ce4 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO.C +++ b/src/Infrastructure/IO/src/ESMCI_IO.C @@ -779,9 +779,13 @@ int IO::open( bool readonly // (in) - If false then read/write ) { // !DESCRIPTION: -// Open a file or stream for I/O. Create a new IO_Handler if necessary -// It is an error if a handler exists with a different I/O format (iofmt) -// It is an error if the IO_Handler is already connected to an open stream +// Open a file or stream for I/O. Create a new IO_Handler if necessary. +// It is an error if a handler exists with a different I/O format (iofmt). +// It is an error if the IO_Handler is already connected to an open stream. +// If this IO object may be used to read / write multi-tile arrays, then +// those arrays must be added via a call to addArray before calling this +// open function (so that we can open the appropriate files for multi-tile +// I/O). // //EOP //----------------------------------------------------------------------------- @@ -800,7 +804,7 @@ int IO::open( // Ensure that we have an IO_Handler (create if necessary) if ((IO_Handler *)NULL == ioHandler) { - ioHandler = IO_Handler::create(file, iofmt, &localrc); + ioHandler = IO_Handler::create(file, iofmt, getNtiles(), &localrc); if (ESMF_SUCCESS != localrc) { PRINTMSG("IO_Handler::create returned " << localrc); ioHandler = (IO_Handler *)NULL; @@ -1018,6 +1022,15 @@ int IO::addArray( return localrc; } + // Confirm that this array has the same number of tiles as other arrays that + // have been added to this IO object, or set the number of tiles if it hasn't + // yet been set. (See some comments about ntiles in ESMCI_IO.h for more + // details.) + int thisNtiles = arr_p->getDistGrid()->getTileCount(); + localrc = setOrCheckNtiles(thisNtiles); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &rc)) + return rc; + // Push Array onto the list try { IO_ObjectContainer *newObj = new IO_ObjectContainer((Array *)arr_p, @@ -1436,4 +1449,103 @@ void IO::clear(void) { } // end IO::close //------------------------------------------------------------------------- +//------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO::setOrCheckNtiles()" +//BOPI +// !IROUTINE: IO::setOrCheckNtiles - Set or check the ntiles value +// +// !INTERFACE: +int IO::setOrCheckNtiles( +// +// !RETURN VALUE: +// int return code +// +// !ARGUMENTS: + int ntiles_arg // (in) - number of tiles to set or check + ) { +// +// !DESCRIPTION: +// If ntiles has not yet been set (i.e., this function has not yet been +// called), then set ntiles to the given value. If ntiles has already been +// set, then verify that ntiles matches the already-set value; if it +// doesn't, return an error via the return value. Note that all arrays +// handled by this IO object must have the same number of tiles; to confirm +// that this is the case, this function should be called for each array, +// specifying the number of tiles for that array. +// +// If this IO object will be handling multi-tile arrays, then this function +// must be called before calling open or any other function that depends on +// the number of tiles. +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + int rc = ESMC_RC_NOT_IMPL; // final return code + + if (!ntilesIsLocked) { + // ntiles hasn't been set on this object yet; set it and mark it as locked + ntiles = ntiles_arg; + ntilesIsLocked = true; + rc = ESMF_SUCCESS; + return rc; + } else { + // ntiles has already been set; verify that the new ntiles value matches the + // already-set value (because all arrays handled by a given IO object must + // have the same number of tiles) + int localrc = checkNtiles(ntiles_arg); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &rc)) + return rc; + rc = ESMF_SUCCESS; + return rc; + } +} // end IO::setOrCheckNtiles +//------------------------------------------------------------------------- + +//------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO::checkNtiles()" +//BOPI +// !IROUTINE: IO::checkNtiles - Check the ntiles value +// +// !INTERFACE: +int IO::checkNtiles( +// +// !RETURN VALUE: +// int return code +// +// !ARGUMENTS: + int ntiles_arg // (in) - number of tiles to check + )const{ +// +// !DESCRIPTION: +// Verify that the given value of ntiles matches the already-set ntiles (set +// via a prior call to setOrCheckNtiles); if it doesn't, return an error via +// the return value. (Note that all arrays handled by this IO object must +// have the same number tiles.) +// +// It is often better to use setOrCheckNtiles, since that version will set +// ntiles if it hasn't already been set; this version is meant only for the +// situation where ntiles should already have been set previously. +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + int rc = ESMC_RC_NOT_IMPL; // final return code + + if (ntiles_arg == ntiles) { + rc = ESMF_SUCCESS; + return rc; + } else { + std::stringstream errmsg; + errmsg << "New number of tiles (" << ntiles_arg + << ") does not match previously-set number of tiles (" << ntiles + << ") for this IO object. All arrays handled by a given IO object " + << "must have the same number of tiles."; + ESMC_LogDefault.MsgFoundError(ESMF_RC_VAL_WRONG, errmsg, ESMC_CONTEXT, &rc); + return rc; + } +} // end IO::checkNtiles +//------------------------------------------------------------------------- + } // end namespace ESMCI diff --git a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C index 729f968491..7d3286a6bd 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C @@ -70,7 +70,8 @@ IO_Handler::IO_Handler ( // // // !ARGUMENTS: - ESMC_IOFmt_Flag fmtArg // (in) - the desired I/O format + ESMC_IOFmt_Flag fmtArg, // (in) - the desired I/O format + int ntilesArg // (in) - the number of tiles in arrays handled by this object // ) { // @@ -85,11 +86,7 @@ IO_Handler::IO_Handler ( fileStatusFlag = ESMC_FILESTATUS_UNKNOWN; overwrite = false; filename[0] = '\0'; - // FIXME(wjs, 2022-07-25) Determine ntiles dynamically, here or later; for now we'll fix - // at 6 for testing. If we end up setting it dynamically elsewhere, then it should be - // initialized to 1 here. - ntiles = 6; - + ntiles = ntilesArg; } //----------------------------------------------------------------------------- @@ -114,13 +111,14 @@ IO_Handler *IO_Handler::create ( // // !ARGUMENTS: ESMC_IOFmt_Flag iofmt, // (in) the desired I/O format + int ntiles, // (in) the number of tiles in arrays handled by this object // int *rc // (out) return code ) { // // !DESCRIPTION: // Create an initialized {\tt IO_Handler} object of the correct type for -// the specified I/O format (iofmt). +// the specified I/O format (iofmt) and number of tiles (ntiles). //EOPI //----------------------------------------------------------------------------- // initialize return code; assume routine not implemented @@ -147,7 +145,7 @@ IO_Handler *IO_Handler::create ( // No break case ESMF_IOFMT_NETCDF4C: #if defined(ESMF_PIO) && (defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)) - iohandler = new PIO_Handler(iofmt, &localrc); + iohandler = new PIO_Handler(iofmt, ntiles, &localrc); #else // defined(ESMF_PIO) && (defined(ESMF_NETCDF) || defined(ESMF_PNETCDF)) errmsg = "PIO & (P)NetCDF libraries required for I/O operation"; localrc = ESMF_RC_LIB_NOT_PRESENT; @@ -202,13 +200,14 @@ IO_Handler *IO_Handler::create ( // !ARGUMENTS: const std::string& file, // (in) A file for Handler ESMC_IOFmt_Flag iofmt, // (in) the desired I/O format + int ntiles, // (in) the number of tiles in arrays handled by this object // int *rc // (out) return code ) { // // !DESCRIPTION: // Create an initialized {\tt IO_Handler} object of the correct type for -// the specified I/O format (iofmt). +// the specified I/O format (iofmt) and number of tiles (ntiles). //EOPI //----------------------------------------------------------------------------- // initialize return code; assume routine not implemented @@ -217,7 +216,7 @@ IO_Handler *IO_Handler::create ( *rc = ESMF_RC_NOT_IMPL; // final return code } - IO_Handler *iohandler = IO_Handler::create(iofmt, &localrc); + IO_Handler *iohandler = IO_Handler::create(iofmt, ntiles, &localrc); if (ESMC_NULL_POINTER != iohandler) iohandler->filename = file; @@ -549,6 +548,46 @@ bool IO_Handler::fileExists( } // end IO_Handler::fileExists //------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO_Handler::checkArray()" +//BOPI +// !IROUTINE: IO_Handler::checkArray - Check compatibility of an array with this object +// +// !INTERFACE: +int IO_Handler::checkArray( +// +// !RETURN VALUE: +// int error return code +// +// !ARGUMENTS: + const Array *arr_p // (in) - array to check + )const{ +// +// !DESCRIPTION: +// Checks compatibility of an array with this IO Handler object (correct number of tiles). +// Returns an error code if incompatible. +// +//EOPI +//----------------------------------------------------------------------------- + // initialize return code; assume routine not implemented + int rc = ESMC_RC_NOT_IMPL; // final return code + + int thisNtiles = arr_p->getDistGrid()->getTileCount(); + if (thisNtiles == ntiles) { + rc = ESMF_SUCCESS; + return rc; + } else { + std::stringstream errmsg; + errmsg << "Number of tiles in array for IO (" << thisNtiles + << ") does not match this IO Handler's ntiles value (" << ntiles + << "). All arrays handled by a given IO handler must have the same " + << "number of tiles."; + ESMC_LogDefault.MsgFoundError(ESMF_RC_VAL_WRONG, errmsg, ESMC_CONTEXT, &rc); + return rc; + } +} // end IO_Handler::checkArray +//------------------------------------------------------------------------- //------------------------------------------------------------------------- #undef ESMC_METHOD diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index f0224a215b..caa1ca92ab 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -466,8 +466,9 @@ PIO_Handler::PIO_Handler( // !ARGUMENTS: // ESMC_IOFmt_Flag fmtArg, // (in) - File format for PIO to use + int ntilesArg, // (in) - Number of tiles in arrays handled by this object int *rc // (out) - Error return code - ) : IO_Handler(fmtArg) { + ) : IO_Handler(fmtArg, ntilesArg) { // // !DESCRIPTION: // Construct the internal information structure of an ESMCI::PIO_Handler @@ -603,6 +604,11 @@ void PIO_Handler::arrayRead( 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; + // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 localDE = 0; @@ -793,6 +799,11 @@ void PIO_Handler::arrayWrite( 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; + iodesc = getIODesc(pioSystemDesc, arr_p, &ioDims, &nioDims, &arrDims, &narrDims, &basepiotype, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, From d14703615cc76a4c5c741381bfa691a14563d90c Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 7 Aug 2022 07:25:14 -0600 Subject: [PATCH 089/266] Add some comments --- src/Infrastructure/IO/src/ESMCI_IO.C | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Infrastructure/IO/src/ESMCI_IO.C b/src/Infrastructure/IO/src/ESMCI_IO.C index 1157397ce4..47372e0654 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO.C +++ b/src/Infrastructure/IO/src/ESMCI_IO.C @@ -971,6 +971,8 @@ int IO::addArray( // !DESCRIPTION: // Add an array to the list of objects to read or write. // {\tt arr_p} is required +// If any arrays have multiple tiles, all arrays handled by a given IO +// object must have the same number of tiles. // //EOP //----------------------------------------------------------------------------- @@ -1006,6 +1008,8 @@ int IO::addArray( // {\tt dimAttPack} optional Attribute package for dimension names // {\tt varAttPack} optional Attribute package for variable attributes // {\tt gblAttPack} optional Attribute package for global attributes +// If any arrays have multiple tiles, all arrays handled by a given IO +// object must have the same number of tiles. // //EOP //----------------------------------------------------------------------------- From 7d8086bb5fa7c2260afafe434fed5aa00f5c278c Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 7 Aug 2022 16:31:30 -0600 Subject: [PATCH 090/266] Have separate IO Descriptors for each tile --- .../IO/include/ESMCI_PIO_Handler.h | 2 +- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 46 +++++++++++-------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h index cec44fe3a5..d61aacd4b9 100644 --- a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h @@ -140,7 +140,7 @@ namespace ESMCI { void close(int *rc = NULL); private: - int getIODesc(int iosys, Array *arr_p, + int getIODesc(int iosys, Array *arr_p, int tile, int ** iodims = (int **)NULL, int *nioDims = (int *)NULL, int ** arrdims = (int **)NULL, diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index caa1ca92ab..5c81295433 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -81,6 +81,7 @@ namespace ESMCI int *dims; // The shape of the Array IO 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 int arrayRank; // The rank of array_p int *arrayShape; // The shape of array_p public: @@ -90,6 +91,7 @@ namespace ESMCI array_p = arrayArg; nDims = 0; dims = (int *)NULL; + tile = 0; arrayRank = 0; arrayShape = (int *)NULL; } @@ -97,7 +99,7 @@ namespace ESMCI public: ~PIO_IODescHandler(); static void finalize(void); - static int constructPioDecomp(int iosys, Array *arr_p, + static int constructPioDecomp(int iosys, Array *arr_p, int tile, int *newDecomp_p); static int freePioDecomp(int *decomp_p); static int getDims(const int &iodesc, @@ -107,7 +109,7 @@ namespace ESMCI int ** arrDims = (int **)NULL); static int getIOType(const int &iodesc, int *rc = (int *)NULL); static int getIODesc(int iosys, - Array *arrayArg, int *rc = (int *)NULL); + Array *arrayArg, int tileArg, int *rc = (int *)NULL); }; // @@ -609,6 +611,9 @@ void PIO_Handler::arrayRead( if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; + // FIXME(wjs, 2022-07-22) Add loop over tiles + int tile = 1; + // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 localDE = 0; @@ -622,7 +627,7 @@ void PIO_Handler::arrayRead( int nDims; // If frame >= 0 then we need to not use the unlimited dim in the iodesc. - iodesc = getIODesc(pioSystemDesc, arr_p, &ioDims, &nioDims, + iodesc = getIODesc(pioSystemDesc, arr_p, tile, &ioDims, &nioDims, &arrDims, &narrDims, &basepiotype, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; @@ -690,9 +695,6 @@ void PIO_Handler::arrayRead( return; } if (*timeslice > time_len) { - // FIXME(wjs, 2022-07-26) Hard-coding tile here for now because it's needed for - // the interface. Eventually we'll get it as an argument or in a loop. - int tile = 1; PRINTMSG(" (" << my_rank << "): " << "Timeframe is greater than that in file" << getFilename(tile) << ", file time = " << time_len << @@ -804,7 +806,9 @@ void PIO_Handler::arrayWrite( if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; - iodesc = getIODesc(pioSystemDesc, arr_p, &ioDims, &nioDims, + // FIXME(wjs, 2022-07-22) Add loop over tiles + int tile = 1; + iodesc = getIODesc(pioSystemDesc, arr_p, tile, &ioDims, &nioDims, &arrDims, &narrDims, &basepiotype, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; @@ -826,8 +830,6 @@ void PIO_Handler::arrayWrite( // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 localDE = 0; - // FIXME(wjs, 2022-07-22) Add loop over tiles - int tile = 1; int tileOfThisDe = arr_p->getDistGrid()->getTilePLocalDe(localDE, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; @@ -1655,6 +1657,7 @@ void PIO_Handler::close( // int iosys, // (in) - PIO system handle to use Array *arr_p, // (in) - Array for IO decompomposition + int tile, // (in) - Tile number in array int ** ioDims, // (out) - Array shape for IO int *nioDims, // (out) - Rank of Array IO int ** arrDims, // (out) - Array shape for IO @@ -1677,11 +1680,11 @@ void PIO_Handler::close( } PRINTPOS; - new_io_desc = PIO_IODescHandler::getIODesc(iosys, arr_p, &localrc); + new_io_desc = PIO_IODescHandler::getIODesc(iosys, arr_p, tile, &localrc); if ((int)NULL == new_io_desc) { PRINTMSG("calling constructPioDecomp"); localrc = PIO_IODescHandler::constructPioDecomp(iosys, - arr_p, &new_io_desc); + arr_p, tile, &new_io_desc); PRINTMSG("constructPioDecomp call complete" << ", localrc = " << localrc); } if ((ioDims != (int **)NULL) || (nioDims != (int *)NULL) || @@ -1908,8 +1911,9 @@ int PIO_IODescHandler::constructPioDecomp( // // !ARGUMENTS: // - int iosys, // (in) - PIO system handle to use - Array *arr_p, // (in) - Array for IO decompomposition + int iosys, // (in) - PIO system handle to use + Array *arr_p, // (in) - Array for IO decompomposition + int tile, // (in) - Tile number in array int *newDecomp_p // (out) - New decomposition descriptor ) { // @@ -1938,6 +1942,11 @@ int PIO_IODescHandler::constructPioDecomp( 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); @@ -1956,9 +1965,6 @@ int PIO_IODescHandler::constructPioDecomp( return ESMF_RC_NOT_IMPL; } - // FIXME(wjs, 2022-07-20) Do we need a tile argument to this function (replacing the - // local tile variable)? Otherwise, need to have a loop over tiles. - int tile = 1; // TODO: To support multiple DEs per PE, we would need to extend this to be an array bool thisDeIsThisTile = false; @@ -2051,6 +2057,7 @@ int PIO_IODescHandler::constructPioDecomp( 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(); @@ -2333,8 +2340,9 @@ int PIO_IODescHandler::getIODesc( // !ARGUMENTS: // int iosys, // (in) - The PIO IO system - Array *arrayArg, // (in) - The IO descriptor - int *rc // (out) - Error return code + Array *arrayArg, // (in) - The IO descriptor + int tileArg, // (in) - Tile number in array + int *rc // (out) - Error return code ) { // // !DESCRIPTION: @@ -2352,7 +2360,7 @@ int PIO_IODescHandler::getIODesc( for (it = PIO_IODescHandler::activePioIoDescriptors.begin(); it < PIO_IODescHandler::activePioIoDescriptors.end(); ++it) { - if ((iosys == (*it)->ios) && (arrayArg == (*it)->array_p)) { + if ((iosys == (*it)->ios) && (arrayArg == (*it)->array_p) && (tileArg == (*it)->tile)) { iodesc = (*it)->io_descriptor; localrc = ESMF_SUCCESS; } From a4301d652aa1599029263257e838dff481e57447 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 7 Aug 2022 17:10:11 -0600 Subject: [PATCH 091/266] Remove unused variable, user_count --- src/Infrastructure/IO/include/ESMCI_PIO_Handler.h | 1 - src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h index d61aacd4b9..c51a6a4368 100644 --- a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h @@ -78,7 +78,6 @@ namespace ESMCI { int stride; int rearr; int base; - int user_count; bool new_file; public: diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 5c81295433..abe7e802ed 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -494,7 +494,6 @@ PIO_Handler::PIO_Handler( pioSystemDesc = 0; pioFileDesc = 0; pioIODesc = 0; - user_count = 0; localrc = ESMF_SUCCESS; new_file = false; // Get the rest from initialize From bec67f75dc5a5ba7f0955b31d0e4c500dfbfd3c8 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 7 Aug 2022 17:12:01 -0600 Subject: [PATCH 092/266] Remove unused variable, pioIODesc --- src/Infrastructure/IO/include/ESMCI_PIO_Handler.h | 1 - src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h index c51a6a4368..5434851fd9 100644 --- a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h @@ -71,7 +71,6 @@ namespace ESMCI { static std::vector activePioInstances; int pioSystemDesc; // Descriptor for initialized PIO inst. int pioFileDesc; // Descriptor for open PIO file - int pioIODesc; // Descriptor created by initdecomp MPI_Comm communicator; int my_rank; int num_iotasks; diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index abe7e802ed..5b2b611138 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -493,7 +493,6 @@ PIO_Handler::PIO_Handler( // fill in the PIO_Handler objecte pioSystemDesc = 0; pioFileDesc = 0; - pioIODesc = 0; localrc = ESMF_SUCCESS; new_file = false; // Get the rest from initialize From 7f1591ae713fbea166e8c748bf949f0d123e4a7b Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 7 Aug 2022 20:42:09 -0600 Subject: [PATCH 093/266] Remove unusual error handling conditional This check of (ESMF_SUCCESS == localrc) appears unnecessary --- src/Infrastructure/IO/src/ESMCI_IO.C | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_IO.C b/src/Infrastructure/IO/src/ESMCI_IO.C index 47372e0654..aa403b00c7 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO.C +++ b/src/Infrastructure/IO/src/ESMCI_IO.C @@ -932,13 +932,11 @@ int IO::close(void &rc)) { return rc; } - if (ESMF_SUCCESS == localrc) { ioHandler->close(); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, &rc)) { return rc; } - } } else { localrc = ESMC_RC_FILE_CLOSE; if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, From 04fb94f46da34d8f60998c89507d7ebc98517ad2 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Sun, 7 Aug 2022 20:52:56 -0600 Subject: [PATCH 094/266] Remove some unnecessary isOpen checks These checks are either (1) redundant with existing checks in the IO_Handler functions called or (2) unnecessary because the IO_Handler functions gracefully handle the case of a closed file. And these checks are going to be hard to maintain with an upcoming change to make isOpen work on just one tile. --- src/Infrastructure/IO/src/ESMCI_IO.C | 52 +++++++++------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_IO.C b/src/Infrastructure/IO/src/ESMCI_IO.C index aa403b00c7..731d50fc80 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO.C +++ b/src/Infrastructure/IO/src/ESMCI_IO.C @@ -820,15 +820,6 @@ int IO::open( } // No else (state looks OK) - // Check to make sure that a file is not already open - if (ioHandler->isOpen() != ESMF_FALSE) { - PRINTMSG("IO_Handler is already open "); - localrc = ESMC_RC_FILE_OPEN; - ESMC_LogDefault.Write("Internal error, ioHandler is already open", - ESMC_LOGMSG_ERROR, ESMC_CONTEXT); - return localrc; - } - // Open the file ioHandler->open(file, filestatusflag, overwrite, readonly, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, @@ -876,13 +867,11 @@ int IO::flush(void } } - // Check to make sure that a file is already open - if (ioHandler->isOpen() != ESMF_FALSE) { - ioHandler->flush(&localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - &rc)) { - return rc; - } + // Note that it is safe to call this even if the file isn't open + ioHandler->flush(&localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &rc)) { + return rc; } // return successfully @@ -906,8 +895,8 @@ int IO::close(void ) { // !DESCRIPTION: // Close an open file or stream -// It is an error if the file is not open // It is an error if no IOHandler exists +// It is NOT an error if the file is not open // //EOP //----------------------------------------------------------------------------- @@ -925,24 +914,17 @@ int IO::close(void } } - // Check to make sure that a file is already open - if (ioHandler->isOpen() != ESMF_FALSE) { - ioHandler->flush(&localrc); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, - &rc)) { - return rc; - } - ioHandler->close(); - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, - ESMC_CONTEXT, &rc)) { - return rc; - } - } else { - localrc = ESMC_RC_FILE_CLOSE; - if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, - ESMC_CONTEXT, &rc)) { - return rc; - } + // No need to check if file is open: flush and close just won't do anything if + // the file isn't already open + ioHandler->flush(&localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, + &rc)) { + return rc; + } + ioHandler->close(); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, + ESMC_CONTEXT, &rc)) { + return rc; } // return successfully From c764928372711b54776023c9eec6cffe954038ad Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 9 Aug 2022 11:49:50 -0600 Subject: [PATCH 095/266] Add the necessary loops and arrays for multi-tile I/O With this commit, multi-tile writes are working, at least for basic cases! (Tested with billsacks/esmfprojects-multi_tile_io@b288bc9 .) I think some more (minor) changes are needed for multi-tile read. --- .../IO/include/ESMCI_IO_Handler.h | 42 ++- .../IO/include/ESMCI_PIO_Handler.h | 34 +-- src/Infrastructure/IO/src/ESMCI_IO.C | 2 +- src/Infrastructure/IO/src/ESMCI_IO_Handler.C | 251 ++++++++++++++++-- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 230 ++++++++-------- 5 files changed, 401 insertions(+), 158 deletions(-) diff --git a/src/Infrastructure/IO/include/ESMCI_IO_Handler.h b/src/Infrastructure/IO/include/ESMCI_IO_Handler.h index 2af7a2b67b..b536b19d37 100644 --- a/src/Infrastructure/IO/include/ESMCI_IO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_IO_Handler.h @@ -88,21 +88,36 @@ namespace ESMCI { static void finalize(int *rc = NULL); private: virtual void destruct(void) { } + + protected: + // read() + // Non-atomic reads which are only successful on an open IO stream + virtual void arrayReadOneTileFile(Array *arr_p, int tile, const char *name, + int *timeslice = NULL, int *rc = NULL) = 0; + + // write() + // Non-atomic writes which are only successful on an open IO stream + virtual void arrayWriteOneTileFile(Array *arr_p, int tile, const char *name, + const std::vector &dimLabels, + int *timeslice = NULL, + const ESMCI::Info *varAttPack = NULL, + const ESMCI::Info *gblAttPack = NULL, + int *rc = NULL) = 0; public: // read() // Non-atomic reads which are only successful on an open IO stream - virtual void arrayRead(Array *arr_p, const char *name, - int *timeslice = NULL, int *rc = NULL) = 0; + void arrayRead(Array *arr_p, const char *name, + int *timeslice = NULL, int *rc = NULL); // write() // Non-atomic writes which are only successful on an open IO stream - virtual void arrayWrite(Array *arr_p, const char *name, - const std::vector &dimLabels, - int *timeslice = NULL, - const ESMCI::Info *varAttPack = NULL, - const ESMCI::Info *gblAttPack = NULL, - int *rc = NULL) = 0; + void arrayWrite(Array *arr_p, const char *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: @@ -141,7 +156,9 @@ namespace ESMCI { // open(), close() and helper functions protected: - virtual void open(bool readonly_arg, int *rc = NULL) = 0; + virtual void openOneTileFile(int tile, bool readonly_arg, int *rc = NULL) = 0; + virtual void flushOneTileFile(int tile, int *rc = NULL) = 0; + virtual void closeOneTileFile(int tile, int *rc = NULL) = 0; // Check compatibility of an array with this IO Handler object; return error if incompatible int checkArray(const Array *arr_p) const; @@ -151,9 +168,10 @@ namespace ESMCI { bool overwrite_arg, bool readonly_arg, int *rc = NULL); - virtual ESMC_Logical isOpen(void) { return ESMF_FALSE; } - virtual void flush(int *rc = NULL) = 0; - virtual void close(int *rc = NULL) = 0; + ESMC_Logical isOpenAnyTile(void); + virtual ESMC_Logical isOpen(int tile) { return ESMF_FALSE; } + void flush(int *rc = NULL); + void close(int *rc = NULL); // Don't know yet if we will need these #if 0 diff --git a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h index 5434851fd9..41d4c021cc 100644 --- a/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h +++ b/src/Infrastructure/IO/include/ESMCI_PIO_Handler.h @@ -70,14 +70,14 @@ namespace ESMCI { // global information static std::vector activePioInstances; int pioSystemDesc; // Descriptor for initialized PIO inst. - int pioFileDesc; // Descriptor for open PIO file + int *pioFileDesc; // Descriptor(s) for open PIO 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; + bool *new_file; // Typically just one value, but multiple for I/O of multi-tile arrays public: // native constructor and destructor @@ -103,17 +103,17 @@ namespace ESMCI { // read() // Non-atomic reads which are only successful on an open IO stream - void arrayRead(Array *arr_p, const char * const name, - int *timeslice = NULL, int *rc = NULL); + 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 arrayWrite(Array *arr_p, const char * const name, - const std::vector &dimLabels, - int *timeslice = NULL, - const ESMCI::Info *varAttPack = NULL, - const ESMCI::Info *gblAttPack = NULL, - int *rc = NULL); + 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: @@ -129,13 +129,13 @@ namespace ESMCI { } // open() and close() - void open(bool readonly_arg, int *rc = NULL); - ESMC_Logical isOpen(void); - ESMC_Logical isNewFile(void) { - return (new_file ? ESMF_TRUE : ESMF_FALSE); + 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 flush(int *rc = NULL); - void close(int *rc = NULL); + void flushOneTileFile(int tile, int *rc = NULL); + void closeOneTileFile(int tile, int *rc = NULL); private: int getIODesc(int iosys, Array *arr_p, int tile, @@ -145,7 +145,7 @@ namespace ESMCI { int *narrDims = (int *)NULL, int *basepiotype = (int *)NULL, int *rc = (int *)NULL); - void attPackPut (int vardesc, const ESMCI::Info *attPack, int *rc); + void attPackPut (int vardesc, const ESMCI::Info *attPack, int tile, int *rc); public: // Error recording routine diff --git a/src/Infrastructure/IO/src/ESMCI_IO.C b/src/Infrastructure/IO/src/ESMCI_IO.C index 731d50fc80..82755a0c7a 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO.C +++ b/src/Infrastructure/IO/src/ESMCI_IO.C @@ -1430,7 +1430,7 @@ void IO::clear(void) { objects.pop_back(); delete obj; } -} // end IO::close +} // end IO::clear //------------------------------------------------------------------------- //------------------------------------------------------------------------- diff --git a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C index 7d3286a6bd..35079cfa26 100644 --- a/src/Infrastructure/IO/src/ESMCI_IO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_IO_Handler.C @@ -366,6 +366,101 @@ void IO_Handler::finalize ( } // end IO_Handler::finalize //------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO_Handler::arrayRead()" +//BOPI +// !IROUTINE: ESMCI::IO_Handler::arrayRead - Read an array from a file +// +// !INTERFACE: +void IO_Handler::arrayRead( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: +// + Array *arr_p, // (inout) - Destination of read + 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. If timeslice is not +// NULL, it should point to an integer representing the timeslice to read +// from the Array. +// +//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; + + for (int tile = 1; tile <= ntiles; ++tile) { + arrayReadOneTileFile(arr_p, tile, name, timeslice, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + } + // return successfully + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } +} // IO_Handler::arrayRead() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO_Handler::arrayWrite()" +//BOPI +// !IROUTINE: ESMCI::IO_Handler::arrayWrite - Write an Array to a file +// +// !INTERFACE: +void IO_Handler::arrayWrite( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: + Array *arr_p, // (in) Destination of write + 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. +// +//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; + + for (int tile = 1; tile <= ntiles; ++tile) { + arrayWriteOneTileFile(arr_p, tile, name, dimLabels, timeslice, + varAttPack, gblAttPack, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + } + // return successfully + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } +} // IO_Handler::arrayWrite() +//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #undef ESMC_METHOD @@ -397,7 +492,7 @@ int IO_Handler::setFilename( int localrc = ESMF_RC_NOT_IMPL; // local return code // It is an error if we already have an open file - if (isOpen() != ESMF_FALSE) { + if (isOpenAnyTile() != ESMF_FALSE) { ESMC_LogDefault.MsgFoundError(ESMF_RC_FILE_ACTIVE, "- Cannot change name, file open", ESMC_CONTEXT, &rc); return rc; @@ -599,7 +694,7 @@ int IO_Handler::checkArray( void IO_Handler::open ( // // !RETURN VALUE: -// int error return code +// // // !ARGUMENTS: @@ -627,33 +722,147 @@ void IO_Handler::open ( localrc = ESMF_RC_PTR_NULL; ESMC_LogDefault.MsgFoundError(localrc, "- NULL filename argument pointer", ESMC_CONTEXT, rc); - } else if (isOpen() == ESMF_TRUE) { - // Check to make sure that a file is not already open - localrc = ESMF_RC_FILE_OPEN; - ESMC_LogDefault.MsgFoundError(localrc, "- File already open", ESMC_CONTEXT, - rc); + return; } - if (ESMF_SUCCESS == localrc) { - // Set the filename - localrc = setFilename(file); - } + // Set the filename + localrc = setFilename(file); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; - if (ESMF_SUCCESS == localrc) { - // Store the IO status and overwrite fields - fileStatusFlag = filestatusflag_arg; - overwrite = overwrite_arg; - // Open the file - open(readonly_arg, &localrc); - ESMC_LogDefault.MsgFoundError(localrc, "- Error opening file", ESMC_CONTEXT, - rc); + // Store the IO status and overwrite fields + fileStatusFlag = filestatusflag_arg; + overwrite = overwrite_arg; + // Open the file(s) + for (int tile = 1; tile <= ntiles; ++tile) { + if (isOpen(tile) == ESMF_TRUE) { + // Check to make sure that a file is not already open + localrc = ESMF_RC_FILE_OPEN; + ESMC_LogDefault.MsgFoundError(localrc, "- File already open", ESMC_CONTEXT, rc); + return; + } + openOneTileFile(tile, readonly_arg, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, "- Error opening file", ESMC_CONTEXT, rc)) + return; } // return - if (rc != (int *)NULL) { - *rc = localrc; + if (rc != NULL) { + *rc = ESMF_SUCCESS; } } // end IO_Handler::open //------------------------------------------------------------------------- +//------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO_Handler::isOpenAnyTile()" +//BOPI +// !IROUTINE: IO_Handler::isOpenAnyTile - Determine if the file for any tile is open +// +// !INTERFACE: +ESMC_Logical IO_Handler::isOpenAnyTile( +// +// !RETURN VALUE: +// +// ESMC_Logical ESMF_TRUE if the file for any tile is open, ESMF_FALSE otherwise +// +// !ARGUMENTS: + ) { +// !DESCRIPTION: +// Determine if the file for any tile is open, returning ESMF_TRUE if so, +// or ESMF_FALSE if no associated files are open. (For I/O on typical +// single-tile arrays, this is the same as calling isOpen(1), but for +// multi-tile arrays, with each tile being read / written to a different +// file, this checks the status of all associated files.) +// +//EOPI +//----------------------------------------------------------------------------- + for (int tile = 1; tile <= ntiles; ++tile) { + if (isOpen(tile) == ESMF_TRUE) { + return ESMF_TRUE; + } + } + return ESMF_FALSE; +} // end IO_Handler::isOpenAnyTile +//------------------------------------------------------------------------- + +//------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO_Handler::flush()" +//BOPI +// !IROUTINE: IO_Handler::flush - Flush any pending I/O operations +// +// !INTERFACE: +void IO_Handler::flush( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: + int *rc // (out) - Error return code + ) { +// !DESCRIPTION: +// Flush any pending I/O operations. +// +//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; + for (int tile = 1; tile <= ntiles; ++tile) { + flushOneTileFile(tile, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + } + // return successfully + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } +} // end IO_Handler::flush +//------------------------------------------------------------------------- + +//------------------------------------------------------------------------- +#undef ESMC_METHOD +#define ESMC_METHOD "ESMCI::IO_Handler::close()" +//BOPI +// !IROUTINE: IO_Handler::close - Close possibly-open file(s) +// +// !INTERFACE: +void IO_Handler::close( +// +// !RETURN VALUE: +// +// +// !ARGUMENTS: + int *rc // (out) - Error return code + ) { +// !DESCRIPTION: +// Close possibly-open file(s) +// 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; + for (int tile = 1; tile <= ntiles; ++tile) { + closeOneTileFile(tile, &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) + return; + } + // return successfully + if (rc != NULL) { + *rc = ESMF_SUCCESS; + } +} // end IO_Handler::close +//------------------------------------------------------------------------- + } // end namespace ESMCI diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 5b2b611138..8122cf80b9 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -81,7 +81,7 @@ namespace ESMCI int *dims; // The shape of the Array IO 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 + 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: @@ -490,11 +490,17 @@ PIO_Handler::PIO_Handler( try { - // fill in the PIO_Handler objecte - pioSystemDesc = 0; - pioFileDesc = 0; + // fill in the PIO_Handler object + pioSystemDesc = 0; + pioFileDesc = new int[ntilesArg]; + for (int i = 0; i < ntilesArg; ++i) { + pioFileDesc[i] = 0; + } localrc = ESMF_SUCCESS; - new_file = false; + new_file = new bool[ntilesArg]; + for (int i = 0; i < ntilesArg; ++i) { + new_file[i] = false; + } // Get the rest from initialize localrc = initializeVM(); @@ -539,26 +545,27 @@ void PIO_Handler::destruct (void //----------------------------------------------------------------------------- int localrc; // Only for debug! PRINTPOS; - // Make sure the file is closed - if (isOpen() == ESMF_TRUE) { - PRINTMSG(" (" << my_rank << "): closing file"); - close((int *)NULL); // Don't care about an error, continue with cleanup - } + // 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 PIO_Handler object // NB: This does not shutdown the PIO instance, it may be reused. pioSystemDesc = 0; + // Deallocate some memory + delete[] pioFileDesc; + delete[] new_file; } // PIO_Handler::destruct() //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #undef ESMC_METHOD -#define ESMC_METHOD "ESMCI::PIO_Handler::arrayRead()" +#define ESMC_METHOD "ESMCI::PIO_Handler::arrayReadOneTileFile()" //BOPI -// !IROUTINE: ESMCI::PIO_Handler::arrayRead - Read an array from a file +// !IROUTINE: ESMCI::PIO_Handler::arrayReadOneTileFile - Read an array from a file, for the given tile // // !INTERFACE: -void PIO_Handler::arrayRead( +void PIO_Handler::arrayReadOneTileFile( // // !RETURN VALUE: // @@ -566,15 +573,16 @@ void PIO_Handler::arrayRead( // !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. If timeslice is not -// NULL, it should point to an integer representing the timeslice to read -// from the Array. +// Read data from field from the open file for the given tile. If +// timeslice is not NULL, it should point to an integer representing the +// timeslice to read from the Array. // //EOPI //----------------------------------------------------------------------------- @@ -585,6 +593,7 @@ void PIO_Handler::arrayRead( int * arrDims; // Array shape int narrDims; // Array rank int iodesc; // PIO IO descriptor + int filedesc; // PIO file descriptor int vardesc; // PIO variable descriptor int basepiotype; // PIO version of Array data type void *baseAddress; // The address of the Array IO data @@ -599,8 +608,9 @@ void PIO_Handler::arrayRead( } PRINTPOS; + // File open? - if (isOpen() != ESMF_TRUE) + if (isOpen(tile) != ESMF_TRUE) if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", ESMC_CONTEXT, rc)) return; @@ -609,8 +619,7 @@ void PIO_Handler::arrayRead( if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; - // FIXME(wjs, 2022-07-22) Add loop over tiles - int tile = 1; + filedesc = pioFileDesc[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 @@ -631,7 +640,7 @@ void PIO_Handler::arrayRead( ESMC_CONTEXT, rc)) return; // This should work if it is a NetCDF file. - piorc = PIOc_inq(pioFileDesc, &nDims, + piorc = PIOc_inq(filedesc, &nDims, &nVar, &nAtt, &unlim); if (!CHECKPIOERROR(piorc, "File is not in NetCDF format", ESMF_RC_FILE_READ, (*rc))) { return; @@ -643,7 +652,7 @@ void PIO_Handler::arrayRead( varname = arr_p->getName(); } - piorc = PIOc_inq_varid(pioFileDesc, varname.c_str(), &vardesc); + piorc = PIOc_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 (!CHECKPIOERROR(piorc, errmsg, ESMF_RC_FILE_READ, (*rc))) { @@ -656,7 +665,7 @@ void PIO_Handler::arrayRead( // Do not use the unlimited dim in iodesc calculation // int dimids[narrDims]; - piorc = PIOc_inq_vardimid(pioFileDesc, vardesc, dimids); + piorc = PIOc_inq_vardimid(filedesc, vardesc, dimids); // This should never happen const std::string errmsg = "variable " + varname + " inq_dimid failed"; if (!CHECKPIOERROR(piorc, errmsg, ESMF_RC_FILE_READ, (*rc))) { @@ -672,7 +681,7 @@ void PIO_Handler::arrayRead( int dimid_time; MPI_Offset time_len; - piorc = PIOc_inq_dimid(pioFileDesc, "time", &dimid_time); + piorc = PIOc_inq_dimid(filedesc, "time", &dimid_time); if (!CHECKPIOERROR(piorc, "No time dimension found in file", ESMF_RC_FILE_READ, (*rc))) { return; } @@ -687,7 +696,7 @@ void PIO_Handler::arrayRead( } } // Check to make sure the requested record is in the file - piorc = PIOc_inq_dimlen(pioFileDesc, + piorc = PIOc_inq_dimlen(filedesc, dimid_time, &time_len); if (!CHECKPIOERROR(piorc, "Error finding time length", ESMF_RC_FILE_READ, (*rc))) { return; @@ -713,7 +722,7 @@ void PIO_Handler::arrayRead( } if (unlim >= 0 && frame > 0) { PRINTMSG("calling setframe for read_darray, frame = " << frame); - PIOc_setframe(pioFileDesc, vardesc, frame-1); + PIOc_setframe(filedesc, vardesc, frame-1); } #endif // defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) @@ -723,7 +732,7 @@ void PIO_Handler::arrayRead( PRINTMSG("calling read_darray, pio type = " << basepiotype << ", address = " << baseAddress); // Read in the array - piorc = PIOc_read_darray(pioFileDesc, vardesc, iodesc, + piorc = PIOc_read_darray(filedesc, vardesc, iodesc, arrlen, (void *)baseAddress); if (!CHECKPIOERROR(piorc, "Error reading array data", ESMF_RC_FILE_READ, (*rc))) { @@ -734,23 +743,24 @@ void PIO_Handler::arrayRead( if (rc != NULL) { *rc = localrc; } -} // PIO_Handler::arrayRead() +} // PIO_Handler::arrayReadOneTileFile() //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #undef ESMC_METHOD -#define ESMC_METHOD "ESMCI::PIO_Handler::arrayWrite()" +#define ESMC_METHOD "ESMCI::PIO_Handler::arrayWriteOneTileFile()" //BOPI -// !IROUTINE: ESMCI::PIO_Handler::arrayWrite - Write an Array to a file +// !IROUTINE: ESMCI::PIO_Handler::arrayWriteOneTileFile - Write an Array to a file, for the given tile // // !INTERFACE: -void PIO_Handler::arrayWrite( +void PIO_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 @@ -761,7 +771,8 @@ void PIO_Handler::arrayWrite( ) { // // !DESCRIPTION: -// Call the appropriate PIO write_darray__ function +// Write data to field to the open file, for the given tile. +// Calls the appropriate PIO write_darray__ function. // It is an error if this handler object does not have an open // PIO file descriptor and a valid PIO IO descriptor (these items should // all be in place after a successful call to PIO_Handler::open). @@ -775,8 +786,9 @@ void PIO_Handler::arrayWrite( int nioDims; // Array IO rank int * arrDims; // Array shape int narrDims; // Array rank - int iodesc; // PIO IO descriptor - int vardesc = 0; // PIO variable descriptor + int iodesc; // PIO IO descriptor + int filedesc; // PIO file descriptor + int vardesc = 0; // PIO variable descriptor int basepiotype; // PIO version of Array data type void *baseAddress; // The address of the Array IO data int localDE; // DE to use for IO @@ -791,11 +803,12 @@ void PIO_Handler::arrayWrite( } PRINTPOS; + if ((int *)NULL != timeslice) { timesliceVal = *timeslice; } // File open? - if (isOpen() != ESMF_TRUE) + if (isOpen(tile) != ESMF_TRUE) if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_READ, "file not open", ESMC_CONTEXT, rc)) return; @@ -804,8 +817,7 @@ void PIO_Handler::arrayWrite( if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; - // FIXME(wjs, 2022-07-22) Add loop over tiles - int tile = 1; + filedesc = pioFileDesc[tile-1]; // note that tile indices are 1-based iodesc = getIODesc(pioSystemDesc, arr_p, tile, &ioDims, &nioDims, &arrDims, &narrDims, &basepiotype, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, @@ -854,14 +866,14 @@ void PIO_Handler::arrayWrite( varname = arr_p->getName(); } PRINTMSG("varname = \"" << varname << "\""); - if (ESMF_TRUE == isNewFile()) { + 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)"); - piorc = PIOc_redef(pioFileDesc); + piorc = PIOc_redef(filedesc); // Not all NetCDF errors are really errors here so we need to check if ((PIO_NOERR != piorc) && (NC_EINDEFINE != piorc)) { if (!CHECKPIOERROR(piorc, @@ -875,7 +887,7 @@ void PIO_Handler::arrayWrite( // This should work if it is a NetCDF file. PRINTMSG("Calling PIOc_inq"); - piorc = PIOc_inq(pioFileDesc, &nfDims, + piorc = PIOc_inq(filedesc, &nfDims, &nVar, &nAtt, &unlim); if (!CHECKPIOERROR(piorc, "File is not in NetCDF format", ESMF_RC_FILE_WRITE, (*rc))) { @@ -884,7 +896,7 @@ void PIO_Handler::arrayWrite( // We have a NetCDF file, see if the variable is in there PRINTMSG("Looking for variable in file"); - piorc = PIOc_inq_varid(pioFileDesc, varname.c_str(), &vardesc); + piorc = PIOc_inq_varid(filedesc, varname.c_str(), &vardesc); // This should succeed if the variable exists varExists = (PIO_NOERR == piorc); } @@ -895,8 +907,8 @@ void PIO_Handler::arrayWrite( int dimidTime; PIO_Offset timeLen; PRINTMSG("Checking time dimension"); - //piorc = PIOc_inq_dimid(pioFileDesc, "time", &dimidTime); - piorc = PIOc_inq_unlimdim(pioFileDesc, &dimidTime); + //piorc = PIOc_inq_dimid(filedesc, "time", &dimidTime); + piorc = PIOc_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). @@ -906,7 +918,7 @@ void PIO_Handler::arrayWrite( PRINTMSG("unlim = " << unlim); if (hasTimeDim) { // Retrieve the max time field - piorc = PIOc_inq_dimlen(pioFileDesc, dimidTime, &timeLen); + piorc = PIOc_inq_dimlen(filedesc, dimidTime, &timeLen); PRINTMSG("inq_dimlen = " << piorc); PRINTMSG("dimidTime = " << dimidTime); PRINTMSG("timeLen = " << timeLen); @@ -950,7 +962,7 @@ void PIO_Handler::arrayWrite( int nArrdims = nioDims + ((timeFrame > 0) ? 1 : 0); // Check compatibility between array to write and existing variable. - piorc = PIOc_inq_varndims(pioFileDesc, vardesc, &nDims); + piorc = PIOc_inq_varndims(filedesc, vardesc, &nDims); if (!CHECKPIOERROR(piorc, "Error retrieving information about variable", ESMF_RC_FILE_WRITE, (*rc))) { return; @@ -968,7 +980,7 @@ void PIO_Handler::arrayWrite( PRINTMSG("Calling pio_cpp_inq_vardimid_vdesc"); std::vector dimIds(nDims); - piorc = PIOc_inq_vardimid(pioFileDesc, vardesc, &dimIds.front()); + piorc = PIOc_inq_vardimid(filedesc, vardesc, &dimIds.front()); if (!CHECKPIOERROR(piorc, "Error retrieving information about variable", ESMF_RC_FILE_WRITE, (*rc))) { return; @@ -977,7 +989,7 @@ void PIO_Handler::arrayWrite( MPI_Offset dimLen; int ioDimNum = 0; for (int i = 0; i < nDims; i++) { - piorc = PIOc_inq_dimlen(pioFileDesc, dimIds[i], &dimLen); + piorc = PIOc_inq_dimlen(filedesc, dimIds[i], &dimLen); if (!CHECKPIOERROR(piorc, "Error retrieving dimension information", ESMF_RC_FILE_WRITE, (*rc))) { return; @@ -1025,7 +1037,7 @@ void PIO_Handler::arrayWrite( if (!varExists) { // Ensure we are in define mode PRINTMSG("Going into NetCDF define mode (redef)"); - piorc = PIOc_redef(pioFileDesc); + piorc = PIOc_redef(filedesc); // Not all NetCDF errors are really errors here so we need to check if ((PIO_NOERR != piorc) && (NC_EINDEFINE != piorc)) { if (!CHECKPIOERROR(piorc, @@ -1052,10 +1064,10 @@ void PIO_Handler::arrayWrite( // if dimension already exists, use it. int dimid_existing; - piorc = PIOc_inq_dimid(pioFileDesc, axis.c_str(), &dimid_existing); + piorc = PIOc_inq_dimid(filedesc, axis.c_str(), &dimid_existing); if (PIO_NOERR == piorc) { MPI_Offset dim_len; - piorc = PIOc_inq_dimlen(pioFileDesc, dimid_existing, &dim_len); + piorc = PIOc_inq_dimlen(filedesc, dimid_existing, &dim_len); if (!CHECKPIOERROR(piorc, "Error finding existing dimension length", ESMF_RC_FILE_WRITE, (*rc))) { return; } @@ -1070,7 +1082,7 @@ void PIO_Handler::arrayWrite( ncDims[nioDims - i - 1] = dimid_existing; } else { PRINTMSG("Defining dimension " << i); - piorc = PIOc_def_dim(pioFileDesc, axis.c_str(), + piorc = PIOc_def_dim(filedesc, axis.c_str(), ioDims[i], &ncDims[nioDims - i - 1]); if (!CHECKPIOERROR(piorc, std::string("Defining dimension: ") + axis, ESMF_RC_FILE_WRITE, (*rc))) { @@ -1085,14 +1097,14 @@ void PIO_Handler::arrayWrite( for(int i=nioDims;i>0;i--) ncDims[i] = ncDims[i-1]; if (hasTimeDim) { - piorc = PIOc_inq_dimid (pioFileDesc, "time", &ncDims[0]); + piorc = PIOc_inq_dimid (filedesc, "time", &ncDims[0]); if (!CHECKPIOERROR(piorc, "Attempting to obtain 'time' dimension ID", ESMF_RC_FILE_WRITE, (*rc))) { return; } } else { PRINTMSG("Defining time dimension"); - piorc = PIOc_def_dim(pioFileDesc, "time", + piorc = PIOc_def_dim(filedesc, "time", PIO_UNLIMITED, &ncDims[0]); if (!CHECKPIOERROR(piorc, "Attempting to define 'time' dimension", ESMF_RC_FILE_WRITE, (*rc))) { @@ -1106,7 +1118,7 @@ void PIO_Handler::arrayWrite( PRINTMSG("niodims = " << nioDims); PRINTMSG("basepiotype = " << basepiotype); - piorc = PIOc_def_var(pioFileDesc, varname.c_str(), basepiotype, + piorc = PIOc_def_var(filedesc, varname.c_str(), basepiotype, nioDims, ncDims, &vardesc); if (!CHECKPIOERROR(piorc, "Attempting to define PIO vardesc for: " + varname, ESMF_RC_FILE_WRITE, (*rc))) { @@ -1116,10 +1128,10 @@ void PIO_Handler::arrayWrite( if (timeFrame >= 0) { #ifdef ESMFIO_DEBUG int nvdims; - PIOc_inq_varndims(pioFileDesc, vardesc, &nvdims); + PIOc_inq_varndims(filedesc, vardesc, &nvdims); PRINTMSG("calling setframe, timeFrame = " << timeFrame); #endif // ESMFIO_DEBUG - piorc = PIOc_setframe(pioFileDesc, vardesc, timeFrame-1); + piorc = PIOc_setframe(filedesc, vardesc, timeFrame-1); if (!CHECKPIOERROR(piorc, "Attempting to setframe for: " + varname, ESMF_RC_FILE_WRITE, (*rc))) { return; @@ -1132,21 +1144,21 @@ void PIO_Handler::arrayWrite( if (varExists) { int varid; int lrc; - lrc = PIOc_inq_varid(pioFileDesc, varname.c_str(), &varid); + lrc = PIOc_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, &localrc); + attPackPut (vardesc, varAttPack, tile, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) { return; } } if (gblAttPack) { - attPackPut (NULL, gblAttPack, &localrc); + attPackPut (NULL, gblAttPack, tile, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) { return; @@ -1156,7 +1168,7 @@ void PIO_Handler::arrayWrite( PRINTMSG("calling enddef, status = " << rc); - piorc = PIOc_enddef(pioFileDesc); + piorc = PIOc_enddef(filedesc); if (!CHECKPIOERROR(piorc, "Attempting to end definition of variable: " + varname, ESMF_RC_FILE_WRITE, (*rc))) { return; @@ -1169,13 +1181,13 @@ void PIO_Handler::arrayWrite( #endif // ESMFIO_DEBUG // Write the array ESMCI_IOREGION_ENTER("PIOc_write_darray"); - piorc = PIOc_write_darray(pioFileDesc, vardesc, iodesc, arrlen, + piorc = PIOc_write_darray(filedesc, vardesc, iodesc, arrlen, (void *)baseAddress, NULL); if (!CHECKPIOERROR(piorc, "Attempting to write file", ESMF_RC_FILE_WRITE, (*rc))) { return; } - new_file = false; + new_file[tile-1] = false; ESMCI_IOREGION_EXIT("PIOc_write_darray"); @@ -1184,29 +1196,30 @@ void PIO_Handler::arrayWrite( if (rc != NULL) { *rc = ESMF_SUCCESS; } -} // PIO_Handler::arrayWrite() +} // PIO_Handler::arrayWriteOneTileFile() //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #undef ESMC_METHOD -#define ESMC_METHOD "ESMCI::PIO_Handler::open()" +#define ESMC_METHOD "ESMCI::PIO_Handler::openOneTileFile()" //BOPI -// !IROUTINE: ESMCI::PIO_Handler::open - open a stream with stored filename +// !IROUTINE: ESMCI::PIO_Handler::openOneTileFile - open a stream with stored filename, for the given tile // // !INTERFACE: -void PIO_Handler::open( +void PIO_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. +// Open a file for reading and/or writing for the given tile. // PIO 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) // @@ -1245,9 +1258,6 @@ void PIO_Handler::open( int iofmt_map_size = sizeof (iofmt_map)/sizeof (iofmt_map_t); - // FIXME(wjs, 2022-07-26) Get tile as an argument or loop over tiles - int tile = 1; - if (rc != NULL) { *rc = ESMF_RC_NOT_IMPL; // final return code } @@ -1257,9 +1267,9 @@ void PIO_Handler::open( if (ESMC_LogDefault.MsgFoundError (ESMF_RC_INTNRL_BAD, "PIO not initialized", ESMC_CONTEXT, rc)) return; - } else if (isOpen() == ESMF_TRUE) { + } else if (isOpen(tile) == ESMF_TRUE) { if (ESMC_LogDefault.MsgFoundError (ESMF_RC_FILE_OPEN, - "PIO not initialized", + "File is already open", ESMC_CONTEXT, rc)) return; } else if (pioSystemDesc <= 0 ) { // Just grab last created PIO instance for now (TBD: need way to choose) @@ -1295,7 +1305,7 @@ void PIO_Handler::open( mode = PIO_WRITE; } // Figure out if we need to call createfile or openfile - new_file = false; + new_file[tile-1] = false; const std::string thisFilename = getFilename(tile, &localrc); if (ESMC_LogDefault.MsgFoundError(localrc, ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) return; @@ -1350,20 +1360,20 @@ void PIO_Handler::open( } ESMCI_IOREGION_ENTER("PIOc_createfile"); - piorc = PIOc_createfile(pioSystemDesc, &pioFileDesc, + piorc = PIOc_createfile(pioSystemDesc, &(pioFileDesc[tile-1]), &iotype, thisFilename.c_str(), mode); ESMCI_IOREGION_EXIT("PIOc_createfile"); if (!CHECKPIOWARN(piorc, std::string("Unable to create file: ") + thisFilename, ESMF_RC_FILE_OPEN, (*rc))) { return; } else { - new_file = true; + new_file[tile-1] = true; PRINTMSG("call to PIOc_createfile: success for " << thisFilename << " iotype= "<< iotype << " Mode "<< mode << " ESMF FMT "<getStorageRef(); for (json::const_iterator it=j.cbegin(); it!=j.cend(); it++) { @@ -1452,7 +1464,7 @@ void PIO_Handler::attPackPut ( return; } const std::string value = jcurr[0]; - piorc = PIOc_put_att_text (pioFileDesc, vardesc, + piorc = PIOc_put_att_text (filedesc, vardesc, it.key().c_str(), strlen(value.c_str()), value.c_str()); if (!CHECKPIOERROR(piorc, "Attempting to set string Attribute: " + it.key(), ESMF_RC_FILE_WRITE, (*rc))) return; @@ -1460,7 +1472,7 @@ void PIO_Handler::attPackPut ( } case ESMC_TYPEKIND_I8: { const std::vector value = jcurr.get>(); - piorc = PIOc_put_att_long (pioFileDesc, vardesc, + piorc = PIOc_put_att_long (filedesc, vardesc, it.key().c_str(), att_type, size, value.data()); if (!CHECKPIOERROR(piorc, "Attempting to set I8 Attribute: " + it.key(), ESMF_RC_FILE_WRITE, (*rc))) return; @@ -1468,7 +1480,7 @@ void PIO_Handler::attPackPut ( } case ESMC_TYPEKIND_R8: { const std::vector value = jcurr.get>(); - piorc = PIOc_put_att_double (pioFileDesc, vardesc, + piorc = PIOc_put_att_double (filedesc, vardesc, it.key().c_str(), att_type, size, value.data()); if (!CHECKPIOERROR(piorc, "Attempting to set R8 Attribute: " + it.key(), ESMF_RC_FILE_WRITE, (*rc))) return; @@ -1476,7 +1488,7 @@ void PIO_Handler::attPackPut ( } case ESMC_TYPEKIND_I4: { const std::vector value = jcurr.get>(); - piorc = PIOc_put_att_int (pioFileDesc, vardesc, + piorc = PIOc_put_att_int (filedesc, vardesc, it.key().c_str(), att_type, size, value.data()); if (!CHECKPIOERROR(piorc, "Attempting to set I4 Attribute: " + it.key(), ESMF_RC_FILE_WRITE, (*rc))) return; @@ -1484,7 +1496,7 @@ void PIO_Handler::attPackPut ( } case ESMC_TYPEKIND_R4: { const std::vector value = jcurr.get>(); - piorc = PIOc_put_att_float (pioFileDesc, vardesc, + piorc = PIOc_put_att_float (filedesc, vardesc, it.key().c_str(), att_type, size, value.data()); if (!CHECKPIOERROR(piorc, "Attempting to set R4 Attribute: " + it.key(), ESMF_RC_FILE_WRITE, (*rc))) return; @@ -1517,6 +1529,8 @@ ESMC_Logical PIO_Handler::isOpen( // // !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: @@ -1526,17 +1540,16 @@ ESMC_Logical PIO_Handler::isOpen( //EOPI //----------------------------------------------------------------------------- PRINTPOS; - if (pioFileDesc == 0) { + int filedesc = pioFileDesc[tile-1]; // note that tile indices are 1-based + if (filedesc == 0) { PRINTMSG("pioFileDesc is NULL"); return ESMF_FALSE; - } else if (PIOc_File_is_Open(pioFileDesc) != 0) { + } else if (PIOc_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; - // FIXME(wjs, 2022-07-26) Get tile as an argument or loop over tiles - int tile = 1; const std::string thisFilename = getFilename(tile); errmsg = std::string ("File, ") + thisFilename + ", closed by PIO"; ESMC_LogDefault.Write(errmsg, ESMC_LOGMSG_WARN, ESMC_CONTEXT); @@ -1547,23 +1560,25 @@ ESMC_Logical PIO_Handler::isOpen( //----------------------------------------------------------------------------- #undef ESMC_METHOD -#define ESMC_METHOD "ESMCI::PIO_Handler::flush()" +#define ESMC_METHOD "ESMCI::PIO_Handler::flushOneTileFile()" //BOPI -// !IROUTINE: ESMCI::PIO_Handler::flush - Flush any pending I/O operations +// !IROUTINE: ESMCI::PIO_Handler::flushOneTileFile - Flush any pending I/O operations for this tile's file // // !INTERFACE: -void PIO_Handler::flush( +void PIO_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: -// xxx +// Flush any pending I/O operations for this tile's file. +// It is safe to call this on a non-open file; in this case, nothing is done. // //EOPI //----------------------------------------------------------------------------- @@ -1576,40 +1591,41 @@ void PIO_Handler::flush( PRINTPOS; // Not open? No problem, just skip - if (isOpen() == ESMF_TRUE) { + if (isOpen(tile) == ESMF_TRUE) { PRINTMSG("calling sync"); ESMCI_IOREGION_ENTER("PIOc_sync"); - PIOc_sync(pioFileDesc); + PIOc_sync(pioFileDesc[tile-1]); ESMCI_IOREGION_EXIT("PIOc_sync"); } // return successfully if (rc != NULL) { *rc = ESMF_SUCCESS; } -} // PIO_Handler::flush() +} // PIO_Handler::flushOneTileFile() //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #undef ESMC_METHOD -#define ESMC_METHOD "ESMCI::PIO_Handler::close()" +#define ESMC_METHOD "ESMCI::PIO_Handler::closeOneTileFile()" //BOPI -// !IROUTINE: ESMCI::PIO_Handler::close - Close an open file +// !IROUTINE: ESMCI::PIO_Handler::closeOneTileFile - Close this tile's possibly-open file // // !INTERFACE: -void PIO_Handler::close( +void PIO_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 (if any). -// It is not an error if no file is open +// Close the open file associated with this tile (if any). +// It is NOT an error if no file is open // //EOPI //----------------------------------------------------------------------------- @@ -1622,11 +1638,11 @@ void PIO_Handler::close( PRINTPOS; // Not open? No problem, just skip - if (isOpen() == ESMF_TRUE) { - ESMCI_IOREGION_ENTER("PIOc_closefile"); - int piorc = PIOc_closefile(pioFileDesc); - ESMCI_IOREGION_EXIT("PIOc_closefile"); - new_file = false; + if (isOpen(tile) == ESMF_TRUE) { + ESMCI_IOREGION_ENTER("PIOc_closefile"); + int piorc = PIOc_closefile(pioFileDesc[tile-1]); + ESMCI_IOREGION_EXIT("PIOc_closefile"); + new_file[tile-1] = false; if (rc != NULL) *rc = piorc; } @@ -1634,7 +1650,7 @@ void PIO_Handler::close( if (rc != NULL) { *rc = ESMF_SUCCESS; } -} // PIO_Handler::close() +} // PIO_Handler::closeOneTileFile() //----------------------------------------------------------------------------- @@ -1655,7 +1671,7 @@ void PIO_Handler::close( // int iosys, // (in) - PIO system handle to use Array *arr_p, // (in) - Array for IO decompomposition - int tile, // (in) - Tile number in array + 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 @@ -1911,7 +1927,7 @@ int PIO_IODescHandler::constructPioDecomp( // int iosys, // (in) - PIO system handle to use Array *arr_p, // (in) - Array for IO decompomposition - int tile, // (in) - Tile number in array + int tile, // (in) - Tile number in array (1-based indexing) int *newDecomp_p // (out) - New decomposition descriptor ) { // @@ -2339,7 +2355,7 @@ int PIO_IODescHandler::getIODesc( // int iosys, // (in) - The PIO IO system Array *arrayArg, // (in) - The IO descriptor - int tileArg, // (in) - Tile number in array + int tileArg, // (in) - Tile number in array (1-based indexing) int *rc // (out) - Error return code ) { // From b48e3b10f8b155d3f72440e0b5ac9aa617cdc4fe Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 9 Aug 2022 11:56:16 -0600 Subject: [PATCH 096/266] Add some comments --- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 8122cf80b9..f070490760 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -580,8 +580,9 @@ void PIO_Handler::arrayReadOneTileFile( ) { // // !DESCRIPTION: -// Read data from field from the open file for the given tile. If -// timeslice is not NULL, it should point to an integer representing the +// 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 @@ -772,6 +773,7 @@ void PIO_Handler::arrayWriteOneTileFile( // // !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 PIO write_darray__ function. // It is an error if this handler object does not have an open // PIO file descriptor and a valid PIO IO descriptor (these items should @@ -1220,6 +1222,7 @@ void PIO_Handler::openOneTileFile( // // !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. // PIO 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) // @@ -1578,6 +1581,7 @@ void PIO_Handler::flushOneTileFile( // // !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 @@ -1625,6 +1629,7 @@ void PIO_Handler::closeOneTileFile( // // !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 From 37f8988f8a1995314805e1b1a10ecbccf8d5d536 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 9 Aug 2022 11:27:34 -0700 Subject: [PATCH 097/266] ESMF_MACHINE=arm64 to set ESMF_ABI=64. --- build/common.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/common.mk b/build/common.mk index dea441ea16..0aef0b697e 100644 --- a/build/common.mk +++ b/build/common.mk @@ -356,6 +356,10 @@ ifeq ($(ESMF_MACHINE),x86_64) # except x86_64 export ESMF_ABI = 64 endif +ifeq ($(ESMF_MACHINE),arm64) +# and arm64 +export ESMF_ABI = 64 +endif endif ifeq ($(ESMF_OS),Cygwin) From 37bfa1facce4fcc70b32b96f0181536c598f6985 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 9 Aug 2022 13:01:48 -0700 Subject: [PATCH 098/266] Additional logging under Verbosity bit 4. --- src/addon/NUOPC/src/NUOPC_Driver.F90 | 38 +++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index 91e0eaf3ee..6a8dde5b3e 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -8180,6 +8180,13 @@ recursive subroutine IInitRealize(driver, importState, exportState, clock, rc) if (stateIsCreated) then ! - complete all the fields in the importState + if (btest(verbosity,4)) then + call ESMF_LogWrite("Calling into completeAllFields() for importState", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif call completeAllFields(importState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out @@ -8191,6 +8198,13 @@ recursive subroutine IInitRealize(driver, importState, exportState, clock, rc) if (stateIsCreated) then ! - complete all the fields in the exportState + if (btest(verbosity,4)) then + call ESMF_LogWrite("Calling into completeAllFields() for exportState", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif call completeAllFields(exportState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out @@ -8242,18 +8256,34 @@ recursive subroutine completeAllFields(state, rc) line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out if (associated(fieldList)) then do i=1, size(fieldList) - + ! See if the Field is shared. If so, don't need to do anything ! here, because the Connector will have realized the Fields ! automatically, using reference sharing. Otherwise realize here. - + call NUOPC_GetAttribute(fieldList(i), name="ShareStatusField", & value=value, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out - - if (trim(value)=="not shared") then + + if (trim(value)=="shared") then + ! shared -> must complete the field here + if (btest(verbosity,4)) then + call ESMF_LogWrite("- "//trim(itemNameList(i))// & + ": shared --> don't know what to do!!!!!.", ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif + else ! not shared -> must complete the field here + if (btest(verbosity,4)) then + call ESMF_LogWrite("- "//trim(itemNameList(i))// & + ": not shared --> complete here.", ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & + return ! bail out + endif call NUOPC_Realize(stateList(i), fieldName=itemNameList(i), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out From 896e2a5ca600ea664acdd0eaa0b8919db95af3c8 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 11 Aug 2022 09:05:56 -0700 Subject: [PATCH 099/266] fix a doc issue in ESMPy --- src/addon/ESMPy/doc/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/doc/api.rst b/src/addon/ESMPy/doc/api.rst index bf2356b2b0..c6db0bc048 100644 --- a/src/addon/ESMPy/doc/api.rst +++ b/src/addon/ESMPy/doc/api.rst @@ -99,7 +99,7 @@ The :class:`~ESMF.api.esmpymanager.Manager` is also used to enable logging: .. code:: mg = ESMF.Manager(debug=True) - local_pet = mg.local_pet() + local_pet = mg.local_pet The output will be logged in files named PET.ESMF_LogFile. From 2445a43f6392c68ffdbf5da2cbeb83b6c56b19f2 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 11 Aug 2022 09:06:54 -0700 Subject: [PATCH 100/266] add argtype for ESMC_Initialize --- src/addon/ESMPy/src/ESMF/interface/cbindings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/src/ESMF/interface/cbindings.py b/src/addon/ESMPy/src/ESMF/interface/cbindings.py index 4a1c28aae8..26c2d82c8b 100644 --- a/src/addon/ESMPy/src/ESMF/interface/cbindings.py +++ b/src/addon/ESMPy/src/ESMF/interface/cbindings.py @@ -192,7 +192,7 @@ def from_param(cls, param): #### INIT/FINAL ################################################### _ESMF.ESMC_Initialize.restype = ct.c_int -#_ESMF.ESMC_Initialize.argtypes = [] +_ESMF.ESMC_Initialize.argtypes = [ct.POINTER(ct.int)] def ESMP_Initialize(logkind = constants.LogKind.MULTI): """ From 60e561f853937d6bce7538a639d28a21991edfdd Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 11 Aug 2022 16:22:52 -0700 Subject: [PATCH 101/266] Partially merge feature/neptune-sami3 into develop. --- .../Field/src/ESMF_FieldGather.cppF90 | 62 +++++++++++++++++-- src/Superstructure/ESMFMod/src/ESMF_Init.F90 | 17 ++++- .../src/ESMF_StateReconcile.F90 | 18 ++++++ src/addon/NUOPC/src/NUOPC_ModelBase.F90 | 8 --- 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/Infrastructure/Field/src/ESMF_FieldGather.cppF90 b/src/Infrastructure/Field/src/ESMF_FieldGather.cppF90 index fe65cf82c7..5f6ce97931 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldGather.cppF90 +++ b/src/Infrastructure/Field/src/ESMF_FieldGather.cppF90 @@ -114,8 +114,8 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below ! \item[field] ! The {\tt ESMF\_Field} object to fill with data. ! \item[{[dataFillScheme]}] -! The fill scheme. The available options are "sincos", "one", and "const". -! Defaults to "sincos". +! The fill scheme. The available options are "sincos", "one", "const", and +! "random". Defaults to "sincos". ! \item[{[const1]}] ! Constant of real type. Defaults to 0. ! \item[{[member]}] @@ -208,7 +208,7 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below l_step = 1 if(present(step)) l_step = step if(present(param3I4)) l_member = param3I4 - l_dataFillScheme = "sincos" + l_dataFillScheme = "sincos" ! default if(present(dataFillScheme)) l_dataFillScheme = dataFillScheme allocate(coordDimCount(rank)) @@ -911,7 +911,7 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below rcToReturn=rc) return ! bail out endif - else if (trim(dataFillScheme)=="one") then + else if (trim(l_dataFillScheme)=="one") then do lde=0, ldeCount-1 if (typekind==ESMF_TYPEKIND_R8 .and. rank==1) then ! 1D all 1. @@ -963,7 +963,7 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below dataPtrR4D3 = 1._ESMF_KIND_R4 endif enddo - else if (trim(dataFillScheme)=="const") then + else if (trim(l_dataFillScheme)=="const") then do lde=0, ldeCount-1 if (typekind==ESMF_TYPEKIND_R8 .and. rank==1) then ! 1D all 1. @@ -1015,6 +1015,58 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords below dataPtrR4D3 = real(l_const1,ESMF_KIND_R4); endif enddo + else if (trim(l_dataFillScheme)=="random") then + do lde=0, ldeCount-1 + if (typekind==ESMF_TYPEKIND_R8 .and. rank==1) then + ! 1D all 1. + call ESMF_FieldGet(field, localDe=lde, farrayPtr=dataPtrR8D1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT)) & + return ! bail out + ! initialize the entire array + call random_number(dataPtrR8D1) + elseif (typekind==ESMF_TYPEKIND_R4 .and. rank==1) then + ! 1D all 1. + call ESMF_FieldGet(field, localDe=lde, farrayPtr=dataPtrR4D1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT)) & + return ! bail out + ! initialize the entire array + call random_number(dataPtrR4D1) + elseif (typekind==ESMF_TYPEKIND_R8 .and. rank==2) then + ! 2D all 1. + call ESMF_FieldGet(field, localDe=lde, farrayPtr=dataPtrR8D2, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT)) & + return ! bail out + ! initialize the entire array + call random_number(dataPtrR8D2) + elseif (typekind==ESMF_TYPEKIND_R4 .and. rank==2) then + ! 2D all 1. + call ESMF_FieldGet(field, localDe=lde, farrayPtr=dataPtrR4D2, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT)) & + return ! bail out + ! initialize the entire array + call random_number(dataPtrR4D2) + elseif (typekind==ESMF_TYPEKIND_R8 .and. rank==3) then + ! 3D all 1. + call ESMF_FieldGet(field, localDe=lde, farrayPtr=dataPtrR8D3, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT)) & + return ! bail out + ! initialize the entire array + call random_number(dataPtrR8D3) + elseif (typekind==ESMF_TYPEKIND_R4 .and. rank==3) then + ! 3D all 1. + call ESMF_FieldGet(field, localDe=lde, farrayPtr=dataPtrR4D3, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT)) & + return ! bail out + ! initialize the entire array + call random_number(dataPtrR4D3) + endif + enddo else call ESMF_LogSetError(ESMF_RC_ARG_BAD, & msg="Unknown dataFillScheme requested.", & diff --git a/src/Superstructure/ESMFMod/src/ESMF_Init.F90 b/src/Superstructure/ESMFMod/src/ESMF_Init.F90 index a1fa6ef6e6..d1a76d6c48 100644 --- a/src/Superstructure/ESMFMod/src/ESMF_Init.F90 +++ b/src/Superstructure/ESMFMod/src/ESMF_Init.F90 @@ -48,6 +48,7 @@ module ESMF_InitMod use ESMF_CalendarMod use ESMF_TraceMod use ESMF_UtilMod + use ESMF_TraceMod implicit none private @@ -337,7 +338,12 @@ subroutine ESMF_Initialize(keywordEnforcer, configFilename, & return endif ! on success LogErr is assumed to be functioning - + + ! provide complete ESMF profile region + call ESMF_TraceRegionEnter("[ESMF]", rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) return + ! obtain global VM call ESMF_VMGetGlobal(localvm, rc=localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & @@ -1164,6 +1170,13 @@ subroutine ESMF_Finalize(keywordEnforcer, endflag, rc) return endif + ! provide complete ESMF profile region + call ESMF_TraceRegionExit("[ESMF]", rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, rcToReturn=rc)) then + write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": TraceRegionExit() error." + endif + ! Write final message to the log call ESMF_LogWrite("Finalizing ESMF", & ESMF_LOGMSG_INFO, rc=localrc) @@ -1220,7 +1233,7 @@ subroutine ESMF_Finalize(keywordEnforcer, endflag, rc) if (endflag==ESMF_END_ABORT) abortFlag = .true. if (endflag==ESMF_END_KEEPMPI) keepMpiFlag = ESMF_TRUE endif - + if (abortFlag) then ! Abort the VM call ESMF_VMAbort(rc=localrc) diff --git a/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 b/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 index ed91a7eff8..8ec719562e 100644 --- a/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 +++ b/src/Superstructure/StateReconcile/src/ESMF_StateReconcile.F90 @@ -65,6 +65,8 @@ module ESMF_StateReconcileMod use ESMF_FieldBundleMod use ESMF_RHandleMod + use ESMF_TraceMod + use ESMF_InfoMod, only : ESMF_Info, ESMF_InfoGetFromBase, ESMF_InfoUpdate use ESMF_InfoCacheMod @@ -2064,6 +2066,7 @@ subroutine ESMF_ReconcileExchgNeeds (vm, id_info, recv_needs, rc) character(ESMF_MAXSTR) :: msgstring logical, parameter :: debug = .false. + logical, parameter :: profile = .false. localrc = ESMF_RC_NOT_IMPL @@ -2142,6 +2145,14 @@ subroutine ESMF_ReconcileExchgNeeds (vm, id_info, recv_needs, rc) call ESMF_ReconcileDebugPrint (ESMF_METHOD // & ': calling VMAllToAll') end if + + if (profile) then + call ESMF_TraceRegionEnter("ESMF_VMAllToAllV", rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, & + rcToReturn=rc)) return + endif + call ESMF_VMAllToAllV (vm, & sendData=buffer_send, sendCounts=counts_send, sendOffsets=offsets_send, & recvData=buffer_recv, recvCounts=counts_recv, recvOffsets=offsets_recv, & @@ -2150,6 +2161,13 @@ subroutine ESMF_ReconcileExchgNeeds (vm, id_info, recv_needs, rc) ESMF_CONTEXT, & rcToReturn=rc)) return + if (profile) then + call ESMF_TraceRegionExit("ESMF_VMAllToAllV", rc=localrc) + if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & + ESMF_CONTEXT, & + rcToReturn=rc)) return + endif + ! Copy recv buffers into recv_needs do, i=0, npets-1 diff --git a/src/addon/NUOPC/src/NUOPC_ModelBase.F90 b/src/addon/NUOPC/src/NUOPC_ModelBase.F90 index 8cf3bd4fa4..95bc4655f1 100644 --- a/src/addon/NUOPC/src/NUOPC_ModelBase.F90 +++ b/src/addon/NUOPC/src/NUOPC_ModelBase.F90 @@ -469,14 +469,6 @@ subroutine InitializeP0(gcomp, importState, exportState, clock, rc) isPresent=isPresentDataInitialize, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME)) return ! bail out - ! Detect inconsistent specialization combinations - if (isPresentAdvertise.neqv.isPresentRealizeProvided) then - call ESMF_LogSetError(ESMF_RC_ARG_BAD, & - msg="NUOPC INCOMPATIBILITY DETECTED: "// & - "Advertise and RealizeProvided must both be present or absent.", & - line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc) - return ! bail out - endif ! Advertise: conditionally activate the generic code if (isPresentAdvertise) then call NUOPC_CompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & From 50529d48e89863eed8ed3b24b1c709330e95792c Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 12 Aug 2022 10:14:59 -0700 Subject: [PATCH 102/266] type in ESMP_Initialize argtypes --- src/addon/ESMPy/src/ESMF/interface/cbindings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/src/ESMF/interface/cbindings.py b/src/addon/ESMPy/src/ESMF/interface/cbindings.py index 26c2d82c8b..a7a7e3acf4 100644 --- a/src/addon/ESMPy/src/ESMF/interface/cbindings.py +++ b/src/addon/ESMPy/src/ESMF/interface/cbindings.py @@ -192,7 +192,7 @@ def from_param(cls, param): #### INIT/FINAL ################################################### _ESMF.ESMC_Initialize.restype = ct.c_int -_ESMF.ESMC_Initialize.argtypes = [ct.POINTER(ct.int)] +_ESMF.ESMC_Initialize.argtypes = [ct.POINTER(ct.c_int)] def ESMP_Initialize(logkind = constants.LogKind.MULTI): """ From 756eae115b73d0dc36a208f56f3ad0081f8bae3d Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Tue, 16 Aug 2022 15:52:37 -0600 Subject: [PATCH 103/266] Use vm->getSsiMaxPetCount() in PIO handler to determine number of cores per node. --- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 27ebe1c5d1..bf9022d784 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -278,7 +278,7 @@ int PIO_Handler::initializeVM (void // Figure out the inputs for the initialize call int numtasks = vm->getPetCount(); - stride = vm->getSsiLocalPetCount(); + 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); From a39e383478e98564640a39b20c880607a8adeb8d Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Tue, 16 Aug 2022 16:22:57 -0600 Subject: [PATCH 104/266] Make doc about Grid and Mesh priorities for XGrid creation clearer. --- .../XGrid/src/ESMF_XGridCreate.F90 | 80 +++++++++++-------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 b/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 index 02bf1a1c04..64925d102a 100644 --- a/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 +++ b/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 @@ -499,25 +499,33 @@ function ESMF_XGridCreate(keywordEnforcer, & ! Parametric 2D Meshes on side B, for example, ! these Meshes can be either Cartesian 2D or Spherical. ! \item [{[sideAGridPriority]}] -! Priority array of Grids on {\tt sideA} during overlay generation. -! The priority arrays describe the priorities of Grids at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Grid of the -! highest priority to the lowest priority. +! Priority array of Grids on sideA during overlay generation. +! The {\tt sideAGridPriority} array should be the same length as {\tt sideAGrid}. The values +! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Grid whose corresponding +! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh +! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sideAMeshPriority]}] -! Priority array of Meshes on {\tt sideA} during overlay generation. -! The priority arrays describe the priorities of Meshes at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Mesh of the -! highest priority to the lowest priority. +! Priority array of Meshes on sideA during overlay generation. +! The {\tt sideAMeshPriority} array should be the same length as {\tt sideAMesh}. The values +! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Mesh whose corresponding +! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh +! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sideBGridPriority]}] -! Priority of Grids on {\tt sideB} during overlay generation -! The priority arrays describe the priorities of Grids at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Grid of the -! highest priority to the lowest priority. +! Priority array of Grids on sideB during overlay generation. +! The {\tt sideBGridPriority} array should be the same length as {\tt sideBGrid}. The values +! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Grid whose corresponding +! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh +! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sideBMeshPriority]}] -! Priority array of Meshes on {\tt sideB} during overlay generation. -! The priority arrays describe the priorities of Meshes at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Mesh of the -! highest priority to the lowest priority. +! Priority array of Meshes on sideB during overlay generation. +! The {\tt sideBMeshPriority} array should be the same length as {\tt sideBMesh}. The values +! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Mesh whose corresponding +! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh +! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sideAMaskValues]}] ! Mask information can be set in the Grid (see~\ref{sec:usage:items}) or Mesh (see~\ref{sec:mesh:mask}) ! upon which the {\tt Field} is built. The {\tt sideAMaskValues} argument specifies the values in that @@ -1635,25 +1643,33 @@ function ESMF_XGridCreateFromSparseMat(keywordEnforcer, & ! Parametric 2D Meshes on side B, for example, ! these Meshes can be either Cartesian 2D or Spherical. ! \item [{[sideAGridPriority]}] -! Priority array of Grids on {\tt sideA} during overlay generation. -! The priority arrays describe the priorities of Grids at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Grid of the -! highest priority to the lowest priority. +! Priority array of Grids on sideA during overlay generation. +! The {\tt sideAGridPriority} array should be the same length as {\tt sideAGrid}. The values +! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Grid whose corresponding +! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh +! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sideAMeshPriority]}] -! Priority array of Meshes on {\tt sideA} during overlay generation. -! The priority arrays describe the priorities of Meshes at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Mesh of the -! highest priority to the lowest priority. +! Priority array of Meshes on sideA during overlay generation. +! The {\tt sideAMeshPriority} array should be the same length as {\tt sideAMesh}. The values +! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Mesh whose corresponding +! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh +! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sideBGridPriority]}] -! Priority of Grids on {\tt sideB} during overlay generation -! The priority arrays describe the priorities of Grids at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Grid of the -! highest priority to the lowest priority. +! Priority array of Grids on sideB during overlay generation. +! The {\tt sideBGridPriority} array should be the same length as {\tt sideBGrid}. The values +! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Grid whose corresponding +! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh +! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sideBMeshPriority]}] -! Priority array of Meshes on {\tt sideB} during overlay generation. -! The priority arrays describe the priorities of Meshes at the overlapping region. -! Flux contributions at the overlapping region are computed in the order from the Mesh of the -! highest priority to the lowest priority. +! Priority array of Meshes on sideB during overlay generation. +! The {\tt sideBMeshPriority} array should be the same length as {\tt sideBMesh}. The values +! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Mesh whose corresponding +! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh +! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and +! the other Grid or Mesh part will be clipped away. ! \item [{[sparseMatA2X]}] ! indexlist from a Grid index space on side A to xgrid index space; ! indexFactorlist from a Grid index space on side A to xgrid index space. From 508652cf1196154083881f3dc1c6f451f3b4f7bd Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 16 Aug 2022 19:35:56 -0700 Subject: [PATCH 105/266] Re-implement the global [ESMF] trace level the right way: in the ESMCI::Trace layer. --- src/Infrastructure/Trace/src/ESMCI_Trace.C | 15 +++++++++++++++ src/Superstructure/ESMFMod/src/ESMF_Init.F90 | 13 ------------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Infrastructure/Trace/src/ESMCI_Trace.C b/src/Infrastructure/Trace/src/ESMCI_Trace.C index 367d8208d7..92a5ea0039 100644 --- a/src/Infrastructure/Trace/src/ESMCI_Trace.C +++ b/src/Infrastructure/Trace/src/ESMCI_Trace.C @@ -655,6 +655,13 @@ namespace ESMCI { InitializeWrappers(); } + // enter global ESMF region + TraceEventRegionEnter("[ESMF]", &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, + ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) { + return; + } + if (rc!=NULL) *rc = ESMF_SUCCESS; } @@ -1063,6 +1070,14 @@ namespace ESMCI { // allow calling multiple times, only closes // on the first call, needed in testing if (traceInitialized) { + + // exit global ESMF region + TraceEventRegionExit("[ESMF]", &localrc); + if (ESMC_LogDefault.MsgFoundError(localrc, + ESMCI_ERR_PASSTHRU, ESMC_CONTEXT, rc)) { + return; + } + traceInitialized = false; FinalizeWrappers(); diff --git a/src/Superstructure/ESMFMod/src/ESMF_Init.F90 b/src/Superstructure/ESMFMod/src/ESMF_Init.F90 index d1a76d6c48..54ce26977f 100644 --- a/src/Superstructure/ESMFMod/src/ESMF_Init.F90 +++ b/src/Superstructure/ESMFMod/src/ESMF_Init.F90 @@ -48,7 +48,6 @@ module ESMF_InitMod use ESMF_CalendarMod use ESMF_TraceMod use ESMF_UtilMod - use ESMF_TraceMod implicit none private @@ -339,11 +338,6 @@ subroutine ESMF_Initialize(keywordEnforcer, configFilename, & endif ! on success LogErr is assumed to be functioning - ! provide complete ESMF profile region - call ESMF_TraceRegionEnter("[ESMF]", rc=localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) return - ! obtain global VM call ESMF_VMGetGlobal(localvm, rc=localrc) if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & @@ -1170,13 +1164,6 @@ subroutine ESMF_Finalize(keywordEnforcer, endflag, rc) return endif - ! provide complete ESMF profile region - call ESMF_TraceRegionExit("[ESMF]", rc=localrc) - if (ESMF_LogFoundError(localrc, ESMF_ERR_PASSTHRU, & - ESMF_CONTEXT, rcToReturn=rc)) then - write (ESMF_UtilIOStderr,*) ESMF_METHOD, ": TraceRegionExit() error." - endif - ! Write final message to the log call ESMF_LogWrite("Finalizing ESMF", & ESMF_LOGMSG_INFO, rc=localrc) From 82d6c0761cb57513436e3bb4fe9e97c13069ccf4 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 17 Aug 2022 13:39:12 -0700 Subject: [PATCH 106/266] Turn OFF all extra logging having to do with the large message support. --- src/Infrastructure/VM/src/ESMCI_VMKernel.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/VM/src/ESMCI_VMKernel.C b/src/Infrastructure/VM/src/ESMCI_VMKernel.C index 5f33248600..256c19f40a 100644 --- a/src/Infrastructure/VM/src/ESMCI_VMKernel.C +++ b/src/Infrastructure/VM/src/ESMCI_VMKernel.C @@ -19,10 +19,10 @@ #define VM_PETMANAGEMENTLOG_off #define VM_MEMLOG_off #define VM_COMMQUEUELOG_off -#define VM_EPOCHLOG_on +#define VM_EPOCHLOG_off #define VM_EPOCHMEMLOG_off #define VM_SSISHMLOG_off -#define VM_SIZELOG_on +#define VM_SIZELOG_off // On SunOS systems there are a couple of macros that need to be set // in order to get POSIX compliant functions IPC, pthreads, gethostid From b5275bc969863ec1406bbe26cadef14880a8cd54 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 17 Aug 2022 13:56:35 -0700 Subject: [PATCH 107/266] Revert "Set versioning for 8.3.0 release." This reverts commit 6ed324f6a22f5ec6df23bb3710431493a3067b8b. --- src/Infrastructure/Util/include/ESMC_Macros.h | 6 +++--- src/Infrastructure/Util/src/ESMF_UtilTypes.F90 | 6 +++--- src/addon/NUOPC/doc/NUOPC_howtodoc.ctex | 2 +- src/addon/NUOPC/doc/NUOPC_refdoc.ctex | 2 +- src/doc/ESMC_crefdoc.ctex | 2 +- src/doc/ESMF_refdoc.ctex | 2 +- src/doc/ESMF_usrdoc.ctex | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Infrastructure/Util/include/ESMC_Macros.h b/src/Infrastructure/Util/include/ESMC_Macros.h index 60a17ac290..da10b6b2de 100644 --- a/src/Infrastructure/Util/include/ESMC_Macros.h +++ b/src/Infrastructure/Util/include/ESMC_Macros.h @@ -54,10 +54,10 @@ #define ESMF_VERSION_MINOR 3 #define ESMF_VERSION_REVISION 0 #define ESMF_VERSION_PATCHLEVEL 0 -#define ESMF_VERSION_PUBLIC 'T' -#define ESMF_VERSION_BETASNAPSHOT 'F' +#define ESMF_VERSION_PUBLIC 'F' +#define ESMF_VERSION_BETASNAPSHOT 'T' -#define ESMF_VERSION_STRING "8.3.0" +#define ESMF_VERSION_STRING "8.3.0 beta snapshot" #endif // ESMC_MACROS_H diff --git a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 index 7bf186c789..4cbbc5253b 100644 --- a/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 +++ b/src/Infrastructure/Util/src/ESMF_UtilTypes.F90 @@ -85,10 +85,10 @@ module ESMF_UtilTypesMod integer, parameter :: ESMF_VERSION_MINOR = 3 integer, parameter :: ESMF_VERSION_REVISION = 0 integer, parameter :: ESMF_VERSION_PATCHLEVEL = 0 - logical, parameter :: ESMF_VERSION_PUBLIC = .true. - logical, parameter :: ESMF_VERSION_BETASNAPSHOT = .false. + logical, parameter :: ESMF_VERSION_PUBLIC = .false. + logical, parameter :: ESMF_VERSION_BETASNAPSHOT = .true. - character(*), parameter :: ESMF_VERSION_STRING = "8.3.0" + character(*), parameter :: ESMF_VERSION_STRING = "8.3.0 beta snapshot" #if defined (ESMF_NETCDF) logical, parameter :: ESMF_IO_NETCDF_PRESENT = .true. diff --git a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex index 1a15a6cda7..dfb98691f1 100644 --- a/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_howtodoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf Building a NUOPC Model}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.3.0} +\newcommand{\myversion}{ESMF 8.3.0 beta snapshot} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex index 6086ef57ce..ab93cea2ce 100644 --- a/src/addon/NUOPC/doc/NUOPC_refdoc.ctex +++ b/src/addon/NUOPC/doc/NUOPC_refdoc.ctex @@ -17,7 +17,7 @@ \addtolength{\oddsidemargin}{-.75in} \newcommand{\mytitle}{\Large {\bf NUOPC Layer Reference}} \newcommand{\myauthors}{\large {\it Content Standards Committee (CSC) Members}} -\newcommand{\myversion}{ESMF 8.3.0} +\newcommand{\myversion}{ESMF 8.3.0 beta snapshot} % set a standard paragraph style \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} diff --git a/src/doc/ESMC_crefdoc.ctex b/src/doc/ESMC_crefdoc.ctex index d4f93d3d60..335760281d 100644 --- a/src/doc/ESMC_crefdoc.ctex +++ b/src/doc/ESMC_crefdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.3.0} +\newcommand{\myversion}{Version 8.3.0 beta snapshot} \newenvironment {reqlist} diff --git a/src/doc/ESMF_refdoc.ctex b/src/doc/ESMF_refdoc.ctex index a1c3ddbe46..720769f712 100644 --- a/src/doc/ESMF_refdoc.ctex +++ b/src/doc/ESMF_refdoc.ctex @@ -15,7 +15,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.3.0} +\newcommand{\myversion}{Version 8.3.0 beta snapshot} \input{common_commands} diff --git a/src/doc/ESMF_usrdoc.ctex b/src/doc/ESMF_usrdoc.ctex index a5d3d65f46..be35e07754 100644 --- a/src/doc/ESMF_usrdoc.ctex +++ b/src/doc/ESMF_usrdoc.ctex @@ -14,7 +14,7 @@ \newcommand{\sreq}[1]{\subsection{\hspace{.2in}#1}} \newcommand{\ssreq}[1]{\subsubsection{\hspace{.2in}#1}} \newcommand{\mytitle}{\longname \docmttype ~~} -\newcommand{\myversion}{Version 8.3.0} +\newcommand{\myversion}{Version 8.3.0 beta snapshot} \newenvironment {reqlist} From 63d75a63fe52db7a49b9fafa5c9d8a93adb61e9c Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 17 Aug 2022 15:50:18 -0700 Subject: [PATCH 108/266] One more place in PIO handler to use vm->getSsiMaxPetCount() to determine number of cores per node. --- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index bf9022d784..5ec9ed478c 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -1190,7 +1190,7 @@ void PIO_Handler::open( int piorc; // PIO error value VM *vm = VM::getCurrent(&localrc); int numtasks = vm->getPetCount(); - int petspernode = vm->getSsiLocalPetCount(); + int petspernode = vm->getSsiMaxPetCount(); struct iofmt_map_t { From 8e54e9d227a82bb973410d149c0b876611546c68 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 17 Aug 2022 17:10:58 -0700 Subject: [PATCH 109/266] add documentation on rules for automatic file detection in ESMF_RegridWeightGen --- src/doc/ESMF_RegridWeightGen.tex | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/doc/ESMF_RegridWeightGen.tex b/src/doc/ESMF_RegridWeightGen.tex index 55cb69e68e..1be5f593cf 100644 --- a/src/doc/ESMF_RegridWeightGen.tex +++ b/src/doc/ESMF_RegridWeightGen.tex @@ -32,7 +32,17 @@ \subsection{Description} the ESMF unstructured grid format~\ref{sec:fileformat:esmf} or the proposed CF unstructured grid data model (UGRID) ~\ref{sec:fileformat:ugrid}. GRIDSPEC is a proposed CF extension for the annotation of complex Earth system grids. In the latest ESMF library, we added support for multi-tile GRIDSPEC Mosaic file with non-overlapping tiles. For UGRID, we support the 2D flexible mesh topology with mixed triangles and quadrilaterals and fully 3D unstructured mesh topology with hexahedrons and tetrahedrons. In the latest ESMF implementation, the {\tt ESMF\_RegridWeightGen} command line toll can detect the type of the input grid files automatically. The user -doesn't need to provide the source and destination grid file type arguments anymore. The following arguments {\tt -t}, {\tt --src\_type}, {\tt --dst\_type}, {\tt --src\_meshname}, and {\tt --dst\_meshname} are no longer needed. If provided, the application will simply ingore them. +doesn't need to provide the source and destination grid file type arguments anymore. The following arguments {\tt -t}, {\tt --src\_type}, {\tt --dst\_type}, {\tt --src\_meshname}, and {\tt --dst\_meshname} are no longer needed. If provided, the application will simply ingore them. The rule to determine the file format is the following: + +\begin{itemize} + \item ESMF\_FILEFORMAT\_SCRIP: variables grid\_corner\_lon and grid\_corner\_lat exists + \item ESMF\_FILEFORMAT\_UGRID: a variable with attribute "cf\_role" or "standard\_name" set to "mesh\_topology" + \item ESMF\_FILEFORMAT\_ESMFMESH: variables nodeCoords and elementConn exists + \item ESMF\_FILEFORMAT\_CFGRID: variables with attributes "degree\_north" and "degree\_east" exists + \item ESMF\_FILEFORMAT\_MOSAIC: a variable with attribute "standard\_name" set to "grid\_mosaic\_spec" + \item ESMF\_FILEFORMAT\_TILE: a varilable with attribute "standard\_name" set to "grid\_tile\_spec" +\end{itemize} + This command line tool can do regrid weight generation from a global or regional source grid to a global or regional destination grid. As is true with many global models, this application currently assumes the latitude and longitude values refer to positions on a perfect sphere, as opposed to a more complex and accurate representation of the Earth's true shape such as would be used in a GIS system. (ESMF's current user base doesn't require this level of detail in representing the Earth's shape, but it could be added in the future if necessary.) From 50e7d32c0ea9a3748c8ab1ab50e4f5b5b6498f6c Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Thu, 18 Aug 2022 10:39:30 -0600 Subject: [PATCH 110/266] Small XGrid doc fix. --- .../XGrid/src/ESMF_XGridCreate.F90 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 b/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 index 64925d102a..3ad5a64f06 100644 --- a/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 +++ b/src/Infrastructure/XGrid/src/ESMF_XGridCreate.F90 @@ -500,28 +500,28 @@ function ESMF_XGridCreate(keywordEnforcer, & ! these Meshes can be either Cartesian 2D or Spherical. ! \item [{[sideAGridPriority]}] ! Priority array of Grids on sideA during overlay generation. -! The {\tt sideAGridPriority} array should be the same length as {\tt sideAGrid}. The values +! The {\tt sideAGridPriority} array should be the same size as the {\tt sideAGrid} array. The values ! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Grid whose corresponding ! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh ! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and ! the other Grid or Mesh part will be clipped away. ! \item [{[sideAMeshPriority]}] ! Priority array of Meshes on sideA during overlay generation. -! The {\tt sideAMeshPriority} array should be the same length as {\tt sideAMesh}. The values +! The {\tt sideAMeshPriority} array should be the same size as the {\tt sideAMesh} array. The values ! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Mesh whose corresponding ! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh ! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and ! the other Grid or Mesh part will be clipped away. ! \item [{[sideBGridPriority]}] ! Priority array of Grids on sideB during overlay generation. -! The {\tt sideBGridPriority} array should be the same length as {\tt sideBGrid}. The values +! The {\tt sideBGridPriority} array should be the same size as the {\tt sideBGrid} array. The values ! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Grid whose corresponding ! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh ! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and ! the other Grid or Mesh part will be clipped away. ! \item [{[sideBMeshPriority]}] ! Priority array of Meshes on sideB during overlay generation. -! The {\tt sideBMeshPriority} array should be the same length as {\tt sideBMesh}. The values +! The {\tt sideBMeshPriority} array should be the same size as the {\tt sideBMesh} array. The values ! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Mesh whose corresponding ! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh ! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and @@ -1644,28 +1644,28 @@ function ESMF_XGridCreateFromSparseMat(keywordEnforcer, & ! these Meshes can be either Cartesian 2D or Spherical. ! \item [{[sideAGridPriority]}] ! Priority array of Grids on sideA during overlay generation. -! The {\tt sideAGridPriority} array should be the same length as {\tt sideAGrid}. The values +! The {\tt sideAGridPriority} array should be the same size as the {\tt sideAGrid} array. The values ! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Grid whose corresponding ! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh ! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and ! the other Grid or Mesh part will be clipped away. ! \item [{[sideAMeshPriority]}] ! Priority array of Meshes on sideA during overlay generation. -! The {\tt sideAMeshPriority} array should be the same length as {\tt sideAMesh}. The values +! The {\tt sideAMeshPriority} array should be the same size as the {\tt sideAMesh} array. The values ! in the array should range from 1 to size(sideAGrid)+size(sideAMesh). A Mesh whose corresponding ! value in this array is lower than another side A Grid or Mesh, will take precedence over that Grid or Mesh ! during side A merging. In other words, if both have parts in the same region, then the object with the lower value will win, and ! the other Grid or Mesh part will be clipped away. ! \item [{[sideBGridPriority]}] ! Priority array of Grids on sideB during overlay generation. -! The {\tt sideBGridPriority} array should be the same length as {\tt sideBGrid}. The values +! The {\tt sideBGridPriority} array should be the same size as the {\tt sideBGrid} array. The values ! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Grid whose corresponding ! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh ! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and ! the other Grid or Mesh part will be clipped away. ! \item [{[sideBMeshPriority]}] ! Priority array of Meshes on sideB during overlay generation. -! The {\tt sideBMeshPriority} array should be the same length as {\tt sideBMesh}. The values +! The {\tt sideBMeshPriority} array should be the same size as the {\tt sideBMesh} array. The values ! in the array should range from 1 to size(sideBGrid)+size(sideBMesh). A Mesh whose corresponding ! value in this array is lower than another side B Grid or Mesh, will take precedence over that Grid or Mesh ! during side B merging. In other words, if both have parts in the same region, then the object with the lower value will win, and From a39cf4576b433d4cb189ff2c98b5a9f5b3ece7e6 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 18 Aug 2022 16:45:12 -0700 Subject: [PATCH 111/266] fix typo in ESMPy doc and BOP ESMC_FieldRead doc --- src/Infrastructure/Field/include/ESMC_Field.h | 4 ++-- src/addon/ESMPy/src/ESMF/api/field.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/Field/include/ESMC_Field.h b/src/Infrastructure/Field/include/ESMC_Field.h index 829c305252..4b302789f9 100644 --- a/src/Infrastructure/Field/include/ESMC_Field.h +++ b/src/Infrastructure/Field/include/ESMC_Field.h @@ -655,7 +655,7 @@ int ESMC_FieldPrint( //----------------------------------------------------------------------------- -//BOPI +//BOP // !IROUTINE: ESMC_FieldRead - Read Array data into a Field // // !INTERFACE: @@ -702,7 +702,7 @@ int ESMC_FieldPrint( // \end{sloppypar} // \end{description} // -//EOPI +//EOP //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- diff --git a/src/addon/ESMPy/src/ESMF/api/field.py b/src/addon/ESMPy/src/ESMF/api/field.py index 6064db3dfc..1b19d37724 100755 --- a/src/addon/ESMPy/src/ESMF/api/field.py +++ b/src/addon/ESMPy/src/ESMF/api/field.py @@ -382,7 +382,7 @@ def read(self, filename, variable, timeslice=None): *OPTIONAL:* - :param list timeslice: The number of timeslices to read. + :param int timeslice: The number of timeslices to read. """ import ESMF.api.constants as constants From 88bff8a5deabb62ec62ec47cf6586bdc4aad5873 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 19 Aug 2022 10:10:29 -0700 Subject: [PATCH 112/266] reactivate setup.py for ESMPy testing up through Python 3.9 --- src/addon/ESMPy/{setup.py.old => setup.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/addon/ESMPy/{setup.py.old => setup.py} (100%) diff --git a/src/addon/ESMPy/setup.py.old b/src/addon/ESMPy/setup.py similarity index 100% rename from src/addon/ESMPy/setup.py.old rename to src/addon/ESMPy/setup.py From f98019dbffbe1d22b571721977f745e2ebee9550 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 15:03:43 -0600 Subject: [PATCH 113/266] Add issue template with esmf_support contact info --- .github/ISSUE_TEMPLATE/config.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..e6d7cdab6d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: ESMF Support + url: http://earthsystemmodeling.org/support/ + about: To get help with using ESMF, please send an email esmf_support@ucar.edu. From c8730f904394de49b61861621135b0318632d83c Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 15:05:33 -0600 Subject: [PATCH 114/266] Add template for framework issues --- .github/ISSUE_TEMPLATE/01_esmf_issue.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/01_esmf_issue.md diff --git a/.github/ISSUE_TEMPLATE/01_esmf_issue.md b/.github/ISSUE_TEMPLATE/01_esmf_issue.md new file mode 100644 index 0000000000..b89e97d44c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/01_esmf_issue.md @@ -0,0 +1,5 @@ +--- +name: Framework Issue +about: Issues for tracking specific changes to the ESMF codebase. These are typically created by ESMF Core Team members. + +--- From 1f3d272e3769973d9054daa965bdbdeeb8b4e29c Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 15:13:51 -0600 Subject: [PATCH 115/266] Add workflow to build ESMF docs as a GitHub Action --- .github/workflows/build-esmf-docs.yml | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/build-esmf-docs.yml diff --git a/.github/workflows/build-esmf-docs.yml b/.github/workflows/build-esmf-docs.yml new file mode 100644 index 0000000000..5d15ba1e0e --- /dev/null +++ b/.github/workflows/build-esmf-docs.yml @@ -0,0 +1,64 @@ +name: Build ESMF Docs + +on: + workflow_dispatch: +# push: +# branches: [ "develop" ] +# pull_request: +# branches: [ "develop" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + + - name: Checkout Dockerfiles + uses: actions/checkout@v3 + with: + repository: esmf-org/esmf-containers + path: esmf-containers + ref: main + + - name: Build Docker image + run: | + cd ${{ github.workspace }}/esmf-containers/build-esmf-docs/esmf + docker build . --tag esmf/build-esmf-docs --build-arg ESMF_BRANCH="${{ github.ref_name }}" --no-cache + + - name: Extract artifacts + run: | + mkdir -p ${{ github.workspace }}/artifacts + CID=$(docker run -dit --name runner esmf/build-esmf-docs) + docker cp ${CID}:/artifacts/doc-artifacts.zip ${{ github.workspace }}/artifacts + docker stop ${CID} + docker rm ${CID} + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: esmf-docs + path: ${{ github.workspace }}/artifacts + + - name: Checkout esmf-org.github.io + uses: actions/checkout@v3 + with: + repository: esmf-org/esmf-org.github.io + path: esmf-org.github.io + + - name: Copy docs + run: | + cd ${{ github.workspace }}/esmf-org.github.io + mkdir -p docs/nightly/${{ github.ref_name }} + cd ${{ github.workspace }}/artifacts + unzip doc-artifacts.zip + cd ${{ github.workspace }}/artifacts/artifacts/doc-esmf + cp -rf ./* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cd ${{ github.workspace }}/artifacts/artifacts/doc-nuopc + cp -rf NUOPC_refdoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cp -rf NUOPC_refdoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cp -rf NUOPC_howtodoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cp -rf NUOPC_howtodoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cd ${{ github.workspace }}/artifacts/artifacts/doc-dev_guide + cp -rf ./dev_guide/dev_guide/* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/dev_guide/ From 1d49ac0b00d69638227ef24e4558e3e9707eec11 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 15:15:21 -0600 Subject: [PATCH 116/266] Add workflow to build ESMPy docs --- .github/workflows/build-esmpy-docs.yml | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/build-esmpy-docs.yml diff --git a/.github/workflows/build-esmpy-docs.yml b/.github/workflows/build-esmpy-docs.yml new file mode 100644 index 0000000000..36ccf5e1a8 --- /dev/null +++ b/.github/workflows/build-esmpy-docs.yml @@ -0,0 +1,58 @@ +name: Build ESMPy Docs + +on: + workflow_dispatch: +# push: +# branches: [ "develop" ] +# pull_request: +# branches: [ "develop" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + + - name: Checkout Dockerfiles + uses: actions/checkout@v3 + with: + repository: esmf-org/esmf-containers + path: esmf-containers + ref: main + + - name: Build Docker image + run: | + cd ${{ github.workspace }}/esmf-containers/build-esmf-docs/esmpy + docker build . --tag esmf/build-esmpy-docs + + - name: Copy artifacts + run: | + mkdir -p ${{ github.workspace }}/artifacts + CID=$(docker run -dit --name runner esmf/build-esmpy-docs) + docker cp ${CID}:/artifacts/doc-esmpy.zip ${{ github.workspace }}/artifacts + docker stop ${CID} + docker rm ${CID} + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: esmpy-docs + path: ${{ github.workspace }}/artifacts + + - name: Checkout esmpy_doc + uses: actions/checkout@v3 + with: + repository: esmf-org/esmpy_doc + path: esmpy_doc + + - name: Copy docs + run: | + cd ${{ github.workspace }}/esmpy_doc + mkdir -p docs/nightly/${{ github.ref_name }} + cd ${{ github.workspace }}/artifacts + unzip doc-esmpy.zip + cd ${{ github.workspace }}/artifacts/doc-esmpy/esmpy_doc + cp -rf html ${{ github.workspace }}/esmpy_doc/docs/nightly/${{ github.ref_name }}/ + cp -rf latex/ESMPy.pdf ${{ github.workspace }}/esmpy_doc/docs/nightly/${{ github.ref_name }}/ From a89bda7f27e4486fad61a1c247a46338deb760ea Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 15:17:07 -0600 Subject: [PATCH 117/266] Add workflow for generating API changes --- .github/workflows/api-change.yml | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/api-change.yml diff --git a/.github/workflows/api-change.yml b/.github/workflows/api-change.yml new file mode 100644 index 0000000000..9927a96129 --- /dev/null +++ b/.github/workflows/api-change.yml @@ -0,0 +1,47 @@ +name: Generate API changes + +on: + workflow_dispatch: + inputs: + tag1: + description: 'First ESMF Tag' + required: true + default: 'v8.3.0' + tag2: + description: 'Second ESMF Tag' + required: true + default: 'develop' + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + + - name: Checkout Dockerfiles + uses: actions/checkout@v3 + with: + repository: esmf-org/esmf-containers + path: esmf-containers + ref: main + + - name: Build Docker image + run: | + cd ${{ github.workspace }}/esmf-containers/api-change + docker build . --tag esmf/api-change --build-arg TAG1="${{ inputs.tag1 }}" --build-arg TAG2="${{ inputs.tag2 }}" + + - name: Copy artifacts + run: | + mkdir -p ${{ github.workspace }}/artifacts + CID=$(docker run -dit --name runner esmf/api-change) + docker cp ${CID}:/artifacts/api_change-artifacts.zip ${{ github.workspace }}/artifacts + docker stop ${CID} + docker rm ${CID} + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: api-change + path: ${{ github.workspace }}/artifacts From 700d728ceacbd445f21fab17b2c2a019d88bcca0 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 15:18:05 -0600 Subject: [PATCH 118/266] Add workflow for test coverage script --- .github/workflows/test-coverage.yml | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/test-coverage.yml diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml new file mode 100644 index 0000000000..ee49fda09d --- /dev/null +++ b/.github/workflows/test-coverage.yml @@ -0,0 +1,43 @@ +name: Test Coverage + +on: + workflow_dispatch: + inputs: + esmf_branch: + description: 'ESMF Branch' + required: true + default: 'develop' + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + + - name: Checkout Dockerfiles + uses: actions/checkout@v3 + with: + repository: esmf-org/esmf-containers + path: esmf-containers + ref: main + + - name: Build Docker image + run: | + cd ${{ github.workspace }}/esmf-containers/test-coverage + docker build . --tag esmf/test-coverage --build-arg ESMF_BRANCH="${{ inputs.esmf_branch }}" + + - name: Copy artifacts + run: | + mkdir -p ${{ github.workspace }}/artifacts + CID=$(docker run -dit --name runner esmf/test-coverage) + docker cp ${CID}:/artifacts/test_coverage-artifacts.zip ${{ github.workspace }}/artifacts + docker stop ${CID} + docker rm ${CID} + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: test-coverage + path: ${{ github.workspace }}/artifacts From d3c606648401b0f740143529fd7ccdfe35e9b89e Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 16:04:37 -0600 Subject: [PATCH 119/266] Update build ESMF docs workflow to publish docs --- .github/workflows/build-esmf-docs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-esmf-docs.yml b/.github/workflows/build-esmf-docs.yml index 5d15ba1e0e..2ede1ea335 100644 --- a/.github/workflows/build-esmf-docs.yml +++ b/.github/workflows/build-esmf-docs.yml @@ -62,3 +62,9 @@ jobs: cp -rf NUOPC_howtodoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ cd ${{ github.workspace }}/artifacts/artifacts/doc-dev_guide cp -rf ./dev_guide/dev_guide/* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/dev_guide/ + + - name: Commit and publish docs + uses: actions-js/push@master + with: + directory: ${{ github.workspace }}/esmf-org.github.io + github_token: ${{ secrets.GITHUB_TOKEN }} From 13eb3e40aa26445dcf566c58eaf6e547d9ad52f0 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 19 Aug 2022 16:08:11 -0600 Subject: [PATCH 120/266] Update ESMPy doc workflow to publish docs --- .github/workflows/build-esmpy-docs.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-esmpy-docs.yml b/.github/workflows/build-esmpy-docs.yml index 36ccf5e1a8..9f2265caf8 100644 --- a/.github/workflows/build-esmpy-docs.yml +++ b/.github/workflows/build-esmpy-docs.yml @@ -56,3 +56,9 @@ jobs: cd ${{ github.workspace }}/artifacts/doc-esmpy/esmpy_doc cp -rf html ${{ github.workspace }}/esmpy_doc/docs/nightly/${{ github.ref_name }}/ cp -rf latex/ESMPy.pdf ${{ github.workspace }}/esmpy_doc/docs/nightly/${{ github.ref_name }}/ + + - name: Commit and publish docs + uses: actions-js/push@master + with: + directory: ${{ github.workspace }}/esmpy_doc + github_token: ${{ secrets.GITHUB_TOKEN }} From d87e6ce4ff35c2dc8317637caa02ca40f77bf884 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Mon, 22 Aug 2022 11:23:32 -0600 Subject: [PATCH 121/266] Fix typo in issue chooser --- .github/ISSUE_TEMPLATE/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e6d7cdab6d..a2116143d0 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,4 +2,4 @@ blank_issues_enabled: false contact_links: - name: ESMF Support url: http://earthsystemmodeling.org/support/ - about: To get help with using ESMF, please send an email esmf_support@ucar.edu. + about: To get help with using ESMF, please send an email to esmf_support@ucar.edu. From 8c9a3e7b1bf386b23ed244cc00548fefa488bf96 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Mon, 22 Aug 2022 11:52:40 -0700 Subject: [PATCH 122/266] Convert ESMPy testing from nose to pytest --- src/addon/ESMPy/Makefile | 53 +++++++++++++++ src/addon/ESMPy/examples/exampletest.py | 32 ++++++---- src/addon/ESMPy/examples/exampletestdryrun.py | 15 +++++ src/addon/ESMPy/pyproject.toml | 14 ++++ src/addon/ESMPy/setup.cfg | 7 +- src/addon/ESMPy/{setup.py => setup.py.old} | 0 src/addon/ESMPy/src/ESMF/__init__.py | 5 -- src/addon/ESMPy/src/ESMF/api/constants.py | 3 + src/addon/ESMPy/src/ESMF/api/esmpymanager.py | 12 +++- .../ESMPy/src/ESMF/interface/cbindings.py | 2 +- src/addon/ESMPy/src/ESMF/test/base.py | 1 - src/addon/ESMPy/src/ESMF/test/base_test.py | 3 +- .../read_test_cases_from_control_file.py | 4 +- .../src/ESMF/test/regrid_from_file/rfftest.py | 18 ++++++ .../test/regrid_from_file/rfftestdryrun.py | 14 ++++ .../run_regrid_from_file_dryrun.py | 24 +++---- .../src/ESMF/test/test_api/test_field.py | 33 +++++----- .../ESMPy/src/ESMF/test/test_api/test_grid.py | 64 +++++++------------ .../src/ESMF/test/test_api/test_locstream.py | 3 +- .../ESMPy/src/ESMF/test/test_api/test_mesh.py | 22 ++----- .../src/ESMF/test/test_api/test_regrid.py | 55 ++++++++-------- .../ESMPy/src/ESMF/test/test_api/test_vm.py | 6 +- src/addon/ESMPy/src/ESMF/util/decorators.py | 22 ------- src/addon/ESMPy/src/ESMF/util/exceptions.py | 13 ++-- 24 files changed, 243 insertions(+), 182 deletions(-) create mode 100644 src/addon/ESMPy/Makefile create mode 100644 src/addon/ESMPy/examples/exampletestdryrun.py rename src/addon/ESMPy/{setup.py => setup.py.old} (100%) create mode 100644 src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftest.py create mode 100644 src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftestdryrun.py diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile new file mode 100644 index 0000000000..78eeea3042 --- /dev/null +++ b/src/addon/ESMPy/Makefile @@ -0,0 +1,53 @@ +.PHONY: clean install test test_int test_all uninstall + +clean: + rm -rf build + rm -rf dist + rm -rf *.egg-info + # find . -name "*.pyc" -exec rm -f {} \;') + # find . -name "*ESMF_LogFile*" -exec rm -f {} \;') + # find . -name "*.log" -exec rm -f {} \;') + # find . -name "*.vtk" -exec rm -f {} \;') + # rm src/ESMF/interface/esmfmkfile.py') + # rm -rf build') + # rm -rf dist') + # rm -rf src/ESMF/test/regrid_from_file/data') + # rm -rf examples/data') + + +install: + pip install . + +test_unit: + pytest -m="not parallel" + +test_unit_parallel: + mpirun -n 4 python -m pytest -m="not serial" + +test_examples_dryrun: + pytest -vs examples/exampletestdryrun.py + +test_examples: + pytest -m="not parallel" examples/exampletest.py + +test_examples_parallel: + mpirun -n 4 python -m pytest -m="not serial" examples/exampletest.py + +test_regrid_from_file_dryrun: + pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py + +test_regrid_from_file: + pytest -vs src/ESMF/test/regrid_from_file/rfftest.py + +test_regrid_from_file_parallel: + pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py + mpirun -n 4 python -m pytest -vs src/ESMF/test/regrid_from_file/rfftest.py + +test_all: test_unit test_parallel test_examples_dryrun test_examples test_examples_parallel + +test: test_unit test_unit_parallel test_examples test_examples_parallel + +test_uni: test_unit test_examples + +uninstall: + pip uninstall ESMPy diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/exampletest.py index a6f57047a6..a48a59480d 100644 --- a/src/addon/ESMPy/examples/exampletest.py +++ b/src/addon/ESMPy/examples/exampletest.py @@ -3,25 +3,29 @@ """ examples test file """ -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest + +import pytest from ESMF.test.base import TestBase, attr import ESMF.api.constants as constants class TestExamples(TestBase): + + # '0' in the name is so it is run first + def test_0_examples_dryrun(self): + from ESMF.util.cache_data import cache_data_files + cache_data_files() def test_helloworld(self): from . import hello_world - # # ESMF IO does not work in mpiuni mode - # def test_cubed_sphere_to_mesh_regrid(self): - # if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - # raise SkipTest('ESMF must be built with MPI for test') - # else: - # from . import cubed_sphere_to_mesh_regrid + # ESMF IO does not work in mpiuni mode + @pytest.mark.parallel + def test_cubed_sphere_to_mesh_regrid(self): + if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: + raise SkipTest('ESMF must be built with MPI for test') + else: + from . import cubed_sphere_to_mesh_regrid # ESMF IO does not work in mpiuni mode # only example, not in documentation @@ -58,10 +62,10 @@ def test_regrid_from_file(self): else: from . import regrid_from_file - # only example, not in documentation - @attr('slow') - def _tripole_regrid(self): - from . import tripole_regrid + # # only example, not in documentation, datafile missing from repo + # @pytest.mark.slow + # def test_tripole_regrid(self): + # from . import tripole_regrid # only example, not in documentation def test_ugrid_latlon_regrid(self): diff --git a/src/addon/ESMPy/examples/exampletestdryrun.py b/src/addon/ESMPy/examples/exampletestdryrun.py new file mode 100644 index 0000000000..8484ede406 --- /dev/null +++ b/src/addon/ESMPy/examples/exampletestdryrun.py @@ -0,0 +1,15 @@ +# $Id$ + +""" +examples dryrun test file +""" + +import pytest + +from ESMF.test.base import TestBase, attr + +class TestExamplesDryrun(TestBase): + + def test_examples_dryrun(self): + from ESMF.util.cache_data import cache_data_files + cache_data_files() diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml index 894c1b3a35..044b8d7bc3 100644 --- a/src/addon/ESMPy/pyproject.toml +++ b/src/addon/ESMPy/pyproject.toml @@ -22,3 +22,17 @@ build-backend = "setuptools.build_meta" # # [tool.setuptools.dynamic] # version = {attr = "ESMPy.VERSION"} +# + +[tool.pytest.ini_options] +markers = [ + "dryrun: marks a function that will only download test data files (deselect with '-m \"not parallel\"')", + "parallel: marks a test which requires mpi (deselect with '-m \"not parallel\"')", + "serial: marks a test which should be run on one core (deselect with '-m \"not serial\"')" +] +filterwarnings = [ + # "ignore:DeprecationWarning", + # note the use of single quote below to denote "raw" strings in TOML + # 'ignore:DeprecationWarning: Call to deprecated function ESMP_FieldRegridStoreFile', + # 'ignore:DeprecationWarning: Call to deprecated function ESMP_FieldSMMStore', +] diff --git a/src/addon/ESMPy/setup.cfg b/src/addon/ESMPy/setup.cfg index c492282869..1bbcf9f332 100644 --- a/src/addon/ESMPy/setup.cfg +++ b/src/addon/ESMPy/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = ESMPy -version = 8.4.0 +version = 8.4.0beta description = ESMF Python interface long_description = file: README.md, LICENSE license = University of Illinois-NCSA @@ -24,7 +24,7 @@ package_dir= packages = find: install_requires = numpy - nose2 + pytest [options.packages.find] where=src @@ -32,6 +32,3 @@ exclude = doc* examples* test* - -[nosetests] -attr=!slow,!data diff --git a/src/addon/ESMPy/setup.py b/src/addon/ESMPy/setup.py.old similarity index 100% rename from src/addon/ESMPy/setup.py rename to src/addon/ESMPy/setup.py.old diff --git a/src/addon/ESMPy/src/ESMF/__init__.py b/src/addon/ESMPy/src/ESMF/__init__.py index 9aee630788..a82ce63453 100644 --- a/src/addon/ESMPy/src/ESMF/__init__.py +++ b/src/addon/ESMPy/src/ESMF/__init__.py @@ -76,9 +76,6 @@ from ESMF.util.helpers import * from ESMF.api.constants import _ESMF_VERSION -# for testing -from ESMF.util.decorators import expected_failure - #### SET UP SOME INFO ######################################################### __name__ = "ESMF" @@ -94,5 +91,3 @@ __license__ = "University of Illinois-NCSA" __release__ = _ESMF_VERSION __version__ = _ESMF_VERSION - - diff --git a/src/addon/ESMPy/src/ESMF/api/constants.py b/src/addon/ESMPy/src/ESMF/api/constants.py index 98fa1c2fc8..b76a69d47d 100644 --- a/src/addon/ESMPy/src/ESMF/api/constants.py +++ b/src/addon/ESMPy/src/ESMF/api/constants.py @@ -4,6 +4,9 @@ from ESMF.util.enum import IntEnum +# Test exhaustive parameter +esmpy_test_exhaustive=False + # error message _errmsg = 'Please check the log files (named "*ESMF_LogFile").' _ESMP_SUCCESS = 0 diff --git a/src/addon/ESMPy/src/ESMF/api/esmpymanager.py b/src/addon/ESMPy/src/ESMF/api/esmpymanager.py index be1e72608f..286121effe 100644 --- a/src/addon/ESMPy/src/ESMF/api/esmpymanager.py +++ b/src/addon/ESMPy/src/ESMF/api/esmpymanager.py @@ -75,9 +75,14 @@ class Manager(object): will always be called prior to exiting Python. Calling __init__ explicitly results in a no-op. - The Manager can be used to enable the + The :class:`~ESMF.api.esmpymanager.Manager` can be used to enable the `MOAB `_ - mesh backend to the Mesh. This is done by calling ``set_moab()`` with ``moab_on=True``. + mesh backend to the :class:`~ESMF.api.esmpymanager.Mesh`. This is done by calling ``set_moab()`` with ``moab_on=True``. + + The :class:`~ESMF.api.esmpymanager.Manager` has a `test_exhaustive` member + variable that can be enabled to run + combinatorial expansions of :class:`~ESMF.api.esmpymanager.Grid` and + :class:`~ESMF.api.esmpymanager.Field` creation parameters. :param bool debug: outputs logging information to ESMF logfiles. If ``None``, defaults to False. @@ -126,6 +131,9 @@ def __init__(self, debug=False): # set up to use the ESMF native mesh backend by default self._moab = False + + # exhaustive testing set to False by default + self._test_exhaustive = False return diff --git a/src/addon/ESMPy/src/ESMF/interface/cbindings.py b/src/addon/ESMPy/src/ESMF/interface/cbindings.py index a7a7e3acf4..4adaea4f83 100644 --- a/src/addon/ESMPy/src/ESMF/interface/cbindings.py +++ b/src/addon/ESMPy/src/ESMF/interface/cbindings.py @@ -1943,6 +1943,7 @@ def ESMP_FieldPrint(field): Py3Char, ct.c_uint, ct.c_uint] +@netcdf def ESMP_FieldRead(field, filename, variablename, timeslice, iofmt=1): #TODO: C doc says it defaults to NETCDF(1), but actually defaults to BIN(0) """ @@ -2160,7 +2161,6 @@ def ESMP_FieldRegridStore(srcField, OptionalBool, OptionalField, OptionalField] -@deprecated def ESMP_FieldRegridStoreFile(srcField, dstField, filename, srcMaskValues=None, dstMaskValues=None, regridmethod=None, diff --git a/src/addon/ESMPy/src/ESMF/test/base.py b/src/addon/ESMPy/src/ESMF/test/base.py index 54344429dc..c54a9dd952 100644 --- a/src/addon/ESMPy/src/ESMF/test/base.py +++ b/src/addon/ESMPy/src/ESMF/test/base.py @@ -113,4 +113,3 @@ def wrap_ob(ob): return ob return wrap_ob - diff --git a/src/addon/ESMPy/src/ESMF/test/base_test.py b/src/addon/ESMPy/src/ESMF/test/base_test.py index 1a8fff0c7e..27a249db30 100644 --- a/src/addon/ESMPy/src/ESMF/test/base_test.py +++ b/src/addon/ESMPy/src/ESMF/test/base_test.py @@ -8,6 +8,7 @@ class Test(TestBase): def setup(self): mg = Manager() + mg.test_exhaustive = False # mg.barrier() def test_assertNumpyAll_bad_mask(self): @@ -25,4 +26,4 @@ def tearDown(self): # mg.barrier() if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py index 6dca02d866..313a76e63f 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py +++ b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py @@ -18,9 +18,9 @@ def read_control_file(): # Parse each test case line from the control file. test_cases = [] for line in open(os.path.join(TEST_REGRID_DIR, CONTROL_FNAME), 'r'): - if line[0] != '#' and re.match('(\s*.+\s*:){3}', line): + if line[0] != '#' and re.match(r'(\s*.+\s*:){3}', line): (src_fname, dst_fname, regrid_method, options, mean_err_str, - max_err_str, max_area_err_str) = re.split('\s*:\s*', line) + max_err_str, max_area_err_str) = re.split(r'\s*:\s*', line) test_cases.append([src_fname, dst_fname, regrid_method, options, float(mean_err_str), float(max_err_str), float(max_area_err_str)]) diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftest.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftest.py new file mode 100644 index 0000000000..788408c105 --- /dev/null +++ b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftest.py @@ -0,0 +1,18 @@ +# $Id$ + +""" +examples test file +""" + +import pytest + +from ESMF.test.base import TestBase, attr + +class TestRFF(TestBase): + + # # '0' in the name is so it is run first + # def test_0_regrid_from_file_dryrun(self): + # from ESMF.test.regrid_from_file import run_regrid_from_file_dryrun + + def test_regrid_from_file(self): + from ESMF.test.regrid_from_file import run_regrid_from_file diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftestdryrun.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftestdryrun.py new file mode 100644 index 0000000000..dc8e40e123 --- /dev/null +++ b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftestdryrun.py @@ -0,0 +1,14 @@ +# $Id$ + +""" +examples test file +""" + +import pytest + +from ESMF.test.base import TestBase, attr + +class TestRFFDryrun(TestBase): + + def test_regrid_from_file_dryrun(self): + from ESMF.test.regrid_from_file import run_regrid_from_file_dryrun diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py index fdc512551f..88ac6ee8a4 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py +++ b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py @@ -36,18 +36,12 @@ def cache_data_files_for_test_cases(test_cases): break return status_ok -# Main program: Retrieve data files from a remote server if they do not exist -# locally for each test read from a control file. -def main(): - # Read the test case parameters from the control file. - test_cases = read_control_file() - - # Retrieve the data files needed for the test cases from the remote server. - status_ok = cache_data_files_for_test_cases(test_cases) - if status_ok: - print ('RESULT: PASS - regrid_from_file_dryrun ok\n\n') - else: - print ('RESULT: FAIL - regrid_from_file_dryrun error\n\n') - -if __name__ == '__main__': - sys.exit(main()) +# Read the test case parameters from the control file. +test_cases = read_control_file() + +# Retrieve the data files needed for the test cases from the remote server. +status_ok = cache_data_files_for_test_cases(test_cases) +if status_ok: + print ('RESULT: PASS - regrid_from_file_dryrun ok\n\n') +else: + print ('RESULT: FAIL - regrid_from_file_dryrun error\n\n') diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py index e06c28c1f6..4ffb5ae7da 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py @@ -2,10 +2,7 @@ field unit test file """ -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest +import pytest from ESMF import * from ESMF.interface.cbindings import * @@ -14,6 +11,10 @@ class TestField(TestBase): + + mg = Manager(debug=True) + mg.test_exhaustive = False + # this is for the documentation, do not modify def create_field(grid_or_mesh, name): ''' @@ -71,7 +72,7 @@ def test_meta_del(self): del (self.field) assert (not hasattr(self, 'field')) - @attr('serial') + @pytest.mark.serial def test_numpy_funcs(self): field = self.make_field(np.array([10, 10], dtype=np.int32)) @@ -97,8 +98,8 @@ def test_numpy_funcs(self): - @attr('serial') - @attr('slow') + @pytest.mark.serial + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") #nosetests src/ESMF/test/test_api/test_field.py:TestField.test_field_create_2d_grid def _field_create_2d_grid(self): keywords = dict( @@ -148,8 +149,8 @@ def _field_create_2d_grid(self): raise ValueError( "The following combinations of parameters failed to create a proper Field: " + str(fail)) - @attr('serial') - @attr('slow') + @pytest.mark.serial + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") def _field_create_3d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -200,7 +201,7 @@ def _field_create_3d_grid(self): raise ValueError( "The following combinations of parameters failed to create a proper Field: " + str(len(fail))) - @attr('slow') + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") def _field_create_2d_mesh(self): parallel = False if pet_count() > 1: @@ -315,7 +316,7 @@ def test_field_uniqueness(self): assert (field.struct.ptr != field2.struct.ptr) - @attr('serial') + @pytest.mark.serial def test_field_area(self): grid = Grid(np.array([3, 4]), staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER], coord_sys=CoordSys.SPH_DEG, num_peri_dims=1, @@ -431,7 +432,7 @@ def test_field_extradims_mesh(self): field2.data[...] = 10 self.examine_field_attributes(field2) - @attr('serial') + @pytest.mark.serial def test_field_slice_grid(self): typekind = TypeKind.R8 grid = Grid(np.array([100, 100]), coord_sys=CoordSys.CART, @@ -471,7 +472,7 @@ def test_field_slice_grid(self): assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) # slicing is disabled in parallel - @attr('serial') + @pytest.mark.serial def test_field_slice_mesh(self): parallel = False if pet_count() > 1: @@ -510,7 +511,7 @@ def test_field_slice_mesh(self): assert (field2.grid.size[0] == 5) assert (field3.grid.size[0] == 2) - @attr('serial') + @pytest.mark.serial def test_field_slice_grid_extraindices(self): n = 10 grid = Grid(np.array([n,n]), coord_sys=CoordSys.CART, staggerloc=StaggerLoc.CENTER) @@ -548,7 +549,7 @@ def test_field_slice_grid_extraindices(self): assert (field2.grid.upper_bounds[0].tolist() == [5, 5]) assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) - @attr('serial') + @pytest.mark.serial def disable_est_field_slice_mesh_extraindices(self): parallel = False if pet_count() > 1: @@ -584,7 +585,7 @@ def disable_est_field_slice_mesh_extraindices(self): assert field2.data.shape == (5, 2, 1) assert field3.data.shape == (2, 1, 1) - @attr('serial') + @pytest.mark.serial def test_field_reshape(self): field = self.make_field(np.array([10, 10], dtype=np.int32), ndbounds=False) diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py index 11cca7fe5d..03e1ea73d8 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py @@ -11,11 +11,12 @@ import numpy as np import os import inspect -import unittest +import pytest class TestGrid(TestBase): - Manager(debug=True) + mg = Manager(debug=True) + mg.test_exhaustive = False def examine_grid_attributes(self, grid): # ~~~~~~~~~~~~~~~~~~~~~~ STAGGER LOCATIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,9 +179,9 @@ def test_grid_periodic(self): grid,_,_ = self.make_grid_periodic() self.examine_grid_attributes(grid) - @attr('serial') - @attr('slow') - def _grid_create_2d(self): + @pytest.mark.serial + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + def test_grid_create_2d(self): keywords = dict( # periodic specifies all valid combos of [pole_kind, num_peri_dims, periodic_dim, pole_dim] pole_kind=[[PoleKind.NONE, PoleKind.NONE], @@ -224,9 +225,9 @@ def _grid_create_2d(self): raise ValueError( "The following combinations of Grid parameters failed to create a proper Grid: " + str(fail)) - @attr('serial') - @attr('slow') - def _grid_create_3d(self): + @pytest.mark.serial + @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + def test_grid_create_3d(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] periodic=[[None, None, None], [None, None, 0], [None, None, 1], [None, None, 2], @@ -259,7 +260,7 @@ def _grid_create_3d(self): raise ValueError( "The following combinations of Grid parameters failed to create a proper Grid: " + str(fail)) - @attr('serial') + @pytest.mark.serial def test_grid_create_cubed_sphere(self): # keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -297,7 +298,7 @@ def test_grid_create_cubed_sphere(self): grid.destroy() # grid2.destroy() - @attr('serial') + @pytest.mark.serial def test_grid_slice_2d(self): grid = self.make_grid_2d() @@ -317,7 +318,7 @@ def test_grid_slice_2d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1] - @attr('serial') + @pytest.mark.serial def test_grid_slice_2d_corners(self): grid = self.make_grid_2d() @@ -348,7 +349,7 @@ def test_grid_slice_2d_corners(self): assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] - @attr('serial') + @pytest.mark.serial def test_grid_slice_3d(self): grid = self.make_grid_3d() @@ -368,7 +369,7 @@ def test_grid_slice_3d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1, 2) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1, 2] - @attr('serial') + @pytest.mark.serial def test_grid_slice_3d_corners(self): grid = self.make_grid_3d() @@ -403,7 +404,7 @@ def test_grid_slice_3d_corners(self): assert grid3.coords[cvf][0].shape == (3, 2, 3) assert grid3.upper_bounds[cvf].tolist() == [3, 2, 3] - @attr('serial') + @pytest.mark.serial def test_grid_slice_periodic(self): grid, x, y = self.make_grid_periodic() @@ -429,8 +430,7 @@ def test_grid_slice_periodic(self): assert grid3.coords[StaggerLoc.CORNER][0].shape == (3, 2) assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] - @attr('data') - @attr('serial') + @pytest.mark.serial def test_slice_grid_created_from_file_scrip(self): reg_decomp = [pet_count(), 1] try: @@ -629,7 +629,6 @@ def test_grid_area_3D(self): area[:] = areavals assert(np.all(area[...] == 12*np.ones([10, 20, 30]))) - @attr('data') def test_grid_create_from_file_gridspec1D(self): esmfdir = os.path.dirname(inspect.getfile(ESMF)) grid = Grid(filename=os.path.join(esmfdir, "test/data/gridspec1Dcoords.nc"), @@ -638,7 +637,6 @@ def test_grid_create_from_file_gridspec1D(self): self.examine_grid_attributes(grid) - @attr('data') def test_grid_create_from_file_scrip(self): reg_decomp = [pet_count(), 1] try: @@ -649,7 +647,6 @@ def test_grid_create_from_file_scrip(self): except: raise NameError('grid_create_from_file_scrip failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.BALANCED], @@ -662,7 +659,6 @@ def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): except: raise NameError('grid_create_from_file_scrip_balanced_balanced failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTFIRST], @@ -675,7 +671,6 @@ def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): except: raise NameError('grid_create_from_file_scrip_balanced_restfirst failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTLAST], @@ -688,8 +683,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): except: raise NameError('grid_create_from_file_scrip_balanced_restlast failed!') - @attr('data') - @unittest.expectedFailure + @pytest.mark.xfail def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.CYCLIC], @@ -702,7 +696,6 @@ def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): except: raise NameError('grid_create_from_file_scrip_balanced_cyclic failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.BALANCED], @@ -715,7 +708,6 @@ def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): except: raise NameError('grid_create_from_file_scrip_restfirst_balanced failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTFIRST], @@ -728,7 +720,6 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): except: raise NameError('grid_create_from_file_scrip_restfirst_restfirst failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTLAST], @@ -741,8 +732,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): except: raise NameError('grid_create_from_file_scrip_restfirst_restlast failed!') - @attr('data') - @unittest.expectedFailure + @pytest.mark.xfail def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.CYCLIC], @@ -755,7 +745,6 @@ def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): except: raise NameError('grid_create_from_file_scrip_restfirst_cyclic failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.BALANCED], @@ -768,7 +757,6 @@ def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): except: raise NameError('grid_create_from_file_scrip_restlast_balanced failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTFIRST], @@ -781,7 +769,6 @@ def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): except: raise NameError('grid_create_from_file_scrip_restlast_restfirst failed!') - @attr('data') def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTLAST], @@ -794,8 +781,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): except: raise NameError('grid_create_from_file_scrip_restlast_restlast failed!') - @attr('data') - @unittest.expectedFailure + @pytest.mark.xfail def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.CYCLIC], @@ -808,8 +794,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): except: raise NameError('grid_create_from_file_scrip_restlast_cyclic failed!') - @attr('data') - @unittest.expectedFailure + @pytest.mark.xfail def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.BALANCED], @@ -822,8 +807,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): except: raise NameError('grid_create_from_file_scrip_cyclic_balanced failed!') - @attr('data') - @unittest.expectedFailure + @pytest.mark.xfail def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTFIRST], @@ -836,8 +820,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): except: raise NameError('grid_create_from_file_scrip_cyclic_restfirst failed!') - @attr('data') - @unittest.expectedFailure + @pytest.mark.xfail def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTLAST], @@ -850,8 +833,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): except: raise NameError('grid_create_from_file_scrip_cyclic_restlast failed!') - @attr('data') - @unittest.expectedFailure + @pytest.mark.xfail def test_grid_create_from_file_scrip_decomp_cyclic_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.CYCLIC], diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py index 03c799b19d..1cdcb3dbdf 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py @@ -8,6 +8,7 @@ from ESMF.test.base import TestBase, attr import unittest +import pytest class TestLocStream(TestBase): @@ -52,7 +53,7 @@ def test_copy(self): assert np.all(l2["ESMF:X"] == [0, 1, 2, 3, 4]) - @attr('serial') + @pytest.mark.serial def test_slice(self): locstream = LocStream(5, name="Test LocStream") diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py index 18204e71e0..6bd06f4cf0 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py @@ -3,12 +3,7 @@ mesh unit test file """ -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - -import unittest +import pytest import os import inspect @@ -181,7 +176,6 @@ def test_mesh_50_mask_area(self): self.assertNumpyAll(mesh.area, elemArea) - @attr('data') def test_mesh_create_from_file_scrip(self): try: esmfdir = os.path.dirname(inspect.getfile(ESMF)) @@ -190,7 +184,6 @@ def test_mesh_create_from_file_scrip(self): except: raise NameError('mesh_create_from_file_scrip failed!') - @attr('data') def test_mesh_create_from_file_esmfmesh(self): try: esmfdir = os.path.dirname(inspect.getfile(ESMF)) @@ -221,7 +214,7 @@ def test_mesh_copy(self): self.check_mesh(mesh2, nodeCoord, nodeOwner) # slicing is disabled in parallel - @attr('serial') + @pytest.mark.serial def test_mesh_slicing(self): parallel = False if pet_count() > 1: @@ -257,8 +250,7 @@ def test_mesh_slicing(self): assert mesh3.size == [2, None] assert mesh3.size_owned == [2, None] - @attr('data') - @attr('serial') + @pytest.mark.serial def test_slice_mesh_created_from_file_scrip(self): try: esmfdir = os.path.dirname(inspect.getfile(ESMF)) @@ -281,8 +273,7 @@ def test_slice_mesh_created_from_file_scrip(self): assert mesh2.size == [5, None] assert mesh2.size_owned == [5, None] - @attr('data') - @attr('serial') + @pytest.mark.serial def test_slice_mesh_created_from_file_esmfmesh(self): try: esmfdir = os.path.dirname(inspect.getfile(ESMF)) @@ -304,9 +295,8 @@ def test_slice_mesh_created_from_file_esmfmesh(self): assert mesh2.size_owned == [5, None] - @attr('data') - @attr('serial') - @unittest.expectedFailure + @pytest.mark.serial + @pytest.mark.xfail #TODO: remove expected failure once we have a smaller data file with mesh element coordinates to use # TODO: have to define slicing for mesh element coordinates as well.. def test_slice_mesh_created_from_file_elem_coords(self): diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py index 2e82f7b650..cacf811154 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py @@ -2,10 +2,7 @@ regrid unit test file """ -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest +import pytest import os @@ -84,7 +81,7 @@ def test_field_regrid(self): line_type=LineType.CART, factors=False) _ = rh(srcfield, dstfield) - @attr('serial') + @pytest.mark.serial def test_field_regrid_factor_retrieval(self): # Test retrieving factors from a route handle. @@ -187,7 +184,7 @@ def test_field_regrid_factor_retrieval(self): rh.destroy() - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_file1(self): mgr = Manager() @@ -241,7 +238,7 @@ def test_field_regrid_file1(self): if os.path.isfile(path): os.remove(path) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_file2(self): mgr = Manager() filename = 'esmpy_test_field_regrid_file2.nc' @@ -312,7 +309,7 @@ def test_field_regrid_file2(self): if os.path.isfile(path): os.remove(path) - @attr('parallel') + @pytest.mark.parallel # remove this test for 8.2.0 due to unexplained segv def tet_field_regrid_file_withaux(self): import os @@ -377,7 +374,7 @@ def tet_field_regrid_file_withaux(self): if os.path.isfile(path): os.remove(path) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_file3(self): mgr = Manager() filename = 'esmpy_test_field_from_file.nc' @@ -472,7 +469,7 @@ def test_field_regrid_file3(self): os.remove(path) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_file4(self): mgr = Manager() filename = 'routehandlefile.nc' @@ -611,7 +608,7 @@ def test_field_regrid_gridmesh(self): rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.CONSERVE) dstfield = rh(srcfield, dstfield) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_zeroregion(self): parallel = False if pet_count() > 1: @@ -658,7 +655,7 @@ def test_field_regrid_zeroregion(self): if dstfield.grid.mask[StaggerLoc.CENTER][i, j] == 0: assert(dstfield[i, j] == 0) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_zeroregion_select_ndbounds(self): # Test zero region select during a sparse matrix multiplication # having undistributed dimensions. @@ -710,7 +707,7 @@ def test_field_regrid_zeroregion_select_ndbounds(self): if os.path.exists(filename): os.remove(filename) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_area(self): parallel = False if pet_count() > 1: @@ -752,7 +749,7 @@ def test_field_regrid_area(self): if (dstarea.data[i] != 0.25): assert (dstarea.data[i] == 0.125) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_periodic(self): parallel = False if pet_count() > 1: @@ -802,7 +799,7 @@ def test_field_regrid_periodic(self): self.assertAlmostEqual(meanrel, 0.0016447124122954575) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_grid_3d_bilinear_cartesian(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -832,7 +829,7 @@ def test_grid_grid_3d_bilinear_cartesian(self): self.assertAlmostEqual(meanrel, 0.00215601743167) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_grid_3d_bilinear_spherical(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -862,7 +859,7 @@ def test_grid_grid_3d_bilinear_spherical(self): self.assertAlmostEqual(meanrel, 0.00061587737764545617) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_grid_regrid_csrv_mask_3D(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -903,7 +900,7 @@ def test_grid_grid_regrid_csrv_mask_3D(self): self.assertAlmostEqual(meanrel, 0.0021560174316746865) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_grid_regrid_csrv_mask(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -945,7 +942,7 @@ def test_grid_grid_regrid_csrv_mask(self): self.assertAlmostEqual(meanrel, 0.0024803189848013785) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_grid_regrid_csrv_2nd_mask(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -987,7 +984,7 @@ def test_grid_grid_regrid_csrv_2nd_mask(self): self.assertAlmostEqual(meanrel, 0.0020296891000258252) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_grid_regrid_srcmask_types(self): # NOTE: this tests an old issue where the items of a grid were not properly set when # the grid coord_typekind differed from the field typekind. @@ -1033,7 +1030,7 @@ def test_grid_grid_regrid_srcmask_types(self): self.assertAlmostEqual(meanrel, 0.0024803189848013785) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_mesh_regrid_csrv_mask(self): parallel = False if pet_count() > 1: @@ -1091,7 +1088,7 @@ def test_grid_mesh_regrid_csrv_mask(self): self.assertAlmostEqual(meanrel, 0.038806630051265847) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_mesh_regrid_csrv(self): parallel = False if pet_count() > 1: @@ -1147,7 +1144,7 @@ def test_grid_mesh_regrid_csrv(self): self.assertAlmostEqual(meanrel, 0.037733241800767432) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_mesh_regrid_mask(self): parallel = False if pet_count() > 1: @@ -1192,7 +1189,7 @@ def test_grid_mesh_regrid_mask(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_grid_mesh_regrid(self): parallel = False if pet_count() > 1: @@ -1236,7 +1233,7 @@ def test_grid_mesh_regrid(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_extrapolation(self): parallel = False if pet_count() > 1: @@ -1283,7 +1280,7 @@ def test_field_regrid_extrapolation(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_field_regrid_extrapolation_creepfill(self): parallel = False if pet_count() > 1: @@ -1328,7 +1325,7 @@ def test_field_regrid_extrapolation_creepfill(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def test_mesh_mesh_regrid(self): parallel = False if pet_count() > 1: @@ -1388,7 +1385,7 @@ def test_mesh_mesh_regrid(self): self.assertAlmostEqual(meanrel, 0.037109375) self.assertAlmostEqual(csrvrel, 0.0) - @attr('parallel') + @pytest.mark.parallel def est_grid_mesh_pentatri_regrid_csrv(self): parallel = False if pet_count() > 1: @@ -1497,7 +1494,7 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): assert (meanrel < 10E-2) assert (csrvrel < 10E-14) - @attr('parallel') + @pytest.mark.parallel def test_grid_mesh_pentatri_regrid_bilinear(self): parallel = False if pet_count() > 1: diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py index e8c7223d4d..52234f2b25 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py @@ -6,8 +6,10 @@ from ESMF.interface.cbindings import * from ESMF.test.base import TestBase, attr +import pytest + class TestVM(TestBase): - @attr('parallel') + @pytest.mark.parallel def test_vm_broadcast(self): mg = Manager() @@ -27,7 +29,7 @@ def test_vm_broadcast(self): mg.barrier() - @attr('parallel') + @pytest.mark.parallel def test_vm_reduce(self): send = np.ones(4, dtype=np.float64) recv = np.zeros(4, dtype=np.float64) diff --git a/src/addon/ESMPy/src/ESMF/util/decorators.py b/src/addon/ESMPy/src/ESMF/util/decorators.py index 2c98ad8cd2..b3a297d9c9 100644 --- a/src/addon/ESMPy/src/ESMF/util/decorators.py +++ b/src/addon/ESMPy/src/ESMF/util/decorators.py @@ -12,28 +12,6 @@ from ESMF.api.constants import LogKind, _ESMF_NETCDF from ESMF.util.exceptions import NetCDFMissing -try: - import nose - - def expected_failure(test): - @functools.wraps(test) - def inner(*args, **kwargs): - try: - test(*args, **kwargs) - except Exception: - raise nose.SkipTest - return inner -except: - def expected_failure(test): - @functools.wraps(test) - def inner(*args, **kwargs): - try: - test(*args, **kwargs) - except: - raise AssertionError('SkipTest: Failure expected') - return inner - - def beta(func): '''This is a decorator that can be used to mark functions as beta. Other decorators must be upper.''' diff --git a/src/addon/ESMPy/src/ESMF/util/exceptions.py b/src/addon/ESMPy/src/ESMF/util/exceptions.py index 4075087fc8..0ecb885176 100644 --- a/src/addon/ESMPy/src/ESMF/util/exceptions.py +++ b/src/addon/ESMPy/src/ESMF/util/exceptions.py @@ -26,6 +26,10 @@ class SerialMethod(ESMPyException): """This method is not safe to run in parallel!""" pass +class SkipTest(ESMPyException): + """This test is skipped for some reason.""" + pass + class GridException(ESMPyException): @@ -79,12 +83,3 @@ class FieldDOError(FieldException): """Raised when an attempt is made to build a Field on an undefined discretization object (e.g. not a Grid or a Mesh)""" pass - -class TestException(ESMPyException): - """Base class for errors in the ESMPy testing.""" - pass - -class TestGridWriteBeforeCoords(TestException): - """Raised when an attempt is made to write a Grid before c - coordinates have been specified""" - pass From aead97d6220044c540e89028184f8d6e3cebdc88 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Mon, 22 Aug 2022 14:37:06 -0600 Subject: [PATCH 123/266] Cheyenne adjustments --- src/addon/ESMPy/Makefile | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 78eeea3042..770c6634c0 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -14,34 +14,33 @@ clean: # rm -rf src/ESMF/test/regrid_from_file/data') # rm -rf examples/data') - install: - pip install . + python3 -m pip install --user . test_unit: - pytest -m="not parallel" + python3 -m pytest -m="not parallel" test_unit_parallel: - mpirun -n 4 python -m pytest -m="not serial" + mpirun -n 4 python3 -m pytest -m="not serial" test_examples_dryrun: - pytest -vs examples/exampletestdryrun.py + python3 -m pytest -vs examples/exampletestdryrun.py test_examples: - pytest -m="not parallel" examples/exampletest.py + python3 -m pytest -vs -m="not parallel" examples/exampletest.py test_examples_parallel: - mpirun -n 4 python -m pytest -m="not serial" examples/exampletest.py + mpirun -n 4 python3 -vs -m pytest -m="not serial" examples/exampletest.py test_regrid_from_file_dryrun: - pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py + python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py test_regrid_from_file: - pytest -vs src/ESMF/test/regrid_from_file/rfftest.py + python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftest.py test_regrid_from_file_parallel: - pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py - mpirun -n 4 python -m pytest -vs src/ESMF/test/regrid_from_file/rfftest.py + python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py + mpirun -n 4 python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftest.py test_all: test_unit test_parallel test_examples_dryrun test_examples test_examples_parallel @@ -50,4 +49,5 @@ test: test_unit test_unit_parallel test_examples test_examples_parallel test_uni: test_unit test_examples uninstall: - pip uninstall ESMPy + python3 -m pip uninstall ESMPy + From 84cf0c115f1daabd965549de2d3aef1d9e703de2 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Mon, 22 Aug 2022 13:37:43 -0700 Subject: [PATCH 124/266] remove more unittest usage --- src/addon/ESMPy/examples/grid_locstream_regrid.py | 5 ----- src/addon/ESMPy/examples/locstream_grid_regrid.py | 5 ----- src/addon/ESMPy/examples/mesh_locstream_regrid.py | 5 ----- src/addon/ESMPy/src/ESMF/test/base_test.py | 5 ----- src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py | 5 ++--- src/addon/ESMPy/src/ESMF/test/test_cbindings.py | 6 ++---- 6 files changed, 4 insertions(+), 27 deletions(-) diff --git a/src/addon/ESMPy/examples/grid_locstream_regrid.py b/src/addon/ESMPy/examples/grid_locstream_regrid.py index ffcdf7b535..bd64c03c5f 100644 --- a/src/addon/ESMPy/examples/grid_locstream_regrid.py +++ b/src/addon/ESMPy/examples/grid_locstream_regrid.py @@ -9,11 +9,6 @@ # from ESMF.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - import ESMF import numpy diff --git a/src/addon/ESMPy/examples/locstream_grid_regrid.py b/src/addon/ESMPy/examples/locstream_grid_regrid.py index e09db8956b..534f89a4cf 100644 --- a/src/addon/ESMPy/examples/locstream_grid_regrid.py +++ b/src/addon/ESMPy/examples/locstream_grid_regrid.py @@ -9,11 +9,6 @@ # from ESMF.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - import ESMF import numpy diff --git a/src/addon/ESMPy/examples/mesh_locstream_regrid.py b/src/addon/ESMPy/examples/mesh_locstream_regrid.py index c707a6c56e..a5f218ff0c 100644 --- a/src/addon/ESMPy/examples/mesh_locstream_regrid.py +++ b/src/addon/ESMPy/examples/mesh_locstream_regrid.py @@ -1,10 +1,5 @@ # This example demonstrates how to regrid between a mesh and a locstream. -try: - from unittest import SkipTest -except ImportError: - from nose import SkipTest - import ESMF import numpy diff --git a/src/addon/ESMPy/src/ESMF/test/base_test.py b/src/addon/ESMPy/src/ESMF/test/base_test.py index 27a249db30..ba7bfd7a3c 100644 --- a/src/addon/ESMPy/src/ESMF/test/base_test.py +++ b/src/addon/ESMPy/src/ESMF/test/base_test.py @@ -1,9 +1,7 @@ -import unittest from ESMF.test.base import TestBase import numpy as np from ESMF import Manager - class Test(TestBase): def setup(self): @@ -24,6 +22,3 @@ def test_assertNumpyAll_type_differs(self): def tearDown(self): mg = Manager() # mg.barrier() - -if __name__ == "__main__": - unittest.main() diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py index 1cdcb3dbdf..92a3af7c45 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py @@ -7,7 +7,6 @@ from ESMF.interface.cbindings import * from ESMF.test.base import TestBase, attr -import unittest import pytest class TestLocStream(TestBase): @@ -70,7 +69,7 @@ def test_slice(self): assert(np.all(locstream["ESMF:X"] == np.array([0, 1, 2, 3, 4]))) - @unittest.expectedFailure + @pytest.mark.xfail def test_pickle(self): locstream = LocStream(10, name="Test LocStream") @@ -78,7 +77,7 @@ def test_pickle(self): pickle.dumps(locstream) - @unittest.expectedFailure + @pytest.mark.xfail def test_properties(self): locstream = LocStream(10, name="Test LocStream") locstream["ESMF:X"] = (1, 2, 3, 4, 5) diff --git a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py b/src/addon/ESMPy/src/ESMF/test/test_cbindings.py index a7369977d5..391c9ff91b 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py +++ b/src/addon/ESMPy/src/ESMF/test/test_cbindings.py @@ -10,8 +10,6 @@ import numpy as np -import unittest - class TestCbindings(TestBase): def test_log(self): @@ -34,7 +32,7 @@ def test_interfaceint(self): interfaceint = ESMP_InterfaceInt(Narray) - @unittest.expectedFailure + @pytest.mark.xfail def test_interfaceint2(self): # This test should fail try: @@ -44,7 +42,7 @@ def test_interfaceint2(self): except: raise TypeError('FAIL: tuples cannot be used in place of numpy.array') - @unittest.expectedFailure + @pytest.mark.xfail def test_interfaceint3(self): # This test should fail try: From 05591045414eb892b1ef6111ad4029f65169e638 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Mon, 22 Aug 2022 15:20:16 -0600 Subject: [PATCH 125/266] add pytest import to test_cbindings --- src/addon/ESMPy/src/ESMF/test/test_cbindings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py b/src/addon/ESMPy/src/ESMF/test/test_cbindings.py index 391c9ff91b..2099857328 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py +++ b/src/addon/ESMPy/src/ESMF/test/test_cbindings.py @@ -4,6 +4,8 @@ unit test file """ +import pytest + from ESMF import * from ESMF.interface.cbindings import * from ESMF.test.base import TestBase, attr From 31e0ccfbbddc227a18a0724562e3d2e9e6a4cf90 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Mon, 22 Aug 2022 14:47:14 -0700 Subject: [PATCH 126/266] use unittest.SkipTest, cleanup some warnings, more adjustments to makefile targets --- src/addon/ESMPy/Makefile | 27 +++++---- src/addon/ESMPy/examples/exampletest.py | 2 +- .../ESMPy/examples/grid_locstream_regrid.py | 1 + .../ESMPy/examples/locstream_grid_regrid.py | 1 + .../ESMPy/examples/mesh_locstream_regrid.py | 1 + src/addon/ESMPy/src/ESMF/test/base.py | 1 + .../src/ESMF/test/test_api/test_field.py | 2 +- .../ESMPy/src/ESMF/test/test_api/test_mesh.py | 2 +- .../src/ESMF/test/test_api/test_regrid.py | 2 +- src/addon/ESMPy/src/ESMF/util/exceptions.py | 5 -- .../ESMPy/src/ESMF/util/grid_utilities.py | 20 +++---- .../ESMPy/src/ESMF/util/mesh_utilities.py | 56 +++++++++---------- 12 files changed, 59 insertions(+), 61 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 770c6634c0..caa773d0c3 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -3,16 +3,16 @@ clean: rm -rf build rm -rf dist - rm -rf *.egg-info - # find . -name "*.pyc" -exec rm -f {} \;') - # find . -name "*ESMF_LogFile*" -exec rm -f {} \;') - # find . -name "*.log" -exec rm -f {} \;') - # find . -name "*.vtk" -exec rm -f {} \;') - # rm src/ESMF/interface/esmfmkfile.py') - # rm -rf build') - # rm -rf dist') - # rm -rf src/ESMF/test/regrid_from_file/data') - # rm -rf examples/data') + find . -name "*.egg-info" -exec rm -rf {} \; + find . -name "*.pyc" -exec rm -f {} \; + find . -name "*ESMF_LogFile*" -exec rm -f {} \; + find . -name "*.log" -exec rm -f {} \; + find . -name "*.vtk" -exec rm -f {} \; + find . -name "*.pytest_cache" -exec rm -rf {} \; + find . -name "*.python-version" -exec rm -f {} \; + rm -rf src/ESMF/test/regrid_from_file/data + rm -rf examples/data + rm src/ESMF/interface/esmfmkfile.py install: python3 -m pip install --user . @@ -30,7 +30,7 @@ test_examples: python3 -m pytest -vs -m="not parallel" examples/exampletest.py test_examples_parallel: - mpirun -n 4 python3 -vs -m pytest -m="not serial" examples/exampletest.py + mpirun -n 4 python3 -m pytest -vs -m="not serial" examples/exampletest.py test_regrid_from_file_dryrun: python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py @@ -42,12 +42,11 @@ test_regrid_from_file_parallel: python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py mpirun -n 4 python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftest.py -test_all: test_unit test_parallel test_examples_dryrun test_examples test_examples_parallel +test_all: test_unit test_parallel test_examples test_examples_parallel -test: test_unit test_unit_parallel test_examples test_examples_parallel +test_parallel: test_unit_parallel test_examples_dryrun test_examples_parallel test_uni: test_unit test_examples uninstall: python3 -m pip uninstall ESMPy - diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/exampletest.py index a48a59480d..d82f2e56ad 100644 --- a/src/addon/ESMPy/examples/exampletest.py +++ b/src/addon/ESMPy/examples/exampletest.py @@ -6,7 +6,7 @@ import pytest -from ESMF.test.base import TestBase, attr +from ESMF.test.base import TestBase, attr, SkipTest import ESMF.api.constants as constants class TestExamples(TestBase): diff --git a/src/addon/ESMPy/examples/grid_locstream_regrid.py b/src/addon/ESMPy/examples/grid_locstream_regrid.py index bd64c03c5f..164d5c9211 100644 --- a/src/addon/ESMPy/examples/grid_locstream_regrid.py +++ b/src/addon/ESMPy/examples/grid_locstream_regrid.py @@ -14,6 +14,7 @@ import ESMF.util.helpers as helpers import ESMF.api.constants as constants +from ESMF.test.base import SkipTest # This call enables debug logging ESMF.Manager(debug=True) diff --git a/src/addon/ESMPy/examples/locstream_grid_regrid.py b/src/addon/ESMPy/examples/locstream_grid_regrid.py index 534f89a4cf..4d1019b409 100644 --- a/src/addon/ESMPy/examples/locstream_grid_regrid.py +++ b/src/addon/ESMPy/examples/locstream_grid_regrid.py @@ -14,6 +14,7 @@ import ESMF.util.helpers as helpers import ESMF.api.constants as constants +from ESMF.test.base import TestBase, attr, SkipTest # This call enables debug logging ESMF.Manager(debug=True) diff --git a/src/addon/ESMPy/examples/mesh_locstream_regrid.py b/src/addon/ESMPy/examples/mesh_locstream_regrid.py index a5f218ff0c..e88425410c 100644 --- a/src/addon/ESMPy/examples/mesh_locstream_regrid.py +++ b/src/addon/ESMPy/examples/mesh_locstream_regrid.py @@ -5,6 +5,7 @@ import ESMF.util.helpers as helpers import ESMF.api.constants as constants +from ESMF.test.base import TestBase, attr, SkipTest # This call enables debug logging # ESMF.Manager(debug=True) diff --git a/src/addon/ESMPy/src/ESMF/test/base.py b/src/addon/ESMPy/src/ESMF/test/base.py index c54a9dd952..e0ad849d30 100644 --- a/src/addon/ESMPy/src/ESMF/test/base.py +++ b/src/addon/ESMPy/src/ESMF/test/base.py @@ -3,6 +3,7 @@ import ESMF from ESMF.util.itester import iter_product_keywords +from unittest import SkipTest class TestBase(unittest.TestCase): diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py index 4ffb5ae7da..a77fa63dfb 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py @@ -6,7 +6,7 @@ from ESMF import * from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr +from ESMF.test.base import TestBase, attr, SkipTest from ESMF.util.mesh_utilities import mesh_create_50, mesh_create_50_parallel diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py index 6bd06f4cf0..2faa246899 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py @@ -10,7 +10,7 @@ import ESMF from ESMF import * -from ESMF.test.base import TestBase, attr +from ESMF.test.base import TestBase, attr, SkipTest from ESMF.util.mesh_utilities import * class TestMesh(TestBase): diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py b/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py index cacf811154..aaac4f78cd 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py @@ -7,7 +7,7 @@ import os from ESMF import * -from ESMF.test.base import TestBase, attr +from ESMF.test.base import TestBase, attr, SkipTest from ESMF.util.field_utilities import compare_fields from ESMF.util.grid_utilities import * from ESMF.util.mesh_utilities import * diff --git a/src/addon/ESMPy/src/ESMF/util/exceptions.py b/src/addon/ESMPy/src/ESMF/util/exceptions.py index 0ecb885176..3924539904 100644 --- a/src/addon/ESMPy/src/ESMF/util/exceptions.py +++ b/src/addon/ESMPy/src/ESMF/util/exceptions.py @@ -26,11 +26,6 @@ class SerialMethod(ESMPyException): """This method is not safe to run in parallel!""" pass -class SkipTest(ESMPyException): - """This test is skipped for some reason.""" - pass - - class GridException(ESMPyException): """Base class for errors in the Grid class.""" diff --git a/src/addon/ESMPy/src/ESMF/util/grid_utilities.py b/src/addon/ESMPy/src/ESMF/util/grid_utilities.py index cf2492a432..2227f3bb62 100644 --- a/src/addon/ESMPy/src/ESMF/util/grid_utilities.py +++ b/src/addon/ESMPy/src/ESMF/util/grid_utilities.py @@ -401,12 +401,12 @@ def grid_create_from_coordinates_periodic_3d(longitudes, latitudes, heights, return grid def initialize_field_grid(field, domask=False, doarea=False): - ''' + """ PRECONDITIONS: A Field has been created. POSTCONDITIONS: The 'field' has been initialized to an analytic field. RETURN VALUES: \n Field :: field \n - ''' + """ if domask: mask = field.grid.get_item(ESMF.GridItem.MASK) @@ -423,14 +423,14 @@ def initialize_field_grid(field, domask=False, doarea=False): return field def initialize_field_grid_periodic(field): - ''' + """ PRECONDITIONS: A Field has been created as 'field' with a 'grid' where coordinates have been set on both the center and corner stagger locations. \n POSTCONDITIONS: The 'field' has been initialized to an analytic field.\n RETURN VALUES: \n Field :: field \n - ''' + """ DEG2RAD = 3.141592653589793/180.0 # get the coordinate pointers and set the coordinates @@ -444,14 +444,14 @@ def initialize_field_grid_periodic(field): return field def initialize_field_grid_periodic_3d(field): - ''' + """ PRECONDITIONS: A Field has been created as 'field' with a 'grid' where coordinates have been set on both the center and corner stagger locations. \n POSTCONDITIONS: The 'field' has been initialized to an analytic field.\n RETURN VALUES: \n Field :: field \n - ''' + """ DEG2RAD = 3.141592653589793/180.0 # get the coordinate pointers and set the coordinates @@ -467,12 +467,12 @@ def initialize_field_grid_periodic_3d(field): return field def initialize_field_grid_3d(field, domask=False): - ''' + """ PRECONDITIONS: A Field has been created. POSTCONDITIONS: The 'field' has been initialized to an analytic field. RETURN VALUES: \n Field :: field \n - ''' + """ if domask: mask = field.grid.get_item(ESMF.GridItem.MASK) @@ -491,14 +491,14 @@ def initialize_field_grid_3d(field, domask=False): def compute_mass_grid(valuefield, dofrac=False, fracfield=None, uninitval=422397696.): - ''' + """ PRECONDITIONS: 'fracfield' contains the fractions of each cell which contributed to a regridding operation involving 'valuefield. 'dofrac' is a boolean value that gives the option to not use the 'fracfield'.\n POSTCONDITIONS: The mass of the data field is computed.\n RETURN VALUES: float :: mass \n - ''' + """ mass = 0.0 areafield = ESMF.Field(valuefield.grid, name='areafield') areafield.get_area() diff --git a/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py b/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py index 40b2cc030d..f9ff990b16 100644 --- a/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py +++ b/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py @@ -19,7 +19,7 @@ def mesh_create_5_pentahexa(coord_sys=None): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -43,7 +43,7 @@ def mesh_create_5_pentahexa(coord_sys=None): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) @@ -91,7 +91,7 @@ def mesh_create_5_pentahexa(coord_sys=None): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_4_ngons(): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 4 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -113,7 +113,7 @@ def mesh_create_4_ngons(): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -149,7 +149,7 @@ def mesh_create_4_ngons(): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_5(): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -170,7 +170,7 @@ def mesh_create_5(): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -212,7 +212,7 @@ def mesh_create_5(): return mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord def mesh_create_10(): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 10 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -237,7 +237,7 @@ def mesh_create_10(): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -281,7 +281,7 @@ def mesh_create_10(): return mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord def mesh_create_50(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -322,7 +322,7 @@ def mesh_create_50(domask=False, doarea=False): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -397,7 +397,7 @@ def mesh_create_50(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord def mesh_create_50_ngons(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -443,7 +443,7 @@ def mesh_create_50_ngons(domask=False, doarea=False): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -524,7 +524,7 @@ def mesh_create_50_ngons(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_4_ngons(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 4 element Mesh has been created. RETURN VALUES: \n Mesh :: mesh \n @@ -546,7 +546,7 @@ def mesh_create_4_ngons(domask=False, doarea=False): Element Ids in centers Note: This mesh is not parallel, it can only be used in serial - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -592,7 +592,7 @@ def mesh_create_4_ngons(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_5_parallel (): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -620,7 +620,7 @@ def mesh_create_5_parallel (): # # Node Id labels at corners # Element Id labels in centers - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -702,7 +702,7 @@ def mesh_create_5_parallel (): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_5_pentahexa_parallel (): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 5 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -733,7 +733,7 @@ def mesh_create_5_pentahexa_parallel (): # # Node Id labels at corners # Element Id labels in centers - ''' + """ # Two parametric dimensions, and two spatial dimensions mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) @@ -821,7 +821,7 @@ def mesh_create_5_pentahexa_parallel (): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_10_parallel (): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 10 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -855,7 +855,7 @@ def mesh_create_10_parallel (): # # Node Id labels at corners # Element Id labels in centers - ''' + """ if ESMF.pet_count() > 1: if ESMF.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') @@ -947,7 +947,7 @@ def mesh_create_10_parallel (): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_50_parallel(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -993,7 +993,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): Node Ids at corners Element Ids in centers - ''' + """ if ESMF.pet_count() > 1: if ESMF.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') @@ -1137,7 +1137,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): return mesh, nodeCoord, nodeOwner, elemType, elemConn def mesh_create_50_ngons_parallel(domask=False, doarea=False): - ''' + """ PRECONDITIONS: None POSTCONDITIONS: A 50 element Mesh has been created in parallel. RETURN VALUES: \n Mesh :: mesh \n @@ -1188,7 +1188,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): Node Ids at corners Element Ids in centers - ''' + """ if ESMF.pet_count() > 1: if ESMF.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') @@ -1337,12 +1337,12 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, domask=False, elemMask=None): - ''' + """ PRECONDITIONS: A Field has been created on the elements of a Mesh. POSTCONDITIONS: The Field has been initialized to an analytic field. RETURN VALUES: \n Field :: field \n - ''' + """ [node, element] = [0,1] @@ -1404,14 +1404,14 @@ def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, def compute_mass_mesh(valuefield, dofrac=False, fracfield=None, uninitval=422397696.): - ''' + """ PRECONDITIONS: 'fracfield' contains the fractions of each cell which contributed to a regridding operation involving 'valuefield. 'dofrac' is a boolean value that gives the option to not use the 'fracfield'.\n POSTCONDITIONS: The mass of the data field is computed.\n RETURN VALUES: float :: mass \n - ''' + """ mass = 0.0 # mesh area field must be built on elements areafield = ESMF.Field(valuefield.grid, name='areafield', From 5f2b55acea21c6b043da89480c60596242746f9f Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 23 Aug 2022 13:34:47 -0700 Subject: [PATCH 127/266] Officially document the label_Pre/PostChildrenAdvertise/Realize/DataInitialize specialization points. --- .../NUOPC/doc/NUOPC_Driver_manual_fapi.tex | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/addon/NUOPC/doc/NUOPC_Driver_manual_fapi.tex b/src/addon/NUOPC/doc/NUOPC_Driver_manual_fapi.tex index 3f6c6471e5..8143c7d973 100644 --- a/src/addon/NUOPC/doc/NUOPC_Driver_manual_fapi.tex +++ b/src/addon/NUOPC/doc/NUOPC_Driver_manual_fapi.tex @@ -82,6 +82,36 @@ \item Optional. By default CplList attributes are not modified. \item Modify the CplList attribute on the child components as desired. This can be useful to set custom Connection Options for specific Field pairs. \end{itemize} + \item {\bf label\_PreChildrenAdvertise} + \begin{itemize} + \item Optional. + \item Allow driver to execute specific code before calling the Advertise phase of its children. + \end{itemize} + \item {\bf label\_PostChildrenAdvertise} + \begin{itemize} + \item Optional. + \item Allow driver to execute specific code after calling the Advertise phase of its children. + \end{itemize} + \item {\bf label\_PreChildrenRealize} + \begin{itemize} + \item Optional. + \item Allow driver to execute specific code before calling the Realize phase of its children. + \end{itemize} + \item {\bf label\_PostChildrenRealize} + \begin{itemize} + \item Optional. + \item Allow driver to execute specific code after calling the Realize phase of its children. + \end{itemize} + \item {\bf label\_PreChildrenDataInitialize} + \begin{itemize} + \item Optional. + \item Allow driver to execute specific code before calling the DataInitialize phase of its children. + \end{itemize} + \item {\bf label\_PostChildrenDataInitialize} + \begin{itemize} + \item Optional. + \item Allow driver to execute specific code after calling the DataInitialize phase of its children. + \end{itemize} \end{itemize} \item Run: \begin{itemize} From 512b56a4aae41ec8badcc1a3647bd47874d386f1 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Tue, 23 Aug 2022 16:59:50 -0700 Subject: [PATCH 128/266] update ESMPy docs with pytest commands --- src/addon/ESMPy/doc/install.rst | 39 ++++++++++++++------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/addon/ESMPy/doc/install.rst b/src/addon/ESMPy/doc/install.rst index aec7b904b6..40a02896ff 100644 --- a/src/addon/ESMPy/doc/install.rst +++ b/src/addon/ESMPy/doc/install.rst @@ -17,7 +17,7 @@ The following packages are *optional*: * ESMF installation with NetCDF - required to create :class:`Grids ` and :class:`Meshes ` from file - NetCDF must be built as a shared library for ESMPy installation to succeed * `mpi4py `_- python bindings to MPI, needed to run some of the parallel regridding examples -* `nose2 `_ - for nose testing +* `pytest `_ - for testing ---------------- Getting the code @@ -76,7 +76,7 @@ with the following command issued from the top level ESMPy directory: .. code:: - pip install . + python3 -m pip install . Please contact esmf_support@ucar.edu with any questions. @@ -94,22 +94,29 @@ To use ESMPy in an external program, import it with: Validation ---------- -The ESMPy testing is done with the nose package, both in serial and -parallel. The nose commands are wrapped in the following ESMPy targets: +The ESMPy testing is done with the pytest package, both in serial and +parallel. Basic unit tests can be run with the following command: .. code:: - python setup.py test + python3 -m pytest + +There are a few other pytest targets available for a wider range of testing if +greater test coverage is desired: - python setup.py test_examples +.. code:: + + make test_unit + + make test_examples - python setup.py test_regrid_from_file + make test_regrid_from_file - python setup.py test_parallel + make test_unit_parallel - python setup.py test_examples_parallel + make test_examples_parallel - python setup.py test_regrid_from_file_parallel + make test_regrid_from_file_parallel .. Note:: @@ -118,18 +125,6 @@ parallel. The nose commands are wrapped in the following ESMPy targets: files without actually running them (allowing the stress on the machine to be applied to bandwidth first, and then memory). -Alternatively, individual tests can be run with nose using the following format: - -.. code:: - - nosetests : - -e.g. - -.. code:: - - nosetests src/ESMF/test/test_api/test_regrid.py:TestRegrid.test_field_regrid - ----------- Limitations ----------- From d808ee9846f95e630afd7dd212de65602ed6ed73 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 24 Aug 2022 12:26:12 -0700 Subject: [PATCH 129/266] remove the old esmfmkfile.py strategy from ESMPy --- src/addon/ESMPy/.gitignore | 1 - src/addon/ESMPy/Makefile | 1 - .../ESMPy/src/ESMF/interface/loadESMF.py | 19 ++----------------- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/addon/ESMPy/.gitignore b/src/addon/ESMPy/.gitignore index 15e6c72411..c427f66ad7 100644 --- a/src/addon/ESMPy/.gitignore +++ b/src/addon/ESMPy/.gitignore @@ -30,7 +30,6 @@ PET* build dist doc/esmpy_doc -src/ESMF/interface/esmfmkfile.py src/ESMPy.egg-info examples/data src/ESMF/test/data diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index caa773d0c3..d0018c2723 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -12,7 +12,6 @@ clean: find . -name "*.python-version" -exec rm -f {} \; rm -rf src/ESMF/test/regrid_from_file/data rm -rf examples/data - rm src/ESMF/interface/esmfmkfile.py install: python3 -m pip install --user . diff --git a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py b/src/addon/ESMPy/src/ESMF/interface/loadESMF.py index ca5395f4a3..dfed9ae412 100644 --- a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py +++ b/src/addon/ESMPy/src/ESMF/interface/loadESMF.py @@ -20,25 +20,10 @@ raise ImportError('The CTypes library cannot be found.') esmfmk = None -mked = False -esmfmkfile_local = os.path.join(os.getcwd(),"src/ESMF/interface/esmfmkfile.py") try: - - if os.path.isfile(esmfmkfile_local): - from ESMF.interface.esmfmkfile import ESMFMKFILE as esmfmk - mked = True + esmfmk = os.environ["ESMFMKFILE"] except: - raise ImportError('The esmf.mk file could not be loaded.') -else: - if not mked: - esmfmk = os.getenv("ESMFMKFILE") - if not esmfmk: - raise ImportError('The ESMFMKFILE was not set in the build, nor is it available as an environment variable.') - else: - with open(esmfmkfile_local, 'w') as emfl: - emfl.write('ESMFMKFILE = "'+esmfmk+'"') - emfl.close() - + raise ImportError('The ESMFMKFILE environment variable is not available.') #### INVESTIGATE esmf.mk ###################################################### From f82e1ddf432e414eaa34794448a2bec50856da3d Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 24 Aug 2022 12:27:03 -0700 Subject: [PATCH 130/266] remove --user from ESMPy pip install target --- src/addon/ESMPy/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index d0018c2723..2fd15cb6ee 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -14,7 +14,7 @@ clean: rm -rf examples/data install: - python3 -m pip install --user . + python3 -m pip install . test_unit: python3 -m pytest -m="not parallel" From 8e1b807dfae9b60773f634d96cce6f217f32cbfc Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 24 Aug 2022 12:29:33 -0700 Subject: [PATCH 131/266] add || : to allow clean target of ESMPy to continue if files labeled for removal do not exist --- src/addon/ESMPy/Makefile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 2fd15cb6ee..08b852bbfb 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -1,17 +1,17 @@ .PHONY: clean install test test_int test_all uninstall clean: - rm -rf build - rm -rf dist - find . -name "*.egg-info" -exec rm -rf {} \; - find . -name "*.pyc" -exec rm -f {} \; - find . -name "*ESMF_LogFile*" -exec rm -f {} \; - find . -name "*.log" -exec rm -f {} \; - find . -name "*.vtk" -exec rm -f {} \; - find . -name "*.pytest_cache" -exec rm -rf {} \; - find . -name "*.python-version" -exec rm -f {} \; - rm -rf src/ESMF/test/regrid_from_file/data - rm -rf examples/data + rm -rf build || : + rm -rf dist || : + find . -name "*.egg-info" -exec rm -rf {} \; || : + find . -name "*.pyc" -exec rm -f {} \; || : + find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : + find . -name "*.log" -exec rm -f {} \; || : + find . -name "*.vtk" -exec rm -f {} \; || : + find . -name "*.pytest_cache" -exec rm -rf {} \; || : + find . -name "*.python-version" -exec rm -f {} \; || : + rm -rf src/ESMF/test/regrid_from_file/data || : + rm -rf examples/data || : install: python3 -m pip install . From 0c49e34a6ee6252a3e50ed4acea57b466f857053 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 24 Aug 2022 12:51:47 -0600 Subject: [PATCH 132/266] Document file name convention for multi-tile I/O --- .../Array/interface/ESMF_Array.F90 | 7 ++++++- .../Array/interface/ESMF_ArrayHa.F90 | 7 ++++++- .../interface/ESMF_ArrayBundle.F90 | 18 +++++++++++++++-- src/Infrastructure/Field/src/ESMF_FieldPr.F90 | 7 ++++++- src/Infrastructure/Field/src/ESMF_FieldWr.F90 | 7 ++++++- .../FieldBundle/src/ESMF_FieldBundle.cppF90 | 20 ++++++++++++++++--- 6 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/Infrastructure/Array/interface/ESMF_Array.F90 b/src/Infrastructure/Array/interface/ESMF_Array.F90 index 2cbd37e9ff..0cc45b75ec 100644 --- a/src/Infrastructure/Array/interface/ESMF_Array.F90 +++ b/src/Infrastructure/Array/interface/ESMF_Array.F90 @@ -3858,7 +3858,6 @@ subroutine ESMF_ArrayWrite(array, fileName, keywordEnforcer, & ! ! Limitations: ! \begin{itemize} -! \item Only single tile Arrays are supported. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -3868,6 +3867,12 @@ subroutine ESMF_ArrayWrite(array, fileName, keywordEnforcer, & ! The {\tt ESMF\_Array} object that contains data to be written. ! \item[fileName] ! The name of the output file to which Array data is written. +! If this is a multi-tile Array, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being written to a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be written to +! "myfile1.nc", tile 2 to "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] ! Variable name in the output file; default is the "name" of Array. ! Use this argument only in the I/O format (such as NetCDF) that diff --git a/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 b/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 index 6d0870f466..ea0a577a63 100644 --- a/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 +++ b/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 @@ -644,7 +644,6 @@ subroutine ESMF_ArrayRead(array, fileName, keywordEnforcer, variableName, & ! ! Limitations: ! \begin{itemize} -! \item Only single tile Arrays are supported. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -654,6 +653,12 @@ subroutine ESMF_ArrayRead(array, fileName, keywordEnforcer, variableName, & ! The {\tt ESMF\_Array} object in which the read data is returned. ! \item[fileName] ! The name of the file from which Array data is read. +! If this is a multi-tile Array, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being read from a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be read from +! "myfile1.nc", tile 2 from "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] ! Variable name in the file; default is the "name" of Array. ! Use this argument only in the I/O format (such as NetCDF) that diff --git a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 index 1504b56cf0..00caa8f7c9 100644 --- a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 +++ b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 @@ -1675,7 +1675,8 @@ subroutine ESMF_ArrayBundleRead(arraybundle, fileName, keywordEnforcer, & ! ! Limitations: ! \begin{itemize} -! \item Only single tile Arrays are supported. +! \item For multi-tile Arrays, all Arrays in the ArrayBundle must contain +! the same number of tiles. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -1685,6 +1686,12 @@ subroutine ESMF_ArrayBundleRead(arraybundle, fileName, keywordEnforcer, & ! An {\tt ESMF\_ArrayBundle} object. ! \item[fileName] ! The name of the file from which ArrayBundle data is read. +! If the ArrayBundle contains multi-tile Arrays, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being read from a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be read from +! "myfile1.nc", tile 2 from "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[singleFile]}] ! A logical flag, the default is .true., i.e., all Arrays in the bundle ! are stored in one single file. If .false., each Array is stored @@ -3823,7 +3830,8 @@ subroutine ESMF_ArrayBundleWrite(arraybundle, fileName, keywordEnforcer, & ! ! Limitations: ! \begin{itemize} -! \item Only single tile Arrays are supported. +! \item For multi-tile Arrays,all Arrays in the ArrayBundle must contain +! the same number of tiles. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -3833,6 +3841,12 @@ subroutine ESMF_ArrayBundleWrite(arraybundle, fileName, keywordEnforcer, & ! An {\tt ESMF\_ArrayBundle} object. ! \item[fileName] ! The name of the output file to which array bundle data is written. +! If the ArrayBundle contains multi-tile Arrays, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being written to a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be written to +! "myfile1.nc", tile 2 to "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[convention]}] ! Specifies an Attribute package associated with the ArrayBundle, and the ! contained Arrays, used to create NetCDF dimension labels and attributes diff --git a/src/Infrastructure/Field/src/ESMF_FieldPr.F90 b/src/Infrastructure/Field/src/ESMF_FieldPr.F90 index 43cc4a9186..2ce72f514d 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldPr.F90 +++ b/src/Infrastructure/Field/src/ESMF_FieldPr.F90 @@ -241,7 +241,6 @@ subroutine ESMF_FieldRead(field, fileName, keywordEnforcer, & ! ! Limitations: ! \begin{itemize} -! \item Only single tile Fields are supported. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -251,6 +250,12 @@ subroutine ESMF_FieldRead(field, fileName, keywordEnforcer, & ! The {\tt ESMF\_Field} object in which the read data is returned. ! \item[fileName] ! The name of the file from which Field data is read. +! If the Field is a multi-tile Array, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being read from a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be read from +! "myfile1.nc", tile 2 from "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] ! Variable name in the file; default is the "name" of Field. ! Use this argument only in the I/O format (such as NetCDF) that diff --git a/src/Infrastructure/Field/src/ESMF_FieldWr.F90 b/src/Infrastructure/Field/src/ESMF_FieldWr.F90 index af926400a5..02eb82e7fe 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldWr.F90 +++ b/src/Infrastructure/Field/src/ESMF_FieldWr.F90 @@ -120,7 +120,6 @@ subroutine ESMF_FieldWrite(field, fileName, keywordEnforcer, & ! ! Limitations: ! \begin{itemize} -! \item Only single tile Fields are supported. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -130,6 +129,12 @@ subroutine ESMF_FieldWrite(field, fileName, keywordEnforcer, & ! The {\tt ESMF\_Field} object that contains data to be written. ! \item[fileName] ! The name of the output file to which Field data is written. +! If the Field is a multi-tile Array, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being written to a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be written to +! "myfile1.nc", tile 2 to "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] ! Variable name in the output file; default is the "name" of field. ! Use this argument only in the I/O format (such as NetCDF) that diff --git a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 index 0397edd558..907d057562 100644 --- a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 +++ b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 @@ -2769,7 +2769,8 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! ! Limitations: ! \begin{itemize} -! \item Only single tile Arrays within Fields are supported. +! \item For multi-tile Fields, all Fields in the FieldBundle must contain +! the same number of tiles. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -2778,7 +2779,13 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! \item[fieldbundle] ! An {\tt ESMF\_FieldBundle} object. ! \item[fileName] -! The name of the file from which fieldbundle data is read. +! The name of the file from which FieldBundle data is read. +! If the FieldBundle contains multi-tile Arrays, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being read from a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be read from +! "myfile1.nc", tile 2 from "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[singleFile]}] ! A logical flag, the default is .true., i.e., all Fields in the bundle ! are stored in one single file. If .false., each field is stored @@ -6248,7 +6255,8 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! ! Limitations: ! \begin{itemize} -! \item Only single tile Fields are supported. +! \item For multi-tile Fields, all Fields in the FieldBundle must contain +! the same number of tiles. ! \item Not supported in {\tt ESMF\_COMM=mpiuni} mode. ! \end{itemize} ! @@ -6258,6 +6266,12 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! An {\tt ESMF\_FieldBundle} object. ! \item[fileName] ! The name of the output file to which field bundle data is written. +! If the FieldBundle contains multi-tile Arrays, then fileName must contain +! exactly one instance of "#"; this is a placeholder that will be replaced +! by the tile number, with each tile being written to a separate file. (For +! example, for a fileName of "myfile#.nc", tile 1 will be written to +! "myfile1.nc", tile 2 to "myfile2.nc", etc.) +! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[convention]}] ! Specifies an Attribute package associated with the FieldBundle, and the ! contained Fields, used to create NetCDF dimension labels and attributes From 959029a2d976dfc423dbef17b2d5b4a946b935ab Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 24 Aug 2022 14:14:03 -0600 Subject: [PATCH 133/266] Fix documentation of requirement for ESMF_PIO setting --- src/Infrastructure/Array/interface/ESMF_Array.F90 | 2 +- src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 | 2 +- src/Infrastructure/Array/src/ESMCI_Array.C | 4 ++-- src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 | 4 ++-- src/Infrastructure/ArrayBundle/src/ESMCI_ArrayBundle.C | 4 ++-- src/Infrastructure/Field/include/ESMC_Field.h | 4 ++-- src/Infrastructure/Field/src/ESMF_FieldPr.F90 | 2 +- src/Infrastructure/Field/src/ESMF_FieldWr.F90 | 2 +- src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Infrastructure/Array/interface/ESMF_Array.F90 b/src/Infrastructure/Array/interface/ESMF_Array.F90 index 0cc45b75ec..67d212b2d8 100644 --- a/src/Infrastructure/Array/interface/ESMF_Array.F90 +++ b/src/Infrastructure/Array/interface/ESMF_Array.F90 @@ -3835,7 +3835,7 @@ subroutine ESMF_ArrayWrite(array, fileName, keywordEnforcer, & ! ! !DESCRIPTION: ! Write Array data into a file. For this API to be functional, the -! environment variable {\tt ESMF\_PIO} should be set to "internal" when +! environment variable {\tt ESMF\_PIO} should be set to either "internal" or "external" when ! the ESMF library is built. Please see the section on ! Data I/O,~\ref{io:dataio}. ! diff --git a/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 b/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 index ea0a577a63..c59f2c89db 100644 --- a/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 +++ b/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 @@ -639,7 +639,7 @@ subroutine ESMF_ArrayRead(array, fileName, keywordEnforcer, variableName, & ! !DESCRIPTION: ! Read Array data from file and put it into an {\tt ESMF\_Array} object. ! For this API to be functional, the environment variable {\tt ESMF\_PIO} -! should be set to "internal" when the ESMF library is built. +! should be set to either "internal" or "external" when the ESMF library is built. ! Please see the section on Data I/O,~\ref{io:dataio}. ! ! Limitations: diff --git a/src/Infrastructure/Array/src/ESMCI_Array.C b/src/Infrastructure/Array/src/ESMCI_Array.C index 593f4deb51..c281c7469b 100644 --- a/src/Infrastructure/Array/src/ESMCI_Array.C +++ b/src/Infrastructure/Array/src/ESMCI_Array.C @@ -3891,7 +3891,7 @@ int Array::read( // !DESCRIPTION: // Read Array data from file and put it into an ESMF_Array object. // For this API to be functional, the environment variable ESMF_PIO -// should be set to "internal" when the ESMF library is built. +// should be set to either "internal" or "external" when the ESMF library is built. // //EOPI //----------------------------------------------------------------------------- @@ -3969,7 +3969,7 @@ int Array::write( // // !DESCRIPTION: // Write Array data into a file. For this API to be functional, the -// environment variable {\tt ESMF\_PIO} should be set to "internal" when +// environment variable {\tt ESMF\_PIO} should be set to either "internal" or "external" when // the ESMF library is built. // //EOPI diff --git a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 index 00caa8f7c9..126586014f 100644 --- a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 +++ b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 @@ -1670,7 +1670,7 @@ subroutine ESMF_ArrayBundleRead(arraybundle, fileName, keywordEnforcer, & ! !DESCRIPTION: ! Read Array data to an ArrayBundle object from file(s). ! For this API to be functional, the environment variable {\tt ESMF\_PIO} -! should be set to "internal" when the ESMF library is built. +! should be set to either "internal" or "external" when the ESMF library is built. ! Please see the section on Data I/O,~\ref{io:dataio}. ! ! Limitations: @@ -3815,7 +3815,7 @@ subroutine ESMF_ArrayBundleWrite(arraybundle, fileName, keywordEnforcer, & ! ! !DESCRIPTION: ! Write the Arrays into a file. For this API to be functional, -! the environment variable {\tt ESMF\_PIO} should be set to "internal" +! the environment variable {\tt ESMF\_PIO} should be set to either "internal" or "external" ! when the ESMF library is built. Please see the section on ! Data I/O,~\ref{io:dataio}. ! diff --git a/src/Infrastructure/ArrayBundle/src/ESMCI_ArrayBundle.C b/src/Infrastructure/ArrayBundle/src/ESMCI_ArrayBundle.C index 6ed6af307e..a9cfa4dcdd 100644 --- a/src/Infrastructure/ArrayBundle/src/ESMCI_ArrayBundle.C +++ b/src/Infrastructure/ArrayBundle/src/ESMCI_ArrayBundle.C @@ -318,7 +318,7 @@ int ArrayBundle::read( // !DESCRIPTION: // Read Array data to an ArrayBundle object from file(s). // For this API to be functional, the environment variable {\tt ESMF\_PIO} -// should be set to "internal" when the ESMF library is built. +// should be set to either "internal" or "external" when the ESMF library is built. // //EOPI //----------------------------------------------------------------------------- @@ -426,7 +426,7 @@ int ArrayBundle::write( // // !DESCRIPTION: // Write the Arrays into a file. For this API to be functional, -// the environment variable {\tt ESMF\_PIO} should be set to "internal" +// the environment variable {\tt ESMF\_PIO} should be set to either "internal" or "external" // when the ESMF library is built. // //EOPI diff --git a/src/Infrastructure/Field/include/ESMC_Field.h b/src/Infrastructure/Field/include/ESMC_Field.h index 829c305252..2ecf9aa506 100644 --- a/src/Infrastructure/Field/include/ESMC_Field.h +++ b/src/Infrastructure/Field/include/ESMC_Field.h @@ -673,7 +673,7 @@ int ESMC_FieldPrint( // // Read Field data from a file and put it into an {ESMF\_Field} object. // For this API to be functional, the environment variable {\tt ESMF\_PIO} -// should be set to "internal" when the ESMF library is built. +// should be set to either "internal" or "external" when the ESMF library is built. // Please see the section on Data I/O,~\ref{io:dataio}. // // Limitations: @@ -1192,7 +1192,7 @@ int ESMC_FieldSMMStore( // // !DESCRIPTION: // Write Field data into a file. For this API to be functional, the -// environment variable {\tt ESMF\_PIO} should be set to "internal" when +// environment variable {\tt ESMF\_PIO} should be set to either "internal" or "external" when // the ESMF library is built. Please see the section on // Data I/O,~\ref{io:dataio}. // diff --git a/src/Infrastructure/Field/src/ESMF_FieldPr.F90 b/src/Infrastructure/Field/src/ESMF_FieldPr.F90 index 2ce72f514d..de4e369cac 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldPr.F90 +++ b/src/Infrastructure/Field/src/ESMF_FieldPr.F90 @@ -236,7 +236,7 @@ subroutine ESMF_FieldRead(field, fileName, keywordEnforcer, & ! !DESCRIPTION: ! Read Field data from a file and put it into an {ESMF\_Field} object. ! For this API to be functional, the environment variable {\tt ESMF\_PIO} -! should be set to "internal" when the ESMF library is built. +! should be set to either "internal" or "external" when the ESMF library is built. ! Please see the section on Data I/O,~\ref{io:dataio}. ! ! Limitations: diff --git a/src/Infrastructure/Field/src/ESMF_FieldWr.F90 b/src/Infrastructure/Field/src/ESMF_FieldWr.F90 index 02eb82e7fe..f74ea6d354 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldWr.F90 +++ b/src/Infrastructure/Field/src/ESMF_FieldWr.F90 @@ -97,7 +97,7 @@ subroutine ESMF_FieldWrite(field, fileName, keywordEnforcer, & ! ! !DESCRIPTION: ! Write Field data into a file. For this API to be functional, the -! environment variable {\tt ESMF\_PIO} should be set to "internal" when +! environment variable {\tt ESMF\_PIO} should be set to either "internal" or "external" when ! the ESMF library is built. Please see the section on ! Data I/O,~\ref{io:dataio}. ! diff --git a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 index 907d057562..4b300ea2ca 100644 --- a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 +++ b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 @@ -2764,7 +2764,7 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! !DESCRIPTION: ! Read field data to a FieldBundle object from file(s). ! For this API to be functional, the environment variable {\tt ESMF\_PIO} -! should be set to "internal" when the ESMF library is built. +! should be set to either "internal" or "external" when the ESMF library is built. ! Please see the section on Data I/O,~\ref{io:dataio}. ! ! Limitations: @@ -6240,7 +6240,7 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! ! !DESCRIPTION: ! Write the Fields into a file. For this API to be functional, -! the environment variable {\tt ESMF\_PIO} should be set to "internal" +! the environment variable {\tt ESMF\_PIO} should be set to either "internal" or "external" ! when the ESMF library is built. Please see the section on ! Data I/O,~\ref{io:dataio}. ! From a5b56ebbdba4ce8dfb177f5ea329a6bfcdd62505 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 25 Aug 2022 17:36:36 -0700 Subject: [PATCH 134/266] add proper versions to ESMPy from git tags, and other metadata from setup.cfg --- src/addon/ESMPy/pyproject.toml | 34 +++-------------- src/addon/ESMPy/setup.cfg | 14 ++----- src/addon/ESMPy/src/ESMF/__init__.py | 56 +++++++++++++++++++++------- 3 files changed, 51 insertions(+), 53 deletions(-) diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml index 044b8d7bc3..3879856669 100644 --- a/src/addon/ESMPy/pyproject.toml +++ b/src/addon/ESMPy/pyproject.toml @@ -1,28 +1,12 @@ [build-system] -requires = ["setuptools"] +requires = [ "setuptools>=41", "wheel", "setuptools-git-versioning", ] build-backend = "setuptools.build_meta" -# [project] -# name = "ESMPy" -# description = "ESMF Python interface" -# license = {text = "University of Illinois-NCSA"} -# readme = "README.md" -# # dynamic = ["version"] -# dependencies = [ -# "numpy", -# ] -# -# [tool.setuptools.packages.find] -# where = ["src"] -# exclude = [ -# "ESMPy.doc*", -# "ESMPy.example*", -# "ESMPy.test*", -# ] -# -# [tool.setuptools.dynamic] -# version = {attr = "ESMPy.VERSION"} -# +[tool.setuptools-git-versioning] +enabled = true +template = "{tag}" +dev_template = "{tag}" +dirty_template = "{tag}" [tool.pytest.ini_options] markers = [ @@ -30,9 +14,3 @@ markers = [ "parallel: marks a test which requires mpi (deselect with '-m \"not parallel\"')", "serial: marks a test which should be run on one core (deselect with '-m \"not serial\"')" ] -filterwarnings = [ - # "ignore:DeprecationWarning", - # note the use of single quote below to denote "raw" strings in TOML - # 'ignore:DeprecationWarning: Call to deprecated function ESMP_FieldRegridStoreFile', - # 'ignore:DeprecationWarning: Call to deprecated function ESMP_FieldSMMStore', -] diff --git a/src/addon/ESMPy/setup.cfg b/src/addon/ESMPy/setup.cfg index 1bbcf9f332..6a9d5feea2 100644 --- a/src/addon/ESMPy/setup.cfg +++ b/src/addon/ESMPy/setup.cfg @@ -1,19 +1,11 @@ [metadata] name = ESMPy -version = 8.4.0beta description = ESMF Python interface long_description = file: README.md, LICENSE license = University of Illinois-NCSA -author = 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 -author_email = "esmf_support@ucar.edu", -url="http://earthsystemmodeling.org/esmpy/", +author = 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 +maintainer_email = esmf_support@ucar.edu +url = http://earthsystemmodeling.org/esmpy/ [options] diff --git a/src/addon/ESMPy/src/ESMF/__init__.py b/src/addon/ESMPy/src/ESMF/__init__.py index a82ce63453..0f93b78555 100644 --- a/src/addon/ESMPy/src/ESMF/__init__.py +++ b/src/addon/ESMPy/src/ESMF/__init__.py @@ -74,20 +74,48 @@ from ESMF.api.regrid import * from ESMF.api.constants import * from ESMF.util.helpers import * -from ESMF.api.constants import _ESMF_VERSION #### SET UP SOME INFO ######################################################### -__name__ = "ESMF" -__description__ = "ESMF Python interface" -__author__ = "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" -__license__ = "University of Illinois-NCSA" -__release__ = _ESMF_VERSION -__version__ = _ESMF_VERSION +# pre Python 3.8, not sure how far yet +from pkg_resources import get_distribution +pkgInfo = get_distribution('ESMPy').get_metadata('METADATA') + +# parse it using email.Parser +from email import message_from_string +msg = message_from_string(pkgInfo) + +__name__ = msg["Name"] +__version__ = msg["Version"] +__author__ = msg["Author"] +__description__ = msg["Summary"] +__homepage__ = msg["Home-page"] +__email__ = msg["Maintainer-email"] +__license__ = msg["License"] + +# # this requires Python 3.8 or higher +# import importlib.metadata as ilm +# +# md = ilm.metadata("ESMPy") +# +# __name__ = md["Name"] +# __version__ = md["Version"] +# __author__ = md["Author"] +# __description__ = md["Description"] +# __summary__ = md["Summary"] +# __homepage__ = md["Home-page"] + +# # this is the old hardcoded version + +# __name__ = "ESMF" +# __version__ = "" +# __description__ = "ESMF Python interface" +# __author__ = "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" +# __license__ = "University of Illinois-NCSA" From 6b25561eaac96b1739385012fb57bc768a6547b8 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 25 Aug 2022 17:37:21 -0700 Subject: [PATCH 135/266] remove setup.py --- src/addon/ESMPy/setup.py.old | 278 ----------------------------------- 1 file changed, 278 deletions(-) delete mode 100644 src/addon/ESMPy/setup.py.old diff --git a/src/addon/ESMPy/setup.py.old b/src/addon/ESMPy/setup.py.old deleted file mode 100644 index d4f53c3191..0000000000 --- a/src/addon/ESMPy/setup.py.old +++ /dev/null @@ -1,278 +0,0 @@ -# $Id$ - -import os -import sys -from distutils.core import setup, Command -from distutils.util import get_platform -import subprocess - - -def download_test_data(func): - def wrapper(self): - update_system_path() - from ESMF.util.cache_data import cache_data_files - cache_data_files() - return func(self) - return wrapper - - -def update_system_path(): - if 'src' not in sys.path: - sys.path.insert(0, 'src') - - -class AbstractESMFCommand(Command): - user_options = [] - - def initialize_options(self): - self.cwd = None - - def finalize_options(self): - self.cwd = os.getcwd() - - def _validate_(self): - if os.getcwd() != self.cwd: - raise RuntimeError('Must be in package root: %s' % self.cwd) - - -class AbstractESMFNoseCommand(AbstractESMFCommand): - _nose_attrs = None - _nose_base_attrs = ['!slow'] - _nose_parallel = False - _nose_flags = None - _default_target = os.path.join('src', 'ESMF') - _needs_data = False - - def run(self): - self._validate_() - cmd = self.nosetests_command() - subprocess.check_call(cmd) - - @classmethod - def nosetests_command(cls): - ret = ['nosetests', '-vs', '--with-xunit'] - if not isinstance(cls._nose_attrs, type(None)): - nose_attrs = cls._nose_base_attrs + cls._nose_attrs - nose_attrs = ','.join(nose_attrs) - cmd_nose_attrs = ['-a', nose_attrs] - ret = ret + cmd_nose_attrs - - if cls._nose_parallel: - # Needed for ESMF constants import - sys.path.append('src') - - from ESMF.api import constants - - # -np is used in place of -n for esmf mpirun.srun wrapper - mpisyntax = "-n"; - if "mpirun.srun" in constants._ESMF_MPIRUN: - mpisyntax = "-np"; - mpirun_prefix = [constants._ESMF_MPIRUN, mpisyntax, str(constants._ESMF_MPIRUN_NP)] - ret = mpirun_prefix + ret - - if not isinstance(cls._nose_flags, type(None)): - ret.append(cls._nose_flags) - ret.append(cls._default_target) - return ret - - -class BuildCommand(AbstractESMFCommand): - description = "build: will build the ESMF package" - user_options = [('ESMFMKFILE=', 'e', - "Location of esmf.mk for the ESMF installation")] - - def initialize_options(self): - self.cwd = None - self.ESMFMKFILE = None - SITEDIR = os.system('%s -m site --user-site' % sys.executable) - self.build_base = 'build' - self.build_lib = None - self.plat_name = None - - def finalize_options(self): - self.cwd = os.getcwd() - if isinstance(self.ESMFMKFILE, type(None)): - self.ESMFMKFILE = os.getenv('ESMFMKFILE') - if isinstance(self.build_lib, type(None)): - self.build_lib = os.path.join(self.build_base, 'lib') - if isinstance(self.plat_name, type(None)): - self.plat_name = get_platform() - - def run(self): - assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd - - # Create "esmfmkfile.py" file holding the path to the ESMF "esmf.mk" file - if not isinstance(self.ESMFMKFILE, type(None)): - f = open(os.path.join('src', 'ESMF', 'interface', 'esmfmkfile.py'), 'w') - f.write('ESMFMKFILE = "%s"' % self.ESMFMKFILE) - f.close() - - # Attempt to load ESMF. - update_system_path() - import ESMF.interface.loadESMF - - -class CleanCommand(AbstractESMFCommand): - description = "clean: will remove all libraries, log and output files" - - def run(self): - assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd - os.system('find . -name "*.pyc" -exec rm -f {} \;') - os.system('find . -name "*ESMF_LogFile*" -exec rm -f {} \;') - os.system('find . -name "*.log" -exec rm -f {} \;') - os.system('find . -name "*.vtk" -exec rm -f {} \;') - os.system('rm src/ESMF/interface/esmfmkfile.py') - os.system('rm -rf build') - os.system('rm -rf dist') - os.system('rm -rf src/ESMF/test/regrid_from_file/data') - os.system('rm -rf examples/data') - - -class DustCommand(AbstractESMFCommand): - description = "dust: will remove log and output files" - - def run(self): - assert os.getcwd() == self.cwd, 'Must be in package root: %s' % self.cwd - os.system('find . -name "*ESMF_LogFile*" -exec rm -f {} \;') - os.system('find . -name "*.log" -exec rm -f {} \;') - os.system('find . -name "*.vtk" -exec rm -f {} \;') - os.system('find . -name "*.pyc" -exec rm -f {} \;') - - -class TestCommand(AbstractESMFNoseCommand): - description = "run serial tests" - _nose_attrs = ['!parallel'] - - -class TestParallelCommand(AbstractESMFNoseCommand): - description = "run parallel tests" - _nose_attrs = ['!serial'] - _nose_parallel = True - - -class TestRegridCommand(AbstractESMFNoseCommand): - description = "run test_regrid.py" - _default_target = os.path.join('src', 'ESMF', 'test', 'test_api', 'test_regrid.py') - - -class TestRegridParallelCommand(TestRegridCommand): - description = "test regrid parallel" - _nose_attrs = ['!serial'] - _nose_parallel = True - -class TestExamplesCommand(AbstractESMFNoseCommand): - description = "run examples in serial" - _nose_attrs = ['!parallel'] - _default_target = os.path.join('examples', 'exampletest.py') - - @download_test_data - def run(self): - update_system_path() - AbstractESMFNoseCommand.run(self) - -class TestExamplesParallelCommand(TestExamplesCommand): - description = "run examples in parallel" - _nose_attrs = ['!serial'] - _nose_parallel = True - -class TestExamplesDryrunCommand(TestExamplesCommand): - description = "collect example tests only and download data" - _nose_flags = '--collect-only' - - -class TestRegridFromFileCommand(AbstractESMFCommand): - description = "test regrid from file" - _filename = 'run_regrid_from_file.py' - _flags = None - - def run(self): - original_pp = os.environ.get('PYTHONPATH', '') - path = os.path.join(os.getcwd(), 'src') - os.environ['PYTHONPATH'] = '{0}:{1}'.format(path, original_pp) - self._validate_() - target = os.path.join('src', 'ESMF', 'test', 'regrid_from_file', self._filename) - cmd = [sys.executable, target] - if not isinstance(self._flags, type(None)): - cmd.append(self._flags) - subprocess.check_call(cmd) - - -class TestRegridFromFileDryrunCommand(TestRegridFromFileCommand): - description = "test regrid from file dryrun" - _filename = 'run_regrid_from_file_dryrun.py' - - -class TestRegridFromFileParallelCommand(TestRegridFromFileCommand): - description = "test regrid from file parallel" - _filename = 'run_regrid_from_file.py' - _flags = '--parallel' - - def run(self): - TestRegridFromFileCommand.run(self) - - -class TestAllCommand(AbstractESMFCommand): - description = "run serial, parallel, and example tests" - - @download_test_data - def run(self): - self._validate_() - to_run = [TestCommand, TestParallelCommand, TestExamplesCommand, TestExamplesParallelCommand] - for t in to_run: - cmd = t.nosetests_command() - subprocess.check_call(cmd) - - -# Get package structure -def _get_dot_(path, root='src'): - ret = [] - path_parse = path - while True: - path_parse, tail = os.path.split(path_parse) - if tail == root: - break - else: - ret.append(tail) - ret.reverse() - return '.'.join(ret) - - -src_path = os.path.join('src', 'ESMF') -packages = [] -for dirpath, dirnames, filenames in os.walk(src_path): - if '__init__.py' in filenames: - package = _get_dot_(dirpath) - packages.append(package) - -# TODO: build doc command -# TODO: remove duplicated metadata: here and src/ESMF/__init__.py -setup(name="ESMPy", - version="8.4.0", - description="ESMF Python interface", - author="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", - license="University of Illinois-NCSA", - author_email="esmf_support@ucar.edu", - url="http://earthsystemmodeling.org/esmpy/", - packages=packages, - package_dir={'': 'src'}, - cmdclass={'build': BuildCommand, - 'clean': CleanCommand, - 'dust': DustCommand, - 'test': TestCommand, - 'test_all': TestAllCommand, - 'test_parallel': TestParallelCommand, - 'test_examples': TestExamplesCommand, - 'test_examples_dryrun': TestExamplesDryrunCommand, - 'test_examples_parallel': TestExamplesParallelCommand, - 'test_regrid': TestRegridCommand, - 'test_regrid_from_file': TestRegridFromFileCommand, - 'test_regrid_from_file_dryrun': TestRegridFromFileDryrunCommand, - 'test_regrid_parallel': TestRegridParallelCommand, - 'test_regrid_from_file_parallel': TestRegridFromFileParallelCommand}) From 7ec2ce6bedca08f42137f48cb6f0c7d04c6bb78e Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 26 Aug 2022 11:14:39 -0600 Subject: [PATCH 136/266] Update documentation to replace references to Cupid with the esmf-profiler --- src/Infrastructure/Trace/doc/Trace_desc.tex | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Infrastructure/Trace/doc/Trace_desc.tex b/src/Infrastructure/Trace/doc/Trace_desc.tex index 30885f080e..e01d00528f 100644 --- a/src/Infrastructure/Trace/doc/Trace_desc.tex +++ b/src/Infrastructure/Trace/doc/Trace_desc.tex @@ -25,7 +25,7 @@ \subsubsection{Profiling} \item in text at the end of ESMF Log files \item in separate text file, one per PET (if the ESMF Logs are turned off) \item in a single summary text file that aggregates timings over multiple PETs -\item in a binary format for import into \htmladdnormallink{Cupid}{https://cupid.readthedocs.io/en/latest/} for detailed analysis +\item in a binary format for import into the \htmladdnormallink{esmf-profiler}{https://github.com/esmf-org/esmf-profiler} for profile visualization \end{itemize} The following table lists important environment variables that control @@ -68,9 +68,9 @@ \subsubsection{Tracing} analyzing ESMF applications and the second two are general purpose tools for working with all CTF traces. \begin{itemize} -\item \htmladdnormallink{Cupid}{https://cupid.readthedocs.io/en/latest/} - is a plugin for the Eclipse Integrated Development Environment - that can read and analyze ESMF traces. +\item \htmladdnormallink{esmf-profiler}{https://github.com/esmf-org/esmf-profiler} + is a tool that ingests traces from an ESMF application and generates + performance profile plots. \item \htmladdnormallink{TraceCompass}{http://tracecompass.org/} is a general purpose tool for reading, analyzing, and visualizing traces. \item \htmladdnormallink{Babeltrace}{http://www.efficios.com/babeltrace} @@ -86,7 +86,6 @@ \subsubsection{Tracing} \item [phase\_exit] indicates exit from an initialize, run, or finalize ESMF component routine \item [region\_enter] indicates entry into a user-defined code region \item [region\_exit] indicates exit from a user-defined code region -\item [mem] records current memory usage information \end{description} The following table lists important environment variables that control From 4cb82f5829464fbba828dff617b3956fc54e1bfe Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 26 Aug 2022 11:33:20 -0600 Subject: [PATCH 137/266] use importlib from Python 3.8 onward, pkg_resources before --- src/addon/ESMPy/src/ESMF/__init__.py | 54 +++++++++++++++------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/addon/ESMPy/src/ESMF/__init__.py b/src/addon/ESMPy/src/ESMF/__init__.py index 0f93b78555..0378e67de3 100644 --- a/src/addon/ESMPy/src/ESMF/__init__.py +++ b/src/addon/ESMPy/src/ESMF/__init__.py @@ -77,33 +77,37 @@ #### SET UP SOME INFO ######################################################### -# pre Python 3.8, not sure how far yet -from pkg_resources import get_distribution -pkgInfo = get_distribution('ESMPy').get_metadata('METADATA') +import sys -# parse it using email.Parser -from email import message_from_string -msg = message_from_string(pkgInfo) +if (sys.version_info >= (3,8)): + # this requires Python 3.8 or higher + import importlib.metadata as ilm + + md = ilm.metadata("ESMPy") + + __name__ = md["Name"] + __version__ = md["Version"] + __author__ = md["Author"] + __description__ = md["Description"] + __summary__ = md["Summary"] + __homepage__ = md["Home-page"] -__name__ = msg["Name"] -__version__ = msg["Version"] -__author__ = msg["Author"] -__description__ = msg["Summary"] -__homepage__ = msg["Home-page"] -__email__ = msg["Maintainer-email"] -__license__ = msg["License"] - -# # this requires Python 3.8 or higher -# import importlib.metadata as ilm -# -# md = ilm.metadata("ESMPy") -# -# __name__ = md["Name"] -# __version__ = md["Version"] -# __author__ = md["Author"] -# __description__ = md["Description"] -# __summary__ = md["Summary"] -# __homepage__ = md["Home-page"] +else: + # pre Python 3.8, not sure how far yet + from pkg_resources import get_distribution + pkgInfo = get_distribution('ESMPy').get_metadata('METADATA') + + # parse it using email.Parser + from email import message_from_string + msg = message_from_string(pkgInfo) + + __name__ = msg["Name"] + __version__ = msg["Version"] + __author__ = msg["Author"] + __description__ = msg["Summary"] + __homepage__ = msg["Home-page"] + __email__ = msg["Maintainer-email"] + __license__ = msg["License"] # # this is the old hardcoded version From 3180d4b239471d3fafde04f3705bb136f6489014 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 26 Aug 2022 15:25:16 -0600 Subject: [PATCH 138/266] Add unit tests of multi-tile write --- .../IO/tests/ESMF_IO_MultitileUTest.F90 | 237 ++++++++++++++++++ src/Infrastructure/IO/tests/makefile | 10 +- 2 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 diff --git a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 new file mode 100644 index 0000000000..ff8bab2d47 --- /dev/null +++ b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 @@ -0,0 +1,237 @@ +! $Id$ +! +! Earth System Modeling Framework +! Copyright 2002-2022, 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_MultitileUTest + +!------------------------------------------------------------------------------ + +#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_Grid) :: grid6tile + ! The following fields make up the field bundle: + type(ESMF_Field) :: field1, field2, field1Copy + type(ESMF_FieldBundle) :: fieldBundle + ! This field is not in the field bundle: + type(ESMF_Field) :: field3 + ! This is used for error testing: + type(ESMF_Grid) :: gridSingleTile + type(ESMF_Field) :: fieldSingleTile + type(ESMF_FieldBundle) :: fieldBundleMixedTileCounts + + character(len=*), parameter :: fileName = "ESMF_IO_MultitileUTest#.nc" + character(len=*), parameter :: fileNameFail = "ESMF_IO_MultitileUTestFail#.nc" + + !------------------------------------------------------------------------ + call ESMF_TestStart(ESMF_SRCLINE, rc=rc) ! calls ESMF_Initialize() internally + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(name, *) "Create fields for multitile IO tests" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call createFields(rc) + call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(name, *) "Write a FieldBundle with multi-tile fields" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldBundleWrite(fieldBundle, fileName=fileName, overwrite=.true., rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 + !------------------------------------------------------------------------ + + ! FIXME(wjs, 2022-08-26) Add tests of FieldBundleRead and FieldRead; in + ! addition to checking rc, also check equality to the original fields + +#ifdef ESMF_TESTEXHAUSTIVE + ! The following tests don't add much code coverage, so are only done when + ! ESMF_TESTEXHAUSTIVE is set + + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + write(name, *) "Write a multi-tile Field to existing files" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldWrite(field3, fileName=fileName, overwrite=.true., rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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, *) "Create single-tile field for failure testing" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call createSingleTileField(rc) + call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + write(name, *) "Failure test: try to write fields with different tile counts" + write(failMsg, *) "Did not return ESMF_RC_VAL_WRONG" + call ESMF_FieldBundleWrite(fieldBundleMixedTileCounts, fileName=fileNameFail, overwrite=.true., rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + call ESMF_Test((rc == ESMF_RC_VAL_WRONG), 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 + !------------------------------------------------------------------------ + + ! FIXME(wjs, 2022-08-26) Add tests of ArrayBundleWrite and ArrayWrite + + ! FIXME(wjs, 2022-08-26) Add tests of ArrayBundleRead and ArrayRead; in + ! addition to checking rc, also check equality to the original fields + +#endif ! ESMF_TESTEXHAUSTIVE + + !------------------------------------------------------------------------ + call ESMF_TestEnd(ESMF_SRCLINE) ! calls ESMF_Finalize() internally + !------------------------------------------------------------------------ + +contains + + subroutine createFields(rc) + ! Creates Fields and FieldBundles used by the tests in this module + integer, intent(out) :: rc + + integer :: decompPTile(2,6) + type(ESMF_ArraySpec) :: arraySpec + type(ESMF_Array) :: array1 + + !------------------------------------------------------------------------ + ! Set up 6-tile grid + !------------------------------------------------------------------------ + + ! Decomposition for 8 PEs: Tiles 1 and 3 each have two DEs (along different + ! dimensions); the other tiles each have one DE. + decompPTile(1,:) = [2,1,1,1,1,1] + decompPTile(2,:) = [1,1,2,1,1,1] + grid6tile = ESMF_GridCreateCubedSphere( & + tilesize = 4, & + regDecompPTile = decompPTile, & + staggerLocList = [ESMF_STAGGERLOC_CENTER], & + rc = rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + ! Create fields on the 6-tile grid and associated field bundle + !------------------------------------------------------------------------ + + call ESMF_ArraySpecSet(arraySpec, typekind=ESMF_TYPEKIND_R8, rank=2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + field1 = ESMF_FieldCreate(grid6tile, arraySpec, name="field1", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldFill(field1, dataFillScheme='sincos', member=1, rc=rc) + if (rc /= ESMF_SUCCESS) return + + field2 = ESMF_FieldCreate(grid6tile, arraySpec, name="field2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldFill(field2, dataFillScheme='sincos', member=2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + field3 = ESMF_FieldCreate(grid6tile, arraySpec, name="field3", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldFill(field3, dataFillScheme='sincos', member=3, rc=rc) + if (rc /= ESMF_SUCCESS) return + + ! Create a copy of field1 that uses the same array, so we can test writing + ! the same array twice from a single call. + call ESMF_FieldGet(field1, array=array1, rc=rc) + if (rc /= ESMF_SUCCESS) return + field1Copy = ESMF_FieldCreate(grid6tile, array1, name="field1Copy", rc=rc) + if (rc /= ESMF_SUCCESS) return + + fieldBundle = ESMF_FieldBundleCreate(name="fb", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldBundleAdd(fieldBundle, [field1, field2, field1Copy], rc=rc) + if (rc /= ESMF_SUCCESS) return + + end subroutine createFields + + subroutine createSingleTileField(rc) + ! Creates a single-tile field and associated field bundle for failure testing + integer, intent(out) :: rc + + type(ESMF_ArraySpec) :: arraySpec + + !------------------------------------------------------------------------ + ! Set up a single-tile grid + !------------------------------------------------------------------------ + + gridSingleTile = ESMF_GridCreateNoPeriDimUfrm( & + maxIndex = [4,4], & + minCornerCoord = [0._ESMF_KIND_R8, 0._ESMF_KIND_R8], & + maxCornerCoord = [4._ESMF_KIND_R8, 4._ESMF_KIND_R8], & + staggerLocList = [ESMF_STAGGERLOC_CENTER], & + rc = rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + ! Create a field on the single-tile grid and associated field bundle + !------------------------------------------------------------------------ + + call ESMF_ArraySpecSet(arraySpec, typekind=ESMF_TYPEKIND_R8, rank=2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + fieldSingleTile = ESMF_FieldCreate(gridSingleTile, arraySpec, name="fieldSingleTile", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldFill(fieldSingleTile, dataFillScheme='sincos', rc=rc) + if (rc /= ESMF_SUCCESS) return + + fieldBundleMixedTileCounts = ESMF_FieldBundleCreate(name="fbmixed", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldBundleAdd(fieldBundleMixedTileCounts, [field1, fieldSingleTile], rc=rc) + if (rc /= ESMF_SUCCESS) return + + end subroutine createSingleTileField + +end program ESMF_IO_MultitileUTest diff --git a/src/Infrastructure/IO/tests/makefile b/src/Infrastructure/IO/tests/makefile index da1f56b883..dd78d93ca8 100644 --- a/src/Infrastructure/IO/tests/makefile +++ b/src/Infrastructure/IO/tests/makefile @@ -12,13 +12,15 @@ TESTS_BUILD = $(ESMF_TESTDIR)/ESMCI_IO_NetCDFUTest \ $(ESMF_TESTDIR)/ESMCI_IO_PIOUTest \ $(ESMF_TESTDIR)/ESMC_IO_InqUTest \ $(ESMF_TESTDIR)/ESMF_IO_YAMLUTest \ - $(ESMF_TESTDIR)/ESMF_IOUTest + $(ESMF_TESTDIR)/ESMF_IOUTest \ + $(ESMF_TESTDIR)/ESMF_IO_MultitileUTest TESTS_RUN = RUN_ESMCI_IO_NetCDFUTest \ RUN_ESMCI_IO_PIOUTest \ RUN_ESMC_IO_InqUTest \ RUN_ESMF_IO_YAMLUTest \ - RUN_ESMF_IOUTest + RUN_ESMF_IOUTest \ + RUN_ESMF_IO_MultitileUTest TESTS_RUN_UNI = RUN_ESMCI_IO_NetCDFUTestUNI \ RUN_ESMCI_IO_PIOUTestUNI \ @@ -75,3 +77,7 @@ RUN_ESMF_IO_YAMLUTest: RUN_ESMF_IO_YAMLUTestUNI: cp -f fd.yaml $(ESMF_TESTDIR) $(MAKE) TNAME=IO_YAML NP=1 ftest + +RUN_ESMF_IO_MultitileUTest: + rm -f $(ESMF_TESTDIR)/ESMF_IO_MultitileUTest*.nc + $(MAKE) TNAME=IO_Multitile NP=8 ftest From eabd4ad7f7c18376bf1cd80ead131e4c96f3800e Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 26 Aug 2022 17:04:54 -0700 Subject: [PATCH 139/266] Merge two explicit type casts that Jim Edwards suggested under PR #33 to build with CCE. --- src/Infrastructure/Mesh/src/Legacy/ESMCI_MeshPNC.C | 2 +- src/Infrastructure/Mesh/src/Legacy/ESMCI_WriteWeightsPar.C | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/Mesh/src/Legacy/ESMCI_MeshPNC.C b/src/Infrastructure/Mesh/src/Legacy/ESMCI_MeshPNC.C index fea1d7f7e5..b097ee26be 100644 --- a/src/Infrastructure/Mesh/src/Legacy/ESMCI_MeshPNC.C +++ b/src/Infrastructure/Mesh/src/Legacy/ESMCI_MeshPNC.C @@ -122,7 +122,7 @@ void LoadNCDualMeshPar(Mesh &mesh, const std::string fname) { local_grid_start = my_start*grid_dims[0]; } - int local_grid_dims[2] = {grid_dims[0], my_num > 0 ? my_num+1 : 0}; + int local_grid_dims[2] = {grid_dims[0], (int) my_num > 0 ? (int) my_num+1 : 0}; Par::Out() << "min_row=" << min_row << ", max_row=" << max_row << std::endl; Par::Out() << "local_grid_start=" << local_grid_start << ", local_grid_size:" << local_grid_size << std::endl; diff --git a/src/Infrastructure/Mesh/src/Legacy/ESMCI_WriteWeightsPar.C b/src/Infrastructure/Mesh/src/Legacy/ESMCI_WriteWeightsPar.C index a3f4cfa30b..a8d0653128 100644 --- a/src/Infrastructure/Mesh/src/Legacy/ESMCI_WriteWeightsPar.C +++ b/src/Infrastructure/Mesh/src/Legacy/ESMCI_WriteWeightsPar.C @@ -229,7 +229,7 @@ static void get_nc_grid_file1(nc_grid_file1 &ncf, const std::string &ncfile, boo ncf.local_grid_size = local_grid_size; ncf.local_grid_start = local_grid_start; - int local_grid_dims[2] = {grid_dims[0], my_num > 0 ? my_num+1 : 0}; + int local_grid_dims[2] = {grid_dims[0], (int) my_num > 0 ? (int) my_num+1 : 0}; Par::Out() << "min_row=" << min_row << ", max_row=" << max_row << std::endl; Par::Out() << "local_grid_start=" << local_grid_start << ", local_grid_size:" << local_grid_size << std::endl; From 692b6daf271ae28d9f036ca1f397d742e78cb698 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Mon, 29 Aug 2022 14:48:10 -0700 Subject: [PATCH 140/266] enable pyproject.toml and remove setup.cfg, add starting_version to git-versioning --- src/addon/ESMPy/{setup.cfg => old.setup.cfg} | 5 ++- src/addon/ESMPy/pyproject.toml | 22 +++++++++++ src/addon/ESMPy/src/ESMF/__init__.py | 40 +++++++++++--------- 3 files changed, 48 insertions(+), 19 deletions(-) rename src/addon/ESMPy/{setup.cfg => old.setup.cfg} (91%) diff --git a/src/addon/ESMPy/setup.cfg b/src/addon/ESMPy/old.setup.cfg similarity index 91% rename from src/addon/ESMPy/setup.cfg rename to src/addon/ESMPy/old.setup.cfg index 6a9d5feea2..48cdbf3ff0 100644 --- a/src/addon/ESMPy/setup.cfg +++ b/src/addon/ESMPy/old.setup.cfg @@ -1,12 +1,13 @@ [metadata] name = ESMPy description = ESMF Python interface -long_description = file: README.md, LICENSE license = University of Illinois-NCSA author = 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 maintainer_email = esmf_support@ucar.edu url = http://earthsystemmodeling.org/esmpy/ - +obsoletes = ESMF +requires = numpy +python_requires = '>=3.7', [options] zip_safe = False diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml index 3879856669..00e35c5c30 100644 --- a/src/addon/ESMPy/pyproject.toml +++ b/src/addon/ESMPy/pyproject.toml @@ -2,11 +2,33 @@ requires = [ "setuptools>=41", "wheel", "setuptools-git-versioning", ] build-backend = "setuptools.build_meta" +[project] +name = "ESMPy" +description = "ESMF Python interface" +# readme = "README.md" +maintainers = [{author = "ESMF Core Team", email = "esmf_support@ucar.edu"}] +requires-python = ">=3.7" +license = {text = "University of Illinois-NCSA"} +dependencies = [ + "numpy", + 'importlib-metadata; python_version<"3.8"', +] +dynamic = ["version"] + [tool.setuptools-git-versioning] enabled = true template = "{tag}" dev_template = "{tag}" dirty_template = "{tag}" +starting_version = "8.4.0" # this is a backup for pip <= 22.0 where git-versioning doesn't work + +[tool.dynamic] +version = "placeholder" # this is a placeholder for the version pulled with git-versioning + + +[tool.setuptools.packages.find] +where = ["src"] +exclude = ["doc*", "examples*", "test*"] [tool.pytest.ini_options] markers = [ diff --git a/src/addon/ESMPy/src/ESMF/__init__.py b/src/addon/ESMPy/src/ESMF/__init__.py index 0378e67de3..a69935ab09 100644 --- a/src/addon/ESMPy/src/ESMF/__init__.py +++ b/src/addon/ESMPy/src/ESMF/__init__.py @@ -79,35 +79,41 @@ import sys +msg = "" + if (sys.version_info >= (3,8)): # this requires Python 3.8 or higher import importlib.metadata as ilm - md = ilm.metadata("ESMPy") - - __name__ = md["Name"] - __version__ = md["Version"] - __author__ = md["Author"] - __description__ = md["Description"] - __summary__ = md["Summary"] - __homepage__ = md["Home-page"] + msg = ilm.metadata("ESMPy") else: # pre Python 3.8, not sure how far yet from pkg_resources import get_distribution - pkgInfo = get_distribution('ESMPy').get_metadata('METADATA') + try: + pkgInfo = get_distribution('ESMPy').get_metadata('METADATA') + except: + try: + pkgInfo = get_distribution('ESMPy').get_metadata('PKG-INFO') + except: + raise ImportError("Could not find METADATA or PKG-INFO for ESMPy") # parse it using email.Parser from email import message_from_string msg = message_from_string(pkgInfo) - - __name__ = msg["Name"] - __version__ = msg["Version"] - __author__ = msg["Author"] - __description__ = msg["Summary"] - __homepage__ = msg["Home-page"] - __email__ = msg["Maintainer-email"] - __license__ = msg["License"] + +# set the private metadata +__name__ = msg["Name"] +__version__ = msg["Version"] +__license__ = msg["License"] +__email__ = msg["Maintainer-email"] +__description__ = msg["Summary"] +__requires__ = msg["Requires-Dist"] +__requires_python__ = msg["Requires-Python"] +# these don't seem to work with setuptools pyproject.toml +__author__ = msg["Author"] +__homepage__ = msg["Home-page"] +__obsoletes__ = msg["obsoletes"] # # this is the old hardcoded version From 277ef668804c7f16cc6d82d7ebf6551986c75644 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Tue, 30 Aug 2022 10:29:39 -0700 Subject: [PATCH 141/266] change module name ESMF to esmpy --- src/addon/ESMPy/.gitignore | 15 +- src/addon/ESMPy/Makefile | 10 +- src/addon/ESMPy/doc/CoordSys.rst | 2 +- src/addon/ESMPy/doc/ExtrapMethod.rst | 2 +- src/addon/ESMPy/doc/FileFormat.rst | 2 +- src/addon/ESMPy/doc/FileMode.rst | 2 +- src/addon/ESMPy/doc/GridItem.rst | 2 +- src/addon/ESMPy/doc/LineType.rst | 2 +- src/addon/ESMPy/doc/LogKind.rst | 2 +- src/addon/ESMPy/doc/MeshElemType.rst | 2 +- src/addon/ESMPy/doc/MeshLoc.rst | 2 +- src/addon/ESMPy/doc/NormType.rst | 2 +- src/addon/ESMPy/doc/PoleKind.rst | 2 +- src/addon/ESMPy/doc/PoleMethod.rst | 2 +- src/addon/ESMPy/doc/Region.rst | 2 +- src/addon/ESMPy/doc/RegridMethod.rst | 2 +- src/addon/ESMPy/doc/StaggerLoc.rst | 2 +- src/addon/ESMPy/doc/TypeKind.rst | 2 +- src/addon/ESMPy/doc/UnmappedAction.rst | 2 +- src/addon/ESMPy/doc/api.rst | 487 +++++++++--------- src/addon/ESMPy/doc/conf.py | 4 +- src/addon/ESMPy/doc/examples.rst | 32 +- src/addon/ESMPy/doc/field.rst | 2 +- src/addon/ESMPy/doc/grid.rst | 2 +- src/addon/ESMPy/doc/install.rst | 26 +- src/addon/ESMPy/doc/intro.rst | 3 +- src/addon/ESMPy/doc/locstream.rst | 2 +- src/addon/ESMPy/doc/manager.rst | 2 +- src/addon/ESMPy/doc/mesh.rst | 2 +- src/addon/ESMPy/doc/regrid.rst | 2 +- src/addon/ESMPy/doc/regridfromfile.rst | 2 +- .../examples/cubed_sphere_to_mesh_regrid.py | 48 +- src/addon/ESMPy/examples/exampletest.py | 6 +- src/addon/ESMPy/examples/exampletestdryrun.py | 4 +- src/addon/ESMPy/examples/field_read.py | 22 +- .../examples/grid_create_peridim_mask.py | 40 +- .../ESMPy/examples/grid_locstream_regrid.py | 42 +- src/addon/ESMPy/examples/hello_world.py | 6 +- .../ESMPy/examples/locstream_grid_regrid.py | 42 +- .../ESMPy/examples/mesh_locstream_regrid.py | 30 +- src/addon/ESMPy/examples/mpi_spawn_regrid.py | 36 +- .../notebooks/AdvancedRegridding.ipynb | 40 +- .../examples/notebooks/BasicRegridding.ipynb | 18 +- .../examples/notebooks/GridCellArea.ipynb | 18 +- .../notebooks/GridMeshLocStreamField.ipynb | 50 +- .../ESMPy/examples/notebooks/Periodic.ipynb | 24 +- .../notebooks/ugrid_latlon_regrid.ipynb | 32 +- .../ungridded_dimension_regrid.ipynb | 38 +- .../ESMPy/examples/read_write_weight_file.py | 56 +- src/addon/ESMPy/examples/regrid_from_file.py | 26 +- src/addon/ESMPy/examples/tripole_regrid.py | 46 +- .../ESMPy/examples/ugrid_latlon_regrid.py | 42 +- .../examples/ungridded_dimension_regrid.py | 52 +- .../regrid_from_file_consts.py | 31 -- .../ESMPy/src/{ESMF => esmpy}/__init__.py | 39 +- .../ESMPy/src/{ESMF => esmpy}/api/__init__.py | 0 .../src/{ESMF => esmpy}/api/constants.py | 78 +-- .../src/{ESMF => esmpy}/api/esmpymanager.py | 34 +- .../ESMPy/src/{ESMF => esmpy}/api/field.py | 102 ++-- .../ESMPy/src/{ESMF => esmpy}/api/grid.py | 152 +++--- .../src/{ESMF => esmpy}/api/locstream.py | 60 +-- .../ESMPy/src/{ESMF => esmpy}/api/mesh.py | 134 ++--- .../ESMPy/src/{ESMF => esmpy}/api/regrid.py | 130 ++--- .../fragments/dump_esmf_internal_info.py | 0 .../src/{ESMF => esmpy}/fragments/extras.py | 0 .../src/{ESMF => esmpy}/fragments/remap.py | 0 .../src/{ESMF => esmpy}/interface/__init__.py | 0 .../{ESMF => esmpy}/interface/cbindings.py | 8 +- .../src/{ESMF => esmpy}/interface/loadESMF.py | 2 +- .../src/{ESMF => esmpy}/test/__init__.py | 0 .../ESMPy/src/{ESMF => esmpy}/test/base.py | 4 +- .../src/{ESMF => esmpy}/test/base_test.py | 4 +- .../src/{ESMF => esmpy}/test/data/T42_grid.nc | Bin .../test/data/gridspec1Dcoords.nc | Bin .../{ESMF => esmpy}/test/data/ne4np4-esmf.nc | Bin .../test/data/ne4np4-pentagons.nc | Bin .../test/regrid_from_file/__init__.py | 0 .../read_test_cases_from_control_file.py | 2 +- .../test/regrid_from_file/regrid_check.py | 64 +-- .../regrid_from_file/regrid_check_driver.py | 24 +- .../regrid_from_file_consts.py | 31 ++ .../regrid_from_file/regrid_test_data.txt | 0 .../test/regrid_from_file/rfftest.py | 6 +- .../test/regrid_from_file/rfftestdryrun.py | 4 +- .../regrid_from_file/run_regrid_from_file.py | 4 +- .../run_regrid_from_file_dryrun.py | 6 +- .../{ESMF => esmpy}/test/test_api/__init__.py | 0 .../test/test_api/test_array.py | 8 +- .../test/test_api/test_field.py | 9 +- .../test/test_api/test_grid.py | 64 +-- .../test/test_api/test_locstream.py | 6 +- .../test/test_api/test_mesh.py | 18 +- .../test/test_api/test_regrid.py | 402 +++++++-------- .../{ESMF => esmpy}/test/test_api/test_vm.py | 6 +- .../{ESMF => esmpy}/test/test_cbindings.py | 6 +- .../src/{ESMF => esmpy}/util/__init__.py | 0 .../src/{ESMF => esmpy}/util/cache_data.py | 0 .../src/{ESMF => esmpy}/util/decorators.py | 8 +- .../src/{ESMF => esmpy}/util/enum/LICENSE | 0 .../src/{ESMF => esmpy}/util/enum/README | 0 .../src/{ESMF => esmpy}/util/enum/__init__.py | 0 .../{ESMF => esmpy}/util/enum/doc/enum.pdf | Bin .../{ESMF => esmpy}/util/enum/doc/enum.rst | 0 .../src/{ESMF => esmpy}/util/esmpyarray.py | 8 +- .../src/{ESMF => esmpy}/util/exceptions.py | 0 .../{ESMF => esmpy}/util/field_utilities.py | 18 +- .../{ESMF => esmpy}/util/grid_utilities.py | 144 +++--- .../ESMPy/src/{ESMF => esmpy}/util/helpers.py | 4 +- .../ESMPy/src/{ESMF => esmpy}/util/itester.py | 0 .../util/locstream_utilities.py | 54 +- .../{ESMF => esmpy}/util/mesh_utilities.py | 202 ++++---- .../ESMPy/src/{ESMF => esmpy}/util/slicing.py | 26 +- 112 files changed, 1606 insertions(+), 1639 deletions(-) delete mode 100644 src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_from_file_consts.py rename src/addon/ESMPy/src/{ESMF => esmpy}/__init__.py (80%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/__init__.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/constants.py (84%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/esmpymanager.py (87%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/field.py (75%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/grid.py (89%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/locstream.py (79%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/mesh.py (81%) rename src/addon/ESMPy/src/{ESMF => esmpy}/api/regrid.py (81%) rename src/addon/ESMPy/src/{ESMF => esmpy}/fragments/dump_esmf_internal_info.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/fragments/extras.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/fragments/remap.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/interface/__init__.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/interface/cbindings.py (99%) rename src/addon/ESMPy/src/{ESMF => esmpy}/interface/loadESMF.py (99%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/__init__.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/base.py (98%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/base_test.py (91%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/data/T42_grid.nc (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/data/gridspec1Dcoords.nc (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/data/ne4np4-esmf.nc (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/data/ne4np4-pentagons.nc (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/__init__.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/read_test_cases_from_control_file.py (91%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/regrid_check.py (84%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/regrid_check_driver.py (82%) create mode 100644 src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_from_file_consts.py rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/regrid_test_data.txt (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/rfftest.py (52%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/rfftestdryrun.py (51%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/run_regrid_from_file.py (92%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/regrid_from_file/run_regrid_from_file_dryrun.py (87%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/__init__.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/test_array.py (98%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/test_field.py (98%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/test_grid.py (94%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/test_locstream.py (95%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/test_mesh.py (95%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/test_regrid.py (78%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_api/test_vm.py (89%) rename src/addon/ESMPy/src/{ESMF => esmpy}/test/test_cbindings.py (95%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/__init__.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/cache_data.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/decorators.py (91%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/enum/LICENSE (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/enum/README (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/enum/__init__.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/enum/doc/enum.pdf (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/enum/doc/enum.rst (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/esmpyarray.py (97%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/exceptions.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/field_utilities.py (93%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/grid_utilities.py (78%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/helpers.py (87%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/itester.py (100%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/locstream_utilities.py (77%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/mesh_utilities.py (92%) rename src/addon/ESMPy/src/{ESMF => esmpy}/util/slicing.py (85%) diff --git a/src/addon/ESMPy/.gitignore b/src/addon/ESMPy/.gitignore index c427f66ad7..b3ed4aefa2 100644 --- a/src/addon/ESMPy/.gitignore +++ b/src/addon/ESMPy/.gitignore @@ -2,11 +2,6 @@ ################### *.pyc -# Nose # -######## -*.noseids -nosetests.xml - # Misc # ######## *~ @@ -19,12 +14,6 @@ PET* *.vtk *.csv -# Eclipse # -########### -*.project -*.pydevproject -*.settings - # ESMPy build and docs # ######################## build @@ -32,9 +21,9 @@ dist doc/esmpy_doc src/ESMPy.egg-info examples/data -src/ESMF/test/data +src/esmpy/test/data examples/notebooks/ESMPy-data -src/ESMF/test/regrid_from_file/data +src/esmpy/test/regrid_from_file/data # notebooks # ############# diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 08b852bbfb..22c8330913 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -10,7 +10,7 @@ clean: find . -name "*.vtk" -exec rm -f {} \; || : find . -name "*.pytest_cache" -exec rm -rf {} \; || : find . -name "*.python-version" -exec rm -f {} \; || : - rm -rf src/ESMF/test/regrid_from_file/data || : + rm -rf src/esmpy/test/regrid_from_file/data || : rm -rf examples/data || : install: @@ -32,14 +32,10 @@ test_examples_parallel: mpirun -n 4 python3 -m pytest -vs -m="not serial" examples/exampletest.py test_regrid_from_file_dryrun: - python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py + python3 -m pytest -vs src/esmpy/test/regrid_from_file/rfftestdryrun.py test_regrid_from_file: - python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftest.py - -test_regrid_from_file_parallel: - python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftestdryrun.py - mpirun -n 4 python3 -m pytest -vs src/ESMF/test/regrid_from_file/rfftest.py + python3 -m pytest -vs src/esmpy/test/regrid_from_file/rfftest.py test_all: test_unit test_parallel test_examples test_examples_parallel diff --git a/src/addon/ESMPy/doc/CoordSys.rst b/src/addon/ESMPy/doc/CoordSys.rst index b3d321f566..c60b52ca6b 100644 --- a/src/addon/ESMPy/doc/CoordSys.rst +++ b/src/addon/ESMPy/doc/CoordSys.rst @@ -2,6 +2,6 @@ CoordSys ~~~~~~~~ -.. autoclass:: ESMF.api.constants.CoordSys +.. autoclass:: esmpy.api.constants.CoordSys :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/ExtrapMethod.rst b/src/addon/ESMPy/doc/ExtrapMethod.rst index ec65fb1edd..203eb2e679 100644 --- a/src/addon/ESMPy/doc/ExtrapMethod.rst +++ b/src/addon/ESMPy/doc/ExtrapMethod.rst @@ -2,6 +2,6 @@ ExtrapMethod ~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.ExtrapMethod +.. autoclass:: esmpy.api.constants.ExtrapMethod :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/FileFormat.rst b/src/addon/ESMPy/doc/FileFormat.rst index 7a66198768..0d7c5864bf 100755 --- a/src/addon/ESMPy/doc/FileFormat.rst +++ b/src/addon/ESMPy/doc/FileFormat.rst @@ -2,6 +2,6 @@ FileFormat ~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.FileFormat +.. autoclass:: esmpy.api.constants.FileFormat :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/FileMode.rst b/src/addon/ESMPy/doc/FileMode.rst index 28b075b6be..1d2ec75a6d 100644 --- a/src/addon/ESMPy/doc/FileMode.rst +++ b/src/addon/ESMPy/doc/FileMode.rst @@ -2,6 +2,6 @@ FileMode ~~~~~~~~ -.. autoclass:: ESMF.api.constants.FileMode +.. autoclass:: esmpy.api.constants.FileMode :members: :exclude-members: __new__ diff --git a/src/addon/ESMPy/doc/GridItem.rst b/src/addon/ESMPy/doc/GridItem.rst index 22690888c7..dcb838c55c 100755 --- a/src/addon/ESMPy/doc/GridItem.rst +++ b/src/addon/ESMPy/doc/GridItem.rst @@ -2,6 +2,6 @@ GridItem ~~~~~~~~ -.. autoclass:: ESMF.api.constants.GridItem +.. autoclass:: esmpy.api.constants.GridItem :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/LineType.rst b/src/addon/ESMPy/doc/LineType.rst index e0c37fd9d8..11cd684536 100644 --- a/src/addon/ESMPy/doc/LineType.rst +++ b/src/addon/ESMPy/doc/LineType.rst @@ -2,6 +2,6 @@ LineType ~~~~~~~~ -.. autoclass:: ESMF.api.constants.LineType +.. autoclass:: esmpy.api.constants.LineType :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/LogKind.rst b/src/addon/ESMPy/doc/LogKind.rst index e9a329f9bc..721ef17565 100755 --- a/src/addon/ESMPy/doc/LogKind.rst +++ b/src/addon/ESMPy/doc/LogKind.rst @@ -2,6 +2,6 @@ LogKind ~~~~~~~ -.. autoclass:: ESMF.api.constants.LogKind +.. autoclass:: esmpy.api.constants.LogKind :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/MeshElemType.rst b/src/addon/ESMPy/doc/MeshElemType.rst index 9338f22562..34357fe187 100755 --- a/src/addon/ESMPy/doc/MeshElemType.rst +++ b/src/addon/ESMPy/doc/MeshElemType.rst @@ -2,6 +2,6 @@ MeshElemType ~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.MeshElemType +.. autoclass:: esmpy.api.constants.MeshElemType :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/MeshLoc.rst b/src/addon/ESMPy/doc/MeshLoc.rst index 05f3ae3ab5..888c3672a4 100755 --- a/src/addon/ESMPy/doc/MeshLoc.rst +++ b/src/addon/ESMPy/doc/MeshLoc.rst @@ -2,6 +2,6 @@ MeshLoc ~~~~~~~ -.. autoclass:: ESMF.api.constants.MeshLoc +.. autoclass:: esmpy.api.constants.MeshLoc :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/NormType.rst b/src/addon/ESMPy/doc/NormType.rst index 4a80e66d62..d4b6cbaa06 100644 --- a/src/addon/ESMPy/doc/NormType.rst +++ b/src/addon/ESMPy/doc/NormType.rst @@ -2,6 +2,6 @@ NormType ~~~~~~~~ -.. autoclass:: ESMF.api.constants.NormType +.. autoclass:: esmpy.api.constants.NormType :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/PoleKind.rst b/src/addon/ESMPy/doc/PoleKind.rst index 20206874d2..590cc25d30 100644 --- a/src/addon/ESMPy/doc/PoleKind.rst +++ b/src/addon/ESMPy/doc/PoleKind.rst @@ -2,6 +2,6 @@ PoleKind ~~~~~~~~ -.. autoclass:: ESMF.api.constants.PoleKind +.. autoclass:: esmpy.api.constants.PoleKind :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/PoleMethod.rst b/src/addon/ESMPy/doc/PoleMethod.rst index 4be0362658..6d59b56e33 100644 --- a/src/addon/ESMPy/doc/PoleMethod.rst +++ b/src/addon/ESMPy/doc/PoleMethod.rst @@ -2,6 +2,6 @@ PoleMethod ~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.PoleMethod +.. autoclass:: esmpy.api.constants.PoleMethod :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/Region.rst b/src/addon/ESMPy/doc/Region.rst index 620d792092..b905f434e8 100755 --- a/src/addon/ESMPy/doc/Region.rst +++ b/src/addon/ESMPy/doc/Region.rst @@ -2,6 +2,6 @@ Region ~~~~~~ -.. autoclass:: ESMF.api.constants.Region +.. autoclass:: esmpy.api.constants.Region :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/RegridMethod.rst b/src/addon/ESMPy/doc/RegridMethod.rst index acef1267c5..fc2e5027d0 100755 --- a/src/addon/ESMPy/doc/RegridMethod.rst +++ b/src/addon/ESMPy/doc/RegridMethod.rst @@ -2,6 +2,6 @@ RegridMethod ~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.RegridMethod +.. autoclass:: esmpy.api.constants.RegridMethod :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/StaggerLoc.rst b/src/addon/ESMPy/doc/StaggerLoc.rst index 2e09ba247f..7eac7ae404 100755 --- a/src/addon/ESMPy/doc/StaggerLoc.rst +++ b/src/addon/ESMPy/doc/StaggerLoc.rst @@ -2,6 +2,6 @@ StaggerLoc ~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.StaggerLoc +.. autoclass:: esmpy.api.constants.StaggerLoc :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/TypeKind.rst b/src/addon/ESMPy/doc/TypeKind.rst index 3b4c5e944c..378973d3e2 100755 --- a/src/addon/ESMPy/doc/TypeKind.rst +++ b/src/addon/ESMPy/doc/TypeKind.rst @@ -2,6 +2,6 @@ TypeKind ~~~~~~~~ -.. autoclass:: ESMF.api.constants.TypeKind +.. autoclass:: esmpy.api.constants.TypeKind :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/UnmappedAction.rst b/src/addon/ESMPy/doc/UnmappedAction.rst index a9fe04f401..c09ffaf6f8 100755 --- a/src/addon/ESMPy/doc/UnmappedAction.rst +++ b/src/addon/ESMPy/doc/UnmappedAction.rst @@ -2,6 +2,6 @@ UnmappedAction ~~~~~~~~~~~~~~ -.. autoclass:: ESMF.api.constants.UnmappedAction +.. autoclass:: esmpy.api.constants.UnmappedAction :members: :exclude-members: __new__ \ No newline at end of file diff --git a/src/addon/ESMPy/doc/api.rst b/src/addon/ESMPy/doc/api.rst index c6db0bc048..2daf88a531 100644 --- a/src/addon/ESMPy/doc/api.rst +++ b/src/addon/ESMPy/doc/api.rst @@ -6,25 +6,25 @@ API Classes ------- -ESMPy uses a :class:`~ESMF.api.field.Field` object to represent data variables +ESMPy uses a :class:`~esmpy.api.field.Field` object to represent data variables built on an underlying spatial discretization, which is represented by a -:class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or -:class:`~ESMF.api.locstream.LocStream`. -Regridding between :class:`Fields ` is accomplished with the -:class:`~ESMF.api.regrid.Regrid` class. All of these classes are explained in +:class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or +:class:`~esmpy.api.locstream.LocStream`. +Regridding between :class:`Fields ` is accomplished with the +:class:`~esmpy.api.regrid.Regrid` class. All of these classes are explained in more detail in the sections provided by the links in the following table. -======================================== ============================================================================== -Class Description -======================================== ============================================================================== -:class:`~ESMF.api.esmpymanager.Manager` A manager class to initialize and finalize ESMF -:class:`~ESMF.api.field.Field` A data field built on a :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, or :class:`~ESMF.api.locstream.LocStream` -:class:`~ESMF.api.grid.Grid` A class to represent a logically rectangular grid -:class:`~ESMF.api.mesh.Mesh` A class to represent an unstructured grid -:class:`~ESMF.api.locstream.LocStream` A class to represent observational data as a collection of disconnected points -:class:`~ESMF.api.regrid.Regrid` The regridding utility -:class:`~ESMF.api.regrid.RegridFromFile` The from file regridding utility -======================================== ============================================================================== +========================================= ============================================================================== +Class Description +========================================= ============================================================================== +:class:`~esmpy.api.esmpymanager.Manager` A manager class to initialize and finalize ESMF +:class:`~esmpy.api.field.Field` A data field built on a :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, or :class:`~esmpy.api.locstream.LocStream` +:class:`~esmpy.api.grid.Grid` A class to represent a logically rectangular grid +:class:`~esmpy.api.mesh.Mesh` A class to represent an unstructured grid +:class:`~esmpy.api.locstream.LocStream` A class to represent observational data as a collection of disconnected points +:class:`~esmpy.api.regrid.Regrid` The regridding utility +:class:`~esmpy.api.regrid.RegridFromFile` The from file regridding utility +========================================= ============================================================================== --------------- @@ -36,33 +36,33 @@ available options for parameters that expect a variety of specific inputs. The following table lists the available named constants and provides links to pages that further explain the available values. -=========================================================== ============================== -Named constants Description -=========================================================== ============================== -:class:`CoordSys` Specify the coordinate system of a :class:`~ESMF.api.grid.Grid` -:class:`ExtrapMethod` Specify the extrapolation method -:class:`FileFormat` Specify the format of a data file -:class:`FileMode` Specify the mode of a data file -:class:`GridItem` Specify a mask or area item on a :class:`~ESMF.api.grid.Grid` -:class:`LineType` Specify the type of line that connects two points on a sphere -:class:`LogKind` Specify how much logging should be done -:class:`MeshElemType` Specify the type of the :class:`~ESMF.api.mesh.Mesh` elements -:class:`MeshLoc` Specify a nodal or elemental :class:`~ESMF.api.mesh.Mesh` -:class:`NormType` Specify the type of normalization to use for conservative regridding weights -:class:`PoleKind` Specify the type of connection that appears at the poles of the :class:`~ESMF.api.grid.Grid` -:class:`PoleMethod` Specify which type of artificial pole to construct on the source :class:`~ESMF.api.grid.Grid` for regridding -:class:`Region` Specify various regions in the data layout of -:class:`RegridMethod` Specify which interpolation method to use regridding -:class:`StaggerLoc` Specify the position for data in a :class:`~ESMF.api.grid.Grid` cell -:class:`TypeKind` Specify the type and kind of data -:class:`UnmappedAction` Specify which action to take with respect to unmapped destination points -=========================================================== ============================== +============================================================ ============================== +Named constants Description +============================================================ ============================== +:class:`CoordSys` Specify the coordinate system of a :class:`~esmpy.api.grid.Grid` +:class:`ExtrapMethod` Specify the extrapolation method +:class:`FileFormat` Specify the format of a data file +:class:`FileMode` Specify the mode of a data file +:class:`GridItem` Specify a mask or area item on a :class:`~esmpy.api.grid.Grid` +:class:`LineType` Specify the type of line that connects two points on a sphere +:class:`LogKind` Specify how much logging should be done +:class:`MeshElemType` Specify the type of the :class:`~esmpy.api.mesh.Mesh` elements +:class:`MeshLoc` Specify a nodal or elemental :class:`~esmpy.api.mesh.Mesh` +:class:`NormType` Specify the type of normalization to use for conservative regridding weights +:class:`PoleKind` Specify the type of connection that appears at the poles of the :class:`~esmpy.api.grid.Grid` +:class:`PoleMethod` Specify which type of artificial pole to construct on the source :class:`~esmpy.api.grid.Grid` for regridding +:class:`Region` Specify various regions in the data layout of +:class:`RegridMethod` Specify which interpolation method to use regridding +:class:`StaggerLoc` Specify the position for data in a :class:`~esmpy.api.grid.Grid` cell +:class:`TypeKind` Specify the type and kind of data +:class:`UnmappedAction` Specify which action to take with respect to unmapped destination points +============================================================ ============================== ------- Manager ------- -The :class:`~ESMF.api.esmpymanager.Manager` is used by ESMPy to simplify a +The :class:`~esmpy.api.esmpymanager.Manager` is used by ESMPy to simplify a number of low-level calls used by the underlying ESMF framework to allocate resources, enable logging, and control garbage collection. @@ -78,11 +78,11 @@ allocates computational resources in the form of system threads with a lifetime of at least that of the ESMPy execution. In the simplest, and most common case, a PET is equivalent to an MPI process. The number of PETs and the current PET can be queried from the -:class:`~ESMF.api.esmpymanager.Manager`: +:class:`~esmpy.api.esmpymanager.Manager`: .. code:: - mg = ESMF.Manager() + mg = esmpy.Manager() pet_count = mg.pet_count() local_pet = mg.local_pet() @@ -94,11 +94,11 @@ for more information. Logging ~~~~~~~ -The :class:`~ESMF.api.esmpymanager.Manager` is also used to enable logging: +The :class:`~esmpy.api.esmpymanager.Manager` is also used to enable logging: .. code:: - mg = ESMF.Manager(debug=True) + mg = esmpy.Manager(debug=True) local_pet = mg.local_pet The output will be logged in files named PET.ESMF_LogFile. @@ -109,10 +109,10 @@ Memory management The underlying ESMF framework needs to be initialized and finalized once and only once per execution. This is handled internally by the -:class:`~ESMF.api.esmpymanager.Manager` and **does not** require any explicit +:class:`~esmpy.api.esmpymanager.Manager` and **does not** require any explicit user intervention. However, the ESMF garbage collection feature is not triggered until the finalization routine is invoked, which may not happen until the -:class:`~ESMF.api.esmpymanager.Manager` goes out of scope at the end of the +:class:`~esmpy.api.esmpymanager.Manager` goes out of scope at the end of the program execution. If memory deallocation of ESMPy @@ -121,12 +121,12 @@ objects is required *prior* to the end of the program, the class level .. code:: - mg = ESMF.Manager() + mg = esmpy.Manager() mg.destroy() -This is commonly required when reusing a :class:`~ESMF.api.regrid.Regrid` object -to interpolate data between many :class:`~ESMF.api.field.Field` pairs. +This is commonly required when reusing a :class:`~esmpy.api.regrid.Regrid` object +to interpolate data between many :class:`~esmpy.api.field.Field` pairs. ~~~~~~~~~~~~~~~~~ MOAB Mesh backend @@ -147,9 +147,9 @@ Spatial Discretization Objects ------------------------------ There are three different objects used for spatial coordinate representation: -:class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, and :class:`~ESMF.api.locstream.LocStream`. :class:`Grids ` are used to represent logically rectangular -grids, :class:`Meshes ` are used for unstructured collections of polygons, and -:class:`LocStreams ` are used for unstructured collections of individual points. These +:class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, and :class:`~esmpy.api.locstream.LocStream`. :class:`Grids ` are used to represent logically rectangular +grids, :class:`Meshes ` are used for unstructured collections of polygons, and +:class:`LocStreams ` are used for unstructured collections of individual points. These objects are nearly identical counterparts to the objects of the same name in ESMF, with some simplifications for ease of use in the Python environment. @@ -157,9 +157,9 @@ ESMF, with some simplifications for ease of use in the Python environment. Grid ~~~~ -The :class:`~ESMF.api.grid.Grid` is used to represent the geometry and discretization of logically -rectangular physical grids. The :class:`~ESMF.api.grid.Grid` can also hold information that can used in -calculations involving the :class:`~ESMF.api.grid.Grid`, like a mask or the cell areas. Refer to the Grid Class of the +The :class:`~esmpy.api.grid.Grid` is used to represent the geometry and discretization of logically +rectangular physical grids. The :class:`~esmpy.api.grid.Grid` can also hold information that can used in +calculations involving the :class:`~esmpy.api.grid.Grid`, like a mask or the cell areas. Refer to the Grid Class of the `ESMF Reference Manual `_ for more information. ++++++++++ @@ -169,103 +169,103 @@ Staggering Staggering is a finite difference technique in which the values of different physical quantities are placed at different locations within a grid cell. -The ESMF :class:`~ESMF.api.grid.Grid` class supports a variety of stagger locations, including cell +The ESMF :class:`~esmpy.api.grid.Grid` class supports a variety of stagger locations, including cell centers, corners, and edge centers. The default stagger location in ESMF is the -cell center, and cell counts in :class:`~ESMF.api.grid.Grid` are based on this assumption. Combinations +cell center, and cell counts in :class:`~esmpy.api.grid.Grid` are based on this assumption. Combinations of the 2D ESMF stagger locations are sufficient to specify any of the Arakawa staggers. ESMF also supports staggering in 3D and higher dimensions. There are shortcuts for standard staggers, and interfaces through which users can create custom staggers. -As a default the ESMF :class:`~ESMF.api.grid.Grid` class provides symmetric staggering, so that cell +As a default the ESMF :class:`~esmpy.api.grid.Grid` class provides symmetric staggering, so that cell centers are enclosed by cell perimeter (e.g. corner) stagger locations. This means the coordinate arrays for stagger locations other than the center will have an additional element of padding in order to enclose the cell center locations. However, to achieve other types of staggering, the user may alter or eliminate this padding by using the appropriate options when adding coordinates -to a :class:`~ESMF.api.grid.Grid`. +to a :class:`~esmpy.api.grid.Grid`. -:class:`~ESMF.api.grid.Grid` staggers are indicated using -:class:`StaggerLoc`. +:class:`~esmpy.api.grid.Grid` staggers are indicated using +:class:`StaggerLoc`. .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER) + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER) +++++++++++++++++++++ Spherical Coordinates +++++++++++++++++++++ -In the case that the :class:`~ESMF.api.grid.Grid` is on a sphere (coord_sys = :class:`ESMF.api.constants.CoordSys.SPH_DEG` or -:class:`ESMF.api.constants.CoordSys.SPH_RAD`) then the coordinates given in the :class:`~ESMF.api.grid.Grid` are interpreted +In the case that the :class:`~esmpy.api.grid.Grid` is on a sphere (coord_sys = :class:`esmpy.api.constants.CoordSys.SPH_DEG` or +:class:`esmpy.api.constants.CoordSys.SPH_RAD`) then the coordinates given in the :class:`~esmpy.api.grid.Grid` are interpreted as latitude and longitude values. The coordinates can either be in degrees or -radians as indicated by the ``coord_sys`` flag set during :class:`~ESMF.api.grid.Grid` creation. As is +radians as indicated by the ``coord_sys`` flag set during :class:`~esmpy.api.grid.Grid` creation. As is true with many global models, this application currently assumes the latitude and longitude refer to positions on a perfect sphere. -The :class:`~ESMF.api.grid.Grid` coordinate system is represented using -:class:`CoordSys`. +The :class:`~esmpy.api.grid.Grid` coordinate system is represented using +:class:`CoordSys`. .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG) + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG) +++++++++++ Periodicity +++++++++++ -A periodic connection can be specified when building :class:`Grids ` in spherical +A periodic connection can be specified when building :class:`Grids ` in spherical coordinates. The ``num_peri_dims`` parameter indicates the total number of periodic dimensions and ``periodic_dim`` is used to identify which dimensions should be considered periodic. There must always be at least one non-periodic -dimension. For example, to create a global latitude-longitude :class:`~ESMF.api.grid.Grid` there would +dimension. For example, to create a global latitude-longitude :class:`~esmpy.api.grid.Grid` there would be one periodic dimension, dimension 0 (longitude). .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG, + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG, num_peri_dims=1, periodic_dim=0) +++++++++++++++ Pole Generation +++++++++++++++ -The :class:`~ESMF.api.grid.Grid` can generate an artificial pole by using the ``pole_dim`` parameter. This +The :class:`~esmpy.api.grid.Grid` can generate an artificial pole by using the ``pole_dim`` parameter. This can be helpful for regridding operations to smooth out the interpolated values in the polar region. For the example of creating a global latitude-longitude -:class:`~ESMF.api.grid.Grid`, the pole dimension would be 1 (latitude). +:class:`~esmpy.api.grid.Grid`, the pole dimension would be 1 (latitude). .. code:: - grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG, + grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG, num_peri_dims=1, periodic_dim=0, pole_dim=1) +++++++ Masking +++++++ -Masking is the process used to mark parts of a :class:`~ESMF.api.grid.Grid` to be ignored during an -operation. Marking :class:`~ESMF.api.grid.Grid` cells as masked can affect the :class:`~ESMF.api.field.Field` values that are +Masking is the process used to mark parts of a :class:`~esmpy.api.grid.Grid` to be ignored during an +operation. Marking :class:`~esmpy.api.grid.Grid` cells as masked can affect the :class:`~esmpy.api.field.Field` values that are represented by those cells. Masking is specified by assigning an integer value -to a :class:`~ESMF.api.grid.Grid` cell. This allows many different masks to be defined on the same :class:`~ESMF.api.grid.Grid`, -any combination of which may be also activated on the :class:`~ESMF.api.field.Field` by specifying the -corresponding integer values. The activation of :class:`~ESMF.api.field.Field` masks with respect to the -underlying :class:`~ESMF.api.grid.Grid` mask is handled by :class:`~ESMF.api.regrid.Regrid`, and a more +to a :class:`~esmpy.api.grid.Grid` cell. This allows many different masks to be defined on the same :class:`~esmpy.api.grid.Grid`, +any combination of which may be also activated on the :class:`~esmpy.api.field.Field` by specifying the +corresponding integer values. The activation of :class:`~esmpy.api.field.Field` masks with respect to the +underlying :class:`~esmpy.api.grid.Grid` mask is handled by :class:`~esmpy.api.regrid.Regrid`, and a more general discussion of masking is covered in the :ref:`masking ` section. .. code:: In [1]: import numpy as np - ...: import ESMF - ...: grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER, - ...: coord_sys=ESMF.CoordSys.SPH_DEG, + ...: import esmpy + ...: grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER, + ...: coord_sys=esmpy.CoordSys.SPH_DEG, ...: num_peri_dims=1, periodic_dim=0, pole_dim=1) ...: - ...: mask = grid.add_item(ESMF.GridItem.MASK, staggerloc=ESMF.StaggerLoc.CENTER) + ...: mask = grid.add_item(esmpy.GridItem.MASK, staggerloc=esmpy.StaggerLoc.CENTER) ...: mask ...: Out[1]: @@ -277,29 +277,29 @@ section. Cell Areas ++++++++++ -:class:`~ESMF.api.grid.Grid` cell areas can be calculated by ESMPy. Space must first be allocated for +:class:`~esmpy.api.grid.Grid` cell areas can be calculated by ESMPy. Space must first be allocated for this calculation by adding an -:class:`~ESMF.api.constants.GridItem.AREA` item to the :class:`~ESMF.api.grid.Grid`. -Then a :class:`~ESMF.api.field.Field` must be created, and the -:class:`~ESMF.api.field.Field.get_area()` function called. +:class:`~esmpy.api.constants.GridItem.AREA` item to the :class:`~esmpy.api.grid.Grid`. +Then a :class:`~esmpy.api.field.Field` must be created, and the +:class:`~esmpy.api.field.Field.get_area()` function called. -.. Note:: The :class:`~ESMF.api.grid.Grid` area calculation assumes the :class:`~ESMF.api.grid.Grid` is a unit sphere. +.. Note:: The :class:`~esmpy.api.grid.Grid` area calculation assumes the :class:`~esmpy.api.grid.Grid` is a unit sphere. -:class:`~ESMF.api.grid.Grid` cell areas may also be set to user-defined values -after the :class:`~ESMF.api.constants.GridItem.AREA` item has -been allocated and retrieved using :class:`~ESMF.api.grid.Grid.get_item()`. +:class:`~esmpy.api.grid.Grid` cell areas may also be set to user-defined values +after the :class:`~esmpy.api.constants.GridItem.AREA` item has +been allocated and retrieved using :class:`~esmpy.api.grid.Grid.get_item()`. .. code:: - In [1]: grid = ESMF.Grid(np.array([3,4]), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], - ...: coord_sys=ESMF.CoordSys.SPH_DEG, + In [1]: grid = esmpy.Grid(np.array([3,4]), staggerloc=[esmpy.StaggerLoc.CENTER, esmpy.StaggerLoc.CORNER], + ...: coord_sys=esmpy.CoordSys.SPH_DEG, ...: num_peri_dims=1, periodic_dim=0, pole_dim=1) ...: ...: ...: gridLon = grid.get_coords(0) ...: gridLat = grid.get_coords(1) - ...: gridLonCorner = grid.get_coords(0, staggerloc=ESMF.StaggerLoc.CORNER) - ...: gridLatCorner = grid.get_coords(1, staggerloc=ESMF.StaggerLoc.CORNER) + ...: gridLonCorner = grid.get_coords(0, staggerloc=esmpy.StaggerLoc.CORNER) + ...: gridLatCorner = grid.get_coords(1, staggerloc=esmpy.StaggerLoc.CORNER) ...: ...: lon = np.linspace(-120,120,3) ...: lat = np.linspace(-67.5, 67.5,4) @@ -314,7 +314,7 @@ been allocated and retrieved using :class:`~ESMF.api.grid.Grid.get_item()`. ...: gridLonCorner[:] = lonm_corner ...: gridLatCorner[:] = latm_corner ...: - ...: field = ESMF.Field(grid) + ...: field = esmpy.Field(grid) ...: field.get_area() ...: field.data ...: @@ -327,101 +327,101 @@ been allocated and retrieved using :class:`~ESMF.api.grid.Grid.get_item()`. Mesh ~~~~ -A :class:`~ESMF.api.mesh.Mesh` is an object for representing unstructured grids. +A :class:`~esmpy.api.mesh.Mesh` is an object for representing unstructured grids. Refer to the Mesh Class of the `ESMF Reference Manual `_ for more information. -A :class:`~ESMF.api.mesh.Mesh` is constructed of *nodes* and *elements*. A node, also known as a vertex -or corner, is a part of a :class:`~ESMF.api.mesh.Mesh` which represents a single point. An element, -also known as a cell, is a part of a :class:`~ESMF.api.mesh.Mesh` which represents a small +A :class:`~esmpy.api.mesh.Mesh` is constructed of *nodes* and *elements*. A node, also known as a vertex +or corner, is a part of a :class:`~esmpy.api.mesh.Mesh` which represents a single point. An element, +also known as a cell, is a part of a :class:`~esmpy.api.mesh.Mesh` which represents a small region of space. Elements are described in terms of a connected set of nodes which represent locations along their boundaries. -:class:`~ESMF.api.field.Field` data may be located on either the nodes or elements of a :class:`~ESMF.api.mesh.Mesh`. :class:`Fields ` -created on a :class:`~ESMF.api.mesh.Mesh` can also be used as either the source or destination or both +:class:`~esmpy.api.field.Field` data may be located on either the nodes or elements of a :class:`~esmpy.api.mesh.Mesh`. :class:`Fields ` +created on a :class:`~esmpy.api.mesh.Mesh` can also be used as either the source or destination or both of a regridding operation. -The dimension of a :class:`~ESMF.api.mesh.Mesh` in ESMF is specified with two parameters: the +The dimension of a :class:`~esmpy.api.mesh.Mesh` in ESMF is specified with two parameters: the *parametric* dimension and the *spatial* dimension. -The parametric dimension of a :class:`~ESMF.api.mesh.Mesh` is the dimension of the topology of the :class:`~ESMF.api.mesh.Mesh`. -This can be thought of as the dimension of the elements which make up the :class:`~ESMF.api.mesh.Mesh`. -For example, a :class:`~ESMF.api.mesh.Mesh` composed of triangles would have a parametric dimension of -2, and a :class:`~ESMF.api.mesh.Mesh` composed of tetrahedra would have a parametric dimension of 3. +The parametric dimension of a :class:`~esmpy.api.mesh.Mesh` is the dimension of the topology of the :class:`~esmpy.api.mesh.Mesh`. +This can be thought of as the dimension of the elements which make up the :class:`~esmpy.api.mesh.Mesh`. +For example, a :class:`~esmpy.api.mesh.Mesh` composed of triangles would have a parametric dimension of +2, and a :class:`~esmpy.api.mesh.Mesh` composed of tetrahedra would have a parametric dimension of 3. -The spatial dimension of a :class:`~ESMF.api.mesh.Mesh` is the dimension of the space in which the :class:`~ESMF.api.mesh.Mesh` +The spatial dimension of a :class:`~esmpy.api.mesh.Mesh` is the dimension of the space in which the :class:`~esmpy.api.mesh.Mesh` is embedded. In other words, it is the number of coordinate dimensions needed to -describe the location of the nodes making up the :class:`~ESMF.api.mesh.Mesh`. +describe the location of the nodes making up the :class:`~esmpy.api.mesh.Mesh`. -For example, a :class:`~ESMF.api.mesh.Mesh` constructed of squares on a plane would have a parametric -dimension of 2 and a spatial dimension of 2. If that same :class:`~ESMF.api.mesh.Mesh` were used to -represent the 2D surface of a sphere, then the :class:`~ESMF.api.mesh.Mesh` would still have a +For example, a :class:`~esmpy.api.mesh.Mesh` constructed of squares on a plane would have a parametric +dimension of 2 and a spatial dimension of 2. If that same :class:`~esmpy.api.mesh.Mesh` were used to +represent the 2D surface of a sphere, then the :class:`~esmpy.api.mesh.Mesh` would still have a parametric dimension of 2, but now its spatial dimension would be 3. -Only :class:`Meshes ` whose number of coordinate dimensions (spatial dimension) is 2 or 3 -are supported. The dimension of the elements in a :class:`~ESMF.api.mesh.Mesh` (parametric dimension) must +Only :class:`Meshes ` whose number of coordinate dimensions (spatial dimension) is 2 or 3 +are supported. The dimension of the elements in a :class:`~esmpy.api.mesh.Mesh` (parametric dimension) must be less than or equal to the spatial dimension, but also must be either 2 or 3. -This means that a :class:`~ESMF.api.mesh.Mesh` may be either 2D elements in 2D space, 3D elements in 3D +This means that a :class:`~esmpy.api.mesh.Mesh` may be either 2D elements in 2D space, 3D elements in 3D space, or a manifold constructed of 2D elements embedded in 3D space. For a parametric dimension of 2, the native supported element types are triangles and quadrilaterals. In addition to these, ESMF supports 2D polygons with any number of sides. Internally these are represented as sets of triangles, but to the user should behave like any other element. For a parametric dimension -of 3, the supported element types are tetrahedrons and hexahedrons. The :class:`~ESMF.api.mesh.Mesh` +of 3, the supported element types are tetrahedrons and hexahedrons. The :class:`~esmpy.api.mesh.Mesh` supports any combination of element types within a particular dimension, but -types from different dimensions may not be mixed. For example, a :class:`~ESMF.api.mesh.Mesh` cannot be +types from different dimensions may not be mixed. For example, a :class:`~esmpy.api.mesh.Mesh` cannot be constructed of both quadrilaterals and tetrahedra. +++++++++++++ Mesh Creation +++++++++++++ -To create a :class:`~ESMF.api.mesh.Mesh` we need to set some properties of the :class:`~ESMF.api.mesh.Mesh` as a whole, some -properties of each node in the :class:`~ESMF.api.mesh.Mesh` and then some properties of each element +To create a :class:`~esmpy.api.mesh.Mesh` we need to set some properties of the :class:`~esmpy.api.mesh.Mesh` as a whole, some +properties of each node in the :class:`~esmpy.api.mesh.Mesh` and then some properties of each element which connects the nodes. -For the :class:`~ESMF.api.mesh.Mesh` as a whole we set its parametric dimension and spatial dimension. -A :class:`Mesh's ` parametric dimension can be thought of as the dimension of the elements -which make up the :class:`~ESMF.api.mesh.Mesh`. A :class:`Mesh's ` spatial dimension, on the other hand, is the +For the :class:`~esmpy.api.mesh.Mesh` as a whole we set its parametric dimension and spatial dimension. +A :class:`Mesh's ` parametric dimension can be thought of as the dimension of the elements +which make up the :class:`~esmpy.api.mesh.Mesh`. A :class:`Mesh's ` spatial dimension, on the other hand, is the number of coordinate dimensions needed to describe the location of the nodes -making up the :class:`~ESMF.api.mesh.Mesh`. +making up the :class:`~esmpy.api.mesh.Mesh`. -The structure of the per node and element information used to create a :class:`~ESMF.api.mesh.Mesh` is -influenced by the :class:`~ESMF.api.mesh.Mesh` distribution strategy. The :class:`~ESMF.api.mesh.Mesh` class is distributed by +The structure of the per node and element information used to create a :class:`~esmpy.api.mesh.Mesh` is +influenced by the :class:`~esmpy.api.mesh.Mesh` distribution strategy. The :class:`~esmpy.api.mesh.Mesh` class is distributed by elements. This means that a node must be present on any PET that contains an element associated with that node, but not on any other PET (a node can't be on a PET without an element "home"). Since a node may be used by two or more elements located on different PETs, a node may be duplicated on multiple PETs. When a node is duplicated in this manner, one and only one of the PETs that contain the node must "own" the node. The user sets -this ownership when they define the nodes during :class:`~ESMF.api.mesh.Mesh` -creation. When a :class:`~ESMF.api.field.Field` is created on a -:class:`~ESMF.api.mesh.Mesh` (i.e. on the :class:`~ESMF.api.mesh.Mesh` nodes), -on each PET the :class:`~ESMF.api.field.Field` is only +this ownership when they define the nodes during :class:`~esmpy.api.mesh.Mesh` +creation. When a :class:`~esmpy.api.field.Field` is created on a +:class:`~esmpy.api.mesh.Mesh` (i.e. on the :class:`~esmpy.api.mesh.Mesh` nodes), +on each PET the :class:`~esmpy.api.field.Field` is only created on the nodes which are owned by that PET. This means that the size -of the :class:`~ESMF.api.field.Field` memory on the PET can be smaller than the -number of nodes used to create the :class:`~ESMF.api.mesh.Mesh` on that PET. +of the :class:`~esmpy.api.field.Field` memory on the PET can be smaller than the +number of nodes used to create the :class:`~esmpy.api.mesh.Mesh` on that PET. -Three properties need to be defined for each :class:`~ESMF.api.mesh.Mesh` node: the global id of the node +Three properties need to be defined for each :class:`~esmpy.api.mesh.Mesh` node: the global id of the node (``node_ids``), node coordinates (``node_coords``), and which PET owns the node (``node_owners``). The node id is a unique (across all PETs) integer attached to the particular node. It is used to indicate which nodes are the same when -connecting together pieces of the :class:`~ESMF.api.mesh.Mesh` on different PETs. The node -coordinates indicate the location of a node in space and are used in the :class:`~ESMF.api.regrid.Regrid` +connecting together pieces of the :class:`~esmpy.api.mesh.Mesh` on different PETs. The node +coordinates indicate the location of a node in space and are used in the :class:`~esmpy.api.regrid.Regrid` functionality when interpolating. The node owner indicates which PET is in -charge of the node. This is used when creating a :class:`~ESMF.api.field.Field` on the :class:`~ESMF.api.mesh.Mesh` to indicate -which PET should contain a :class:`~ESMF.api.field.Field` location for the data. +charge of the node. This is used when creating a :class:`~esmpy.api.field.Field` on the :class:`~esmpy.api.mesh.Mesh` to indicate +which PET should contain a :class:`~esmpy.api.field.Field` location for the data. -Three properties need to be defined for each :class:`~ESMF.api.mesh.Mesh` element: the global id of the +Three properties need to be defined for each :class:`~esmpy.api.mesh.Mesh` element: the global id of the element (``element_ids``), the topology type of the element (``element_types``), and which nodes are connected together to form the element (``element_conn``). The element id is a unique (across all PETs) integer attached to the particular element. The element type describes the topology of the element (e.g. a triangle vs. a quadrilateral). The range of choices for the topology of -the elements in a :class:`~ESMF.api.mesh.Mesh` are restricted by the :class:`Mesh's ` parametric dimension (e.g. a -:class:`~ESMF.api.mesh.Mesh` can't contain a 2D element like a triangle, when its parametric dimension +the elements in a :class:`~esmpy.api.mesh.Mesh` are restricted by the :class:`Mesh's ` parametric dimension (e.g. a +:class:`~esmpy.api.mesh.Mesh` can't contain a 2D element like a triangle, when its parametric dimension is 3D), but it can contain any combination of elements appropriate to its dimension. In particular, in 2D ESMF supports two native element types triangle and quadrilateral, but also provides support for polygons with any number of @@ -433,7 +433,7 @@ which nodes are to be connected together to form the element. The number of nodes connected together for each element is implied by the elements topology type (``element_types``). It is IMPORTANT to note, that the entries in this list are NOT the global ids of the nodes, but are indices into the PET local lists -of node info used in the :class:`~ESMF.api.mesh.Mesh` creation. In other words, the element connectivity +of node info used in the :class:`~esmpy.api.mesh.Mesh` creation. In other words, the element connectivity isn't specified in terms of the global list of nodes, but instead is specified in terms of the locally described node info. One other important point about connectivities is that the order of the nodes in the connectivity list of an @@ -441,9 +441,9 @@ element is important. In general, when specifying an element with parametric dimension 2, the nodes should be given in counterclockwise order around the element. -The three step :class:`~ESMF.api.mesh.Mesh` creation process starts with a call to the :class:`~ESMF.api.mesh.Mesh` constructor. -It is then followed by the :class:`~ESMF.api.mesh.Mesh.add_nodes()` call to -specify nodes, and then the :class:`~ESMF.api.mesh.Mesh.add_elements()` call to +The three step :class:`~esmpy.api.mesh.Mesh` creation process starts with a call to the :class:`~esmpy.api.mesh.Mesh` constructor. +It is then followed by the :class:`~esmpy.api.mesh.Mesh.add_nodes()` call to +specify nodes, and then the :class:`~esmpy.api.mesh.Mesh.add_elements()` call to specify elements. .. code:: @@ -466,7 +466,7 @@ specify elements. # Element Ids in centers # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) num_node = 12 num_elem = 5 @@ -488,9 +488,9 @@ specify elements. nodeOwner = np.zeros(num_node) elemId = np.array([1,2,3,4,5]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI, 5, 6]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI, 5, 6]) elemConn=np.array([0,1,4,3, # elem id 1 1,2,4, # elem id 2 @@ -506,24 +506,24 @@ specify elements. Masking +++++++ -There are two types of masking available in :class:`~ESMF.api.mesh.Mesh`: node masking and element +There are two types of masking available in :class:`~esmpy.api.mesh.Mesh`: node masking and element masking. These both work in a similar manner, but vary slightly in the details -of setting the mask information during :class:`~ESMF.api.mesh.Mesh` creation. +of setting the mask information during :class:`~esmpy.api.mesh.Mesh` creation. For node masking, the mask information is set using the ``node_mask`` parameter. -When a :class:`~ESMF.api.regrid.Regrid` object is created the mask values arguments ``src_mask_values`` and +When a :class:`~esmpy.api.regrid.Regrid` object is created the mask values arguments ``src_mask_values`` and ``dst_mask_values`` can then be used to indicate which particular values set in the ``node_mask`` array indicate that the node should be masked. For example, if -``dst_mask_values`` has been set to 1, then any node in the destination :class:`~ESMF.api.mesh.Mesh` whose +``dst_mask_values`` has been set to 1, then any node in the destination :class:`~esmpy.api.mesh.Mesh` whose corresponding ``node_mask`` value is 1 will be masked out (a node with any other value than 1 will not be masked). For element masking, the mask information is set using the ``element_mask`` -parameter when adding elements to the :class:`~ESMF.api.mesh.Mesh`. In a similar manner to node masking, -the mask values parameters to :class:`~ESMF.api.regrid.Regrid`, ``src_mask_values`` and ``dst_mask_values`` +parameter when adding elements to the :class:`~esmpy.api.mesh.Mesh`. In a similar manner to node masking, +the mask values parameters to :class:`~esmpy.api.regrid.Regrid`, ``src_mask_values`` and ``dst_mask_values`` can then be used to indicate which particular values set in the ``element_mask`` array indicate that the element should be masked. For example, if -``dst_mask_values`` has been set to 1, then any element in the destination :class:`~ESMF.api.mesh.Mesh` +``dst_mask_values`` has been set to 1, then any element in the destination :class:`~esmpy.api.mesh.Mesh` whose corresponding ``element_mask`` value is 1 will be masked out (an element with any other value than 1 will not be masked). @@ -531,21 +531,21 @@ with any other value than 1 will not be masked). Areas +++++ -:class:`~ESMF.api.mesh.Mesh` cell areas can be specified using the ``element_areas`` parameter to -:class:`~ESMF.api.mesh.Mesh.add_elements()`. +:class:`~esmpy.api.mesh.Mesh` cell areas can be specified using the ``element_areas`` parameter to +:class:`~esmpy.api.mesh.Mesh.add_elements()`. If cell areas are not specified by the user they can be calculated by ESMPy -using :class:`~ESMF.api.field.Field.get_area()`. +using :class:`~esmpy.api.field.Field.get_area()`. ~~~~~~~~~ LocStream ~~~~~~~~~ -A :class:`~ESMF.api.locstream.LocStream` can be used to represent the locations of a set of -data points. For example, in the data assimilation world, :class:`LocStreams ` can be used +A :class:`~esmpy.api.locstream.LocStream` can be used to represent the locations of a set of +data points. For example, in the data assimilation world, :class:`LocStreams ` can be used to represent a set of observations. The values of the data points are stored -within a :class:`~ESMF.api.field.Field` created using the :class:`~ESMF.api.locstream.LocStream`. +within a :class:`~esmpy.api.field.Field` created using the :class:`~esmpy.api.locstream.LocStream`. Refer to the LocStream Class of the `ESMF Reference Manual `_ for more information. @@ -556,26 +556,26 @@ called *keys*. A key is essentially a list of point descriptors, one for each da point. They may hold other information besides the coordinates - a mask, for example. They may also hold a second set of coordinates. Keys are referenced by name. Each key must contain the same number of elements as there are data points -in the :class:`~ESMF.api.locstream.LocStream`. While there is no assumption in the ordering of the points, +in the :class:`~esmpy.api.locstream.LocStream`. While there is no assumption in the ordering of the points, the order chosen must be maintained in each of the keys. -A :class:`~ESMF.api.locstream.LocStream` can be very large. Data assimilation systems might use :class:`LocStreams ` -with up to :math:`10^8` observations, so efficiency is critical. :class:`LocStreams ` can be +A :class:`~esmpy.api.locstream.LocStream` can be very large. Data assimilation systems might use :class:`LocStreams ` +with up to :math:`10^8` observations, so efficiency is critical. :class:`LocStreams ` can be created from file. -A :class:`~ESMF.api.locstream.LocStream` is similar to a :class:`~ESMF.api.mesh.Mesh` in that both are collections of irregularly -positioned points. However, the two structures differ because a :class:`~ESMF.api.mesh.Mesh` also has +A :class:`~esmpy.api.locstream.LocStream` is similar to a :class:`~esmpy.api.mesh.Mesh` in that both are collections of irregularly +positioned points. However, the two structures differ because a :class:`~esmpy.api.mesh.Mesh` also has connectivity: each data point represents either a center or corner of a cell. -There is no requirement that the points in a :class:`~ESMF.api.locstream.LocStream` have connectivity, in +There is no requirement that the points in a :class:`~esmpy.api.locstream.LocStream` have connectivity, in fact there is no requirement that any two points have any particular spatial relationship at all. .. code:: - locstream = ESMF.LocStream(16, coord_sys=coord_sys) + locstream = esmpy.LocStream(16, coord_sys=coord_sys) deg_rad = pi - if coord_sys == ESMF.CoordSys.SPH_DEG: + if coord_sys == esmpy.CoordSys.SPH_DEG: deg_rad = 180 locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad] @@ -592,17 +592,17 @@ Create a Grid or Mesh from File File Formats ~~~~~~~~~~~~ -ESMPy can create :class:`~ESMF.api.grid.Grid` or :class:`~ESMF.api.mesh.Mesh` objects from NetCDF files in a variety -of formats. A :class:`~ESMF.api.mesh.Mesh` can be created from files in :class:`~ESMF.api.constants.FileFormat.SCRIP`, :class:`~ESMF.api.constants.FileFormat.ESMFMESH`, and :class:`~ESMF.api.constants.FileFormat.UGRID` -formats. :class:`~ESMF.api.grid.Grid` files can be in :class:`~ESMF.api.constants.FileFormat.SCRIP` and :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` format. +ESMPy can create :class:`~esmpy.api.grid.Grid` or :class:`~esmpy.api.mesh.Mesh` objects from NetCDF files in a variety +of formats. A :class:`~esmpy.api.mesh.Mesh` can be created from files in :class:`~esmpy.api.constants.FileFormat.SCRIP`, :class:`~esmpy.api.constants.FileFormat.ESMFMESH`, and :class:`~esmpy.api.constants.FileFormat.UGRID` +formats. :class:`~esmpy.api.grid.Grid` files can be in :class:`~esmpy.api.constants.FileFormat.SCRIP` and :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` format. +++++ SCRIP +++++ .. _scrip: -This file format is used by the :class:`~ESMF.api.constants.FileFormat.SCRIP` :cite:`ref:SCRIP`, package, grid files that -work with that package should also work here. :class:`~ESMF.api.constants.FileFormat.SCRIP` format files are +This file format is used by the :class:`~esmpy.api.constants.FileFormat.SCRIP` :cite:`ref:SCRIP`, package, grid files that +work with that package should also work here. :class:`~esmpy.api.constants.FileFormat.SCRIP` format files are capable of storing either 2D logically rectangular grids or 2D unstructured grids. More information can be found in the `ESMF Reference Manual `_. @@ -612,10 +612,10 @@ ESMFMESH ++++++++ .. _esmfmesh: -ESMF has a custom unstructured grid file format for describing :class:`Meshes `. -This format is more compatible than the :class:`~ESMF.api.constants.FileFormat.SCRIP` format with the methods -used to create a :class:`~ESMF.api.mesh.Mesh` object, so less conversion needs to be done to -create a :class:`~ESMF.api.mesh.Mesh`. The :class:`~ESMF.api.constants.FileFormat.ESMFMESH` format is thus more efficient than :class:`~ESMF.api.constants.FileFormat.SCRIP` when +ESMF has a custom unstructured grid file format for describing :class:`Meshes `. +This format is more compatible than the :class:`~esmpy.api.constants.FileFormat.SCRIP` format with the methods +used to create a :class:`~esmpy.api.mesh.Mesh` object, so less conversion needs to be done to +create a :class:`~esmpy.api.mesh.Mesh`. The :class:`~esmpy.api.constants.FileFormat.ESMFMESH` format is thus more efficient than :class:`~esmpy.api.constants.FileFormat.SCRIP` when used with ESMPy. More information can be found in the `ESMF Reference Manual `_. @@ -624,9 +624,9 @@ GRIDSPEC ++++++++ .. _gridspec: -:class:`~ESMF.api.constants.FileFormat.GRIDSPEC` is an extension to the Climate and Forecast (CF) metadata +:class:`~esmpy.api.constants.FileFormat.GRIDSPEC` is an extension to the Climate and Forecast (CF) metadata conventions for the representation of gridded data for Earth System -Models. ESMPy supports NetCDF files that follow the CF :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` +Models. ESMPy supports NetCDF files that follow the CF :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` convention to support logically rectangular lat/lon grids. More information can be found in the `ESMF Reference Manual `_. @@ -636,9 +636,9 @@ UGRID +++++ .. _ugrid: -:class:`~ESMF.api.constants.FileFormat.UGRID` is an extension to the CF metadata +:class:`~esmpy.api.constants.FileFormat.UGRID` is an extension to the CF metadata conventions for the unstructured grid data model. ESMPy support -NetCDF files that follow the CF :class:`~ESMF.api.constants.FileFormat.UGRID` convention for unstructured grids. +NetCDF files that follow the CF :class:`~esmpy.api.constants.FileFormat.UGRID` convention for unstructured grids. More information can be found in the `ESMF Reference Manual `_. @@ -646,18 +646,18 @@ More information can be found in the Meshes from File ~~~~~~~~~~~~~~~~ -When creating a :class:`~ESMF.api.mesh.Mesh` from a :class:`~ESMF.api.constants.FileFormat.SCRIP` format file, there are a number of -options to control the output :class:`~ESMF.api.mesh.Mesh`. The data is located at the center -of the grid cell in a :class:`~ESMF.api.constants.FileFormat.SCRIP` grid. Therefore, when the :class:`~ESMF.api.mesh.Mesh` will be +When creating a :class:`~esmpy.api.mesh.Mesh` from a :class:`~esmpy.api.constants.FileFormat.SCRIP` format file, there are a number of +options to control the output :class:`~esmpy.api.mesh.Mesh`. The data is located at the center +of the grid cell in a :class:`~esmpy.api.constants.FileFormat.SCRIP` grid. Therefore, when the :class:`~esmpy.api.mesh.Mesh` will be part of a conservative regridding operation, the ``convert_to_dual`` flag must be set to True to properly generate coordinates at the the cell corners. -A :class:`~ESMF.api.mesh.Mesh` may also be created with boolean flags to specify whether or not to -add an area property to the :class:`~ESMF.api.mesh.Mesh` ``add_user_area``, or to add a mask +A :class:`~esmpy.api.mesh.Mesh` may also be created with boolean flags to specify whether or not to +add an area property to the :class:`~esmpy.api.mesh.Mesh` ``add_user_area``, or to add a mask ``add_mask`` held by the NetCDF variable indicated in the optional argument, -``varname``. These argument are only valid for :class:`~ESMF.api.constants.FileFormat.UGRID` formatted files. -The mask generated for a :class:`~ESMF.api.mesh.Mesh` created from file will +``varname``. These argument are only valid for :class:`~esmpy.api.constants.FileFormat.UGRID` formatted files. +The mask generated for a :class:`~esmpy.api.mesh.Mesh` created from file will have 0 for the masked values and 1 for the unmasked values. ~~~~~~~~~~~~~~~ @@ -665,22 +665,22 @@ Grids from File ~~~~~~~~~~~~~~~ A number of optional boolean arguments are also supported to create a -structured :class:`~ESMF.api.grid.Grid` from a file. These include ``is_sphere`` to indicate whether +structured :class:`~esmpy.api.grid.Grid` from a file. These include ``is_sphere`` to indicate whether the grid is spherical or regional, ``add_corner_stagger`` to add the corner -stagger information to the :class:`~ESMF.api.grid.Grid` for conservative regridding, and +stagger information to the :class:`~esmpy.api.grid.Grid` for conservative regridding, and ``add_user_area`` to specify whether to read in the cell area from the NetCDF file or to calculate them. -For :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` formated files +For :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` formated files there is the ``add_mask`` optional argument to add a mask held by the NetCDF variable indicated in optional argument, ``varname``, and the ``coord_names`` argument to specify the longitude -and latitude variable names in a :class:`~ESMF.api.constants.FileFormat.GRIDSPEC` file containing multiple sets of +and latitude variable names in a :class:`~esmpy.api.constants.FileFormat.GRIDSPEC` file containing multiple sets of coordinates. -For :class:`~ESMF.api.constants.FileFormat.SCRIP` formated files the integer array ``grid_imask`` is used to mask out grid cells which should not participate in the regridding. +For :class:`~esmpy.api.constants.FileFormat.SCRIP` formated files the integer array ``grid_imask`` is used to mask out grid cells which should not participate in the regridding. -The mask generated for a :class:`~ESMF.api.grid.Grid` created from +The mask generated for a :class:`~esmpy.api.grid.Grid` created from file (any format) will have 0 for the masked values and 1 for the unmasked values. @@ -694,20 +694,20 @@ More information can be found on these options in the `ESMF Reference Manual `_. -====================================================== =============================================== -Class Description -====================================================== =============================================== -:class:`~ESMF.api.constants.RegridMethod.BILINEAR` Linear regridding in two dimensions -:class:`~ESMF.api.constants.RegridMethod.PATCH` Higher-order least squares method -:class:`~ESMF.api.constants.RegridMethod.NEAREST_STOD` Nearest source point used for each destination -:class:`~ESMF.api.constants.RegridMethod.NEAREST_DTOS` Nearest destination point used for each source -:class:`~ESMF.api.constants.RegridMethod.CONSERVE` First-order conservative -:class:`~ESMF.api.constants.RegridMethod.CONSERVE_2ND` Second-order conservative -:class:`~ESMF.api.constants.NormType` Normalization options for integral conservation -:class:`~ESMF.api.constants.LineType` Line types for spherical and Cartesian space -:class:`~ESMF.api.constants.UnmappedAction` Unmapped destination point handling options -:class:`~ESMF.api.constants.CoordSys` Spherical grids and pole handling -====================================================== =============================================== +======================================================= =============================================== +Class Description +======================================================= =============================================== +:class:`~esmpy.api.constants.RegridMethod.BILINEAR` Linear regridding in two dimensions +:class:`~esmpy.api.constants.RegridMethod.PATCH` Higher-order least squares method +:class:`~esmpy.api.constants.RegridMethod.NEAREST_STOD` Nearest source point used for each destination +:class:`~esmpy.api.constants.RegridMethod.NEAREST_DTOS` Nearest destination point used for each source +:class:`~esmpy.api.constants.RegridMethod.CONSERVE` First-order conservative +:class:`~esmpy.api.constants.RegridMethod.CONSERVE_2ND` Second-order conservative +:class:`~esmpy.api.constants.NormType` Normalization options for integral conservation +:class:`~esmpy.api.constants.LineType` Line types for spherical and Cartesian space +:class:`~esmpy.api.constants.UnmappedAction` Unmapped destination point handling options +:class:`~esmpy.api.constants.CoordSys` Spherical grids and pole handling +======================================================= =============================================== ~~~~~~~~~~~~~~~~~~ Great Circle Cells @@ -737,21 +737,21 @@ Masking ------- .. _masking: -Masking is the process whereby parts of a :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` can be marked to be ignored -during an operation, such as when they are used in regridding. Masking can be used on a :class:`~ESMF.api.field.Field` +Masking is the process whereby parts of a :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` can be marked to be ignored +during an operation, such as when they are used in regridding. Masking can be used on a :class:`~esmpy.api.field.Field` created from a regridding source to indicate that certain portions should not be used to generate regridded data. This is useful, for example, if a portion of the source contains unusable values. -Masking can also be used on a :class:`~ESMF.api.field.Field` created from a regridding destination to indicate that a certain +Masking can also be used on a :class:`~esmpy.api.field.Field` created from a regridding destination to indicate that a certain portion should not receive regridded data. This is useful, for example, when part of the destination isn't being used (e.g. the land portion of an ocean grid). -The user may mask out points in the source :class:`~ESMF.api.field.Field` or destination :class:`~ESMF.api.field.Field` or both. To do masking the user -sets mask information in the :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, or :class:`~ESMF.api.locstream.LocStream` upon -which the :class:`Fields ` passed into the :class:`~ESMF.api.regrid.Regrid` call are built. The ``src_mask_values`` and +The user may mask out points in the source :class:`~esmpy.api.field.Field` or destination :class:`~esmpy.api.field.Field` or both. To do masking the user +sets mask information in the :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, or :class:`~esmpy.api.locstream.LocStream` upon +which the :class:`Fields ` passed into the :class:`~esmpy.api.regrid.Regrid` call are built. The ``src_mask_values`` and ``dst_mask_values`` arguments to that call can then be used to specify which values in that mask information indicate that a location should be masked out. For example, if ``dst_mask_values`` is set to [1,2], then any -location that has a value of 1 or 2 in the mask information of the :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` upon which -the destination :class:`~ESMF.api.field.Field` is built will be masked out. +location that has a value of 1 or 2 in the mask information of the :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` upon which +the destination :class:`~esmpy.api.field.Field` is built will be masked out. Masking behavior differs slightly between regridding methods. For non-conservative regridding methods (e.g. bilinear or high-order patch), masking is done on points. For these methods, masking a destination @@ -763,28 +763,29 @@ Masking a destination cell means that the cell won't participate in regridding. Similarly, masking a source cell means that the cell won't participate in regridding. For any type of interpolation method (conservative or non-conservative) the masking is set on the location upon which the -:class:`Fields ` passed into the regridding call are built. -For example, if :class:`Fields ` built on -:class:`StaggerLoc.CENTER ` are passed into -:class:`~ESMF.api.regrid.Regrid` -then the masking should also be set on :class:`StaggerLoc.CENTER `. - -The mask generated for a :class:`~ESMF.api.grid.Grid`, -:class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` created +:class:`Fields ` passed into the regridding call are built. +For example, if :class:`Fields ` built on +:class:`StaggerLoc.CENTER ` are passed into +:class:`~esmpy.api.regrid.Regrid` +then the masking should also be set on :class:`StaggerLoc.CENTER `. + +The mask generated for a :class:`~esmpy.api.grid.Grid`, +:class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` created from file will have 0 for the masked values and 1 for the unmasked values. -.. Note:: The :class:`Region.SELECT ` flag to the -``zero_region`` parameter of :class:`~ESMF.api.regrid.Regrid` can be used to -maintain :class:`Fields ` values on locations that do not +.. Note:: The :class:`Region.SELECT ` flag to the +``zero_region`` parameter of :class:`~esmpy.api.regrid.Regrid` can be used to +maintain :class:`Fields ` values on locations that do not participate in the regridding operation. This is useful when setting an uninitialized value to help identify masked locations within the -:class:`Fields ` data. +:class:`Fields ` data. + -------------------------- Numpy Slicing and Indexing -------------------------- -Numpy arrays are used to represent :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` and :class:`~ESMF.api.locstream.LocStream` coordinates and :class:`~ESMF.api.field.Field` data, +Numpy arrays are used to represent :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` and :class:`~esmpy.api.locstream.LocStream` coordinates and :class:`~esmpy.api.field.Field` data, among other things. Standard numpy conventions for array indexing and slicing can be expected. There are some exceptions when it comes to fancy indexing, index arrays, and multi-dimensional slicing. Significant effort has @@ -795,9 +796,9 @@ It is very important to remember that all indexing and slicing operations apply **ONLY** to the ESMPy level objects, and these operations do not propagate down to the lower-level Fortran- and C-based representations of the ESMF objects. One example of where this could come up is when passing -a :class:`~ESMF.api.field.Field` slice into regridding. The entire original :class:`~ESMF.api.field.Field` will still be run +a :class:`~esmpy.api.field.Field` slice into regridding. The entire original :class:`~esmpy.api.field.Field` will still be run through the ESMF regridding engine, and only the appropriate portion of -the :class:`~ESMF.api.field.Field` slice will be updated with the regridded values. +the :class:`~esmpy.api.field.Field` slice will be updated with the regridded values. ~~~~~~~~~~~~~~~~~~ Dimension Ordering @@ -815,9 +816,9 @@ Dimension Ordering .. code:: In [1]: import numpy as np - ...: import ESMF + ...: import esmpy ...: - ...: grid = ESMF.Grid(np.array([3,4]), staggerloc=ESMF.StaggerLoc.CENTER) + ...: grid = esmpy.Grid(np.array([3,4]), staggerloc=esmpy.StaggerLoc.CENTER) ...: ...: gridLon = grid.get_coords(0) ...: gridLat = grid.get_coords(1) @@ -831,7 +832,7 @@ Dimension Ordering ...: gridLat[:] = latm ...: - In [2]: grid.coords[ESMF.StaggerLoc.CENTER][0].shape + In [2]: grid.coords[esmpy.StaggerLoc.CENTER][0].shape Out[2]: (3, 4) In [3]: lon.shape @@ -840,19 +841,19 @@ Dimension Ordering In [4]: lat.shape Out[4]: (4,) - In [5]: grid.coords[ESMF.StaggerLoc.CENTER][0] + In [5]: grid.coords[esmpy.StaggerLoc.CENTER][0] Out[5]: array([[-120., -120., -120., -120.], [ 0., 0., 0., 0.], [ 120., 120., 120., 120.]]) - In [6]: grid.coords[ESMF.StaggerLoc.CENTER][1] + In [6]: grid.coords[esmpy.StaggerLoc.CENTER][1] Out[6]: array([[-67.5, -22.5, 22.5, 67.5], [-67.5, -22.5, 22.5, 67.5], [-67.5, -22.5, 22.5, 67.5]]) - In [7]: field = ESMF.Field(grid, ndbounds=[10]) # create a Field with a time dimension + In [7]: field = esmpy.Field(grid, ndbounds=[10]) # create a Field with a time dimension In [8]: field.data.shape Out[8]: (3, 4, 10) @@ -870,15 +871,15 @@ environment to be utilized by the ESMPy user with little use of specialized parallel programming techniques. ESMPy objects will be distributed across the available computing resources with -no additional parameters required. The :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, :class:`~ESMF.api.locstream.LocStream`, and :class:`~ESMF.api.field.Field` classes +no additional parameters required. The :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, :class:`~esmpy.api.locstream.LocStream`, and :class:`~esmpy.api.field.Field` classes will all be transparently "parallelized" with no need for user calls to a -message passing interface. Likewise, the :class:`~ESMF.api.regrid.Regrid` class will compute and apply +message passing interface. Likewise, the :class:`~esmpy.api.regrid.Regrid` class will compute and apply the interpolation weights using all available computing resources with no need for user intervention. -However, it is useful to remember that resulting :class:`~ESMF.api.field.Field` values will only be +However, it is useful to remember that resulting :class:`~esmpy.api.field.Field` values will only be accessible on certain PETs. The mpi4py package may be necessary for post -processing tasks that require access to global :class:`~ESMF.api.field.Field` values. +processing tasks that require access to global :class:`~esmpy.api.field.Field` values. ~~~~~~~~~~~~~~~~~~~~ mpirun vs. MPI.Spawn diff --git a/src/addon/ESMPy/doc/conf.py b/src/addon/ESMPy/doc/conf.py index f14df17791..3d482edae5 100644 --- a/src/addon/ESMPy/doc/conf.py +++ b/src/addon/ESMPy/doc/conf.py @@ -18,7 +18,7 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('../src')) -import ESMF +import esmpy # -- General configuration ----------------------------------------------------- @@ -58,7 +58,7 @@ # built documents. # # The full version, including alpha/beta/rc tags. -release = ESMF.__release__ +release = esmpy.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/addon/ESMPy/doc/examples.rst b/src/addon/ESMPy/doc/examples.rst index 4363274b6a..06e8c522ec 100644 --- a/src/addon/ESMPy/doc/examples.rst +++ b/src/addon/ESMPy/doc/examples.rst @@ -13,57 +13,57 @@ Regridding Helper Functions --------------------------- The following code snippets demonstrate how to build all of the pieces -necessary to regrid data between :class:`Fields ` built on -:class:`Grids `, :class:`Meshes ` -and :class:`LocStreams `. +necessary to regrid data between :class:`Fields ` built on +:class:`Grids `, :class:`Meshes ` +and :class:`LocStreams `. ~~~~~~~~~~~~~~~~ LocStream Create ~~~~~~~~~~~~~~~~ -.. literalinclude:: ../src/ESMF/util/locstream_utilities.py +.. literalinclude:: ../src/esmpy/util/locstream_utilities.py :pyobject: create_locstream_spherical_16 ~~~~~~~~~~~~~~~~~~~~~~~~~ LocStream Create Parallel ~~~~~~~~~~~~~~~~~~~~~~~~~ -.. literalinclude:: ../src/ESMF/util/locstream_utilities.py +.. literalinclude:: ../src/esmpy/util/locstream_utilities.py :pyobject: create_locstream_spherical_16_parallel ~~~~~~~~~~~~~~~~ Create a 2D Grid ~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: grid_create_from_coordinates ~~~~~~~~~~~~~~~~ Create a 3D Grid ~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: grid_create_from_coordinates_3d ~~~~~~~~~~~~~~~~~~~~~~ Create a Periodic Grid ~~~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: grid_create_from_coordinates_periodic ~~~~~~~~~~~~~~~~~~~~~~~ Create a 5 Element Mesh ~~~~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/mesh_utilities.py + .. literalinclude:: ../src/esmpy/util/mesh_utilities.py :pyobject: mesh_create_5 ~~~~~~~~~~~~~~ Create a Field ~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/test/test_api/test_field.py + .. literalinclude:: ../src/esmpy/test/test_api/test_field.py :pyobject: TestField.create_field @@ -71,7 +71,7 @@ Create a Field Initialize an Analytic Field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: initialize_field_grid_periodic @@ -79,7 +79,7 @@ Initialize an Analytic Field Run ESMPy Regridding ~~~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/test/test_api/test_regrid.py + .. literalinclude:: ../src/esmpy/test/test_api/test_regrid.py :pyobject: TestRegrid.run_regridding @@ -87,7 +87,7 @@ Run ESMPy Regridding Compute Field Mass ~~~~~~~~~~~~~~~~~~ - .. literalinclude:: ../src/ESMF/util/grid_utilities.py + .. literalinclude:: ../src/esmpy/util/grid_utilities.py :pyobject: compute_mass_grid @@ -96,9 +96,9 @@ Regridding ---------- The following stand alone scripts demonstrate how to use regridding between -:class:`Fields ` built on -:class:`Grids `, :class:`Meshes ` -and :class:`LocStreams `. These scripts +:class:`Fields ` built on +:class:`Grids `, :class:`Meshes ` +and :class:`LocStreams `. These scripts can be run in serial or parallel with no modification. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/addon/ESMPy/doc/field.rst b/src/addon/ESMPy/doc/field.rst index 6b1f42fc60..f1644ce199 100644 --- a/src/addon/ESMPy/doc/field.rst +++ b/src/addon/ESMPy/doc/field.rst @@ -2,7 +2,7 @@ Field ~~~~~ -.. autoclass:: ESMF.api.field.Field +.. autoclass:: esmpy.api.field.Field :members: copy, destroy, get_area, read, data, grid, lower_bounds, name, ndbounds, rank, staggerloc, type, upper_bounds, xd diff --git a/src/addon/ESMPy/doc/grid.rst b/src/addon/ESMPy/doc/grid.rst index f6f0b4249f..e399592494 100644 --- a/src/addon/ESMPy/doc/grid.rst +++ b/src/addon/ESMPy/doc/grid.rst @@ -2,7 +2,7 @@ Grid ~~~~ -.. autoclass:: ESMF.api.grid.Grid +.. autoclass:: esmpy.api.grid.Grid :members: add_coords, add_item, copy, destroy, get_coords, get_item, area, areatype, coords, coord_sys, has_corners, lower_bounds, mask, max_index, num_peri_dims, periodic_dim, pole_dim, diff --git a/src/addon/ESMPy/doc/install.rst b/src/addon/ESMPy/doc/install.rst index 40a02896ff..dbd79dd29a 100644 --- a/src/addon/ESMPy/doc/install.rst +++ b/src/addon/ESMPy/doc/install.rst @@ -9,12 +9,12 @@ Requirements The following packages are *required* to work with ESMPy: * `ESMF installation `_ -* `python `_ +* `python `_, minimum version 3.7 * `numpy `_ The following packages are *optional*: -* ESMF installation with NetCDF - required to create :class:`Grids ` and :class:`Meshes ` from file +* ESMF installation with NetCDF - required to create :class:`Grids ` and :class:`Meshes ` from file - NetCDF must be built as a shared library for ESMPy installation to succeed * `mpi4py `_- python bindings to MPI, needed to run some of the parallel regridding examples * `pytest `_ - for testing @@ -27,7 +27,7 @@ The ESMPy source code can be downloaded from the `ESMF git repository `_. The `ESMF User's Guide `_ -contains information on building and installing ESMF. +contains information on building and installing esmpy. The `ESMF Reference Manual `_ contains information on the architecture of ESMF, example code, and details of the API (Application Programming @@ -88,7 +88,7 @@ To use ESMPy in an external program, import it with: .. code:: - import ESMF + import esmpy ---------- Validation @@ -110,13 +110,11 @@ greater test coverage is desired: make test_examples - make test_regrid_from_file - make test_unit_parallel make test_examples_parallel - - make test_regrid_from_file_parallel + + make test_regrid_from_file .. Note:: @@ -136,16 +134,16 @@ to ESMF offline and integrated regridding capabilities. - ESMPy cannot use an ESMF installation that is built with external LAPACK support. - Coordinates cannot be retrieved from the elements of a - :class:`~ESMF.api.mesh.Mesh`. This can affect the ability to set - :class:`~ESMF.api.field.Field` values on a source :class:`~ESMF.api.mesh.Mesh` + :class:`~esmpy.api.mesh.Mesh`. This can affect the ability to set + :class:`~esmpy.api.field.Field` values on a source :class:`~esmpy.api.mesh.Mesh` created from file when using conservative regridding. -- Multi-tile :class:`~ESMF.api.grid.Grid` support is limited to cubed-sphere +- Multi-tile :class:`~esmpy.api.grid.Grid` support is limited to cubed-sphere grids created on 6 processors. A cubed-sphere grid can be created on any number of processors, but only when it is created on 6 processors will the coordinates be retrievable for the entire object. A - :class:`~ESMF.api.field.Field` created from a cubed-sphere - :class:`~ESMF.api.grid.Grid` cannot be written to file in parallel. -- There is no ``FieldBundle`` class, only single :class:`Fields `. + :class:`~esmpy.api.field.Field` created from a cubed-sphere + :class:`~esmpy.api.grid.Grid` cannot be written to file in parallel. +- There is no ``FieldBundle`` class, only single :class:`Fields `. Testing related: diff --git a/src/addon/ESMPy/doc/intro.rst b/src/addon/ESMPy/doc/intro.rst index dd618cfc8c..ce4ee2b2ca 100644 --- a/src/addon/ESMPy/doc/intro.rst +++ b/src/addon/ESMPy/doc/intro.rst @@ -2,7 +2,7 @@ Overview -------- -.. automodule:: ESMF +.. automodule:: esmpy --------------- Important Links @@ -28,4 +28,3 @@ Information on these can be found in the `_. Please contact esmf_support@ucar.edu with any questions or problems. - diff --git a/src/addon/ESMPy/doc/locstream.rst b/src/addon/ESMPy/doc/locstream.rst index 1a0f414a12..79a784a206 100644 --- a/src/addon/ESMPy/doc/locstream.rst +++ b/src/addon/ESMPy/doc/locstream.rst @@ -2,5 +2,5 @@ LocStream ~~~~~~~~~ -.. autoclass:: ESMF.api.locstream.LocStream +.. autoclass:: esmpy.api.locstream.LocStream :members: copy, destroy, lower_bounds, name, rank, size, upper_bounds diff --git a/src/addon/ESMPy/doc/manager.rst b/src/addon/ESMPy/doc/manager.rst index fc28fd9656..5b3fa31648 100644 --- a/src/addon/ESMPy/doc/manager.rst +++ b/src/addon/ESMPy/doc/manager.rst @@ -2,5 +2,5 @@ Manager ~~~~~~~ -.. autoclass:: ESMF.api.esmpymanager.Manager +.. autoclass:: esmpy.api.esmpymanager.Manager :members: local_pet, moab, pet_count, barrier, set_moab \ No newline at end of file diff --git a/src/addon/ESMPy/doc/mesh.rst b/src/addon/ESMPy/doc/mesh.rst index 28b6a4f546..7c2b38399e 100644 --- a/src/addon/ESMPy/doc/mesh.rst +++ b/src/addon/ESMPy/doc/mesh.rst @@ -2,6 +2,6 @@ Mesh ~~~~ -.. autoclass:: ESMF.api.mesh.Mesh +.. autoclass:: esmpy.api.mesh.Mesh :members: copy, destroy, add_elements, add_nodes, free_memory, get_coords, area, coords, coord_sys, mask, rank, size, size_owned \ No newline at end of file diff --git a/src/addon/ESMPy/doc/regrid.rst b/src/addon/ESMPy/doc/regrid.rst index 9fe086690f..f647deb5cf 100644 --- a/src/addon/ESMPy/doc/regrid.rst +++ b/src/addon/ESMPy/doc/regrid.rst @@ -2,5 +2,5 @@ Regrid ~~~~~~ -.. autoclass:: ESMF.api.regrid.Regrid +.. autoclass:: esmpy.api.regrid.Regrid :members: copy, destroy, __call__, get_factors, get_weights_dict diff --git a/src/addon/ESMPy/doc/regridfromfile.rst b/src/addon/ESMPy/doc/regridfromfile.rst index 66d9ea9705..ed5af263f9 100644 --- a/src/addon/ESMPy/doc/regridfromfile.rst +++ b/src/addon/ESMPy/doc/regridfromfile.rst @@ -2,5 +2,5 @@ RegridFromFile ~~~~~~~~~~~~~~ -.. autoclass:: ESMF.api.regrid.RegridFromFile +.. autoclass:: esmpy.api.regrid.RegridFromFile :members: copy, destroy, __call__ diff --git a/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py b/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py index c5cc0a3672..0544e036dc 100644 --- a/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py +++ b/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py @@ -7,46 +7,46 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging when debug=True -mg = ESMF.Manager(debug=False) +mg = esmpy.Manager(debug=False) -# if ESMF.pet_count() != 6: +# if esmpy.pet_count() != 6: # print ("ESMPy cubed sphere regridding example requires 6 processors") # import sys; sys.exit(0) grid1 = "examples/data/ll1deg_grid.nc" # Create a cubed sphere grid with 20 elements per tile -srcgrid = ESMF.Grid(tilesize=20, name="cubed_sphere") +srcgrid = esmpy.Grid(tilesize=20, name="cubed_sphere") # create an regular lat lon grid from file -dstgrid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) +dstgrid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) # create a field on the center stagger locations of the source grid -srcfield = ESMF.Field(srcgrid, name='srcfield', staggerloc=ESMF.StaggerLoc.CENTER) -srcfracfield = ESMF.Field(srcgrid, name='srcfracfield', staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(srcgrid, name='srcfield', staggerloc=esmpy.StaggerLoc.CENTER) +srcfracfield = esmpy.Field(srcgrid, name='srcfracfield', staggerloc=esmpy.StaggerLoc.CENTER) # create a field on the center stagger locations of the destination grid -dstfield = ESMF.Field(dstgrid, name='dstfield', staggerloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(dstgrid, name='xctfield', staggerloc=ESMF.StaggerLoc.CENTER) -dstfracfield = ESMF.Field(dstgrid, name='dstfracfield', staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(dstgrid, name='dstfield', staggerloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(dstgrid, name='xctfield', staggerloc=esmpy.StaggerLoc.CENTER) +dstfracfield = esmpy.Field(dstgrid, name='dstfracfield', staggerloc=esmpy.StaggerLoc.CENTER) # initialize the fields [lon,lat] = [0, 1] deg2rad = 3.14/180. -gridLon = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridLat = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridLon = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridLat = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) x = numpy.cos(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) y = numpy.sin(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) @@ -54,8 +54,8 @@ srcfield.data[...] = 200.0 + x + y + z -gridLon = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridLat = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridLon = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridLat = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) x = numpy.cos(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) y = numpy.sin(numpy.radians(gridLon))*numpy.sin(numpy.radians(90-gridLat)) @@ -68,18 +68,18 @@ # write regridding weights to file import os filename = "esmpy_example_weight_file_cs.nc" -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: if os.path.isfile(os.path.join(os.getcwd(), filename)): os.remove(os.path.join(os.getcwd(), filename)) mg.barrier() -regrid = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) +regrid = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) mg.barrier() -regrid = ESMF.RegridFromFile(srcfield, dstfield, filename=filename) +regrid = esmpy.RegridFromFile(srcfield, dstfield, filename=filename) # do the regridding from source to destination field mg.barrier() @@ -97,13 +97,13 @@ maxrelerr = numpy.max(numpy.abs(dstfield.data - xctfield.data) / numpy.abs(xctfield.data)) # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) maxrelerr = helpers.reduce_val(maxrelerr, op=constants.Reduce.MAX) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy cubed sphere regridding example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/exampletest.py index d82f2e56ad..7ec3c92018 100644 --- a/src/addon/ESMPy/examples/exampletest.py +++ b/src/addon/ESMPy/examples/exampletest.py @@ -6,14 +6,14 @@ import pytest -from ESMF.test.base import TestBase, attr, SkipTest -import ESMF.api.constants as constants +from esmpy.test.base import TestBase, attr, SkipTest +import esmpy.api.constants as constants class TestExamples(TestBase): # '0' in the name is so it is run first def test_0_examples_dryrun(self): - from ESMF.util.cache_data import cache_data_files + from esmpy.util.cache_data import cache_data_files cache_data_files() def test_helloworld(self): diff --git a/src/addon/ESMPy/examples/exampletestdryrun.py b/src/addon/ESMPy/examples/exampletestdryrun.py index 8484ede406..7e8e5e304b 100644 --- a/src/addon/ESMPy/examples/exampletestdryrun.py +++ b/src/addon/ESMPy/examples/exampletestdryrun.py @@ -6,10 +6,10 @@ import pytest -from ESMF.test.base import TestBase, attr +from esmpy.test.base import TestBase, attr class TestExamplesDryrun(TestBase): def test_examples_dryrun(self): - from ESMF.util.cache_data import cache_data_files + from esmpy.util.cache_data import cache_data_files cache_data_files() diff --git a/src/addon/ESMPy/examples/field_read.py b/src/addon/ESMPy/examples/field_read.py index c69060e989..d09e536606 100644 --- a/src/addon/ESMPy/examples/field_read.py +++ b/src/addon/ESMPy/examples/field_read.py @@ -7,45 +7,45 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "so_Omon_GISS-E2.nc")) # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -import ESMF +import esmpy # This call enables debug logging -esmpy = ESMF.Manager(debug=True) +esmpy.Manager(debug=True) datafile = "examples/data/so_Omon_GISS-E2.nc" gridfile = "examples/data/ll1deg_grid.nc" # Create a grid from a GRIDSPEC formatted file -srcgrid = ESMF.Grid(filename=datafile, filetype=ESMF.FileFormat.GRIDSPEC) +srcgrid = esmpy.Grid(filename=datafile, filetype=esmpy.FileFormat.GRIDSPEC) # Create a field on the center stagger locations of the source grid with # ungridded dimensions large enough to receive the data from file # dimensions follow Fortran index order: lon, lat, level, time -srcfield = ESMF.Field(srcgrid, staggerloc=ESMF.StaggerLoc.CENTER, ndbounds=[33, 2]) +srcfield = esmpy.Field(srcgrid, staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[33, 2]) # Read the field data into the data structure srcfield.read(filename=datafile, variable="so", timeslice=2) # Create a 1 degree latlon grid -dstgrid = ESMF.Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP) +dstgrid = esmpy.Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP) # Create a field on the center stagger locations of the latlon grid, also with # ungridded dimensions large enough to recieve the data from the source field -dstfield = ESMF.Field(dstgrid, name='dstfield', meshloc=ESMF.StaggerLoc.CENTER, +dstfield = esmpy.Field(dstgrid, name='dstfield', meshloc=esmpy.StaggerLoc.CENTER, ndbounds=[33, 2]) dstfield.data[...] = 1e20 # Create an object to regrid data from the source to the destination field -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # Do the regridding from source to destination field dstfield = regrid(srcfield, dstfield) # Output the results from one processor only -if ESMF.local_pet() == 0: print ("ESMPy Field Data Regridding Example Finished Successfully") \ No newline at end of file +if esmpy.local_pet() == 0: print ("ESMPy Field Data Regridding Example Finished Successfully") diff --git a/src/addon/ESMPy/examples/grid_create_peridim_mask.py b/src/addon/ESMPy/examples/grid_create_peridim_mask.py index bae26f869d..04553bf3b2 100644 --- a/src/addon/ESMPy/examples/grid_create_peridim_mask.py +++ b/src/addon/ESMPy/examples/grid_create_peridim_mask.py @@ -7,19 +7,19 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants gridfile = "examples/data/ll2.5deg_grid.nc" # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) # Create the source grid from memory with periodic dimension specified. [lat,lon] = [1,0] @@ -27,51 +27,51 @@ lats = numpy.arange( 0, 360, 360./70.) lons = numpy.arange(-90., 90.1, 180./140.) max_index = numpy.array([lons.size, lats.size]) -srcgrid = ESMF.Grid(max_index, coord_sys=ESMF.CoordSys.SPH_DEG, coord_typekind=ESMF.TypeKind.R4, +srcgrid = esmpy.Grid(max_index, coord_sys=esmpy.CoordSys.SPH_DEG, coord_typekind=esmpy.TypeKind.R4, num_peri_dims=1, periodic_dim=1, pole_dim=0) # Add coordinates to the source grid. -srcgrid.add_coords(staggerloc=[ESMF.StaggerLoc.CENTER]) +srcgrid.add_coords(staggerloc=[esmpy.StaggerLoc.CENTER]) # Get and set the source grid coordinates. gridCoordLat = srcgrid.get_coords(lat) gridCoordLon = srcgrid.get_coords(lon) -lons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] -lats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] +lons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] +lats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] gridCoordLat[...] = lats_par.reshape(1, lats_par.size) gridCoordLon[...] = lons_par.reshape(lons_par.size, 1) # Add a mask to the source grid -mask = srcgrid.add_item(ESMF.GridItem.MASK) +mask = srcgrid.add_item(esmpy.GridItem.MASK) dx=gridCoordLon-max_index[0]/2.0 dy=gridCoordLat-max_index[1]/2.0 mask[...] = 0 mask[numpy.where(numpy.sqrt(dx*dx+dy*dy) < 10.0)] = 2 # Create a field on the centers of the source grid with the mask applied. -srcfield = ESMF.Field(srcgrid, name="srcfield", staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(srcgrid, name="srcfield", staggerloc=esmpy.StaggerLoc.CENTER) srcfield.data[...] = 0 # Create a destination grid from a SCRIP formatted file. -dstgrid = ESMF.Grid(filename=gridfile, - filetype=ESMF.FileFormat.SCRIP) +dstgrid = esmpy.Grid(filename=gridfile, + filetype=esmpy.FileFormat.SCRIP) # Create a field on the centers of the destination grid. -dstfield = ESMF.Field(dstgrid, name="dstfield", staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(dstgrid, name="dstfield", staggerloc=esmpy.StaggerLoc.CENTER) missing_val = 1000 dstfield.data[...] = missing_val # Regrid from source grid to destination grid. -regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, +regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=numpy.array([2], dtype=numpy.int32), - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) -dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=esmpy.Region.SELECT) dgridCoordLat = dstgrid.get_coords(lat) dstmaskedlats = dgridCoordLat[numpy.where(dstfield.data == missing_val)] @@ -79,9 +79,9 @@ masked_values = dstmaskedlats.size # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: masked_values = helpers.reduce_val(dstmaskedlats.size, op=constants.Reduce.SUM) -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: assert (masked_values > 0) print ("Successfully created a grid with masking and switched periodic dimensions for regridding!") diff --git a/src/addon/ESMPy/examples/grid_locstream_regrid.py b/src/addon/ESMPy/examples/grid_locstream_regrid.py index 164d5c9211..5c2b6e3720 100644 --- a/src/addon/ESMPy/examples/grid_locstream_regrid.py +++ b/src/addon/ESMPy/examples/grid_locstream_regrid.py @@ -6,23 +6,23 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants -from ESMF.test.base import SkipTest +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants +from esmpy.test.base import SkipTest # This call enables debug logging -ESMF.Manager(debug=True) +esmpy.Manager(debug=True) -from ESMF.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel -coord_sys=ESMF.CoordSys.SPH_DEG +from esmpy.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel +coord_sys=esmpy.CoordSys.SPH_DEG domask=True -if ESMF.pet_count() == 1: +if esmpy.pet_count() == 1: locstream = create_locstream_spherical_16(coord_sys=coord_sys, domask=domask) else: if constants._ESMF_MPIRUN_NP != 4: @@ -31,13 +31,13 @@ locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) grid1 = "examples/data/ll1deg_grid.nc" -grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) +grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) # create a field -srcfield = ESMF.Field(grid, name='srcfield') +srcfield = esmpy.Field(grid, name='srcfield') -dstfield = ESMF.Field(locstream, name='dstfield') -xctfield = ESMF.Field(locstream, name='xctfield') +dstfield = esmpy.Field(locstream, name='dstfield') +xctfield = esmpy.Field(locstream, name='xctfield') # initialize the fields [x, y] = [0, 1] @@ -49,9 +49,9 @@ gridXCoord = locstream["ESMF:Lon"] gridYCoord = locstream["ESMF:Lat"] -if coord_sys == ESMF.CoordSys.SPH_DEG: +if coord_sys == esmpy.CoordSys.SPH_DEG: xctfield.data[...] = 10.0 + numpy.cos(gridXCoord * deg2rad) ** 2 + numpy.cos(2 * gridYCoord * deg2rad) -elif coord_sys == ESMF.CoordSys.SPH_RAD: +elif coord_sys == esmpy.CoordSys.SPH_RAD: xctfield.data[...] = 10.0 + numpy.cos(gridXCoord) ** 2 + numpy.cos(2 * gridYCoord) else: raise ValueError("coordsys value does not work in this example") @@ -63,13 +63,13 @@ if domask: dst_mask_values=numpy.array([0]) -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR, dst_mask_values=dst_mask_values) # do the regridding from source to destination field -dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # compute the mean relative error num_nodes = numpy.prod(xctfield.data.shape[:]) @@ -85,12 +85,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy Grid LocStream Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/hello_world.py b/src/addon/ESMPy/examples/hello_world.py index c5fa2dc174..412da2e2f3 100644 --- a/src/addon/ESMPy/examples/hello_world.py +++ b/src/addon/ESMPy/examples/hello_world.py @@ -1,6 +1,6 @@ -import ESMF +import esmpy # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) -print ("Hello ESMPy World from PET (processor) {0}!".format(ESMF.local_pet())) \ No newline at end of file +print ("Hello ESMPy World from PET (processor) {0}!".format(esmpy.local_pet())) \ No newline at end of file diff --git a/src/addon/ESMPy/examples/locstream_grid_regrid.py b/src/addon/ESMPy/examples/locstream_grid_regrid.py index 4d1019b409..159fcac2d4 100644 --- a/src/addon/ESMPy/examples/locstream_grid_regrid.py +++ b/src/addon/ESMPy/examples/locstream_grid_regrid.py @@ -6,26 +6,26 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants -from ESMF.test.base import TestBase, attr, SkipTest +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants +from esmpy.test.base import TestBase, attr, SkipTest # This call enables debug logging -ESMF.Manager(debug=True) +esmpy.Manager(debug=True) grid1 = "examples/data/ll1deg_grid.nc" -grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) +grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) -from ESMF.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel -coord_sys=ESMF.CoordSys.SPH_DEG +from esmpy.util.locstream_utilities import create_locstream_spherical_16, create_locstream_spherical_16_parallel +coord_sys=esmpy.CoordSys.SPH_DEG domask=True -if ESMF.pet_count() == 1: +if esmpy.pet_count() == 1: locstream = create_locstream_spherical_16(coord_sys=coord_sys, domask=domask) else: if constants._ESMF_MPIRUN_NP != 4: @@ -34,10 +34,10 @@ locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) # create a field -srcfield = ESMF.Field(locstream, name='srcfield') +srcfield = esmpy.Field(locstream, name='srcfield') -dstfield = ESMF.Field(grid, name='dstfield') -xctfield = ESMF.Field(grid, name='xctfield') +dstfield = esmpy.Field(grid, name='dstfield') +xctfield = esmpy.Field(grid, name='xctfield') # initialize the fields [x, y] = [0, 1] @@ -45,9 +45,9 @@ gridXCoord = locstream["ESMF:Lon"] gridYCoord = locstream["ESMF:Lat"] -if coord_sys == ESMF.CoordSys.SPH_DEG: +if coord_sys == esmpy.CoordSys.SPH_DEG: srcfield.data[...] = 10.0 + numpy.cos(gridXCoord * deg2rad) ** 2 + numpy.cos(2 * gridYCoord * deg2rad) -elif coord_sys == ESMF.CoordSys.SPH_RAD: +elif coord_sys == esmpy.CoordSys.SPH_RAD: srcfield.data[...] = 10.0 + numpy.cos(gridXCoord) ** 2 + numpy.cos(2 * gridYCoord) else: raise ValueError("coordsys value does not apply in this example") @@ -64,13 +64,13 @@ if domask: mask_values=numpy.array([0]) -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.NEAREST_DTOS, - unmapped_action=ESMF.UnmappedAction.ERROR, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.NEAREST_DTOS, + unmapped_action=esmpy.UnmappedAction.ERROR, src_mask_values=mask_values) # do the regridding from source to destination field -dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # compute the mean relative error from operator import mul @@ -87,12 +87,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy LocStream Grid Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/mesh_locstream_regrid.py b/src/addon/ESMPy/examples/mesh_locstream_regrid.py index e88425410c..e0841d06ca 100644 --- a/src/addon/ESMPy/examples/mesh_locstream_regrid.py +++ b/src/addon/ESMPy/examples/mesh_locstream_regrid.py @@ -1,18 +1,18 @@ # This example demonstrates how to regrid between a mesh and a locstream. -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants -from ESMF.test.base import TestBase, attr, SkipTest +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants +from esmpy.test.base import TestBase, attr, SkipTest # This call enables debug logging -# ESMF.Manager(debug=True) +# esmpy.Manager(debug=True) -from ESMF.util.mesh_utilities import mesh_create_5, mesh_create_5_parallel -from ESMF.util.locstream_utilities import create_locstream_16, create_locstream_16_parallel -if ESMF.pet_count() == 1: +from esmpy.util.mesh_utilities import mesh_create_5, mesh_create_5_parallel +from esmpy.util.locstream_utilities import create_locstream_16, create_locstream_16_parallel +if esmpy.pet_count() == 1: mesh, _, _, _, _, _ = mesh_create_5() locstream = create_locstream_16() else: @@ -23,11 +23,11 @@ locstream = create_locstream_16_parallel() # create a field -srcfield = ESMF.Field(mesh, name='srcfield')#, meshloc=ESMF.MeshLoc.ELEMENT) +srcfield = esmpy.Field(mesh, name='srcfield')#, meshloc=esmpy.MeshLoc.ELEMENT) # create a field on the locstream -dstfield = ESMF.Field(locstream, name='dstfield') -xctfield = ESMF.Field(locstream, name='xctfield') +dstfield = esmpy.Field(locstream, name='dstfield') +xctfield = esmpy.Field(locstream, name='xctfield') # initialize the fields [x, y] = [0, 1] @@ -45,8 +45,8 @@ # create an object to regrid data from the source to the destination field # TODO: this example seems to fail occasionally with UnmappedAction.ERROR, probably due to a tolerance issue - ask Bob -regrid = ESMF.Regrid(srcfield=srcfield, dstfield=dstfield, regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield=srcfield, dstfield=dstfield, regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # do the regridding from source to destination field dstfield = regrid(srcfield, dstfield) @@ -61,12 +61,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy Grid Mesh Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) diff --git a/src/addon/ESMPy/examples/mpi_spawn_regrid.py b/src/addon/ESMPy/examples/mpi_spawn_regrid.py index 9541f15ccd..ea838a121f 100644 --- a/src/addon/ESMPy/examples/mpi_spawn_regrid.py +++ b/src/addon/ESMPy/examples/mpi_spawn_regrid.py @@ -11,7 +11,7 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) # cache_data_file(os.path.join(DD, "mpas_uniform_10242_dual_counterclockwise.nc")) @@ -21,7 +21,7 @@ def regrid(): try: - import ESMF + import esmpy except: raise ImportError("ESMF is not available on this machine") @@ -29,45 +29,45 @@ def regrid(): grid2 = "examples/data/mpas_uniform_10242_dual_counterclockwise.nc" # Create a uniform global latlon grid from a SCRIP formatted file - grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP) + grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) # NOTE: corners are needed for conservative regridding - # grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP, + # grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP, # add_corner_stagger=True) # create a field on the center stagger locations of the source grid - srcfield = ESMF.Field(grid, name='srcfield', - staggerloc=ESMF.StaggerLoc.CENTER) + srcfield = esmpy.Field(grid, name='srcfield', + staggerloc=esmpy.StaggerLoc.CENTER) # create an ESMF formatted unstructured mesh with clockwise cells removed - mesh = ESMF.Mesh(filename=grid2, filetype=ESMF.FileFormat.ESMFMESH) + mesh = esmpy.Mesh(filename=grid2, filetype=esmpy.FileFormat.ESMFMESH) # create a field on the nodes of the destination mesh - dstfield = ESMF.Field(mesh, name='dstfield', meshloc=ESMF.MeshLoc.NODE) - xctfield = ESMF.Field(mesh, name='xctfield', meshloc=ESMF.MeshLoc.NODE) + dstfield = esmpy.Field(mesh, name='dstfield', meshloc=esmpy.MeshLoc.NODE) + xctfield = esmpy.Field(mesh, name='xctfield', meshloc=esmpy.MeshLoc.NODE) # NOTE: Field must be built on elements of Mesh for conservative regridding - # dstfield = ESMF.Field(mesh, name='dstfield', meshloc=ESMF.MeshLoc.ELEMENT) - # xctfield = ESMF.Field(mesh, name='xctfield', meshloc=ESMF.MeshLoc.ELEMENT) + # dstfield = esmpy.Field(mesh, name='dstfield', meshloc=esmpy.MeshLoc.ELEMENT) + # xctfield = esmpy.Field(mesh, name='xctfield', meshloc=esmpy.MeshLoc.ELEMENT) # initialize the fields [lon, lat] = [0, 1] deg2rad = 3.14159 / 180 - gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) - gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) + gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) + gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) srcfield.data[...] = 10.0 + (gridXCoord * deg2rad) ** 2 + ( gridYCoord * deg2rad) ** 2 - gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) - gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) + gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) + gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) xctfield.data[...] = 10.0 + (gridXCoord * deg2rad) ** 2 + ( gridYCoord * deg2rad) ** 2 dstfield.data[...] = 1e20 # create an object to regrid data from the source to the destination field - regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) # do the regridding from source to destination field dstfield = regrid(srcfield, dstfield) diff --git a/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb b/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb index 3a827a6134..dad0644086 100644 --- a/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb +++ b/src/addon/ESMPy/examples/notebooks/AdvancedRegridding.ipynb @@ -22,11 +22,11 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy as np\n", "\n", "# pull in some extra ESMF symbols for the sake of brevity\n", - "from ESMF import Grid, Mesh, LocStream, Field, Regrid, RegridFromFile" + "from esmpy import Grid, Mesh, LocStream, Field, Regrid, RegridFromFile" ] }, { @@ -51,7 +51,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"))" ] @@ -67,7 +67,7 @@ "gridfile = os.path.join(DD, \"ll1deg_grid.nc\")\n", "\n", "# Create a grid from a SCRIP formatted file\n", - "grid = Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)" + "grid = Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)" ] }, { @@ -84,11 +84,11 @@ "outputs": [], "source": [ "# Environment Canada CMIP5 climate data\n", - "grid_CanCM = ESMF.Grid(filename=os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"),\n", - " filetype=ESMF.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"tas\")\n", + "grid_CanCM = esmpy.Grid(filename=os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"),\n", + " filetype=esmpy.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"tas\")\n", "\n", "timeslice = 12\n", - "field = ESMF.Field(grid_CanCM, ndbounds=[timeslice])\n", + "field = esmpy.Field(grid_CanCM, ndbounds=[timeslice])\n", "\n", "field.read(filename=os.path.join(DD, \"tas_day_CanCM4_decadal2000_r2i1p1_20010101-20101231.nc\"), \n", " variable=\"tas\", timeslice=timeslice)" @@ -101,7 +101,7 @@ "outputs": [], "source": [ "# create a target field on latlon 1 degree grid, with space for time dimension\n", - "target_field = ESMF.Field(grid, ndbounds=[timeslice])" + "target_field = esmpy.Field(grid, ndbounds=[timeslice])" ] }, { @@ -125,8 +125,8 @@ "outputs": [], "source": [ "# generate weights, note that masks read from file generally use 0 to represent masked values and 1 for non masked\n", - "regrid = ESMF.Regrid(field, target_field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, dst_mask_values=[0])" + "regrid = esmpy.Regrid(field, target_field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, dst_mask_values=[0])" ] }, { @@ -136,8 +136,8 @@ "outputs": [], "source": [ "# also generation a reverse Regrid to bring the data back to the original grid (for error measurement)\n", - "regrid_T= ESMF.Regrid(target_field, field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, src_mask_values=[0])" + "regrid_T= esmpy.Regrid(target_field, field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, src_mask_values=[0])" ] }, { @@ -154,8 +154,8 @@ "outputs": [], "source": [ "# Apply the weights in the Regrid/Regrid_T to regrid data from field to target_field and then back to field\n", - "target_field = regrid(field, target_field, zero_region=ESMF.Region.SELECT)\n", - "solution_CanCM = regrid_T(target_field, field, zero_region=ESMF.Region.SELECT)" + "target_field = regrid(field, target_field, zero_region=esmpy.Region.SELECT)\n", + "solution_CanCM = regrid_T(target_field, field, zero_region=esmpy.Region.SELECT)" ] }, { @@ -248,8 +248,8 @@ "!{cmd}\n", "\n", "# generate weights and output them to a file\n", - "rf1 = ESMF.Regrid(field, target_field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, filename=weightfile)" + "rf1 = esmpy.Regrid(field, target_field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, filename=weightfile)" ] }, { @@ -292,8 +292,8 @@ "source": [ "# generate weights and output them to a file \n", "routehandlefile = \"CanCMtoLatLon1deg.rh\"\n", - "rf2 = ESMF.Regrid(field, target_field, regrid_method=ESMF.RegridMethod.CONSERVE, \n", - " unmapped_action=ESMF.UnmappedAction.IGNORE, rh_filename=routehandlefile)" + "rf2 = esmpy.Regrid(field, target_field, regrid_method=esmpy.RegridMethod.CONSERVE, \n", + " unmapped_action=esmpy.UnmappedAction.IGNORE, rh_filename=routehandlefile)" ] }, { @@ -302,8 +302,8 @@ "metadata": {}, "outputs": [], "source": [ - "rf1 = ESMF.RegridFromFile(field, target_field, filename=weightfile)\n", - "rf2 = ESMF.RegridFromFile(field, target_field, rh_filename=routehandlefile)" + "rf1 = esmpy.RegridFromFile(field, target_field, filename=weightfile)\n", + "rf2 = esmpy.RegridFromFile(field, target_field, rh_filename=routehandlefile)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb b/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb index 1786e289ba..24836d9864 100644 --- a/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb +++ b/src/addon/ESMPy/examples/notebooks/BasicRegridding.ipynb @@ -20,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy as np" ] }, @@ -55,7 +55,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"ll2.5deg_grid.nc\"))" ] @@ -73,10 +73,10 @@ "metadata": {}, "outputs": [], "source": [ - "srcgrid = ESMF.Grid(filename=os.path.join(DD, \"ll1deg_grid.nc\"),\n", - " filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)\n", - "dstgrid = ESMF.Grid(filename=os.path.join(DD, \"ll2.5deg_grid.nc\"), \n", - " filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)" + "srcgrid = esmpy.Grid(filename=os.path.join(DD, \"ll1deg_grid.nc\"),\n", + " filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)\n", + "dstgrid = esmpy.Grid(filename=os.path.join(DD, \"ll2.5deg_grid.nc\"), \n", + " filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)" ] }, { @@ -92,8 +92,8 @@ "metadata": {}, "outputs": [], "source": [ - "srcfield = ESMF.Field(srcgrid)\n", - "dstfield = ESMF.Field(dstgrid)" + "srcfield = esmpy.Field(srcgrid)\n", + "dstfield = esmpy.Field(dstgrid)" ] }, { @@ -125,7 +125,7 @@ "metadata": {}, "outputs": [], "source": [ - "regridS2D = ESMF.Regrid(srcfield, dstfield)" + "regridS2D = esmpy.Regrid(srcfield, dstfield)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb b/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb index cb2363b691..529a3b28df 100644 --- a/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb +++ b/src/addon/ESMPy/examples/notebooks/GridCellArea.ipynb @@ -25,8 +25,8 @@ ], "source": [ "import numpy as np\n", - "import ESMF\n", - "ESMF.__version__" + "import esmpy\n", + "esmpy.__version__" ] }, { @@ -84,9 +84,9 @@ "metadata": {}, "outputs": [], "source": [ - "sourcegrid = ESMF.Grid(np.array([20,20]), \n", - " staggerloc = ESMF.StaggerLoc.CENTER,\n", - " coord_sys = ESMF.CoordSys.SPH_DEG)\n", + "sourcegrid = esmpy.Grid(np.array([20,20]), \n", + " staggerloc = esmpy.StaggerLoc.CENTER,\n", + " coord_sys = esmpy.CoordSys.SPH_DEG)\n", "\n", "source_lon = sourcegrid.get_coords(0)\n", "source_lat = sourcegrid.get_coords(1)\n", @@ -106,12 +106,12 @@ "metadata": {}, "outputs": [], "source": [ - "sourcegrid.add_coords(staggerloc = ESMF.StaggerLoc.CORNER_VCENTER)\n", + "sourcegrid.add_coords(staggerloc = esmpy.StaggerLoc.CORNER_VCENTER)\n", "\n", "source_lat_b = sourcegrid.get_coords(coord_dim = 1, \n", - " staggerloc = ESMF.StaggerLoc.CORNER)\n", + " staggerloc = esmpy.StaggerLoc.CORNER)\n", "source_lon_b = sourcegrid.get_coords(coord_dim = 0, \n", - " staggerloc = ESMF.StaggerLoc.CORNER)\n", + " staggerloc = esmpy.StaggerLoc.CORNER)\n", "\n", "source_lon_b[...], source_lat_b[...] = np.meshgrid(lon_b, lat_b)" ] @@ -221,7 +221,7 @@ } ], "source": [ - "sourcegridareafield = ESMF.Field(sourcegrid)\n", + "sourcegridareafield = esmpy.Field(sourcegrid)\n", "sourcegridareafield.get_area()\n", "sourcegridareafield.data" ] diff --git a/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb b/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb index 26dfe8c341..ed244bfe6e 100644 --- a/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb +++ b/src/addon/ESMPy/examples/notebooks/GridMeshLocStreamField.ipynb @@ -24,7 +24,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy as np" ] }, @@ -50,7 +50,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"ne30np4_esmf.nc\"))\n", "cache_data_file(os.path.join(DD, \"so_Omon_GISS-E2.nc\"))" @@ -77,8 +77,8 @@ } ], "source": [ - "ESMF.Manager(debug=True)\n", - "print(ESMF.local_pet(), ESMF.pet_count())" + "esmpy.Manager(debug=True)\n", + "print(esmpy.local_pet(), esmpy.pet_count())" ] }, { @@ -105,8 +105,8 @@ "outputs": [], "source": [ "gridfile = \"ll1deg_grid.nc\"\n", - "grid = ESMF.Grid(filename=os.path.join(DD, gridfile),\n", - " filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True)" + "grid = esmpy.Grid(filename=os.path.join(DD, gridfile),\n", + " filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True)" ] }, { @@ -126,7 +126,7 @@ "# ESMPy follows ESMF/Fortran/Mathematics convention for indices in order lon, lat\n", "lon = 0\n", "lat = 1\n", - "print (grid.coords[ESMF.StaggerLoc.CENTER][lon].shape)" + "print (grid.coords[esmpy.StaggerLoc.CENTER][lon].shape)" ] }, { @@ -160,9 +160,9 @@ ], "source": [ "# Coordinates are stored as numpy arrays, basic slicing capabilites are available\n", - "print (type(grid.coords[ESMF.StaggerLoc.CENTER][lon]))\n", + "print (type(grid.coords[esmpy.StaggerLoc.CENTER][lon]))\n", "\n", - "print (grid.coords[ESMF.StaggerLoc.CENTER][lon][2:4])\n" + "print (grid.coords[esmpy.StaggerLoc.CENTER][lon][2:4])\n" ] }, { @@ -219,11 +219,11 @@ "outputs": [], "source": [ "max_index = np.array([360, 179])\n", - "grid = ESMF.Grid(max_index, staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.EDGE1, ESMF.StaggerLoc.EDGE2, ESMF.StaggerLoc.CORNER], \n", - " coord_sys=ESMF.CoordSys.SPH_DEG, \n", - " coord_typekind=ESMF.TypeKind.R4, \n", + "grid = esmpy.Grid(max_index, staggerloc=[esmpy.StaggerLoc.CENTER, esmpy.StaggerLoc.EDGE1, esmpy.StaggerLoc.EDGE2, esmpy.StaggerLoc.CORNER], \n", + " coord_sys=esmpy.CoordSys.SPH_DEG, \n", + " coord_typekind=esmpy.TypeKind.R4, \n", " num_peri_dims = 1,\n", - " pole_kind=[ESMF.PoleKind.MONOPOLE, ESMF.PoleKind.BIPOLE])\n", + " pole_kind=[esmpy.PoleKind.MONOPOLE, esmpy.PoleKind.BIPOLE])\n", "\n", "gridLonCenter = grid.get_coords(0)\n", "gridLatCenter = grid.get_coords(1)\n", @@ -291,7 +291,7 @@ "source": [ "# cubed-sphere grid is represented as an unstructured Mesh\n", "meshfile = \"ne30np4_esmf.nc\"\n", - "mesh = ESMF.Mesh(filename=os.path.join(DD, meshfile), filetype=ESMF.FileFormat.ESMFMESH)\n", + "mesh = esmpy.Mesh(filename=os.path.join(DD, meshfile), filetype=esmpy.FileFormat.ESMFMESH)\n", "# print(mesh)" ] }, @@ -358,7 +358,7 @@ "metadata": {}, "outputs": [], "source": [ - "meshinmem = ESMF.Mesh(parametric_dim=2, spatial_dim=2)\n", + "meshinmem = esmpy.Mesh(parametric_dim=2, spatial_dim=2)\n", "\n", "num_node = 12\n", "num_elem = 5\n", @@ -369,8 +369,8 @@ "nodeOwner = np.zeros(num_node)\n", "\n", "elemId = np.array([1,2,3,4,5])\n", - "elemType=np.array([ESMF.MeshElemType.QUAD,ESMF.MeshElemType.TRI,\n", - " ESMF.MeshElemType.TRI, 5, 6])\n", + "elemType=np.array([esmpy.MeshElemType.QUAD,esmpy.MeshElemType.TRI,\n", + " esmpy.MeshElemType.TRI, 5, 6])\n", " \n", "elemConn=np.array([0,1,4,3, 1,2,4, 2,5,4, 3,4,8,7,6, 4,5,11,10,9,8])\n", "\n", @@ -443,7 +443,7 @@ ], "source": [ "# locstreams can currently only be created in memory\n", - "locstream = ESMF.LocStream(16)\n", + "locstream = esmpy.LocStream(16)\n", "\n", "locstream[\"ESMF:X\"] = [0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0]\n", "locstream[\"ESMF:Y\"] = [0.0, 0.0, 0.0, 0.0, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 4.0, 4.0, 4.0, 4.0]\n", @@ -504,7 +504,7 @@ } ], "source": [ - "locstream = ESMF.LocStream(10, coord_sys=ESMF.CoordSys.SPH_RAD)\n", + "locstream = esmpy.LocStream(10, coord_sys=esmpy.CoordSys.SPH_RAD)\n", "\n", "locstream[\"ESMF:Lon\"] = np.linspace(0, 2*np.pi, 10).tolist()\n", "locstream[\"ESMF:Lat\"] = np.linspace(np.pi/-2.0, np.pi/2.0, 10).tolist()\n", @@ -596,9 +596,9 @@ } ], "source": [ - "field_grid = ESMF.Field(grid, name=\"field_grid\", typekind=ESMF.TypeKind.I8, staggerloc=ESMF.StaggerLoc.CORNER)\n", - "field_mesh = ESMF.Field(mesh, name=\"field_mesh\", typekind=ESMF.TypeKind.R4, meshloc=ESMF.MeshLoc.ELEMENT)\n", - "field_locs = ESMF.Field(locstream, name=\"field_locs\", typekind=ESMF.TypeKind.R4)\n", + "field_grid = esmpy.Field(grid, name=\"field_grid\", typekind=esmpy.TypeKind.I8, staggerloc=esmpy.StaggerLoc.CORNER)\n", + "field_mesh = esmpy.Field(mesh, name=\"field_mesh\", typekind=esmpy.TypeKind.R4, meshloc=esmpy.MeshLoc.ELEMENT)\n", + "field_locs = esmpy.Field(locstream, name=\"field_locs\", typekind=esmpy.TypeKind.R4)\n", "print(field_locs)" ] }, @@ -616,11 +616,11 @@ "outputs": [], "source": [ "# NASA-GISS sea water salinity data with 33 vertical layers and 2 timesteps\n", - "grid_so = ESMF.Grid(filename=os.path.join(DD, \"so_Omon_GISS-E2.nc\"),\n", - " filetype=ESMF.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"so\")\n", + "grid_so = esmpy.Grid(filename=os.path.join(DD, \"so_Omon_GISS-E2.nc\"),\n", + " filetype=esmpy.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname=\"so\")\n", "\n", "timeslice = 12\n", - "field_so = ESMF.Field(grid_so, ndbounds=[33, 2])\n", + "field_so = esmpy.Field(grid_so, ndbounds=[33, 2])\n", "\n", "field_so.read(filename=os.path.join(DD, \"so_Omon_GISS-E2.nc\"), \n", " variable=\"so\", timeslice=2)" diff --git a/src/addon/ESMPy/examples/notebooks/Periodic.ipynb b/src/addon/ESMPy/examples/notebooks/Periodic.ipynb index d25ea1f429..05c74f2ed6 100644 --- a/src/addon/ESMPy/examples/notebooks/Periodic.ipynb +++ b/src/addon/ESMPy/examples/notebooks/Periodic.ipynb @@ -16,7 +16,7 @@ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "import ESMF" + "import esmpy" ] }, { @@ -118,9 +118,9 @@ "metadata": {}, "outputs": [], "source": [ - "sourcegrid = ESMF.Grid(np.array([lon_in.size, lat_in.size]), \n", - " staggerloc = [ESMF.StaggerLoc.CENTER],\n", - " coord_sys = ESMF.CoordSys.SPH_DEG,\n", + "sourcegrid = esmpy.Grid(np.array([lon_in.size, lat_in.size]), \n", + " staggerloc = [esmpy.StaggerLoc.CENTER],\n", + " coord_sys = esmpy.CoordSys.SPH_DEG,\n", " num_peri_dims = 1)\n", "\n", "source_lon = sourcegrid.get_coords(0)\n", @@ -155,9 +155,9 @@ "metadata": {}, "outputs": [], "source": [ - "destgrid = ESMF.Grid(np.array([lon_out.size, lat_out.size]), \n", - " staggerloc = [ESMF.StaggerLoc.CENTER],\n", - " coord_sys = ESMF.CoordSys.SPH_DEG,\n", + "destgrid = esmpy.Grid(np.array([lon_out.size, lat_out.size]), \n", + " staggerloc = [esmpy.StaggerLoc.CENTER],\n", + " coord_sys = esmpy.CoordSys.SPH_DEG,\n", " num_peri_dims = 1)\n", "\n", "\n", @@ -173,8 +173,8 @@ "metadata": {}, "outputs": [], "source": [ - "sourcefield = ESMF.Field(sourcegrid)\n", - "destfield = ESMF.Field(destgrid)" + "sourcefield = esmpy.Field(sourcegrid)\n", + "destfield = esmpy.Field(destgrid)" ] }, { @@ -183,9 +183,9 @@ "metadata": {}, "outputs": [], "source": [ - "regrid_bi = ESMF.Regrid(sourcefield, destfield, \n", - " regrid_method = ESMF.RegridMethod.BILINEAR, \n", - " unmapped_action = ESMF.UnmappedAction.ERROR)" + "regrid_bi = esmpy.Regrid(sourcefield, destfield, \n", + " regrid_method = esmpy.RegridMethod.BILINEAR, \n", + " unmapped_action = esmpy.UnmappedAction.ERROR)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb b/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb index 5286787a27..88feeb6d8c 100644 --- a/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb +++ b/src/addon/ESMPy/examples/notebooks/ugrid_latlon_regrid.ipynb @@ -31,7 +31,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy" ] }, @@ -60,7 +60,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll1deg_grid.nc\"))\n", "# cache_data_file(os.path.join(DD, \"aggregAtlanticESTOFS.nc\"))\n", "os.system(\"wget https://www.dropbox.com/s/ke5mdukbjwyqaru/aggregAtlanticESTOFS.nc\")\n", @@ -82,7 +82,7 @@ "outputs": [], "source": [ "gridfile = \"ESMPy-data/ll1deg_grid.nc\"\n", - "grid = ESMF.Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP, is_sphere=True)" + "grid = esmpy.Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP, is_sphere=True)" ] }, { @@ -99,7 +99,7 @@ "outputs": [], "source": [ "meshfile = \"ESMPy-data/aggregAtlanticESTOFS.nc\"\n", - "mesh = ESMF.Mesh(filename=meshfile, filetype=ESMF.FileFormat.UGRID, meshname='adcirc_mesh')" + "mesh = esmpy.Mesh(filename=meshfile, filetype=esmpy.FileFormat.UGRID, meshname='adcirc_mesh')" ] }, { @@ -115,20 +115,20 @@ "metadata": {}, "outputs": [], "source": [ - "srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.NODE)\n", + "srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.NODE)\n", "\n", - "dstfield = ESMF.Field(grid, name='dstfield', staggerloc=ESMF.StaggerLoc.CENTER)\n", - "xctfield = ESMF.Field(grid, name='xctfield', staggerloc=ESMF.StaggerLoc.CENTER)\n", + "dstfield = esmpy.Field(grid, name='dstfield', staggerloc=esmpy.StaggerLoc.CENTER)\n", + "xctfield = esmpy.Field(grid, name='xctfield', staggerloc=esmpy.StaggerLoc.CENTER)\n", "\n", "[lon, lat] = [0, 1]\n", "\n", - "srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=ESMF.MeshLoc.NODE)\n", - "srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=ESMF.MeshLoc.NODE)\n", + "srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=esmpy.MeshLoc.NODE)\n", + "srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=esmpy.MeshLoc.NODE)\n", "srcfield.data[...] = 2.0 + numpy.cos(numpy.radians(srcgridYCoord)[...])**2 * \\\n", " numpy.cos(2.0*numpy.radians(srcgridXCoord)[...])\n", "\n", - "dstgridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER)\n", - "dstgridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER)\n", + "dstgridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER)\n", + "dstgridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER)\n", "xctfield.data[...] = 2.0 + numpy.cos(numpy.radians(dstgridYCoord)[...])**2 * \\\n", " numpy.cos(2.0*numpy.radians(dstgridXCoord)[...])\n", "\n", @@ -149,11 +149,11 @@ "metadata": {}, "outputs": [], "source": [ - "regrid = ESMF.Regrid(srcfield, dstfield,\n", - " regrid_method=ESMF.RegridMethod.BILINEAR,\n", - " unmapped_action=ESMF.UnmappedAction.IGNORE)\n", + "regrid = esmpy.Regrid(srcfield, dstfield,\n", + " regrid_method=esmpy.RegridMethod.BILINEAR,\n", + " unmapped_action=esmpy.UnmappedAction.IGNORE)\n", "\n", - "dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT)" + "dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT)" ] }, { @@ -258,7 +258,7 @@ "source": [ "dstfield.data[...] = uninitval\n", "\n", - "dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT)" + "dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT)" ] }, { diff --git a/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb b/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb index b31881f6b4..c5cf86c2a1 100644 --- a/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb +++ b/src/addon/ESMPy/examples/notebooks/ungridded_dimension_regrid.ipynb @@ -31,7 +31,7 @@ "metadata": {}, "outputs": [], "source": [ - "import ESMF\n", + "import esmpy\n", "import numpy" ] }, @@ -60,7 +60,7 @@ "DD = os.path.join(os.getcwd(), \"ESMPy-data\")\n", "if not os.path.isdir(DD):\n", " os.makedirs(DD)\n", - "from ESMF.util.cache_data import cache_data_file\n", + "from esmpy.util.cache_data import cache_data_file\n", "cache_data_file(os.path.join(DD, \"ll2.5deg_grid.nc\"))\n", "cache_data_file(os.path.join(DD, \"T42_grid.nc\"))\n", "print('Done.')" @@ -96,11 +96,11 @@ "metadata": {}, "outputs": [], "source": [ - "srcgrid = ESMF.Grid(filename=\"ESMPy-data/ll2.5deg_grid.nc\", \n", - " filetype=ESMF.FileFormat.SCRIP,\n", + "srcgrid = esmpy.Grid(filename=\"ESMPy-data/ll2.5deg_grid.nc\", \n", + " filetype=esmpy.FileFormat.SCRIP,\n", " add_corner_stagger=True)\n", - "dstgrid = ESMF.Grid(filename=\"ESMPy-data/T42_grid.nc\", \n", - " filetype=ESMF.FileFormat.SCRIP,\n", + "dstgrid = esmpy.Grid(filename=\"ESMPy-data/T42_grid.nc\", \n", + " filetype=esmpy.FileFormat.SCRIP,\n", " add_corner_stagger=True)" ] }, @@ -117,14 +117,14 @@ "metadata": {}, "outputs": [], "source": [ - "srcfield = ESMF.Field(srcgrid, name='srcfield',\n", - " staggerloc=ESMF.StaggerLoc.CENTER,\n", + "srcfield = esmpy.Field(srcgrid, name='srcfield',\n", + " staggerloc=esmpy.StaggerLoc.CENTER,\n", " ndbounds=[levels, time])\n", - "dstfield = ESMF.Field(dstgrid, name='dstfield',\n", - " staggerloc=ESMF.StaggerLoc.CENTER,\n", + "dstfield = esmpy.Field(dstgrid, name='dstfield',\n", + " staggerloc=esmpy.StaggerLoc.CENTER,\n", " ndbounds=[levels, time])\n", - "xctfield = ESMF.Field(dstgrid, name='xctfield',\n", - " staggerloc=ESMF.StaggerLoc.CENTER,\n", + "xctfield = esmpy.Field(dstgrid, name='xctfield',\n", + " staggerloc=esmpy.StaggerLoc.CENTER,\n", " ndbounds=[levels, time])" ] }, @@ -142,8 +142,8 @@ "outputs": [], "source": [ "[lon,lat] = [0, 1]\n", - "gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER)\n", - "gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER)\n", + "gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER)\n", + "gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER)\n", "\n", "deg2rad = 3.14159/180\n", "\n", @@ -169,8 +169,8 @@ "metadata": {}, "outputs": [], "source": [ - "gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER)\n", - "gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER)\n", + "gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER)\n", + "gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER)\n", "\n", "for timestep in range(time):\n", " for level in range(levels):\n", @@ -196,9 +196,9 @@ "metadata": {}, "outputs": [], "source": [ - "regrid = ESMF.Regrid(srcfield, dstfield,\n", - " regrid_method=ESMF.RegridMethod.CONSERVE,\n", - " unmapped_action=ESMF.UnmappedAction.ERROR)" + "regrid = esmpy.Regrid(srcfield, dstfield,\n", + " regrid_method=esmpy.RegridMethod.CONSERVE,\n", + " unmapped_action=esmpy.UnmappedAction.ERROR)" ] }, { diff --git a/src/addon/ESMPy/examples/read_write_weight_file.py b/src/addon/ESMPy/examples/read_write_weight_file.py index 4c779e72ec..836a2267ba 100644 --- a/src/addon/ESMPy/examples/read_write_weight_file.py +++ b/src/addon/ESMPy/examples/read_write_weight_file.py @@ -6,18 +6,18 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) # cache_data_file(os.path.join(DD, "mpas_uniform_10242_dual_counterclockwise.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -mg = ESMF.Manager(debug=True) +mg = esmpy.Manager(debug=True) # ESMPy uses Fortran style dimension ordering (as of November 2017) [lat,lon] = [1,0] @@ -25,17 +25,17 @@ # Create the source grid from memory with periodic dimension specified. lons = numpy.arange(5, 350.1, 10) lats = numpy.arange(-85, 85.1, 10) -srcgrid = ESMF.Grid(numpy.array([lons.size, lats.size]), - coord_sys=ESMF.CoordSys.SPH_DEG, - staggerloc=ESMF.StaggerLoc.CENTER, +srcgrid = esmpy.Grid(numpy.array([lons.size, lats.size]), + coord_sys=esmpy.CoordSys.SPH_DEG, + staggerloc=esmpy.StaggerLoc.CENTER, num_peri_dims=1, periodic_dim=0, pole_dim=1) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(lon) srcGridCoordLat = srcgrid.get_coords(lat) -slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] -slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] +slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] +slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = numpy.meshgrid(slons_par, slats_par, indexing='ij') @@ -46,17 +46,17 @@ # Create the dest grid from memory with periodic dimension specified. lons = numpy.arange(2.5, 357.6, 5) lats = numpy.arange(-87.5, 87.6, 5) -dstgrid = ESMF.Grid(numpy.array([lons.size, lats.size]), - coord_sys=ESMF.CoordSys.SPH_DEG, - staggerloc=ESMF.StaggerLoc.CENTER, +dstgrid = esmpy.Grid(numpy.array([lons.size, lats.size]), + coord_sys=esmpy.CoordSys.SPH_DEG, + staggerloc=esmpy.StaggerLoc.CENTER, num_peri_dims=1, periodic_dim=1, pole_dim=0) # Get and set the source grid coordinates. dstGridCoordLat = dstgrid.get_coords(lat) dstGridCoordLon = dstgrid.get_coords(lon) -dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] -dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] +dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] +dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = numpy.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -65,14 +65,14 @@ dstGridCoordLat[:] = latm # Create a field on the centers of the source grid with the mask applied. -srcfield = ESMF.Field(srcgrid, name="srcfield", staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(srcgrid, name="srcfield", staggerloc=esmpy.StaggerLoc.CENTER) # Create a field on the centers of the source grid with the mask applied. -dstfield = ESMF.Field(dstgrid, name="dstfield", staggerloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(dstgrid, name="xctfield", staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(dstgrid, name="dstfield", staggerloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(dstgrid, name="xctfield", staggerloc=esmpy.StaggerLoc.CENTER) -gridLon = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridLat = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridLon = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridLat = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) # wave = lambda x,k: numpy.sin(x*k*numpy.pi/180.0) # srcfield.data[...] = numpy.outer(wave(slons_par,3), wave(slats_par,3)) + 2 @@ -90,20 +90,20 @@ # write regridding weights to file filename = "esmpy_example_weight_file.nc" -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: import os if os.path.isfile( os.path.join(os.getcwd(), filename)): os.remove(os.path.join(os.getcwd(), filename)) mg.barrier() -regrid = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # # create a regrid object from file -regrid = ESMF.RegridFromFile(srcfield, dstfield, filename) +regrid = esmpy.RegridFromFile(srcfield, dstfield, filename) # calculate the regridding from source to destination field dstfield = regrid(srcfield, dstfield) @@ -118,12 +118,12 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes print ("ESMPy Grid Mesh Regridding Example") print (" interpolation mean relative error = {0}".format(meanrelerr)) @@ -132,7 +132,7 @@ os.remove(os.path.join(os.getcwd(), filename)) # set to 1 to output results -# if ESMF.pet_count() == 0: +# if esmpy.pet_count() == 0: # import matplotlib.pyplot as plt # fig = plt.figure(1, (15, 6)) # fig.suptitle('ESMPy Periodic Grids', fontsize=14, fontweight='bold') diff --git a/src/addon/ESMPy/examples/regrid_from_file.py b/src/addon/ESMPy/examples/regrid_from_file.py index 0af92b238f..f68fb8edb2 100644 --- a/src/addon/ESMPy/examples/regrid_from_file.py +++ b/src/addon/ESMPy/examples/regrid_from_file.py @@ -7,46 +7,46 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "so_Omon_GISS-E2.nc")) # cache_data_file(os.path.join(DD, "mpas_uniform_10242_dual_counterclockwise.nc")) import os -import ESMF +import esmpy # This call enables debug logging -# ESMF.Manager(debug=True) +# esmpy.Manager(debug=True) # Set up the DATADIR DATADIR = os.path.join(os.getcwd(), "examples/data") # Create a global grid from a GRIDSPEC formatted file -grid = ESMF.Grid(filename=os.path.join(DATADIR, "so_Omon_GISS-E2.nc"), - filetype=ESMF.FileFormat.GRIDSPEC) +grid = esmpy.Grid(filename=os.path.join(DATADIR, "so_Omon_GISS-E2.nc"), + filetype=esmpy.FileFormat.GRIDSPEC) # Create a field on the centers of the grid, with extra dimensions -srcfield = ESMF.Field(grid, staggerloc=ESMF.StaggerLoc.CENTER, ndbounds=[33, 2]) +srcfield = esmpy.Field(grid, staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[33, 2]) # Read the field data from file srcfield.read(filename=os.path.join(DATADIR, "so_Omon_GISS-E2.nc"), variable="so", timeslice=2) # Create an ESMF formatted unstructured mesh with clockwise cells removed -mesh = ESMF.Mesh(filename=os.path.join(DATADIR, "mpas_uniform_10242_dual_counterclockwise.nc"), - filetype=ESMF.FileFormat.ESMFMESH) +mesh = esmpy.Mesh(filename=os.path.join(DATADIR, "mpas_uniform_10242_dual_counterclockwise.nc"), + filetype=esmpy.FileFormat.ESMFMESH) # Create a field on the nodes of the mesh -dstfield = ESMF.Field(mesh, meshloc=ESMF.MeshLoc.NODE, ndbounds=[33, 2]) +dstfield = esmpy.Field(mesh, meshloc=esmpy.MeshLoc.NODE, ndbounds=[33, 2]) dstfield.data[:] = 1e20 # compute the weight matrix for regridding -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # calculate the regridding from source to destination field dstfield = regrid(srcfield, dstfield) -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: print ("Fields created from file regridded successfully :)") diff --git a/src/addon/ESMPy/examples/tripole_regrid.py b/src/addon/ESMPy/examples/tripole_regrid.py index 9fd4371d45..5afdb72101 100644 --- a/src/addon/ESMPy/examples/tripole_regrid.py +++ b/src/addon/ESMPy/examples/tripole_regrid.py @@ -7,47 +7,47 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "GRIDSPEC_ACCESS1.nc")) # cache_data_file(os.path.join(DD, "tx0.1v2_070911.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) grid1 = "examples/data/GRIDSPEC_ACCESS1.nc" grid2 = "examples/data/tx0.1v2_070911.nc" # Create a grid from a GRIDSPEC formatted file -grid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.GRIDSPEC, +grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.GRIDSPEC, add_corner_stagger=True, add_mask=True, varname="so") # create a field on the center stagger locations of the source grid -srcfield = ESMF.Field(grid, name='srcfield', staggerloc=ESMF.StaggerLoc.CENTER) +srcfield = esmpy.Field(grid, name='srcfield', staggerloc=esmpy.StaggerLoc.CENTER) # create a tripole grid -tripole = ESMF.Grid(filename=grid2, filetype=ESMF.FileFormat.SCRIP, +tripole = esmpy.Grid(filename=grid2, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True, add_mask=True, varname="grid_imask") # create fields on the center stagger locations of the tripole grid -dstfield = ESMF.Field(tripole, name='dstfield', meshloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(tripole, name='xctfield', meshloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(tripole, name='dstfield', meshloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(tripole, name='xctfield', meshloc=esmpy.StaggerLoc.CENTER) # create fields needed to analyze accuracy of conservative regridding -srcfracfield = ESMF.Field(grid, name='srcfracfield') -dstfracfield = ESMF.Field(tripole, name='dstfracfield') -srcareafield = ESMF.Field(grid, name='srcareafield') -dstareafield = ESMF.Field(tripole, name='dstareafield') +srcfracfield = esmpy.Field(grid, name='srcfracfield') +dstfracfield = esmpy.Field(tripole, name='dstfracfield') +srcareafield = esmpy.Field(grid, name='srcareafield') +dstareafield = esmpy.Field(tripole, name='dstareafield') # get the coordinate pointers and set the coordinates [lon,lat] = [0, 1] -gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) deg2rad = 3.14159/180 @@ -55,8 +55,8 @@ # get the coordinate pointers and set the coordinates [lon,lat] = [0, 1] -gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) xctfield.data[...] = 10.0 + (gridXCoord*deg2rad)**2 + (gridYCoord*deg2rad)**2 @@ -64,9 +64,9 @@ # create an object to regrid data from the source to the destination field # NOTE: this example requires the unmapped_action flag to be set to IGNORE missing values due to masking -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.IGNORE, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.IGNORE, src_mask_values=numpy.array([0]), dst_mask_values=numpy.array([0]), src_frac_field=srcfracfield, @@ -96,14 +96,14 @@ meanrelerr = relerr / num_nodes # handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) srcmass = helpers.reduce_val(srcmass, op=constants.Reduce.SUM) dstmass = helpers.reduce_val(dstmass, op=constants.Reduce.SUM) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes csrverr = numpy.abs(srcmass - dstmass) / dstmass diff --git a/src/addon/ESMPy/examples/ugrid_latlon_regrid.py b/src/addon/ESMPy/examples/ugrid_latlon_regrid.py index 47476e0417..89716d8906 100644 --- a/src/addon/ESMPy/examples/ugrid_latlon_regrid.py +++ b/src/addon/ESMPy/examples/ugrid_latlon_regrid.py @@ -6,12 +6,12 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll1deg_grid.nc")) # cache_data_file(os.path.join(DD, "ne30np4-t2UGRID_nodual.nc")) # cache_data_file(os.path.join(DD, "aggregAtlanticESTOFS.nc")) -import ESMF +import esmpy import numpy def plot_error(field1, field2, uninitval): @@ -90,35 +90,35 @@ def plot_field(field2, uninitval): plt.show() # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) # these are for a new test using opendap, dataset has periodic failures.. # meshfile = "http://coastalmodeldev.data.noaa.gov/thredds/dodsC/aggregAtlanticESTOFS" meshfile = "examples/data/aggregAtlanticESTOFS.nc" -mesh = ESMF.Mesh(filename=meshfile, filetype=ESMF.FileFormat.UGRID, meshname='adcirc_mesh') +mesh = esmpy.Mesh(filename=meshfile, filetype=esmpy.FileFormat.UGRID, meshname='adcirc_mesh') # Create a global latlon grid from a SCRIP formatted file gridfile = "examples/data/ll1deg_grid.nc" -grid = ESMF.Grid(filename=gridfile, filetype=ESMF.FileFormat.SCRIP, +grid = esmpy.Grid(filename=gridfile, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True, is_sphere=True) # create a field on the element locations of the source mesh -srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.NODE) +srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.NODE) # create a field on the centers of the destination grid -dstfield = ESMF.Field(grid, name='dstfield', staggerloc=ESMF.StaggerLoc.CENTER) -xctfield = ESMF.Field(grid, name='xctfield', staggerloc=ESMF.StaggerLoc.CENTER) +dstfield = esmpy.Field(grid, name='dstfield', staggerloc=esmpy.StaggerLoc.CENTER) +xctfield = esmpy.Field(grid, name='xctfield', staggerloc=esmpy.StaggerLoc.CENTER) # initialize the fields [lon,lat] = [0, 1] -srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=ESMF.MeshLoc.NODE) -srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=ESMF.MeshLoc.NODE) +srcgridXCoord = srcfield.grid.get_coords(lon, meshloc=esmpy.MeshLoc.NODE) +srcgridYCoord = srcfield.grid.get_coords(lat, meshloc=esmpy.MeshLoc.NODE) srcfield.data[...] = 2.0 + numpy.cos(numpy.radians(srcgridYCoord)[...])**2 * \ numpy.cos(2.0*numpy.radians(srcgridXCoord)[...]) -dstgridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -dstgridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +dstgridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +dstgridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) xctfield.data[...] = 2.0 + numpy.cos(numpy.radians(dstgridYCoord)[...])**2 * \ numpy.cos(2.0*numpy.radians(dstgridXCoord)[...]) @@ -126,15 +126,15 @@ def plot_field(field2, uninitval): dstfield.data[...] = uninitval # create an object to regrid data from the source to the destination field -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) # do the regridding from source to destination field -dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: print ("ESMPy UGRID to LatLon Regridding Example") # plot_error(xctfield, dstfield, uninitval=uninitval) @@ -154,11 +154,11 @@ def plot_field(field2, uninitval): # dstfield.data[...] = uninitval # # create an object to regrid data from the source to the destination field -# regrid = ESMF.Regrid(srcfield, dstfield, -# regrid_method=ESMF.RegridMethod.BILINEAR, -# unmapped_action=ESMF.UnmappedAction.IGNORE) +# regrid = esmpy.Regrid(srcfield, dstfield, +# regrid_method=esmpy.RegridMethod.BILINEAR, +# unmapped_action=esmpy.UnmappedAction.IGNORE) # # # do the regridding from source to destination field -# dstfield = regrid(srcfield, dstfield, zero_region=ESMF.Region.SELECT) +# dstfield = regrid(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # # plot_field(dstfield, uninitval=uninitval) \ No newline at end of file diff --git a/src/addon/ESMPy/examples/ungridded_dimension_regrid.py b/src/addon/ESMPy/examples/ungridded_dimension_regrid.py index 41f21e3d49..f4ab910df0 100644 --- a/src/addon/ESMPy/examples/ungridded_dimension_regrid.py +++ b/src/addon/ESMPy/examples/ungridded_dimension_regrid.py @@ -7,18 +7,18 @@ # DD = os.path.join(os.getcwd(), "examples/data") # if not os.path.isdir(DD): # os.makedirs(DD) -# from ESMF.util.cache_data import cache_data_file +# from esmpy.util.cache_data import cache_data_file # cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) # cache_data_file(os.path.join(DD, "T42_grid.nc")) -import ESMF +import esmpy import numpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants # This call enables debug logging -# esmpy = ESMF.Manager(debug=True) +# esmpy = esmpy.Manager(debug=True) grid1 = "examples/data/ll2.5deg_grid.nc" grid2 = "examples/data/T42_grid.nc" @@ -28,39 +28,39 @@ time = 5 # Create a uniform global latlon grid from a SCRIP formatted file -srcgrid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP, +srcgrid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) # Create a uniform global latlon grid from a SCRIP formatted file -dstgrid = ESMF.Grid(filename=grid2, filetype=ESMF.FileFormat.SCRIP, +dstgrid = esmpy.Grid(filename=grid2, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) # Create a field on the center stagger locations of the source grid -srcfield = ESMF.Field(srcgrid, name='srcfield', - staggerloc=ESMF.StaggerLoc.CENTER, +srcfield = esmpy.Field(srcgrid, name='srcfield', + staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[levels, time]) # Create a field on the center stagger locations of the destination grid -dstfield = ESMF.Field(dstgrid, name='dstfield', - staggerloc=ESMF.StaggerLoc.CENTER, +dstfield = esmpy.Field(dstgrid, name='dstfield', + staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[levels, time]) # Create a field on the center stagger locations of the destination grid -xctfield = ESMF.Field(dstgrid, name='xctfield', - staggerloc=ESMF.StaggerLoc.CENTER, +xctfield = esmpy.Field(dstgrid, name='xctfield', + staggerloc=esmpy.StaggerLoc.CENTER, ndbounds=[levels, time]) # Create fields needed to analyze accuracy of conservative regridding -srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') -dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') -srcareafield = ESMF.Field(srcgrid, name='srcareafield') -dstareafield = ESMF.Field(dstgrid, name='dstareafield') +srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') +dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') +srcareafield = esmpy.Field(srcgrid, name='srcareafield') +dstareafield = esmpy.Field(dstgrid, name='dstareafield') # Get the coordinate pointers and initialize the source field [lon,lat] = [0, 1] -gridXCoord = srcfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = srcfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = srcfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = srcfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) deg2rad = 3.14159/180 @@ -73,8 +73,8 @@ (gridYCoord*deg2rad)**2 # Get the coordinate pointers and initialize the exact solution -gridXCoord = xctfield.grid.get_coords(lon, ESMF.StaggerLoc.CENTER) -gridYCoord = xctfield.grid.get_coords(lat, ESMF.StaggerLoc.CENTER) +gridXCoord = xctfield.grid.get_coords(lon, esmpy.StaggerLoc.CENTER) +gridYCoord = xctfield.grid.get_coords(lat, esmpy.StaggerLoc.CENTER) for level in range(levels): for timestep in range(time): @@ -87,9 +87,9 @@ dstfield.data[...] = 1e20 # Create an object to regrid data from the source to the destination field -regrid = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, +regrid = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) @@ -126,14 +126,14 @@ csrverr = numpy.abs(srcmass - dstmass) / dstmass # Handle the parallel case -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: relerr = helpers.reduce_val(relerr, op=constants.Reduce.SUM) num_nodes = helpers.reduce_val(num_nodes, op=constants.Reduce.SUM) srcmass = helpers.reduce_val(srcmass, op=constants.Reduce.SUM) dstmass = helpers.reduce_val(dstmass, op=constants.Reduce.SUM) # Output the results from one processor only -if ESMF.local_pet() == 0: +if esmpy.local_pet() == 0: meanrelerr = relerr / num_nodes csrverr = numpy.abs(srcmass - dstmass) / dstmass diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_from_file_consts.py b/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_from_file_consts.py deleted file mode 100644 index 3c4277dad2..0000000000 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_from_file_consts.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Constants required for the regrid from file tests. -""" -import os -try: - import ESMF -except: - raise ImportError('The ESMF library cannot be found!') -# -TEST_REGRID_DIR = 'src/ESMF/test/regrid_from_file/' -CONTROL_FNAME = 'regrid_test_data.txt' -DATA_SUBDIR = os.path.join(TEST_REGRID_DIR,'data/') -DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' -UNINITVAL = 422397696. -EPSILON = 1E-30 -# -regrid_method_map = {"bilinear" : ESMF.RegridMethod.BILINEAR, - "patch" : ESMF.RegridMethod.PATCH, - "conserve" : ESMF.RegridMethod.CONSERVE, - "neareststod" : ESMF.RegridMethod.NEAREST_STOD, - "nearestdtos" : ESMF.RegridMethod.NEAREST_DTOS} -file_type_map = {"VTK" : ESMF.FileFormat.VTK, - "SCRIP" : ESMF.FileFormat.SCRIP, - "ESMF" : ESMF.FileFormat.ESMFMESH, - "ESMFMESH" : ESMF.FileFormat.ESMFMESH, - "ESMFGRID" : ESMF.FileFormat.ESMFGRID, - "UGRID" : ESMF.FileFormat.UGRID, - "GRIDSPEC" : ESMF.FileFormat.GRIDSPEC} -pole_method_map = {"none" : ESMF.PoleMethod.NONE, - "all" : ESMF.PoleMethod.ALLAVG, - "teeth" : ESMF.PoleMethod.TEETH} diff --git a/src/addon/ESMPy/src/ESMF/__init__.py b/src/addon/ESMPy/src/esmpy/__init__.py similarity index 80% rename from src/addon/ESMPy/src/ESMF/__init__.py rename to src/addon/ESMPy/src/esmpy/__init__.py index a69935ab09..ec5f90f4bd 100644 --- a/src/addon/ESMPy/src/ESMF/__init__.py +++ b/src/addon/ESMPy/src/esmpy/__init__.py @@ -15,9 +15,9 @@ can be found in the `ESMF Reference Manual `_. -ESMPy provides a :class:`~ESMF.api.grid.Grid` to represent single-tile logically -rectangular coordinate data, a :class:`~ESMF.api.mesh.Mesh` for unstructured -coordinates, and a :class:`~ESMF.api.locstream.LocStream` for collections of +ESMPy provides a :class:`~esmpy.api.grid.Grid` to represent single-tile logically +rectangular coordinate data, a :class:`~esmpy.api.mesh.Mesh` for unstructured +coordinates, and a :class:`~esmpy.api.locstream.LocStream` for collections of unconnected points like observational data streams. ESMPy supports bilinear, nearest neighbor, higher order patch recovery, first-order conservative and second-order conservative regridding. There is @@ -26,7 +26,7 @@ spherical coordinates and extrapolate data to points outside of the destination domain. Regridding on the sphere takes place in 3D Cartesian space, so the pole problem is not an issue as it commonly is with many Earth system grid remapping -softwares. :class:`~ESMF.api.grid.Grid` and :class:`~ESMF.api.mesh.Mesh` +softwares. :class:`~esmpy.api.grid.Grid` and :class:`~esmpy.api.mesh.Mesh` objects can be created in 2D or 3D space, and 3D conservative regridding is fully supported. @@ -66,14 +66,14 @@ #### IMPORT LIBRARIES ######################################################### -from ESMF.api.esmpymanager import * -from ESMF.api.grid import * -from ESMF.api.mesh import * -from ESMF.api.locstream import * -from ESMF.api.field import * -from ESMF.api.regrid import * -from ESMF.api.constants import * -from ESMF.util.helpers import * +from esmpy.api.esmpymanager import * +from esmpy.api.grid import * +from esmpy.api.mesh import * +from esmpy.api.locstream import * +from esmpy.api.field import * +from esmpy.api.regrid import * +from esmpy.api.constants import * +from esmpy.util.helpers import * #### SET UP SOME INFO ######################################################### @@ -114,18 +114,3 @@ __author__ = msg["Author"] __homepage__ = msg["Home-page"] __obsoletes__ = msg["obsoletes"] - -# # this is the old hardcoded version - -# __name__ = "ESMF" -# __version__ = "" -# __description__ = "ESMF Python interface" -# __author__ = "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" -# __license__ = "University of Illinois-NCSA" diff --git a/src/addon/ESMPy/src/ESMF/api/__init__.py b/src/addon/ESMPy/src/esmpy/api/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/api/__init__.py rename to src/addon/ESMPy/src/esmpy/api/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/api/constants.py b/src/addon/ESMPy/src/esmpy/api/constants.py similarity index 84% rename from src/addon/ESMPy/src/ESMF/api/constants.py rename to src/addon/ESMPy/src/esmpy/api/constants.py index b76a69d47d..4094e2901e 100644 --- a/src/addon/ESMPy/src/ESMF/api/constants.py +++ b/src/addon/ESMPy/src/esmpy/api/constants.py @@ -2,7 +2,7 @@ import numpy as np -from ESMF.util.enum import IntEnum +from esmpy.util.enum import IntEnum # Test exhaustive parameter esmpy_test_exhaustive=False @@ -57,33 +57,33 @@ # CoordSys class CoordSys(IntEnum): """ - This flag indicates the coordinate system of a :class:`~ESMF.api.grid.Grid`. This value is + This flag indicates the coordinate system of a :class:`~esmpy.api.grid.Grid`. This value is useful both to indicate to other users the type of the coordinates, but also to control how the coordinates are interpreted in - regridding methods (e.g. :class:`~ESMF.api.regrid.Regrid`). + regridding methods (e.g. :class:`~esmpy.api.regrid.Regrid`). """ INVALID = -2 UNINIT = -1 CART = 0 """ Cartesian coordinate system. In this system, the Cartesian - coordinates are mapped to the :class:`~ESMF.api.grid.Grid` coordinate dimensions in the + coordinates are mapped to the :class:`~esmpy.api.grid.Grid` coordinate dimensions in the following order: x, y, z. (e.g. using coord_dim=1 in - :class:`~ESMF.api.grid.Grid.get_coords()` references the y dimension) + :class:`~esmpy.api.grid.Grid.get_coords()` references the y dimension) """ SPH_DEG = 1 """ Spherical coordinates in degrees. In this system, the spherical - coordinates are mapped to the :class:`~ESMF.api.grid.Grid` coordinate dimensions in the + coordinates are mapped to the :class:`~esmpy.api.grid.Grid` coordinate dimensions in the following order: longitude, latitude, radius. (E.g. using - coord_dim=1 in :class:`~ESMF.api.grid.:class:`~ESMF.api.grid.Grid.get_coords()`` references the latitude dimension). + coord_dim=1 in :class:`~esmpy.api.grid.:class:`~esmpy.api.grid.Grid.get_coords()`` references the latitude dimension). """ SPH_RAD = 2 """ Spherical coordinates in radians. In this system, the spherical - coordinates are mapped to the :class:`~ESMF.api.grid.Grid` coordinate dimensions in the + coordinates are mapped to the :class:`~esmpy.api.grid.Grid` coordinate dimensions in the following order: longitude, latitude, radius. (E.g. using - coord_dim=1 in :class:`~ESMF.api.grid.Grid.get_coords()` references the latitude dimension). + coord_dim=1 in :class:`~esmpy.api.grid.Grid.get_coords()` references the latitude dimension). """ # DecompFlag @@ -156,7 +156,7 @@ class ExtrapMethod(IntEnum): # FileFormat class FileFormat(IntEnum): """ - The :class:`~ESMF.api.grid.Grid` and :class:`~ESMF.api.mesh.Mesh` objects + The :class:`~esmpy.api.grid.Grid` and :class:`~esmpy.api.mesh.Mesh` objects may be created from specifications in a NetCDF data file. This flag indicates the format of the data file. """ @@ -203,9 +203,9 @@ class FileMode(IntEnum): # GridItem class GridItem(IntEnum): """ - The :class:`~ESMF.api.grid.Grid` can contain other kinds of data besides coordinates. This - data is referred to as :class:`~ESMF.api.grid.Grid` "items". Some items may be used - for calculations involving the :class:`~ESMF.api.grid.Grid`. + The :class:`~esmpy.api.grid.Grid` can contain other kinds of data besides coordinates. This + data is referred to as :class:`~esmpy.api.grid.Grid` "items". Some items may be used + for calculations involving the :class:`~esmpy.api.grid.Grid`. """ INVALID = -2 UNINIT = -1 @@ -263,11 +263,11 @@ class LogKind(IntEnum): # MeshElemType class MeshElemType(IntEnum): """ - A :class:`~ESMF.api.mesh.Mesh` can be constructed from a combination of different elements. - The type of elements that can be used in a :class:`~ESMF.api.mesh.Mesh` depends on the - parametric dimension of the :class:`~ESMF.api.mesh.Mesh`, which is set during :class:`~ESMF.api.mesh.Mesh` - creation. The following are the valid :class:`~ESMF.api.mesh.Mesh` element types for each - valid :class:`~ESMF.api.mesh.Mesh` parametric dimension (2D or 3D). + A :class:`~esmpy.api.mesh.Mesh` can be constructed from a combination of different elements. + The type of elements that can be used in a :class:`~esmpy.api.mesh.Mesh` depends on the + parametric dimension of the :class:`~esmpy.api.mesh.Mesh`, which is set during :class:`~esmpy.api.mesh.Mesh` + creation. The following are the valid :class:`~esmpy.api.mesh.Mesh` element types for each + valid :class:`~esmpy.api.mesh.Mesh` parametric dimension (2D or 3D). """ TRI = 3 """ @@ -289,15 +289,15 @@ class MeshElemType(IntEnum): # MeshLoc class MeshLoc(IntEnum): """ - The :class:`~ESMF.api.mesh.Mesh` location used to hold :class:`~ESMF.api.field.Field` data. + The :class:`~esmpy.api.mesh.Mesh` location used to hold :class:`~esmpy.api.field.Field` data. """ NODE = 0 """ - The nodes of the :class:`~ESMF.api.mesh.Mesh`. + The nodes of the :class:`~esmpy.api.mesh.Mesh`. """ ELEMENT = 1 """ - The elements of the :class:`~ESMF.api.mesh.Mesh`. + The elements of the :class:`~esmpy.api.mesh.Mesh`. """ # NormType @@ -326,7 +326,7 @@ class NormType(IntEnum): class PoleKind(IntEnum): """ This type describes the type of connection that occurs at the pole of a - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ NONE = 0 """ @@ -346,12 +346,12 @@ class PoleKind(IntEnum): class PoleMethod(IntEnum): """ Indicates which type of artificial pole to construct on the source - :class:`~ESMF.api.grid.Grid` for regridding. + :class:`~esmpy.api.grid.Grid` for regridding. """ NONE = 0 """ No pole. Destination points which lie above the top or below the bottom row - of the source :class:`~ESMF.api.grid.Grid` won't be mapped. + of the source :class:`~esmpy.api.grid.Grid` won't be mapped. """ ALLAVG = 1 """ @@ -374,11 +374,11 @@ class PoleMethod(IntEnum): TEETH = 3 """ No new pole point is constructed, instead the holes at the poles are filled - by constructing triangles across the top and bottom row of the source :class:`~ESMF.api.grid.Grid`. + by constructing triangles across the top and bottom row of the source :class:`~esmpy.api.grid.Grid`. This can be useful because no averaging occurs, however, because the top and bottom of the sphere are now flat, for a big enough mismatch between the size of the destination and source pole holes, some destination points may - still not be able to be mapped to the source :class:`~ESMF.api.grid.Grid`. + still not be able to be mapped to the source :class:`~esmpy.api.grid.Grid`. """ # Region @@ -402,7 +402,7 @@ class Reduce(IntEnum): # Region class Region(IntEnum): """ - Specify various regions in the data layout of a :class:`~ESMF.api.field.Field` object. + Specify various regions in the data layout of a :class:`~esmpy.api.field.Field` object. """ TOTAL = 0 """ @@ -411,7 +411,7 @@ class Region(IntEnum): SELECT = 1 """ An operation applies to a select portion of the domain. One use of this is - to specify that the portions of a :class:`~ESMF.api.field.Field` that are not mapped in a regridding + to specify that the portions of a :class:`~esmpy.api.field.Field` that are not mapped in a regridding operation should retain their original value (as opposed to being initialized to 0). """ @@ -451,10 +451,10 @@ class RegridMethod(IntEnum): is calculated as the weighted sum of the values of the source cells that it overlaps. The weights are determined by the amount the source cell overlaps the destination cell. This method requires corner coordinate values to be - provided in the :class:`~ESMF.api.grid.Grid`. It currently only works for - :class:`Fields `s created on the - :class:`~ESMF.api.grid.Grid` center stagger or - the :class:`~ESMF.api.mesh.Mesh` element location. + provided in the :class:`~esmpy.api.grid.Grid`. It currently only works for + :class:`Fields `s created on the + :class:`~esmpy.api.grid.Grid` center stagger or + the :class:`~esmpy.api.mesh.Mesh` element location. """ NEAREST_STOD = 3 """ @@ -485,18 +485,18 @@ class RegridMethod(IntEnum): mininum value in the source field is 0.0, then it's possible that after regridding with the second-order method, the destination field will contain values less than 0.0. This method requires corner coordinate values to be - provided in the :class:`~ESMF.api.grid.Grid`. It currently only works for - :class:`Fields `s created on the - :class:`~ESMF.api.grid.Grid` center stagger or - the :class:`~ESMF.api.mesh.Mesh` element location. + provided in the :class:`~esmpy.api.grid.Grid`. It currently only works for + :class:`Fields `s created on the + :class:`~esmpy.api.grid.Grid` center stagger or + the :class:`~esmpy.api.mesh.Mesh` element location. """ # StaggerLoc class StaggerLoc(IntEnum): """ - In the :class:`~ESMF.api.grid.Grid` class, data can be located at different positions in a - :class:`~ESMF.api.grid.Grid` cell. When setting or retrieving coordinate data the stagger - location is specified to tell the :class:`~ESMF.api.grid.Grid` method from where in the + In the :class:`~esmpy.api.grid.Grid` class, data can be located at different positions in a + :class:`~esmpy.api.grid.Grid` cell. When setting or retrieving coordinate data the stagger + location is specified to tell the :class:`~esmpy.api.grid.Grid` method from where in the cell to get the data. """ INVALID = -2 diff --git a/src/addon/ESMPy/src/ESMF/api/esmpymanager.py b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py similarity index 87% rename from src/addon/ESMPy/src/ESMF/api/esmpymanager.py rename to src/addon/ESMPy/src/esmpy/api/esmpymanager.py index 286121effe..ddf8f481c0 100644 --- a/src/addon/ESMPy/src/ESMF/api/esmpymanager.py +++ b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py @@ -6,10 +6,10 @@ #### IMPORT LIBRARIES ######################################################### -from ESMF.api.constants import * -from ESMF.util.exceptions import * -from ESMF.interface.cbindings import * -from ESMF.util.decorators import initialize +from esmpy.api.constants import * +from esmpy.util.exceptions import * +from esmpy.interface.cbindings import * +from esmpy.util.decorators import initialize import re @@ -46,28 +46,28 @@ class Manager(object): ''' This singleton class is designed to ensure that ESMF is properly initialized and finalized. ESMF is initialized at - :class:`~ESMF.api.esmpymanager.Manager` creation, and the __del__ + :class:`~esmpy.api.esmpymanager.Manager` creation, and the __del__ method is registered with atexit to ensure ESMF is always finalized prior to exiting Python. If the object is copied, the copy will always be an alias - to the original :class:`~ESMF.api.esmpymanager.Manager` object. The - :class:`~ESMF.api.esmpymanager.Manager` will be created when the first + to the original :class:`~esmpy.api.esmpymanager.Manager` object. The + :class:`~esmpy.api.esmpymanager.Manager` will be created when the first ESMPy object is created if it is not created explicitly by the user. - Explicit creation of a :class:`~ESMF.api.esmpymanager.Manager` object allows + Explicit creation of a :class:`~esmpy.api.esmpymanager.Manager` object allows for setting a flag which results in the output of debug information from the ESMF logging capability during the application runtime. The output log files are named PET.ESMF_LogFile. The PET rank (local_pet) and total number of PETs (pet_count) - can also be retrieved from the :class:`~ESMF.api.esmpymanager.Manager` + can also be retrieved from the :class:`~esmpy.api.esmpymanager.Manager` using the following calls:: - ESMF.local_pet() - ESMF.pet_count() + esmpy.local_pet() + esmpy.pet_count() ``local_pet`` and ``pet_count`` are also properties of the - :class:`~ESMF.api.esmpymanager.Manager`. + :class:`~esmpy.api.esmpymanager.Manager`. Calls ESMP_Initialize and registers __del__ with atexit when called the first time. Subsequent calls only return whether or not ESMF is @@ -75,14 +75,14 @@ class Manager(object): will always be called prior to exiting Python. Calling __init__ explicitly results in a no-op. - The :class:`~ESMF.api.esmpymanager.Manager` can be used to enable the + The :class:`~esmpy.api.esmpymanager.Manager` can be used to enable the `MOAB `_ - mesh backend to the :class:`~ESMF.api.esmpymanager.Mesh`. This is done by calling ``set_moab()`` with ``moab_on=True``. + mesh backend to the :class:`~esmpy.api.esmpymanager.Mesh`. This is done by calling ``set_moab()`` with ``moab_on=True``. - The :class:`~ESMF.api.esmpymanager.Manager` has a `test_exhaustive` member + The :class:`~esmpy.api.esmpymanager.Manager` has a `test_exhaustive` member variable that can be enabled to run - combinatorial expansions of :class:`~ESMF.api.esmpymanager.Grid` and - :class:`~ESMF.api.esmpymanager.Field` creation parameters. + combinatorial expansions of :class:`~esmpy.api.esmpymanager.Grid` and + :class:`~esmpy.api.esmpymanager.Field` creation parameters. :param bool debug: outputs logging information to ESMF logfiles. If ``None``, defaults to False. diff --git a/src/addon/ESMPy/src/ESMF/api/field.py b/src/addon/ESMPy/src/esmpy/api/field.py similarity index 75% rename from src/addon/ESMPy/src/ESMF/api/field.py rename to src/addon/ESMPy/src/esmpy/api/field.py index 1b19d37724..9704a419ed 100755 --- a/src/addon/ESMPy/src/ESMF/api/field.py +++ b/src/addon/ESMPy/src/esmpy/api/field.py @@ -6,63 +6,63 @@ #### IMPORT LIBRARIES ######################################################### -from ESMF.api.grid import * -from ESMF.api.mesh import * -from ESMF.api.locstream import * -from ESMF.util.esmpyarray import * +from esmpy.api.grid import * +from esmpy.api.mesh import * +from esmpy.api.locstream import * +from esmpy.util.esmpyarray import * #### Field class ############################################################## [node, element] = [0, 1] class Field(object): """ - The :class:`~ESMF.api.field.Field` class is a Python wrapper object for the ESMF Field. + The :class:`~esmpy.api.field.Field` class is a Python wrapper object for the ESMF Field. The individual values of all data arrays are referenced to those of the underlying Fortran ESMF object. - A :class:`~ESMF.api.field.Field` represents a physical field, such as temperature. The :class:`~ESMF.api.field.Field` class + A :class:`~esmpy.api.field.Field` represents a physical field, such as temperature. The :class:`~esmpy.api.field.Field` class contains distributed and discretized field data, a reference to its - associated grid, and metadata. The :class:`~ESMF.api.field.Field` class stores the grid staggering + associated grid, and metadata. The :class:`~esmpy.api.field.Field` class stores the grid staggering for that physical field. This is the relationship of how the data array of a field maps onto a grid (e.g. one item per cell located at the cell center, one item per cell located at the NW corner, one item per cell vertex, etc.). - This means that different :class:`Fields ` which are on the same underlying :class:`~ESMF.api.grid.Grid` but - have different staggerings can share the same :class:`~ESMF.api.grid.Grid` object without needing to + This means that different :class:`Fields ` which are on the same underlying :class:`~esmpy.api.grid.Grid` but + have different staggerings can share the same :class:`~esmpy.api.grid.Grid` object without needing to replicate it multiple times. Refer to the Field Class of the `ESMF Reference Manual `_ for more information. - The following parameters are used to create a :class:`~ESMF.api.field.Field` - from a :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or - :class:`~ESMF.api.locstream.LocStream`. + The following parameters are used to create a :class:`~esmpy.api.field.Field` + from a :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or + :class:`~esmpy.api.locstream.LocStream`. *REQUIRED:* - :param :class:`~ESMF.api.grid.Grid`/Mesh/:class:`~ESMF.api.locstream.LocStream` grid: A :class:`~ESMF.api.grid.Grid`, - :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream` + :param :class:`~esmpy.api.grid.Grid`/Mesh/:class:`~esmpy.api.locstream.LocStream` grid: A :class:`~esmpy.api.grid.Grid`, + :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream` with coordinates allocated on at least one stagger location. *OPTIONAL:* :param str name: An optional user friendly name for the - :class:`~ESMF.api.field.Field`. - :param TypeKind typekind: Type of the :class:`~ESMF.api.field.Field` - data. If ``None``, defaults to :attr:`~ESMF.api.constants.TypeKind.R8`. + :class:`~esmpy.api.field.Field`. + :param TypeKind typekind: Type of the :class:`~esmpy.api.field.Field` + data. If ``None``, defaults to :attr:`~esmpy.api.constants.TypeKind.R8`. :param StaggerLoc staggerloc: The stagger location of the - :class:`~ESMF.api.field.Field` data, only specify this argument when - using a :class:`~ESMF.api.grid.Grid`. - If ``None``, defaults to :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + :class:`~esmpy.api.field.Field` data, only specify this argument when + using a :class:`~esmpy.api.grid.Grid`. + If ``None``, defaults to :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param MeshLoc meshloc: The mesh location of the - :class:`~ESMF.api.field.Field` data, only specify this argument when - using a :class:`~ESMF.api.mesh.Mesh` - if ``None``, defaults to :attr:`~ESMF.api.constants.MeshLoc.NODE`. + :class:`~esmpy.api.field.Field` data, only specify this argument when + using a :class:`~esmpy.api.mesh.Mesh` + if ``None``, defaults to :attr:`~esmpy.api.constants.MeshLoc.NODE`. :param tuple ndbounds: The number of entries in an extra - :class:`~ESMF.api.field.Field` dimension. This is represented as a + :class:`~esmpy.api.field.Field` dimension. This is represented as a single value, a list or a tuple containing the number of entries for - each desired extra dimension of the :class:`~ESMF.api.field.Field`. The + each desired extra dimension of the :class:`~esmpy.api.field.Field`. The time dimension must be last, following Fortran indexing conventions. """ @@ -222,8 +222,8 @@ def __repr__(self): @property def data(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The data of the :class:`~ESMF.api.field.Field` + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The data of the :class:`~esmpy.api.field.Field` """ return self._data @@ -240,10 +240,10 @@ def finalized(self): @property def grid(self): """ - :rtype: :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh`, or - :class:`~ESMF.api.locstream.LocStream` + :rtype: :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh`, or + :class:`~esmpy.api.locstream.LocStream` :return: The discretization object upon which the - :class:`~ESMF.api.field.Field` is built. + :class:`~esmpy.api.field.Field` is built. """ return self._grid @@ -251,7 +251,7 @@ def grid(self): def lower_bounds(self): """ :rtype: ndarray - :return: The lower bounds of the :class:`~ESMF.api.field.Field`. + :return: The lower bounds of the :class:`~esmpy.api.field.Field`. """ return self._lower_bounds @@ -267,7 +267,7 @@ def meta(self): def name(self): """ :rtype: str - :return: the name of the :class:`~ESMF.api.field.Field`. + :return: the name of the :class:`~esmpy.api.field.Field`. """ return self._name @@ -276,7 +276,7 @@ def ndbounds(self): """ :rtype: list :return: The bounds of the extra dimensions in the - :class:`~ESMF.api.field.Field`. + :class:`~esmpy.api.field.Field`. """ return self._ndbounds @@ -284,16 +284,16 @@ def ndbounds(self): def rank(self): """ :rtype: int - :return: The rank of the :class:`~ESMF.api.field.Field`. + :return: The rank of the :class:`~esmpy.api.field.Field`. """ return self._rank @property def staggerloc(self): """ - :rtype: :attr:`~ESMF.api.constants.StaggerLoc` or - :attr:`~ESMF.api.constants.MeshLoc` - :return: The location upon which the :class:`~ESMF.api.field.Field` + :rtype: :attr:`~esmpy.api.constants.StaggerLoc` or + :attr:`~esmpy.api.constants.MeshLoc` + :return: The location upon which the :class:`~esmpy.api.field.Field` is built. """ return self._staggerloc @@ -303,15 +303,15 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.field.Field`. + :class:`~esmpy.api.field.Field`. """ return self._struct @property def type(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The type of the data in the :class:`~ESMF.api.field.Field`. + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The type of the data in the :class:`~esmpy.api.field.Field`. """ return self._type @@ -319,7 +319,7 @@ def type(self): def upper_bounds(self): """ :rtype: ndarray - :return: The upper bounds of the :class:`~ESMF.api.field.Field`. + :return: The upper bounds of the :class:`~esmpy.api.field.Field`. """ return self._upper_bounds @@ -328,15 +328,15 @@ def xd(self): """ :rtype: int :return: The number of extra (ungridded) dimensions of the - :class:`~ESMF.api.field.Field`. + :class:`~esmpy.api.field.Field`. """ return self._xd def copy(self): """ - Copy a :class:`~ESMF.api.field.Field` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.field.Field` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.field.Field` shallow copy. + :return: A :class:`~esmpy.api.field.Field` shallow copy. """ # shallow copy ret = copy(self) @@ -347,7 +347,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.field.Field`. + Release the memory associated with a :class:`~esmpy.api.field.Field`. """ if hasattr(self, '_finalized'): if self._finalized == False: @@ -356,9 +356,9 @@ def destroy(self): def get_area(self): """ - Initialize an existing :class:`~ESMF.api.field.Field` with the areas of - the cells of the underlying :class:`~ESMF.api.grid.Grid` or - :class:`~ESMF.api.mesh.Mesh`. + Initialize an existing :class:`~esmpy.api.field.Field` with the areas of + the cells of the underlying :class:`~esmpy.api.grid.Grid` or + :class:`~esmpy.api.mesh.Mesh`. """ # call into the ctypes layer @@ -366,7 +366,7 @@ def get_area(self): def read(self, filename, variable, timeslice=None): """ - Read data into an existing :class:`~ESMF.api.field.Field` from a + Read data into an existing :class:`~esmpy.api.field.Field` from a CF-compliant NetCDF file. :note: This interface is not supported when ESMF is built with @@ -385,7 +385,7 @@ def read(self, filename, variable, timeslice=None): :param int timeslice: The number of timeslices to read. """ - import ESMF.api.constants as constants + import esmpy.api.constants as constants if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: raise ImportError("Field.Read() requires PIO and does not work if ESMF has not been built with MPI support") diff --git a/src/addon/ESMPy/src/ESMF/api/grid.py b/src/addon/ESMPy/src/esmpy/api/grid.py similarity index 89% rename from src/addon/ESMPy/src/ESMF/api/grid.py rename to src/addon/ESMPy/src/esmpy/api/grid.py index 299900f4d1..dda0bb53fe 100755 --- a/src/addon/ESMPy/src/ESMF/api/grid.py +++ b/src/addon/ESMPy/src/esmpy/api/grid.py @@ -9,25 +9,25 @@ import warnings from copy import copy -from ESMF.api.esmpymanager import * -from ESMF.util.esmpyarray import ndarray_from_esmf -import ESMF.api.constants as constants -from ESMF.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound, get_none_or_ssslice +from esmpy.api.esmpymanager import * +from esmpy.util.esmpyarray import ndarray_from_esmf +import esmpy.api.constants as constants +from esmpy.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound, get_none_or_ssslice #### Grid class ######################################################### class Grid(object): """ - The :class:`~ESMF.api.grid.Grid` class is a Python wrapper object for the ESMF Grid. The individual + The :class:`~esmpy.api.grid.Grid` class is a Python wrapper object for the ESMF Grid. The individual values of all coordinate and mask arrays are referenced to those of the underlying Fortran ESMF object. - The :class:`~ESMF.api.grid.Grid` class is used to describe the geometry and + The :class:`~esmpy.api.grid.Grid` class is used to describe the geometry and discretization of logically rectangular physical grids. It also contains the description of the underlying topology and decomposition of the physical grid across the available computational resources. The most frequent use of - the :class:`~ESMF.api.grid.Grid` class is to describe physical grids in user + the :class:`~esmpy.api.grid.Grid` class is to describe physical grids in user code so that sufficient information is available to perform regridding operations. @@ -35,9 +35,9 @@ class Grid(object): `ESMF Reference Manual `_ for more information. - A :class:`~ESMF.api.grid.Grid` can be created in two different ways, as a - :class:`~ESMF.api.grid.Grid` in memory, or from SCRIP formatted or CF compliant GRIDSPEC file. The - arguments for each type of :class:`~ESMF.api.grid.Grid` creation are + A :class:`~esmpy.api.grid.Grid` can be created in two different ways, as a + :class:`~esmpy.api.grid.Grid` in memory, or from SCRIP formatted or CF compliant GRIDSPEC file. The + arguments for each type of :class:`~esmpy.api.grid.Grid` creation are outlined below. **Created in-memory:** @@ -56,30 +56,30 @@ class Grid(object): :param int pole_dim: The pole dimension ``0`` or ``1``. If ``None``, defaults to ``1``. :param CoordSys coord_sys: Coordinate system for the - :class:`~ESMF.api.grid.Grid`. - If ``None``, defaults to :attr:`~ESMF.api.constants.CoordSys.SPH_DEG`. - :param TypeKind coord_typekind: Type of the :class:`~ESMF.api.grid.Grid` + :class:`~esmpy.api.grid.Grid`. + If ``None``, defaults to :attr:`~esmpy.api.constants.CoordSys.SPH_DEG`. + :param TypeKind coord_typekind: Type of the :class:`~esmpy.api.grid.Grid` coordinates. - If ``None``, defaults to :attr:`~ESMF.api.constants.TypeKind.R8`. + If ``None``, defaults to :attr:`~esmpy.api.constants.TypeKind.R8`. **Created either from file or in-memory:** :param StaggerLoc staggerloc: The stagger location of the coordinate values. - If ``None``, defaults to :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + If ``None``, defaults to :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param PoleKind pole_kind: Two item list which specifies the type of connection which occurs at the pole. The first value specifies the connection that occurs at the minimum end of the pole dimension. The second value specifies the connection that occurs at the maximum end of the pole dimension. - If ``None``, defaults to :attr:`~ESMF.api.constants.PoleKind.MONOPOLE`. + If ``None``, defaults to :attr:`~esmpy.api.constants.PoleKind.MONOPOLE`. **Created from file:** *REQUIRED:* :param str filename: The name of the NetCDF grid file. - :param FileFormat filetype: The grid :attr:`~ESMF.api.constants.FileFormat`. + :param FileFormat filetype: The grid :attr:`~esmpy.api.constants.FileFormat`. *OPTIONAL:* @@ -94,7 +94,7 @@ class Grid(object): :param bool add_mask: Set to ``True`` to generate the mask using the ``missing_value`` attribute defined in ``varname``. This argument is only supported with filetype - :attr:`~ESMF.api.constants.FileFormat.GRIDSPEC`. + :attr:`~esmpy.api.constants.FileFormat.GRIDSPEC`. Defaults to ``False``. :param str varname: If add_mask is ``True``, provide a variable name stored in the grid file and the mask will be generated using the missing value @@ -102,12 +102,12 @@ class Grid(object): variable has to be the longitude and the latitude dimension and the mask is derived from the first 2D values of this variable even if this data is a 3D, or 4D array. This argument is only supported with - filetype :attr:`~ESMF.api.constants.FileFormat.GRIDSPEC`. + filetype :attr:`~esmpy.api.constants.FileFormat.GRIDSPEC`. Defaults to ``None``. :param list coord_names: A two-element array containing the longitude and latitude variable names in a GRIDSPEC file if there are multiple coordinates defined in the file. This argument is only supported with - filetype :attr:`~ESMF.api.constants.FileFormat.GRIDSPEC`. + filetype :attr:`~esmpy.api.constants.FileFormat.GRIDSPEC`. Defaults to ``None``. **Cubed sphere:** @@ -130,7 +130,7 @@ class Grid(object): PET count. For instance, if the total PET count is 16, the total DE count will be 12 with each tile decomposed into 1x2 blocks. The 12 DEs are mapped to the first 12 PETs and the remaining 4 PETs have no DEs locally. - :param str name: The name of the :class:`~ESMF.api.grid.Grid`. + :param str name: The name of the :class:`~esmpy.api.grid.Grid`. """ # :param list decompFlagPTile: # :param list deLabelList: @@ -561,8 +561,8 @@ def __repr__(self): def area(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The :class:`~ESMF.api.grid.Grid` cell areas represented as + of the :class:`~esmpy.api.grid.Grid`. + :return: The :class:`~esmpy.api.grid.Grid` cell areas represented as numpy arrays of floats of size given by ``upper_bounds - lower_bounds``. """ @@ -572,8 +572,8 @@ def area(self): @property def areatype(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The ESMF typekind of the :class:`~ESMF.api.grid.Grid` cell + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The ESMF typekind of the :class:`~esmpy.api.grid.Grid` cell areas. """ @@ -584,10 +584,10 @@ def coords(self): """ :rtype: 2D list of numpy arrays of size given by ``upper_bounds - lower_bounds``, where the first index represents - the stagger locations of the :class:`~ESMF.api.grid.Grid` and the + the stagger locations of the :class:`~esmpy.api.grid.Grid` and the second index represent the coordinate dimensions of the - :class:`~ESMF.api.grid.Grid`. - :return: The coordinates of the :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. + :return: The coordinates of the :class:`~esmpy.api.grid.Grid`. """ return self._coords @@ -595,8 +595,8 @@ def coords(self): @property def coord_sys(self): """ - :rtype: :attr:`~ESMF.api.constants.CoordSys` - :return: The coordinate system of the :class:`~ESMF.api.grid.Grid`. + :rtype: :attr:`~esmpy.api.constants.CoordSys` + :return: The coordinate system of the :class:`~esmpy.api.grid.Grid`. """ return self._coord_sys @@ -615,7 +615,7 @@ def finalized(self): def has_corners(self): """ :rtype: bool - :return: A boolean value to tell if the :class:`~ESMF.api.grid.Grid` + :return: A boolean value to tell if the :class:`~esmpy.api.grid.Grid` has corners allocated. """ @@ -625,8 +625,8 @@ def has_corners(self): def lower_bounds(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The lower bounds of the :class:`~ESMF.api.grid.Grid` + of the :class:`~esmpy.api.grid.Grid`. + :return: The lower bounds of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ``upper_bounds - lower_bounds``. """ @@ -637,8 +637,8 @@ def lower_bounds(self): def mask(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The mask of the :class:`~ESMF.api.grid.Grid` represented as + of the :class:`~esmpy.api.grid.Grid`. + :return: The mask of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ` `upper_bounds - lower_bounds``. """ @@ -649,8 +649,8 @@ def mask(self): def max_index(self): """ :rtype: A numpy array with as many values as the - :class:`~ESMF.api.grid.Grid` rank. - :return: The number of :class:`~ESMF.api.grid.Grid` cells in each + :class:`~esmpy.api.grid.Grid` rank. + :return: The number of :class:`~esmpy.api.grid.Grid` cells in each dimension of the grid. """ @@ -669,7 +669,7 @@ def meta(self): def name(self): """ :rtype: str - :return: The name of the :class:`~ESMF.api.grid.Grid`. + :return: The name of the :class:`~esmpy.api.grid.Grid`. """ return self._name @@ -679,7 +679,7 @@ def ndims(self): """ :rtype: int :return: The rank of the coordinate arrays of the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._ndims @@ -689,7 +689,7 @@ def num_peri_dims(self): """ :rtype: int :return: The total number of periodic dimensions in the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._num_peri_dims @@ -699,7 +699,7 @@ def decount(self): """ :rtype: int :return: The total number of tiles in the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._decount @@ -708,7 +708,7 @@ def decount(self): def periodic_dim(self): """ :rtype: int - :return: The periodic dimension of the :class:`~ESMF.api.grid.Grid` + :return: The periodic dimension of the :class:`~esmpy.api.grid.Grid` (e.g. ``0`` for ``x`` or ``longitude``, ``1`` for ``y`` or ``latitude``, etc.). """ @@ -719,7 +719,7 @@ def periodic_dim(self): def pole_dim(self): """ :rtype: int - :return: The pole dimension of the :class:`~ESMF.api.grid.Grid` + :return: The pole dimension of the :class:`~esmpy.api.grid.Grid` (e.g. ``0`` for ``x`` or ``longitude``, ``1`` for ``y`` or ``latitude``, etc.). """ @@ -730,8 +730,8 @@ def pole_dim(self): def pole_kind(self): """ :rtype: A numpy array with as many values as the - :class:`~ESMF.api.grid.Grid` has poles. - :return: The number of connections at each pole of the :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid` has poles. + :return: The number of connections at each pole of the :class:`~esmpy.api.grid.Grid`. """ return self._pole_kind @@ -740,7 +740,7 @@ def pole_kind(self): def rank(self): """ :rtype: int - :return: The rank of the :class:`~ESMF.api.grid.Grid`. + :return: The rank of the :class:`~esmpy.api.grid.Grid`. """ return self._rank @@ -749,8 +749,8 @@ def rank(self): def size(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The size of the :class:`~ESMF.api.grid.Grid` represented as + of the :class:`~esmpy.api.grid.Grid`. + :return: The size of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ``upper_bounds - lower_bounds``. """ @@ -762,7 +762,7 @@ def staggerloc(self): """ :rtype: list of bools :return: The stagger locations that have been allocated for the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._staggerloc @@ -772,7 +772,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for the - :class:`~ESMF.api.grid.Grid`. + :class:`~esmpy.api.grid.Grid`. """ return self._struct @@ -780,8 +780,8 @@ def struct(self): @property def type(self): """ - :rtype: :attr:`~ESMF.api.constants.TypeKind` - :return: The ESMF typekind of the :class:`~ESMF.api.grid.Grid` + :rtype: :attr:`~esmpy.api.constants.TypeKind` + :return: The ESMF typekind of the :class:`~esmpy.api.grid.Grid` coordinates. """ return self._type @@ -790,8 +790,8 @@ def type(self): def upper_bounds(self): """ :rtype: A list of numpy arrays with an entry for every stagger location - of the :class:`~ESMF.api.grid.Grid`. - :return: The upper bounds of the :class:`~ESMF.api.grid.Grid` + of the :class:`~esmpy.api.grid.Grid`. + :return: The upper bounds of the :class:`~esmpy.api.grid.Grid` represented as numpy arrays of ints of size given by ``upper_bounds - lower_bounds``. """ @@ -799,20 +799,20 @@ def upper_bounds(self): def add_coords(self, staggerloc=None, coord_dim=None, from_file=False): """ - Add coordinates to the :class:`~ESMF.api.grid.Grid` at the specified + Add coordinates to the :class:`~esmpy.api.grid.Grid` at the specified stagger location. :param StaggerLoc staggerloc: The stagger location of the coordinate values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param int coord_dim: The dimension number of the coordinates to return e.g. ``[x, y, z] = (0, 1, 2)``, or ``[lon, lat] = (0, 1)`` (coordinates will not be returned if coord_dim is not specified and staggerlocs is a list with more than one element). :param bool from_file: Boolean for internal use to determine whether the - :class:`~ESMF.api.grid.Grid` has already been created from file. + :class:`~esmpy.api.grid.Grid` has already been created from file. :return: A numpy array of coordinate values if staggerloc and coord_dim are specified, otherwise return None. @@ -844,23 +844,23 @@ def add_coords(self, staggerloc=None, coord_dim=None, from_file=False): def add_item(self, item, staggerloc=None, from_file=False): """ - Allocate space for a :class:`~ESMF.api.grid.Grid` item (mask or areas) + Allocate space for a :class:`~esmpy.api.grid.Grid` item (mask or areas) at a specified stagger location. *REQUIRED:* - :param GridItem item: The :attr:`~ESMF.api.constants.GridItem` to + :param GridItem item: The :attr:`~esmpy.api.constants.GridItem` to allocate. *OPTIONAL:* :param StaggerLoc staggerloc: The stagger location of the item values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :param bool from_file: Boolean for internal use to determine whether the - :class:`~ESMF.api.grid.Grid` has already been created from file. + :class:`~esmpy.api.grid.Grid` has already been created from file. :return: A numpy array of the mask or area values if a single staggerloc is given, otherwise return None. @@ -905,9 +905,9 @@ def add_item(self, item, staggerloc=None, from_file=False): def copy(self): """ - Copy a :class:`~ESMF.api.grid.Grid` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.grid.Grid` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.grid.Grid` shallow copy. + :return: A :class:`~esmpy.api.grid.Grid` shallow copy. """ # shallow copy ret = copy(self) @@ -918,7 +918,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.grid.Grid`. + Release the memory associated with a :class:`~esmpy.api.grid.Grid`. """ if hasattr(self, '_finalized'): if not self._finalized: @@ -929,7 +929,7 @@ def get_coords(self, coord_dim, staggerloc=None): """ Return a numpy array of coordinates at a specified stagger location. The returned array is NOT a copy, it is - directly aliased to the underlying memory allocated by ESMF. + directly aliased to the underlying memory allocated by esmpy. *REQUIRED:* @@ -942,8 +942,8 @@ def get_coords(self, coord_dim, staggerloc=None): :param StaggerLoc staggerloc: The stagger location of the coordinate values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` - in 2D and :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` + in 2D and :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :return: A numpy array of coordinate values at the specified staggerloc. @@ -967,19 +967,19 @@ def get_item(self, item, staggerloc=None): """ Return a numpy array of item values at a specified stagger location. The returned array is NOT a copy, it is - directly aliased to the underlying memory allocated by ESMF. + directly aliased to the underlying memory allocated by esmpy. *REQUIRED:* - :param GridItem item: The :attr:`~ESMF.api.constants.GridItem` to + :param GridItem item: The :attr:`~esmpy.api.constants.GridItem` to return. *OPTIONAL:* :param StaggerLoc staggerloc: The stagger location of the item values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` in 2D and - :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` in 2D and + :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. :return: A numpy array of mask or area values at the specified staggerloc. """ @@ -1177,8 +1177,8 @@ def _write_(self, filename, staggerloc=None): :param StaggerLoc staggerloc: The stagger location of the item values. If ``None``, defaults to - :attr:`~ESMF.api.constants.StaggerLoc.CENTER` in 2D and - :attr:`~ESMF.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. + :attr:`~esmpy.api.constants.StaggerLoc.CENTER` in 2D and + :attr:`~esmpy.api.constants.StaggerLoc.CENTER_VCENTER` in 3D. """ # handle the default case diff --git a/src/addon/ESMPy/src/ESMF/api/locstream.py b/src/addon/ESMPy/src/esmpy/api/locstream.py similarity index 79% rename from src/addon/ESMPy/src/ESMF/api/locstream.py rename to src/addon/ESMPy/src/esmpy/api/locstream.py index 07a10a472d..e5d5982140 100644 --- a/src/addon/ESMPy/src/ESMF/api/locstream.py +++ b/src/addon/ESMPy/src/esmpy/api/locstream.py @@ -6,25 +6,25 @@ #### IMPORT LIBRARIES ######################################################### -from ESMF.api.esmpymanager import * -from ESMF.util.esmpyarray import ndarray_from_esmf -import ESMF.api.constants as constants -from ESMF.util.slicing import get_formatted_slice +from esmpy.api.esmpymanager import * +from esmpy.util.esmpyarray import ndarray_from_esmf +import esmpy.api.constants as constants +from esmpy.util.slicing import get_formatted_slice #### LocStream class ######################################################### class LocStream(dict): """ - The :class:`~ESMF.api.locstream.LocStream` class is a Python wrapper object for the ESMF LocStream. - :class:`~ESMF.api.locstream.LocStream` is a derived type of a Python dictionary. + The :class:`~esmpy.api.locstream.LocStream` class is a Python wrapper object for the ESMF LocStream. + :class:`~esmpy.api.locstream.LocStream` is a derived type of a Python dictionary. The individual values of all key arrays are referenced to those of the underlying Fortran ESMF object. - A :class:`~ESMF.api.locstream.LocStream` is used to represent the locations of a + A :class:`~esmpy.api.locstream.LocStream` is used to represent the locations of a set of data points. The values of the data points are stored within a - :class:`~ESMF.api.field.Field` created using the :class:`~ESMF.api.locstream.LocStream`. + :class:`~esmpy.api.field.Field` created using the :class:`~esmpy.api.locstream.LocStream`. In the data assimilation world, location streams can be thought of as a set of observations. Their locations are generally described using Cartesian @@ -38,7 +38,7 @@ class LocStream(dict): `ESMF Reference Manual `_ for more information. - :class:`~ESMF.api.locstream.LocStream` follows standard dictionary syntax. For example: + :class:`~esmpy.api.locstream.LocStream` follows standard dictionary syntax. For example: >>> locstream["ESMF:X"] = [1, 2, 3] >>> x = locstream["ESMF:X"] @@ -54,29 +54,29 @@ class LocStream(dict): .. note:: - Mask must be of type :attr:`~ESMF.api.constants.TypeKind.I4`, - and coordinates must by of type :attr:`~ESMF.api.constants.TypeKind.R8`. + Mask must be of type :attr:`~esmpy.api.constants.TypeKind.I4`, + and coordinates must by of type :attr:`~esmpy.api.constants.TypeKind.R8`. - For ESMF to be able to recognize coordinates specified in a :class:`~ESMF.api.locstream.LocStream` key + For ESMF to be able to recognize coordinates specified in a :class:`~esmpy.api.locstream.LocStream` key they need to be named with the appropriate identifiers. The particular identifiers depend on the coordinate system (i.e. ``coord_sys`` argument) - used to create the :class:`~ESMF.api.locstream.LocStream`. + used to create the :class:`~esmpy.api.locstream.LocStream`. The valid values are: ============================================ =========== =========== =========== Coordinate System dimension 1 dimension 2 dimension 3 ============================================ =========== =========== =========== - :attr:`~ESMF.api.constants.CoordSys.SPH_DEG` ESMF:Lon ESMF:Lat ESMF:Radius - :attr:`~ESMF.api.constants.CoordSys.SPH_RAD` ESMF:Lon ESMF:Lat ESMF:Radius - :attr:`~ESMF.api.constants.CoordSys.CART` ESMF:X ESMF:Y ESMF:Z + :attr:`~esmpy.api.constants.CoordSys.SPH_DEG` ESMF:Lon ESMF:Lat ESMF:Radius + :attr:`~esmpy.api.constants.CoordSys.SPH_RAD` ESMF:Lon ESMF:Lat ESMF:Radius + :attr:`~esmpy.api.constants.CoordSys.CART` ESMF:X ESMF:Y ESMF:Z ============================================ =========== =========== =========== :param int location_count: The number of points in this stream. :param CoordSys coord_sys: Coordinate system for the location stream. - If ``None``, defaults to :attr:`~ESMF.api.constants.CoordSys.SPH_DEG`. + If ``None``, defaults to :attr:`~esmpy.api.constants.CoordSys.SPH_DEG`. :param str name: Optional name for the location stream. - :param bool esmf: Internal parameter controlling shallow copying by ESMF. + :param bool esmf: Internal parameter controlling shallow copying by esmpy. """ @initialize @@ -189,7 +189,7 @@ def finalized(self): def lower_bounds(self): """ :rtype: int - :return: The lower bounds of the :class:`~ESMF.api.locstream.LocStream`. + :return: The lower bounds of the :class:`~esmpy.api.locstream.LocStream`. """ return self._lower_bounds @@ -198,7 +198,7 @@ def lower_bounds(self): def mask(self): """ :rtype: list - :return: The mask of the :class:`~ESMF.api.locstream.LocStream`. + :return: The mask of the :class:`~esmpy.api.locstream.LocStream`. """ return self.get("ESMF:Mask") @@ -216,7 +216,7 @@ def meta(self): def name(self): """ :rtype: str - :return: The name of the :class:`~ESMF.api.locstream.LocStream`. + :return: The name of the :class:`~esmpy.api.locstream.LocStream`. """ return self._name @@ -225,7 +225,7 @@ def name(self): def rank(self): """ :rtype: int - :return: The rank of the :class:`~ESMF.api.locstream.LocStream`. + :return: The rank of the :class:`~esmpy.api.locstream.LocStream`. """ return self._rank @@ -235,7 +235,7 @@ def singlestagger(self): """ :rtype: bool :return: A boolean value to tell if this - :class:`~ESMF.api.locstream.LocStream` has been sliced. + :class:`~esmpy.api.locstream.LocStream` has been sliced. """ return self._singlestagger @@ -244,7 +244,7 @@ def singlestagger(self): def size(self): """ :rtype: int - :return: The size of the :class:`~ESMF.api.locstream.LocStream`. + :return: The size of the :class:`~esmpy.api.locstream.LocStream`. """ return self._size @@ -254,7 +254,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.locstream.LocStream`. + :class:`~esmpy.api.locstream.LocStream`. """ return self._struct @@ -263,16 +263,16 @@ def struct(self): def upper_bounds(self): """ :rtype: int - :return: The upper bounds of the :class:`~ESMF.api.locstream.LocStream`. + :return: The upper bounds of the :class:`~esmpy.api.locstream.LocStream`. """ return self._upper_bounds def copy(self): """ - Copy a :class:`~ESMF.api.locstream.LocStream` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.locstream.LocStream` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.locstream.LocStream` shallow copy. + :return: A :class:`~esmpy.api.locstream.LocStream` shallow copy. """ # shallow copy ret = LocStream(self._size, name=self._name, esmf=False) @@ -292,7 +292,7 @@ def copy(self): def destroy(self): """ Release the memory associated with a - :class:`~ESMF.api.locstream.LocStream`. + :class:`~esmpy.api.locstream.LocStream`. """ if hasattr(self, '_finalized'): @@ -310,4 +310,4 @@ def _add_(self, key_name, typekind=None): # create a numpy array out of the pointer keyvals = ndarray_from_esmf(key_ptr, typekind, (self.size,)) - return keyvals \ No newline at end of file + return keyvals diff --git a/src/addon/ESMPy/src/ESMF/api/mesh.py b/src/addon/ESMPy/src/esmpy/api/mesh.py similarity index 81% rename from src/addon/ESMPy/src/ESMF/api/mesh.py rename to src/addon/ESMPy/src/esmpy/api/mesh.py index a2ff3e9e12..7bfc1cdbff 100755 --- a/src/addon/ESMPy/src/ESMF/api/mesh.py +++ b/src/addon/ESMPy/src/esmpy/api/mesh.py @@ -8,12 +8,12 @@ from copy import copy -from ESMF.api.constants import * -from ESMF.interface.cbindings import * -from ESMF.util.decorators import initialize +from esmpy.api.constants import * +from esmpy.interface.cbindings import * +from esmpy.util.decorators import initialize -from ESMF.api.esmpymanager import * -from ESMF.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound_list +from esmpy.api.esmpymanager import * +from esmpy.util.slicing import get_formatted_slice, get_none_or_slice, get_none_or_bound_list import warnings @@ -22,91 +22,91 @@ class Mesh(object): """ - The :class:`~ESMF.api.mesh.Mesh` class is a Python wrapper object for the ESMF Mesh. + The :class:`~esmpy.api.mesh.Mesh` class is a Python wrapper object for the ESMF Mesh. The individual values of all coordinate and mask arrays are referenced to those of the underlying Fortran ESMF object. The ESMF library provides a class for representing unstructured grids called - the :class:`~ESMF.api.mesh.Mesh`. :class:`Fields ` can be created on a :class:`~ESMF.api.mesh.Mesh` to hold data. :class:`Fields ` created on a - :class:`~ESMF.api.mesh.Mesh` can also be used as either the source or destination or both of a + the :class:`~esmpy.api.mesh.Mesh`. :class:`Fields ` can be created on a :class:`~esmpy.api.mesh.Mesh` to hold data. :class:`Fields ` created on a + :class:`~esmpy.api.mesh.Mesh` can also be used as either the source or destination or both of a regrididng operation which allows data to be moved between unstructured - grids. A :class:`~ESMF.api.mesh.Mesh` is constructed of nodes and elements. A node, also known as - a vertex or corner, is a part of a :class:`~ESMF.api.mesh.Mesh` which represents a single point. + grids. A :class:`~esmpy.api.mesh.Mesh` is constructed of nodes and elements. A node, also known as + a vertex or corner, is a part of a :class:`~esmpy.api.mesh.Mesh` which represents a single point. Coordinate information is set in a node. An element, also known as a cell, is a part of a mesh which represents a small region of space. Elements are described in terms of a connected set of nodes which represent locations - along their boundaries. :class:`~ESMF.api.field.Field` data may be located on either the nodes or - elements of a :class:`~ESMF.api.mesh.Mesh`. + along their boundaries. :class:`~esmpy.api.field.Field` data may be located on either the nodes or + elements of a :class:`~esmpy.api.mesh.Mesh`. Refer to the Mesh Class of the `ESMF Reference Manual `_ for more information. - An unstructured :class:`~ESMF.api.mesh.Mesh` can be created in two different ways, as a :class:`~ESMF.api.mesh.Mesh` in + An unstructured :class:`~esmpy.api.mesh.Mesh` can be created in two different ways, as a :class:`~esmpy.api.mesh.Mesh` in memory, or from a SCRIP formatted or CF compliant UGRID file. The arguments - for each type of :class:`~ESMF.api.mesh.Mesh` creation are outlined below. + for each type of :class:`~esmpy.api.mesh.Mesh` creation are outlined below. **Created in-memory:** - The in-memory :class:`~ESMF.api.mesh.Mesh` can be created manually in 3 steps: - 1. create the :class:`~ESMF.api.mesh.Mesh` (specifying ``parametric_dim`` and ``spatial_dim``), + The in-memory :class:`~esmpy.api.mesh.Mesh` can be created manually in 3 steps: + 1. create the :class:`~esmpy.api.mesh.Mesh` (specifying ``parametric_dim`` and ``spatial_dim``), 2. add nodes, 3. add elements. *REQUIRED:* :param int parametric_dim: the dimension of the topology of the - :class:`~ESMF.api.mesh.Mesh` (e.g. a :class:`~ESMF.api.mesh.Mesh` composed of squares would have a - parametric dimension of 2 and a :class:`~ESMF.api.mesh.Mesh` composed of cubes + :class:`~esmpy.api.mesh.Mesh` (e.g. a :class:`~esmpy.api.mesh.Mesh` composed of squares would have a + parametric dimension of 2 and a :class:`~esmpy.api.mesh.Mesh` composed of cubes would have a parametric dimension of 3). :param int spatial_dim: the number of coordinate dimensions needed to describe the locations of the nodes making up the - :class:`~ESMF.api.mesh.Mesh`. For a manifold the spatial dimension can be larger + :class:`~esmpy.api.mesh.Mesh`. For a manifold the spatial dimension can be larger than the parametric dimension (e.g. the 2D surface of a sphere in 3D space), but it cannot be smaller. *OPTIONAL:* :param CoordSys coord_sys: Coordinate system for the - :class:`~ESMF.api.mesh.Mesh`. - If ``None``, defaults to :attr:`~ESMF.api.constants.CoordSys.SPH_DEG`. + :class:`~esmpy.api.mesh.Mesh`. + If ``None``, defaults to :attr:`~esmpy.api.constants.CoordSys.SPH_DEG`. **Created from file:** - Note that :class:`Meshes ` created from file do not use the ``parametric_dim`` and + Note that :class:`Meshes ` created from file do not use the ``parametric_dim`` and ``spatial_dim`` parameters. *REQUIRED:* - :param str filename: the name of NetCDF file containing the :class:`~ESMF.api.mesh.Mesh`. + :param str filename: the name of NetCDF file containing the :class:`~esmpy.api.mesh.Mesh`. :param FileFormat filetype: the input - :attr:`~ESMF.api.constants.FileFormat` of the :class:`~ESMF.api.mesh.Mesh`. + :attr:`~esmpy.api.constants.FileFormat` of the :class:`~esmpy.api.mesh.Mesh`. *OPTIONAL:* :param bool convert_to_dual: a boolean value to specify if the - dual :class:`~ESMF.api.mesh.Mesh` should be calculated. Defaults to False. This + dual :class:`~esmpy.api.mesh.Mesh` should be calculated. Defaults to False. This argument is only supported with - :attr:`~ESMF.api.constants.FileFormat.SCRIP`. + :attr:`~esmpy.api.constants.FileFormat.SCRIP`. :param bool add_user_area: a boolean value to specify if an area property should be added to the mesh. This argument is only - supported for :attr:`~ESMF.api.constants.FileFormat.SCRIP` - or :attr:`~ESMF.api.constants.FileFormat.ESMFMESH`. + supported for :attr:`~esmpy.api.constants.FileFormat.SCRIP` + or :attr:`~esmpy.api.constants.FileFormat.ESMFMESH`. If ``None``, defaults to False. - :param str meshname: the name of the :class:`~ESMF.api.mesh.Mesh` metadata variable in + :param str meshname: the name of the :class:`~esmpy.api.mesh.Mesh` metadata variable in a UGRID file. This argument is only supported with - :attr:`~ESMF.api.constants.FileFormat.UGRID`. + :attr:`~esmpy.api.constants.FileFormat.UGRID`. If ``None``, defaults to the empty string. :param MeshLoc mask_flag: an enumerated integer that, if specified, tells whether a mask in a UGRID file should be - defined on the :attr:`~ESMF.api.constants.MeshLoc.NODE`s, or - :attr:`~ESMF.api.constants.MeshLoc.ELEMENT`s of the :class:`~ESMF.api.mesh.Mesh`. + defined on the :attr:`~esmpy.api.constants.MeshLoc.NODE`s, or + :attr:`~esmpy.api.constants.MeshLoc.ELEMENT`s of the :class:`~esmpy.api.mesh.Mesh`. This argument is only supported with - :attr:`~ESMF.api.constants.FileFormat.UGRID`. + :attr:`~esmpy.api.constants.FileFormat.UGRID`. If ``None``, defaults to no masking. :param str varname: a variable name for the mask in a UGRID file if mask_flag is specified. This argument is only supported - for :attr:`~ESMF.api.constants.FileFormat.UGRID`. + for :attr:`~esmpy.api.constants.FileFormat.UGRID`. If ``None``, defaults to the empty string. """ @@ -255,9 +255,9 @@ def __repr__(self): def area(self): """ :rtype: A two element list of numpy arrays to hold values for the nodes - and elements of the :class:`~ESMF.api.mesh.Mesh`. - :return: The :class:`~ESMF.api.mesh.Mesh` area represented as a numpy - array of floats of the same number of entries as :class:`~ESMF.api.mesh.Mesh` elements. + and elements of the :class:`~esmpy.api.mesh.Mesh`. + :return: The :class:`~esmpy.api.mesh.Mesh` area represented as a numpy + array of floats of the same number of entries as :class:`~esmpy.api.mesh.Mesh` elements. """ return self._area @@ -265,18 +265,18 @@ def area(self): def coords(self): """ :rtype: A two element list of numpy arrays to hold values for the nodes - and elements of the :class:`~ESMF.api.mesh.Mesh`. + and elements of the :class:`~esmpy.api.mesh.Mesh`. :return: The coordinates represented as a numpy array of floats - with a value for each node and/or element of the :class:`~ESMF.api.mesh.Mesh` - :class:`~ESMF.api.mesh.Mesh`. + with a value for each node and/or element of the :class:`~esmpy.api.mesh.Mesh` + :class:`~esmpy.api.mesh.Mesh`. """ return self._coords @property def coord_sys(self): """ - :rtype: :attr:`~ESMF.api.constants.CoordSys` - :return: The coordinate system of the :class:`~ESMF.api.mesh.Mesh`. + :rtype: :attr:`~esmpy.api.constants.CoordSys` + :return: The coordinate system of the :class:`~esmpy.api.mesh.Mesh`. """ return self._coord_sys @@ -321,9 +321,9 @@ def finalized(self): def mask(self): """ :rtype: A two element list of numpy arrays to hold values for the nodes - and elements of the :class:`~ESMF.api.mesh.Mesh`. + and elements of the :class:`~esmpy.api.mesh.Mesh`. :return: The masked values on the nodes and elements of the - :class:`~ESMF.api.mesh.Mesh`. + :class:`~esmpy.api.mesh.Mesh`. """ return self._mask @@ -367,7 +367,7 @@ def rank(self): def size(self): """ :rtype: A two element list of integers. - :return: The number of nodes and elements in the :class:`~ESMF.api.mesh.Mesh` on the current + :return: The number of nodes and elements in the :class:`~esmpy.api.mesh.Mesh` on the current processor. """ return self._size @@ -376,7 +376,7 @@ def size(self): def size_owned(self): """ :rtype: A two element list of integers. - :return: The number of owned nodes and elements in the :class:`~ESMF.api.mesh.Mesh` on the + :return: The number of owned nodes and elements in the :class:`~esmpy.api.mesh.Mesh` on the current processor. """ return self._size_owned @@ -390,7 +390,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.mesh.Mesh`. + :class:`~esmpy.api.mesh.Mesh`. """ return self._struct @@ -402,19 +402,19 @@ def add_elements(self, element_count, element_area=None, element_coords=None): """ - Add elements to a :class:`~ESMF.api.mesh.Mesh`, this must be done after adding nodes. + Add elements to a :class:`~esmpy.api.mesh.Mesh`, this must be done after adding nodes. *REQUIRED:* - :param int element_count: the number of elements to add to the :class:`~ESMF.api.mesh.Mesh`. + :param int element_count: the number of elements to add to the :class:`~esmpy.api.mesh.Mesh`. :param ndarray element_ids: a numpy array of of shape ``(element_count, 1)`` to specify the element ids. :param ndarray element_types: a numpy array of - :attr:`~ESMF.api.constants.MeshElemType`s of shape + :attr:`~esmpy.api.constants.MeshElemType`s of shape ``(element_count, 1)`` to specify the element types. :param ndarray element_conn: a numpy array of shape ``sum(element_types[:], 1)`` to specify the connectivity of the - :class:`~ESMF.api.mesh.Mesh`. The connectivity array is constructed by concatenating the + :class:`~esmpy.api.mesh.Mesh`. The connectivity array is constructed by concatenating the tuples that correspond to the element_ids. The connectivity tuples are constructed by listing the node_ids of each element in **COUNTERCLOCKWISE** order. @@ -424,7 +424,7 @@ def add_elements(self, element_count, :param ndarray element_mask: a numpy array of shape ``(element_count, 1)`` containing integer values to specify masked elements. The specific values that are masked are specified in the - :class:`~ESMF.api.regrid.Regrid` constructor. + :class:`~esmpy.api.regrid.Regrid` constructor. :param ndarray element_area: a numpy array of shape ``(element_count, 1)`` to specify the areas of the elements. :param ndarray element_coords: a numpy array of shape @@ -483,13 +483,13 @@ def add_nodes(self, node_count, node_coords, node_owners): """ - Add nodes to a :class:`~ESMF.api.mesh.Mesh`, this must be done before adding elements. + Add nodes to a :class:`~esmpy.api.mesh.Mesh`, this must be done before adding elements. - :param int node_count: the number of nodes to add to the :class:`~ESMF.api.mesh.Mesh`. + :param int node_count: the number of nodes to add to the :class:`~esmpy.api.mesh.Mesh`. :param ndarray node_ids: a numpy array of shape (node_count, 1) to specify the node_ids. :param ndarray node_coords: a numpy array of shape - (spatial_dim*node_count, 1) to specify the coordinates of the :class:`~ESMF.api.mesh.Mesh`. + (spatial_dim*node_count, 1) to specify the coordinates of the :class:`~esmpy.api.mesh.Mesh`. The array should be constructed by concatenating the coordinate tuples into a numpy array that correspond to node_ids. :param ndarray node_owners: a numpy array of shape (node_count, 1) to @@ -517,9 +517,9 @@ def add_nodes(self, node_count, def copy(self): """ - Copy a :class:`~ESMF.api.mesh.Mesh` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.mesh.Mesh` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.mesh.Mesh` shallow copy. + :return: A :class:`~esmpy.api.mesh.Mesh` shallow copy. """ # shallow copy ret = copy(self) @@ -531,7 +531,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.mesh.Mesh`. + Release the memory associated with a :class:`~esmpy.api.mesh.Mesh`. """ if hasattr(self, '_finalized'): if not self._finalized: @@ -541,7 +541,7 @@ def destroy(self): def free_memory(self): """ Free memory associated with the creation of a - :class:`~ESMF.api.mesh.Mesh` which is no longer needed for ongoing + :class:`~esmpy.api.mesh.Mesh` which is no longer needed for ongoing operations. """ # call into ctypes layer @@ -549,11 +549,11 @@ def free_memory(self): def get_coords(self, coord_dim, meshloc=MeshLoc.NODE): """ - Return a numpy array of coordinates at a specified :class:`~ESMF.api.mesh.Mesh` - location (coordinates can only be returned for the :class:`~ESMF.api.mesh.Mesh` - :attr:`~ESMF.api.constants.MeshLoc.NODE`\s + Return a numpy array of coordinates at a specified :class:`~esmpy.api.mesh.Mesh` + location (coordinates can only be returned for the :class:`~esmpy.api.mesh.Mesh` + :attr:`~esmpy.api.constants.MeshLoc.NODE` at this time). The returned array is NOT a copy, it is - directly aliased to the underlying memory allocated by ESMF. + directly aliased to the underlying memory allocated by esmpy. *REQUIRED:* @@ -562,12 +562,12 @@ def get_coords(self, coord_dim, meshloc=MeshLoc.NODE): *OPTIONAL:* - :param MeshLoc meshloc: the :attr:`~ESMF.api.constants.MeshLoc` of the + :param MeshLoc meshloc: the :attr:`~esmpy.api.constants.MeshLoc` of the coordinates. If ``None``, defaults to - :attr:`~ESMF.api.constants.MeshLoc.NODE`. + :attr:`~esmpy.api.constants.MeshLoc.NODE`. :return: A numpy array of coordinate values at the specified - :attr:`~ESMF.api.constants.MeshLoc`. + :attr:`~esmpy.api.constants.MeshLoc`. """ ret = None @@ -619,7 +619,7 @@ def _link_coords_(self): def _write_(self, filename): """ - Write the :class:`~ESMF.api.mesh.Mesh` to a vtk formatted file. + Write the :class:`~esmpy.api.mesh.Mesh` to a vtk formatted file. :param str filename: the name of the output file, .vtk will be appended. """ diff --git a/src/addon/ESMPy/src/ESMF/api/regrid.py b/src/addon/ESMPy/src/esmpy/api/regrid.py similarity index 81% rename from src/addon/ESMPy/src/ESMF/api/regrid.py rename to src/addon/ESMPy/src/esmpy/api/regrid.py index 7552960306..b63f6f59ca 100644 --- a/src/addon/ESMPy/src/ESMF/api/regrid.py +++ b/src/addon/ESMPy/src/esmpy/api/regrid.py @@ -3,32 +3,32 @@ """ The Regrid API """ -from ESMF.api import constants -from ESMF.api.field import * +from esmpy.api import constants +from esmpy.api.field import * class Regrid(object): """ - The :class:`~ESMF.api.regrid.Regrid` object represents a regridding operator between two :class:`Fields `. The + The :class:`~esmpy.api.regrid.Regrid` object represents a regridding operator between two :class:`Fields `. The creation of this object is analogous to ESMF_FieldRegridStore(), and calling this object corresponds to ESMF_FieldRegrid(). - ESMF_FieldRegridRelease() is called when the :class:`~ESMF.api.regrid.Regrid` object goes out of - scope (this only happens when the :class:`~ESMF.api.esmpymanager.Manager` goes out of scope, there is a - destroy() call for explicit deallocation of the :class:`~ESMF.api.regrid.Regrid`). + ESMF_FieldRegridRelease() is called when the :class:`~esmpy.api.regrid.Regrid` object goes out of + scope (this only happens when the :class:`~esmpy.api.esmpymanager.Manager` goes out of scope, there is a + destroy() call for explicit deallocation of the :class:`~esmpy.api.regrid.Regrid`). Refer to the ESMF_FieldRegrid methods in the `ESMF Reference Manual `_ for more information. The following arguments are used to create a handle to a Regridding - operation between two :class:`Fields `. + operation between two :class:`Fields `. *REQUIRED:* - :param Field srcfield: source :class:`~ESMF.api.field.Field` associated with an underlying :class:`~ESMF.api.grid.Grid`, - :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream`. - :param Field dstfield: destination :class:`~ESMF.api.field.Field` associated with an underlying - :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` or :class:`~ESMF.api.locstream.LocStream`. The data in this :class:`~ESMF.api.field.Field` may be overwritten + :param Field srcfield: source :class:`~esmpy.api.field.Field` associated with an underlying :class:`~esmpy.api.grid.Grid`, + :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream`. + :param Field dstfield: destination :class:`~esmpy.api.field.Field` associated with an underlying + :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` or :class:`~esmpy.api.locstream.LocStream`. The data in this :class:`~esmpy.api.field.Field` may be overwritten by this call. *OPTIONAL:* @@ -36,65 +36,65 @@ class Regrid(object): :param string filename: path to the output netCDF weight file. :param string rh_filename: path to the output RouteHandle file. :param ndarray src_mask_values: a numpy array of values that should be - considered masked value on the source :class:`~ESMF.api.field.Field`. + considered masked value on the source :class:`~esmpy.api.field.Field`. :param ndarray dst_mask_values: a numpy array of values that should be - considered masked value on the destination :class:`~ESMF.api.field.Field`. + considered masked value on the destination :class:`~esmpy.api.field.Field`. :param RegridMethod regrid_method: specifies which - :attr:`~ESMF.api.constants.RegridMethod` to use. If ``None``, defaults - to :attr:`~ESMF.api.constants.RegridMethod.BILINEAR`. + :attr:`~esmpy.api.constants.RegridMethod` to use. If ``None``, defaults + to :attr:`~esmpy.api.constants.RegridMethod.BILINEAR`. :param PoleMethod pole_method: specifies which type of artificial pole - to construct on the source :class:`~ESMF.api.grid.Grid` for regridding. If - ``None``, defaults to: :attr:`~ESMF.api.constants.PoleMethod.NONE` for - regridmethod == :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`, or - :attr:`~ESMF.api.constants.PoleMethod.ALLAVG` for - regridmethod != :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`. + to construct on the source :class:`~esmpy.api.grid.Grid` for regridding. If + ``None``, defaults to: :attr:`~esmpy.api.constants.PoleMethod.NONE` for + regridmethod == :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`, or + :attr:`~esmpy.api.constants.PoleMethod.ALLAVG` for + regridmethod != :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`. :param int regrid_pole_npoints: specifies how many points to average over - if polemethod == :attr:`~ESMF.api.constants.PoleMethod.ALLAVG`. + if polemethod == :attr:`~esmpy.api.constants.PoleMethod.ALLAVG`. :param LineType line_type: select the path of the line that connects two points on the surface of a sphere. This in turn controls the path along which distances are calculated and the shape of the edges that make up a cell. If ``None``, defaults to: - :attr:`~ESMF.api.constants.LineType.GREAT_CIRCLE` for - regridmethod == :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`, or - :attr:`~ESMF.api.constants.LineType.CART` for - regridmethod != :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`. + :attr:`~esmpy.api.constants.LineType.GREAT_CIRCLE` for + regridmethod == :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`, or + :attr:`~esmpy.api.constants.LineType.CART` for + regridmethod != :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`. :param NormType norm_type: control which type of normalization to do when generating conservative regridding weights. If ``None``, defaults to - :attr:`~ESMF.api.constants.NormType.DSTAREA`. + :attr:`~esmpy.api.constants.NormType.DSTAREA`. :param ExtrapMethod extrap_method: Specify which extrapolation method to use on unmapped destination points after regridding. :param int extrap_num_src_pnts: The number of source points to use for the extrapolation methods that use more than one source point - (e.g. :attr:`~ESMF.api.constants.ExtrapMethod.NEAREST_IDAVG`). If not + (e.g. :attr:`~esmpy.api.constants.ExtrapMethod.NEAREST_IDAVG`). If not specified, defaults to 8. :param float extrap_dist_exponent: The exponent to raise the distance to when - calculating weights for the :attr:`~ESMF.api.constants.ExtrapMethod.NEAREST_IDAVG` + calculating weights for the :attr:`~esmpy.api.constants.ExtrapMethod.NEAREST_IDAVG` extrapolation method. A higher value reduces the influence of more distant points. If not specified, defaults to ``2.0``. :param int extrap_num_levels: The number of levels to output for the extrapolation - methods that fill levels (e.g. :attr:`~ESMF.api.constants.ExtrapMethod.CREEP`). + methods that fill levels (e.g. :attr:`~esmpy.api.constants.ExtrapMethod.CREEP`). When a method is used that requires this, then an error will be returned if it is not specified. :param UnmappedAction unmapped_action: specifies which action to take if a destination point is found which does not map to any source point. If - ``None``, defaults to :attr:`~ESMF.api.constants.UnmappedAction.ERROR`. + ``None``, defaults to :attr:`~esmpy.api.constants.UnmappedAction.ERROR`. :param bool ignore_degenerate: Ignore degenerate cells when checking the - input :class:`Grids ` or :class:`Meshes ` + input :class:`Grids ` or :class:`Meshes ` for errors. If this is set to True, then the regridding proceeds, but degenerate cells will be skipped. If set to False, a degenerate cell produces - an error. This currently only applies to :attr:`~ESMF.api.constants.RegridMethod.CONSERVE`, + an error. This currently only applies to :attr:`~esmpy.api.constants.RegridMethod.CONSERVE`, other regrid methods currently always skip degenerate cells. If ``None``, defaults to ``False``. :param ndarray src_frac_field: return a numpy array of values containing - weights corresponding to the amount of each :class:`~ESMF.api.field.Field` - value which contributes to the total mass of the :class:`~ESMF.api.field.Field`. + weights corresponding to the amount of each :class:`~esmpy.api.field.Field` + value which contributes to the total mass of the :class:`~esmpy.api.field.Field`. :param ndarray dst_frac_field: return a numpy array of values containing - weights corresponding to the amount of each :class:`~ESMF.api.field.Field` - value which contributes to the total mass of the :class:`~ESMF.api.field.Field`. + weights corresponding to the amount of each :class:`~esmpy.api.field.Field` + value which contributes to the total mass of the :class:`~esmpy.api.field.Field`. :param bool factors: If ``True``, return the factor and factor index list when calling into ``ESMF``'s regrid store method. These lists are converted to NumPy arrays and attached to the regrid object. The factor arrays - are retrievable via :meth:`~ESMF.api.regrid.get_factors` or :meth:`~ESMF.api.regrid.get_weights_dict`. + are retrievable via :meth:`~esmpy.api.regrid.get_factors` or :meth:`~esmpy.api.regrid.get_weights_dict`. See the respective documentation on those methods for additional information. For more information on how ``ESMF`` treats factor retrieval see the ESMF_FieldRegridStore interface in the @@ -247,15 +247,15 @@ def __call__(self, srcfield, dstfield, zero_region=None): *REQUIRED:* - :param Field srcfield: the :class:`~ESMF.api.field.Field` of source data to regrid. - :param Field dstfield: the :class:`~ESMF.api.field.Field` to hold the regridded data. + :param Field srcfield: the :class:`~esmpy.api.field.Field` of source data to regrid. + :param Field dstfield: the :class:`~esmpy.api.field.Field` to hold the regridded data. *OPTIONAL:* :param Region zero_region: specify which region of the field indices will be zeroed out before adding the values resulting from the interpolation. If ``None``, defaults to - :attr:`~ESMF.api.constants.Region.TOTAL`. + :attr:`~esmpy.api.constants.Region.TOTAL`. :return: dstfield """ @@ -390,7 +390,7 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.regrid.Regrid`. + :class:`~esmpy.api.regrid.Regrid`. """ return self.struct @@ -401,9 +401,9 @@ def unmapped_action(self): def copy(self): """ - Copy a :class:`~ESMF.api.regrid.Regrid` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.regrid.Regrid` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.regrid.Regrid` shallow copy. + :return: A :class:`~esmpy.api.regrid.Regrid` shallow copy. """ # shallow copy @@ -415,7 +415,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with a :class:`~ESMF.api.regrid.Regrid`. + Release the memory associated with a :class:`~esmpy.api.regrid.Regrid`. """ # This detects if the object has made it through initialization @@ -459,7 +459,7 @@ def get_factors(self, deep_copy=False): .. note:: If ``deep_copy=True``, array memory is C contiguous according to NumPy array flags (``.flags``). - .. warning:: Remember to call :meth:`~ESMF.api.regrid.destroy` to deallocate + .. warning:: Remember to call :meth:`~esmpy.api.regrid.destroy` to deallocate memory associated with a regrid operation. This will be called by the Python garbage collector. However, if numerous regridding operations are called in a tight loop, a memory leak will occur without a call @@ -481,7 +481,7 @@ def get_factors(self, deep_copy=False): def get_weights_dict(self, deep_copy=False): """ Return a dictionary mapping that is more user-friendly for weight/factor - retrieval. Please read the documentation for :meth:`~ESMF.api.regrid.get_factors` + retrieval. Please read the documentation for :meth:`~esmpy.api.regrid.get_factors` before using this function. =========== ======================= @@ -549,30 +549,30 @@ def _handle_factors_(self, fil, fl, num_factors): class RegridFromFile(object): """ - The :class:`~ESMF.api.regrid.RegridFromFile` object represents a regridding - operator between two :class:`Fields ` that is read + The :class:`~esmpy.api.regrid.RegridFromFile` object represents a regridding + operator between two :class:`Fields ` that is read from a file. The creation of this object is analogous to= ESMF_FieldSMMStore(), and calling this object corresponds to ESMF_FieldRegrid(). ESMF_FieldRegridRelease() - is called when the :class:`~ESMF.api.regrid.RegridFromFile` object goes - out of scope (this only happens when the :class:`~ESMF.api.esmpymanager.Manager` + is called when the :class:`~esmpy.api.regrid.RegridFromFile` object goes + out of scope (this only happens when the :class:`~esmpy.api.esmpymanager.Manager` goes out of scope, there is a destroy() call for explicit deallocation of - the :class:`~ESMF.api.regrid.RegridFromFile`). + the :class:`~esmpy.api.regrid.RegridFromFile`). For more information about the ESMF Regridding functionality, please see the ESMF_FieldRegrid methods in the `ESMF Reference Manual `_. The following arguments are used to create a handle to a regridding - operation between two :class:`Fields `. + operation between two :class:`Fields `. *REQUIRED:* - :param Field srcfield: source :class:`~ESMF.api.field.Field` associated - with an underlying :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` - or :class:`~ESMF.api.locstream.LocStream`. - :param Field dstfield: destination :class:`~ESMF.api.field.Field` associated - with an underlying :class:`~ESMF.api.grid.Grid`, :class:`~ESMF.api.mesh.Mesh` - or :class:`~ESMF.api.locstream.LocStream`. The data in this :class:`~ESMF.api.field.Field` + :param Field srcfield: source :class:`~esmpy.api.field.Field` associated + with an underlying :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` + or :class:`~esmpy.api.locstream.LocStream`. + :param Field dstfield: destination :class:`~esmpy.api.field.Field` associated + with an underlying :class:`~esmpy.api.grid.Grid`, :class:`~esmpy.api.mesh.Mesh` + or :class:`~esmpy.api.locstream.LocStream`. The data in this :class:`~esmpy.api.field.Field` may be overwritten by this call. :param string filename: the name of the file from which to retrieve the weights. @@ -607,15 +607,15 @@ def __call__(self, srcfield, dstfield, zero_region=None): *REQUIRED:* - :param Field srcfield: the :class:`~ESMF.api.field.Field` of source data to regrid. - :param Field dstfield: the :class:`~ESMF.api.field.Field` to hold the regridded data. + :param Field srcfield: the :class:`~esmpy.api.field.Field` of source data to regrid. + :param Field dstfield: the :class:`~esmpy.api.field.Field` to hold the regridded data. *OPTIONAL:* :param Region zero_region: specify which region of the field indices will be zeroed out before adding the values resulting from the interpolation. If ``None``, defaults to - :attr:`~ESMF.api.constants.Region.TOTAL`. + :attr:`~esmpy.api.constants.Region.TOTAL`. :return: dstfield """ @@ -664,16 +664,16 @@ def struct(self): """ :rtype: pointer :return: A pointer to the underlying ESMF allocation for this - :class:`~ESMF.api.regrid.Regrid`. + :class:`~esmpy.api.regrid.Regrid`. """ return self.struct def copy(self): """ - Copy a :class:`~ESMF.api.regrid.Regrid` in an ESMF-safe manner. + Copy a :class:`~esmpy.api.regrid.Regrid` in an ESMF-safe manner. - :return: A :class:`~ESMF.api.regrid.Regrid` shallow copy. + :return: A :class:`~esmpy.api.regrid.Regrid` shallow copy. """ # shallow copy @@ -685,7 +685,7 @@ def copy(self): def destroy(self): """ - Release the memory associated with the :class:`~ESMF.api.regrid.RegridFromFile` + Release the memory associated with the :class:`~esmpy.api.regrid.RegridFromFile` object. """ diff --git a/src/addon/ESMPy/src/ESMF/fragments/dump_esmf_internal_info.py b/src/addon/ESMPy/src/esmpy/fragments/dump_esmf_internal_info.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/fragments/dump_esmf_internal_info.py rename to src/addon/ESMPy/src/esmpy/fragments/dump_esmf_internal_info.py diff --git a/src/addon/ESMPy/src/ESMF/fragments/extras.py b/src/addon/ESMPy/src/esmpy/fragments/extras.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/fragments/extras.py rename to src/addon/ESMPy/src/esmpy/fragments/extras.py diff --git a/src/addon/ESMPy/src/ESMF/fragments/remap.py b/src/addon/ESMPy/src/esmpy/fragments/remap.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/fragments/remap.py rename to src/addon/ESMPy/src/esmpy/fragments/remap.py diff --git a/src/addon/ESMPy/src/ESMF/interface/__init__.py b/src/addon/ESMPy/src/esmpy/interface/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/interface/__init__.py rename to src/addon/ESMPy/src/esmpy/interface/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/interface/cbindings.py b/src/addon/ESMPy/src/esmpy/interface/cbindings.py similarity index 99% rename from src/addon/ESMPy/src/ESMF/interface/cbindings.py rename to src/addon/ESMPy/src/esmpy/interface/cbindings.py index 4adaea4f83..c344b48d37 100644 --- a/src/addon/ESMPy/src/ESMF/interface/cbindings.py +++ b/src/addon/ESMPy/src/esmpy/interface/cbindings.py @@ -8,9 +8,9 @@ import numpy as np import sys -import ESMF.api.constants as constants -from ESMF.util.decorators import deprecated, netcdf, beta -from ESMF.interface.loadESMF import _ESMF +import esmpy.api.constants as constants +from esmpy.util.decorators import deprecated, netcdf, beta +from esmpy.interface.loadESMF import _ESMF def copy_struct(src): @@ -20,7 +20,7 @@ def copy_struct(src): def handle_esmf_error(rc, esmf_name): - from ESMF.api import constants + from esmpy.api import constants if rc != constants._ESMP_SUCCESS: msg = esmf_name + ' failed with rc = ' + str(rc) + '. ' + constants._errmsg raise ValueError(msg) diff --git a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py similarity index 99% rename from src/addon/ESMPy/src/ESMF/interface/loadESMF.py rename to src/addon/ESMPy/src/esmpy/interface/loadESMF.py index dfed9ae412..803134ccc4 100644 --- a/src/addon/ESMPy/src/ESMF/interface/loadESMF.py +++ b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py @@ -6,7 +6,7 @@ import sys import traceback -import ESMF.api.constants as constants +import esmpy.api.constants as constants try: import numpy as np diff --git a/src/addon/ESMPy/src/ESMF/test/__init__.py b/src/addon/ESMPy/src/esmpy/test/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/__init__.py rename to src/addon/ESMPy/src/esmpy/test/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/test/base.py b/src/addon/ESMPy/src/esmpy/test/base.py similarity index 98% rename from src/addon/ESMPy/src/ESMF/test/base.py rename to src/addon/ESMPy/src/esmpy/test/base.py index e0ad849d30..2d655206dc 100644 --- a/src/addon/ESMPy/src/ESMF/test/base.py +++ b/src/addon/ESMPy/src/esmpy/test/base.py @@ -1,7 +1,7 @@ import unittest import numpy as np -import ESMF -from ESMF.util.itester import iter_product_keywords +import esmpy +from esmpy.util.itester import iter_product_keywords from unittest import SkipTest diff --git a/src/addon/ESMPy/src/ESMF/test/base_test.py b/src/addon/ESMPy/src/esmpy/test/base_test.py similarity index 91% rename from src/addon/ESMPy/src/ESMF/test/base_test.py rename to src/addon/ESMPy/src/esmpy/test/base_test.py index ba7bfd7a3c..b95a9313d2 100644 --- a/src/addon/ESMPy/src/ESMF/test/base_test.py +++ b/src/addon/ESMPy/src/esmpy/test/base_test.py @@ -1,6 +1,6 @@ -from ESMF.test.base import TestBase +from esmpy.test.base import TestBase import numpy as np -from ESMF import Manager +from esmpy import Manager class Test(TestBase): diff --git a/src/addon/ESMPy/src/ESMF/test/data/T42_grid.nc b/src/addon/ESMPy/src/esmpy/test/data/T42_grid.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/T42_grid.nc rename to src/addon/ESMPy/src/esmpy/test/data/T42_grid.nc diff --git a/src/addon/ESMPy/src/ESMF/test/data/gridspec1Dcoords.nc b/src/addon/ESMPy/src/esmpy/test/data/gridspec1Dcoords.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/gridspec1Dcoords.nc rename to src/addon/ESMPy/src/esmpy/test/data/gridspec1Dcoords.nc diff --git a/src/addon/ESMPy/src/ESMF/test/data/ne4np4-esmf.nc b/src/addon/ESMPy/src/esmpy/test/data/ne4np4-esmf.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/ne4np4-esmf.nc rename to src/addon/ESMPy/src/esmpy/test/data/ne4np4-esmf.nc diff --git a/src/addon/ESMPy/src/ESMF/test/data/ne4np4-pentagons.nc b/src/addon/ESMPy/src/esmpy/test/data/ne4np4-pentagons.nc similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/data/ne4np4-pentagons.nc rename to src/addon/ESMPy/src/esmpy/test/data/ne4np4-pentagons.nc diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/__init__.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/__init__.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/read_test_cases_from_control_file.py similarity index 91% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/read_test_cases_from_control_file.py index 313a76e63f..a07eec5913 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/read_test_cases_from_control_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/read_test_cases_from_control_file.py @@ -10,7 +10,7 @@ import os import re -from ESMF.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR, CONTROL_FNAME +from esmpy.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR, CONTROL_FNAME def read_control_file(): diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py similarity index 84% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py index 4a7582b869..0714009da0 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py @@ -16,21 +16,21 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') -from ESMF.test.regrid_from_file.regrid_from_file_consts import regrid_method_map, file_type_map, pole_method_map, UNINITVAL -from ESMF.util.grid_utilities import compute_mass_grid -from ESMF.util.mesh_utilities import compute_mass_mesh -from ESMF.util.field_utilities import compare_fields +from esmpy.test.regrid_from_file.regrid_from_file_consts import regrid_method_map, file_type_map, pole_method_map, UNINITVAL +from esmpy.util.grid_utilities import compute_mass_grid +from esmpy.util.mesh_utilities import compute_mass_mesh +from esmpy.util.field_utilities import compare_fields def nc_is_mesh(filename, filetype): is_mesh = False - if (filetype == ESMF.FileFormat.UGRID) or (filetype == ESMF.FileFormat.ESMFMESH): + if (filetype == esmpy.FileFormat.UGRID) or (filetype == esmpy.FileFormat.ESMFMESH): is_mesh = True - elif filetype == ESMF.FileFormat.SCRIP: - grid_rank, dims = ESMF.ESMP_ScripInq(filename) + elif filetype == esmpy.FileFormat.SCRIP: + grid_rank, dims = esmpy.ESMP_ScripInq(filename) if grid_rank == 1: is_mesh = True return is_mesh @@ -42,7 +42,7 @@ def create_grid_or_mesh_from_file(filename, filetype, meshname=None, missingvalue=None): is_mesh = False if nc_is_mesh(filename, filetype): - grid_or_mesh = ESMF.Mesh(filename=filename, + grid_or_mesh = esmpy.Mesh(filename=filename, filetype=filetype, meshname=meshname, convert_to_dual=convert_to_dual) @@ -50,7 +50,7 @@ def create_grid_or_mesh_from_file(filename, filetype, meshname=None, add_mask = False else: add_mask = (missingvalue is not None) and (len(missingvalue) > 0) - grid_or_mesh = ESMF.Grid(filename=filename, filetype=filetype, + grid_or_mesh = esmpy.Grid(filename=filename, filetype=filetype, add_corner_stagger=add_corner_stagger, is_sphere=isSphere, add_mask=add_mask, varname=missingvalue) @@ -59,16 +59,16 @@ def create_grid_or_mesh_from_file(filename, filetype, meshname=None, def get_coords_from_grid_or_mesh(grid_or_mesh, is_mesh, regrid_method): if is_mesh: # Mesh - if regrid_method == ESMF.RegridMethod.CONSERVE: - lons = grid_or_mesh.get_coords(0, meshloc=ESMF.element) - lats = grid_or_mesh.get_coords(1, meshloc=ESMF.element) + if regrid_method == esmpy.RegridMethod.CONSERVE: + lons = grid_or_mesh.get_coords(0, meshloc=esmpy.element) + lats = grid_or_mesh.get_coords(1, meshloc=esmpy.element) else: - lons = grid_or_mesh.get_coords(0, meshloc=ESMF.node) - lats = grid_or_mesh.get_coords(1, meshloc=ESMF.node) + lons = grid_or_mesh.get_coords(0, meshloc=esmpy.node) + lats = grid_or_mesh.get_coords(1, meshloc=esmpy.node) else: # Grid - lons = grid_or_mesh.get_coords(0, staggerloc=ESMF.StaggerLoc.CENTER) - lats = grid_or_mesh.get_coords(1, staggerloc=ESMF.StaggerLoc.CENTER) + lons = grid_or_mesh.get_coords(0, staggerloc=esmpy.StaggerLoc.CENTER) + lats = grid_or_mesh.get_coords(1, staggerloc=esmpy.StaggerLoc.CENTER) # Convert to radians lons = np.radians(lons) lats = np.radians(lats) @@ -80,13 +80,13 @@ def create_field(grid, name, regrid_method=None): will be used to initialize the name of a new Field. POSTCONDITIONS: A Field has been created. ''' - if isinstance(grid,ESMF.Mesh): - if regrid_method == ESMF.RegridMethod.CONSERVE: - field = ESMF.Field(grid, name=name, meshloc=ESMF.MeshLoc.ELEMENT) + if isinstance(grid,esmpy.Mesh): + if regrid_method == esmpy.RegridMethod.CONSERVE: + field = esmpy.Field(grid, name=name, meshloc=esmpy.MeshLoc.ELEMENT) else: - field = ESMF.Field(grid, name=name, meshloc=ESMF.MeshLoc.NODE) + field = esmpy.Field(grid, name=name, meshloc=esmpy.MeshLoc.NODE) else: - field = ESMF.Field(grid, name=name) + field = esmpy.Field(grid, name=name) return field @@ -121,7 +121,7 @@ def run_regridding(srcfield, dstfield, src_mask, dst_mask, if dst_mask: dst_mask_vals = np.array([0]) - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=src_mask_vals, dst_mask_values=dst_mask_vals, regrid_method=regrid_method, @@ -130,7 +130,7 @@ def run_regridding(srcfield, dstfield, src_mask, dst_mask, dst_frac_field=dstfracfield, pole_method=pole_method, regrid_pole_npoints=regrid_pole_npoints) - dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=ESMF.Region.SELECT) + dstfield = regridSrc2Dst(srcfield, dstfield, zero_region=esmpy.Region.SELECT) regridSrc2Dst.destroy() return dstfield @@ -148,7 +148,7 @@ def parse_options(options): src_meshname = "Undefined" dst_meshname = "Undefined" pole_method_str = None - unmapped_action = ESMF.UnmappedAction.ERROR + unmapped_action = esmpy.UnmappedAction.ERROR src_regional = False dst_regional = False src_missingvalue = "" @@ -163,7 +163,7 @@ def parse_options(options): elif opt == '--dst_meshname': dst_meshname = arg elif opt == '-i' or opt == '--ignore_unmapped': - unmapped_action = ESMF.UnmappedAction.IGNORE + unmapped_action = esmpy.UnmappedAction.IGNORE elif opt == '-t': src_type_str = arg dst_type_str = arg @@ -190,7 +190,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, # print ("\nregrid_weight_gen_check.py: mesh_check()") parallel = False - if ESMF.pet_count() > 1: + if esmpy.pet_count() > 1: parallel = True # Settings for regrid @@ -200,8 +200,8 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, src_type = file_type_map[src_type_str] dst_type = file_type_map[dst_type_str] regrid_method = regrid_method_map[regrid_method] - convert_to_dual = (regrid_method != ESMF.RegridMethod.CONSERVE) - add_corner_stagger = (regrid_method == ESMF.RegridMethod.CONSERVE) + convert_to_dual = (regrid_method != esmpy.RegridMethod.CONSERVE) + add_corner_stagger = (regrid_method == esmpy.RegridMethod.CONSERVE) src_is_sphere = not src_regional dst_is_sphere = not dst_regional pole_method = None @@ -210,7 +210,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, if pole_method_str in pole_method_map: pole_method = pole_method_map[pole_method_str] else: - pole_method = ESMF.PoleMethod.NPNTAVG + pole_method = esmpy.PoleMethod.NPNTAVG pole_method_npntavg = int(pole_method_str) src_mask = False @@ -259,7 +259,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, srcmass = None dstmass = None - if regrid_method == ESMF.RegridMethod.CONSERVE: + if regrid_method == esmpy.RegridMethod.CONSERVE: if src_is_mesh: srcmass = compute_mass_mesh(srcfield, dofrac=True, fracfield=srcfracfield) @@ -290,7 +290,7 @@ def regrid_check(src_fname, dst_fname, regrid_method, options, srcfield.destroy() dstfield.destroy() dstfield2.destroy() - if regrid_method == ESMF.RegridMethod.CONSERVE: + if regrid_method == esmpy.RegridMethod.CONSERVE: srcfracfield.destroy() dstfracfield.destroy() srcgrid.destroy() diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check_driver.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check_driver.py similarity index 82% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check_driver.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check_driver.py index c11335bf6a..25edc3e0d3 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_check_driver.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check_driver.py @@ -14,29 +14,29 @@ import traceback try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') -from ESMF.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR -from ESMF.test.regrid_from_file.run_regrid_from_file_dryrun import cache_data_files_for_test_cases -from ESMF.test.regrid_from_file.regrid_check import regrid_check -from ESMF.test.regrid_from_file.read_test_cases_from_control_file import read_control_file +from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR +from esmpy.test.regrid_from_file.run_regrid_from_file_dryrun import cache_data_files_for_test_cases +from esmpy.test.regrid_from_file.regrid_check import regrid_check +from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file # Start up ESMF and run regrid test for each line of options # read from a control file. Retrieve data files for each test from a remote # server if they do not exist locally. -# Start up ESMF. -mg = ESMF.Manager(debug=True) +# Start up esmpy. +mg = esmpy.Manager(debug=True) parallel = False -if ESMF.pet_count() > 1: +if esmpy.pet_count() > 1: parallel = True # Read the test case parameters from the control file. print('Reading control file...') test_cases = read_control_file() -if (ESMF.local_pet() == 0): +if (esmpy.local_pet() == 0): # Retrieve the data files needed for the test cases from the remote server. print('Retrieving regrid_from_file data...') status_ok = cache_data_files_for_test_cases(test_cases) @@ -66,7 +66,7 @@ traceback.print_exc(file=sys.stdout) skip = False - for i in range(ESMF.pet_count()): + for i in range(esmpy.pet_count()): for line in open("PET"+str(i)+".ESMF_LogFile"): if "ESMF_NETCDF not defined when lib was compiled" in line or \ "File format is not supported" in line: @@ -80,10 +80,10 @@ print (line) # clean the log files - for i in range(ESMF.pet_count()): + for i in range(esmpy.pet_count()): os.system("echo ' ' > PET"+str(i)+".ESMF_LogFile") - print ("\nPET: " + str(ESMF.local_pet()) + " - " + test_str + " - FINISH\n") + print ("\nPET: " + str(esmpy.local_pet()) + " - " + test_str + " - FINISH\n") if skip: print ('RESULT: SKIP\n\n') diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_from_file_consts.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_from_file_consts.py new file mode 100644 index 0000000000..8e0b7fcc6f --- /dev/null +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_from_file_consts.py @@ -0,0 +1,31 @@ +""" +Constants required for the regrid from file tests. +""" +import os +try: + import esmpy +except: + raise ImportError('The ESMF library cannot be found!') +# +TEST_REGRID_DIR = 'src/esmpy/test/regrid_from_file/' +CONTROL_FNAME = 'regrid_test_data.txt' +DATA_SUBDIR = os.path.join(TEST_REGRID_DIR,'data/') +DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' +UNINITVAL = 422397696. +EPSILON = 1E-30 +# +regrid_method_map = {"bilinear" : esmpy.RegridMethod.BILINEAR, + "patch" : esmpy.RegridMethod.PATCH, + "conserve" : esmpy.RegridMethod.CONSERVE, + "neareststod" : esmpy.RegridMethod.NEAREST_STOD, + "nearestdtos" : esmpy.RegridMethod.NEAREST_DTOS} +file_type_map = {"VTK" : esmpy.FileFormat.VTK, + "SCRIP" : esmpy.FileFormat.SCRIP, + "ESMF" : esmpy.FileFormat.ESMFMESH, + "ESMFMESH" : esmpy.FileFormat.ESMFMESH, + "ESMFGRID" : esmpy.FileFormat.ESMFGRID, + "UGRID" : esmpy.FileFormat.UGRID, + "GRIDSPEC" : esmpy.FileFormat.GRIDSPEC} +pole_method_map = {"none" : esmpy.PoleMethod.NONE, + "all" : esmpy.PoleMethod.ALLAVG, + "teeth" : esmpy.PoleMethod.TEETH} diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_test_data.txt b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_test_data.txt similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/regrid_test_data.txt rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_test_data.txt diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftest.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftest.py similarity index 52% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftest.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftest.py index 788408c105..4c19cf6dfe 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftest.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftest.py @@ -6,13 +6,13 @@ import pytest -from ESMF.test.base import TestBase, attr +from esmpy.test.base import TestBase, attr class TestRFF(TestBase): # # '0' in the name is so it is run first # def test_0_regrid_from_file_dryrun(self): - # from ESMF.test.regrid_from_file import run_regrid_from_file_dryrun + # from esmpy.test.regrid_from_file import run_regrid_from_file_dryrun def test_regrid_from_file(self): - from ESMF.test.regrid_from_file import run_regrid_from_file + from esmpy.test.regrid_from_file import run_regrid_from_file diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftestdryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftestdryrun.py similarity index 51% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftestdryrun.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftestdryrun.py index dc8e40e123..2ee122f2ac 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/rfftestdryrun.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftestdryrun.py @@ -6,9 +6,9 @@ import pytest -from ESMF.test.base import TestBase, attr +from esmpy.test.base import TestBase, attr class TestRFFDryrun(TestBase): def test_regrid_from_file_dryrun(self): - from ESMF.test.regrid_from_file import run_regrid_from_file_dryrun + from esmpy.test.regrid_from_file import run_regrid_from_file_dryrun diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py similarity index 92% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py index e219c1d865..67b82288c2 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py @@ -3,8 +3,8 @@ import os import sys -import ESMF.api.constants as constants -from ESMF.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR +import esmpy.api.constants as constants +from esmpy.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR parallel = False diff --git a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py similarity index 87% rename from src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py index 88ac6ee8a4..5b7ca181b3 100644 --- a/src/addon/ESMPy/src/ESMF/test/regrid_from_file/run_regrid_from_file_dryrun.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py @@ -11,9 +11,9 @@ import sys import os -from ESMF.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR, DATA_URL_ROOT -from ESMF.util.cache_data import cache_data_file -from ESMF.test.regrid_from_file.read_test_cases_from_control_file import read_control_file +from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR, DATA_URL_ROOT +from esmpy.util.cache_data import cache_data_file +from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file def cache_data_files_for_test_cases(test_cases): # Create data subdirectory if it doesn't exist. diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/__init__.py b/src/addon/ESMPy/src/esmpy/test/test_api/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/test/test_api/__init__.py rename to src/addon/ESMPy/src/esmpy/test/test_api/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_array.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py similarity index 98% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_array.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_array.py index 7787555af3..3e4f1dfb43 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_array.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py @@ -3,9 +3,9 @@ unit test file """ -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase import numpy as np @@ -59,7 +59,7 @@ def make_maskedarray(self, array, type=TypeKind.R8): :param array: maxindices of a 2- or 3d array :type array: np.array of dtype=np.int32 :param type: the type of the esmf buffer - :type type: ESMF.TypeKind + :type type: esmpy.TypeKind ''' # create manager because we are doing some lower level stuff here without automatic initialization Manager() diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py similarity index 98% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_field.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_field.py index a77fa63dfb..8f46dd69de 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py @@ -4,10 +4,10 @@ import pytest -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr, SkipTest -from ESMF.util.mesh_utilities import mesh_create_50, mesh_create_50_parallel +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase, attr, SkipTest +from esmpy.util.mesh_utilities import mesh_create_50, mesh_create_50_parallel class TestField(TestBase): @@ -100,7 +100,6 @@ def test_numpy_funcs(self): @pytest.mark.serial @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - #nosetests src/ESMF/test/test_api/test_field.py:TestField.test_field_create_2d_grid def _field_create_2d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py similarity index 94% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py index 03e1ea73d8..37a9b57ace 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py @@ -3,10 +3,10 @@ grid unit test file """ -import ESMF -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr +import esmpy +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase, attr import numpy as np import os @@ -140,28 +140,28 @@ def make_grid_periodic(self): assert lon.size == 100 assert lat.size == 100 - grid = ESMF.Grid(np.array([lon.size, lat.size], 'int32'), + grid = esmpy.Grid(np.array([lon.size, lat.size], 'int32'), num_peri_dims=1, staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER]) - gridXCorner = grid.get_coords(0, staggerloc=ESMF.StaggerLoc.CORNER) - lon_par = lon[grid.lower_bounds[ESMF.StaggerLoc.CORNER][0]:grid.upper_bounds[ESMF.StaggerLoc.CORNER][0]] + gridXCorner = grid.get_coords(0, staggerloc=esmpy.StaggerLoc.CORNER) + lon_par = lon[grid.lower_bounds[esmpy.StaggerLoc.CORNER][0]:grid.upper_bounds[esmpy.StaggerLoc.CORNER][0]] gridXCorner[...] = lon_par.reshape((lon_par.size, 1)) - gridYCorner = grid.get_coords(1, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(1, staggerloc=esmpy.StaggerLoc.CORNER) lat_corner = np.linspace(90, -90, lat.size + 1) - lat_par = lat_corner[grid.lower_bounds[ESMF.StaggerLoc.CORNER][1]:grid.upper_bounds[ESMF.StaggerLoc.CORNER][1]] + lat_par = lat_corner[grid.lower_bounds[esmpy.StaggerLoc.CORNER][1]:grid.upper_bounds[esmpy.StaggerLoc.CORNER][1]] gridYCorner[...] = lat_par.reshape((1, lat_par.size)) offset_lon = 360. / lon.size / 2. lon -= offset_lon gridXCenter = grid.get_coords(0) - lon_par = lon[grid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] + lon_par = lon[grid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] gridXCenter[...] = lon_par.reshape((lon_par.size, 1)) offset_lat = 180. / (lat.size) / 2. lat = np.linspace(90 - offset_lat, -90 + offset_lat, lat.size) gridYCenter = grid.get_coords(1) - lat_par = lat[grid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + lat_par = lat[grid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] gridYCenter[...] = lat_par.reshape((1, lat_par.size)) @@ -283,7 +283,7 @@ def test_grid_create_cubed_sphere(self): # [DecompFlag.DEFAULT, 6]], dtype=np.int32) # deLabelList = np.array([11,12,13,14,15,16], dtype=np.int32) - ESMF.Manager(debug=True) + esmpy.Manager(debug=True) grid = Grid(tilesize = 45, regDecompPTile = regDecompPTile, #decompFlagPTile = decompFlagPTile, @@ -322,7 +322,7 @@ def test_grid_slice_2d(self): def test_grid_slice_2d_corners(self): grid = self.make_grid_2d() - grid.add_coords(staggerloc=ESMF.StaggerLoc.CORNER) + grid.add_coords(staggerloc=esmpy.StaggerLoc.CORNER) grid_row = grid.get_coords(0, staggerloc=StaggerLoc.CORNER) grid_col = grid.get_coords(1, staggerloc=StaggerLoc.CORNER) @@ -434,7 +434,7 @@ def test_grid_slice_periodic(self): def test_slice_grid_created_from_file_scrip(self): reg_decomp = [pet_count(), 1] try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, pole_kind=[PoleKind.MONOPOLE, PoleKind.BIPOLE], @@ -630,7 +630,7 @@ def test_grid_area_3D(self): assert(np.all(area[...] == 12*np.ones([10, 20, 30]))) def test_grid_create_from_file_gridspec1D(self): - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid = Grid(filename=os.path.join(esmfdir, "test/data/gridspec1Dcoords.nc"), filetype=FileFormat.GRIDSPEC, add_corner_stagger=True, coord_names=["longitude", "latitude"]) @@ -640,7 +640,7 @@ def test_grid_create_from_file_gridspec1D(self): def test_grid_create_from_file_scrip(self): reg_decomp = [pet_count(), 1] try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp) @@ -652,7 +652,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): decompflag = np.array([DecompFlag.BALANCED, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -664,7 +664,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -676,7 +676,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -689,7 +689,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): decompflag = np.array([DecompFlag.BALANCED, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -701,7 +701,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -713,7 +713,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -725,7 +725,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -738,7 +738,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -750,7 +750,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -762,7 +762,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -774,7 +774,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -787,7 +787,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -800,7 +800,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.BALANCED], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -813,7 +813,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTFIRST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -826,7 +826,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTLAST], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) @@ -839,7 +839,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_cyclic(self): decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.CYCLIC], dtype=np.int32) try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid_from_file = Grid(filename=os.path.join(esmfdir, "test/data/T42_grid.nc"), filetype=FileFormat.SCRIP, reg_decomp=reg_decomp, decompflag=decompflag) diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py similarity index 95% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py index 92a3af7c45..c1b1dbf508 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py @@ -3,9 +3,9 @@ locstream unit test file """ -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase, attr import pytest diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py similarity index 95% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py index 2faa246899..7ca0a9c9aa 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py @@ -8,10 +8,10 @@ import os import inspect -import ESMF -from ESMF import * -from ESMF.test.base import TestBase, attr, SkipTest -from ESMF.util.mesh_utilities import * +import esmpy +from esmpy import * +from esmpy.test.base import TestBase, attr, SkipTest +from esmpy.util.mesh_utilities import * class TestMesh(TestBase): mg = Manager(debug=True) @@ -178,7 +178,7 @@ def test_mesh_50_mask_area(self): def test_mesh_create_from_file_scrip(self): try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), filetype=FileFormat.SCRIP) except: @@ -186,7 +186,7 @@ def test_mesh_create_from_file_scrip(self): def test_mesh_create_from_file_esmfmesh(self): try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), filetype=FileFormat.ESMFMESH) except: @@ -253,7 +253,7 @@ def test_mesh_slicing(self): @pytest.mark.serial def test_slice_mesh_created_from_file_scrip(self): try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), filetype=FileFormat.SCRIP, convert_to_dual=True) @@ -276,7 +276,7 @@ def test_slice_mesh_created_from_file_scrip(self): @pytest.mark.serial def test_slice_mesh_created_from_file_esmfmesh(self): try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), filetype=FileFormat.ESMFMESH) except: @@ -301,7 +301,7 @@ def test_slice_mesh_created_from_file_esmfmesh(self): # TODO: have to define slicing for mesh element coordinates as well.. def test_slice_mesh_created_from_file_elem_coords(self): try: - esmfdir = os.path.dirname(inspect.getfile(ESMF)) + esmfdir = os.path.dirname(inspect.getfile(esmpy)) mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne30np4-t2.nc"), filetype=FileFormat.SCRIP) except: diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py similarity index 78% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py index aaac4f78cd..d25f712cc4 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py @@ -6,11 +6,11 @@ import os -from ESMF import * -from ESMF.test.base import TestBase, attr, SkipTest -from ESMF.util.field_utilities import compare_fields -from ESMF.util.grid_utilities import * -from ESMF.util.mesh_utilities import * +from esmpy import * +from esmpy.test.base import TestBase, attr, SkipTest +from esmpy.util.field_utilities import compare_fields +from esmpy.util.grid_utilities import * +from esmpy.util.mesh_utilities import * class TestRegrid(TestBase): @@ -31,9 +31,9 @@ def run_regridding(srcfield, dstfield, srcfracfield, dstfracfield): Field :: dstfracfield \n ''' # call the regridding functions - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -248,9 +248,9 @@ def test_field_regrid_file2(self): os.remove(path) mgr.barrier() - srcgrid = ESMF.Grid(np.array([20, 20]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG) + srcgrid = esmpy.Grid(np.array([20, 20]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(0) @@ -260,8 +260,8 @@ def test_field_regrid_file2(self): lats = np.linspace(-60, 60, 20) # parallel coordinates - slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(slons_par, slats_par, indexing='ij') @@ -269,9 +269,9 @@ def test_field_regrid_file2(self): srcGridCoordLon[:] = lonm srcGridCoordLat[:] = latm - dstgrid = ESMF.Grid(np.array([10, 10]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.SPH_DEG) + dstgrid = esmpy.Grid(np.array([10, 10]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.SPH_DEG) # Get and set the source grid coordinates. dstGridCoordLon = dstgrid.get_coords(0) @@ -281,8 +281,8 @@ def test_field_regrid_file2(self): lats = np.linspace(-60, 60, 10) # parallel coordinates - dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -290,12 +290,12 @@ def test_field_regrid_file2(self): dstGridCoordLon[:] = lonm dstGridCoordLat[:] = latm - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) - _ = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + _ = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) mgr.barrier() self.assertTrue(os.path.exists(filename)) @@ -316,7 +316,7 @@ def tet_field_regrid_file_withaux(self): DD = os.path.join(os.getcwd(), "test/data") if not os.path.isdir(DD): os.makedirs(DD) - from ESMF.util.cache_data import cache_data_file + from esmpy.util.cache_data import cache_data_file cache_data_file(os.path.join(DD, "ll2.5deg_grid.nc")) cache_data_file(os.path.join(DD, "T42_grid.nc")) @@ -329,21 +329,21 @@ def tet_field_regrid_file_withaux(self): mgr.barrier() grid1 = "test/data/ll2.5deg_grid.nc" - srcgrid = ESMF.Grid(filename=grid1, filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True) + srcgrid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) grid2 = "test/data/T42_grid.nc" - dstgrid = ESMF.Grid(filename=grid2, filetype=ESMF.FileFormat.SCRIP, add_corner_stagger=True) + dstgrid = esmpy.Grid(filename=grid2, filetype=esmpy.FileFormat.SCRIP, add_corner_stagger=True) - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) - _ = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE, - filemode=ESMF.FileMode.WITHAUX, + _ = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE, + filemode=esmpy.FileMode.WITHAUX, src_file=grid1, dst_file=grid2, - src_file_type=ESMF.FileFormat.SCRIP, - dst_file_type=ESMF.FileFormat.SCRIP) + src_file_type=esmpy.FileFormat.SCRIP, + dst_file_type=esmpy.FileFormat.SCRIP) mgr.barrier() self.assertTrue(os.path.exists(filename)) @@ -385,9 +385,9 @@ def test_field_regrid_file3(self): os.remove(path) mgr.barrier() - srcgrid = ESMF.Grid(np.array([20, 20]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + srcgrid = esmpy.Grid(np.array([20, 20]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(0) @@ -397,8 +397,8 @@ def test_field_regrid_file3(self): lats = np.linspace(-60, 60, 20) # parallel coordinates - slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(slons_par, slats_par, indexing='ij') @@ -406,9 +406,9 @@ def test_field_regrid_file3(self): srcGridCoordLon[:] = lonm srcGridCoordLat[:] = latm - dstgrid = ESMF.Grid(np.array([10, 10]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + dstgrid = esmpy.Grid(np.array([10, 10]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. dstGridCoordLon = dstgrid.get_coords(0) @@ -418,8 +418,8 @@ def test_field_regrid_file3(self): lats = np.linspace(-60, 60, 10) # parallel coordinates - dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -428,9 +428,9 @@ def test_field_regrid_file3(self): dstGridCoordLat[:] = latm - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) - xctfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) + xctfield = esmpy.Field(dstgrid) srcfield.data[:,:] = 24 xctfield.data[:,:] = 24 @@ -439,9 +439,9 @@ def test_field_regrid_file3(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertTrue(np.all(dstfield.data[:,:] == 0)) - regridS2D = ESMF.Regrid(srcfield, dstfield, filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridS2D = esmpy.Regrid(srcfield, dstfield, filename=filename, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR, create_rh=True, ignore_degenerate=False) mgr.barrier() @@ -451,7 +451,7 @@ def test_field_regrid_file3(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertNumpyAllClose(xctfield.data, dstfield.data) - regridS2D = ESMF.RegridFromFile(srcfield, dstfield, filename) + regridS2D = esmpy.RegridFromFile(srcfield, dstfield, filename) mgr.barrier() self.assertTrue(np.all(srcfield.data[:,:] == 24)) @@ -480,9 +480,9 @@ def test_field_regrid_file4(self): os.remove(path) mgr.barrier() - srcgrid = ESMF.Grid(np.array([20, 20]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + srcgrid = esmpy.Grid(np.array([20, 20]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. srcGridCoordLon = srcgrid.get_coords(0) @@ -492,8 +492,8 @@ def test_field_regrid_file4(self): lats = np.linspace(-60, 60, 20) # parallel coordinates - slons_par = lons[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - slats_par = lats[srcgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + slons_par = lons[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + slats_par = lats[srcgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:srcgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(slons_par, slats_par, indexing='ij') @@ -501,9 +501,9 @@ def test_field_regrid_file4(self): srcGridCoordLon[:] = lonm srcGridCoordLat[:] = latm - dstgrid = ESMF.Grid(np.array([10, 10]), - staggerloc=ESMF.StaggerLoc.CENTER, - coord_sys=ESMF.CoordSys.CART) + dstgrid = esmpy.Grid(np.array([10, 10]), + staggerloc=esmpy.StaggerLoc.CENTER, + coord_sys=esmpy.CoordSys.CART) # Get and set the source grid coordinates. dstGridCoordLon = dstgrid.get_coords(0) @@ -513,8 +513,8 @@ def test_field_regrid_file4(self): lats = np.linspace(-60, 60, 10) # parallel coordinates - dlons_par = lons[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][0]] - dlats_par = lats[dstgrid.lower_bounds[ESMF.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[ESMF.StaggerLoc.CENTER][1]] + dlons_par = lons[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + dlats_par = lats[dstgrid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:dstgrid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] # make sure to use indexing='ij' as ESMPy backend uses matrix indexing (not Cartesian) lonm, latm = np.meshgrid(dlons_par, dlats_par, indexing='ij') @@ -523,9 +523,9 @@ def test_field_regrid_file4(self): dstGridCoordLat[:] = latm - srcfield = ESMF.Field(srcgrid) - dstfield = ESMF.Field(dstgrid) - xctfield = ESMF.Field(dstgrid) + srcfield = esmpy.Field(srcgrid) + dstfield = esmpy.Field(dstgrid) + xctfield = esmpy.Field(dstgrid) srcfield.data[:,:] = 24 xctfield.data[:,:] = 24 @@ -534,10 +534,10 @@ def test_field_regrid_file4(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertTrue(np.all(dstfield.data[:,:] == 0)) - regridS2D = ESMF.Regrid(srcfield, dstfield, + regridS2D = esmpy.Regrid(srcfield, dstfield, rh_filename=filename, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR, create_rh=True, ignore_degenerate=False) mgr.barrier() @@ -547,7 +547,7 @@ def test_field_regrid_file4(self): self.assertTrue(np.all(srcfield.data[:,:] == 24)) self.assertNumpyAllClose(xctfield.data, dstfield.data) - regridS2D = ESMF.RegridFromFile(srcfield, dstfield, rh_filename=filename) + regridS2D = esmpy.RegridFromFile(srcfield, dstfield, rh_filename=filename) mgr.barrier() self.assertTrue(np.all(srcfield.data[:,:] == 24)) @@ -697,13 +697,13 @@ def test_field_regrid_zeroregion_select_ndbounds(self): # Compute the regrid from file route handle rh2 = RegridFromFile(srcfield, dstfield, filename=filename) self.assertTrue(np.all(dstfield.data == -999)) - dstfield = rh2(srcfield, dstfield, zero_region=ESMF.Region.SELECT) + dstfield = rh2(srcfield, dstfield, zero_region=esmpy.Region.SELECT) # Assert fill values are retained self.assertGreater(np.sum(dstfield.data == 33.33), 10) self.assertGreater(np.sum(dstfield.data == -999), 10) - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): if os.path.exists(filename): os.remove(filename) @@ -764,23 +764,23 @@ def test_field_regrid_periodic(self): dstgrid = grid_create_from_bounds_periodic(55, 28, corners=True) # create the Fields - srcfield = ESMF.Field(srcgrid, name='srcfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # create the fraction fields - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_periodic(srcfield) exact_field = initialize_field_grid_periodic(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -808,18 +808,18 @@ def test_grid_grid_3d_bilinear_cartesian(self): dstgrid = grid_create_from_bounds_3d([0.5, 19.5], [0.5, 19.5], [0.5, 19.5], 19, 19, 19, corners=False) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_3d(srcfield) exactfield = initialize_field_grid_3d(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL @@ -838,18 +838,18 @@ def test_grid_grid_3d_bilinear_spherical(self): dstgrid = grid_create_from_bounds_periodic_3d(50, 50, 11, corners=False) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_periodic_3d(srcfield) exactfield = initialize_field_grid_periodic_3d(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL @@ -868,20 +868,20 @@ def test_grid_grid_regrid_csrv_mask_3D(self): dstgrid = grid_create_from_bounds_3d([0.5, 19.5], [0.5, 19.5], [0.5, 19.5], 19, 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid_3d(srcfield) exactfield = initialize_field_grid_3d(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -909,21 +909,21 @@ def test_grid_grid_regrid_csrv_mask(self): dstgrid = grid_create_from_bounds([0.5, 19.5], [0.5, 19.5], 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) dstfield2 = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -951,21 +951,21 @@ def test_grid_grid_regrid_csrv_2nd_mask(self): dstgrid = grid_create_from_bounds([0.5, 19.5], [0.5, 19.5], 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) dstfield2 = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE_2ND, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.CONSERVE_2ND, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -993,25 +993,25 @@ def test_grid_grid_regrid_srcmask_types(self): # create two unique Grid objects srcgrid = grid_create_from_bounds([0, 21], [0, 21], 21, 21, corners=True, domask=True, - ctk=ESMF.TypeKind.R4) + ctk=esmpy.TypeKind.R4) dstgrid = grid_create_from_bounds([0.5, 19.5], [0.5, 19.5], 19, 19, corners=True) # create Field objects on the Meshes - srcfield = ESMF.Field(srcgrid, name='srcfield') - srcfracfield = ESMF.Field(srcgrid, name='srcfracfield') - dstfield = ESMF.Field(dstgrid, name='dstfield') - dstfracfield = ESMF.Field(dstgrid, name='dstfracfield') - exactfield = ESMF.Field(dstgrid, name='exactfield') + srcfield = esmpy.Field(srcgrid, name='srcfield') + srcfracfield = esmpy.Field(srcgrid, name='srcfracfield') + dstfield = esmpy.Field(dstgrid, name='dstfield') + dstfracfield = esmpy.Field(dstgrid, name='dstfracfield') + exactfield = esmpy.Field(dstgrid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) dstfield2 = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=[0], - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1052,13 +1052,13 @@ def test_grid_mesh_regrid_csrv_mask(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn, @@ -1066,10 +1066,10 @@ def test_grid_mesh_regrid_csrv_mask(self): exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1110,21 +1110,21 @@ def test_grid_mesh_regrid_csrv(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) # create Fields - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - norm_type=ESMF.NormType.FRACAREA, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + norm_type=esmpy.NormType.FRACAREA, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1166,25 +1166,25 @@ def test_grid_mesh_regrid_mask(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(mesh, name='srcfield') - dstfield = ESMF.Field(grid, name='dstfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='srcfield') + dstfield = esmpy.Field(grid, name='dstfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield, domask=True) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, dst_mask_values=np.array([0]), - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.IGNORE) + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.IGNORE) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 20E-1, 20E-1, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) @@ -1211,24 +1211,24 @@ def test_grid_mesh_regrid(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(mesh, name='srcfield') - dstfield = ESMF.Field(grid, name='dstfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='srcfield') + dstfield = esmpy.Field(grid, name='dstfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 40E-2, 40E-2, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) @@ -1255,27 +1255,27 @@ def test_field_regrid_extrapolation(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(grid, name='srcfield') - dstfield = ESMF.Field(mesh, name='dstfield') - exactfield = ESMF.Field(mesh, name='exactfield') + srcfield = esmpy.Field(grid, name='srcfield') + dstfield = esmpy.Field(mesh, name='dstfield') + exactfield = esmpy.Field(mesh, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_grid(srcfield) exactfield = initialize_field_mesh(exactfield, nodeCoord, nodeOwner, elemType, elemConn) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - extrap_method=ESMF.ExtrapMethod.NEAREST_IDAVG, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + extrap_method=esmpy.ExtrapMethod.NEAREST_IDAVG, extrap_num_src_pnts=10, extrap_dist_exponent=1.2, - unmapped_action=ESMF.UnmappedAction.ERROR) + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 40E-2, 40E-2, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) @@ -1302,25 +1302,25 @@ def test_field_regrid_extrapolation_creepfill(self): mesh_create_50() # create Field objects - srcfield = ESMF.Field(mesh, name='dstfield') - dstfield = ESMF.Field(grid, name='srcfield') - exactfield = ESMF.Field(grid, name='exactfield') + srcfield = esmpy.Field(mesh, name='dstfield') + dstfield = esmpy.Field(grid, name='srcfield') + exactfield = esmpy.Field(grid, name='exactfield') # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) exactfield = initialize_field_grid(exactfield) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - extrap_method=ESMF.ExtrapMethod.CREEP_FILL, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + extrap_method=esmpy.ExtrapMethod.CREEP_FILL, extrap_num_levels=100) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL meanrel, csrvrel, correct = compare_fields(dstfield, exactfield, 40E-2, 40E-2, 10E-16, - regrid_method=ESMF.RegridMethod.BILINEAR) + regrid_method=esmpy.RegridMethod.BILINEAR) self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) @@ -1348,11 +1348,11 @@ def test_mesh_mesh_regrid(self): mesh_create_10() # create ESMP_Field objects on the Meshes - srcfield = ESMF.Field(srcmesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(srcmesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) - dstfield = ESMF.Field(dstmesh, name='dstfield', meshloc=ESMF.MeshLoc.ELEMENT) - dstfracfield = ESMF.Field(dstmesh, name='dstfracfield', meshloc=ESMF.MeshLoc.ELEMENT) - exactfield = ESMF.Field(dstmesh, name='exactfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(srcmesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(srcmesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) + dstfield = esmpy.Field(dstmesh, name='dstfield', meshloc=esmpy.MeshLoc.ELEMENT) + dstfracfield = esmpy.Field(dstmesh, name='dstfracfield', meshloc=esmpy.MeshLoc.ELEMENT) + exactfield = esmpy.Field(dstmesh, name='exactfield', meshloc=esmpy.MeshLoc.ELEMENT) # initialize the Fields to an analytic function srcfield = initialize_field_mesh(srcfield, nodeCoordSrc, nodeOwnerSrc, @@ -1361,10 +1361,10 @@ def test_mesh_mesh_regrid(self): elemTypeDst, elemConnDst) # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - norm_type=ESMF.NormType.FRACAREA, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + norm_type=esmpy.NormType.FRACAREA, + unmapped_action=esmpy.UnmappedAction.ERROR, ignore_degenerate=True, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) @@ -1407,13 +1407,13 @@ def est_grid_mesh_pentatri_regrid_csrv(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') # initialize the Fields to an analytic function # srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) @@ -1423,9 +1423,9 @@ def est_grid_mesh_pentatri_regrid_csrv(self): exactfield.data[...] = 25. # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1446,7 +1446,7 @@ def est_grid_mesh_pentatri_regrid_csrv(self): # TODO: this test is disable, I don't remember why def est_grid_mesh_pentatri_regrid_csrv_simple(self): - if ESMF.pet_count() > 1: + if esmpy.pet_count() > 1: raise NameError('This test can only be run in serial!') # create a Mesh @@ -1457,13 +1457,13 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.ELEMENT) - srcfracfield = ESMF.Field(mesh, name='srcfracfield', meshloc=ESMF.MeshLoc.ELEMENT) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.ELEMENT) + srcfracfield = esmpy.Field(mesh, name='srcfracfield', meshloc=esmpy.MeshLoc.ELEMENT) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') - dstfracfield = ESMF.Field(grid, name='dstfracfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') + dstfracfield = esmpy.Field(grid, name='dstfracfield') # initialize the Fields to an analytic function # srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) @@ -1473,9 +1473,9 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): exactfield.data[...] = 25. # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.CONSERVE, - unmapped_action=ESMF.UnmappedAction.ERROR, + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.CONSERVE, + unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, dst_frac_field=dstfracfield) dstfield = regridSrc2Dst(srcfield, dstfield) @@ -1516,11 +1516,11 @@ def test_grid_mesh_pentatri_regrid_bilinear(self): grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, doarea=True) # create Field objects on the Meshes - srcfield = ESMF.Field(mesh, name='srcfield', meshloc=ESMF.MeshLoc.NODE) + srcfield = esmpy.Field(mesh, name='srcfield', meshloc=esmpy.MeshLoc.NODE) # make gridded fields - exactfield = ESMF.Field(grid, name='exactfield') - dstfield = ESMF.Field(grid, name='dstfield') + exactfield = esmpy.Field(grid, name='exactfield') + dstfield = esmpy.Field(grid, name='dstfield') # initialize the Fields to an analytic function # srcfield = initialize_field_mesh(srcfield, nodeCoord, nodeOwner, elemType, elemConn) @@ -1530,9 +1530,9 @@ def test_grid_mesh_pentatri_regrid_bilinear(self): exactfield.data[...] = 25. # run the ESMF regridding - regridSrc2Dst = ESMF.Regrid(srcfield, dstfield, - regrid_method=ESMF.RegridMethod.BILINEAR, - unmapped_action=ESMF.UnmappedAction.ERROR) + regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, + regrid_method=esmpy.RegridMethod.BILINEAR, + unmapped_action=esmpy.UnmappedAction.ERROR) dstfield = regridSrc2Dst(srcfield, dstfield) # compare results and output PASS or FAIL diff --git a/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py similarity index 89% rename from src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py rename to src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py index 52234f2b25..4f3a544a18 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_api/test_vm.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py @@ -2,9 +2,9 @@ vm unit test file """ -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase, attr import pytest diff --git a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py b/src/addon/ESMPy/src/esmpy/test/test_cbindings.py similarity index 95% rename from src/addon/ESMPy/src/ESMF/test/test_cbindings.py rename to src/addon/ESMPy/src/esmpy/test/test_cbindings.py index 2099857328..30185967c2 100644 --- a/src/addon/ESMPy/src/ESMF/test/test_cbindings.py +++ b/src/addon/ESMPy/src/esmpy/test/test_cbindings.py @@ -6,9 +6,9 @@ import pytest -from ESMF import * -from ESMF.interface.cbindings import * -from ESMF.test.base import TestBase, attr +from esmpy import * +from esmpy.interface.cbindings import * +from esmpy.test.base import TestBase, attr import numpy as np diff --git a/src/addon/ESMPy/src/ESMF/util/__init__.py b/src/addon/ESMPy/src/esmpy/util/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/__init__.py rename to src/addon/ESMPy/src/esmpy/util/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/util/cache_data.py b/src/addon/ESMPy/src/esmpy/util/cache_data.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/cache_data.py rename to src/addon/ESMPy/src/esmpy/util/cache_data.py diff --git a/src/addon/ESMPy/src/ESMF/util/decorators.py b/src/addon/ESMPy/src/esmpy/util/decorators.py similarity index 91% rename from src/addon/ESMPy/src/ESMF/util/decorators.py rename to src/addon/ESMPy/src/esmpy/util/decorators.py index b3a297d9c9..c6ceea769c 100644 --- a/src/addon/ESMPy/src/ESMF/util/decorators.py +++ b/src/addon/ESMPy/src/esmpy/util/decorators.py @@ -9,8 +9,8 @@ import warnings import functools -from ESMF.api.constants import LogKind, _ESMF_NETCDF -from ESMF.util.exceptions import NetCDFMissing +from esmpy.api.constants import LogKind, _ESMF_NETCDF +from esmpy.util.exceptions import NetCDFMissing def beta(func): '''This is a decorator that can be used to mark functions @@ -53,7 +53,7 @@ def initialize(func): @functools.wraps(func) def new_func(*args, **kwargs): - from ESMF.api import esmpymanager + from esmpy.api import esmpymanager esmp = esmpymanager.Manager(debug = False) return func(*args, **kwargs) @@ -65,7 +65,7 @@ def netcdf(func): @functools.wraps(func) def new_func(*args, **kwargs): - from ESMF.api.constants import _ESMF_NETCDF + from esmpy.api.constants import _ESMF_NETCDF if _ESMF_NETCDF: return func(*args, **kwargs) diff --git a/src/addon/ESMPy/src/ESMF/util/enum/LICENSE b/src/addon/ESMPy/src/esmpy/util/enum/LICENSE similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/LICENSE rename to src/addon/ESMPy/src/esmpy/util/enum/LICENSE diff --git a/src/addon/ESMPy/src/ESMF/util/enum/README b/src/addon/ESMPy/src/esmpy/util/enum/README similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/README rename to src/addon/ESMPy/src/esmpy/util/enum/README diff --git a/src/addon/ESMPy/src/ESMF/util/enum/__init__.py b/src/addon/ESMPy/src/esmpy/util/enum/__init__.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/__init__.py rename to src/addon/ESMPy/src/esmpy/util/enum/__init__.py diff --git a/src/addon/ESMPy/src/ESMF/util/enum/doc/enum.pdf b/src/addon/ESMPy/src/esmpy/util/enum/doc/enum.pdf similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/doc/enum.pdf rename to src/addon/ESMPy/src/esmpy/util/enum/doc/enum.pdf diff --git a/src/addon/ESMPy/src/ESMF/util/enum/doc/enum.rst b/src/addon/ESMPy/src/esmpy/util/enum/doc/enum.rst similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/enum/doc/enum.rst rename to src/addon/ESMPy/src/esmpy/util/enum/doc/enum.rst diff --git a/src/addon/ESMPy/src/ESMF/util/esmpyarray.py b/src/addon/ESMPy/src/esmpy/util/esmpyarray.py similarity index 97% rename from src/addon/ESMPy/src/ESMF/util/esmpyarray.py rename to src/addon/ESMPy/src/esmpy/util/esmpyarray.py index 0683eae8fc..9bb7605c17 100755 --- a/src/addon/ESMPy/src/ESMF/util/esmpyarray.py +++ b/src/addon/ESMPy/src/esmpy/util/esmpyarray.py @@ -5,7 +5,7 @@ """ #### IMPORT LIBRARIES ######################################################### -import ESMF.api.constants as constants +import esmpy.api.constants as constants import numpy as np import numpy.ma as ma import ctypes as ct @@ -16,7 +16,7 @@ def ndarray_from_esmf(data, dtype, shape): :param data: buffer of fortran allocated ESMF array :type data: ctypes void_p :param dtype: the type of the esmf buffer - :type dtype: ESMF.TypeKind + :type dtype: esmpy.TypeKind :param shape: N-D Python shape corresponding to 1D ESMF allocation :type shape: list or tuple :return: numpy array representing the data with dtype and shape @@ -50,7 +50,7 @@ def __new__(cls, data, mask, dtype, shape): :param mask: mask corresponding to the fortran allocated ESMF array :type mask: list :param dtype: the type of the esmf buffer - :type dtype: ESMF.TypeKind + :type dtype: esmpy.TypeKind :param shape: N-D Python shape corresponding to 1D ESMF allocation :type shape: list or tuple :return: MaskedArray object @@ -93,7 +93,7 @@ def __new__(cls, data, dtype, shape): :param data: buffer of fortran allocated ESMF array :type data: ctypes void_p :param dtype: the type of the esmf buffer - :type dtype: ESMF.TypeKind + :type dtype: esmpy.TypeKind :param shape: N-D Python shape corresponding to 1D ESMF allocation :type shape: list or tuple :return: Array object diff --git a/src/addon/ESMPy/src/ESMF/util/exceptions.py b/src/addon/ESMPy/src/esmpy/util/exceptions.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/exceptions.py rename to src/addon/ESMPy/src/esmpy/util/exceptions.py diff --git a/src/addon/ESMPy/src/ESMF/util/field_utilities.py b/src/addon/ESMPy/src/esmpy/util/field_utilities.py similarity index 93% rename from src/addon/ESMPy/src/ESMF/util/field_utilities.py rename to src/addon/ESMPy/src/esmpy/util/field_utilities.py index af85c5977f..122526cfc1 100644 --- a/src/addon/ESMPy/src/ESMF/util/field_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/field_utilities.py @@ -3,14 +3,14 @@ """ import numpy as np -import ESMF +import esmpy -import ESMF.util.helpers as helpers -import ESMF.api.constants as constants +import esmpy.util.helpers as helpers +import esmpy.api.constants as constants def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, dstfracfield=None, mass1=None, mass2=None, - regrid_method=ESMF.RegridMethod.CONSERVE, + regrid_method=esmpy.RegridMethod.CONSERVE, uninitval=422397696., mask_values=[0]): """ Compare the values of two fields to verify the accuracy of a Regrid. The @@ -32,7 +32,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, import numpy.ma as ma parallel = False - if ESMF.pet_count() > 1: + if esmpy.pet_count() > 1: parallel = True correct = False @@ -54,7 +54,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, field2_flat = np.ravel(field2.data) dstfracfield_flat = np.ravel(dstfracfield.data) # setup mask, no Mask on a Mesh (yet) so need to look at the type first - if (isinstance(field2.grid, ESMF.Grid)) and \ + if (isinstance(field2.grid, esmpy.Grid)) and \ (not isinstance(field2.grid.mask[field2.staggerloc], type(None))): if not isinstance(field2.grid.mask[field2.staggerloc], type(None)): field2mask_flat = [True if x in mask_values else False for x in field2.grid.mask[field2.staggerloc].flatten().tolist()] @@ -105,7 +105,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, itrp_mean = False itrp_max = False csrv = False - if ESMF.local_pet() == 0: + if esmpy.local_pet() == 0: if mass1_global == 0.: csrv_error_global = abs(mass2_global - mass1_global) else: @@ -140,9 +140,9 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, # print pass or fail if (itrp_mean and itrp_max and csrv): - print ("PET{0} - PASS".format(ESMF.local_pet())) + print ("PET{0} - PASS".format(esmpy.local_pet())) correct = True else: - print ("PET{0} - FAIL".format(ESMF.local_pet())) + print ("PET{0} - FAIL".format(esmpy.local_pet())) return total_error_global, csrv_error_global, correct \ No newline at end of file diff --git a/src/addon/ESMPy/src/ESMF/util/grid_utilities.py b/src/addon/ESMPy/src/esmpy/util/grid_utilities.py similarity index 78% rename from src/addon/ESMPy/src/ESMF/util/grid_utilities.py rename to src/addon/ESMPy/src/esmpy/util/grid_utilities.py index 2227f3bb62..83597f85ca 100644 --- a/src/addon/ESMPy/src/ESMF/util/grid_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/grid_utilities.py @@ -10,11 +10,11 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') -def grid_create_from_bounds(xdom, ydom, nx, ny, corners=False, domask=False, doarea=False, ctk=ESMF.TypeKind.R8): +def grid_create_from_bounds(xdom, ydom, nx, ny, corners=False, domask=False, doarea=False, ctk=esmpy.TypeKind.R8): """ Create a 2 dimensional Grid using the bounds of the domain defined in the `xdom` and `ydom` lists. The parameters `nx` and `ny` are used to define the number coordinate points between the bounds of the domain. @@ -45,7 +45,7 @@ def grid_create_from_bounds(xdom, ydom, nx, ny, corners=False, domask=False, doa return grid -def grid_create_from_coordinates(xcoords, ycoords, xcorners=False, ycorners=False, corners=False, domask=False, doarea=False, ctk=ESMF.TypeKind.R8): +def grid_create_from_coordinates(xcoords, ycoords, xcorners=False, ycorners=False, corners=False, domask=False, doarea=False, ctk=esmpy.TypeKind.R8): """ Create a 2 dimensional Grid using the bounds of the x and y coordiantes. :param xcoords: The 1st dimension or 'x' coordinates at cell centers, as a Python list or numpy Array @@ -62,45 +62,45 @@ def grid_create_from_coordinates(xcoords, ycoords, xcorners=False, ycorners=Fals # create a grid given the number of grid cells in each dimension, the center stagger location is allocated, the # Cartesian coordinate system and type of the coordinates are specified max_index = np.array([len(xcoords), len(ycoords)]) - grid = ESMF.Grid(max_index, staggerloc=[ESMF.StaggerLoc.CENTER], coord_sys=ESMF.CoordSys.CART, coord_typekind=ctk) + grid = esmpy.Grid(max_index, staggerloc=[esmpy.StaggerLoc.CENTER], coord_sys=esmpy.CoordSys.CART, coord_typekind=ctk) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(x) - x_par = xcoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER][x]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][x]] + x_par = xcoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER][x]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][x]] gridXCenter[...] = x_par.reshape((x_par.size, 1)) gridYCenter = grid.get_coords(y) - y_par = ycoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER][y]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][y]] + y_par = ycoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER][y]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][y]] gridYCenter[...] = y_par.reshape((1, y_par.size)) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER][x] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER][x] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER][y] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER][y] + grid.add_coords([esmpy.StaggerLoc.CORNER]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER][x] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER][x] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER][y] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER][y] - gridXCorner = grid.get_coords(x, staggerloc=ESMF.StaggerLoc.CORNER) + gridXCorner = grid.get_coords(x, staggerloc=esmpy.StaggerLoc.CORNER) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :] = xcorners[i0+lbx, 0] gridXCorner[i0 + 1, :] = xcorners[i0+lbx, 1] - gridYCorner = grid.get_coords(y, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(y, staggerloc=esmpy.StaggerLoc.CORNER) for i1 in range(uby - lby - 1): gridYCorner[:, i1] = ycorners[i1+lby, 0] gridYCorner[:, i1 + 1] = ycorners[i1+lby, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 <= gridXCenter.any() < 2.25) & (1.75 <= gridYCenter.any() < 2.25))] = 0 # add arbitrary areas values if doarea: - area = grid.add_item(ESMF.GridItem.AREA) + area = grid.add_item(esmpy.GridItem.AREA) area[:] = 5.0 return grid @@ -147,38 +147,38 @@ def grid_create_from_coordinates_periodic(longitudes, latitudes, lon_corners=Fal # create a grid given the number of grid cells in each dimension the center stagger location is allocated max_index = np.array([len(longitudes), len(latitudes)]) - grid = ESMF.Grid(max_index, num_peri_dims=1, staggerloc=[ESMF.StaggerLoc.CENTER]) + grid = esmpy.Grid(max_index, num_peri_dims=1, staggerloc=[esmpy.StaggerLoc.CENTER]) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(lon) - lon_par = longitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lon]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lon]] + lon_par = longitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lon]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lon]] gridXCenter[...] = lon_par.reshape((lon_par.size, 1)) gridYCenter = grid.get_coords(lat) - lat_par = latitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lat]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lat]] + lat_par = latitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lat]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lat]] gridYCenter[...] = lat_par.reshape((1, lat_par.size)) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lon] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lon] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lat] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lat] + grid.add_coords([esmpy.StaggerLoc.CORNER]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lon] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lon] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lat] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lat] - gridXCorner = grid.get_coords(lon, staggerloc=ESMF.StaggerLoc.CORNER) + gridXCorner = grid.get_coords(lon, staggerloc=esmpy.StaggerLoc.CORNER) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :] = lon_corners[i0+lbx, 0] gridXCorner[i0 + 1, :] = lon_corners[i0+lbx, 1] - gridYCorner = grid.get_coords(lat, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(lat, staggerloc=esmpy.StaggerLoc.CORNER) for i1 in range(uby - lby - 1): gridYCorner[:, i1] = lat_corners[i1+lby, 0] gridYCorner[:, i1 + 1] = lat_corners[i1+lby, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 <= gridXCenter.any() < 2.25) & (1.75 <= gridYCenter.any() < 2.25))] = 0 @@ -242,49 +242,49 @@ def grid_create_from_coordinates_3d(xcoords, ycoords, zcoords, xcorners=False, y # create a grid given the number of grid cells in each dimension, the center stagger location is allocated and the # Cartesian coordinate system is specified max_index = np.array([len(xcoords), len(ycoords), len(zcoords)]) - grid = ESMF.Grid(max_index, staggerloc=[ESMF.StaggerLoc.CENTER_VCENTER], coord_sys=ESMF.CoordSys.CART) + grid = esmpy.Grid(max_index, staggerloc=[esmpy.StaggerLoc.CENTER_VCENTER], coord_sys=esmpy.CoordSys.CART) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(x) - x_par = xcoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER_VCENTER][x]:grid.upper_bounds[ESMF.StaggerLoc.CENTER_VCENTER][x]] + x_par = xcoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER_VCENTER][x]:grid.upper_bounds[esmpy.StaggerLoc.CENTER_VCENTER][x]] gridXCenter[...] = x_par.reshape(x_par.size, 1, 1) gridYCenter = grid.get_coords(y) - y_par = ycoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER_VCENTER][y]:grid.upper_bounds[ESMF.StaggerLoc.CENTER_VCENTER][y]] + y_par = ycoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER_VCENTER][y]:grid.upper_bounds[esmpy.StaggerLoc.CENTER_VCENTER][y]] gridYCenter[...] = y_par.reshape(1, y_par.size, 1) gridZCenter = grid.get_coords(z) - z_par = zcoords[grid.lower_bounds[ESMF.StaggerLoc.CENTER_VCENTER][z]:grid.upper_bounds[ESMF.StaggerLoc.CENTER_VCENTER][z]] + z_par = zcoords[grid.lower_bounds[esmpy.StaggerLoc.CENTER_VCENTER][z]:grid.upper_bounds[esmpy.StaggerLoc.CENTER_VCENTER][z]] gridZCenter[...] = z_par.reshape(1, 1, z_par.size) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER_VFACE]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER_VFACE][x] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER_VFACE][x] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER_VFACE][y] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER_VFACE][y] - lbz = grid.lower_bounds[ESMF.StaggerLoc.CORNER_VFACE][z] - ubz = grid.upper_bounds[ESMF.StaggerLoc.CORNER_VFACE][z] - - gridXCorner = grid.get_coords(x, staggerloc=ESMF.StaggerLoc.CORNER_VFACE) + grid.add_coords([esmpy.StaggerLoc.CORNER_VFACE]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER_VFACE][x] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER_VFACE][x] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER_VFACE][y] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER_VFACE][y] + lbz = grid.lower_bounds[esmpy.StaggerLoc.CORNER_VFACE][z] + ubz = grid.upper_bounds[esmpy.StaggerLoc.CORNER_VFACE][z] + + gridXCorner = grid.get_coords(x, staggerloc=esmpy.StaggerLoc.CORNER_VFACE) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :, :] = xcorners[i0+lbx, 0] gridXCorner[i0 + 1, :, :] = xcorners[i0+lbx, 1] - gridYCorner = grid.get_coords(y, staggerloc=ESMF.StaggerLoc.CORNER_VFACE) + gridYCorner = grid.get_coords(y, staggerloc=esmpy.StaggerLoc.CORNER_VFACE) for i1 in range(uby - lby - 1): gridYCorner[:, i1, :] = ycorners[i1+lby, 0] gridYCorner[:, i1 + 1, :] = ycorners[i1+lby, 1] - gridZCorner = grid.get_coords(z, staggerloc=ESMF.StaggerLoc.CORNER_VFACE) + gridZCorner = grid.get_coords(z, staggerloc=esmpy.StaggerLoc.CORNER_VFACE) for i2 in range(ubz - lbz - 1): gridZCorner[:, :, i2] = zcorners[i2+lbz, 0] gridZCorner[:, :, i2 + 1] = zcorners[i2+lbz, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 < gridXCenter.data < 2.25) & (1.75 < gridYCenter.data < 2.25) & @@ -292,7 +292,7 @@ def grid_create_from_coordinates_3d(xcoords, ycoords, zcoords, xcorners=False, y # add arbitrary areas values if doarea: - area = grid.add_item(ESMF.GridItem.AREA) + area = grid.add_item(esmpy.GridItem.AREA) area[:] = 5.0 return grid @@ -350,49 +350,49 @@ def grid_create_from_coordinates_periodic_3d(longitudes, latitudes, heights, # create a grid given the number of grid cells in each dimension the center stagger location is allocated max_index = np.array([len(longitudes), len(latitudes), len(heights)]) - grid = ESMF.Grid(max_index, num_peri_dims=1, staggerloc=[ESMF.StaggerLoc.CENTER]) + grid = esmpy.Grid(max_index, num_peri_dims=1, staggerloc=[esmpy.StaggerLoc.CENTER]) # set the grid coordinates using numpy arrays, parallel case is handled using grid bounds gridXCenter = grid.get_coords(lon) - lon_par = longitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lon]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lon]] + lon_par = longitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lon]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lon]] gridXCenter[...] = lon_par.reshape((lon_par.size, 1, 1)) gridYCenter = grid.get_coords(lat) - lat_par = latitudes[grid.lower_bounds[ESMF.StaggerLoc.CENTER][lat]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][lat]] + lat_par = latitudes[grid.lower_bounds[esmpy.StaggerLoc.CENTER][lat]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][lat]] gridYCenter[...] = lat_par.reshape((1, lat_par.size, 1)) gridZCenter = grid.get_coords(z) - z_par = heights[grid.lower_bounds[ESMF.StaggerLoc.CENTER][z]:grid.upper_bounds[ESMF.StaggerLoc.CENTER][z]] + z_par = heights[grid.lower_bounds[esmpy.StaggerLoc.CENTER][z]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][z]] gridZCenter[...] = z_par.reshape((1, 1, z_par.size)) # create grid corners in a slightly different manner to account for the bounds format common in CF-like files if corners: - grid.add_coords([ESMF.StaggerLoc.CORNER]) - lbx = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lon] - ubx = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lon] - lby = grid.lower_bounds[ESMF.StaggerLoc.CORNER][lat] - uby = grid.upper_bounds[ESMF.StaggerLoc.CORNER][lat] - lbz = grid.lower_bounds[ESMF.StaggerLoc.CORNER][z] - ubz = grid.upper_bounds[ESMF.StaggerLoc.CORNER][z] - - gridXCorner = grid.get_coords(lon, staggerloc=ESMF.StaggerLoc.CORNER) + grid.add_coords([esmpy.StaggerLoc.CORNER]) + lbx = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lon] + ubx = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lon] + lby = grid.lower_bounds[esmpy.StaggerLoc.CORNER][lat] + uby = grid.upper_bounds[esmpy.StaggerLoc.CORNER][lat] + lbz = grid.lower_bounds[esmpy.StaggerLoc.CORNER][z] + ubz = grid.upper_bounds[esmpy.StaggerLoc.CORNER][z] + + gridXCorner = grid.get_coords(lon, staggerloc=esmpy.StaggerLoc.CORNER) for i0 in range(ubx - lbx - 1): gridXCorner[i0, :, :] = lon_corners[i0+lbx, 0] gridXCorner[i0 + 1, :, :] = lon_corners[i0+lbx, 1] - gridYCorner = grid.get_coords(lat, staggerloc=ESMF.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(lat, staggerloc=esmpy.StaggerLoc.CORNER) for i1 in range(uby - lby - 1): gridYCorner[:, i1, :] = lat_corners[i1+lby, 0] gridYCorner[:, i1 + 1, :] = lat_corners[i1+lby, 1] - gridZCorner = grid.get_coords(z, staggerloc=ESMF.StaggerLoc.CORNER) + gridZCorner = grid.get_coords(z, staggerloc=esmpy.StaggerLoc.CORNER) for i2 in range(ubz - lbz - 1): gridZCorner[:, :, i2] = z_corners[i2+lbz, 0] gridZCorner[:, :, i2 + 1] = z_corners[i2+lbz, 1] # add an arbitrary mask if domask: - mask = grid.add_item(ESMF.GridItem.MASK) + mask = grid.add_item(esmpy.GridItem.MASK) mask[:] = 1 mask[np.where((1.75 <= gridXCenter.data < 2.25) & (1.75 <= gridYCenter.data < 2.25) & @@ -408,12 +408,12 @@ def initialize_field_grid(field, domask=False, doarea=False): RETURN VALUES: \n Field :: field \n """ if domask: - mask = field.grid.get_item(ESMF.GridItem.MASK) + mask = field.grid.get_item(esmpy.GridItem.MASK) # get the coordinate pointers and set the coordinates [x,y] = [0, 1] - gridXCoord = field.grid.get_coords(0, ESMF.StaggerLoc.CENTER) - gridYCoord = field.grid.get_coords(1, ESMF.StaggerLoc.CENTER) + gridXCoord = field.grid.get_coords(0, esmpy.StaggerLoc.CENTER) + gridYCoord = field.grid.get_coords(1, esmpy.StaggerLoc.CENTER) field.data[:] = 20.0 + gridXCoord**2 + gridXCoord*gridYCoord + gridYCoord**2 @@ -435,8 +435,8 @@ def initialize_field_grid_periodic(field): # get the coordinate pointers and set the coordinates [x,y] = [0, 1] - gridXCoord = field.grid.get_coords(x, ESMF.StaggerLoc.CENTER) - gridYCoord = field.grid.get_coords(y, ESMF.StaggerLoc.CENTER) + gridXCoord = field.grid.get_coords(x, esmpy.StaggerLoc.CENTER) + gridYCoord = field.grid.get_coords(y, esmpy.StaggerLoc.CENTER) field.data[:] = 2.0 + np.cos(DEG2RAD*gridXCoord)**2 * \ np.cos(2.0*DEG2RAD*(90.0 - gridYCoord)) @@ -456,9 +456,9 @@ def initialize_field_grid_periodic_3d(field): # get the coordinate pointers and set the coordinates [x,y,z] = [0, 1, 2] - gridXCoord = field.grid.get_coords(x, ESMF.StaggerLoc.CENTER) - gridYCoord = field.grid.get_coords(y, ESMF.StaggerLoc.CENTER) - gridZCoord = field.grid.get_coords(z, ESMF.StaggerLoc.CENTER) + gridXCoord = field.grid.get_coords(x, esmpy.StaggerLoc.CENTER) + gridYCoord = field.grid.get_coords(y, esmpy.StaggerLoc.CENTER) + gridZCoord = field.grid.get_coords(z, esmpy.StaggerLoc.CENTER) field.data[:] = 2.0 + np.cos(DEG2RAD*gridXCoord)**2 * \ np.cos(2.0*DEG2RAD*(90.0 - gridYCoord)) + \ @@ -474,13 +474,13 @@ def initialize_field_grid_3d(field, domask=False): RETURN VALUES: \n Field :: field \n """ if domask: - mask = field.grid.get_item(ESMF.GridItem.MASK) + mask = field.grid.get_item(esmpy.GridItem.MASK) # get the coordinate pointers and set the coordinates [x,y,z] = [0,1,2] - gridXCoord = field.grid.get_coords(x, ESMF.StaggerLoc.CENTER_VCENTER) - gridYCoord = field.grid.get_coords(y, ESMF.StaggerLoc.CENTER_VCENTER) - gridZCoord = field.grid.get_coords(z, ESMF.StaggerLoc.CENTER_VCENTER) + gridXCoord = field.grid.get_coords(x, esmpy.StaggerLoc.CENTER_VCENTER) + gridYCoord = field.grid.get_coords(y, esmpy.StaggerLoc.CENTER_VCENTER) + gridZCoord = field.grid.get_coords(z, esmpy.StaggerLoc.CENTER_VCENTER) field.data[:]=20.0 + gridXCoord**2 + gridXCoord*gridYCoord + gridZCoord**2 @@ -500,7 +500,7 @@ def compute_mass_grid(valuefield, dofrac=False, fracfield=None, RETURN VALUES: float :: mass \n """ mass = 0.0 - areafield = ESMF.Field(valuefield.grid, name='areafield') + areafield = esmpy.Field(valuefield.grid, name='areafield') areafield.get_area() ind = np.where(valuefield.data != uninitval) diff --git a/src/addon/ESMPy/src/ESMF/util/helpers.py b/src/addon/ESMPy/src/esmpy/util/helpers.py similarity index 87% rename from src/addon/ESMPy/src/ESMF/util/helpers.py rename to src/addon/ESMPy/src/esmpy/util/helpers.py index 98e4973689..a7087de0e6 100644 --- a/src/addon/ESMPy/src/ESMF/util/helpers.py +++ b/src/addon/ESMPy/src/esmpy/util/helpers.py @@ -1,5 +1,5 @@ -from ESMF import Manager -from ESMF.api.constants import Reduce +from esmpy import Manager +from esmpy.api.constants import Reduce import numpy as np diff --git a/src/addon/ESMPy/src/ESMF/util/itester.py b/src/addon/ESMPy/src/esmpy/util/itester.py similarity index 100% rename from src/addon/ESMPy/src/ESMF/util/itester.py rename to src/addon/ESMPy/src/esmpy/util/itester.py diff --git a/src/addon/ESMPy/src/ESMF/util/locstream_utilities.py b/src/addon/ESMPy/src/esmpy/util/locstream_utilities.py similarity index 77% rename from src/addon/ESMPy/src/ESMF/util/locstream_utilities.py rename to src/addon/ESMPy/src/esmpy/util/locstream_utilities.py index dac2b07bb1..9dda92df3c 100644 --- a/src/addon/ESMPy/src/ESMF/util/locstream_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/locstream_utilities.py @@ -10,7 +10,7 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') @@ -22,10 +22,10 @@ def create_locstream_16(domask=False): :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 1: + if esmpy.pet_count() != 1: raise ValueError("processor count must be 1 to use this function") - locstream = ESMF.LocStream(16) + locstream = esmpy.LocStream(16) locstream["ESMF:X"] = [0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0, 0.0, 1.5, 2.5, 4.0] locstream["ESMF:Y"] = [0.0, 0.0, 0.0, 0.0, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 4.0, 4.0, 4.0, 4.0] @@ -39,30 +39,30 @@ def create_locstream_16_parallel(domask=False): :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 4: + if esmpy.pet_count() != 4: raise ValueError("processor count must be 4 to use this function") locstream = None - if ESMF.local_pet() == 0: - locstream = ESMF.LocStream(4) + if esmpy.local_pet() == 0: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [0.0, 1.5, 0.0, 1.5] locstream["ESMF:Y"] = [0.0, 0.0, 1.5, 1.5] if domask: locstream["ESMF:Mask"] = [1, 0, 0, 1] - elif ESMF.local_pet() == 1: - locstream = ESMF.LocStream(4) + elif esmpy.local_pet() == 1: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [2.5, 4.0, 2.5, 4.0] locstream["ESMF:Y"] = [0.0, 0.0, 1.5, 1.5] if domask: locstream["ESMF:Mask"] = [1, 1, 1, 1] - elif ESMF.local_pet() == 2: - locstream = ESMF.LocStream(4) + elif esmpy.local_pet() == 2: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [0.0, 1.5, 0.0, 1.5] locstream["ESMF:Y"] = [2.5, 2.5, 4.0, 4.0] if domask: locstream["ESMF:Mask"] = [1, 1, 1, 1] - elif ESMF.local_pet() == 3: - locstream = ESMF.LocStream(4) + elif esmpy.local_pet() == 3: + locstream = esmpy.LocStream(4) locstream["ESMF:X"] = [2.5, 4.0, 2.5, 4.0] locstream["ESMF:Y"] = [2.5, 2.5, 4.0, 4.0] if domask: @@ -70,19 +70,19 @@ def create_locstream_16_parallel(domask=False): return locstream -def create_locstream_spherical_16(coord_sys=ESMF.CoordSys.SPH_DEG, domask=False): +def create_locstream_spherical_16(coord_sys=esmpy.CoordSys.SPH_DEG, domask=False): """ :param coord_sys: the coordinate system of the LocStream :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 1: + if esmpy.pet_count() != 1: raise ValueError("processor count must be 1 to use this function") - locstream = ESMF.LocStream(16, coord_sys=coord_sys) + locstream = esmpy.LocStream(16, coord_sys=coord_sys) deg_rad = pi - if coord_sys == ESMF.CoordSys.SPH_DEG: + if coord_sys == esmpy.CoordSys.SPH_DEG: deg_rad = 180 locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad, 0.0, 0.5*deg_rad, 1.5*deg_rad, 2*deg_rad] @@ -92,40 +92,40 @@ def create_locstream_spherical_16(coord_sys=ESMF.CoordSys.SPH_DEG, domask=False) return locstream -def create_locstream_spherical_16_parallel(coord_sys=ESMF.CoordSys.SPH_DEG, domask=False): +def create_locstream_spherical_16_parallel(coord_sys=esmpy.CoordSys.SPH_DEG, domask=False): """ :param coord_sys: the coordinate system of the LocStream :param domask: a boolean to tell whether or not to add a mask :return: LocStream """ - if ESMF.pet_count() != 4: + if esmpy.pet_count() != 4: raise ValueError("processor count must be 4 to use this function") deg_rad = pi - if coord_sys == ESMF.CoordSys.SPH_DEG: + if coord_sys == esmpy.CoordSys.SPH_DEG: deg_rad = 180.0 locstream = None - if ESMF.local_pet() == 0: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + if esmpy.local_pet() == 0: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 0.0, 0.5*deg_rad] locstream["ESMF:Lat"] = [deg_rad/-2.0, deg_rad/-2.0, -0.25*deg_rad, -0.25*deg_rad] if domask: locstream["ESMF:Mask"] = np.array([1, 0, 1, 1], dtype=np.int32) - elif ESMF.local_pet() == 1: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + elif esmpy.local_pet() == 1: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [1.5*deg_rad, 2*deg_rad, 1.5*deg_rad, 2*deg_rad] locstream["ESMF:Lat"] = [deg_rad/-2.0, deg_rad/-2.0, -0.25*deg_rad, -0.25*deg_rad] if domask: locstream["ESMF:Mask"] = np.array([0, 1, 1, 1], dtype=np.int32) - elif ESMF.local_pet() == 2: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + elif esmpy.local_pet() == 2: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [0.0, 0.5*deg_rad, 0.0, 0.5*deg_rad] locstream["ESMF:Lat"] = [0.25*deg_rad, 0.25*deg_rad, deg_rad/2.0, deg_rad/2.0] if domask: locstream["ESMF:Mask"] = np.array([1, 1, 1, 1], dtype=np.int32) - elif ESMF.local_pet() == 3: - locstream = ESMF.LocStream(4, coord_sys=coord_sys) + elif esmpy.local_pet() == 3: + locstream = esmpy.LocStream(4, coord_sys=coord_sys) locstream["ESMF:Lon"] = [1.5*deg_rad, 2*deg_rad, 1.5*deg_rad, 2*deg_rad] locstream["ESMF:Lat"] = [0.25*deg_rad, 0.25*deg_rad, deg_rad/2.0, deg_rad/2.0] if domask: diff --git a/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py b/src/addon/ESMPy/src/esmpy/util/mesh_utilities.py similarity index 92% rename from src/addon/ESMPy/src/ESMF/util/mesh_utilities.py rename to src/addon/ESMPy/src/esmpy/util/mesh_utilities.py index f9ff990b16..76ab3e664d 100644 --- a/src/addon/ESMPy/src/ESMF/util/mesh_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/mesh_utilities.py @@ -10,7 +10,7 @@ raise ImportError('The Numpy library cannot be found!') try: - import ESMF + import esmpy except: raise ImportError('The ESMF library cannot be found!') @@ -45,7 +45,7 @@ def mesh_create_5_pentahexa(coord_sys=None): Note: This mesh is not parallel, it can only be used in serial """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2, coord_sys=coord_sys) num_node = 12 num_elem = 5 @@ -67,9 +67,9 @@ def mesh_create_5_pentahexa(coord_sys=None): nodeOwner = np.zeros(num_node) elemId = np.array([1,2,3,4,5]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI, 5, 6]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI, 5, 6]) # I believe python connections are 0-based @@ -115,7 +115,7 @@ def mesh_create_4_ngons(): Note: This mesh is not parallel, it can only be used in serial """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 9 num_elem = 4 @@ -172,7 +172,7 @@ def mesh_create_5(): Note: This mesh is not parallel, it can only be used in serial """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 9 num_elem = 5 @@ -189,11 +189,11 @@ def mesh_create_5(): nodeOwner = np.zeros(num_node) elemId = np.array([11,12,21,22,23]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn=np.array([0,1,4,3, # element 11 1,2,5,4, # element 12 3,4,7,6, # element 21 @@ -239,7 +239,7 @@ def mesh_create_10(): Note: This mesh is not parallel, it can only be used in serial """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 16 num_elem = 10 @@ -250,16 +250,16 @@ def mesh_create_10(): 0.0,4.0, 1.5,4.0, 2.5,4.0, 4.0,4.0]) nodeOwner = np.zeros(num_node) elemId = np.array([11,12,13,21,22,23,31,32,33,34]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn = np.array([0,1,5,4, 1,2,6,5, 2,3,7,6, @@ -324,7 +324,7 @@ def mesh_create_50(domask=False, doarea=False): Note: This mesh is not parallel, it can only be used in serial """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 64 num_elem = 50 @@ -352,8 +352,8 @@ def mesh_create_50(domask=False, doarea=False): 51,52,53,54,55,56,57, 61,62,63,64,65,66,67, 71,72,73,74,75,76,77,78]) - elemType = np.ones(num_elem-2)*ESMF.MeshElemType.QUAD - elemType = np.append(elemType, [ESMF.MeshElemType.TRI, ESMF.MeshElemType.TRI]) + elemType = np.ones(num_elem-2)*esmpy.MeshElemType.QUAD + elemType = np.append(elemType, [esmpy.MeshElemType.TRI, esmpy.MeshElemType.TRI]) elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23,14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 21,22,32,31,22,23,33,32,23,24,34,33,24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 31,32,42,41,32,33,43,42,33,34,44,43,34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47, @@ -446,7 +446,7 @@ def mesh_create_50_ngons(domask=False, doarea=False): """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 65 num_elem = 50 @@ -474,11 +474,11 @@ def mesh_create_50_ngons(domask=False, doarea=False): 51,52,53,54,55,56,57, 61,62,63,64,65,66,67,68, 71,72,73,74,75,76,77]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemType[35] = 5 - elemType[36] = ESMF.MeshElemType.TRI + elemType[36] = esmpy.MeshElemType.TRI elemType[37] = 5 - elemType[38] = ESMF.MeshElemType.TRI + elemType[38] = esmpy.MeshElemType.TRI elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23,14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 21,22,32,31,22,23,33,32,23,24,34,33,24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 31,32,42,41,32,33,43,42,33,34,44,43,34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47, @@ -548,7 +548,7 @@ def mesh_create_4_ngons(domask=False, doarea=False): Note: This mesh is not parallel, it can only be used in serial """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) num_node = 9 num_elem = 4 @@ -560,9 +560,9 @@ def mesh_create_4_ngons(domask=False, doarea=False): elemId = np.array([61,62,63,64]) elemType = np.ones(num_elem) elemType[0] = 5 - elemType[1] = ESMF.MeshElemType.TRI + elemType[1] = esmpy.MeshElemType.TRI elemType[2] = 5 - elemType[3] = ESMF.MeshElemType.TRI + elemType[3] = esmpy.MeshElemType.TRI elemConn = np.array([61, 62, 69, 72, 71, 62, 63, 69, 63, 64, 74, 73, 69, 69, 73, 72]) elemConn = np.array([np.where(a==nodeId) for a in elemConn]).flatten() elemMask = None @@ -622,13 +622,13 @@ def mesh_create_5_parallel (): # Element Id labels in centers """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): num_node=4 num_elem=1 @@ -639,10 +639,10 @@ def mesh_create_5_parallel (): 2.0,2.0 ]) nodeOwner=np.zeros(num_node) elemId=np.array([11]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2]) - elif (ESMF.local_pet() == 1): + elif (esmpy.local_pet() == 1): num_node=4 num_elem=1 @@ -656,10 +656,10 @@ def mesh_create_5_parallel (): 0, 1]) elemId=np.array([12]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2]) - elif (ESMF.local_pet() == 2): + elif (esmpy.local_pet() == 2): num_node=4 num_elem=1 @@ -673,10 +673,10 @@ def mesh_create_5_parallel (): 2, 2]) elemId=np.array([21]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2]) - elif (ESMF.local_pet() == 3): + elif (esmpy.local_pet() == 3): num_node=4 num_elem=2 @@ -690,8 +690,8 @@ def mesh_create_5_parallel (): 2, 3]) elemId=np.array([22,23]) - elemType=np.array([ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn=np.array([0,3,2, 0,1,3]) @@ -736,13 +736,13 @@ def mesh_create_5_pentahexa_parallel (): """ # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): num_node=4 num_elem=1 @@ -753,10 +753,10 @@ def mesh_create_5_pentahexa_parallel (): 1.0, 1.0 ]) nodeOwner=np.zeros(num_node) elemId=np.array([1]) - elemType=np.array([ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD]) elemConn=np.array([0, 1, 3, 2 ]) - elif (ESMF.local_pet() == 1): + elif (esmpy.local_pet() == 1): num_node=4 num_elem=2 @@ -770,11 +770,11 @@ def mesh_create_5_pentahexa_parallel (): 0, 1]) elemId=np.array([2, 3]) - elemType=np.array([ESMF.MeshElemType.TRI, ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.TRI, esmpy.MeshElemType.TRI]) elemConn=np.array([0, 1, 2, 1, 3, 2]) - elif (ESMF.local_pet() == 2): + elif (esmpy.local_pet() == 2): num_node=5 num_elem=1 @@ -793,7 +793,7 @@ def mesh_create_5_pentahexa_parallel (): elemType=np.array([5]) elemConn=np.array([0, 1, 4, 3, 2]) - elif (ESMF.local_pet() == 3): + elif (esmpy.local_pet() == 3): num_node=6 num_elem=1 @@ -856,14 +856,14 @@ def mesh_create_10_parallel (): # Node Id labels at corners # Element Id labels in centers """ - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if (ESMF.local_pet() == 0): + if (esmpy.local_pet() == 0): num_node=9 num_elem=4 @@ -879,16 +879,16 @@ def mesh_create_10_parallel (): 2.5,2.5]) nodeOwner=np.zeros(num_node) elemId=np.array([11,12,21,22]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,4,3, 1,2,5,4, 3,4,7,6, 4,5,8,7]) - elif (ESMF.local_pet() == 1): + elif (esmpy.local_pet() == 1): num_node=6 num_elem=2 @@ -901,12 +901,12 @@ def mesh_create_10_parallel (): 4.0,2.5 ]) nodeOwner=np.array([0,1,0,1,0,1]) elemId=np.array([13,23]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,3,2, 2,3,5,4]) - elif (ESMF.local_pet() == 2): + elif (esmpy.local_pet() == 2): num_node=6 num_elem=2 @@ -919,12 +919,12 @@ def mesh_create_10_parallel (): 2.5,4.0 ]) nodeOwner=np.array([0,0,0,2,2,2]) elemId=np.array([31,32]) - elemType=np.array([ESMF.MeshElemType.QUAD, - ESMF.MeshElemType.QUAD]) + elemType=np.array([esmpy.MeshElemType.QUAD, + esmpy.MeshElemType.QUAD]) elemConn=np.array([0,1,4,3, 1,2,5,4]) - elif (ESMF.local_pet() == 3): + elif (esmpy.local_pet() == 3): num_node=4 num_elem=2 @@ -935,8 +935,8 @@ def mesh_create_10_parallel (): 4.0,4.0 ]) nodeOwner=np.array([0,1,2,3]) elemId=np.array([33,34]) - elemType=np.array([ESMF.MeshElemType.TRI, - ESMF.MeshElemType.TRI]) + elemType=np.array([esmpy.MeshElemType.TRI, + esmpy.MeshElemType.TRI]) elemConn=np.array([0,3,2, 0,1,3]) @@ -994,14 +994,14 @@ def mesh_create_50_parallel(domask=False, doarea=False): Node Ids at corners Element Ids in centers """ - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.local_pet() == 0: + if esmpy.local_pet() == 0: num_node = 16 num_elem = 9 nodeId = np.array([11,12,13,14, @@ -1016,7 +1016,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): elemId = np.array([11,12,13, 21,22,23, 31,32,33]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23, 21,22,32,31,22,23,33,32,23,24,34,33, 31,32,42,41,32,33,43,42,33,34,44,43]) @@ -1029,7 +1029,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 1: + elif esmpy.local_pet() == 1: num_node = 20 num_elem = 12 nodeId = np.array([14,15,16,17,18, @@ -1044,7 +1044,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): elemId = np.array([14,15,16,17, 24,25,26,27, 34,35,36,37]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47]) @@ -1056,7 +1056,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 2: + elif esmpy.local_pet() == 2: num_node = 20 num_elem = 12 nodeId = np.array([41,42,43,44, @@ -1074,7 +1074,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): 51,52,53, 61,62,63, 71,72,73]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([41,42,52,51,42,43,53,52,43,44,54,53, 51,52,62,61,52,53,63,62,53,54,64,63, 61,62,72,71,62,63,73,72,63,64,74,73, @@ -1087,7 +1087,7 @@ def mesh_create_50_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 3: + elif esmpy.local_pet() == 3: num_node = 25 num_elem = 17 nodeId = np.array([44,45,46,47,48, @@ -1105,8 +1105,8 @@ def mesh_create_50_parallel(domask=False, doarea=False): 54,55,56,57, 64,65,66,67, 74,75,76,77,78]) - elemType = np.ones(num_elem-2)*ESMF.MeshElemType.QUAD - elemType = np.append(elemType, [ESMF.MeshElemType.TRI, ESMF.MeshElemType.TRI]) + elemType = np.ones(num_elem-2)*esmpy.MeshElemType.QUAD + elemType = np.append(elemType, [esmpy.MeshElemType.TRI, esmpy.MeshElemType.TRI]) elemConn = np.array([44,45,55,54,45,46,56,55,46,47,57,56,47,48,58,57, 54,55,65,64,55,56,66,65,56,57,67,66,57,58,68,67, 64,65,75,74,65,66,76,75,66,67,77,76,67,68,78,77, @@ -1189,14 +1189,14 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): Node Ids at corners Element Ids in centers """ - if ESMF.pet_count() > 1: - if ESMF.pet_count() != 4: + if esmpy.pet_count() > 1: + if esmpy.pet_count() != 4: raise NameError('MPI rank must be 4 to build this mesh!') # Two parametric dimensions, and two spatial dimensions - mesh = ESMF.Mesh(parametric_dim=2, spatial_dim=2) + mesh = esmpy.Mesh(parametric_dim=2, spatial_dim=2) - if ESMF.local_pet() == 0: + if esmpy.local_pet() == 0: num_node = 16 num_elem = 9 nodeId = np.array([11,12,13,14, @@ -1211,7 +1211,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): elemId = np.array([11,12,13, 21,22,23, 31,32,33]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([11,12,22,21,12,13,23,22,13,14,24,23, 21,22,32,31,22,23,33,32,23,24,34,33, 31,32,42,41,32,33,43,42,33,34,44,43]) @@ -1224,7 +1224,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 1: + elif esmpy.local_pet() == 1: num_node = 20 num_elem = 12 nodeId = np.array([14,15,16,17,18, @@ -1239,7 +1239,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): elemId = np.array([14,15,16,17, 24,25,26,27, 34,35,36,37]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([14,15,25,24,15,16,26,25,16,17,27,26,17,18,28,27, 24,25,35,34,25,26,36,35,26,27,37,36,27,28,38,37, 34,35,45,44,35,36,46,45,36,37,47,46,37,38,48,47]) @@ -1251,7 +1251,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): if doarea: elemArea = np.ones(num_elem)*5 - elif ESMF.local_pet() == 2: + elif esmpy.local_pet() == 2: num_node = 21 num_elem = 13 nodeId = np.array([41,42,43,44, @@ -1269,11 +1269,11 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): 51,52,53, 61,62,63,68, 71,72,73]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemType[6] = 5 - elemType[7] = ESMF.MeshElemType.TRI + elemType[7] = esmpy.MeshElemType.TRI elemType[8] = 5 - elemType[9] = ESMF.MeshElemType.TRI + elemType[9] = esmpy.MeshElemType.TRI elemConn = np.array([41,42,52,51,42,43,53,52,43,44,54,53, 51,52,62,61,52,53,63,62,53,54,64,63, 61,62,69,72,71,62,63,69,63,64,74,73,69,69,73,72, @@ -1290,7 +1290,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): elemArea[8] = 6.25 elemArea[9] = 1.25 - elif ESMF.local_pet() == 3: + elif esmpy.local_pet() == 3: num_node = 25 num_elem = 16 nodeId = np.array([44,45,46,47,48, @@ -1308,7 +1308,7 @@ def mesh_create_50_ngons_parallel(domask=False, doarea=False): 54,55,56,57, 64,65,66,67, 74,75,76,77]) - elemType = np.ones(num_elem)*ESMF.MeshElemType.QUAD + elemType = np.ones(num_elem)*esmpy.MeshElemType.QUAD elemConn = np.array([44,45,55,54,45,46,56,55,46,47,57,56,47,48,58,57, 54,55,65,64,55,56,66,65,56,57,67,66,57,58,68,67, 64,65,75,74,65,66,76,75,66,67,77,76,67,68,78,77, @@ -1349,7 +1349,7 @@ def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, if field.staggerloc == element: offset = 0 for i in range(field.grid.size_owned[element]): - if (elemType[i] == ESMF.MeshElemType.TRI): + if (elemType[i] == esmpy.MeshElemType.TRI): x1 = nodeCoord[(elemConn[offset])*2] x2 = nodeCoord[(elemConn[offset+1])*2] x3 = nodeCoord[(elemConn[offset+2])*2] @@ -1359,7 +1359,7 @@ def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, x = (x1 + x2 + x3) / 3.0 y = (y1 + y2 + y3) / 3.0 offset = offset + 3 - elif (elemType[i] == ESMF.MeshElemType.QUAD): + elif (elemType[i] == esmpy.MeshElemType.QUAD): x1 = nodeCoord[(elemConn[offset])*2] x2 = nodeCoord[(elemConn[offset+1])*2] y1 = nodeCoord[(elemConn[offset+1])*2+1] @@ -1385,7 +1385,7 @@ def initialize_field_mesh(field, nodeCoord, nodeOwner, elemType, elemConn, x = nodeCoord[i*2] y = nodeCoord[i*2+1] - if (nodeOwner[i] == ESMF.local_pet()): + if (nodeOwner[i] == esmpy.local_pet()): if ind > field.grid.size_owned[node]: raise ValueError("Overstepped the mesh bounds!") field.data[ind] = 20.0 + x**2 +x*y + y**2 @@ -1414,8 +1414,8 @@ def compute_mass_mesh(valuefield, dofrac=False, fracfield=None, """ mass = 0.0 # mesh area field must be built on elements - areafield = ESMF.Field(valuefield.grid, name='areafield', - meshloc=ESMF.MeshLoc.ELEMENT) + areafield = esmpy.Field(valuefield.grid, name='areafield', + meshloc=esmpy.MeshLoc.ELEMENT) areafield.get_area() ind = np.where(valuefield.data != uninitval) diff --git a/src/addon/ESMPy/src/ESMF/util/slicing.py b/src/addon/ESMPy/src/esmpy/util/slicing.py similarity index 85% rename from src/addon/ESMPy/src/ESMF/util/slicing.py rename to src/addon/ESMPy/src/esmpy/util/slicing.py index 1f53467948..0bb83864f3 100644 --- a/src/addon/ESMPy/src/ESMF/util/slicing.py +++ b/src/addon/ESMPy/src/esmpy/util/slicing.py @@ -3,7 +3,7 @@ """ import numpy as np -import ESMF +import esmpy #### HELPERS ######################################################### @@ -65,15 +65,15 @@ def get_none_or_ssslice(target, slc, stagger, rank): slc2 = None if rank == 2: assert(len(slc) == 2) - if stagger == ESMF.StaggerLoc.CENTER: + if stagger == esmpy.StaggerLoc.CENTER: slc2 = slc - elif stagger == ESMF.StaggerLoc.EDGE1: + elif stagger == esmpy.StaggerLoc.EDGE1: #slc[0] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slc[1]) - elif stagger == ESMF.StaggerLoc.EDGE2: + elif stagger == esmpy.StaggerLoc.EDGE2: #slc[1] + 1 slc2 = (slc[0], slice(slc[1].start, slc[1].stop + 1, slc[1].step)) - elif stagger == ESMF.StaggerLoc.CORNER: + elif stagger == esmpy.StaggerLoc.CORNER: #slc[0] + 1 #slc[1] + 1 slc2 = ([slice(slc[i].start, slc[i].stop + 1, slc[i].step) for i in range(len(slc))]) @@ -82,30 +82,30 @@ def get_none_or_ssslice(target, slc, stagger, rank): elif rank == 3: assert (len(slc) == 3) - if stagger == ESMF.StaggerLoc.CENTER_VCENTER: + if stagger == esmpy.StaggerLoc.CENTER_VCENTER: slc2 = slc - elif stagger == ESMF.StaggerLoc.EDGE1_VCENTER: + elif stagger == esmpy.StaggerLoc.EDGE1_VCENTER: #slc[0] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slc[1], slc[2]) - elif stagger == ESMF.StaggerLoc.EDGE2_VCENTER: + elif stagger == esmpy.StaggerLoc.EDGE2_VCENTER: #slc[1] + 1 slc2 = (slc[0], slice(slc[1].start, slc[1].stop + 1, slc[1].step), slc[2]) - elif stagger == ESMF.StaggerLoc.CORNER_VCENTER: + elif stagger == esmpy.StaggerLoc.CORNER_VCENTER: #slc[0] + 1 #slc[1] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slice(slc[1].start, slc[1].stop + 1, slc[1].step), slc[2]) - elif stagger == ESMF.StaggerLoc.CENTER_VFACE: + elif stagger == esmpy.StaggerLoc.CENTER_VFACE: #slc[2] + 1 slc2 = (slc[0], slc[1], slice(slc[2].start, slc[2].stop + 1, slc[2].step)) - elif stagger == ESMF.StaggerLoc.EDGE1_VFACE: + elif stagger == esmpy.StaggerLoc.EDGE1_VFACE: #slc[0] + 1 #slc[2] + 1 slc2 = (slice(slc[0].start, slc[0].stop + 1, slc[0].step), slc[1], slice(slc[2].start, slc[2].stop + 1, slc[2].step)) - elif stagger == ESMF.StaggerLoc.EDGE2_VFACE: + elif stagger == esmpy.StaggerLoc.EDGE2_VFACE: #slc[1] + 1 #slc[2] + 1 slc2 = (slc[0], slice(slc[1].start, slc[1].stop + 1, slc[1].step), slice(slc[2].start, slc[2].stop + 1, slc[2].step)) - elif stagger == ESMF.StaggerLoc.CORNER_VFACE: + elif stagger == esmpy.StaggerLoc.CORNER_VFACE: #slc[0] + 1 #slc[1] + 1 #slc[2] + 1 From b7c4e787ba2f0d12ddd74bafb6a7f73cbeb681a4 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Tue, 30 Aug 2022 12:03:59 -0600 Subject: [PATCH 142/266] fix esmpy regrid from file test runner --- .../src/esmpy/test/regrid_from_file/run_regrid_from_file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py index 67b82288c2..6742911c76 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py @@ -25,7 +25,7 @@ rtestoutfile='run_regrid_from_file_parallel.log' constants._ESMF_MPIRUN + " -n " -os.system(constants._ESMF_MPIRUN + " -n " + str(constants._ESMF_MPIRUN_NP) + " python " + rtestfile + " > " + rtestoutfile + " 2>&1") +os.system(constants._ESMF_MPIRUN + " -n " + str(constants._ESMF_MPIRUN_NP) + " python3 " + rtestfile + " > " + rtestoutfile + " 2>&1") # traverse output, find number of pass and fail and print report RTEST = open(rtestoutfile) From 1d65e88792958973a3a956243535c40f17f41d27 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Tue, 30 Aug 2022 11:05:58 -0700 Subject: [PATCH 143/266] improve esmpy test targets --- src/addon/ESMPy/Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 22c8330913..b0f7e908fc 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -37,11 +37,13 @@ test_regrid_from_file_dryrun: test_regrid_from_file: python3 -m pytest -vs src/esmpy/test/regrid_from_file/rfftest.py -test_all: test_unit test_parallel test_examples test_examples_parallel +test_serial: test_unit test_examples -test_parallel: test_unit_parallel test_examples_dryrun test_examples_parallel +test_dryrun: test_examples_dryrun test_regrid_from_file_dryrun -test_uni: test_unit test_examples +test_parallel: test_unit_parallel test_examples_parallel test_regrid_from_file + +test_all: test_unit test_unit_parallel test_examples test_examples_parallel test_regrid_from_file uninstall: python3 -m pip uninstall ESMPy From 95bea1f96f3ba6be0703043e2052f07243406f38 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Tue, 30 Aug 2022 15:01:53 -0700 Subject: [PATCH 144/266] convert ESMPy regrid from file testing to use pytest --- src/addon/ESMPy/Makefile | 27 +++-- src/addon/ESMPy/src/esmpy/api/esmpymanager.py | 2 +- .../regrid_from_file/regrid_check_driver.py | 93 ---------------- .../esmpy/test/regrid_from_file/rfftest.py | 18 --- .../test/regrid_from_file/rfftestdryrun.py | 14 --- .../regrid_from_file/run_regrid_from_file.py | 103 ++++++++---------- .../run_regrid_from_file_dryrun.py | 10 +- .../ESMPy/src/esmpy/util/field_utilities.py | 4 +- 8 files changed, 71 insertions(+), 200 deletions(-) delete mode 100644 src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check_driver.py delete mode 100644 src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftest.py delete mode 100644 src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftestdryrun.py diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index b0f7e908fc..32435bdbdc 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -17,33 +17,36 @@ install: python3 -m pip install . test_unit: - python3 -m pytest -m="not parallel" + python3 -m pytest -m="not parallel" --json-report --json-report-summary test_unit_parallel: - mpirun -n 4 python3 -m pytest -m="not serial" + mpirun -n 4 python3 -m pytest -m="not serial" --json-report --json-report-summary -test_examples_dryrun: - python3 -m pytest -vs examples/exampletestdryrun.py - test_examples: python3 -m pytest -vs -m="not parallel" examples/exampletest.py test_examples_parallel: mpirun -n 4 python3 -m pytest -vs -m="not serial" examples/exampletest.py +test_examples_dryrun: + python3 -m pytest -vs examples/exampletestdryrun.py + +test_regrid_from_file: + python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file.py + +test_regrid_from_file_parallel: + mpirun -n 4 python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file.py + test_regrid_from_file_dryrun: - python3 -m pytest -vs src/esmpy/test/regrid_from_file/rfftestdryrun.py + python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py -test_regrid_from_file: - python3 -m pytest -vs src/esmpy/test/regrid_from_file/rfftest.py +test_serial: test_unit test_examples test_regrid_from_file -test_serial: test_unit test_examples +test_parallel: test_unit_parallel test_examples_parallel test_regrid_from_file_parallel test_dryrun: test_examples_dryrun test_regrid_from_file_dryrun -test_parallel: test_unit_parallel test_examples_parallel test_regrid_from_file - -test_all: test_unit test_unit_parallel test_examples test_examples_parallel test_regrid_from_file +test_all: test_unit test_unit_parallel test_examples test_examples_parallel test_regrid_from_file test_regrid_from_file_parallel uninstall: python3 -m pip uninstall ESMPy diff --git a/src/addon/ESMPy/src/esmpy/api/esmpymanager.py b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py index ddf8f481c0..cda53527da 100644 --- a/src/addon/ESMPy/src/esmpy/api/esmpymanager.py +++ b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py @@ -18,7 +18,7 @@ def _preprocess(v, separator, ignorecase): if ignorecase: v = v.lower() return [int(x) if x.isdigit() else [int(y) if y.isdigit() else y for y in - re.findall("\d+|[a-zA-Z]+", x)] for x in v.split(separator)] + re.findall(r"\d+|[a-zA-Z]+", x)] for x in v.split(separator)] def version_compare(a, b, separator = '.', ignorecase = True): a = _preprocess(a, separator, ignorecase) diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check_driver.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check_driver.py deleted file mode 100644 index 25edc3e0d3..0000000000 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check_driver.py +++ /dev/null @@ -1,93 +0,0 @@ -# $Id$ - -""" -Reads each line of a control file where each line corresponds to one test -case. Parses each line and calls a test subroutine that creates meshes from -source and destination NetCDF files, creates an analytic field across the -source mesh, regrids the source mesh to the grid of the destination mesh, -and compares the analytic field of the resulting regridded mesh to that of the -source mesh. -""" - -import sys -import os -import traceback - -try: - import esmpy -except: - raise ImportError('The ESMF library cannot be found!') -from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR -from esmpy.test.regrid_from_file.run_regrid_from_file_dryrun import cache_data_files_for_test_cases -from esmpy.test.regrid_from_file.regrid_check import regrid_check -from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file - -# Start up ESMF and run regrid test for each line of options -# read from a control file. Retrieve data files for each test from a remote -# server if they do not exist locally. -# Start up esmpy. -mg = esmpy.Manager(debug=True) - -parallel = False -if esmpy.pet_count() > 1: - parallel = True - -# Read the test case parameters from the control file. - -print('Reading control file...') -test_cases = read_control_file() -if (esmpy.local_pet() == 0): - # Retrieve the data files needed for the test cases from the remote server. - print('Retrieving regrid_from_file data...') - status_ok = cache_data_files_for_test_cases(test_cases) - -# For each test case line from the control file parse the line and call -# the test subroutine. -for ctr, test_case in enumerate(test_cases, start=1): - print('Running {0} of {1} regrid_from_file test cases...'.format(ctr, len(test_cases))) - (src_fname, dst_fname, regrid_method, options, - itrp_mean_err, itrp_max_err, csrv_err) = test_case - test_str = 'Regrid %s to %s as %s with %s itrp_mean_err=%f, itrp_max_err=%f, and csrv_err=%f' % (src_fname, dst_fname, regrid_method, options, itrp_mean_err, itrp_max_err, csrv_err) - print ('\n' + test_str + ' - START\n') - src_fname_full = os.path.join(DATA_SUBDIR, src_fname) - dst_fname_full = os.path.join(DATA_SUBDIR, dst_fname) - - if parallel: - # set a barrier to wait for files to be downloaded - mg.barrier() - - # run the data file retrieval and regridding through try/except - correct = False - try: - correct = regrid_check(src_fname_full, dst_fname_full, regrid_method, - options, itrp_mean_err, itrp_max_err, csrv_err) - except: - print ("Regridding ERROR:\n") - traceback.print_exc(file=sys.stdout) - - skip = False - for i in range(esmpy.pet_count()): - for line in open("PET"+str(i)+".ESMF_LogFile"): - if "ESMF_NETCDF not defined when lib was compiled" in line or \ - "File format is not supported" in line: - # set skip - skip = True - - # print the file - print ('\n***NOTE*** The log files must be deleted in this test case, they are printed below for future reference\n') - if skip: - for line in open("PET"+str(i)+".ESMF_LogFile"): - print (line) - - # clean the log files - for i in range(esmpy.pet_count()): - os.system("echo ' ' > PET"+str(i)+".ESMF_LogFile") - - print ("\nPET: " + str(esmpy.local_pet()) + " - " + test_str + " - FINISH\n") - - if skip: - print ('RESULT: SKIP\n\n') - elif correct: - print ('RESULT: PASS\n\n') - else: - print ('RESULT: FAIL\n\n') diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftest.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftest.py deleted file mode 100644 index 4c19cf6dfe..0000000000 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftest.py +++ /dev/null @@ -1,18 +0,0 @@ -# $Id$ - -""" -examples test file -""" - -import pytest - -from esmpy.test.base import TestBase, attr - -class TestRFF(TestBase): - - # # '0' in the name is so it is run first - # def test_0_regrid_from_file_dryrun(self): - # from esmpy.test.regrid_from_file import run_regrid_from_file_dryrun - - def test_regrid_from_file(self): - from esmpy.test.regrid_from_file import run_regrid_from_file diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftestdryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftestdryrun.py deleted file mode 100644 index 2ee122f2ac..0000000000 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/rfftestdryrun.py +++ /dev/null @@ -1,14 +0,0 @@ -# $Id$ - -""" -examples test file -""" - -import pytest - -from esmpy.test.base import TestBase, attr - -class TestRFFDryrun(TestBase): - - def test_regrid_from_file_dryrun(self): - from esmpy.test.regrid_from_file import run_regrid_from_file_dryrun diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py index 6742911c76..f8dca3a750 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py @@ -1,58 +1,51 @@ # $Id$ -import os -import sys - -import esmpy.api.constants as constants -from esmpy.test.regrid_from_file.regrid_from_file_consts import TEST_REGRID_DIR - - -parallel = False -if len(sys.argv) > 1: - if "--parallel" in sys.argv[1]: - parallel = True - -# run utests, pipe to file -rtestfile=os.path.join(TEST_REGRID_DIR, 'regrid_check_driver.py') -rtestoutfile='run_regrid_from_file.log' -num_proc = 1 -if parallel: - # make sure we are not in uni mode - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise ValueError("Cannot run parallel tests when ESMF is built with ESMF_COMM=mpiuni") - - # setup the constants - rtestoutfile='run_regrid_from_file_parallel.log' - -constants._ESMF_MPIRUN + " -n " -os.system(constants._ESMF_MPIRUN + " -n " + str(constants._ESMF_MPIRUN_NP) + " python3 " + rtestfile + " > " + rtestoutfile + " 2>&1") +""" +Reads each line of a control file where each line corresponds to one test +case. Parses each line and calls a test subroutine that creates meshes from +source and destination NetCDF files, creates an analytic field across the +source mesh, regrids the source mesh to the grid of the destination mesh, +and compares the analytic field of the resulting regridded mesh to that of the +source mesh. +""" -# traverse output, find number of pass and fail and print report -RTEST = open(rtestoutfile) - -rtpass = 0 -rtfail = 0 -rtskip = 0 - -for line in RTEST: - if 'RESULT: PASS' in line: - rtpass=rtpass+1 - if 'RESULT: FAIL' in line: - rtfail=rtfail+1 - if 'RESULT: SKIP' in line: - rtskip=rtskip+1 - -RTEST.close() - -rtpass = rtpass/num_proc -rtfail = rtfail/num_proc -rtskip = rtskip/num_proc - -print("Regrid from file test results: "+rtestoutfile) -print("PASS = "+str(int(rtpass))) -print("FAIL = "+str(int(rtfail))) -print("SKIP = "+str(int(rtskip))) - -if rtpass == 0 and rtfail == 0 and rtskip == 0: - print(rtestoutfile+":") - os.system("tail "+rtestoutfile) +import sys +import os +import traceback +import pytest + +try: + import esmpy +except: + raise ImportError('The ESMF library cannot be found!') +from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR +from esmpy.test.regrid_from_file.regrid_check import regrid_check +from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file + +# Start up esmpy. +mg = esmpy.Manager(debug=True) + +# Read the test case parameters from the control file. +print('Reading control file...') +test_cases = read_control_file() + +# For each test case line from the control file parse the line and call +# the test subroutine. + +@pytest.mark.parametrize('test_case', test_cases) +def test_run_regrid_from_file(test_case): + (src_fname, dst_fname, regrid_method, options, + itrp_mean_err, itrp_max_err, csrv_err) = test_case + test_str = 'Regrid %s to %s as %s with %s itrp_mean_err=%f, itrp_max_err=%f, and csrv_err=%f' % (src_fname, dst_fname, regrid_method, options, itrp_mean_err, itrp_max_err, csrv_err) + if esmpy.local_pet() == 0: + print ('\n' + test_str) + src_fname_full = os.path.join(DATA_SUBDIR, src_fname) + dst_fname_full = os.path.join(DATA_SUBDIR, dst_fname) + + # run the data file retrieval and regridding through try/except + try: + correct = regrid_check(src_fname_full, dst_fname_full, regrid_method, + options, itrp_mean_err, itrp_max_err, csrv_err) + except: + print ("PET {}: Regridding ERROR:{}".format(esmpy.local_pet(), correct)) + traceback.print_exc(file=sys.stdout) diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py index 5b7ca181b3..21eb31c7d1 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py @@ -40,8 +40,8 @@ def cache_data_files_for_test_cases(test_cases): test_cases = read_control_file() # Retrieve the data files needed for the test cases from the remote server. -status_ok = cache_data_files_for_test_cases(test_cases) -if status_ok: - print ('RESULT: PASS - regrid_from_file_dryrun ok\n\n') -else: - print ('RESULT: FAIL - regrid_from_file_dryrun error\n\n') +try: + status_ok = cache_data_files_for_test_cases(test_cases) +except: + print ("Cache data file error: {}\n".format(status_ok)) + traceback.print_exc(file=sys.stdout) diff --git a/src/addon/ESMPy/src/esmpy/util/field_utilities.py b/src/addon/ESMPy/src/esmpy/util/field_utilities.py index 122526cfc1..bda753fa62 100644 --- a/src/addon/ESMPy/src/esmpy/util/field_utilities.py +++ b/src/addon/ESMPy/src/esmpy/util/field_utilities.py @@ -123,7 +123,7 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, csrv = True # print out diagnostic information - print ("\n Mean relative error = "+str(total_error_global)) + print (" Mean relative error = "+str(total_error_global)) print (" Max relative error = "+str(max_error_global)) print (" Conservation error = "+str(csrv_error_global)) #print (" Min error = "+str(min_error_global)) @@ -145,4 +145,4 @@ def compare_fields(field1, field2, itrp_mean_tol, itrp_max_tol, csrv_tol, else: print ("PET{0} - FAIL".format(esmpy.local_pet())) - return total_error_global, csrv_error_global, correct \ No newline at end of file + return total_error_global, csrv_error_global, correct From 638b5e945b1b83ea01c9c35a141bdff82567caa3 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Tue, 30 Aug 2022 15:06:48 -0700 Subject: [PATCH 145/266] fix the ESMPy cubed sphere example --- src/addon/ESMPy/Makefile | 8 +-- .../examples/cubed_sphere_to_mesh_regrid.py | 3 +- src/addon/ESMPy/examples/exampletest.py | 52 +++++++++++-------- .../src/esmpy/test/test_api/test_grid.py | 1 - 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 32435bdbdc..7eec02c873 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -17,16 +17,16 @@ install: python3 -m pip install . test_unit: - python3 -m pytest -m="not parallel" --json-report --json-report-summary + python3 -m pytest -m="not parallel" test_unit_parallel: - mpirun -n 4 python3 -m pytest -m="not serial" --json-report --json-report-summary + mpirun -n 4 python3 -m pytest -m="not serial" test_examples: - python3 -m pytest -vs -m="not parallel" examples/exampletest.py + python3 -m pytest -vs examples/exampletest.py test_examples_parallel: - mpirun -n 4 python3 -m pytest -vs -m="not serial" examples/exampletest.py + mpirun -n 4 python3 -m pytest -vs examples/exampletest.py test_examples_dryrun: python3 -m pytest -vs examples/exampletestdryrun.py diff --git a/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py b/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py index 0544e036dc..ee54fa2b0b 100644 --- a/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py +++ b/src/addon/ESMPy/examples/cubed_sphere_to_mesh_regrid.py @@ -26,7 +26,8 @@ grid1 = "examples/data/ll1deg_grid.nc" # Create a cubed sphere grid with 20 elements per tile -srcgrid = esmpy.Grid(tilesize=20, name="cubed_sphere") +regDecompPTile = numpy.array([[2,2,1,1,1,1],[2,2,2,2,2,2]], dtype=numpy.int32) +srcgrid = esmpy.Grid(tilesize=20, regDecompPTile = regDecompPTile, name="cubed_sphere") # create an regular lat lon grid from file dstgrid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/exampletest.py index 7ec3c92018..e3325578ef 100644 --- a/src/addon/ESMPy/examples/exampletest.py +++ b/src/addon/ESMPy/examples/exampletest.py @@ -20,15 +20,6 @@ def test_helloworld(self): from . import hello_world # ESMF IO does not work in mpiuni mode - @pytest.mark.parallel - def test_cubed_sphere_to_mesh_regrid(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import cubed_sphere_to_mesh_regrid - - # ESMF IO does not work in mpiuni mode - # only example, not in documentation def test_field_read(self): if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: raise SkipTest('ESMF must be built with MPI for test') @@ -37,13 +28,22 @@ def test_field_read(self): # only example, not in documentation def test_grid_create_peridim_mask(self): - from . import grid_create_peridim_mask + if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: + raise SkipTest('ESMF must be built with MPI for test') + else: + from . import grid_create_peridim_mask def test_grid_locstream_regrid(self): - from . import grid_locstream_regrid + if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: + raise SkipTest('ESMF must be built with MPI for test') + else: + from . import grid_locstream_regrid def test_locstream_grid_regrid(self): - from . import locstream_grid_regrid + if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: + raise SkipTest('ESMF must be built with MPI for test') + else: + from . import locstream_grid_regrid def test_mesh_locstream_regrid(self): from . import mesh_locstream_regrid @@ -62,15 +62,25 @@ def test_regrid_from_file(self): else: from . import regrid_from_file - # # only example, not in documentation, datafile missing from repo - # @pytest.mark.slow - # def test_tripole_regrid(self): - # from . import tripole_regrid - - # only example, not in documentation def test_ugrid_latlon_regrid(self): - from . import ugrid_latlon_regrid + if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: + raise SkipTest('ESMF must be built with MPI for test') + else: + from . import ugrid_latlon_regrid - # only example, not in documentation def test_ungridded_dimension_regrid(self): - from . import ungridded_dimension_regrid + if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: + raise SkipTest('ESMF must be built with MPI for test') + else: + from . import ungridded_dimension_regrid + + # # ESMF IO does not work in mpiuni mode + # def test_cubed_sphere_to_mesh_regrid(self): + # if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: + # raise SkipTest('ESMF must be built with MPI for test') + # else: + # from . import cubed_sphere_to_mesh_regrid + + # # datafile missing from repo + # def test_tripole_regrid(self): + # from . import tripole_regrid diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py index 37a9b57ace..f8183b48ef 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py @@ -260,7 +260,6 @@ def test_grid_create_3d(self): raise ValueError( "The following combinations of Grid parameters failed to create a proper Grid: " + str(fail)) - @pytest.mark.serial def test_grid_create_cubed_sphere(self): # keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] From 54957bd5d65c0e7235dfd685255b803e8f98b1ab Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 1 Sep 2022 10:55:41 -0700 Subject: [PATCH 146/266] Squashed commit of feature/nvhpc. This also includes OpenACC work done for GPUs. --- .../Darwin.gfortran.default/build_rules.mk | 13 ++ .../Linux.gfortran.default/build_rules.mk | 9 + .../Linux.nvhpc.default/build_rules.mk | 9 +- .../Unicos.gfortran.default/build_rules.mk | 9 + build_config/Unicos.nvhpc.default/ESMC_Conf.h | 33 ++++ .../Unicos.nvhpc.default/ESMF_Conf.inc | 11 ++ build_config/Unicos.nvhpc.default/README | 5 + .../Unicos.nvhpc.default/build_rules.mk | 167 ++++++++++++++++++ 8 files changed, 252 insertions(+), 4 deletions(-) create mode 100644 build_config/Unicos.nvhpc.default/ESMC_Conf.h create mode 100644 build_config/Unicos.nvhpc.default/ESMF_Conf.inc create mode 100644 build_config/Unicos.nvhpc.default/README create mode 100644 build_config/Unicos.nvhpc.default/build_rules.mk diff --git a/build_config/Darwin.gfortran.default/build_rules.mk b/build_config/Darwin.gfortran.default/build_rules.mk index 6331b7ff43..ca06b3d270 100644 --- a/build_config/Darwin.gfortran.default/build_rules.mk +++ b/build_config/Darwin.gfortran.default/build_rules.mk @@ -202,6 +202,19 @@ else ESMF_OPENMP=OFF endif +############################################################ +# OpenACC compiler and linker flags +# +ifneq ($(ESMF_CLANGSTR), clang) +ESMF_OPENACCDEFAULT = OFF +ESMF_OPENACC_F90COMPILEOPTS += -fopenacc +ESMF_OPENACC_CXXCOMPILEOPTS += -fopenacc +ESMF_OPENACC_F90LINKOPTS += -fopenacc +ESMF_OPENACC_CXXLINKOPTS += -fopenacc +else +ESMF_OPENACC=OFF +endif + ############################################################ # Need this until the file convention is fixed (then remove these two lines) # diff --git a/build_config/Linux.gfortran.default/build_rules.mk b/build_config/Linux.gfortran.default/build_rules.mk index a4a55e3c84..dbbb1e557d 100644 --- a/build_config/Linux.gfortran.default/build_rules.mk +++ b/build_config/Linux.gfortran.default/build_rules.mk @@ -230,6 +230,15 @@ ESMF_OPENMP_CXXCOMPILEOPTS += -fopenmp ESMF_OPENMP_F90LINKOPTS += -fopenmp ESMF_OPENMP_CXXLINKOPTS += -fopenmp +############################################################ +# OpenACC compiler and linker flags +# +ESMF_OPENACCDEFAULT = OFF +ESMF_OPENACC_F90COMPILEOPTS += -fopenacc +ESMF_OPENACC_CXXCOMPILEOPTS += -fopenacc +ESMF_OPENACC_F90LINKOPTS += -fopenacc +ESMF_OPENACC_CXXLINKOPTS += -fopenacc + ############################################################ # Need this until the file convention is fixed (then remove these two lines) # diff --git a/build_config/Linux.nvhpc.default/build_rules.mk b/build_config/Linux.nvhpc.default/build_rules.mk index 1a7be55967..c163e27d32 100644 --- a/build_config/Linux.nvhpc.default/build_rules.mk +++ b/build_config/Linux.nvhpc.default/build_rules.mk @@ -8,7 +8,7 @@ # ESMF_F90DEFAULT = nvfortran ESMF_CXXDEFAULT = nvc++ -ESMF_CDEFAULT = nvcc +ESMF_CDEFAULT = nvc ############################################################ # Default MPI setting. @@ -130,9 +130,9 @@ endif ############################################################ # Print compiler version string # -ESMF_F90COMPILER_VERSION = ${ESMF_F90COMPILER} --version -ESMF_CXXCOMPILER_VERSION = ${ESMF_CXXCOMPILER} --version -ESMF_CCOMPILER_VERSION = ${ESMF_CCOMPILER} --version +ESMF_F90COMPILER_VERSION = ${ESMF_F90COMPILER} --version -c +ESMF_CXXCOMPILER_VERSION = ${ESMF_CXXCOMPILER} --version -c +ESMF_CCOMPILER_VERSION = ${ESMF_CCOMPILER} --version -c ############################################################ # Currently no support the Fortran2018 assumed type feature @@ -200,6 +200,7 @@ ESMF_OPENMP_CXXLINKOPTS += -mp ############################################################ # OpenACC compiler and linker flags (the -Minfo just there for debugging) # +ESMF_OPENACCDEFAULT = OFF ESMF_OPENACC_F90COMPILEOPTS += -acc -Minfo ESMF_OPENACC_CXXCOMPILEOPTS += -acc -Minfo ESMF_OPENACC_F90LINKOPTS += -acc -Minfo diff --git a/build_config/Unicos.gfortran.default/build_rules.mk b/build_config/Unicos.gfortran.default/build_rules.mk index fb3413fcd4..260ed7a37b 100644 --- a/build_config/Unicos.gfortran.default/build_rules.mk +++ b/build_config/Unicos.gfortran.default/build_rules.mk @@ -101,6 +101,15 @@ ESMF_OPENMP_CXXCOMPILEOPTS += -fopenmp ESMF_OPENMP_F90LINKOPTS += -fopenmp ESMF_OPENMP_CXXLINKOPTS += -fopenmp +############################################################ +# OpenACC compiler and linker flags +# +ESMF_OPENACCDEFAULT = OFF +ESMF_OPENACC_F90COMPILEOPTS += -fopenacc +ESMF_OPENACC_CXXCOMPILEOPTS += -fopenacc +ESMF_OPENACC_F90LINKOPTS += -fopenacc +ESMF_OPENACC_CXXLINKOPTS += -fopenacc + ############################################################ # Need this until the file convention is fixed (then remove these two lines) # diff --git a/build_config/Unicos.nvhpc.default/ESMC_Conf.h b/build_config/Unicos.nvhpc.default/ESMC_Conf.h new file mode 100644 index 0000000000..aee30299c8 --- /dev/null +++ b/build_config/Unicos.nvhpc.default/ESMC_Conf.h @@ -0,0 +1,33 @@ +#ifdef ESMC_RCS_HEADER +"$Id$" +"Defines the configuration for this machine" +#endif + +#if 0 +Earth System Modeling Framework +Copyright 2002-2022, 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. +#endif + +#if !defined(INCLUDED_CONF_H) +#define INCLUDED_CONF_H + +#define PARCH_linux + +#define FTN_X(func) func##_ +#define FTNX(func) func##_ + +#if defined (__cplusplus) +// Typedef to match the data type of the 'hidden' string length +// argument that Fortran uses when passing CHARACTER strings. +#include +typedef size_t ESMCI_FortranStrLenArg; +#endif + +#define ESMC_PRESENT(arg) ( (arg) != 0 ) + +#endif diff --git a/build_config/Unicos.nvhpc.default/ESMF_Conf.inc b/build_config/Unicos.nvhpc.default/ESMF_Conf.inc new file mode 100644 index 0000000000..7c130bde51 --- /dev/null +++ b/build_config/Unicos.nvhpc.default/ESMF_Conf.inc @@ -0,0 +1,11 @@ +#if 0 +$Id$ + +Earth System Modeling Framework +Copyright 2002-2022, 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. +#endif diff --git a/build_config/Unicos.nvhpc.default/README b/build_config/Unicos.nvhpc.default/README new file mode 100644 index 0000000000..a65d957223 --- /dev/null +++ b/build_config/Unicos.nvhpc.default/README @@ -0,0 +1,5 @@ +Settings for Linux/lc on Cray, using the NVIDIA HPC compilers. + +Requires the following environment settings: + +ESMF_COMPILER nvhpc diff --git a/build_config/Unicos.nvhpc.default/build_rules.mk b/build_config/Unicos.nvhpc.default/build_rules.mk new file mode 100644 index 0000000000..edde1d3d35 --- /dev/null +++ b/build_config/Unicos.nvhpc.default/build_rules.mk @@ -0,0 +1,167 @@ +# $Id$ +# +# Unicos.nvhpc.default +# + +############################################################ +# Default compiler setting. +# +ESMF_F90DEFAULT = ftn +ESMF_CXXDEFAULT = CC +ESMF_CDEFAULT = cc + +############################################################ +# Default MPI setting. +# +ifeq ($(ESMF_COMM),default) +export ESMF_COMM := mpi +endif + +############################################################ +# MPI dependent settings. +# +ifeq ($(ESMF_COMM),mpiuni) +# MPI stub library ----------------------------------------- +ESMF_F90COMPILECPPFLAGS+= -DESMF_MPIUNI +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_MPIUNI +ESMF_CXXCOMPILEPATHS += -I$(ESMF_DIR)/src/Infrastructure/stubs/mpiuni +ESMF_MPIRUNDEFAULT = $(ESMF_DIR)/src/Infrastructure/stubs/mpiuni/mpirun +else +ifeq ($(ESMF_COMM),mpi) +# Vendor MPI ----------------------------------------------- +ESMF_F90LINKLIBS += +ESMF_CXXLINKLIBS += +ESMF_MPIRUNDEFAULT = mpirun.srun +ESMF_MPIMPMDRUNDEFAULT = +else +ifeq ($(ESMF_COMM),user) +# User specified flags ------------------------------------- +else +$(error Invalid ESMF_COMM setting: $(ESMF_COMM)) +endif +endif +endif + +############################################################ +# Print compiler version string +# +ESMF_F90COMPILER_VERSION = ${ESMF_F90COMPILER} --version -c +ESMF_CXXCOMPILER_VERSION = ${ESMF_CXXCOMPILER} --version -c +ESMF_CCOMPILER_VERSION = ${ESMF_CCOMPILER} --version -c + +############################################################ +# Currently no support the Fortran2018 assumed type feature +# +ESMF_F90COMPILECPPFLAGS += -DESMF_NO_F2018ASSUMEDTYPE +ESMF_CXXCOMPILECPPFLAGS += -DESMF_NO_F2018ASSUMEDTYPE + +############################################################ +# Construct the ABISTRING +# +ifeq ($(ESMF_MACHINE),x86_64) +ifeq ($(ESMF_ABI),32) +ESMF_ABISTRING := $(ESMF_MACHINE)_32 +endif +ifeq ($(ESMF_ABI),64) +ESMF_ABISTRING := x86_64_small +endif +endif + +############################################################ +# Set memory model compiler flags according to ABISTRING +# +ifeq ($(ESMF_ABISTRING),x86_64_32) +ESMF_CXXCOMPILEOPTS += +ESMF_CXXLINKOPTS += +ESMF_F90COMPILEOPTS += +ESMF_F90LINKOPTS += +endif +ifeq ($(ESMF_ABISTRING),x86_64_small) +ESMF_CXXCOMPILEOPTS += -mcmodel=small +ESMF_CXXLINKOPTS += -mcmodel=small +ESMF_F90COMPILEOPTS += -mcmodel=small +ESMF_F90LINKOPTS += -mcmodel=small +endif +ifeq ($(ESMF_ABISTRING),x86_64_medium) +ESMF_CXXCOMPILEOPTS += -mcmodel=medium +ESMF_CXXLINKOPTS += -mcmodel=medium +ESMF_F90COMPILEOPTS += -mcmodel=medium +ESMF_F90LINKOPTS += -mcmodel=medium +endif + +############################################################ +# Enable TR15581/F2003 Allocatable array resizing +# +ESMF_F90COMPILEOPTS += -Mallocatable=03 + +############################################################ +# Conditionally add pthread compiler and linker flags +# +ifeq ($(ESMF_PTHREADS),ON) +ESMF_F90COMPILEOPTS += -pthread +ESMF_CXXCOMPILEOPTS += -pthread +ESMF_F90LINKOPTS += -pthread +ESMF_CXXLINKOPTS += -pthread +endif + +############################################################ +# OpenMP compiler and linker flags +# +ESMF_OPENMP_F90COMPILEOPTS += -mp +ESMF_OPENMP_CXXCOMPILEOPTS += -mp +ESMF_OPENMP_F90LINKOPTS += -mp +ESMF_OPENMP_CXXLINKOPTS += -mp + +############################################################ +# OpenACC compiler and linker flags (the -Minfo just there for debugging) +# +ESMF_OPENACCDEFAULT = OFF +ESMF_OPENACC_F90COMPILEOPTS += -acc -Minfo +ESMF_OPENACC_CXXCOMPILEOPTS += -acc -Minfo +ESMF_OPENACC_F90LINKOPTS += -acc -Minfo +ESMF_OPENACC_CXXLINKOPTS += -acc -Minfo + +############################################################ +# Need this until the file convention is fixed (then remove these two lines) +# +ESMF_F90COMPILEFREENOCPP = -Mfreeform +ESMF_F90COMPILEFIXCPP = -Mpreprocess -Mnofreeform + +############################################################ +# Set rpath syntax +# +ESMF_F90RPATHPREFIX = -Wl,-rpath, +ESMF_CXXRPATHPREFIX = -Wl,-rpath, +ESMF_CRPATHPREFIX = -Wl,-rpath, + +############################################################ +# Link against libesmf.a using the F90 linker front-end +# +ESMF_F90LINKLIBS += -c++libs + +############################################################ +# Link against libesmf.a using the C++ linker front-end +# +ESMF_CXXLINKLIBS += -fortranlibs + +############################################################ +# Linker option that ensures that the specified libraries are +# used to also resolve symbols needed by other libraries. +# +ESMF_F90LINKOPTS += -Wl,--no-as-needed +ESMF_CXXLINKOPTS += -Wl,--no-as-needed + +############################################################ +# Shared library options +# +ESMF_SL_LIBOPTS += -shared + +############################################################ +# Shared object options +# +ESMF_SO_F90COMPILEOPTS = -fpic +ESMF_SO_F90LINKOPTS = -shared +ESMF_SO_F90LINKOPTSEXE = -Wl,-export-dynamic +ESMF_SO_CXXCOMPILEOPTS = -fpic +ESMF_SO_CXXLINKOPTS = -shared +ESMF_SO_CXXLINKOPTSEXE = -Wl,-export-dynamic From cfa92d9aaba0fe37b8aa2d3897cad822b518ebbb Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 1 Sep 2022 10:58:05 -0700 Subject: [PATCH 147/266] Squashed commit of feature/aocc. --- build_config/Linux.aocc.default/ESMC_Conf.h | 43 +++ build_config/Linux.aocc.default/ESMF_Conf.inc | 22 ++ build_config/Linux.aocc.default/README | 5 + .../Linux.aocc.default/build_rules.mk | 271 ++++++++++++++++++ build_config/Unicos.aocc.default/ESMC_Conf.h | 43 +++ .../Unicos.aocc.default/ESMF_Conf.inc | 22 ++ build_config/Unicos.aocc.default/README | 5 + .../Unicos.aocc.default/build_rules.mk | 168 +++++++++++ 8 files changed, 579 insertions(+) create mode 100644 build_config/Linux.aocc.default/ESMC_Conf.h create mode 100644 build_config/Linux.aocc.default/ESMF_Conf.inc create mode 100644 build_config/Linux.aocc.default/README create mode 100644 build_config/Linux.aocc.default/build_rules.mk create mode 100644 build_config/Unicos.aocc.default/ESMC_Conf.h create mode 100644 build_config/Unicos.aocc.default/ESMF_Conf.inc create mode 100644 build_config/Unicos.aocc.default/README create mode 100644 build_config/Unicos.aocc.default/build_rules.mk diff --git a/build_config/Linux.aocc.default/ESMC_Conf.h b/build_config/Linux.aocc.default/ESMC_Conf.h new file mode 100644 index 0000000000..e38d89f02c --- /dev/null +++ b/build_config/Linux.aocc.default/ESMC_Conf.h @@ -0,0 +1,43 @@ +#ifdef ESMC_RCS_HEADER +"$Id$" +"Defines the configuration for this machine" +#endif + +#if 0 +Earth System Modeling Framework +Copyright 2002-2022, 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. +#endif + +#if !defined(INCLUDED_CONF_H) +#define INCLUDED_CONF_H + +#define PARCH_linux + +#ifdef ESMF_LOWERCASE_SINGLEUNDERSCORE +#define FTN_X(func) func##_ +#define FTNX(func) func##_ +#endif +#ifdef ESMF_LOWERCASE_DOUBLEUNDERSCORE +#define FTN_X(func) func##__ +#define FTNX(func) func##_ +#endif + +#if defined (__cplusplus) +// Typedef to match the data type of the 'hidden' string length +// argument that Fortran uses when passing CHARACTER strings. +#if (__GNUC__ > 7) +#include +typedef size_t ESMCI_FortranStrLenArg; +#else +typedef int ESMCI_FortranStrLenArg; +#endif +#endif + +#define ESMC_PRESENT(arg) ( (arg) != 0 ) + +#endif diff --git a/build_config/Linux.aocc.default/ESMF_Conf.inc b/build_config/Linux.aocc.default/ESMF_Conf.inc new file mode 100644 index 0000000000..28343681b2 --- /dev/null +++ b/build_config/Linux.aocc.default/ESMF_Conf.inc @@ -0,0 +1,22 @@ +#if 0 +$Id$ + +Earth System Modeling Framework +Copyright 2002-2022, 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. +#endif + +#if !defined(__cplusplus) +#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) +#error "The gfortran compiler must be version 4.5 or newer." +#endif + +#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 6) +#define ESMF_NO_F2003_ALLOC_STRING_LENS +#endif + +#endif diff --git a/build_config/Linux.aocc.default/README b/build_config/Linux.aocc.default/README new file mode 100644 index 0000000000..d93a29a30e --- /dev/null +++ b/build_config/Linux.aocc.default/README @@ -0,0 +1,5 @@ +Settings for Linux, using the AMD Optimized Compilers (AOCC). + +Requires the following environment settings: + +ESMF_COMPILER aocc diff --git a/build_config/Linux.aocc.default/build_rules.mk b/build_config/Linux.aocc.default/build_rules.mk new file mode 100644 index 0000000000..8636c5f1a9 --- /dev/null +++ b/build_config/Linux.aocc.default/build_rules.mk @@ -0,0 +1,271 @@ +# $Id$ +# +# Linux.aocc.default +# + +############################################################ +# Default compiler setting. +# +ESMF_F90DEFAULT = flang +ESMF_CXXDEFAULT = clang++ +ESMF_CDEFAULT = clang +ESMF_CPPDEFAULT = clang -E -P -x c + +ESMF_CXXCOMPILECPPFLAGS += -x c++ + +############################################################ +# Default MPI setting. +# +ifeq ($(ESMF_COMM),default) +export ESMF_COMM := mpiuni +endif + +############################################################ +# MPI dependent settings. +# +ifeq ($(ESMF_COMM),mpiuni) +# MPI stub library ----------------------------------------- +ESMF_F90COMPILECPPFLAGS+= -DESMF_MPIUNI +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_MPIUNI +ESMF_CXXCOMPILEPATHS += -I$(ESMF_DIR)/src/Infrastructure/stubs/mpiuni +ESMF_MPIRUNDEFAULT = $(ESMF_DIR)/src/Infrastructure/stubs/mpiuni/mpirun +else +ifeq ($(ESMF_COMM),mpi) +# Vendor MPI ----------------------------------------------- +ESMF_F90LINKLIBS += -lmpi -lmpi++ +ESMF_CXXLINKLIBS += -lmpi -lmpi++ +ESMF_MPIRUNDEFAULT = mpiexec_mpt $(ESMF_MPILAUNCHOPTIONS) +ESMF_MPIMPMDRUNDEFAULT = mpiexec_mpt $(ESMF_MPILAUNCHOPTIONS) +else +ifeq ($(ESMF_COMM),mpt) +# MPT with compiler wrappers ------------------------------- +ESMF_F90DEFAULT = mpif90 +ESMF_F90LINKLIBS += -lmpi++ +ESMF_CXXDEFAULT = mpicxx +ESMF_CDEFAULT = mpicc +ESMF_MPIRUNDEFAULT = mpirun $(ESMF_MPILAUNCHOPTIONS) +ESMF_MPIMPMDRUNDEFAULT = mpiexec $(ESMF_MPILAUNCHOPTIONS) +else +ifeq ($(ESMF_COMM),mpich1) +# Mpich1 --------------------------------------------------- +ESMF_F90COMPILECPPFLAGS+= -DESMF_MPICH1 +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_MPICH1 +ESMF_F90DEFAULT = mpif90 +ESMF_F90LINKLIBS += -lpmpich++ -lmpich +ESMF_CXXDEFAULT = mpiCC +ESMF_CDEFAULT = mpicc +ESMF_MPIRUNDEFAULT = mpirun $(ESMF_MPILAUNCHOPTIONS) +ESMF_F90COMPILECPPFLAGS+= -DESMF_NO_MPI3 +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_NO_MPI3 +else +ifeq ($(ESMF_COMM),mpich2) +# Mpich2 --------------------------------------------------- +ESMF_F90DEFAULT = mpif90 +ESMF_CXXDEFAULT = mpicxx +ESMF_CDEFAULT = mpicc +ESMF_MPIRUNDEFAULT = mpirun $(ESMF_MPILAUNCHOPTIONS) +ESMF_MPIMPMDRUNDEFAULT = mpiexec $(ESMF_MPILAUNCHOPTIONS) +ESMF_F90COMPILECPPFLAGS+= -DESMF_NO_MPI3 +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_NO_MPI3 +else +ifeq ($(ESMF_COMM),mpich) +# Mpich3 and up -------------------------------------------- +ESMF_F90DEFAULT = mpif90 +ESMF_CXXDEFAULT = mpicxx +ESMF_CDEFAULT = mpicc +ESMF_MPIRUNDEFAULT = mpirun $(ESMF_MPILAUNCHOPTIONS) +ESMF_MPIMPMDRUNDEFAULT = mpiexec $(ESMF_MPILAUNCHOPTIONS) +else +ifeq ($(ESMF_COMM),mvapich2) +# Mvapich2 --------------------------------------------------- +ESMF_F90DEFAULT = mpif90 +ESMF_CXXDEFAULT = mpicxx +ESMF_CDEFAULT = mpicc +ESMF_MPIRUNDEFAULT = mpirun $(ESMF_MPILAUNCHOPTIONS) +ESMF_MPIMPMDRUNDEFAULT = mpiexec $(ESMF_MPILAUNCHOPTIONS) +else +ifeq ($(ESMF_COMM),lam) +# LAM (assumed to be built with gfortran) ----------------------- +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_NO_SIGUSR2 +ESMF_F90DEFAULT = mpif77 +ESMF_CXXDEFAULT = mpic++ +ESMF_CDEFAULT = mpicc +ESMF_MPIRUNDEFAULT = mpirun $(ESMF_MPILAUNCHOPTIONS) +ESMF_MPIMPMDRUNDEFAULT = mpiexec $(ESMF_MPILAUNCHOPTIONS) +ESMF_F90COMPILECPPFLAGS+= -DESMF_NO_MPI3 +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_NO_MPI3 +else +ifeq ($(ESMF_COMM),openmpi) +# OpenMPI -------------------------------------------------- +ifeq ($(shell $(ESMF_DIR)/scripts/available mpifort),mpifort) +ESMF_F90DEFAULT = mpifort +else +ESMF_F90DEFAULT = mpif90 +endif +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_NO_SIGUSR2 +ESMF_F90LINKLIBS += $(shell $(ESMF_DIR)/scripts/libs.openmpif90 $(ESMF_F90DEFAULT)) +ESMF_CXXDEFAULT = mpicxx +ESMF_CDEFAULT = mpicc +ESMF_MPIRUNDEFAULT = mpirun $(ESMF_MPILAUNCHOPTIONS) +ESMF_MPIMPMDRUNDEFAULT = mpiexec $(ESMF_MPILAUNCHOPTIONS) +else +ifeq ($(ESMF_COMM),user) +# User specified flags ------------------------------------- +else +$(error Invalid ESMF_COMM setting: $(ESMF_COMM)) +endif +endif +endif +endif +endif +endif +endif +endif +endif +endif + +############################################################ +# Print compiler version string +# +ESMF_F90COMPILER_VERSION = ${ESMF_F90COMPILER} -v --version +ESMF_CXXCOMPILER_VERSION = ${ESMF_CXXCOMPILER} -v --version +ESMF_CCOMPILER_VERSION = ${ESMF_CCOMPILER} -v --version + +############################################################ +# Currently no support the Fortran2018 assumed type feature +# +ESMF_F90COMPILECPPFLAGS += -DESMF_NO_F2018ASSUMEDTYPE +ESMF_CXXCOMPILECPPFLAGS += -DESMF_NO_F2018ASSUMEDTYPE + +############################################################ +# Special debug flags +# +ESMF_F90OPTFLAG_G += -Wall -Wextra -Wconversion -Wno-unused + +############################################################ +# Fortran symbol convention +# +ifeq ($(ESMF_FORTRANSYMBOLS),default) +ESMF_F90COMPILEOPTS += +ESMF_F90LINKOPTS += +ESMF_CXXCOMPILEOPTS += -DESMF_LOWERCASE_SINGLEUNDERSCORE +else +ifeq ($(ESMF_FORTRANSYMBOLS),lowercase_singleunderscore) +ESMF_F90COMPILEOPTS += -fno-second-underscore +ESMF_F90LINKOPTS += -fno-second-underscore +ESMF_CXXCOMPILEOPTS += -DESMF_LOWERCASE_SINGLEUNDERSCORE +else +ifeq ($(ESMF_FORTRANSYMBOLS),lowercase_doubleunderscore) +ESMF_F90COMPILEOPTS += -fsecond-underscore +ESMF_F90LINKOPTS += -fsecond-underscore +ESMF_CXXCOMPILEOPTS += -DESMF_LOWERCASE_DOUBLEUNDERSCORE +else +$(error "ESMF_FORTRANSYMBOLS = $(ESMF_FORTRANSYMBOLS)" not supported by ESMF and/or this platform) +endif +endif +endif + +############################################################ +# Construct the ABISTRING +# +ifeq ($(ESMF_MACHINE),ia64) +ifeq ($(ESMF_ABI),64) +ESMF_ABISTRING := $(ESMF_MACHINE)_64 +else +$(error Invalid ESMF_MACHINE / ESMF_ABI combination: $(ESMF_MACHINE) / $(ESMF_ABI)) +endif +endif +ifeq ($(ESMF_MACHINE),x86_64) +ifeq ($(ESMF_ABI),32) +ESMF_ABISTRING := $(ESMF_MACHINE)_32 +endif +ifeq ($(ESMF_ABI),64) +ESMF_ABISTRING := x86_64_small +endif +endif + +############################################################ +# Set memory model compiler flags according to ABISTRING +# +ifeq ($(ESMF_ABISTRING),x86_64_32) +ESMF_CXXCOMPILEOPTS += -m32 +ESMF_CXXLINKOPTS += -m32 +ESMF_F90COMPILEOPTS += -m32 +ESMF_F90LINKOPTS += -m32 +endif +ifeq ($(ESMF_ABISTRING),x86_64_small) +ESMF_CXXCOMPILEOPTS += -m64 -mcmodel=small +ESMF_CXXLINKOPTS += -m64 -mcmodel=small +ESMF_F90COMPILEOPTS += -m64 -mcmodel=small +ESMF_F90LINKOPTS += -m64 -mcmodel=small +endif +ifeq ($(ESMF_ABISTRING),x86_64_medium) +ESMF_CXXCOMPILEOPTS += -m64 -mcmodel=medium +ESMF_CXXLINKOPTS += -m64 -mcmodel=medium +ESMF_F90COMPILEOPTS += -m64 -mcmodel=medium +ESMF_F90LINKOPTS += -m64 -mcmodel=medium +endif + +############################################################ +# Conditionally add pthread compiler and linker flags +# +ifeq ($(ESMF_PTHREADS),ON) +ESMF_F90COMPILEOPTS += -pthread +ESMF_CXXCOMPILEOPTS += -pthread +ESMF_F90LINKOPTS += -pthread +ESMF_CXXLINKOPTS += -pthread +endif + +############################################################ +# OpenMP compiler and linker flags +# +ESMF_OPENMP=ON +ESMF_OPENMP_F90COMPILEOPTS += -fopenmp +ESMF_OPENMP_CXXCOMPILEOPTS += -fopenmp +ESMF_OPENMP_F90LINKOPTS += -fopenmp +ESMF_OPENMP_CXXLINKOPTS += -fopenmp + +############################################################ +# Need this until the file convention is fixed (then remove these two lines) +# +ESMF_F90COMPILEFREENOCPP = -ffree-form +ESMF_F90COMPILEFIXCPP = -cpp -ffixed-form + +############################################################ +# Set rpath syntax +# +ESMF_F90RPATHPREFIX = -Wl,-rpath, +ESMF_CXXRPATHPREFIX = -Wl,-rpath, +ESMF_CRPATHPREFIX = -Wl,-rpath, + +############################################################ +# Link against libesmf.a using the F90 linker front-end +# +ESMF_F90LINKLIBS += -lrt -lstdc++ -ldl + +############################################################ +# Link against libesmf.a using the C++ linker front-end +# +ESMF_CXXLINKLIBS += -lrt -lflang -lflangrti -lpgmath -ldl + +############################################################ +# Linker option that ensures that the specified libraries are +# used to also resolve symbols needed by other libraries. +# +ESMF_F90LINKOPTS += -Wl,--no-as-needed +ESMF_CXXLINKOPTS += -Wl,--no-as-needed + +############################################################ +# Shared library options +# +ESMF_SL_LIBOPTS += -shared + +############################################################ +# Shared object options +# +ESMF_SO_F90COMPILEOPTS = -fPIC +ESMF_SO_F90LINKOPTS = -shared +ESMF_SO_F90LINKOPTSEXE = -Wl,-export-dynamic +ESMF_SO_CXXCOMPILEOPTS = -fPIC +ESMF_SO_CXXLINKOPTS = -shared +ESMF_SO_CXXLINKOPTSEXE = -Wl,-export-dynamic diff --git a/build_config/Unicos.aocc.default/ESMC_Conf.h b/build_config/Unicos.aocc.default/ESMC_Conf.h new file mode 100644 index 0000000000..e38d89f02c --- /dev/null +++ b/build_config/Unicos.aocc.default/ESMC_Conf.h @@ -0,0 +1,43 @@ +#ifdef ESMC_RCS_HEADER +"$Id$" +"Defines the configuration for this machine" +#endif + +#if 0 +Earth System Modeling Framework +Copyright 2002-2022, 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. +#endif + +#if !defined(INCLUDED_CONF_H) +#define INCLUDED_CONF_H + +#define PARCH_linux + +#ifdef ESMF_LOWERCASE_SINGLEUNDERSCORE +#define FTN_X(func) func##_ +#define FTNX(func) func##_ +#endif +#ifdef ESMF_LOWERCASE_DOUBLEUNDERSCORE +#define FTN_X(func) func##__ +#define FTNX(func) func##_ +#endif + +#if defined (__cplusplus) +// Typedef to match the data type of the 'hidden' string length +// argument that Fortran uses when passing CHARACTER strings. +#if (__GNUC__ > 7) +#include +typedef size_t ESMCI_FortranStrLenArg; +#else +typedef int ESMCI_FortranStrLenArg; +#endif +#endif + +#define ESMC_PRESENT(arg) ( (arg) != 0 ) + +#endif diff --git a/build_config/Unicos.aocc.default/ESMF_Conf.inc b/build_config/Unicos.aocc.default/ESMF_Conf.inc new file mode 100644 index 0000000000..28343681b2 --- /dev/null +++ b/build_config/Unicos.aocc.default/ESMF_Conf.inc @@ -0,0 +1,22 @@ +#if 0 +$Id$ + +Earth System Modeling Framework +Copyright 2002-2022, 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. +#endif + +#if !defined(__cplusplus) +#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) +#error "The gfortran compiler must be version 4.5 or newer." +#endif + +#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 6) +#define ESMF_NO_F2003_ALLOC_STRING_LENS +#endif + +#endif diff --git a/build_config/Unicos.aocc.default/README b/build_config/Unicos.aocc.default/README new file mode 100644 index 0000000000..8df09e459d --- /dev/null +++ b/build_config/Unicos.aocc.default/README @@ -0,0 +1,5 @@ +Settings for Unicos/lc on Cray, using the AMD Optimized Compilers (AOCC). + +Requires the following environment settings: + +ESMF_COMPILER aocc diff --git a/build_config/Unicos.aocc.default/build_rules.mk b/build_config/Unicos.aocc.default/build_rules.mk new file mode 100644 index 0000000000..d0b0784ff7 --- /dev/null +++ b/build_config/Unicos.aocc.default/build_rules.mk @@ -0,0 +1,168 @@ +# $Id$ +# +# Unicos.aocc.default +# + +############################################################ +# Default compiler setting. +# +ESMF_F90DEFAULT = ftn +ESMF_CXXDEFAULT = CC +ESMF_CDEFAULT = cc + +############################################################ +# Default MPI setting. +# +ifeq ($(ESMF_COMM),default) +export ESMF_COMM := mpi +endif + +############################################################ +# MPI dependent settings. +# +ifeq ($(ESMF_COMM),mpiuni) +# MPI stub library ----------------------------------------- +ESMF_F90COMPILECPPFLAGS+= -DESMF_MPIUNI +ESMF_CXXCOMPILECPPFLAGS+= -DESMF_MPIUNI +ESMF_CXXCOMPILEPATHS += -I$(ESMF_DIR)/src/Infrastructure/stubs/mpiuni +ESMF_MPIRUNDEFAULT = $(ESMF_DIR)/src/Infrastructure/stubs/mpiuni/mpirun +else +ifeq ($(ESMF_COMM),mpi) +# Vendor MPI ----------------------------------------------- +ESMF_F90LINKLIBS += +ESMF_CXXLINKLIBS += +ESMF_MPIRUNDEFAULT = mpirun.srun +ESMF_MPIMPMDRUNDEFAULT = +else +ifeq ($(ESMF_COMM),user) +# User specified flags ------------------------------------- +else +$(error Invalid ESMF_COMM setting: $(ESMF_COMM)) +endif +endif +endif + +############################################################ +# Print compiler version string +# +ESMF_F90COMPILER_VERSION = ${ESMF_F90COMPILER} -v --version +ESMF_CXXCOMPILER_VERSION = ${ESMF_CXXCOMPILER} -v --version +ESMF_CCOMPILER_VERSION = ${ESMF_CCOMPILER} -v --version + +############################################################ +# Currently no support the Fortran2018 assumed type feature +# +ESMF_F90COMPILECPPFLAGS += -DESMF_NO_F2018ASSUMEDTYPE +ESMF_CXXCOMPILECPPFLAGS += -DESMF_NO_F2018ASSUMEDTYPE + +############################################################ +# Special debug flags +# +ESMF_F90OPTFLAG_G += -Wall -Wextra -Wconversion -Wno-unused + +############################################################ +# Fortran symbol convention +# +ifeq ($(ESMF_FORTRANSYMBOLS),default) +ESMF_F90COMPILEOPTS += +ESMF_F90LINKOPTS += +ESMF_CXXCOMPILEOPTS += -DESMF_LOWERCASE_SINGLEUNDERSCORE +else +ifeq ($(ESMF_FORTRANSYMBOLS),lowercase_singleunderscore) +ESMF_F90COMPILEOPTS += -fno-second-underscore +ESMF_F90LINKOPTS += -fno-second-underscore +ESMF_CXXCOMPILEOPTS += -DESMF_LOWERCASE_SINGLEUNDERSCORE +else +ifeq ($(ESMF_FORTRANSYMBOLS),lowercase_doubleunderscore) +ESMF_F90COMPILEOPTS += -fsecond-underscore +ESMF_F90LINKOPTS += -fsecond-underscore +ESMF_CXXCOMPILEOPTS += -DESMF_LOWERCASE_DOUBLEUNDERSCORE +else +$(error "ESMF_FORTRANSYMBOLS = $(ESMF_FORTRANSYMBOLS)" not supported by ESMF and/or this platform) +endif +endif +endif + +############################################################ +# XT compute nodes do not have support for POSIX IPC (memory mapped files) +# +ESMF_CXXCOMPILECPPFLAGS += -DESMF_NO_POSIXIPC + +############################################################ +# Conditionally add pthread compiler and linker flags +# +ifeq ($(ESMF_PTHREADS),ON) +ESMF_F90COMPILEOPTS += -pthread +ESMF_CXXCOMPILEOPTS += -pthread +ESMF_F90LINKOPTS += -pthread +ESMF_CXXLINKOPTS += -pthread +endif + +############################################################ +# OpenMP compiler and linker flags +# +ESMF_OPENMP=ON +ESMF_OPENMP_F90COMPILEOPTS += -fopenmp +ESMF_OPENMP_CXXCOMPILEOPTS += -fopenmp +ESMF_OPENMP_F90LINKOPTS += -fopenmp +ESMF_OPENMP_CXXLINKOPTS += -fopenmp + +############################################################ +# OpenACC compiler and linker flags +# +ESMF_OPENACCDEFAULT = OFF +ESMF_OPENACC_F90COMPILEOPTS += -fopenacc +ESMF_OPENACC_CXXCOMPILEOPTS += -fopenacc +ESMF_OPENACC_F90LINKOPTS += -fopenacc +ESMF_OPENACC_CXXLINKOPTS += -fopenacc + +############################################################ +# Need this until the file convention is fixed (then remove these two lines) +# +ESMF_F90COMPILEFREENOCPP = -ffree-form +ESMF_F90COMPILEFIXCPP = -cpp -ffixed-form + +############################################################ +# Set rpath syntax +# +ESMF_F90RPATHPREFIX = -Wl,-rpath, +ESMF_CXXRPATHPREFIX = -Wl,-rpath, +ESMF_CRPATHPREFIX = -Wl,-rpath, + +############################################################ +# Link against libesmf.a using the F90 linker front-end +# +ESMF_F90LINKLIBS += -lrt -lstdc++ -ldl + +############################################################ +# Link against libesmf.a using the C++ linker front-end +# +ESMF_CXXLINKLIBS += -lrt -lflang -lflangrti -lpgmath -ldl + +############################################################ +# Shared library options +# +ESMF_SL_LIBOPTS += -shared + +############################################################ +# Shared object options +# +ESMF_SO_F90COMPILEOPTS = -fPIC +ESMF_SO_F90LINKOPTS = -shared +ESMF_SO_F90LINKOPTSEXE = -Wl,-export-dynamic +ESMF_SO_CXXCOMPILEOPTS = -fPIC +ESMF_SO_CXXLINKOPTS = -shared +ESMF_SO_CXXLINKOPTSEXE = -Wl,-export-dynamic + +############################################################ +# Disable WebService testing for now +# +# TODO: Remove this variable and associated infrastructure as soon as +# TODO: WebService testing is robust enough to work on all systems. +# +ESMF_NOWEBSERVTESTING = TRUE + +############################################################ +# Override default C preprocessor on this platform +# +ESMF_CPPDEFAULT = gcc -E -P -x c From 6bbdd74014ec1d57ac8c9523a7ac81519c78a7aa Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 1 Sep 2022 11:06:44 -0700 Subject: [PATCH 148/266] Adding new nvhpc and aocc combos to the table. --- build/doc/user_arch.tex | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build/doc/user_arch.tex b/build/doc/user_arch.tex index 4bed5cda99..9638439576 100644 --- a/build/doc/user_arch.tex +++ b/build/doc/user_arch.tex @@ -36,6 +36,11 @@ IRIX64 &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 32, {\bf 64} \\ Linux &\tt absoft &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64 \\ Linux &\tt absoftintel &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,lam,openmpi,user &\tt 32, 64 \\ +Linux &\tt aocc &\footnotesize \tt {\bf mpiuni},mpi,mpt,mpich,mpich1,mpich2,mpich3,mvapich2, &\tt 32, 64, \\ + &\footnotesize \tt intelmpi,lam,openmpi,user &\tt ia64\_64, \\ + & &\tt x86\_64\_32, \\ + & &\tt x86\_64\_small, \\ + & &\tt x86\_64\_medium \\ Linux &\tt g95 &\footnotesize \tt {\bf mpiuni},mpich,mpich1,mpich2,mpich3,mvapich2,lam,openmpi,user &\tt 32, 64, \\ & & &\tt ia64\_64, \\ & & &\tt x86\_64\_32, \\ @@ -86,9 +91,11 @@ OSF1 &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ SunOS &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 32, {\bf 64} \\ Unicos &\tt default &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +Unicos &\tt aocc &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ Unicos &\tt cce &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ Unicos &\tt gfortran &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ Unicos &\tt intel &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ +Unicos &\tt nvhpc &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ Unicos &\tt pathscale &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 \\ Unicos &\tt pgi &\footnotesize \tt mpiuni,{\bf mpi},user &\tt 64 From 505b6a76db00990a886cb63d8c0a089494db0d6a Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 1 Sep 2022 13:34:37 -0700 Subject: [PATCH 149/266] remove beta decorator from ESMPy GridCreateCubedSphere --- src/addon/ESMPy/src/esmpy/interface/cbindings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/addon/ESMPy/src/esmpy/interface/cbindings.py b/src/addon/ESMPy/src/esmpy/interface/cbindings.py index c344b48d37..b15f247102 100644 --- a/src/addon/ESMPy/src/esmpy/interface/cbindings.py +++ b/src/addon/ESMPy/src/esmpy/interface/cbindings.py @@ -613,7 +613,6 @@ def ESMP_GridCreateNoPeriDim(maxIndex, coordSys=None, coordTypeKind=None): ct.POINTER(ESMP_InterfaceInt), ct.c_void_p, ct.POINTER(ct.c_int)] -@beta def ESMP_GridCreateCubedSphere(tilesize, regDecompPTile=None, #decompFlagPTile=None, deLabelList=None, staggerLocList=None, name=None): From 1934fa45deffbf6ec56955f9cbd273fb5c0a6c24 Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Thu, 1 Sep 2022 15:15:22 -0600 Subject: [PATCH 150/266] Add more explanation about restrictions to easy elem Mesh create doc. --- src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 b/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 index 57993be1e3..9e6e491fd9 100644 --- a/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 +++ b/src/Infrastructure/Mesh/interface/ESMF_Mesh.F90 @@ -3759,7 +3759,10 @@ function ESMF_MeshCreateEasyElems1Type(parametricDim, coordSys, & ! a bit easier. ! After this call the Mesh is usable, for ! example, a Field may be built on the created Mesh object and -! this Field may be used in a {\tt ESMF\_FieldRegridStore()} call. +! this Field may be used in {\tt ESMF\_FieldRegridStore()}. However, the Mesh created by this +! call consists of a set of disconnected elements, and so shouldn't be used in a situation where +! connections between elements are necessary (e.g. bilinear regridding on element centers, patch regridding, +! or second-order conservative regridding). ! ! This call sets the dimension of the elements in the Mesh ! via {\tt parametricDim} and the number of coordinate dimensions in the mesh @@ -3902,7 +3905,10 @@ function ESMF_MeshCreateEasyElemsGen(parametricDim, coordSys, & ! Internally these corners are turned into nodes forming the outside edges of the elements. ! After this call the Mesh is usable, for ! example, a Field may be built on the created Mesh object and -! this Field may be used in a {\tt ESMF\_FieldRegridStore()} call. +! this Field may be used in {\tt ESMF\_FieldRegridStore()}. However, the Mesh created by this +! call consists of a set of disconnected elements, and so shouldn't be used in a situation where +! connections between elements are necessary (e.g. bilinear regridding on element centers, patch regridding, +! or second-order conservative regridding). ! ! This call sets the dimension of the elements in the Mesh ! via {\tt parametricDim} and the number of coordinate dimensions in the mesh From dcfe53bc9f9c0414d7c4f83cdfd25eda602f4a47 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 2 Sep 2022 08:52:29 -0700 Subject: [PATCH 151/266] First implementation of the Earth System Model eXecutable (ESMX) layer. (This is merging feature/unex where this idea was implemented first.) --- build/common.mk | 3 + makefile | 4 +- .../VM/tests/ESMF_VMComponentUTest.F90 | 261 ++++++++- .../Component/src/ESMF_CplComp.F90 | 6 +- .../Component/src/ESMF_GridComp.F90 | 6 +- .../tests/ESMF_CplCompCreateUTest.F90 | 93 +++- .../tests/ESMF_GridCompCreateUTest.F90 | 55 +- src/addon/ESMX/CMakeLists.txt | 30 + src/addon/ESMX/cmake/FindESMF.cmake | 138 +++++ src/addon/ESMX/esmx.F90 | 513 ++++++++++++++++++ src/addon/ESMX/esmxGen.py | 94 ++++ src/addon/NUOPC/src/NUOPC_Driver.F90 | 28 +- 12 files changed, 1192 insertions(+), 39 deletions(-) create mode 100644 src/addon/ESMX/CMakeLists.txt create mode 100644 src/addon/ESMX/cmake/FindESMF.cmake create mode 100644 src/addon/ESMX/esmx.F90 create mode 100755 src/addon/ESMX/esmxGen.py diff --git a/build/common.mk b/build/common.mk index 0aef0b697e..7bce715e6a 100644 --- a/build/common.mk +++ b/build/common.mk @@ -637,6 +637,9 @@ ESMF_EXDIR = $(ESMF_BUILD)/examples/examples$(ESMF_BOPT)/$(ESMF_OS).$(ESMF_ # apps executable directory ESMF_APPSDIR = $(ESMF_BUILD)/apps/apps$(ESMF_BOPT)/$(ESMF_OS).$(ESMF_COMPILER).$(ESMF_ABI).$(ESMF_COMM).$(ESMF_SITE) +# unified nuopc executable directory +ESMF_ESMXDIR = $(ESMF_BUILD)/src/addon/ESMX + # include file directory ESMF_INCDIR = $(ESMF_BUILD)/src/include diff --git a/makefile b/makefile index 17dac06d7f..5d66726882 100644 --- a/makefile +++ b/makefile @@ -445,6 +445,7 @@ endif -@echo "" >> $(MKINFO) -@echo "ESMF_APPSDIR=$(ESMF_APPSDIR)" >> $(MKINFO) -@echo "ESMF_LIBSDIR=$(ESMF_LIBDIR)" >> $(MKINFO) + -@echo "ESMF_ESMXDIR=$(ESMF_ESMXDIR)" >> $(MKINFO) -@echo "" >> $(MKINFO) -@echo "" >> $(MKINFO) -@echo "ESMF_F90COMPILER=$(ESMF_F90COMPILER)" >> $(MKINFO) @@ -658,7 +659,7 @@ endif # Rewrite esmf.mk during installation to ensure correct installation paths are encoded install_info_mk: - $(MAKE) info_mk ESMF_APPSDIR=$(ESMF_INSTALL_BINDIR_ABSPATH) ESMF_LDIR=$(ESMF_INSTALL_LIBDIR_ABSPATH) ESMF_LIBDIR=$(ESMF_INSTALL_LIBDIR_ABSPATH) ESMF_MODDIR=$(ESMF_INSTALL_MODDIR_ABSPATH) ESMF_INCDIR=$(ESMF_INSTALL_HEADERDIR_ABSPATH) + $(MAKE) info_mk ESMF_APPSDIR=$(ESMF_INSTALL_BINDIR_ABSPATH) ESMF_LDIR=$(ESMF_INSTALL_LIBDIR_ABSPATH) ESMF_LIBDIR=$(ESMF_INSTALL_LIBDIR_ABSPATH) ESMF_ESMXDIR=$(ESMF_INSTALL_HEADERDIR_ABSPATH)/ESMX ESMF_MODDIR=$(ESMF_INSTALL_MODDIR_ABSPATH) ESMF_INCDIR=$(ESMF_INSTALL_HEADERDIR_ABSPATH) # Relink apps during installation to ensure correct shared library location is encoded install_apps: @@ -695,6 +696,7 @@ install: cp -f $(ESMF_BUILD)/src/include/ESMC.h $(ESMF_INSTALL_HEADERDIR_ABSPATH) cp -f $(ESMF_BUILD)/src/include/ESMC_*.h $(ESMF_INSTALL_HEADERDIR_ABSPATH) cp -f $(ESMF_DIR)/build_config/$(ESMF_OS).$(ESMF_COMPILER).$(ESMF_SITE)/ESMC_Conf.h $(ESMF_INSTALL_HEADERDIR_ABSPATH) + cp -fr $(ESMF_ESMXDIR) $(ESMF_INSTALL_HEADERDIR_ABSPATH) mkdir -p $(ESMF_INSTALL_MODDIR_ABSPATH) cp -f $(ESMF_MODDIR)/*.mod $(ESMF_INSTALL_MODDIR_ABSPATH) mkdir -p $(ESMF_INSTALL_LIBDIR_ABSPATH) diff --git a/src/Infrastructure/VM/tests/ESMF_VMComponentUTest.F90 b/src/Infrastructure/VM/tests/ESMF_VMComponentUTest.F90 index 6898f8a6e7..fa2d5be0c6 100644 --- a/src/Infrastructure/VM/tests/ESMF_VMComponentUTest.F90 +++ b/src/Infrastructure/VM/tests/ESMF_VMComponentUTest.F90 @@ -200,10 +200,11 @@ program ESMF_VMComponentUTest character(ESMF_MAXSTR) :: name ! local variables - integer:: i, j, rc, loop_rc + integer:: i, j, rc, loop_rc, localPet, petCount, loc_petCount type(ESMF_VM):: vm, vm2 type(ESMF_GridComp):: gcomp(1000), gcomp2 logical :: isCreated + integer, allocatable :: petList(:) !------------------------------------------------------------------------------ ! The unit tests are divided into Sanity and Exhaustive. The Sanity tests are @@ -218,17 +219,23 @@ program ESMF_VMComponentUTest ! Get global VM and print info call ESMF_VMGetGlobal(vm, rc=rc) - call ESMF_VMPrint(vm) - + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_VMGet(vm, petCount=petCount, localPet=localPet, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_VMLog(vm, rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + !---------------------------------------------------------------- + !---------------------------------------------------------------- ! Prepare for loop testing - loop_rc=ESMF_SUCCESS + loop_rc=ESMF_SUCCESS do j=1, 1 do i=1, 2 gcomp(i) = ESMF_GridCompCreate(name='My gridded component', rc=loop_rc) if (loop_rc /= ESMF_SUCCESS) goto 10 - + call ESMF_GridCompSetVM(gcomp(i), userRoutine=mygcomp_setvm, & rc=loop_rc) if (loop_rc /= ESMF_SUCCESS) goto 10 @@ -240,9 +247,11 @@ program ESMF_VMComponentUTest enddo do i=1, 2 + call ESMF_GridCompGet(gcomp(i), petCount=loc_petCount, rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 10 call ESMF_GridCompDestroy(gcomp(i), rc=loop_rc) if (loop_rc /= ESMF_SUCCESS) goto 10 - + enddo enddo @@ -253,16 +262,24 @@ program ESMF_VMComponentUTest write(name, *) "Component Create/SetServices/Destroy Test" write(failMsg, *) "Failure codes returned!" call ESMF_Test((loop_rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !Check petCount + !NEX_UTest + write(name, *) "Check petCount for Component Create/SetServices/Destroy Test" + write(failMsg, *) "Incorrect petCount!" + call ESMF_Test((loc_petCount==petCount), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !---------------------------------------------------------------- ! Prepare for loop testing - loop_rc=ESMF_SUCCESS + loop_rc=ESMF_SUCCESS do j=1, 1 do i=1, 2 gcomp(i) = ESMF_GridCompCreate(name='My gridded component', rc=loop_rc) if (loop_rc /= ESMF_SUCCESS) goto 15 - + call ESMF_GridCompSetVM(gcomp(i), userRoutine=mygcomp_setvmForcePthreads,& rc=loop_rc) if (loop_rc /= ESMF_SUCCESS) goto 15 @@ -274,9 +291,11 @@ program ESMF_VMComponentUTest enddo do i=1, 2 + call ESMF_GridCompGet(gcomp(i), petCount=loc_petCount, rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 15 call ESMF_GridCompDestroy(gcomp(i), rc=loop_rc) if (loop_rc /= ESMF_SUCCESS) goto 15 - + enddo enddo @@ -287,6 +306,222 @@ program ESMF_VMComponentUTest write(name, *) "Component Create/SetServices/Destroy ForcePthreads Test" write(failMsg, *) "Failure codes returned!" call ESMF_Test((loop_rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !Check petCount + !NEX_UTest + write(name, *) "Check petCount for Component Create/SetServices/Destroy ForcePthreads Test" + write(failMsg, *) "Incorrect petCount!" + call ESMF_Test((loc_petCount==petCount), name, failMsg, result, ESMF_SRCLINE) + + !---------------------------------------------------------------- + !---------------------------------------------------------------- + ! Prepare for loop testing + loop_rc=ESMF_SUCCESS + loc_petCount = -1 + + do j=1, 1 + do i=1, 2 + + gcomp(i) = ESMF_GridCompCreate(name='My gridded component', & + petList=(/0/), rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 110 + + call ESMF_GridCompSetVM(gcomp(i), userRoutine=mygcomp_setvm, & + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 110 + + call ESMF_GridCompSetServices(gcomp(i), userRoutine=mygcomp_register_nexh, & + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 110 + + enddo + do i=1, 2 + + call ESMF_GridCompGet(gcomp(i), petCount=loc_petCount, rc=rc) + if (localPet==0) then + loop_rc=rc + elseif (rc/=ESMF_SUCCESS) then + loop_rc=ESMF_SUCCESS + endif + if (loop_rc /= ESMF_SUCCESS) goto 110 + call ESMF_GridCompDestroy(gcomp(i), rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 110 + + enddo + enddo + +110 continue + !---------------------------------------------------------------- + !Verify loop test results + !NEX_UTest + write(name, *) "Component Create/SetServices/Destroy with petList Test" + write(failMsg, *) "Failure codes returned!" + call ESMF_Test((loop_rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !Check petCount + !NEX_UTest + write(name, *) "Check petCount for Component Create/SetServices/Destroy with petList Test" + write(failMsg, *) "Incorrect petCount!" + if (localPet==0) then + call ESMF_Test((loc_petCount==1), name, failMsg, result, ESMF_SRCLINE) + else + call ESMF_Test((loc_petCount==-1), name, failMsg, result, ESMF_SRCLINE) + endif + + !---------------------------------------------------------------- + !---------------------------------------------------------------- + ! Prepare for loop testing + loop_rc=ESMF_SUCCESS + loc_petCount = -1 + + do j=1, 1 + do i=1, 2 + + gcomp(i) = ESMF_GridCompCreate(name='My gridded component', & + petList=(/0/), rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 115 + + call ESMF_GridCompSetVM(gcomp(i), userRoutine=mygcomp_setvmForcePthreads,& + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 115 + + call ESMF_GridCompSetServices(gcomp(i), userRoutine=mygcomp_register_nexh, & + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 115 + + enddo + do i=1, 2 + + call ESMF_GridCompGet(gcomp(i), petCount=loc_petCount, rc=rc) + if (localPet==0) then + loop_rc=rc + elseif (rc/=ESMF_SUCCESS) then + loop_rc=ESMF_SUCCESS + endif + if (loop_rc /= ESMF_SUCCESS) goto 115 + call ESMF_GridCompDestroy(gcomp(i), rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 115 + + enddo + enddo + +115 continue + !---------------------------------------------------------------- + !Verify loop test results + !NEX_UTest + write(name, *) "Component Create/SetServices/Destroy ForcePthreads with petList Test" + write(failMsg, *) "Failure codes returned!" + call ESMF_Test((loop_rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !Check petCount + !NEX_UTest + write(name, *) "Check petCount for Component Create/SetServices/Destroy ForcePthreads with petList Test" + write(failMsg, *) "Incorrect petCount!" + if (localPet==0) then + call ESMF_Test((loc_petCount==1), name, failMsg, result, ESMF_SRCLINE) + else + call ESMF_Test((loc_petCount==-1), name, failMsg, result, ESMF_SRCLINE) + endif + + !---------------------------------------------------------------- + !---------------------------------------------------------------- + + !---------------------------------------------------------------- + !---------------------------------------------------------------- + ! Prepare for loop testing + loop_rc=ESMF_SUCCESS + allocate(petList(0)) + + do j=1, 1 + do i=1, 2 + + gcomp(i) = ESMF_GridCompCreate(name='My gridded component', & + petList=petList, rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 210 + + call ESMF_GridCompSetVM(gcomp(i), userRoutine=mygcomp_setvm, & + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 210 + + call ESMF_GridCompSetServices(gcomp(i), userRoutine=mygcomp_register_nexh, & + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 210 + + enddo + do i=1, 2 + + call ESMF_GridCompGet(gcomp(i), petCount=loc_petCount, rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 210 + call ESMF_GridCompDestroy(gcomp(i), rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 210 + + enddo + enddo + deallocate(petList) + +210 continue + !---------------------------------------------------------------- + !Verify loop test results + !NEX_UTest + write(name, *) "Component Create/SetServices/Destroy with empty petList Test" + write(failMsg, *) "Failure codes returned!" + call ESMF_Test((loop_rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !Check petCount + !NEX_UTest + write(name, *) "Check petCount for Component Create/SetServices/Destroy with empty petList Test" + write(failMsg, *) "Incorrect petCount!" + call ESMF_Test((loc_petCount==petCount), name, failMsg, result, ESMF_SRCLINE) + + !---------------------------------------------------------------- + !---------------------------------------------------------------- + ! Prepare for loop testing + loop_rc=ESMF_SUCCESS + allocate(petList(0)) + + do j=1, 1 + do i=1, 2 + + gcomp(i) = ESMF_GridCompCreate(name='My gridded component', & + petList=petList, rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 215 + + call ESMF_GridCompSetVM(gcomp(i), userRoutine=mygcomp_setvmForcePthreads,& + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 215 + + call ESMF_GridCompSetServices(gcomp(i), userRoutine=mygcomp_register_nexh, & + rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 215 + + enddo + do i=1, 2 + + call ESMF_GridCompGet(gcomp(i), petCount=loc_petCount, rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 215 + call ESMF_GridCompDestroy(gcomp(i), rc=loop_rc) + if (loop_rc /= ESMF_SUCCESS) goto 215 + + enddo + enddo + deallocate(petList) + +215 continue + !---------------------------------------------------------------- + !Verify loop test results + !NEX_UTest + write(name, *) "Component Create/SetServices/Destroy ForcePthreads with empty petList Test" + write(failMsg, *) "Failure codes returned!" + call ESMF_Test((loop_rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !Check petCount + !NEX_UTest + write(name, *) "Check petCount for Component Create/SetServices/Destroy ForcePthreads with empty petList Test" + write(failMsg, *) "Incorrect petCount!" + call ESMF_Test((loc_petCount==petCount), name, failMsg, result, ESMF_SRCLINE) + + !---------------------------------------------------------------- + !---------------------------------------------------------------- !------------------------------------------------------------------------ !NEX_UTest @@ -353,8 +588,10 @@ program ESMF_VMComponentUTest #ifdef ESMF_TESTEXHAUSTIVE + !---------------------------------------------------------------- + !---------------------------------------------------------------- ! Prepare for loop testing - loop_rc=ESMF_SUCCESS + loop_rc=ESMF_SUCCESS do j=1, 20 do i=1, 200 @@ -386,8 +623,10 @@ program ESMF_VMComponentUTest write(failMsg, *) "Failure codes returned!" call ESMF_Test((loop_rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !---------------------------------------------------------------- + !---------------------------------------------------------------- ! Prepare for loop testing - loop_rc=ESMF_SUCCESS + loop_rc=ESMF_SUCCESS do j=1, 20 do i=1, 200 diff --git a/src/Superstructure/Component/src/ESMF_CplComp.F90 b/src/Superstructure/Component/src/ESMF_CplComp.F90 index 776fe68ca8..7ffd51d840 100644 --- a/src/Superstructure/Component/src/ESMF_CplComp.F90 +++ b/src/Superstructure/Component/src/ESMF_CplComp.F90 @@ -415,9 +415,9 @@ recursive function ESMF_CplCompCreate(keywordEnforcer, config, configFile, & ! \end{sloppypar} ! \item[{[petList]}] ! List of parent {\tt PET}s given to the created child component by the -! parent component. If {\tt petList} is not specified all of the -! parent {\tt PET}s will be given to the child component. The order of -! PETs in {\tt petList} determines how the child local PETs refer back to +! parent component. If {\tt petList} is not specified, or is empty, all of the +! parent {\tt PET}s are given to the child component. The order of +! PETs in {\tt petList} determines how the child local PETs map back to ! the parent PETs. ! \item[{[contextflag]}] ! Specify the component's VM context. The default context is diff --git a/src/Superstructure/Component/src/ESMF_GridComp.F90 b/src/Superstructure/Component/src/ESMF_GridComp.F90 index 0bd6262c85..40476bb0d6 100644 --- a/src/Superstructure/Component/src/ESMF_GridComp.F90 +++ b/src/Superstructure/Component/src/ESMF_GridComp.F90 @@ -520,9 +520,9 @@ recursive function ESMF_GridCompCreate(keywordEnforcer, grid, gridList, & ! \end{sloppypar} ! \item[{[petList]}] ! List of parent {\tt PET}s given to the created child component by the -! parent component. If {\tt petList} is not specified all of the -! parent {\tt PET}s will be given to the child component. The order of -! PETs in {\tt petList} determines how the child local PETs refer back to +! parent component. If {\tt petList} is not specified, or is empty, all of the +! parent {\tt PET}s are given to the child component. The order of +! PETs in {\tt petList} determines how the child local PETs map back to ! the parent PETs. ! \item[{[contextflag]}] ! Specify the component's VM context. The default context is diff --git a/src/Superstructure/Component/tests/ESMF_CplCompCreateUTest.F90 b/src/Superstructure/Component/tests/ESMF_CplCompCreateUTest.F90 index 3584dda90c..712b7a33a6 100644 --- a/src/Superstructure/Component/tests/ESMF_CplCompCreateUTest.F90 +++ b/src/Superstructure/Component/tests/ESMF_CplCompCreateUTest.F90 @@ -66,6 +66,7 @@ program ESMF_CplCompCreateUTest type(ESMF_Config) :: config integer :: fred, i character(len=:), allocatable :: labelList(:) + integer, allocatable :: petList(:) #endif !------------------------------------------------------------------------------- @@ -549,9 +550,6 @@ program ESMF_CplCompCreateUTest write(failMsg, *) "Did not return correct value in fred" write(name, *) "Config handling Test - validate attribute value" call ESMF_Test((fred==1), name, failMsg, result, ESMF_SRCLINE) - - - !------------------------------------------------------------------------- ! ! @@ -575,9 +573,96 @@ program ESMF_CplCompCreateUTest write(name, *) "Destroying a Coupler Component Test" call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Test creation of a Component with petList + cpl = ESMF_CplCompCreate(petList=(/0/), rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Creating a Component with petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Destroying a component + + call ESMF_CplCompDestroy(cpl, rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Destroying a Component created with petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Test creation of a Component with empty petList + allocate(petList(0)) + cpl = ESMF_CplCompCreate(petList=petList, rc=rc) + deallocate(petList) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Creating a Component with empty petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Destroying a component + + call ESMF_CplCompDestroy(cpl, rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Destroying a Component created with empty petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Test creation of a Component with petList + cpl = ESMF_CplCompCreate(petList=(/0/), rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Creating a Component with petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Destroying a component + + call ESMF_CplCompDestroy(cpl, rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Destroying a Component created with petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Test creation of a Component with empty petList + allocate(petList(0)) + cpl = ESMF_CplCompCreate(petList=petList, rc=rc) + deallocate(petList) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Creating a Component with empty petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Destroying a component + + call ESMF_CplCompDestroy(cpl, rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Destroying a Component created with empty petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + #endif call ESMF_TestEnd(ESMF_SRCLINE) end program ESMF_CplCompCreateUTest - + diff --git a/src/Superstructure/Component/tests/ESMF_GridCompCreateUTest.F90 b/src/Superstructure/Component/tests/ESMF_GridCompCreateUTest.F90 index b9f14fa66b..c8deeb3f7c 100644 --- a/src/Superstructure/Component/tests/ESMF_GridCompCreateUTest.F90 +++ b/src/Superstructure/Component/tests/ESMF_GridCompCreateUTest.F90 @@ -65,6 +65,7 @@ program ESMF_GridCompCreateUTest type(ESMF_Config) :: config integer :: fred, i character(len=:), allocatable :: labelList(:) + integer, allocatable :: petList(:) #endif !------------------------------------------------------------------------------- @@ -102,7 +103,7 @@ program ESMF_GridCompCreateUTest !------------------------------------------------------------------------ !NEX_UTest cname = "Atmosphere" - comp1 = ESMF_GridCompCreate(name=cname, configFile="comp.rc", rc=rc) + comp1 = ESMF_GridCompCreate(name=cname, configFile="comp.rc", rc=rc) write(failMsg, *) "Did not return ESMF_SUCCESS" write(name, *) "Creating a Component Test" call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -196,7 +197,7 @@ program ESMF_GridCompCreateUTest !------------------------------------------------------------------------ !NEX_UTest cname = "Atmosphere" - comp1 = ESMF_GridCompCreate(name=cname, configFile="comp.rc", rc=rc) + comp1 = ESMF_GridCompCreate(name=cname, configFile="comp.rc", rc=rc) write(failMsg, *) "Did not return ESMF_SUCCESS" write(name, *) "Creating a Component Test" call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) @@ -225,7 +226,7 @@ program ESMF_GridCompCreateUTest ! ! !EX_UTest ! ! Test creation of a Component - comp1 = ESMF_GridCompCreate(rc=rc) + comp1 = ESMF_GridCompCreate(rc=rc) write(failMsg, *) "Did not return ESMF_SUCCESS" write(name, *) "Creating a Component Test" @@ -769,7 +770,7 @@ program ESMF_GridCompCreateUTest !EX_UTest ! ! Test creation of a Component cname = "Atmosphere" - comp1 = ESMF_GridCompCreate(name=cname, configFile="comp.rc", rc=rc) + comp1 = ESMF_GridCompCreate(name=cname, configFile="comp.rc", rc=rc) write(failMsg, *) "Did not return ESMF_SUCCESS" write(name, *) "Creating a Component Test" @@ -1134,9 +1135,53 @@ program ESMF_GridCompCreateUTest write(name, *) "Destroying a Component Test" call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Test creation of a Component with petList + comp1 = ESMF_GridCompCreate(petList=(/0/), rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Creating a Component with petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Destroying a component + + call ESMF_GridCompDestroy(comp1, rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Destroying a Component created with petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Test creation of a Component with empty petList + allocate(petList(0)) + comp1 = ESMF_GridCompCreate(petList=petList, rc=rc) + deallocate(petList) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Creating a Component with empty petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + +!------------------------------------------------------------------------- +! ! + !EX_UTest +! ! Destroying a component + + call ESMF_GridCompDestroy(comp1, rc=rc) + + write(failMsg, *) "Did not return ESMF_SUCCESS" + write(name, *) "Destroying a Component created with empty petList Test" + call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + #endif call ESMF_TestEnd(ESMF_SRCLINE) end program ESMF_GridCompCreateUTest - + diff --git a/src/addon/ESMX/CMakeLists.txt b/src/addon/ESMX/CMakeLists.txt new file mode 100644 index 0000000000..f193c1b2a7 --- /dev/null +++ b/src/addon/ESMX/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.12) +enable_language(Fortran) + +# Where to look for Find.cmake files +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +# Find ESMF +find_package(ESMF 8.4.0 REQUIRED) + +# Set compilers per ESMFMKFILE +set(CMAKE_CXX_COMPILER ${ESMF_CXXCOMPILER}) +set(CMAKE_Fortran_COMPILER ${ESMF_F90COMPILER}) + +# Specific project settings +project(ESMX VERSION 0.1.0 DESCRIPTION "Unified Nuopc EXecutable") +add_executable(esmx esmx.F90) +target_link_libraries(esmx PRIVATE ESMF) +install(TARGETS esmx) +target_include_directories(esmx PUBLIC ${PROJECT_BINARY_DIR}) + +# Generate +find_package(Python 3 COMPONENTS Interpreter REQUIRED) +execute_process(COMMAND ${Python_EXECUTABLE} + ${CMAKE_CURRENT_LIST_DIR}/esmxGen.py --ifile ./esmxBuild.yaml --odir ${CMAKE_CURRENT_BINARY_DIR} + RESULT_VARIABLE ret) +if(ret EQUAL "1") + message( FATAL_ERROR "esmxGen.py failed processing esmxBuild.yaml") +endif() + +include(${CMAKE_CURRENT_BINARY_DIR}/compList.txt) diff --git a/src/addon/ESMX/cmake/FindESMF.cmake b/src/addon/ESMX/cmake/FindESMF.cmake new file mode 100644 index 0000000000..8b709ed50f --- /dev/null +++ b/src/addon/ESMX/cmake/FindESMF.cmake @@ -0,0 +1,138 @@ +# - Try to find ESMF +# +# Uses ESMFMKFILE to find the filepath of esmf.mk. If this is NOT set, then this +# module will attempt to find esmf.mk. If ESMFMKFILE exists, then +# ESMF_FOUND=TRUE and all ESMF makefile variables will be set in the global +# scope. Optionally, set ESMF_MKGLOBALS to a string list to filter makefile +# variables. For example, to globally scope only ESMF_LIBSDIR and ESMF_APPSDIR +# variables, use this CMake command in CMakeLists.txt: +# +# set(ESMF_MKGLOBALS "LIBSDIR" "APPSDIR") + +# Set ESMFMKFILE as defined by system env variable. If it's not explicitly set +# try to find esmf.mk file in default locations (ESMF_ROOT, CMAKE_PREFIX_PATH, +# etc) +if(NOT DEFINED ESMFMKFILE) + if(NOT DEFINED ENV{ESMFMKFILE}) + find_path(ESMFMKFILE_PATH esmf.mk PATH_SUFFIXES lib lib64) + if(ESMFMKFILE_PATH) + set(ESMFMKFILE ${ESMFMKFILE_PATH}/esmf.mk) + message(STATUS "Found esmf.mk file ${ESMFMKFILE}") + endif() + else() + set(ESMFMKFILE $ENV{ESMFMKFILE}) + endif() +endif() + +# Only parse the mk file if it is found +if(EXISTS ${ESMFMKFILE}) + set(ESMFMKFILE ${ESMFMKFILE} CACHE FILEPATH "Path to esmf.mk file") + set(ESMF_FOUND TRUE CACHE BOOL "esmf.mk file found" FORCE) + + # Read the mk file + file(STRINGS "${ESMFMKFILE}" esmfmkfile_contents) + # Parse each line in the mk file + foreach(str ${esmfmkfile_contents}) + # Only consider uncommented lines + string(REGEX MATCH "^[^#]" def ${str}) + # Line is not commented + if(def) + # Extract the variable name + string(REGEX MATCH "^[^=]+" esmf_varname ${str}) + # Extract the variable's value + string(REGEX MATCH "=.+$" esmf_vardef ${str}) + # Only for variables with a defined value + if(esmf_vardef) + # Get rid of the assignment string + string(SUBSTRING ${esmf_vardef} 1 -1 esmf_vardef) + # Remove whitespace + string(STRIP ${esmf_vardef} esmf_vardef) + # A string or single-valued list + if(NOT DEFINED ESMF_MKGLOBALS) + # Set in global scope + set(${esmf_varname} ${esmf_vardef}) + # Don't display by default in GUI + mark_as_advanced(esmf_varname) + else() # Need to filter global promotion + foreach(m ${ESMF_MKGLOBALS}) + string(FIND ${esmf_varname} ${m} match) + # Found the string + if(NOT ${match} EQUAL -1) + # Promote to global scope + set(${esmf_varname} ${esmf_vardef}) + # Don't display by default in the GUI + mark_as_advanced(esmf_varname) + # No need to search for the current string filter + break() + endif() + endforeach() + endif() + endif() + endif() + endforeach() + + # Construct ESMF_VERSION from ESMF_VERSION_STRING_GIT + # ESMF_VERSION_MAJOR and ESMF_VERSION_MINOR are defined in ESMFMKFILE + set(ESMF_VERSION 0) + set(ESMF_VERSION_PATCH ${ESMF_VERSION_REVISION}) + set(ESMF_BETA_RELEASE FALSE) + if(ESMF_VERSION_BETASNAPSHOT MATCHES "^('T')$") + set(ESMF_BETA_RELEASE TRUE) + if(ESMF_VERSION_STRING_GIT MATCHES "^ESMF.*beta_snapshot_[0-9]") + string(REGEX REPLACE "^ESMF.*beta_snapshot_\([0-9]*\).*" "\\1" ESMF_BETA_SNAPSHOT "${ESMF_VERSION_STRING_GIT}") + elseif(ESMF_VERSION_STRING_GIT MATCHES "^v.*b[0-9]") + string(REGEX REPLACE "^v.*b\([0-9]*\).*" "\\1" ESMF_BETA_SNAPSHOT "${ESMF_VERSION_STRING_GIT}") + else() + set(ESMF_BETA_SNAPSHOT 0) + endif() + message(STATUS "Detected ESMF Beta snapshot ${ESMF_BETA_SNAPSHOT}") + endif() + set(ESMF_VERSION "${ESMF_VERSION_MAJOR}.${ESMF_VERSION_MINOR}.${ESMF_VERSION_PATCH}") + + # Find the ESMF library + if(USE_ESMF_STATIC_LIBS) + find_library(ESMF_LIBRARY_LOCATION NAMES libesmf.a PATHS ${ESMF_LIBSDIR} NO_DEFAULT_PATH) + if(ESMF_LIBRARY_LOCATION MATCHES "ESMF_LIBRARY_LOCATION-NOTFOUND") + message(WARNING "Static ESMF library (libesmf.a) not found in \ + ${ESMF_LIBSDIR}. Try setting USE_ESMF_STATIC_LIBS=OFF") + endif() + add_library(ESMF STATIC IMPORTED) + else() + find_library(ESMF_LIBRARY_LOCATION NAMES esmf PATHS ${ESMF_LIBSDIR} NO_DEFAULT_PATH) + if(ESMF_LIBRARY_LOCATION MATCHES "ESMF_LIBRARY_LOCATION-NOTFOUND") + message(WARNING "ESMF library not found in ${ESMF_LIBSDIR}.") + endif() + add_library(ESMF UNKNOWN IMPORTED) + endif() + + # Add ESMF include directories + set(ESMF_INCLUDE_DIRECTORIES "") + separate_arguments(_ESMF_F90COMPILEPATHS NATIVE_COMMAND ${ESMF_F90COMPILEPATHS}) + foreach(_ITEM ${_ESMF_F90COMPILEPATHS}) + string(REGEX REPLACE "^-I" "" _ITEM "${_ITEM}") + list(APPEND ESMF_INCLUDE_DIRECTORIES ${_ITEM}) + endforeach() + + # Add ESMF link libraries + string(STRIP "${ESMF_F90LINKRPATHS} ${ESMF_F90ESMFLINKRPATHS} ${ESMF_F90ESMFLINKPATHS} ${ESMF_F90LINKPATHS} ${ESMF_F90LINKLIBS} ${ESMF_F90LINKOPTS}" ESMF_INTERFACE_LINK_LIBRARIES) + + # Finalize find_package + include(FindPackageHandleStandardArgs) + + find_package_handle_standard_args( + ${CMAKE_FIND_PACKAGE_NAME} + REQUIRED_VARS ESMF_LIBRARY_LOCATION + ESMF_INTERFACE_LINK_LIBRARIES + ESMF_F90COMPILEPATHS + VERSION_VAR ESMF_VERSION) + + set_target_properties(ESMF PROPERTIES + IMPORTED_LOCATION "${ESMF_LIBRARY_LOCATION}" + INTERFACE_INCLUDE_DIRECTORIES "${ESMF_INCLUDE_DIRECTORIES}" + INTERFACE_LINK_LIBRARIES "${ESMF_INTERFACE_LINK_LIBRARIES}") + +else() + set(ESMF_FOUND FALSE CACHE BOOL "esmf.mk file NOT found" FORCE) + message(WARNING "ESMFMKFILE ${ESMFMKFILE} not found. Try setting ESMFMKFILE \ + to esmf.mk location.") +endif() diff --git a/src/addon/ESMX/esmx.F90 b/src/addon/ESMX/esmx.F90 new file mode 100644 index 0000000000..3d0f29be99 --- /dev/null +++ b/src/addon/ESMX/esmx.F90 @@ -0,0 +1,513 @@ +!============================================================================== +! ESMX (Earth System Model eXecutable) +! This file contains the main application program and the top level driver. +!============================================================================== + +module esmxDriver + + use ESMF + use NUOPC + use NUOPC_Driver, driverSS => SetServices + + include "compUse.inc" + + implicit none + + private + + public SetServices, SetVM + + type type_CompDef + procedure(SetServices), pointer, nopass :: ssPtr => null() + procedure(SetVM), pointer, nopass :: svPtr => null() + character(ESMF_MAXSTR) :: name = "__uninitialized__" + end type + + !----------------------------------------------------------------------------- + contains + !----------------------------------------------------------------------------- + + subroutine SetServices(driver, rc) + type(ESMF_GridComp) :: driver + integer, intent(out) :: rc + + rc = ESMF_SUCCESS + + ! Derive from NUOPC_Driver + call NUOPC_CompDerive(driver, driverSS, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! Specialize Driver + call NUOPC_CompSpecialize(driver, specLabel=label_SetModelServices, & + specRoutine=SetModelServices, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + call NUOPC_CompSpecialize(driver, specLabel=label_SetRunSequence, & + specRoutine=SetRunSequence, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + end subroutine SetServices + + !----------------------------------------------------------------------------- + + subroutine SetModelServices(driver, rc) + type(ESMF_GridComp) :: driver + integer, intent(out) :: rc + + ! local variables + character(len=32) :: startTimeString, stopTimeString + type(ESMF_Time) :: startTime, stopTime + type(ESMF_TimeInterval) :: timeStep + type(ESMF_Clock) :: internalClock + integer :: i, j, componentCount, ompNumThreads + integer, allocatable :: petList(:) + type(ESMF_GridComp) :: comp + type(ESMF_Config) :: config + type(NUOPC_FreeFormat) :: ff + character(len=32), allocatable :: compLabels(:) + character(len=32) :: prefix + character(len=240) :: model + type(ESMF_Info) :: info + type(type_CompDef), allocatable :: CompDef(:) + logical :: inCompDef + + ! get the config + call ESMF_GridCompGet(driver, config=config, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! determine the generic component labels + componentCount = ESMF_ConfigGetLen(config, label="ESMX_component_list:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + allocate(compLabels(componentCount)) + call ESMF_ConfigGetAttribute(config, valueList=compLabels, & + label="ESMX_component_list:", count=componentCount, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! setup CompDef structure + allocate(CompDef(componentCount)) + include "compDef.inc" + + ! determine information for each component and add to the driver + do i=1, componentCount + ! construct component prefix + prefix=trim(compLabels(i)) + + ! set up petList + ff = NUOPC_FreeFormatCreate(config, label=trim(prefix)//"_petlist:", & + relaxedFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call NUOPC_IngestPetList(petList, ff, rc=rc) + call ESMF_ConfigGetAttribute(config, model, & + label=trim(prefix)//"_model:", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! set up NUOPC hint for OpenMP + call ESMF_ConfigGetAttribute(config, ompNumThreads, & + label=trim(prefix)//"_omp_num_threads:", default=-1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + info = ESMF_InfoCreate(rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + if (ompNumThreads /= -1) then + call ESMF_InfoSet(info, key="/NUOPC/Hint/PePerPet/MaxCount", & + value=ompNumThreads, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + endif + + ! see whether there is an entry for this component inside CompDef + inCompDef = .false. + do j=1, componentCount + if (trim(CompDef(j)%name)=="__uninitialized__") exit + if (trim(CompDef(j)%name)==trim(model)) then + inCompDef = .true. + exit + endif + enddo + + if (inCompDef) then + ! add child component with SetVM and SetServices in CompDef + call NUOPC_DriverAddComp(driver, trim(prefix), config=config, & + compSetServicesRoutine=CompDef(j)%ssPtr, compSetVMRoutine=CompDef(j)%svPtr, & + info=info, petList=petList, comp=comp, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, & + msg="Unable to add component '"//trim(prefix)// & + "' to driver via Fortran module.", & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + else + ! add child component with SetVM and SetServices in shared object + call NUOPC_DriverAddComp(driver, trim(prefix), config=config, & + sharedObj=trim(model), info=info, petList=petList, comp=comp, & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, & + msg="Unable to add component '"//trim(prefix)// & + "' to driver via shared object: "//trim(model), & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + endif + + ! read and ingest free format component attributes + ff = NUOPC_FreeFormatCreate(config, & + label=trim(prefix)//"_attributes::", relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + ff = NUOPC_FreeFormatCreate(config, & + label="ALLCOMP_attributes::", relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! clean-up + deallocate(petList) + call ESMF_InfoDestroy(info, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + enddo + + deallocate(compLabels) + + ! read startTimeString and stopTimeString from config + call ESMF_ConfigGetAttribute(config, startTimeString, label="startTime:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call ESMF_ConfigGetAttribute(config, stopTimeString, label="stopTime:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! set the driver clock startTime/stopTime + call ESMF_TimeSet(startTime, timeString=startTimeString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + call ESMF_TimeSet(stopTime, timeString=stopTimeString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! set the driver clock default timeStep = stopTime - startTime + ! use with runSequence @*, + ! or overwritten with explicit timeStep in runSequence + timeStep = stopTime - startTime + + internalClock = ESMF_ClockCreate(name="Application Clock", & + timeStep=timeStep, startTime=startTime, stopTime=stopTime, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + call ESMF_GridCompSet(driver, clock=internalClock, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + rc = ESMF_SUCCESS + + end subroutine SetModelServices + + !----------------------------------------------------------------------------- + + subroutine SetRunSequence(driver, rc) + type(ESMF_GridComp) :: driver + integer, intent(out) :: rc + + ! local variables + character(ESMF_MAXSTR) :: name + type(ESMF_Config) :: config + type(NUOPC_FreeFormat) :: runSeqFF + + rc = ESMF_SUCCESS + + ! query the driver for its name and config + call ESMF_GridCompGet(driver, name=name, config=config, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! read free format run sequence from config + runSeqFF = NUOPC_FreeFormatCreate(config, label="runSeq::", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! ingest FreeFormat run sequence + call NUOPC_DriverIngestRunSequence(driver, runSeqFF, & + autoAddConnectors=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + ! clean-up + call NUOPC_FreeFormatDestroy(runSeqFF, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + return ! bail out + + end subroutine SetRunSequence + + !----------------------------------------------------------------------------- + +end module esmxDriver + +!============================================================================== +! ESMX application +!============================================================================== + +program ESMX + + use ESMF + use NUOPC + use esmxDriver, only: driverSS => SetServices + + implicit none + + integer :: rc, urc + type(ESMF_GridComp) :: driver + type(ESMF_Config) :: config + character(len=240) :: fieldDictionary + logical :: logFlush + type(NUOPC_FreeFormat) :: ff + + ! Initialize ESMF + call ESMF_Initialize(configFileName="esmxRun.config", config=config, & + defaultCalkind=ESMF_CALKIND_GREGORIAN, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_ConfigGetAttribute(config, logFlush, & + label="ESMX_log_flush:", default=.false., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_LogSet(flush=logFlush, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_LogWrite("=============================================", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_LogWrite("ESMX (Earth System Model eXecutable) STARTING", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_LogWrite("=============================================", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_ConfigGetAttribute(config, fieldDictionary, & + label="ESMX_field_dictionary:", default="", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + if (trim(fieldDictionary)/="") then + ! Read custom dictionary from YAML file + call NUOPC_FieldDictionarySetup(fileName=trim(fieldDictionary), rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, & + msg="Unable to read Field Dictionary file: "//trim(fieldDictionary), & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + endif + + ! Create the esmx driver + driver = ESMF_GridCompCreate(name="esmxDriver", config=config, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! SetServices for the esmx driver + call ESMF_GridCompSetServices(driver, driverSS, userRc=urc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! read and ingest free format driver attributes + ff = NUOPC_FreeFormatCreate(config, label="ESMX_attributes::", & + relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call NUOPC_CompAttributeIngest(driver, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + ff = NUOPC_FreeFormatCreate(config, label="ALLCOMP_attributes::", & + relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call NUOPC_CompAttributeIngest(driver, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Call Initialize for the esmx driver + call ESMF_GridCompInitialize(driver, userRc=urc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Call Run for the esmx driver + call ESMF_GridCompRun(driver, userRc=urc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Call Finalize for the esmx driver + call ESMF_GridCompFinalize(driver, userRc=urc, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Destroy the esmx driver + call ESMF_GridCompDestroy(driver, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + call ESMF_LogWrite("=============================================", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_LogWrite("ESMX (Earth System Model eXecutable) FINISHED", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + call ESMF_LogWrite("=============================================", & + ESMF_LOGMSG_INFO, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=__FILE__)) & + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Finalize ESMF + call ESMF_Finalize(rc=rc) + +end program ESMX diff --git a/src/addon/ESMX/esmxGen.py b/src/addon/ESMX/esmxGen.py new file mode 100755 index 0000000000..caee22c41e --- /dev/null +++ b/src/addon/ESMX/esmxGen.py @@ -0,0 +1,94 @@ +try: + from yaml import CDumper as Dumper + from yaml import CLoader as Loader +except ImportError: + from yaml import Loader, Dumper + +from pathlib import Path +import os +import sys +import yaml +import argparse +import collections + +def read_drv_yaml_file(file_path): + # open yaml file and read it + if not os.path.exists(file_path): + sys.exit('File not found: {}'.format(file_path)) + with open(file_path) as _file: + data = yaml.load(_file, Loader=Loader) + return dict({k.replace("-", "_"): v for k, v in data.items()}) + +def create_compList(_dict, odir): + # open file + with open(os.path.join(odir, 'compList.txt'), 'w') as f: + # loop through components and create use statements + od = collections.OrderedDict(_dict['components'].items()) + comp_str = [comp for comp in od.keys()] + f.write('set(COMPS {})\n\n'.format(' '.join(comp_str))) + for k1, v1 in od.items(): + if 'config' in v1: + # only entires that have config field are considered + f.write('# - auto-generated section for component: {}\n'.format(k1)) + configFile = os.path.join(os.getcwd(), v1['config']) + f.write('include({})\n\n'.format(configFile)) + +def create_compUse(_dict, odir): + # open file + with open(os.path.join(odir, 'compUse.inc'), 'w') as f: + # loop through components and create use statements + od = collections.OrderedDict(_dict['components'].items()) + for k1, v1 in od.items(): + if 'config' in v1: + # only entires that have config field are considered + if 'fort_module' in v1: + # if fort_module field present, use it to identify fortran module + f.write('use {}, only: {}SS => SetServices, {}SV => SetVM\n'.format(v1['fort_module'], k1, k1)) + else: + # otherwise use step of the config name + f.write('use {}, only: {}SS => SetServices, {}SV => SetVM\n'.format(Path(v1['config']).stem, k1, k1)) + +def create_compDef(_dict, odir): + # open file + with open(os.path.join(odir, 'compDef.inc'), 'w') as f: + # loop through components and create use statements + i = 1 + od = collections.OrderedDict(_dict['components'].items()) + for k1, v1 in od.items(): + if 'config' in v1: + # only entires that have config field are considered + f.write('CompDef({})%ssPtr => {}SS\n'.format(i, k1)) + f.write('CompDef({})%svPtr => {}SV\n'.format(i, k1)) + f.write('CompDef({})%name = "{}"\n'.format(i, k1)) + i = i+1 + +def main(argv): + + # default value + odir = '.' + + # read input arguments + parser = argparse.ArgumentParser() + parser.add_argument('--ifile' , help='Input driver yaml file', required=True) + parser.add_argument('--odir' , help='Output directory for generated code') + args = parser.parse_args() + + if args.ifile: + ifile = args.ifile + if args.odir: + odir = args.odir + + # read driver configuration yaml file + dict_drv = read_drv_yaml_file(ifile) + + # create compList.txt for CMake + create_compList(dict_drv, odir) + + # create compUse.inc + create_compUse(dict_drv, odir) + + # create compDef.inc + create_compDef(dict_drv, odir) + +if __name__== "__main__": + main(sys.argv[1:]) diff --git a/src/addon/NUOPC/src/NUOPC_Driver.F90 b/src/addon/NUOPC/src/NUOPC_Driver.F90 index 83c450ff3d..db941f43b6 100644 --- a/src/addon/NUOPC/src/NUOPC_Driver.F90 +++ b/src/addon/NUOPC/src/NUOPC_Driver.F90 @@ -4412,14 +4412,16 @@ recursive subroutine compSetVMRoutine(gridcomp, rc) if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out - + + nullify(cmEntry%wrap%petList) ! invalidate the petList if (present(petList)) then - allocate(cmEntry%wrap%petList(size(petList))) - cmEntry%wrap%petList = petList ! copy the petList elements - else - nullify(cmEntry%wrap%petList) ! invalidate the petList + if (size(petList)>0) then + ! a usable petList was provided + allocate(cmEntry%wrap%petList(size(petList))) + cmEntry%wrap%petList = petList ! copy the petList elements + endif endif - + if (btest(verbosity,13)) then if (associated(cmEntry%wrap%petList)) then write (lString, *) size(cmEntry%wrap%petList) @@ -4585,14 +4587,16 @@ recursive subroutine NUOPC_DriverAddGridCompSO(driver, compLabel, & if (ESMF_LogFoundError(rcToCheck=localrc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, file=trim(name)//":"//FILENAME, rcToReturn=rc)) & return ! bail out - + + nullify(cmEntry%wrap%petList) ! invalidate the petList if (present(petList)) then - allocate(cmEntry%wrap%petList(size(petList))) - cmEntry%wrap%petList = petList ! copy the petList elements - else - nullify(cmEntry%wrap%petList) ! invalidate the petList + if (size(petList)>0) then + ! a usable petList was provided + allocate(cmEntry%wrap%petList(size(petList))) + cmEntry%wrap%petList = petList ! copy the petList elements + endif endif - + if (btest(verbosity,13)) then if (associated(cmEntry%wrap%petList)) then write (lString, *) size(cmEntry%wrap%petList) From f5d74853430ddda748c7e3e7bbf0fab7bc73d584 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 11:29:31 -0600 Subject: [PATCH 152/266] Update ESMF doc build action --- .github/workflows/build-esmf-docs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-esmf-docs.yml b/.github/workflows/build-esmf-docs.yml index 2ede1ea335..cf555bc8c8 100644 --- a/.github/workflows/build-esmf-docs.yml +++ b/.github/workflows/build-esmf-docs.yml @@ -66,5 +66,7 @@ jobs: - name: Commit and publish docs uses: actions-js/push@master with: + repository: esmf-org/esmf-org.github.io directory: ${{ github.workspace }}/esmf-org.github.io github_token: ${{ secrets.GITHUB_TOKEN }} + message: 'Publish ESMF Docs' From 3c5d4af398ce546a2590dba2a4c555385e762527 Mon Sep 17 00:00:00 2001 From: Robert Oehmke Date: Fri, 2 Sep 2022 11:32:59 -0600 Subject: [PATCH 153/266] Fix correspondence of _NOOP and _NETCDF_ERROR error codes with error messages. --- src/Infrastructure/LogErr/include/ESMCI_ErrMsgs.C | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/LogErr/include/ESMCI_ErrMsgs.C b/src/Infrastructure/LogErr/include/ESMCI_ErrMsgs.C index 4be4aff6d4..7f0105e32d 100644 --- a/src/Infrastructure/LogErr/include/ESMCI_ErrMsgs.C +++ b/src/Infrastructure/LogErr/include/ESMCI_ErrMsgs.C @@ -97,9 +97,10 @@ static const char *errMsg[] = { "File already exists ", // 63 = ESMF_RC_FILE_EXISTS "File is not a directory ", // 64 = ESMF_RC_FILE_NOTDIR "The MOAB library returned an error ", // 65 = ESMF_RC_MOAB_ERROR - "The NetCDF Library returned an error ", // 66 = ESMF_RC_NETCDF_ERROR - "", // 67 = ESMF_RC_NOOP + "", // 66 = ESMF_RC_NOOP + "The NetCDF Library returned an error ", // 67 = ESMF_RC_NETCDF_ERROR + // 68-499 reserved for future F90 symmetric return code definitions "","","","","","","","", @@ -204,9 +205,10 @@ static const char *errMsg[] = { "File already exists ", // 563 = ESMC_RC_FILE_EXISTS "File is not a directory ", // 564 = ESMC_RC_FILE_NOTDIR "The MOAB library returned an error ", // 565 = ESMC_RC_MOAB_ERROR - "The NetCDF library returned an error ", // 566 = ESMC_RC_NETCDF_ERROR - "", // 567 = ESMC_RC_NOOP + "", // 566 = ESMC_RC_NOOP + "The NetCDF library returned an error ", // 567 = ESMC_RC_NETCDF_ERROR + // 568-999 reserved for future C++ symmetric return code definitions "","","","","","","", From 6d9747ab9a6f48faf35ec6fa0456c48ae177a62d Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 12:08:01 -0600 Subject: [PATCH 154/266] Use secret token to allow pushing docs --- .github/workflows/build-esmf-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-esmf-docs.yml b/.github/workflows/build-esmf-docs.yml index cf555bc8c8..ffd88850a8 100644 --- a/.github/workflows/build-esmf-docs.yml +++ b/.github/workflows/build-esmf-docs.yml @@ -68,5 +68,5 @@ jobs: with: repository: esmf-org/esmf-org.github.io directory: ${{ github.workspace }}/esmf-org.github.io - github_token: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.ESMF_WEB_TOKEN }} message: 'Publish ESMF Docs' From 62dc4da65e57a87848599c6fed775f0d4f7b6369 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 13:21:59 -0600 Subject: [PATCH 155/266] Working on doc push --- .github/workflows/build-esmf-docs.yml | 69 ++++++++++++++------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build-esmf-docs.yml b/.github/workflows/build-esmf-docs.yml index ffd88850a8..03865352d1 100644 --- a/.github/workflows/build-esmf-docs.yml +++ b/.github/workflows/build-esmf-docs.yml @@ -22,46 +22,51 @@ jobs: path: esmf-containers ref: main - - name: Build Docker image - run: | - cd ${{ github.workspace }}/esmf-containers/build-esmf-docs/esmf - docker build . --tag esmf/build-esmf-docs --build-arg ESMF_BRANCH="${{ github.ref_name }}" --no-cache +# - name: Build Docker image +# run: | +# cd ${{ github.workspace }}/esmf-containers/build-esmf-docs/esmf +# docker build . --tag esmf/build-esmf-docs --build-arg ESMF_BRANCH="${{ github.ref_name }}" --no-cache - - name: Extract artifacts - run: | - mkdir -p ${{ github.workspace }}/artifacts - CID=$(docker run -dit --name runner esmf/build-esmf-docs) - docker cp ${CID}:/artifacts/doc-artifacts.zip ${{ github.workspace }}/artifacts - docker stop ${CID} - docker rm ${CID} +# - name: Extract artifacts +# run: | +# mkdir -p ${{ github.workspace }}/artifacts +# CID=$(docker run -dit --name runner esmf/build-esmf-docs) +# docker cp ${CID}:/artifacts/doc-artifacts.zip ${{ github.workspace }}/artifacts +# docker stop ${CID} +# docker rm ${CID} - - name: Upload artifacts - uses: actions/upload-artifact@v3 - with: - name: esmf-docs - path: ${{ github.workspace }}/artifacts +# - name: Upload artifacts +# uses: actions/upload-artifact@v3 +# with: +# name: esmf-docs +# path: ${{ github.workspace }}/artifacts - name: Checkout esmf-org.github.io uses: actions/checkout@v3 with: repository: esmf-org/esmf-org.github.io path: esmf-org.github.io - - - name: Copy docs - run: | - cd ${{ github.workspace }}/esmf-org.github.io - mkdir -p docs/nightly/${{ github.ref_name }} - cd ${{ github.workspace }}/artifacts - unzip doc-artifacts.zip - cd ${{ github.workspace }}/artifacts/artifacts/doc-esmf - cp -rf ./* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ - cd ${{ github.workspace }}/artifacts/artifacts/doc-nuopc - cp -rf NUOPC_refdoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ - cp -rf NUOPC_refdoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ - cp -rf NUOPC_howtodoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ - cp -rf NUOPC_howtodoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ - cd ${{ github.workspace }}/artifacts/artifacts/doc-dev_guide - cp -rf ./dev_guide/dev_guide/* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/dev_guide/ + + - name: Test file + run: | + cd ${{ github.workspace }}/esmf-org.github.io + echo 'test' > test.txt + +# - name: Copy docs +# run: | +# cd ${{ github.workspace }}/esmf-org.github.io +# mkdir -p docs/nightly/${{ github.ref_name }} +# cd ${{ github.workspace }}/artifacts +# unzip doc-artifacts.zip +# cd ${{ github.workspace }}/artifacts/artifacts/doc-esmf +# cp -rf ./* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ +# cd ${{ github.workspace }}/artifacts/artifacts/doc-nuopc +# cp -rf NUOPC_refdoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ +# cp -rf NUOPC_refdoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ +# cp -rf NUOPC_howtodoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ +# cp -rf NUOPC_howtodoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ +# cd ${{ github.workspace }}/artifacts/artifacts/doc-dev_guide +# cp -rf ./dev_guide/dev_guide/* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/dev_guide/ - name: Commit and publish docs uses: actions-js/push@master From 4fab40c0b6c6d564502b28c3c868924748fd2721 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 13:29:03 -0600 Subject: [PATCH 156/266] Update build-esmf-docs.yml --- .github/workflows/build-esmf-docs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-esmf-docs.yml b/.github/workflows/build-esmf-docs.yml index 03865352d1..325a0110c9 100644 --- a/.github/workflows/build-esmf-docs.yml +++ b/.github/workflows/build-esmf-docs.yml @@ -51,6 +51,8 @@ jobs: run: | cd ${{ github.workspace }}/esmf-org.github.io echo 'test' > test.txt + git commit test.txt -m 'please ignore' + git push # - name: Copy docs # run: | From 8079d85b7a808e1a636e075740c30c96a40009c5 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 14:49:45 -0600 Subject: [PATCH 157/266] ESMF and ESMPy automatic doc builds (#62) * Update build-esmf-docs.yml * Update build-esmf-docs.yml * Update build-esmf-docs.yml * Update build-esmf-docs.yml * Update build-esmf-docs.yml * Update build-esmpy-docs.yml * Update build-esmf-docs.yml * Update build-esmpy-docs.yml * Update build-esmf-docs.yml * Update build-esmpy-docs.yml --- .github/workflows/build-esmf-docs.yml | 84 ++++++++++++-------------- .github/workflows/build-esmpy-docs.yml | 17 ++++-- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/.github/workflows/build-esmf-docs.yml b/.github/workflows/build-esmf-docs.yml index 325a0110c9..f68f3193e0 100644 --- a/.github/workflows/build-esmf-docs.yml +++ b/.github/workflows/build-esmf-docs.yml @@ -2,10 +2,11 @@ name: Build ESMF Docs on: workflow_dispatch: -# push: -# branches: [ "develop" ] -# pull_request: -# branches: [ "develop" ] + push: + +concurrency: + group: build-esmf-docs + cancel-in-progress: true jobs: @@ -22,58 +23,53 @@ jobs: path: esmf-containers ref: main -# - name: Build Docker image -# run: | -# cd ${{ github.workspace }}/esmf-containers/build-esmf-docs/esmf -# docker build . --tag esmf/build-esmf-docs --build-arg ESMF_BRANCH="${{ github.ref_name }}" --no-cache + - name: Build Docker image + run: | + cd ${{ github.workspace }}/esmf-containers/build-esmf-docs/esmf + docker build . --tag esmf/build-esmf-docs --build-arg ESMF_BRANCH="${{ github.ref_name }}" --no-cache -# - name: Extract artifacts -# run: | -# mkdir -p ${{ github.workspace }}/artifacts -# CID=$(docker run -dit --name runner esmf/build-esmf-docs) -# docker cp ${CID}:/artifacts/doc-artifacts.zip ${{ github.workspace }}/artifacts -# docker stop ${CID} -# docker rm ${CID} + - name: Extract artifacts + run: | + mkdir -p ${{ github.workspace }}/artifacts + CID=$(docker run -dit --name runner esmf/build-esmf-docs) + docker cp ${CID}:/artifacts/doc-artifacts.zip ${{ github.workspace }}/artifacts + docker stop ${CID} + docker rm ${CID} -# - name: Upload artifacts -# uses: actions/upload-artifact@v3 -# with: -# name: esmf-docs -# path: ${{ github.workspace }}/artifacts - + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: esmf-docs + path: ${{ github.workspace }}/artifacts + - name: Checkout esmf-org.github.io uses: actions/checkout@v3 with: repository: esmf-org/esmf-org.github.io - path: esmf-org.github.io + path: esmf-org.github.io + token: ${{ secrets.ESMF_WEB_TOKEN }} - - name: Test file - run: | - cd ${{ github.workspace }}/esmf-org.github.io - echo 'test' > test.txt - git commit test.txt -m 'please ignore' - git push - -# - name: Copy docs -# run: | -# cd ${{ github.workspace }}/esmf-org.github.io -# mkdir -p docs/nightly/${{ github.ref_name }} -# cd ${{ github.workspace }}/artifacts -# unzip doc-artifacts.zip -# cd ${{ github.workspace }}/artifacts/artifacts/doc-esmf -# cp -rf ./* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ -# cd ${{ github.workspace }}/artifacts/artifacts/doc-nuopc -# cp -rf NUOPC_refdoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ -# cp -rf NUOPC_refdoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ -# cp -rf NUOPC_howtodoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ -# cp -rf NUOPC_howtodoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ -# cd ${{ github.workspace }}/artifacts/artifacts/doc-dev_guide -# cp -rf ./dev_guide/dev_guide/* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/dev_guide/ + - name: Copy docs + run: | + cd ${{ github.workspace }}/esmf-org.github.io + mkdir -p docs/nightly/${{ github.ref_name }} + cd ${{ github.workspace }}/artifacts + unzip doc-artifacts.zip + cd ${{ github.workspace }}/artifacts/artifacts/doc-esmf + cp -rf ./* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cd ${{ github.workspace }}/artifacts/artifacts/doc-nuopc + cp -rf NUOPC_refdoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cp -rf NUOPC_refdoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cp -rf NUOPC_howtodoc ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cp -rf NUOPC_howtodoc.pdf ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/ + cd ${{ github.workspace }}/artifacts/artifacts/doc-dev_guide + cp -rf ./dev_guide/dev_guide/* ${{ github.workspace }}/esmf-org.github.io/docs/nightly/${{ github.ref_name }}/dev_guide/ - name: Commit and publish docs uses: actions-js/push@master with: repository: esmf-org/esmf-org.github.io directory: ${{ github.workspace }}/esmf-org.github.io + branch: master github_token: ${{ secrets.ESMF_WEB_TOKEN }} message: 'Publish ESMF Docs' diff --git a/.github/workflows/build-esmpy-docs.yml b/.github/workflows/build-esmpy-docs.yml index 9f2265caf8..e63a74797c 100644 --- a/.github/workflows/build-esmpy-docs.yml +++ b/.github/workflows/build-esmpy-docs.yml @@ -2,10 +2,11 @@ name: Build ESMPy Docs on: workflow_dispatch: -# push: -# branches: [ "develop" ] -# pull_request: -# branches: [ "develop" ] + push: + +concurrency: + group: build-esmpy-docs + cancel-in-progress: true jobs: @@ -45,7 +46,8 @@ jobs: uses: actions/checkout@v3 with: repository: esmf-org/esmpy_doc - path: esmpy_doc + path: esmpy_doc + token: ${{ secrets.ESMF_WEB_TOKEN }} - name: Copy docs run: | @@ -60,5 +62,8 @@ jobs: - name: Commit and publish docs uses: actions-js/push@master with: + repository: esmf-org/esmpy_doc directory: ${{ github.workspace }}/esmpy_doc - github_token: ${{ secrets.GITHUB_TOKEN }} + branch: master + github_token: ${{ secrets.ESMF_WEB_TOKEN }} + message: 'Publish ESMPy Docs' From 9d797937905d463a2f728d76b15d191b08614619 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 14:53:33 -0600 Subject: [PATCH 158/266] Turn off automatic CircleCI doc builds, but leave option to run manually --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ba5b565e96..0b78024140 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -490,11 +490,11 @@ workflows: docs-commit: jobs: -# - should-build-docs: -# type: approval -# - build-esmf-docs: -# requires: -# - should-build-docs + - should-build-docs: + type: approval + - build-esmf-docs: + requires: + - should-build-docs - build-esmf-docs - publish-esmf-docs: requires: From 5faee2ae6210726c74d12695d1a760bc3af08b49 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 14:56:31 -0600 Subject: [PATCH 159/266] Fix CircleCI doc build approval --- .circleci/config.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0b78024140..cfefa41f3c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -495,7 +495,6 @@ workflows: - build-esmf-docs: requires: - should-build-docs - - build-esmf-docs - publish-esmf-docs: requires: - build-esmf-docs @@ -504,9 +503,9 @@ workflows: # only: # - develop # - /^release/.*$/ - - build-esmpy-docs -# requires: -# - should-build-docs + - build-esmpy-docs: + requires: + - should-build-docs - publish-esmpy-docs: requires: - build-esmpy-docs From fd3fd1f45e5f917224d0845d8ef68a78e83c5bac Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Fri, 2 Sep 2022 14:37:28 -0700 Subject: [PATCH 160/266] Integration of addon layers wrt README.md's, specifically ESMX. --- README.md | 8 +- src/addon/ESMX/README.md | 114 ++++++++++++++++++++++++++ src/addon/NUOPC/{README => README.md} | 6 +- 3 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 src/addon/ESMX/README.md rename src/addon/NUOPC/{README => README.md} (87%) diff --git a/README.md b/README.md index 737bc743d7..b7fb629935 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![ESMF](https://circleci.com/gh/esmf-org/esmf.svg?style=svg)](http://www.earthsystemmodeling.org/docs/nightly/develop/ESMF_refdoc/) -# Earth System Modeling Framework (ESMF) +# Earth System Modeling Framework (ESMF) >Copyright (c) 2002-2022 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. All rights reserved. @@ -32,8 +32,10 @@ conda create -c conda-forge -n esmf esmpy ## Add-On Packages Several add-on packages are included with ESMF under [`./src/addon`](https://github.com/esmf-org/esmf/tree/master/src/addon): - * [ESMPy](src/addon/ESMPy/README.md) - Python interface to ESMF. - * [NUOPC](src/addon/NUOPC/README) - Interoperability layer developed under the National Unified Operational Prediction Capability (NUOPC) program. + * [ESMPy](src/addon/ESMPy) - Python interface to ESMF. + * [ESMX](src/addon/ESMX) - A layer providing the Earth System Model eXecutable. + The ESMX layer is built on top of ESMF and NUOPC. + * [NUOPC](src/addon/NUOPC) - Interoperability layer developed under the National Unified Operational Prediction Capability (NUOPC) program. See each addon package for a specific README file. diff --git a/src/addon/ESMX/README.md b/src/addon/ESMX/README.md new file mode 100644 index 0000000000..71bc0519c6 --- /dev/null +++ b/src/addon/ESMX/README.md @@ -0,0 +1,114 @@ +# ESMX + +ESMX is the **E**arth **S**ystem **M**odel e**X**ecutable layer. + +The ESMX layer is built on top of ESMF and NUOPC. ESMX user interfaces are typically implemented through configuration files. + +The idea is to make it as simple as possible for a user to build, run, and test NUOPC based systems. The approach is supposed to be the same whether applied to a single component, or a fully coupled system of NUOPC-compliant components. + +ESMX tries to unify, provide, and maintain those parts of NUOPC-based modeling systems that are common across most such implementations. This includes the top level application and driver code, parts of the build infrastructure, and tools to manage run configurations. + +The objectives of ESMX are: + - **Simplification** of standing up new NUOPC-based systems. + - **Reduction** of maintenance cost for established NUOPC-based systems. + - **Improved** alignment and interoperability between different NUOPC-based systems. (Configuration files, procedures, etc.) + - **Faster and more coordinated** role out of new NUOPC/ESMF features. + +## The Unified Driver Executable + +One of the main features provided by ESMX is the *unified driver executable*. A good starting point to explore this feature is the [ESMX_AtmOcnProto](https://github.com/esmf-org/nuopc-app-prototypes/tree/develop/ESMX_AtmOcnProto) under the NUOPC prototype repository. + +The default name of the unified driver executable built by ESMX is lower case `esmx`. This will be used for the remainder of this section to refer to the unfied driver executable. + +### Project integration + +A build target for `esmx` needs to be added to the projects build system. ESMX provides a CMake based approach that makes this easy. A simple target based on GNU Make looks like this: + + include $(ESMFMKFILE) + + esmx: esmxBuild.yaml + cmake -H$(ESMF_ESMXDIR) -Bbuild + cmake --build ./build + +The `ESMF_ESMXDIR` variable used is defined by the ESMF installation through the `esmf.mk` file included in the first line. +A successful execution of this target will result in the unfied driver executable as `build/esmx`. + +### esmxBuild.yaml + +As shown above, building `esmx` has a dependency on file `esmxBuild.yaml`. This is a yaml file with a very simple format. An example is given here: + + components: + + tawas: + config: TaWaS/tawas.cmake + fort_module: tawas + + lumo: + config: Lumo/lumo.cmake + +In this example two components are built into `esmx` explicitly. (Read about dynamically loading components from shared objects at run-time later.) + +Each component is given a name, here `tawas` and `lumo`. Components will be referred to by this *component-name* in the run-time configuration (esmxRun.config) discussed below. + +Each component must define the `config` key, specifying a file that can be included by the CMake based `esmx` build. This file must specify three CMake elements: +- `add_library(component-name ... )` +- `set_target_properties(component-name ... )` +- `target_link_libraries(esmx PRIVATE component-name)` + +Here *component-name* is the name under which the component was defined in the `esmxBuild.yaml` file, here `tawas` or `lumo`. + +Further, a component can optionally provide the `fort_module` key. This explicitly specifys the name of the Fortran module that provides the entry points into the respective NUOPC component. By default the *component-name* is used. + +### esmxRun.config + +The esmxRun.config file needs to be located under the run directory from where the `esmx` executable is launched. It is read by `esmx` during startup. It specifies a few global ESMF and ESMX level settings, the list of components accessed during this run, details about the components, and finally the run sequence. + + logKindFlag: ESMF_LOGKIND_MULTI + globalResourceControl: .true. + + ESMX_log_flush: .true. + ESMX_field_dictionary: ./fd.yaml + + ESMX_component_list: ATM OCN + ESMX_attributes:: + Verbosity = high + :: + + ATM_model: tawas + ATM_omp_num_threads: 4 + ATM_attributes:: + Verbosity = high + :: + + OCN_model: lumo + OCN_petlist: 1 3 + OCN_attributes:: + Verbosity = high + :: + + startTime: 2012-10-24T18:00:00 + stopTime: 2012-10-24T19:00:00 + + runSeq:: + @900 + ATM -> OCN + OCN -> ATM + ATM + OCN + @ + :: + +The first two fields, `logKindFlag` and `globalResourceControl`, are examples of ESMF level configuration options. They are ingested by the [ESMF_Initialize()](https://earthsystemmodeling.org/docs/nightly/develop/ESMF_refdoc/node4.html#SECTION04024100000000000000) method (called by `esmx`) as documented in the [ESMF Reference Manual](https://earthsystemmodeling.org/docs/nightly/develop/ESMF_refdoc/ESMF_refdoc.html). + +Fields starting with `ESMX_` are defined by the ESMX unified driver executable. Most important on this level is `ESMX_component_list`. This field defines the generic components participating in the execution. There is no restriction what labels can be used for the generic components, however, `ATM` and `OCN` are typical labels for "atmosphere" and "ocean", respectively. Note that the run sequence under `runSeq`, toward the end of the file, is defined in terms of the generic component labels introduced by `ESMX_component_list`. + +Each generic component label must be associated with an actual component model through the `XXX_model` field, where `XXX` is replaced by the actual generic component label, e.g. `ATM`, `OCN`, etc. The association is made by specifying the *component-name* used in the `esmxBuild.yaml` file discussed earlier. The options in the example are `tawas` and `lumo`. + +Finally the `startTime` and `stopTime` fields set the start and stop time of the run, respectively. The `runSeq` field defines the run sequence. + +### Dynamically loading components from shared objects at run-time + +There are two options recognized when specifying the value of the `XXX_model` field: +- First, if the value specified is recognized as a *component-name* provided by any of the components built into `esmx` during build-time, as specified by `esmxBuild.yaml`, the respective component is accessed via its Fortran module. +- Second, if the value does not match a build-time dependency, it is assumed to correspond to a shared object. In that case the attempt is made to load the specified shared object at run-time, and to associate with the generic component label. + diff --git a/src/addon/NUOPC/README b/src/addon/NUOPC/README.md similarity index 87% rename from src/addon/NUOPC/README rename to src/addon/NUOPC/README.md index e7b599e1ce..dc70a52913 100644 --- a/src/addon/NUOPC/README +++ b/src/addon/NUOPC/README.md @@ -1,5 +1,6 @@ -NUOPC Layer -=========== +# NUOPC Layer + +NUOPC is the **N**ational **U**nified **O**perational **P**rediction **C**apability. The National Unified Operational Prediction Capability (NUOPC) is a consortium of Navy, NOAA, and Air Force modelers and their research partners. It aims to @@ -15,4 +16,3 @@ reference manual, please visit: http://earthsystemmodeling.org/nuopc/ --- From 85d3dc6b75dab8d131a158389c81aaaf4d602016 Mon Sep 17 00:00:00 2001 From: Rocky Dunlap Date: Fri, 2 Sep 2022 16:22:20 -0600 Subject: [PATCH 161/266] Update README with new doc build status badges --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b7fb629935..01947a0af0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![ESMF](https://circleci.com/gh/esmf-org/esmf.svg?style=svg)](http://www.earthsystemmodeling.org/docs/nightly/develop/ESMF_refdoc/) +[![ESMF Doc Build](https://github.com/esmf-org/esmf/actions/workflows/build-esmf-docs.yml/badge.svg)](https://github.com/esmf-org/esmf/actions/workflows/build-esmf-docs.yml) +[![ESMPy Doc Build](https://github.com/esmf-org/esmf/actions/workflows/build-esmpy-docs.yml/badge.svg)](https://github.com/esmf-org/esmf/actions/workflows/build-esmpy-docs.yml) # Earth System Modeling Framework (ESMF) From ce85282b0e711e2ea3fd832809b895d9e2c1db5e Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Sat, 3 Sep 2022 11:21:33 -0700 Subject: [PATCH 162/266] Lower required CMake version (to the same as is required by PIO). --- src/addon/ESMX/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMX/CMakeLists.txt b/src/addon/ESMX/CMakeLists.txt index f193c1b2a7..727548fef1 100644 --- a/src/addon/ESMX/CMakeLists.txt +++ b/src/addon/ESMX/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.5.2) enable_language(Fortran) # Where to look for Find.cmake files From 679812f63eb3bd2f12a4291200492102da83abaf Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Mon, 5 Sep 2022 06:15:45 -0600 Subject: [PATCH 163/266] Add unit tests of FieldBundleRead and FieldRead These actually pass already. This was a bit surprising to me. I'm still going to check the arrayRead and arrayReadOneTileFile routines to make sure they seem to have everything they need. --- .../IO/tests/ESMF_IO_MultitileUTest.F90 | 107 +++++++++++++++++- 1 file changed, 105 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 index ff8bab2d47..53504764fb 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 @@ -45,16 +45,34 @@ program ESMF_IO_MultitileUTest character(ESMF_MAXSTR) :: name type(ESMF_Grid) :: grid6tile + + ! Fields used for writing: + ! ! The following fields make up the field bundle: type(ESMF_Field) :: field1, field2, field1Copy + real(ESMF_KIND_R8), pointer :: data1(:,:), data2(:,:), data1Copy(:,:) type(ESMF_FieldBundle) :: fieldBundle ! This field is not in the field bundle: type(ESMF_Field) :: field3 + real(ESMF_KIND_R8), pointer :: data3(:,:) + + ! Fields used for reading: + ! + ! The following fields make up the field bundle: + type(ESMF_Field) :: field1Read, field2Read, field1CopyRead + real(ESMF_KIND_R8), pointer :: data1Read(:,:), data2Read(:,:), data1CopyRead(:,:) + type(ESMF_FieldBundle) :: fieldBundleRead + ! This field is not in the field bundle: + type(ESMF_Field) :: field3Read + real(ESMF_KIND_R8), pointer :: data3Read(:,:) + ! This is used for error testing: type(ESMF_Grid) :: gridSingleTile type(ESMF_Field) :: fieldSingleTile type(ESMF_FieldBundle) :: fieldBundleMixedTileCounts + logical :: allEqual + character(len=*), parameter :: fileName = "ESMF_IO_MultitileUTest#.nc" character(len=*), parameter :: fileNameFail = "ESMF_IO_MultitileUTestFail#.nc" @@ -84,8 +102,34 @@ program ESMF_IO_MultitileUTest #endif !------------------------------------------------------------------------ - ! FIXME(wjs, 2022-08-26) Add tests of FieldBundleRead and FieldRead; in - ! addition to checking rc, also check equality to the original fields + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(name, *) "Read a FieldBundle with multi-tile fields" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldBundleRead(fieldBundleRead, fileName=fileName, rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !NEX_UTest_Multi_Proc_Only + write(name, *) "Confirm that FieldBundle-read fields match originals" + write(failMsg, *) "Some read-in fields differ from originals" + allEqual = ( & + all(data1Read == data1) .and. & + all(data2Read == data2) .and. & + all(data1CopyRead == data1Copy)) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 + !------------------------------------------------------------------------ #ifdef ESMF_TESTEXHAUSTIVE ! The following tests don't add much code coverage, so are only done when @@ -104,6 +148,32 @@ program ESMF_IO_MultitileUTest #endif !------------------------------------------------------------------------ + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + write(name, *) "Read a multi-tile Field" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldRead(field3Read, fileName=fileName, rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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(data3Read == data3) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 + !------------------------------------------------------------------------ + !------------------------------------------------------------------------ !EX_UTest_Multi_Proc_Only write(name, *) "Create single-tile field for failure testing" @@ -172,16 +242,37 @@ subroutine createFields(rc) if (rc /= ESMF_SUCCESS) return call ESMF_FieldFill(field1, dataFillScheme='sincos', member=1, rc=rc) if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field1, farrayPtr=data1) + if (rc /= ESMF_SUCCESS) return + + field1Read = ESMF_FieldCreate(grid6tile, arraySpec, name="field1", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field1Read, farrayPtr=data1Read) + if (rc /= ESMF_SUCCESS) return field2 = ESMF_FieldCreate(grid6tile, arraySpec, name="field2", rc=rc) if (rc /= ESMF_SUCCESS) return call ESMF_FieldFill(field2, dataFillScheme='sincos', member=2, rc=rc) if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field2, farrayPtr=data2) + if (rc /= ESMF_SUCCESS) return + + field2Read = ESMF_FieldCreate(grid6tile, arraySpec, name="field2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field2Read, farrayPtr=data2Read) + if (rc /= ESMF_SUCCESS) return field3 = ESMF_FieldCreate(grid6tile, arraySpec, name="field3", rc=rc) if (rc /= ESMF_SUCCESS) return call ESMF_FieldFill(field3, dataFillScheme='sincos', member=3, rc=rc) if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field3, farrayPtr=data3) + if (rc /= ESMF_SUCCESS) return + + field3Read = ESMF_FieldCreate(grid6tile, arraySpec, name="field3", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field3Read, farrayPtr=data3Read) + if (rc /= ESMF_SUCCESS) return ! Create a copy of field1 that uses the same array, so we can test writing ! the same array twice from a single call. @@ -189,12 +280,24 @@ subroutine createFields(rc) if (rc /= ESMF_SUCCESS) return field1Copy = ESMF_FieldCreate(grid6tile, array1, name="field1Copy", rc=rc) if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field1Copy, farrayPtr=data1Copy) + if (rc /= ESMF_SUCCESS) return + + field1CopyRead = ESMF_FieldCreate(grid6tile, arraySpec, name="field1Copy", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldGet(field1CopyRead, farrayPtr=data1CopyRead) + if (rc /= ESMF_SUCCESS) return fieldBundle = ESMF_FieldBundleCreate(name="fb", rc=rc) if (rc /= ESMF_SUCCESS) return call ESMF_FieldBundleAdd(fieldBundle, [field1, field2, field1Copy], rc=rc) if (rc /= ESMF_SUCCESS) return + fieldBundleRead = ESMF_FieldBundleCreate(name="fbRead", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_FieldBundleAdd(fieldBundleRead, [field1Read, field2Read, field1CopyRead], rc=rc) + if (rc /= ESMF_SUCCESS) return + end subroutine createFields subroutine createSingleTileField(rc) From 966e7354932b318e269f8fa0cf4de84ce8c17eaf Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 5 Sep 2022 14:37:10 -0700 Subject: [PATCH 164/266] Work around more issues flagged on some platforms by nightly testing. --- src/addon/ESMX/CMakeLists.txt | 2 +- src/addon/ESMX/esmx.F90 | 116 +++++++++++++++++----------------- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/src/addon/ESMX/CMakeLists.txt b/src/addon/ESMX/CMakeLists.txt index 727548fef1..0d6c6d5c17 100644 --- a/src/addon/ESMX/CMakeLists.txt +++ b/src/addon/ESMX/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_CXX_COMPILER ${ESMF_CXXCOMPILER}) set(CMAKE_Fortran_COMPILER ${ESMF_F90COMPILER}) # Specific project settings -project(ESMX VERSION 0.1.0 DESCRIPTION "Unified Nuopc EXecutable") +project(ESMX VERSION 0.1.0) add_executable(esmx esmx.F90) target_link_libraries(esmx PRIVATE ESMF) install(TARGETS esmx) diff --git a/src/addon/ESMX/esmx.F90 b/src/addon/ESMX/esmx.F90 index 3d0f29be99..d517ff966b 100644 --- a/src/addon/ESMX/esmx.F90 +++ b/src/addon/ESMX/esmx.F90 @@ -2,6 +2,8 @@ ! ESMX (Earth System Model eXecutable) ! This file contains the main application program and the top level driver. !============================================================================== +#define FILENAME "src/addon/ESMX/esmx.F90" +!============================================================================== module esmxDriver @@ -37,7 +39,7 @@ subroutine SetServices(driver, rc) call NUOPC_CompDerive(driver, driverSS, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! Specialize Driver @@ -45,14 +47,14 @@ subroutine SetServices(driver, rc) specRoutine=SetModelServices, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call NUOPC_CompSpecialize(driver, specLabel=label_SetRunSequence, & specRoutine=SetRunSequence, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out end subroutine SetServices @@ -84,7 +86,7 @@ subroutine SetModelServices(driver, rc) call ESMF_GridCompGet(driver, config=config, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! determine the generic component labels @@ -92,14 +94,14 @@ subroutine SetModelServices(driver, rc) rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out allocate(compLabels(componentCount)) call ESMF_ConfigGetAttribute(config, valueList=compLabels, & label="ESMX_component_list:", count=componentCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! setup CompDef structure @@ -116,14 +118,14 @@ subroutine SetModelServices(driver, rc) relaxedFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call NUOPC_IngestPetList(petList, ff, rc=rc) call ESMF_ConfigGetAttribute(config, model, & label=trim(prefix)//"_model:", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! set up NUOPC hint for OpenMP @@ -131,19 +133,19 @@ subroutine SetModelServices(driver, rc) label=trim(prefix)//"_omp_num_threads:", default=-1, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out info = ESMF_InfoCreate(rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out if (ompNumThreads /= -1) then call ESMF_InfoSet(info, key="/NUOPC/Hint/PePerPet/MaxCount", & value=ompNumThreads, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out endif @@ -166,7 +168,7 @@ subroutine SetModelServices(driver, rc) msg="Unable to add component '"//trim(prefix)// & "' to driver via Fortran module.", & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out else ! add child component with SetVM and SetServices in shared object @@ -177,7 +179,7 @@ subroutine SetModelServices(driver, rc) msg="Unable to add component '"//trim(prefix)// & "' to driver via shared object: "//trim(model), & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out endif @@ -186,33 +188,33 @@ subroutine SetModelServices(driver, rc) label=trim(prefix)//"_attributes::", relaxedflag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call NUOPC_FreeFormatDestroy(ff, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ff = NUOPC_FreeFormatCreate(config, & label="ALLCOMP_attributes::", relaxedflag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call NUOPC_FreeFormatDestroy(ff, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! clean-up @@ -220,7 +222,7 @@ subroutine SetModelServices(driver, rc) call ESMF_InfoDestroy(info, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out enddo @@ -231,25 +233,25 @@ subroutine SetModelServices(driver, rc) rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call ESMF_ConfigGetAttribute(config, stopTimeString, label="stopTime:", & rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! set the driver clock startTime/stopTime call ESMF_TimeSet(startTime, timeString=startTimeString, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call ESMF_TimeSet(stopTime, timeString=stopTimeString, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! set the driver clock default timeStep = stopTime - startTime @@ -261,13 +263,13 @@ subroutine SetModelServices(driver, rc) timeStep=timeStep, startTime=startTime, stopTime=stopTime, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out call ESMF_GridCompSet(driver, clock=internalClock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out rc = ESMF_SUCCESS @@ -291,14 +293,14 @@ subroutine SetRunSequence(driver, rc) call ESMF_GridCompGet(driver, name=name, config=config, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! read free format run sequence from config runSeqFF = NUOPC_FreeFormatCreate(config, label="runSeq::", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! ingest FreeFormat run sequence @@ -306,14 +308,14 @@ subroutine SetRunSequence(driver, rc) autoAddConnectors=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out ! clean-up call NUOPC_FreeFormatDestroy(runSeqFF, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out end subroutine SetRunSequence @@ -346,45 +348,45 @@ program ESMX defaultCalkind=ESMF_CALKIND_GREGORIAN, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_ConfigGetAttribute(config, logFlush, & label="ESMX_log_flush:", default=.false., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogSet(flush=logFlush, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogWrite("=============================================", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogWrite("ESMX (Earth System Model eXecutable) STARTING", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogWrite("=============================================", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_ConfigGetAttribute(config, fieldDictionary, & label="ESMX_field_dictionary:", default="", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) if (trim(fieldDictionary)/="") then ! Read custom dictionary from YAML file @@ -392,7 +394,7 @@ program ESMX if (ESMF_LogFoundError(rcToCheck=rc, & msg="Unable to read Field Dictionary file: "//trim(fieldDictionary), & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) endif @@ -400,18 +402,18 @@ program ESMX driver = ESMF_GridCompCreate(name="esmxDriver", config=config, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! SetServices for the esmx driver call ESMF_GridCompSetServices(driver, driverSS, userRc=urc, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! read and ingest free format driver attributes @@ -419,92 +421,92 @@ program ESMX relaxedflag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call NUOPC_CompAttributeIngest(driver, ff, addFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call NUOPC_FreeFormatDestroy(ff, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ff = NUOPC_FreeFormatCreate(config, label="ALLCOMP_attributes::", & relaxedflag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call NUOPC_CompAttributeIngest(driver, ff, addFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call NUOPC_FreeFormatDestroy(ff, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Call Initialize for the esmx driver call ESMF_GridCompInitialize(driver, userRc=urc, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Call Run for the esmx driver call ESMF_GridCompRun(driver, userRc=urc, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Call Finalize for the esmx driver call ESMF_GridCompFinalize(driver, userRc=urc, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) if (ESMF_LogFoundError(rcToCheck=urc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Destroy the esmx driver call ESMF_GridCompDestroy(driver, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogWrite("=============================================", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogWrite("ESMX (Earth System Model eXecutable) FINISHED", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_LogWrite("=============================================", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! Finalize ESMF From fd0845b833030cbc9fce35be49c7a398ffb15b0c Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 5 Sep 2022 14:59:46 -0700 Subject: [PATCH 165/266] Fix bug. --- src/addon/NUOPC/src/NUOPC_Base.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/NUOPC/src/NUOPC_Base.F90 b/src/addon/NUOPC/src/NUOPC_Base.F90 index 16d1efe350..cc55965d09 100644 --- a/src/addon/NUOPC/src/NUOPC_Base.F90 +++ b/src/addon/NUOPC/src/NUOPC_Base.F90 @@ -2389,7 +2389,7 @@ subroutine NUOPC_IngestPetList(petList, freeFormat, rc) blockCount = blockCount + tokenCount enddo - allocate(lb(tokenCount),ub(tokenCount)) + allocate(lb(blockCount),ub(blockCount)) petCount = 0 k = 1 From d8588da95068b93413681c0cd45f45f36e66a9eb Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 6 Sep 2022 13:58:10 -0600 Subject: [PATCH 166/266] Add some comments --- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index 6dd0a10e2e..bc86f22ad9 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -630,6 +630,8 @@ void PIO_Handler::arrayReadOneTileFile( // anyway? // - (2022-07-22) I think I should set it to NULL baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); + // 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 PIO) int arrlen = 1; #if defined(ESMF_NETCDF) || defined(ESMF_PNETCDF) int nDims; @@ -677,6 +679,7 @@ void PIO_Handler::arrayReadOneTileFile( narrDims = narrDims - 1; } for (int i=0; i Date: Tue, 6 Sep 2022 13:32:22 -0700 Subject: [PATCH 167/266] Ensure to only use CMake elements that are available at v3.5.2. --- src/addon/ESMX/cmake/FindESMF.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMX/cmake/FindESMF.cmake b/src/addon/ESMX/cmake/FindESMF.cmake index 8b709ed50f..4b7dcf4c3a 100644 --- a/src/addon/ESMX/cmake/FindESMF.cmake +++ b/src/addon/ESMX/cmake/FindESMF.cmake @@ -107,7 +107,7 @@ if(EXISTS ${ESMFMKFILE}) # Add ESMF include directories set(ESMF_INCLUDE_DIRECTORIES "") - separate_arguments(_ESMF_F90COMPILEPATHS NATIVE_COMMAND ${ESMF_F90COMPILEPATHS}) + separate_arguments(_ESMF_F90COMPILEPATHS UNIX_COMMAND ${ESMF_F90COMPILEPATHS}) foreach(_ITEM ${_ESMF_F90COMPILEPATHS}) string(REGEX REPLACE "^-I" "" _ITEM "${_ITEM}") list(APPEND ESMF_INCLUDE_DIRECTORIES ${_ITEM}) From 7af98e21f475009f2479dad5ebd200e489912661 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Tue, 6 Sep 2022 15:57:40 -0600 Subject: [PATCH 168/266] For arrayRead, set baseAddress to NULL if this PE is not involved This isn't necessary, but is an extra safety measure. Also initialize arrlen to 0 in this situation to more clearly signify that this will be the final value in this situation. (And this might also impact a 0-d case, though that's probably irrelevant for multi-tile I/O.) --- src/Infrastructure/IO/src/ESMCI_PIO_Handler.C | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C index bc86f22ad9..20ba9816cf 100644 --- a/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C +++ b/src/Infrastructure/IO/src/ESMCI_PIO_Handler.C @@ -625,14 +625,19 @@ void PIO_Handler::arrayReadOneTileFile( // Get a pointer to the array data // Still have the one DE restriction so use localDE = 0 localDE = 0; - // FIXME(wjs, 2022-07-21) Should this be something special (like NULL) if this DE - // doesn't belong to the tile of interest? Or is it okay for it to be set like this - // anyway? - // - (2022-07-22) I think I should set it to NULL - baseAddress = arr_p->getLocalarrayList()[localDE]->getBaseAddr(); + 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 PIO) - int arrlen = 1; + 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; From dc4b1d64705c9b64889038a369ed4ac1463a56ca Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 6 Sep 2022 15:03:07 -0700 Subject: [PATCH 169/266] Split the ESMX_Driver out of esmx.F90 in order to be available as a separate library that can be accessed via the NUOPC External Driver API. --- src/addon/ESMX/CMakeLists.txt | 9 +- src/addon/ESMX/ESMX_Driver.F90 | 325 +++++++++++++++++++++++++++++++++ src/addon/ESMX/esmx.F90 | 325 +-------------------------------- 3 files changed, 336 insertions(+), 323 deletions(-) create mode 100644 src/addon/ESMX/ESMX_Driver.F90 diff --git a/src/addon/ESMX/CMakeLists.txt b/src/addon/ESMX/CMakeLists.txt index 0d6c6d5c17..8a63e98b67 100644 --- a/src/addon/ESMX/CMakeLists.txt +++ b/src/addon/ESMX/CMakeLists.txt @@ -18,7 +18,7 @@ target_link_libraries(esmx PRIVATE ESMF) install(TARGETS esmx) target_include_directories(esmx PUBLIC ${PROJECT_BINARY_DIR}) -# Generate +# Generate comp*.* files from esmxBuild.yaml find_package(Python 3 COMPONENTS Interpreter REQUIRED) execute_process(COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/esmxGen.py --ifile ./esmxBuild.yaml --odir ${CMAKE_CURRENT_BINARY_DIR} @@ -27,4 +27,11 @@ if(ret EQUAL "1") message( FATAL_ERROR "esmxGen.py failed processing esmxBuild.yaml") endif() +# Specify driver dependency +add_library(esmx_driver ESMX_Driver.F90) +target_include_directories(esmx_driver PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +target_link_libraries(esmx_driver PRIVATE ESMF) +target_link_libraries(esmx PUBLIC esmx_driver) + +# Include compList.txt which in turn includes component libraries include(${CMAKE_CURRENT_BINARY_DIR}/compList.txt) diff --git a/src/addon/ESMX/ESMX_Driver.F90 b/src/addon/ESMX/ESMX_Driver.F90 new file mode 100644 index 0000000000..3a59cd0ba7 --- /dev/null +++ b/src/addon/ESMX/ESMX_Driver.F90 @@ -0,0 +1,325 @@ +!============================================================================== +! ESMX_Driver (Earth System Model eXecutable Driver) +! This file contains the ESMX top level driver. +!============================================================================== +#define FILENAME "src/addon/ESMX/ESMX_Driver.F90" +!============================================================================== + +module ESMX_Driver + + use ESMF + use NUOPC + use NUOPC_Driver, driverSS => SetServices + + include "compUse.inc" + + implicit none + + private + + public SetServices, SetVM + + type type_CompDef + procedure(SetServices), pointer, nopass :: ssPtr => null() + procedure(SetVM), pointer, nopass :: svPtr => null() + character(ESMF_MAXSTR) :: name = "__uninitialized__" + end type + + !----------------------------------------------------------------------------- + contains + !----------------------------------------------------------------------------- + + subroutine SetServices(driver, rc) + type(ESMF_GridComp) :: driver + integer, intent(out) :: rc + + rc = ESMF_SUCCESS + + ! Derive from NUOPC_Driver + call NUOPC_CompDerive(driver, driverSS, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! Specialize Driver + call NUOPC_CompSpecialize(driver, specLabel=label_SetModelServices, & + specRoutine=SetModelServices, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + call NUOPC_CompSpecialize(driver, specLabel=label_SetRunSequence, & + specRoutine=SetRunSequence, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + end subroutine SetServices + + !----------------------------------------------------------------------------- + + subroutine SetModelServices(driver, rc) + type(ESMF_GridComp) :: driver + integer, intent(out) :: rc + + ! local variables + character(len=32) :: startTimeString, stopTimeString + type(ESMF_Time) :: startTime, stopTime + type(ESMF_TimeInterval) :: timeStep + type(ESMF_Clock) :: internalClock + integer :: i, j, componentCount, ompNumThreads + integer, allocatable :: petList(:) + type(ESMF_GridComp) :: comp + type(ESMF_Config) :: config + type(NUOPC_FreeFormat) :: ff + character(len=32), allocatable :: compLabels(:) + character(len=32) :: prefix + character(len=240) :: model + type(ESMF_Info) :: info + type(type_CompDef), allocatable :: CompDef(:) + logical :: inCompDef + + ! get the config + call ESMF_GridCompGet(driver, config=config, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! determine the generic component labels + componentCount = ESMF_ConfigGetLen(config, label="ESMX_component_list:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + allocate(compLabels(componentCount)) + call ESMF_ConfigGetAttribute(config, valueList=compLabels, & + label="ESMX_component_list:", count=componentCount, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! setup CompDef structure + allocate(CompDef(componentCount)) + include "compDef.inc" + + ! determine information for each component and add to the driver + do i=1, componentCount + ! construct component prefix + prefix=trim(compLabels(i)) + + ! set up petList + ff = NUOPC_FreeFormatCreate(config, label=trim(prefix)//"_petlist:", & + relaxedFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_IngestPetList(petList, ff, rc=rc) + call ESMF_ConfigGetAttribute(config, model, & + label=trim(prefix)//"_model:", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! set up NUOPC hint for OpenMP + call ESMF_ConfigGetAttribute(config, ompNumThreads, & + label=trim(prefix)//"_omp_num_threads:", default=-1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + info = ESMF_InfoCreate(rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + if (ompNumThreads /= -1) then + call ESMF_InfoSet(info, key="/NUOPC/Hint/PePerPet/MaxCount", & + value=ompNumThreads, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + endif + + ! see whether there is an entry for this component inside CompDef + inCompDef = .false. + do j=1, componentCount + if (trim(CompDef(j)%name)=="__uninitialized__") exit + if (trim(CompDef(j)%name)==trim(model)) then + inCompDef = .true. + exit + endif + enddo + + if (inCompDef) then + ! add child component with SetVM and SetServices in CompDef + call NUOPC_DriverAddComp(driver, trim(prefix), config=config, & + compSetServicesRoutine=CompDef(j)%ssPtr, compSetVMRoutine=CompDef(j)%svPtr, & + info=info, petList=petList, comp=comp, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, & + msg="Unable to add component '"//trim(prefix)// & + "' to driver via Fortran module.", & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + else + ! add child component with SetVM and SetServices in shared object + call NUOPC_DriverAddComp(driver, trim(prefix), config=config, & + sharedObj=trim(model), info=info, petList=petList, comp=comp, & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, & + msg="Unable to add component '"//trim(prefix)// & + "' to driver via shared object: "//trim(model), & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + endif + + ! read and ingest free format component attributes + ff = NUOPC_FreeFormatCreate(config, & + label=trim(prefix)//"_attributes::", relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + ff = NUOPC_FreeFormatCreate(config, & + label="ALLCOMP_attributes::", relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! clean-up + deallocate(petList) + call ESMF_InfoDestroy(info, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + enddo + + deallocate(compLabels) + + ! read startTimeString and stopTimeString from config + call ESMF_ConfigGetAttribute(config, startTimeString, label="startTime:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call ESMF_ConfigGetAttribute(config, stopTimeString, label="stopTime:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! set the driver clock startTime/stopTime + call ESMF_TimeSet(startTime, timeString=startTimeString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call ESMF_TimeSet(stopTime, timeString=stopTimeString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! set the driver clock default timeStep = stopTime - startTime + ! use with runSequence @*, + ! or overwritten with explicit timeStep in runSequence + timeStep = stopTime - startTime + + internalClock = ESMF_ClockCreate(name="Application Clock", & + timeStep=timeStep, startTime=startTime, stopTime=stopTime, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + call ESMF_GridCompSet(driver, clock=internalClock, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + rc = ESMF_SUCCESS + + end subroutine SetModelServices + + !----------------------------------------------------------------------------- + + subroutine SetRunSequence(driver, rc) + type(ESMF_GridComp) :: driver + integer, intent(out) :: rc + + ! local variables + character(ESMF_MAXSTR) :: name + type(ESMF_Config) :: config + type(NUOPC_FreeFormat) :: runSeqFF + + rc = ESMF_SUCCESS + + ! query the driver for its name and config + call ESMF_GridCompGet(driver, name=name, config=config, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! read free format run sequence from config + runSeqFF = NUOPC_FreeFormatCreate(config, label="runSeq::", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! ingest FreeFormat run sequence + call NUOPC_DriverIngestRunSequence(driver, runSeqFF, & + autoAddConnectors=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + ! clean-up + call NUOPC_FreeFormatDestroy(runSeqFF, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + end subroutine SetRunSequence + + !----------------------------------------------------------------------------- + +end module ESMX_Driver diff --git a/src/addon/ESMX/esmx.F90 b/src/addon/ESMX/esmx.F90 index d517ff966b..d23ff0588b 100644 --- a/src/addon/ESMX/esmx.F90 +++ b/src/addon/ESMX/esmx.F90 @@ -1,329 +1,10 @@ !============================================================================== ! ESMX (Earth System Model eXecutable) -! This file contains the main application program and the top level driver. +! This file contains the main ESMX application program. !============================================================================== #define FILENAME "src/addon/ESMX/esmx.F90" !============================================================================== -module esmxDriver - - use ESMF - use NUOPC - use NUOPC_Driver, driverSS => SetServices - - include "compUse.inc" - - implicit none - - private - - public SetServices, SetVM - - type type_CompDef - procedure(SetServices), pointer, nopass :: ssPtr => null() - procedure(SetVM), pointer, nopass :: svPtr => null() - character(ESMF_MAXSTR) :: name = "__uninitialized__" - end type - - !----------------------------------------------------------------------------- - contains - !----------------------------------------------------------------------------- - - subroutine SetServices(driver, rc) - type(ESMF_GridComp) :: driver - integer, intent(out) :: rc - - rc = ESMF_SUCCESS - - ! Derive from NUOPC_Driver - call NUOPC_CompDerive(driver, driverSS, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! Specialize Driver - call NUOPC_CompSpecialize(driver, specLabel=label_SetModelServices, & - specRoutine=SetModelServices, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - call NUOPC_CompSpecialize(driver, specLabel=label_SetRunSequence, & - specRoutine=SetRunSequence, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - end subroutine SetServices - - !----------------------------------------------------------------------------- - - subroutine SetModelServices(driver, rc) - type(ESMF_GridComp) :: driver - integer, intent(out) :: rc - - ! local variables - character(len=32) :: startTimeString, stopTimeString - type(ESMF_Time) :: startTime, stopTime - type(ESMF_TimeInterval) :: timeStep - type(ESMF_Clock) :: internalClock - integer :: i, j, componentCount, ompNumThreads - integer, allocatable :: petList(:) - type(ESMF_GridComp) :: comp - type(ESMF_Config) :: config - type(NUOPC_FreeFormat) :: ff - character(len=32), allocatable :: compLabels(:) - character(len=32) :: prefix - character(len=240) :: model - type(ESMF_Info) :: info - type(type_CompDef), allocatable :: CompDef(:) - logical :: inCompDef - - ! get the config - call ESMF_GridCompGet(driver, config=config, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! determine the generic component labels - componentCount = ESMF_ConfigGetLen(config, label="ESMX_component_list:", & - rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - allocate(compLabels(componentCount)) - call ESMF_ConfigGetAttribute(config, valueList=compLabels, & - label="ESMX_component_list:", count=componentCount, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! setup CompDef structure - allocate(CompDef(componentCount)) - include "compDef.inc" - - ! determine information for each component and add to the driver - do i=1, componentCount - ! construct component prefix - prefix=trim(compLabels(i)) - - ! set up petList - ff = NUOPC_FreeFormatCreate(config, label=trim(prefix)//"_petlist:", & - relaxedFlag=.true., rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call NUOPC_IngestPetList(petList, ff, rc=rc) - call ESMF_ConfigGetAttribute(config, model, & - label=trim(prefix)//"_model:", rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! set up NUOPC hint for OpenMP - call ESMF_ConfigGetAttribute(config, ompNumThreads, & - label=trim(prefix)//"_omp_num_threads:", default=-1, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - info = ESMF_InfoCreate(rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - if (ompNumThreads /= -1) then - call ESMF_InfoSet(info, key="/NUOPC/Hint/PePerPet/MaxCount", & - value=ompNumThreads, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - endif - - ! see whether there is an entry for this component inside CompDef - inCompDef = .false. - do j=1, componentCount - if (trim(CompDef(j)%name)=="__uninitialized__") exit - if (trim(CompDef(j)%name)==trim(model)) then - inCompDef = .true. - exit - endif - enddo - - if (inCompDef) then - ! add child component with SetVM and SetServices in CompDef - call NUOPC_DriverAddComp(driver, trim(prefix), config=config, & - compSetServicesRoutine=CompDef(j)%ssPtr, compSetVMRoutine=CompDef(j)%svPtr, & - info=info, petList=petList, comp=comp, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, & - msg="Unable to add component '"//trim(prefix)// & - "' to driver via Fortran module.", & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - else - ! add child component with SetVM and SetServices in shared object - call NUOPC_DriverAddComp(driver, trim(prefix), config=config, & - sharedObj=trim(model), info=info, petList=petList, comp=comp, & - rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, & - msg="Unable to add component '"//trim(prefix)// & - "' to driver via shared object: "//trim(model), & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - endif - - ! read and ingest free format component attributes - ff = NUOPC_FreeFormatCreate(config, & - label=trim(prefix)//"_attributes::", relaxedflag=.true., rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call NUOPC_FreeFormatDestroy(ff, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - ff = NUOPC_FreeFormatCreate(config, & - label="ALLCOMP_attributes::", relaxedflag=.true., rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call NUOPC_CompAttributeIngest(comp, ff, addFlag=.true., rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call NUOPC_FreeFormatDestroy(ff, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! clean-up - deallocate(petList) - call ESMF_InfoDestroy(info, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - enddo - - deallocate(compLabels) - - ! read startTimeString and stopTimeString from config - call ESMF_ConfigGetAttribute(config, startTimeString, label="startTime:", & - rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call ESMF_ConfigGetAttribute(config, stopTimeString, label="stopTime:", & - rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! set the driver clock startTime/stopTime - call ESMF_TimeSet(startTime, timeString=startTimeString, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call ESMF_TimeSet(stopTime, timeString=stopTimeString, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! set the driver clock default timeStep = stopTime - startTime - ! use with runSequence @*, - ! or overwritten with explicit timeStep in runSequence - timeStep = stopTime - startTime - - internalClock = ESMF_ClockCreate(name="Application Clock", & - timeStep=timeStep, startTime=startTime, stopTime=stopTime, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - call ESMF_GridCompSet(driver, clock=internalClock, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - rc = ESMF_SUCCESS - - end subroutine SetModelServices - - !----------------------------------------------------------------------------- - - subroutine SetRunSequence(driver, rc) - type(ESMF_GridComp) :: driver - integer, intent(out) :: rc - - ! local variables - character(ESMF_MAXSTR) :: name - type(ESMF_Config) :: config - type(NUOPC_FreeFormat) :: runSeqFF - - rc = ESMF_SUCCESS - - ! query the driver for its name and config - call ESMF_GridCompGet(driver, name=name, config=config, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! read free format run sequence from config - runSeqFF = NUOPC_FreeFormatCreate(config, label="runSeq::", rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! ingest FreeFormat run sequence - call NUOPC_DriverIngestRunSequence(driver, runSeqFF, & - autoAddConnectors=.true., rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - ! clean-up - call NUOPC_FreeFormatDestroy(runSeqFF, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - - end subroutine SetRunSequence - - !----------------------------------------------------------------------------- - -end module esmxDriver - !============================================================================== ! ESMX application !============================================================================== @@ -332,7 +13,7 @@ program ESMX use ESMF use NUOPC - use esmxDriver, only: driverSS => SetServices + use ESMX_Driver, only: driverSS => SetServices implicit none @@ -399,7 +80,7 @@ program ESMX endif ! Create the esmx driver - driver = ESMF_GridCompCreate(name="esmxDriver", config=config, rc=rc) + driver = ESMF_GridCompCreate(name="ESMX_Driver", config=config, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=FILENAME)) & From 7a789662033355c5beee653fa2cc284f9348ca9f Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Tue, 6 Sep 2022 17:28:45 -0700 Subject: [PATCH 170/266] use pytest markers throughout ESMPy for NetCDF, PIO and MPI support --- src/addon/ESMPy/examples/exampletest.py | 77 +++--- src/addon/ESMPy/examples/exampletestdryrun.py | 2 +- .../ESMPy/examples/grid_locstream_regrid.py | 6 +- .../ESMPy/examples/locstream_grid_regrid.py | 6 +- .../ESMPy/examples/mesh_locstream_regrid.py | 8 +- src/addon/ESMPy/pyproject.toml | 10 +- src/addon/ESMPy/src/esmpy/api/constants.py | 3 + src/addon/ESMPy/src/esmpy/api/field.py | 4 - src/addon/ESMPy/src/esmpy/api/regrid.py | 5 - .../ESMPy/src/esmpy/interface/cbindings.py | 6 +- .../ESMPy/src/esmpy/interface/loadESMF.py | 14 +- src/addon/ESMPy/src/esmpy/test/base.py | 32 +-- .../src/esmpy/test/test_api/test_field.py | 89 ++----- .../src/esmpy/test/test_api/test_grid.py | 38 ++- .../src/esmpy/test/test_api/test_locstream.py | 6 +- .../src/esmpy/test/test_api/test_mesh.py | 149 ++++-------- .../src/esmpy/test/test_api/test_regrid.py | 230 +++++------------- .../ESMPy/src/esmpy/test/test_api/test_vm.py | 4 +- .../ESMPy/src/esmpy/test/test_cbindings.py | 2 +- src/addon/ESMPy/src/esmpy/util/decorators.py | 32 ++- src/addon/ESMPy/src/esmpy/util/exceptions.py | 4 + 21 files changed, 270 insertions(+), 457 deletions(-) diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/exampletest.py index e3325578ef..97e9607a13 100644 --- a/src/addon/ESMPy/examples/exampletest.py +++ b/src/addon/ESMPy/examples/exampletest.py @@ -6,11 +6,15 @@ import pytest -from esmpy.test.base import TestBase, attr, SkipTest +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO import esmpy.api.constants as constants +from esmpy.api.esmpymanager import Manager class TestExamples(TestBase): + mg = Manager(debug=True) + # '0' in the name is so it is run first def test_0_examples_dryrun(self): from esmpy.util.cache_data import cache_data_files @@ -19,67 +23,54 @@ def test_0_examples_dryrun(self): def test_helloworld(self): from . import hello_world - # ESMF IO does not work in mpiuni mode + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_read(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import field_read + from . import field_read # only example, not in documentation + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_peridim_mask(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import grid_create_peridim_mask + from . import grid_create_peridim_mask + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_locstream_regrid(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import grid_locstream_regrid + from . import grid_locstream_regrid + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_locstream_grid_regrid(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import locstream_grid_regrid + from . import locstream_grid_regrid + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_locstream_regrid(self): from . import mesh_locstream_regrid - # ESMF IO does not work in mpiuni mode + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_read_write_weight_file(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import read_write_weight_file + from . import read_write_weight_file - # ESMF IO does not work in mpiuni mode + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_regrid_from_file(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import regrid_from_file + from . import regrid_from_file + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_ugrid_latlon_regrid(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import ugrid_latlon_regrid + from . import ugrid_latlon_regrid + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_ungridded_dimension_regrid(self): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise SkipTest('ESMF must be built with MPI for test') - else: - from . import ungridded_dimension_regrid - - # # ESMF IO does not work in mpiuni mode - # def test_cubed_sphere_to_mesh_regrid(self): - # if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - # raise SkipTest('ESMF must be built with MPI for test') - # else: - # from . import cubed_sphere_to_mesh_regrid + from . import ungridded_dimension_regrid + + # this will currently never run because it isn't yet possible to run pytest with mpiexec + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(mg.pet_count!=6, reason="test must be run with 6 cores") + def test_cubed_sphere_to_mesh_regrid(self): + from . import cubed_sphere_to_mesh_regrid # # datafile missing from repo # def test_tripole_regrid(self): diff --git a/src/addon/ESMPy/examples/exampletestdryrun.py b/src/addon/ESMPy/examples/exampletestdryrun.py index 7e8e5e304b..348f08431a 100644 --- a/src/addon/ESMPy/examples/exampletestdryrun.py +++ b/src/addon/ESMPy/examples/exampletestdryrun.py @@ -6,7 +6,7 @@ import pytest -from esmpy.test.base import TestBase, attr +from esmpy.test.base import TestBase class TestExamplesDryrun(TestBase): diff --git a/src/addon/ESMPy/examples/grid_locstream_regrid.py b/src/addon/ESMPy/examples/grid_locstream_regrid.py index 5c2b6e3720..a9d58b139f 100644 --- a/src/addon/ESMPy/examples/grid_locstream_regrid.py +++ b/src/addon/ESMPy/examples/grid_locstream_regrid.py @@ -14,7 +14,6 @@ import esmpy.util.helpers as helpers import esmpy.api.constants as constants -from esmpy.test.base import SkipTest # This call enables debug logging esmpy.Manager(debug=True) @@ -25,10 +24,7 @@ if esmpy.pet_count() == 1: locstream = create_locstream_spherical_16(coord_sys=coord_sys, domask=domask) else: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('processor count must be 4 or 1 for this example') - else: - locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) + locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) grid1 = "examples/data/ll1deg_grid.nc" grid = esmpy.Grid(filename=grid1, filetype=esmpy.FileFormat.SCRIP) diff --git a/src/addon/ESMPy/examples/locstream_grid_regrid.py b/src/addon/ESMPy/examples/locstream_grid_regrid.py index 159fcac2d4..7a53c1273f 100644 --- a/src/addon/ESMPy/examples/locstream_grid_regrid.py +++ b/src/addon/ESMPy/examples/locstream_grid_regrid.py @@ -14,7 +14,6 @@ import esmpy.util.helpers as helpers import esmpy.api.constants as constants -from esmpy.test.base import TestBase, attr, SkipTest # This call enables debug logging esmpy.Manager(debug=True) @@ -28,10 +27,7 @@ if esmpy.pet_count() == 1: locstream = create_locstream_spherical_16(coord_sys=coord_sys, domask=domask) else: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('processor count must be 4 or 1 for this example') - else: - locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) + locstream = create_locstream_spherical_16_parallel(coord_sys=coord_sys, domask=domask) # create a field srcfield = esmpy.Field(locstream, name='srcfield') diff --git a/src/addon/ESMPy/examples/mesh_locstream_regrid.py b/src/addon/ESMPy/examples/mesh_locstream_regrid.py index e0841d06ca..69dfb6bc02 100644 --- a/src/addon/ESMPy/examples/mesh_locstream_regrid.py +++ b/src/addon/ESMPy/examples/mesh_locstream_regrid.py @@ -5,7 +5,6 @@ import esmpy.util.helpers as helpers import esmpy.api.constants as constants -from esmpy.test.base import TestBase, attr, SkipTest # This call enables debug logging # esmpy.Manager(debug=True) @@ -16,11 +15,8 @@ mesh, _, _, _, _, _ = mesh_create_5() locstream = create_locstream_16() else: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('processor count must be 4 or 1 for this example') - else: - mesh, _, _, _, _ = mesh_create_5_parallel() - locstream = create_locstream_16_parallel() + mesh, _, _, _, _ = mesh_create_5_parallel() + locstream = create_locstream_16_parallel() # create a field srcfield = esmpy.Field(mesh, name='srcfield')#, meshloc=esmpy.MeshLoc.ELEMENT) diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml index 00e35c5c30..7478d31a21 100644 --- a/src/addon/ESMPy/pyproject.toml +++ b/src/addon/ESMPy/pyproject.toml @@ -25,14 +25,12 @@ starting_version = "8.4.0" # this is a backup for pip <= 22.0 where git-versioni [tool.dynamic] version = "placeholder" # this is a placeholder for the version pulled with git-versioning - [tool.setuptools.packages.find] where = ["src"] -exclude = ["doc*", "examples*", "test*"] +exclude = ["doc*"] [tool.pytest.ini_options] -markers = [ - "dryrun: marks a function that will only download test data files (deselect with '-m \"not parallel\"')", - "parallel: marks a test which requires mpi (deselect with '-m \"not parallel\"')", - "serial: marks a test which should be run on one core (deselect with '-m \"not serial\"')" +testpaths = [ + "src/esmpy/test/test_api", + "examples/exampletest.py", ] diff --git a/src/addon/ESMPy/src/esmpy/api/constants.py b/src/addon/ESMPy/src/esmpy/api/constants.py index 4094e2901e..52791233da 100644 --- a/src/addon/ESMPy/src/esmpy/api/constants.py +++ b/src/addon/ESMPy/src/esmpy/api/constants.py @@ -41,6 +41,9 @@ # ESMF_NETCDF _ESMF_NETCDF = False +# ESMF_NETCDF +_ESMF_PIO = False + # ESMF_COMM _ESMF_COMM = None _ESMF_COMM_MPIUNI = -1 diff --git a/src/addon/ESMPy/src/esmpy/api/field.py b/src/addon/ESMPy/src/esmpy/api/field.py index 9704a419ed..978251c104 100755 --- a/src/addon/ESMPy/src/esmpy/api/field.py +++ b/src/addon/ESMPy/src/esmpy/api/field.py @@ -385,10 +385,6 @@ def read(self, filename, variable, timeslice=None): :param int timeslice: The number of timeslices to read. """ - import esmpy.api.constants as constants - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - raise ImportError("Field.Read() requires PIO and does not work if ESMF has not been built with MPI support") - assert (type(filename) is str) assert (type(variable) is str) diff --git a/src/addon/ESMPy/src/esmpy/api/regrid.py b/src/addon/ESMPy/src/esmpy/api/regrid.py index b63f6f59ca..d5d608425a 100644 --- a/src/addon/ESMPy/src/esmpy/api/regrid.py +++ b/src/addon/ESMPy/src/esmpy/api/regrid.py @@ -143,11 +143,6 @@ def __init__(self, srcfield=None, dstfield=None, filename=None, rh_filename=None # Write weights to file if requested. if not isinstance(filename, type(None)): - if constants._ESMF_COMM == constants._ESMF_COMM_MPIUNI: - msg = "Regrid(filename) requires PIO and does not work if ESMF has " \ - "not been built with MPI support" - raise ImportError(msg) - self._routehandle = ESMP_FieldRegridStoreFile( srcfield, dstfield, diff --git a/src/addon/ESMPy/src/esmpy/interface/cbindings.py b/src/addon/ESMPy/src/esmpy/interface/cbindings.py index b15f247102..b0499f19d0 100644 --- a/src/addon/ESMPy/src/esmpy/interface/cbindings.py +++ b/src/addon/ESMPy/src/esmpy/interface/cbindings.py @@ -9,7 +9,7 @@ import sys import esmpy.api.constants as constants -from esmpy.util.decorators import deprecated, netcdf, beta +from esmpy.util.decorators import * from esmpy.interface.loadESMF import _ESMF @@ -1209,6 +1209,7 @@ def ESMP_MeshCreate(parametricDim, spatialDim, coordSys=None): OptionalNamedConstant, Py3Char] +@pio @netcdf def ESMP_MeshCreateFromFile(filename, fileTypeFlag, convertToDual=None, addUserArea=None, @@ -1942,6 +1943,7 @@ def ESMP_FieldPrint(field): Py3Char, ct.c_uint, ct.c_uint] +@pio @netcdf def ESMP_FieldRead(field, filename, variablename, timeslice, iofmt=1): #TODO: C doc says it defaults to NETCDF(1), but actually defaults to BIN(0) @@ -2160,6 +2162,8 @@ def ESMP_FieldRegridStore(srcField, OptionalBool, OptionalField, OptionalField] +@pio +@netcdf def ESMP_FieldRegridStoreFile(srcField, dstField, filename, srcMaskValues=None, dstMaskValues=None, regridmethod=None, diff --git a/src/addon/ESMPy/src/esmpy/interface/loadESMF.py b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py index 803134ccc4..bf791c0c4d 100644 --- a/src/addon/ESMPy/src/esmpy/interface/loadESMF.py +++ b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py @@ -29,6 +29,7 @@ # TODO: look for various dependecies in the ESMF build log # - NetCDF +# - PIO # - LAPACK # - mpirun # use this information to set variables that can be checked at beginning @@ -42,7 +43,8 @@ esmfabi = None esmfcomm = None esmfversion = None - netcdf = [False, False] + netcdf = False + pio = False use_inmem_factors = False for line in MKFILE: @@ -53,9 +55,7 @@ elif 'ESMF_ABI:' in line: esmfabi = line.split(":")[1] elif 'ESMF_NETCDF:' in line: - netcdf[0] = True - elif 'ESMF_PIO:' in line: - netcdf[1] = True + netcdf = True elif 'ESMF_COMM:' in line: esmfcomm = line.split(":")[1] elif 'ESMF_VERSION_STRING=' in line: @@ -93,9 +93,13 @@ raise ValueError("Unrecognized ESMF_ABI setting!") # set _ESMF_NETCDF -if np.any(netcdf): +if netcdf: constants._ESMF_NETCDF = True +# set _ESMF_PIO +if "mpiuni" not in esmfcomm: + constants._ESMF_PIO = True + # set _ESMF_COMM if "mpiuni" in esmfcomm: constants._ESMF_COMM = constants._ESMF_COMM_MPIUNI diff --git a/src/addon/ESMPy/src/esmpy/test/base.py b/src/addon/ESMPy/src/esmpy/test/base.py index 2d655206dc..1bfcd785e7 100644 --- a/src/addon/ESMPy/src/esmpy/test/base.py +++ b/src/addon/ESMPy/src/esmpy/test/base.py @@ -1,15 +1,24 @@ import unittest import numpy as np -import esmpy from esmpy.util.itester import iter_product_keywords -from unittest import SkipTest - class TestBase(unittest.TestCase): + # mg = None + def __init__(self, *args, **kwds): super(TestBase, self).__init__(*args, **kwds) + # @classmethod + # def setUpClass(cls): + # import esmpy + # cls.mg = esmpy.Manager(debug = True) + # cls.mg.test_exhaustive = False + # + # @classmethod + # def tearDownClass(cls): + # del cls.mg + def assertNumpyAll(self, arr1, arr2, check_fill_value_dtype=True, check_arr_dtype=True): """ :type arr1: :class:`numpy.ndarray` @@ -97,20 +106,3 @@ def assertWeightFileIsRational(self, filename, src_size, dst_size): @staticmethod def iter_product_keywords(keywords, as_namedtuple=True): return iter_product_keywords(keywords, as_namedtuple=as_namedtuple) - - -def attr(*args, **kwargs): - """ - Decorator that adds attributes to classes or functions for use with the Attribute (-a) plugin. - - http://nose.readthedocs.org/en/latest/plugins/attrib.html - """ - - def wrap_ob(ob): - for name in args: - setattr(ob, name, True) - for name, value in kwargs.items(): - setattr(ob, name, value) - return ob - - return wrap_ob diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py index 8f46dd69de..c02e2012e2 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py @@ -6,7 +6,7 @@ from esmpy import * from esmpy.interface.cbindings import * -from esmpy.test.base import TestBase, attr, SkipTest +from esmpy.test.base import TestBase from esmpy.util.mesh_utilities import mesh_create_50, mesh_create_50_parallel @@ -72,7 +72,7 @@ def test_meta_del(self): del (self.field) assert (not hasattr(self, 'field')) - @pytest.mark.serial + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_numpy_funcs(self): field = self.make_field(np.array([10, 10], dtype=np.int32)) @@ -98,8 +98,8 @@ def test_numpy_funcs(self): - @pytest.mark.serial @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def _field_create_2d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -148,8 +148,8 @@ def _field_create_2d_grid(self): raise ValueError( "The following combinations of parameters failed to create a proper Field: " + str(fail)) - @pytest.mark.serial @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def _field_create_3d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -201,15 +201,8 @@ def _field_create_3d_grid(self): "The following combinations of parameters failed to create a proper Field: " + str(len(fail))) @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def _field_create_2d_mesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - keywords = dict( meshloc=[MeshLoc.NODE, MeshLoc.ELEMENT], typekind_field=[None, TypeKind.I4, TypeKind.I8, TypeKind.R4, TypeKind.R8], @@ -223,7 +216,7 @@ def _field_create_2d_mesh(self): try: # create mesh mesh = None - if parallel: + if (pet_count == 4): mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord = \ mesh_create_50_parallel() else: @@ -284,17 +277,10 @@ def create_field(gml, name): return field + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_uniqueness(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if (pet_count() == 4): mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -315,7 +301,7 @@ def test_field_uniqueness(self): assert (field.struct.ptr != field2.struct.ptr) - @pytest.mark.serial + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_area(self): grid = Grid(np.array([3, 4]), staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER], coord_sys=CoordSys.SPH_DEG, num_peri_dims=1, @@ -351,7 +337,7 @@ def test_field_area(self): assert(np.all(field.data == field2.data)) - + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_locstream_mask(self): # LocStream creation and simple validation locstream = LocStream(5, name="Test LocStream") @@ -404,18 +390,13 @@ def test_field_extradims_grid(self): field2.data[...] = 10 self.examine_field_attributes(field2) - + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_extradims_mesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - + + print("Pet count {}".format(pet_count())) + mesh = None - if parallel: + if (pet_count() == 4): mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -431,7 +412,7 @@ def test_field_extradims_mesh(self): field2.data[...] = 10 self.examine_field_attributes(field2) - @pytest.mark.serial + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_grid(self): typekind = TypeKind.R8 grid = Grid(np.array([100, 100]), coord_sys=CoordSys.CART, @@ -471,18 +452,10 @@ def test_field_slice_grid(self): assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) # slicing is disabled in parallel - @pytest.mark.serial + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_mesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() > 1: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -510,7 +483,7 @@ def test_field_slice_mesh(self): assert (field2.grid.size[0] == 5) assert (field3.grid.size[0] == 2) - @pytest.mark.serial + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_grid_extraindices(self): n = 10 grid = Grid(np.array([n,n]), coord_sys=CoordSys.CART, staggerloc=StaggerLoc.CENTER) @@ -548,23 +521,9 @@ def test_field_slice_grid_extraindices(self): assert (field2.grid.upper_bounds[0].tolist() == [5, 5]) assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) - @pytest.mark.serial + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def disable_est_field_slice_mesh_extraindices(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - mesh = None - if parallel: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ - mesh_create_50_parallel() - else: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ - mesh_create_50() + mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord = mesh_create_50() field = Field(mesh, typekind=TypeKind.R8, meshloc=MeshLoc.NODE, ndbounds=[5, 2]) @@ -572,9 +531,9 @@ def disable_est_field_slice_mesh_extraindices(self): for i in range(5): for j in range(2): - field[:, :, i, j] = i + j + field.data[:, i, j] = i + j - field2 = field[0:5, 0:2, 0:1] + field2 = field[0:4, 0:1, 0:1] self.examine_field_attributes(field2) field3 = field2[2:4, 1:2, 0:1] @@ -584,7 +543,7 @@ def disable_est_field_slice_mesh_extraindices(self): assert field2.data.shape == (5, 2, 1) assert field3.data.shape == (2, 1, 1) - @pytest.mark.serial + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_reshape(self): field = self.make_field(np.array([10, 10], dtype=np.int32), ndbounds=False) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py index f8183b48ef..3186877b5a 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py @@ -6,7 +6,8 @@ import esmpy from esmpy import * from esmpy.interface.cbindings import * -from esmpy.test.base import TestBase, attr +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF import numpy as np import os @@ -179,8 +180,8 @@ def test_grid_periodic(self): grid,_,_ = self.make_grid_periodic() self.examine_grid_attributes(grid) - @pytest.mark.serial @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_grid_create_2d(self): keywords = dict( # periodic specifies all valid combos of [pole_kind, num_peri_dims, periodic_dim, pole_dim] @@ -225,8 +226,8 @@ def test_grid_create_2d(self): raise ValueError( "The following combinations of Grid parameters failed to create a proper Grid: " + str(fail)) - @pytest.mark.serial @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_grid_create_3d(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -297,7 +298,7 @@ def test_grid_create_cubed_sphere(self): grid.destroy() # grid2.destroy() - @pytest.mark.serial + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_grid_slice_2d(self): grid = self.make_grid_2d() @@ -317,7 +318,7 @@ def test_grid_slice_2d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1] - @pytest.mark.serial + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_grid_slice_2d_corners(self): grid = self.make_grid_2d() @@ -348,7 +349,7 @@ def test_grid_slice_2d_corners(self): assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] - @pytest.mark.serial + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_grid_slice_3d(self): grid = self.make_grid_3d() @@ -368,7 +369,7 @@ def test_grid_slice_3d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1, 2) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1, 2] - @pytest.mark.serial + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_grid_slice_3d_corners(self): grid = self.make_grid_3d() @@ -403,7 +404,7 @@ def test_grid_slice_3d_corners(self): assert grid3.coords[cvf][0].shape == (3, 2, 3) assert grid3.upper_bounds[cvf].tolist() == [3, 2, 3] - @pytest.mark.serial + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_grid_slice_periodic(self): grid, x, y = self.make_grid_periodic() @@ -429,7 +430,8 @@ def test_grid_slice_periodic(self): assert grid3.coords[StaggerLoc.CORNER][0].shape == (3, 2) assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] - @pytest.mark.serial + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_slice_grid_created_from_file_scrip(self): reg_decomp = [pet_count(), 1] try: @@ -628,6 +630,7 @@ def test_grid_area_3D(self): area[:] = areavals assert(np.all(area[...] == 12*np.ones([10, 20, 30]))) + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_gridspec1D(self): esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid = Grid(filename=os.path.join(esmfdir, "test/data/gridspec1Dcoords.nc"), @@ -636,6 +639,7 @@ def test_grid_create_from_file_gridspec1D(self): self.examine_grid_attributes(grid) + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip(self): reg_decomp = [pet_count(), 1] try: @@ -646,6 +650,7 @@ def test_grid_create_from_file_scrip(self): except: raise NameError('grid_create_from_file_scrip failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.BALANCED], @@ -658,6 +663,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): except: raise NameError('grid_create_from_file_scrip_balanced_balanced failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTFIRST], @@ -670,6 +676,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): except: raise NameError('grid_create_from_file_scrip_balanced_restfirst failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTLAST], @@ -683,6 +690,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): raise NameError('grid_create_from_file_scrip_balanced_restlast failed!') @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.CYCLIC], @@ -695,6 +703,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): except: raise NameError('grid_create_from_file_scrip_balanced_cyclic failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.BALANCED], @@ -707,6 +716,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): except: raise NameError('grid_create_from_file_scrip_restfirst_balanced failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTFIRST], @@ -719,6 +729,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): except: raise NameError('grid_create_from_file_scrip_restfirst_restfirst failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTLAST], @@ -732,6 +743,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): raise NameError('grid_create_from_file_scrip_restfirst_restlast failed!') @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.CYCLIC], @@ -744,6 +756,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): except: raise NameError('grid_create_from_file_scrip_restfirst_cyclic failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.BALANCED], @@ -756,6 +769,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): except: raise NameError('grid_create_from_file_scrip_restlast_balanced failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTFIRST], @@ -768,6 +782,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): except: raise NameError('grid_create_from_file_scrip_restlast_restfirst failed!') + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTLAST], @@ -781,6 +796,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): raise NameError('grid_create_from_file_scrip_restlast_restlast failed!') @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.CYCLIC], @@ -794,6 +810,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): raise NameError('grid_create_from_file_scrip_restlast_cyclic failed!') @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.BALANCED], @@ -807,6 +824,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): raise NameError('grid_create_from_file_scrip_cyclic_balanced failed!') @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTFIRST], @@ -820,6 +838,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): raise NameError('grid_create_from_file_scrip_cyclic_restfirst failed!') @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTLAST], @@ -833,6 +852,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): raise NameError('grid_create_from_file_scrip_cyclic_restlast failed!') @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_cyclic(self): reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.CYCLIC], diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py index c1b1dbf508..b455acbc04 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py @@ -5,12 +5,14 @@ from esmpy import * from esmpy.interface.cbindings import * -from esmpy.test.base import TestBase, attr +from esmpy.test.base import TestBase import pytest class TestLocStream(TestBase): + mg = Manager(debug=True) + def test_create(self): # LocStream creation and simple validation locstream = LocStream(5, name="Test LocStream") @@ -52,7 +54,7 @@ def test_copy(self): assert np.all(l2["ESMF:X"] == [0, 1, 2, 3, 4]) - @pytest.mark.serial + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_slice(self): locstream = LocStream(5, name="Test LocStream") diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py index 7ca0a9c9aa..8d97691b76 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py @@ -10,7 +10,8 @@ import esmpy from esmpy import * -from esmpy.test.base import TestBase, attr, SkipTest +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO from esmpy.util.mesh_utilities import * class TestMesh(TestBase): @@ -47,17 +48,11 @@ def check_mesh(self, mesh, nodeCoord, nodeOwner, elemCoord=None): # this call fails if nodes and elements have not been added first # mesh.free_memory() + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_5(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_5_parallel() else: @@ -66,17 +61,11 @@ def test_mesh_5(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_10(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_10_parallel() else: @@ -85,17 +74,11 @@ def test_mesh_10(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -104,22 +87,16 @@ def test_mesh_50(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_moab(self): - # set this mesh to be created with the MOAB backend mg = Manager() mg.set_moab() elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -135,16 +112,10 @@ def test_mesh_50_moab(self): assert (mg.moab == False) + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_ngons(self): parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: @@ -153,17 +124,11 @@ def test_mesh_50_ngons(self): self.check_mesh(mesh, nodeCoord, nodeOwner) + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_mask_area(self): elemCoord = None parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn, elemMask, elemArea = \ mesh_create_50_parallel(domask=True, doarea=True) else: @@ -176,32 +141,23 @@ def test_mesh_50_mask_area(self): self.assertNumpyAll(mesh.area, elemArea) + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_mesh_create_from_file_scrip(self): - try: - esmfdir = os.path.dirname(inspect.getfile(esmpy)) - mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), filetype=FileFormat.SCRIP) - except: - raise NameError('mesh_create_from_file_scrip failed!') + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_mesh_create_from_file_esmfmesh(self): - try: - esmfdir = os.path.dirname(inspect.getfile(esmpy)) - mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), filetype=FileFormat.ESMFMESH) - except: - raise NameError('mesh_create_from_file_scrip failed!') + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_copy(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: @@ -214,21 +170,9 @@ def test_mesh_copy(self): self.check_mesh(mesh2, nodeCoord, nodeOwner) # slicing is disabled in parallel - @pytest.mark.serial + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_mesh_slicing(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - if parallel: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ - mesh_create_5_pentahexa_parallel() - else: - mesh, nodeCoord, nodeOwner, elemType, elemConn = \ + mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_5_pentahexa() mesh2 = mesh[0:5] @@ -250,15 +194,14 @@ def test_mesh_slicing(self): assert mesh3.size == [2, None] assert mesh3.size_owned == [2, None] - @pytest.mark.serial + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_slice_mesh_created_from_file_scrip(self): - try: - esmfdir = os.path.dirname(inspect.getfile(esmpy)) - mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), - filetype=FileFormat.SCRIP, - convert_to_dual=True) - except: - raise NameError('mesh_create_from_file_scrip failed!') + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), + filetype=FileFormat.SCRIP, + convert_to_dual=True) mesh2 = mesh[0:5] @@ -273,14 +216,13 @@ def test_slice_mesh_created_from_file_scrip(self): assert mesh2.size == [5, None] assert mesh2.size_owned == [5, None] - @pytest.mark.serial + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_slice_mesh_created_from_file_esmfmesh(self): - try: - esmfdir = os.path.dirname(inspect.getfile(esmpy)) - mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), - filetype=FileFormat.ESMFMESH) - except: - raise NameError('mesh_create_from_file_esmfmesh failed!') + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), + filetype=FileFormat.ESMFMESH) mesh2 = mesh[0:5] @@ -295,17 +237,16 @@ def test_slice_mesh_created_from_file_esmfmesh(self): assert mesh2.size_owned == [5, None] - @pytest.mark.serial @pytest.mark.xfail + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") #TODO: remove expected failure once we have a smaller data file with mesh element coordinates to use # TODO: have to define slicing for mesh element coordinates as well.. def test_slice_mesh_created_from_file_elem_coords(self): - try: - esmfdir = os.path.dirname(inspect.getfile(esmpy)) - mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne30np4-t2.nc"), - filetype=FileFormat.SCRIP) - except: - raise NameError('mesh_create_from_file_elem_coords failed!') + esmfdir = os.path.dirname(inspect.getfile(esmpy)) + mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne30np4-t2.nc"), + filetype=FileFormat.SCRIP) mesh2 = mesh[0:5] diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py index d25f712cc4..3a6e1ffefe 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py @@ -7,7 +7,8 @@ import os from esmpy import * -from esmpy.test.base import TestBase, attr, SkipTest +from esmpy.test.base import TestBase +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO from esmpy.util.field_utilities import compare_fields from esmpy.util.grid_utilities import * from esmpy.util.mesh_utilities import * @@ -15,6 +16,9 @@ class TestRegrid(TestBase): + mg = Manager(debug=True) + mg.test_exhaustive = False + def run_regridding(srcfield, dstfield, srcfracfield, dstfracfield): # This is for documentation. Do not modify. ''' @@ -81,7 +85,8 @@ def test_field_regrid(self): line_type=LineType.CART, factors=False) _ = rh(srcfield, dstfield) - @pytest.mark.serial + @pytest.mark.skipif(constants._ESMF_USE_INMEM_FACTORS, reason="compiler does not support in-memory weights") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_regrid_factor_retrieval(self): # Test retrieving factors from a route handle. @@ -132,17 +137,11 @@ def test_field_regrid_factor_retrieval(self): keywords = dict(deep_copy=[False, True], as_dict=[False, True]) for k in self.iter_product_keywords(keywords): - try: - rh = Regrid(srcfield, dstfield, - regrid_method=RegridMethod.BILINEAR, - line_type=LineType.CART, factors=True, - create_rh=False, - unmapped_action=UnmappedAction.IGNORE) - except RuntimeError: - if constants._ESMF_USE_INMEM_FACTORS: - raise - else: - raise SkipTest("compiler does not support in-memory weights") + rh = Regrid(srcfield, dstfield, + regrid_method=RegridMethod.BILINEAR, + line_type=LineType.CART, factors=True, + create_rh=False, + unmapped_action=UnmappedAction.IGNORE) _ = rh(srcfield, dstfield) fl, fil, fdict = [None] * 3 # Reset at each loop @@ -184,7 +183,8 @@ def test_field_regrid_factor_retrieval(self): rh.destroy() - @pytest.mark.parallel + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_file1(self): mgr = Manager() @@ -238,7 +238,8 @@ def test_field_regrid_file1(self): if os.path.isfile(path): os.remove(path) - @pytest.mark.parallel + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_file2(self): mgr = Manager() filename = 'esmpy_test_field_regrid_file2.nc' @@ -309,9 +310,10 @@ def test_field_regrid_file2(self): if os.path.isfile(path): os.remove(path) - @pytest.mark.parallel + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") # remove this test for 8.2.0 due to unexplained segv - def tet_field_regrid_file_withaux(self): + def test_field_regrid_file_withaux(self): import os DD = os.path.join(os.getcwd(), "test/data") if not os.path.isdir(DD): @@ -374,7 +376,8 @@ def tet_field_regrid_file_withaux(self): if os.path.isfile(path): os.remove(path) - @pytest.mark.parallel + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_file3(self): mgr = Manager() filename = 'esmpy_test_field_from_file.nc' @@ -468,8 +471,6 @@ def test_field_regrid_file3(self): if os.path.isfile(path): os.remove(path) - - @pytest.mark.parallel def test_field_regrid_file4(self): mgr = Manager() filename = 'routehandlefile.nc' @@ -564,17 +565,10 @@ def test_field_regrid_file4(self): if os.path.isfile(path): os.remove(path) + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_gridmesh(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -608,18 +602,10 @@ def test_field_regrid_gridmesh(self): rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.CONSERVE) dstfield = rh(srcfield, dstfield) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_zeroregion(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -655,7 +641,8 @@ def test_field_regrid_zeroregion(self): if dstfield.grid.mask[StaggerLoc.CENTER][i, j] == 0: assert(dstfield[i, j] == 0) - @pytest.mark.parallel + @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") + @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_field_regrid_zeroregion_select_ndbounds(self): # Test zero region select during a sparse matrix multiplication # having undistributed dimensions. @@ -707,18 +694,10 @@ def test_field_regrid_zeroregion_select_ndbounds(self): if os.path.exists(filename): os.remove(filename) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_area(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - mesh = None - if parallel: + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -749,16 +728,7 @@ def test_field_regrid_area(self): if (dstarea.data[i] != 0.25): assert (dstarea.data[i] == 0.125) - @pytest.mark.parallel def test_field_regrid_periodic(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - # create a grid srcgrid = grid_create_from_bounds_periodic(60, 30, corners=True, domask=True) dstgrid = grid_create_from_bounds_periodic(55, 28, corners=True) @@ -799,7 +769,6 @@ def test_field_regrid_periodic(self): self.assertAlmostEqual(meanrel, 0.0016447124122954575) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel def test_grid_grid_3d_bilinear_cartesian(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -829,7 +798,6 @@ def test_grid_grid_3d_bilinear_cartesian(self): self.assertAlmostEqual(meanrel, 0.00215601743167) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel def test_grid_grid_3d_bilinear_spherical(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -859,7 +827,6 @@ def test_grid_grid_3d_bilinear_spherical(self): self.assertAlmostEqual(meanrel, 0.00061587737764545617) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel def test_grid_grid_regrid_csrv_mask_3D(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -900,7 +867,6 @@ def test_grid_grid_regrid_csrv_mask_3D(self): self.assertAlmostEqual(meanrel, 0.0021560174316746865) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel def test_grid_grid_regrid_csrv_mask(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -942,7 +908,6 @@ def test_grid_grid_regrid_csrv_mask(self): self.assertAlmostEqual(meanrel, 0.0024803189848013785) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel def test_grid_grid_regrid_csrv_2nd_mask(self): # RO: This test creates the same Grid on every processor, it could be improved @@ -984,7 +949,6 @@ def test_grid_grid_regrid_csrv_2nd_mask(self): self.assertAlmostEqual(meanrel, 0.0020296891000258252) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel def test_grid_grid_regrid_srcmask_types(self): # NOTE: this tests an old issue where the items of a grid were not properly set when # the grid coord_typekind differed from the field typekind. @@ -1030,18 +994,10 @@ def test_grid_grid_regrid_srcmask_types(self): self.assertAlmostEqual(meanrel, 0.0024803189848013785) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_csrv_mask(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn, elemMask, elemArea = \ mesh_create_50_parallel(domask=True, doarea=True) else: @@ -1088,18 +1044,10 @@ def test_grid_mesh_regrid_csrv_mask(self): self.assertAlmostEqual(meanrel, 0.038806630051265847) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_csrv(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1144,21 +1092,13 @@ def test_grid_mesh_regrid_csrv(self): self.assertAlmostEqual(meanrel, 0.037733241800767432) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_mask(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a grid + # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, domask=True) - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1189,21 +1129,13 @@ def test_grid_mesh_regrid_mask(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a grid + # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1233,21 +1165,13 @@ def test_grid_mesh_regrid(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_extrapolation(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1280,21 +1204,13 @@ def test_field_regrid_extrapolation(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_extrapolation_creepfill(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) - # create a Mesh - if parallel: + mesh = None + if pet_count == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_parallel() else: @@ -1325,18 +1241,11 @@ def test_field_regrid_extrapolation_creepfill(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_mesh_regrid(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create two unique Mesh objects - if parallel: + srcmesh = None + dstmesh = None + if pet_count() == 4: srcmesh, nodeCoordSrc, nodeOwnerSrc, elemTypeSrc, elemConnSrc = \ mesh_create_50_parallel() dstmesh, nodeCoordDst, nodeOwnerDst, elemTypeDst, elemConnDst = \ @@ -1385,18 +1294,10 @@ def test_mesh_mesh_regrid(self): self.assertAlmostEqual(meanrel, 0.037109375) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def est_grid_mesh_pentatri_regrid_csrv(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: @@ -1444,11 +1345,8 @@ def est_grid_mesh_pentatri_regrid_csrv(self): assert (meanrel < 10E-2) assert (csrvrel < 10E-14) - # TODO: this test is disable, I don't remember why + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def est_grid_mesh_pentatri_regrid_csrv_simple(self): - if esmpy.pet_count() > 1: - raise NameError('This test can only be run in serial!') - # create a Mesh mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_4_ngons() @@ -1494,18 +1392,10 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): assert (meanrel < 10E-2) assert (csrvrel < 10E-14) - @pytest.mark.parallel + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_pentatri_regrid_bilinear(self): - parallel = False - if pet_count() > 1: - parallel = True - - if parallel: - if constants._ESMF_MPIRUN_NP != 4: - raise SkipTest('This test must be run with 4 processors.') - - # create a Mesh - if parallel: + mesh = None + if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_50_ngons_parallel() else: diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py index 4f3a544a18..3be54d4fd5 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py @@ -4,12 +4,11 @@ from esmpy import * from esmpy.interface.cbindings import * -from esmpy.test.base import TestBase, attr +from esmpy.test.base import TestBase import pytest class TestVM(TestBase): - @pytest.mark.parallel def test_vm_broadcast(self): mg = Manager() @@ -29,7 +28,6 @@ def test_vm_broadcast(self): mg.barrier() - @pytest.mark.parallel def test_vm_reduce(self): send = np.ones(4, dtype=np.float64) recv = np.zeros(4, dtype=np.float64) diff --git a/src/addon/ESMPy/src/esmpy/test/test_cbindings.py b/src/addon/ESMPy/src/esmpy/test/test_cbindings.py index 30185967c2..deb06fce9a 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_cbindings.py +++ b/src/addon/ESMPy/src/esmpy/test/test_cbindings.py @@ -8,7 +8,7 @@ from esmpy import * from esmpy.interface.cbindings import * -from esmpy.test.base import TestBase, attr +from esmpy.test.base import TestBase import numpy as np diff --git a/src/addon/ESMPy/src/esmpy/util/decorators.py b/src/addon/ESMPy/src/esmpy/util/decorators.py index c6ceea769c..38eb52631d 100644 --- a/src/addon/ESMPy/src/esmpy/util/decorators.py +++ b/src/addon/ESMPy/src/esmpy/util/decorators.py @@ -9,8 +9,8 @@ import warnings import functools -from esmpy.api.constants import LogKind, _ESMF_NETCDF -from esmpy.util.exceptions import NetCDFMissing +from esmpy.api.constants import LogKind, _ESMF_NETCDF, _ESMF_PIO +from esmpy.util.exceptions import NetCDFMissing, PIOMissing def beta(func): '''This is a decorator that can be used to mark functions @@ -73,3 +73,31 @@ def new_func(*args, **kwargs): raise NetCDFMissing("This function requires ESMF to have been built with NetCDF.") return new_func + +def pio(func): + '''This is a decorator that can be used to error out of functions + if PIO is not available. (e.g. if ESMF was built using ESMF_COMM=mpiuni).''' + + @functools.wraps(func) + def new_func(*args, **kwargs): + from esmpy.api.constants import _ESMF_PIO + + if _ESMF_PIO: + return func(*args, **kwargs) + else: + raise PIOMissing("This function requires ESMF to have been built with PIO.") + + return new_func + +def PETx4(func): + '''This is a decorator that can be used to error out of functions + if execution does not have 4 cores available.''' + + @functools.wraps(func) + def new_func(*args, **kwargs): + if esmpy.pet_count() == 4: + return func(*args, **kwargs) + else: + raise PETx4NotSatisfied("This function requires 4 core execution.") + + return new_func diff --git a/src/addon/ESMPy/src/esmpy/util/exceptions.py b/src/addon/ESMPy/src/esmpy/util/exceptions.py index 3924539904..206eaae900 100644 --- a/src/addon/ESMPy/src/esmpy/util/exceptions.py +++ b/src/addon/ESMPy/src/esmpy/util/exceptions.py @@ -18,6 +18,10 @@ class NetCDFMissing(ESMPyException): """ESMF was not built with the NetCDF package.""" pass +class PIOMissing(ESMPyException): + """ESMF was not built with PIO support.""" + pass + class MethodNotImplemented(ESMPyException): """Raised when an unimplemented method is called.""" pass From 16ad4eac47c077c35a05313c52d4bb2d1e931d55 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 6 Sep 2022 18:14:25 -0700 Subject: [PATCH 171/266] - Restructure for split program and driver. - Support NUOPC External Driver API. --- src/addon/ESMX/CMakeLists.txt | 27 +--- src/addon/ESMX/Driver/CMakeLists.txt | 28 ++++ src/addon/ESMX/{ => Driver}/ESMX_Driver.F90 | 149 +++++++++++++----- .../ESMX/{ => Driver}/cmake/FindESMF.cmake | 0 src/addon/ESMX/{ => Driver}/esmxGen.py | 0 5 files changed, 139 insertions(+), 65 deletions(-) create mode 100644 src/addon/ESMX/Driver/CMakeLists.txt rename src/addon/ESMX/{ => Driver}/ESMX_Driver.F90 (69%) rename src/addon/ESMX/{ => Driver}/cmake/FindESMF.cmake (100%) rename src/addon/ESMX/{ => Driver}/esmxGen.py (100%) diff --git a/src/addon/ESMX/CMakeLists.txt b/src/addon/ESMX/CMakeLists.txt index 8a63e98b67..e9f63e9039 100644 --- a/src/addon/ESMX/CMakeLists.txt +++ b/src/addon/ESMX/CMakeLists.txt @@ -1,37 +1,12 @@ cmake_minimum_required(VERSION 3.5.2) enable_language(Fortran) -# Where to look for Find.cmake files -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) - -# Find ESMF -find_package(ESMF 8.4.0 REQUIRED) - -# Set compilers per ESMFMKFILE -set(CMAKE_CXX_COMPILER ${ESMF_CXXCOMPILER}) -set(CMAKE_Fortran_COMPILER ${ESMF_F90COMPILER}) +add_subdirectory(Driver) # Specific project settings project(ESMX VERSION 0.1.0) add_executable(esmx esmx.F90) -target_link_libraries(esmx PRIVATE ESMF) install(TARGETS esmx) target_include_directories(esmx PUBLIC ${PROJECT_BINARY_DIR}) - -# Generate comp*.* files from esmxBuild.yaml -find_package(Python 3 COMPONENTS Interpreter REQUIRED) -execute_process(COMMAND ${Python_EXECUTABLE} - ${CMAKE_CURRENT_LIST_DIR}/esmxGen.py --ifile ./esmxBuild.yaml --odir ${CMAKE_CURRENT_BINARY_DIR} - RESULT_VARIABLE ret) -if(ret EQUAL "1") - message( FATAL_ERROR "esmxGen.py failed processing esmxBuild.yaml") -endif() - -# Specify driver dependency -add_library(esmx_driver ESMX_Driver.F90) -target_include_directories(esmx_driver PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -target_link_libraries(esmx_driver PRIVATE ESMF) target_link_libraries(esmx PUBLIC esmx_driver) -# Include compList.txt which in turn includes component libraries -include(${CMAKE_CURRENT_BINARY_DIR}/compList.txt) diff --git a/src/addon/ESMX/Driver/CMakeLists.txt b/src/addon/ESMX/Driver/CMakeLists.txt new file mode 100644 index 0000000000..c25e31d0e9 --- /dev/null +++ b/src/addon/ESMX/Driver/CMakeLists.txt @@ -0,0 +1,28 @@ +# Where to look for Find.cmake files +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +# Find ESMF +find_package(ESMF 8.4.0 REQUIRED) + +# Set compilers per ESMFMKFILE +set(CMAKE_CXX_COMPILER ${ESMF_CXXCOMPILER}) +set(CMAKE_Fortran_COMPILER ${ESMF_F90COMPILER}) +set(CMAKE_CXX_COMPILER ${ESMF_CXXCOMPILER} PARENT_SCOPE) +set(CMAKE_Fortran_COMPILER ${ESMF_F90COMPILER} PARENT_SCOPE) + +# Specify driver dependency +add_library(esmx_driver ESMX_Driver.F90) +target_include_directories(esmx_driver PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +target_link_libraries(esmx_driver PUBLIC ESMF) + +# Generate comp*.* files from esmxBuild.yaml +find_package(Python 3 COMPONENTS Interpreter REQUIRED) +execute_process(COMMAND ${Python_EXECUTABLE} + ${CMAKE_CURRENT_LIST_DIR}/esmxGen.py --ifile ./esmxBuild.yaml --odir ${CMAKE_CURRENT_BINARY_DIR} + RESULT_VARIABLE ret) +if(ret EQUAL "1") + message( FATAL_ERROR "esmxGen.py failed processing esmxBuild.yaml") +endif() + +# Include compList.txt which in turn includes component libraries +include(${CMAKE_CURRENT_BINARY_DIR}/compList.txt) diff --git a/src/addon/ESMX/ESMX_Driver.F90 b/src/addon/ESMX/Driver/ESMX_Driver.F90 similarity index 69% rename from src/addon/ESMX/ESMX_Driver.F90 rename to src/addon/ESMX/Driver/ESMX_Driver.F90 index 3a59cd0ba7..6268f92dbc 100644 --- a/src/addon/ESMX/ESMX_Driver.F90 +++ b/src/addon/ESMX/Driver/ESMX_Driver.F90 @@ -80,15 +80,75 @@ subroutine SetModelServices(driver, rc) character(len=240) :: model type(ESMF_Info) :: info type(type_CompDef), allocatable :: CompDef(:) - logical :: inCompDef + logical :: inCompDef, isPresent - ! get the config - call ESMF_GridCompGet(driver, config=config, rc=rc) + ! see if config is present + call ESMF_GridCompGet(driver, configIsPresent=isPresent, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=FILENAME)) & return ! bail out + if (isPresent) then + ! get the config from component + call ESMF_GridCompGet(driver, config=config, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + else + ! attempt to open config from default file "esmxRun.config" + config = ESMF_ConfigCreate(rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call ESMF_ConfigLoadFile(config, filename="esmxRun.config", rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + ! set it on the component + call ESMF_GridCompSet(driver, config=config, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + ! also ingest ESMX_attributes + ff = NUOPC_FreeFormatCreate(config, label="ESMX_attributes::", & + relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_CompAttributeIngest(driver, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + ff = NUOPC_FreeFormatCreate(config, label="ALLCOMP_attributes::", & + relaxedflag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_CompAttributeIngest(driver, ff, addFlag=.true., rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call NUOPC_FreeFormatDestroy(ff, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + endif + ! determine the generic component labels componentCount = ESMF_ConfigGetLen(config, label="ESMX_component_list:", & rc=rc) @@ -228,49 +288,60 @@ subroutine SetModelServices(driver, rc) deallocate(compLabels) - ! read startTimeString and stopTimeString from config - call ESMF_ConfigGetAttribute(config, startTimeString, label="startTime:", & - rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call ESMF_ConfigGetAttribute(config, stopTimeString, label="stopTime:", & - rc=rc) + ! check if driver clock is set (by parent) + call ESMF_GridCompGet(driver, clockIsPresent=isPresent, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=FILENAME)) & + file=__FILE__)) & return ! bail out - ! set the driver clock startTime/stopTime - call ESMF_TimeSet(startTime, timeString=startTimeString, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out - call ESMF_TimeSet(stopTime, timeString=stopTimeString, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out + if (.not.isPresent) then + ! set clock according to config - ! set the driver clock default timeStep = stopTime - startTime - ! use with runSequence @*, - ! or overwritten with explicit timeStep in runSequence - timeStep = stopTime - startTime + ! read startTimeString and stopTimeString from config + call ESMF_ConfigGetAttribute(config, startTimeString, label="startTime:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call ESMF_ConfigGetAttribute(config, stopTimeString, label="stopTime:", & + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out - internalClock = ESMF_ClockCreate(name="Application Clock", & - timeStep=timeStep, startTime=startTime, stopTime=stopTime, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out + ! set the driver clock startTime/stopTime + call ESMF_TimeSet(startTime, timeString=startTimeString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + call ESMF_TimeSet(stopTime, timeString=stopTimeString, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out - call ESMF_GridCompSet(driver, clock=internalClock, rc=rc) - if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & - line=__LINE__, & - file=FILENAME)) & - return ! bail out + ! set the driver clock default timeStep = stopTime - startTime + ! use with runSequence @*, + ! or overwritten with explicit timeStep in runSequence + timeStep = stopTime - startTime + + internalClock = ESMF_ClockCreate(name="Application Clock", & + timeStep=timeStep, startTime=startTime, stopTime=stopTime, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + + call ESMF_GridCompSet(driver, clock=internalClock, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & + line=__LINE__, & + file=FILENAME)) & + return ! bail out + endif rc = ESMF_SUCCESS diff --git a/src/addon/ESMX/cmake/FindESMF.cmake b/src/addon/ESMX/Driver/cmake/FindESMF.cmake similarity index 100% rename from src/addon/ESMX/cmake/FindESMF.cmake rename to src/addon/ESMX/Driver/cmake/FindESMF.cmake diff --git a/src/addon/ESMX/esmxGen.py b/src/addon/ESMX/Driver/esmxGen.py similarity index 100% rename from src/addon/ESMX/esmxGen.py rename to src/addon/ESMX/Driver/esmxGen.py From a185290d11bd799c92a62c1d9eb3da3a6015f601 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 7 Sep 2022 10:15:48 -0700 Subject: [PATCH 172/266] add pytest-json-report, cleap up pytest markers for netcdf and pio dependencies --- src/addon/ESMPy/Makefile | 2 + src/addon/ESMPy/pyproject.toml | 4 +- .../regrid_from_file/run_regrid_from_file.py | 27 +++++----- .../run_regrid_from_file_dryrun.py | 6 +-- .../src/esmpy/test/test_api/test_array.py | 5 +- .../src/esmpy/test/test_api/test_field.py | 30 +++++------- .../src/esmpy/test/test_api/test_grid.py | 49 +++++++++++++------ .../src/esmpy/test/test_api/test_locstream.py | 5 +- .../src/esmpy/test/test_api/test_mesh.py | 1 - .../src/esmpy/test/test_api/test_regrid.py | 2 +- .../ESMPy/src/esmpy/test/test_api/test_vm.py | 5 +- 11 files changed, 74 insertions(+), 62 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 7eec02c873..e5d25fe110 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -10,6 +10,8 @@ clean: find . -name "*.vtk" -exec rm -f {} \; || : find . -name "*.pytest_cache" -exec rm -rf {} \; || : find . -name "*.python-version" -exec rm -f {} \; || : + find . -name "*__pycache__" -exec rm -rf {} \; || : + find . -name ".report.json" -exec rm -rf {} \; || : rm -rf src/esmpy/test/regrid_from_file/data || : rm -rf examples/data || : diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml index 7478d31a21..35590d6390 100644 --- a/src/addon/ESMPy/pyproject.toml +++ b/src/addon/ESMPy/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = [ "setuptools>=41", "wheel", "setuptools-git-versioning", ] +requires = [ "setuptools>=41", "wheel", "setuptools-git-versioning"] build-backend = "setuptools.build_meta" [project] @@ -12,6 +12,7 @@ license = {text = "University of Illinois-NCSA"} dependencies = [ "numpy", 'importlib-metadata; python_version<"3.8"', + "pytest-json-report" ] dynamic = ["version"] @@ -33,4 +34,5 @@ exclude = ["doc*"] testpaths = [ "src/esmpy/test/test_api", "examples/exampletest.py", + "src/esmpy/test/regrid_from_file/run_regrid_from_file.py", ] diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py index f8dca3a750..d1ce83e1f2 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py @@ -9,21 +9,24 @@ source mesh. """ +import pytest + import sys import os import traceback -import pytest -try: - import esmpy -except: - raise ImportError('The ESMF library cannot be found!') +from esmpy import * +from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR from esmpy.test.regrid_from_file.regrid_check import regrid_check from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file -# Start up esmpy. -mg = esmpy.Manager(debug=True) + +# Start up esmpy +mg = Manager(debug=True) + +if mg.pet_count == 1: + import esmpy.test.regrid_from_file.run_regrid_from_file_dryrun # Read the test case parameters from the control file. print('Reading control file...') @@ -32,20 +35,18 @@ # For each test case line from the control file parse the line and call # the test subroutine. +@pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") +@pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") @pytest.mark.parametrize('test_case', test_cases) def test_run_regrid_from_file(test_case): (src_fname, dst_fname, regrid_method, options, itrp_mean_err, itrp_max_err, csrv_err) = test_case test_str = 'Regrid %s to %s as %s with %s itrp_mean_err=%f, itrp_max_err=%f, and csrv_err=%f' % (src_fname, dst_fname, regrid_method, options, itrp_mean_err, itrp_max_err, csrv_err) - if esmpy.local_pet() == 0: + if local_pet() == 0: print ('\n' + test_str) src_fname_full = os.path.join(DATA_SUBDIR, src_fname) dst_fname_full = os.path.join(DATA_SUBDIR, dst_fname) # run the data file retrieval and regridding through try/except - try: - correct = regrid_check(src_fname_full, dst_fname_full, regrid_method, + regrid_check(src_fname_full, dst_fname_full, regrid_method, options, itrp_mean_err, itrp_max_err, csrv_err) - except: - print ("PET {}: Regridding ERROR:{}".format(esmpy.local_pet(), correct)) - traceback.print_exc(file=sys.stdout) diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py index 21eb31c7d1..b0e4d9b896 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py @@ -40,8 +40,4 @@ def cache_data_files_for_test_cases(test_cases): test_cases = read_control_file() # Retrieve the data files needed for the test cases from the remote server. -try: - status_ok = cache_data_files_for_test_cases(test_cases) -except: - print ("Cache data file error: {}\n".format(status_ok)) - traceback.print_exc(file=sys.stdout) +cache_data_files_for_test_cases(test_cases) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py index 3e4f1dfb43..69cf12f670 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_array.py @@ -3,12 +3,13 @@ unit test file """ +import pytest +import numpy as np + from esmpy import * from esmpy.interface.cbindings import * from esmpy.test.base import TestBase -import numpy as np - # TODO: test view casting # TODO: demonstrate Fortran reordering in reshape call diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py index c02e2012e2..f7314c34bc 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py @@ -5,7 +5,6 @@ import pytest from esmpy import * -from esmpy.interface.cbindings import * from esmpy.test.base import TestBase from esmpy.util.mesh_utilities import mesh_create_50, mesh_create_50_parallel @@ -72,7 +71,7 @@ def test_meta_del(self): del (self.field) assert (not hasattr(self, 'field')) - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_numpy_funcs(self): field = self.make_field(np.array([10, 10], dtype=np.int32)) @@ -99,7 +98,7 @@ def test_numpy_funcs(self): @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def _field_create_2d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -149,7 +148,7 @@ def _field_create_2d_grid(self): "The following combinations of parameters failed to create a proper Field: " + str(fail)) @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def _field_create_3d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -201,7 +200,7 @@ def _field_create_3d_grid(self): "The following combinations of parameters failed to create a proper Field: " + str(len(fail))) @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def _field_create_2d_mesh(self): keywords = dict( meshloc=[MeshLoc.NODE, MeshLoc.ELEMENT], @@ -277,7 +276,7 @@ def create_field(gml, name): return field - @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_uniqueness(self): mesh = None if (pet_count() == 4): @@ -301,7 +300,7 @@ def test_field_uniqueness(self): assert (field.struct.ptr != field2.struct.ptr) - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_area(self): grid = Grid(np.array([3, 4]), staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER], coord_sys=CoordSys.SPH_DEG, num_peri_dims=1, @@ -337,7 +336,7 @@ def test_field_area(self): assert(np.all(field.data == field2.data)) - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_locstream_mask(self): # LocStream creation and simple validation locstream = LocStream(5, name="Test LocStream") @@ -390,11 +389,8 @@ def test_field_extradims_grid(self): field2.data[...] = 10 self.examine_field_attributes(field2) - @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_extradims_mesh(self): - - print("Pet count {}".format(pet_count())) - mesh = None if (pet_count() == 4): mesh, nodeCoord, nodeOwner, elemType, elemConn = \ @@ -412,7 +408,7 @@ def test_field_extradims_mesh(self): field2.data[...] = 10 self.examine_field_attributes(field2) - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_slice_grid(self): typekind = TypeKind.R8 grid = Grid(np.array([100, 100]), coord_sys=CoordSys.CART, @@ -452,7 +448,7 @@ def test_field_slice_grid(self): assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) # slicing is disabled in parallel - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_slice_mesh(self): mesh = None if pet_count() > 1: @@ -483,7 +479,7 @@ def test_field_slice_mesh(self): assert (field2.grid.size[0] == 5) assert (field3.grid.size[0] == 2) - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_slice_grid_extraindices(self): n = 10 grid = Grid(np.array([n,n]), coord_sys=CoordSys.CART, staggerloc=StaggerLoc.CENTER) @@ -521,7 +517,7 @@ def test_field_slice_grid_extraindices(self): assert (field2.grid.upper_bounds[0].tolist() == [5, 5]) assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def disable_est_field_slice_mesh_extraindices(self): mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord = mesh_create_50() @@ -543,7 +539,7 @@ def disable_est_field_slice_mesh_extraindices(self): assert field2.data.shape == (5, 2, 1) assert field3.data.shape == (2, 1, 1) - @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") + @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_reshape(self): field = self.make_field(np.array([10, 10], dtype=np.int32), ndbounds=False) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py index 3186877b5a..2452e046c0 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py @@ -3,17 +3,17 @@ grid unit test file """ -import esmpy +import pytest +import numpy as np + +import os +import inspect + from esmpy import * from esmpy.interface.cbindings import * from esmpy.test.base import TestBase from esmpy.api.constants import _ESMF_NETCDF -import numpy as np -import os -import inspect -import pytest - class TestGrid(TestBase): mg = Manager(debug=True) @@ -141,28 +141,28 @@ def make_grid_periodic(self): assert lon.size == 100 assert lat.size == 100 - grid = esmpy.Grid(np.array([lon.size, lat.size], 'int32'), + grid = Grid(np.array([lon.size, lat.size], 'int32'), num_peri_dims=1, staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER]) - gridXCorner = grid.get_coords(0, staggerloc=esmpy.StaggerLoc.CORNER) - lon_par = lon[grid.lower_bounds[esmpy.StaggerLoc.CORNER][0]:grid.upper_bounds[esmpy.StaggerLoc.CORNER][0]] + gridXCorner = grid.get_coords(0, staggerloc=StaggerLoc.CORNER) + lon_par = lon[grid.lower_bounds[StaggerLoc.CORNER][0]:grid.upper_bounds[StaggerLoc.CORNER][0]] gridXCorner[...] = lon_par.reshape((lon_par.size, 1)) - gridYCorner = grid.get_coords(1, staggerloc=esmpy.StaggerLoc.CORNER) + gridYCorner = grid.get_coords(1, staggerloc=StaggerLoc.CORNER) lat_corner = np.linspace(90, -90, lat.size + 1) - lat_par = lat_corner[grid.lower_bounds[esmpy.StaggerLoc.CORNER][1]:grid.upper_bounds[esmpy.StaggerLoc.CORNER][1]] + lat_par = lat_corner[grid.lower_bounds[StaggerLoc.CORNER][1]:grid.upper_bounds[StaggerLoc.CORNER][1]] gridYCorner[...] = lat_par.reshape((1, lat_par.size)) offset_lon = 360. / lon.size / 2. lon -= offset_lon gridXCenter = grid.get_coords(0) - lon_par = lon[grid.lower_bounds[esmpy.StaggerLoc.CENTER][0]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][0]] + lon_par = lon[grid.lower_bounds[StaggerLoc.CENTER][0]:grid.upper_bounds[StaggerLoc.CENTER][0]] gridXCenter[...] = lon_par.reshape((lon_par.size, 1)) offset_lat = 180. / (lat.size) / 2. lat = np.linspace(90 - offset_lat, -90 + offset_lat, lat.size) gridYCenter = grid.get_coords(1) - lat_par = lat[grid.lower_bounds[esmpy.StaggerLoc.CENTER][1]:grid.upper_bounds[esmpy.StaggerLoc.CENTER][1]] + lat_par = lat[grid.lower_bounds[StaggerLoc.CENTER][1]:grid.upper_bounds[StaggerLoc.CENTER][1]] gridYCenter[...] = lat_par.reshape((1, lat_par.size)) @@ -283,8 +283,6 @@ def test_grid_create_cubed_sphere(self): # [DecompFlag.DEFAULT, 6]], dtype=np.int32) # deLabelList = np.array([11,12,13,14,15,16], dtype=np.int32) - esmpy.Manager(debug=True) - grid = Grid(tilesize = 45, regDecompPTile = regDecompPTile, #decompFlagPTile = decompFlagPTile, #deLabelList = deLabelList, @@ -322,7 +320,7 @@ def test_grid_slice_2d(self): def test_grid_slice_2d_corners(self): grid = self.make_grid_2d() - grid.add_coords(staggerloc=esmpy.StaggerLoc.CORNER) + grid.add_coords(staggerloc=StaggerLoc.CORNER) grid_row = grid.get_coords(0, staggerloc=StaggerLoc.CORNER) grid_col = grid.get_coords(1, staggerloc=StaggerLoc.CORNER) @@ -433,6 +431,7 @@ def test_grid_slice_periodic(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_slice_grid_created_from_file_scrip(self): + import esmpy reg_decomp = [pet_count(), 1] try: esmfdir = os.path.dirname(inspect.getfile(esmpy)) @@ -632,6 +631,7 @@ def test_grid_area_3D(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_gridspec1D(self): + import esmpy esmfdir = os.path.dirname(inspect.getfile(esmpy)) grid = Grid(filename=os.path.join(esmfdir, "test/data/gridspec1Dcoords.nc"), filetype=FileFormat.GRIDSPEC, add_corner_stagger=True, @@ -641,6 +641,7 @@ def test_grid_create_from_file_gridspec1D(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip(self): + import esmpy reg_decomp = [pet_count(), 1] try: esmfdir = os.path.dirname(inspect.getfile(esmpy)) @@ -652,6 +653,7 @@ def test_grid_create_from_file_scrip(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.BALANCED], dtype=np.int32) @@ -665,6 +667,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_balanced(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTFIRST], dtype=np.int32) @@ -678,6 +681,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restfirst(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.RESTLAST], dtype=np.int32) @@ -692,6 +696,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_restlast(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.BALANCED, DecompFlag.CYCLIC], dtype=np.int32) @@ -705,6 +710,7 @@ def test_grid_create_from_file_scrip_decomp_balanced_cyclic(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.BALANCED], dtype=np.int32) @@ -718,6 +724,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_balanced(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTFIRST], dtype=np.int32) @@ -731,6 +738,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restfirst(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.RESTLAST], dtype=np.int32) @@ -745,6 +753,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_restlast(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTFIRST, DecompFlag.CYCLIC], dtype=np.int32) @@ -758,6 +767,7 @@ def test_grid_create_from_file_scrip_decomp_restfirst_cyclic(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.BALANCED], dtype=np.int32) @@ -771,6 +781,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_balanced(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTFIRST], dtype=np.int32) @@ -784,6 +795,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restfirst(self): @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.RESTLAST], dtype=np.int32) @@ -798,6 +810,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_restlast(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.RESTLAST, DecompFlag.CYCLIC], dtype=np.int32) @@ -812,6 +825,7 @@ def test_grid_create_from_file_scrip_decomp_restlast_cyclic(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.BALANCED], dtype=np.int32) @@ -826,6 +840,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_balanced(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTFIRST], dtype=np.int32) @@ -840,6 +855,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restfirst(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.RESTLAST], dtype=np.int32) @@ -854,6 +870,7 @@ def test_grid_create_from_file_scrip_decomp_cyclic_restlast(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_create_from_file_scrip_decomp_cyclic_cyclic(self): + import esmpy reg_decomp = [pet_count(), 1] decompflag = np.array([DecompFlag.CYCLIC, DecompFlag.CYCLIC], dtype=np.int32) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py index b455acbc04..7ec83755b9 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py @@ -3,12 +3,11 @@ locstream unit test file """ +import pytest + from esmpy import * -from esmpy.interface.cbindings import * from esmpy.test.base import TestBase -import pytest - class TestLocStream(TestBase): mg = Manager(debug=True) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py index 8d97691b76..41b87d4bb8 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py @@ -8,7 +8,6 @@ import os import inspect -import esmpy from esmpy import * from esmpy.test.base import TestBase from esmpy.api.constants import _ESMF_NETCDF, _ESMF_PIO diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py index 3a6e1ffefe..a42d0e8306 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py @@ -313,7 +313,7 @@ def test_field_regrid_file2(self): @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") # remove this test for 8.2.0 due to unexplained segv - def test_field_regrid_file_withaux(self): + def _field_regrid_file_withaux(self): import os DD = os.path.join(os.getcwd(), "test/data") if not os.path.isdir(DD): diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py index 3be54d4fd5..7fd61057b7 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py @@ -2,12 +2,11 @@ vm unit test file """ +import pytest + from esmpy import * -from esmpy.interface.cbindings import * from esmpy.test.base import TestBase -import pytest - class TestVM(TestBase): def test_vm_broadcast(self): mg = Manager() From f1b50ddf40746bebdfbe04a0b88f45bf37af8720 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 7 Sep 2022 15:45:36 -0600 Subject: [PATCH 173/266] remove old.setup.cfg --- src/addon/ESMPy/old.setup.cfg | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 src/addon/ESMPy/old.setup.cfg diff --git a/src/addon/ESMPy/old.setup.cfg b/src/addon/ESMPy/old.setup.cfg deleted file mode 100644 index 48cdbf3ff0..0000000000 --- a/src/addon/ESMPy/old.setup.cfg +++ /dev/null @@ -1,27 +0,0 @@ -[metadata] -name = ESMPy -description = ESMF Python interface -license = University of Illinois-NCSA -author = 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 -maintainer_email = esmf_support@ucar.edu -url = http://earthsystemmodeling.org/esmpy/ -obsoletes = ESMF -requires = numpy -python_requires = '>=3.7', - -[options] -zip_safe = False -include_package_data = True -package_dir= - =src -packages = find: -install_requires = - numpy - pytest - -[options.packages.find] -where=src -exclude = - doc* - examples* - test* From 24241cc3b20fcec985b3ae1b05ea8421495a73fe Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 7 Sep 2022 14:50:54 -0700 Subject: [PATCH 174/266] Update README.md Small changes in the text after review during core meeting. Also correction wrt ESMX_Driver separation. --- src/addon/ESMX/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/addon/ESMX/README.md b/src/addon/ESMX/README.md index 71bc0519c6..0ad590ad4b 100644 --- a/src/addon/ESMX/README.md +++ b/src/addon/ESMX/README.md @@ -4,9 +4,9 @@ ESMX is the **E**arth **S**ystem **M**odel e**X**ecutable layer. The ESMX layer is built on top of ESMF and NUOPC. ESMX user interfaces are typically implemented through configuration files. -The idea is to make it as simple as possible for a user to build, run, and test NUOPC based systems. The approach is supposed to be the same whether applied to a single component, or a fully coupled system of NUOPC-compliant components. +The idea is to make it as simple as possible for a user to build, run, and test NUOPC based systems. The approach implemented by ESMX is the same whether applied to a single component, or a fully coupled system of NUOPC-compliant components. -ESMX tries to unify, provide, and maintain those parts of NUOPC-based modeling systems that are common across most such implementations. This includes the top level application and driver code, parts of the build infrastructure, and tools to manage run configurations. +ESMX unifies, provides, and maintains those parts of NUOPC-based modeling systems that are common across most such implementations. This includes the top level application and driver code, parts of the build infrastructure, and tools to manage run configurations. The objectives of ESMX are: - **Simplification** of standing up new NUOPC-based systems. @@ -40,20 +40,20 @@ As shown above, building `esmx` has a dependency on file `esmxBuild.yaml`. This components: tawas: - config: TaWaS/tawas.cmake + cmake_config: TaWaS/tawas.cmake fort_module: tawas lumo: - config: Lumo/lumo.cmake + cmake_config: Lumo/lumo.cmake In this example two components are built into `esmx` explicitly. (Read about dynamically loading components from shared objects at run-time later.) Each component is given a name, here `tawas` and `lumo`. Components will be referred to by this *component-name* in the run-time configuration (esmxRun.config) discussed below. -Each component must define the `config` key, specifying a file that can be included by the CMake based `esmx` build. This file must specify three CMake elements: +Each component must define the `cmake_config` key, specifying a file that can be included by the CMake based `esmx` build. This file must specify three CMake elements: - `add_library(component-name ... )` - `set_target_properties(component-name ... )` -- `target_link_libraries(esmx PRIVATE component-name)` +- `target_link_libraries(esmx_driver PUBLIC component-name)` Here *component-name* is the name under which the component was defined in the `esmxBuild.yaml` file, here `tawas` or `lumo`. From 4bf9050978c301a1454afe5048caa042fa68c0a8 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 7 Sep 2022 15:51:24 -0600 Subject: [PATCH 175/266] ESMPy test script and targets for Cheyenne --- src/addon/ESMPy/Makefile | 28 ++++++++++++++++------------ src/addon/ESMPy/test_all.bash | 17 +++++++++++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 src/addon/ESMPy/test_all.bash diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index e5d25fe110..707e9dde4b 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -12,42 +12,46 @@ clean: find . -name "*.python-version" -exec rm -f {} \; || : find . -name "*__pycache__" -exec rm -rf {} \; || : find . -name ".report.json" -exec rm -rf {} \; || : + find . -name ".test" -exec rm -rf {} \; || : rm -rf src/esmpy/test/regrid_from_file/data || : rm -rf examples/data || : install: python3 -m pip install . +dryrun_examples: + python3 -m pytest -vs examples/exampletestdryrun.py + +dryrun_regrid_from_file: + python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py + +dryrun: dryrun_examples dryrun_regrid_from_file + +test: + bash test_all.bash + test_unit: - python3 -m pytest -m="not parallel" + python3 -m pytest -vs test_unit_parallel: - mpirun -n 4 python3 -m pytest -m="not serial" + mpiexec -n 4 python3 -vs test_examples: python3 -m pytest -vs examples/exampletest.py test_examples_parallel: - mpirun -n 4 python3 -m pytest -vs examples/exampletest.py + mpiexec -n 4 python3 -m pytest -vs examples/exampletest.py -test_examples_dryrun: - python3 -m pytest -vs examples/exampletestdryrun.py - test_regrid_from_file: python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file.py test_regrid_from_file_parallel: - mpirun -n 4 python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file.py - -test_regrid_from_file_dryrun: - python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py + mpiexec -n 4 python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file.py test_serial: test_unit test_examples test_regrid_from_file test_parallel: test_unit_parallel test_examples_parallel test_regrid_from_file_parallel -test_dryrun: test_examples_dryrun test_regrid_from_file_dryrun - test_all: test_unit test_unit_parallel test_examples test_examples_parallel test_regrid_from_file test_regrid_from_file_parallel uninstall: diff --git a/src/addon/ESMPy/test_all.bash b/src/addon/ESMPy/test_all.bash new file mode 100644 index 0000000000..cf55141a0f --- /dev/null +++ b/src/addon/ESMPy/test_all.bash @@ -0,0 +1,17 @@ +#!/bin/bash + +VERSION=$(python3 -c "import esmpy; print (esmpy.__version__)") + +echo "Testing ESMPy ${VERSION}" + +for NP in 1 4 6 +do + REPORT="esmpy${VERSION}-cheyenne-intelmpt-petx${NP}.test" + COMMAND="mpiexec -n ${NP} python3 -m pytest -vs --json-report --json-report-summary > $REPORT 2>&1"00 + echo ${COMMAND} + eval "${COMMAND}" + find . -name "*.ESMF_LogFile" -exec cat {} >> ${REPORT} \; + cat .report.json >> ${REPORT} +done + +echo "Report is in ${REPORT}" From 96ff82d56ae4b4013376983fa5fdf7b9c886f7b4 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 7 Sep 2022 15:01:39 -0700 Subject: [PATCH 176/266] Change from 'config' to 'cmake_config' in esmxBuild.yaml format - as per ESMF Core review. --- src/addon/ESMX/Driver/esmxGen.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/addon/ESMX/Driver/esmxGen.py b/src/addon/ESMX/Driver/esmxGen.py index caee22c41e..ea09a0af51 100755 --- a/src/addon/ESMX/Driver/esmxGen.py +++ b/src/addon/ESMX/Driver/esmxGen.py @@ -27,10 +27,10 @@ def create_compList(_dict, odir): comp_str = [comp for comp in od.keys()] f.write('set(COMPS {})\n\n'.format(' '.join(comp_str))) for k1, v1 in od.items(): - if 'config' in v1: - # only entires that have config field are considered + if 'cmake_config' in v1: + # only entires that have cmake_config field are considered f.write('# - auto-generated section for component: {}\n'.format(k1)) - configFile = os.path.join(os.getcwd(), v1['config']) + configFile = os.path.join(os.getcwd(), v1['cmake_config']) f.write('include({})\n\n'.format(configFile)) def create_compUse(_dict, odir): @@ -39,14 +39,14 @@ def create_compUse(_dict, odir): # loop through components and create use statements od = collections.OrderedDict(_dict['components'].items()) for k1, v1 in od.items(): - if 'config' in v1: - # only entires that have config field are considered + if 'cmake_config' in v1: + # only entires that have cmake_config field are considered if 'fort_module' in v1: # if fort_module field present, use it to identify fortran module f.write('use {}, only: {}SS => SetServices, {}SV => SetVM\n'.format(v1['fort_module'], k1, k1)) else: - # otherwise use step of the config name - f.write('use {}, only: {}SS => SetServices, {}SV => SetVM\n'.format(Path(v1['config']).stem, k1, k1)) + # otherwise use step of the cmake_config name + f.write('use {}, only: {}SS => SetServices, {}SV => SetVM\n'.format(Path(v1['cmake_config']).stem, k1, k1)) def create_compDef(_dict, odir): # open file @@ -55,8 +55,8 @@ def create_compDef(_dict, odir): i = 1 od = collections.OrderedDict(_dict['components'].items()) for k1, v1 in od.items(): - if 'config' in v1: - # only entires that have config field are considered + if 'cmake_config' in v1: + # only entires that have cmake_config field are considered f.write('CompDef({})%ssPtr => {}SS\n'.format(i, k1)) f.write('CompDef({})%svPtr => {}SV\n'.format(i, k1)) f.write('CompDef({})%name = "{}"\n'.format(i, k1)) From 830bda657844be68e93acfd48864aa53d8bd532b Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Wed, 7 Sep 2022 15:15:36 -0700 Subject: [PATCH 177/266] rename ESMPy example and regrid_from_file test files, add dryrun target and clean up dryruns --- src/addon/ESMPy/Makefile | 19 ++++++++++++------- src/addon/ESMPy/examples/exampletestdryrun.py | 15 --------------- .../{exampletest.py => test_examples.py} | 14 +++++++------- .../ESMPy/examples/test_examples_dryrun.py | 8 ++++++++ src/addon/ESMPy/pyproject.toml | 6 +++--- .../test/regrid_from_file/regrid_check.py | 4 ++-- ..._from_file.py => test_regrid_from_file.py} | 2 +- ...run.py => test_regrid_from_file_dryrun.py} | 2 +- .../src/esmpy/test/test_api/test_regrid.py | 18 +++++++++--------- src/addon/ESMPy/test_all.bash | 2 +- 10 files changed, 44 insertions(+), 46 deletions(-) delete mode 100644 src/addon/ESMPy/examples/exampletestdryrun.py rename src/addon/ESMPy/examples/{exampletest.py => test_examples.py} (93%) create mode 100644 src/addon/ESMPy/examples/test_examples_dryrun.py rename src/addon/ESMPy/src/esmpy/test/regrid_from_file/{run_regrid_from_file.py => test_regrid_from_file.py} (96%) rename src/addon/ESMPy/src/esmpy/test/regrid_from_file/{run_regrid_from_file_dryrun.py => test_regrid_from_file_dryrun.py} (95%) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 707e9dde4b..157e7c82db 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -5,25 +5,30 @@ clean: rm -rf dist || : find . -name "*.egg-info" -exec rm -rf {} \; || : find . -name "*.pyc" -exec rm -f {} \; || : - find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : find . -name "*.log" -exec rm -f {} \; || : find . -name "*.vtk" -exec rm -f {} \; || : find . -name "*.pytest_cache" -exec rm -rf {} \; || : find . -name "*.python-version" -exec rm -f {} \; || : find . -name "*__pycache__" -exec rm -rf {} \; || : + find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : find . -name ".report.json" -exec rm -rf {} \; || : find . -name ".test" -exec rm -rf {} \; || : rm -rf src/esmpy/test/regrid_from_file/data || : rm -rf examples/data || : +dust: + find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : + find . -name ".report.json" -exec rm -rf {} \; || : + find . -name ".test" -exec rm -rf {} \; || : + install: python3 -m pip install . dryrun_examples: - python3 -m pytest -vs examples/exampletestdryrun.py + python3 examples/test_examples_dryrun.py dryrun_regrid_from_file: - python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py + python3 src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py dryrun: dryrun_examples dryrun_regrid_from_file @@ -37,16 +42,16 @@ test_unit_parallel: mpiexec -n 4 python3 -vs test_examples: - python3 -m pytest -vs examples/exampletest.py + python3 -m pytest -vs examples/test_examples.py test_examples_parallel: - mpiexec -n 4 python3 -m pytest -vs examples/exampletest.py + mpiexec -n 4 python3 -m pytest -vs examples/test_examples.py test_regrid_from_file: - python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file.py + python3 -m pytest -vs src/esmpy/test/regrid_from_file/test_regrid_from_file.py test_regrid_from_file_parallel: - mpiexec -n 4 python3 -m pytest -vs src/esmpy/test/regrid_from_file/run_regrid_from_file.py + mpiexec -n 4 python3 -m pytest -vs src/esmpy/test/regrid_from_file/test_regrid_from_file.py test_serial: test_unit test_examples test_regrid_from_file diff --git a/src/addon/ESMPy/examples/exampletestdryrun.py b/src/addon/ESMPy/examples/exampletestdryrun.py deleted file mode 100644 index 348f08431a..0000000000 --- a/src/addon/ESMPy/examples/exampletestdryrun.py +++ /dev/null @@ -1,15 +0,0 @@ -# $Id$ - -""" -examples dryrun test file -""" - -import pytest - -from esmpy.test.base import TestBase - -class TestExamplesDryrun(TestBase): - - def test_examples_dryrun(self): - from esmpy.util.cache_data import cache_data_files - cache_data_files() diff --git a/src/addon/ESMPy/examples/exampletest.py b/src/addon/ESMPy/examples/test_examples.py similarity index 93% rename from src/addon/ESMPy/examples/exampletest.py rename to src/addon/ESMPy/examples/test_examples.py index 97e9607a13..94bdf1a6c9 100644 --- a/src/addon/ESMPy/examples/exampletest.py +++ b/src/addon/ESMPy/examples/test_examples.py @@ -11,15 +11,15 @@ import esmpy.api.constants as constants from esmpy.api.esmpymanager import Manager +# Start up esmpy +mg = Manager(debug=True) + +if mg.pet_count == 1: + from esmpy.util.cache_data import cache_data_files + cache_data_files() + class TestExamples(TestBase): - - mg = Manager(debug=True) - # '0' in the name is so it is run first - def test_0_examples_dryrun(self): - from esmpy.util.cache_data import cache_data_files - cache_data_files() - def test_helloworld(self): from . import hello_world diff --git a/src/addon/ESMPy/examples/test_examples_dryrun.py b/src/addon/ESMPy/examples/test_examples_dryrun.py new file mode 100644 index 0000000000..14319d7b86 --- /dev/null +++ b/src/addon/ESMPy/examples/test_examples_dryrun.py @@ -0,0 +1,8 @@ +# $Id$ + +""" +examples data dryrun +""" + +from esmpy.util.cache_data import cache_data_files +cache_data_files() diff --git a/src/addon/ESMPy/pyproject.toml b/src/addon/ESMPy/pyproject.toml index 35590d6390..91a8ecb838 100644 --- a/src/addon/ESMPy/pyproject.toml +++ b/src/addon/ESMPy/pyproject.toml @@ -11,8 +11,8 @@ requires-python = ">=3.7" license = {text = "University of Illinois-NCSA"} dependencies = [ "numpy", + "pytest-json-report", 'importlib-metadata; python_version<"3.8"', - "pytest-json-report" ] dynamic = ["version"] @@ -33,6 +33,6 @@ exclude = ["doc*"] [tool.pytest.ini_options] testpaths = [ "src/esmpy/test/test_api", - "examples/exampletest.py", - "src/esmpy/test/regrid_from_file/run_regrid_from_file.py", + "examples/test_examples.py", + "src/esmpy/test/regrid_from_file/test_regrid_from_file.py", ] diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py index 0714009da0..f0748021d8 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/regrid_check.py @@ -117,9 +117,9 @@ def run_regridding(srcfield, dstfield, src_mask, dst_mask, src_mask_vals = None dst_mask_vals = None if src_mask: - src_mask_vals = np.array([0]) + src_mask_vals = np.atleast_1d(np.array([0])) if dst_mask: - dst_mask_vals = np.array([0]) + dst_mask_vals = np.atleast_1d(np.array([0])) regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, src_mask_values=src_mask_vals, diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py similarity index 96% rename from src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py index d1ce83e1f2..37ac3e70da 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py @@ -26,7 +26,7 @@ mg = Manager(debug=True) if mg.pet_count == 1: - import esmpy.test.regrid_from_file.run_regrid_from_file_dryrun + import esmpy.test.regrid_from_file.test_regrid_from_file_dryrun # Read the test case parameters from the control file. print('Reading control file...') diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py similarity index 95% rename from src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py index b0e4d9b896..99d415aee6 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/run_regrid_from_file_dryrun.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py @@ -4,7 +4,7 @@ coordinate grid. Parses each line and retrieves the source and destination files from a remote server if they do not already exist locally. On parallel computers where the compute nodes do not have internet access, this script must -be run on the front-end machine before running run_regrid_from_file.py to do +be run on the front-end machine before running test_regrid_from_file.py to do the regridding. """ diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py index a42d0e8306..ba515571a9 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py @@ -632,7 +632,7 @@ def test_field_regrid_zeroregion(self): # regridding rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.CONSERVE, - dst_mask_values=np.array([0])) + dst_mask_values=np.atleast_1d(np.array([0]))) dstfield = rh(srcfield, dstfield, zero_region=Region.SELECT) # validate that the masked values were not zeroed out @@ -663,8 +663,8 @@ def test_field_regrid_zeroregion_select_ndbounds(self): # Regrid in-memory rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.BILINEAR, - src_mask_values=np.array([0]), - dst_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), + dst_mask_values=np.atleast_1d(np.array([0])), unmapped_action=UnmappedAction.IGNORE) _ = rh(srcfield, dstfield, zero_region=Region.SELECT) @@ -676,7 +676,7 @@ def test_field_regrid_zeroregion_select_ndbounds(self): dstfield.data[:] = -999 filename = '_esmf_test_weights_.nc' _ = Regrid(srcfield, dstfield, regrid_method=RegridMethod.BILINEAR, - src_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), unmapped_action=UnmappedAction.IGNORE, filename=filename) self.assertTrue(np.all(dstfield.data == -999)) @@ -748,7 +748,7 @@ def test_field_regrid_periodic(self): # run the ESMF regridding regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), regrid_method=esmpy.RegridMethod.CONSERVE, unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, @@ -887,7 +887,7 @@ def test_grid_grid_regrid_csrv_mask(self): # run the ESMF regridding regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), regrid_method=esmpy.RegridMethod.CONSERVE, unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, @@ -928,7 +928,7 @@ def test_grid_grid_regrid_csrv_2nd_mask(self): # run the ESMF regridding regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), regrid_method=esmpy.RegridMethod.CONSERVE_2ND, unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, @@ -1023,7 +1023,7 @@ def test_grid_mesh_regrid_csrv_mask(self): # run the ESMF regridding regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, - src_mask_values=np.array([0]), + src_mask_values=np.atleast_1d(np.array([0])), regrid_method=esmpy.RegridMethod.CONSERVE, unmapped_action=esmpy.UnmappedAction.ERROR, src_frac_field=srcfracfield, @@ -1116,7 +1116,7 @@ def test_grid_mesh_regrid_mask(self): # run the ESMF regridding regridSrc2Dst = esmpy.Regrid(srcfield, dstfield, - dst_mask_values=np.array([0]), + dst_mask_values=np.atleast_1d(np.array([0])), regrid_method=esmpy.RegridMethod.BILINEAR, unmapped_action=esmpy.UnmappedAction.IGNORE) dstfield = regridSrc2Dst(srcfield, dstfield) diff --git a/src/addon/ESMPy/test_all.bash b/src/addon/ESMPy/test_all.bash index cf55141a0f..a2aee0ce57 100644 --- a/src/addon/ESMPy/test_all.bash +++ b/src/addon/ESMPy/test_all.bash @@ -7,7 +7,7 @@ echo "Testing ESMPy ${VERSION}" for NP in 1 4 6 do REPORT="esmpy${VERSION}-cheyenne-intelmpt-petx${NP}.test" - COMMAND="mpiexec -n ${NP} python3 -m pytest -vs --json-report --json-report-summary > $REPORT 2>&1"00 + COMMAND="mpiexec -n ${NP} python3 -m pytest -vs --json-report --json-report-summary > $REPORT 2>&1" echo ${COMMAND} eval "${COMMAND}" find . -name "*.ESMF_LogFile" -exec cat {} >> ${REPORT} \; From bdbd5a0118f0930b5037a377e90eae2f9dbb850e Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 7 Sep 2022 16:04:55 -0700 Subject: [PATCH 178/266] Update README.md Start discussion of the ESMX_Driver layer. --- src/addon/ESMX/README.md | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/addon/ESMX/README.md b/src/addon/ESMX/README.md index 0ad590ad4b..a72bc18dbb 100644 --- a/src/addon/ESMX/README.md +++ b/src/addon/ESMX/README.md @@ -18,7 +18,7 @@ The objectives of ESMX are: One of the main features provided by ESMX is the *unified driver executable*. A good starting point to explore this feature is the [ESMX_AtmOcnProto](https://github.com/esmf-org/nuopc-app-prototypes/tree/develop/ESMX_AtmOcnProto) under the NUOPC prototype repository. -The default name of the unified driver executable built by ESMX is lower case `esmx`. This will be used for the remainder of this section to refer to the unfied driver executable. +The name of the unified driver executable built by ESMX is lower case `esmx`. This will be used for the remainder of this section to refer to the unfied driver executable. ### Project integration @@ -112,3 +112,41 @@ There are two options recognized when specifying the value of the `XXX_model` fi - First, if the value specified is recognized as a *component-name* provided by any of the components built into `esmx` during build-time, as specified by `esmxBuild.yaml`, the respective component is accessed via its Fortran module. - Second, if the value does not match a build-time dependency, it is assumed to correspond to a shared object. In that case the attempt is made to load the specified shared object at run-time, and to associate with the generic component label. +## The Unfied ESMX_Driver + +The ESMX layer provides access to the `ESMX_Driver` via the public NUOPC Driver API. This means that `ESMX_Driver` can be plugged into a larger NUOPC application as a standard NUOPC component, or alternatively be accessed through the [External NUOPC Interface](https://earthsystemmodeling.org/docs/nightly/develop/NUOPC_refdoc/node3.html#SECTION00038000000000000000). +A good starting point to explore this feature is the [ESMX_ExternalDriverAPIProto](https://github.com/esmf-org/nuopc-app-prototypes/tree/develop/ESMX_ExternalDriverAPIProto) under the NUOPC prototype repository. + +### Project integration + +The typical situation where `ESMX_Driver` comes into play is where a user application needs to access a NUOPC based system that uses the unified ESMX driver. Assuming the user application uses CMake, integration of ESMX is straight forward. All that is required is `add_subdirectory()` in the application's `CMakeLists.txt` file to add the `${ESMF_ESMXDIR}/Driver` directory, and make the application dependent on target `esmx_driver`. An example for a very simple application is shown: + + cmake_minimum_required(VERSION 3.5.2) + enable_language(Fortran) + + add_subdirectory(${ESMF_ESMXDIR}/Driver ./ESMX_Driver) + + # Specific project settings + project(ExternalDriverAPIProto VERSION 0.1.0) + add_executable(externalApp externalApp.F90) + install(TARGETS externalApp) + target_include_directories(externalApp PUBLIC ${PROJECT_BINARY_DIR}) + target_link_libraries(externalApp PUBLIC esmx_driver) + +The applcation can then be built as typically via cmake commands, only requiring that the `ESMF_ESMXDIR` variable is passed in. It can be convenient to wrap the cmake commands into a GNU Makefile, accessing the `ESMF_ESMXDIR` variable through the `ESMFMKFILE` mechanism. + + include $(ESMFMKFILE) + + build/externalApp: externalApp.F90 esmxBuild.yaml + cmake -Bbuild -DESMF_ESMXDIR=$(ESMF_ESMXDIR) + cmake --build ./build + +### esmxBuild.yaml and esmxRun.config + +The `esmx_driver` target defined by the `add_subdirectory(${ESMF_ESMXDIR}/Driver ./ESMX_Driver)` has a build-time dependency on the `esmxBuild.yaml` file already discussed under the [unfied driver executable section](#esmxbuildyaml). The identical file can be used when working on the `ESMX_Driver` level. + +The run-time configuration needed by `ESMX_Driver` can either be supplied by the user application, or alternatively default to `esmxRun.config`. The following rules apply: + + + + From 3ceb99b907fced94c751acc60a951c25e637bfb3 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Wed, 7 Sep 2022 17:44:06 -0600 Subject: [PATCH 179/266] Add tests of multi-tile Array and ArrayBundle writes and reads --- .../IO/tests/ESMF_IO_MultitileUTest.F90 | 249 ++++++++++++++++-- 1 file changed, 225 insertions(+), 24 deletions(-) diff --git a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 index 53504764fb..6113f249d6 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 @@ -45,35 +45,57 @@ program ESMF_IO_MultitileUTest character(ESMF_MAXSTR) :: name 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 - real(ESMF_KIND_R8), pointer :: data1(:,:), data2(:,:), data1Copy(:,:) + real(ESMF_KIND_R8), pointer :: field1Data(:,:), field2Data(:,:), field1CopyData(:,:) type(ESMF_FieldBundle) :: fieldBundle ! This field is not in the field bundle: type(ESMF_Field) :: field3 - real(ESMF_KIND_R8), pointer :: data3(:,:) + real(ESMF_KIND_R8), pointer :: field3Data(:,:) ! Fields used for reading: ! ! The following fields make up the field bundle: type(ESMF_Field) :: field1Read, field2Read, field1CopyRead - real(ESMF_KIND_R8), pointer :: data1Read(:,:), data2Read(:,:), data1CopyRead(:,:) + real(ESMF_KIND_R8), pointer :: field1ReadData(:,:), field2ReadData(:,:), field1CopyReadData(:,:) type(ESMF_FieldBundle) :: fieldBundleRead ! This field is not in the field bundle: type(ESMF_Field) :: field3Read - real(ESMF_KIND_R8), pointer :: data3Read(:,:) + 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 :: fileName = "ESMF_IO_MultitileUTest#.nc" + character(len=*), parameter :: fileNameFields = "ESMF_IO_MultitileUTestFields#.nc" + character(len=*), parameter :: fileNameArrays = "ESMF_IO_MultitileUTestArrays#.nc" character(len=*), parameter :: fileNameFail = "ESMF_IO_MultitileUTestFail#.nc" !------------------------------------------------------------------------ @@ -93,7 +115,7 @@ program ESMF_IO_MultitileUTest !NEX_UTest_Multi_Proc_Only write(name, *) "Write a FieldBundle with multi-tile fields" write(failMsg, *) "Did not return ESMF_SUCCESS" - call ESMF_FieldBundleWrite(fieldBundle, fileName=fileName, overwrite=.true., rc=rc) + call ESMF_FieldBundleWrite(fieldBundle, fileName=fileNameFields, overwrite=.true., rc=rc) #if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else @@ -106,7 +128,7 @@ program ESMF_IO_MultitileUTest !NEX_UTest_Multi_Proc_Only write(name, *) "Read a FieldBundle with multi-tile fields" write(failMsg, *) "Did not return ESMF_SUCCESS" - call ESMF_FieldBundleRead(fieldBundleRead, fileName=fileName, rc=rc) + call ESMF_FieldBundleRead(fieldBundleRead, fileName=fileNameFields, rc=rc) #if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else @@ -120,9 +142,9 @@ program ESMF_IO_MultitileUTest write(name, *) "Confirm that FieldBundle-read fields match originals" write(failMsg, *) "Some read-in fields differ from originals" allEqual = ( & - all(data1Read == data1) .and. & - all(data2Read == data2) .and. & - all(data1CopyRead == data1Copy)) + all(field1ReadData == field1Data) .and. & + all(field2ReadData == field2Data) .and. & + all(field1CopyReadData == field1CopyData)) #if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) call ESMF_Test(allEqual, name, failMsg, result, ESMF_SRCLINE) #else @@ -139,7 +161,7 @@ program ESMF_IO_MultitileUTest !EX_UTest_Multi_Proc_Only write(name, *) "Write a multi-tile Field to existing files" write(failMsg, *) "Did not return ESMF_SUCCESS" - call ESMF_FieldWrite(field3, fileName=fileName, overwrite=.true., rc=rc) + call ESMF_FieldWrite(field3, fileName=fileNameFields, overwrite=.true., rc=rc) #if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else @@ -152,7 +174,7 @@ program ESMF_IO_MultitileUTest !EX_UTest_Multi_Proc_Only write(name, *) "Read a multi-tile Field" write(failMsg, *) "Did not return ESMF_SUCCESS" - call ESMF_FieldRead(field3Read, fileName=fileName, rc=rc) + call ESMF_FieldRead(field3Read, fileName=fileNameFields, rc=rc) #if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) #else @@ -165,7 +187,7 @@ program ESMF_IO_MultitileUTest !EX_UTest_Multi_Proc_Only write(name, *) "Confirm that Field-read field matches original" write(failMsg, *) "Read-in field differs from original" - allEqual = all(data3Read == data3) + allEqual = all(field3ReadData == field3Data) #if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) call ESMF_Test(allEqual, name, failMsg, result, ESMF_SRCLINE) #else @@ -195,10 +217,93 @@ program ESMF_IO_MultitileUTest #endif !------------------------------------------------------------------------ - ! FIXME(wjs, 2022-08-26) Add tests of ArrayBundleWrite and ArrayWrite + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + write(name, *) "Create arrays for multitile IO tests" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call createArrays(rc) + call ESMF_Test((rc == ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE) + !------------------------------------------------------------------------ + + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + write(name, *) "Write an ArrayBundle with multi-tile arrays" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayBundleWrite(arrayBundle, fileName=fileNameArrays, overwrite=.true., rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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, *) "Read an ArrayBundle with multi-tile arrays" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayBundleRead(arrayBundleRead, fileName=fileNameArrays, rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 ArrayBundle-read arrays match originals" + write(failMsg, *) "Some read-in arrays differ from originals" + allEqual = ( & + all(array1ReadData == array1Data) .and. & + all(array2ReadData == array2Data)) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 + !------------------------------------------------------------------------ - ! FIXME(wjs, 2022-08-26) Add tests of ArrayBundleRead and ArrayRead; in - ! addition to checking rc, also check equality to the original fields + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + write(name, *) "Write a multi-tile Array to existing files" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayWrite(array3, fileName=fileNameArrays, overwrite=.true., rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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, *) "Read a multi-tile Array" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_ArrayRead(array3Read, fileName=fileNameArrays, rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 Array-read array matches original" + write(failMsg, *) "Read-in array differs from original" + allEqual = all(array3ReadData == array3Data) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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 + !------------------------------------------------------------------------ #endif ! ESMF_TESTEXHAUSTIVE @@ -242,36 +347,36 @@ subroutine createFields(rc) if (rc /= ESMF_SUCCESS) return call ESMF_FieldFill(field1, dataFillScheme='sincos', member=1, rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field1, farrayPtr=data1) + call ESMF_FieldGet(field1, farrayPtr=field1Data, rc=rc) if (rc /= ESMF_SUCCESS) return field1Read = ESMF_FieldCreate(grid6tile, arraySpec, name="field1", rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field1Read, farrayPtr=data1Read) + call ESMF_FieldGet(field1Read, farrayPtr=field1ReadData, rc=rc) if (rc /= ESMF_SUCCESS) return field2 = ESMF_FieldCreate(grid6tile, arraySpec, name="field2", rc=rc) if (rc /= ESMF_SUCCESS) return call ESMF_FieldFill(field2, dataFillScheme='sincos', member=2, rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field2, farrayPtr=data2) + call ESMF_FieldGet(field2, farrayPtr=field2Data, rc=rc) if (rc /= ESMF_SUCCESS) return field2Read = ESMF_FieldCreate(grid6tile, arraySpec, name="field2", rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field2Read, farrayPtr=data2Read) + call ESMF_FieldGet(field2Read, farrayPtr=field2ReadData, rc=rc) if (rc /= ESMF_SUCCESS) return field3 = ESMF_FieldCreate(grid6tile, arraySpec, name="field3", rc=rc) if (rc /= ESMF_SUCCESS) return call ESMF_FieldFill(field3, dataFillScheme='sincos', member=3, rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field3, farrayPtr=data3) + call ESMF_FieldGet(field3, farrayPtr=field3Data, rc=rc) if (rc /= ESMF_SUCCESS) return field3Read = ESMF_FieldCreate(grid6tile, arraySpec, name="field3", rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field3Read, farrayPtr=data3Read) + call ESMF_FieldGet(field3Read, farrayPtr=field3ReadData, rc=rc) if (rc /= ESMF_SUCCESS) return ! Create a copy of field1 that uses the same array, so we can test writing @@ -280,12 +385,12 @@ subroutine createFields(rc) if (rc /= ESMF_SUCCESS) return field1Copy = ESMF_FieldCreate(grid6tile, array1, name="field1Copy", rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field1Copy, farrayPtr=data1Copy) + call ESMF_FieldGet(field1Copy, farrayPtr=field1CopyData, rc=rc) if (rc /= ESMF_SUCCESS) return field1CopyRead = ESMF_FieldCreate(grid6tile, arraySpec, name="field1Copy", rc=rc) if (rc /= ESMF_SUCCESS) return - call ESMF_FieldGet(field1CopyRead, farrayPtr=data1CopyRead) + call ESMF_FieldGet(field1CopyRead, farrayPtr=field1CopyReadData, rc=rc) if (rc /= ESMF_SUCCESS) return fieldBundle = ESMF_FieldBundleCreate(name="fb", rc=rc) @@ -337,4 +442,100 @@ subroutine createSingleTileField(rc) end subroutine createSingleTileField + subroutine createArrays(rc) + ! Creates Arrays and ArrayBundles used by the tests in this module + integer, intent(out) :: rc + + ! Information for a 2-d, 3-tile array + integer :: minIndexPTile(2,3) + integer :: maxIndexPTile(2,3) + integer :: decompPTile(2,3) + + type(ESMF_ArraySpec) :: arraySpec + + !------------------------------------------------------------------------ + ! Set up 3-tile distgrid + !------------------------------------------------------------------------ + + minIndexPTile(:,1) = [11,1] + maxIndexPTile(:,1) = [20,10] + minIndexPTile(:,2) = [11,11] + maxIndexPTile(:,2) = [20,20] + minIndexPTile(:,3) = [1,11] + maxIndexPTile(:,3) = [10,20] + + ! Decomposition for 8 PEs: Tiles 1 and 3 each have 2 DEs (along different + ! dimensions); tile 2 has 4 DEs (2x2) + decompPTile(:,1) = [1,2] + decompPTile(:,2) = [2,2] + decompPTile(:,3) = [2,1] + + distgrid3tile = ESMF_DistGridCreate( & + minIndexPTile = minIndexPTile, & + maxIndexPTile = maxIndexPTile, & + regDecompPTile = decompPTile, & + rc = rc) + if (rc /= ESMF_SUCCESS) return + + !------------------------------------------------------------------------ + ! Create arrays on the 3-tile distgrid and associated array bundle + !------------------------------------------------------------------------ + + call ESMF_ArraySpecSet(arraySpec, typekind=ESMF_TYPEKIND_R8, rank=2, rc=rc) + if (rc /= ESMF_SUCCESS) return + + array1 = ESMF_ArrayCreate(distgrid3tile, arraySpec, name="array1", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(array1, farrayPtr=array1Data, rc=rc) + if (rc /= ESMF_SUCCESS) return + call fillArray(array1Data, 1) + + array1Read = ESMF_ArrayCreate(distgrid3tile, arraySpec, name="array1", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(array1Read, farrayPtr=array1ReadData, rc=rc) + if (rc /= ESMF_SUCCESS) return + + array2 = ESMF_ArrayCreate(distgrid3tile, arraySpec, name="array2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(array2, farrayPtr=array2Data, rc=rc) + if (rc /= ESMF_SUCCESS) return + call fillArray(array2Data, 2) + + array2Read = ESMF_ArrayCreate(distgrid3tile, arraySpec, name="array2", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(array2Read, farrayPtr=array2ReadData, rc=rc) + if (rc /= ESMF_SUCCESS) return + + array3 = ESMF_ArrayCreate(distgrid3tile, arraySpec, name="array3", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(array3, farrayPtr=array3Data, rc=rc) + if (rc /= ESMF_SUCCESS) return + call fillArray(array3Data, 3) + + array3Read = ESMF_ArrayCreate(distgrid3tile, arraySpec, name="array3", rc=rc) + if (rc /= ESMF_SUCCESS) return + call ESMF_ArrayGet(array3Read, farrayPtr=array3ReadData, rc=rc) + if (rc /= ESMF_SUCCESS) return + + arrayBundle = ESMF_ArrayBundleCreate(arrayList=[array1, array2], name="ab", rc=rc) + if (rc /= ESMF_SUCCESS) return + + arrayBundleRead = ESMF_ArrayBundleCreate(arrayList=[array1Read, array2Read], name="abRead", rc=rc) + if (rc /= ESMF_SUCCESS) return + + end subroutine createArrays + + subroutine fillArray(array, multiplier) + ! Fill the given 2-d array based on indices times a multiplier + real(ESMF_KIND_R8), intent(out) :: array(:,:) + integer, intent(in) :: multiplier + integer :: i, j + + do j = 1, size(array, 2) + do i = 1, size(array, 1) + array(i,j) = multiplier * ((i-1)*size(array,2) + (j-1)) + end do + end do + end subroutine fillArray + end program ESMF_IO_MultitileUTest From ddbe1c98f97ccaeda74864edc7099749510e1037 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 8 Sep 2022 09:41:04 -0700 Subject: [PATCH 180/266] Update README.md Finish the ESMX_Driver section. --- src/addon/ESMX/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/addon/ESMX/README.md b/src/addon/ESMX/README.md index a72bc18dbb..36985b7613 100644 --- a/src/addon/ESMX/README.md +++ b/src/addon/ESMX/README.md @@ -104,7 +104,7 @@ Fields starting with `ESMX_` are defined by the ESMX unified driver executable. Each generic component label must be associated with an actual component model through the `XXX_model` field, where `XXX` is replaced by the actual generic component label, e.g. `ATM`, `OCN`, etc. The association is made by specifying the *component-name* used in the `esmxBuild.yaml` file discussed earlier. The options in the example are `tawas` and `lumo`. -Finally the `startTime` and `stopTime` fields set the start and stop time of the run, respectively. The `runSeq` field defines the run sequence. +Finally the `startTime` and `stopTime` fields set the start and stop time of the run, respectively. The `runSeq` field defines the run sequence. The *default* time step of the outer run sequence loop, i.e. if using the `@*` syntax, is set to `stopTime - startTime`. ### Dynamically loading components from shared objects at run-time @@ -146,7 +146,9 @@ The applcation can then be built as typically via cmake commands, only requiring The `esmx_driver` target defined by the `add_subdirectory(${ESMF_ESMXDIR}/Driver ./ESMX_Driver)` has a build-time dependency on the `esmxBuild.yaml` file already discussed under the [unfied driver executable section](#esmxbuildyaml). The identical file can be used when working on the `ESMX_Driver` level. The run-time configuration needed by `ESMX_Driver` can either be supplied by the user application, or alternatively default to `esmxRun.config`. The following rules apply: - - - - +- `ESMX_Driver`, at the beginning of its `SetModelServices()` method checks whether the parent level has provided an `ESMF_Config` object by setting the `config` member on the `ESMX_Driver` component. If so, the provided `config` object is used. Otherwise `ESMX_Driver` itself creates `config` from file `esmxRun.config`. +- For the case where the `config` object was provided by the parent layer, `ESMX_Driver` does not ingest attributes from `config`. Instead the assumption is made that the parent layer sets the desired attributes on `ESMX_Driver`. +- For the case where the `config` object was loaded from `esmxRun.config` by `ESMX_Driver`, the driver ingests attributes from `config`, potentially overriding parent level settings. +- The `ESMX_component_list`, child component, and run sequence information is ingested from `config` as described under the [unfied driver executable section](#esmxrunconfig). +- If the parent level passes an `ESMF_Clock` object to `ESMX_Driver` during initialize, the driver uses it instead of looking for `startTime` and `stopTime` in `config`. +- For the case where a clock is provided by the parent layer, its `timeStep` is used as the *default* time step of the outer run sequence loop when using the `@*` syntax. If a specific time step is set in the run sequence with `@DT`, then `DT` must be a divisor of the `timeStep` provided by the parent clock. From 46533806b31256e97a67aa7bfc78608277f5f32c Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 10:56:54 -0700 Subject: [PATCH 181/266] remove deprecated decorator from ESMP_FieldSMMStore --- src/addon/ESMPy/src/esmpy/interface/cbindings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/addon/ESMPy/src/esmpy/interface/cbindings.py b/src/addon/ESMPy/src/esmpy/interface/cbindings.py index b0499f19d0..126ff6372f 100644 --- a/src/addon/ESMPy/src/esmpy/interface/cbindings.py +++ b/src/addon/ESMPy/src/esmpy/interface/cbindings.py @@ -2329,7 +2329,6 @@ def ESMP_FieldRegrid(srcField, dstField, routehandle, zeroregion=None): _ESMF.ESMC_FieldSMMStore.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_char_p, ct.POINTER(ESMP_RouteHandle), ct.c_bool, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int)] -@deprecated def ESMP_FieldSMMStore(srcField, dstField, filename, ignoreUnmatchedIndices=None): """ From e89e1c46786e0204ef754c4638ffd1e1450ae5dd Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 10:57:23 -0700 Subject: [PATCH 182/266] fix clean and dust targets of ESMPy Makefile --- src/addon/ESMPy/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 157e7c82db..3129383ef6 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -11,15 +11,15 @@ clean: find . -name "*.python-version" -exec rm -f {} \; || : find . -name "*__pycache__" -exec rm -rf {} \; || : find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : - find . -name ".report.json" -exec rm -rf {} \; || : - find . -name ".test" -exec rm -rf {} \; || : + find . -name "*.report.json" -exec rm -rf {} \; || : + find . -name "*.test" -exec rm -rf {} \; || : rm -rf src/esmpy/test/regrid_from_file/data || : rm -rf examples/data || : dust: find . -name "*ESMF_LogFile*" -exec rm -f {} \; || : - find . -name ".report.json" -exec rm -rf {} \; || : - find . -name ".test" -exec rm -rf {} \; || : + find . -name "*.report.json" -exec rm -rf {} \; || : + find . -name "*.test" -exec rm -rf {} \; || : install: python3 -m pip install . From 7624b3ce3821f54a9eb8447ee79decfa8ad6cd59 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 10:57:43 -0700 Subject: [PATCH 183/266] add a version check for ESMPy and ESMF installations --- src/addon/ESMPy/src/esmpy/__init__.py | 25 +++++++++++-------- src/addon/ESMPy/src/esmpy/api/constants.py | 4 +++ src/addon/ESMPy/src/esmpy/api/esmpymanager.py | 3 ++- .../ESMPy/src/esmpy/interface/loadESMF.py | 23 ++++++++++++++--- src/addon/ESMPy/src/esmpy/util/exceptions.py | 17 +++++++++++-- 5 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/addon/ESMPy/src/esmpy/__init__.py b/src/addon/ESMPy/src/esmpy/__init__.py index ec5f90f4bd..a7f90a2a3e 100644 --- a/src/addon/ESMPy/src/esmpy/__init__.py +++ b/src/addon/ESMPy/src/esmpy/__init__.py @@ -64,19 +64,10 @@ data values. """ -#### IMPORT LIBRARIES ######################################################### - -from esmpy.api.esmpymanager import * -from esmpy.api.grid import * -from esmpy.api.mesh import * -from esmpy.api.locstream import * -from esmpy.api.field import * -from esmpy.api.regrid import * -from esmpy.api.constants import * -from esmpy.util.helpers import * - #### SET UP SOME INFO ######################################################### +import esmpy.api.constants as constants + import sys msg = "" @@ -105,6 +96,7 @@ # set the private metadata __name__ = msg["Name"] __version__ = msg["Version"] +constants._ESMPY_VERSION = __version__ # required to check against ESMF_VERSION in loadESMF __license__ = msg["License"] __email__ = msg["Maintainer-email"] __description__ = msg["Summary"] @@ -114,3 +106,14 @@ __author__ = msg["Author"] __homepage__ = msg["Home-page"] __obsoletes__ = msg["obsoletes"] + +#### IMPORT LIBRARIES ######################################################### + +from esmpy.api.esmpymanager import * +from esmpy.api.grid import * +from esmpy.api.mesh import * +from esmpy.api.locstream import * +from esmpy.api.field import * +from esmpy.api.regrid import * +from esmpy.api.constants import * +from esmpy.util.helpers import * diff --git a/src/addon/ESMPy/src/esmpy/api/constants.py b/src/addon/ESMPy/src/esmpy/api/constants.py index 52791233da..87f6abac97 100644 --- a/src/addon/ESMPy/src/esmpy/api/constants.py +++ b/src/addon/ESMPy/src/esmpy/api/constants.py @@ -51,6 +51,10 @@ # ESMF_VERSION _ESMF_VERSION = None +# ESMPY_VERSION, this is required to avoid a circular import in loadESMF when +# checking that the ESMF_VERSION matches esmpy.__version__ +_ESMPY_VERSION = None + # ESMF_MPIRUN _ESMF_MPIRUN = None _ESMF_MPIRUN_NP = None diff --git a/src/addon/ESMPy/src/esmpy/api/esmpymanager.py b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py index cda53527da..8dd02bb50c 100644 --- a/src/addon/ESMPy/src/esmpy/api/esmpymanager.py +++ b/src/addon/ESMPy/src/esmpy/api/esmpymanager.py @@ -6,9 +6,10 @@ #### IMPORT LIBRARIES ######################################################### +from esmpy.interface.cbindings import * + from esmpy.api.constants import * from esmpy.util.exceptions import * -from esmpy.interface.cbindings import * from esmpy.util.decorators import initialize import re diff --git a/src/addon/ESMPy/src/esmpy/interface/loadESMF.py b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py index bf791c0c4d..0b57d47775 100644 --- a/src/addon/ESMPy/src/esmpy/interface/loadESMF.py +++ b/src/addon/ESMPy/src/esmpy/interface/loadESMF.py @@ -5,8 +5,10 @@ import os import sys import traceback +import re import esmpy.api.constants as constants +from esmpy.util.exceptions import VersionWarning, VersionMismatch try: import numpy as np @@ -65,6 +67,24 @@ if "gfortran" in line: use_inmem_factors = True +# check and set _ESMF_VERSION_STRING +esmfvs = re.split(r'\D+',esmfversion) +esmpyvs = re.split(r'\D+',constants._ESMPY_VERSION) + +if esmfversion != constants._ESMPY_VERSION: + # check if major, minor and patch version numbers are equivalent + if esmfvs[0:2] != esmpyvs[0:2]: + raise VersionMismatch("ESMF installation version {}, ESMPy version {}".format( + esmfversion, constants._ESMPY_VERSION)) + # otherwise warn that beta versions may be in use + else: + import warnings + warnings.warn("ESMF installation version {}, ESMPy version {}".format( + esmfversion, constants._ESMPY_VERSION), VersionWarning) + +constants._ESMF_VERSION = esmfversion + + if not libsdir: raise ValueError("ESMF_LIBSDIR not found!") if not esmfos: @@ -104,9 +124,6 @@ if "mpiuni" in esmfcomm: constants._ESMF_COMM = constants._ESMF_COMM_MPIUNI -# set _ESMF_VERSION_STRING -constants._ESMF_VERSION = esmfversion - # look for ESMPY_MPIRUN, set accordingly try: constants._ESMF_MPIRUN = os.environ['ESMPY_MPIRUN'] diff --git a/src/addon/ESMPy/src/esmpy/util/exceptions.py b/src/addon/ESMPy/src/esmpy/util/exceptions.py index 206eaae900..746692b6a5 100644 --- a/src/addon/ESMPy/src/esmpy/util/exceptions.py +++ b/src/addon/ESMPy/src/esmpy/util/exceptions.py @@ -10,8 +10,16 @@ class ESMPyException(Exception): """Base class for errors in the ESMPy package.""" pass -class RequiredArgs(ESMPyException): - """Required arguments were not specified.""" +class ESMPyWarning(Warning): + """Base class for warnings in the ESMPy package.""" + pass + +class VersionMismatch(ESMPyException): + """The ESMF installation is not compatible with this version of ESMPy.""" + pass + +class VersionWarning(ESMPyWarning): + """The ESMF and/or ESMPy installations are beta version which may not be fully compatible.""" pass class NetCDFMissing(ESMPyException): @@ -22,6 +30,7 @@ class PIOMissing(ESMPyException): """ESMF was not built with PIO support.""" pass + class MethodNotImplemented(ESMPyException): """Raised when an unimplemented method is called.""" pass @@ -30,6 +39,10 @@ class SerialMethod(ESMPyException): """This method is not safe to run in parallel!""" pass +class RequiredArgs(ESMPyException): + """Required arguments were not specified.""" + pass + class GridException(ESMPyException): """Base class for errors in the Grid class.""" From 458d4a315676a0aaee43028b9434ad556e2b0f70 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 11:00:39 -0700 Subject: [PATCH 184/266] move test_all.bash to src/esmpy/test --- src/addon/ESMPy/Makefile | 2 +- src/addon/ESMPy/{ => src/esmpy/test}/test_all.bash | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/addon/ESMPy/{ => src/esmpy/test}/test_all.bash (100%) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 3129383ef6..e87cd11770 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -33,7 +33,7 @@ dryrun_regrid_from_file: dryrun: dryrun_examples dryrun_regrid_from_file test: - bash test_all.bash + bash src/esmpy/test/test_all.bash test_unit: python3 -m pytest -vs diff --git a/src/addon/ESMPy/test_all.bash b/src/addon/ESMPy/src/esmpy/test/test_all.bash similarity index 100% rename from src/addon/ESMPy/test_all.bash rename to src/addon/ESMPy/src/esmpy/test/test_all.bash From 0e17ea875f076741062d858674fc52b0dc2ef99d Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 11:05:41 -0700 Subject: [PATCH 185/266] fix esmpy skipif marker for inmemory factors with compilers other than GNU --- src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py index ba515571a9..3f19a3ef9f 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py @@ -85,7 +85,7 @@ def test_field_regrid(self): line_type=LineType.CART, factors=False) _ = rh(srcfield, dstfield) - @pytest.mark.skipif(constants._ESMF_USE_INMEM_FACTORS, reason="compiler does not support in-memory weights") + @pytest.mark.skipif(not constants._ESMF_USE_INMEM_FACTORS, reason="compiler does not support in-memory weights") @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") def test_field_regrid_factor_retrieval(self): # Test retrieving factors from a route handle. From 8a52bc1cd65f8a9131a7c7ae32736c26bac3d295 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 12:53:21 -0700 Subject: [PATCH 186/266] remove platform specific info from ESMPy test script --- src/addon/ESMPy/src/esmpy/test/test_all.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMPy/src/esmpy/test/test_all.bash b/src/addon/ESMPy/src/esmpy/test/test_all.bash index a2aee0ce57..a847a0d0e1 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_all.bash +++ b/src/addon/ESMPy/src/esmpy/test/test_all.bash @@ -6,7 +6,7 @@ echo "Testing ESMPy ${VERSION}" for NP in 1 4 6 do - REPORT="esmpy${VERSION}-cheyenne-intelmpt-petx${NP}.test" + REPORT="esmpy${VERSION}-petx${NP}.test" COMMAND="mpiexec -n ${NP} python3 -m pytest -vs --json-report --json-report-summary > $REPORT 2>&1" echo ${COMMAND} eval "${COMMAND}" From 9336e59fc2b1f0a2988de280e1ed880667e7b0e5 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 14:04:47 -0700 Subject: [PATCH 187/266] remove old ESMPy test file --- src/addon/ESMPy/src/esmpy/test/base_test.py | 24 --------------------- 1 file changed, 24 deletions(-) delete mode 100644 src/addon/ESMPy/src/esmpy/test/base_test.py diff --git a/src/addon/ESMPy/src/esmpy/test/base_test.py b/src/addon/ESMPy/src/esmpy/test/base_test.py deleted file mode 100644 index b95a9313d2..0000000000 --- a/src/addon/ESMPy/src/esmpy/test/base_test.py +++ /dev/null @@ -1,24 +0,0 @@ -from esmpy.test.base import TestBase -import numpy as np -from esmpy import Manager - -class Test(TestBase): - - def setup(self): - mg = Manager() - mg.test_exhaustive = False - # mg.barrier() - - def test_assertNumpyAll_bad_mask(self): - arr = np.ma.array([1,2,3],mask=[True,False,True]) - arr2 = np.ma.array([1,2,3],mask=[False,True,False]) - self.assertRaises(AssertionError, lambda: self.assertNumpyAll(arr,arr2)) - - def test_assertNumpyAll_type_differs(self): - arr = np.ma.array([1,2,3],mask=[True,False,True]) - arr2 = np.array([1,2,3]) - self.assertRaises(AssertionError, lambda: self.assertNumpyAll(arr,arr2)) - - def tearDown(self): - mg = Manager() - # mg.barrier() From 1f2363edd8c5f87055d9b885d88c89926f77cb9f Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 14:05:44 -0700 Subject: [PATCH 188/266] add ESMPy Manager to TestBase --- src/addon/ESMPy/examples/test_examples.py | 10 +++--- src/addon/ESMPy/src/esmpy/test/base.py | 21 ++++++------- .../src/esmpy/test/test_api/test_field.py | 27 ++++++++-------- .../src/esmpy/test/test_api/test_grid.py | 19 ++++++------ .../src/esmpy/test/test_api/test_locstream.py | 4 +-- .../src/esmpy/test/test_api/test_mesh.py | 23 +++++++------- .../src/esmpy/test/test_api/test_regrid.py | 31 +++++++++---------- .../ESMPy/src/esmpy/test/test_api/test_vm.py | 25 +++++++-------- 8 files changed, 77 insertions(+), 83 deletions(-) diff --git a/src/addon/ESMPy/examples/test_examples.py b/src/addon/ESMPy/examples/test_examples.py index 94bdf1a6c9..d3e01accd5 100644 --- a/src/addon/ESMPy/examples/test_examples.py +++ b/src/addon/ESMPy/examples/test_examples.py @@ -14,7 +14,7 @@ # Start up esmpy mg = Manager(debug=True) -if mg.pet_count == 1: +if pet_count() == 1: from esmpy.util.cache_data import cache_data_files cache_data_files() @@ -33,17 +33,17 @@ def test_field_read(self): def test_grid_create_peridim_mask(self): from . import grid_create_peridim_mask - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_locstream_regrid(self): from . import grid_locstream_regrid - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_locstream_grid_regrid(self): from . import locstream_grid_regrid - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_locstream_regrid(self): from . import mesh_locstream_regrid @@ -68,7 +68,7 @@ def test_ungridded_dimension_regrid(self): # this will currently never run because it isn't yet possible to run pytest with mpiexec @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") - @pytest.mark.skipif(mg.pet_count!=6, reason="test must be run with 6 cores") + @pytest.mark.skipif(pet_count()!=6, reason="test must be run with 6 cores") def test_cubed_sphere_to_mesh_regrid(self): from . import cubed_sphere_to_mesh_regrid diff --git a/src/addon/ESMPy/src/esmpy/test/base.py b/src/addon/ESMPy/src/esmpy/test/base.py index 1bfcd785e7..28bd37ff37 100644 --- a/src/addon/ESMPy/src/esmpy/test/base.py +++ b/src/addon/ESMPy/src/esmpy/test/base.py @@ -1,23 +1,22 @@ import unittest import numpy as np from esmpy.util.itester import iter_product_keywords +from esmpy.api.esmpymanager import Manager class TestBase(unittest.TestCase): - # mg = None + @property + def mg(self): + """ + :rtype: :class:`~esmpy.api.esmpymanager.Manager` + :return: :class:`~esmpy.api.esmpymanager.Manager` + """ + return self._mg def __init__(self, *args, **kwds): super(TestBase, self).__init__(*args, **kwds) - - # @classmethod - # def setUpClass(cls): - # import esmpy - # cls.mg = esmpy.Manager(debug = True) - # cls.mg.test_exhaustive = False - # - # @classmethod - # def tearDownClass(cls): - # del cls.mg + self._mg = Manager(debug = True) + self._mg.test_exhaustive = False def assertNumpyAll(self, arr1, arr2, check_fill_value_dtype=True, check_arr_dtype=True): """ diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py index f7314c34bc..1a443e0d05 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_field.py @@ -11,6 +11,7 @@ class TestField(TestBase): + # prefer TestBase.mg, but in this case required for test_exhaustive in pytest markers mg = Manager(debug=True) mg.test_exhaustive = False @@ -71,7 +72,7 @@ def test_meta_del(self): del (self.field) assert (not hasattr(self, 'field')) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_numpy_funcs(self): field = self.make_field(np.array([10, 10], dtype=np.int32)) @@ -98,7 +99,7 @@ def test_numpy_funcs(self): @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def _field_create_2d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -148,7 +149,7 @@ def _field_create_2d_grid(self): "The following combinations of parameters failed to create a proper Field: " + str(fail)) @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def _field_create_3d_grid(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -200,7 +201,7 @@ def _field_create_3d_grid(self): "The following combinations of parameters failed to create a proper Field: " + str(len(fail))) @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def _field_create_2d_mesh(self): keywords = dict( meshloc=[MeshLoc.NODE, MeshLoc.ELEMENT], @@ -276,7 +277,7 @@ def create_field(gml, name): return field - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_uniqueness(self): mesh = None if (pet_count() == 4): @@ -300,7 +301,7 @@ def test_field_uniqueness(self): assert (field.struct.ptr != field2.struct.ptr) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_area(self): grid = Grid(np.array([3, 4]), staggerloc=[StaggerLoc.CENTER, StaggerLoc.CORNER], coord_sys=CoordSys.SPH_DEG, num_peri_dims=1, @@ -336,7 +337,7 @@ def test_field_area(self): assert(np.all(field.data == field2.data)) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_locstream_mask(self): # LocStream creation and simple validation locstream = LocStream(5, name="Test LocStream") @@ -389,7 +390,7 @@ def test_field_extradims_grid(self): field2.data[...] = 10 self.examine_field_attributes(field2) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_extradims_mesh(self): mesh = None if (pet_count() == 4): @@ -408,7 +409,7 @@ def test_field_extradims_mesh(self): field2.data[...] = 10 self.examine_field_attributes(field2) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_grid(self): typekind = TypeKind.R8 grid = Grid(np.array([100, 100]), coord_sys=CoordSys.CART, @@ -448,7 +449,7 @@ def test_field_slice_grid(self): assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) # slicing is disabled in parallel - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_mesh(self): mesh = None if pet_count() > 1: @@ -479,7 +480,7 @@ def test_field_slice_mesh(self): assert (field2.grid.size[0] == 5) assert (field3.grid.size[0] == 2) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_slice_grid_extraindices(self): n = 10 grid = Grid(np.array([n,n]), coord_sys=CoordSys.CART, staggerloc=StaggerLoc.CENTER) @@ -517,7 +518,7 @@ def test_field_slice_grid_extraindices(self): assert (field2.grid.upper_bounds[0].tolist() == [5, 5]) assert (field3.grid.upper_bounds[0].tolist() == [2, 2]) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def disable_est_field_slice_mesh_extraindices(self): mesh, nodeCoord, nodeOwner, elemType, elemConn, elemCoord = mesh_create_50() @@ -539,7 +540,7 @@ def disable_est_field_slice_mesh_extraindices(self): assert field2.data.shape == (5, 2, 1) assert field3.data.shape == (2, 1, 1) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_reshape(self): field = self.make_field(np.array([10, 10], dtype=np.int32), ndbounds=False) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py index 2452e046c0..300c810f9a 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_grid.py @@ -16,9 +16,10 @@ class TestGrid(TestBase): + # prefer TestBase.mg, but in this case required for test_exhaustive in pytest markers mg = Manager(debug=True) mg.test_exhaustive = False - + def examine_grid_attributes(self, grid): # ~~~~~~~~~~~~~~~~~~~~~~ STAGGER LOCATIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # grid.staggerloc returns a boolean list of the activated stagger locations @@ -181,7 +182,7 @@ def test_grid_periodic(self): self.examine_grid_attributes(grid) @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_create_2d(self): keywords = dict( # periodic specifies all valid combos of [pole_kind, num_peri_dims, periodic_dim, pole_dim] @@ -227,7 +228,7 @@ def test_grid_create_2d(self): "The following combinations of Grid parameters failed to create a proper Grid: " + str(fail)) @pytest.mark.skipif(mg.test_exhaustive==False, reason="only run in exhaustive mode") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_create_3d(self): keywords = dict( # periodic specifies all valid combos of [num_peri_dims, periodic_dim, pole_dim] @@ -296,7 +297,7 @@ def test_grid_create_cubed_sphere(self): grid.destroy() # grid2.destroy() - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_2d(self): grid = self.make_grid_2d() @@ -316,7 +317,7 @@ def test_grid_slice_2d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1] - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_2d_corners(self): grid = self.make_grid_2d() @@ -347,7 +348,7 @@ def test_grid_slice_2d_corners(self): assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_3d(self): grid = self.make_grid_3d() @@ -367,7 +368,7 @@ def test_grid_slice_3d(self): assert grid3.coords[StaggerLoc.CENTER][0].shape == (2, 1, 2) assert grid3.upper_bounds[StaggerLoc.CENTER].tolist() == [2, 1, 2] - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_3d_corners(self): grid = self.make_grid_3d() @@ -402,7 +403,7 @@ def test_grid_slice_3d_corners(self): assert grid3.coords[cvf][0].shape == (3, 2, 3) assert grid3.upper_bounds[cvf].tolist() == [3, 2, 3] - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_grid_slice_periodic(self): grid, x, y = self.make_grid_periodic() @@ -429,7 +430,7 @@ def test_grid_slice_periodic(self): assert grid3.upper_bounds[StaggerLoc.CORNER].tolist() == [3, 2] @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice_grid_created_from_file_scrip(self): import esmpy reg_decomp = [pet_count(), 1] diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py index 7ec83755b9..ea9b71bbaa 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_locstream.py @@ -10,8 +10,6 @@ class TestLocStream(TestBase): - mg = Manager(debug=True) - def test_create(self): # LocStream creation and simple validation locstream = LocStream(5, name="Test LocStream") @@ -53,7 +51,7 @@ def test_copy(self): assert np.all(l2["ESMF:X"] == [0, 1, 2, 3, 4]) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice(self): locstream = LocStream(5, name="Test LocStream") diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py index 41b87d4bb8..88a537e642 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_mesh.py @@ -14,7 +14,6 @@ from esmpy.util.mesh_utilities import * class TestMesh(TestBase): - mg = Manager(debug=True) def check_mesh(self, mesh, nodeCoord, nodeOwner, elemCoord=None): @@ -47,7 +46,7 @@ def check_mesh(self, mesh, nodeCoord, nodeOwner, elemCoord=None): # this call fails if nodes and elements have not been added first # mesh.free_memory() - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_5(self): elemCoord = None parallel = False @@ -60,7 +59,7 @@ def test_mesh_5(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_10(self): elemCoord = None parallel = False @@ -73,7 +72,7 @@ def test_mesh_10(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50(self): elemCoord = None parallel = False @@ -86,7 +85,7 @@ def test_mesh_50(self): self.check_mesh(mesh, nodeCoord, nodeOwner, elemCoord=elemCoord) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_moab(self): # set this mesh to be created with the MOAB backend mg = Manager() @@ -111,7 +110,7 @@ def test_mesh_50_moab(self): assert (mg.moab == False) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_ngons(self): parallel = False if pet_count() == 4: @@ -123,7 +122,7 @@ def test_mesh_50_ngons(self): self.check_mesh(mesh, nodeCoord, nodeOwner) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_50_mask_area(self): elemCoord = None parallel = False @@ -154,7 +153,7 @@ def test_mesh_create_from_file_esmfmesh(self): mesh_from_file = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), filetype=FileFormat.ESMFMESH) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_copy(self): if pet_count() == 4: mesh, nodeCoord, nodeOwner, elemType, elemConn = \ @@ -169,7 +168,7 @@ def test_mesh_copy(self): self.check_mesh(mesh2, nodeCoord, nodeOwner) # slicing is disabled in parallel - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_mesh_slicing(self): mesh, nodeCoord, nodeOwner, elemType, elemConn = \ mesh_create_5_pentahexa() @@ -195,7 +194,7 @@ def test_mesh_slicing(self): @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice_mesh_created_from_file_scrip(self): esmfdir = os.path.dirname(inspect.getfile(esmpy)) mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-pentagons.nc"), @@ -217,7 +216,7 @@ def test_slice_mesh_created_from_file_scrip(self): @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_slice_mesh_created_from_file_esmfmesh(self): esmfdir = os.path.dirname(inspect.getfile(esmpy)) mesh = Mesh(filename=os.path.join(esmfdir, "test/data/ne4np4-esmf.nc"), @@ -239,7 +238,7 @@ def test_slice_mesh_created_from_file_esmfmesh(self): @pytest.mark.xfail @pytest.mark.skipif(_ESMF_PIO==False, reason="PIO required in ESMF build") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") #TODO: remove expected failure once we have a smaller data file with mesh element coordinates to use # TODO: have to define slicing for mesh element coordinates as well.. def test_slice_mesh_created_from_file_elem_coords(self): diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py index 3f19a3ef9f..88a43f0c69 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_regrid.py @@ -16,9 +16,6 @@ class TestRegrid(TestBase): - mg = Manager(debug=True) - mg.test_exhaustive = False - def run_regridding(srcfield, dstfield, srcfracfield, dstfracfield): # This is for documentation. Do not modify. ''' @@ -86,7 +83,7 @@ def test_field_regrid(self): _ = rh(srcfield, dstfield) @pytest.mark.skipif(not constants._ESMF_USE_INMEM_FACTORS, reason="compiler does not support in-memory weights") - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def test_field_regrid_factor_retrieval(self): # Test retrieving factors from a route handle. @@ -565,7 +562,7 @@ def test_field_regrid_file4(self): if os.path.isfile(path): os.remove(path) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_gridmesh(self): mesh = None if pet_count() == 4: @@ -602,7 +599,7 @@ def test_field_regrid_gridmesh(self): rh = Regrid(srcfield, dstfield, regrid_method=RegridMethod.CONSERVE) dstfield = rh(srcfield, dstfield) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_zeroregion(self): mesh = None if pet_count() == 4: @@ -694,7 +691,7 @@ def test_field_regrid_zeroregion_select_ndbounds(self): if os.path.exists(filename): os.remove(filename) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_area(self): mesh = None if pet_count() == 4: @@ -994,7 +991,7 @@ def test_grid_grid_regrid_srcmask_types(self): self.assertAlmostEqual(meanrel, 0.0024803189848013785) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_csrv_mask(self): mesh = None if pet_count() == 4: @@ -1044,7 +1041,7 @@ def test_grid_mesh_regrid_csrv_mask(self): self.assertAlmostEqual(meanrel, 0.038806630051265847) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_csrv(self): mesh = None if pet_count() == 4: @@ -1092,7 +1089,7 @@ def test_grid_mesh_regrid_csrv(self): self.assertAlmostEqual(meanrel, 0.037733241800767432) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid_mask(self): # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True, domask=True) @@ -1129,7 +1126,7 @@ def test_grid_mesh_regrid_mask(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_regrid(self): # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) @@ -1165,7 +1162,7 @@ def test_grid_mesh_regrid(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_extrapolation(self): # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) @@ -1204,7 +1201,7 @@ def test_field_regrid_extrapolation(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_field_regrid_extrapolation_creepfill(self): # create a grid grid = grid_create_from_bounds([0, 4], [0, 4], 8, 8, corners=True) @@ -1241,7 +1238,7 @@ def test_field_regrid_extrapolation_creepfill(self): self.assertAlmostEqual(meanrel, 0.0) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_mesh_regrid(self): srcmesh = None dstmesh = None @@ -1294,7 +1291,7 @@ def test_mesh_mesh_regrid(self): self.assertAlmostEqual(meanrel, 0.037109375) self.assertAlmostEqual(csrvrel, 0.0) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def est_grid_mesh_pentatri_regrid_csrv(self): mesh = None if pet_count() == 4: @@ -1345,7 +1342,7 @@ def est_grid_mesh_pentatri_regrid_csrv(self): assert (meanrel < 10E-2) assert (csrvrel < 10E-14) - @pytest.mark.skipif(mg.pet_count!=1, reason="test must be run in serial") + @pytest.mark.skipif(pet_count()!=1, reason="test must be run in serial") def est_grid_mesh_pentatri_regrid_csrv_simple(self): # create a Mesh mesh, nodeCoord, nodeOwner, elemType, elemConn = \ @@ -1392,7 +1389,7 @@ def est_grid_mesh_pentatri_regrid_csrv_simple(self): assert (meanrel < 10E-2) assert (csrvrel < 10E-14) - @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") def test_grid_mesh_pentatri_regrid_bilinear(self): mesh = None if pet_count() == 4: diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py index 7fd61057b7..c06cbe1121 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_vm.py @@ -9,23 +9,22 @@ class TestVM(TestBase): def test_vm_broadcast(self): - mg = Manager() bcst = np.ones(4, dtype=np.float64) - if mg.local_pet != 0: + if self.mg.local_pet != 0: bcst[:] = 2 - if mg.local_pet == 0: + if self.mg.local_pet == 0: assert(np.all(bcst == 1)) else: assert(np.all(bcst == 2)) - mg.barrier() - mg._broadcast_(bcst, 4) - mg.barrier() + self.mg.barrier() + self.mg._broadcast_(bcst, 4) + self.mg.barrier() assert(np.all(bcst == 1)) - mg.barrier() + self.mg.barrier() def test_vm_reduce(self): send = np.ones(4, dtype=np.float64) @@ -33,13 +32,13 @@ def test_vm_reduce(self): mg = Manager() - mg.barrier() - mg._reduce_(send, recv, 4, Reduce.SUM, 0) - mg.barrier() + self.mg.barrier() + self.mg._reduce_(send, recv, 4, Reduce.SUM, 0) + self.mg.barrier() - if mg.local_pet == 0: - assert(np.all(recv == mg.pet_count)) + if self.mg.local_pet == 0: + assert(np.all(recv == self.mg.pet_count)) else: assert(np.all(recv == 0)) - mg.barrier() + self.mg.barrier() From cc821abd0720e46d857724b79a4bdeab70a4732e Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 14:11:29 -0700 Subject: [PATCH 189/266] add file to test pytest functionality in question --- .../src/esmpy/test/test_api/test_pytest.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py new file mode 100644 index 0000000000..c4e7560708 --- /dev/null +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py @@ -0,0 +1,28 @@ +""" +pytest tests +""" + +import pytest + +from esmpy.test.base import TestBase +from esmpy.api.esmpymanager import pet_count + +class TestPyTest(TestBase): + + @pytest.mark.xfail + @pytest.mark.skipif(pet_count()<3, reason="test must be run with more than 3 cores") + def test_pytest_2(self): + + print ("Test2: I AM PET {}".format(self.mg.local_pet)) + + if self.mg.local_pet == 2: + raise ValueError("Test failure on a single PET") + + @pytest.mark.mpi(min_size=2) + def test_pytest_1(self): + from mpi4py import MPI + + comm = MPI.COMM_WORLD + rank = comm.Get_rank() + + print ("Test1: I AM PET {} and rank {}".format(local_pet(), rank)) From 94489e281e0fc6e78291edf00506b76e1302b813 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Thu, 8 Sep 2022 14:23:34 -0700 Subject: [PATCH 190/266] better pytest names --- src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py index c4e7560708..e3516f4c95 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py @@ -11,7 +11,7 @@ class TestPyTest(TestBase): @pytest.mark.xfail @pytest.mark.skipif(pet_count()<3, reason="test must be run with more than 3 cores") - def test_pytest_2(self): + def test_pytest_singlecorefailure(self): print ("Test2: I AM PET {}".format(self.mg.local_pet)) @@ -19,7 +19,7 @@ def test_pytest_2(self): raise ValueError("Test failure on a single PET") @pytest.mark.mpi(min_size=2) - def test_pytest_1(self): + def test_pytest_mpi4py(self): from mpi4py import MPI comm = MPI.COMM_WORLD From 2aa5d4dfcd00933112a7f141c51a16ab12c32359 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 9 Sep 2022 12:04:28 -0700 Subject: [PATCH 191/266] add a missing esmpy symbol --- src/addon/ESMPy/examples/test_examples.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/addon/ESMPy/examples/test_examples.py b/src/addon/ESMPy/examples/test_examples.py index d3e01accd5..94bdf1a6c9 100644 --- a/src/addon/ESMPy/examples/test_examples.py +++ b/src/addon/ESMPy/examples/test_examples.py @@ -14,7 +14,7 @@ # Start up esmpy mg = Manager(debug=True) -if pet_count() == 1: +if mg.pet_count == 1: from esmpy.util.cache_data import cache_data_files cache_data_files() @@ -33,17 +33,17 @@ def test_field_read(self): def test_grid_create_peridim_mask(self): from . import grid_create_peridim_mask - @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_grid_locstream_regrid(self): from . import grid_locstream_regrid - @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") def test_locstream_grid_regrid(self): from . import locstream_grid_regrid - @pytest.mark.skipif(pet_count() not in {1, 4}, reason="test requires 1 or 4 cores") + @pytest.mark.skipif(mg.pet_count not in {1, 4}, reason="test requires 1 or 4 cores") def test_mesh_locstream_regrid(self): from . import mesh_locstream_regrid @@ -68,7 +68,7 @@ def test_ungridded_dimension_regrid(self): # this will currently never run because it isn't yet possible to run pytest with mpiexec @pytest.mark.skipif(_ESMF_NETCDF==False, reason="NetCDF required in ESMF build") - @pytest.mark.skipif(pet_count()!=6, reason="test must be run with 6 cores") + @pytest.mark.skipif(mg.pet_count!=6, reason="test must be run with 6 cores") def test_cubed_sphere_to_mesh_regrid(self): from . import cubed_sphere_to_mesh_regrid From 34ac7c145f9b031366441812ca8d6333efb05d7c Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Fri, 9 Sep 2022 13:49:10 -0600 Subject: [PATCH 192/266] Multitile array unit tests: different values on different PETs --- src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 index 6113f249d6..22cfa10e0c 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 @@ -44,6 +44,8 @@ program ESMF_IO_MultitileUTest character(ESMF_MAXSTR) :: failMsg character(ESMF_MAXSTR) :: name + type(ESMF_VM) :: vm + integer :: localPet type(ESMF_Grid) :: grid6tile type(ESMF_DistGrid) :: distgrid3tile @@ -101,6 +103,10 @@ program ESMF_IO_MultitileUTest !------------------------------------------------------------------------ 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) !------------------------------------------------------------------------ !------------------------------------------------------------------------ @@ -533,7 +539,7 @@ subroutine fillArray(array, multiplier) do j = 1, size(array, 2) do i = 1, size(array, 1) - array(i,j) = multiplier * ((i-1)*size(array,2) + (j-1)) + array(i,j) = (localPet+1) * multiplier * ((i-1)*size(array,2) + (j-1)) end do end do end subroutine fillArray From 1d6d93476c257673b34af88e7a154bb418639920 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 9 Sep 2022 19:15:42 -0700 Subject: [PATCH 193/266] change esmpy dryrun target to download --- src/addon/ESMPy/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index e87cd11770..15fc33f6d6 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -24,13 +24,13 @@ dust: install: python3 -m pip install . -dryrun_examples: +download_examples: python3 examples/test_examples_dryrun.py -dryrun_regrid_from_file: +download_regrid_from_file: python3 src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py -dryrun: dryrun_examples dryrun_regrid_from_file +download: download_examples download_regrid_from_file test: bash src/esmpy/test/test_all.bash From 074e4bf86527126fd5ab7ab66edd8a6250d78e24 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 9 Sep 2022 19:17:46 -0700 Subject: [PATCH 194/266] remove pytest that require pytest-mpi --- .../src/esmpy/test/test_api/test_pytest.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py index e3516f4c95..a8184efd60 100644 --- a/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py +++ b/src/addon/ESMPy/src/esmpy/test/test_api/test_pytest.py @@ -18,11 +18,12 @@ def test_pytest_singlecorefailure(self): if self.mg.local_pet == 2: raise ValueError("Test failure on a single PET") - @pytest.mark.mpi(min_size=2) - def test_pytest_mpi4py(self): - from mpi4py import MPI - - comm = MPI.COMM_WORLD - rank = comm.Get_rank() - - print ("Test1: I AM PET {} and rank {}".format(local_pet(), rank)) + # # this requires pytest-mpi package + # @pytest.mark.mpi(min_size=2) + # def test_pytest_mpi4py(self): + # from mpi4py import MPI + # + # comm = MPI.COMM_WORLD + # rank = comm.Get_rank() + # + # print ("Test1: I AM PET {} and rank {}".format(local_pet(), rank)) From 2626e0053622cd90da7d2ad9011efd4c3d00ef97 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Fri, 9 Sep 2022 19:34:29 -0700 Subject: [PATCH 195/266] add optional dataurl command line argument to esmpy data download scripts --- src/addon/ESMPy/examples/test_examples_dryrun.py | 9 ++++++++- .../test_regrid_from_file_dryrun.py | 13 ++++++++++--- src/addon/ESMPy/src/esmpy/util/cache_data.py | 11 ++++++----- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/addon/ESMPy/examples/test_examples_dryrun.py b/src/addon/ESMPy/examples/test_examples_dryrun.py index 14319d7b86..4c25b40f9e 100644 --- a/src/addon/ESMPy/examples/test_examples_dryrun.py +++ b/src/addon/ESMPy/examples/test_examples_dryrun.py @@ -4,5 +4,12 @@ examples data dryrun """ +import sys + from esmpy.util.cache_data import cache_data_files -cache_data_files() + +DATAURL = None +if len(sys.argv) > 1: + DATAURL = sys.argv[1] + +cache_data_files(DATAURL) diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py index 99d415aee6..94c4d5c384 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py @@ -11,15 +11,18 @@ import sys import os -from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR, DATA_URL_ROOT +from esmpy.test.regrid_from_file.regrid_from_file_consts import DATA_SUBDIR from esmpy.util.cache_data import cache_data_file from esmpy.test.regrid_from_file.read_test_cases_from_control_file import read_control_file -def cache_data_files_for_test_cases(test_cases): +def cache_data_files_for_test_cases(test_cases, DATA_URL_ROOT=None): # Create data subdirectory if it doesn't exist. if not os.path.exists(DATA_SUBDIR): os.mkdir(DATA_SUBDIR) + if DATA_URL_ROOT == None: + DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' + # For each test case line from the control file parse the line and call # the test subroutine. status_ok = True @@ -36,8 +39,12 @@ def cache_data_files_for_test_cases(test_cases): break return status_ok +DATAURL = None +if len(sys.argv) > 1: + DATAURL = sys.argv[1] + # Read the test case parameters from the control file. test_cases = read_control_file() # Retrieve the data files needed for the test cases from the remote server. -cache_data_files_for_test_cases(test_cases) +cache_data_files_for_test_cases(test_cases, DATAURL) diff --git a/src/addon/ESMPy/src/esmpy/util/cache_data.py b/src/addon/ESMPy/src/esmpy/util/cache_data.py index 4b414209f3..ab3171bfb6 100644 --- a/src/addon/ESMPy/src/esmpy/util/cache_data.py +++ b/src/addon/ESMPy/src/esmpy/util/cache_data.py @@ -1,9 +1,7 @@ import os -DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' - # If fname doesn't exist, retrieve it from the remote server via http. -def cache_data_file(fname, DATA_URL_ROOT=DATA_URL_ROOT): +def cache_data_file(fname, DATA_URL_ROOT=None): import sys if sys.version_info[0] >= 3: from urllib.request import urlopen, URLError @@ -12,6 +10,9 @@ def cache_data_file(fname, DATA_URL_ROOT=DATA_URL_ROOT): from shutil import copyfileobj + if DATA_URL_ROOT == None: + DATA_URL_ROOT = 'http://data.earthsystemmodeling.org/download/data/' + status_ok = True if not os.path.exists(fname): url = os.path.join(DATA_URL_ROOT, os.path.basename(fname)) @@ -30,7 +31,7 @@ def cache_data_file(fname, DATA_URL_ROOT=DATA_URL_ROOT): return status_ok -def cache_data_files(): +def cache_data_files(dataurl=None): # Filenames to download. datafilelist = ["aggregAtlanticESTOFS.nc", "GRIDSPEC_ACCESS1.nc", @@ -49,6 +50,6 @@ def cache_data_files(): # Download each test file. for fname in datafilelist: # Retrieve the data files needed for the test cases from the remote server. - status_ok = cache_data_file(os.path.join(datadir, fname)) + status_ok = cache_data_file(os.path.join(datadir, fname), dataurl) if not status_ok: raise IOError("Error downloading '{}'".format(fname)) From 08f639de3e3c5ba460640b72299ea5010e2f3fd3 Mon Sep 17 00:00:00 2001 From: Ryan O'Kuinghttons Date: Mon, 12 Sep 2022 09:55:30 -0700 Subject: [PATCH 196/266] change dryrun to download in esmpy file names_ --- src/addon/ESMPy/Makefile | 4 ++-- src/addon/ESMPy/doc/install.rst | 9 +++++---- ...test_examples_dryrun.py => test_examples_download.py} | 2 +- .../esmpy/test/regrid_from_file/test_regrid_from_file.py | 2 +- ..._file_dryrun.py => test_regrid_from_file_download.py} | 0 5 files changed, 9 insertions(+), 8 deletions(-) rename src/addon/ESMPy/examples/{test_examples_dryrun.py => test_examples_download.py} (88%) rename src/addon/ESMPy/src/esmpy/test/regrid_from_file/{test_regrid_from_file_dryrun.py => test_regrid_from_file_download.py} (100%) diff --git a/src/addon/ESMPy/Makefile b/src/addon/ESMPy/Makefile index 15fc33f6d6..2eb768b263 100644 --- a/src/addon/ESMPy/Makefile +++ b/src/addon/ESMPy/Makefile @@ -25,10 +25,10 @@ install: python3 -m pip install . download_examples: - python3 examples/test_examples_dryrun.py + python3 examples/test_examples_download.py download_regrid_from_file: - python3 src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py + python3 src/esmpy/test/regrid_from_file/test_regrid_from_file_download.py download: download_examples download_regrid_from_file diff --git a/src/addon/ESMPy/doc/install.rst b/src/addon/ESMPy/doc/install.rst index dbd79dd29a..fa514d782f 100644 --- a/src/addon/ESMPy/doc/install.rst +++ b/src/addon/ESMPy/doc/install.rst @@ -118,10 +118,11 @@ greater test coverage is desired: .. Note:: - The ``regrid_from_file`` tests can take up a lot of memory and bandwidth. - The ``test_regrid_from_file_dryrun`` command will simply download the test - files without actually running them (allowing the stress on the machine to - be applied to bandwidth first, and then memory). + The ``regrid_from_file`` and ``example`` tests can take up a lot of memory + and bandwidth. The ``download_regrid_from_file`` and ``download_examples`` + commands will simply download the test files without actually running them + (allowing the stress on the machine to be applied to bandwidth first, and + then memory). ----------- Limitations diff --git a/src/addon/ESMPy/examples/test_examples_dryrun.py b/src/addon/ESMPy/examples/test_examples_download.py similarity index 88% rename from src/addon/ESMPy/examples/test_examples_dryrun.py rename to src/addon/ESMPy/examples/test_examples_download.py index 4c25b40f9e..ac6c18da48 100644 --- a/src/addon/ESMPy/examples/test_examples_dryrun.py +++ b/src/addon/ESMPy/examples/test_examples_download.py @@ -1,7 +1,7 @@ # $Id$ """ -examples data dryrun +examples data download """ import sys diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py index 37ac3e70da..7c5a648fb4 100644 --- a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py +++ b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file.py @@ -26,7 +26,7 @@ mg = Manager(debug=True) if mg.pet_count == 1: - import esmpy.test.regrid_from_file.test_regrid_from_file_dryrun + import esmpy.test.regrid_from_file.test_regrid_from_file_download # Read the test case parameters from the control file. print('Reading control file...') diff --git a/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py b/src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_download.py similarity index 100% rename from src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_dryrun.py rename to src/addon/ESMPy/src/esmpy/test/regrid_from_file/test_regrid_from_file_download.py From ba7f4523aa389eec575ad675a24a7b1190562ec2 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Mon, 12 Sep 2022 14:53:16 -0600 Subject: [PATCH 197/266] Add a unit test of rewriting an existing field The purpose of this test is to make sure that the code for checking consistency with an existing field works for multi-tile fields (at least in the case where they *are* consistent). --- .../IO/tests/ESMF_IO_MultitileUTest.F90 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 index 22cfa10e0c..d9069161c4 100644 --- a/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 +++ b/src/Infrastructure/IO/tests/ESMF_IO_MultitileUTest.F90 @@ -176,6 +176,22 @@ program ESMF_IO_MultitileUTest #endif !------------------------------------------------------------------------ + !------------------------------------------------------------------------ + !EX_UTest_Multi_Proc_Only + ! The purpose of this test is to make sure that the code for checking consistency with + ! an existing field works for multi-tile fields (at least in the case where they *are* + ! consistent). + write(name, *) "Rewrite an existing multi-tile Field to existing files" + write(failMsg, *) "Did not return ESMF_SUCCESS" + call ESMF_FieldWrite(field3, fileName=fileNameFields, overwrite=.true., rc=rc) +#if (defined ESMF_PIO && (defined ESMF_NETCDF || defined ESMF_PNETCDF)) + 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, *) "Read a multi-tile Field" From 9734584bcdd14ec2598fe19fbcd5fbad9fcb29f8 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Mon, 12 Sep 2022 14:00:00 -0700 Subject: [PATCH 198/266] Update README.md Wording. --- src/addon/ESMX/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMX/README.md b/src/addon/ESMX/README.md index 36985b7613..75febb4ed9 100644 --- a/src/addon/ESMX/README.md +++ b/src/addon/ESMX/README.md @@ -50,7 +50,7 @@ In this example two components are built into `esmx` explicitly. (Read about dyn Each component is given a name, here `tawas` and `lumo`. Components will be referred to by this *component-name* in the run-time configuration (esmxRun.config) discussed below. -Each component must define the `cmake_config` key, specifying a file that can be included by the CMake based `esmx` build. This file must specify three CMake elements: +Each component must define the `cmake_config` key, specifying a file that can be included by the CMake based `esmx` build. This file must provide three CMake elements: - `add_library(component-name ... )` - `set_target_properties(component-name ... )` - `target_link_libraries(esmx_driver PUBLIC component-name)` From a5f29dc291de57b5a2c12b631111af401c29b3d0 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 13 Sep 2022 08:28:10 -0700 Subject: [PATCH 199/266] Avoid __FILE__ in this layer to not run into line length issues across compilers. --- src/addon/ESMX/Driver/ESMX_Driver.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMX/Driver/ESMX_Driver.F90 b/src/addon/ESMX/Driver/ESMX_Driver.F90 index 6268f92dbc..b53f410a29 100644 --- a/src/addon/ESMX/Driver/ESMX_Driver.F90 +++ b/src/addon/ESMX/Driver/ESMX_Driver.F90 @@ -292,7 +292,7 @@ subroutine SetModelServices(driver, rc) call ESMF_GridCompGet(driver, clockIsPresent=isPresent, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & - file=__FILE__)) & + file=FILENAME)) & return ! bail out if (.not.isPresent) then From f62da39b32da8d8d2cc353150ecfdc5aac7c2764 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Tue, 13 Sep 2022 08:43:15 -0700 Subject: [PATCH 200/266] Escape "#" symbol with "\" for LaTeX. --- src/Infrastructure/Array/interface/ESMF_Array.F90 | 4 ++-- src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 | 4 ++-- .../ArrayBundle/interface/ESMF_ArrayBundle.F90 | 8 ++++---- src/Infrastructure/Field/src/ESMF_FieldPr.F90 | 4 ++-- src/Infrastructure/Field/src/ESMF_FieldWr.F90 | 4 ++-- .../FieldBundle/src/ESMF_FieldBundle.cppF90 | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Infrastructure/Array/interface/ESMF_Array.F90 b/src/Infrastructure/Array/interface/ESMF_Array.F90 index 67d212b2d8..693cc5f512 100644 --- a/src/Infrastructure/Array/interface/ESMF_Array.F90 +++ b/src/Infrastructure/Array/interface/ESMF_Array.F90 @@ -3868,9 +3868,9 @@ subroutine ESMF_ArrayWrite(array, fileName, keywordEnforcer, & ! \item[fileName] ! The name of the output file to which Array data is written. ! If this is a multi-tile Array, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being written to a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be written to +! example, for a fileName of "myfile\#.nc", tile 1 will be written to ! "myfile1.nc", tile 2 to "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] diff --git a/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 b/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 index c59f2c89db..f2ef0a028a 100644 --- a/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 +++ b/src/Infrastructure/Array/interface/ESMF_ArrayHa.F90 @@ -654,9 +654,9 @@ subroutine ESMF_ArrayRead(array, fileName, keywordEnforcer, variableName, & ! \item[fileName] ! The name of the file from which Array data is read. ! If this is a multi-tile Array, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being read from a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be read from +! example, for a fileName of "myfile\#.nc", tile 1 will be read from ! "myfile1.nc", tile 2 from "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] diff --git a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 index 126586014f..0ca67e1d31 100644 --- a/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 +++ b/src/Infrastructure/ArrayBundle/interface/ESMF_ArrayBundle.F90 @@ -1687,9 +1687,9 @@ subroutine ESMF_ArrayBundleRead(arraybundle, fileName, keywordEnforcer, & ! \item[fileName] ! The name of the file from which ArrayBundle data is read. ! If the ArrayBundle contains multi-tile Arrays, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being read from a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be read from +! example, for a fileName of "myfile\#.nc", tile 1 will be read from ! "myfile1.nc", tile 2 from "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[singleFile]}] @@ -3842,9 +3842,9 @@ subroutine ESMF_ArrayBundleWrite(arraybundle, fileName, keywordEnforcer, & ! \item[fileName] ! The name of the output file to which array bundle data is written. ! If the ArrayBundle contains multi-tile Arrays, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being written to a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be written to +! example, for a fileName of "myfile\#.nc", tile 1 will be written to ! "myfile1.nc", tile 2 to "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[convention]}] diff --git a/src/Infrastructure/Field/src/ESMF_FieldPr.F90 b/src/Infrastructure/Field/src/ESMF_FieldPr.F90 index de4e369cac..50225538cf 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldPr.F90 +++ b/src/Infrastructure/Field/src/ESMF_FieldPr.F90 @@ -251,9 +251,9 @@ subroutine ESMF_FieldRead(field, fileName, keywordEnforcer, & ! \item[fileName] ! The name of the file from which Field data is read. ! If the Field is a multi-tile Array, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being read from a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be read from +! example, for a fileName of "myfile\#.nc", tile 1 will be read from ! "myfile1.nc", tile 2 from "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] diff --git a/src/Infrastructure/Field/src/ESMF_FieldWr.F90 b/src/Infrastructure/Field/src/ESMF_FieldWr.F90 index f74ea6d354..3ee5f15e52 100644 --- a/src/Infrastructure/Field/src/ESMF_FieldWr.F90 +++ b/src/Infrastructure/Field/src/ESMF_FieldWr.F90 @@ -130,9 +130,9 @@ subroutine ESMF_FieldWrite(field, fileName, keywordEnforcer, & ! \item[fileName] ! The name of the output file to which Field data is written. ! If the Field is a multi-tile Array, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being written to a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be written to +! example, for a fileName of "myfile\#.nc", tile 1 will be written to ! "myfile1.nc", tile 2 to "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[variableName]}] diff --git a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 index 4b300ea2ca..56bdfc9b03 100644 --- a/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 +++ b/src/Infrastructure/FieldBundle/src/ESMF_FieldBundle.cppF90 @@ -2781,9 +2781,9 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! \item[fileName] ! The name of the file from which FieldBundle data is read. ! If the FieldBundle contains multi-tile Arrays, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being read from a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be read from +! example, for a fileName of "myfile\#.nc", tile 1 will be read from ! "myfile1.nc", tile 2 from "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[singleFile]}] @@ -6267,9 +6267,9 @@ type(ESMF_KeywordEnforcer), optional:: keywordEnforcer ! must use keywords for t ! \item[fileName] ! The name of the output file to which field bundle data is written. ! If the FieldBundle contains multi-tile Arrays, then fileName must contain -! exactly one instance of "#"; this is a placeholder that will be replaced +! exactly one instance of "\#"; this is a placeholder that will be replaced ! by the tile number, with each tile being written to a separate file. (For -! example, for a fileName of "myfile#.nc", tile 1 will be written to +! example, for a fileName of "myfile\#.nc", tile 1 will be written to ! "myfile1.nc", tile 2 to "myfile2.nc", etc.) ! (This handling of the fileName for multi-tile I/O is subject to change.) ! \item[{[convention]}] From 53b80f4bb797f62b67a02d4604b2a9a2d308a33c Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 14 Sep 2022 14:44:54 -0700 Subject: [PATCH 201/266] Set the Python version requirement to 3.5, since esmxGen.py depends on PyYAML, which is only available for Python 3.5+. --- src/addon/ESMX/Driver/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addon/ESMX/Driver/CMakeLists.txt b/src/addon/ESMX/Driver/CMakeLists.txt index c25e31d0e9..c346458d1b 100644 --- a/src/addon/ESMX/Driver/CMakeLists.txt +++ b/src/addon/ESMX/Driver/CMakeLists.txt @@ -16,7 +16,7 @@ target_include_directories(esmx_driver PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(esmx_driver PUBLIC ESMF) # Generate comp*.* files from esmxBuild.yaml -find_package(Python 3 COMPONENTS Interpreter REQUIRED) +find_package(Python 3.5 COMPONENTS Interpreter REQUIRED) execute_process(COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/esmxGen.py --ifile ./esmxBuild.yaml --odir ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE ret) From e760d02ce019cc1f5039b10419112b08d1193ae0 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 14 Sep 2022 15:26:21 -0700 Subject: [PATCH 202/266] - Better reporting of ESMF beta tags. - For now do not define CMake install for ESMX. --- src/addon/ESMX/CMakeLists.txt | 1 - src/addon/ESMX/Driver/cmake/FindESMF.cmake | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/addon/ESMX/CMakeLists.txt b/src/addon/ESMX/CMakeLists.txt index e9f63e9039..cfcc852070 100644 --- a/src/addon/ESMX/CMakeLists.txt +++ b/src/addon/ESMX/CMakeLists.txt @@ -6,7 +6,6 @@ add_subdirectory(Driver) # Specific project settings project(ESMX VERSION 0.1.0) add_executable(esmx esmx.F90) -install(TARGETS esmx) target_include_directories(esmx PUBLIC ${PROJECT_BINARY_DIR}) target_link_libraries(esmx PUBLIC esmx_driver) diff --git a/src/addon/ESMX/Driver/cmake/FindESMF.cmake b/src/addon/ESMX/Driver/cmake/FindESMF.cmake index 4b7dcf4c3a..161654428d 100644 --- a/src/addon/ESMX/Driver/cmake/FindESMF.cmake +++ b/src/addon/ESMX/Driver/cmake/FindESMF.cmake @@ -78,14 +78,14 @@ if(EXISTS ${ESMFMKFILE}) set(ESMF_BETA_RELEASE FALSE) if(ESMF_VERSION_BETASNAPSHOT MATCHES "^('T')$") set(ESMF_BETA_RELEASE TRUE) - if(ESMF_VERSION_STRING_GIT MATCHES "^ESMF.*beta_snapshot_[0-9]") - string(REGEX REPLACE "^ESMF.*beta_snapshot_\([0-9]*\).*" "\\1" ESMF_BETA_SNAPSHOT "${ESMF_VERSION_STRING_GIT}") - elseif(ESMF_VERSION_STRING_GIT MATCHES "^v.*b[0-9]") - string(REGEX REPLACE "^v.*b\([0-9]*\).*" "\\1" ESMF_BETA_SNAPSHOT "${ESMF_VERSION_STRING_GIT}") + if(ESMF_VERSION_STRING_GIT MATCHES "^ESMF.*beta_snapshot") + set(ESMF_BETA_SNAPSHOT ${ESMF_VERSION_STRING_GIT}) + elseif(ESMF_VERSION_STRING_GIT MATCHES "^v.\..\..b") + set(ESMF_BETA_SNAPSHOT ${ESMF_VERSION_STRING_GIT}) else() set(ESMF_BETA_SNAPSHOT 0) endif() - message(STATUS "Detected ESMF Beta snapshot ${ESMF_BETA_SNAPSHOT}") + message(STATUS "Detected ESMF Beta snapshot: ${ESMF_BETA_SNAPSHOT}") endif() set(ESMF_VERSION "${ESMF_VERSION_MAJOR}.${ESMF_VERSION_MINOR}.${ESMF_VERSION_PATCH}") From 4d665c296aad06f4db680ceb1e5d1a940f48e386 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Wed, 14 Sep 2022 16:00:44 -0700 Subject: [PATCH 203/266] Switch to FindPythonInterp which is supported back down to CMake 3.5.2, which is the lowest supported by ESMX. --- src/addon/ESMX/Driver/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/addon/ESMX/Driver/CMakeLists.txt b/src/addon/ESMX/Driver/CMakeLists.txt index c346458d1b..7a13493abd 100644 --- a/src/addon/ESMX/Driver/CMakeLists.txt +++ b/src/addon/ESMX/Driver/CMakeLists.txt @@ -16,8 +16,9 @@ target_include_directories(esmx_driver PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(esmx_driver PUBLIC ESMF) # Generate comp*.* files from esmxBuild.yaml -find_package(Python 3.5 COMPONENTS Interpreter REQUIRED) -execute_process(COMMAND ${Python_EXECUTABLE} +list(APPEND Python_ADDITIONAL_VERSIONS 3.5) +find_package(PythonInterp) +execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/esmxGen.py --ifile ./esmxBuild.yaml --odir ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE ret) if(ret EQUAL "1") From 5c566101b0d97bd09621d920bcb324477fa96789 Mon Sep 17 00:00:00 2001 From: Gerhard Theurich Date: Thu, 15 Sep 2022 09:11:30 -0700 Subject: [PATCH 204/266] Update README.md Add list of dependencies for ESMX: CMake, Python, PyYaml. --- src/addon/ESMX/README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/addon/ESMX/README.md b/src/addon/ESMX/README.md index 75febb4ed9..e99801143e 100644 --- a/src/addon/ESMX/README.md +++ b/src/addon/ESMX/README.md @@ -129,7 +129,6 @@ The typical situation where `ESMX_Driver` comes into play is where a user applic # Specific project settings project(ExternalDriverAPIProto VERSION 0.1.0) add_executable(externalApp externalApp.F90) - install(TARGETS externalApp) target_include_directories(externalApp PUBLIC ${PROJECT_BINARY_DIR}) target_link_libraries(externalApp PUBLIC esmx_driver) @@ -152,3 +151,20 @@ The run-time configuration needed by `ESMX_Driver` can either be supplied by the - The `ESMX_component_list`, child component, and run sequence information is ingested from `config` as described under the [unfied driver executable section](#esmxrunconfig). - If the parent level passes an `ESMF_Clock` object to `ESMX_Driver` during initialize, the driver uses it instead of looking for `startTime` and `stopTime` in `config`. - For the case where a clock is provided by the parent layer, its `timeStep` is used as the *default* time step of the outer run sequence loop when using the `@*` syntax. If a specific time step is set in the run sequence with `@DT`, then `DT` must be a divisor of the `timeStep` provided by the parent clock. + +## ESMX Software Dependencies + +The ESMX layer has the following dependencies: +- **ESMF Library**: The ESMX layer is part of the ESMF repository. In order to use ESMX as described above, the ESMF library first needs to be built following the instructions for [Building ESMF](https://github.com/esmf-org/esmf#building-esmf). +- **CMake**: v3.5.2 or greater. +- **Python**: v3.5 or greater. + - Available as `python3` in `$PATH`. + - `PyYaml` module installed in the Python environment. + +There are many ways to provide a suitable Python environment. One portable way based on [venv](https://docs.python.org/3/library/venv.html) is shown below. + + python3 -m venv ESMXenv + source ESMXenv/bin/activate (for Bash) or source ESMXenv/bin/activate.csh (for Csh) + pip install pyyaml + ... Environment ready for ESMX ... + deactivate From 2692d550ab86052b718eaf0e30caf4d7f0b1e918 Mon Sep 17 00:00:00 2001 From: Bill Sacks Date: Thu, 15 Sep 2022 11:26:03 -0600 Subject: [PATCH 205/266] Update json library from v3.7.3 to v3.11.2 --- .../Base/include/nlohmann/json/LICENSE.MIT | 2 +- .../Base/include/nlohmann/json/README.md | 6 +- .../Base/include/nlohmann/json/json.hpp | 25141 +++++++++------- 3 files changed, 13436 insertions(+), 11713 deletions(-) diff --git a/src/Infrastructure/Base/include/nlohmann/json/LICENSE.MIT b/src/Infrastructure/Base/include/nlohmann/json/LICENSE.MIT index db73c5f7d6..1c1f7a690d 100644 --- a/src/Infrastructure/Base/include/nlohmann/json/LICENSE.MIT +++ b/src/Infrastructure/Base/include/nlohmann/json/LICENSE.MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2013-2019 Niels Lohmann +Copyright (c) 2013-2022 Niels Lohmann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Infrastructure/Base/include/nlohmann/json/README.md b/src/Infrastructure/Base/include/nlohmann/json/README.md index 1ca7582aae..6e4a83fb56 100644 --- a/src/Infrastructure/Base/include/nlohmann/json/README.md +++ b/src/Infrastructure/Base/include/nlohmann/json/README.md @@ -1,7 +1,7 @@ # JSON for Modern C++ * URL: https://github.com/nlohmann/json -* Release: v3.7.3 +* Release: v3.11.2 * Git Clone Command: `git clone -b --depth 1 ` ## Updating to New Version @@ -17,4 +17,6 @@ * Added initial code (v3.2.0) to ESMF Attribute directory * Added `README.md` describing how to bring in additional versions * 2020-03-02, Ben Koziol - * Updated `nlohmann/json` to tag `v3.7.3`. \ No newline at end of file + * Updated `nlohmann/json` to tag `v3.7.3`. +* 2022-09-15, Bill Sacks + * Updated `nlohmann/json` to tag `v3.11.2`. diff --git a/src/Infrastructure/Base/include/nlohmann/json/json.hpp b/src/Infrastructure/Base/include/nlohmann/json/json.hpp index 7629ff7bbe..4d1a37ad7c 100644 --- a/src/Infrastructure/Base/include/nlohmann/json/json.hpp +++ b/src/Infrastructure/Base/include/nlohmann/json/json.hpp @@ -1,46 +1,30 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.7.3 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2013-2019 Niels Lohmann . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ #ifndef INCLUDE_NLOHMANN_JSON_HPP_ #define INCLUDE_NLOHMANN_JSON_HPP_ -#define NLOHMANN_JSON_VERSION_MAJOR 3 -#define NLOHMANN_JSON_VERSION_MINOR 7 -#define NLOHMANN_JSON_VERSION_PATCH 3 - #include // all_of, find, for_each -#include // assert -#include // and, not, or #include // nullptr_t, ptrdiff_t, size_t #include // hash, less #include // initializer_list -#include // istream, ostream +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr #include // accumulate @@ -49,16 +33,133 @@ SOFTWARE. #include // vector // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // transform #include // array -#include // and, not #include // forward_list #include // inserter, front_inserter, end #include // map @@ -70,63 +171,169 @@ SOFTWARE. #include // valarray // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include // nullptr_t #include // exception #include // runtime_error #include // to_string +#include // vector -// #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include // array #include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + -namespace nlohmann +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void { + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -/// struct to capture the start position of the current token -struct position_t + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch { - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; }; -} // namespace detail -} // namespace nlohmann +template class Op, class... Args> +using is_detected = typename detector::value_t; -// #include +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END -#include // pair // #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + /* Hedley - https://nemequ.github.io/hedley * Created by Evan Nemerson - * - * To the extent possible under law, the author(s) have dedicated all - * copyright and related and neighboring rights to this software to - * the public domain worldwide. This software is distributed without - * any warranty. - * - * For details, see . - * SPDX-License-Identifier: CC0-1.0 */ -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 11) +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) #if defined(JSON_HEDLEY_VERSION) #undef JSON_HEDLEY_VERSION #endif -#define JSON_HEDLEY_VERSION 11 +#define JSON_HEDLEY_VERSION 15 #if defined(JSON_HEDLEY_STRINGIFY_EX) #undef JSON_HEDLEY_STRINGIFY_EX @@ -148,6 +355,16 @@ struct position_t #endif #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + #if defined(JSON_HEDLEY_VERSION_ENCODE) #undef JSON_HEDLEY_VERSION_ENCODE #endif @@ -189,18 +406,18 @@ struct position_t #if defined(JSON_HEDLEY_MSVC_VERSION) #undef JSON_HEDLEY_MSVC_VERSION #endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) && !defined(__ICL) #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) #endif #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) #undef JSON_HEDLEY_MSVC_VERSION_CHECK #endif -#if !defined(_MSC_VER) +#if !defined(JSON_HEDLEY_MSVC_VERSION) #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) #elif defined(_MSC_VER) && (_MSC_VER >= 1400) #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) @@ -213,9 +430,9 @@ struct position_t #if defined(JSON_HEDLEY_INTEL_VERSION) #undef JSON_HEDLEY_INTEL_VERSION #endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) #endif @@ -228,6 +445,22 @@ struct position_t #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) #endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + #if defined(JSON_HEDLEY_PGI_VERSION) #undef JSON_HEDLEY_PGI_VERSION #endif @@ -323,9 +556,17 @@ struct position_t #if defined(JSON_HEDLEY_TI_VERSION) #undef JSON_HEDLEY_TI_VERSION #endif -#if defined(__TI_COMPILER_VERSION__) +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif +#endif #if defined(JSON_HEDLEY_TI_VERSION_CHECK) #undef JSON_HEDLEY_TI_VERSION_CHECK @@ -336,6 +577,102 @@ struct position_t #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) #endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + #if defined(JSON_HEDLEY_CRAY_VERSION) #undef JSON_HEDLEY_CRAY_VERSION #endif @@ -363,7 +700,7 @@ struct position_t #if __VER__ > 1000 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) #endif #endif @@ -440,17 +777,41 @@ struct position_t #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) #endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + #if defined(JSON_HEDLEY_GCC_VERSION) #undef JSON_HEDLEY_GCC_VERSION #endif #if \ defined(JSON_HEDLEY_GNUC_VERSION) && \ - !(defined(__clang__) && !defined(__INTEL_COMPILER)) && \ + !defined(__clang__) && \ !defined(JSON_HEDLEY_INTEL_VERSION) && \ !defined(JSON_HEDLEY_PGI_VERSION) && \ !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(__COMPCERT__) + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION #endif @@ -466,17 +827,21 @@ struct position_t #if defined(JSON_HEDLEY_HAS_ATTRIBUTE) #undef JSON_HEDLEY_HAS_ATTRIBUTE #endif -#if defined(__has_attribute) - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) #else - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) #else #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif @@ -485,7 +850,7 @@ struct position_t #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) #else #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif @@ -509,6 +874,7 @@ struct position_t #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) #elif \ !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) @@ -669,30 +1035,21 @@ struct position_t #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -#else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - #if \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__clang__) && !defined(__INTEL_COMPILER)) || \ + defined(__clang__) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ @@ -710,7 +1067,7 @@ struct position_t #if defined(JSON_HEDLEY_DIAGNOSTIC_POP) #undef JSON_HEDLEY_DIAGNOSTIC_POP #endif -#if (defined(__clang__) && !defined(__INTEL_COMPILER)) +#if defined(__clang__) #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) @@ -719,13 +1076,21 @@ struct position_t #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif JSON_HEDLEY_TI_VERSION_CHECK(8,1,0) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) @@ -736,50 +1101,173 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_POP #endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ #endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") #else #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #endif @@ -793,14 +1281,25 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") #else #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES #endif @@ -818,39 +1317,73 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + #if defined(JSON_HEDLEY_DEPRECATED) #undef JSON_HEDLEY_DEPRECATED #endif #if defined(JSON_HEDLEY_DEPRECATED_FOR) #undef JSON_HEDLEY_DEPRECATED_FOR #endif -#if defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) #elif \ - JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,3,0) + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) @@ -867,7 +1400,8 @@ struct position_t #if \ JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) #else #define JSON_HEDLEY_UNAVAILABLE(available_since) @@ -876,21 +1410,41 @@ struct position_t #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) #undef JSON_HEDLEY_WARN_UNUSED_RESULT #endif -#if defined(__cplusplus) && (__cplusplus >= 201703L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif \ +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #elif defined(_Check_return_) /* SAL */ #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ #else #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) #endif #if defined(JSON_HEDLEY_SENTINEL) @@ -900,7 +1454,8 @@ struct position_t JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) #else #define JSON_HEDLEY_SENTINEL(position) @@ -911,7 +1466,9 @@ struct position_t #endif #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_NO_RETURN __noreturn -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define JSON_HEDLEY_NO_RETURN _Noreturn @@ -923,14 +1480,26 @@ struct position_t JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) @@ -955,54 +1524,57 @@ struct position_t #if defined(JSON_HEDLEY_UNREACHABLE_RETURN) #undef JSON_HEDLEY_UNREACHABLE_RETURN #endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) - #define JSON_HEDLEY_UNREACHABLE() __assume(0) -#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_UNREACHABLE() std::_nassert(0) - #else - #define JSON_HEDLEY_UNREACHABLE() _nassert(0) - #endif - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value -#elif defined(EXIT_FAILURE) - #define JSON_HEDLEY_UNREACHABLE() abort() -#else - #define JSON_HEDLEY_UNREACHABLE() - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() -#endif - #if defined(JSON_HEDLEY_ASSUME) #undef JSON_HEDLEY_ASSUME #endif #if \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_ASSUME(expr) __assume(expr) #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) #if defined(__cplusplus) #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) #else #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) #endif -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && !defined(JSON_HEDLEY_ARM_VERSION)) || \ +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) - #define JSON_HEDLEY_ASSUME(expr) ((void) ((expr) ? 1 : (__builtin_unreachable(), 1))) + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif #else - #define JSON_HEDLEY_ASSUME(expr) ((void) (expr)) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) #endif JSON_HEDLEY_DIAGNOSTIC_PUSH @@ -1013,7 +1585,7 @@ JSON_HEDLEY_DIAGNOSTIC_PUSH #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #endif #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if (defined(__clang__) && !defined(__INTEL_COMPILER)) + #if defined(__clang__) #pragma clang diagnostic ignored "-Wvariadic-macros" #elif defined(JSON_HEDLEY_GCC_VERSION) #pragma GCC diagnostic ignored "-Wvariadic-macros" @@ -1046,8 +1618,18 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) @@ -1080,44 +1662,50 @@ JSON_HEDLEY_DIAGNOSTIC_POP #undef JSON_HEDLEY_UNPREDICTABLE #endif #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable(!!(expr)) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) #endif #if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(expr, value, probability) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, probability) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, probability) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#if !defined(JSON_HEDLEY_BUILTIN_UNPREDICTABLE) - #define JSON_HEDLEY_BUILTIN_UNPREDICTABLE(expr) __builtin_expect_with_probability(!!(expr), 1, 0.5) -#endif + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) #elif \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) # define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect(!!(expr), (expected)) : (((void) (expected)), !!(expr))) + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ (__extension__ ({ \ - JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + double hedley_probability_ = (probability); \ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ })) # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ (__extension__ ({ \ - JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + double hedley_probability_ = (probability); \ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ })) # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) #else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (((void) (expected)), !!(expr)) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) # define JSON_HEDLEY_LIKELY(expr) (!!(expr)) @@ -1137,12 +1725,24 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_MALLOC __declspec(restrict) #else #define JSON_HEDLEY_MALLOC @@ -1152,22 +1752,37 @@ JSON_HEDLEY_DIAGNOSTIC_POP #undef JSON_HEDLEY_PURE #endif #if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_PURE __attribute__((__pure__)) + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") #else - #define JSON_HEDLEY_PURE +# define JSON_HEDLEY_PURE #endif #if defined(JSON_HEDLEY_CONST) @@ -1180,9 +1795,19 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_CONST __attribute__((__const__)) #elif \ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) @@ -1200,13 +1825,18 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - (defined(__clang__) && !defined(__INTEL_COMPILER)) + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_RESTRICT __restrict #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) #define JSON_HEDLEY_RESTRICT _Restrict @@ -1227,8 +1857,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_HEDLEY_INLINE __inline__ #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_INLINE __inline #else #define JSON_HEDLEY_INLINE @@ -1238,23 +1875,44 @@ JSON_HEDLEY_DIAGNOSTIC_POP #undef JSON_HEDLEY_ALWAYS_INLINE #endif #if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) - #define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) - #define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif JSON_HEDLEY_TI_VERSION_CHECK(7,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") #else - #define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE #endif #if defined(JSON_HEDLEY_NEVER_INLINE) @@ -1267,14 +1925,27 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") @@ -1296,26 +1967,32 @@ JSON_HEDLEY_DIAGNOSTIC_POP #undef JSON_HEDLEY_IMPORT #endif #if defined(_WIN32) || defined(__CYGWIN__) - #define JSON_HEDLEY_PRIVATE - #define JSON_HEDLEY_PUBLIC __declspec(dllexport) - #define JSON_HEDLEY_IMPORT __declspec(dllimport) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) #else - #if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_EABI__) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) - #define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) - #define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) - #else - #define JSON_HEDLEY_PRIVATE - #define JSON_HEDLEY_PUBLIC - #endif - #define JSON_HEDLEY_IMPORT extern +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern #endif #if defined(JSON_HEDLEY_NO_THROW) @@ -1324,10 +2001,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if \ JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) #define JSON_HEDLEY_NO_THROW __declspec(nothrow) #else @@ -1337,7 +2016,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_FALL_THROUGH) #undef JSON_HEDLEY_FALL_THROUGH #endif -#if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) @@ -1354,7 +2036,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) #elif defined(_Ret_notnull_) /* SAL */ #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ @@ -1394,9 +2077,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) #endif #if !defined(__cplusplus) @@ -1415,8 +2099,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) #endif # elif \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ @@ -1431,8 +2119,13 @@ JSON_HEDLEY_DIAGNOSTIC_POP defined(JSON_HEDLEY_GCC_VERSION) || \ defined(JSON_HEDLEY_INTEL_VERSION) || \ defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_VERSION) || \ - (defined(__clang__) && !defined(__INTEL_COMPILER)) + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ sizeof(void) != \ sizeof(*( \ @@ -1481,7 +2174,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if \ !defined(__cplusplus) && ( \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ defined(_Static_assert) \ @@ -1490,58 +2183,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP #elif \ (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)) + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) #else # define JSON_HEDLEY_STATIC_ASSERT(expr, message) #endif -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (*((T*) &(expr))) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_CPP_CAST(T, expr) static_cast(expr) -#else - #define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - #if defined(JSON_HEDLEY_NULL) #undef JSON_HEDLEY_NULL #endif @@ -1593,9 +2240,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_DIAGNOSTIC_POP #elif \ JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) #else # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) @@ -1631,8 +2281,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_FLAGS) #undef JSON_HEDLEY_FLAGS #endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS #endif #if defined(JSON_HEDLEY_FLAGS_CAST) @@ -1652,7 +2304,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_EMPTY_BASES) #undef JSON_HEDLEY_EMPTY_BASES #endif -#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) #else #define JSON_HEDLEY_EMPTY_BASES @@ -1663,7 +2317,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK #endif -#if (defined(__clang__) && !defined(__INTEL_COMPILER)) +#if defined(__clang__) #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) #else #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) @@ -1707,12 +2361,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ -// This file contains all internal macro definitions +// This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them +// #include + + // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if (defined(__clang__) && !defined(__INTEL_COMPILER)) + #if defined(__clang__) #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif @@ -1724,26 +2381,128 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif // C++ language standard detection -#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 #endif -// disable float-equal warnings on GCC/clang -#if (defined(__clang__) && !defined(__INTEL_COMPILER)) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" +#ifdef __has_include + #if __has_include() + #include + #endif #endif -// disable documentation warnings on clang -#if (defined(__clang__) && !defined(__INTEL_COMPILER)) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdocumentation" -#endif +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif -// allow to disable exceptions + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) #define JSON_THROW(exception) throw exception #define JSON_TRY try @@ -1777,6 +2536,19 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER #endif +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + /*! @brief macro to briefly define a mapping between an enum and JSON @def NLOHMANN_JSON_SERIALIZE_ENUM @@ -1817,413 +2589,603 @@ JSON_HEDLEY_DIAGNOSTIC_POP class StringType, class BooleanType, class NumberIntegerType, \ class NumberUnsignedType, class NumberFloatType, \ template class AllocatorType, \ - template class JSONSerializer> + template class JSONSerializer, \ + class BinaryType> #define NLOHMANN_BASIC_JSON_TPL \ basic_json + AllocatorType, JSONSerializer, BinaryType> + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } -namespace nlohmann -{ -namespace detail -{ -//////////////// -// exceptions // -//////////////// +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } /*! -@brief general exception of the @ref basic_json class +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } -This class is an extension of `std::exception` objects with a member @a id for -exception ids. It is used as the base class for all exceptions thrown by the -@ref basic_json class. This class can hence be used as "wildcard" to catch -exceptions. +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } -Subclasses: -- @ref parse_error for exceptions indicating a parse error -- @ref invalid_iterator for exceptions indicating errors with iterators -- @ref type_error for exceptions indicating executing a member function with - a wrong type -- @ref out_of_range for exceptions indicating access out of the defined range -- @ref other_error for exceptions indicating other library errors -@internal -@note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. -@endinternal +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif -@liveexample{The following code shows how arbitrary library exceptions can be -caught.,exception} +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif -@since version 3.0.0 -*/ -class exception : public std::exception +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail { - public: - /// returns the explanatory string - JSON_HEDLEY_RETURNS_NON_NULL - const char* what() const noexcept override - { - return m.what(); - } - /// the id of the exception - const int id; +/////////////////////////// +// JSON type enumeration // +/////////////////////////// - protected: - JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} +/*! +@brief the JSON type enumeration - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. - private: - /// an exception object as storage for error messages - std::runtime_error m; +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function }; /*! -@brief exception indicating a parse error - -This exception is thrown by the library when a parse error occurs. Parse errors -can occur during the deserialization of JSON text, CBOR, MessagePack, as well -as when using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -Exceptions have ids 1xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. -json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). - -@note For an input with n bytes, 1 is the index of the first character and n+1 - is the index of the terminating null byte or the end of file. This also - holds true when reading a byte vector (CBOR or MessagePack). - -@liveexample{The following code shows how a `parse_error` exception can be -caught.,parse_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 */ -class parse_error : public exception +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif { - public: - /*! - @brief create a parse error exception - @param[in] id_ the id of the exception - @param[in] pos the position where the error occurred (or with - chars_read_total=0 if the position cannot be - determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - static parse_error create(int id_, const position_t& pos, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id_, byte_, w.c_str()); + return order[l_index] <=> order[r_index]; // *NOPAD* } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} - /*! - @brief byte index of the parse error +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif - The byte index of the last read character in the input file. +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END - @note For an input with n bytes, 1 is the index of the first character and - n+1 is the index of the terminating null byte or the end of file. - This also holds true when reading a byte vector (CBOR or MessagePack). - */ - const std::size_t byte; +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; -/*! -@brief exception indicating errors with iterators - -This exception is thrown if iterators passed to a library function do not match -the expected semantics. - -Exceptions have ids 2xx. - -name / id | example message | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@liveexample{The following code shows how an `invalid_iterator` exception can be -caught.,invalid_iterator} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class invalid_iterator : public exception -{ - public: - static invalid_iterator create(int id_, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id_) + what_arg; - return invalid_iterator(id_, w.c_str()); - } +// #include - private: - JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} -}; + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ /*! -@brief exception indicating executing a member function with a wrong type - -This exception is thrown in case of a type error; that is, a library function is -executed on a JSON value whose type does not match the expected semantics. - -Exceptions have ids 3xx. - -name / id | example message | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. -json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | -json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | - -@liveexample{The following code shows how a `type_error` exception can be -caught.,type_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 */ -class type_error : public exception +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) { - public: - static type_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("type_error", id_) + what_arg; - return type_error(id_, w.c_str()); - } + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} - private: - JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} /*! -@brief exception indicating access out of the defined range - -This exception is thrown in case a library function is called on an input -parameter that exceeds the expected range, for instance in case of array -indices or nonexisting object keys. - -Exceptions have ids 4xx. - -name / id | example message | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | -json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | -json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | - -@liveexample{The following code shows how an `out_of_range` exception can be -caught.,out_of_range} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class out_of_range : public exception + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) { - public: - static out_of_range create(int id_, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id_) + what_arg; - return out_of_range(id_, w.c_str()); - } + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} - private: - JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -/*! -@brief exception indicating other library errors -This exception is thrown in case of errors that cannot be classified with the -other exception types. -Exceptions have ids 5xx. +#include // size_t -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. +// #include -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@liveexample{The following code shows how an `other_error` exception can be -caught.,other_error} +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ -@since version 3.0.0 -*/ -class other_error : public exception +/// struct to capture the start position of the current token +struct position_t { - public: - static other_error create(int id_, const std::string& what_arg) + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const { - std::string w = exception::name("other_error", id_) + what_arg; - return other_error(id_, w.c_str()); + return chars_read_total; } - - private: - JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT -#include // not + +#include // array #include // size_t #include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for -namespace nlohmann -{ +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; template using uncvref_t = typename std::remove_cv::type>::type; -// implementation of C++14 index_sequence and affiliates -// source: https://stackoverflow.com/a/32223343 -template -struct index_sequence -{ - using type = index_sequence; - using value_type = std::size_t; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; +#ifdef JSON_HAS_CPP_14 -template -struct merge_and_renumber; +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; -template -struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; +#else -template -struct make_index_sequence - : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > {}; +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal -template<> struct make_index_sequence<0> : index_sequence<> {}; -template<> struct make_index_sequence<1> : index_sequence<0> {}; +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; -template +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template using index_sequence_for = make_index_sequence; +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + // dispatch utility (taken from ranges-v3) template struct priority_tag : priority_tag < N - 1 > {}; template<> struct priority_tag<0> {}; @@ -2232,53 +3194,67 @@ template<> struct priority_tag<0> {}; template struct static_const { - static constexpr T value{}; + static JSON_INLINE_VARIABLE constexpr T value{}; }; -template -constexpr T static_const::value; +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + -#include // not #include // numeric_limits #include // false_type, is_constructible, is_integral, is_same, true_type #include // declval +#include // tuple // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -#include // random_access_iterator_tag -// #include +#include // random_access_iterator_tag +// #include -namespace nlohmann -{ -namespace detail -{ -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann +// #include // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -template + +template struct iterator_types {}; -template +template struct iterator_types < It, void_t +template struct iterator_traits { }; -template +template struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> : iterator_types { }; -template +template struct iterator_traits::value>> { using iterator_category = std::random_access_iterator_tag; @@ -2313,143 +3289,135 @@ struct iterator_traits::value>> using pointer = T*; using reference = T&; }; -} // namespace detail -} // namespace nlohmann + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // #include -// #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -// #include -#include +// #include -// #include +NLOHMANN_JSON_NAMESPACE_BEGIN -// http://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ -namespace detail -{ -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; +NLOHMANN_JSON_NAMESPACE_END -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -template