Skip to content

Commit

Permalink
Add Array IO unit tests that cover more types and run with mpiuni
Browse files Browse the repository at this point in the history
The existing Array IO unit tests don't run with mpiuni. The main
motivation for adding these is to add testing of I/O via PIO with
mpiuni. I especially want to cover all data types to make sure that the
mpiuni handling of different data types - and other I/O handling of
different data types - is working correctly.
  • Loading branch information
billsacks committed Jul 13, 2024
1 parent 2afdc55 commit 7133ea3
Show file tree
Hide file tree
Showing 3 changed files with 296 additions and 1 deletion.
282 changes: 282 additions & 0 deletions src/Infrastructure/Array/tests/ESMF_ArrayIOTypesUTest.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
! $Id$
!
! Earth System Modeling Framework
! Copyright (c) 2002-2024, 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_ArrayIOTypesUTest

!------------------------------------------------------------------------------

#include "ESMF.h"

!==============================================================================
!BOP
! !PROGRAM: ESMF_ArrayIOTypesUTest - Tests ArrayWrite() and ArrayRead() on available types
!
! !DESCRIPTION:
! There are two purposes of this program that go beyond what's in ESMF_ArrayIOUTest:
!
! (1) This covers writing and reading additional data types
!
! (2) This works with mpiuni as well as with a real mpi library, and so adds more I/O coverage with mpiuni
!
!-----------------------------------------------------------------------------
! !USES:
use ESMF_TestMod ! test methods
use ESMF

! -------------------------------------------------------------------------
! -- The sole purpose of the netcdf/pnetcdf use statements is to trigger a
! -- compile-time error in case the ESMF module above were to "leak" NetCDF
! -- symbols.
#if (defined ESMF_NETCDF)
use netcdf, only: nf90_nowrite, nf90_noerr
#elif (defined ESMF_PNETCDF)
use pnetcdf, only: nf90_nowrite, nf90_noerr
#endif
! -------------------------------------------------------------------------

implicit none

!-------------------------------------------------------------------------
!=========================================================================

! cumulative result: count failures; no failures equals "all pass"
integer :: result = 0

! individual test failure message
character(ESMF_MAXSTR) :: failMsg
character(ESMF_MAXSTR) :: name

! local variables
type(ESMF_VM):: vm
integer :: rc
integer :: localPet, petCount
type(ESMF_DistGrid) :: distgrid
type(ESMF_Array) :: arrayInt, arrayFloat, arrayDouble
type(ESMF_Array) :: arrayIntRead, arrayFloatRead, arrayDoubleRead
integer, pointer :: arrayIntData(:,:), arrayIntReadData(:,:)
real(ESMF_KIND_R4), pointer :: arrayFloatData(:,:), arrayFloatReadData(:,:)
real(ESMF_KIND_R8), pointer :: arrayDoubleData(:,:), arrayDoubleReadData(:,:)
logical :: allEqual

character(len=*), parameter :: fileName = "ESMF_ArrayIOTypesUTest.nc"

!------------------------------------------------------------------------
call ESMF_TestStart(ESMF_SRCLINE, rc=rc) ! calls ESMF_Initialize() internally
if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT)
!------------------------------------------------------------------------

! Set up
! *******
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)

!------------------------------------------------------------------------
!NEX_UTest
write(name, *) "Create Arrays"
write(failMsg, *) "Did not return ESMF_SUCCESS"
call createArrays(rc)
call ESMF_Test((rc.eq.ESMF_SUCCESS), name, failMsg, result, ESMF_SRCLINE)
!------------------------------------------------------------------------

