CCPP SciDoc v7.0.x  v7.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
lnd_iau_mod.F90
1!***********************************************************************
3!* GNU Lesser General Public License
4!* <http://www.gnu.org/licenses/>.
5!***********************************************************************
6
9
10!! \section land_iau_mod
16
19!-------------------------------------------------------------------------------
20
25
26 use machine, only: kind_phys, kind_dyn
27 use netcdf
28
29 implicit none
30
31 private
32
37 real(kind=kind_phys),allocatable :: stc_inc(:,:,:)
38 real(kind=kind_phys),allocatable :: slc_inc(:,:,:)
39 logical :: in_interval = .false.
40 real(kind=kind_phys) :: hr1
41 real(kind=kind_phys) :: hr2
42 real(kind=kind_phys) :: wt
43 real(kind=kind_phys) :: wt_normfact
44 real(kind=kind_phys) :: rdt
45 integer :: itnext ! track the increment steps here
47
48!!> \section arg_table_land_iau_state_type Argument Table
49!! \htmlinclude land_iau_state_type.html
50!!
51 ! land_iau_state_type holds 'raw' (not interpolated) inrements,
52 ! read during land_iau_mod_init
54 real(kind=kind_phys),allocatable :: stc_inc(:,:,:,:)
55 real(kind=kind_phys),allocatable :: slc_inc(:,:,:,:)
56 end type land_iau_state_type
57
58
59!!!> \section arg_table_land_iau_control_type Argument Table
60!! \htmlinclude land_iau_control_type.html
61!!
63 integer :: isc
64 integer :: jsc
65 integer :: nx
66 integer :: ny
67 integer :: tile_num
68 integer :: nblks
69 integer, allocatable :: blksz(:) ! this could vary for the last block
70 integer, allocatable :: blk_strt_indx(:)
71
72 integer :: lsoil
73 integer :: lsnow_lsm
74 logical :: do_land_iau
75 real(kind=kind_phys) :: iau_delthrs ! iau time interval (to scale increments) in hours
76 character(len=240) :: iau_inc_files(7) ! list of increment files
77 real(kind=kind_phys) :: iaufhrs(7) ! forecast hours associated with increment files
78 logical :: iau_filter_increments
79 integer :: lsoil_incr ! soil layers (from top) updated by DA
80 logical :: upd_stc
81 logical :: upd_slc
82 logical :: do_stcsmc_adjustment !do moisture/temperature adjustment for consistency after increment add
83 real(kind=kind_phys) :: min_t_increment
84 real(kind=kind_phys) :: min_slc_increment
85
86 integer :: me
87 integer :: mpi_root
88 character(len=64) :: fn_nml
89 real(kind=kind_phys) :: dtp
90 real(kind=kind_phys) :: fhour
91
92 integer :: ntimes
93
95
97 land_iau_mod_init, land_iau_mod_getiauforcing, land_iau_mod_finalize, calculate_landinc_mask
98
99contains
100
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)
104
105 type (land_iau_control_type), intent(inout) :: land_iau_control
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 !(one:) !GFS_Control%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
115
116 integer :: nb, ix
117 integer :: nlunit = 360 ! unit for namelist !, intent(in)
118 integer :: ios
119 logical :: exists
120 character(len=512) :: ioerrmsg
121
122 character(len=4) :: iosstr
123
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.
130
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
137
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
141 !Errors messages handled through CCPP error handling variables
142 errmsg = ''
143 errflg = 0
144
145!3.11.24: copied from GFS_typedefs.F90
146#ifdef INTERNAL_FILE_NML
147 read(input_nml_file, nml=land_iau_nml, err=888, END=999, iostat=ios)
148#else
149 inquire (file=trim(fn_nml), exist=exists) ! TODO: this maybe be replaced by nlunit passed from ccpp
150 if (.not. exists) then
151 errmsg = 'lnd_iau_mod_set_control: namelist file '//trim(fn_nml)//' does not exist'
152 errflg = 1
153 return
154 else
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)
157 rewind(nlunit)
158 read (nlunit, nml=land_iau_nml, err=888, END=999, iostat=ios)
159 close (nlunit)
160 if (ios /= 0) then
161 errmsg = 'lnd_iau_mod_set_control: error reading namelist file '//trim(fn_nml) &
162 // 'the error message from file handler:' //trim(ioerrmsg)
163 errflg = 1
164 return
165 end if
166 endif
167#endif
168
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'
172 errflg = 1
173#ifndef INTERNAL_FILE_NML
174 close(nlunit)
175#endif
176 return
177 end if
178
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.'
184 endif
185#ifndef INTERNAL_FILE_NML
186 close(nlunit)
187#endif
188 endif
189
190 if (me == mpi_root) then
191 write(6,*) "land_iau_nml"
192 write(6, land_iau_nml)
193 endif
194
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
201
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
214
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
220
221 allocate(land_iau_control%blksz(nblks))
222 allocate(land_iau_control%blk_strt_indx(nblks))
223
224 ! Land_IAU_Control%blk_strt_indx = start index of each block, for flattened (ncol=nx*ny) arrays
225 ! It's required in noahmpdriv_run to get subsection of the stc array for each proces/thread
226 ix = 1
227 do nb=1, nblks
228 land_iau_control%blksz(nb) = blksz(nb)
229 land_iau_control%blk_strt_indx(nb) = ix
230 ix = ix + blksz(nb)
231 enddo
232
233end subroutine land_iau_mod_set_control
234
235subroutine land_iau_mod_init (Land_IAU_Control, Land_IAU_Data, Land_IAU_State, errmsg, errflg)
236 type (land_iau_control_type), intent(inout) :: land_iau_control
237 type (land_iau_external_data_type), intent(inout) :: land_iau_data
238 type(land_iau_state_type), intent(inout) :: land_iau_state
239 character(len=*), intent( out) :: errmsg
240 integer, intent( out) :: errflg
241
242 ! local
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
249 logical :: exists
250 integer :: ncid, dimid, varid, status, idim
251
252 real(kind=kind_phys) :: dt !, rdt
253 integer :: im, jm, km, nfiles, ntimes
254
255 integer :: is, ie, js, je
256 integer :: npz
257 integer :: i, j
258
259 !Errors messages handled through CCPP error handling variables
260 errmsg = ''
261 errflg = 0
262
263 npz = land_iau_control%lsoil
264 km = land_iau_control%lsoil
265
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
272
273 ! allocate arrays that will hold iau state
274 allocate(land_iau_data%stc_inc(nlon, nlat, km))
275 allocate(land_iau_data%slc_inc(nlon, nlat, km))
276
277 land_iau_data%hr1=land_iau_control%iaufhrs(1)
278 land_iau_data%wt = 1.0 ! IAU increment filter weights (default 1.0)
279 land_iau_data%wt_normfact = 1.0
280 if (land_iau_control%iau_filter_increments) then
281 ! compute increment filter weights, sum to obtain normalization factor
282 dtp=land_iau_control%dtp
283 nstep = 0.5*land_iau_control%iau_delthrs*3600/dtp
284 ! compute normalization factor for filter weights
285 normfact = 0.
286 do k=1,2*nstep+1
287 kstep = k-1-nstep
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
292 else
293 wt = 1.0
294 endif
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
298 endif
299 enddo
300 land_iau_data%wt_normfact = (2*nstep+1)/normfact
301 endif
302
303 ! increment files are in fv3 tiles
304 if (trim(land_iau_control%iau_inc_files(1)) .eq. '' .or. land_iau_control%iaufhrs(1) .lt. 0) then ! only 1 file expected
305 errmsg = "Error! in Land IAU init: increment file name is empty or iaufhrs(1) is negative"
306 errflg = 1
307 return
308 endif
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)))
311 endif
312
313 ! determine number of valid forecast hours; read from the increment file ("Time" dim)
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"
316 endif
317 ntimesall = size(land_iau_control%iaufhrs)
318 ntimes = 0
319 do k=1,ntimesall
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)
323 endif
324 ntimes = ntimes + 1
325 enddo
326
327 land_iau_control%ntimes = ntimes
328 if (ntimes < 1) then
329 errmsg = "Error! in Land IAU init: ntimes < 1 (no valid hour with increments); do_land_iau should not be .true."
330 errflg = 1
331 return
332 endif
333 if (ntimes > 1) then
334 allocate(idt(ntimes-1))
335 idt = land_iau_control%iaufhrs(2:ntimes)-land_iau_control%iaufhrs(1:ntimes-1)
336 do k=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'
339 errflg = 1
340 return
341 endif
342 enddo
343 deallocate(idt)
344 endif
345 dt = (land_iau_control%iau_delthrs*3600.)
346 land_iau_data%rdt = 1.0/dt !rdt
347
348 ! Read all increment files at iau init time (at beginning of cycle)
349 ! increments are already in the fv3 grid--no need for interpolation
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
352
353 if (ntimes.EQ.1) then ! only need to get incrments once since constant forcing over window
354 call setiauforcing(land_iau_control, land_iau_data, land_iau_state)
355 land_iau_data%itnext = 0
356 endif
357 if (ntimes.GT.1) then !have increments at multiple forecast hours,
358 ! but only need 2 at a time and interpoalte for timesteps between them
359 ! interpolation is done in land_iau_mod_getiauforcing
360 land_iau_data%hr2=land_iau_control%iaufhrs(2)
361 land_iau_data%itnext = 2
362 endif
363
364end subroutine land_iau_mod_init
365
366subroutine land_iau_mod_finalize(Land_IAU_Control, Land_IAU_Data, Land_IAU_state, errmsg, errflg)
367
368 implicit none
369
370 type(land_iau_control_type), intent(in) :: land_iau_control
371 type(land_iau_external_data_type), intent(inout) :: land_iau_data
372 type(land_iau_state_type), intent(inout) :: land_iau_state
373 character(len=*), intent(out) :: errmsg
374 integer, intent(out) :: errflg
375
376 ! Initialize CCPP error handling variables
377 errmsg = ''
378 errflg = 0
379
380 if (allocated(land_iau_data%stc_inc)) deallocate (land_iau_data%stc_inc)
381 if (allocated(land_iau_data%slc_inc)) deallocate (land_iau_data%slc_inc)
382
383 if (allocated(land_iau_state%stc_inc)) deallocate(land_iau_state%stc_inc)
384 if (allocated(land_iau_state%slc_inc)) deallocate(land_iau_state%slc_inc)
385
386end subroutine land_iau_mod_finalize
387
388 subroutine land_iau_mod_getiauforcing(Land_IAU_Control, Land_IAU_Data, Land_IAU_State, errmsg, errflg)
389
390 implicit none
391 type(land_iau_control_type), intent(inout) :: land_iau_control
392 type(land_iau_external_data_type), intent(inout) :: land_iau_data
393 type(land_iau_state_type), intent(in) :: land_iau_state
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
398 integer :: ntimes
399
400 ! Initialize CCPP error handling variables
401 errmsg = ''
402 errflg = 0
403
404 ntimes = land_iau_control%ntimes
405
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.'
409 errflg = 1
410 return
411 endif
412
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
416 else
417 t1 = land_iau_control%iaufhrs(1)
418 t2 = land_iau_control%iaufhrs(ntimes)
419 endif
420 if (land_iau_control%iau_filter_increments) then
421 ! compute increment filter weight
422 ! t1 is beginning of window, t2 end of window, and Land_IAU_Control%fhour is current time
423 ! in window kstep=-nstep,nstep (2*nstep+1 total) with time step of Land_IAU_Control%dtp
424 dtp=land_iau_control%dtp
425 nstep = 0.5*land_iau_control%iau_delthrs*3600/dtp
426 ! compute normalized filter weight
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)
433 else
434 wt = 1.
435 endif
436 land_iau_data%wt = land_iau_data%wt_normfact*wt
437 else
438 land_iau_data%wt = 0.
439 endif
440 endif
441
442 if (ntimes.EQ.1) then
443 ! check to see if we are in the IAU window, no need to update the states since they are fixed over the window
444 if ( land_iau_control%fhour <= t1 .or. land_iau_control%fhour > t2 ) then
445 land_iau_data%in_interval=.false.
446 else
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
451 endif
452 if (land_iau_control%iau_filter_increments) call setiauforcing(land_iau_control, land_iau_data, land_iau_state)
453 endif
454 return
455 endif
456
457 if (ntimes > 1) then
458 if ( land_iau_control%fhour <= t1 .or. land_iau_control%fhour > t2 ) then
459 land_iau_data%in_interval=.false.
460 else
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
465 endif
466 if (land_iau_control%fhour > land_iau_data%hr2) then ! need to read in next increment file
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)
470 endif
471
472 call updateiauforcing(land_iau_control, land_iau_data, land_iau_state)
473 endif
474 endif
475
476 end subroutine land_iau_mod_getiauforcing
477
478subroutine updateiauforcing(Land_IAU_Control, Land_IAU_Data, Land_IAU_State)
479
480 implicit none
481
482 type (land_iau_control_type), intent(in) :: Land_IAU_Control
483 type(land_iau_external_data_type), intent(inout) :: Land_IAU_Data
484 type(land_iau_state_type), intent(in) :: Land_IAU_State
485 real(kind=kind_phys) delt_t
486 integer i,j,k
487 integer :: is, ie, js, je, npz, t1, t2
488
489 t2 = land_iau_data%itnext
490 t1 = t2 - 1
491 is = 1 ! Land_IAU_Control%isc
492 ie = is + land_iau_control%nx-1
493 js = 1 ! Land_IAU_Control%jsc
494 je = js + land_iau_control%ny-1
495 npz = land_iau_control%lsoil
496
497 delt_t = (land_iau_data%hr2-(land_iau_control%fhour))/(land_iau_data%hr2-land_iau_data%hr1)
498
499 do j = js,je
500 do i = is,ie
501 do k = 1,npz ! do k = 1,n_soill !
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
504 end do
505 enddo
506 enddo
507 end subroutine updateiauforcing
508
509 subroutine setiauforcing(Land_IAU_Control, Land_IAU_Data, Land_IAU_State)
510
511 implicit none
512 type(land_iau_control_type), intent(in ) :: Land_IAU_Control
513 type(land_iau_external_data_type), intent(inout) :: Land_IAU_Data
514 type(land_iau_state_type), intent(in ) :: Land_IAU_State
515 real(kind=kind_phys) delt
516 integer i, j, k
517 integer :: is, ie, js, je, npz
518
519 is = 1
520 ie = is + land_iau_control%nx-1
521 js = 1
522 je = js + land_iau_control%ny-1
523 npz = land_iau_control%lsoil
524
525 do j = js, je
526 do i = is, ie
527 do k = 1, npz
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
530 end do
531 enddo
532 enddo
533
534 end subroutine setiauforcing
535
536subroutine read_iau_forcing_fv3(Land_IAU_Control, wk3_stc, wk3_slc, errmsg, errflg)
537
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
542
543 integer :: i, it, km
544 logical :: exists
545 integer :: ncid, status, varid
546 integer :: ierr
547 character(len=500) :: fname
548 character(len=2) :: tile_str
549 integer :: n_t, n_y, n_x
550
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"
554
555 !Errors messages handled through CCPP error handling variables
556 errmsg = ''
557 errflg = 0
558
559 km = land_iau_control%lsoil
560
561 write(tile_str, '(I0)') land_iau_control%tile_num
562
563 fname = 'INPUT/'//trim(land_iau_control%iau_inc_files(1))//".tile"//trim(tile_str)//".nc"
564
565 inquire (file=trim(fname), exist=exists)
566 if (exists) then
567 status = nf90_open(trim(fname), nf90_nowrite, ncid) ! open the file
568 call netcdf_err(status, ' opening file '//trim(fname), errflg, errmsg)
569 if (errflg .ne. 0) return
570 else
571 errmsg = 'FATAL Error in land iau read_iau_forcing_fv3: Expected file '//trim(fname)//' for DA increment does not exist'
572 errflg = 1
573 return
574 endif
575 ! var stored as soilt1_inc(Time, yaxis_1, xaxis_1)
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
582
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)
585 errflg = 1
586 return
587 endif
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)
590 errflg = 1
591 return
592 endif
593
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))
596
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
601 do it = 1, n_t
602 ! var stored as soilt1_inc(Time, yaxis_1, xaxis_1)
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
606 enddo
607 else
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'
610 endif
611 wk3_stc(:, :, :, i) = 0.
612 endif
613 enddo
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
618 do it = 1, n_t
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
622 end do
623 else
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'
626 endif
627 wk3_slc(:, :, :, i) = 0.
628 endif
629 enddo
630
631 !set too small increments to zero
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
634
635 status =nf90_close(ncid)
636 call netcdf_err(status, 'closing file '//trim(fname), errflg, errmsg)
637
638end subroutine read_iau_forcing_fv3
639
651 subroutine calculate_landinc_mask(swe,vtype,stype,lensfc,veg_type_landice, mask)
652
653 implicit none
654
655 integer, intent(in) :: lensfc, veg_type_landice
656 real(kind=kind_phys), intent(in) :: swe(lensfc)
657 integer, intent(in) :: vtype(lensfc),stype(lensfc)
658 integer, intent(out) :: mask(lensfc)
659
660 integer :: i
661
662 mask = -1 ! not land
663
664 ! land (but not land-ice)
665 do i=1,lensfc
666 if (stype(i) .GT. 0) then
667 if (swe(i) .GT. 0.001) then ! snow covered land
668 mask(i) = 2
669 else ! non-snow covered land
670 mask(i) = 1
671 endif
672 end if ! else should work here too
673 if ( vtype(i) == veg_type_landice ) then ! land-ice
674 mask(i) = 0
675 endif
676 end do
677
678 end subroutine calculate_landinc_mask
679
680 subroutine netcdf_err(ERR, STRING, errflg, errmsg_out)
681
682 !--------------------------------------------------------------
683 ! Process the error flag from a NETCDF call and return it as (human readable) MESSAGE
684 !--------------------------------------------------------------
685 IMPLICIT NONE
686
687 include 'mpif.h'
688
689 INTEGER, INTENT(IN) :: ERR
690 CHARACTER(LEN=*), INTENT(IN) :: STRING
691 CHARACTER(LEN=80) :: ERRMSG
692 integer :: errflg
693 character(len=*) :: errmsg_out
694
695 !Errors messages handled through CCPP error handling variables
696 errmsg_out = ''
697 errflg = 0
698
699 IF (err == nf90_noerr) RETURN
700 errmsg = nf90_strerror(err)
701 errmsg_out = 'FATAL ERROR in Land IAU '//trim(string)//': '//trim(errmsg)
702 errflg = 1
703 return
704
705 end subroutine netcdf_err
706
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
711 integer :: dimid
712 integer :: errflg
713 character(len=*) :: errmsg_out
714 integer :: status
715
716 !Errors messages handled through CCPP error handling variables
717 errmsg_out = ''
718 errflg = 0
719
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)
725
726 end subroutine get_nc_dimlen
727
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)
732 integer :: errflg
733 character(len=*) :: errmsg_out
734 integer :: varid, status
735
736 !Errors messages handled through CCPP error handling variables
737 errmsg_out = ''
738 errflg = 0
739
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
743
744 status = nf90_get_var(ncid, varid, var_arr)
745 call netcdf_err(status, 'reading var: '//trim(var_name), errflg, errmsg_out)
746
747 end subroutine get_var1d
748
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
755 integer :: errflg
756 character(len=*) :: errmsg_out
757
758 !Errors messages handled through CCPP error handling variables
759 errmsg_out = ''
760 errflg = 0
761
762 status = nf90_get_var(ncid, varid, var3d, &
763 start = (/is, js, ks/), count = (/ix, jy, kz/))
764
765 call netcdf_err(status, 'get_var3d_values '//trim(var_name), errflg, errmsg_out)
766
767
768 end subroutine get_var3d_values
769
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
776 integer :: errflg
777 character(len=*) :: errmsg_out
778
779 !Errors messages handled through CCPP error handling variables
780 errmsg_out = ''
781 errflg = 0
782
783 status = nf90_get_var(ncid, varid, var3d, & !start = start, count = nreco)
784 start = (/is, js, ks/), count = (/ix, jy, kz/))
785
786 call netcdf_err(status, 'get_var3d_values_int '//trim(var_name), errflg, errmsg_out)
787
788 end subroutine get_var3d_values_int
789
790end module land_iau_mod
791
792
TODO: replace with appropriate licence for CCPP.