Skip to content

Commit

Permalink
abort on missing files, add cmeps (NOAA-EMC#12)
Browse files Browse the repository at this point in the history
* add abort of datm if forcing file is not found or if reading the file does not return success

* adds scalars for cmeps

Other minor fixes:

* adds check for missing settings in datm_data_table

* add dump of fields at initialization

* add dbug_flag setting read from nems.configure to control
output. dbug_flag defaults to zero

* remove unused importState where possible
  • Loading branch information
DeniseWorthen authored Jun 9, 2020
1 parent 8477b2a commit a14e3bb
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 145 deletions.
3 changes: 1 addition & 2 deletions DATM/AtmBundleCreate.F90
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
subroutine AtmBundleCreate(gcomp,importState, exportState, rc)
subroutine AtmBundleCreate(gcomp, exportState, rc)

use ESMF

Expand All @@ -7,7 +7,6 @@ subroutine AtmBundleCreate(gcomp,importState, exportState, rc)
implicit none

type(ESMF_GridComp) :: gcomp
type(ESMF_State) :: importState
type(ESMF_State) :: exportState
integer, intent(out) :: rc

Expand Down
136 changes: 105 additions & 31 deletions DATM/AtmFieldUtils.F90
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module AtmFieldUtils
public :: AtmFieldsAdvertise, AtmFieldsRealize
public :: AtmFieldCheck
public :: AtmFieldDump
public :: State_SetScalar

! called by AtmInit, AtmRun
public :: AtmForceFwd2Bak, AtmBundleCheck
Expand Down Expand Up @@ -57,6 +58,13 @@ subroutine AtmFieldsAdvertise(state, field_defs, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
enddo

! advertise scalars for cmeps
if (len_trim(scalar_field_name) > 0) then
call NUOPC_Advertise(state, standardName=trim(scalar_field_name), name=trim(scalar_field_name), rc=rc)
call ESMF_LogWrite("Advertise Field "// trim(scalar_field_name), ESMF_LOGMSG_INFO)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
endif

end subroutine AtmFieldsAdvertise

!-----------------------------------------------------------------------------
Expand All @@ -73,9 +81,7 @@ subroutine AtmFieldsRealize(state, grid, field_defs, tag, rc)
type(ESMF_Field) :: field
type(ESMF_StaggerLoc) :: staggerloc
character(len=ESMF_MAXSTR) :: msgString

integer :: ii,nfields
logical :: connected

rc = ESMF_SUCCESS
call ESMF_LogWrite("User routine AtmFieldsRealize "//trim(tag)//" started", ESMF_LOGMSG_INFO)
Expand All @@ -96,30 +102,41 @@ subroutine AtmFieldsRealize(state, grid, field_defs, tag, rc)
name=trim(field_defs(ii)%shortname), rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call NUOPC_Realize(state, grid, rc=rc)
call NUOPC_Realize(state, field=field, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call ESMF_FieldGet(field, farrayPtr=field_defs(ii)%farrayPtr, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

! initialize
field_defs(ii)%farrayPtr = 0.0
!do j = lbound(field_defs(ii)%farrayPtr,2),ubound(field_defs(ii)%farrayPtr,2)
! do i = lbound(field_defs(ii)%farrayPtr,1),ubound(field_defs(ii)%farrayPtr,1)
! field_defs(ii)%farrayPtr(i,j) = 0.0
! enddo
!enddo

msgString = trim(tag)//" Field "// trim(field_defs(ii)%shortname) // " is connected on root pe"
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
enddo

! realize scalars for cmeps
if (len_trim(scalar_field_name) > 0) then
call SetScalarField(field, rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call NUOPC_Realize(state, field=field, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

msgString = trim(tag)//" Field "// trim(scalar_field_name) // " is connected on root pe"
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
endif

call ESMF_LogWrite("User routine AtmFieldsRealize "//trim(tag)//" finished", ESMF_LOGMSG_INFO)
end subroutine AtmFieldsRealize

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

subroutine AtmFieldCheck(importState, exportState, tag, rc)
subroutine AtmFieldCheck(exportState, tag, rc)

use AtmInternalFields, only : iprnt, jprnt

type(ESMF_State) :: importState, exportState
type(ESMF_State) :: exportState
character(len=*), intent( in) :: tag
integer, intent(out) :: rc

Expand Down Expand Up @@ -170,37 +187,32 @@ end subroutine AtmFieldCheck

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

subroutine AtmFieldDump(importState, exportState, tag, timestr, rc)
subroutine AtmFieldDump(exportState, filename, rc)

type(ESMF_State) :: importState
type(ESMF_State) :: exportState
character(len=*), intent( in) :: tag
character(len=*), intent( in) :: timestr
character(len=*), intent( in) :: filename
integer, intent(out) :: rc

! Local variables
type(ESMF_Field) :: field

integer :: ii,nfields
character(len=ESMF_MAXSTR) :: varname
character(len=ESMF_MAXSTR) :: filename
character(len=ESMF_MAXSTR) :: msgString

! Initialize return code
rc = ESMF_SUCCESS

call ESMF_LogWrite("User routine AtmFieldDump started", ESMF_LOGMSG_INFO)

! Atm variables in exportState
nfields = size(AtmBundleFields)
do ii = 1,nfields
call ESMF_StateGet(exportState, &
itemName = trim(AtmBundleFields(ii)%shortname), &
field=field,rc=rc)
varname = trim(AtmBundleFields(ii)%shortname)

if(trim(tag) .eq. 'before AtmRun')filename = 'field_atm_exportb_'//trim(timestr)//'.nc'
if(trim(tag) .eq. 'after AtmRun')filename = 'field_atm_exporta_'//trim(timestr)//'.nc'

write(msgString, '(a,i6)')'Writing exportState field '//trim(varname)//' to ' &
//trim(filename)
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
Expand All @@ -209,11 +221,6 @@ subroutine AtmFieldDump(importState, exportState, tag, timestr, rc)
fileName =trim(filename), &
timeslice=1, &
overwrite=.true., rc=rc)
!endif
!if(iicnt .eq. 1)then
! write(msgString, *)'Writing exportState field ',trim(varname),' to ',trim(filename)
! call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
!endif
enddo
call ESMF_LogWrite("User routine AtmFieldDump finished", ESMF_LOGMSG_INFO)

Expand Down Expand Up @@ -325,15 +332,14 @@ end subroutine AtmBundleCheck

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

subroutine AtmBundleIntp(gcomp, importState, exportState, externalClock, hour, rc)
subroutine AtmBundleIntp(gcomp, exportState, externalClock, hour, rc)

use AtmInternalFields, only : hfwd,hbak
use AtmInternalFields, only : iprnt,jprnt
use AtmInternalFields, only : AtmBundleFields
use AtmInternalFields, only : AtmBundleFwd, AtmBundleBak

type(ESMF_GridComp) :: gcomp
type(ESMF_State) :: importState
type(ESMF_State) :: exportState
type(ESMF_Clock) :: externalClock

Expand Down Expand Up @@ -404,12 +410,14 @@ subroutine AtmBundleIntp(gcomp, importState, exportState, externalClock, hour, r
! real(AtmBundleFields(ii)%farrayPtr_fwd(ijloc(1),ijloc(2)),4)
!call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)

write (msgString,*)' AtmIntp ',&
trim(AtmBundleFields(ii)%shortname),&
real(AtmBundleFields(ii)%farrayPtr(iprnt,jprnt),4),&
real(AtmBundleFields(ii)%farrayPtr_bak(iprnt,jprnt),4),&
real(AtmBundleFields(ii)%farrayPtr_fwd(iprnt,jprnt),4)
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
if(dbug_flag > 0)then
write (msgString,*)' AtmIntp ',&
trim(AtmBundleFields(ii)%shortname),&
real(AtmBundleFields(ii)%farrayPtr(iprnt,jprnt),4),&
real(AtmBundleFields(ii)%farrayPtr_bak(iprnt,jprnt),4),&
real(AtmBundleFields(ii)%farrayPtr_fwd(iprnt,jprnt),4)
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
end if

!write (msgString,*)' AtmBundleFields ',&
! trim(AtmBundleFields(ii)%field_name),' min,max,sum ',&
Expand All @@ -422,4 +430,70 @@ subroutine AtmBundleIntp(gcomp, importState, exportState, externalClock, hour, r
call ESMF_LogWrite("User routine AtmBundleIntp finished", ESMF_LOGMSG_INFO)
end subroutine AtmBundleIntp

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

!> Set scalar data from state for a particular name
subroutine State_SetScalar(value, scalar_id, State, mytask, scalar_name, scalar_count, rc)
real(ESMF_KIND_R8),intent(in) :: value
integer, intent(in) :: scalar_id
type(ESMF_State), intent(inout) :: State
integer, intent(in) :: mytask
character(len=*), intent(in) :: scalar_name
integer, intent(in) :: scalar_count
integer, intent(inout) :: rc !< return code

! local variables
type(ESMF_Field) :: field
real(ESMF_KIND_R8), pointer :: farrayptr(:,:)
character(len=*), parameter :: subname='(DATM: State_SetScalar)'
!--------------------------------------------------------

rc = ESMF_SUCCESS

call ESMF_StateGet(State, itemName=trim(scalar_name), field=field, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

if (mytask == 0) then
call ESMF_FieldGet(field, farrayPtr=farrayptr, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

if (scalar_id < 0 .or. scalar_id > scalar_count) then
call ESMF_LogSetError(ESMF_RC_ARG_BAD, &
msg=subname//": ERROR in scalar_id", line=__LINE__, file=__FILE__, rcToReturn=rc)
return
endif

farrayptr(scalar_id,1) = value
endif

end subroutine State_SetScalar

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

subroutine SetScalarField(field, rc)

! create a field with scalar data on the root pe
type(ESMF_Field), intent(inout) :: field
integer, intent(inout) :: rc

! local variables
type(ESMF_Distgrid) :: distgrid
type(ESMF_Grid) :: grid
character(len=*), parameter :: subname='(DATM: SetScalarField)'

rc = ESMF_SUCCESS

! create a DistGrid with a single index space element, which gets mapped onto DE 0.
distgrid = ESMF_DistGridCreate(minIndex=(/1/), maxIndex=(/1/), rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

grid = ESMF_GridCreate(distgrid, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

! num of scalar values
field = ESMF_FieldCreate(name=trim(scalar_field_name), grid=grid, typekind=ESMF_TYPEKIND_R8, &
ungriddedLBound=(/1/), ungriddedUBound=(/scalar_field_count/), gridToFieldMap=(/2/), rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

end subroutine SetScalarField
end module AtmFieldUtils
77 changes: 52 additions & 25 deletions DATM/AtmForce.F90
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ subroutine AtmForce(gcomp,exportState,externalClock,initmode,rc)
type(ESMF_Time) :: currTime
type(ESMF_Time) :: nextTime
type(ESMF_TimeInterval) :: timeStep
type(ESMF_VM) :: vm

integer(kind=ESMF_KIND_I4) :: year, month, day, hour, jday

integer :: mytask
integer :: ii,nfields
integer :: iii, iid, iiu
logical :: fexists
integer :: fpresent(1) = 0

character(len=ESMF_MAXSTR) :: varname
character(len=ESMF_MAXSTR) :: filename
Expand All @@ -45,6 +49,12 @@ subroutine AtmForce(gcomp,exportState,externalClock,initmode,rc)

call ESMF_LogWrite("User routine AtmForce started", ESMF_LOGMSG_INFO)

call ESMF_GridCompGet(gcomp, vm=vm, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call ESMF_VMGet(vm, localPet=mytask, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

! at initialization, get the current forecast hour file, not the forward
! forecast hour
if(initmode .eq. 0)then
Expand Down Expand Up @@ -76,35 +86,52 @@ subroutine AtmForce(gcomp,exportState,externalClock,initmode,rc)

call ESMF_TimeGet(nextTime,h_r8=hfwd,rc=rc)
endif
write(msgString,'(3a,f12.3)')'using ',trim(filename),' at fwd clock hour ',real(hfwd,4)
write(msgString,'(3a,f12.3)')'using ',trim(filename),' at fwd clock hour ',hfwd
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)

! read the Atm field data into the Fwd bundle
nfields = size(AtmBundleFields)
do ii = 1,nfields
if(AtmBundleFields(ii)%isPresent)then
varname = trim(AtmBundleFields(ii)%file_varname)

! get the '_fwd' field
call ESMF_FieldBundleGet(AtmBundleFwd, &
fieldName=trim(AtmBundleFields(ii)%field_name)//'_fwd', &
field=field, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call ESMF_FieldRead(field, &
fileName=trim(filename), &
variableName = trim(varname), &
rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
fexists = .false.
if(mytask == 0)inquire(file=trim(filename), exist=fexists)
if(fexists) fpresent(1) = 1
call ESMF_VMBroadCast(vm, fpresent, count=1, rootPet=0, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if(fpresent(1) == 1)fexists = .true.

if(.not. fexists)then
if(mytask == 0)print *,'Cannot read file '//trim(filename)//': Aborting'
call ESMF_LogWrite('Cannot read file '//trim(filename)//': Aborting', ESMF_LOGMSG_INFO)
call ESMF_Finalize(endflag=ESMF_END_ABORT)
else
! read the Atm field data into the Fwd bundle
nfields = size(AtmBundleFields)
do ii = 1,nfields
if(AtmBundleFields(ii)%isPresent)then
varname = trim(AtmBundleFields(ii)%file_varname)

! get the '_fwd' field
call ESMF_FieldBundleGet(AtmBundleFwd, &
fieldName=trim(AtmBundleFields(ii)%field_name)//'_fwd', &
field=field, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call ESMF_FieldRead(field, &
fileName=trim(filename), &
variableName = trim(varname), &
rc=rc)
if( rc /= ESMF_SUCCESS)then
call ESMF_LogWrite('Problem reading '//trim(filename), ESMF_LOGMSG_INFO)
call ESMF_Finalize(endflag=ESMF_END_ABORT)
endif
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call ESMF_FieldGet(field,farrayPtr=AtmBundleFields(ii)%farrayPtr_fwd,rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call ESMF_FieldGet(field,farrayPtr=AtmBundleFields(ii)%farrayPtr_fwd,rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

write(msgString,'(i6,2a18,f14.5)')ii,' inside AtmForce ',trim(varname), &
AtmBundleFields(ii)%farrayPtr_fwd(iprnt,jprnt)
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
endif !isPresent
enddo
write(msgString,'(i6,2a18,f14.5)')ii,' inside AtmForce ',trim(varname), &
AtmBundleFields(ii)%farrayPtr_fwd(iprnt,jprnt)
call ESMF_LogWrite(trim(msgString), ESMF_LOGMSG_INFO)
endif !isPresent
enddo
end if

! Check for fields which are not Present but are needed
! Not very clean---would have been better to create this field in the forcing file
Expand Down
Loading

0 comments on commit a14e3bb

Please sign in to comment.