!------------------------------------------------------------------------
!NEX_UTest
write(name, *) "Write an I4 Array"
write(failMsg, *) "Did not return ESMF_SUCCESS"
call ESMF_ArrayWrite(arrayInt, 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
!------------------------------------------------------------------------

!------------------------------------------------------------------------
!NEX_UTest
write(name, *) "Write an R4 Array"
write(failMsg, *) "Did not return ESMF_SUCCESS"
call ESMF_ArrayWrite(arrayFloat, 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
!------------------------------------------------------------------------

!------------------------------------------------------------------------
!NEX_UTest
write(name, *) "Write an R8 Array"
write(failMsg, *) "Did not return ESMF_SUCCESS"
call ESMF_ArrayWrite(arrayDouble, 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
!------------------------------------------------------------------------

!------------------------------------------------------------------------
!NEX_UTest
write(name, *) "Read an I4 Array"
write(failMsg, *) "Did not return ESMF_SUCCESS"
call ESMF_ArrayRead(arrayIntRead, 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
write(name, *) "Read an R4 Array"
write(failMsg, *) "Did not return ESMF_SUCCESS"
call ESMF_ArrayRead(arrayFloatRead, 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
write(name, *) "Read an R8 Array"
write(failMsg, *) "Did not return ESMF_SUCCESS"
call ESMF_ArrayRead(arrayDoubleRead, 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
write(name, *) "Confirm that Array-read array matches original for I4 Array"
write(failMsg, *) "Read-in array differs from original"
allEqual = all(arrayIntReadData == arrayIntData)
#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
!------------------------------------------------------------------------

!------------------------------------------------------------------------
!NEX_UTest
write(name, *) "Confirm that Array-read array matches original for R4 Array"
write(failMsg, *) "Read-in array differs from original"
allEqual = all(arrayFloatReadData == arrayFloatData)
#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
!------------------------------------------------------------------------

!------------------------------------------------------------------------
!NEX_UTest
write(name, *) "Confirm that Array-read array matches original for R8 Array"
write(failMsg, *) "Read-in array differs from original"
allEqual = all(arrayDoubleReadData == arrayDoubleData)
#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
!------------------------------------------------------------------------

!------------------------------------------------------------------------
call ESMF_TestEnd(ESMF_SRCLINE) ! calls ESMF_Finalize() internally
!------------------------------------------------------------------------

contains

subroutine createArrays(rc)
! Creates Arrays used by the tests used in this module
integer, intent(out) :: rc

type(ESMF_ArraySpec) :: arraySpecInt
type(ESMF_ArraySpec) :: arraySpecFloat
type(ESMF_ArraySpec) :: arraySpecDouble
integer :: i, j

distgrid = ESMF_DistGridCreate(minIndex=[1,1], maxIndex=[3*petCount,4], regDecomp=[petCount,1], rc=rc)
if (rc /= ESMF_SUCCESS) return

call ESMF_ArraySpecSet(arraySpecInt, typekind=ESMF_TYPEKIND_I4, rank=2, rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArraySpecSet(arraySpecFloat, typekind=ESMF_TYPEKIND_R4, rank=2, rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArraySpecSet(arraySpecDouble, typekind=ESMF_TYPEKIND_R8, rank=2, rc=rc)
if (rc /= ESMF_SUCCESS) return

arrayInt = ESMF_ArrayCreate(distgrid, arraySpecInt, name="arrayInt", rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArrayGet(arrayInt, farrayPtr=arrayIntData, rc=rc)
if (rc /= ESMF_SUCCESS) return
do j = 1, size(arrayIntData, 2)
do i = 1, size(arrayIntData, 1)
arrayIntData(i,j) = (localPet+1) * 17 * ((i-1)*size(arrayIntData,2) + (j-1))
end do
end do

arrayIntRead = ESMF_ArrayCreate(distgrid, arraySpecInt, name="arrayInt", rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArrayGet(arrayIntRead, farrayPtr=arrayIntReadData, rc=rc)
if (rc /= ESMF_SUCCESS) return

arrayFloat = ESMF_ArrayCreate(distgrid, arraySpecFloat, name="arrayFloat", rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArrayGet(arrayFloat, farrayPtr=arrayFloatData, rc=rc)
if (rc /= ESMF_SUCCESS) return
do j = 1, size(arrayFloatData, 2)
do i = 1, size(arrayFloatData, 1)
arrayFloatData(i,j) = (localPet+1) * 27.0 * ((i-1)*size(arrayFloatData,2) + (j-1))
end do
end do

arrayFloatRead = ESMF_ArrayCreate(distgrid, arraySpecFloat, name="arrayFloat", rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArrayGet(arrayFloatRead, farrayPtr=arrayFloatReadData, rc=rc)
if (rc /= ESMF_SUCCESS) return

arrayDouble = ESMF_ArrayCreate(distgrid, arraySpecDouble, name="arrayDouble", rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArrayGet(arrayDouble, farrayPtr=arrayDoubleData, rc=rc)
if (rc /= ESMF_SUCCESS) return
do j = 1, size(arrayDoubleData, 2)
do i = 1, size(arrayDoubleData, 1)
arrayDoubleData(i,j) = (localPet+1) * 37.0 * ((i-1)*size(arrayDoubleData,2) + (j-1))
end do
end do

arrayDoubleRead = ESMF_ArrayCreate(distgrid, arraySpecDouble, name="arrayDouble", rc=rc)
if (rc /= ESMF_SUCCESS) return
call ESMF_ArrayGet(arrayDoubleRead, farrayPtr=arrayDoubleReadData, rc=rc)
if (rc /= ESMF_SUCCESS) return

end subroutine createArrays

end program ESMF_ArrayIOTypesUTest
2 changes: 1 addition & 1 deletion src/Infrastructure/Array/tests/ESMF_ArrayIOUTest.F90
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ program ESMF_ArrayIOUTest

!==============================================================================
!BOP
! !PROGRAM: ESMF_PIOArrayUTest - Tests ArrayWrite() and ArrayRead()
! !PROGRAM: ESMF_ArrayIOUTest - Tests ArrayWrite() and ArrayRead()
!
! !DESCRIPTION:
!
Expand Down
13 changes: 13 additions & 0 deletions src/Infrastructure/Array/tests/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ TESTS_BUILD = $(ESMF_TESTDIR)/ESMF_ArrayCreateGetUTest \
$(ESMF_TESTDIR)/ESMF_ArrayDataUTest \
$(ESMF_TESTDIR)/ESMF_ArrayScatterUTest \
$(ESMF_TESTDIR)/ESMF_ArrayGatherUTest \
$(ESMF_TESTDIR)/ESMF_ArrayIOTypesUTest \
$(ESMF_TESTDIR)/ESMF_ArrayIOUTest \
$(ESMF_TESTDIR)/ESMF_ArraySMMUTest \
$(ESMF_TESTDIR)/ESMF_ArraySMMFromFileUTest \
Expand All @@ -24,6 +25,7 @@ TESTS_RUN = RUN_ESMF_ArrayCreateGetUTest \
RUN_ESMF_ArrayDataUTest \
RUN_ESMF_ArrayScatterUTest \
RUN_ESMF_ArrayGatherUTest \
RUN_ESMF_ArrayIOTypesUTest \
RUN_ESMF_ArrayIOUTest \
RUN_ESMF_ArraySMMUTest \
RUN_ESMF_ArraySMMFromFileUTest \
Expand All @@ -34,6 +36,7 @@ TESTS_RUN = RUN_ESMF_ArrayCreateGetUTest \
RUN_ESMC_ArrayUTest

TESTS_RUN_UNI = RUN_ESMF_ArrayDataUTestUNI \
RUN_ESMF_ArrayIOTypesUTestUNI \
RUN_ESMF_ArraySMMUTestUNI \
RUN_ESMF_ArraySMMFromFileUTestUNI \
RUN_ESMC_ArrayUTestUNI
Expand Down Expand Up @@ -85,6 +88,16 @@ RUN_ESMF_ArrayGatherUTest:

# ---

RUN_ESMF_ArrayIOTypesUTest:
rm -f $(ESMF_TESTDIR)/ESMF_ArrayIOTypesUTest.nc
$(MAKE) TNAME=ArrayIOTypes NP=4 ftest

RUN_ESMF_ArrayIOTypesUTestUNI:
rm -f $(ESMF_TESTDIR)/ESMF_ArrayIOTypesUTest.nc
$(MAKE) TNAME=ArrayIOTypes NP=1 ftest

# ---

RUN_ESMF_ArrayIOUTest:
$(MAKE) TNAME=ArrayIO NP=6 ftest

Expand Down

0 comments on commit 7133ea3

Please sign in to comment.