5 ! ESMF Application Wrapper for coupling WRF with a "dummy" component
6 ! that simply reads SSTs from a file, sends to WRF, receives SST from
7 ! WRF (two-way coupling). and checks that the SSTs match.
9 ! This file contains the main program and associated modules for the
10 ! SST "dummy" component and a simple coupler. It creates ESMF Gridded
11 ! and Coupler Components.
13 ! This source file is only built when ESMF coupling is used.
20 ! Modules module_sst_component_top and module_sst_setservices define the
21 ! "SST" dummy component.
24 MODULE module_sst_component_top
26 ! This module defines sst_component_init1(), sst_component_init2(),
27 ! sst_component_run1(), sst_component_run2(), and sst_component_finalize()
28 ! routines that are called when SST is run as an ESMF component.
31 ! Updated for ESMF 5.2.0r -- see:
32 ! http://www.earthsystemmodeling.org/esmf_releases/public/ESMF_5_2_0r/InterfaceChanges520to520r.pdf
35 USE module_esmf_extensions
36 USE module_metadatautils, ONLY: AttachTimesToState
41 ! everything is private by default
45 PUBLIC sst_component_init1
46 PUBLIC sst_component_init2
47 PUBLIC sst_component_run1
48 PUBLIC sst_component_run2
49 PUBLIC sst_component_finalize
52 TYPE(ESMF_Grid), SAVE :: esmfgrid ! grid used in fields
53 CHARACTER (4096) :: str
54 INTEGER, SAVE :: fid ! file handle
55 ! decomposition information
56 INTEGER, SAVE :: ids, ide, jds, jde, kds, kde
57 INTEGER, SAVE :: ims, ime, jms, jme, kms, kme
58 INTEGER, SAVE :: ips, ipe, jps, jpe, kps, kpe
59 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_out_sst(:,:)
60 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_out_landmask(:,:)
61 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_in_sst(:,:)
62 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_in_landmask(:,:)
63 INTEGER, SAVE :: domdesc
64 LOGICAL, SAVE :: bdy_mask(4)
65 ! MPI communicator, if needed
66 INTEGER, SAVE :: mpicom
68 REAL, POINTER, SAVE :: file_landmask_data(:,:), file_sst_data(:,:)
69 ! input data file name
70 CHARACTER ( ESMF_MAXSTR ), SAVE :: sstinfilename
72 INTEGER, PARAMETER :: datacount = 2
73 INTEGER, PARAMETER :: SST_INDX = 1
74 INTEGER, PARAMETER :: LANDMASK_INDX = 2
75 CHARACTER(LEN=ESMF_MAXSTR), SAVE :: datanames(datacount)
77 REAL, POINTER :: r2d(:,:)
79 TYPE(real2d) :: this_data(datacount)
86 ! First-phase "init" reads "SST" data file and returns "time" metadata in
88 SUBROUTINE sst_component_init1( gcomp, importState, exportState, clock, rc )
90 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
91 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState
92 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: exportState
93 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
94 INTEGER, INTENT( OUT) :: rc
96 ! SST component init routine, phase 1.
100 ! importState Importstate
101 ! exportState Exportstate
102 ! clock External clock
103 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
104 ! otherwise ESMF_FAILURE.
112 CHARACTER (LEN=19) :: date_string
117 TYPE(ESMF_Time) :: startTime, stopTime, currentTime, dataTime
118 TYPE(ESMF_TimeInterval) :: timeStep
119 INTEGER :: ierr, num_steps, time_loop_max
120 INTEGER :: status_next_var
122 !TODO: For now, sstinfilename is hard-coded
123 !TODO: Upgrade to use a variant of construct_filename() via startTime
124 !TODO: extracted from clock.
125 sstinfilename = 'sstin_d01_000000'
127 ! get MPI communicator out of current VM and duplicate (if needed)
129 CALL ESMF_VMGetCurrent(vm, rc=rc)
130 IF ( rc /= ESMF_SUCCESS ) THEN
131 CALL wrf_error_fatal ( 'sst_component_init1: ESMF_VMGetCurrent failed' )
133 CALL ESMF_VMGet(vm, mpiCommunicator=mpicomtmp, rc=rc)
134 IF ( rc /= ESMF_SUCCESS ) THEN
135 CALL wrf_error_fatal ( 'sst_component_init1: ESMF_VMGet failed' )
137 CALL MPI_Comm_dup( mpicomtmp, mpicom, ierr )
141 ! Open the "SST" input data file for reading.
142 write(str,'(A,A)') 'Subroutine sst_component_init1: Opening data file ', &
144 CALL wrf_message ( TRIM(str) )
145 CALL wrf_open_for_read ( TRIM(sstinfilename) , &
151 IF ( ierr .NE. 0 ) THEN
152 WRITE( str , FMT='(A,A,A,I8)' ) &
153 'subroutine sst_component_init1: error opening ', &
154 TRIM(sstinfilename),' for reading ierr=',ierr
155 CALL wrf_error_fatal ( TRIM(str) )
157 WRITE( str , FMT='(A,A,A,I8)' ) &
158 'subroutine sst_component_init1: opened file ', &
159 TRIM(sstinfilename),' for reading fid=',fid
160 CALL wrf_debug ( 100, TRIM(str) )
162 ! How many data time levels are in the SST input file?
165 CALL wrf_debug ( 100, 'subroutine sst_component_init1: find time_loop_max' )
166 ! compute SST start time, time step, and end time here
167 get_the_right_time : DO
168 CALL wrf_get_next_time ( fid, date_string, status_next_var )
169 write(str,'(A,A)') 'Subroutine sst_component_init1: SST data startTime: ', &
171 CALL wrf_debug ( 100 , TRIM(str) )
172 IF ( status_next_var == 0 ) THEN
173 IF ( time_loop_max == 0 ) THEN
174 CALL wrf_atotime( date_string, startTime )
175 ELSEIF ( time_loop_max == 1 ) THEN
176 ! assumes fixed time step!
177 CALL wrf_atotime( date_string, dataTime )
178 timeStep = dataTime - startTime
180 time_loop_max = time_loop_max + 1
181 CALL wrf_atotime( date_string, stopTime )
183 EXIT get_the_right_time
185 END DO get_the_right_time
186 CALL wrf_timetoa ( stopTime, date_string )
187 write(str,'(A,A)') 'Subroutine sst_component_init1: SST data stopTime: ', &
189 CALL wrf_debug ( 100 , TRIM(str) )
190 ! attach times to exportState for use by driver
191 CALL AttachTimesToState( exportState, startTime, stopTime, timeStep )
193 ! There should be a more elegant way to get to the beginning of the
194 ! file, but this will do.
195 CALL wrf_ioclose( fid , ierr )
196 IF ( ierr .NE. 0 ) THEN
197 CALL wrf_error_fatal ( 'sst_component_init1: wrf_ioclose failed' )
199 WRITE( str , FMT='(A,I8)' ) &
200 'subroutine sst_component_init1: closed file fid=',fid
201 CALL wrf_debug ( 100, TRIM(str) )
204 !TODO: use CF conventions for "standard_name" once WRF Registry supports them
205 !TODO: datanames(SST_INDX) = "sea_surface_temperature"
206 !TODO: datanames(LANDMASK_INDX) = "land_binary_mask"
207 datanames(SST_INDX) = "SST"
208 datanames(LANDMASK_INDX) = "LANDMASK"
212 END SUBROUTINE sst_component_init1
216 SUBROUTINE read_data( exportState, clock )
218 TYPE(ESMF_State), INTENT(INOUT) :: exportState
219 TYPE(ESMF_Clock), INTENT(IN ) :: clock
221 ! Reads data from file and stores. Then
222 ! stuffs the file data into the SST exportState.
225 #include <wrf_status_codes.h>
226 #include <wrf_io_flags.h>
229 CHARACTER (LEN=19) :: date_string
230 TYPE(ESMF_Time) :: currentTime, dataTime
231 REAL(ESMF_KIND_R4), POINTER :: out_sst_ptr(:,:), out_landmask_ptr(:,:)
232 TYPE(ESMF_Field) :: out_sst_field, out_landmask_field
233 TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
235 CHARACTER(LEN=ESMF_MAXSTR) :: fieldname, debugmsg, errormsg, timestr
239 ! This call to wrf_get_next_time will position the dataset over the next
240 ! time-frame in the file and return the date_string, which is used as an
241 ! argument to the read_field routines in the blocks of code included
244 CALL wrf_get_next_time( fid, date_string , ierr )
245 WRITE(str,'(A,A)') 'Subroutine read_data: SST data time: ', &
247 CALL wrf_debug ( 100 , TRIM(str) )
248 IF ( ierr .NE. 0 .AND. ierr .NE. WRF_WARN_NOTSUPPORTED .AND. &
249 ierr .NE. WRF_WARN_DRYRUN_READ ) THEN
250 CALL wrf_error_fatal ( "... May have run out of valid SST data ..." )
251 ELSE IF ( ierr .NE. WRF_WARN_NOTSUPPORTED .AND. &
252 ierr .NE. WRF_WARN_DRYRUN_READ) THEN
253 ! check input time against current time (which will be start time at
255 CALL wrf_atotime( date_string, dataTime )
256 CALL ESMF_ClockGet( clock, CurrTime=currentTime, rc=rc )
257 IF (rc /= ESMF_SUCCESS) THEN
258 CALL wrf_error_fatal ( 'read_data: ESMF_ClockGet() failed' )
260 CALL wrf_clockprint(150, clock, &
261 'DEBUG read_data(): get currentTime from clock,')
262 IF ( dataTime .NE. currentTime ) THEN
263 CALL wrf_timetoa ( dataTime, timestr )
264 WRITE( errormsg , * )'Time in file: ',trim( timestr )
265 CALL wrf_message ( trim(errormsg) )
266 CALL wrf_timetoa ( currentTime, timestr )
267 WRITE( errormsg , * )'Time on domain: ',trim( timestr )
268 CALL wrf_message ( trim(errormsg) )
269 CALL wrf_error_fatal( &
270 "**ERROR** Time in input file not equal to time on domain **ERROR**" )
274 ! doing this in a loop only works if staggering is the same for all fields
275 this_data(SST_INDX)%r2d => file_sst_data
276 this_data(LANDMASK_INDX)%r2d => file_landmask_data
278 fieldname = TRIM(datanames(i))
279 debugmsg = 'ext_read_field '//TRIM(fieldname)//' memorder XY'
280 errormsg = 'could not read '//TRIM(fieldname)//' data from file'
281 CALL wrf_ext_read_field ( &
283 date_string , & ! DateStr
284 TRIM(fieldname) , & ! Data Name
285 this_data(i)%r2d , & ! Field
286 WRF_REAL , & ! FieldType
288 mpicom , & ! I/O Comm
289 domdesc , & ! Domain descriptor
290 bdy_mask , & ! bdy_mask
291 'XY' , & ! MemoryOrder
293 TRIM(debugmsg) , & ! Debug message
295 ids , (ide-1) , jds , (jde-1) , 1 , 1 , &
296 ims , ime , jms , jme , 1 , 1 , &
297 ips , MIN( (ide-1), ipe ) , jps , MIN( (jde-1), jpe ) , 1 , 1 , &
299 !jm the dimensions have already been reduced to the non-staggered WRF grid when
300 ! they were stored in this module.. Just use as is.
301 ids , ide , jds , jde , 1 , 1 , &
302 ims , ime , jms , jme , 1 , 1 , &
303 ips , ipe , jps , jpe , 1 , 1 , &
307 CALL wrf_error_fatal ( TRIM(errormsg) )
311 ! stuff fields into exportState
312 !TODO: change this to Bundles, eventually
313 CALL ESMF_StateGet( exportState, TRIM(datanames(SST_INDX)), &
314 out_sst_field, rc=rc )
315 IF (rc /= ESMF_SUCCESS) THEN
316 CALL wrf_error_fatal ( &
317 'could not find sea_surface_temperature field in exportState' )
319 CALL ESMF_StateGet( exportState, TRIM(datanames(LANDMASK_INDX)), &
320 out_landmask_field, rc=rc )
321 IF (rc /= ESMF_SUCCESS) THEN
322 CALL wrf_error_fatal ( &
323 'could not find land_binary_mask field in exportState' )
325 ! CALL ESMF_FieldGetDataPointer( out_sst_field, out_sst_ptr, rc=rc )
326 CALL ESMF_FieldGet( out_sst_field, 0, out_sst_ptr, rc=rc )
327 IF (rc /= ESMF_SUCCESS) THEN
328 CALL wrf_error_fatal ( &
329 'could not find sea_surface_temperature data in sea_surface_temperature field' )
331 ! CALL ESMF_FieldGetDataPointer( out_landmask_field, out_landmask_ptr, rc=rc )
332 CALL ESMF_FieldGet( out_landmask_field, 0, out_landmask_ptr, rc=rc )
333 IF (rc /= ESMF_SUCCESS) THEN
334 CALL wrf_error_fatal ( &
335 'could not find land_binary_mask data in land_binary_mask field' )
337 ! staggered starts/ends
340 out_sst_ptr(i,j) = file_sst_data(i,j)
341 out_landmask_ptr(i,j) = file_landmask_data(i,j)
345 END SUBROUTINE read_data
350 SUBROUTINE compare_data( importState, clock )
351 TYPE(ESMF_State), INTENT(INOUT) :: importState
352 !TODO: remove clock after debugging is finished
353 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
355 ! Gets data from coupler via importState
356 ! and compares with data read from file and
357 ! error-exits if they differ.
360 ! importState Importstate
364 TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
365 REAL(ESMF_KIND_R4), POINTER :: in_sst_ptr(:,:), in_landmask_ptr(:,:)
366 REAL, POINTER :: in_sst_ptr_real(:,:), in_landmask_ptr_real(:,:)
369 LOGICAL :: landmask_ok, sst_ok
370 ! use these for debug prints
371 TYPE(ESMF_Time) :: currentTime
372 INTEGER, SAVE :: numtimes=0 ! track number of calls
373 CHARACTER(LEN=256) :: timestamp
375 ! count calls for debug prints...
376 CALL ESMF_ClockGet( clock, CurrTime=currentTime, rc=rc )
377 IF (rc /= ESMF_SUCCESS) THEN
378 CALL wrf_error_fatal ( 'compare_data: ESMF_ClockGet() failed' )
380 CALL wrf_timetoa ( currentTime, timestamp )
381 numtimes = numtimes + 1
382 WRITE(str,*) 'SST compare_data: begin, numtimes = ',numtimes,' time = ',TRIM(timestamp)
383 CALL wrf_debug ( 100 , TRIM(str) )
385 ! extract data from the importState and compare with data from file
386 !TODO: change this to Bundles, eventually
387 CALL ESMF_StateGet( importState, TRIM(datanames(SST_INDX)), &
388 in_sst_field, rc=rc )
389 IF (rc /= ESMF_SUCCESS) THEN
390 CALL wrf_error_fatal ( &
391 'could not extract sea_surface_temperature field from importState' )
393 CALL ESMF_StateGet( importState, TRIM(datanames(LANDMASK_INDX)), &
394 in_landmask_field, rc=rc )
395 IF (rc /= ESMF_SUCCESS) THEN
396 CALL wrf_error_fatal ( &
397 'could not extract land_binary_mask field from importState' )
399 ! CALL ESMF_FieldGetDataPointer( in_sst_field, in_sst_ptr, rc=rc )
400 CALL ESMF_FieldGet( in_sst_field, 0, in_sst_ptr, rc=rc )
401 IF (rc /= ESMF_SUCCESS) THEN
402 CALL wrf_error_fatal ( &
403 'could not extract sea_surface_temperature data from sea_surface_temperature field' )
405 ALLOCATE( in_sst_ptr_real(ims:ime,jms:jme) )
406 WRITE( str,* ) 'compare_data, ips:ipe,jps:jpe = ', &
407 ips,':',ipe,',',jps,':',jpe, &
408 ', in_sst_ptr(BOUNDS) = ', &
409 LBOUND(in_sst_ptr,1),':',UBOUND(in_sst_ptr,1),',', &
410 LBOUND(in_sst_ptr,2),':',UBOUND(in_sst_ptr,2)
411 CALL wrf_debug ( 100 , TRIM(str) )
414 in_sst_ptr_real(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
417 in_sst_ptr_real(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe)) = &
418 in_sst_ptr(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe))
419 ! CALL ESMF_FieldGetDataPointer( in_landmask_field, in_landmask_ptr, rc=rc )
420 CALL ESMF_FieldGet( in_landmask_field, 0, in_landmask_ptr, rc=rc )
421 IF (rc /= ESMF_SUCCESS) THEN
422 CALL wrf_error_fatal ( &
423 'could not extract land_binary_mask data from land_binary_mask field' )
425 ALLOCATE( in_landmask_ptr_real(ims:ime,jms:jme) )
426 WRITE( str,* ) 'compare_data, ips:ipe,jps:jpe = ', &
427 ips,':',ipe,',',jps,':',jpe, &
428 ', in_landmask_ptr(BOUNDS) = ', &
429 LBOUND(in_landmask_ptr,1),':',UBOUND(in_landmask_ptr,1),',', &
430 LBOUND(in_landmask_ptr,2),':',UBOUND(in_landmask_ptr,2)
431 CALL wrf_debug ( 100 , TRIM(str) )
434 in_landmask_ptr_real(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
437 in_landmask_ptr_real(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe)) = &
438 in_landmask_ptr(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe))
440 ! compare LANDMASK...
442 ! staggered starts/ends
443 LANDMASK_COMPARE : DO j= jps , MIN( (jde-1), jpe )
444 DO i= ips , MIN( (ide-1), ipe )
445 IF ( file_landmask_data(i,j) /= in_landmask_ptr_real(i,j) ) THEN
446 landmask_ok = .FALSE.
447 WRITE( str , * ) 'error landmask mismatch at (i,j) = (',i,',',j, &
448 '), values are',file_landmask_data(i,j),' and ', &
449 in_landmask_ptr_real(i,j)
450 EXIT LANDMASK_COMPARE
453 ENDDO LANDMASK_COMPARE
454 IF ( landmask_ok ) THEN
455 WRITE(str,*) 'TESTING data returned from WRF through ESMF: LANDMASK compares OK'
456 CALL wrf_debug ( 0 , TRIM(str) )
458 CALL wrf_error_fatal ( TRIM(str) )
463 ! staggered starts/ends
464 SST_COMPARE : DO j= jps , MIN( (jde-1), jpe )
465 DO i= ips , MIN( (ide-1), ipe )
466 IF ( file_sst_data(i,j) /= in_sst_ptr_real(i,j) ) THEN
468 WRITE( str , * ) 'error sst mismatch at (i,j) = (',i,',',j, &
469 '), values are',file_sst_data(i,j),' and ', &
476 WRITE(str,*) 'TESTING data returned from WRF through ESMF: SST compares OK'
477 CALL wrf_debug ( 0 , TRIM(str) )
479 CALL wrf_error_fatal ( TRIM(str) )
482 DEALLOCATE( in_sst_ptr_real, in_landmask_ptr_real )
484 WRITE(str,*) 'compare_data: end, numtimes = ',numtimes
485 CALL wrf_debug ( 100 , TRIM(str) )
487 END SUBROUTINE compare_data
489 ! Second-phase "init" gets decomposition information from
491 SUBROUTINE sst_component_init2( gcomp, importState, exportState, clock, rc )
492 USE module_metadatautils, ONLY: GetDecompFromState
494 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
495 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState
496 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: exportState
497 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
498 INTEGER, INTENT( OUT) :: rc
500 ! SST component init routine, phase 2.
504 ! importState Importstate
505 ! exportState Exportstate
506 ! clock External clock
507 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
508 ! otherwise ESMF_FAILURE.
512 TYPE(ESMF_Field) :: out_sst_field, out_landmask_field
513 TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
514 INTEGER, PARAMETER :: NUMDIMS=2
515 INTEGER :: DomainStart(NUMDIMS)
516 INTEGER :: DomainEnd(NUMDIMS)
517 INTEGER :: MemoryStart(NUMDIMS)
518 INTEGER :: MemoryEnd(NUMDIMS)
519 INTEGER :: PatchStart(NUMDIMS)
520 INTEGER :: PatchEnd(NUMDIMS)
524 ! Get decomposition information from importState. Note that index
525 ! values are for staggered dimensions, following the WRF convention.
526 !TODO: Note that this will only work for SPMD serial operation. For
527 !TODO: concurrent operation (SPMD or MPMD), we will need to create a new
528 !TODO: "domdesc" suitable for the task layout of the SST component. For
529 !TODO: MPMD serial operation, we will need to extract serialized domdesc
530 !TODO: from export state metadata and de-serialize it. Similar arguments
531 !TODO: apply to [ij][mp][se] and bdy_mask.
532 write(str,*) 'sst_component_init2: calling GetDecompFromState'
533 CALL wrf_debug ( 100 , TRIM(str) )
534 CALL GetDecompFromState( importState, &
535 ids, ide, jds, jde, kds, kde, &
536 ims, ime, jms, jme, kms, kme, &
537 ips, ipe, jps, jpe, kps, kpe, &
539 write(str,*) 'sst_component_init2: back from GetDecompFromState'
540 CALL wrf_debug ( 100 , TRIM(str) )
541 write(str,*) 'sst_component_init2: ids, ide, jds, jde, kds, kde = ', ids, ide, jds, jde, kds, kde
542 CALL wrf_debug ( 100 , TRIM(str) )
543 write(str,*) 'sst_component_init2: ims, ime, jms, jme, kms, kme = ', ims, ime, jms, jme, kms, kme
544 CALL wrf_debug ( 100 , TRIM(str) )
545 write(str,*) 'sst_component_init2: ips, ipe, jps, jpe, kps, kpe = ', ips, ipe, jps, jpe, kps, kpe
546 CALL wrf_debug ( 100 , TRIM(str) )
548 ! allocate space for data read from disk
549 ALLOCATE( file_sst_data (ims:ime,jms:jme) )
552 file_sst_data(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
555 !TODO: Hmmm... really need to load these pointers here? Check...
556 this_data(SST_INDX)%r2d => file_sst_data
557 ALLOCATE( file_landmask_data(ims:ime,jms:jme) )
560 file_landmask_data(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
563 this_data(LANDMASK_INDX)%r2d => file_landmask_data
565 ! Create ESMF_Fields in importState and exportState
566 ! Create ESMF_Grid. Use exactly the same method as WRF so WRFIO will
568 DomainStart(1) = ids; DomainEnd(1) = ide;
569 DomainStart(2) = jds; DomainEnd(2) = jde;
570 MemoryStart(1) = ims; MemoryEnd(1) = ime;
571 MemoryStart(2) = jms; MemoryEnd(2) = jme;
572 PatchStart(1) = ips; PatchEnd(1) = ipe;
573 PatchStart(2) = jps; PatchEnd(2) = jpe
574 !write(0,*)__FILE__,__LINE__,'DomainStart ',DomainStart(1:2)
575 !write(0,*)__FILE__,__LINE__,'DomainEnd ',DomainEnd(1:2)
576 !write(0,*)__FILE__,__LINE__,'MemoryStart ',MemoryStart(1:2)
577 !write(0,*)__FILE__,__LINE__,'MemoryEnd ',MemoryEnd(1:2)
578 !write(0,*)__FILE__,__LINE__,'PatchStart ',PatchStart(1:2)
579 !write(0,*)__FILE__,__LINE__,'PatchEnd ',PatchEnd(1:2)
580 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: Calling ioesmf_create_grid_int()' )
581 CALL ioesmf_create_grid_int( esmfgrid, NUMDIMS, &
582 DomainStart, DomainEnd, &
583 MemoryStart, MemoryEnd, &
584 PatchStart, PatchEnd )
585 !write(0,*)__FILE__,__LINE__
586 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: back from ioesmf_create_grid_int()' )
588 ! Note use of patch dimension for POINTERs allocated by ESMF.
589 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: Calling ESMF_GridValidate(esmfgrid)' )
590 CALL ESMF_GridValidate( esmfgrid, rc=rc )
591 !write(0,*)__FILE__,__LINE__
592 IF ( rc /= ESMF_SUCCESS ) THEN
593 WRITE( str,* ) 'Error in ESMF_GridValidate ', &
598 CALL wrf_error_fatal ( TRIM(str) )
600 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: back OK from ESMF_GridValidate(esmfgrid)' )
601 !TODO: Once new ESMF 3.0 interfaces have settled down, eliminate "tmp_data_"
602 !TODO: arrays and let ESMF allocate/deallocate them. Assuming of course that
603 !TODO: we can convince ESMF to deallocate safely...
604 !write(0,*)__FILE__,__LINE__
605 ALLOCATE( tmp_data_out_sst(ips:ipe,jps:jpe) )
606 !write(0,*)__FILE__,__LINE__
607 write(str,*) 'sst_component_init2: tmp_data_out_sst(', &
608 LBOUND(tmp_data_out_sst,1),':',UBOUND(tmp_data_out_sst,1),',',LBOUND(tmp_data_out_sst,2),':',UBOUND(tmp_data_out_sst,2),')'
609 CALL wrf_debug ( 100 , TRIM(str) )
610 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(out_sst_field)' )
611 !write(0,*)__FILE__,__LINE__,trim(datanames(sst_indx))
612 !write(0,*)__FILE__,__LINE__,ips,jps,ipe,jpe
613 out_sst_field = ESMF_FieldCreate( &
614 esmfgrid, tmp_data_out_sst, &
615 datacopyflag=ESMF_DATACOPY_REFERENCE, &
616 staggerloc=ESMF_STAGGERLOC_CENTER, &
617 name=TRIM(datanames(SST_INDX)), &
619 !write(0,*)__FILE__,__LINE__,'Creating out_sst_field for exportState of SST component name ',TRIM(datanames(SST_INDX))
620 IF ( rc /= ESMF_SUCCESS ) THEN
621 WRITE( str,* ) 'ESMF_FieldCreate(out_sst_field) failed ', &
626 CALL wrf_error_fatal ( TRIM(str) )
628 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(out_sst_field)' )
629 write(str,*) 'sst_component_init2: ips:ipe,jps:jpe = ', &
630 ips,':',ipe,',',jps,':',jpe
631 CALL wrf_debug ( 100 , TRIM(str) )
632 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
633 ! validate ESMF allocation
634 IF ( ( ips /= LBOUND(tmp_data_out_sst,1) ) .OR. ( ipe /= UBOUND(tmp_data_out_sst,1) ) .OR. &
635 ( jps /= LBOUND(tmp_data_out_sst,2) ) .OR. ( jpe /= UBOUND(tmp_data_out_sst,2) ) ) THEN
636 WRITE( str,* ) 'ESMF_FieldCreate(out_sst_field) allocation failed ', &
640 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
641 ', tmp_data_out_sst(BOUNDS) = ',LBOUND(tmp_data_out_sst,1),':',UBOUND(tmp_data_out_sst,1),',', &
642 LBOUND(tmp_data_out_sst,2),':',UBOUND(tmp_data_out_sst,2)
643 CALL wrf_error_fatal ( TRIM(str) )
645 ALLOCATE( tmp_data_out_landmask(ips:ipe,jps:jpe) )
646 write(str,*) 'sst_component_init2: tmp_data_out_landmask(', &
647 LBOUND(tmp_data_out_landmask,1),':',UBOUND(tmp_data_out_landmask,1),',',LBOUND(tmp_data_out_landmask,2),':',UBOUND(tmp_data_out_landmask,2),')'
648 CALL wrf_debug ( 100 , TRIM(str) )
649 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(out_landmask_field)' )
650 out_landmask_field = ESMF_FieldCreate( &
651 esmfgrid, tmp_data_out_landmask, &
652 datacopyflag=ESMF_DATACOPY_REFERENCE, &
653 staggerloc=ESMF_STAGGERLOC_CENTER, &
654 name=TRIM(datanames(LANDMASK_INDX)), &
655 ! lbounds=(/ips,jps/), &
656 ! ubounds=(/ipe,jpe/), &
658 IF ( rc /= ESMF_SUCCESS ) THEN
659 CALL wrf_error_fatal ( 'ESMF_FieldCreate(out_landmask_field) failed' )
661 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(out_landmask_field)' )
662 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
663 ! validate ESMF allocation
664 IF ( ( ips /= LBOUND(tmp_data_out_landmask,1) ) .OR. ( ipe /= UBOUND(tmp_data_out_landmask,1) ) .OR. &
665 ( jps /= LBOUND(tmp_data_out_landmask,2) ) .OR. ( jpe /= UBOUND(tmp_data_out_landmask,2) ) ) THEN
666 WRITE( str,* ) 'ESMF_FieldCreate(out_landmask_field) allocation failed ', &
670 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
671 ', tmp_data_out_landmask(BOUNDS) = ',LBOUND(tmp_data_out_landmask,1),':',UBOUND(tmp_data_out_landmask,1),',', &
672 LBOUND(tmp_data_out_landmask,2),':',UBOUND(tmp_data_out_landmask,2)
673 CALL wrf_error_fatal ( TRIM(str) )
675 ALLOCATE( tmp_data_in_sst(ips:ipe,jps:jpe) )
676 write(str,*) 'sst_component_init2: tmp_data_in_sst(', &
677 LBOUND(tmp_data_in_sst,1),':',UBOUND(tmp_data_in_sst,1),',',LBOUND(tmp_data_in_sst,2),':',UBOUND(tmp_data_in_sst,2),')'
678 CALL wrf_debug ( 100 , TRIM(str) )
679 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(in_sst_field)' )
680 in_sst_field = ESMF_FieldCreate( &
681 esmfgrid, tmp_data_in_sst, &
682 datacopyflag=ESMF_DATACOPY_REFERENCE, &
683 staggerloc=ESMF_STAGGERLOC_CENTER, &
684 name=TRIM(datanames(SST_INDX)), &
685 ! lbounds=(/ips,jps/), &
686 ! ubounds=(/ipe,jpe/), &
688 IF ( rc /= ESMF_SUCCESS ) THEN
689 CALL wrf_error_fatal ( 'ESMF_FieldCreate(in_sst_field) failed' )
691 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(in_sst_field)' )
692 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
693 ! validate ESMF allocation
694 IF ( ( ips /= LBOUND(tmp_data_in_sst,1) ) .OR. ( ipe /= UBOUND(tmp_data_in_sst,1) ) .OR. &
695 ( jps /= LBOUND(tmp_data_in_sst,2) ) .OR. ( jpe /= UBOUND(tmp_data_in_sst,2) ) ) THEN
696 WRITE( str,* ) 'ESMF_FieldCreate(in_sst_field) allocation failed ', &
700 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
701 ', tmp_data_in_sst(BOUNDS) = ',LBOUND(tmp_data_in_sst,1),':',UBOUND(tmp_data_in_sst,1),',', &
702 LBOUND(tmp_data_in_sst,2),':',UBOUND(tmp_data_in_sst,2)
703 CALL wrf_error_fatal ( TRIM(str) )
705 ALLOCATE( tmp_data_in_landmask(ips:ipe,jps:jpe) )
706 write(str,*) 'sst_component_init2: tmp_data_in_landmask(', &
707 LBOUND(tmp_data_in_landmask,1),':',UBOUND(tmp_data_in_landmask,1),',',LBOUND(tmp_data_in_landmask,2),':',UBOUND(tmp_data_in_landmask,2),')'
708 CALL wrf_debug ( 100 , TRIM(str) )
709 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(in_landmask_field)' )
710 in_landmask_field = ESMF_FieldCreate( &
711 esmfgrid, tmp_data_in_landmask, &
712 datacopyflag=ESMF_DATACOPY_REFERENCE, &
713 staggerloc=ESMF_STAGGERLOC_CENTER, &
714 name=TRIM(datanames(LANDMASK_INDX)), &
715 ! lbounds=(/ips,jps/), &
716 ! ubounds=(/ipe,jpe/), &
718 IF ( rc /= ESMF_SUCCESS ) THEN
719 CALL wrf_error_fatal ( 'ESMF_FieldCreate(in_landmask_field) failed' )
721 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(in_landmask_field)' )
722 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
723 ! validate ESMF allocation
724 IF ( ( ips /= LBOUND(tmp_data_in_landmask,1) ) .OR. ( ipe /= UBOUND(tmp_data_in_landmask,1) ) .OR. &
725 ( jps /= LBOUND(tmp_data_in_landmask,2) ) .OR. ( jpe /= UBOUND(tmp_data_in_landmask,2) ) ) THEN
726 WRITE( str,* ) 'ESMF_FieldCreate(in_landmask_field) allocation failed ', &
730 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
731 ', tmp_data_in_landmask(BOUNDS) = ',LBOUND(tmp_data_in_landmask,1),':',UBOUND(tmp_data_in_landmask,1),',', &
732 LBOUND(tmp_data_in_landmask,2),':',UBOUND(tmp_data_in_landmask,2)
733 CALL wrf_error_fatal ( TRIM(str) )
736 ! attach ESMF_Field to importState
737 CALL ESMF_StateAdd( importState, fieldList=(/in_sst_field/), rc=rc )
738 IF ( rc /= ESMF_SUCCESS ) THEN
739 CALL wrf_error_fatal ( 'ESMF_StateAdd(in_sst_field) failed' )
741 CALL ESMF_StateAdd( importState, fieldList=(/in_landmask_field/), rc=rc )
742 IF ( rc /= ESMF_SUCCESS ) THEN
743 CALL wrf_error_fatal ( 'ESMF_StateAdd(in_landmask_field) failed' )
745 ! attach ESMF_Field to exportState
746 CALL ESMF_StateAdd( exportState, fieldList=(/out_sst_field/), rc=rc )
747 IF ( rc /= ESMF_SUCCESS ) THEN
748 CALL wrf_error_fatal ( 'ESMF_StateAdd(out_sst_field) failed' )
750 CALL ESMF_StateAdd( exportState, fieldList=(/out_landmask_field/), rc=rc )
751 IF ( rc /= ESMF_SUCCESS ) THEN
752 CALL wrf_error_fatal ( 'ESMF_StateAdd(out_landmask_field) failed' )
755 ! Open the "SST" input data file for reading.
756 write(str,'(A,A)') 'sst_component_init2: Opening data file ', &
758 CALL wrf_message ( TRIM(str) )
759 CALL wrf_open_for_read ( TRIM(sstinfilename) , &
765 IF ( ierr .NE. 0 ) THEN
766 WRITE( str , FMT='(A,A,A,I8)' ) &
767 'sst_component_init2: error opening ', &
768 TRIM(sstinfilename),' for reading ierr=',ierr
769 CALL wrf_error_fatal ( TRIM(str) )
771 WRITE( str , FMT='(A,A,A,I8)' ) &
772 'subroutine sst_component_init2: opened file ', &
773 TRIM(sstinfilename),' for reading fid=',fid
774 CALL wrf_debug ( 100, TRIM(str) )
776 write(str,'(A)') 'sst_component_init2: returning rc=ESMF_SUCCESS'
777 CALL wrf_debug ( 100 , TRIM(str) )
781 END SUBROUTINE sst_component_init2
785 SUBROUTINE sst_component_run1( gcomp, importState, exportState, clock, rc )
786 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
787 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
788 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
789 INTEGER, INTENT( OUT) :: rc
791 ! SST component run routine, phase 1.
792 ! Read "SST" data from file and stuff into exportState.
796 ! importState Importstate
797 ! exportState Exportstate
798 ! clock External clock
799 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
800 ! otherwise ESMF_FAILURE.
805 ! Get "SST" data from file and stuff it into exportState.
806 CALL read_data( exportState, clock )
808 END SUBROUTINE sst_component_run1
812 SUBROUTINE sst_component_run2( gcomp, importState, exportState, clock, rc )
813 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
814 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
815 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
816 INTEGER, INTENT( OUT) :: rc
818 ! SST component run routine, phase 2.
819 ! Get from importState, compare with file data, and error-exit
820 ! if they differ... If they are the same, then
821 ! stuff the file data into the exportState.
825 ! importState Importstate
826 ! exportState Exportstate
827 ! clock External clock
828 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
829 ! otherwise ESMF_FAILURE.
834 ! Get from importState, compare with file data, and error_exit
836 !TODO: change this once WRF can load exportState after integrating
837 ! This works because WRF loads its exportState BEFORE integrating.
838 CALL wrf_clockprint ( 50, clock, 'sst_component_run2: clock before call to compare_data()' )
839 CALL compare_data( importState, clock )
840 CALL wrf_clockprint ( 50, clock, 'sst_component_run2: clock after call to compare_data()' )
842 END SUBROUTINE sst_component_run2
846 SUBROUTINE sst_component_finalize( gcomp, importState, exportState, clock, rc )
848 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
849 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
850 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
851 INTEGER, INTENT( OUT) :: rc
853 ! SST component finalize routine.
857 ! importState Importstate
858 ! exportState Exportstate
859 ! clock External clock
860 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
861 ! otherwise ESMF_FAILURE.
865 TYPE(ESMF_Field) :: tmp_field
870 ! destroy ESMF_Fields and other "deep" objects created by this component
871 ! note that this component relied on ESMF to allocate data pointers during
872 ! calls to ESMF_FieldCreate() so it also expects ESMF to free these pointers
874 ! destroy field in importState
875 CALL ESMF_StateGet( importState, TRIM(datanames(i)), tmp_field, &
877 IF (rc /= ESMF_SUCCESS) THEN
879 'sst_component_finalize: ESMF_StateGet( importState,', &
880 TRIM(datanames(i)),') failed'
881 CALL wrf_error_fatal ( TRIM(str) )
883 CALL ESMF_FieldDestroy( tmp_field, rc=rc )
884 IF (rc /= ESMF_SUCCESS) THEN
886 'sst_component_finalize: ESMF_FieldDestroy( importState,', &
887 TRIM(datanames(i)),') failed'
888 CALL wrf_error_fatal ( TRIM(str) )
890 ! destroy field in exportState
891 CALL ESMF_StateGet( exportState, TRIM(datanames(i)), tmp_field, &
893 IF (rc /= ESMF_SUCCESS) THEN
895 'sst_component_finalize: ESMF_StateGet( exportState,', &
896 TRIM(datanames(i)),') failed'
897 CALL wrf_error_fatal ( TRIM(str) )
899 CALL ESMF_FieldDestroy( tmp_field, rc=rc )
900 IF (rc /= ESMF_SUCCESS) THEN
902 'sst_component_finalize: ESMF_FieldDestroy( exportState,', &
903 TRIM(datanames(i)),') failed'
904 CALL wrf_error_fatal ( TRIM(str) )
908 ! deallocate space for data read from disk
909 DEALLOCATE( file_sst_data, file_landmask_data )
911 ! close SST data file
912 WRITE( str , FMT='(A,I8)' ) &
913 'subroutine sst_component_finalize: closing file fid=',fid
914 CALL wrf_debug ( 100, TRIM(str) )
915 CALL wrf_ioclose( fid , ierr )
916 IF ( ierr .NE. 0 ) THEN
917 CALL wrf_error_fatal ( 'sst_component_finalize: wrf_ioclose failed' )
920 END SUBROUTINE sst_component_finalize
923 END MODULE module_sst_component_top
928 MODULE module_sst_setservices
930 ! This module defines SST "Set Services" method sst_register()
931 ! used for ESMF coupling.
934 USE module_sst_component_top, ONLY: sst_component_init1, &
935 sst_component_init2, &
936 sst_component_run1, &
937 sst_component_run2, &
938 sst_component_finalize
939 ! Updated for ESMF 5.2.0r
945 ! everything is private by default
948 ! Public entry point for ESMF_GridCompSetServices()
952 CHARACTER (ESMF_MAXSTR) :: str
957 SUBROUTINE sst_register(gcomp, rc)
958 TYPE(ESMF_GridComp), INTENT(INOUT) :: gcomp
959 INTEGER, INTENT(OUT) :: rc
963 ! SST_register - Externally visible registration routine
965 ! User-supplied SetServices routine.
966 ! The Register routine sets the subroutines to be called
967 ! as the init, run, and finalize routines. Note that these are
968 ! private to the module.
972 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
973 ! otherwise ESMF_FAILURE.
976 finalrc = ESMF_SUCCESS
977 ! Register the callback routines.
978 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, &
979 sst_component_init1, phase=1, rc=rc)
980 IF ( rc /= ESMF_SUCCESS) THEN
981 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_init1) failed with rc = ', rc
982 CALL wrf_error_fatal ( TRIM(str) )
984 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, &
985 sst_component_init2, phase=2, rc=rc)
986 IF ( rc /= ESMF_SUCCESS) THEN
987 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_init2) failed with rc = ', rc
988 CALL wrf_error_fatal ( TRIM(str) )
990 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, &
991 sst_component_run1, phase=1, rc=rc)
992 IF ( rc /= ESMF_SUCCESS) THEN
993 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_run1) failed with rc = ', rc
994 CALL wrf_error_fatal ( TRIM(str) )
996 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, &
997 sst_component_run2, phase=2, rc=rc)
998 IF ( rc /= ESMF_SUCCESS) THEN
999 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_run2) failed with rc = ', rc
1000 CALL wrf_error_fatal ( TRIM(str) )
1002 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_FINALIZE, &
1003 sst_component_finalize, rc=rc)
1004 IF ( rc /= ESMF_SUCCESS) THEN
1005 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_finalize) failed with rc = ', rc
1006 CALL wrf_error_fatal ( TRIM(str) )
1009 PRINT *,'SST: Registered Initialize, Run, and Finalize routines'
1013 END SUBROUTINE sst_register
1015 END MODULE module_sst_setservices
1020 ! Module module_wrfsst_coupler defines the
1021 ! "WRF-SST" coupler component. It provides two-way coupling between
1022 ! the "SST" and "WRF" components.
1023 ! In its run routine it transfers data directly from the
1024 ! SST Component's export state to the WRF Component's import state.
1025 ! It also transfers data directly from the
1026 ! WRF Component's export state to the SST Component's import state.
1028 ! This is derived from src/demo/coupled_flow/src/CouplerMod.F90
1029 ! created by Nancy Collins and others on the ESMF Core Team.
1033 MODULE module_wrfsst_coupler
1035 ! Updated for ESMF 5.2.0r
1041 ! everything is private by default
1044 ! Public entry point
1045 PUBLIC WRFSSTCpl_register
1047 ! private data members
1048 ! route handles and flags
1049 TYPE(ESMF_RouteHandle), SAVE :: fromWRF_rh, fromSST_rh
1050 LOGICAL, SAVE :: fromWRF_rh_ready = .FALSE.
1051 LOGICAL, SAVE :: fromSST_rh_ready = .FALSE.
1053 INTEGER, PARAMETER :: datacount = 2
1054 INTEGER, PARAMETER :: SST_INDX = 1
1055 INTEGER, PARAMETER :: LANDMASK_INDX = 2
1056 CHARACTER(LEN=ESMF_MAXSTR), SAVE :: datanames(datacount)
1057 CHARACTER(LEN=ESMF_MAXSTR) :: str
1063 SUBROUTINE WRFSSTCpl_register(comp, rc)
1064 TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
1065 INTEGER, INTENT(OUT) :: rc
1068 ! WRFSSTCpl_register - Externally visible registration routine
1070 ! User-supplied SetServices routine.
1071 ! The Register routine sets the subroutines to be called
1072 ! as the init, run, and finalize routines. Note that these are
1073 ! private to the module.
1075 ! The arguments are:
1077 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1078 ! otherwise ESMF_FAILURE.
1081 ! guilty until proven innocent
1084 ! Register the callback routines.
1086 call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, WRFSSTCpl_init, &
1088 IF ( rc /= ESMF_SUCCESS ) THEN
1089 CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_init) failed' )
1091 call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, WRFSSTCpl_run, &
1093 IF ( rc /= ESMF_SUCCESS ) THEN
1094 CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_run) failed' )
1096 call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, WRFSSTCpl_final, &
1098 IF ( rc /= ESMF_SUCCESS ) THEN
1099 CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_final) failed' )
1102 print *, "module_wrfsst_coupler: Registered Initialize, Run, and Finalize routines"
1104 END SUBROUTINE WRFSSTCpl_register
1107 SUBROUTINE WRFSSTCpl_init(comp, importState, exportState, clock, rc)
1108 USE module_metadatautils, ONLY: AttachDecompToState, GetDecompFromState
1109 TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
1110 TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
1111 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
1112 INTEGER, INTENT(OUT) :: rc
1114 ! WRF-SST coupler component init routine. This simply passes needed
1115 ! metadata from WRF to SST. Initialization of ESMF_RouteHandle objects
1116 ! is handled later via lazy evaluation.
1118 ! The arguments are:
1120 ! importState Importstate
1121 ! exportState Exportstate
1122 ! clock External clock
1123 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1124 ! otherwise ESMF_FAILURE.
1128 CHARACTER(ESMF_MAXSTR) :: importstatename
1129 ! decomposition information
1130 INTEGER :: ids, ide, jds, jde, kds, kde
1131 INTEGER :: ims, ime, jms, jme, kms, kme
1132 INTEGER :: ips, ipe, jps, jpe, kps, kpe
1134 LOGICAL :: bdy_mask(4)
1136 PRINT *, "DEBUG: Coupler Init starting"
1138 ! guilty until proven innocent
1141 CALL ESMF_StateGet(importState, name=importstatename, rc=rc)
1142 IF ( rc /= ESMF_SUCCESS ) THEN
1143 CALL wrf_error_fatal ( 'WRFSSTCpl_init: ESMF_StateGet failed' )
1146 IF ( TRIM(importstatename) .EQ. "WRF Export State" ) THEN
1147 ! get metadata from WRF export state
1148 CALL GetDecompFromState( importState, &
1149 ids, ide, jds, jde, kds, kde, &
1150 ims, ime, jms, jme, kms, kme, &
1151 ips, ipe, jps, jpe, kps, kpe, &
1153 ! put metadata from in SST import state
1154 CALL AttachDecompToState( exportState, &
1155 ids, ide, jds, jde, kds, kde, &
1156 ims, ime, jms, jme, kms, kme, &
1157 ips, ipe, jps, jpe, kps, kpe, &
1162 WRITE(str,*)'WRFSSTCpl_init: invalid importState name: ',TRIM(importstatename)
1163 CALL wrf_error_fatal ( TRIM(str) )
1166 ! set up field names
1167 !TODO: use CF conventions for "standard_name" once WRF Registry supports them
1168 !TODO: datanames(SST_INDX) = "sea_surface_temperature"
1169 !TODO: datanames(LANDMASK_INDX) = "land_binary_mask"
1170 datanames(SST_INDX) = "SST"
1171 datanames(LANDMASK_INDX) = "LANDMASK"
1173 PRINT *, "DEBUG: Coupler Init returning"
1175 END SUBROUTINE WRFSSTCpl_init
1179 SUBROUTINE WRFSSTCpl_run(comp, importState, exportState, clock, rc)
1181 TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
1182 TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
1183 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
1184 INTEGER, INTENT(OUT) :: rc
1186 ! WRF-SST coupler component run routine.
1188 ! The arguments are:
1190 ! importState Importstate
1191 ! exportState Exportstate
1192 ! clock External clock
1193 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1194 ! otherwise ESMF_FAILURE.
1197 ! Note that comments in this code are preserved from the sample coupler
1198 ! provided by the ESMF core team.
1201 TYPE(ESMF_Field) :: src_field, dst_field
1202 TYPE(ESMF_Array) :: src_array, dst_array
1203 TYPE(ESMF_RouteHandle) :: routehandle
1205 LOGICAL :: build_fromWRF_rh, build_fromSST_rh, fromWRF
1206 CHARACTER(LEN=ESMF_MAXSTR) :: importStatename
1207 CHARACTER(LEN=ESMF_MAXSTR) :: SST_exportStatename, WRF_exportStatename
1209 CHARACTER(LEN=256) :: directionString
1210 LOGICAL :: neededFlag(1)
1212 WRITE(str,*) 'WRFSSTCpl_run: begin'
1213 CALL wrf_debug ( 100 , TRIM(str) )
1215 ! guilty until proven innocent
1218 ! Which way is this coupling going?
1219 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGet(importState,name,...)'
1220 CALL wrf_debug ( 100 , TRIM(str) )
1221 CALL ESMF_StateGet( importState, name=importStatename, rc=rc )
1222 WRITE(str,*) 'WRFSSTCpl_run: importStatename ', trim(importStatename), 'rc = ', rc
1223 CALL wrf_debug ( 100, TRIM(str) )
1224 IF ( rc /= ESMF_SUCCESS ) THEN
1225 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGet(importState,name,...) failed' )
1227 WRITE(str,*) 'WRFSSTCpl_run: back from ESMF_StateGet, importStatename = <',TRIM(importStatename),'>'
1228 CALL wrf_debug ( 100 , TRIM(str) )
1230 ! first time through in each direction: create route handle and
1231 ! associated objects
1232 WRF_exportStatename = "WRF Export State"
1233 SST_exportStatename = "SST Export State"
1234 IF ( TRIM(importStatename) .EQ. TRIM(WRF_exportStatename) ) THEN
1236 directionString = 'WRFtoSST'
1237 ELSE IF ( TRIM(importStatename) .EQ. TRIM(SST_exportStatename) ) THEN
1239 directionString = 'SSTtoWRF'
1241 WRITE(str,*)'WRFSSTCpl_run: invalid importState name: ',TRIM(importstatename)
1242 CALL wrf_error_fatal ( TRIM(str) )
1244 WRITE(str,*) 'WRFSSTCpl_run: fromWRF = ',fromWRF
1245 CALL wrf_debug ( 100 , TRIM(str) )
1246 build_fromWRF_rh = fromWRF .AND. ( .NOT. fromWRF_rh_ready )
1247 build_fromSST_rh = ( .NOT. fromWRF ) .AND. ( .NOT. fromSST_rh_ready )
1248 WRITE(str,*) 'WRFSSTCpl_run: build_fromWRF_rh = ',build_fromWRF_rh
1249 CALL wrf_debug ( 100 , TRIM(str) )
1250 WRITE(str,*) 'WRFSSTCpl_run: build_fromSST_rh = ',build_fromSST_rh
1251 CALL wrf_debug ( 100 , TRIM(str) )
1252 IF ( build_fromWRF_rh .OR. build_fromSST_rh ) THEN
1253 CALL ESMF_CplCompGet( comp, vm=vm, rc=rc )
1254 IF ( rc /= ESMF_SUCCESS ) THEN
1255 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_CplCompGet failed' )
1257 ! The use of literal index "1" here indicates that we don't care which
1258 ! ESMF_Field we get so we might as well get the first one.
1259 WRITE(str,*) 'WRFSSTCpl_run: grabbing first field <',TRIM(datanames(1)), &
1260 '> from import state'
1261 CALL wrf_debug ( 100 , TRIM(str) )
1263 CALL ESMF_StateGet( importState, TRIM(datanames(1)), src_field, &
1265 IF ( rc /= ESMF_SUCCESS ) THEN
1266 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGet(importState) failed' )
1269 CALL ESMF_FieldGet( src_field, array=src_array, rc=rc )
1270 IF ( rc /= ESMF_SUCCESS ) THEN
1271 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldGet src_array failed' )
1273 WRITE(str,*) 'WRFSSTCpl_run: grabbing first field <',TRIM(datanames(1)), &
1274 '> from export state'
1275 CALL wrf_debug ( 100 , TRIM(str) )
1277 CALL ESMF_StateGet( exportState, TRIM(datanames(1)), dst_field, &
1279 IF ( rc /= ESMF_SUCCESS ) THEN
1280 WRITE(str,*)'WRFSSTCpl_run: datanames(1) ',TRIM(datanames(1)),' rc ',rc
1281 CALL wrf_message(TRIM(str))
1282 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGet(exportState) failed' )
1284 CALL ESMF_FieldGet( dst_field, array=dst_array, &
1286 IF ( rc /= ESMF_SUCCESS ) THEN
1287 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldGet dst_array failed' )
1291 IF ( build_fromWRF_rh ) THEN
1292 WRITE(str,*) 'WRFSSTCpl_run: creating fromWRF_rh'
1293 CALL wrf_debug ( 100 , TRIM(str) )
1294 fromWRF_rh = ESMF_RouteHandleCreate( rc )
1295 IF ( rc /= ESMF_SUCCESS ) THEN
1296 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_RouteHandleCreate(fromWRF_rh) failed' )
1298 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedistStore(fromWRF_rh)'
1299 CALL wrf_debug ( 100 , TRIM(str) )
1300 CALL ESMF_ArrayRedistStore( src_array, dst_array, &
1301 routehandle=fromWRF_rh, rc=rc )
1302 IF ( rc /= ESMF_SUCCESS ) THEN
1303 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedistStore(fromWRF_rh) failed' )
1305 fromWRF_rh_ready = .TRUE.
1307 IF ( build_fromSST_rh ) THEN
1308 WRITE(str,*) 'WRFSSTCpl_run: creating fromSST_rh'
1309 CALL wrf_debug ( 100 , TRIM(str) )
1310 fromSST_rh = ESMF_RouteHandleCreate( rc )
1311 IF ( rc /= ESMF_SUCCESS ) THEN
1312 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_RouteHandleCreate(fromSST_rh) failed' )
1314 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedistStore(fromSST_rh)'
1315 CALL wrf_debug ( 100 , TRIM(str) )
1316 CALL ESMF_ArrayRedistStore( src_array, dst_array, &
1317 routehandle=fromSST_rh, rc=rc )
1318 !write(0,*)__FILE__,__LINE__,'rc = ',rc
1319 IF ( rc /= ESMF_SUCCESS ) THEN
1320 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedistStore(fromSST_rh) failed' )
1322 fromSST_rh_ready = .TRUE.
1325 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_AttributeSet(importState, ',TRIM(datanames(i))//':needed',')'
1326 CALL wrf_debug ( 100 , TRIM(str) )
1327 !5.2.0r CALL ESMF_StateSetNeeded( importState, TRIM(datanames(i)), &
1328 !5.2.0r ESMF_NEEDED, rc=rc )
1329 CALL ESMF_AttributeSet( importState, name=TRIM(datanames(i))//':needed',value=.true.,rc=rc)
1330 IF ( rc /= ESMF_SUCCESS ) THEN
1331 WRITE(str,*) 'WRFSSTCpl_run: ESMF_AttributeSet(',TRIM(datanames(i))//':needed',') failed'
1332 CALL wrf_error_fatal ( str )
1337 ! In this case, the coupling is symmetric - you call redist going
1338 ! both ways - so we only care about the coupling direction in order
1339 ! to get the right routehandle selected.
1341 WRITE(str,*) 'WRFSSTCpl_run: routehandle = fromWRF_rh'
1342 CALL wrf_debug ( 100 , TRIM(str) )
1343 routehandle = fromWRF_rh
1345 WRITE(str,*) 'WRFSSTCpl_run: routehandle = fromSST_rh'
1346 CALL wrf_debug ( 100 , TRIM(str) )
1347 routehandle = fromSST_rh
1351 WRITE(str,*) 'WRFSSTCpl_run: grabbing field <',TRIM(datanames(i)),'>'
1352 CALL wrf_debug ( 100 , TRIM(str) )
1353 ! check isneeded flag here
1354 !5.2.0r IF ( .NOT. ESMF_StateIsNeeded( importState, TRIM(datanames(i)), rc=rc ) ) THEN
1355 !5.2.0r IF ( rc /= ESMF_SUCCESS ) THEN
1356 !5.2.0r WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateIsNeeded(',TRIM(datanames(i)),') failed'
1357 !5.2.0r CALL wrf_error_fatal ( str )
1359 !5.2.0r WRITE(str,*) 'WRFSSTCpl_run: skipping field <',TRIM(datanames(i)),'>'
1360 !5.2.0r CALL wrf_debug ( 100 , TRIM(str) )
1363 CALL ESMF_AttributeGet(importState,name=TRIM(datanames(i))//':needed',valueList=neededFlag,rc=rc)
1364 IF ( rc == ESMF_SUCCESS ) THEN
1365 IF ( .NOT. neededFlag(1) ) THEN
1366 WRITE(str,*) 'WRFSSTCpl_run: skipping field <',TRIM(datanames(i)),'>'
1367 CALL wrf_debug ( 100 , TRIM(str) )
1371 WRITE(str,*) 'WRFSSTCpl_run: ESMF_AttributeGet(',TRIM(datanames(i))//':needed',') failed'
1372 CALL wrf_error_fatal ( str )
1375 WRITE(str,*) 'WRFSSTCpl_run: processing field <',TRIM(datanames(i)),'>'
1376 CALL wrf_debug ( 100 , TRIM(str) )
1378 ! The following piece of code provides an example of calling the data
1379 ! redistribution routine between two Fields in the Coupler Component.
1380 ! Unlike regrid, which translates between
1381 ! different Grids, redist translates between different DELayouts on
1382 ! the same Grid. The first two lines get the Fields from the
1383 ! States, each corresponding to a different subcomponent. One is
1384 ! an Export State and the other is an Import State.
1386 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGet(importState,', &
1387 TRIM(datanames(i)),')...'
1388 CALL wrf_debug ( 100 , TRIM(str) )
1389 CALL ESMF_StateGet( importState, TRIM(datanames(i)), src_field, &
1391 IF ( rc /= ESMF_SUCCESS ) THEN
1392 WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateGet(importState,', &
1393 TRIM(datanames(i)),') failed'
1394 CALL wrf_error_fatal ( str )
1396 CALL ESMF_FieldGet( src_field, array=src_array, rc=rc )
1397 IF ( rc /= ESMF_SUCCESS ) THEN
1398 WRITE(str,*) 'WRFSSTCpl_run: ESMF_FieldGet(src_field,src_array,rc) failed'
1399 CALL wrf_error_fatal ( str )
1402 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGet(exportState,', &
1403 TRIM(datanames(i)),')...'
1404 CALL wrf_debug ( 100 , TRIM(str) )
1405 CALL ESMF_StateGet( exportState, TRIM(datanames(i)), dst_field, &
1407 IF ( rc /= ESMF_SUCCESS ) THEN
1408 WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateGet(exportState,', &
1409 TRIM(datanames(i)),') failed'
1410 CALL wrf_error_fatal ( str )
1412 CALL ESMF_FieldGet( dst_field, array=dst_array, rc=rc )
1413 IF ( rc /= ESMF_SUCCESS ) THEN
1414 WRITE(str,*) 'WRFSSTCpl_run: ESMF_FieldGet(dst_field,dst_array,rc) failed'
1415 CALL wrf_error_fatal ( str )
1418 ! The redist routine uses information contained in the Fields and the
1419 ! Coupler VM object to call the communication routines to move the data.
1420 ! Because many Fields may share the same Grid association, the same
1421 ! routing information may be needed repeatedly. Route information is
1422 ! saved so the precomputed information can be retained. The following
1423 ! is an example of a Field redist call:
1424 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedist for <', &
1425 TRIM(datanames(i)),'>...'
1426 CALL wrf_debug ( 100 , TRIM(str) )
1427 CALL ESMF_ArrayRedist( src_array, dst_array, routehandle, rc=rc )
1428 IF ( rc /= ESMF_SUCCESS ) THEN
1429 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedist failed' )
1431 WRITE(str,*) 'WRFSSTCpl_run: back from ESMF_FieldRedist for <', &
1432 TRIM(datanames(i)),'>...'
1433 CALL wrf_debug ( 100 , TRIM(str) )
1437 WRITE(str,*) 'WRFSSTCpl_run: end'
1438 CALL wrf_debug ( 100 , TRIM(str) )
1440 END SUBROUTINE WRFSSTCpl_run
1444 SUBROUTINE WRFSSTCpl_final(comp, importState, exportState, clock, rc)
1445 TYPE(ESMF_CplComp) :: comp
1446 TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
1447 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
1448 INTEGER, INTENT(OUT) :: rc
1450 ! WRF-SST coupler component finalize routine.
1452 ! The arguments are:
1454 ! importState Importstate
1455 ! exportState Exportstate
1456 ! clock External clock
1457 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1458 ! otherwise ESMF_FAILURE.
1461 PRINT *, "DEBUG: Coupler Final starting"
1463 ! guilty until proven innocent
1466 ! Only thing to do here is release redist and route handles
1467 IF ( fromWRF_rh_ready ) THEN
1468 CALL ESMF_RouteHandleDestroy(fromWRF_rh, rc)
1469 IF ( rc /= ESMF_SUCCESS ) THEN
1470 CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_RouteHandleDestroy(fromWRF_rh) failed' )
1473 IF ( fromSST_rh_ready ) THEN
1474 CALL ESMF_RouteHandleDestroy(fromSST_rh, rc)
1475 IF ( rc /= ESMF_SUCCESS ) THEN
1476 CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_RouteHandleDestroy(fromSST_rh) failed' )
1480 PRINT *, "DEBUG: Coupler Final returning"
1482 END SUBROUTINE WRFSSTCpl_final
1485 END MODULE module_wrfsst_coupler
1490 PROGRAM wrf_SST_ESMF
1493 ! ESMF Application Wrapper for coupling WRF with a "dummy" component
1494 ! that simply reads SSTs from a file and sends them to WRF (one-way
1495 ! coupling). Fields are returned from WRF to SST via the coupler for
1498 ! Note that, like other WRF coupling methods (MCEL, MCT), ESMF coupling is
1499 ! supported only via auxiliary input and history streams.
1501 ! This is the main program that creates the ESMF Gridded and Coupler
1504 ! "init" looks like this:
1505 ! 1. Init phase 1 for WRF, sets WRF exportState metadata for "time"
1506 ! and "domain" information needed by WRF IOAPI (which is called from
1507 ! the SST component). It also sets up all WRF and WSF modules. Note
1508 ! that this must be called before SST phase-1 init because SST uses
1510 ! 2. Init phase 1 for SST, sets "time" metadata in SST exportState.
1511 ! 3. Initialize coupler, passing decomposition metadata from WRF exportState
1512 ! to SST importState.
1513 ! 4. Resolve any "time" metadata inconsistencies and create top-level clock.
1514 ! 5. Init phase 2 for SST, gets "domain" information from importState,
1515 ! creates an ESMF_Grid based on "domain" information using the exact same
1516 ! method as WRF (so WRF IOAPI calls will work), and sets up SST
1517 ! importState and exportState.
1518 ! 6. Init phase 2 for WRF, runs up to the end of the head_grid I/O "training"
1519 ! phase (done in med_before_solve_io()). This initializes WRF
1520 ! importState and exportState prior to the first coupling step during the
1521 ! "run" loop. Note that this only works for head_grid at present because
1522 ! recursion in WRF traversal of subdomains is not dealt with yet and
1523 ! because the code that populates the WRF importState and exportState is
1524 ! not yet sophisticated enough to handle creating and destroying nested
1525 ! domains at any time during the model run.
1526 !TODO: ESMF auxio must begin at the start of the run. Remove this
1527 !TODO: restriction later, if needed.
1529 !TODO: Note that coupling is currently limited to one auxin plus one auxout
1530 !TODO: streams. Extension to multiple pairs of auxio streams requires
1531 !TODO: nested states (one for each auxio stream pair).
1532 !TODO: For now, only support one input and/or one output stream via
1533 !TODO: io_esmf. This condition is asserted in
1534 !TODO: ext_esmf_open_for_read_begin() and
1535 !TODO: ext_esmf_open_for_write_begin().
1537 ! "run" loop looks like this:
1538 ! 1. Run SST phase 1, reads SST from file and writes it to SST exportState
1539 ! for coupling to WRF.
1540 ! 2. Couple SST exportState -> WRF importState. First iteration: set up
1541 ! SST->WRF routeHandle via lazy evaluation.
1542 ! 3. Run WRF. First iteration: head_grid resumes after I/O "training"
1543 ! phase. Other iterations and domains: run normally.
1544 ! Read WRF importState and write WRF exportState (via med_before_solve_io()).
1545 ! Note that WRF assigns sst -> tsk for sea points in
1546 ! share/module_soil_pre.F.
1547 ! 4. Couple WRF exportState -> SST importState. First iteration: set up
1548 ! WRF->SST routeHandle via lazy evaluation.
1549 ! 5. Run SST phase 2, compare SST from file with SST from WRF (via
1550 ! SST importState) and error-exit if they differ.
1551 ! 6. Advance clock and goto step 1
1553 ! "finalize" is trivial, except for destruction of ESMF objects which is
1554 ! quite non-trivial at the moment.
1558 ! WRF registration routine
1559 USE module_wrf_setservices, ONLY: WRF_register
1560 ! SST registration routine
1561 USE module_sst_setservices, ONLY: SST_register
1562 ! WRF-SST coupler registration routine
1563 USE module_wrfsst_coupler, ONLY: WRFSSTCpl_register
1564 ! ESMF module, defines all ESMF data types and procedures
1565 ! Updated for ESMF 5.2.0r
1568 ! Not-yet-implemented ESMF features
1569 USE module_esmf_extensions
1570 ! Component-independent utilities
1571 USE module_metadatautils, ONLY: GetTimesFromStates
1578 TYPE(ESMF_GridComp) :: compGriddedWRF ! WRF
1579 TYPE(ESMF_GridComp) :: compGriddedSST ! SST reader
1580 TYPE(ESMF_CplComp) :: compCplWRFSST ! WRF-SST coupler
1582 ! State, Virtual Machine, and DELayout
1584 TYPE(ESMF_State) :: importStateWRF, exportStateWRF
1585 TYPE(ESMF_State) :: importStateSST, exportStateSST
1587 ! A clock, some times, and a time step
1588 TYPE(ESMF_Clock) :: driverClock
1589 TYPE(ESMF_Time) :: startTime
1590 TYPE(ESMF_Time) :: stopTime
1591 TYPE(ESMF_TimeInterval) :: couplingInterval
1594 TYPE(ESMF_State) :: tmpState
1595 INTEGER :: timestepdebug
1596 INTEGER :: thecount ! ah ah ah
1598 ! Return codes for error checks
1600 CHARACTER (ESMF_MAXSTR) :: str
1603 CHARACTER(LEN=256) :: couplingIntervalString
1604 integer(ESMF_KIND_I4) :: timevals(6)
1607 ! Warn users that this is not yet ready for general use.
1608 PRINT *, ' W A R N I N G '
1609 PRINT *, ' ESMF COUPLING CAPABILITY IS EXPERIMENTAL AND UNSUPPORTED '
1610 PRINT *, ' IN THIS VERSION OF WRF-CPL-SST '
1611 PRINT *, ' U S E A T Y O U R O W N R I S K '
1613 ! Initialize ESMF, get the default Global VM, and set
1614 ! the default calendar to be Gregorian.
1615 #ifdef NO_LEAP_CALENDAR
1616 CALL ESMF_Initialize( vm=vm, defaultCalKind=ESMF_CALKIND_NOLEAP, logkindflag=ESMF_LOGKIND_MULTI,rc=rc )
1618 CALL ESMF_Initialize( vm=vm, defaultCalKind=ESMF_CALKIND_GREGORIAN, logkindflag=ESMF_LOGKIND_MULTI,rc=rc )
1620 IF ( rc /= ESMF_SUCCESS ) THEN
1621 PRINT *, 'wrf_SST_ESMF: ESMF_Initialize failed'
1623 ! Note: wrf_debug and wrf_error_fatal are not initialized yet
1624 PRINT *, 'DEBUG wrf_SST_ESMF: returned from ESMF_Initialize'
1625 CALL ESMF_SetInitialized() ! eliminate this once ESMF does it internally
1627 ! Create the WRF Gridded Component, passing in the default VM.
1628 compGriddedWRF = ESMF_GridCompCreate( name="WRF Model", rc=rc)
1629 IF ( rc /= ESMF_SUCCESS ) THEN
1630 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompCreate(WRF Model) failed'
1633 ! Create the SST Gridded Component, passing in the default VM.
1634 compGriddedSST = ESMF_GridCompCreate( name="SST Dummy Model", rc=rc)
1635 IF ( rc /= ESMF_SUCCESS ) THEN
1636 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompCreate(WRF Dummy Model) failed'
1639 ! Create the WRF-SST Coupler Component, passing in the default VM.
1640 compCplWRFSST = ESMF_CplCompCreate( name="WRF-SST Coupler", rc=rc)
1641 IF ( rc /= ESMF_SUCCESS ) THEN
1642 PRINT *, 'wrf_SST_ESMF: ESMF_CplCompCreate failed'
1645 ! Create empty import and export states for WRF
1646 importStateWRF = ESMF_StateCreate(name="WRF Import State", stateintent=ESMF_STATEINTENT_IMPORT, rc=rc)
1647 IF ( rc /= ESMF_SUCCESS ) THEN
1648 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(WRF Import State) failed'
1650 exportStateWRF = ESMF_StateCreate(name="WRF Export State", stateintent=ESMF_STATEINTENT_EXPORT, rc=rc)
1651 IF ( rc /= ESMF_SUCCESS ) THEN
1652 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(WRF Export State) failed'
1655 ! Create empty import and export states for SST
1656 importStateSST = ESMF_StateCreate(name="SST Import State", stateintent=ESMF_STATEINTENT_IMPORT, rc=rc)
1657 IF ( rc /= ESMF_SUCCESS ) THEN
1658 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(SST Import State) failed'
1660 exportStateSST = ESMF_StateCreate(name="SST Export State", stateintent=ESMF_STATEINTENT_EXPORT, rc=rc)
1661 IF ( rc /= ESMF_SUCCESS ) THEN
1662 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(SST Export State) failed'
1665 ! Register the WRF Gridded Component
1666 CALL ESMF_GridCompSetServices(compGriddedWRF, WRF_register, rc=rc)
1667 IF ( rc /= ESMF_SUCCESS ) THEN
1668 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompSetServices(compGriddedWRF) failed'
1671 ! Register the SST Gridded Component
1672 CALL ESMF_GridCompSetServices(compGriddedSST, SST_register, rc=rc)
1673 IF ( rc /= ESMF_SUCCESS ) THEN
1674 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompSetServices(compGriddedSST) failed'
1677 ! Register the WRF-SST Coupler Component
1678 CALL ESMF_CplCompSetServices(compCplWRFSST, WRFSSTCpl_register, rc=rc)
1679 IF ( rc /= ESMF_SUCCESS ) THEN
1680 PRINT *, 'wrf_SST_ESMF: ESMF_CplCompSetServices failed'
1683 ! Create top-level clock. There is no way to create an "empty" clock, so
1684 ! stuff in bogus values for start time, stop time, and time step and fix
1685 ! them after gridded component "init" phases return.
1686 CALL ESMF_TimeSet(startTime, yy=2000, mm=1, dd=1, &
1687 h=0, m=0, s=0, rc=rc)
1688 IF ( rc /= ESMF_SUCCESS ) THEN
1689 PRINT *, 'wrf_SST_ESMF: ESMF_TimeSet(startTime) failed'
1691 CALL ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, &
1692 h=12, m=0, s=0, rc=rc)
1693 IF ( rc /= ESMF_SUCCESS ) THEN
1694 PRINT *, 'wrf_SST_ESMF: ESMF_TimeSet(stopTime) failed'
1696 CALL ESMF_TimeIntervalSet(couplingInterval, s=2, rc=rc)
1697 IF ( rc /= ESMF_SUCCESS ) THEN
1698 PRINT *, 'wrf_SST_ESMF: ESMF_TimeIntervalSet failed'
1700 driverClock = ESMF_ClockCreate(timeStep=couplingInterval, &
1701 startTime=startTime, &
1702 stopTime=stopTime, rc=rc)
1703 IF ( rc /= ESMF_SUCCESS ) THEN
1704 PRINT *, 'wrf_SST_ESMF: ESMF_ClockCreate failed'
1707 ! Init, Run, and Finalize section
1710 ! initialize WRF, phase 1
1711 ! Phase 1 init returns WRF time and decomposition information as
1712 ! exportState metadata.
1713 PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 WRF init (wrf_component_init1)'
1714 CALL ESMF_GridCompInitialize(compGriddedWRF, importstate=importStateWRF, &
1715 exportstate=exportStateWRF, clock=driverClock, phase=1, rc=rc)
1716 thecount = size(timevals)
1717 call esmf_attributeget(exportstatewrf,'ComponentCouplingInterval',timevals,itemcount=thecount,rc=rc)
1718 !write(0,*) 'exportStateWRF year ',timevals(1),__LINE__
1719 !write(0,*) 'exportStateWRF month ',timevals(2),__LINE__
1720 !write(0,*) 'exportStateWRF day ',timevals(3),__LINE__
1721 !write(0,*) 'exportStateWRF hour ',timevals(4),__LINE__
1722 !write(0,*) 'exportStateWRF minute ',timevals(5),__LINE__
1723 !write(0,*) 'exportStateWRF second ',timevals(6),__LINE__
1724 ! Note: wrf_debug and wrf_error_fatal are now initialized
1725 IF ( rc /= ESMF_SUCCESS ) THEN
1726 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(WRF phase 1) failed' )
1729 ! initialize SST, phase 1
1730 ! Phase 1 init returns SST time information as
1731 ! exportState metadata.
1732 PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 SST init (sst_component_init1)'
1733 CALL ESMF_GridCompInitialize(compGriddedSST, importstate=importStateSST, &
1734 exportstate=exportStateSST, clock=driverClock, phase=1, rc=rc)
1735 thecount = size(timevals)
1736 call esmf_attributeget(exportstatesst,'ComponentCouplingInterval',timevals,itemcount=thecount,rc=rc)
1737 !write(0,*) 'exportStateSST year ',timevals(1),__LINE__
1738 !write(0,*) 'exportStateSST month ',timevals(2),__LINE__
1739 !write(0,*) 'exportStateSST day ',timevals(3),__LINE__
1740 !write(0,*) 'exportStateSST hour ',timevals(4),__LINE__
1741 !write(0,*) 'exportStateSST minute ',timevals(5),__LINE__
1742 !write(0,*) 'exportStateSST second ',timevals(6),__LINE__
1743 IF ( rc /= ESMF_SUCCESS ) THEN
1744 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(SST phase 1) failed' )
1747 ! Reconcile clock settings from WRF and SST components to set up
1748 ! top-level clock. These are passed back from each "init" as attributes
1750 ! Stuff both States into a single State to pass into GetTimesFromStates()
1751 ! which is smart enough to deal with a Composite.
1752 PRINT *, 'DEBUG wrf_SST_ESMF: reconciling clock from WRF and SST components'
1753 tmpState = ESMF_StateCreate( rc=rc )
1754 IF ( rc /= ESMF_SUCCESS ) THEN
1755 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateCreate(tmpState) failed' )
1757 CALL ESMF_StateAdd( tmpState, nestedStateList=(/exportStateWRF,exportStateSST/), rc=rc )
1758 IF ( rc /= ESMF_SUCCESS ) THEN
1759 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateAdd(exportStateWRF,exportStateSST) failed' )
1761 CALL GetTimesFromStates( tmpState, startTime, stopTime, couplingInterval )
1762 CALL ESMF_TimeIntervalGet( couplingInterval, TimeString=couplingIntervalString, &
1764 IF ( rc /= ESMF_SUCCESS ) THEN
1765 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_TimeIntervalGet failed' )
1767 CALL wrf_debug( 100, 'wrf_SST_ESMF: couplingInterval = '//TRIM(couplingIntervalString) )
1768 CALL ESMF_StateDestroy( tmpState, rc=rc )
1769 IF ( rc /= ESMF_SUCCESS ) THEN
1770 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(tmpState) failed' )
1772 ! update driver clock
1773 CALL ESMF_ClockDestroy(driverClock, rc=rc)
1774 IF ( rc /= ESMF_SUCCESS ) THEN
1775 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockDestroy failed' )
1777 driverClock = ESMF_ClockCreate(timeStep=couplingInterval, &
1778 startTime=startTime, &
1779 stopTime=stopTime, rc=rc)
1780 IF ( rc /= ESMF_SUCCESS ) THEN
1781 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockCreate(driverClock) failed' )
1783 PRINT *, 'DEBUG wrf_SST_ESMF: done reconciling clock from WRF and SST components'
1784 CALL wrf_clockprint(50, driverClock, &
1785 'DEBUG wrf_SST_ESMF: driverClock after creation,')
1787 ! initialize WRF-SST Coupler
1788 PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 CPL init (WRFSSTCpl_init)'
1789 CALL ESMF_CplCompInitialize(compCplWRFSST, importstate=exportStateWRF, &
1790 exportstate=importStateSST, clock=driverClock, rc=rc)
1791 IF ( rc /= ESMF_SUCCESS ) THEN
1792 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompInitialize(WRF -> SST) failed' )
1795 ! TBH: this bit is not needed, but would be in general
1796 ! CALL ESMF_CplCompInitialize(compCplWRFSST, importstate=exportStateSST, &
1797 ! exportstate=importStateWRF, clock=driverClock, rc=rc)
1798 ! IF ( rc /= ESMF_SUCCESS ) THEN
1799 ! CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompInitialize(SST -> WRF) failed' )
1802 ! initialize SST, phase 2
1803 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 init for SST (sst_component_init2)'
1804 CALL wrf_debug ( 100 , TRIM(str) )
1805 CALL ESMF_GridCompInitialize(compGriddedSST, importstate=importStateSST, &
1806 exportstate=exportStateSST, clock=driverClock, phase=2, rc=rc)
1807 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 init for SST'
1808 CALL wrf_debug ( 100 , TRIM(str) )
1809 IF ( rc /= ESMF_SUCCESS ) THEN
1810 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(SST phase 2) failed' )
1813 ! initialize WRF, phase 2
1814 ! Phase 2 init sets up WRF importState and exportState.
1815 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 init for WRF (wrf_component_init2)'
1816 CALL wrf_debug ( 100 , TRIM(str) )
1817 CALL ESMF_GridCompInitialize(compGriddedWRF, importstate=importStateWRF, &
1818 exportstate=exportStateWRF, clock=driverClock, phase=2, rc=rc)
1819 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 init for WRF'
1820 CALL wrf_debug ( 100 , TRIM(str) )
1821 IF ( rc /= ESMF_SUCCESS ) THEN
1822 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(WRF phase 2) failed' )
1825 CALL wrf_clockprint(50, driverClock, &
1826 'DEBUG wrf_SST_ESMF: driverClock before main time-stepping loop,')
1828 ! main time-stepping loop
1830 DO WHILE ( .NOT. ESMF_ClockIsStopTime(driverClock, rc=rc) )
1832 timestepdebug = timestepdebug + 1
1833 WRITE(str,'(A,I8)') 'PROGRAM wrf_SST_ESMF: Top of time-stepping loop, timestepdebug = ',timestepdebug
1834 CALL wrf_debug ( 100 , TRIM(str) )
1835 CALL wrf_clockprint(50, driverClock, &
1836 'DEBUG wrf_SST_ESMF: driverClock at top of time-stepping loop,')
1839 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-1 run for SST (sst_component_run1)'
1840 CALL wrf_debug ( 100 , TRIM(str) )
1841 CALL ESMF_GridCompRun(compGriddedSST, importstate=importStateSST, exportstate=exportStateSST, &
1842 clock=driverClock, phase=1, rc=rc)
1843 IF ( rc /= ESMF_SUCCESS ) THEN
1844 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(SST phase 1) failed' )
1846 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-1 run for SST (sst_component_run1)'
1847 CALL wrf_debug ( 100 , TRIM(str) )
1849 ! couple SST export -> WRF import
1850 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for CPL SST->WRF (WRFSSTCpl_run)'
1851 CALL wrf_debug ( 100 , TRIM(str) )
1852 CALL ESMF_CplCompRun(compCplWRFSST, importstate=exportStateSST, &
1853 exportstate=importStateWRF, clock=driverClock, rc=rc)
1854 IF ( rc /= ESMF_SUCCESS ) THEN
1855 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompRun(SST -> WRF) failed' )
1857 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for CPL SST->WRF (WRFSSTCpl_run)'
1858 CALL wrf_debug ( 100 , TRIM(str) )
1861 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for WRF (wrf_component_run)'
1862 CALL wrf_debug ( 100 , TRIM(str) )
1863 CALL ESMF_GridCompRun(compGriddedWRF, importstate=importStateWRF, exportstate=exportStateWRF, &
1864 clock=driverClock, rc=rc)
1865 IF ( rc /= ESMF_SUCCESS ) THEN
1866 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(WRF) failed' )
1868 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for WRF (wrf_component_run)'
1869 CALL wrf_debug ( 100 , TRIM(str) )
1871 ! couple WRF export -> SST import
1872 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for CPL WRF->SST (WRFSSTCpl_run)'
1873 CALL wrf_debug ( 100 , TRIM(str) )
1874 CALL ESMF_CplCompRun(compCplWRFSST, importstate=exportStateWRF, &
1875 exportstate=importStateSST, clock=driverClock, rc=rc)
1876 IF ( rc /= ESMF_SUCCESS ) THEN
1877 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompRun(WRF -> SST) failed' )
1879 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for CPL WRF->SST (WRFSSTCpl_run)'
1880 CALL wrf_debug ( 100 , TRIM(str) )
1883 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 run for SST (sst_component_run2)'
1884 CALL wrf_debug ( 100 , TRIM(str) )
1885 CALL ESMF_GridCompRun(compGriddedSST, importstate=importStateSST, exportstate=exportStateSST, &
1886 clock=driverClock, phase=2, rc=rc)
1887 IF ( rc /= ESMF_SUCCESS ) THEN
1888 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(SST phase 2) failed' )
1890 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 run for SST (sst_component_run2)'
1891 CALL wrf_debug ( 100 , TRIM(str) )
1893 ! advance clock to next coupling time step
1894 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: advancing clock'
1895 CALL wrf_debug ( 100 , TRIM(str) )
1896 CALL ESMF_ClockAdvance( driverClock, rc=rc )
1897 IF ( rc /= ESMF_SUCCESS ) THEN
1898 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockAdvance failed' )
1900 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: done advancing clock'
1901 CALL wrf_debug ( 100 , TRIM(str) )
1903 CALL wrf_clockprint(50, driverClock, &
1904 'DEBUG wrf_SST_ESMF: driverClock at end of time-stepping loop,')
1908 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: done with time-stepping loop'
1909 CALL wrf_debug ( 100 , TRIM(str) )
1912 CALL ESMF_GridCompFinalize(compGriddedSST, importstate=importStateSST, exportstate=exportStateSST, &
1913 clock=driverClock, rc=rc)
1914 IF ( rc /= ESMF_SUCCESS ) THEN
1915 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompFinalize(compGriddedSST) failed' )
1918 ! clean up compCplWRFSST
1919 CALL ESMF_CplCompFinalize( compCplWRFSST, importstate=exportStateWRF, exportstate=importStateSST, &
1920 clock=driverClock, rc=rc)
1921 IF ( rc /= ESMF_SUCCESS ) THEN
1922 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompFinalize(compCplWRFSST) failed' )
1926 ! must do this AFTER clean up of SST since SST uses WRF IOAPI
1927 CALL ESMF_GridCompFinalize(compGriddedWRF, importstate=importStateWRF, exportstate=exportStateWRF, &
1928 clock=driverClock, rc=rc)
1929 IF ( rc /= ESMF_SUCCESS ) THEN
1930 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompFinalize(compGriddedWRF) failed' )
1935 CALL ESMF_GridCompDestroy(compGriddedWRF, rc=rc)
1936 IF ( rc /= ESMF_SUCCESS ) THEN
1937 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompDestroy(compGriddedWRF) failed' )
1939 CALL ESMF_StateDestroy(importStateWRF, rc=rc)
1940 IF ( rc /= ESMF_SUCCESS ) THEN
1941 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(importStateWRF) failed' )
1943 CALL ESMF_StateDestroy(exportStateWRF, rc=rc)
1944 IF ( rc /= ESMF_SUCCESS ) THEN
1945 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(exportStateWRF) failed' )
1947 CALL ESMF_StateDestroy(importStateSST, rc=rc)
1948 IF ( rc /= ESMF_SUCCESS ) THEN
1949 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(importStateSST) failed' )
1951 CALL ESMF_StateDestroy(exportStateSST, rc=rc)
1952 IF ( rc /= ESMF_SUCCESS ) THEN
1953 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(exportStateSST) failed' )
1955 CALL ESMF_ClockDestroy(driverClock, rc=rc)
1956 IF ( rc /= ESMF_SUCCESS ) THEN
1957 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockDestroy(driverClock) failed' )
1960 CALL ESMF_Finalize( rc=rc )
1961 IF ( rc /= ESMF_SUCCESS ) THEN
1962 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_Finalize failed' )
1965 END PROGRAM wrf_SST_ESMF