101subroutine land_iau_mod_set_control(Land_IAU_Control,fn_nml,input_nml_file, me, mpi_root, &
102 isc, jsc, nx, ny, tile_num, nblks, blksz, &
103 lsoil, lsnow_lsm, dtp, fhour, errmsg, errflg)
106 character(*),
intent(in) :: fn_nml
107 character(len=:),
intent(in),
dimension(:),
pointer :: input_nml_file
108 integer,
intent(in) :: me, mpi_root
109 integer,
intent(in) :: isc, jsc, nx, ny, tile_num, nblks, lsoil, lsnow_lsm
110 integer,
dimension(:),
intent(in) :: blksz
111 real(kind=kind_phys),
intent(in) :: dtp
112 real(kind=kind_phys),
intent(in) :: fhour
113 character(len=*),
intent(out) :: errmsg
114 integer,
intent(out) :: errflg
117 integer :: nlunit = 360
120 character(len=512) :: ioerrmsg
122 character(len=4) :: iosstr
125 logical :: do_land_iau = .false.
126 real(kind=kind_phys) :: land_iau_delthrs = 0
127 character(len=240) :: land_iau_inc_files(7) =
''
128 real(kind=kind_phys) :: land_iau_fhrs(7) = -1
129 logical :: land_iau_filter_increments = .false.
131 integer :: lsoil_incr = 4
132 logical :: land_iau_upd_stc = .false.
133 logical :: land_iau_upd_slc = .false.
134 logical :: land_iau_do_stcsmc_adjustment = .false.
135 real(kind=kind_phys) :: land_iau_min_t_increment = 0.0001
136 real(kind=kind_phys) :: land_iau_min_slc_increment = 0.000001
138 namelist /land_iau_nml/ do_land_iau, land_iau_delthrs, land_iau_inc_files, land_iau_fhrs, &
139 land_iau_filter_increments, lsoil_incr, land_iau_upd_stc, land_iau_upd_slc, &
140 land_iau_do_stcsmc_adjustment, land_iau_min_t_increment, land_iau_min_slc_increment
146#ifdef INTERNAL_FILE_NML
147 read(input_nml_file, nml=land_iau_nml, err=888,
END=999, iostat=ios)
149 inquire (file=trim(fn_nml), exist=exists)
150 if (.not. exists)
then
151 errmsg =
'lnd_iau_mod_set_control: namelist file '//trim(fn_nml)//
' does not exist'
155 land_iau_control%fn_nml = trim(fn_nml)
156 open (unit=nlunit, file=trim(fn_nml), action=
'READ', status=
'OLD', iostat=ios, iomsg=ioerrmsg)
158 read (nlunit, nml=land_iau_nml, err=888,
END=999, iostat=ios)
161 errmsg =
'lnd_iau_mod_set_control: error reading namelist file '//trim(fn_nml) &
162 //
'the error message from file handler:' //trim(ioerrmsg)
169888
if (ios /= 0)
then
170 write(iosstr,
'(I0)') ios
171 errmsg =
'lnd_iau_mod_set_control: I/O error code '//trim(iosstr)//
' at land_iau namelist read'
173#ifndef INTERNAL_FILE_NML
179999
if (ios /= 0)
then
180 write(iosstr,
'(I0)') ios
181 if (me == mpi_root)
then
182 WRITE(6, * )
'lnd_iau_mod_set_control: Warning! EoF ('//trim(iosstr)//
') while reading land_iau namelist,' &
183 //
' likely because land_iau_nml was not found in input.nml. It will be set to default.'
185#ifndef INTERNAL_FILE_NML
190 if (me == mpi_root)
then
191 write(6,*)
"land_iau_nml"
192 write(6, land_iau_nml)
195 land_iau_control%do_land_iau = do_land_iau
196 land_iau_control%iau_delthrs = land_iau_delthrs
197 land_iau_control%iau_inc_files = land_iau_inc_files
198 land_iau_control%iaufhrs = land_iau_fhrs
199 land_iau_control%iau_filter_increments = land_iau_filter_increments
200 land_iau_control%lsoil_incr = lsoil_incr
202 land_iau_control%me = me
203 land_iau_control%mpi_root = mpi_root
204 land_iau_control%isc = isc
205 land_iau_control%jsc = jsc
206 land_iau_control%nx = nx
207 land_iau_control%ny = ny
208 land_iau_control%tile_num = tile_num
209 land_iau_control%nblks = nblks
210 land_iau_control%lsoil = lsoil
211 land_iau_control%lsnow_lsm = lsnow_lsm
212 land_iau_control%dtp = dtp
213 land_iau_control%fhour = fhour
215 land_iau_control%upd_stc = land_iau_upd_stc
216 land_iau_control%upd_slc = land_iau_upd_slc
217 land_iau_control%do_stcsmc_adjustment = land_iau_do_stcsmc_adjustment
218 land_iau_control%min_T_increment = land_iau_min_t_increment
219 land_iau_control%min_SLC_increment = land_iau_min_slc_increment
221 allocate(land_iau_control%blksz(nblks))
222 allocate(land_iau_control%blk_strt_indx(nblks))
228 land_iau_control%blksz(nb) = blksz(nb)
229 land_iau_control%blk_strt_indx(nb) = ix
235subroutine land_iau_mod_init (Land_IAU_Control, Land_IAU_Data, Land_IAU_State, errmsg, errflg)
239 character(len=*),
intent( out) :: errmsg
240 integer,
intent( out) :: errflg
243 character(len=128) :: fname
244 real(kind=kind_phys) :: sx, wx, wt, normfact, dtp
245 integer :: k, nstep, kstep
246 integer :: nfilesall, ntimesall
247 integer,
allocatable :: idt(:)
248 integer :: nlon, nlat
250 integer :: ncid, dimid, varid, status, idim
252 real(kind=kind_phys) :: dt
253 integer :: im, jm, km, nfiles, ntimes
255 integer :: is, ie, js, je
263 npz = land_iau_control%lsoil
264 km = land_iau_control%lsoil
266 is = land_iau_control%isc
267 ie = is + land_iau_control%nx-1
268 js = land_iau_control%jsc
269 je = js + land_iau_control%ny-1
270 nlon = land_iau_control%nx
271 nlat = land_iau_control%ny
274 allocate(land_iau_data%stc_inc(nlon, nlat, km))
275 allocate(land_iau_data%slc_inc(nlon, nlat, km))
277 land_iau_data%hr1=land_iau_control%iaufhrs(1)
278 land_iau_data%wt = 1.0
279 land_iau_data%wt_normfact = 1.0
280 if (land_iau_control%iau_filter_increments)
then
282 dtp=land_iau_control%dtp
283 nstep = 0.5*land_iau_control%iau_delthrs*3600/dtp
288 sx = acos(-1.)*kstep/nstep
289 wx = acos(-1.)*kstep/(nstep+1)
290 if (kstep .ne. 0)
then
291 wt = sin(wx)/wx*sin(sx)/sx
295 normfact = normfact + wt
296 if (land_iau_control%me == land_iau_control%mpi_root)
then
297 print *,
'Land IAU init: IAU filter weights params k, kstep, wt ',k, kstep, wt
300 land_iau_data%wt_normfact = (2*nstep+1)/normfact
304 if (trim(land_iau_control%iau_inc_files(1)) .eq.
'' .or. land_iau_control%iaufhrs(1) .lt. 0)
then
305 errmsg =
"Error! in Land IAU init: increment file name is empty or iaufhrs(1) is negative"
309 if (land_iau_control%me == land_iau_control%mpi_root)
then
310 print*,
"Land_iau_init: Increment file name: ", trim(adjustl(land_iau_control%iau_inc_files(1)))
314 if (land_iau_control%me == land_iau_control%mpi_root)
then
315 print *,
"Land_iau_init: timesetps and forecast times (in hours) with valid increment values"
317 ntimesall =
size(land_iau_control%iaufhrs)
320 if (land_iau_control%iaufhrs(k) .lt. 0)
exit
321 if (land_iau_control%me == land_iau_control%mpi_root)
then
322 print *,k,
" fhour ", land_iau_control%iaufhrs(k)
327 land_iau_control%ntimes = ntimes
329 errmsg =
"Error! in Land IAU init: ntimes < 1 (no valid hour with increments); do_land_iau should not be .true."
334 allocate(idt(ntimes-1))
335 idt = land_iau_control%iaufhrs(2:ntimes)-land_iau_control%iaufhrs(1:ntimes-1)
337 if (idt(k) .ne. land_iau_control%iaufhrs(2)-land_iau_control%iaufhrs(1))
then
338 errmsg =
'Fatal error in land_iau_init. forecast intervals in iaufhrs must be constant'
345 dt = (land_iau_control%iau_delthrs*3600.)
346 land_iau_data%rdt = 1.0/dt
350 call read_iau_forcing_fv3(land_iau_control, land_iau_state%stc_inc, land_iau_state%slc_inc, errmsg, errflg)
351 if (errflg .ne. 0)
return
353 if (ntimes.EQ.1)
then
354 call setiauforcing(land_iau_control, land_iau_data, land_iau_state)
355 land_iau_data%itnext = 0
357 if (ntimes.GT.1)
then
360 land_iau_data%hr2=land_iau_control%iaufhrs(2)
361 land_iau_data%itnext = 2
388 subroutine land_iau_mod_getiauforcing(Land_IAU_Control, Land_IAU_Data, Land_IAU_State, errmsg, errflg)
394 character(len=*),
intent(out) :: errmsg
395 integer,
intent(out) :: errflg
396 real(kind=kind_phys) t1,t2,sx,wx,wt,dtp
397 integer n,i,j,k,kstep,nstep
404 ntimes = land_iau_control%ntimes
406 land_iau_data%in_interval=.false.
407 if (ntimes.LE.0)
then
408 errmsg =
'called land_iau_mod_getiauforcing, but ntimes <=0, probably there is no increment file. Exiting.'
413 if (ntimes .eq. 1)
then
414 t1 = land_iau_control%iaufhrs(1)-0.5*land_iau_control%iau_delthrs
415 t2 = land_iau_control%iaufhrs(1)+0.5*land_iau_control%iau_delthrs
417 t1 = land_iau_control%iaufhrs(1)
418 t2 = land_iau_control%iaufhrs(ntimes)
420 if (land_iau_control%iau_filter_increments)
then
424 dtp=land_iau_control%dtp
425 nstep = 0.5*land_iau_control%iau_delthrs*3600/dtp
427 kstep = ((land_iau_control%fhour-t1) - 0.5*land_iau_control%iau_delthrs)*3600./dtp
428 if (land_iau_control%fhour >= t1 .and. land_iau_control%fhour < t2)
then
429 sx = acos(-1.)*kstep/nstep
430 wx = acos(-1.)*kstep/(nstep+1)
431 if (kstep .ne. 0)
then
432 wt = (sin(wx)/wx*sin(sx)/sx)
436 land_iau_data%wt = land_iau_data%wt_normfact*wt
438 land_iau_data%wt = 0.
442 if (ntimes.EQ.1)
then
444 if ( land_iau_control%fhour <= t1 .or. land_iau_control%fhour > t2 )
then
445 land_iau_data%in_interval=.false.
447 land_iau_data%in_interval=.true.
448 if (land_iau_control%me == land_iau_control%mpi_root)
then
449 print *,
'land_iau_mod_getiauforcing: applying forcing at t for t1,t,t2,filter wt rdt ', &
450 t1,land_iau_control%fhour,t2,land_iau_data%wt/land_iau_data%wt_normfact,land_iau_data%rdt
452 if (land_iau_control%iau_filter_increments)
call setiauforcing(land_iau_control, land_iau_data, land_iau_state)
458 if ( land_iau_control%fhour <= t1 .or. land_iau_control%fhour > t2 )
then
459 land_iau_data%in_interval=.false.
461 land_iau_data%in_interval=.true.
462 if (land_iau_control%me == land_iau_control%mpi_root)
then
463 print *,
'land_iau_mod_getiauforcing: applying forcing at t for t1,t,t2,filter wt rdt ', &
464 t1,land_iau_control%fhour,t2,land_iau_data%wt/land_iau_data%wt_normfact,land_iau_data%rdt
466 if (land_iau_control%fhour > land_iau_data%hr2)
then
467 land_iau_data%itnext = land_iau_data%itnext + 1
468 land_iau_data%hr1=land_iau_data%hr2
469 land_iau_data%hr2=land_iau_control%iaufhrs(land_iau_data%itnext)
472 call updateiauforcing(land_iau_control, land_iau_data, land_iau_state)
478subroutine updateiauforcing(Land_IAU_Control, Land_IAU_Data, Land_IAU_State)
482 type (land_iau_control_type),
intent(in) :: Land_IAU_Control
485 real(kind=kind_phys) delt_t
487 integer :: is, ie, js, je, npz, t1, t2
489 t2 = land_iau_data%itnext
492 ie = is + land_iau_control%nx-1
494 je = js + land_iau_control%ny-1
495 npz = land_iau_control%lsoil
497 delt_t = (land_iau_data%hr2-(land_iau_control%fhour))/(land_iau_data%hr2-land_iau_data%hr1)
502 land_iau_data%stc_inc(i,j,k) =(delt_t*land_iau_state%stc_inc(t1,i,j,k) + (1.-delt_t)* land_iau_state%stc_inc(t2,i,j,k))*land_iau_data%rdt*land_iau_data%wt
503 land_iau_data%slc_inc(i,j,k) =(delt_t*land_iau_state%slc_inc(t1,i,j,k) + (1.-delt_t)* land_iau_state%slc_inc(t2,i,j,k))*land_iau_data%rdt*land_iau_data%wt
509 subroutine setiauforcing(Land_IAU_Control, Land_IAU_Data, Land_IAU_State)
515 real(kind=kind_phys) delt
517 integer :: is, ie, js, je, npz
520 ie = is + land_iau_control%nx-1
522 je = js + land_iau_control%ny-1
523 npz = land_iau_control%lsoil
528 land_iau_data%stc_inc(i,j,k) = land_iau_data%wt*land_iau_state%stc_inc(1,i,j,k)*land_iau_data%rdt
529 land_iau_data%slc_inc(i,j,k) = land_iau_data%wt*land_iau_state%slc_inc(1,i,j,k)*land_iau_data%rdt
536subroutine read_iau_forcing_fv3(Land_IAU_Control, wk3_stc, wk3_slc, errmsg, errflg)
538 type (land_iau_control_type),
intent(in) :: Land_IAU_Control
539 real(kind=kind_phys),
allocatable,
intent(out) :: wk3_stc(:, :, :, :), wk3_slc(:, :, :, :)
540 character(len=*),
intent(inout) :: errmsg
541 integer,
intent(inout) :: errflg
545 integer :: ncid, status, varid
547 character(len=500) :: fname
548 character(len=2) :: tile_str
549 integer :: n_t, n_y, n_x
551 character(len=32),
dimension(4) :: stc_vars = [character(len=32) ::
'soilt1_inc',
'soilt2_inc',
'soilt3_inc',
'soilt4_inc']
552 character(len=32),
dimension(4) :: slc_vars = [character(len=32) ::
'slc1_inc',
'slc2_inc',
'slc3_inc',
'slc4_inc']
553 character(len=32) :: slsn_mask =
"soilsnow_mask"
559 km = land_iau_control%lsoil
561 write(tile_str,
'(I0)') land_iau_control%tile_num
563 fname =
'INPUT/'//trim(land_iau_control%iau_inc_files(1))//
".tile"//trim(tile_str)//
".nc"
565 inquire (file=trim(fname), exist=exists)
567 status = nf90_open(trim(fname), nf90_nowrite, ncid)
568 call netcdf_err(status,
' opening file '//trim(fname), errflg, errmsg)
569 if (errflg .ne. 0)
return
571 errmsg =
'FATAL Error in land iau read_iau_forcing_fv3: Expected file '//trim(fname)//
' for DA increment does not exist'
576 call get_nc_dimlen(ncid,
"Time", n_t, errflg, errmsg)
577 if (errflg .ne. 0)
return
578 call get_nc_dimlen(ncid,
"yaxis_1", n_y, errflg, errmsg)
579 if (errflg .ne. 0)
return
580 call get_nc_dimlen(ncid,
"xaxis_1", n_x, errflg, errmsg)
581 if (errflg .ne. 0)
return
583 if (n_x .lt. land_iau_control%nx)
then
584 errmsg =
'Error in land iau read_iau_forcing_fv3: Land_IAU_Control%nx bigger than dim xaxis_1 in file '//trim(fname)
588 if (n_y .lt. land_iau_control%ny)
then
589 errmsg =
'Error in land iau read_iau_forcing_fv3: Land_IAU_Control%ny bigger than dim yaxis_1 in file '//trim(fname)
594 allocate(wk3_stc(n_t, land_iau_control%nx, land_iau_control%ny, km))
595 allocate(wk3_slc(n_t, land_iau_control%nx, land_iau_control%ny, km))
597 do i = 1,
size(stc_vars)
598 if (land_iau_control%me == land_iau_control%mpi_root) print *, trim(stc_vars(i))
599 status = nf90_inq_varid(ncid, trim(stc_vars(i)), varid)
600 if (status == nf90_noerr)
then
603 call get_var3d_values(ncid, varid, trim(stc_vars(i)), land_iau_control%isc, land_iau_control%nx, land_iau_control%jsc, land_iau_control%ny, &
604 it, 1, wk3_stc(it,:, :, i), status, errflg, errmsg)
605 if (errflg .ne. 0)
return
608 if (land_iau_control%me == land_iau_control%mpi_root)
then
609 print *,
'warning! No increment for ',trim(stc_vars(i)),
' found, assuming zero'
611 wk3_stc(:, :, :, i) = 0.
614 do i = 1,
size(slc_vars)
615 if (land_iau_control%me == land_iau_control%mpi_root) print *, trim(slc_vars(i))
616 status = nf90_inq_varid(ncid, trim(slc_vars(i)), varid)
617 if (status == nf90_noerr)
then
619 call get_var3d_values(ncid, varid, trim(slc_vars(i)), land_iau_control%isc, land_iau_control%nx, land_iau_control%jsc, land_iau_control%ny, &
620 it, 1, wk3_slc(it, :, :, i), status, errflg, errmsg)
621 if (errflg .ne. 0)
return
624 if (land_iau_control%me == land_iau_control%mpi_root)
then
625 print *,
'warning! No increment for ',trim(slc_vars(i)),
' found, assuming zero'
627 wk3_slc(:, :, :, i) = 0.
632 where(abs(wk3_stc) < land_iau_control%min_T_increment) wk3_stc = 0.0
633 where(abs(wk3_slc) < land_iau_control%min_SLC_increment) wk3_slc = 0.0
635 status =nf90_close(ncid)
636 call netcdf_err(status,
'closing file '//trim(fname), errflg, errmsg)
707 subroutine get_nc_dimlen(ncid, dim_name, dim_len, errflg, errmsg_out )
708 integer,
intent(in):: ncid
709 character(len=*),
intent(in):: dim_name
710 integer,
intent(out):: dim_len
713 character(len=*) :: errmsg_out
720 status = nf90_inq_dimid(ncid, dim_name, dimid)
721 CALL netcdf_err(status,
'reading dim id '//trim(dim_name), errflg, errmsg_out)
722 if (errflg .ne. 0)
return
723 status = nf90_inquire_dimension(ncid, dimid, len = dim_len)
724 CALL netcdf_err(status,
'reading dim length '//trim(dim_name), errflg, errmsg_out)
728 subroutine get_var1d(ncid, dim_len, var_name, var_arr, errflg, errmsg_out)
729 integer,
intent(in):: ncid, dim_len
730 character(len=*),
intent(in):: var_name
731 real(kind=kind_phys),
intent(out):: var_arr(dim_len)
733 character(len=*) :: errmsg_out
734 integer :: varid, status
740 status = nf90_inq_varid(ncid, trim(var_name), varid)
741 call netcdf_err(status,
'getting varid: '//trim(var_name), errflg, errmsg_out)
742 if (errflg .ne. 0)
return
744 status = nf90_get_var(ncid, varid, var_arr)
745 call netcdf_err(status,
'reading var: '//trim(var_name), errflg, errmsg_out)
749 subroutine get_var3d_values(ncid, varid, var_name, is,ix, js,jy, ks,kz, var3d, status, errflg, errmsg_out)
750 integer,
intent(in):: ncid, varid
751 integer,
intent(in):: is, ix, js, jy, ks,kz
752 character(len=*),
intent(in):: var_name
753 real(kind=kind_phys),
intent(out):: var3d(ix, jy, kz)
754 integer,
intent(out):: status
756 character(len=*) :: errmsg_out
762 status = nf90_get_var(ncid, varid, var3d, &
763 start = (/is, js, ks/), count = (/ix, jy, kz/))
765 call netcdf_err(status,
'get_var3d_values '//trim(var_name), errflg, errmsg_out)
770 subroutine get_var3d_values_int(ncid, varid, var_name, is,ix, js,jy, ks,kz, var3d, status, errflg, errmsg_out)
771 integer,
intent(in):: ncid, varid
772 integer,
intent(in):: is, ix, js, jy, ks,kz
773 character(len=*),
intent(in):: var_name
774 integer,
intent(out):: var3d(ix, jy, kz)
775 integer,
intent(out):: status
777 character(len=*) :: errmsg_out
783 status = nf90_get_var(ncid, varid, var3d, &
784 start = (/is, js, ks/), count = (/ix, jy, kz/))
786 call netcdf_err(status,
'get_var3d_values_int '//trim(var_name), errflg, errmsg_out)