Skip to content

Commit

Permalink
Merge pull request #285 from esmf-org/c_finalize_stst
Browse files Browse the repository at this point in the history
New system test that tests ESMC_FinalizeWithFlag() as well as some basic C-API regridding functionality
  • Loading branch information
oehmke authored Sep 9, 2024
2 parents edb848d + 169a408 commit 4b42fcb
Show file tree
Hide file tree
Showing 66 changed files with 407 additions and 96 deletions.
17 changes: 17 additions & 0 deletions build/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,10 @@ $(ESMF_TESTDIR)/ESMF_%STest : ESMF_%STest.o $(SYSTEM_TESTS_OBJ) $(addsuffix .$(E
$(ESMF_F90LINKER) $(ESMF_EXE_F90LINKOPTS) $(ESMF_F90LINKOPTS) $(ESMF_F90LINKPATHS) $(ESMF_F90LINKRPATHS) $(ESMF_EXEOUT_OPTION) $(SYSTEM_TESTS_OBJ) $< $(ESMF_F90ESMFLINKLIBS)
$(ESMF_RM) -f *.o *.mod

$(ESMF_TESTDIR)/ESMC_%STest : ESMC_%STest.o $(SYSTEM_TESTS_OBJ) $(addsuffix .$(ESMF_SL_SUFFIX), $(SYSTEM_TESTS_SHOBJ)) $(ESMFLIB)
$(MAKE) chkdir_tests
$(ESMF_CLINKER) $(ESMF_EXE_CLINKOPTS) $(ESMF_CLINKOPTS) $(ESMF_CLINKPATHS) $(ESMF_CLINKRPATHS) $(ESMF_EXEOUT_OPTION) $(SYSTEM_TESTS_OBJ) $< $(ESMF_CESMFLINKLIBS)
$(ESMF_RM) -f *.o *.mod

# debugging aid: link the executable, standard output, and log file to
# temporary names in the current directory (they are built in the test
Expand Down Expand Up @@ -2977,6 +2981,19 @@ stest:
cat ./PET*$(TNAME)STest.Log> ./ESMF_$(TNAME)STest.Log ; \
$(ESMF_RM) ./PET*$(TNAME)STest.Log

sctest:
-@cd $(ESMF_TESTDIR) ; \
$(ESMF_RM) ./PET*$(TNAME)STest.Log ; \
if [ $(ESMF_BATCHDEPRECATED) = "true" ] ; then \
echo $(ESMF_MPIRUN) -np $(NP) $(ESMF_TOOLRUN) ./ESMC_$(TNAME)STest ; \
$(ESMF_MPIRUN) -np $(NP) $(ESMF_TOOLRUN) ./ESMC_$(TNAME)STest ; \
else \
echo $(ESMF_MPIRUN) -np $(NP) $(ESMF_TOOLRUN) ./ESMC_$(TNAME)STest 1\> ./ESMC_$(TNAME)STest.stdout 2\>\&1 ; \
$(ESMF_MPIRUN) -np $(NP) $(ESMF_TOOLRUN) ./ESMC_$(TNAME)STest 1> ./ESMC_$(TNAME)STest.stdout 2>&1 ; \
fi ; \
cat ./PET*$(TNAME)STest.Log> ./ESMC_$(TNAME)STest.Log ; \
$(ESMF_RM) ./PET*$(TNAME)STest.Log

#
# this target deletes only the system test related files from the test subdir
#
Expand Down
13 changes: 11 additions & 2 deletions scripts/test_scripts/sys_tests_results.pl
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ sub get_pet_count {
s/ESMF//;# Break first ESMF string
s/ESMF/ ESMF/;# Break it into 2 fields
s/([^ ]*) ([^ ]*)/$2/; # Get rid of the 1st field
s/ESMC//;# Break first ESMC string
s/ESMC/ ESMC/;# Break it into 2 fields
s/([^ ]*) ([^ ]*)/$2/; # Get rid of the 1st field
s/\./ /; # Break it into 2 fields
s/([^ ]*) ([^ ]*)/$1.Log\n/; # Get rid of the 2nd field
}
Expand Down Expand Up @@ -225,7 +228,7 @@ sub get_pet_count {
@Log_files=grep (/STest/, @tmp_Log_files);
#Sort the list of Log files.
@Log_files = sort (@Log_files);
# Find the Log fles that are in the st_ex_files
# Find the Log fles that are in the st_st_files
foreach $file ( @st_st_files) {
push @Log_st_files, grep (/$file/, @Log_files);
}
Expand Down Expand Up @@ -279,6 +282,12 @@ sub get_pet_count {
foreach $file ( @pass_tests) {
push @pass_st_files, grep (/$file.F90/, @act_st_files);
}
foreach $file ( @pass_tests) {
push @pass_st_files, grep (/$file.C/, @act_st_files);
}
foreach $file ( @pass_tests) {
push @pass_st_files, grep (/$file.c/, @act_st_files);
}
if (!$SUMMARY) { # Print only if full output requested
print "\n\n";
if ($pass_count == 1) {
Expand Down Expand Up @@ -345,7 +354,7 @@ sub get_pet_count {
s/\.stdout//; # Delete stdout
}

# Find the system test executable files that are in the st_ex_files
# Find the system test executable files that are in the st_x_files
foreach $file ( @st_st_files) {
push @stdout_st_files, grep (/$file/, @st_x_files);
}
Expand Down
12 changes: 6 additions & 6 deletions src/Infrastructure/FieldBundle/tests/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ run_uni: run_unit_tests_uni
LOCDIR = src/Infrastructure/FieldBundle/tests

.NOTPARALLEL:
TESTS_BUILD = $(ESMC_TESTDIR)/ESMF_FieldBundleUTest \
$(ESMC_TESTDIR)/ESMF_FieldBundleCrGetUTest \
$(ESMC_TESTDIR)/ESMF_FieldBundleRedistUTest \
$(ESMC_TESTDIR)/ESMF_FieldBundleSMMUTest \
$(ESMC_TESTDIR)/ESMF_FieldBundleIOUTest \
$(ESMC_TESTDIR)/ESMF_FieldBundleRegridUTest
TESTS_BUILD = $(ESMF_TESTDIR)/ESMF_FieldBundleUTest \
$(ESMF_TESTDIR)/ESMF_FieldBundleCrGetUTest \
$(ESMF_TESTDIR)/ESMF_FieldBundleRedistUTest \
$(ESMF_TESTDIR)/ESMF_FieldBundleSMMUTest \
$(ESMF_TESTDIR)/ESMF_FieldBundleIOUTest \
$(ESMF_TESTDIR)/ESMF_FieldBundleRegridUTest

TESTS_RUN = RUN_ESMF_FieldBundleUTest \
RUN_ESMF_FieldBundleCrGetUTest \
Expand Down
7 changes: 5 additions & 2 deletions src/Infrastructure/TimeMgr/interface/ESMF_Clock.F90
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,11 @@ function ESMF_ClockCreateNew(timeStep, startTime, keywordEnforcer, &
! The {\tt ESMF\_Clock}'s reference time. Provides reference point
! for simulation time (see currSimTime in ESMF\_ClockGet() below).
! \item[{[repeatDuration]}]
! If specified and not 0, then makes {\tt ESMF\_Clock} a repeating clock that runs for
! {\tt repeatDuration} and then resets back to {\tt statTime}.
! If specified and not 0, then makes {\tt ESMF\_Clock} a repeating clock that stays within
! the range of {\tt startTime} to {\tt startTime}+{\tt repeatDuration}. For example, when advancing
! if the current time goes past {\tt startTime}+{\tt repeatDuration}, then it resets
! back to {\tt startTime} to continue. Currently, the repeat functionality is not supported with clocks
! that run backwards (e.g. that have a negative timeStep).
! \item[{[name]}]
! The name for the newly created clock. If not specified, a
! default unique name will be generated: "ClockNNN" where NNN
Expand Down
246 changes: 246 additions & 0 deletions src/system_tests/ESMC_FieldRegrid/ESMC_FieldRegridSTest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// $Id$
//
//-------------------------------------------------------------------------
//ESMF_SYSTEM_TEST String used by test script to count system tests.
//=========================================================================

//-------------------------------------------------------------------------
// //DESCRIPTION:
// System test ESMC_FieldRegrid
// This system test is a basic check of the C-API when used for regridding.
// It creates two Grids, two Field on the two Grids, and then does bilinear
// regridding between the Fields. After the regridding, it does a simple check
// that the destination values resulting from the regridding seem reasonable.
// This test also checks the ESMC_Initialize(), ESMC_Finalize(), and
// ESMC_FinalizeWithFlag() calls.
//-------------------------------------------------------------------------
//\begin{verbatim}

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

// ESMF header
#include "ESMC.h"

// ESMF Test header
#include "ESMC_Test.h"

int main(void) {
char name[ESMF_MAXSTR];
char failMsg[ESMF_MAXSTR];
char msg[ESMF_MAXSTR];
int result=0;
int localrc, finalrc;
int localPet, petCount;
ESMC_VM vm;
enum ESMC_IndexFlag indexFlag=ESMC_INDEX_GLOBAL;

//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
strcpy(name, "System Test ESMC_FieldRegridSTest");
strcpy(failMsg, "System Test failure");

// Initialize
localrc = ESMC_Initialize(NULL, ESMC_InitArgLogFilename("ESMC_FieldRegridSTest.Log"),
ESMC_ArgLast);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

// Get parallel information
vm=ESMC_VMGetGlobal(&localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);
localrc=ESMC_VMGet(vm, &localPet, &petCount, (int *)NULL, (MPI_Comm *)NULL, (int *)NULL, (int *)NULL);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

// Output that we started on this PET
printf("%s started on localPet=%d\n",name,localPet);

// Create source Grid
int srcMaxIndex[2]={20,36};
ESMC_InterArrayInt srcMaxIndexIA;
localrc=ESMC_InterArrayIntSet(&srcMaxIndexIA, srcMaxIndex, 2);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

ESMC_Grid srcGrid = ESMC_GridCreate1PeriDim(&srcMaxIndexIA, NULL, NULL, NULL, NULL, NULL,
&indexFlag, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Add Center stagger
localrc=ESMC_GridAddCoord(srcGrid, ESMC_STAGGERLOC_CENTER);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Create source Field
ESMC_Field srcField=ESMC_FieldCreateGridTypeKind(srcGrid, ESMC_TYPEKIND_R8, ESMC_STAGGERLOC_CENTER,
NULL, NULL, NULL, NULL, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Get source coordinate memory
int srcExLBnd[2], srcExUBnd[2];
double *srcLon=(double *)ESMC_GridGetCoord(srcGrid, 1, ESMC_STAGGERLOC_CENTER, NULL,
srcExLBnd, srcExUBnd, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

double *srcLat=(double *)ESMC_GridGetCoord(srcGrid, 2, ESMC_STAGGERLOC_CENTER, NULL,
srcExLBnd, srcExUBnd, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Get Field data memory
double *srcData=(double *)ESMC_FieldGetPtr(srcField, 0, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Set source coords and data
double dSrcLon=360.0/((double)srcMaxIndex[0]); // Delta increment for each lon index
double dSrcLat=180.0/((double)srcMaxIndex[1]); // Delta increment for each lat index
for (int p=0,i1=srcExLBnd[1]; i1<=srcExUBnd[1]; i1++) {
for (int i0=srcExLBnd[0]; i0<=srcExUBnd[0]; i0++) {
srcLon[p]=dSrcLon*(double)i0;
srcLat[p]=dSrcLat*(double)i1-90.0-0.5*dSrcLat; // Center lat by moving half a cell down
srcData[p]=srcLat[p]; // Something simple since this more a test of the C interface than of regridding
p++;
}
}

// Debug output
// localrc = ESMC_GridWrite(srcGrid, ESMC_STAGGERLOC_CENTER, "srcGrid");
//if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Create destination Grid
int dstMaxIndex[2]={10,18};
ESMC_InterArrayInt dstMaxIndexIA;
localrc=ESMC_InterArrayIntSet(&dstMaxIndexIA, dstMaxIndex, 2);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

ESMC_Grid dstGrid = ESMC_GridCreate1PeriDim(&dstMaxIndexIA, NULL, NULL, NULL, NULL, NULL,
&indexFlag, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Add center stagger
localrc=ESMC_GridAddCoord(dstGrid, ESMC_STAGGERLOC_CENTER);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Create destination Field
ESMC_Field dstField=ESMC_FieldCreateGridTypeKind(dstGrid, ESMC_TYPEKIND_R8, ESMC_STAGGERLOC_CENTER,
NULL, NULL, NULL, NULL, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Get destination coordinate memory
int dstExLBnd[2], dstExUBnd[2];
double *dstLon=(double *)ESMC_GridGetCoord(dstGrid, 1, ESMC_STAGGERLOC_CENTER, NULL,
dstExLBnd, dstExUBnd, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

double *dstLat=(double *)ESMC_GridGetCoord(dstGrid, 2, ESMC_STAGGERLOC_CENTER, NULL,
dstExLBnd, dstExUBnd, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Get destination Field data memory
double *dstData=(double *)ESMC_FieldGetPtr(dstField, 0, &localrc);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Set destination Grid coords and init destination Field to 0.0
double dDstLon=360.0/((double)dstMaxIndex[0]); // Delta increment for each lon index
double dDstLat=180.0/((double)dstMaxIndex[1]); // Delta increment for each lat index
for (int p=0,i1=dstExLBnd[1]; i1<=dstExUBnd[1]; i1++) {
for (int i0=dstExLBnd[0]; i0<=dstExUBnd[0]; i0++) {
dstLon[p]=dDstLon*(double)i0;
dstLat[p]=dDstLat*(double)i1-90.0-0.5*dDstLat; // Center lat by moving half a cell down
dstData[p]=0.0;
p++;
}
}


// Debug output
//localrc = ESMC_GridWrite(dstGrid, ESMC_STAGGERLOC_CENTER, "dstGrid");
//if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Calculate regridding weights and routeHandle
ESMC_RouteHandle routehandle;
localrc = ESMC_FieldRegridStore(srcField, dstField, NULL, NULL, &routehandle,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Apply routehandle
localrc = ESMC_FieldRegrid(srcField, dstField, routehandle, NULL);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Deallocate routehandle
localrc = ESMC_FieldRegridRelease(&routehandle);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);


// Check output
bool correct=true;
for (int p=0,i1=dstExLBnd[1]; i1<=dstExUBnd[1]; i1++) {
for (int i0=dstExLBnd[0]; i0<=dstExUBnd[0]; i0++) {

// Check that destination values are close to what's expected (latitude)
if (abs(dstLat[p]-dstData[p]) > 1.0E-12) correct=false;

// Move to next memory location
p++;
}
}

// Deallocate source Field
localrc = ESMC_FieldDestroy(&srcField);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

// Deallocate source Grid
localrc = ESMC_GridDestroy(&srcGrid);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

// Deallocate destination Field
localrc = ESMC_FieldDestroy(&dstField);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

// Deallocate destination Grid
localrc = ESMC_GridDestroy(&dstGrid);
if (localrc != ESMF_SUCCESS) ESMC_FinalizeWithFlag(ESMC_END_ABORT);

// Output that this PET finished test
printf("%s finished on localPet=%d\n",name,localPet);

// Write standard system test output.
// (On Fortran side this is written by ESMF_STest, but that doesn't exist in C.)
snprintf(msg,ESMF_MAXSTR,"NUMBER_OF_PROCESSORS %d\n",petCount);
ESMC_LogWrite(msg, ESMC_LOGMSG_INFO);

// Check that test results were correct
ESMC_Test(correct, name, failMsg, &result, __FILE__, __LINE__, 0);

// NOTE:
// There's kind of a chicken and egg problem in testing ESMF finalize where when you run
// finalize it gets rid of the log file output, but then you can't report if finalize
// succeeded. However, at least it gets run here and outputs an error to
// standard out so we can see a failure with manual testing.
// Also, I'm testing both interfaces here because we don't have
// another test of them. Once we do, get rid of the if and just test one.
if (localPet%2 == 0) {
localrc = ESMC_Finalize();
if (localrc != ESMF_SUCCESS) {
printf("ERROR! ESMF_Finalize() did not return success!\n");
}
} else {
localrc = ESMC_FinalizeWithFlag(ESMC_END_NORMAL);
if (localrc != ESMF_SUCCESS) {
printf("ERROR! ESMF_FinalizeWithFlag() did not return success!\n");
}
}
}

37 changes: 37 additions & 0 deletions src/system_tests/ESMC_FieldRegrid/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# $Id$


ALL: tree_build_system_tests

run: tree_run_system_tests
run_uni: tree_run_system_tests_uni

LOCDIR = src/system_tests/ESMC_FieldRegrid


SYSTEM_TESTS_BUILD = $(ESMF_TESTDIR)/ESMC_FieldRegridSTest

# Object files other than SysTest%.o that the
# system tests executable will depend on.
# List objects files in the order that they
# are to be compiled/created.
SYSTEM_TESTS_OBJ =

SYSTEM_TESTS_RUN = RUN_ESMC_FieldRegrid

SYSTEM_TESTS_RUN_UNI = RUN_ESMC_FieldRegridUNI

include $(ESMF_DIR)/makefile

DIRS =

CLEANDIRS =
CLEANFILES = $(SYSTEM_TESTS_BUILD)
CLOBBERDIRS =

RUN_ESMC_FieldRegrid:
$(MAKE) TNAME=FieldRegrid NP=4 sctest

RUN_ESMC_FieldRegridUNI:
$(MAKE) TNAME=FieldRegrid NP=1 sctest

2 changes: 1 addition & 1 deletion src/system_tests/ESMF_ArrayBundleRedist/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ run: tree_run_system_tests
LOCDIR = src/system_tests/ESMF_ArrayBundleRedist


SYSTEM_TESTS_BUILD = $(ESMC_TESTDIR)/ESMF_ArrayBundleRedistSTest
SYSTEM_TESTS_BUILD = $(ESMF_TESTDIR)/ESMF_ArrayBundleRedistSTest

# Object files other than SysTest%.o that the
# system tests executable will depend on.
Expand Down
Loading

0 comments on commit 4b42fcb

Please sign in to comment.