8 ! WRF-specific package-independent interface to package-dependent WRF-specific
11 ! These routines have the same names as those specified in the WRF I/O API
13 ! - Routines defined in this file and called by users of this module have
15 ! - Routines defined in the I/O packages and called from routines in this
16 ! file have the "ext_" prefix.
17 ! - Routines called from routines in this file to initiate communication
18 ! with I/O quilt servers have the "wrf_quilt_" prefix.
20 ! See http://www.mmm.ucar.edu/wrf/WG2/software_2.0/IOAPI.doc for the latest
21 ! version of the WRF I/O API. This document includes detailed descriptions
22 ! of subroutines and their arguments that are not duplicated in this file.
24 ! We wish to be able to link to different packages depending on whether
25 ! the I/O is restart, initial, history, or boundary.
31 LOGICAL :: is_inited = .FALSE.
32 INTEGER, PARAMETER, PRIVATE :: MAX_WRF_IO_HANDLE = 1000
33 INTEGER :: wrf_io_handles(MAX_WRF_IO_HANDLE), how_opened(MAX_WRF_IO_HANDLE)
34 LOGICAL :: for_output(MAX_WRF_IO_HANDLE), first_operation(MAX_WRF_IO_HANDLE)
36 LOGICAL, PRIVATE :: bdy_dist_flag = .TRUE. ! false is old style undecomposed boundary data structs,
37 ! true is new style decomposed boundary data structs
38 ! are_bdys_distributed, bdys_are_distributed and
39 ! bdys_not_distributed routines access this flag
40 CHARACTER*256 extradims
45 ! include the file generated from md_calls.m4 using the m4 preprocessor
46 ! note that this file also includes the CONTAINS declaration for the module
50 #include "md_calls.inc"
52 !--- registry-generated routine that gets the io format being used for a dataset
54 INTEGER FUNCTION io_form_for_dataset ( DataSet )
56 CHARACTER*(*), INTENT(IN) :: DataSet
58 #include "io_form_for_dataset.inc"
59 io_form_for_dataset = io_form
61 END FUNCTION io_form_for_dataset
65 SUBROUTINE wrf_ioinit( Status )
68 ! Initialize the WRF I/O system.
72 INTEGER, INTENT(INOUT) :: Status
74 CHARACTER(len=80) :: SysDepInfo
75 INTEGER :: ierr(10), minerr, maxerr
80 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_ioinit' )
81 CALL init_io_handles ! defined below
83 CALL ext_ncd_ioinit( SysDepInfo, ierr(1) )
86 CALL ext_int_ioinit( SysDepInfo, ierr(2) )
89 CALL ext_phdf5_ioinit( SysDepInfo, ierr(3) )
92 CALL ext_pnc_ioinit( SysDepInfo, ierr(3) )
95 CALL ext_mcel_ioinit( SysDepInfo, ierr(4) )
98 CALL ext_xxx_ioinit( SysDepInfo, ierr(5) )
101 CALL ext_yyy_ioinit( SysDepInfo, ierr(6) )
104 CALL ext_zzz_ioinit( SysDepInfo, ierr(7) )
107 CALL ext_esmf_ioinit( SysDepInfo, ierr(8) )
110 CALL ext_gr1_ioinit( SysDepInfo, ierr(9) )
113 CALL ext_gr2_ioinit( SysDepInfo, ierr(10) )
115 minerr = MINVAL(ierr)
116 maxerr = MAXVAL(ierr)
117 IF ( minerr < 0 ) THEN
119 ELSE IF ( maxerr > 0 ) THEN
124 END SUBROUTINE wrf_ioinit
128 SUBROUTINE wrf_ioexit( Status )
131 ! Shut down the WRF I/O system.
135 INTEGER, INTENT(INOUT) :: Status
137 LOGICAL, EXTERNAL :: use_output_servers
138 INTEGER :: ierr(11), minerr, maxerr
142 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_ioexit' )
144 CALL ext_ncd_ioexit( ierr(1) )
147 CALL ext_int_ioexit( ierr(2) )
150 CALL ext_phdf5_ioexit(ierr(3) )
153 CALL ext_pnc_ioexit(ierr(3) )
156 CALL ext_mcel_ioexit( ierr(4) )
159 CALL ext_xxx_ioexit( ierr(5) )
162 CALL ext_yyy_ioexit( ierr(6) )
165 CALL ext_zzz_ioexit( ierr(7) )
168 CALL ext_esmf_ioexit( ierr(8) )
171 CALL ext_gr1_ioexit( ierr(9) )
174 CALL ext_gr2_ioexit( ierr(10) )
177 IF ( use_output_servers() ) CALL wrf_quilt_ioexit( ierr(11) )
178 minerr = MINVAL(ierr)
179 maxerr = MAXVAL(ierr)
180 IF ( minerr < 0 ) THEN
182 ELSE IF ( maxerr > 0 ) THEN
187 END SUBROUTINE wrf_ioexit
189 !--- open_for_write_begin
191 SUBROUTINE wrf_open_for_write_begin( FileName , Comm_compute, Comm_io, SysDepInfo, &
192 DataHandle , Status )
195 ! Begin data definition ("training") phase for writing to WRF dataset
199 USE module_state_description
201 #include "wrf_io_flags.h"
202 CHARACTER*(*) :: FileName
203 INTEGER , INTENT(IN) :: Comm_compute , Comm_io
204 CHARACTER*(*), INTENT(INOUT):: SysDepInfo
205 INTEGER , INTENT(OUT) :: DataHandle
206 INTEGER , INTENT(OUT) :: Status
208 CHARACTER*128 :: DataSet
211 INTEGER, EXTERNAL :: use_package
212 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
213 CHARACTER*128 :: LocFilename ! for appending the process ID if necessary
215 CHARACTER*128 :: mess
216 CHARACTER*1028 :: tstr
218 WRITE(mess,*) 'module_io.F: in wrf_open_for_write_begin, FileName = ',TRIM(FileName)
219 CALL wrf_debug( DEBUG_LVL, mess )
221 CALL get_value_from_pairs ( "DATASET" , SysDepInfo , DataSet )
223 io_form = io_form_for_dataset( DataSet )
227 IF ( multi_files( io_form ) .OR. .NOT. use_output_servers() ) THEN
228 SELECT CASE ( use_package(io_form) )
231 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
232 IF ( multi_files(io_form) ) THEN
233 CALL wrf_get_myproc ( myproc )
234 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
236 LocFilename = FileName
238 CALL ext_ncd_open_for_write_begin ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
241 IF ( .NOT. multi_files(io_form) ) THEN
242 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
243 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
248 CALL ext_phdf5_open_for_write_begin( FileName, Comm_compute, Comm_io, SysDepInfo, &
253 CALL ext_pnc_open_for_write_begin( FileName, Comm_compute, Comm_io, SysDepInfo, &
258 CALL ext_xxx_open_for_write_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
263 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
264 IF ( multi_files(io_form) ) THEN
265 CALL wrf_get_myproc ( myproc )
266 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
268 LocFilename = FileName
270 CALL ext_yyy_open_for_write_begin ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
273 IF ( .NOT. multi_files(io_form) ) THEN
274 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
275 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
280 CALL ext_zzz_open_for_write_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
285 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
286 IF ( multi_files(io_form) ) THEN
287 CALL wrf_get_myproc ( myproc )
288 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
290 LocFilename = FileName
292 CALL ext_gr1_open_for_write_begin ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
295 IF ( .NOT. multi_files(io_form) ) THEN
296 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
297 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
302 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
303 IF ( multi_files(io_form) ) THEN
304 CALL wrf_get_myproc ( myproc )
305 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
307 LocFilename = FileName
309 CALL ext_gr2_open_for_write_begin ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
312 IF ( .NOT. multi_files(io_form) ) THEN
313 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
314 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
319 IF ( wrf_dm_on_monitor() ) THEN
320 tstr = TRIM(SysDepInfo) // ',' // 'LAT_R=XLAT,LON_R=XLONG,LANDMASK_I=LU_MASK'
321 CALL ext_mcel_open_for_write_begin ( FileName , Comm_compute, Comm_io, tstr, &
324 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
325 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
329 CALL ext_esmf_open_for_write_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
334 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
335 IF ( multi_files(io_form) ) THEN
336 CALL wrf_get_myproc ( myproc )
337 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
339 LocFilename = FileName
341 CALL ext_int_open_for_write_begin ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
344 IF ( .NOT. multi_files(io_form) ) THEN
345 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
346 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
350 IF ( io_form .NE. 0 ) THEN
351 WRITE(mess,*)'Tried to open ',FileName,' writing: no valid io_form (',io_form,')'
352 CALL wrf_debug(1, mess)
353 Status = WRF_FILE_NOT_OPENED
356 ELSE IF ( use_output_servers() ) THEN
357 IF ( io_form .GT. 0 ) THEN
358 CALL wrf_quilt_open_for_write_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
359 Hndl , io_form, Status )
364 CALL add_new_handle( Hndl, io_form, .TRUE., DataHandle )
365 END SUBROUTINE wrf_open_for_write_begin
367 !--- open_for_write_commit
369 SUBROUTINE wrf_open_for_write_commit( DataHandle , Status )
372 ! This routine switches an internal flag to enable output for the data set
373 ! referenced by DataHandle. The call to wrf_open_for_write_commit() must be
374 ! paired with a call to wrf_open_for_write_begin().
377 USE module_state_description
379 INTEGER , INTENT(IN ) :: DataHandle
380 INTEGER , INTENT(OUT) :: Status
382 CHARACTER (128) :: DataSet
386 INTEGER, EXTERNAL :: use_package
387 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
388 #include "wrf_io_flags.h"
390 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_open_for_write_commit' )
393 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
394 CALL set_first_operation( DataHandle )
395 IF ( Hndl .GT. -1 ) THEN
396 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
397 SELECT CASE ( use_package(io_form) )
400 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
401 CALL ext_ncd_open_for_write_commit ( Hndl , Status )
403 IF ( .NOT. multi_files(io_form) ) CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
407 IF ( wrf_dm_on_monitor() ) THEN
408 CALL ext_mcel_open_for_write_commit ( Hndl , Status )
410 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
414 CALL ext_esmf_open_for_write_commit ( Hndl , Status )
418 CALL ext_phdf5_open_for_write_commit ( Hndl , Status )
422 CALL ext_pnc_open_for_write_commit ( Hndl , Status )
426 CALL ext_xxx_open_for_write_commit ( Hndl , Status )
430 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
431 CALL ext_yyy_open_for_write_commit ( Hndl , Status )
433 IF ( .NOT. multi_files(io_form) ) CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
437 CALL ext_zzz_open_for_write_commit ( Hndl , Status )
441 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
442 CALL ext_gr1_open_for_write_commit ( Hndl , Status )
444 IF ( .NOT. multi_files(io_form) ) CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
448 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
449 CALL ext_gr2_open_for_write_commit ( Hndl , Status )
451 IF ( .NOT. multi_files(io_form) ) CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
455 CALL ext_int_open_for_write_commit ( Hndl , Status )
460 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
461 CALL wrf_quilt_open_for_write_commit ( Hndl , Status )
469 END SUBROUTINE wrf_open_for_write_commit
471 !--- open_for_read_begin
473 SUBROUTINE wrf_open_for_read_begin( FileName , Comm_compute, Comm_io, SysDepInfo, &
474 DataHandle , Status )
477 ! Begin data definition ("training") phase for reading from WRF dataset
481 USE module_state_description
483 #include "wrf_io_flags.h"
484 CHARACTER*(*) :: FileName
485 INTEGER , INTENT(IN) :: Comm_compute , Comm_io
486 CHARACTER*(*) :: SysDepInfo
487 INTEGER , INTENT(OUT) :: DataHandle
488 INTEGER , INTENT(OUT) :: Status
490 CHARACTER*128 :: DataSet
493 LOGICAL :: also_for_out
494 INTEGER, EXTERNAL :: use_package
495 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
497 CHARACTER*128 :: LocFilename ! for appending the process ID if necessary
499 CHARACTER*128 :: mess, fhand
500 CHARACTER*1028 :: tstr
502 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_open_for_read_begin' )
504 CALL get_value_from_pairs ( "DATASET" , SysDepInfo , DataSet )
506 io_form = io_form_for_dataset( DataSet )
510 also_for_out = .FALSE.
511 ! IF ( .NOT. use_output_servers() ) THEN
512 SELECT CASE ( use_package(io_form) )
515 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
516 IF ( multi_files(io_form) ) THEN
517 CALL wrf_get_myproc ( myproc )
518 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
520 LocFilename = FileName
522 CALL ext_ncd_open_for_read_begin ( LocFilename , Comm_compute, Comm_io, SysDepInfo, &
525 IF ( .NOT. multi_files(io_form) ) THEN
526 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
527 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
532 CALL ext_xxx_open_for_read_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
537 CALL ext_yyy_open_for_read_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
542 CALL ext_zzz_open_for_read_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
547 also_for_out = .TRUE.
548 IF ( wrf_dm_on_monitor() ) THEN
550 WRITE(fhand,'(a,i0)')"filter_",filtno
552 tstr = TRIM(SysDepInfo) // ',' // 'READ_MODE=UPDATE,LAT_R=XLAT,LON_R=XLONG,LANDMASK_I=LU_MASK,FILTER_HANDLE=' // TRIM(fhand)
553 CALL ext_mcel_open_for_read_begin ( FileName , Comm_compute, Comm_io, tstr, &
556 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
557 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
561 also_for_out = .TRUE.
562 CALL ext_esmf_open_for_read_begin ( FileName , Comm_compute, Comm_io, SysDepInfo, &
567 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
568 IF ( multi_files(io_form) ) THEN
569 CALL wrf_get_myproc ( myproc )
570 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
572 LocFilename = FileName
574 CALL ext_gr1_open_for_read_begin ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
577 IF ( .NOT. multi_files(io_form) ) THEN
578 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
579 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
584 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
585 IF ( multi_files(io_form) ) THEN
586 CALL wrf_get_myproc ( myproc )
587 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
589 LocFilename = FileName
591 CALL ext_gr2_open_for_read_begin ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
594 IF ( .NOT. multi_files(io_form) ) THEN
595 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
596 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
603 IF ( io_form .NE. 0 ) THEN
604 WRITE(mess,*)'Tried to open ',FileName,' reading: no valid io_form (',io_form,')'
605 CALL wrf_message(mess)
607 Status = WRF_FILE_NOT_OPENED
612 CALL add_new_handle( Hndl, io_form, also_for_out, DataHandle )
613 END SUBROUTINE wrf_open_for_read_begin
615 !--- open_for_read_commit
617 SUBROUTINE wrf_open_for_read_commit( DataHandle , Status )
620 ! End "training" phase for WRF dataset FileName. The call to
621 ! wrf_open_for_read_commit() must be paired with a call to
622 ! wrf_open_for_read_begin().
625 USE module_state_description
627 INTEGER , INTENT(IN ) :: DataHandle
628 INTEGER , INTENT(OUT) :: Status
630 CHARACTER (128) :: DataSet
634 INTEGER, EXTERNAL :: use_package
635 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
636 #include "wrf_io_flags.h"
638 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_open_for_read_commit' )
641 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
642 CALL set_first_operation( DataHandle )
643 IF ( Hndl .GT. -1 ) THEN
644 IF ( .NOT. (for_out .AND. use_output_servers()) ) THEN
645 SELECT CASE ( use_package(io_form) )
648 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
649 CALL ext_ncd_open_for_read_commit ( Hndl , Status )
651 IF ( .NOT. multi_files(io_form) ) CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
655 IF ( wrf_dm_on_monitor() ) THEN
656 CALL ext_mcel_open_for_read_commit ( Hndl , Status )
658 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
662 CALL ext_esmf_open_for_read_commit ( Hndl , Status )
666 CALL ext_xxx_open_for_read_commit ( Hndl , Status )
670 CALL ext_yyy_open_for_read_commit ( Hndl , Status )
674 CALL ext_zzz_open_for_read_commit ( Hndl , Status )
678 CALL ext_gr1_open_for_read_commit ( Hndl , Status )
682 CALL ext_gr2_open_for_read_commit ( Hndl , Status )
694 Status = WRF_FILE_NOT_OPENED
697 END SUBROUTINE wrf_open_for_read_commit
701 SUBROUTINE wrf_open_for_read ( FileName , Comm_compute, Comm_io, SysDepInfo, &
702 DataHandle , Status )
705 ! Opens a WRF dataset for reading.
708 USE module_state_description
710 CHARACTER*(*) :: FileName
711 INTEGER , INTENT(IN) :: Comm_compute , Comm_io
712 CHARACTER*(*) :: SysDepInfo
713 INTEGER , INTENT(OUT) :: DataHandle
714 INTEGER , INTENT(OUT) :: Status
716 CHARACTER (128) :: DataSet, LocFileName
717 INTEGER :: io_form, myproc
719 INTEGER, EXTERNAL :: use_package
720 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
722 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_open_for_read' )
724 CALL get_value_from_pairs ( "DATASET" , SysDepInfo , DataSet )
726 io_form = io_form_for_dataset( DataSet )
730 SELECT CASE ( use_package(io_form) )
733 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
734 IF ( multi_files(io_form) ) THEN
735 CALL wrf_get_myproc ( myproc )
736 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
738 LocFilename = FileName
741 CALL ext_ncd_open_for_read ( LocFilename , Comm_compute, Comm_io, SysDepInfo, &
744 IF ( .NOT. multi_files(io_form) ) THEN
745 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
746 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
751 CALL ext_phdf5_open_for_read ( FileName , Comm_compute, Comm_io, SysDepInfo, &
756 CALL ext_pnc_open_for_read ( FileName , Comm_compute, Comm_io, SysDepInfo, &
761 CALL ext_xxx_open_for_read ( FileName , Comm_compute, Comm_io, SysDepInfo, &
766 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
767 IF ( multi_files(io_form) ) THEN
768 CALL wrf_get_myproc ( myproc )
769 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
771 LocFilename = FileName
774 CALL ext_yyy_open_for_read ( LocFilename , Comm_compute, Comm_io, SysDepInfo, &
777 IF ( .NOT. multi_files(io_form) ) THEN
778 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
779 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
784 CALL ext_zzz_open_for_read ( FileName , Comm_compute, Comm_io, SysDepInfo, &
789 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
790 IF ( multi_files(io_form) ) THEN
791 CALL wrf_get_myproc ( myproc )
792 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
794 LocFilename = FileName
797 CALL ext_gr1_open_for_read ( LocFilename , Comm_compute, Comm_io, SysDepInfo, &
800 IF ( .NOT. multi_files(io_form) ) THEN
801 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
802 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
807 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
808 IF ( multi_files(io_form) ) THEN
809 CALL wrf_get_myproc ( myproc )
810 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
812 LocFilename = FileName
815 CALL ext_gr2_open_for_read ( LocFilename , Comm_compute, Comm_io, SysDepInfo, &
818 IF ( .NOT. multi_files(io_form) ) THEN
819 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
820 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
825 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) THEN
826 IF ( multi_files(io_form) ) THEN
827 CALL wrf_get_myproc ( myproc )
828 CALL append_to_filename ( LocFilename , FileName , myproc, 4 )
830 LocFilename = FileName
832 CALL ext_int_open_for_read ( LocFileName , Comm_compute, Comm_io, SysDepInfo, &
835 IF ( .NOT. multi_files(io_form) ) THEN
836 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
837 CALL wrf_dm_bcast_bytes( Hndl, IWORDSIZE )
843 CALL add_new_handle( Hndl, io_form, .FALSE., DataHandle )
845 END SUBROUTINE wrf_open_for_read
849 SUBROUTINE wrf_inquire_opened ( DataHandle, FileName , FileStatus, Status )
852 ! Inquire if the dataset referenced by DataHandle is open.
855 USE module_state_description
857 INTEGER , INTENT(IN) :: DataHandle
858 CHARACTER*(*) :: FileName
859 INTEGER , INTENT(OUT) :: FileStatus
860 INTEGER , INTENT(OUT) :: Status
862 INTEGER, EXTERNAL :: use_package
863 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
864 #include "wrf_io_flags.h"
865 #include "wrf_status_codes.h"
867 INTEGER io_form , Hndl
869 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_inquire_opened' )
872 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
873 IF ( Hndl .GT. -1 ) THEN
874 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
875 SELECT CASE ( use_package(io_form) )
878 IF (wrf_dm_on_monitor()) CALL ext_ncd_inquire_opened ( Hndl, FileName , FileStatus, Status )
879 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
880 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
884 CALL ext_phdf5_inquire_opened ( Hndl, FileName , FileStatus, Status )
888 CALL ext_pnc_inquire_opened ( Hndl, FileName , FileStatus, Status )
892 CALL ext_xxx_inquire_opened ( Hndl, FileName , FileStatus, Status )
896 IF (wrf_dm_on_monitor()) CALL ext_yyy_inquire_opened ( Hndl, FileName , FileStatus, Status )
897 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
898 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
902 CALL ext_zzz_inquire_opened ( Hndl, FileName , FileStatus, Status )
906 IF (wrf_dm_on_monitor()) CALL ext_gr1_inquire_opened ( Hndl, FileName , FileStatus, Status )
907 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
908 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
912 IF (wrf_dm_on_monitor()) CALL ext_gr2_inquire_opened ( Hndl, FileName , FileStatus, Status )
913 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
914 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
918 IF (wrf_dm_on_monitor()) CALL ext_int_inquire_opened ( Hndl, FileName , FileStatus, Status )
919 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
920 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
923 FileStatus = WRF_FILE_NOT_OPENED
926 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
927 CALL wrf_quilt_inquire_opened ( Hndl, FileName , FileStatus, Status )
930 FileStatus = WRF_FILE_NOT_OPENED
934 END SUBROUTINE wrf_inquire_opened
936 !--- inquire_filename
939 SUBROUTINE wrf_inquire_filename ( DataHandle, FileName , FileStatus, Status )
942 ! Returns the Filename and FileStatus associated with DataHandle.
945 USE module_state_description
947 INTEGER , INTENT(IN) :: DataHandle
948 CHARACTER*(*) :: FileName
949 INTEGER , INTENT(OUT) :: FileStatus
950 INTEGER , INTENT(OUT) :: Status
951 #include "wrf_status_codes.h"
952 INTEGER, EXTERNAL :: use_package
953 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
956 INTEGER io_form , Hndl
958 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_inquire_filename' )
961 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
962 IF ( Hndl .GT. -1 ) THEN
963 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
964 SELECT CASE ( use_package( io_form ) )
967 IF (wrf_dm_on_monitor()) CALL ext_ncd_inquire_filename ( Hndl, FileName , FileStatus, Status )
968 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
969 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
973 CALL ext_phdf5_inquire_filename ( Hndl, FileName , FileStatus, Status )
977 CALL ext_pnc_inquire_filename ( Hndl, FileName , FileStatus, Status )
981 CALL ext_xxx_inquire_filename ( Hndl, FileName , FileStatus, Status )
985 IF (wrf_dm_on_monitor()) CALL ext_yyy_inquire_filename ( Hndl, FileName , FileStatus, Status )
986 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
987 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
991 CALL ext_zzz_inquire_filename ( Hndl, FileName , FileStatus, Status )
995 IF (wrf_dm_on_monitor()) CALL ext_gr1_inquire_filename ( Hndl, FileName , FileStatus, Status )
996 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
997 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1001 IF (wrf_dm_on_monitor()) CALL ext_gr2_inquire_filename ( Hndl, FileName , FileStatus, Status )
1002 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
1003 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1007 IF (wrf_dm_on_monitor()) CALL ext_int_inquire_filename ( Hndl, FileName , FileStatus, Status )
1008 CALL wrf_dm_bcast_bytes( FileStatus, IWORDSIZE )
1009 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1014 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1015 CALL wrf_quilt_inquire_filename ( Hndl, FileName , FileStatus, Status )
1022 END SUBROUTINE wrf_inquire_filename
1026 SUBROUTINE wrf_iosync ( DataHandle, Status )
1029 ! Synchronize the disk copy of a dataset with memory buffers.
1032 USE module_state_description
1034 INTEGER , INTENT(IN) :: DataHandle
1035 INTEGER , INTENT(OUT) :: Status
1036 #include "wrf_status_codes.h"
1037 INTEGER, EXTERNAL :: use_package
1038 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
1041 INTEGER io_form , Hndl
1043 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_iosync' )
1046 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1047 IF ( Hndl .GT. -1 ) THEN
1048 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
1049 SELECT CASE ( use_package(io_form) )
1052 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_ncd_iosync( Hndl, Status )
1053 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1057 CALL ext_xxx_iosync( Hndl, Status )
1061 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_yyy_iosync( Hndl, Status )
1062 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1066 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr1_iosync( Hndl, Status )
1067 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1071 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr2_iosync( Hndl, Status )
1072 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1076 CALL ext_zzz_iosync( Hndl, Status )
1080 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_int_iosync( Hndl, Status )
1081 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
1086 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1087 CALL wrf_quilt_iosync( Hndl, Status )
1092 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
1095 END SUBROUTINE wrf_iosync
1099 SUBROUTINE wrf_ioclose ( DataHandle, Status )
1102 ! Close the dataset referenced by DataHandle.
1105 USE module_state_description
1107 INTEGER , INTENT(IN) :: DataHandle
1108 INTEGER , INTENT(OUT) :: Status
1109 #include "wrf_status_codes.h"
1110 INTEGER, EXTERNAL :: use_package
1111 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
1112 INTEGER io_form , Hndl
1115 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_ioclose' )
1118 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1119 IF ( Hndl .GT. -1 ) THEN
1120 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
1121 SELECT CASE ( use_package(io_form) )
1124 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_ncd_ioclose( Hndl, Status )
1125 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1129 CALL ext_phdf5_ioclose( Hndl, Status )
1133 CALL ext_pnc_ioclose( Hndl, Status )
1137 CALL ext_xxx_ioclose( Hndl, Status )
1141 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_yyy_ioclose( Hndl, Status )
1142 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1146 CALL ext_zzz_ioclose( Hndl, Status )
1150 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr1_ioclose( Hndl, Status )
1151 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1155 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr2_ioclose( Hndl, Status )
1156 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1160 CALL ext_mcel_ioclose( Hndl, Status )
1164 CALL ext_esmf_ioclose( Hndl, Status )
1168 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_int_ioclose( Hndl, Status )
1169 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1174 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1175 CALL wrf_quilt_ioclose( Hndl, Status )
1179 CALL free_handle( DataHandle )
1181 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
1184 END SUBROUTINE wrf_ioclose
1186 !--- get_next_time (not defined for IntIO )
1188 SUBROUTINE wrf_get_next_time ( DataHandle, DateStr, Status )
1191 ! Returns the next time stamp.
1194 USE module_state_description
1196 INTEGER , INTENT(IN) :: DataHandle
1197 CHARACTER*(*) :: DateStr
1198 INTEGER , INTENT(OUT) :: Status
1199 #include "wrf_status_codes.h"
1201 INTEGER, EXTERNAL :: use_package
1202 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
1203 INTEGER io_form , Hndl, len_of_str
1206 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_get_next_time' )
1209 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1210 IF ( Hndl .GT. -1 ) THEN
1211 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
1212 SELECT CASE ( use_package(io_form) )
1215 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_ncd_get_next_time( Hndl, DateStr, Status )
1216 IF ( .NOT. multi_files(io_form) ) THEN
1217 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1218 len_of_str = LEN(DateStr)
1219 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1224 CALL ext_phdf5_get_next_time( Hndl, DateStr, Status )
1228 CALL ext_pnc_get_next_time( Hndl, DateStr, Status )
1232 CALL ext_xxx_get_next_time( Hndl, DateStr, Status )
1236 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_yyy_get_next_time( Hndl, DateStr, Status )
1237 IF ( .NOT. multi_files(io_form) ) THEN
1238 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1239 len_of_str = LEN(DateStr)
1240 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1245 CALL ext_zzz_get_next_time( Hndl, DateStr, Status )
1249 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr1_get_next_time( Hndl, DateStr, Status )
1250 IF ( .NOT. multi_files(io_form) ) THEN
1251 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1252 len_of_str = LEN(DateStr)
1253 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1258 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr2_get_next_time( Hndl, DateStr, Status )
1259 IF ( .NOT. multi_files(io_form) ) THEN
1260 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1261 len_of_str = LEN(DateStr)
1262 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1267 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_int_get_next_time( Hndl, DateStr, Status )
1268 IF ( .NOT. multi_files(io_form) ) THEN
1269 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1270 len_of_str = LEN(DateStr)
1271 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1277 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1278 CALL wrf_quilt_get_next_time( Hndl, DateStr, Status )
1283 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
1286 END SUBROUTINE wrf_get_next_time
1288 !--- get_previous_time (not defined for IntIO )
1290 SUBROUTINE wrf_get_previous_time ( DataHandle, DateStr, Status )
1293 ! Returns the previous time stamp.
1296 USE module_state_description
1298 INTEGER , INTENT(IN) :: DataHandle
1299 CHARACTER*(*) :: DateStr
1300 INTEGER , INTENT(OUT) :: Status
1301 #include "wrf_status_codes.h"
1303 INTEGER, EXTERNAL :: use_package
1304 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
1305 INTEGER io_form , Hndl, len_of_str
1308 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_get_previous_time' )
1311 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1312 IF ( Hndl .GT. -1 ) THEN
1313 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
1314 SELECT CASE ( use_package(io_form) )
1317 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_ncd_get_previous_time( Hndl, DateStr, Status )
1318 IF ( .NOT. multi_files(io_form) ) THEN
1319 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1320 len_of_str = LEN(DateStr)
1321 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1326 CALL ext_phdf5_get_previous_time( Hndl, DateStr, Status )
1330 CALL ext_pnc_get_previous_time( Hndl, DateStr, Status )
1334 CALL ext_xxx_get_previous_time( Hndl, DateStr, Status )
1338 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_yyy_get_previous_time( Hndl, DateStr, Status )
1339 IF ( .NOT. multi_files(io_form) ) THEN
1340 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1341 len_of_str = LEN(DateStr)
1342 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1347 CALL ext_zzz_get_previous_time( Hndl, DateStr, Status )
1351 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr1_get_previous_time( Hndl, DateStr, Status )
1352 IF ( .NOT. multi_files(io_form) ) THEN
1353 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1354 len_of_str = LEN(DateStr)
1355 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1360 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr2_get_previous_time( Hndl, DateStr, Status )
1361 IF ( .NOT. multi_files(io_form) ) THEN
1362 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1363 len_of_str = LEN(DateStr)
1364 CALL wrf_dm_bcast_string ( DateStr , len_of_str )
1372 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1373 CALL wrf_quilt_get_previous_time( Hndl, DateStr, Status )
1378 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
1381 END SUBROUTINE wrf_get_previous_time
1385 SUBROUTINE wrf_set_time ( DataHandle, DateStr, Status )
1388 ! Sets the time stamp.
1391 USE module_state_description
1393 INTEGER , INTENT(IN) :: DataHandle
1394 CHARACTER*(*) :: DateStr
1395 INTEGER , INTENT(OUT) :: Status
1396 #include "wrf_status_codes.h"
1398 INTEGER, EXTERNAL :: use_package
1399 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
1400 INTEGER io_form , Hndl
1403 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_set_time' )
1406 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1407 IF ( Hndl .GT. -1 ) THEN
1408 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
1409 SELECT CASE ( use_package( io_form ) )
1412 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_ncd_set_time( Hndl, DateStr, Status )
1413 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1417 CALL ext_phdf5_set_time( Hndl, DateStr, Status )
1421 CALL ext_pnc_set_time( Hndl, DateStr, Status )
1425 CALL ext_xxx_set_time( Hndl, DateStr, Status )
1429 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_yyy_set_time( Hndl, DateStr, Status )
1430 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1434 CALL ext_zzz_set_time( Hndl, DateStr, Status )
1438 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr1_set_time( Hndl, DateStr, Status )
1439 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1443 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr2_set_time( Hndl, DateStr, Status )
1444 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1448 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_int_set_time( Hndl, DateStr, Status )
1449 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1454 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1455 CALL wrf_quilt_set_time( Hndl, DateStr, Status )
1460 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
1463 END SUBROUTINE wrf_set_time
1465 !--- get_next_var (not defined for IntIO)
1467 SUBROUTINE wrf_get_next_var ( DataHandle, VarName, Status )
1470 ! On reading, this routine returns the name of the next variable in the
1471 ! current time frame.
1474 USE module_state_description
1476 INTEGER , INTENT(IN) :: DataHandle
1477 CHARACTER*(*) :: VarName
1478 INTEGER , INTENT(OUT) :: Status
1479 #include "wrf_status_codes.h"
1481 INTEGER, EXTERNAL :: use_package
1482 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
1483 INTEGER io_form , Hndl
1486 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_get_next_var' )
1489 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1490 IF ( Hndl .GT. -1 ) THEN
1491 IF ( multi_files( io_form ) .OR. .NOT. (for_out .AND. use_output_servers()) ) THEN
1492 SELECT CASE ( use_package( io_form ) )
1495 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_ncd_get_next_var( Hndl, VarName, Status )
1496 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1500 CALL ext_xxx_get_next_var( Hndl, VarName, Status )
1504 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_yyy_get_next_var( Hndl, VarName, Status )
1505 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1509 CALL ext_zzz_get_next_var( Hndl, VarName, Status )
1513 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr1_get_next_var( Hndl, VarName, Status )
1514 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1518 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_gr2_get_next_var( Hndl, VarName, Status )
1519 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1523 IF ( multi_files(io_form) .OR. wrf_dm_on_monitor() ) CALL ext_int_get_next_var( Hndl, VarName, Status )
1524 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
1529 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1530 CALL wrf_quilt_get_next_var( Hndl, VarName, Status )
1535 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
1538 END SUBROUTINE wrf_get_next_var
1541 ! wrf_get_var_info (not implemented for IntIO)
1543 SUBROUTINE wrf_get_var_info ( DataHandle , VarName , NDim , MemoryOrder , Stagger , &
1544 DomainStart , DomainEnd , Status )
1547 ! This routine applies only to a dataset that is open for read. It returns
1548 ! information about a variable.
1551 USE module_state_description
1553 INTEGER ,INTENT(IN) :: DataHandle
1554 CHARACTER*(*) ,INTENT(IN) :: VarName
1555 INTEGER ,INTENT(OUT) :: NDim
1556 CHARACTER*(*) ,INTENT(OUT) :: MemoryOrder
1557 CHARACTER*(*) ,INTENT(OUT) :: Stagger
1558 INTEGER ,dimension(*) ,INTENT(OUT) :: DomainStart, DomainEnd
1559 INTEGER ,INTENT(OUT) :: Status
1560 #include "wrf_status_codes.h"
1561 INTEGER io_form , Hndl
1563 INTEGER, EXTERNAL :: use_package
1564 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
1566 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_get_var_info' )
1569 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1570 IF ( Hndl .GT. -1 ) THEN
1571 IF (( multi_files(io_form) .OR. wrf_dm_on_monitor() ) .AND. .NOT. (for_out .AND. use_output_servers()) ) THEN
1572 SELECT CASE ( use_package( io_form ) )
1575 CALL ext_ncd_get_var_info ( Hndl , VarName , NDim , &
1576 MemoryOrder , Stagger , &
1577 DomainStart , DomainEnd , &
1582 CALL ext_phdf5_get_var_info ( Hndl , VarName , NDim , &
1583 MemoryOrder , Stagger , &
1584 DomainStart , DomainEnd , &
1589 CALL ext_pnc_get_var_info ( Hndl , VarName , NDim , &
1590 MemoryOrder , Stagger , &
1591 DomainStart , DomainEnd , &
1596 CALL ext_xxx_get_var_info ( Hndl , VarName , NDim , &
1597 MemoryOrder , Stagger , &
1598 DomainStart , DomainEnd , &
1603 CALL ext_yyy_get_var_info ( Hndl , VarName , NDim , &
1604 MemoryOrder , Stagger , &
1605 DomainStart , DomainEnd , &
1610 CALL ext_gr1_get_var_info ( Hndl , VarName , NDim , &
1611 MemoryOrder , Stagger , &
1612 DomainStart , DomainEnd , &
1617 CALL ext_gr2_get_var_info ( Hndl , VarName , NDim , &
1618 MemoryOrder , Stagger , &
1619 DomainStart , DomainEnd , &
1625 ELSE IF ( io_form .GT. 0 .AND. for_out .AND. use_output_servers() ) THEN
1626 CALL wrf_quilt_get_var_info ( Hndl , VarName , NDim , &
1627 MemoryOrder , Stagger , &
1628 DomainStart , DomainEnd , &
1634 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
1638 END SUBROUTINE wrf_get_var_info
1642 !---------------------------------------------------------------------------------
1645 SUBROUTINE init_io_handles()
1648 ! Initialize all I/O handles.
1653 IF ( .NOT. is_inited ) THEN
1654 DO i = 1, MAX_WRF_IO_HANDLE
1655 wrf_io_handles(i) = -999319
1660 END SUBROUTINE init_io_handles
1662 SUBROUTINE add_new_handle( Hndl, Hopened, for_out, DataHandle )
1665 ! Stash the package-specific I/O handle (Hndl) and return a WRF I/O handle
1667 ! File format ID is passed in via Hopened.
1668 ! for_out will be .TRUE. if this routine was called from an
1669 ! open-for-read/write-begin operation and .FALSE. otherwise.
1673 INTEGER, INTENT(IN) :: Hndl
1674 INTEGER, INTENT(IN) :: Hopened
1675 LOGICAL, INTENT(IN) :: for_out
1676 INTEGER, INTENT(OUT) :: DataHandle
1678 INTEGER, EXTERNAL :: use_package
1679 LOGICAL, EXTERNAL :: multi_files
1680 IF ( .NOT. is_inited ) THEN
1681 CALL wrf_error_fatal( 'add_new_handle: not initialized' )
1683 IF ( multi_files( Hopened ) ) THEN
1684 SELECT CASE ( use_package( Hopened ) )
1686 CALL wrf_error_fatal( 'add_new_handle: multiple output files not supported for PHDF5' )
1688 CALL wrf_error_fatal( 'add_new_handle: multiple output files not supported for PNETCDF' )
1691 CALL wrf_error_fatal( 'add_new_handle: multiple output files not supported for MCEL' )
1695 CALL wrf_error_fatal( 'add_new_handle: multiple output files not supported for ESMF' )
1700 DO i = 1, MAX_WRF_IO_HANDLE
1701 IF ( wrf_io_handles(i) .EQ. -999319 ) THEN
1703 wrf_io_handles(i) = Hndl
1704 how_opened(i) = Hopened
1705 for_output(DataHandle) = for_out
1706 first_operation(DataHandle) = .TRUE.
1710 IF ( DataHandle .EQ. -1 ) THEN
1711 CALL wrf_error_fatal( 'add_new_handle: no handles left' )
1714 END SUBROUTINE add_new_handle
1716 SUBROUTINE get_handle ( Hndl, Hopened, for_out, DataHandle )
1719 ! Return the package-specific handle (Hndl) from a WRF handle
1721 ! Return file format ID via Hopened.
1722 ! Also, for_out will be set to .TRUE. if the file was opened
1723 ! with an open-for-read/write-begin operation and .FALSE.
1728 INTEGER, INTENT(OUT) :: Hndl
1729 INTEGER, INTENT(OUT) :: Hopened
1730 LOGICAL, INTENT(OUT) :: for_out
1731 INTEGER, INTENT(IN) :: DataHandle
1734 IF ( .NOT. is_inited ) THEN
1735 CALL wrf_error_fatal( 'module_io.F: get_handle: not initialized' )
1737 IF ( DataHandle .GE. 1 .AND. DataHandle .LE. MAX_WRF_IO_HANDLE ) THEN
1738 Hndl = wrf_io_handles(DataHandle)
1739 Hopened = how_opened(DataHandle)
1740 for_out = for_output(DataHandle)
1745 END SUBROUTINE get_handle
1747 SUBROUTINE set_first_operation( DataHandle )
1750 ! Sets internal flag to indicate that the first read or write has not yet
1751 ! happened for the dataset referenced by DataHandle.
1755 INTEGER, INTENT(IN) :: DataHandle
1756 IF ( .NOT. is_inited ) THEN
1757 CALL wrf_error_fatal( 'module_io.F: get_handle: not initialized' )
1759 IF ( DataHandle .GE. 1 .AND. DataHandle .LE. MAX_WRF_IO_HANDLE ) THEN
1760 first_operation(DataHandle) = .TRUE.
1763 END SUBROUTINE set_first_operation
1765 SUBROUTINE reset_first_operation( DataHandle )
1768 ! Resets internal flag to indicate that the first read or write has already
1769 ! happened for the dataset referenced by DataHandle.
1773 INTEGER, INTENT(IN) :: DataHandle
1774 IF ( .NOT. is_inited ) THEN
1775 CALL wrf_error_fatal( 'module_io.F: get_handle: not initialized' )
1777 IF ( DataHandle .GE. 1 .AND. DataHandle .LE. MAX_WRF_IO_HANDLE ) THEN
1778 first_operation(DataHandle) = .FALSE.
1781 END SUBROUTINE reset_first_operation
1783 LOGICAL FUNCTION is_first_operation( DataHandle )
1786 ! Returns .TRUE. the first read or write has not yet happened for the dataset
1787 ! referenced by DataHandle.
1791 INTEGER, INTENT(IN) :: DataHandle
1792 IF ( .NOT. is_inited ) THEN
1793 CALL wrf_error_fatal( 'module_io.F: get_handle: not initialized' )
1795 IF ( DataHandle .GE. 1 .AND. DataHandle .LE. MAX_WRF_IO_HANDLE ) THEN
1796 is_first_operation = first_operation(DataHandle)
1799 END FUNCTION is_first_operation
1801 SUBROUTINE free_handle ( DataHandle )
1804 ! Trash a handle and return to "unused" pool.
1808 INTEGER, INTENT(IN) :: DataHandle
1810 IF ( .NOT. is_inited ) THEN
1811 CALL wrf_error_fatal( 'free_handle: not initialized' )
1813 IF ( DataHandle .GE. 1 .AND. DataHandle .LE. MAX_WRF_IO_HANDLE ) THEN
1814 wrf_io_handles(DataHandle) = -999319
1817 END SUBROUTINE free_handle
1819 !--------------------------------------------------------------
1821 SUBROUTINE init_module_io
1824 ! Initialize this module. Must be called before any other operations are
1828 CALL init_io_handles
1829 END SUBROUTINE init_module_io
1831 SUBROUTINE are_bdys_distributed( res )
1833 LOGICAL, INTENT(OUT) :: res
1835 END SUBROUTINE are_bdys_distributed
1837 SUBROUTINE bdys_not_distributed
1839 bdy_dist_flag = .FALSE.
1840 END SUBROUTINE bdys_not_distributed
1842 SUBROUTINE bdys_are_distributed
1844 bdy_dist_flag = .TRUE.
1845 END SUBROUTINE bdys_are_distributed
1847 LOGICAL FUNCTION on_stream ( mask , switch )
1849 INTEGER, INTENT(IN) :: mask(*), switch
1851 ! get_mask is a C routine defined in frame/pack_utils.c
1852 ! switch is decremented from its fortran value so it is zero based
1853 CALL get_mask( mask, switch-1, result )
1854 on_stream = ( result .NE. 0 )
1855 END FUNCTION on_stream
1857 END MODULE module_io
1862 ! Remaining routines in this file are defined outside of the module to
1863 ! defeat arg/param type checking.
1866 SUBROUTINE wrf_read_field ( DataHandle , DateStr , VarName , Field , FieldType , &
1868 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
1869 DomainStart , DomainEnd , &
1870 MemoryStart , MemoryEnd , &
1871 PatchStart , PatchEnd , &
1875 ! Read the variable named VarName from the dataset pointed to by DataHandle.
1876 ! This routine is a wrapper that ensures uniform treatment of logicals across
1877 ! platforms by reading as integer and then converting to logical.
1880 USE module_state_description
1881 USE module_configure
1883 INTEGER , INTENT(IN) :: DataHandle
1884 CHARACTER*(*) :: DateStr
1885 CHARACTER*(*) :: VarName
1886 LOGICAL , INTENT(INOUT) :: Field(*)
1887 INTEGER ,INTENT(IN) :: FieldType
1888 INTEGER ,INTENT(INOUT) :: Comm
1889 INTEGER ,INTENT(INOUT) :: IOComm
1890 INTEGER ,INTENT(IN) :: DomainDesc
1891 LOGICAL, DIMENSION(4) :: bdy_mask
1892 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
1893 CHARACTER*(*) ,INTENT(IN) :: Stagger
1894 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
1895 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
1896 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
1897 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
1898 INTEGER ,INTENT(OUT) :: Status
1899 #include "wrf_status_codes.h"
1900 #include "wrf_io_flags.h"
1901 INTEGER, ALLOCATABLE :: ICAST(:)
1902 LOGICAL perturb_input
1903 IF ( FieldType .EQ. WRF_LOGICAL ) THEN
1904 ALLOCATE(ICAST((MemoryEnd(1)-MemoryStart(1)+1)*(MemoryEnd(2)-MemoryStart(2)+1)*(MemoryEnd(3)-MemoryStart(3)+1)))
1906 CALL wrf_read_field1 ( DataHandle , DateStr , VarName , ICAST , WRF_INTEGER , &
1908 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
1909 DomainStart , DomainEnd , &
1910 MemoryStart , MemoryEnd , &
1911 PatchStart , PatchEnd , &
1913 Field(1:(MemoryEnd(1)-MemoryStart(1)+1)*(MemoryEnd(2)-MemoryStart(2)+1)*(MemoryEnd(3)-MemoryStart(3)+1)) = ICAST == 1
1916 CALL wrf_read_field1 ( DataHandle , DateStr , VarName , Field , FieldType , &
1918 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
1919 DomainStart , DomainEnd , &
1920 MemoryStart , MemoryEnd , &
1921 PatchStart , PatchEnd , &
1923 CALL nl_get_perturb_input( 1, perturb_input )
1924 IF ( perturb_input .AND. FieldType .EQ. WRF_FLOAT .AND. TRIM(MemoryOrder) .EQ. 'XZY' ) THEN
1925 CALL perturb_real ( Field, DomainStart, DomainEnd, &
1926 MemoryStart, MemoryEnd, &
1927 PatchStart, PatchEnd )
1930 END SUBROUTINE wrf_read_field
1932 SUBROUTINE wrf_read_field1 ( DataHandle , DateStr , VarName , Field , FieldType , &
1934 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
1935 DomainStart , DomainEnd , &
1936 MemoryStart , MemoryEnd , &
1937 PatchStart , PatchEnd , &
1941 ! Read the variable named VarName from the dataset pointed to by DataHandle.
1942 ! Calls ext_pkg_read_field() via call_pkg_and_dist().
1945 USE module_state_description
1946 USE module_configure
1949 INTEGER , INTENT(IN) :: DataHandle
1950 CHARACTER*(*) :: DateStr
1951 CHARACTER*(*) :: VarName
1952 INTEGER , INTENT(INOUT) :: Field(*)
1953 INTEGER ,INTENT(IN) :: FieldType
1954 INTEGER ,INTENT(INOUT) :: Comm
1955 INTEGER ,INTENT(INOUT) :: IOComm
1956 INTEGER ,INTENT(IN) :: DomainDesc
1957 LOGICAL, DIMENSION(4) :: bdy_mask
1958 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
1959 CHARACTER*(*) ,INTENT(IN) :: Stagger
1960 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
1961 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
1962 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
1963 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
1964 INTEGER ,INTENT(OUT) :: Status
1965 #include "wrf_status_codes.h"
1966 INTEGER io_form , Hndl
1968 INTEGER, EXTERNAL :: use_package
1969 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers, use_input_servers
1971 EXTERNAL ext_ncd_read_field
1974 EXTERNAL ext_mcel_read_field
1977 EXTERNAL ext_esmf_read_field
1980 EXTERNAL ext_int_read_field
1983 EXTERNAL ext_xxx_read_field
1986 EXTERNAL ext_yyy_read_field
1989 EXTERNAL ext_gr1_read_field
1992 EXTERNAL ext_gr2_read_field
1995 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_read_field' )
1998 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
1999 CALL reset_first_operation( DataHandle )
2000 IF ( Hndl .GT. -1 ) THEN
2001 IF ( .NOT. io_form .GT. 0 ) THEN
2003 ELSE IF ( .NOT. use_input_servers() ) THEN
2004 SELECT CASE ( use_package( io_form ) )
2008 CALL call_pkg_and_dist ( ext_ncd_read_field, multi_files(io_form), .false. , &
2009 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2010 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2011 DomainStart , DomainEnd , &
2012 MemoryStart , MemoryEnd , &
2013 PatchStart , PatchEnd , &
2019 CALL ext_phdf5_read_field ( &
2020 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2021 DomainDesc , MemoryOrder , Stagger , DimNames , &
2022 DomainStart , DomainEnd , &
2023 MemoryStart , MemoryEnd , &
2024 PatchStart , PatchEnd , &
2029 CALL ext_pnc_read_field ( &
2030 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2031 DomainDesc , MemoryOrder , Stagger , DimNames , &
2032 DomainStart , DomainEnd , &
2033 MemoryStart , MemoryEnd , &
2034 PatchStart , PatchEnd , &
2039 CALL call_pkg_and_dist ( ext_mcel_read_field, multi_files(io_form), .true. , &
2040 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2041 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2042 DomainStart , DomainEnd , &
2043 MemoryStart , MemoryEnd , &
2044 PatchStart , PatchEnd , &
2049 CALL ext_esmf_read_field( Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2050 DomainDesc , MemoryOrder , Stagger , DimNames , &
2051 DomainStart , DomainEnd , &
2052 MemoryStart , MemoryEnd , &
2053 PatchStart , PatchEnd , &
2058 CALL call_pkg_and_dist ( ext_xxx_read_field, multi_files(io_form), .false., &
2059 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2060 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2061 DomainStart , DomainEnd , &
2062 MemoryStart , MemoryEnd , &
2063 PatchStart , PatchEnd , &
2068 CALL call_pkg_and_dist ( ext_yyy_read_field, multi_files(io_form), .false., &
2069 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2070 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2071 DomainStart , DomainEnd , &
2072 MemoryStart , MemoryEnd , &
2073 PatchStart , PatchEnd , &
2078 CALL call_pkg_and_dist ( ext_int_read_field, multi_files(io_form), .false., &
2079 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2080 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2081 DomainStart , DomainEnd , &
2082 MemoryStart , MemoryEnd , &
2083 PatchStart , PatchEnd , &
2088 CALL call_pkg_and_dist ( ext_gr1_read_field, multi_files(io_form), .false., &
2089 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2090 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2091 DomainStart , DomainEnd , &
2092 MemoryStart , MemoryEnd , &
2093 PatchStart , PatchEnd , &
2098 CALL call_pkg_and_dist ( ext_gr2_read_field, multi_files(io_form), .false., &
2099 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2100 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2101 DomainStart , DomainEnd , &
2102 MemoryStart , MemoryEnd , &
2103 PatchStart , PatchEnd , &
2110 CALL wrf_error_fatal('module_io.F: wrf_read_field: input_servers not implemented yet')
2113 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
2116 END SUBROUTINE wrf_read_field1
2118 SUBROUTINE wrf_write_field ( DataHandle , DateStr , VarName , Field , FieldType , &
2120 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2121 DomainStart , DomainEnd , &
2122 MemoryStart , MemoryEnd , &
2123 PatchStart , PatchEnd , &
2127 ! Write the variable named VarName to the dataset pointed to by DataHandle.
2128 ! This routine is a wrapper that ensures uniform treatment of logicals across
2129 ! platforms by converting to integer before writing.
2132 USE module_state_description
2133 USE module_configure
2135 INTEGER , INTENT(IN) :: DataHandle
2136 CHARACTER*(*) :: DateStr
2137 CHARACTER*(*) :: VarName
2138 LOGICAL , INTENT(IN) :: Field(*)
2139 INTEGER ,INTENT(IN) :: FieldType
2140 INTEGER ,INTENT(INOUT) :: Comm
2141 INTEGER ,INTENT(INOUT) :: IOComm
2142 INTEGER ,INTENT(IN) :: DomainDesc
2143 LOGICAL, DIMENSION(4) ,INTENT(IN) :: bdy_mask
2144 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2145 CHARACTER*(*) ,INTENT(IN) :: Stagger
2146 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2147 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2148 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2149 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2150 INTEGER ,INTENT(OUT) :: Status
2151 #include "wrf_status_codes.h"
2152 #include "wrf_io_flags.h"
2153 INTEGER, ALLOCATABLE :: ICAST(:)
2154 IF ( FieldType .EQ. WRF_LOGICAL ) THEN
2155 ALLOCATE(ICAST((MemoryEnd(1)-MemoryStart(1)+1)*(MemoryEnd(2)-MemoryStart(2)+1)*(MemoryEnd(3)-MemoryStart(3)+1)))
2157 WHERE ( Field(1:(MemoryEnd(1)-MemoryStart(1)+1)*(MemoryEnd(2)-MemoryStart(2)+1)*(MemoryEnd(3)-MemoryStart(3)+1)) )
2160 CALL wrf_write_field1 ( DataHandle , DateStr , VarName , ICAST , WRF_INTEGER , &
2162 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2163 DomainStart , DomainEnd , &
2164 MemoryStart , MemoryEnd , &
2165 PatchStart , PatchEnd , &
2169 CALL wrf_write_field1 ( DataHandle , DateStr , VarName , Field , FieldType , &
2171 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2172 DomainStart , DomainEnd , &
2173 MemoryStart , MemoryEnd , &
2174 PatchStart , PatchEnd , &
2177 END SUBROUTINE wrf_write_field
2179 SUBROUTINE wrf_write_field1 ( DataHandle , DateStr , VarName , Field , FieldType , &
2181 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2182 DomainStart , DomainEnd , &
2183 MemoryStart , MemoryEnd , &
2184 PatchStart , PatchEnd , &
2188 ! Write the variable named VarName to the dataset pointed to by DataHandle.
2189 ! Calls ext_pkg_write_field() via collect_fld_and_call_pkg().
2193 USE module_state_description
2194 USE module_configure
2197 INTEGER , INTENT(IN) :: DataHandle
2198 CHARACTER*(*) :: DateStr
2199 CHARACTER*(*) :: VarName
2200 INTEGER , INTENT(IN) :: Field(*)
2201 INTEGER ,INTENT(IN) :: FieldType
2202 INTEGER ,INTENT(INOUT) :: Comm
2203 INTEGER ,INTENT(INOUT) :: IOComm
2204 INTEGER ,INTENT(IN) :: DomainDesc
2205 LOGICAL, DIMENSION(4) ,INTENT(IN) :: bdy_mask
2206 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2207 CHARACTER*(*) ,INTENT(IN) :: Stagger
2208 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2209 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2210 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2211 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2212 INTEGER ,INTENT(OUT) :: Status
2213 #include "wrf_status_codes.h"
2214 INTEGER, DIMENSION(3) :: starts, ends
2215 INTEGER io_form , Hndl
2217 LOGICAL :: for_out, okay_to_call
2218 INTEGER, EXTERNAL :: use_package
2219 LOGICAL, EXTERNAL :: wrf_dm_on_monitor, multi_files, use_output_servers
2221 EXTERNAL ext_ncd_write_field
2224 EXTERNAL ext_mcel_write_field
2227 EXTERNAL ext_esmf_write_field
2230 EXTERNAL ext_int_write_field
2233 EXTERNAL ext_xxx_write_field
2236 EXTERNAL ext_yyy_write_field
2239 EXTERNAL ext_gr1_write_field
2242 EXTERNAL ext_gr2_write_field
2245 CALL wrf_debug( DEBUG_LVL, 'module_io.F: in wrf_write_field' )
2248 CALL get_handle ( Hndl, io_form , for_out, DataHandle )
2249 CALL reset_first_operation ( DataHandle )
2250 IF ( Hndl .GT. -1 ) THEN
2251 IF ( multi_files( io_form ) .OR. .NOT. use_output_servers() ) THEN
2252 SELECT CASE ( use_package( io_form ) )
2255 CALL collect_fld_and_call_pkg ( ext_ncd_write_field, multi_files(io_form), &
2256 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2257 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2258 DomainStart , DomainEnd , &
2259 MemoryStart , MemoryEnd , &
2260 PatchStart , PatchEnd , &
2265 CALL collect_fld_and_call_pkg ( ext_mcel_write_field, multi_files(io_form), &
2266 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2267 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2268 DomainStart , DomainEnd , &
2269 MemoryStart , MemoryEnd , &
2270 PatchStart , PatchEnd , &
2275 CALL ext_esmf_write_field( Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2276 DomainDesc , MemoryOrder , Stagger , DimNames , &
2277 DomainStart , DomainEnd , &
2278 MemoryStart , MemoryEnd , &
2279 PatchStart , PatchEnd , &
2284 CALL ext_phdf5_write_field( &
2285 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2286 DomainDesc , MemoryOrder , Stagger , DimNames , &
2287 DomainStart , DomainEnd , &
2288 MemoryStart , MemoryEnd , &
2289 PatchStart , PatchEnd , &
2294 CALL lower_case( MemoryOrder, MemOrd )
2295 okay_to_call = .TRUE.
2296 IF ((TRIM(MemOrd).EQ.'xsz' .OR. TRIM(MemOrd).EQ.'xs').AND. .NOT. bdy_mask(P_XSB)) okay_to_call = .FALSE.
2297 IF ((TRIM(MemOrd).EQ.'xez' .OR. TRIM(MemOrd).EQ.'xe').AND. .NOT. bdy_mask(P_XEB)) okay_to_call = .FALSE.
2298 IF ((TRIM(MemOrd).EQ.'ysz' .OR. TRIM(MemOrd).EQ.'ys').AND. .NOT. bdy_mask(P_YSB)) okay_to_call = .FALSE.
2299 IF ((TRIM(MemOrd).EQ.'yez' .OR. TRIM(MemOrd).EQ.'ye').AND. .NOT. bdy_mask(P_YEB)) okay_to_call = .FALSE.
2300 IF ( okay_to_call ) THEN
2301 starts(1:3) = PatchStart(1:3) ; ends(1:3) = PatchEnd(1:3)
2303 starts(1:3) = PatchStart(1:3) ; ends(1:3) = PatchStart(1:3)-1
2306 CALL ext_pnc_write_field( &
2307 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2308 DomainDesc , MemoryOrder , Stagger , DimNames , &
2309 DomainStart , DomainEnd , &
2310 MemoryStart , MemoryEnd , &
2316 CALL collect_fld_and_call_pkg ( ext_xxx_write_field, multi_files(io_form), &
2317 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2318 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2319 DomainStart , DomainEnd , &
2320 MemoryStart , MemoryEnd , &
2321 PatchStart , PatchEnd , &
2326 CALL collect_fld_and_call_pkg ( ext_yyy_write_field, multi_files(io_form), &
2327 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2328 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2329 DomainStart , DomainEnd , &
2330 MemoryStart , MemoryEnd , &
2331 PatchStart , PatchEnd , &
2336 CALL collect_fld_and_call_pkg ( ext_gr1_write_field, multi_files(io_form), &
2337 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2338 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2339 DomainStart , DomainEnd , &
2340 MemoryStart , MemoryEnd , &
2341 PatchStart , PatchEnd , &
2346 CALL collect_fld_and_call_pkg ( ext_gr2_write_field, multi_files(io_form), &
2347 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2348 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2349 DomainStart , DomainEnd , &
2350 MemoryStart , MemoryEnd , &
2351 PatchStart , PatchEnd , &
2356 CALL collect_fld_and_call_pkg ( ext_int_write_field, multi_files(io_form), &
2357 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2358 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2359 DomainStart , DomainEnd , &
2360 MemoryStart , MemoryEnd , &
2361 PatchStart , PatchEnd , &
2367 ELSE IF ( use_output_servers() ) THEN
2368 IF ( io_form .GT. 0 ) THEN
2369 CALL wrf_quilt_write_field ( Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2370 DomainDesc , MemoryOrder , Stagger , DimNames , &
2371 DomainStart , DomainEnd , &
2372 MemoryStart , MemoryEnd , &
2373 PatchStart , PatchEnd , &
2378 Status = WRF_ERR_FATAL_BAD_FILE_STATUS
2381 END SUBROUTINE wrf_write_field1
2383 SUBROUTINE get_value_from_pairs ( varname , str , retval )
2386 ! parse comma separated list of VARIABLE=VALUE strings and return the
2387 ! value for the matching variable if such exists, otherwise return
2392 CHARACTER*(*) :: varname
2393 CHARACTER*(*) :: str
2394 CHARACTER*(*) :: retval
2396 CHARACTER (128) varstr, tstr
2397 INTEGER i,j,n,varstrn
2398 LOGICAL nobreak, nobreakouter
2400 varstr = TRIM(varname)//"="
2401 varstrn = len(TRIM(varstr))
2405 nobreakouter = .TRUE.
2406 DO WHILE ( nobreakouter )
2410 ! Potential for out of bounds array ref on str(i:i) for i > n; reported by jedwards
2411 ! DO WHILE ( nobreak )
2412 ! IF ( str(i:i) .NE. ',' .AND. i .LE. n ) THEN
2413 ! tstr(j:j) = str(i:i)
2421 DO WHILE ( nobreak )
2423 IF ( i .LE. n ) THEN
2424 IF (str(i:i) .NE. ',' ) THEN
2425 tstr(j:j) = str(i:i)
2432 IF ( i .GT. n ) nobreakouter = .FALSE.
2433 IF ( varstr(1:varstrn) .EQ. tstr(1:varstrn) ) THEN
2434 retval(1:) = TRIM(tstr(varstrn+1:))
2435 nobreakouter = .FALSE.
2439 END SUBROUTINE get_value_from_pairs
2441 LOGICAL FUNCTION multi_files ( io_form )
2444 ! Returns .TRUE. iff io_form is a multi-file format. A multi-file format
2445 ! results in one file for each compute process and can be used with any
2446 ! I/O package. A multi-file dataset can only be read by the same number
2447 ! of tasks that were used to write it. This feature can be useful for
2448 ! speeding up restarts on machines that support efficient parallel I/O.
2449 ! Multi-file formats cannot be used with I/O quilt servers.
2453 INTEGER, INTENT(IN) :: io_form
2455 multi_files = io_form > 99
2457 multi_files = .FALSE.
2459 END FUNCTION multi_files
2461 INTEGER FUNCTION use_package ( io_form )
2464 ! Returns the ID of the external I/O package referenced by io_form.
2468 INTEGER, INTENT(IN) :: io_form
2469 use_package = MOD( io_form, 100 )
2470 END FUNCTION use_package
2473 SUBROUTINE collect_fld_and_call_pkg ( fcn, donotcollect_arg, &
2474 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2475 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2476 DomainStart , DomainEnd , &
2477 MemoryStart , MemoryEnd , &
2478 PatchStart , PatchEnd , &
2482 ! The collect_*_and_call_pkg routines collect a distributed array onto one
2483 ! processor and then call an I/O function to write the result (or in the
2484 ! case of replicated data simply write monitor node's copy of the data)
2485 ! This routine handle cases where collection can be skipped and deals with
2486 ! different data types for Field.
2490 #include "wrf_io_flags.h"
2492 LOGICAL, INTENT(IN) :: donotcollect_arg
2493 INTEGER , INTENT(IN) :: Hndl
2494 CHARACTER*(*) :: DateStr
2495 CHARACTER*(*) :: VarName
2496 INTEGER , INTENT(IN) :: Field(*)
2497 INTEGER ,INTENT(IN) :: FieldType
2498 INTEGER ,INTENT(INOUT) :: Comm
2499 INTEGER ,INTENT(INOUT) :: IOComm
2500 INTEGER ,INTENT(IN) :: DomainDesc
2501 LOGICAL, DIMENSION(4) :: bdy_mask
2502 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2503 CHARACTER*(*) ,INTENT(IN) :: Stagger
2504 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2505 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2506 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2507 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2508 INTEGER ,INTENT(OUT) :: Status
2509 LOGICAL donotcollect
2510 INTEGER ndims, nproc
2512 CALL dim_from_memorder( MemoryOrder , ndims)
2513 CALL wrf_get_nproc( nproc )
2514 donotcollect = donotcollect_arg .OR. (nproc .EQ. 1)
2516 IF ( donotcollect ) THEN
2518 CALL fcn ( Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2519 DomainDesc , MemoryOrder , Stagger , DimNames , &
2520 DomainStart , DomainEnd , &
2521 MemoryStart , MemoryEnd , &
2522 PatchStart , PatchEnd , &
2525 ELSE IF ( FieldType .EQ. WRF_DOUBLE ) THEN
2527 CALL collect_double_and_call_pkg ( fcn, &
2528 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2529 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2530 DomainStart , DomainEnd , &
2531 MemoryStart , MemoryEnd , &
2532 PatchStart , PatchEnd , &
2535 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
2537 CALL collect_real_and_call_pkg ( fcn, &
2538 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2539 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2540 DomainStart , DomainEnd , &
2541 MemoryStart , MemoryEnd , &
2542 PatchStart , PatchEnd , &
2545 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
2547 CALL collect_int_and_call_pkg ( fcn, &
2548 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2549 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2550 DomainStart , DomainEnd , &
2551 MemoryStart , MemoryEnd , &
2552 PatchStart , PatchEnd , &
2555 ELSE IF ( FieldType .EQ. WRF_LOGICAL ) THEN
2557 CALL collect_logical_and_call_pkg ( fcn, &
2558 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2559 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2560 DomainStart , DomainEnd , &
2561 MemoryStart , MemoryEnd , &
2562 PatchStart , PatchEnd , &
2567 END SUBROUTINE collect_fld_and_call_pkg
2569 SUBROUTINE collect_real_and_call_pkg ( fcn, &
2570 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2571 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2572 DomainStart , DomainEnd , &
2573 MemoryStart , MemoryEnd , &
2574 PatchStart , PatchEnd , &
2578 ! The collect_*_and_call_pkg routines collect a distributed array onto one
2579 ! processor and then call an I/O function to write the result (or in the
2580 ! case of replicated data simply write monitor node's copy of the data)
2581 ! The sole purpose of this wrapper is to allocate a big real buffer and
2582 ! pass it down to collect_generic_and_call_pkg() to do the actual work.
2585 USE module_state_description
2586 USE module_driver_constants
2589 INTEGER , INTENT(IN) :: Hndl
2590 CHARACTER*(*) :: DateStr
2591 CHARACTER*(*) :: VarName
2592 REAL , INTENT(IN) :: Field(*)
2593 INTEGER ,INTENT(IN) :: FieldType
2594 INTEGER ,INTENT(INOUT) :: Comm
2595 INTEGER ,INTENT(INOUT) :: IOComm
2596 INTEGER ,INTENT(IN) :: DomainDesc
2597 LOGICAL, DIMENSION(4) :: bdy_mask
2598 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2599 CHARACTER*(*) ,INTENT(IN) :: Stagger
2600 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2601 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2602 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2603 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2604 INTEGER ,INTENT(INOUT) :: Status
2605 REAL, ALLOCATABLE :: globbuf (:)
2606 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
2608 IF ( wrf_dm_on_monitor() ) THEN
2609 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ) )
2611 ALLOCATE( globbuf( 1 ) )
2615 # define FRSTELEM (1)
2620 CALL collect_generic_and_call_pkg ( fcn, globbuf FRSTELEM, &
2621 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2622 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2623 DomainStart , DomainEnd , &
2624 MemoryStart , MemoryEnd , &
2625 PatchStart , PatchEnd , &
2627 DEALLOCATE ( globbuf )
2630 END SUBROUTINE collect_real_and_call_pkg
2632 SUBROUTINE collect_int_and_call_pkg ( fcn, &
2633 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2634 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2635 DomainStart , DomainEnd , &
2636 MemoryStart , MemoryEnd , &
2637 PatchStart , PatchEnd , &
2641 ! The collect_*_and_call_pkg routines collect a distributed array onto one
2642 ! processor and then call an I/O function to write the result (or in the
2643 ! case of replicated data simply write monitor node's copy of the data)
2644 ! The sole purpose of this wrapper is to allocate a big integer buffer and
2645 ! pass it down to collect_generic_and_call_pkg() to do the actual work.
2648 USE module_state_description
2649 USE module_driver_constants
2652 INTEGER , INTENT(IN) :: Hndl
2653 CHARACTER*(*) :: DateStr
2654 CHARACTER*(*) :: VarName
2655 INTEGER , INTENT(IN) :: Field(*)
2656 INTEGER ,INTENT(IN) :: FieldType
2657 INTEGER ,INTENT(INOUT) :: Comm
2658 INTEGER ,INTENT(INOUT) :: IOComm
2659 INTEGER ,INTENT(IN) :: DomainDesc
2660 LOGICAL, DIMENSION(4) :: bdy_mask
2661 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2662 CHARACTER*(*) ,INTENT(IN) :: Stagger
2663 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2664 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2665 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2666 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2667 INTEGER ,INTENT(INOUT) :: Status
2668 INTEGER, ALLOCATABLE :: globbuf (:)
2669 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
2671 IF ( wrf_dm_on_monitor() ) THEN
2672 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ) )
2674 ALLOCATE( globbuf( 1 ) )
2677 CALL collect_generic_and_call_pkg ( fcn, globbuf FRSTELEM , &
2678 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2679 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2680 DomainStart , DomainEnd , &
2681 MemoryStart , MemoryEnd , &
2682 PatchStart , PatchEnd , &
2684 DEALLOCATE ( globbuf )
2687 END SUBROUTINE collect_int_and_call_pkg
2689 SUBROUTINE collect_double_and_call_pkg ( fcn, &
2690 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2691 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2692 DomainStart , DomainEnd , &
2693 MemoryStart , MemoryEnd , &
2694 PatchStart , PatchEnd , &
2698 ! The collect_*_and_call_pkg routines collect a distributed array onto one
2699 ! processor and then call an I/O function to write the result (or in the
2700 ! case of replicated data simply write monitor node's copy of the data)
2701 ! The sole purpose of this wrapper is to allocate a big double precision
2702 ! buffer and pass it down to collect_generic_and_call_pkg() to do the
2706 USE module_state_description
2707 USE module_driver_constants
2710 INTEGER , INTENT(IN) :: Hndl
2711 CHARACTER*(*) :: DateStr
2712 CHARACTER*(*) :: VarName
2713 DOUBLE PRECISION , INTENT(IN) :: Field(*)
2714 INTEGER ,INTENT(IN) :: FieldType
2715 INTEGER ,INTENT(INOUT) :: Comm
2716 INTEGER ,INTENT(INOUT) :: IOComm
2717 INTEGER ,INTENT(IN) :: DomainDesc
2718 LOGICAL, DIMENSION(4) :: bdy_mask
2719 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2720 CHARACTER*(*) ,INTENT(IN) :: Stagger
2721 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2722 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2723 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2724 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2725 INTEGER ,INTENT(INOUT) :: Status
2726 DOUBLE PRECISION, ALLOCATABLE :: globbuf (:)
2727 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
2729 IF ( wrf_dm_on_monitor() ) THEN
2730 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ) )
2732 ALLOCATE( globbuf( 1 ) )
2735 CALL collect_generic_and_call_pkg ( fcn, globbuf FRSTELEM , &
2736 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2737 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2738 DomainStart , DomainEnd , &
2739 MemoryStart , MemoryEnd , &
2740 PatchStart , PatchEnd , &
2742 DEALLOCATE ( globbuf )
2745 END SUBROUTINE collect_double_and_call_pkg
2747 SUBROUTINE collect_logical_and_call_pkg ( fcn, &
2748 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2749 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2750 DomainStart , DomainEnd , &
2751 MemoryStart , MemoryEnd , &
2752 PatchStart , PatchEnd , &
2756 ! The collect_*_and_call_pkg routines collect a distributed array onto one
2757 ! processor and then call an I/O function to write the result (or in the
2758 ! case of replicated data simply write monitor node's copy of the data)
2759 ! The sole purpose of this wrapper is to allocate a big logical buffer
2760 ! and pass it down to collect_generic_and_call_pkg() to do the actual work.
2763 USE module_state_description
2764 USE module_driver_constants
2767 INTEGER , INTENT(IN) :: Hndl
2768 CHARACTER*(*) :: DateStr
2769 CHARACTER*(*) :: VarName
2770 LOGICAL , INTENT(IN) :: Field(*)
2771 INTEGER ,INTENT(IN) :: FieldType
2772 INTEGER ,INTENT(INOUT) :: Comm
2773 INTEGER ,INTENT(INOUT) :: IOComm
2774 INTEGER ,INTENT(IN) :: DomainDesc
2775 LOGICAL, DIMENSION(4) :: bdy_mask
2776 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2777 CHARACTER*(*) ,INTENT(IN) :: Stagger
2778 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2779 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2780 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2781 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2782 INTEGER ,INTENT(INOUT) :: Status
2783 LOGICAL, ALLOCATABLE :: globbuf (:)
2784 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
2786 IF ( wrf_dm_on_monitor() ) THEN
2787 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ) )
2789 ALLOCATE( globbuf( 1 ) )
2792 CALL collect_generic_and_call_pkg ( fcn, globbuf FRSTELEM , &
2793 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2794 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2795 DomainStart , DomainEnd , &
2796 MemoryStart , MemoryEnd , &
2797 PatchStart , PatchEnd , &
2799 DEALLOCATE ( globbuf )
2802 END SUBROUTINE collect_logical_and_call_pkg
2805 SUBROUTINE collect_generic_and_call_pkg ( fcn, globbuf, &
2806 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
2807 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
2808 DomainStart , DomainEnd , &
2809 MemoryStart , MemoryEnd , &
2810 PatchStart , PatchEnd , &
2814 ! The collect_*_and_call_pkg routines collect a distributed array onto one
2815 ! processor and then call an I/O function to write the result (or in the
2816 ! case of replicated data simply write monitor node's copy of the data)
2817 ! This routine calls the distributed memory communication routines that
2818 ! collect the array and then calls I/O function fcn to write it to disk.
2821 USE module_state_description
2822 USE module_driver_constants
2824 #include "wrf_io_flags.h"
2825 #if defined( DM_PARALLEL ) && ! defined(STUBMPI)
2829 REAL , DIMENSION(*) , INTENT(INOUT) :: globbuf
2830 INTEGER , INTENT(IN) :: Hndl
2831 CHARACTER*(*) :: DateStr
2832 CHARACTER*(*) :: VarName
2833 REAL , INTENT(IN) :: Field(*)
2834 INTEGER ,INTENT(IN) :: FieldType
2835 INTEGER ,INTENT(INOUT) :: Comm
2836 INTEGER ,INTENT(INOUT) :: IOComm
2837 INTEGER ,INTENT(IN) :: DomainDesc
2838 LOGICAL, DIMENSION(4) :: bdy_mask
2839 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
2840 CHARACTER*(*) ,INTENT(IN) :: Stagger
2841 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
2842 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
2843 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
2844 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
2845 INTEGER ,INTENT(OUT) :: Status
2847 LOGICAL, EXTERNAL :: has_char
2848 INTEGER ids, ide, jds, jde, kds, kde
2849 INTEGER ims, ime, jms, jme, kms, kme
2850 INTEGER ips, ipe, jps, jpe, kps, kpe
2851 INTEGER, ALLOCATABLE :: counts(:), displs(:)
2852 INTEGER nproc, communicator, mpi_bdyslice_type, ierr, my_displ
2854 INTEGER , dimension(3) :: dom_end_rev
2855 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
2856 INTEGER, EXTERNAL :: wrf_dm_monitor_rank
2857 LOGICAL distributed_field
2858 INTEGER i,j,k,idx,lx,idx2,lx2
2859 INTEGER collective_root
2861 CALL wrf_get_nproc( nproc )
2862 CALL wrf_get_dm_communicator ( communicator )
2864 ALLOCATE( counts( nproc ) )
2865 ALLOCATE( displs( nproc ) )
2866 CALL lower_case( MemoryOrder, MemOrd )
2868 collective_root = wrf_dm_monitor_rank()
2870 dom_end_rev(1) = DomainEnd(1)
2871 dom_end_rev(2) = DomainEnd(2)
2872 dom_end_rev(3) = DomainEnd(3)
2874 SELECT CASE (TRIM(MemOrd))
2876 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
2877 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
2878 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
2880 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
2881 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
2882 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
2884 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
2885 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
2886 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
2888 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
2889 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
2891 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
2892 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
2893 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
2895 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
2896 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
2898 ! do nothing; the boundary orders and others either dont care or set themselves
2901 SELECT CASE (TRIM(MemOrd))
2903 CASE ( 'xzy','zxy','xyz','yxz','xy','yx' )
2905 distributed_field = .TRUE.
2906 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
2907 CALL wrf_patch_to_global_double ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
2908 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
2909 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
2910 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
2911 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
2912 CALL wrf_patch_to_global_real ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
2913 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
2914 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
2915 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
2916 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
2917 CALL wrf_patch_to_global_integer ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
2918 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
2919 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
2920 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
2921 ELSE IF ( FieldType .EQ. WRF_LOGICAL ) THEN
2922 CALL wrf_patch_to_global_logical ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
2923 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
2924 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
2925 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
2928 #if defined(DM_PARALLEL) && !defined(STUBMPI)
2929 CASE ( 'xsz', 'xez' )
2930 distributed_field = .FALSE.
2931 IF ( nproc .GT. 1 ) THEN
2932 jds = DomainStart(1) ; jde = DomainEnd(1) ; IF ( .NOT. has_char( Stagger, 'y' ) ) jde = jde+1 ! ns strip
2933 kds = DomainStart(2) ; kde = DomainEnd(2) ; IF ( .NOT. has_char( Stagger, 'z' ) ) kde = kde+1 ! levels
2934 ids = DomainStart(3) ; ide = DomainEnd(3) ; ! bdy_width
2935 dom_end_rev(1) = jde
2936 dom_end_rev(2) = kde
2937 dom_end_rev(3) = ide
2938 distributed_field = .TRUE.
2939 IF ( (MemOrd .eq. 'xsz' .AND. bdy_mask( P_XSB )) .OR. &
2940 (MemOrd .eq. 'xez' .AND. bdy_mask( P_XEB )) ) THEN
2941 my_displ = PatchStart(1)-1
2942 my_count = PatchEnd(1)-PatchStart(1)+1
2947 CALL mpi_gather( my_displ, 1, MPI_INTEGER, displs, 1, MPI_INTEGER, collective_root, communicator, ierr )
2948 CALL mpi_gather( my_count, 1, MPI_INTEGER, counts, 1, MPI_INTEGER, collective_root, communicator, ierr )
2949 do i = DomainStart(3),DomainEnd(3) ! bdy_width
2950 do k = DomainStart(2),DomainEnd(2) ! levels
2951 lx = MemoryEnd(1)-MemoryStart(1)+1
2952 lx2 = dom_end_rev(1)-DomainStart(1)+1
2953 idx = lx*((k-1)+(i-1)*(MemoryEnd(2)-MemoryStart(2)+1))
2954 idx2 = lx2*((k-1)+(i-1)*(MemoryEnd(2)-MemoryStart(2)+1))
2955 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
2957 CALL wrf_gatherv_double ( Field, PatchStart(1)-MemoryStart(1)+1+idx , &
2958 my_count , & ! sendcount
2959 globbuf, 1+idx2 , & ! recvbuf
2960 counts , & ! recvcounts
2962 collective_root , & ! root
2963 communicator , & ! communicator
2966 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
2968 CALL wrf_gatherv_real ( Field, PatchStart(1)-MemoryStart(1)+1+idx , &
2969 my_count , & ! sendcount
2970 globbuf, 1+idx2 , & ! recvbuf
2971 counts , & ! recvcounts
2973 collective_root , & ! root
2974 communicator , & ! communicator
2977 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
2979 CALL wrf_gatherv_integer ( Field, PatchStart(1)-MemoryStart(1)+1+idx , &
2980 my_count , & ! sendcount
2981 globbuf, 1+idx2 , & ! recvbuf
2982 counts , & ! recvcounts
2984 collective_root , & ! root
2985 communicator , & ! communicator
2993 distributed_field = .FALSE.
2994 IF ( nproc .GT. 1 ) THEN
2995 jds = DomainStart(1) ; jde = DomainEnd(1) ; IF ( .NOT. has_char( Stagger, 'y' ) ) jde = jde+1 ! ns strip
2996 ids = DomainStart(2) ; ide = DomainEnd(2) ; ! bdy_width
2997 dom_end_rev(1) = jde
2998 dom_end_rev(2) = ide
2999 distributed_field = .TRUE.
3000 IF ( (MemOrd .eq. 'xs' .AND. bdy_mask( P_XSB )) .OR. &
3001 (MemOrd .eq. 'xe' .AND. bdy_mask( P_XEB )) ) THEN
3002 my_displ = PatchStart(1)-1
3003 my_count = PatchEnd(1)-PatchStart(1)+1
3008 CALL mpi_gather( my_displ, 1, MPI_INTEGER, displs, 1, MPI_INTEGER, collective_root, communicator, ierr )
3009 CALL mpi_gather( my_count, 1, MPI_INTEGER, counts, 1, MPI_INTEGER, collective_root, communicator, ierr )
3010 do i = DomainStart(2),DomainEnd(2) ! bdy_width
3011 lx = MemoryEnd(1)-MemoryStart(1)+1
3013 lx2 = dom_end_rev(1)-DomainStart(1)+1
3015 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3017 CALL wrf_gatherv_double ( Field, PatchStart(1)-MemoryStart(1)+1+idx , &
3018 my_count , & ! sendcount
3019 globbuf, 1+idx2 , & ! recvbuf
3020 counts , & ! recvcounts
3022 collective_root , & ! root
3023 communicator , & ! communicator
3026 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
3028 CALL wrf_gatherv_real ( Field, PatchStart(1)-MemoryStart(1)+1+idx , &
3029 my_count , & ! sendcount
3030 globbuf, 1+idx2 , & ! recvbuf
3031 counts , & ! recvcounts
3033 collective_root , & ! root
3034 communicator , & ! communicator
3037 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3039 CALL wrf_gatherv_integer ( Field, PatchStart(1)-MemoryStart(1)+1+idx , &
3040 my_count , & ! sendcount
3041 globbuf, 1+idx2 , & ! recvbuf
3042 counts , & ! recvcounts
3044 collective_root , & ! root
3045 communicator , & ! communicator
3051 CASE ( 'ysz', 'yez' )
3052 distributed_field = .FALSE.
3053 IF ( nproc .GT. 1 ) THEN
3054 ids = DomainStart(1) ; ide = DomainEnd(1) ; IF ( .NOT. has_char( Stagger, 'y' ) ) ide = ide+1 ! ns strip
3055 kds = DomainStart(2) ; kde = DomainEnd(2) ; IF ( .NOT. has_char( Stagger, 'z' ) ) kde = kde+1 ! levels
3056 jds = DomainStart(3) ; jde = DomainEnd(3) ; ! bdy_width
3057 dom_end_rev(1) = ide
3058 dom_end_rev(2) = kde
3059 dom_end_rev(3) = jde
3060 distributed_field = .TRUE.
3061 IF ( (MemOrd .eq. 'ysz' .AND. bdy_mask( P_YSB )) .OR. &
3062 (MemOrd .eq. 'yez' .AND. bdy_mask( P_YEB )) ) THEN
3063 my_displ = PatchStart(1)-1
3064 my_count = PatchEnd(1)-PatchStart(1)+1
3069 CALL mpi_gather( my_displ, 1, MPI_INTEGER, displs, 1, MPI_INTEGER, collective_root, communicator, ierr )
3070 CALL mpi_gather( my_count, 1, MPI_INTEGER, counts, 1, MPI_INTEGER, collective_root, communicator, ierr )
3071 do j = DomainStart(3),DomainEnd(3) ! bdy_width
3072 do k = DomainStart(2),DomainEnd(2) ! levels
3073 lx = MemoryEnd(1)-MemoryStart(1)+1
3074 lx2 = dom_end_rev(1)-DomainStart(1)+1
3075 idx = lx*((k-1)+(j-1)*(MemoryEnd(2)-MemoryStart(2)+1))
3076 idx2 = lx2*((k-1)+(j-1)*(MemoryEnd(2)-MemoryStart(2)+1))
3078 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3080 CALL wrf_gatherv_double ( Field, PatchStart(1)-MemoryStart(1)+1+idx , & ! sendbuf
3081 my_count , & ! sendcount
3082 globbuf, 1+idx2 , & ! recvbuf
3083 counts , & ! recvcounts
3085 collective_root , & ! root
3086 communicator , & ! communicator
3089 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
3091 CALL wrf_gatherv_real( Field, PatchStart(1)-MemoryStart(1)+1+idx , & ! sendbuf
3092 my_count , & ! sendcount
3093 globbuf, 1+idx2 , & ! recvbuf
3094 counts , & ! recvcounts
3096 collective_root , & ! root
3097 communicator , & ! communicator
3100 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3102 CALL wrf_gatherv_integer( Field, PatchStart(1)-MemoryStart(1)+1+idx , & ! sendbuf
3103 my_count , & ! sendcount
3104 globbuf, 1+idx2 , & ! recvbuf
3105 counts , & ! recvcounts
3107 collective_root , & ! root
3108 communicator , & ! communicator
3116 distributed_field = .FALSE.
3117 IF ( nproc .GT. 1 ) THEN
3118 ids = DomainStart(1) ; ide = DomainEnd(1) ; IF ( .NOT. has_char( Stagger, 'y' ) ) ide = ide+1 ! ns strip
3119 jds = DomainStart(2) ; jde = DomainEnd(2) ; ! bdy_width
3120 dom_end_rev(1) = ide
3121 dom_end_rev(2) = jde
3122 distributed_field = .TRUE.
3123 IF ( (MemOrd .eq. 'ys' .AND. bdy_mask( P_YSB )) .OR. &
3124 (MemOrd .eq. 'ye' .AND. bdy_mask( P_YEB )) ) THEN
3125 my_displ = PatchStart(1)-1
3126 my_count = PatchEnd(1)-PatchStart(1)+1
3131 CALL mpi_gather( my_displ, 1, MPI_INTEGER, displs, 1, MPI_INTEGER, collective_root, communicator, ierr )
3132 CALL mpi_gather( my_count, 1, MPI_INTEGER, counts, 1, MPI_INTEGER, collective_root, communicator, ierr )
3133 do j = DomainStart(2),DomainEnd(2) ! bdy_width
3134 lx = MemoryEnd(1)-MemoryStart(1)+1
3136 lx2 = dom_end_rev(1)-DomainStart(1)+1
3139 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3141 CALL wrf_gatherv_double( Field, PatchStart(1)-MemoryStart(1)+1+idx , & ! sendbuf
3142 my_count , & ! sendcount
3143 globbuf, 1+idx2 , & ! recvbuf
3144 counts , & ! recvcounts
3146 collective_root , & ! root
3147 communicator , & ! communicator
3150 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
3152 CALL wrf_gatherv_real( Field, PatchStart(1)-MemoryStart(1)+1+idx , & ! sendbuf
3153 my_count , & ! sendcount
3154 globbuf, 1+idx2 , & ! recvbuf
3155 counts , & ! recvcounts
3157 collective_root , & ! root
3158 communicator , & ! communicator
3161 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3163 CALL wrf_gatherv_integer( Field, PatchStart(1)-MemoryStart(1)+1+idx , & ! sendbuf
3164 my_count , & ! sendcount
3165 globbuf, 1+idx2 , & ! recvbuf
3166 counts , & ! recvcounts
3168 collective_root , & ! root
3169 communicator , & ! communicator
3178 distributed_field = .FALSE.
3180 IF ( wrf_dm_on_monitor() ) THEN
3181 IF ( distributed_field ) THEN
3182 CALL fcn ( Hndl , DateStr , VarName , globbuf , FieldType , Comm , IOComm , &
3183 DomainDesc , MemoryOrder , Stagger , DimNames , &
3184 DomainStart , DomainEnd , &
3185 DomainStart , dom_end_rev , & ! memory dims adjust out for unstag
3186 DomainStart , DomainEnd , &
3189 CALL fcn ( Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3190 DomainDesc , MemoryOrder , Stagger , DimNames , &
3191 DomainStart , DomainEnd , &
3192 MemoryStart , MemoryEnd , &
3193 PatchStart , PatchEnd , &
3197 CALL wrf_dm_bcast_bytes( Status , IWORDSIZE )
3198 DEALLOCATE( counts )
3199 DEALLOCATE( displs )
3201 END SUBROUTINE collect_generic_and_call_pkg
3204 SUBROUTINE call_pkg_and_dist ( fcn, donotdist_arg, update_arg, &
3205 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3206 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3207 DomainStart , DomainEnd , &
3208 MemoryStart , MemoryEnd , &
3209 PatchStart , PatchEnd , &
3213 ! The call_pkg_and_dist* routines call an I/O function to read a field and then
3214 ! distribute or replicate the field across compute tasks.
3215 ! This routine handle cases where distribution/replication can be skipped and
3216 ! deals with different data types for Field.
3220 #include "wrf_io_flags.h"
3222 LOGICAL, INTENT(IN) :: donotdist_arg, update_arg ! update means collect old field update it and dist
3223 INTEGER , INTENT(IN) :: Hndl
3224 CHARACTER*(*) :: DateStr
3225 CHARACTER*(*) :: VarName
3227 INTEGER :: FieldType
3230 INTEGER :: DomainDesc
3231 LOGICAL, DIMENSION(4) :: bdy_mask
3232 CHARACTER*(*) :: MemoryOrder
3233 CHARACTER*(*) :: Stagger
3234 CHARACTER*(*) , dimension (*) :: DimNames
3235 INTEGER ,dimension(*) :: DomainStart, DomainEnd
3236 INTEGER ,dimension(*) :: MemoryStart, MemoryEnd
3237 INTEGER ,dimension(*) :: PatchStart, PatchEnd
3240 INTEGER ndims, nproc
3242 CALL dim_from_memorder( MemoryOrder , ndims)
3243 CALL wrf_get_nproc( nproc )
3244 donotdist = donotdist_arg .OR. (nproc .EQ. 1)
3246 IF ( donotdist ) THEN
3247 CALL fcn ( Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3248 DomainDesc , MemoryOrder , Stagger , DimNames , &
3249 DomainStart , DomainEnd , &
3250 MemoryStart , MemoryEnd , &
3251 PatchStart , PatchEnd , &
3254 ELSE IF (FieldType .EQ. WRF_DOUBLE) THEN
3256 CALL call_pkg_and_dist_double ( fcn, update_arg, &
3257 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3258 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3259 DomainStart , DomainEnd , &
3260 MemoryStart , MemoryEnd , &
3261 PatchStart , PatchEnd , &
3264 ELSE IF (FieldType .EQ. WRF_FLOAT) THEN
3266 CALL call_pkg_and_dist_real ( fcn, update_arg, &
3267 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3268 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3269 DomainStart , DomainEnd , &
3270 MemoryStart , MemoryEnd , &
3271 PatchStart , PatchEnd , &
3274 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3276 CALL call_pkg_and_dist_int ( fcn, update_arg, &
3277 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3278 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3279 DomainStart , DomainEnd , &
3280 MemoryStart , MemoryEnd , &
3281 PatchStart , PatchEnd , &
3284 ELSE IF ( FieldType .EQ. WRF_LOGICAL ) THEN
3286 CALL call_pkg_and_dist_logical ( fcn, update_arg, &
3287 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3288 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3289 DomainStart , DomainEnd , &
3290 MemoryStart , MemoryEnd , &
3291 PatchStart , PatchEnd , &
3296 END SUBROUTINE call_pkg_and_dist
3298 SUBROUTINE call_pkg_and_dist_real ( fcn, update_arg, &
3299 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3300 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3301 DomainStart , DomainEnd , &
3302 MemoryStart , MemoryEnd , &
3303 PatchStart , PatchEnd , &
3307 ! The call_pkg_and_dist* routines call an I/O function to read a field and then
3308 ! distribute or replicate the field across compute tasks.
3309 ! The sole purpose of this wrapper is to allocate a big real buffer and
3310 ! pass it down to call_pkg_and_dist_generic() to do the actual work.
3315 INTEGER , INTENT(IN) :: Hndl
3316 LOGICAL , INTENT(IN) :: update_arg
3317 CHARACTER*(*) :: DateStr
3318 CHARACTER*(*) :: VarName
3319 REAL , INTENT(INOUT) :: Field(*)
3320 INTEGER ,INTENT(IN) :: FieldType
3321 INTEGER ,INTENT(INOUT) :: Comm
3322 INTEGER ,INTENT(INOUT) :: IOComm
3323 INTEGER ,INTENT(IN) :: DomainDesc
3324 LOGICAL, DIMENSION(4) :: bdy_mask
3325 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
3326 CHARACTER*(*) ,INTENT(IN) :: Stagger
3327 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
3328 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
3329 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
3330 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
3331 INTEGER ,INTENT(INOUT) :: Status
3332 REAL, ALLOCATABLE :: globbuf (:)
3333 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
3337 IF ( wrf_dm_on_monitor() ) THEN
3338 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ), &
3340 IF ( test .NE. 0 ) THEN
3341 write(mess,*)"module_io.b",'allocating globbuf ',&
3342 (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3)
3343 CALL wrf_error_fatal(mess)
3346 ALLOCATE( globbuf( 1 ), STAT=test )
3347 IF ( test .NE. 0 ) THEN
3348 write(mess,*)"module_io.b",'allocating globbuf ',1
3349 CALL wrf_error_fatal(mess)
3355 CALL call_pkg_and_dist_generic ( fcn, globbuf FRSTELEM , update_arg, &
3356 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3357 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3358 DomainStart , DomainEnd , &
3359 MemoryStart , MemoryEnd , &
3360 PatchStart , PatchEnd , &
3362 DEALLOCATE ( globbuf )
3364 END SUBROUTINE call_pkg_and_dist_real
3367 SUBROUTINE call_pkg_and_dist_double ( fcn, update_arg , &
3368 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3369 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3370 DomainStart , DomainEnd , &
3371 MemoryStart , MemoryEnd , &
3372 PatchStart , PatchEnd , &
3376 ! The call_pkg_and_dist* routines call an I/O function to read a field and then
3377 ! distribute or replicate the field across compute tasks.
3378 ! The sole purpose of this wrapper is to allocate a big double precision buffer
3379 ! and pass it down to call_pkg_and_dist_generic() to do the actual work.
3384 INTEGER , INTENT(IN) :: Hndl
3385 LOGICAL , INTENT(IN) :: update_arg
3386 CHARACTER*(*) :: DateStr
3387 CHARACTER*(*) :: VarName
3388 DOUBLE PRECISION , INTENT(INOUT) :: Field(*)
3389 INTEGER ,INTENT(IN) :: FieldType
3390 INTEGER ,INTENT(INOUT) :: Comm
3391 INTEGER ,INTENT(INOUT) :: IOComm
3392 INTEGER ,INTENT(IN) :: DomainDesc
3393 LOGICAL, DIMENSION(4) :: bdy_mask
3394 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
3395 CHARACTER*(*) ,INTENT(IN) :: Stagger
3396 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
3397 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
3398 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
3399 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
3400 INTEGER ,INTENT(INOUT) :: Status
3401 DOUBLE PRECISION , ALLOCATABLE :: globbuf (:)
3402 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
3404 IF ( wrf_dm_on_monitor() ) THEN
3405 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ) )
3407 ALLOCATE( globbuf( 1 ) )
3412 CALL call_pkg_and_dist_generic ( fcn, globbuf FRSTELEM , update_arg , &
3413 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3414 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3415 DomainStart , DomainEnd , &
3416 MemoryStart , MemoryEnd , &
3417 PatchStart , PatchEnd , &
3419 DEALLOCATE ( globbuf )
3421 END SUBROUTINE call_pkg_and_dist_double
3424 SUBROUTINE call_pkg_and_dist_int ( fcn, update_arg , &
3425 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3426 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3427 DomainStart , DomainEnd , &
3428 MemoryStart , MemoryEnd , &
3429 PatchStart , PatchEnd , &
3433 ! The call_pkg_and_dist* routines call an I/O function to read a field and then
3434 ! distribute or replicate the field across compute tasks.
3435 ! The sole purpose of this wrapper is to allocate a big integer buffer and
3436 ! pass it down to call_pkg_and_dist_generic() to do the actual work.
3441 INTEGER , INTENT(IN) :: Hndl
3442 LOGICAL , INTENT(IN) :: update_arg
3443 CHARACTER*(*) :: DateStr
3444 CHARACTER*(*) :: VarName
3445 INTEGER , INTENT(INOUT) :: Field(*)
3446 INTEGER ,INTENT(IN) :: FieldType
3447 INTEGER ,INTENT(INOUT) :: Comm
3448 INTEGER ,INTENT(INOUT) :: IOComm
3449 INTEGER ,INTENT(IN) :: DomainDesc
3450 LOGICAL, DIMENSION(4) :: bdy_mask
3451 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
3452 CHARACTER*(*) ,INTENT(IN) :: Stagger
3453 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
3454 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
3455 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
3456 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
3457 INTEGER ,INTENT(INOUT) :: Status
3458 INTEGER , ALLOCATABLE :: globbuf (:)
3459 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
3461 IF ( wrf_dm_on_monitor() ) THEN
3462 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ) )
3464 ALLOCATE( globbuf( 1 ) )
3469 CALL call_pkg_and_dist_generic ( fcn, globbuf FRSTELEM , update_arg , &
3470 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3471 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3472 DomainStart , DomainEnd , &
3473 MemoryStart , MemoryEnd , &
3474 PatchStart , PatchEnd , &
3476 DEALLOCATE ( globbuf )
3478 END SUBROUTINE call_pkg_and_dist_int
3481 SUBROUTINE call_pkg_and_dist_logical ( fcn, update_arg , &
3482 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3483 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3484 DomainStart , DomainEnd , &
3485 MemoryStart , MemoryEnd , &
3486 PatchStart , PatchEnd , &
3490 ! The call_pkg_and_dist* routines call an I/O function to read a field and then
3491 ! distribute or replicate the field across compute tasks.
3492 ! The sole purpose of this wrapper is to allocate a big logical buffer and
3493 ! pass it down to call_pkg_and_dist_generic() to do the actual work.
3498 INTEGER , INTENT(IN) :: Hndl
3499 LOGICAL , INTENT(IN) :: update_arg
3500 CHARACTER*(*) :: DateStr
3501 CHARACTER*(*) :: VarName
3502 logical , INTENT(INOUT) :: Field(*)
3503 INTEGER ,INTENT(IN) :: FieldType
3504 INTEGER ,INTENT(INOUT) :: Comm
3505 INTEGER ,INTENT(INOUT) :: IOComm
3506 INTEGER ,INTENT(IN) :: DomainDesc
3507 LOGICAL, DIMENSION(4) :: bdy_mask
3508 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
3509 CHARACTER*(*) ,INTENT(IN) :: Stagger
3510 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
3511 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
3512 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
3513 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
3514 INTEGER ,INTENT(INOUT) :: Status
3515 LOGICAL , ALLOCATABLE :: globbuf (:)
3516 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
3518 IF ( wrf_dm_on_monitor() ) THEN
3519 ALLOCATE( globbuf( (DomainEnd(1)-DomainStart(1)+3)*(DomainEnd(2)-DomainStart(2)+3)*(DomainEnd(3)-DomainStart(3)+3) ) )
3521 ALLOCATE( globbuf( 1 ) )
3526 CALL call_pkg_and_dist_generic ( fcn, globbuf FRSTELEM , update_arg , &
3527 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3528 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3529 DomainStart , DomainEnd , &
3530 MemoryStart , MemoryEnd , &
3531 PatchStart , PatchEnd , &
3533 DEALLOCATE ( globbuf )
3535 END SUBROUTINE call_pkg_and_dist_logical
3537 SUBROUTINE call_pkg_and_dist_generic ( fcn, globbuf , update_arg , &
3538 Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3539 DomainDesc , bdy_mask, MemoryOrder , Stagger , DimNames , &
3540 DomainStart , DomainEnd , &
3541 MemoryStart , MemoryEnd , &
3542 PatchStart , PatchEnd , &
3547 ! The call_pkg_and_dist* routines call an I/O function to read a field and then
3548 ! distribute or replicate the field across compute tasks.
3549 ! This routine calls I/O function fcn to read the field from disk and then calls
3550 ! the distributed memory communication routines that distribute or replicate the
3554 USE module_state_description
3555 USE module_driver_constants
3558 #include "wrf_io_flags.h"
3559 #if defined( DM_PARALLEL ) && ! defined(STUBMPI)
3564 REAL, DIMENSION(*) :: globbuf
3565 INTEGER , INTENT(IN) :: Hndl
3566 LOGICAL , INTENT(IN) :: update_arg
3567 CHARACTER*(*) :: DateStr
3568 CHARACTER*(*) :: VarName
3570 INTEGER ,INTENT(IN) :: FieldType
3571 INTEGER ,INTENT(INOUT) :: Comm
3572 INTEGER ,INTENT(INOUT) :: IOComm
3573 INTEGER ,INTENT(IN) :: DomainDesc
3574 LOGICAL, DIMENSION(4) :: bdy_mask
3575 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
3576 CHARACTER*(*) ,INTENT(IN) :: Stagger
3577 CHARACTER*(*) , dimension (*) ,INTENT(IN) :: DimNames
3578 INTEGER ,dimension(*) ,INTENT(IN) :: DomainStart, DomainEnd
3579 INTEGER ,dimension(*) ,INTENT(IN) :: MemoryStart, MemoryEnd
3580 INTEGER ,dimension(*) ,INTENT(IN) :: PatchStart, PatchEnd
3581 INTEGER ,INTENT(OUT) :: Status
3583 LOGICAL, EXTERNAL :: has_char
3584 INTEGER ids, ide, jds, jde, kds, kde
3585 INTEGER ims, ime, jms, jme, kms, kme
3586 INTEGER ips, ipe, jps, jpe, kps, kpe
3587 INTEGER , dimension(3) :: dom_end_rev
3589 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
3590 INTEGER, EXTERNAL :: wrf_dm_monitor_rank
3592 INTEGER lx, lx2, i,j,k ,idx,idx2
3593 INTEGER my_count, nproc, communicator, ierr, my_displ
3595 INTEGER, ALLOCATABLE :: counts(:), displs(:)
3597 LOGICAL distributed_field
3598 INTEGER collective_root
3600 CALL lower_case( MemoryOrder, MemOrd )
3602 collective_root = wrf_dm_monitor_rank()
3604 CALL wrf_get_nproc( nproc )
3605 CALL wrf_get_dm_communicator ( communicator )
3607 ALLOCATE(displs( nproc ))
3608 ALLOCATE(counts( nproc ))
3610 dom_end_rev(1) = DomainEnd(1)
3611 dom_end_rev(2) = DomainEnd(2)
3612 dom_end_rev(3) = DomainEnd(3)
3614 SELECT CASE (TRIM(MemOrd))
3616 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
3617 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
3618 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
3620 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
3621 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
3622 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
3624 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
3625 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
3626 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
3628 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
3629 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
3631 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
3632 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
3633 IF ( .NOT. has_char( Stagger, 'z' ) ) dom_end_rev(3) = dom_end_rev(3) + 1
3635 IF ( .NOT. has_char( Stagger, 'y' ) ) dom_end_rev(1) = dom_end_rev(1) + 1
3636 IF ( .NOT. has_char( Stagger, 'x' ) ) dom_end_rev(2) = dom_end_rev(2) + 1
3638 ! do nothing; the boundary orders and others either dont care or set themselves
3641 data_ordering : SELECT CASE ( model_data_order )
3642 CASE ( DATA_ORDER_XYZ )
3643 ids=DomainStart(1); ide=dom_end_rev(1); jds=DomainStart(2); jde=dom_end_rev(2); kds=DomainStart(3); kde=dom_end_rev(3);
3644 ims=MemoryStart(1); ime= MemoryEnd(1); jms=MemoryStart(2); jme= MemoryEnd(2); kms=MemoryStart(3); kme= MemoryEnd(3);
3645 ips= PatchStart(1); ipe= PatchEnd(1); jps= PatchStart(2); jpe= PatchEnd(2); kps= PatchStart(3); kpe= PatchEnd(3);
3646 CASE ( DATA_ORDER_YXZ )
3647 ids=DomainStart(2); ide=dom_end_rev(2); jds=DomainStart(1); jde=dom_end_rev(1); kds=DomainStart(3); kde=dom_end_rev(3);
3648 ims=MemoryStart(2); ime= MemoryEnd(2); jms=MemoryStart(1); jme= MemoryEnd(1); kms=MemoryStart(3); kme= MemoryEnd(3);
3649 ips= PatchStart(2); ipe= PatchEnd(2); jps= PatchStart(1); jpe= PatchEnd(1); kps= PatchStart(3); kpe= PatchEnd(3);
3650 CASE ( DATA_ORDER_ZXY )
3651 ids=DomainStart(2); ide=dom_end_rev(2); jds=DomainStart(3); jde=dom_end_rev(3); kds=DomainStart(1); kde=dom_end_rev(1);
3652 ims=MemoryStart(2); ime= MemoryEnd(2); jms=MemoryStart(3); jme= MemoryEnd(3); kms=MemoryStart(1); kme= MemoryEnd(1);
3653 ips= PatchStart(2); ipe= PatchEnd(2); jps= PatchStart(3); jpe= PatchEnd(3); kps= PatchStart(1); kpe= PatchEnd(1);
3654 CASE ( DATA_ORDER_ZYX )
3655 ids=DomainStart(3); ide=dom_end_rev(3); jds=DomainStart(2); jde=dom_end_rev(2); kds=DomainStart(1); kde=dom_end_rev(1);
3656 ims=MemoryStart(3); ime= MemoryEnd(3); jms=MemoryStart(2); jme= MemoryEnd(2); kms=MemoryStart(1); kme= MemoryEnd(1);
3657 ips= PatchStart(3); ipe= PatchEnd(3); jps= PatchStart(2); jpe= PatchEnd(2); kps= PatchStart(1); kpe= PatchEnd(1);
3658 CASE ( DATA_ORDER_XZY )
3659 ids=DomainStart(1); ide=dom_end_rev(1); jds=DomainStart(3); jde=dom_end_rev(3); kds=DomainStart(2); kde=dom_end_rev(2);
3660 ims=MemoryStart(1); ime= MemoryEnd(1); jms=MemoryStart(3); jme= MemoryEnd(3); kms=MemoryStart(2); kme= MemoryEnd(2);
3661 ips= PatchStart(1); ipe= PatchEnd(1); jps= PatchStart(3); jpe= PatchEnd(3); kps= PatchStart(2); kpe= PatchEnd(2);
3662 CASE ( DATA_ORDER_YZX )
3663 ids=DomainStart(3); ide=dom_end_rev(3); jds=DomainStart(1); jde=dom_end_rev(1); kds=DomainStart(2); kde=dom_end_rev(2);
3664 ims=MemoryStart(3); ime= MemoryEnd(3); jms=MemoryStart(1); jme= MemoryEnd(1); kms=MemoryStart(2); kme= MemoryEnd(2);
3665 ips= PatchStart(3); ipe= PatchEnd(3); jps= PatchStart(1); jpe= PatchEnd(1); kps= PatchStart(2); kpe= PatchEnd(2);
3666 END SELECT data_ordering
3669 SELECT CASE (MemOrd)
3671 CASE ( 'xzy', 'yzx', 'xyz', 'yxz', 'zxy', 'zyx', 'xy', 'yx' )
3672 distributed_field = .TRUE.
3673 CASE ( 'xsz', 'xez', 'xs', 'xe' )
3674 CALL are_bdys_distributed( distributed_field )
3675 CASE ( 'ysz', 'yez', 'ys', 'ye' )
3676 CALL are_bdys_distributed( distributed_field )
3679 ! all other memory orders are replicated
3680 distributed_field = .FALSE.
3683 IF ( distributed_field ) THEN
3685 ! added 8/2004 for interfaces, like MCEL, that want the old values so they can be updated
3686 IF ( update_arg ) THEN
3687 SELECT CASE (TRIM(MemOrd))
3688 CASE ( 'xzy','zxy','xyz','yxz','xy','yx' )
3689 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3690 CALL wrf_patch_to_global_double ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
3691 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3692 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3693 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3694 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
3695 CALL wrf_patch_to_global_real ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
3696 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3697 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3698 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3699 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3700 CALL wrf_patch_to_global_integer ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
3701 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3702 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3703 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3704 ELSE IF ( FieldType .EQ. WRF_LOGICAL ) THEN
3705 CALL wrf_patch_to_global_logical ( Field , globbuf , DomainDesc, Stagger, MemOrd , &
3706 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3707 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3708 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3714 IF ( wrf_dm_on_monitor()) THEN
3715 CALL fcn ( Hndl , DateStr , VarName , globbuf , FieldType , Comm , IOComm , &
3716 DomainDesc , MemoryOrder , Stagger , DimNames , &
3717 DomainStart , DomainEnd , &
3718 DomainStart , dom_end_rev , &
3719 DomainStart , DomainEnd , &
3723 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
3725 CALL lower_case( MemoryOrder, MemOrd )
3727 #if defined(DM_PARALLEL) && !defined(STUBMPI)
3728 ! handle boundaries separately
3729 IF ( TRIM(MemOrd) .EQ. 'xsz' .OR. TRIM(MemOrd) .EQ. 'xez' .OR. &
3730 TRIM(MemOrd) .EQ. 'xs' .OR. TRIM(MemOrd) .EQ. 'xe' .OR. &
3731 TRIM(MemOrd) .EQ. 'ysz' .OR. TRIM(MemOrd) .EQ. 'yez' .OR. &
3732 TRIM(MemOrd) .EQ. 'ys' .OR. TRIM(MemOrd) .EQ. 'ye' ) THEN
3734 IF ( TRIM(MemOrd) .EQ. 'xsz' .OR. TRIM(MemOrd) .EQ. 'xez' .OR. &
3735 TRIM(MemOrd) .EQ. 'xs' .OR. TRIM(MemOrd) .EQ. 'xe' ) THEN
3737 jds=DomainStart(1); jde=dom_end_rev(1); ids=DomainStart(3); ide=dom_end_rev(3); kds=DomainStart(2); kde=dom_end_rev(2);
3738 jms=MemoryStart(1); jme= MemoryEnd(1); ims=MemoryStart(3); ime= MemoryEnd(3); kms=MemoryStart(2); kme= MemoryEnd(2);
3739 jps= PatchStart(1); jpe= PatchEnd(1); ips= PatchStart(3); ipe= PatchEnd(3); kps= PatchStart(2); kpe= PatchEnd(2);
3741 IF ( nproc .GT. 1 ) THEN
3743 ! Will assume that the i,j, and k dimensions correspond to the model_data_order specified by the registry --
3744 ! eg. i is (1), j is (3), and k is (2) for XZY -- and that when these are passed in for xs/xe boundary arrays (left and right
3745 ! sides of domain) the j is fully dimensioned, i is the bdy_width, and k is k. corresponding arrangement for ys/ye
3746 ! boundaries (bottom and top). Note, however, that for the boundary arrays themselves, the innermost dimension is always
3747 ! the "full" dimension: for xs/xe, dimension 1 of the boundary arrays is j. For ys/ye, it's i. So there's a potential
3748 ! for confusion between the MODEL storage order, and which of the sd31:ed31/sd32:ed32/sd33:ed33 framework dimensions
3749 ! correspond to X/Y/Z as determined by the Registry dimespec definitions and what the storage order of the boundary
3750 ! slab arrays are (which depends on which boundaries they represent). The k memory and domain dimensions must be set
3751 ! properly for 2d (ks=1, ke=1) versus 3d fields.
3754 IF ( (MemOrd(1:2) .EQ. 'xs' .AND. bdy_mask( P_XSB )) .OR. &
3755 (MemOrd(1:2) .EQ. 'xe' .AND. bdy_mask( P_XEB )) ) THEN
3757 my_count = jpe-jps+1
3763 IF ( (MemOrd(1:2) .EQ. 'xs' ) .OR. &
3764 (MemOrd(1:2) .EQ. 'xe' ) ) THEN
3766 my_count = jpe-jps+1
3773 CALL mpi_gather( my_displ, 1, MPI_INTEGER, displs, 1, MPI_INTEGER, collective_root, communicator, ierr )
3774 CALL mpi_gather( my_count, 1, MPI_INTEGER, counts, 1, MPI_INTEGER, collective_root, communicator, ierr )
3776 do i = ips,ipe ! bdy_width
3777 do k = kds,kde ! levels
3780 idx = lx*((k-1)+(i-1)*(kme-kms+1))
3781 idx2 = lx2*((k-1)+(i-1)*(kde-kds+1))
3782 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3783 CALL wrf_scatterv_double ( &
3784 globbuf, 1+idx2 , & ! sendbuf
3785 counts , & ! sendcounts
3786 Field, jps-jms+1+idx , &
3787 my_count , & ! recvcount
3789 collective_root , & ! root
3790 communicator , & ! communicator
3792 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
3794 CALL wrf_scatterv_real ( &
3795 globbuf, 1+idx2 , & ! sendbuf
3796 counts , & ! sendcounts
3797 Field, jps-jms+1+idx , &
3798 my_count , & ! recvcount
3800 collective_root , & ! root
3801 communicator , & ! communicator
3804 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3805 CALL wrf_scatterv_integer ( &
3806 globbuf, 1+idx2 , & ! sendbuf
3807 counts , & ! sendcounts
3808 Field, jps-jms+1+idx , &
3809 my_count , & ! recvcount
3811 collective_root , & ! root
3812 communicator , & ! communicator
3820 IF ( TRIM(MemOrd) .EQ. 'ysz' .OR. TRIM(MemOrd) .EQ. 'yez' .OR. &
3821 TRIM(MemOrd) .EQ. 'ys' .OR. TRIM(MemOrd) .EQ. 'ye' ) THEN
3824 ids=DomainStart(1); ide=dom_end_rev(1); jds=DomainStart(3); jde=dom_end_rev(3); kds=DomainStart(2); kde=dom_end_rev(2);
3825 ims=MemoryStart(1); ime= MemoryEnd(1); jms=MemoryStart(3); jme= MemoryEnd(3); kms=MemoryStart(2); kme= MemoryEnd(2);
3826 ips= PatchStart(1); ipe= PatchEnd(1); jps= PatchStart(3); jpe= PatchEnd(3); kps= PatchStart(2); kpe= PatchEnd(2);
3828 IF ( nproc .GT. 1 ) THEN
3831 IF ( (MemOrd(1:2) .EQ. 'ys' .AND. bdy_mask( P_YSB )) .OR. &
3832 (MemOrd(1:2) .EQ. 'ye' .AND. bdy_mask( P_YEB )) ) THEN
3834 my_count = ipe-ips+1
3840 IF ( (MemOrd(1:2) .EQ. 'ys' ) .OR. &
3841 (MemOrd(1:2) .EQ. 'ye' ) ) THEN
3843 my_count = ipe-ips+1
3850 CALL mpi_gather( my_displ, 1, MPI_INTEGER, displs, 1, MPI_INTEGER, collective_root, communicator, ierr )
3851 CALL mpi_gather( my_count, 1, MPI_INTEGER, counts, 1, MPI_INTEGER, collective_root, communicator, ierr )
3853 do j = jds,jde ! bdy_width
3854 do k = kds,kde ! levels
3857 idx = lx*((k-1)+(j-1)*(kme-kms+1))
3858 idx2 = lx2*((k-1)+(j-1)*(kde-kds+1))
3860 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3861 CALL wrf_scatterv_double ( &
3862 globbuf, 1+idx2 , & ! sendbuf
3863 counts , & ! sendcounts
3864 Field, ips-ims+1+idx , &
3865 my_count , & ! recvcount
3867 collective_root , & ! root
3868 communicator , & ! communicator
3870 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
3871 CALL wrf_scatterv_real ( &
3872 globbuf, 1+idx2 , & ! sendbuf
3873 counts , & ! sendcounts
3874 Field, ips-ims+1+idx , &
3875 my_count , & ! recvcount
3877 collective_root , & ! root
3878 communicator , & ! communicator
3880 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3881 CALL wrf_scatterv_integer ( &
3882 globbuf, 1+idx2 , & ! sendbuf
3883 counts , & ! sendcounts
3884 Field, ips-ims+1+idx , &
3885 my_count , & ! recvcount
3887 collective_root , & ! root
3888 communicator , & ! communicator
3896 ELSE ! not a boundary
3898 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3900 SELECT CASE (MemOrd)
3901 CASE ( 'xzy','xyz','yxz','zxy' )
3902 CALL wrf_global_to_patch_double ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3903 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3904 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3905 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3907 CALL wrf_global_to_patch_double ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3908 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), 1 , 1 , &
3909 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), 1 , 1 , &
3910 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , 1 , 1 )
3913 ELSE IF ( FieldType .EQ. WRF_FLOAT ) THEN
3915 SELECT CASE (MemOrd)
3916 CASE ( 'xzy','xyz','yxz','zxy' )
3917 CALL wrf_global_to_patch_real ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3918 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3919 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3920 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3922 CALL wrf_global_to_patch_real ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3923 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), 1 , 1 , &
3924 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), 1 , 1 , &
3925 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , 1 , 1 )
3928 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3930 SELECT CASE (MemOrd)
3931 CASE ( 'xzy','xyz','yxz','zxy' )
3932 CALL wrf_global_to_patch_integer ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3933 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3934 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3935 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3937 CALL wrf_global_to_patch_integer ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3938 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), 1 , 1 , &
3939 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), 1 , 1 , &
3940 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , 1 , 1 )
3943 ELSE IF ( FieldType .EQ. WRF_LOGICAL ) THEN
3945 SELECT CASE (MemOrd)
3946 CASE ( 'xzy','xyz','yxz','zxy' )
3947 CALL wrf_global_to_patch_logical ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3948 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), DomainStart(3), DomainEnd(3), &
3949 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), MemoryStart(3), MemoryEnd(3), &
3950 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , PatchStart(3) , PatchEnd(3) )
3952 CALL wrf_global_to_patch_logical ( globbuf, Field , DomainDesc, Stagger, MemOrd , &
3953 DomainStart(1), DomainEnd(1), DomainStart(2), DomainEnd(2), 1 , 1 , &
3954 MemoryStart(1), MemoryEnd(1), MemoryStart(2), MemoryEnd(2), 1 , 1 , &
3955 PatchStart(1) , PatchEnd(1) , PatchStart(2) , PatchEnd(2) , 1 , 1 )
3962 ELSE ! not a distributed field
3964 IF ( wrf_dm_on_monitor()) THEN
3965 CALL fcn ( Hndl , DateStr , VarName , Field , FieldType , Comm , IOComm , &
3966 DomainDesc , MemoryOrder , Stagger , DimNames , &
3967 DomainStart , DomainEnd , &
3968 MemoryStart , MemoryEnd , &
3969 PatchStart , PatchEnd , &
3972 CALL wrf_dm_bcast_bytes( Status, IWORDSIZE )
3973 memsize = (MemoryEnd(1)-MemoryStart(1)+1)*(MemoryEnd(2)-MemoryStart(2)+1)*(MemoryEnd(3)-MemoryStart(3)+1)
3974 IF ( FieldType .EQ. WRF_DOUBLE ) THEN
3975 CALL wrf_dm_bcast_bytes( Field , DWORDSIZE*memsize )
3976 ELSE IF ( FieldType .EQ. WRF_FLOAT) THEN
3977 CALL wrf_dm_bcast_bytes( Field , RWORDSIZE*memsize )
3978 ELSE IF ( FieldType .EQ. WRF_INTEGER ) THEN
3979 CALL wrf_dm_bcast_bytes( Field , IWORDSIZE*memsize )
3980 ELSE IF ( FieldType .EQ. WRF_LOGICAL ) THEN
3981 CALL wrf_dm_bcast_bytes( Field , LWORDSIZE*memsize )
3989 END SUBROUTINE call_pkg_and_dist_generic
3991 !!!!!! Miscellaneous routines
3993 ! stole these routines from io_netcdf external package; changed names to avoid collisions
3994 SUBROUTINE dim_from_memorder(MemoryOrder,NDim)
3997 ! Decodes array ranks from memory order.
4000 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
4001 INTEGER ,INTENT(OUT) :: NDim
4003 CHARACTER*3 :: MemOrd
4005 CALL Lower_Case(MemoryOrder,MemOrd)
4006 SELECT CASE (MemOrd)
4007 CASE ('xyz','xzy','yxz','yzx','zxy','zyx')
4018 END SUBROUTINE dim_from_memorder
4020 SUBROUTINE lower_case(MemoryOrder,MemOrd)
4023 ! Translates upper-case characters to lower-case.
4026 CHARACTER*(*) ,INTENT(IN) :: MemoryOrder
4027 CHARACTER*(*) ,INTENT(OUT) :: MemOrd
4030 INTEGER ,PARAMETER :: upper_to_lower =IACHAR('a')-IACHAR('A')
4034 N = len(MemoryOrder)
4037 MemOrd(1:N) = MemoryOrder(1:N)
4039 c = MemoryOrder(i:i)
4040 if('A'<=c .and. c <='Z') MemOrd(i:i)=achar(iachar(c)+upper_to_lower)
4043 END SUBROUTINE Lower_Case
4045 LOGICAL FUNCTION has_char( str, c )
4048 ! Returns .TRUE. iff string str contains character c. Ignores character case.
4054 CHARACTER*80 str1, str2, str3
4057 CALL lower_case( TRIM(str), str1 )
4060 CALL lower_case( str2, str3 )
4062 DO i = 1, LEN(TRIM(str1))
4063 IF ( str1(i:i) .EQ. d ) THEN
4070 END FUNCTION has_char