/wrfv2_fire/main/wrf_SST_ESMF.F
FORTRAN Legacy | 1967 lines | 926 code | 214 blank | 827 comment | 3 complexity | 922ed801948ecd1aebca9fa5803ec498 MD5 | raw file
Possible License(s): AGPL-1.0
- !WRF:DRIVER_LAYER:MAIN
- !
- !<DESCRIPTION>
- ! ESMF Application Wrapper for coupling WRF with a "dummy" component
- ! that simply reads SSTs from a file, sends to WRF, receives SST from
- ! WRF (two-way coupling). and checks that the SSTs match.
- !
- ! This file contains the main program and associated modules for the
- ! SST "dummy" component and a simple coupler. It creates ESMF Gridded
- ! and Coupler Components.
- !
- ! This source file is only built when ESMF coupling is used.
- !
- !</DESCRIPTION>
- !<DESCRIPTION>
- ! Modules module_sst_component_top and module_sst_setservices define the
- ! "SST" dummy component.
- !</DESCRIPTION>
- MODULE module_sst_component_top
- !<DESCRIPTION>
- ! This module defines sst_component_init1(), sst_component_init2(),
- ! sst_component_run1(), sst_component_run2(), and sst_component_finalize()
- ! routines that are called when SST is run as an ESMF component.
- !</DESCRIPTION>
- ! Updated for ESMF 5.2.0r -- see:
- ! http://www.earthsystemmodeling.org/esmf_releases/public/ESMF_5_2_0r/InterfaceChanges520to520r.pdf
- ! USE ESMF_Mod
- USE ESMF
- USE module_esmf_extensions
- USE module_metadatautils, ONLY: AttachTimesToState
- IMPLICIT NONE
- ! everything is private by default
- PRIVATE
- ! Public entry points
- PUBLIC sst_component_init1
- PUBLIC sst_component_init2
- PUBLIC sst_component_run1
- PUBLIC sst_component_run2
- PUBLIC sst_component_finalize
- ! private stuff
- TYPE(ESMF_Grid), SAVE :: esmfgrid ! grid used in fields
- CHARACTER (4096) :: str
- INTEGER, SAVE :: fid ! file handle
- ! decomposition information
- INTEGER, SAVE :: ids, ide, jds, jde, kds, kde
- INTEGER, SAVE :: ims, ime, jms, jme, kms, kme
- INTEGER, SAVE :: ips, ipe, jps, jpe, kps, kpe
- REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_out_sst(:,:)
- REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_out_landmask(:,:)
- REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_in_sst(:,:)
- REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_in_landmask(:,:)
- INTEGER, SAVE :: domdesc
- LOGICAL, SAVE :: bdy_mask(4)
- ! MPI communicator, if needed
- INTEGER, SAVE :: mpicom
- ! field data
- REAL, POINTER, SAVE :: file_landmask_data(:,:), file_sst_data(:,:)
- ! input data file name
- CHARACTER ( ESMF_MAXSTR ), SAVE :: sstinfilename
- ! field names
- INTEGER, PARAMETER :: datacount = 2
- INTEGER, PARAMETER :: SST_INDX = 1
- INTEGER, PARAMETER :: LANDMASK_INDX = 2
- CHARACTER(LEN=ESMF_MAXSTR), SAVE :: datanames(datacount)
- TYPE real2d
- REAL, POINTER :: r2d(:,:)
- END TYPE real2d
- TYPE(real2d) :: this_data(datacount)
- CONTAINS
- ! First-phase "init" reads "SST" data file and returns "time" metadata in
- ! exportState.
- SUBROUTINE sst_component_init1( gcomp, importState, exportState, clock, rc )
- USE module_io
- TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
- TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState
- TYPE(ESMF_State), TARGET, INTENT(INOUT) :: exportState
- TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
- INTEGER, INTENT( OUT) :: rc
- !<DESCRIPTION>
- ! SST component init routine, phase 1.
- !
- ! The arguments are:
- ! gcomp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- #ifdef DM_PARALLEL
- INCLUDE 'mpif.h'
- #endif
- ! Local variables
- CHARACTER (LEN=19) :: date_string
- #ifdef DM_PARALLEL
- TYPE(ESMF_VM) :: vm
- INTEGER :: mpicomtmp
- #endif
- TYPE(ESMF_Time) :: startTime, stopTime, currentTime, dataTime
- TYPE(ESMF_TimeInterval) :: timeStep
- INTEGER :: ierr, num_steps, time_loop_max
- INTEGER :: status_next_var
- !TODO: For now, sstinfilename is hard-coded
- !TODO: Upgrade to use a variant of construct_filename() via startTime
- !TODO: extracted from clock.
- sstinfilename = 'sstin_d01_000000'
- ! get MPI communicator out of current VM and duplicate (if needed)
- #ifdef DM_PARALLEL
- CALL ESMF_VMGetCurrent(vm, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'sst_component_init1: ESMF_VMGetCurrent failed' )
- ENDIF
- CALL ESMF_VMGet(vm, mpiCommunicator=mpicomtmp, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'sst_component_init1: ESMF_VMGet failed' )
- ENDIF
- CALL MPI_Comm_dup( mpicomtmp, mpicom, ierr )
- #else
- mpicom = 0
- #endif
- ! Open the "SST" input data file for reading.
- write(str,'(A,A)') 'Subroutine sst_component_init1: Opening data file ', &
- TRIM(sstinfilename)
- CALL wrf_message ( TRIM(str) )
- CALL wrf_open_for_read ( TRIM(sstinfilename) , &
- mpicom , &
- mpicom , &
- "DATASET=INPUT" , &
- fid , &
- ierr )
- IF ( ierr .NE. 0 ) THEN
- WRITE( str , FMT='(A,A,A,I8)' ) &
- 'subroutine sst_component_init1: error opening ', &
- TRIM(sstinfilename),' for reading ierr=',ierr
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- WRITE( str , FMT='(A,A,A,I8)' ) &
- 'subroutine sst_component_init1: opened file ', &
- TRIM(sstinfilename),' for reading fid=',fid
- CALL wrf_debug ( 100, TRIM(str) )
- ! How many data time levels are in the SST input file?
- num_steps = -1
- time_loop_max = 0
- CALL wrf_debug ( 100, 'subroutine sst_component_init1: find time_loop_max' )
- ! compute SST start time, time step, and end time here
- get_the_right_time : DO
- CALL wrf_get_next_time ( fid, date_string, status_next_var )
- write(str,'(A,A)') 'Subroutine sst_component_init1: SST data startTime: ', &
- date_string
- CALL wrf_debug ( 100 , TRIM(str) )
- IF ( status_next_var == 0 ) THEN
- IF ( time_loop_max == 0 ) THEN
- CALL wrf_atotime( date_string, startTime )
- ELSEIF ( time_loop_max == 1 ) THEN
- ! assumes fixed time step!
- CALL wrf_atotime( date_string, dataTime )
- timeStep = dataTime - startTime
- ENDIF
- time_loop_max = time_loop_max + 1
- CALL wrf_atotime( date_string, stopTime )
- ELSE
- EXIT get_the_right_time
- ENDIF
- END DO get_the_right_time
- CALL wrf_timetoa ( stopTime, date_string )
- write(str,'(A,A)') 'Subroutine sst_component_init1: SST data stopTime: ', &
- date_string
- CALL wrf_debug ( 100 , TRIM(str) )
- ! attach times to exportState for use by driver
- CALL AttachTimesToState( exportState, startTime, stopTime, timeStep )
- ! There should be a more elegant way to get to the beginning of the
- ! file, but this will do.
- CALL wrf_ioclose( fid , ierr )
- IF ( ierr .NE. 0 ) THEN
- CALL wrf_error_fatal ( 'sst_component_init1: wrf_ioclose failed' )
- ENDIF
- WRITE( str , FMT='(A,I8)' ) &
- 'subroutine sst_component_init1: closed file fid=',fid
- CALL wrf_debug ( 100, TRIM(str) )
- ! set up field names
- !TODO: use CF conventions for "standard_name" once WRF Registry supports them
- !TODO: datanames(SST_INDX) = "sea_surface_temperature"
- !TODO: datanames(LANDMASK_INDX) = "land_binary_mask"
- datanames(SST_INDX) = "SST"
- datanames(LANDMASK_INDX) = "LANDMASK"
- rc = ESMF_SUCCESS
- END SUBROUTINE sst_component_init1
- SUBROUTINE read_data( exportState, clock )
- USE module_io
- TYPE(ESMF_State), INTENT(INOUT) :: exportState
- TYPE(ESMF_Clock), INTENT(IN ) :: clock
- !<DESCRIPTION>
- ! Reads data from file and stores. Then
- ! stuffs the file data into the SST exportState.
- !</DESCRIPTION>
- #include <wrf_status_codes.h>
- #include <wrf_io_flags.h>
- ! Local variables
- CHARACTER (LEN=19) :: date_string
- TYPE(ESMF_Time) :: currentTime, dataTime
- REAL(ESMF_KIND_R4), POINTER :: out_sst_ptr(:,:), out_landmask_ptr(:,:)
- TYPE(ESMF_Field) :: out_sst_field, out_landmask_field
- TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
- INTEGER :: i, j
- CHARACTER(LEN=ESMF_MAXSTR) :: fieldname, debugmsg, errormsg, timestr
- INTEGER :: ierr
- INTEGER :: rc
- ! This call to wrf_get_next_time will position the dataset over the next
- ! time-frame in the file and return the date_string, which is used as an
- ! argument to the read_field routines in the blocks of code included
- ! below.
- CALL wrf_get_next_time( fid, date_string , ierr )
- WRITE(str,'(A,A)') 'Subroutine read_data: SST data time: ', &
- date_string
- CALL wrf_debug ( 100 , TRIM(str) )
- IF ( ierr .NE. 0 .AND. ierr .NE. WRF_WARN_NOTSUPPORTED .AND. &
- ierr .NE. WRF_WARN_DRYRUN_READ ) THEN
- CALL wrf_error_fatal ( "... May have run out of valid SST data ..." )
- ELSE IF ( ierr .NE. WRF_WARN_NOTSUPPORTED .AND. &
- ierr .NE. WRF_WARN_DRYRUN_READ) THEN
- ! check input time against current time (which will be start time at
- ! beginning)
- CALL wrf_atotime( date_string, dataTime )
- CALL ESMF_ClockGet( clock, CurrTime=currentTime, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( 'read_data: ESMF_ClockGet() failed' )
- ENDIF
- CALL wrf_clockprint(150, clock, &
- 'DEBUG read_data(): get currentTime from clock,')
- IF ( dataTime .NE. currentTime ) THEN
- CALL wrf_timetoa ( dataTime, timestr )
- WRITE( errormsg , * )'Time in file: ',trim( timestr )
- CALL wrf_message ( trim(errormsg) )
- CALL wrf_timetoa ( currentTime, timestr )
- WRITE( errormsg , * )'Time on domain: ',trim( timestr )
- CALL wrf_message ( trim(errormsg) )
- CALL wrf_error_fatal( &
- "**ERROR** Time in input file not equal to time on domain **ERROR**" )
- ENDIF
- ENDIF
- ! doing this in a loop only works if staggering is the same for all fields
- this_data(SST_INDX)%r2d => file_sst_data
- this_data(LANDMASK_INDX)%r2d => file_landmask_data
- DO i=1, datacount
- fieldname = TRIM(datanames(i))
- debugmsg = 'ext_read_field '//TRIM(fieldname)//' memorder XY'
- errormsg = 'could not read '//TRIM(fieldname)//' data from file'
- CALL wrf_ext_read_field ( &
- fid , & ! DataHandle
- date_string , & ! DateStr
- TRIM(fieldname) , & ! Data Name
- this_data(i)%r2d , & ! Field
- WRF_REAL , & ! FieldType
- mpicom , & ! Comm
- mpicom , & ! I/O Comm
- domdesc , & ! Domain descriptor
- bdy_mask , & ! bdy_mask
- 'XY' , & ! MemoryOrder
- '' , & ! Stagger
- TRIM(debugmsg) , & ! Debug message
- #if 1
- ids , (ide-1) , jds , (jde-1) , 1 , 1 , &
- ims , ime , jms , jme , 1 , 1 , &
- ips , MIN( (ide-1), ipe ) , jps , MIN( (jde-1), jpe ) , 1 , 1 , &
- #else
- !jm the dimensions have already been reduced to the non-staggered WRF grid when
- ! they were stored in this module.. Just use as is.
- ids , ide , jds , jde , 1 , 1 , &
- ims , ime , jms , jme , 1 , 1 , &
- ips , ipe , jps , jpe , 1 , 1 , &
- #endif
- ierr )
- IF (ierr /= 0) THEN
- CALL wrf_error_fatal ( TRIM(errormsg) )
- ENDIF
- ENDDO
- ! stuff fields into exportState
- !TODO: change this to Bundles, eventually
- CALL ESMF_StateGet( exportState, TRIM(datanames(SST_INDX)), &
- out_sst_field, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not find sea_surface_temperature field in exportState' )
- ENDIF
- CALL ESMF_StateGet( exportState, TRIM(datanames(LANDMASK_INDX)), &
- out_landmask_field, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not find land_binary_mask field in exportState' )
- ENDIF
- ! CALL ESMF_FieldGetDataPointer( out_sst_field, out_sst_ptr, rc=rc )
- CALL ESMF_FieldGet( out_sst_field, 0, out_sst_ptr, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not find sea_surface_temperature data in sea_surface_temperature field' )
- ENDIF
- ! CALL ESMF_FieldGetDataPointer( out_landmask_field, out_landmask_ptr, rc=rc )
- CALL ESMF_FieldGet( out_landmask_field, 0, out_landmask_ptr, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not find land_binary_mask data in land_binary_mask field' )
- ENDIF
- ! staggered starts/ends
- DO j= jps , jpe
- DO i= ips , ipe
- out_sst_ptr(i,j) = file_sst_data(i,j)
- out_landmask_ptr(i,j) = file_landmask_data(i,j)
- ENDDO
- ENDDO
- END SUBROUTINE read_data
- SUBROUTINE compare_data( importState, clock )
- TYPE(ESMF_State), INTENT(INOUT) :: importState
- !TODO: remove clock after debugging is finished
- TYPE(ESMF_Clock), INTENT(INOUT) :: clock
- !<DESCRIPTION>
- ! Gets data from coupler via importState
- ! and compares with data read from file and
- ! error-exits if they differ.
- !
- ! The arguments are:
- ! importState Importstate
- !</DESCRIPTION>
- ! Local variables
- TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
- REAL(ESMF_KIND_R4), POINTER :: in_sst_ptr(:,:), in_landmask_ptr(:,:)
- REAL, POINTER :: in_sst_ptr_real(:,:), in_landmask_ptr_real(:,:)
- INTEGER :: i, j
- INTEGER :: rc
- LOGICAL :: landmask_ok, sst_ok
- ! use these for debug prints
- TYPE(ESMF_Time) :: currentTime
- INTEGER, SAVE :: numtimes=0 ! track number of calls
- CHARACTER(LEN=256) :: timestamp
- ! count calls for debug prints...
- CALL ESMF_ClockGet( clock, CurrTime=currentTime, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( 'compare_data: ESMF_ClockGet() failed' )
- ENDIF
- CALL wrf_timetoa ( currentTime, timestamp )
- numtimes = numtimes + 1
- WRITE(str,*) 'SST compare_data: begin, numtimes = ',numtimes,' time = ',TRIM(timestamp)
- CALL wrf_debug ( 100 , TRIM(str) )
- ! extract data from the importState and compare with data from file
- !TODO: change this to Bundles, eventually
- CALL ESMF_StateGet( importState, TRIM(datanames(SST_INDX)), &
- in_sst_field, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not extract sea_surface_temperature field from importState' )
- ENDIF
- CALL ESMF_StateGet( importState, TRIM(datanames(LANDMASK_INDX)), &
- in_landmask_field, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not extract land_binary_mask field from importState' )
- ENDIF
- ! CALL ESMF_FieldGetDataPointer( in_sst_field, in_sst_ptr, rc=rc )
- CALL ESMF_FieldGet( in_sst_field, 0, in_sst_ptr, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not extract sea_surface_temperature data from sea_surface_temperature field' )
- ENDIF
- ALLOCATE( in_sst_ptr_real(ims:ime,jms:jme) )
- WRITE( str,* ) 'compare_data, ips:ipe,jps:jpe = ', &
- ips,':',ipe,',',jps,':',jpe, &
- ', in_sst_ptr(BOUNDS) = ', &
- LBOUND(in_sst_ptr,1),':',UBOUND(in_sst_ptr,1),',', &
- LBOUND(in_sst_ptr,2),':',UBOUND(in_sst_ptr,2)
- CALL wrf_debug ( 100 , TRIM(str) )
- DO j= jms, jme
- DO i= ims, ime
- in_sst_ptr_real(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
- ENDDO
- ENDDO
- in_sst_ptr_real(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe)) = &
- in_sst_ptr(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe))
- ! CALL ESMF_FieldGetDataPointer( in_landmask_field, in_landmask_ptr, rc=rc )
- CALL ESMF_FieldGet( in_landmask_field, 0, in_landmask_ptr, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- CALL wrf_error_fatal ( &
- 'could not extract land_binary_mask data from land_binary_mask field' )
- ENDIF
- ALLOCATE( in_landmask_ptr_real(ims:ime,jms:jme) )
- WRITE( str,* ) 'compare_data, ips:ipe,jps:jpe = ', &
- ips,':',ipe,',',jps,':',jpe, &
- ', in_landmask_ptr(BOUNDS) = ', &
- LBOUND(in_landmask_ptr,1),':',UBOUND(in_landmask_ptr,1),',', &
- LBOUND(in_landmask_ptr,2),':',UBOUND(in_landmask_ptr,2)
- CALL wrf_debug ( 100 , TRIM(str) )
- DO j= jms, jme
- DO i= ims, ime
- in_landmask_ptr_real(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
- ENDDO
- ENDDO
- in_landmask_ptr_real(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe)) = &
- in_landmask_ptr(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe))
- ! compare LANDMASK...
- landmask_ok = .TRUE.
- ! staggered starts/ends
- LANDMASK_COMPARE : DO j= jps , MIN( (jde-1), jpe )
- DO i= ips , MIN( (ide-1), ipe )
- IF ( file_landmask_data(i,j) /= in_landmask_ptr_real(i,j) ) THEN
- landmask_ok = .FALSE.
- WRITE( str , * ) 'error landmask mismatch at (i,j) = (',i,',',j, &
- '), values are',file_landmask_data(i,j),' and ', &
- in_landmask_ptr_real(i,j)
- EXIT LANDMASK_COMPARE
- ENDIF
- ENDDO
- ENDDO LANDMASK_COMPARE
- IF ( landmask_ok ) THEN
- WRITE(str,*) 'TESTING data returned from WRF through ESMF: LANDMASK compares OK'
- CALL wrf_debug ( 0 , TRIM(str) )
- ELSE
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ! compare SST...
- sst_ok = .TRUE.
- ! staggered starts/ends
- SST_COMPARE : DO j= jps , MIN( (jde-1), jpe )
- DO i= ips , MIN( (ide-1), ipe )
- IF ( file_sst_data(i,j) /= in_sst_ptr_real(i,j) ) THEN
- sst_ok = .FALSE.
- WRITE( str , * ) 'error sst mismatch at (i,j) = (',i,',',j, &
- '), values are',file_sst_data(i,j),' and ', &
- in_sst_ptr_real(i,j)
- EXIT SST_COMPARE
- ENDIF
- ENDDO
- ENDDO SST_COMPARE
- IF ( sst_ok ) THEN
- WRITE(str,*) 'TESTING data returned from WRF through ESMF: SST compares OK'
- CALL wrf_debug ( 0 , TRIM(str) )
- ELSE
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- DEALLOCATE( in_sst_ptr_real, in_landmask_ptr_real )
- WRITE(str,*) 'compare_data: end, numtimes = ',numtimes
- CALL wrf_debug ( 100 , TRIM(str) )
- END SUBROUTINE compare_data
- ! Second-phase "init" gets decomposition information from
- ! importState.
- SUBROUTINE sst_component_init2( gcomp, importState, exportState, clock, rc )
- USE module_metadatautils, ONLY: GetDecompFromState
- USE module_io
- TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
- TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState
- TYPE(ESMF_State), TARGET, INTENT(INOUT) :: exportState
- TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
- INTEGER, INTENT( OUT) :: rc
- !<DESCRIPTION>
- ! SST component init routine, phase 2.
- !
- ! The arguments are:
- ! gcomp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- ! Local variables
- TYPE(ESMF_Field) :: out_sst_field, out_landmask_field
- TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
- INTEGER, PARAMETER :: NUMDIMS=2
- INTEGER :: DomainStart(NUMDIMS)
- INTEGER :: DomainEnd(NUMDIMS)
- INTEGER :: MemoryStart(NUMDIMS)
- INTEGER :: MemoryEnd(NUMDIMS)
- INTEGER :: PatchStart(NUMDIMS)
- INTEGER :: PatchEnd(NUMDIMS)
- INTEGER :: rc, i, j
- INTEGER :: ierr
- ! Get decomposition information from importState. Note that index
- ! values are for staggered dimensions, following the WRF convention.
- !TODO: Note that this will only work for SPMD serial operation. For
- !TODO: concurrent operation (SPMD or MPMD), we will need to create a new
- !TODO: "domdesc" suitable for the task layout of the SST component. For
- !TODO: MPMD serial operation, we will need to extract serialized domdesc
- !TODO: from export state metadata and de-serialize it. Similar arguments
- !TODO: apply to [ij][mp][se] and bdy_mask.
- write(str,*) 'sst_component_init2: calling GetDecompFromState'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL GetDecompFromState( importState, &
- ids, ide, jds, jde, kds, kde, &
- ims, ime, jms, jme, kms, kme, &
- ips, ipe, jps, jpe, kps, kpe, &
- domdesc, bdy_mask )
- write(str,*) 'sst_component_init2: back from GetDecompFromState'
- CALL wrf_debug ( 100 , TRIM(str) )
- write(str,*) 'sst_component_init2: ids, ide, jds, jde, kds, kde = ', ids, ide, jds, jde, kds, kde
- CALL wrf_debug ( 100 , TRIM(str) )
- write(str,*) 'sst_component_init2: ims, ime, jms, jme, kms, kme = ', ims, ime, jms, jme, kms, kme
- CALL wrf_debug ( 100 , TRIM(str) )
- write(str,*) 'sst_component_init2: ips, ipe, jps, jpe, kps, kpe = ', ips, ipe, jps, jpe, kps, kpe
- CALL wrf_debug ( 100 , TRIM(str) )
- ! allocate space for data read from disk
- ALLOCATE( file_sst_data (ims:ime,jms:jme) )
- DO j= jms, jme
- DO i= ims, ime
- file_sst_data(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
- ENDDO
- ENDDO
- !TODO: Hmmm... really need to load these pointers here? Check...
- this_data(SST_INDX)%r2d => file_sst_data
- ALLOCATE( file_landmask_data(ims:ime,jms:jme) )
- DO j= jms, jme
- DO i= ims, ime
- file_landmask_data(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
- ENDDO
- ENDDO
- this_data(LANDMASK_INDX)%r2d => file_landmask_data
- ! Create ESMF_Fields in importState and exportState
- ! Create ESMF_Grid. Use exactly the same method as WRF so WRFIO will
- ! work.
- DomainStart(1) = ids; DomainEnd(1) = ide;
- DomainStart(2) = jds; DomainEnd(2) = jde;
- MemoryStart(1) = ims; MemoryEnd(1) = ime;
- MemoryStart(2) = jms; MemoryEnd(2) = jme;
- PatchStart(1) = ips; PatchEnd(1) = ipe;
- PatchStart(2) = jps; PatchEnd(2) = jpe
- !write(0,*)__FILE__,__LINE__,'DomainStart ',DomainStart(1:2)
- !write(0,*)__FILE__,__LINE__,'DomainEnd ',DomainEnd(1:2)
- !write(0,*)__FILE__,__LINE__,'MemoryStart ',MemoryStart(1:2)
- !write(0,*)__FILE__,__LINE__,'MemoryEnd ',MemoryEnd(1:2)
- !write(0,*)__FILE__,__LINE__,'PatchStart ',PatchStart(1:2)
- !write(0,*)__FILE__,__LINE__,'PatchEnd ',PatchEnd(1:2)
- CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: Calling ioesmf_create_grid_int()' )
- CALL ioesmf_create_grid_int( esmfgrid, NUMDIMS, &
- DomainStart, DomainEnd, &
- MemoryStart, MemoryEnd, &
- PatchStart, PatchEnd )
- !write(0,*)__FILE__,__LINE__
- CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: back from ioesmf_create_grid_int()' )
- ! create ESMF_Fields
- ! Note use of patch dimension for POINTERs allocated by ESMF.
- CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: Calling ESMF_GridValidate(esmfgrid)' )
- CALL ESMF_GridValidate( esmfgrid, rc=rc )
- !write(0,*)__FILE__,__LINE__
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE( str,* ) 'Error in ESMF_GridValidate ', &
- __FILE__ , &
- ', line ', &
- __LINE__ , &
- ', error code = ',rc
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: back OK from ESMF_GridValidate(esmfgrid)' )
- !TODO: Once new ESMF 3.0 interfaces have settled down, eliminate "tmp_data_"
- !TODO: arrays and let ESMF allocate/deallocate them. Assuming of course that
- !TODO: we can convince ESMF to deallocate safely...
- !write(0,*)__FILE__,__LINE__
- ALLOCATE( tmp_data_out_sst(ips:ipe,jps:jpe) )
- !write(0,*)__FILE__,__LINE__
- write(str,*) 'sst_component_init2: tmp_data_out_sst(', &
- LBOUND(tmp_data_out_sst,1),':',UBOUND(tmp_data_out_sst,1),',',LBOUND(tmp_data_out_sst,2),':',UBOUND(tmp_data_out_sst,2),')'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(out_sst_field)' )
- !write(0,*)__FILE__,__LINE__,trim(datanames(sst_indx))
- !write(0,*)__FILE__,__LINE__,ips,jps,ipe,jpe
- out_sst_field = ESMF_FieldCreate( &
- esmfgrid, tmp_data_out_sst, &
- datacopyflag=ESMF_DATACOPY_REFERENCE, &
- staggerloc=ESMF_STAGGERLOC_CENTER, &
- name=TRIM(datanames(SST_INDX)), &
- rc=rc )
- !write(0,*)__FILE__,__LINE__,'Creating out_sst_field for exportState of SST component name ',TRIM(datanames(SST_INDX))
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE( str,* ) 'ESMF_FieldCreate(out_sst_field) failed ', &
- __FILE__ , &
- ', line ', &
- __LINE__ , &
- ', error code = ',rc
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(out_sst_field)' )
- write(str,*) 'sst_component_init2: ips:ipe,jps:jpe = ', &
- ips,':',ipe,',',jps,':',jpe
- CALL wrf_debug ( 100 , TRIM(str) )
- !TODO: This bit will be useful once ESMF handles allocation/deallocation.
- ! validate ESMF allocation
- IF ( ( ips /= LBOUND(tmp_data_out_sst,1) ) .OR. ( ipe /= UBOUND(tmp_data_out_sst,1) ) .OR. &
- ( jps /= LBOUND(tmp_data_out_sst,2) ) .OR. ( jpe /= UBOUND(tmp_data_out_sst,2) ) ) THEN
- WRITE( str,* ) 'ESMF_FieldCreate(out_sst_field) allocation failed ', &
- __FILE__ , &
- ', line ', &
- __LINE__ , &
- ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
- ', tmp_data_out_sst(BOUNDS) = ',LBOUND(tmp_data_out_sst,1),':',UBOUND(tmp_data_out_sst,1),',', &
- LBOUND(tmp_data_out_sst,2),':',UBOUND(tmp_data_out_sst,2)
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ALLOCATE( tmp_data_out_landmask(ips:ipe,jps:jpe) )
- write(str,*) 'sst_component_init2: tmp_data_out_landmask(', &
- LBOUND(tmp_data_out_landmask,1),':',UBOUND(tmp_data_out_landmask,1),',',LBOUND(tmp_data_out_landmask,2),':',UBOUND(tmp_data_out_landmask,2),')'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(out_landmask_field)' )
- out_landmask_field = ESMF_FieldCreate( &
- esmfgrid, tmp_data_out_landmask, &
- datacopyflag=ESMF_DATACOPY_REFERENCE, &
- staggerloc=ESMF_STAGGERLOC_CENTER, &
- name=TRIM(datanames(LANDMASK_INDX)), &
- ! lbounds=(/ips,jps/), &
- ! ubounds=(/ipe,jpe/), &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_FieldCreate(out_landmask_field) failed' )
- ENDIF
- CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(out_landmask_field)' )
- !TODO: This bit will be useful once ESMF handles allocation/deallocation.
- ! validate ESMF allocation
- IF ( ( ips /= LBOUND(tmp_data_out_landmask,1) ) .OR. ( ipe /= UBOUND(tmp_data_out_landmask,1) ) .OR. &
- ( jps /= LBOUND(tmp_data_out_landmask,2) ) .OR. ( jpe /= UBOUND(tmp_data_out_landmask,2) ) ) THEN
- WRITE( str,* ) 'ESMF_FieldCreate(out_landmask_field) allocation failed ', &
- __FILE__ , &
- ', line ', &
- __LINE__ , &
- ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
- ', tmp_data_out_landmask(BOUNDS) = ',LBOUND(tmp_data_out_landmask,1),':',UBOUND(tmp_data_out_landmask,1),',', &
- LBOUND(tmp_data_out_landmask,2),':',UBOUND(tmp_data_out_landmask,2)
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ALLOCATE( tmp_data_in_sst(ips:ipe,jps:jpe) )
- write(str,*) 'sst_component_init2: tmp_data_in_sst(', &
- LBOUND(tmp_data_in_sst,1),':',UBOUND(tmp_data_in_sst,1),',',LBOUND(tmp_data_in_sst,2),':',UBOUND(tmp_data_in_sst,2),')'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(in_sst_field)' )
- in_sst_field = ESMF_FieldCreate( &
- esmfgrid, tmp_data_in_sst, &
- datacopyflag=ESMF_DATACOPY_REFERENCE, &
- staggerloc=ESMF_STAGGERLOC_CENTER, &
- name=TRIM(datanames(SST_INDX)), &
- ! lbounds=(/ips,jps/), &
- ! ubounds=(/ipe,jpe/), &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_FieldCreate(in_sst_field) failed' )
- ENDIF
- CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(in_sst_field)' )
- !TODO: This bit will be useful once ESMF handles allocation/deallocation.
- ! validate ESMF allocation
- IF ( ( ips /= LBOUND(tmp_data_in_sst,1) ) .OR. ( ipe /= UBOUND(tmp_data_in_sst,1) ) .OR. &
- ( jps /= LBOUND(tmp_data_in_sst,2) ) .OR. ( jpe /= UBOUND(tmp_data_in_sst,2) ) ) THEN
- WRITE( str,* ) 'ESMF_FieldCreate(in_sst_field) allocation failed ', &
- __FILE__ , &
- ', line ', &
- __LINE__ , &
- ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
- ', tmp_data_in_sst(BOUNDS) = ',LBOUND(tmp_data_in_sst,1),':',UBOUND(tmp_data_in_sst,1),',', &
- LBOUND(tmp_data_in_sst,2),':',UBOUND(tmp_data_in_sst,2)
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ALLOCATE( tmp_data_in_landmask(ips:ipe,jps:jpe) )
- write(str,*) 'sst_component_init2: tmp_data_in_landmask(', &
- LBOUND(tmp_data_in_landmask,1),':',UBOUND(tmp_data_in_landmask,1),',',LBOUND(tmp_data_in_landmask,2),':',UBOUND(tmp_data_in_landmask,2),')'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(in_landmask_field)' )
- in_landmask_field = ESMF_FieldCreate( &
- esmfgrid, tmp_data_in_landmask, &
- datacopyflag=ESMF_DATACOPY_REFERENCE, &
- staggerloc=ESMF_STAGGERLOC_CENTER, &
- name=TRIM(datanames(LANDMASK_INDX)), &
- ! lbounds=(/ips,jps/), &
- ! ubounds=(/ipe,jpe/), &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_FieldCreate(in_landmask_field) failed' )
- ENDIF
- CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(in_landmask_field)' )
- !TODO: This bit will be useful once ESMF handles allocation/deallocation.
- ! validate ESMF allocation
- IF ( ( ips /= LBOUND(tmp_data_in_landmask,1) ) .OR. ( ipe /= UBOUND(tmp_data_in_landmask,1) ) .OR. &
- ( jps /= LBOUND(tmp_data_in_landmask,2) ) .OR. ( jpe /= UBOUND(tmp_data_in_landmask,2) ) ) THEN
- WRITE( str,* ) 'ESMF_FieldCreate(in_landmask_field) allocation failed ', &
- __FILE__ , &
- ', line ', &
- __LINE__ , &
- ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
- ', tmp_data_in_landmask(BOUNDS) = ',LBOUND(tmp_data_in_landmask,1),':',UBOUND(tmp_data_in_landmask,1),',', &
- LBOUND(tmp_data_in_landmask,2),':',UBOUND(tmp_data_in_landmask,2)
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ! attach ESMF_Field to importState
- CALL ESMF_StateAdd( importState, fieldList=(/in_sst_field/), rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_StateAdd(in_sst_field) failed' )
- ENDIF
- CALL ESMF_StateAdd( importState, fieldList=(/in_landmask_field/), rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_StateAdd(in_landmask_field) failed' )
- ENDIF
- ! attach ESMF_Field to exportState
- CALL ESMF_StateAdd( exportState, fieldList=(/out_sst_field/), rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_StateAdd(out_sst_field) failed' )
- ENDIF
- CALL ESMF_StateAdd( exportState, fieldList=(/out_landmask_field/), rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_StateAdd(out_landmask_field) failed' )
- ENDIF
- ! Open the "SST" input data file for reading.
- write(str,'(A,A)') 'sst_component_init2: Opening data file ', &
- TRIM(sstinfilename)
- CALL wrf_message ( TRIM(str) )
- CALL wrf_open_for_read ( TRIM(sstinfilename) , &
- mpicom , &
- mpicom , &
- "DATASET=INPUT" , &
- fid , &
- ierr )
- IF ( ierr .NE. 0 ) THEN
- WRITE( str , FMT='(A,A,A,I8)' ) &
- 'sst_component_init2: error opening ', &
- TRIM(sstinfilename),' for reading ierr=',ierr
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- WRITE( str , FMT='(A,A,A,I8)' ) &
- 'subroutine sst_component_init2: opened file ', &
- TRIM(sstinfilename),' for reading fid=',fid
- CALL wrf_debug ( 100, TRIM(str) )
- write(str,'(A)') 'sst_component_init2: returning rc=ESMF_SUCCESS'
- CALL wrf_debug ( 100 , TRIM(str) )
- rc = ESMF_SUCCESS
- END SUBROUTINE sst_component_init2
- SUBROUTINE sst_component_run1( gcomp, importState, exportState, clock, rc )
- TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
- TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
- TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
- INTEGER, INTENT( OUT) :: rc
- !<DESCRIPTION>
- ! SST component run routine, phase 1.
- ! Read "SST" data from file and stuff into exportState.
- !
- ! The arguments are:
- ! gcomp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- rc = ESMF_SUCCESS
- ! Get "SST" data from file and stuff it into exportState.
- CALL read_data( exportState, clock )
- END SUBROUTINE sst_component_run1
- SUBROUTINE sst_component_run2( gcomp, importState, exportState, clock, rc )
- TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
- TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
- TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
- INTEGER, INTENT( OUT) :: rc
- !<DESCRIPTION>
- ! SST component run routine, phase 2.
- ! Get from importState, compare with file data, and error-exit
- ! if they differ... If they are the same, then
- ! stuff the file data into the exportState.
- !
- ! The arguments are:
- ! gcomp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- rc = ESMF_SUCCESS
- ! Get from importState, compare with file data, and error_exit
- ! if they differ...
- !TODO: change this once WRF can load exportState after integrating
- ! This works because WRF loads its exportState BEFORE integrating.
- CALL wrf_clockprint ( 50, clock, 'sst_component_run2: clock before call to compare_data()' )
- CALL compare_data( importState, clock )
- CALL wrf_clockprint ( 50, clock, 'sst_component_run2: clock after call to compare_data()' )
- END SUBROUTINE sst_component_run2
- SUBROUTINE sst_component_finalize( gcomp, importState, exportState, clock, rc )
- USE module_io
- TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
- TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
- TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
- INTEGER, INTENT( OUT) :: rc
- !<DESCRIPTION>
- ! SST component finalize routine.
- !
- ! The arguments are:
- ! gcomp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- ! Local variables
- TYPE(ESMF_Field) :: tmp_field
- INTEGER :: i, ierr
- rc = ESMF_SUCCESS
- ! destroy ESMF_Fields and other "deep" objects created by this component
- ! note that this component relied on ESMF to allocate data pointers during
- ! calls to ESMF_FieldCreate() so it also expects ESMF to free these pointers
- DO i=1, datacount
- ! destroy field in importState
- CALL ESMF_StateGet( importState, TRIM(datanames(i)), tmp_field, &
- rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- WRITE( str , * ) &
- 'sst_component_finalize: ESMF_StateGet( importState,', &
- TRIM(datanames(i)),') failed'
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- CALL ESMF_FieldDestroy( tmp_field, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- WRITE( str , * ) &
- 'sst_component_finalize: ESMF_FieldDestroy( importState,', &
- TRIM(datanames(i)),') failed'
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ! destroy field in exportState
- CALL ESMF_StateGet( exportState, TRIM(datanames(i)), tmp_field, &
- rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- WRITE( str , * ) &
- 'sst_component_finalize: ESMF_StateGet( exportState,', &
- TRIM(datanames(i)),') failed'
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- CALL ESMF_FieldDestroy( tmp_field, rc=rc )
- IF (rc /= ESMF_SUCCESS) THEN
- WRITE( str , * ) &
- 'sst_component_finalize: ESMF_FieldDestroy( exportState,', &
- TRIM(datanames(i)),') failed'
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ENDDO
- ! deallocate space for data read from disk
- DEALLOCATE( file_sst_data, file_landmask_data )
- ! close SST data file
- WRITE( str , FMT='(A,I8)' ) &
- 'subroutine sst_component_finalize: closing file fid=',fid
- CALL wrf_debug ( 100, TRIM(str) )
- CALL wrf_ioclose( fid , ierr )
- IF ( ierr .NE. 0 ) THEN
- CALL wrf_error_fatal ( 'sst_component_finalize: wrf_ioclose failed' )
- ENDIF
- END SUBROUTINE sst_component_finalize
- END MODULE module_sst_component_top
- MODULE module_sst_setservices
- !<DESCRIPTION>
- ! This module defines SST "Set Services" method sst_register()
- ! used for ESMF coupling.
- !</DESCRIPTION>
- USE module_sst_component_top, ONLY: sst_component_init1, &
- sst_component_init2, &
- sst_component_run1, &
- sst_component_run2, &
- sst_component_finalize
- ! Updated for ESMF 5.2.0r
- ! USE ESMF_Mod
- USE ESMF
- IMPLICIT NONE
- ! everything is private by default
- PRIVATE
- ! Public entry point for ESMF_GridCompSetServices()
- PUBLIC SST_register
- ! private stuff
- CHARACTER (ESMF_MAXSTR) :: str
- CONTAINS
- SUBROUTINE sst_register(gcomp, rc)
- TYPE(ESMF_GridComp), INTENT(INOUT) :: gcomp
- INTEGER, INTENT(OUT) :: rc
- INTEGER :: finalrc
- !
- !<DESCRIPTION>
- ! SST_register - Externally visible registration routine
- !
- ! User-supplied SetServices routine.
- ! The Register routine sets the subroutines to be called
- ! as the init, run, and finalize routines. Note that these are
- ! private to the module.
- !
- ! The arguments are:
- ! gcomp Component
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- finalrc = ESMF_SUCCESS
- ! Register the callback routines.
- call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, &
- sst_component_init1, phase=1, rc=rc)
- IF ( rc /= ESMF_SUCCESS) THEN
- WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_init1) failed with rc = ', rc
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, &
- sst_component_init2, phase=2, rc=rc)
- IF ( rc /= ESMF_SUCCESS) THEN
- WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_init2) failed with rc = ', rc
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, &
- sst_component_run1, phase=1, rc=rc)
- IF ( rc /= ESMF_SUCCESS) THEN
- WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_run1) failed with rc = ', rc
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, &
- sst_component_run2, phase=2, rc=rc)
- IF ( rc /= ESMF_SUCCESS) THEN
- WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_run2) failed with rc = ', rc
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_FINALIZE, &
- sst_component_finalize, rc=rc)
- IF ( rc /= ESMF_SUCCESS) THEN
- WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_finalize) failed with rc = ', rc
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- PRINT *,'SST: Registered Initialize, Run, and Finalize routines'
- rc = finalrc
- END SUBROUTINE sst_register
- END MODULE module_sst_setservices
- !<DESCRIPTION>
- ! Module module_wrfsst_coupler defines the
- ! "WRF-SST" coupler component. It provides two-way coupling between
- ! the "SST" and "WRF" components.
- ! In its run routine it transfers data directly from the
- ! SST Component's export state to the WRF Component's import state.
- ! It also transfers data directly from the
- ! WRF Component's export state to the SST Component's import state.
- !
- ! This is derived from src/demo/coupled_flow/src/CouplerMod.F90
- ! created by Nancy Collins and others on the ESMF Core Team.
- !
- !</DESCRIPTION>
- MODULE module_wrfsst_coupler
- ! Updated for ESMF 5.2.0r
- ! USE ESMF_Mod
- USE ESMF
- IMPLICIT NONE
-
- ! everything is private by default
- PRIVATE
- ! Public entry point
- PUBLIC WRFSSTCpl_register
- ! private data members
- ! route handles and flags
- TYPE(ESMF_RouteHandle), SAVE :: fromWRF_rh, fromSST_rh
- LOGICAL, SAVE :: fromWRF_rh_ready = .FALSE.
- LOGICAL, SAVE :: fromSST_rh_ready = .FALSE.
- ! field names
- INTEGER, PARAMETER :: datacount = 2
- INTEGER, PARAMETER :: SST_INDX = 1
- INTEGER, PARAMETER :: LANDMASK_INDX = 2
- CHARACTER(LEN=ESMF_MAXSTR), SAVE :: datanames(datacount)
- CHARACTER(LEN=ESMF_MAXSTR) :: str
- CONTAINS
- SUBROUTINE WRFSSTCpl_register(comp, rc)
- TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
- INTEGER, INTENT(OUT) :: rc
- !
- !<DESCRIPTION>
- ! WRFSSTCpl_register - Externally visible registration routine
- !
- ! User-supplied SetServices routine.
- ! The Register routine sets the subroutines to be called
- ! as the init, run, and finalize routines. Note that these are
- ! private to the module.
- !
- ! The arguments are:
- ! comp Component
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- ! guilty until proven innocent
- rc = ESMF_FAILURE
- ! Register the callback routines.
- call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, WRFSSTCpl_init, &
- rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_init) failed' )
- ENDIF
- call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, WRFSSTCpl_run, &
- rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_run) failed' )
- ENDIF
- call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, WRFSSTCpl_final, &
- rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_final) failed' )
- ENDIF
- print *, "module_wrfsst_coupler: Registered Initialize, Run, and Finalize routines"
- END SUBROUTINE WRFSSTCpl_register
- SUBROUTINE WRFSSTCpl_init(comp, importState, exportState, clock, rc)
- USE module_metadatautils, ONLY: AttachDecompToState, GetDecompFromState
- TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
- TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
- TYPE(ESMF_Clock), INTENT(INOUT) :: clock
- INTEGER, INTENT(OUT) :: rc
- !<DESCRIPTION>
- ! WRF-SST coupler component init routine. This simply passes needed
- ! metadata from WRF to SST. Initialization of ESMF_RouteHandle objects
- ! is handled later via lazy evaluation.
- !
- ! The arguments are:
- ! comp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- ! Local variables
- CHARACTER(ESMF_MAXSTR) :: importstatename
- ! decomposition information
- INTEGER :: ids, ide, jds, jde, kds, kde
- INTEGER :: ims, ime, jms, jme, kms, kme
- INTEGER :: ips, ipe, jps, jpe, kps, kpe
- INTEGER :: domdesc
- LOGICAL :: bdy_mask(4)
- PRINT *, "DEBUG: Coupler Init starting"
- ! guilty until proven innocent
- rc = ESMF_FAILURE
- CALL ESMF_StateGet(importState, name=importstatename, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_init: ESMF_StateGet failed' )
- ENDIF
- IF ( TRIM(importstatename) .EQ. "WRF Export State" ) THEN
- ! get metadata from WRF export state
- CALL GetDecompFromState( importState, &
- ids, ide, jds, jde, kds, kde, &
- ims, ime, jms, jme, kms, kme, &
- ips, ipe, jps, jpe, kps, kpe, &
- domdesc, bdy_mask )
- ! put metadata from in SST import state
- CALL AttachDecompToState( exportState, &
- ids, ide, jds, jde, kds, kde, &
- ims, ime, jms, jme, kms, kme, &
- ips, ipe, jps, jpe, kps, kpe, &
- domdesc, bdy_mask )
- ELSE
- WRITE(str,*)'WRFSSTCpl_init: invalid importState name: ',TRIM(importstatename)
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- ! set up field names
- !TODO: use CF conventions for "standard_name" once WRF Registry supports them
- !TODO: datanames(SST_INDX) = "sea_surface_temperature"
- !TODO: datanames(LANDMASK_INDX) = "land_binary_mask"
- datanames(SST_INDX) = "SST"
- datanames(LANDMASK_INDX) = "LANDMASK"
- PRINT *, "DEBUG: Coupler Init returning"
-
- END SUBROUTINE WRFSSTCpl_init
- SUBROUTINE WRFSSTCpl_run(comp, importState, exportState, clock, rc)
- USE ESMF
- TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
- TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
- TYPE(ESMF_Clock), INTENT(INOUT) :: clock
- INTEGER, INTENT(OUT) :: rc
- !<DESCRIPTION>
- ! WRF-SST coupler component run routine.
- !
- ! The arguments are:
- ! comp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- ! Note that comments in this code are preserved from the sample coupler
- ! provided by the ESMF core team.
- ! Local variables
- TYPE(ESMF_Field) :: src_field, dst_field
- TYPE(ESMF_Array) :: src_array, dst_array
- TYPE(ESMF_RouteHandle) :: routehandle
- TYPE(ESMF_VM) :: vm
- LOGICAL :: build_fromWRF_rh, build_fromSST_rh, fromWRF
- CHARACTER(LEN=ESMF_MAXSTR) :: importStatename
- CHARACTER(LEN=ESMF_MAXSTR) :: SST_exportStatename, WRF_exportStatename
- INTEGER :: i
- CHARACTER(LEN=256) :: directionString
- LOGICAL :: neededFlag(1)
- WRITE(str,*) 'WRFSSTCpl_run: begin'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! guilty until proven innocent
- rc = ESMF_FAILURE
- ! Which way is this coupling going?
- WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGet(importState,name,...)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_StateGet( importState, name=importStatename, rc=rc )
- WRITE(str,*) 'WRFSSTCpl_run: importStatename ', trim(importStatename), 'rc = ', rc
- CALL wrf_debug ( 100, TRIM(str) )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGet(importState,name,...) failed' )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: back from ESMF_StateGet, importStatename = <',TRIM(importStatename),'>'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! first time through in each direction: create route handle and
- ! associated objects
- WRF_exportStatename = "WRF Export State"
- SST_exportStatename = "SST Export State"
- IF ( TRIM(importStatename) .EQ. TRIM(WRF_exportStatename) ) THEN
- fromWRF = .TRUE.
- directionString = 'WRFtoSST'
- ELSE IF ( TRIM(importStatename) .EQ. TRIM(SST_exportStatename) ) THEN
- fromWRF = .FALSE.
- directionString = 'SSTtoWRF'
- ELSE
- WRITE(str,*)'WRFSSTCpl_run: invalid importState name: ',TRIM(importstatename)
- CALL wrf_error_fatal ( TRIM(str) )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: fromWRF = ',fromWRF
- CALL wrf_debug ( 100 , TRIM(str) )
- build_fromWRF_rh = fromWRF .AND. ( .NOT. fromWRF_rh_ready )
- build_fromSST_rh = ( .NOT. fromWRF ) .AND. ( .NOT. fromSST_rh_ready )
- WRITE(str,*) 'WRFSSTCpl_run: build_fromWRF_rh = ',build_fromWRF_rh
- CALL wrf_debug ( 100 , TRIM(str) )
- WRITE(str,*) 'WRFSSTCpl_run: build_fromSST_rh = ',build_fromSST_rh
- CALL wrf_debug ( 100 , TRIM(str) )
- IF ( build_fromWRF_rh .OR. build_fromSST_rh ) THEN
- CALL ESMF_CplCompGet( comp, vm=vm, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_CplCompGet failed' )
- ENDIF
- ! The use of literal index "1" here indicates that we don't care which
- ! ESMF_Field we get so we might as well get the first one.
- WRITE(str,*) 'WRFSSTCpl_run: grabbing first field <',TRIM(datanames(1)), &
- '> from import state'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_StateGet( importState, TRIM(datanames(1)), src_field, &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGet(importState) failed' )
- ENDIF
- CALL ESMF_FieldGet( src_field, array=src_array, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldGet src_array failed' )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: grabbing first field <',TRIM(datanames(1)), &
- '> from export state'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_StateGet( exportState, TRIM(datanames(1)), dst_field, &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE(str,*)'WRFSSTCpl_run: datanames(1) ',TRIM(datanames(1)),' rc ',rc
- CALL wrf_message(TRIM(str))
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGet(exportState) failed' )
- ENDIF
- CALL ESMF_FieldGet( dst_field, array=dst_array, &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldGet dst_array failed' )
- ENDIF
- IF ( build_fromWRF_rh ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: creating fromWRF_rh'
- CALL wrf_debug ( 100 , TRIM(str) )
- fromWRF_rh = ESMF_RouteHandleCreate( rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_RouteHandleCreate(fromWRF_rh) failed' )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedistStore(fromWRF_rh)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_ArrayRedistStore( src_array, dst_array, &
- routehandle=fromWRF_rh, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedistStore(fromWRF_rh) failed' )
- ENDIF
- fromWRF_rh_ready = .TRUE.
- ENDIF
- IF ( build_fromSST_rh ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: creating fromSST_rh'
- CALL wrf_debug ( 100 , TRIM(str) )
- fromSST_rh = ESMF_RouteHandleCreate( rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_RouteHandleCreate(fromSST_rh) failed' )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedistStore(fromSST_rh)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_ArrayRedistStore( src_array, dst_array, &
- routehandle=fromSST_rh, rc=rc )
- !write(0,*)__FILE__,__LINE__,'rc = ',rc
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedistStore(fromSST_rh) failed' )
- ENDIF
- fromSST_rh_ready = .TRUE.
- ENDIF
- DO i=1, datacount
- WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_AttributeSet(importState, ',TRIM(datanames(i))//':needed',')'
- CALL wrf_debug ( 100 , TRIM(str) )
- !5.2.0r CALL ESMF_StateSetNeeded( importState, TRIM(datanames(i)), &
- !5.2.0r ESMF_NEEDED, rc=rc )
- CALL ESMF_AttributeSet( importState, name=TRIM(datanames(i))//':needed',value=.true.,rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: ESMF_AttributeSet(',TRIM(datanames(i))//':needed',') failed'
- CALL wrf_error_fatal ( str )
- ENDIF
- ENDDO
- ENDIF
- ! In this case, the coupling is symmetric - you call redist going
- ! both ways - so we only care about the coupling direction in order
- ! to get the right routehandle selected.
- IF ( fromWRF ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: routehandle = fromWRF_rh'
- CALL wrf_debug ( 100 , TRIM(str) )
- routehandle = fromWRF_rh
- ELSE
- WRITE(str,*) 'WRFSSTCpl_run: routehandle = fromSST_rh'
- CALL wrf_debug ( 100 , TRIM(str) )
- routehandle = fromSST_rh
- ENDIF
- DO i=1, datacount
- WRITE(str,*) 'WRFSSTCpl_run: grabbing field <',TRIM(datanames(i)),'>'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! check isneeded flag here
- !5.2.0r IF ( .NOT. ESMF_StateIsNeeded( importState, TRIM(datanames(i)), rc=rc ) ) THEN
- !5.2.0r IF ( rc /= ESMF_SUCCESS ) THEN
- !5.2.0r WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateIsNeeded(',TRIM(datanames(i)),') failed'
- !5.2.0r CALL wrf_error_fatal ( str )
- !5.2.0r ENDIF
- !5.2.0r WRITE(str,*) 'WRFSSTCpl_run: skipping field <',TRIM(datanames(i)),'>'
- !5.2.0r CALL wrf_debug ( 100 , TRIM(str) )
- !5.2.0r CYCLE
- !5.2.0r ENDIF
- CALL ESMF_AttributeGet(importState,name=TRIM(datanames(i))//':needed',valueList=neededFlag,rc=rc)
- IF ( rc == ESMF_SUCCESS ) THEN
- IF ( .NOT. neededFlag(1) ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: skipping field <',TRIM(datanames(i)),'>'
- CALL wrf_debug ( 100 , TRIM(str) )
- CYCLE
- ENDIF
- ELSE
- WRITE(str,*) 'WRFSSTCpl_run: ESMF_AttributeGet(',TRIM(datanames(i))//':needed',') failed'
- CALL wrf_error_fatal ( str )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: processing field <',TRIM(datanames(i)),'>'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! The following piece of code provides an example of calling the data
- ! redistribution routine between two Fields in the Coupler Component.
- ! Unlike regrid, which translates between
- ! different Grids, redist translates between different DELayouts on
- ! the same Grid. The first two lines get the Fields from the
- ! States, each corresponding to a different subcomponent. One is
- ! an Export State and the other is an Import State.
- !
- WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGet(importState,', &
- TRIM(datanames(i)),')...'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_StateGet( importState, TRIM(datanames(i)), src_field, &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateGet(importState,', &
- TRIM(datanames(i)),') failed'
- CALL wrf_error_fatal ( str )
- ENDIF
- CALL ESMF_FieldGet( src_field, array=src_array, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: ESMF_FieldGet(src_field,src_array,rc) failed'
- CALL wrf_error_fatal ( str )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGet(exportState,', &
- TRIM(datanames(i)),')...'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_StateGet( exportState, TRIM(datanames(i)), dst_field, &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateGet(exportState,', &
- TRIM(datanames(i)),') failed'
- CALL wrf_error_fatal ( str )
- ENDIF
- CALL ESMF_FieldGet( dst_field, array=dst_array, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- WRITE(str,*) 'WRFSSTCpl_run: ESMF_FieldGet(dst_field,dst_array,rc) failed'
- CALL wrf_error_fatal ( str )
- ENDIF
- ! The redist routine uses information contained in the Fields and the
- ! Coupler VM object to call the communication routines to move the data.
- ! Because many Fields may share the same Grid association, the same
- ! routing information may be needed repeatedly. Route information is
- ! saved so the precomputed information can be retained. The following
- ! is an example of a Field redist call:
- WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedist for <', &
- TRIM(datanames(i)),'>...'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_ArrayRedist( src_array, dst_array, routehandle, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedist failed' )
- ENDIF
- WRITE(str,*) 'WRFSSTCpl_run: back from ESMF_FieldRedist for <', &
- TRIM(datanames(i)),'>...'
- CALL wrf_debug ( 100 , TRIM(str) )
- ENDDO
- WRITE(str,*) 'WRFSSTCpl_run: end'
- CALL wrf_debug ( 100 , TRIM(str) )
- END SUBROUTINE WRFSSTCpl_run
- SUBROUTINE WRFSSTCpl_final(comp, importState, exportState, clock, rc)
- TYPE(ESMF_CplComp) :: comp
- TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
- TYPE(ESMF_Clock), INTENT(INOUT) :: clock
- INTEGER, INTENT(OUT) :: rc
- !<DESCRIPTION>
- ! WRF-SST coupler component finalize routine.
- !
- ! The arguments are:
- ! comp Component
- ! importState Importstate
- ! exportState Exportstate
- ! clock External clock
- ! rc Return code; equals ESMF_SUCCESS if there are no errors,
- ! otherwise ESMF_FAILURE.
- !</DESCRIPTION>
- PRINT *, "DEBUG: Coupler Final starting"
-
- ! guilty until proven innocent
- rc = ESMF_FAILURE
- ! Only thing to do here is release redist and route handles
- IF ( fromWRF_rh_ready ) THEN
- CALL ESMF_RouteHandleDestroy(fromWRF_rh, rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_RouteHandleDestroy(fromWRF_rh) failed' )
- ENDIF
- ENDIF
- IF ( fromSST_rh_ready ) THEN
- CALL ESMF_RouteHandleDestroy(fromSST_rh, rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_RouteHandleDestroy(fromSST_rh) failed' )
- ENDIF
- ENDIF
- PRINT *, "DEBUG: Coupler Final returning"
-
- END SUBROUTINE WRFSSTCpl_final
- END MODULE module_wrfsst_coupler
-
-
- PROGRAM wrf_SST_ESMF
- !<DESCRIPTION>
- ! ESMF Application Wrapper for coupling WRF with a "dummy" component
- ! that simply reads SSTs from a file and sends them to WRF (one-way
- ! coupling). Fields are returned from WRF to SST via the coupler for
- ! self-test only.
- !
- ! Note that, like other WRF coupling methods (MCEL, MCT), ESMF coupling is
- ! supported only via auxiliary input and history streams.
- !
- ! This is the main program that creates the ESMF Gridded and Coupler
- ! Component.
- !
- ! "init" looks like this:
- ! 1. Init phase 1 for WRF, sets WRF exportState metadata for "time"
- ! and "domain" information needed by WRF IOAPI (which is called from
- ! the SST component). It also sets up all WRF and WSF modules. Note
- ! that this must be called before SST phase-1 init because SST uses
- ! WRF IOAPI.
- ! 2. Init phase 1 for SST, sets "time" metadata in SST exportState.
- ! 3. Initialize coupler, passing decomposition metadata from WRF exportState
- ! to SST importState.
- ! 4. Resolve any "time" metadata inconsistencies and create top-level clock.
- ! 5. Init phase 2 for SST, gets "domain" information from importState,
- ! creates an ESMF_Grid based on "domain" information using the exact same
- ! method as WRF (so WRF IOAPI calls will work), and sets up SST
- ! importState and exportState.
- ! 6. Init phase 2 for WRF, runs up to the end of the head_grid I/O "training"
- ! phase (done in med_before_solve_io()). This initializes WRF
- ! importState and exportState prior to the first coupling step during the
- ! "run" loop. Note that this only works for head_grid at present because
- ! recursion in WRF traversal of subdomains is not dealt with yet and
- ! because the code that populates the WRF importState and exportState is
- ! not yet sophisticated enough to handle creating and destroying nested
- ! domains at any time during the model run.
- !TODO: ESMF auxio must begin at the start of the run. Remove this
- !TODO: restriction later, if needed.
- !
- !TODO: Note that coupling is currently limited to one auxin plus one auxout
- !TODO: streams. Extension to multiple pairs of auxio streams requires
- !TODO: nested states (one for each auxio stream pair).
- !TODO: For now, only support one input and/or one output stream via
- !TODO: io_esmf. This condition is asserted in
- !TODO: ext_esmf_open_for_read_begin() and
- !TODO: ext_esmf_open_for_write_begin().
- !
- ! "run" loop looks like this:
- ! 1. Run SST phase 1, reads SST from file and writes it to SST exportState
- ! for coupling to WRF.
- ! 2. Couple SST exportState -> WRF importState. First iteration: set up
- ! SST->WRF routeHandle via lazy evaluation.
- ! 3. Run WRF. First iteration: head_grid resumes after I/O "training"
- ! phase. Other iterations and domains: run normally.
- ! Read WRF importState and write WRF exportState (via med_before_solve_io()).
- ! Note that WRF assigns sst -> tsk for sea points in
- ! share/module_soil_pre.F.
- ! 4. Couple WRF exportState -> SST importState. First iteration: set up
- ! WRF->SST routeHandle via lazy evaluation.
- ! 5. Run SST phase 2, compare SST from file with SST from WRF (via
- ! SST importState) and error-exit if they differ.
- ! 6. Advance clock and goto step 1
- !
- ! "finalize" is trivial, except for destruction of ESMF objects which is
- ! quite non-trivial at the moment.
- !
- !</DESCRIPTION>
- ! WRF registration routine
- USE module_wrf_setservices, ONLY: WRF_register
- ! SST registration routine
- USE module_sst_setservices, ONLY: SST_register
- ! WRF-SST coupler registration routine
- USE module_wrfsst_coupler, ONLY: WRFSSTCpl_register
- ! ESMF module, defines all ESMF data types and procedures
- ! Updated for ESMF 5.2.0r
- ! USE ESMF_Mod
- USE ESMF
- ! Not-yet-implemented ESMF features
- USE module_esmf_extensions
- ! Component-independent utilities
- USE module_metadatautils, ONLY: GetTimesFromStates
- IMPLICIT NONE
- ! Local variables
- ! Components
- TYPE(ESMF_GridComp) :: compGriddedWRF ! WRF
- TYPE(ESMF_GridComp) :: compGriddedSST ! SST reader
- TYPE(ESMF_CplComp) :: compCplWRFSST ! WRF-SST coupler
- ! State, Virtual Machine, and DELayout
- TYPE(ESMF_VM) :: vm
- TYPE(ESMF_State) :: importStateWRF, exportStateWRF
- TYPE(ESMF_State) :: importStateSST, exportStateSST
- ! A clock, some times, and a time step
- TYPE(ESMF_Clock) :: driverClock
- TYPE(ESMF_Time) :: startTime
- TYPE(ESMF_Time) :: stopTime
- TYPE(ESMF_TimeInterval) :: couplingInterval
- ! other misc stuff
- TYPE(ESMF_State) :: tmpState
- INTEGER :: timestepdebug
- INTEGER :: thecount ! ah ah ah
- ! Return codes for error checks
- INTEGER :: rc
- CHARACTER (ESMF_MAXSTR) :: str
- ! debugging
- CHARACTER(LEN=256) :: couplingIntervalString
- integer(ESMF_KIND_I4) :: timevals(6)
-
- ! Warn users that this is not yet ready for general use.
- PRINT *, ' W A R N I N G '
- PRINT *, ' ESMF COUPLING CAPABILITY IS EXPERIMENTAL AND UNSUPPORTED '
- PRINT *, ' IN THIS VERSION OF WRF-CPL-SST '
- PRINT *, ' U S E A T Y O U R O W N R I S K '
- ! Initialize ESMF, get the default Global VM, and set
- ! the default calendar to be Gregorian.
- #ifdef NO_LEAP_CALENDAR
- CALL ESMF_Initialize( vm=vm, defaultCalKind=ESMF_CALKIND_NOLEAP, logkindflag=ESMF_LOGKIND_MULTI,rc=rc )
- #else
- CALL ESMF_Initialize( vm=vm, defaultCalKind=ESMF_CALKIND_GREGORIAN, logkindflag=ESMF_LOGKIND_MULTI,rc=rc )
- #endif
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_Initialize failed'
- ENDIF
- ! Note: wrf_debug and wrf_error_fatal are not initialized yet
- PRINT *, 'DEBUG wrf_SST_ESMF: returned from ESMF_Initialize'
- CALL ESMF_SetInitialized() ! eliminate this once ESMF does it internally
- ! Create the WRF Gridded Component, passing in the default VM.
- compGriddedWRF = ESMF_GridCompCreate( name="WRF Model", rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_GridCompCreate(WRF Model) failed'
- ENDIF
- ! Create the SST Gridded Component, passing in the default VM.
- compGriddedSST = ESMF_GridCompCreate( name="SST Dummy Model", rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_GridCompCreate(WRF Dummy Model) failed'
- ENDIF
- ! Create the WRF-SST Coupler Component, passing in the default VM.
- compCplWRFSST = ESMF_CplCompCreate( name="WRF-SST Coupler", rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_CplCompCreate failed'
- ENDIF
- ! Create empty import and export states for WRF
- importStateWRF = ESMF_StateCreate(name="WRF Import State", stateintent=ESMF_STATEINTENT_IMPORT, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(WRF Import State) failed'
- ENDIF
- exportStateWRF = ESMF_StateCreate(name="WRF Export State", stateintent=ESMF_STATEINTENT_EXPORT, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(WRF Export State) failed'
- ENDIF
- ! Create empty import and export states for SST
- importStateSST = ESMF_StateCreate(name="SST Import State", stateintent=ESMF_STATEINTENT_IMPORT, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(SST Import State) failed'
- ENDIF
- exportStateSST = ESMF_StateCreate(name="SST Export State", stateintent=ESMF_STATEINTENT_EXPORT, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(SST Export State) failed'
- ENDIF
- ! Register the WRF Gridded Component
- CALL ESMF_GridCompSetServices(compGriddedWRF, WRF_register, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_GridCompSetServices(compGriddedWRF) failed'
- ENDIF
- ! Register the SST Gridded Component
- CALL ESMF_GridCompSetServices(compGriddedSST, SST_register, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_GridCompSetServices(compGriddedSST) failed'
- ENDIF
- ! Register the WRF-SST Coupler Component
- CALL ESMF_CplCompSetServices(compCplWRFSST, WRFSSTCpl_register, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_CplCompSetServices failed'
- ENDIF
- ! Create top-level clock. There is no way to create an "empty" clock, so
- ! stuff in bogus values for start time, stop time, and time step and fix
- ! them after gridded component "init" phases return.
- CALL ESMF_TimeSet(startTime, yy=2000, mm=1, dd=1, &
- h=0, m=0, s=0, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_TimeSet(startTime) failed'
- ENDIF
- CALL ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, &
- h=12, m=0, s=0, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_TimeSet(stopTime) failed'
- ENDIF
- CALL ESMF_TimeIntervalSet(couplingInterval, s=2, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_TimeIntervalSet failed'
- ENDIF
- driverClock = ESMF_ClockCreate(timeStep=couplingInterval, &
- startTime=startTime, &
- stopTime=stopTime, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- PRINT *, 'wrf_SST_ESMF: ESMF_ClockCreate failed'
- ENDIF
- ! Init, Run, and Finalize section
- ! Init...
- ! initialize WRF, phase 1
- ! Phase 1 init returns WRF time and decomposition information as
- ! exportState metadata.
- PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 WRF init (wrf_component_init1)'
- CALL ESMF_GridCompInitialize(compGriddedWRF, importstate=importStateWRF, &
- exportstate=exportStateWRF, clock=driverClock, phase=1, rc=rc)
- thecount = size(timevals)
- call esmf_attributeget(exportstatewrf,'ComponentCouplingInterval',timevals,itemcount=thecount,rc=rc)
- !write(0,*) 'exportStateWRF year ',timevals(1),__LINE__
- !write(0,*) 'exportStateWRF month ',timevals(2),__LINE__
- !write(0,*) 'exportStateWRF day ',timevals(3),__LINE__
- !write(0,*) 'exportStateWRF hour ',timevals(4),__LINE__
- !write(0,*) 'exportStateWRF minute ',timevals(5),__LINE__
- !write(0,*) 'exportStateWRF second ',timevals(6),__LINE__
- ! Note: wrf_debug and wrf_error_fatal are now initialized
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(WRF phase 1) failed' )
- ENDIF
- ! initialize SST, phase 1
- ! Phase 1 init returns SST time information as
- ! exportState metadata.
- PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 SST init (sst_component_init1)'
- CALL ESMF_GridCompInitialize(compGriddedSST, importstate=importStateSST, &
- exportstate=exportStateSST, clock=driverClock, phase=1, rc=rc)
- thecount = size(timevals)
- call esmf_attributeget(exportstatesst,'ComponentCouplingInterval',timevals,itemcount=thecount,rc=rc)
- !write(0,*) 'exportStateSST year ',timevals(1),__LINE__
- !write(0,*) 'exportStateSST month ',timevals(2),__LINE__
- !write(0,*) 'exportStateSST day ',timevals(3),__LINE__
- !write(0,*) 'exportStateSST hour ',timevals(4),__LINE__
- !write(0,*) 'exportStateSST minute ',timevals(5),__LINE__
- !write(0,*) 'exportStateSST second ',timevals(6),__LINE__
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(SST phase 1) failed' )
- ENDIF
- ! Reconcile clock settings from WRF and SST components to set up
- ! top-level clock. These are passed back from each "init" as attributes
- ! on exportState*.
- ! Stuff both States into a single State to pass into GetTimesFromStates()
- ! which is smart enough to deal with a Composite.
- PRINT *, 'DEBUG wrf_SST_ESMF: reconciling clock from WRF and SST components'
- tmpState = ESMF_StateCreate( rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateCreate(tmpState) failed' )
- ENDIF
- CALL ESMF_StateAdd( tmpState, nestedStateList=(/exportStateWRF,exportStateSST/), rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateAdd(exportStateWRF,exportStateSST) failed' )
- ENDIF
- CALL GetTimesFromStates( tmpState, startTime, stopTime, couplingInterval )
- CALL ESMF_TimeIntervalGet( couplingInterval, TimeString=couplingIntervalString, &
- rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_TimeIntervalGet failed' )
- ENDIF
- CALL wrf_debug( 100, 'wrf_SST_ESMF: couplingInterval = '//TRIM(couplingIntervalString) )
- CALL ESMF_StateDestroy( tmpState, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(tmpState) failed' )
- ENDIF
- ! update driver clock
- CALL ESMF_ClockDestroy(driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockDestroy failed' )
- ENDIF
- driverClock = ESMF_ClockCreate(timeStep=couplingInterval, &
- startTime=startTime, &
- stopTime=stopTime, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockCreate(driverClock) failed' )
- ENDIF
- PRINT *, 'DEBUG wrf_SST_ESMF: done reconciling clock from WRF and SST components'
- CALL wrf_clockprint(50, driverClock, &
- 'DEBUG wrf_SST_ESMF: driverClock after creation,')
- ! initialize WRF-SST Coupler
- PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 CPL init (WRFSSTCpl_init)'
- CALL ESMF_CplCompInitialize(compCplWRFSST, importstate=exportStateWRF, &
- exportstate=importStateSST, clock=driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompInitialize(WRF -> SST) failed' )
- ENDIF
- ! TBH: this bit is not needed, but would be in general
- ! CALL ESMF_CplCompInitialize(compCplWRFSST, importstate=exportStateSST, &
- ! exportstate=importStateWRF, clock=driverClock, rc=rc)
- ! IF ( rc /= ESMF_SUCCESS ) THEN
- ! CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompInitialize(SST -> WRF) failed' )
- ! ENDIF
- ! initialize SST, phase 2
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 init for SST (sst_component_init2)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_GridCompInitialize(compGriddedSST, importstate=importStateSST, &
- exportstate=exportStateSST, clock=driverClock, phase=2, rc=rc)
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 init for SST'
- CALL wrf_debug ( 100 , TRIM(str) )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(SST phase 2) failed' )
- ENDIF
- ! initialize WRF, phase 2
- ! Phase 2 init sets up WRF importState and exportState.
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 init for WRF (wrf_component_init2)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_GridCompInitialize(compGriddedWRF, importstate=importStateWRF, &
- exportstate=exportStateWRF, clock=driverClock, phase=2, rc=rc)
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 init for WRF'
- CALL wrf_debug ( 100 , TRIM(str) )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(WRF phase 2) failed' )
- ENDIF
- CALL wrf_clockprint(50, driverClock, &
- 'DEBUG wrf_SST_ESMF: driverClock before main time-stepping loop,')
- ! Run...
- ! main time-stepping loop
- timestepdebug = 0
- DO WHILE ( .NOT. ESMF_ClockIsStopTime(driverClock, rc=rc) )
- timestepdebug = timestepdebug + 1
- WRITE(str,'(A,I8)') 'PROGRAM wrf_SST_ESMF: Top of time-stepping loop, timestepdebug = ',timestepdebug
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL wrf_clockprint(50, driverClock, &
- 'DEBUG wrf_SST_ESMF: driverClock at top of time-stepping loop,')
- ! Run SST phase 1
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-1 run for SST (sst_component_run1)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_GridCompRun(compGriddedSST, importstate=importStateSST, exportstate=exportStateSST, &
- clock=driverClock, phase=1, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(SST phase 1) failed' )
- ENDIF
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-1 run for SST (sst_component_run1)'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! couple SST export -> WRF import
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for CPL SST->WRF (WRFSSTCpl_run)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_CplCompRun(compCplWRFSST, importstate=exportStateSST, &
- exportstate=importStateWRF, clock=driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompRun(SST -> WRF) failed' )
- ENDIF
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for CPL SST->WRF (WRFSSTCpl_run)'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! Run WRF
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for WRF (wrf_component_run)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_GridCompRun(compGriddedWRF, importstate=importStateWRF, exportstate=exportStateWRF, &
- clock=driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(WRF) failed' )
- ENDIF
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for WRF (wrf_component_run)'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! couple WRF export -> SST import
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for CPL WRF->SST (WRFSSTCpl_run)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_CplCompRun(compCplWRFSST, importstate=exportStateWRF, &
- exportstate=importStateSST, clock=driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompRun(WRF -> SST) failed' )
- ENDIF
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for CPL WRF->SST (WRFSSTCpl_run)'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! Run SST phase 2
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 run for SST (sst_component_run2)'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_GridCompRun(compGriddedSST, importstate=importStateSST, exportstate=exportStateSST, &
- clock=driverClock, phase=2, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(SST phase 2) failed' )
- ENDIF
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 run for SST (sst_component_run2)'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! advance clock to next coupling time step
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: advancing clock'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL ESMF_ClockAdvance( driverClock, rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockAdvance failed' )
- ENDIF
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: done advancing clock'
- CALL wrf_debug ( 100 , TRIM(str) )
- CALL wrf_clockprint(50, driverClock, &
- 'DEBUG wrf_SST_ESMF: driverClock at end of time-stepping loop,')
- ENDDO
- WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: done with time-stepping loop'
- CALL wrf_debug ( 100 , TRIM(str) )
- ! clean up SST
- CALL ESMF_GridCompFinalize(compGriddedSST, importstate=importStateSST, exportstate=exportStateSST, &
- clock=driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompFinalize(compGriddedSST) failed' )
- ENDIF
-
- ! clean up compCplWRFSST
- CALL ESMF_CplCompFinalize( compCplWRFSST, importstate=exportStateWRF, exportstate=importStateSST, &
- clock=driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompFinalize(compCplWRFSST) failed' )
- ENDIF
-
- ! clean up WRF
- ! must do this AFTER clean up of SST since SST uses WRF IOAPI
- CALL ESMF_GridCompFinalize(compGriddedWRF, importstate=importStateWRF, exportstate=exportStateWRF, &
- clock=driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompFinalize(compGriddedWRF) failed' )
- ENDIF
-
- ! Clean up
- CALL ESMF_GridCompDestroy(compGriddedWRF, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompDestroy(compGriddedWRF) failed' )
- ENDIF
- CALL ESMF_StateDestroy(importStateWRF, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(importStateWRF) failed' )
- ENDIF
- CALL ESMF_StateDestroy(exportStateWRF, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(exportStateWRF) failed' )
- ENDIF
- CALL ESMF_StateDestroy(importStateSST, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(importStateSST) failed' )
- ENDIF
- CALL ESMF_StateDestroy(exportStateSST, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(exportStateSST) failed' )
- ENDIF
- CALL ESMF_ClockDestroy(driverClock, rc=rc)
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockDestroy(driverClock) failed' )
- ENDIF
- CALL ESMF_Finalize( rc=rc )
- IF ( rc /= ESMF_SUCCESS ) THEN
- CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_Finalize failed' )
- ENDIF
- END PROGRAM wrf_SST_ESMF