16 use fckit_configuration_module,
only: fckit_configuration
39 integer,
allocatable :: ncid_forfield(:)
45 character(len=maxstring) :: datapath =
''
46 character(len=maxstring) :: filenames(
numfiles) =
''
47 character(len=maxstring) :: filenames_conf(
numfiles) =
''
48 character(len=maxstring) :: filenames_default(
numfiles) =
''
50 logical :: geosingestmeta = .false.
52 logical :: iam_io_proc
53 type(fckit_mpi_comm) :: ccomm
54 integer :: tcomm, ocomm
55 integer :: trank, tsize
56 integer :: crank, csize
57 integer :: orank, osize
59 integer :: is_r3_tile(5), ic_r3_tile(5)
60 integer :: is_r2_tile(4), ic_r2_tile(4)
61 integer :: is_r3_noti(4), ic_r3_noti(4)
62 integer :: is_r2_noti(3), ic_r2_noti(3)
63 integer :: vindex_tile = 4
64 integer :: vindex_noti = 3
66 logical :: clobber = .true.
67 integer :: x_dimid, y_dimid, n_dimid, z_dimid, e_dimid, t_dimid, f_dimid, c_dimid, o_dimid
69 logical :: ps_in_file = .false.
90 type(fckit_configuration),
intent(in) :: f_conf
92 integer :: ierr, n, var
94 integer :: tileoffset, dt_in_name
95 character(len=4) :: yyyy
96 character(len=2) :: mm, dd, hh, min, ss
101 n = n+1; self%filenames_default(n) =
'bkg'
102 n = n+1; self%filenames_default(n) =
'crtmsrf'
103 n = n+1; self%filenames_default(n) =
'fvcore_internal_rst'
104 n = n+1; self%filenames_default(n) =
'moist_internal_rst'
105 n = n+1; self%filenames_default(n) =
'surf_import_rst'
108 call abor1_ftn(
"fv3jedi_io_geos_mod.setup: number of potential restart files &
109 does not match numfiles")
113 self%tiledim(1) = .true.
114 self%tiledim(2) = .true.
115 self%tiledim(3) = .false.
116 self%tiledim(4) = .false.
117 self%tiledim(5) = .false.
119 self%restart(1) = .false.
120 self%restart(2) = .false.
121 self%restart(3) = .true.
122 self%restart(4) = .true.
123 self%restart(5) = .true.
132 self%filenames(n) = trim(self%filenames_conf(n))
137 self%ccomm = geom%f_comm
138 self%csize = self%ccomm%size()
139 self%crank = self%ccomm%rank()
143 self%iam_io_proc = .true.
145 if (self%csize > 6)
then
148 call mpi_comm_split(self%ccomm%communicator(), geom%ntile, self%ccomm%rank(), self%tcomm, ierr)
149 call mpi_comm_rank(self%tcomm, self%trank, ierr)
150 call mpi_comm_size(self%tcomm, self%tsize, ierr)
153 call mpi_comm_split(self%ccomm%communicator(), self%trank, geom%ntile, self%ocomm, ierr)
154 call mpi_comm_rank(self%ocomm, self%orank, ierr)
155 call mpi_comm_size(self%ocomm, self%osize, ierr)
157 if (self%trank .ne. 0) self%iam_io_proc = .false.
162 call mpi_comm_dup(self%ccomm%communicator(), self%ocomm, ierr)
168 if (self%iam_io_proc)
then
171 self%is_r3_tile(1) = 1; self%ic_r3_tile(1) = geom%npx-1
172 self%is_r3_tile(2) = 1; self%ic_r3_tile(2) = geom%npy-1
173 self%is_r3_tile(3) = geom%ntile; self%ic_r3_tile(3) = 1
174 self%is_r3_tile(4) = 1; self%ic_r3_tile(4) = 1
175 self%is_r3_tile(5) = 1; self%ic_r3_tile(5) = 1
176 self%is_r2_tile(1) = 1; self%ic_r2_tile(1) = geom%npx-1
177 self%is_r2_tile(2) = 1; self%ic_r2_tile(2) = geom%npy-1
178 self%is_r2_tile(3) = geom%ntile; self%ic_r2_tile(3) = 1
179 self%is_r2_tile(4) = 1; self%ic_r2_tile(4) = 1
182 tileoffset = (geom%ntile-1)*(6*(geom%npy-1)/geom%ntiles)
183 self%is_r3_noti(1) = 1; self%ic_r3_noti(1) = geom%npx-1
184 self%is_r3_noti(2) = tileoffset+1; self%ic_r3_noti(2) = geom%npy-1
185 self%is_r3_noti(3) = 1; self%ic_r3_noti(3) = 1
186 self%is_r3_noti(4) = 1; self%ic_r3_noti(4) = 1
187 self%is_r2_noti(1) = 1; self%ic_r2_noti(1) = geom%npx-1
188 self%is_r2_noti(2) = tileoffset+1; self%ic_r2_noti(2) = geom%npy-1
189 self%is_r2_noti(3) = 1; self%ic_r2_noti(3) = 1
200 type(datetime),
intent(in) :: vdate
203 character(len=4) :: yyyy
204 character(len=2) :: mm, dd, hh, min, ss
214 self%filenames(n) = trim(self%filenames_conf(n))
217 if (index(self%filenames(n),
"%yyyy") > 0) &
218 self%filenames(n) =
replace_text(self%filenames(n),
'%yyyy',yyyy)
219 if (index(self%filenames(n),
"%mm" ) > 0) &
220 self%filenames(n) =
replace_text(self%filenames(n),
'%mm' ,mm )
221 if (index(self%filenames(n),
"%dd" ) > 0) &
222 self%filenames(n) =
replace_text(self%filenames(n),
'%dd' ,dd )
223 if (index(self%filenames(n),
"%hh" ) > 0) &
224 self%filenames(n) =
replace_text(self%filenames(n),
'%hh' ,hh )
225 if (index(self%filenames(n),
"%MM" ) > 0) &
226 self%filenames(n) =
replace_text(self%filenames(n),
'%MM' ,min )
227 if (index(self%filenames(n),
"%ss" ) > 0) &
228 self%filenames(n) =
replace_text(self%filenames(n),
'%ss' ,ss )
240 type(fckit_configuration),
intent(in) :: f_conf
246 call string_from_conf(f_conf,
"datapath",self%datapath,
'Data',memberswap=.true.)
250 if (.not. f_conf%get(
'geosingestmeta',self%geosingestmeta)) self%geosingestmeta = .false.
254 if (.not. f_conf%get(
'clobber',self%clobber)) self%clobber = .true.
258 if (.not. f_conf%get(
'tiledim',self%tiledim(1))) self%tiledim(1) = .true.
259 if (.not. f_conf%get(
'tiledim',self%tiledim(2))) self%tiledim(2) = .true.
264 n = n+1;
call string_from_conf(f_conf,
"filename_bkgd",self%filenames_conf(1), &
265 self%filenames_default(1),memberswap=.true.)
266 n = n+1;
call string_from_conf(f_conf,
"filename_crtm",self%filenames_conf(2), &
267 self%filenames_default(2),memberswap=.true.)
268 n = n+1;
call string_from_conf(f_conf,
"filename_core",self%filenames_conf(3), &
269 self%filenames_default(3),memberswap=.true.)
270 n = n+1;
call string_from_conf(f_conf,
"filename_mois",self%filenames_conf(4), &
271 self%filenames_default(4),memberswap=.true.)
272 n = n+1;
call string_from_conf(f_conf,
"filename_surf",self%filenames_conf(5), &
273 self%filenames_default(5),memberswap=.true.)
278 call abor1_ftn(
"fv3jedi_io_geos_mod.get_conf: number of potential restart files &
279 does not match numfiles")
282 if (f_conf%has(
"psinfile"))
call f_conf%get_or_die(
"psinfile",self%ps_in_file)
297 if (
allocated(self%ncid_forfield))
deallocate(self%ncid_forfield)
301 if (self%csize > 6)
call mpi_comm_free(self%tcomm, ierr)
302 call mpi_comm_free(self%ocomm, ierr)
308 subroutine read_meta(self, geom, vdate, calendar_type, date_init, fields)
313 type(datetime),
intent(inout) :: vdate
314 integer,
intent(inout) :: calendar_type
315 integer,
intent(inout) :: date_init(6)
318 integer :: varid, date(6), intdate, inttime, idate, isecs
319 character(len=8) :: cdate
320 character(len=6) :: ctime
321 integer(kind=c_int) :: cidate, cisecs, n, df
337 if (self%iam_io_proc)
then
341 if (self%ncid_isneeded(n))
then
347 call nccheck ( nf90_inq_varid(self%ncid(df),
"time", varid),
"nf90_inq_varid time" )
348 call nccheck ( nf90_get_att(self%ncid(df), varid,
"begin_date", intdate), &
349 "nf90_get_att begin_date" )
350 call nccheck ( nf90_get_att(self%ncid(df), varid,
"begin_time", inttime), &
351 "nf90_get_att begin_time" )
354 write(cdate,
"(I0.8)") intdate
355 write(ctime,
"(I0.6)") inttime
358 read(cdate(1:4),*) date(1)
359 read(cdate(5:6),*) date(2)
360 read(cdate(7:8),*) date(3)
361 read(ctime(1:2),*) date(4)
362 read(ctime(3:4),*) date(5)
363 read(ctime(5:6),*) date(6)
366 idate = date(1)*10000 + date(2)*100 + date(3)
367 isecs = date(4)*3600 + date(5)*60 + date(6)
372 call self%ccomm%broadcast(idate,0)
373 call self%ccomm%broadcast(isecs,0)
376 call datetime_from_ifs(vdate, cidate, cisecs)
393 integer :: varid, var, lev, ncid
395 integer,
pointer :: istart(:), icount(:)
396 integer,
allocatable,
target :: is_r3_tile(:), is_r3_noti(:)
397 real(kind=
kind_real),
allocatable :: arrayg(:,:), delp(:,:,:)
409 allocate(is_r3_tile(
size(self%is_r3_tile)))
410 is_r3_tile = self%is_r3_tile
411 allocate(is_r3_noti(
size(self%is_r3_noti)))
412 is_r3_noti = self%is_r3_noti
416 allocate(arrayg(1:geom%npx-1,1:geom%npy-1))
421 do var = 1,
size(fields)
424 ncid = self%ncid(self%ncid_forfield(var))
427 if (.not. self%ps_in_file)
then
428 if (trim(fields(var)%fv3jedi_name) ==
'ps')
then
429 fields(var)%short_name =
'delp'
430 fields(var)%npz = geom%npz
431 allocate(delp(geom%isc:geom%iec,geom%jsc:geom%jec,1:geom%npz))
437 if (self%iam_io_proc)
then
439 tiledim = self%tiledim(self%ncid_forfield(var))
441 if (
associated(istart))
nullify(istart)
442 if (
associated(icount))
nullify(icount)
444 if (fields(var)%npz == 1)
then
446 istart => self%is_r2_tile
447 icount => self%ic_r2_tile
449 istart => self%is_r2_noti
450 icount => self%ic_r2_noti
452 elseif (fields(var)%npz > 1)
then
454 istart => is_r3_tile;
455 icount => self%ic_r3_tile
458 icount => self%ic_r3_noti
463 if (self%iam_io_proc)
then
464 call nccheck ( nf90_inq_varid(ncid, trim(fields(var)%short_name), varid), &
465 "nf90_inq_varid "//trim(fields(var)%short_name) )
470 do lev = 1,fields(var)%npz
472 arrayg = 0.0_kind_real
474 if (self%iam_io_proc)
then
477 is_r3_tile(self%vindex_tile) = lev
478 is_r3_noti(self%vindex_noti) = lev
481 call nccheck ( nf90_get_var( ncid, varid, arrayg, istart, icount), &
482 "nf90_get_var "//trim(fields(var)%short_name) )
488 if (.not. self%ps_in_file .and. trim(fields(var)%fv3jedi_name) ==
'ps')
then
489 if (self%csize > 6)
then
490 call scatter_tile(geom, self%tcomm, 1, arrayg, delp(geom%isc:geom%iec,geom%jsc:geom%jec,lev))
492 delp(geom%isc:geom%iec,geom%jsc:geom%jec,lev) = arrayg(geom%isc:geom%iec,geom%jsc:geom%jec)
495 if (self%csize > 6)
then
497 fields(var)%array(geom%isc:geom%iec,geom%jsc:geom%jec,lev))
499 fields(var)%array(geom%isc:geom%iec,geom%jsc:geom%jec,lev) = &
500 arrayg(geom%isc:geom%iec,geom%jsc:geom%jec)
506 if (.not. self%ps_in_file .and. trim(fields(var)%fv3jedi_name) ==
'ps')
then
507 fields(var)%short_name =
'ps'
509 fields(var)%array(:,:,1) = sum(delp,3)
518 deallocate(is_r3_tile,is_r3_noti)
529 subroutine write(self, geom, fields, vdate)
535 type(datetime),
intent(in) :: vdate
547 if (self%clobber)
call write_meta(self, geom, fields, vdate)
567 type(datetime),
intent(in) :: vdate
569 integer :: var, ymult, k, n, vc
570 character(len=15) :: datefile
571 integer :: date(6), date8, time6
572 character(len=8) :: date8s, cubesize
573 character(len=6) :: time6s
574 character(len=4) :: XdimVar, YdimVar
575 integer :: varid(10000)
577 integer,
pointer :: istart(:), icount(:)
578 integer,
allocatable :: dimidsg(:), tiles(:), levels(:)
579 real(kind=
kind_real),
allocatable :: latg(:,:), long(:,:), xdimydim(:)
584 allocate(latg(1:geom%npx-1,1:geom%npy-1))
585 allocate(long(1:geom%npx-1,1:geom%npy-1))
587 if (self%csize > 6)
then
588 call gather_tile(geom, self%tcomm, 1,
rad2deg*geom%grid_lat(geom%isc:geom%iec,geom%jsc:geom%jec), latg)
589 call gather_tile(geom, self%tcomm, 1,
rad2deg*geom%grid_lon(geom%isc:geom%iec,geom%jsc:geom%jec), long)
591 latg =
rad2deg*geom%grid_lat(geom%isc:geom%iec,geom%jsc:geom%jec)
592 long =
rad2deg*geom%grid_lon(geom%isc:geom%iec,geom%jsc:geom%jec)
595 write(cubesize,
'(I8)') geom%npx-1
599 if (self%iam_io_proc)
then
604 write(date8s,
'(I4,I0.2,I0.2)') date(1),date(2),date(3)
605 write(time6s,
'(I0.2,I0.2,I0.2)') date(4),date(5),date(6)
612 allocate(xdimydim(geom%npx-1))
628 allocate(levels(geom%npz+1))
638 if (self%ncid_isneeded(n))
then
643 if (.not. self%tiledim(n)) ymult = 6
645 if ( self%tiledim(n) )
then
654 call nccheck ( nf90_def_dim(self%ncid(n), trim(xdimvar), geom%npx-1, self%x_dimid), &
655 "nf90_def_dim "//trim(xdimvar) )
656 call nccheck ( nf90_def_dim(self%ncid(n), trim(ydimvar), ymult*(geom%npy-1), self%y_dimid), &
657 "nf90_def_dim "//trim(ydimvar) )
658 if (self%tiledim(n)) &
659 call nccheck ( nf90_def_dim(self%ncid(n),
"n", geom%ntiles, self%n_dimid),
"nf90_def_dim n" )
660 call nccheck ( nf90_def_dim(self%ncid(n),
"lev", geom%npz, self%z_dimid),
"nf90_def_dim lev" )
661 call nccheck ( nf90_def_dim(self%ncid(n),
"edge", geom%npz+1, self%e_dimid),
"nf90_def_dim edge" )
662 call nccheck ( nf90_def_dim(self%ncid(n),
"time", 1, self%t_dimid),
"nf90_def_dim time" )
665 do var = 1,
size(fields)
666 if (fields(var)%npz == 4)
then
667 call nccheck ( nf90_def_dim(self%ncid(n),
"lev4", 4, self%f_dimid),
"nf90_def_dim lev" )
673 call nccheck ( nf90_def_dim(self%ncid(n),
"ncontact", 4, self%c_dimid), &
674 "nf90_def_dim ncontact" )
675 call nccheck ( nf90_def_dim(self%ncid(n),
"orientationStrLen", 5, self%o_dimid), &
676 "nf90_def_dim orientationStrLend" )
679 if (
allocated(dimidsg))
deallocate(dimidsg)
680 if ( self%tiledim(n) )
then
682 dimidsg(:) = (/ self%x_dimid, self%y_dimid, self%n_dimid /)
685 dimidsg(:) = (/ self%x_dimid, self%y_dimid /)
691 if (self%tiledim(n))
then
693 call nccheck( nf90_def_var(self%ncid(n),
"n", nf90_int, self%n_dimid, varid(vc)),
"nf90_def_var n" )
694 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"cubed-sphere face") )
695 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"axis",
"e") )
696 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"grads_dim",
"e") )
700 call nccheck( nf90_def_var(self%ncid(n), trim(xdimvar), nf90_double, self%x_dimid, varid(vc)), &
701 "nf90_def_var "//trim(xdimvar) )
702 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"Fake Longitude for GrADS Compatibility") )
703 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"units",
"degrees_east") )
706 call nccheck( nf90_def_var(self%ncid(n), trim(ydimvar), nf90_double, self%y_dimid, varid(vc)), &
707 "nf90_def_var "//trim(ydimvar) )
708 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"Fake Latitude for GrADS Compatibility") )
709 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"units",
"degrees_north") )
712 call nccheck( nf90_def_var(self%ncid(n),
"lons", nf90_double, dimidsg, varid(vc)),
"nf90_def_var lons" )
713 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"longitude") )
714 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"units",
"degrees_east") )
717 call nccheck( nf90_def_var(self%ncid(n),
"lats", nf90_double, dimidsg, varid(vc)),
"nf90_def_var lats" )
718 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"latitude") )
719 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"units",
"degrees_north") )
722 call nccheck( nf90_def_var(self%ncid(n),
"lev", nf90_double, self%z_dimid, varid(vc)),
"nf90_def_var lev" )
723 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"vertical level") )
724 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"units",
"layer") )
725 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"positive",
"down") )
726 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"coordinate",
"eta") )
727 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"standard_name",
"model_layers") )
730 call nccheck( nf90_def_var(self%ncid(n),
"edge", nf90_double, self%e_dimid, varid(vc)),
"nf90_def_var edge" )
731 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"vertical level edges") )
732 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"units",
"layer") )
733 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"positive",
"down") )
734 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"coordinate",
"eta") )
735 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"standard_name",
"model_layers") )
738 call nccheck( nf90_def_var(self%ncid(n),
"time", nf90_int, self%t_dimid, varid(vc)),
"nf90_def_var time" )
739 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"long_name",
"time"),
"nf90_def_var time long_name" )
740 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"begin_date", date8),
"nf90_def_var time begin_date" )
741 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"begin_time", time6),
"nf90_def_var time begin_time" )
744 call nccheck( nf90_def_var(self%ncid(n),
"cubed_sphere", nf90_char, varid(vc)), &
745 "nf90_def_var cubed_sphere" )
746 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"grid_mapping_name",
"gnomonic cubed-sphere"), &
747 "nf90_def_var time grid_mapping_name" )
748 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"file_format_version",
"2.90"), &
749 "nf90_def_var time file_format_version" )
750 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"additional_vars",
"contacts,orientation,anchor"), &
751 "nf90_def_var time additional_vars" )
752 call nccheck( nf90_put_att(self%ncid(n), varid(vc),
"gridspec_file",
"C"//trim(cubesize)//
"_gridspec.nc4"), &
753 "nf90_def_var gridspec_file" )
761 call nccheck( nf90_enddef(self%ncid(n)),
"nf90_enddef" )
773 if (self%tiledim(n))
then
775 call nccheck( nf90_put_var( self%ncid(n), varid(vc), tiles ),
"nf90_put_var n" )
779 vc=vc+1;
call nccheck( nf90_put_var( self%ncid(n), varid(vc), xdimydim ),
"nf90_put_var "//trim(xdimvar) )
780 vc=vc+1;
call nccheck( nf90_put_var( self%ncid(n), varid(vc), xdimydim ),
"nf90_put_var "//trim(ydimvar) )
783 if (
associated(istart))
nullify(istart)
784 if (
associated(icount))
nullify(icount)
785 if (self%tiledim(n))
then
786 istart => self%is_r2_tile(1:3); icount => self%ic_r2_tile(1:3)
788 istart => self%is_r2_noti(1:2); icount => self%ic_r2_noti(1:2)
792 vc=vc+1;
call nccheck( nf90_put_var( self%ncid(n), varid(vc), long, &
795 "nf90_put_var lons" )
797 vc=vc+1;
call nccheck( nf90_put_var( self%ncid(n), varid(vc), latg, &
800 "nf90_put_var lats" )
803 vc=vc+1;
call nccheck( nf90_put_var( self%ncid(n), varid(vc), levels(1:geom%npz) ),
"nf90_put_var lev" )
804 vc=vc+1;
call nccheck( nf90_put_var( self%ncid(n), varid(vc), levels ),
"nf90_put_var edge" )
807 vc=vc+1;
call nccheck( nf90_put_var( self%ncid(n), varid(vc), 0 ),
"nf90_put_var time" )
825 type(datetime),
intent(in) :: vdate
827 integer :: var, lev, n, ncid, filei, varid
828 integer,
target :: dimids2_tile(4), dimids3_tile(5), dimidse_tile(5), dimids4_tile(5)
829 integer,
target :: dimids2_noti(3), dimids3_noti(4), dimidse_noti(4), dimids4_noti(4)
830 integer,
pointer :: dimids2(:), dimids3(:), dimidse(:), dimids4(:), dimids(:)
831 integer,
allocatable,
target :: is_r3_tile(:), is_r3_noti(:)
832 real(kind=
kind_real),
allocatable :: arrayg(:,:)
833 integer,
pointer :: istart(:), icount(:)
838 allocate(arrayg(1:geom%npx-1,1:geom%npy-1))
843 allocate(is_r3_tile(
size(self%is_r3_tile)))
844 is_r3_tile = self%is_r3_tile
845 allocate(is_r3_noti(
size(self%is_r3_noti)))
846 is_r3_noti = self%is_r3_noti
851 dimids2_tile = (/ self%x_dimid, self%y_dimid, self%n_dimid, self%t_dimid /)
852 dimids3_tile = (/ self%x_dimid, self%y_dimid, self%n_dimid, self%z_dimid, self%t_dimid /)
853 dimidse_tile = (/ self%x_dimid, self%y_dimid, self%n_dimid, self%e_dimid, self%t_dimid /)
854 dimids4_tile = (/ self%x_dimid, self%y_dimid, self%n_dimid, self%f_dimid, self%t_dimid /)
856 dimids2_noti = (/ self%x_dimid, self%y_dimid, self%t_dimid /)
857 dimids3_noti = (/ self%x_dimid, self%y_dimid, self%z_dimid, self%t_dimid /)
858 dimidse_noti = (/ self%x_dimid, self%y_dimid, self%e_dimid, self%t_dimid /)
859 dimids4_noti = (/ self%x_dimid, self%y_dimid, self%f_dimid, self%t_dimid /)
864 do var = 1,
size(fields)
866 if (self%iam_io_proc)
then
870 filei = self%ncid_forfield(var)
871 ncid = self%ncid(filei)
875 if (self%clobber)
then
877 call nccheck( nf90_redef(ncid),
"nf90_enddef" )
881 if (
associated(dimids2))
nullify(dimids2)
882 if (
associated(dimids3))
nullify(dimids3)
883 if (
associated(dimidse))
nullify(dimidse)
884 if (
associated(dimids4))
nullify(dimids4)
886 if (self%tiledim(filei))
then
887 dimids2 => dimids2_tile
888 dimids3 => dimids3_tile
889 dimidse => dimidse_tile
890 dimids4 => dimids4_tile
892 dimids2 => dimids2_noti
893 dimids3 => dimids3_noti
894 dimidse => dimidse_noti
895 dimids4 => dimids4_noti
898 if (
associated(dimids))
nullify (dimids)
900 if (fields(var)%npz == 1)
then
902 elseif (fields(var)%npz == geom%npz)
then
904 elseif (fields(var)%npz == geom%npz+1)
then
906 elseif (fields(var)%npz == 4)
then
909 call abor1_ftn(
"write_geos: vertical dimension not supported")
913 call nccheck( nf90_def_var(ncid, trim(fields(var)%short_name), nf90_double, dimids, varid), &
914 "nf90_def_var"//trim(fields(var)%short_name))
917 if (self%clobber)
then
920 call nccheck( nf90_put_att(ncid, varid,
"long_name" , trim(fields(var)%long_name) ),
"nf90_put_att" )
921 call nccheck( nf90_put_att(ncid, varid,
"units" , trim(fields(var)%units) ),
"nf90_put_att" )
924 if (.not.self%restart(filei))
then
925 call nccheck( nf90_put_att(ncid, varid,
"standard_name", trim(fields(var)%long_name) ),
"nf90_put_att" )
926 call nccheck( nf90_put_att(ncid, varid,
"coordinates" ,
"lons lats" ),
"nf90_put_att" )
927 call nccheck( nf90_put_att(ncid, varid,
"grid_mapping" ,
"cubed_sphere" ),
"nf90_put_att" )
933 call nccheck( nf90_enddef(ncid),
"nf90_enddef" )
938 call nccheck ( nf90_inq_varid(ncid, trim(fields(var)%short_name), varid), &
939 "nf90_inq_varid "//trim(fields(var)%short_name) )
946 if (
associated(istart))
nullify(istart)
947 if (
associated(icount))
nullify(icount)
949 if (fields(var)%npz == 1)
then
950 if (self%tiledim(filei))
then
951 istart => self%is_r2_tile; icount => self%ic_r2_tile
953 istart => self%is_r2_noti; icount => self%ic_r2_noti
955 elseif (fields(var)%npz > 1)
then
956 if (self%tiledim(filei))
then
957 istart => is_r3_tile; icount => self%ic_r3_tile
959 istart => is_r3_noti; icount => self%ic_r3_noti
965 do lev = 1,fields(var)%npz
967 if (self%csize > 6)
then
968 call gather_tile(geom, self%tcomm, 1, fields(var)%array(geom%isc:geom%iec,geom%jsc:geom%jec,lev), arrayg)
970 arrayg = fields(var)%array(geom%isc:geom%iec,geom%jsc:geom%jec,lev)
973 if (self%iam_io_proc)
then
975 is_r3_tile(self%vindex_tile) = lev
976 is_r3_noti(self%vindex_noti) = lev
978 call nccheck( nf90_put_var( ncid, varid, arrayg, start = istart, count = icount ), &
979 "nf90_put_var "//trim(fields(var)%short_name) )
989 deallocate(is_r3_tile,is_r3_noti)
1001 integer,
intent(in) :: comm
1002 integer,
intent(in) :: nlev
1003 real(kind=
kind_real),
intent(in) :: array_l(geom%isc:geom%iec,geom%jsc:geom%jec,1:nlev)
1004 real(kind=
kind_real),
intent(inout) :: array_g(1:geom%npx-1,1:geom%npy-1,1:nlev)
1006 real(kind=
kind_real),
allocatable :: vector_g(:), vector_l(:)
1007 integer :: comm_size, ierr
1008 integer :: ji, jj, jk, jc, n
1009 integer :: npx_g, npy_g, npx_l, npy_l
1010 integer,
allocatable :: isc_l(:), iec_l(:), jsc_l(:), jec_l(:)
1011 integer,
allocatable :: counts(:), displs(:), vectorcounts(:), vectordispls(:)
1014 call mpi_comm_size(comm, comm_size, ierr)
1017 allocate(counts(comm_size), displs(comm_size))
1026 npx_l = geom%iec-geom%isc+1
1027 npy_l = geom%jec-geom%jsc+1
1030 allocate(isc_l(comm_size), iec_l(comm_size), jsc_l(comm_size), jec_l(comm_size))
1031 call mpi_allgatherv(geom%isc, 1, mpi_int, isc_l, counts, displs, mpi_int, comm, ierr)
1032 call mpi_allgatherv(geom%iec, 1, mpi_int, iec_l, counts, displs, mpi_int, comm, ierr)
1033 call mpi_allgatherv(geom%jsc, 1, mpi_int, jsc_l, counts, displs, mpi_int, comm, ierr)
1034 call mpi_allgatherv(geom%jec, 1, mpi_int, jec_l, counts, displs, mpi_int, comm, ierr)
1035 deallocate(counts,displs)
1038 allocate(vectorcounts(comm_size), vectordispls(comm_size))
1043 vectordispls(jc) = n
1045 do jj = jsc_l(jc),jec_l(jc)
1046 do ji = isc_l(jc),iec_l(jc)
1051 vectorcounts(jc) = n - vectordispls(jc)
1055 allocate(vector_l(npx_l*npy_l*nlev))
1058 do jj = geom%jsc,geom%jec
1059 do ji = geom%isc,geom%iec
1061 vector_l(n) = array_l(ji,jj,jk)
1067 allocate(vector_g(npx_g*npy_g*nlev))
1068 call mpi_gatherv( vector_l, npx_l*npy_l, mpi_double_precision, &
1069 vector_g, vectorcounts, vectordispls, mpi_double_precision, &
1071 deallocate(vector_l,vectorcounts,vectordispls)
1077 do jj = jsc_l(jc),jec_l(jc)
1078 do ji = isc_l(jc),iec_l(jc)
1080 array_g(ji,jj,jk) = vector_g(n)
1085 deallocate(isc_l, iec_l, jsc_l, jec_l)
1087 deallocate(vector_g)
1098 integer,
intent(in) :: comm
1099 integer,
intent(in) :: nlev
1100 real(kind=
kind_real),
intent(in) :: array_g(1:geom%npx-1,1:geom%npy-1,nlev)
1101 real(kind=
kind_real),
intent(inout) :: array_l(geom%isc:geom%iec,geom%jsc:geom%jec,nlev)
1103 real(kind=
kind_real),
allocatable :: vector_g(:), vector_l(:)
1104 integer :: comm_size, ierr
1105 integer :: ji, jj, jk, jc, n
1106 integer :: npx_g, npy_g, npx_l, npy_l
1107 integer,
allocatable :: isc_l(:), iec_l(:), jsc_l(:), jec_l(:)
1108 integer,
allocatable :: counts(:), displs(:), vectorcounts(:), vectordispls(:)
1111 call mpi_comm_size(comm, comm_size, ierr)
1114 allocate(counts(comm_size), displs(comm_size))
1123 npx_l = geom%iec-geom%isc+1
1124 npy_l = geom%jec-geom%jsc+1
1127 allocate(isc_l(comm_size), iec_l(comm_size), jsc_l(comm_size), jec_l(comm_size))
1128 call mpi_allgatherv(geom%isc, 1, mpi_int, isc_l, counts, displs, mpi_int, comm, ierr)
1129 call mpi_allgatherv(geom%iec, 1, mpi_int, iec_l, counts, displs, mpi_int, comm, ierr)
1130 call mpi_allgatherv(geom%jsc, 1, mpi_int, jsc_l, counts, displs, mpi_int, comm, ierr)
1131 call mpi_allgatherv(geom%jec, 1, mpi_int, jec_l, counts, displs, mpi_int, comm, ierr)
1132 deallocate(counts,displs)
1135 allocate(vector_g(npx_g*npy_g*nlev))
1136 allocate(vectorcounts(comm_size), vectordispls(comm_size))
1140 vectordispls(jc) = n
1142 do jj = jsc_l(jc),jec_l(jc)
1143 do ji = isc_l(jc),iec_l(jc)
1145 vector_g(n) = array_g(ji,jj,jk)
1149 vectorcounts(jc) = n - vectordispls(jc)
1151 deallocate(isc_l, iec_l, jsc_l, jec_l)
1154 allocate(vector_l(npx_l*npy_l*nlev))
1156 call mpi_scatterv( vector_g, vectorcounts, vectordispls, mpi_double_precision, &
1157 vector_l, npx_l*npy_l, mpi_double_precision, &
1160 deallocate(vector_g,vectorcounts,vectordispls)
1165 do jj = geom%jsc,geom%jec
1166 do ji = geom%isc,geom%iec
1168 array_l(ji,jj,jk) = vector_l(n)
1172 deallocate(vector_l)
1195 if (self%ncid_isneeded(n))
then
1196 call nccheck ( nf90_open( trim(self%datapath)//
'/'//trim(self%filenames(n)), nf90_nowrite, &
1197 self%ncid(n) ),
"nf90_open"//trim(self%filenames(n)) )
1209 integer :: n, fileopts
1213 if (self%iam_io_proc)
then
1215 if (self%clobber)
then
1217 fileopts = ior(nf90_netcdf4, nf90_mpiio)
1221 if (self%ncid_isneeded(n))
then
1222 call nccheck( nf90_create( trim(self%datapath)//
'/'//trim(self%filenames(n)), fileopts, &
1223 self%ncid(n), comm = self%ocomm, info = mpi_info_null), &
1224 "nf90_create"//trim(self%filenames(n)) )
1233 if (self%ncid_isneeded(n))
then
1234 call nccheck ( nf90_open( trim(self%datapath)//
'/'//trim(self%filenames(n)), nf90_write, &
1235 self%ncid(n) ),
"nf90_open"//trim(self%filenames(n)) )
1255 if (self%iam_io_proc)
then
1257 if (self%ncid_isneeded(n))
then
1258 call nccheck ( nf90_close(self%ncid(n)),
"nf90_close" )
1272 integer :: var, grp, indfile
1274 if (
allocated(self%ncid_forfield))
deallocate(self%ncid_forfield)
1275 allocate(self%ncid_forfield(
size(fields)))
1276 self%ncid_forfield = -1
1277 self%ncid_isneeded = .false.
1281 do var = 1,
size(fields)
1283 select case (trim(fields(var)%short_name))
1285 case(
"vtype",
"stype",
"vfrac")
1287 case(
"U",
"V",
"W",
"PT",
"PKZ",
"PE",
"DZ")
1289 case(
"Q",
"QILS",
"QICN",
"QLLS",
"QLCN",
"CLLS",
"CLCN")
1298 self%ncid_forfield(var) = grp
1299 self%ncid_isneeded(grp) = .true.