wrf_SST_ESMF.F
References to this file elsewhere.
1 !WRF:DRIVER_LAYER:MAIN
2 !
3
4 !<DESCRIPTION>
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.
8 !
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.
12 !
13 ! This source file is only built when ESMF coupling is used.
14 !
15 !</DESCRIPTION>
16
17
18
19 !<DESCRIPTION>
20 ! Modules module_sst_component_top and module_sst_setservices define the
21 ! "SST" dummy component.
22 !</DESCRIPTION>
23
24 MODULE module_sst_component_top
25 !<DESCRIPTION>
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.
29 !</DESCRIPTION>
30
31 USE ESMF_Mod
32 USE module_esmf_extensions
33 USE module_metadatautils, ONLY: AttachTimesToState
34
35
36 IMPLICIT NONE
37
38 ! everything is private by default
39 PRIVATE
40
41 ! Public entry points
42 PUBLIC sst_component_init1
43 PUBLIC sst_component_init2
44 PUBLIC sst_component_run1
45 PUBLIC sst_component_run2
46 PUBLIC sst_component_finalize
47
48 ! private stuff
49 TYPE(ESMF_Grid), SAVE :: esmfgrid ! grid used in fields
50 CHARACTER (4096) :: str
51 INTEGER, SAVE :: fid ! file handle
52 ! decomposition information
53 INTEGER, SAVE :: ids, ide, jds, jde, kds, kde
54 INTEGER, SAVE :: ims, ime, jms, jme, kms, kme
55 INTEGER, SAVE :: ips, ipe, jps, jpe, kps, kpe
56 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_out_sst(:,:)
57 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_out_landmask(:,:)
58 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_in_sst(:,:)
59 REAL(ESMF_KIND_R4), POINTER, SAVE :: tmp_data_in_landmask(:,:)
60 INTEGER, SAVE :: domdesc
61 LOGICAL, SAVE :: bdy_mask(4)
62 ! MPI communicator, if needed
63 INTEGER, SAVE :: mpicom
64 ! field data
65 REAL, POINTER, SAVE :: file_landmask_data(:,:), file_sst_data(:,:)
66 ! input data file name
67 CHARACTER ( ESMF_MAXSTR ), SAVE :: sstinfilename
68 ! field names
69 INTEGER, PARAMETER :: datacount = 2
70 INTEGER, PARAMETER :: SST_INDX = 1
71 INTEGER, PARAMETER :: LANDMASK_INDX = 2
72 CHARACTER(LEN=ESMF_MAXSTR), SAVE :: datanames(datacount)
73 TYPE real2d
74 REAL, POINTER :: r2d(:,:)
75 END TYPE real2d
76 TYPE(real2d) :: this_data(datacount)
77
78
79 CONTAINS
80
81
82
83 ! First-phase "init" reads "SST" data file and returns "time" metadata in
84 ! exportState.
85 SUBROUTINE sst_component_init1( gcomp, importState, exportState, clock, rc )
86 USE module_io
87 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
88 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState
89 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: exportState
90 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
91 INTEGER, INTENT( OUT) :: rc
92 !<DESCRIPTION>
93 ! SST component init routine, phase 1.
94 !
95 ! The arguments are:
96 ! gcomp Component
97 ! importState Importstate
98 ! exportState Exportstate
99 ! clock External clock
100 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
101 ! otherwise ESMF_FAILURE.
102 !</DESCRIPTION>
103
104 #ifdef DM_PARALLEL
105 INCLUDE 'mpif.h'
106 #endif
107
108 ! Local variables
109 CHARACTER (LEN=19) :: date_string
110 #ifdef DM_PARALLEL
111 TYPE(ESMF_VM) :: vm
112 INTEGER :: mpicomtmp
113 #endif
114 TYPE(ESMF_Time) :: startTime, stopTime, currentTime, dataTime
115 TYPE(ESMF_TimeInterval) :: timeStep
116 INTEGER :: ierr, num_steps, time_loop_max
117 INTEGER :: status_next_var
118
119 !TODO: For now, sstinfilename is hard-coded
120 !TODO: Upgrade to use a variant of construct_filename() via startTime
121 !TODO: extracted from clock.
122 sstinfilename = 'sstin_d01_000000'
123
124 ! get MPI communicator out of current VM and duplicate (if needed)
125 #ifdef DM_PARALLEL
126 CALL ESMF_VMGetCurrent(vm, rc=rc)
127 IF ( rc /= ESMF_SUCCESS ) THEN
128 CALL wrf_error_fatal ( 'sst_component_init1: ESMF_VMGetCurrent failed' )
129 ENDIF
130 CALL ESMF_VMGet(vm, mpiCommunicator=mpicomtmp, rc=rc)
131 IF ( rc /= ESMF_SUCCESS ) THEN
132 CALL wrf_error_fatal ( 'sst_component_init1: ESMF_VMGet failed' )
133 ENDIF
134 CALL MPI_Comm_dup( mpicomtmp, mpicom, ierr )
135 #else
136 mpicom = 0
137 #endif
138 ! Open the "SST" input data file for reading.
139 write(str,'(A,A)') 'Subroutine sst_component_init1: Opening data file ', &
140 TRIM(sstinfilename)
141 CALL wrf_message ( TRIM(str) )
142 CALL wrf_open_for_read ( TRIM(sstinfilename) , &
143 mpicom , &
144 mpicom , &
145 "DATASET=INPUT" , &
146 fid , &
147 ierr )
148 IF ( ierr .NE. 0 ) THEN
149 WRITE( str , FMT='(A,A,A,I8)' ) &
150 'subroutine sst_component_init1: error opening ', &
151 TRIM(sstinfilename),' for reading ierr=',ierr
152 CALL wrf_error_fatal ( TRIM(str) )
153 ENDIF
154 WRITE( str , FMT='(A,A,A,I8)' ) &
155 'subroutine sst_component_init1: opened file ', &
156 TRIM(sstinfilename),' for reading fid=',fid
157 CALL wrf_debug ( 100, TRIM(str) )
158
159 ! How many data time levels are in the SST input file?
160 num_steps = -1
161 time_loop_max = 0
162 CALL wrf_debug ( 100, 'subroutine sst_component_init1: find time_loop_max' )
163 ! compute SST start time, time step, and end time here
164 get_the_right_time : DO
165 CALL wrf_get_next_time ( fid, date_string, status_next_var )
166 write(str,'(A,A)') 'Subroutine sst_component_init1: SST data startTime: ', &
167 date_string
168 CALL wrf_debug ( 100 , TRIM(str) )
169 IF ( status_next_var == 0 ) THEN
170 IF ( time_loop_max == 0 ) THEN
171 CALL wrf_atotime( date_string, startTime )
172 ELSEIF ( time_loop_max == 1 ) THEN
173 ! assumes fixed time step!
174 CALL wrf_atotime( date_string, dataTime )
175 timeStep = dataTime - startTime
176 ENDIF
177 time_loop_max = time_loop_max + 1
178 CALL wrf_atotime( date_string, stopTime )
179 ELSE
180 EXIT get_the_right_time
181 ENDIF
182 END DO get_the_right_time
183 CALL wrf_timetoa ( stopTime, date_string )
184 write(str,'(A,A)') 'Subroutine sst_component_init1: SST data stopTime: ', &
185 date_string
186 CALL wrf_debug ( 100 , TRIM(str) )
187 ! attach times to exportState for use by driver
188 CALL AttachTimesToState( exportState, startTime, stopTime, timeStep )
189
190 ! There should be a more elegant way to get to the beginning of the
191 ! file, but this will do.
192 CALL wrf_ioclose( fid , ierr )
193 IF ( ierr .NE. 0 ) THEN
194 CALL wrf_error_fatal ( 'sst_component_init1: wrf_ioclose failed' )
195 ENDIF
196 WRITE( str , FMT='(A,I8)' ) &
197 'subroutine sst_component_init1: closed file fid=',fid
198 CALL wrf_debug ( 100, TRIM(str) )
199
200 ! set up field names
201 !TODO: use CF conventions for "standard_name" once WRF Registry supports them
202 !TODO: datanames(SST_INDX) = "sea_surface_temperature"
203 !TODO: datanames(LANDMASK_INDX) = "land_binary_mask"
204 datanames(SST_INDX) = "SST"
205 datanames(LANDMASK_INDX) = "LANDMASK"
206
207 rc = ESMF_SUCCESS
208
209 END SUBROUTINE sst_component_init1
210
211
212
213 SUBROUTINE read_data( exportState, clock )
214 USE module_io
215 TYPE(ESMF_State), INTENT(INOUT) :: exportState
216 TYPE(ESMF_Clock), INTENT(IN ) :: clock
217 !<DESCRIPTION>
218 ! Reads data from file and stores. Then
219 ! stuffs the file data into the SST exportState.
220 !</DESCRIPTION>
221
222 #include <wrf_status_codes.h>
223 #include <wrf_io_flags.h>
224
225 ! Local variables
226 CHARACTER (LEN=19) :: date_string
227 TYPE(ESMF_Time) :: currentTime, dataTime
228 REAL(ESMF_KIND_R4), POINTER :: out_sst_ptr(:,:), out_landmask_ptr(:,:)
229 TYPE(ESMF_Field) :: out_sst_field, out_landmask_field
230 TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
231 INTEGER :: i, j
232 CHARACTER(LEN=ESMF_MAXSTR) :: fieldname, debugmsg, errormsg, timestr
233 INTEGER :: ierr
234 INTEGER :: rc
235
236 ! This call to wrf_get_next_time will position the dataset over the next
237 ! time-frame in the file and return the date_string, which is used as an
238 ! argument to the read_field routines in the blocks of code included
239 ! below.
240
241 CALL wrf_get_next_time( fid, date_string , ierr )
242 WRITE(str,'(A,A)') 'Subroutine read_data: SST data time: ', &
243 date_string
244 CALL wrf_debug ( 100 , TRIM(str) )
245 IF ( ierr .NE. 0 .AND. ierr .NE. WRF_WARN_NOTSUPPORTED .AND. &
246 ierr .NE. WRF_WARN_DRYRUN_READ ) THEN
247 CALL wrf_error_fatal ( "... May have run out of valid SST data ..." )
248 ELSE IF ( ierr .NE. WRF_WARN_NOTSUPPORTED .AND. &
249 ierr .NE. WRF_WARN_DRYRUN_READ) THEN
250 ! check input time against current time (which will be start time at
251 ! beginning)
252 CALL wrf_atotime( date_string, dataTime )
253 CALL ESMF_ClockGet( clock, CurrTime=currentTime, rc=rc )
254 IF (rc /= ESMF_SUCCESS) THEN
255 CALL wrf_error_fatal ( 'read_data: ESMF_ClockGet() failed' )
256 ENDIF
257 CALL wrf_clockprint(150, clock, &
258 'DEBUG read_data(): get currentTime from clock,')
259 IF ( dataTime .NE. currentTime ) THEN
260 CALL wrf_timetoa ( dataTime, timestr )
261 WRITE( errormsg , * )'Time in file: ',trim( timestr )
262 CALL wrf_message ( trim(errormsg) )
263 CALL wrf_timetoa ( currentTime, timestr )
264 WRITE( errormsg , * )'Time on domain: ',trim( timestr )
265 CALL wrf_message ( trim(errormsg) )
266 CALL wrf_error_fatal( &
267 "**ERROR** Time in input file not equal to time on domain **ERROR**" )
268 ENDIF
269 ENDIF
270
271 ! doing this in a loop only works if staggering is the same for all fields
272 this_data(SST_INDX)%r2d => file_sst_data
273 this_data(LANDMASK_INDX)%r2d => file_landmask_data
274 DO i=1, datacount
275 fieldname = TRIM(datanames(i))
276 debugmsg = 'ext_read_field '//TRIM(fieldname)//' memorder XY'
277 errormsg = 'could not read '//TRIM(fieldname)//' data from file'
278 CALL wrf_ext_read_field ( &
279 fid , & ! DataHandle
280 date_string , & ! DateStr
281 TRIM(fieldname) , & ! Data Name
282 this_data(i)%r2d , & ! Field
283 WRF_REAL , & ! FieldType
284 mpicom , & ! Comm
285 mpicom , & ! I/O Comm
286 domdesc , & ! Domain descriptor
287 bdy_mask , & ! bdy_mask
288 'XY' , & ! MemoryOrder
289 '' , & ! Stagger
290 TRIM(debugmsg) , & ! Debug message
291 ids , (ide-1) , jds , (jde-1) , 1 , 1 , &
292 ims , ime , jms , jme , 1 , 1 , &
293 ips , MIN( (ide-1), ipe ) , jps , MIN( (jde-1), jpe ) , 1 , 1 , &
294 ierr )
295 IF (ierr /= 0) THEN
296 CALL wrf_error_fatal ( TRIM(errormsg) )
297 ENDIF
298 ENDDO
299
300 ! stuff fields into exportState
301 !TODO: change this to Bundles, eventually
302 CALL ESMF_StateGetField( exportState, TRIM(datanames(SST_INDX)), &
303 out_sst_field, rc=rc )
304 IF (rc /= ESMF_SUCCESS) THEN
305 CALL wrf_error_fatal ( &
306 'could not find sea_surface_temperature field in exportState' )
307 ENDIF
308 CALL ESMF_StateGetField( exportState, TRIM(datanames(LANDMASK_INDX)), &
309 out_landmask_field, rc=rc )
310 IF (rc /= ESMF_SUCCESS) THEN
311 CALL wrf_error_fatal ( &
312 'could not find land_binary_mask field in exportState' )
313 ENDIF
314 CALL ESMF_FieldGetDataPointer( out_sst_field, out_sst_ptr, rc=rc )
315 IF (rc /= ESMF_SUCCESS) THEN
316 CALL wrf_error_fatal ( &
317 'could not find sea_surface_temperature data in sea_surface_temperature field' )
318 ENDIF
319 CALL ESMF_FieldGetDataPointer( out_landmask_field, out_landmask_ptr, rc=rc )
320 IF (rc /= ESMF_SUCCESS) THEN
321 CALL wrf_error_fatal ( &
322 'could not find land_binary_mask data in land_binary_mask field' )
323 ENDIF
324 ! staggered starts/ends
325 DO j= jps , MIN( (jde-1), jpe )
326 DO i= ips , MIN( (ide-1), ipe )
327 out_sst_ptr(i,j) = file_sst_data(i,j)
328 out_landmask_ptr(i,j) = file_landmask_data(i,j)
329 ENDDO
330 ENDDO
331
332 END SUBROUTINE read_data
333
334
335
336
337 SUBROUTINE compare_data( importState, clock )
338 TYPE(ESMF_State), INTENT(INOUT) :: importState
339 !TODO: remove clock after debugging is finished
340 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
341 !<DESCRIPTION>
342 ! Gets data from coupler via importState
343 ! and compares with data read from file and
344 ! error-exits if they differ.
345 !
346 ! The arguments are:
347 ! importState Importstate
348 !</DESCRIPTION>
349
350 ! Local variables
351 TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
352 REAL(ESMF_KIND_R4), POINTER :: in_sst_ptr(:,:), in_landmask_ptr(:,:)
353 REAL, POINTER :: in_sst_ptr_real(:,:), in_landmask_ptr_real(:,:)
354 INTEGER :: i, j
355 INTEGER :: rc
356 LOGICAL :: landmask_ok, sst_ok
357 ! use these for debug prints
358 TYPE(ESMF_Time) :: currentTime
359 INTEGER, SAVE :: numtimes=0 ! track number of calls
360 CHARACTER(LEN=256) :: timestamp
361
362 ! count calls for debug prints...
363 CALL ESMF_ClockGet( clock, CurrTime=currentTime, rc=rc )
364 IF (rc /= ESMF_SUCCESS) THEN
365 CALL wrf_error_fatal ( 'compare_data: ESMF_ClockGet() failed' )
366 ENDIF
367 CALL wrf_timetoa ( currentTime, timestamp )
368 numtimes = numtimes + 1
369 WRITE(str,*) 'SST compare_data: begin, numtimes = ',numtimes,' time = ',TRIM(timestamp)
370 CALL wrf_debug ( 100 , TRIM(str) )
371
372 ! extract data from the importState and compare with data from file
373 !TODO: change this to Bundles, eventually
374 CALL ESMF_StateGetField( importState, TRIM(datanames(SST_INDX)), &
375 in_sst_field, rc=rc )
376 IF (rc /= ESMF_SUCCESS) THEN
377 CALL wrf_error_fatal ( &
378 'could not extract sea_surface_temperature field from importState' )
379 ENDIF
380 CALL ESMF_StateGetField( importState, TRIM(datanames(LANDMASK_INDX)), &
381 in_landmask_field, rc=rc )
382 IF (rc /= ESMF_SUCCESS) THEN
383 CALL wrf_error_fatal ( &
384 'could not extract land_binary_mask field from importState' )
385 ENDIF
386 CALL ESMF_FieldGetDataPointer( in_sst_field, in_sst_ptr, rc=rc )
387 IF (rc /= ESMF_SUCCESS) THEN
388 CALL wrf_error_fatal ( &
389 'could not extract sea_surface_temperature data from sea_surface_temperature field' )
390 ENDIF
391 ALLOCATE( in_sst_ptr_real(ims:ime,jms:jme) )
392 WRITE( str,* ) 'compare_data, ips:ipe,jps:jpe = ', &
393 ips,':',ipe,',',jps,':',jpe, &
394 ', in_sst_ptr(BOUNDS) = ', &
395 LBOUND(in_sst_ptr,1),':',UBOUND(in_sst_ptr,1),',', &
396 LBOUND(in_sst_ptr,2),':',UBOUND(in_sst_ptr,2)
397 CALL wrf_debug ( 100 , TRIM(str) )
398 DO j= jms, jme
399 DO i= ims, ime
400 in_sst_ptr_real(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
401 ENDDO
402 ENDDO
403 in_sst_ptr_real(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe)) = &
404 in_sst_ptr(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe))
405 CALL ESMF_FieldGetDataPointer( in_landmask_field, in_landmask_ptr, rc=rc )
406 IF (rc /= ESMF_SUCCESS) THEN
407 CALL wrf_error_fatal ( &
408 'could not extract land_binary_mask data from land_binary_mask field' )
409 ENDIF
410 ALLOCATE( in_landmask_ptr_real(ims:ime,jms:jme) )
411 WRITE( str,* ) 'compare_data, ips:ipe,jps:jpe = ', &
412 ips,':',ipe,',',jps,':',jpe, &
413 ', in_landmask_ptr(BOUNDS) = ', &
414 LBOUND(in_landmask_ptr,1),':',UBOUND(in_landmask_ptr,1),',', &
415 LBOUND(in_landmask_ptr,2),':',UBOUND(in_landmask_ptr,2)
416 CALL wrf_debug ( 100 , TRIM(str) )
417 DO j= jms, jme
418 DO i= ims, ime
419 in_landmask_ptr_real(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
420 ENDDO
421 ENDDO
422 in_landmask_ptr_real(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe)) = &
423 in_landmask_ptr(ips:MIN((ide-1),ipe),jps:MIN((jde-1),jpe))
424
425 ! compare LANDMASK...
426 landmask_ok = .TRUE.
427 ! staggered starts/ends
428 LANDMASK_COMPARE : DO j= jps , MIN( (jde-1), jpe )
429 DO i= ips , MIN( (ide-1), ipe )
430 IF ( file_landmask_data(i,j) /= in_landmask_ptr_real(i,j) ) THEN
431 landmask_ok = .FALSE.
432 WRITE( str , * ) 'error landmask mismatch at (i,j) = (',i,',',j, &
433 '), values are',file_landmask_data(i,j),' and ', &
434 in_landmask_ptr_real(i,j)
435 EXIT LANDMASK_COMPARE
436 ENDIF
437 ENDDO
438 ENDDO LANDMASK_COMPARE
439 IF ( landmask_ok ) THEN
440 WRITE(str,*) 'compare_data: LANDMASK compares OK'
441 CALL wrf_debug ( 100 , TRIM(str) )
442 ELSE
443 CALL wrf_error_fatal ( TRIM(str) )
444 ENDIF
445
446 ! compare SST...
447 sst_ok = .TRUE.
448 ! staggered starts/ends
449 SST_COMPARE : DO j= jps , MIN( (jde-1), jpe )
450 DO i= ips , MIN( (ide-1), ipe )
451 IF ( file_sst_data(i,j) /= in_sst_ptr_real(i,j) ) THEN
452 sst_ok = .FALSE.
453 WRITE( str , * ) 'error sst mismatch at (i,j) = (',i,',',j, &
454 '), values are',file_sst_data(i,j),' and ', &
455 in_sst_ptr_real(i,j)
456 EXIT SST_COMPARE
457 ENDIF
458 ENDDO
459 ENDDO SST_COMPARE
460 IF ( sst_ok ) THEN
461 WRITE(str,*) 'compare_data: SST compares OK'
462 CALL wrf_debug ( 100 , TRIM(str) )
463 ELSE
464 CALL wrf_error_fatal ( TRIM(str) )
465 ENDIF
466
467 DEALLOCATE( in_sst_ptr_real, in_landmask_ptr_real )
468
469 WRITE(str,*) 'compare_data: end, numtimes = ',numtimes
470 CALL wrf_debug ( 100 , TRIM(str) )
471
472 END SUBROUTINE compare_data
473
474
475
476
477 ! Second-phase "init" gets decomposition information from
478 ! importState.
479 SUBROUTINE sst_component_init2( gcomp, importState, exportState, clock, rc )
480 USE module_metadatautils, ONLY: GetDecompFromState
481 USE module_io
482 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
483 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState
484 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: exportState
485 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
486 INTEGER, INTENT( OUT) :: rc
487 !<DESCRIPTION>
488 ! SST component init routine, phase 2.
489 !
490 ! The arguments are:
491 ! gcomp Component
492 ! importState Importstate
493 ! exportState Exportstate
494 ! clock External clock
495 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
496 ! otherwise ESMF_FAILURE.
497 !</DESCRIPTION>
498
499 ! Local variables
500 TYPE(ESMF_RelLoc) :: horzRelloc
501 TYPE(ESMF_Field) :: out_sst_field, out_landmask_field
502 TYPE(ESMF_Field) :: in_sst_field, in_landmask_field
503 INTEGER, PARAMETER :: NUMDIMS=2
504 INTEGER :: DomainStart(NUMDIMS)
505 INTEGER :: DomainEnd(NUMDIMS)
506 INTEGER :: MemoryStart(NUMDIMS)
507 INTEGER :: MemoryEnd(NUMDIMS)
508 INTEGER :: PatchStart(NUMDIMS)
509 INTEGER :: PatchEnd(NUMDIMS)
510 INTEGER :: rc, i, j
511 INTEGER :: ierr
512
513 ! Get decomposition information from importState. Note that index
514 ! values are for staggered dimensions, following the WRF convention.
515 !TODO: Note that this will only work for SPMD serial operation. For
516 !TODO: concurrent operation (SPMD or MPMD), we will need to create a new
517 !TODO: "domdesc" suitable for the task layout of the SST component. For
518 !TODO: MPMD serial operation, we will need to extract serialized domdesc
519 !TODO: from export state metadata and de-serialize it. Similar arguments
520 !TODO: apply to [ij][mp][se] and bdy_mask.
521 write(str,*) 'sst_component_init2: calling GetDecompFromState'
522 CALL wrf_debug ( 100 , TRIM(str) )
523 CALL GetDecompFromState( importState, &
524 ids, ide, jds, jde, kds, kde, &
525 ims, ime, jms, jme, kms, kme, &
526 ips, ipe, jps, jpe, kps, kpe, &
527 domdesc, bdy_mask )
528 write(str,*) 'sst_component_init2: back from GetDecompFromState'
529 CALL wrf_debug ( 100 , TRIM(str) )
530 write(str,*) 'sst_component_init2: ids, ide, jds, jde, kds, kde = ', ids, ide, jds, jde, kds, kde
531 CALL wrf_debug ( 100 , TRIM(str) )
532 write(str,*) 'sst_component_init2: ims, ime, jms, jme, kms, kme = ', ims, ime, jms, jme, kms, kme
533 CALL wrf_debug ( 100 , TRIM(str) )
534 write(str,*) 'sst_component_init2: ips, ipe, jps, jpe, kps, kpe = ', ips, ipe, jps, jpe, kps, kpe
535 CALL wrf_debug ( 100 , TRIM(str) )
536
537 ! allocate space for data read from disk
538 ALLOCATE( file_sst_data (ims:ime,jms:jme) )
539 DO j= jms, jme
540 DO i= ims, ime
541 file_sst_data(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
542 ENDDO
543 ENDDO
544 !TODO: Hmmm... really need to load these pointers here? Check...
545 this_data(SST_INDX)%r2d => file_sst_data
546 ALLOCATE( file_landmask_data(ims:ime,jms:jme) )
547 DO j= jms, jme
548 DO i= ims, ime
549 file_landmask_data(i,j) = -(i*1000.0 + j)/100000.0 ! obvious bad value for debugging
550 ENDDO
551 ENDDO
552 this_data(LANDMASK_INDX)%r2d => file_landmask_data
553
554 ! Create ESMF_Fields in importState and exportState
555 ! Create ESMF_Grid. Use exactly the same method as WRF so WRFIO will
556 ! work.
557 DomainStart(1) = ids; DomainEnd(1) = ide;
558 DomainStart(2) = jds; DomainEnd(2) = jde;
559 MemoryStart(1) = ims; MemoryEnd(1) = ime;
560 MemoryStart(2) = jms; MemoryEnd(2) = jme;
561 PatchStart(1) = ips; PatchEnd(1) = ipe;
562 PatchStart(2) = jps; PatchEnd(2) = jpe
563 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: Calling ioesmf_create_grid_int()' )
564 CALL ioesmf_create_grid_int( esmfgrid, NUMDIMS, &
565 DomainStart, DomainEnd, &
566 MemoryStart, MemoryEnd, &
567 PatchStart, PatchEnd )
568 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: back from ioesmf_create_grid_int()' )
569 ! create ESMF_Fields
570 !TODO: use CF standard_names later
571 !TODO: Avoid this hackery by communicating horzrelloc during init sometime...
572 horzrelloc=ESMF_CELL_CENTER
573 ! Note use of patch dimension for POINTERs allocated by ESMF.
574 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: Calling ESMF_GridValidate(esmfgrid)' )
575 CALL ESMF_GridValidate( esmfgrid, rc=rc )
576 IF ( rc /= ESMF_SUCCESS ) THEN
577 WRITE( str,* ) 'Error in ESMF_GridValidate ', &
578 __FILE__ , &
579 ', line ', &
580 __LINE__ , &
581 ', error code = ',rc
582 CALL wrf_error_fatal ( TRIM(str) )
583 ENDIF
584 CALL wrf_debug ( 5 , 'DEBUG sst_component_init2: back OK from ESMF_GridValidate(esmfgrid)' )
585 !TODO: Once new ESMF 3.0 interfaces have settled down, eliminate "tmp_data_"
586 !TODO: arrays and let ESMF allocate/deallocate them. Assuming of course that
587 !TODO: we can convince ESMF to deallocate safely...
588 ALLOCATE( tmp_data_out_sst(ips:ipe,jps:jpe) )
589 write(str,*) 'sst_component_init2: tmp_data_out_sst(', &
590 LBOUND(tmp_data_out_sst,1),':',UBOUND(tmp_data_out_sst,1),',',LBOUND(tmp_data_out_sst,2),':',UBOUND(tmp_data_out_sst,2),')'
591 CALL wrf_debug ( 100 , TRIM(str) )
592 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(out_sst_field)' )
593 out_sst_field = ESMF_FieldCreate( &
594 esmfgrid, tmp_data_out_sst, &
595 copyflag=ESMF_DATA_REF, &
596 horzrelloc=horzrelloc, &
597 name=TRIM(datanames(SST_INDX)), &
598 ! lbounds=(/ips,jps/), &
599 ! ubounds=(/ipe,jpe/), &
600 rc=rc )
601 IF ( rc /= ESMF_SUCCESS ) THEN
602 WRITE( str,* ) 'ESMF_FieldCreate(out_sst_field) failed ', &
603 __FILE__ , &
604 ', line ', &
605 __LINE__ , &
606 ', error code = ',rc
607 CALL wrf_error_fatal ( TRIM(str) )
608 ENDIF
609 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(out_sst_field)' )
610 write(str,*) 'sst_component_init2: ips:ipe,jps:jpe = ', &
611 ips,':',ipe,',',jps,':',jpe
612 CALL wrf_debug ( 100 , TRIM(str) )
613 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
614 ! validate ESMF allocation
615 IF ( ( ips /= LBOUND(tmp_data_out_sst,1) ) .OR. ( ipe /= UBOUND(tmp_data_out_sst,1) ) .OR. &
616 ( jps /= LBOUND(tmp_data_out_sst,2) ) .OR. ( jpe /= UBOUND(tmp_data_out_sst,2) ) ) THEN
617 WRITE( str,* ) 'ESMF_FieldCreate(out_sst_field) allocation failed ', &
618 __FILE__ , &
619 ', line ', &
620 __LINE__ , &
621 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
622 ', tmp_data_out_sst(BOUNDS) = ',LBOUND(tmp_data_out_sst,1),':',UBOUND(tmp_data_out_sst,1),',', &
623 LBOUND(tmp_data_out_sst,2),':',UBOUND(tmp_data_out_sst,2)
624 CALL wrf_error_fatal ( TRIM(str) )
625 ENDIF
626 ALLOCATE( tmp_data_out_landmask(ips:ipe,jps:jpe) )
627 write(str,*) 'sst_component_init2: tmp_data_out_landmask(', &
628 LBOUND(tmp_data_out_landmask,1),':',UBOUND(tmp_data_out_landmask,1),',',LBOUND(tmp_data_out_landmask,2),':',UBOUND(tmp_data_out_landmask,2),')'
629 CALL wrf_debug ( 100 , TRIM(str) )
630 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(out_landmask_field)' )
631 out_landmask_field = ESMF_FieldCreate( &
632 esmfgrid, tmp_data_out_landmask, &
633 copyflag=ESMF_DATA_REF, &
634 horzrelloc=horzrelloc, &
635 name=TRIM(datanames(LANDMASK_INDX)), &
636 ! lbounds=(/ips,jps/), &
637 ! ubounds=(/ipe,jpe/), &
638 rc=rc )
639 IF ( rc /= ESMF_SUCCESS ) THEN
640 CALL wrf_error_fatal ( 'ESMF_FieldCreate(out_landmask_field) failed' )
641 ENDIF
642 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(out_landmask_field)' )
643 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
644 ! validate ESMF allocation
645 IF ( ( ips /= LBOUND(tmp_data_out_landmask,1) ) .OR. ( ipe /= UBOUND(tmp_data_out_landmask,1) ) .OR. &
646 ( jps /= LBOUND(tmp_data_out_landmask,2) ) .OR. ( jpe /= UBOUND(tmp_data_out_landmask,2) ) ) THEN
647 WRITE( str,* ) 'ESMF_FieldCreate(out_landmask_field) allocation failed ', &
648 __FILE__ , &
649 ', line ', &
650 __LINE__ , &
651 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
652 ', tmp_data_out_landmask(BOUNDS) = ',LBOUND(tmp_data_out_landmask,1),':',UBOUND(tmp_data_out_landmask,1),',', &
653 LBOUND(tmp_data_out_landmask,2),':',UBOUND(tmp_data_out_landmask,2)
654 CALL wrf_error_fatal ( TRIM(str) )
655 ENDIF
656 ALLOCATE( tmp_data_in_sst(ips:ipe,jps:jpe) )
657 write(str,*) 'sst_component_init2: tmp_data_in_sst(', &
658 LBOUND(tmp_data_in_sst,1),':',UBOUND(tmp_data_in_sst,1),',',LBOUND(tmp_data_in_sst,2),':',UBOUND(tmp_data_in_sst,2),')'
659 CALL wrf_debug ( 100 , TRIM(str) )
660 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(in_sst_field)' )
661 in_sst_field = ESMF_FieldCreate( &
662 esmfgrid, tmp_data_in_sst, &
663 copyflag=ESMF_DATA_REF, &
664 horzrelloc=horzrelloc, &
665 name=TRIM(datanames(SST_INDX)), &
666 ! lbounds=(/ips,jps/), &
667 ! ubounds=(/ipe,jpe/), &
668 rc=rc )
669 IF ( rc /= ESMF_SUCCESS ) THEN
670 CALL wrf_error_fatal ( 'ESMF_FieldCreate(in_sst_field) failed' )
671 ENDIF
672 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(in_sst_field)' )
673 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
674 ! validate ESMF allocation
675 IF ( ( ips /= LBOUND(tmp_data_in_sst,1) ) .OR. ( ipe /= UBOUND(tmp_data_in_sst,1) ) .OR. &
676 ( jps /= LBOUND(tmp_data_in_sst,2) ) .OR. ( jpe /= UBOUND(tmp_data_in_sst,2) ) ) THEN
677 WRITE( str,* ) 'ESMF_FieldCreate(in_sst_field) allocation failed ', &
678 __FILE__ , &
679 ', line ', &
680 __LINE__ , &
681 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
682 ', tmp_data_in_sst(BOUNDS) = ',LBOUND(tmp_data_in_sst,1),':',UBOUND(tmp_data_in_sst,1),',', &
683 LBOUND(tmp_data_in_sst,2),':',UBOUND(tmp_data_in_sst,2)
684 CALL wrf_error_fatal ( TRIM(str) )
685 ENDIF
686 ALLOCATE( tmp_data_in_landmask(ips:ipe,jps:jpe) )
687 write(str,*) 'sst_component_init2: tmp_data_in_landmask(', &
688 LBOUND(tmp_data_in_landmask,1),':',UBOUND(tmp_data_in_landmask,1),',',LBOUND(tmp_data_in_landmask,2),':',UBOUND(tmp_data_in_landmask,2),')'
689 CALL wrf_debug ( 100 , TRIM(str) )
690 CALL wrf_debug ( 100, 'sst_component_init2: calling ESMF_FieldCreate(in_landmask_field)' )
691 in_landmask_field = ESMF_FieldCreate( &
692 esmfgrid, tmp_data_in_landmask, &
693 copyflag=ESMF_DATA_REF, &
694 horzrelloc=horzrelloc, &
695 name=TRIM(datanames(LANDMASK_INDX)), &
696 ! lbounds=(/ips,jps/), &
697 ! ubounds=(/ipe,jpe/), &
698 rc=rc )
699 IF ( rc /= ESMF_SUCCESS ) THEN
700 CALL wrf_error_fatal ( 'ESMF_FieldCreate(in_landmask_field) failed' )
701 ENDIF
702 CALL wrf_debug ( 100, 'sst_component_init2: back from ESMF_FieldCreate(in_landmask_field)' )
703 !TODO: This bit will be useful once ESMF handles allocation/deallocation.
704 ! validate ESMF allocation
705 IF ( ( ips /= LBOUND(tmp_data_in_landmask,1) ) .OR. ( ipe /= UBOUND(tmp_data_in_landmask,1) ) .OR. &
706 ( jps /= LBOUND(tmp_data_in_landmask,2) ) .OR. ( jpe /= UBOUND(tmp_data_in_landmask,2) ) ) THEN
707 WRITE( str,* ) 'ESMF_FieldCreate(in_landmask_field) allocation failed ', &
708 __FILE__ , &
709 ', line ', &
710 __LINE__ , &
711 ', ips:ipe,jps:jpe = ',ips,':',ipe,',',jps,':',jpe, &
712 ', tmp_data_in_landmask(BOUNDS) = ',LBOUND(tmp_data_in_landmask,1),':',UBOUND(tmp_data_in_landmask,1),',', &
713 LBOUND(tmp_data_in_landmask,2),':',UBOUND(tmp_data_in_landmask,2)
714 CALL wrf_error_fatal ( TRIM(str) )
715 ENDIF
716
717 ! attach ESMF_Field to importState
718 CALL ESMF_StateAddField( importState, in_sst_field, rc=rc )
719 IF ( rc /= ESMF_SUCCESS ) THEN
720 CALL wrf_error_fatal ( 'ESMF_StateAddField(in_sst_field) failed' )
721 ENDIF
722 CALL ESMF_StateAddField( importState, in_landmask_field, rc=rc )
723 IF ( rc /= ESMF_SUCCESS ) THEN
724 CALL wrf_error_fatal ( 'ESMF_StateAddField(in_landmask_field) failed' )
725 ENDIF
726 ! attach ESMF_Field to exportState
727 CALL ESMF_StateAddField( exportState, out_sst_field, rc=rc )
728 IF ( rc /= ESMF_SUCCESS ) THEN
729 CALL wrf_error_fatal ( 'ESMF_StateAddField(out_sst_field) failed' )
730 ENDIF
731 CALL ESMF_StateAddField( exportState, out_landmask_field, rc=rc )
732 IF ( rc /= ESMF_SUCCESS ) THEN
733 CALL wrf_error_fatal ( 'ESMF_StateAddField(out_landmask_field) failed' )
734 ENDIF
735
736 ! Open the "SST" input data file for reading.
737 write(str,'(A,A)') 'sst_component_init2: Opening data file ', &
738 TRIM(sstinfilename)
739 CALL wrf_message ( TRIM(str) )
740 CALL wrf_open_for_read ( TRIM(sstinfilename) , &
741 mpicom , &
742 mpicom , &
743 "DATASET=INPUT" , &
744 fid , &
745 ierr )
746 IF ( ierr .NE. 0 ) THEN
747 WRITE( str , FMT='(A,A,A,I8)' ) &
748 'sst_component_init2: error opening ', &
749 TRIM(sstinfilename),' for reading ierr=',ierr
750 CALL wrf_error_fatal ( TRIM(str) )
751 ENDIF
752 WRITE( str , FMT='(A,A,A,I8)' ) &
753 'subroutine sst_component_init2: opened file ', &
754 TRIM(sstinfilename),' for reading fid=',fid
755 CALL wrf_debug ( 100, TRIM(str) )
756
757 write(str,'(A)') 'sst_component_init2: returning rc=ESMF_SUCCESS'
758 CALL wrf_debug ( 100 , TRIM(str) )
759
760 rc = ESMF_SUCCESS
761
762 END SUBROUTINE sst_component_init2
763
764
765
766 SUBROUTINE sst_component_run1( gcomp, importState, exportState, clock, rc )
767 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
768 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
769 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
770 INTEGER, INTENT( OUT) :: rc
771 !<DESCRIPTION>
772 ! SST component run routine, phase 1.
773 ! Read "SST" data from file and stuff into exportState.
774 !
775 ! The arguments are:
776 ! gcomp Component
777 ! importState Importstate
778 ! exportState Exportstate
779 ! clock External clock
780 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
781 ! otherwise ESMF_FAILURE.
782 !</DESCRIPTION>
783
784 rc = ESMF_SUCCESS
785
786 ! Get "SST" data from file and stuff it into exportState.
787 CALL read_data( exportState, clock )
788
789 END SUBROUTINE sst_component_run1
790
791
792
793 SUBROUTINE sst_component_run2( gcomp, importState, exportState, clock, rc )
794 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
795 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
796 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
797 INTEGER, INTENT( OUT) :: rc
798 !<DESCRIPTION>
799 ! SST component run routine, phase 2.
800 ! Get from importState, compare with file data, and error-exit
801 ! if they differ... If they are the same, then
802 ! stuff the file data into the exportState.
803 !
804 ! The arguments are:
805 ! gcomp Component
806 ! importState Importstate
807 ! exportState Exportstate
808 ! clock External clock
809 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
810 ! otherwise ESMF_FAILURE.
811 !</DESCRIPTION>
812
813 rc = ESMF_SUCCESS
814
815 ! Get from importState, compare with file data, and error_exit
816 ! if they differ...
817 !TODO: change this once WRF can load exportState after integrating
818 ! This works because WRF loads its exportState BEFORE integrating.
819 CALL wrf_clockprint ( 50, clock, 'sst_component_run2: clock before call to compare_data()' )
820 CALL compare_data( importState, clock )
821 CALL wrf_clockprint ( 50, clock, 'sst_component_run2: clock after call to compare_data()' )
822
823 END SUBROUTINE sst_component_run2
824
825
826
827 SUBROUTINE sst_component_finalize( gcomp, importState, exportState, clock, rc )
828 USE module_io
829 TYPE(ESMF_GridComp), TARGET, INTENT(INOUT) :: gcomp
830 TYPE(ESMF_State), TARGET, INTENT(INOUT) :: importState, exportState
831 TYPE(ESMF_Clock), TARGET, INTENT(INOUT) :: clock
832 INTEGER, INTENT( OUT) :: rc
833 !<DESCRIPTION>
834 ! SST component finalize routine.
835 !
836 ! The arguments are:
837 ! gcomp Component
838 ! importState Importstate
839 ! exportState Exportstate
840 ! clock External clock
841 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
842 ! otherwise ESMF_FAILURE.
843 !</DESCRIPTION>
844
845 ! Local variables
846 TYPE(ESMF_Field) :: tmp_field
847 INTEGER :: i, ierr
848
849 rc = ESMF_SUCCESS
850
851 ! destroy ESMF_Fields and other "deep" objects created by this component
852 ! note that this component relied on ESMF to allocate data pointers during
853 ! calls to ESMF_FieldCreate() so it also expects ESMF to free these pointers
854 DO i=1, datacount
855 ! destroy field in importState
856 CALL ESMF_StateGetField( importState, TRIM(datanames(i)), tmp_field, &
857 rc=rc )
858 IF (rc /= ESMF_SUCCESS) THEN
859 WRITE( str , * ) &
860 'sst_component_finalize: ESMF_StateGetField( importState,', &
861 TRIM(datanames(i)),') failed'
862 CALL wrf_error_fatal ( TRIM(str) )
863 ENDIF
864 CALL ESMF_FieldDestroy( tmp_field, rc=rc )
865 IF (rc /= ESMF_SUCCESS) THEN
866 WRITE( str , * ) &
867 'sst_component_finalize: ESMF_FieldDestroy( importState,', &
868 TRIM(datanames(i)),') failed'
869 CALL wrf_error_fatal ( TRIM(str) )
870 ENDIF
871 ! destroy field in exportState
872 CALL ESMF_StateGetField( exportState, TRIM(datanames(i)), tmp_field, &
873 rc=rc )
874 IF (rc /= ESMF_SUCCESS) THEN
875 WRITE( str , * ) &
876 'sst_component_finalize: ESMF_StateGetField( exportState,', &
877 TRIM(datanames(i)),') failed'
878 CALL wrf_error_fatal ( TRIM(str) )
879 ENDIF
880 CALL ESMF_FieldDestroy( tmp_field, rc=rc )
881 IF (rc /= ESMF_SUCCESS) THEN
882 WRITE( str , * ) &
883 'sst_component_finalize: ESMF_FieldDestroy( exportState,', &
884 TRIM(datanames(i)),') failed'
885 CALL wrf_error_fatal ( TRIM(str) )
886 ENDIF
887 ENDDO
888
889 ! deallocate space for data read from disk
890 DEALLOCATE( file_sst_data, file_landmask_data )
891
892 ! close SST data file
893 WRITE( str , FMT='(A,I8)' ) &
894 'subroutine sst_component_finalize: closing file fid=',fid
895 CALL wrf_debug ( 100, TRIM(str) )
896 CALL wrf_ioclose( fid , ierr )
897 IF ( ierr .NE. 0 ) THEN
898 CALL wrf_error_fatal ( 'sst_component_finalize: wrf_ioclose failed' )
899 ENDIF
900
901 END SUBROUTINE sst_component_finalize
902
903
904 END MODULE module_sst_component_top
905
906
907
908
909 MODULE module_sst_setservices
910 !<DESCRIPTION>
911 ! This module defines SST "Set Services" method sst_register()
912 ! used for ESMF coupling.
913 !</DESCRIPTION>
914
915 USE module_sst_component_top, ONLY: sst_component_init1, &
916 sst_component_init2, &
917 sst_component_run1, &
918 sst_component_run2, &
919 sst_component_finalize
920 USE ESMF_Mod
921
922 IMPLICIT NONE
923
924 ! everything is private by default
925 PRIVATE
926
927 ! Public entry point for ESMF_GridCompSetServices()
928 PUBLIC SST_register
929
930 ! private stuff
931 CHARACTER (ESMF_MAXSTR) :: str
932
933 CONTAINS
934
935
936 SUBROUTINE sst_register(gcomp, rc)
937 TYPE(ESMF_GridComp), INTENT(INOUT) :: gcomp
938 INTEGER, INTENT(OUT) :: rc
939 INTEGER :: finalrc
940 !
941 !<DESCRIPTION>
942 ! SST_register - Externally visible registration routine
943 !
944 ! User-supplied SetServices routine.
945 ! The Register routine sets the subroutines to be called
946 ! as the init, run, and finalize routines. Note that these are
947 ! private to the module.
948 !
949 ! The arguments are:
950 ! gcomp Component
951 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
952 ! otherwise ESMF_FAILURE.
953 !</DESCRIPTION>
954
955 finalrc = ESMF_SUCCESS
956 ! Register the callback routines.
957 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_SETINIT, &
958 sst_component_init1, 1, rc)
959 IF ( rc /= ESMF_SUCCESS) THEN
960 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_init1) failed with rc = ', rc
961 CALL wrf_error_fatal ( TRIM(str) )
962 ENDIF
963 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_SETINIT, &
964 sst_component_init2, 2, rc)
965 IF ( rc /= ESMF_SUCCESS) THEN
966 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_init2) failed with rc = ', rc
967 CALL wrf_error_fatal ( TRIM(str) )
968 ENDIF
969 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_SETRUN, &
970 sst_component_run1, 1, rc)
971 IF ( rc /= ESMF_SUCCESS) THEN
972 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_run1) failed with rc = ', rc
973 CALL wrf_error_fatal ( TRIM(str) )
974 ENDIF
975 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_SETRUN, &
976 sst_component_run2, 2, rc)
977 IF ( rc /= ESMF_SUCCESS) THEN
978 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_run2) failed with rc = ', rc
979 CALL wrf_error_fatal ( TRIM(str) )
980 ENDIF
981 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_SETFINAL, &
982 sst_component_finalize, ESMF_SINGLEPHASE, rc)
983 IF ( rc /= ESMF_SUCCESS) THEN
984 WRITE(str,*) 'ESMF_GridCompSetEntryPoint(sst_component_finalize) failed with rc = ', rc
985 CALL wrf_error_fatal ( TRIM(str) )
986 ENDIF
987
988 PRINT *,'SST: Registered Initialize, Run, and Finalize routines'
989
990 rc = finalrc
991
992 END SUBROUTINE sst_register
993
994 END MODULE module_sst_setservices
995
996
997
998 !<DESCRIPTION>
999 ! Module module_wrfsst_coupler defines the
1000 ! "WRF-SST" coupler component. It provides two-way coupling between
1001 ! the "SST" and "WRF" components.
1002 ! In its run routine it transfers data directly from the
1003 ! SST Component's export state to the WRF Component's import state.
1004 ! It also transfers data directly from the
1005 ! WRF Component's export state to the SST Component's import state.
1006 !
1007 ! This is derived from src/demo/coupled_flow/src/CouplerMod.F90
1008 ! created by Nancy Collins and others on the ESMF Core Team.
1009 !
1010 !</DESCRIPTION>
1011
1012 MODULE module_wrfsst_coupler
1013
1014 USE ESMF_Mod
1015
1016 IMPLICIT NONE
1017
1018 ! everything is private by default
1019 PRIVATE
1020
1021 ! Public entry point
1022 PUBLIC WRFSSTCpl_register
1023
1024 ! private data members
1025 ! route handles and flags
1026 TYPE(ESMF_RouteHandle), SAVE :: fromWRF_rh, fromSST_rh
1027 LOGICAL, SAVE :: fromWRF_rh_ready = .FALSE.
1028 LOGICAL, SAVE :: fromSST_rh_ready = .FALSE.
1029 ! field names
1030 INTEGER, PARAMETER :: datacount = 2
1031 INTEGER, PARAMETER :: SST_INDX = 1
1032 INTEGER, PARAMETER :: LANDMASK_INDX = 2
1033 CHARACTER(LEN=ESMF_MAXSTR), SAVE :: datanames(datacount)
1034 CHARACTER(LEN=ESMF_MAXSTR) :: str
1035
1036
1037 CONTAINS
1038
1039
1040 SUBROUTINE WRFSSTCpl_register(comp, rc)
1041 TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
1042 INTEGER, INTENT(OUT) :: rc
1043 !
1044 !<DESCRIPTION>
1045 ! WRFSSTCpl_register - Externally visible registration routine
1046 !
1047 ! User-supplied SetServices routine.
1048 ! The Register routine sets the subroutines to be called
1049 ! as the init, run, and finalize routines. Note that these are
1050 ! private to the module.
1051 !
1052 ! The arguments are:
1053 ! comp Component
1054 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1055 ! otherwise ESMF_FAILURE.
1056 !</DESCRIPTION>
1057
1058 ! guilty until proven innocent
1059 rc = ESMF_FAILURE
1060
1061 ! Register the callback routines.
1062
1063 call ESMF_CplCompSetEntryPoint(comp, ESMF_SETINIT, WRFSSTCpl_init, &
1064 ESMF_SINGLEPHASE, rc)
1065 IF ( rc /= ESMF_SUCCESS ) THEN
1066 CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_init) failed' )
1067 ENDIF
1068 call ESMF_CplCompSetEntryPoint(comp, ESMF_SETRUN, WRFSSTCpl_run, &
1069 ESMF_SINGLEPHASE, rc)
1070 IF ( rc /= ESMF_SUCCESS ) THEN
1071 CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_run) failed' )
1072 ENDIF
1073 call ESMF_CplCompSetEntryPoint(comp, ESMF_SETFINAL, WRFSSTCpl_final, &
1074 ESMF_SINGLEPHASE, rc)
1075 IF ( rc /= ESMF_SUCCESS ) THEN
1076 CALL wrf_error_fatal ( 'ESMF_CplCompSetEntryPoint(WRFSSTCpl_final) failed' )
1077 ENDIF
1078
1079 print *, "module_wrfsst_coupler: Registered Initialize, Run, and Finalize routines"
1080
1081 END SUBROUTINE WRFSSTCpl_register
1082
1083
1084 SUBROUTINE WRFSSTCpl_init(comp, importState, exportState, clock, rc)
1085 USE module_metadatautils, ONLY: AttachDecompToState, GetDecompFromState
1086 TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
1087 TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
1088 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
1089 INTEGER, INTENT(OUT) :: rc
1090 !<DESCRIPTION>
1091 ! WRF-SST coupler component init routine. This simply passes needed
1092 ! metadata from WRF to SST. Initialization of ESMF_RouteHandle objects
1093 ! is handled later via lazy evaluation.
1094 !
1095 ! The arguments are:
1096 ! comp Component
1097 ! importState Importstate
1098 ! exportState Exportstate
1099 ! clock External clock
1100 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1101 ! otherwise ESMF_FAILURE.
1102 !</DESCRIPTION>
1103
1104 ! Local variables
1105 CHARACTER(ESMF_MAXSTR) :: importstatename
1106 ! decomposition information
1107 INTEGER :: ids, ide, jds, jde, kds, kde
1108 INTEGER :: ims, ime, jms, jme, kms, kme
1109 INTEGER :: ips, ipe, jps, jpe, kps, kpe
1110 INTEGER :: domdesc
1111 LOGICAL :: bdy_mask(4)
1112
1113 PRINT *, "DEBUG: Coupler Init starting"
1114
1115 ! guilty until proven innocent
1116 rc = ESMF_FAILURE
1117
1118 CALL ESMF_StateGet(importState, name=importstatename, rc=rc)
1119 IF ( rc /= ESMF_SUCCESS ) THEN
1120 CALL wrf_error_fatal ( 'WRFSSTCpl_init: ESMF_StateGet failed' )
1121 ENDIF
1122
1123 IF ( TRIM(importstatename) .EQ. "WRF Export State" ) THEN
1124 ! get metadata from WRF export state
1125 CALL GetDecompFromState( importState, &
1126 ids, ide, jds, jde, kds, kde, &
1127 ims, ime, jms, jme, kms, kme, &
1128 ips, ipe, jps, jpe, kps, kpe, &
1129 domdesc, bdy_mask )
1130 ! put metadata from in SST import state
1131 CALL AttachDecompToState( exportState, &
1132 ids, ide, jds, jde, kds, kde, &
1133 ims, ime, jms, jme, kms, kme, &
1134 ips, ipe, jps, jpe, kps, kpe, &
1135 domdesc, bdy_mask )
1136
1137
1138 ELSE
1139 CALL wrf_error_fatal ( 'WRFSSTCpl_init: invalid importState name' )
1140 ENDIF
1141
1142 ! set up field names
1143 !TODO: use CF conventions for "standard_name" once WRF Registry supports them
1144 !TODO: datanames(SST_INDX) = "sea_surface_temperature"
1145 !TODO: datanames(LANDMASK_INDX) = "land_binary_mask"
1146 datanames(SST_INDX) = "SST"
1147 datanames(LANDMASK_INDX) = "LANDMASK"
1148
1149 PRINT *, "DEBUG: Coupler Init returning"
1150
1151 END SUBROUTINE WRFSSTCpl_init
1152
1153
1154
1155 SUBROUTINE WRFSSTCpl_run(comp, importState, exportState, clock, rc)
1156 TYPE(ESMF_CplComp), INTENT(INOUT) :: comp
1157 TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
1158 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
1159 INTEGER, INTENT(OUT) :: rc
1160 !<DESCRIPTION>
1161 ! WRF-SST coupler component run routine.
1162 !
1163 ! The arguments are:
1164 ! comp Component
1165 ! importState Importstate
1166 ! exportState Exportstate
1167 ! clock External clock
1168 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1169 ! otherwise ESMF_FAILURE.
1170 !</DESCRIPTION>
1171
1172 ! Note that comments in this code are preserved from the sample coupler
1173 ! provided by the ESMF core team.
1174
1175 ! Local variables
1176 TYPE(ESMF_Field) :: src_field, dst_field
1177 TYPE(ESMF_RouteHandle) :: routehandle
1178 TYPE(ESMF_VM) :: vm
1179 LOGICAL :: build_fromWRF_rh, build_fromSST_rh, fromWRF
1180 CHARACTER(LEN=ESMF_MAXSTR) :: importStatename
1181 CHARACTER(LEN=ESMF_MAXSTR) :: SST_exportStatename, WRF_exportStatename
1182 INTEGER :: i
1183 CHARACTER(LEN=256) :: directionString
1184
1185 WRITE(str,*) 'WRFSSTCpl_run: begin'
1186 CALL wrf_debug ( 100 , TRIM(str) )
1187
1188 ! guilty until proven innocent
1189 rc = ESMF_FAILURE
1190
1191 ! Which way is this coupling going?
1192 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGet(importState,name,...)'
1193 CALL wrf_debug ( 100 , TRIM(str) )
1194 CALL ESMF_StateGet( importState, name=importStatename, rc=rc )
1195 IF ( rc /= ESMF_SUCCESS ) THEN
1196 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGet(importState,name,...) failed' )
1197 ENDIF
1198 WRITE(str,*) 'WRFSSTCpl_run: back from ESMF_StateGet, importStatename = <',TRIM(importStatename),'>'
1199 CALL wrf_debug ( 100 , TRIM(str) )
1200
1201 ! first time through in each direction: create route handle and
1202 ! associated objects
1203 WRF_exportStatename = "WRF Export State"
1204 SST_exportStatename = "SST Export State"
1205 IF ( TRIM(importStatename) .EQ. TRIM(WRF_exportStatename) ) THEN
1206 fromWRF = .TRUE.
1207 directionString = 'WRFtoSST'
1208 ELSE IF ( TRIM(importStatename) .EQ. TRIM(SST_exportStatename) ) THEN
1209 fromWRF = .FALSE.
1210 directionString = 'SSTtoWRF'
1211 ELSE
1212 CALL wrf_error_fatal ( 'WRFSSTCpl_run: invalid importState name' )
1213 ENDIF
1214 WRITE(str,*) 'WRFSSTCpl_run: fromWRF = ',fromWRF
1215 CALL wrf_debug ( 100 , TRIM(str) )
1216 build_fromWRF_rh = fromWRF .AND. ( .NOT. fromWRF_rh_ready )
1217 build_fromSST_rh = ( .NOT. fromWRF ) .AND. ( .NOT. fromSST_rh_ready )
1218 WRITE(str,*) 'WRFSSTCpl_run: build_fromWRF_rh = ',build_fromWRF_rh
1219 CALL wrf_debug ( 100 , TRIM(str) )
1220 WRITE(str,*) 'WRFSSTCpl_run: build_fromSST_rh = ',build_fromSST_rh
1221 CALL wrf_debug ( 100 , TRIM(str) )
1222 IF ( build_fromWRF_rh .OR. build_fromSST_rh ) THEN
1223 CALL ESMF_CplCompGet( comp, vm=vm, rc=rc )
1224 IF ( rc /= ESMF_SUCCESS ) THEN
1225 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_CplCompGet failed' )
1226 ENDIF
1227 ! The use of literal index "1" here indicates that we don't care which
1228 ! ESMF_Field we get so we might as well get the first one.
1229 WRITE(str,*) 'WRFSSTCpl_run: grabbing first field <',TRIM(datanames(1)), &
1230 '> from import state'
1231 CALL wrf_debug ( 100 , TRIM(str) )
1232 CALL ESMF_StateGetField( importState, TRIM(datanames(1)), src_field, &
1233 rc=rc )
1234 IF ( rc /= ESMF_SUCCESS ) THEN
1235 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGetField(importState) failed' )
1236 ENDIF
1237 WRITE(str,*) 'WRFSSTCpl_run: grabbing first field <',TRIM(datanames(1)), &
1238 '> from export state'
1239 CALL wrf_debug ( 100 , TRIM(str) )
1240 CALL ESMF_StateGetField( exportState, TRIM(datanames(1)), dst_field, &
1241 rc=rc )
1242 IF ( rc /= ESMF_SUCCESS ) THEN
1243 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_StateGetField(exportState) failed' )
1244 ENDIF
1245 IF ( build_fromWRF_rh ) THEN
1246 WRITE(str,*) 'WRFSSTCpl_run: creating fromWRF_rh'
1247 CALL wrf_debug ( 100 , TRIM(str) )
1248 fromWRF_rh = ESMF_RouteHandleCreate( rc )
1249 IF ( rc /= ESMF_SUCCESS ) THEN
1250 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_RouteHandleCreate(fromWRF_rh) failed' )
1251 ENDIF
1252 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedistStore(fromWRF_rh)'
1253 CALL wrf_debug ( 100 , TRIM(str) )
1254 CALL ESMF_FieldRedistStore( src_field, dst_field, vm, &
1255 routehandle=fromWRF_rh, rc=rc )
1256 IF ( rc /= ESMF_SUCCESS ) THEN
1257 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedistStore(fromWRF_rh) failed' )
1258 ENDIF
1259 fromWRF_rh_ready = .TRUE.
1260 ENDIF
1261 IF ( build_fromSST_rh ) THEN
1262 WRITE(str,*) 'WRFSSTCpl_run: creating fromSST_rh'
1263 CALL wrf_debug ( 100 , TRIM(str) )
1264 fromSST_rh = ESMF_RouteHandleCreate( rc )
1265 IF ( rc /= ESMF_SUCCESS ) THEN
1266 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_RouteHandleCreate(fromSST_rh) failed' )
1267 ENDIF
1268 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedistStore(fromSST_rh)'
1269 CALL wrf_debug ( 100 , TRIM(str) )
1270 CALL ESMF_FieldRedistStore( src_field, dst_field, vm, &
1271 routehandle=fromSST_rh, rc=rc )
1272 IF ( rc /= ESMF_SUCCESS ) THEN
1273 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedistStore(fromSST_rh) failed' )
1274 ENDIF
1275 fromSST_rh_ready = .TRUE.
1276 ENDIF
1277 DO i=1, datacount
1278 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateSetNeeded(importState, ',TRIM(datanames(i)),')'
1279 CALL wrf_debug ( 100 , TRIM(str) )
1280 CALL ESMF_StateSetNeeded( importState, TRIM(datanames(i)), &
1281 ESMF_NEEDED, rc=rc )
1282 IF ( rc /= ESMF_SUCCESS ) THEN
1283 WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateSetNeeded(',TRIM(datanames(i)),') failed'
1284 CALL wrf_error_fatal ( str )
1285 ENDIF
1286 ENDDO
1287 ENDIF
1288
1289 ! In this case, the coupling is symmetric - you call redist going
1290 ! both ways - so we only care about the coupling direction in order
1291 ! to get the right routehandle selected.
1292 IF ( fromWRF ) THEN
1293 WRITE(str,*) 'WRFSSTCpl_run: routehandle = fromWRF_rh'
1294 CALL wrf_debug ( 100 , TRIM(str) )
1295 routehandle = fromWRF_rh
1296 ELSE
1297 WRITE(str,*) 'WRFSSTCpl_run: routehandle = fromSST_rh'
1298 CALL wrf_debug ( 100 , TRIM(str) )
1299 routehandle = fromSST_rh
1300 ENDIF
1301
1302 DO i=1, datacount
1303 WRITE(str,*) 'WRFSSTCpl_run: grabbing field <',TRIM(datanames(i)),'>'
1304 CALL wrf_debug ( 100 , TRIM(str) )
1305 ! check isneeded flag here
1306 IF ( .NOT. ESMF_StateIsNeeded( importState, TRIM(datanames(i)), rc=rc ) ) THEN
1307 IF ( rc /= ESMF_SUCCESS ) THEN
1308 WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateIsNeeded(',TRIM(datanames(i)),') failed'
1309 CALL wrf_error_fatal ( str )
1310 ENDIF
1311 WRITE(str,*) 'WRFSSTCpl_run: skipping field <',TRIM(datanames(i)),'>'
1312 CALL wrf_debug ( 100 , TRIM(str) )
1313 CYCLE
1314 ENDIF
1315
1316 WRITE(str,*) 'WRFSSTCpl_run: processing field <',TRIM(datanames(i)),'>'
1317 CALL wrf_debug ( 100 , TRIM(str) )
1318
1319 ! The following piece of code provides an example of calling the data
1320 ! redistribution routine between two Fields in the Coupler Component.
1321 ! Unlike regrid, which translates between
1322 ! different Grids, redist translates between different DELayouts on
1323 ! the same Grid. The first two lines get the Fields from the
1324 ! States, each corresponding to a different subcomponent. One is
1325 ! an Export State and the other is an Import State.
1326 !
1327 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGetField(importState,', &
1328 TRIM(datanames(i)),')...'
1329 CALL wrf_debug ( 100 , TRIM(str) )
1330 CALL ESMF_StateGetField( importState, TRIM(datanames(i)), src_field, &
1331 rc=rc )
1332 IF ( rc /= ESMF_SUCCESS ) THEN
1333 WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateGetField(importState,', &
1334 TRIM(datanames(i)),') failed'
1335 CALL wrf_error_fatal ( str )
1336 ENDIF
1337
1338 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_StateGetField(exportState,', &
1339 TRIM(datanames(i)),')...'
1340 CALL wrf_debug ( 100 , TRIM(str) )
1341 CALL ESMF_StateGetField( exportState, TRIM(datanames(i)), dst_field, &
1342 rc=rc )
1343 IF ( rc /= ESMF_SUCCESS ) THEN
1344 WRITE(str,*) 'WRFSSTCpl_run: ESMF_StateGetField(exportState,', &
1345 TRIM(datanames(i)),') failed'
1346 CALL wrf_error_fatal ( str )
1347 ENDIF
1348
1349 ! The redist routine uses information contained in the Fields and the
1350 ! Coupler VM object to call the communication routines to move the data.
1351 ! Because many Fields may share the same Grid association, the same
1352 ! routing information may be needed repeatedly. Route information is
1353 ! saved so the precomputed information can be retained. The following
1354 ! is an example of a Field redist call:
1355 WRITE(str,*) 'WRFSSTCpl_run: calling ESMF_FieldRedist for <', &
1356 TRIM(datanames(i)),'>...'
1357 CALL wrf_debug ( 100 , TRIM(str) )
1358 CALL ESMF_FieldRedist( src_field, dst_field, routehandle, rc=rc )
1359 IF ( rc /= ESMF_SUCCESS ) THEN
1360 CALL wrf_error_fatal ( 'WRFSSTCpl_run: ESMF_FieldRedist failed' )
1361 ENDIF
1362 WRITE(str,*) 'WRFSSTCpl_run: back from ESMF_FieldRedist for <', &
1363 TRIM(datanames(i)),'>...'
1364 CALL wrf_debug ( 100 , TRIM(str) )
1365
1366 ENDDO
1367
1368 WRITE(str,*) 'WRFSSTCpl_run: end'
1369 CALL wrf_debug ( 100 , TRIM(str) )
1370
1371 END SUBROUTINE WRFSSTCpl_run
1372
1373
1374
1375 SUBROUTINE WRFSSTCpl_final(comp, importState, exportState, clock, rc)
1376 TYPE(ESMF_CplComp) :: comp
1377 TYPE(ESMF_State), INTENT(INOUT) :: importState, exportState
1378 TYPE(ESMF_Clock), INTENT(INOUT) :: clock
1379 INTEGER, INTENT(OUT) :: rc
1380 !<DESCRIPTION>
1381 ! WRF-SST coupler component finalize routine.
1382 !
1383 ! The arguments are:
1384 ! comp Component
1385 ! importState Importstate
1386 ! exportState Exportstate
1387 ! clock External clock
1388 ! rc Return code; equals ESMF_SUCCESS if there are no errors,
1389 ! otherwise ESMF_FAILURE.
1390 !</DESCRIPTION>
1391
1392 PRINT *, "DEBUG: Coupler Final starting"
1393
1394 ! guilty until proven innocent
1395 rc = ESMF_FAILURE
1396
1397 ! Only thing to do here is release redist and route handles
1398 IF ( fromWRF_rh_ready ) THEN
1399 CALL ESMF_FieldRedistRelease(fromWRF_rh, rc)
1400 IF ( rc /= ESMF_SUCCESS ) THEN
1401 CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_FieldRedistRelease(fromWRF_rh) failed' )
1402 ENDIF
1403 CALL ESMF_RouteHandleDestroy(fromWRF_rh, rc)
1404 IF ( rc /= ESMF_SUCCESS ) THEN
1405 CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_RouteHandleDestroy(fromWRF_rh) failed' )
1406 ENDIF
1407 ENDIF
1408 IF ( fromSST_rh_ready ) THEN
1409 CALL ESMF_FieldRedistRelease(fromSST_rh, rc)
1410 IF ( rc /= ESMF_SUCCESS ) THEN
1411 CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_FieldRedistRelease(fromSST_rh) failed' )
1412 ENDIF
1413 CALL ESMF_RouteHandleDestroy(fromSST_rh, rc)
1414 IF ( rc /= ESMF_SUCCESS ) THEN
1415 CALL wrf_error_fatal ( 'WRFSSTCpl_final: ESMF_RouteHandleDestroy(fromSST_rh) failed' )
1416 ENDIF
1417 ENDIF
1418
1419 PRINT *, "DEBUG: Coupler Final returning"
1420
1421 END SUBROUTINE WRFSSTCpl_final
1422
1423
1424 END MODULE module_wrfsst_coupler
1425
1426
1427
1428
1429 PROGRAM wrf_SST_ESMF
1430
1431 !<DESCRIPTION>
1432 ! ESMF Application Wrapper for coupling WRF with a "dummy" component
1433 ! that simply reads SSTs from a file and sends them to WRF (one-way
1434 ! coupling). Fields are returned from WRF to SST via the coupler for
1435 ! self-test only.
1436 !
1437 ! Note that, like other WRF coupling methods (MCEL, MCT), ESMF coupling is
1438 ! supported only via auxiliary input and history streams.
1439 !
1440 ! This is the main program that creates the ESMF Gridded and Coupler
1441 ! Component.
1442 !
1443 ! "init" looks like this:
1444 ! 1. Init phase 1 for WRF, sets WRF exportState metadata for "time"
1445 ! and "domain" information needed by WRF IOAPI (which is called from
1446 ! the SST component). It also sets up all WRF and WSF modules. Note
1447 ! that this must be called before SST phase-1 init because SST uses
1448 ! WRF IOAPI.
1449 ! 2. Init phase 1 for SST, sets "time" metadata in SST exportState.
1450 ! 3. Initialize coupler, passing decomposition metadata from WRF exportState
1451 ! to SST importState.
1452 ! 4. Resolve any "time" metadata inconsistencies and create top-level clock.
1453 ! 5. Init phase 2 for SST, gets "domain" information from importState,
1454 ! creates an ESMF_Grid based on "domain" information using the exact same
1455 ! method as WRF (so WRF IOAPI calls will work), and sets up SST
1456 ! importState and exportState.
1457 ! 6. Init phase 2 for WRF, runs up to the end of the head_grid I/O "training"
1458 ! phase (done in med_before_solve_io()). This initializes WRF
1459 ! importState and exportState prior to the first coupling step during the
1460 ! "run" loop. Note that this only works for head_grid at present because
1461 ! recursion in WRF traversal of subdomains is not dealt with yet and
1462 ! because the code that populates the WRF importState and exportState is
1463 ! not yet sophisticated enough to handle creating and destroying nested
1464 ! domains at any time during the model run.
1465 !TODO: ESMF auxio must begin at the start of the run. Remove this
1466 !TODO: restriction later, if needed.
1467 !
1468 !TODO: Note that coupling is currently limited to one auxin plus one auxout
1469 !TODO: streams. Extension to multiple pairs of auxio streams requires
1470 !TODO: nested states (one for each auxio stream pair).
1471 !TODO: For now, only support one input and/or one output stream via
1472 !TODO: io_esmf. This condition is asserted in
1473 !TODO: ext_esmf_open_for_read_begin() and
1474 !TODO: ext_esmf_open_for_write_begin().
1475 !
1476 ! "run" loop looks like this:
1477 ! 1. Run SST phase 1, reads SST from file and writes it to SST exportState
1478 ! for coupling to WRF.
1479 ! 2. Couple SST exportState -> WRF importState. First iteration: set up
1480 ! SST->WRF routeHandle via lazy evaluation.
1481 ! 3. Run WRF. First iteration: head_grid resumes after I/O "training"
1482 ! phase. Other iterations and domains: run normally.
1483 ! Read WRF importState and write WRF exportState (via med_before_solve_io()).
1484 ! Note that WRF assigns sst -> tsk for sea points in
1485 ! share/module_soil_pre.F.
1486 ! 4. Couple WRF exportState -> SST importState. First iteration: set up
1487 ! WRF->SST routeHandle via lazy evaluation.
1488 ! 5. Run SST phase 2, compare SST from file with SST from WRF (via
1489 ! SST importState) and error-exit if they differ.
1490 ! 6. Advance clock and goto step 1
1491 !
1492 ! "finalize" is trivial, except for destruction of ESMF objects which is
1493 ! quite non-trivial at the moment.
1494 !
1495 !</DESCRIPTION>
1496
1497 ! WRF registration routine
1498 USE module_wrf_setservices, ONLY: WRF_register
1499 ! SST registration routine
1500 USE module_sst_setservices, ONLY: SST_register
1501 ! WRF-SST coupler registration routine
1502 USE module_wrfsst_coupler, ONLY: WRFSSTCpl_register
1503 ! ESMF module, defines all ESMF data types and procedures
1504 USE ESMF_Mod
1505 ! Not-yet-implemented ESMF features
1506 USE module_esmf_extensions
1507 ! Component-independent utilities
1508 USE module_metadatautils, ONLY: GetTimesFromStates
1509
1510 IMPLICIT NONE
1511
1512 ! Local variables
1513
1514 ! Components
1515 TYPE(ESMF_GridComp) :: compGriddedWRF ! WRF
1516 TYPE(ESMF_GridComp) :: compGriddedSST ! SST reader
1517 TYPE(ESMF_CplComp) :: compCplWRFSST ! WRF-SST coupler
1518
1519 ! State, Virtual Machine, and DELayout
1520 TYPE(ESMF_VM) :: vm
1521 TYPE(ESMF_State) :: importStateWRF, exportStateWRF
1522 TYPE(ESMF_State) :: importStateSST, exportStateSST
1523
1524 ! A clock, some times, and a time step
1525 TYPE(ESMF_Clock) :: driverClock
1526 TYPE(ESMF_Time) :: startTime
1527 TYPE(ESMF_Time) :: stopTime
1528 TYPE(ESMF_TimeInterval) :: couplingInterval
1529
1530 ! other misc stuff
1531 TYPE(ESMF_State) :: tmpState
1532 INTEGER :: timestepdebug
1533
1534 ! Return codes for error checks
1535 INTEGER :: rc
1536 CHARACTER (ESMF_MAXSTR) :: str
1537
1538 ! debugging
1539 CHARACTER(LEN=256) :: couplingIntervalString
1540
1541
1542 ! Warn users that this is not yet ready for general use.
1543 PRINT *, ' W A R N I N G '
1544 PRINT *, ' ESMF COUPLING CAPABILITY IS EXPERIMENTAL AND UNSUPPORTED '
1545 PRINT *, ' IN THIS VERSION OF WRF-CPL-SST '
1546 PRINT *, ' U S E A T Y O U R O W N R I S K '
1547
1548 ! Initialize ESMF, get the default Global VM, and set
1549 ! the default calendar to be Gregorian.
1550 CALL ESMF_Initialize( vm=vm, defaultCalendar=ESMF_CAL_GREGORIAN, rc=rc )
1551 IF ( rc /= ESMF_SUCCESS ) THEN
1552 PRINT *, 'wrf_SST_ESMF: ESMF_Initialize failed'
1553 ENDIF
1554 ! Note: wrf_debug and wrf_error_fatal are not initialized yet
1555 PRINT *, 'DEBUG wrf_SST_ESMF: returned from ESMF_Initialize'
1556 CALL ESMF_SetInitialized() ! eliminate this once ESMF does it internally
1557
1558 ! Create the WRF Gridded Component, passing in the default VM.
1559 compGriddedWRF = ESMF_GridCompCreate(vm, "WRF Model", rc=rc)
1560 IF ( rc /= ESMF_SUCCESS ) THEN
1561 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompCreate(WRF Model) failed'
1562 ENDIF
1563
1564 ! Create the SST Gridded Component, passing in the default VM.
1565 compGriddedSST = ESMF_GridCompCreate(vm, "SST Dummy Model", rc=rc)
1566 IF ( rc /= ESMF_SUCCESS ) THEN
1567 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompCreate(WRF Dummy Model) failed'
1568 ENDIF
1569
1570 ! Create the WRF-SST Coupler Component, passing in the default VM.
1571 compCplWRFSST = ESMF_CplCompCreate(vm, "WRF-SST Coupler", rc=rc)
1572 IF ( rc /= ESMF_SUCCESS ) THEN
1573 PRINT *, 'wrf_SST_ESMF: ESMF_CplCompCreate failed'
1574 ENDIF
1575
1576 ! Create empty import and export states for WRF
1577 importStateWRF = ESMF_StateCreate("WRF Import State", statetype=ESMF_STATE_IMPORT, rc=rc)
1578 IF ( rc /= ESMF_SUCCESS ) THEN
1579 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(WRF Import State) failed'
1580 ENDIF
1581 exportStateWRF = ESMF_StateCreate("WRF Export State", statetype=ESMF_STATE_EXPORT, rc=rc)
1582 IF ( rc /= ESMF_SUCCESS ) THEN
1583 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(WRF Export State) failed'
1584 ENDIF
1585
1586 ! Create empty import and export states for SST
1587 importStateSST = ESMF_StateCreate("SST Import State", statetype=ESMF_STATE_IMPORT, rc=rc)
1588 IF ( rc /= ESMF_SUCCESS ) THEN
1589 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(SST Import State) failed'
1590 ENDIF
1591 exportStateSST = ESMF_StateCreate("SST Export State", statetype=ESMF_STATE_EXPORT, rc=rc)
1592 IF ( rc /= ESMF_SUCCESS ) THEN
1593 PRINT *, 'wrf_SST_ESMF: ESMF_StateCreate(SST Export State) failed'
1594 ENDIF
1595
1596 ! Register the WRF Gridded Component
1597 CALL ESMF_GridCompSetServices(compGriddedWRF, WRF_register, rc)
1598 IF ( rc /= ESMF_SUCCESS ) THEN
1599 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompSetServices(compGriddedWRF) failed'
1600 ENDIF
1601
1602 ! Register the SST Gridded Component
1603 CALL ESMF_GridCompSetServices(compGriddedSST, SST_register, rc)
1604 IF ( rc /= ESMF_SUCCESS ) THEN
1605 PRINT *, 'wrf_SST_ESMF: ESMF_GridCompSetServices(compGriddedSST) failed'
1606 ENDIF
1607
1608 ! Register the WRF-SST Coupler Component
1609 CALL ESMF_CplCompSetServices(compCplWRFSST, WRFSSTCpl_register, rc)
1610 IF ( rc /= ESMF_SUCCESS ) THEN
1611 PRINT *, 'wrf_SST_ESMF: ESMF_CplCompSetServices failed'
1612 ENDIF
1613
1614 ! Create top-level clock. There is no way to create an "empty" clock, so
1615 ! stuff in bogus values for start time, stop time, and time step and fix
1616 ! them after gridded component "init" phases return.
1617 CALL ESMF_TimeSet(startTime, yy=2000, mm=1, dd=1, &
1618 h=0, m=0, s=0, rc=rc)
1619 IF ( rc /= ESMF_SUCCESS ) THEN
1620 PRINT *, 'wrf_SST_ESMF: ESMF_TimeSet(startTime) failed'
1621 ENDIF
1622 CALL ESMF_TimeSet(stopTime, yy=2000, mm=1, dd=1, &
1623 h=12, m=0, s=0, rc=rc)
1624 IF ( rc /= ESMF_SUCCESS ) THEN
1625 PRINT *, 'wrf_SST_ESMF: ESMF_TimeSet(stopTime) failed'
1626 ENDIF
1627 CALL ESMF_TimeIntervalSet(couplingInterval, s=2, rc=rc)
1628 IF ( rc /= ESMF_SUCCESS ) THEN
1629 PRINT *, 'wrf_SST_ESMF: ESMF_TimeIntervalSet failed'
1630 ENDIF
1631 driverClock = ESMF_ClockCreate(timeStep=couplingInterval, &
1632 startTime=startTime, &
1633 stopTime=stopTime, rc=rc)
1634 IF ( rc /= ESMF_SUCCESS ) THEN
1635 PRINT *, 'wrf_SST_ESMF: ESMF_ClockCreate failed'
1636 ENDIF
1637
1638 ! Init, Run, and Finalize section
1639
1640 ! Init...
1641 ! initialize WRF, phase 1
1642 ! Phase 1 init returns WRF time and decomposition information as
1643 ! exportState metadata.
1644 PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 WRF init (wrf_component_init1)'
1645 CALL ESMF_GridCompInitialize(compGriddedWRF, importStateWRF, &
1646 exportStateWRF, driverClock, phase=1, rc=rc)
1647 ! Note: wrf_debug and wrf_error_fatal are now initialized
1648 IF ( rc /= ESMF_SUCCESS ) THEN
1649 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(WRF phase 1) failed' )
1650 ENDIF
1651
1652 ! initialize SST, phase 1
1653 ! Phase 1 init returns SST time information as
1654 ! exportState metadata.
1655 PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 SST init (sst_component_init1)'
1656 CALL ESMF_GridCompInitialize(compGriddedSST, importStateSST, &
1657 exportStateSST, driverClock, phase=1, rc=rc)
1658 IF ( rc /= ESMF_SUCCESS ) THEN
1659 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(SST phase 1) failed' )
1660 ENDIF
1661
1662 ! Reconcile clock settings from WRF and SST components to set up
1663 ! top-level clock. These are passed back from each "init" as attributes
1664 ! on exportState*.
1665 ! Stuff both States into a single State to pass into GetTimesFromStates()
1666 ! which is smart enough to deal with a Composite.
1667 PRINT *, 'DEBUG wrf_SST_ESMF: reconciling clock from WRF and SST components'
1668 tmpState = ESMF_StateCreate( rc=rc )
1669 IF ( rc /= ESMF_SUCCESS ) THEN
1670 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateCreate(tmpState) failed' )
1671 ENDIF
1672 CALL ESMF_StateAddState( tmpState, exportStateWRF, rc )
1673 IF ( rc /= ESMF_SUCCESS ) THEN
1674 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateAddState(exportStateWRF) failed' )
1675 ENDIF
1676 CALL ESMF_StateAddState( tmpState, exportStateSST, rc )
1677 IF ( rc /= ESMF_SUCCESS ) THEN
1678 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateAddState(exportStateSST) failed' )
1679 ENDIF
1680 CALL GetTimesFromStates( tmpState, startTime, stopTime, couplingInterval )
1681 CALL ESMF_TimeIntervalGet( couplingInterval, TimeString=couplingIntervalString, &
1682 rc=rc )
1683 IF ( rc /= ESMF_SUCCESS ) THEN
1684 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_TimeIntervalGet failed' )
1685 ENDIF
1686 CALL wrf_debug( 100, 'wrf_SST_ESMF: couplingInterval = '//TRIM(couplingIntervalString) )
1687 CALL ESMF_StateDestroy( tmpState, rc )
1688 IF ( rc /= ESMF_SUCCESS ) THEN
1689 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(tmpState) failed' )
1690 ENDIF
1691 ! update driver clock
1692 CALL ESMF_ClockDestroy(driverClock, rc)
1693 IF ( rc /= ESMF_SUCCESS ) THEN
1694 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockDestroy failed' )
1695 ENDIF
1696 driverClock = ESMF_ClockCreate(timeStep=couplingInterval, &
1697 startTime=startTime, &
1698 stopTime=stopTime, rc=rc)
1699 IF ( rc /= ESMF_SUCCESS ) THEN
1700 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockCreate(driverClock) failed' )
1701 ENDIF
1702 PRINT *, 'DEBUG wrf_SST_ESMF: done reconciling clock from WRF and SST components'
1703 CALL wrf_clockprint(50, driverClock, &
1704 'DEBUG wrf_SST_ESMF: driverClock after creation,')
1705
1706 ! initialize WRF-SST Coupler
1707 PRINT *, 'DEBUG wrf_SST_ESMF: calling phase-1 CPL init (WRFSSTCpl_init)'
1708 CALL ESMF_CplCompInitialize(compCplWRFSST, exportStateWRF, &
1709 importStateSST, driverClock, rc=rc)
1710 IF ( rc /= ESMF_SUCCESS ) THEN
1711 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompInitialize(WRF -> SST) failed' )
1712 ENDIF
1713
1714 ! TBH: this bit is not needed, but would be in general
1715 ! CALL ESMF_CplCompInitialize(compCplWRFSST, exportStateSST, &
1716 ! importStateWRF, driverClock, rc=rc)
1717 ! IF ( rc /= ESMF_SUCCESS ) THEN
1718 ! CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompInitialize(SST -> WRF) failed' )
1719 ! ENDIF
1720
1721 ! initialize SST, phase 2
1722 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 init for SST (sst_component_init2)'
1723 CALL wrf_debug ( 100 , TRIM(str) )
1724 CALL ESMF_GridCompInitialize(compGriddedSST, importStateSST, &
1725 exportStateSST, driverClock, phase=2, rc=rc)
1726 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 init for SST'
1727 CALL wrf_debug ( 100 , TRIM(str) )
1728 IF ( rc /= ESMF_SUCCESS ) THEN
1729 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(SST phase 2) failed' )
1730 ENDIF
1731
1732 ! initialize WRF, phase 2
1733 ! Phase 2 init sets up WRF importState and exportState.
1734 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 init for WRF (wrf_component_init2)'
1735 CALL wrf_debug ( 100 , TRIM(str) )
1736 CALL ESMF_GridCompInitialize(compGriddedWRF, importStateWRF, &
1737 exportStateWRF, driverClock, phase=2, rc=rc)
1738 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 init for WRF'
1739 CALL wrf_debug ( 100 , TRIM(str) )
1740 IF ( rc /= ESMF_SUCCESS ) THEN
1741 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompInitialize(WRF phase 2) failed' )
1742 ENDIF
1743
1744 CALL wrf_clockprint(50, driverClock, &
1745 'DEBUG wrf_SST_ESMF: driverClock before main time-stepping loop,')
1746 ! Run...
1747 ! main time-stepping loop
1748 timestepdebug = 0
1749 DO WHILE ( .NOT. ESMF_ClockIsStopTime(driverClock, rc) )
1750
1751 timestepdebug = timestepdebug + 1
1752 WRITE(str,'(A,I8)') 'PROGRAM wrf_SST_ESMF: Top of time-stepping loop, timestepdebug = ',timestepdebug
1753 CALL wrf_debug ( 100 , TRIM(str) )
1754 CALL wrf_clockprint(50, driverClock, &
1755 'DEBUG wrf_SST_ESMF: driverClock at top of time-stepping loop,')
1756
1757 ! Run SST phase 1
1758 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-1 run for SST (sst_component_run1)'
1759 CALL wrf_debug ( 100 , TRIM(str) )
1760 CALL ESMF_GridCompRun(compGriddedSST, importStateSST, exportStateSST, &
1761 driverClock, phase=1, rc=rc)
1762 IF ( rc /= ESMF_SUCCESS ) THEN
1763 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(SST phase 1) failed' )
1764 ENDIF
1765 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-1 run for SST (sst_component_run1)'
1766 CALL wrf_debug ( 100 , TRIM(str) )
1767
1768 ! couple SST export -> WRF import
1769 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for CPL SST->WRF (WRFSSTCpl_run)'
1770 CALL wrf_debug ( 100 , TRIM(str) )
1771 CALL ESMF_CplCompRun(compCplWRFSST, exportStateSST, &
1772 importStateWRF, driverClock, rc=rc)
1773 IF ( rc /= ESMF_SUCCESS ) THEN
1774 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompRun(SST -> WRF) failed' )
1775 ENDIF
1776 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for CPL SST->WRF (WRFSSTCpl_run)'
1777 CALL wrf_debug ( 100 , TRIM(str) )
1778
1779 ! Run WRF
1780 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for WRF (wrf_component_run)'
1781 CALL wrf_debug ( 100 , TRIM(str) )
1782 CALL ESMF_GridCompRun(compGriddedWRF, importStateWRF, exportStateWRF, &
1783 driverClock, rc=rc)
1784 IF ( rc /= ESMF_SUCCESS ) THEN
1785 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(WRF) failed' )
1786 ENDIF
1787 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for WRF (wrf_component_run)'
1788 CALL wrf_debug ( 100 , TRIM(str) )
1789
1790 ! couple WRF export -> SST import
1791 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling run for CPL WRF->SST (WRFSSTCpl_run)'
1792 CALL wrf_debug ( 100 , TRIM(str) )
1793 CALL ESMF_CplCompRun(compCplWRFSST, exportStateWRF, &
1794 importStateSST, driverClock, rc=rc)
1795 IF ( rc /= ESMF_SUCCESS ) THEN
1796 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompRun(WRF -> SST) failed' )
1797 ENDIF
1798 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from run for CPL WRF->SST (WRFSSTCpl_run)'
1799 CALL wrf_debug ( 100 , TRIM(str) )
1800
1801 ! Run SST phase 2
1802 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: Calling phase-2 run for SST (sst_component_run2)'
1803 CALL wrf_debug ( 100 , TRIM(str) )
1804 CALL ESMF_GridCompRun(compGriddedSST, importStateSST, exportStateSST, &
1805 driverClock, phase=2, rc=rc)
1806 IF ( rc /= ESMF_SUCCESS ) THEN
1807 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompRun(SST phase 2) failed' )
1808 ENDIF
1809 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: back from phase-2 run for SST (sst_component_run2)'
1810 CALL wrf_debug ( 100 , TRIM(str) )
1811
1812 ! advance clock to next coupling time step
1813 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: advancing clock'
1814 CALL wrf_debug ( 100 , TRIM(str) )
1815 CALL ESMF_ClockAdvance( driverClock, rc=rc )
1816 IF ( rc /= ESMF_SUCCESS ) THEN
1817 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockAdvance failed' )
1818 ENDIF
1819 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: done advancing clock'
1820 CALL wrf_debug ( 100 , TRIM(str) )
1821
1822 CALL wrf_clockprint(50, driverClock, &
1823 'DEBUG wrf_SST_ESMF: driverClock at end of time-stepping loop,')
1824
1825 ENDDO
1826
1827 WRITE(str,'(A)') 'PROGRAM wrf_SST_ESMF: done with time-stepping loop'
1828 CALL wrf_debug ( 100 , TRIM(str) )
1829
1830 ! clean up SST
1831 CALL ESMF_GridCompFinalize(compGriddedSST, importStateSST, exportStateSST, &
1832 driverClock, rc=rc)
1833 IF ( rc /= ESMF_SUCCESS ) THEN
1834 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompFinalize(compGriddedSST) failed' )
1835 ENDIF
1836
1837 ! clean up compCplWRFSST
1838 CALL ESMF_CplCompFinalize( compCplWRFSST, exportStateWRF, importStateSST, &
1839 driverClock, rc=rc)
1840 IF ( rc /= ESMF_SUCCESS ) THEN
1841 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_CplCompFinalize(compCplWRFSST) failed' )
1842 ENDIF
1843
1844 ! clean up WRF
1845 ! must do this AFTER clean up of SST since SST uses WRF IOAPI
1846 CALL ESMF_GridCompFinalize(compGriddedWRF, importStateWRF, exportStateWRF, &
1847 driverClock, rc=rc)
1848 IF ( rc /= ESMF_SUCCESS ) THEN
1849 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompFinalize(compGriddedWRF) failed' )
1850 ENDIF
1851
1852 ! Clean up
1853
1854 CALL ESMF_GridCompDestroy(compGriddedWRF, rc)
1855 IF ( rc /= ESMF_SUCCESS ) THEN
1856 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_GridCompDestroy(compGriddedWRF) failed' )
1857 ENDIF
1858 CALL ESMF_StateDestroy(importStateWRF, rc)
1859 IF ( rc /= ESMF_SUCCESS ) THEN
1860 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(importStateWRF) failed' )
1861 ENDIF
1862 CALL ESMF_StateDestroy(exportStateWRF, rc)
1863 IF ( rc /= ESMF_SUCCESS ) THEN
1864 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(exportStateWRF) failed' )
1865 ENDIF
1866 CALL ESMF_StateDestroy(importStateSST, rc)
1867 IF ( rc /= ESMF_SUCCESS ) THEN
1868 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(importStateSST) failed' )
1869 ENDIF
1870 CALL ESMF_StateDestroy(exportStateSST, rc)
1871 IF ( rc /= ESMF_SUCCESS ) THEN
1872 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_StateDestroy(exportStateSST) failed' )
1873 ENDIF
1874 CALL ESMF_ClockDestroy(driverClock, rc)
1875 IF ( rc /= ESMF_SUCCESS ) THEN
1876 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_ClockDestroy(driverClock) failed' )
1877 ENDIF
1878
1879 CALL ESMF_Finalize( rc=rc )
1880 IF ( rc /= ESMF_SUCCESS ) THEN
1881 CALL wrf_error_fatal ( 'wrf_SST_ESMF: ESMF_Finalize failed' )
1882 ENDIF
1883
1884 END PROGRAM wrf_SST_ESMF
1885
1886