1 MODULE module_interp_info
2 INTEGER , PARAMETER :: NOT_DEFINED_YET = 0
3 INTEGER , PARAMETER :: BILINEAR = 1
4 INTEGER , PARAMETER :: SINT = 2
5 INTEGER , PARAMETER :: NEAREST_NEIGHBOR = 3
6 INTEGER , PARAMETER :: QUADRATIC = 4
7 INTEGER , PARAMETER :: SPLINE = 5
8 INTEGER , PARAMETER :: SINT_NEW = 12
10 INTEGER :: interp_method_type = 0
12 SUBROUTINE interp_info_init
14 CALL nl_get_interp_method_type ( 1 , interp_method_type )
16 interp_method_type = 2
18 END SUBROUTINE interp_info_init
19 END MODULE module_interp_info
21 !WRF:MEDIATION_LAYER:INTERPOLATIONFUNCTION
25 !=========================================================================
27 SUBROUTINE interp_init
28 USE module_interp_info
30 END SUBROUTINE interp_init
32 !=========================================================================
34 SUBROUTINE interp_fcn ( cfld, & ! CD field
35 cids, cide, ckds, ckde, cjds, cjde, &
36 cims, cime, ckms, ckme, cjms, cjme, &
37 cits, cite, ckts, ckte, cjts, cjte, &
39 nids, nide, nkds, nkde, njds, njde, &
40 nims, nime, nkms, nkme, njms, njme, &
41 nits, nite, nkts, nkte, njts, njte, &
42 shw, & ! stencil half width for interp
43 imask, & ! interpolation mask
44 xstag, ystag, & ! staggering of field
45 ipos, jpos, & ! Position of lower left of nest in CD
46 nri, nrj ) ! Nest ratio, i- and j-directions
48 USE module_interp_info
52 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
53 cims, cime, ckms, ckme, cjms, cjme, &
54 cits, cite, ckts, ckte, cjts, cjte, &
55 nids, nide, nkds, nkde, njds, njde, &
56 nims, nime, nkms, nkme, njms, njme, &
57 nits, nite, nkts, nkte, njts, njte, &
61 LOGICAL, INTENT(IN) :: xstag, ystag
63 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
64 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
65 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
67 IF ( interp_method_type .EQ. NOT_DEFINED_YET ) THEN
68 interp_method_type = SINT
71 IF ( interp_method_type .EQ. BILINEAR ) THEN
72 CALL interp_fcn_blint ( cfld, & ! CD field
73 cids, cide, ckds, ckde, cjds, cjde, &
74 cims, cime, ckms, ckme, cjms, cjme, &
75 cits, cite, ckts, ckte, cjts, cjte, &
77 nids, nide, nkds, nkde, njds, njde, &
78 nims, nime, nkms, nkme, njms, njme, &
79 nits, nite, nkts, nkte, njts, njte, &
80 shw, & ! stencil half width for interp
81 imask, & ! interpolation mask
82 xstag, ystag, & ! staggering of field
83 ipos, jpos, & ! Position of lower left of nest in CD
84 nri, nrj) ! Nest ratio, i- and j-directions
85 ELSE IF ( MOD(interp_method_type,10) .EQ. SINT ) THEN
86 CALL interp_fcn_sint ( cfld, & ! CD field
87 cids, cide, ckds, ckde, cjds, cjde, &
88 cims, cime, ckms, ckme, cjms, cjme, &
89 cits, cite, ckts, ckte, cjts, cjte, &
91 nids, nide, nkds, nkde, njds, njde, &
92 nims, nime, nkms, nkme, njms, njme, &
93 nits, nite, nkts, nkte, njts, njte, &
94 shw, & ! stencil half width for interp
95 imask, & ! interpolation mask
96 xstag, ystag, & ! staggering of field
97 ipos, jpos, & ! Position of lower left of nest in CD
98 nri, nrj) ! Nest ratio, i- and j-directions
99 ELSE IF ( interp_method_type .EQ. NEAREST_NEIGHBOR ) THEN
100 CALL interp_fcn_nn ( cfld, & ! CD field
101 cids, cide, ckds, ckde, cjds, cjde, &
102 cims, cime, ckms, ckme, cjms, cjme, &
103 cits, cite, ckts, ckte, cjts, cjte, &
105 nids, nide, nkds, nkde, njds, njde, &
106 nims, nime, nkms, nkme, njms, njme, &
107 nits, nite, nkts, nkte, njts, njte, &
108 shw, & ! stencil half width for interp
109 imask, & ! interpolation mask
110 xstag, ystag, & ! staggering of field
111 ipos, jpos, & ! Position of lower left of nest in CD
112 nri, nrj) ! Nest ratio, i- and j-directions
113 ELSE IF ( interp_method_type .EQ. QUADRATIC ) THEN
114 CALL interp_fcn_lagr ( cfld, & ! CD field
115 cids, cide, ckds, ckde, cjds, cjde, &
116 cims, cime, ckms, ckme, cjms, cjme, &
117 cits, cite, ckts, ckte, cjts, cjte, &
119 nids, nide, nkds, nkde, njds, njde, &
120 nims, nime, nkms, nkme, njms, njme, &
121 nits, nite, nkts, nkte, njts, njte, &
122 shw, & ! stencil half width for interp
123 imask, & ! interpolation mask
124 xstag, ystag, & ! staggering of field
125 ipos, jpos, & ! Position of lower left of nest in CD
126 nri, nrj) ! Nest ratio, i- and j-directions
128 CALL wrf_error_fatal ('Hold on there cowboy, we need to know which interpolation option you want')
131 END SUBROUTINE interp_fcn
133 !=========================================================================
135 ! Overlapping linear horizontal iterpolation for mass, u, and v staggerings.
137 SUBROUTINE interp_fcn_blint ( cfld, & ! CD field
138 cids, cide, ckds, ckde, cjds, cjde, &
139 cims, cime, ckms, ckme, cjms, cjme, &
140 cits, cite, ckts, ckte, cjts, cjte, &
142 nids, nide, nkds, nkde, njds, njde, &
143 nims, nime, nkms, nkme, njms, njme, &
144 nits, nite, nkts, nkte, njts, njte, &
145 shw, & ! stencil half width for interp
146 imask, & ! interpolation mask
147 xstag, ystag, & ! staggering of field
148 ipos, jpos, & ! Position of lower left of nest in CD
149 nri, nrj) ! Nest ratio, i- and j-directions
153 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
154 cims, cime, ckms, ckme, cjms, cjme, &
155 cits, cite, ckts, ckte, cjts, cjte, &
156 nids, nide, nkds, nkde, njds, njde, &
157 nims, nime, nkms, nkme, njms, njme, &
158 nits, nite, nkts, nkte, njts, njte, &
162 LOGICAL, INTENT(IN) :: xstag, ystag
164 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
165 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
166 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
170 INTEGER ci, cj, ck, ni, nj, nk, istag, jstag, ioff, joff, i, j, k
171 REAL :: wx, wy, cfld_ll, cfld_lr, cfld_ul, cfld_ur
172 REAL :: cxp0, cxp1, nx, cyp0, cyp1, ny
174 ! Fortran functions. Yes, yes, I know, probably pretty slow.
176 REAL, EXTERNAL :: nest_loc_of_cg
177 INTEGER, EXTERNAL :: compute_CGLL
179 ! This stag stuff is to keep us away from the outer most row
180 ! and column for the unstaggered directions. We are going to
181 ! consider "U" an xstag variable and "V" a ystag variable. The
182 ! vertical staggering is handled in the actual arguments. The
183 ! ckte and nkte are the ending vertical dimensions for computations
184 ! for this particular variable.
202 ! Loop over each j-index on this tile for the nested domain.
204 j_loop : DO nj = njts, MIN(njde-jstag,njte)
206 ! This is the lower-left j-index of the CG.
208 ! Example is 3:1 ratio, mass-point staggering. We have listed six CG values
209 ! as an example: A, B, C, D, E, F. For a 3:1 ratio, each of these CG cells has
210 ! nine associated FG points.
211 ! |=========|=========|=========|
212 ! | - - - | - - - | - - - |
214 ! | - D - | - E - | - F - |
216 ! | 1 2 3 | 4 5 6 | 7 8 9 |
217 ! |=========|=========|=========|
218 ! | - - - | - - - | - - - |
220 ! | - A - | - B - | - C - |
222 ! | - - - | - - - | - - - |
223 ! |=========|=========|=========|
224 ! To interpolate to FG point 4, we will use CG points: A, B, D, E. It is adequate to
225 ! find the lower left point. The lower left (LL) point for "4" is "A". Below
226 ! are a few more points.
234 cj = compute_CGLL ( nj , jpos , nrj , jstag )
236 cyp0 = nest_loc_of_cg ( cj , jpos , nrj , joff )
237 cyp1 = nest_loc_of_cg ( cj+1 , jpos , nrj , joff )
239 ! What is the weighting for this CG point to the FG point, j-weight only.
241 wy = ( cyp1 - ny ) / ( cyp1 - cyp0 )
243 ! Vertical dim of the nest domain.
245 k_loop : DO nk = nkts, nkte
247 ! Loop over each i-index on this tile for the nested domain.
249 i_loop : DO ni = nits, MIN(nide-istag,nite)
251 IF ( imask ( ni, nj ) .EQ. 1 ) THEN
253 ! The coarse grid location that is to the lower left of the FG point.
255 ci = compute_CGLL ( ni , ipos , nri , istag )
257 cxp0 = nest_loc_of_cg ( ci , ipos , nri , ioff )
258 cxp1 = nest_loc_of_cg ( ci+1 , ipos , nri , ioff )
260 wx = ( cxp1 - nx ) / ( cxp1 - cxp0 )
262 ! The four surrounding CG values.
264 cfld_ll = cfld(ci ,nk,cj )
265 cfld_lr = cfld(ci+1,nk,cj )
266 cfld_ul = cfld(ci ,nk,cj+1)
267 cfld_ur = cfld(ci+1,nk,cj+1)
269 ! Bilinear interpolation in horizontal.
271 nfld( ni , nk , nj ) = wy * ( cfld_ll * wx + cfld_lr * (1.-wx) ) + &
272 (1.-wy) * ( cfld_ul * wx + cfld_ur * (1.-wx) )
279 END SUBROUTINE interp_fcn_blint
281 !=========================================================================
283 ! Overlapping linear horizontal iterpolation for longitude
285 SUBROUTINE interp_fcn_blint_ll ( cfld_inp, & ! CD field
286 cids, cide, ckds, ckde, cjds, cjde, &
287 cims, cime, ckms, ckme, cjms, cjme, &
288 cits, cite, ckts, ckte, cjts, cjte, &
290 nids, nide, nkds, nkde, njds, njde, &
291 nims, nime, nkms, nkme, njms, njme, &
292 nits, nite, nkts, nkte, njts, njte, &
293 shw, & ! stencil half width for interp
294 imask, & ! interpolation mask
295 xstag, ystag, & ! staggering of field
296 ipos, jpos, & ! Position of lower left of nest in CD
297 nri, nrj, & ! Nest ratio, i- and j-directions
298 clat_in, nlat_in, & ! CG, FG latitude
299 cinput_from_file, ninput_from_file ) ! CG, FG T/F input from file
303 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
304 cims, cime, ckms, ckme, cjms, cjme, &
305 cits, cite, ckts, ckte, cjts, cjte, &
306 nids, nide, nkds, nkde, njds, njde, &
307 nims, nime, nkms, nkme, njms, njme, &
308 nits, nite, nkts, nkte, njts, njte, &
312 LOGICAL, INTENT(IN) :: xstag, ystag
314 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld_inp, cfld
315 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
316 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: clat_in
317 REAL, DIMENSION ( nims:nime, njms:njme ) :: nlat_in
318 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
319 LOGICAL :: cinput_from_file, ninput_from_file
323 INTEGER ci, cj, ck, ni, nj, nk, istag, jstag, ioff, joff, i, j, k
324 REAL :: wx, wy, cfld_ll, cfld_lr, cfld_ul, cfld_ur
325 REAL :: cxp0, cxp1, nx, cyp0, cyp1, ny
326 LOGICAL :: probably_by_dateline
327 REAL :: max_lon, min_lon
328 LOGICAL :: probably_by_pole
329 REAL :: max_lat, min_lat
331 ! Fortran functions. Yes, yes, I know, probably pretty slow.
333 REAL, EXTERNAL :: nest_loc_of_cg
334 INTEGER, EXTERNAL :: compute_CGLL
336 ! This stag stuff is to keep us away from the outer most row
337 ! and column for the unstaggered directions. We are going to
338 ! consider "U" an xstag variable and "V" a ystag variable. The
339 ! vertical staggering is handled in the actual arguments. The
340 ! ckte and nkte are the ending vertical dimensions for computations
341 ! for this particular variable.
359 ! If this is a projection where the nest is over the pole, and
360 ! we are using the parent to interpolate the longitudes, then
361 ! we are going to have longitude troubles. If this is the case,
362 ! stop the model right away.
364 probably_by_pole = .FALSE.
367 DO nj = njts, MIN(njde-jstag,njte)
368 DO ni = nits, MIN(nide-istag,nite)
369 max_lat = MAX ( nlat_in(ni,nj) , max_lat )
370 min_lat = MIN ( nlat_in(ni,nj) , min_lat )
374 IF ( ( max_lat .GT. 85 ) .OR. ( ABS(min_lat) .GT. 85 ) ) THEN
375 probably_by_pole = .TRUE.
378 IF ( ( probably_by_pole ) .AND. ( .NOT. ninput_from_file ) ) THEN
379 CALL wrf_error_fatal ( 'Nest over the pole, single input domain, longitudes will be wrong' )
382 ! Initialize to NOT being by dateline.
384 probably_by_dateline = .FALSE.
387 DO nj = njts, MIN(njde-jstag,njte)
388 cj = compute_CGLL ( nj , jpos , nrj , jstag )
389 DO ni = nits, MIN(nide-istag,nite)
390 ci = compute_CGLL ( ni , ipos , nri , istag )
391 max_lon = MAX ( cfld_inp(ci,1,cj) , max_lon )
392 min_lon = MIN ( cfld_inp(ci,1,cj) , min_lon )
396 IF ( max_lon - min_lon .GT. 300 ) THEN
397 probably_by_dateline = .TRUE.
400 ! Load "continuous" longitude across the date line
402 DO cj = MIN(cjts-1,cjms), MAX(cjte+1,cjme)
403 DO ci = MIN(cits-1,cims), MAX(cite+1,cime)
404 IF ( ( cfld_inp(ci,ckts,cj) .LT. 0 ) .AND. ( probably_by_dateline ) ) THEN
405 cfld(ci,ckts,cj) = 360 + cfld_inp(ci,ckts,cj)
407 cfld(ci,ckts,cj) = cfld_inp(ci,ckts,cj)
412 ! Loop over each j-index on this tile for the nested domain.
414 j_loop : DO nj = njts, MIN(njde-jstag,njte)
416 ! This is the lower-left j-index of the CG.
418 ! Example is 3:1 ratio, mass-point staggering. We have listed six CG values
419 ! as an example: A, B, C, D, E, F. For a 3:1 ratio, each of these CG cells has
420 ! nine associated FG points.
421 ! |=========|=========|=========|
422 ! | - - - | - - - | - - - |
424 ! | - D - | - E - | - F - |
426 ! | 1 2 3 | 4 5 6 | 7 8 9 |
427 ! |=========|=========|=========|
428 ! | - - - | - - - | - - - |
430 ! | - A - | - B - | - C - |
432 ! | - - - | - - - | - - - |
433 ! |=========|=========|=========|
434 ! To interpolate to FG point 4, we will use CG points: A, B, D, E. It is adequate to
435 ! find the lower left point. The lower left (LL) point for "4" is "A". Below
436 ! are a few more points.
444 cj = compute_CGLL ( nj , jpos , nrj , jstag )
446 cyp0 = nest_loc_of_cg ( cj , jpos , nrj , joff )
447 cyp1 = nest_loc_of_cg ( cj+1 , jpos , nrj , joff )
449 ! What is the weighting for this CG point to the FG point, j-weight only.
451 wy = ( cyp1 - ny ) / ( cyp1 - cyp0 )
453 ! Vertical dim of the nest domain.
455 k_loop : DO nk = nkts, nkte
457 ! Loop over each i-index on this tile for the nested domain.
459 i_loop : DO ni = nits, MIN(nide-istag,nite)
461 IF ( imask ( ni, nj ) .EQ. 1 ) THEN
463 ! The coarse grid location that is to the lower left of the FG point.
465 ci = compute_CGLL ( ni , ipos , nri , istag )
467 cxp0 = nest_loc_of_cg ( ci , ipos , nri , ioff )
468 cxp1 = nest_loc_of_cg ( ci+1 , ipos , nri , ioff )
470 wx = ( cxp1 - nx ) / ( cxp1 - cxp0 )
472 ! The four surrounding CG values.
474 cfld_ll = cfld(ci ,nk,cj )
475 cfld_lr = cfld(ci+1,nk,cj )
476 cfld_ul = cfld(ci ,nk,cj+1)
477 cfld_ur = cfld(ci+1,nk,cj+1)
479 ! Bilinear interpolation in horizontal.
481 nfld( ni , nk , nj ) = wy * ( cfld_ll * wx + cfld_lr * (1.-wx) ) + &
482 (1.-wy) * ( cfld_ul * wx + cfld_ur * (1.-wx) )
489 ! Put nested longitude back into the -180 to 180 range.
491 DO nj = njts, MIN(njde-jstag,njte)
492 DO ni = nits, MIN(nide-istag,nite)
493 IF ( nfld(ni,nkts,nj) .GT. 180 ) THEN
494 nfld(ni,nkts,nj) = -360 + nfld(ni,nkts,nj)
499 END SUBROUTINE interp_fcn_blint_ll
501 !=========================================================================
503 ! Lagrange interpolating polynomials, set up as a quadratic, with an average of
506 SUBROUTINE interp_fcn_lagr ( cfld, & ! CD field
507 cids, cide, ckds, ckde, cjds, cjde, &
508 cims, cime, ckms, ckme, cjms, cjme, &
509 cits, cite, ckts, ckte, cjts, cjte, &
511 nids, nide, nkds, nkde, njds, njde, &
512 nims, nime, nkms, nkme, njms, njme, &
513 nits, nite, nkts, nkte, njts, njte, &
514 shw, & ! stencil half width for interp
515 imask, & ! interpolation mask
516 xstag, ystag, & ! staggering of field
517 ipos, jpos, & ! Position of lower left of nest in CD
518 nri, nrj) ! Nest ratio, i- and j-directions
522 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
523 cims, cime, ckms, ckme, cjms, cjme, &
524 cits, cite, ckts, ckte, cjts, cjte, &
525 nids, nide, nkds, nkde, njds, njde, &
526 nims, nime, nkms, nkme, njms, njme, &
527 nits, nite, nkts, nkte, njts, njte, &
531 LOGICAL, INTENT(IN) :: xstag, ystag
533 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
534 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
535 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
539 INTEGER ci, cj, ck, ni, nj, nk, istag, jstag, i, j, k
540 REAL :: nx, x0, x1, x2, x3, x
541 REAL :: ny, y0, y1, y2, y3
542 REAL :: cxm1, cxp0, cxp1, cxp2, nfld_m1, nfld_p0, nfld_p1, nfld_p2
543 REAL :: cym1, cyp0, cyp1, cyp2
544 INTEGER :: ioff, joff
548 REAL, EXTERNAL :: lagrange_quad_avg
549 REAL, EXTERNAL :: nest_loc_of_cg
550 INTEGER, EXTERNAL :: compute_CGLL
552 ! This stag stuff is to keep us away from the outer most row
553 ! and column for the unstaggered directions. We are going to
554 ! consider "U" an xstag variable and "V" a ystag variable. The
555 ! vertical staggering is handled in the actual arguments. The
556 ! ckte and nkte are the ending vertical dimensions for computations
557 ! for this particular variable.
559 ! The ioff and joff are offsets due to the staggering. It is a lot
560 ! simpler with ioff and joff if
564 ! Note that is OPPOSITE of the istag, jstag vars. The stag variables are
565 ! used for the domain dimensions, the offset guys are used in the
566 ! determination of grid points between the CG and FG
584 ! Loop over each j-index on this tile for the nested domain.
586 j_loop : DO nj = njts, MIN(njde-jstag,njte)
588 ! This is the lower-left j-index of the CG.
590 ! Example is 3:1 ratio, mass-point staggering. We have listed sixteen CG values
591 ! as an example: A through P. For a 3:1 ratio, each of these CG cells has
592 ! nine associated FG points.
594 ! |=========|=========|=========|=========|
595 ! | - - - | - - - | - - - | - - - |
597 ! | - M - | - N d | - O - | - P - |
599 ! | - - - | - - - | - - - | - - - |
600 ! |=========|=========|=========|=========|
601 ! | - - - | - - - | - - - | - - - |
603 ! | - I - | - J c | - K - | - L - |
605 ! | - - - | - - - | - - - | - - - |
606 ! |=========|=========|=========|=========|
607 ! | - 1 2 | 3 4 5 | 6 7 8 | - - - |
609 ! | - E - | - F b | - G - | - H - |
611 ! | - - - | - - - | - - - | - - - |
612 ! |=========|=========|=========|=========|
613 ! | - - - | - - - | - - - | - - - |
615 ! | - A - | - B a | - C - | - D - |
617 ! | - - - | - - - | - - - | - - - |
618 ! |=========|=========|=========|=========|
620 ! To interpolate to FG point 4, 5, or 6 we will use CG points: A through P. It is
621 ! sufficient to find the lower left corner of a 4-point interpolation, and then extend
622 ! each side by one unit.
624 ! Here are the lower left hand corners of the following FG points:
634 cj = compute_CGLL ( nj , jpos , nrj , jstag )
636 ! Vertical dim of the nest domain.
638 k_loop : DO nk = nkts, nkte
640 ! Loop over each i-index on this tile for the nested domain.
642 i_loop : DO ni = nits, MIN(nide-istag,nite)
644 ! The coarse grid location that is to the lower left of the FG point.
646 ci = compute_CGLL ( ni , ipos , nri , istag )
648 ! To interpolate to point "*" (look in grid cell "F"):
649 ! 1. Use ABC to get a quadratic valid at "a"
650 ! Use BCD to get a quadratic valid at "a"
651 ! Average these to get the final value for "a"
652 ! 2. Use EFG to get a quadratic valid at "b"
653 ! Use FGH to get a quadratic valid at "b"
654 ! Average these to get the final value for "b"
655 ! 3. Use IJK to get a quadratic valid at "c"
656 ! Use JKL to get a quadratic valid at "c"
657 ! Average these to get the final value for "c"
658 ! 4. Use MNO to get a quadratic valid at "d"
659 ! Use NOP to get a quadratic valid at "d"
660 ! Average these to get the final value for "d"
661 ! 5. Use abc to get a quadratic valid at "*"
662 ! Use bcd to get a quadratic valid at "*"
663 ! Average these to get the final value for "*"
665 ! |=========|=========|=========|=========|
666 ! | - - - | - - - | - - - | - - - |
668 ! | - M - | - N d | - O - | - P - |
670 ! | - - - | - - - | - - - | - - - |
671 ! |=========|=========|=========|=========|
672 ! | - - - | - - - | - - - | - - - |
674 ! | - I - | - J c | - K - | - L - |
676 ! | - - - | - - - | - - - | - - - |
677 ! |=========|=========|=========|=========|
678 ! | - - - | - - * | - - - | - - - |
680 ! | - E - | - F b | - G - | - H - |
682 ! | - - - | - - - | - - - | - - - |
683 ! |=========|=========|=========|=========|
684 ! | - - - | - - - | - - - | - - - |
686 ! | - A - | - B a | - C - | - D - |
688 ! | - - - | - - - | - - - | - - - |
689 ! |=========|=========|=========|=========|
691 ! Overlapping quadratic interpolation.
693 IF ( imask ( ni, nj ) .EQ. 1 ) THEN
695 ! I-direction location of "*"
699 ! I-direction location of "A", "E", "I", "M"
701 cxm1 = nest_loc_of_cg ( ci-1 , ipos , nri , ioff )
703 ! I-direction location of "B", "F", "J", "N"
705 cxp0 = nest_loc_of_cg ( ci , ipos , nri , ioff )
707 ! I-direction location of "C", "G", "K", "O"
709 cxp1 = nest_loc_of_cg ( ci+1 , ipos , nri , ioff )
711 ! I-direction location of "D", "H", "L", "P"
713 cxp2 = nest_loc_of_cg ( ci+2 , ipos , nri , ioff )
717 nfld_m1 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, cfld(ci-1,nk,cj-1), cfld(ci+0,nk,cj-1), cfld(ci+1,nk,cj-1), cfld(ci+2,nk,cj-1) )
721 nfld_p0 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, cfld(ci-1,nk,cj+0), cfld(ci+0,nk,cj+0), cfld(ci+1,nk,cj+0), cfld(ci+2,nk,cj+0) )
725 nfld_p1 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, cfld(ci-1,nk,cj+1), cfld(ci+0,nk,cj+1), cfld(ci+1,nk,cj+1), cfld(ci+2,nk,cj+1) )
729 nfld_p2 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, cfld(ci-1,nk,cj+2), cfld(ci+0,nk,cj+2), cfld(ci+1,nk,cj+2), cfld(ci+2,nk,cj+2) )
731 ! J-direction location of "*"
735 ! J-direction location of "A", "B", "C", "D"
737 cym1 = nest_loc_of_cg ( cj-1 , jpos , nrj , joff )
739 ! J-direction location of "E", "F", "G", "H"
741 cyp0 = nest_loc_of_cg ( cj , jpos , nrj , joff )
743 ! J-direction location of "I", "J", "K", "L"
745 cyp1 = nest_loc_of_cg ( cj+1 , jpos , nrj , joff )
747 ! J-direction location of "M", "N", "O", "P"
749 cyp2 = nest_loc_of_cg ( cj+2 , jpos , nrj , joff )
753 nfld(ni,nk,nj) = lagrange_quad_avg ( ny, cym1, cyp0, cyp1, &
754 cyp2, nfld_m1, nfld_p0, nfld_p1, nfld_p2 )
762 END SUBROUTINE interp_fcn_lagr
764 !=================================================================================
766 REAL FUNCTION lagrange_quad ( x , x0, x1, x2, y0, y1, y2 )
770 REAL :: x , x0, x1, x2, y0, y1, y2
772 ! Lagrange = sum prod ( x - xj )
773 ! i=0,n ( j=0,n --------- * yi )
776 ! For a quadratic, in the above equation, we are setting n=2. Three points
777 ! required for a quadratic, points x0, x1, x2 (hence n=2).
780 (x-x1)*(x-x2)*y0 / ( (x0-x1)*(x0-x2) ) + &
781 (x-x0)*(x-x2)*y1 / ( (x1-x0)*(x1-x2) ) + &
782 (x-x0)*(x-x1)*y2 / ( (x2-x0)*(x2-x1) )
784 END FUNCTION lagrange_quad
786 !=================================================================================
788 REAL FUNCTION lagrange_quad_avg ( x , x0, x1, x2, x3, y0, y1, y2, y3 )
792 REAL, EXTERNAL :: lagrange_quad
793 REAL :: x , x0, x1, x2, x3, y0, y1, y2, y3
795 ! Since there are three points required for a quadratic, we compute it twice
796 ! (once with x0, x1, x2 and once with x1, x2, x3), and then average those values. This will
797 ! reduce overshoot. The "x" point is where we are interpolating TO.
802 lagrange_quad_avg = &
803 ! ( lagrange_quad ( x , x0, x1, x2, y0, y1, y2 ) + &
804 ! lagrange_quad ( x , x1, x2, x3, y1, y2, y3 ) ) / &
806 ( lagrange_quad ( x , x0, x1, x2, y0, y1, y2 ) * ( x2 - x ) + &
807 lagrange_quad ( x , x1, x2, x3, y1, y2, y3 ) * ( x - x1 ) ) / &
810 END FUNCTION lagrange_quad_avg
812 !=================================================================================
814 REAL FUNCTION nest_loc_of_cg ( ci , ipos , nri , ioff )
816 ! I and J direction equations for mass and momentum values for even
817 ! and odd ratios: Given that the starting value of the nest in the
818 ! CG grid cell is defined as (1,1), what is the location of the CG
819 ! location in FG index units. Example, for a 2:1 ratio, the location
820 ! of the mass point T is 1.5 (3:1 ratio = 2, 4:1 ratio = 2.5, etc).
821 ! Note that for momentum points, the CG U point is defined as "1", the
822 ! same as the I-direction of the (1,1) location of the FG U point.
823 ! Same for V, but in the J-direction.
827 INTEGER :: ci , ipos , nri , ioff
830 ( ci - ipos ) * nri + ( 1 - ioff ) * REAL ( nri + 1 ) / 2. + ioff
832 END FUNCTION nest_loc_of_cg
834 !=================================================================================
836 FUNCTION compute_CGLL ( ni , ipos , nri , istag ) RESULT ( CGLL_loc )
840 INTEGER , INTENT(IN ) :: ni , ipos , nri , istag
845 INTEGER :: starting_position , increments_of_CG_cells
846 INTEGER :: location_of_LL_wrt_this_CG
848 INTEGER , PARAMETER :: MOMENTUM_STAG = 0
849 INTEGER , PARAMETER :: MASS_POINT_STAG = 1
851 starting_position = ipos
852 increments_of_CG_cells = ( ni - 1 ) / nri
853 ioff = MOD ( nri , 2 )
855 IF ( istag .EQ. MOMENTUM_STAG ) THEN
856 location_of_LL_wrt_this_CG = MOD ( ( ni - 1 ) , nri ) / ( nri + ioff ) - istag ! zero
857 ELSE IF ( istag .EQ. MASS_POINT_STAG ) THEN
858 location_of_LL_wrt_this_CG = ( MOD ( ( ni - 1 ) , nri ) + ioff ) / ( ( nri + ioff ) / 2 ) - istag
860 CALL wrf_error_fatal ( 'Hold on there pard, there are only two staggerings I accept.' )
863 CGLL_loc = starting_position + increments_of_CG_cells + location_of_LL_wrt_this_CG
864 ! WRITE ( 6 , '(a,i4, i4, i4, i4)') 'ni ipos nri stag', ni, ipos, nri, istag
865 ! WRITE ( 6 , '(a,i4, i4, i4, i4)') 'strt inc loc CGLL', starting_position , increments_of_CG_cells , location_of_LL_wrt_this_CG , CGLL_loc
868 END FUNCTION compute_CGLL
870 !=================================================================================
872 ! Smolarkiewicz positive definite, monotonic transport.
874 SUBROUTINE interp_fcn_sint ( cfld, & ! CD field
875 cids, cide, ckds, ckde, cjds, cjde, &
876 cims, cime, ckms, ckme, cjms, cjme, &
877 cits, cite, ckts, ckte, cjts, cjte, &
879 nids, nide, nkds, nkde, njds, njde, &
880 nims, nime, nkms, nkme, njms, njme, &
881 nits, nite, nkts, nkte, njts, njte, &
882 shw, & ! stencil half width for interp
883 imask, & ! interpolation mask
884 xstag, ystag, & ! staggering of field
885 ipos, jpos, & ! Position of lower left of nest in CD
886 nri, nrj ) ! nest ratios
891 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
892 cims, cime, ckms, ckme, cjms, cjme, &
893 cits, cite, ckts, ckte, cjts, cjte, &
894 nids, nide, nkds, nkde, njds, njde, &
895 nims, nime, nkms, nkme, njms, njme, &
896 nits, nite, nkts, nkte, njts, njte, &
900 LOGICAL, INTENT(IN) :: xstag, ystag
902 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
903 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
904 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
908 INTEGER ci, cj, ck, ni, nj, nk, ip, jp, ioff, joff, nioff, njoff
912 REAL psca(cims:cime,cjms:cjme,nri*nrj)
913 LOGICAL icmask( cims:cime, cjms:cjme )
917 ! Iterate over the ND tile and compute the values
921 nioff = 0 ; njoff = 0
936 !$OMP PRIVATE ( i,j,k,ni,nj,ci,cj,ip,jp,nk,ck,nf,icmask,psca )
941 nj = (j-jpos) * nrj + ( nrjo2 + 1 ) ! j point on nest
943 ni = (i-ipos) * nri + ( nrio2 + 1 ) ! i point on nest
944 if ( ni .ge. nits-nioff-nrio2 .and. &
945 ni .le. nite+nioff+nrio2 .and. &
946 nj .ge. njts-njoff-nrjo2 .and. &
947 nj .le. njte+njoff+nrjo2 ) then
948 if ( ni.ge.nims.and.ni.le.nime.and.nj.ge.njms.and.nj.le.njme) then
949 if ( imask(ni,nj) .eq. 1 ) then
950 icmask( i, j ) = .TRUE.
953 if ( ni-nioff.ge.nims.and.ni.le.nime.and.nj-njoff.ge.njms.and.nj.le.njme) then
954 if (ni .ge. nits-nioff .and. nj .ge. njts-njoff ) then
955 if ( imask(ni-nioff,nj-njoff) .eq. 1) then
956 icmask( i, j ) = .TRUE.
961 psca(i,j,nf) = cfld(i,k,j)
966 ! tile dims in this call to sint are 1-over to account for the fact
967 ! that the number of cells on the nest local subdomain is not
968 ! necessarily a multiple of the nest ratio in a given dim.
969 ! this could be a little less ham-handed.
972 cims, cime, cjms, cjme, icmask, &
973 cits-1, cite+1, cjts-1, cjte+1, nrj*nri, xstag, ystag )
975 DO nj = njts, njte+joff
976 cj = jpos + (nj-1) / nrj ! j coord of CD point
977 jp = mod ( nj-1 , nrj ) ! coord of ND w/i CD point
980 DO ni = nits, nite+ioff
981 ci = ipos + (ni-1) / nri ! i coord of CD point
982 ip = mod ( ni-1 , nri ) ! coord of ND w/i CD point
983 if ( ( ni-ioff .ge. nits ) .and. ( nj-joff .ge. njts ) ) then
984 if ( imask ( ni, nj ) .eq. 1 .or. imask ( ni-ioff, nj-joff ) .eq. 1 ) then
985 nfld( ni-ioff, nk, nj-joff ) = psca( ci , cj, ip+1 + (jp)*nri )
991 !$OMP END PARALLEL DO
993 END SUBROUTINE interp_fcn_sint
995 !=========================================================================
997 ! Nearest neighbor interpolation.
999 SUBROUTINE interp_fcn_nn ( cfld, & ! CD field
1000 cids, cide, ckds, ckde, cjds, cjde, &
1001 cims, cime, ckms, ckme, cjms, cjme, &
1002 cits, cite, ckts, ckte, cjts, cjte, &
1004 nids, nide, nkds, nkde, njds, njde, &
1005 nims, nime, nkms, nkme, njms, njme, &
1006 nits, nite, nkts, nkte, njts, njte, &
1007 shw, & ! stencil half width for interp
1008 imask, & ! interpolation mask
1009 xstag, ystag, & ! staggering of field
1010 ipos, jpos, & ! Position of lower left of nest in CD
1011 nri, nrj ) ! nest ratios
1014 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
1015 cims, cime, ckms, ckme, cjms, cjme, &
1016 cits, cite, ckts, ckte, cjts, cjte, &
1017 nids, nide, nkds, nkde, njds, njde, &
1018 nims, nime, nkms, nkme, njms, njme, &
1019 nits, nite, nkts, nkte, njts, njte, &
1023 LOGICAL, INTENT(IN) :: xstag, ystag
1025 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
1026 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
1027 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
1029 INTEGER ci, cj, ck, ni, nj, nk
1031 ! Iterate over the ND tile and assign the values
1032 ! from the CD tile. This is a trivial implementation
1033 ! of the interp_fcn; just copies the values from the CD into the ND
1036 cj = jpos + (nj-1) / nrj ! j coord of CD point
1040 if ( imask ( ni, nj ) .eq. 1 ) then
1041 ci = ipos + (ni-1) / nri ! i coord of CD point
1042 nfld( ni, nk, nj ) = cfld( ci , ck , cj )
1048 END SUBROUTINE interp_fcn_nn
1050 !=========================================================================
1052 SUBROUTINE interp_fcn_bl ( cfld, & ! CD field
1053 cids, cide, ckds, ckde, cjds, cjde, &
1054 cims, cime, ckms, ckme, cjms, cjme, &
1055 cits, cite, ckts, ckte, cjts, cjte, &
1057 nids, nide, nkds, nkde, njds, njde, &
1058 nims, nime, nkms, nkme, njms, njme, &
1059 nits, nite, nkts, nkte, njts, njte, &
1060 shw, & ! stencil half width for interp
1061 imask, & ! interpolation mask
1062 xstag, ystag, & ! staggering of field
1063 ipos, jpos, & ! Position of lower left of nest in CD
1064 nri, nrj, & ! Nest ratio, i- and j-directions
1065 cht, nht, & ! topography for CG and FG
1066 ct_max_p,nt_max_p, & ! temperature (K) at max press, want CG value
1067 cght_max_p,nght_max_p, & ! height (m) at max press, want CG value
1068 cmax_p,nmax_p, & ! max pressure (Pa) in column, want CG value
1069 ct_min_p,nt_min_p, & ! temperature (K) at min press, want CG value
1070 cght_min_p,nght_min_p, & ! height (m) at min press, want CG value
1071 cmin_p,nmin_p, & ! min pressure (Pa) in column, want CG value
1072 zn, p_top ) ! eta levels
1074 ! USE module_configure
1075 USE module_model_constants , ONLY : g , r_d, cp, p1000mb, t0
1080 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
1081 cims, cime, ckms, ckme, cjms, cjme, &
1082 cits, cite, ckts, ckte, cjts, cjte, &
1083 nids, nide, nkds, nkde, njds, njde, &
1084 nims, nime, nkms, nkme, njms, njme, &
1085 nits, nite, nkts, nkte, njts, njte, &
1089 LOGICAL, INTENT(IN) :: xstag, ystag
1091 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
1092 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
1093 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
1094 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: cht, ct_max_p, cght_max_p, cmax_p, ct_min_p, cght_min_p, cmin_p
1095 REAL, DIMENSION ( nims:nime, njms:njme ) :: nht, nt_max_p, nght_max_p, nmax_p, nt_min_p, nght_min_p, nmin_p
1096 REAL, DIMENSION ( ckms:ckme ) :: zn
1098 REAL, EXTERNAL :: v_interp_col
1102 INTEGER ci, cj, ni, nj, nk, istag, jstag, i, j, k
1103 REAL :: wx, wy, nprs, cfld_ll, cfld_lr, cfld_ul, cfld_ur
1104 REAL , DIMENSION(ckms:ckme) :: cprs
1105 REAL :: p00 , t00 , a , tiso , p_surf
1107 ! Yes, memory sized to allow "outside the tile" indexing for horiz interpolation. This
1108 ! is really an intermediate domain that has quite a bit of usable real estate surrounding
1109 ! the tile dimensions.
1111 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cpb
1113 ! A bit larger than tile sized to allow horizontal interpolation on the CG.
1115 REAL, DIMENSION ( cits-2:cite+2, cjts-2:cjte+2 ) :: cfld_max_p, cfld_min_p
1117 ! The usual tile size for the FG local array.
1119 REAL, DIMENSION ( nits:nite, nkts:nkte, njts:njte ) :: npb
1121 ! Get base state constants
1123 CALL nl_get_base_pres ( 1 , p00 )
1124 CALL nl_get_base_temp ( 1 , t00 )
1125 CALL nl_get_base_lapse ( 1 , a )
1126 CALL nl_get_iso_temp ( 1 , tiso )
1128 ! This stag stuff is to keep us away from the outer most row
1129 ! and column for the unstaggered directions. We are going to
1130 ! consider "U" an xstag variable and "V" a ystag variable. The
1131 ! vertical staggering is handled in the actual arguments. The
1132 ! ckte and nkte are the ending vertical dimensions for computations
1133 ! for this particular variable.
1147 ! Compute the reference pressure for the CG, function only of constants and elevation.
1148 ! We extend the i,j range to allow us to do horizontal interpolation. We only need
1149 ! one extra grid cell surrounding the nest, and the intermediate domain has plenty of
1150 ! room with the halos set up for higher-order interpolations. For intermediate domains,
1151 ! it turns out that the "domain" size actually fits within the "tile" size. Yeppers,
1152 ! that is backwards from what usually happens. That intermediate domain size is a couple
1153 ! grid points larger than necessary, and the tile is a couple of grid cells larger still.
1154 ! For our low-order interpolation, we can use the tile size for the CG, and we will have
1155 ! plenty of data on our boundaries.
1157 DO j = cjts-2 , cjte+2
1158 DO i = cits-2 , cite+2
1159 p_surf = p00 * EXP ( -t00/a + ( (t00/a)**2 - 2.*g*cht(i,j)/a/r_d ) **0.5 )
1161 cpb(i,k,j) = zn(k)*(p_surf - p_top) + p_top
1163 IF ( ckte .EQ. ckme ) THEN
1164 cfld_max_p(i,j) = cght_max_p(i,j) * g
1165 cfld_min_p(i,j) = cght_min_p(i,j) * g
1167 cfld_max_p(i,j) = ct_max_p(i,j) * (p1000mb/cmax_p(i,j))**(r_d/cp) - t0
1168 cfld_min_p(i,j) = ct_min_p(i,j) * (p1000mb/cmin_p(i,j))**(r_d/cp) - t0
1173 ! Compute the reference pressure for the FG. This is actually the size of the entire
1174 ! domain, not some chopped down piece of intermediate domain, as in the parent
1175 ! grid. We do the traditional MAX(dom end -1,tile end), since we know a priori that the
1176 ! pressure is a mass point field (because the topo elevation is a mass point field).
1178 DO j = njts , MIN(njde-1,njte)
1179 DO i = nits , MIN(nide-1,nite)
1180 p_surf = p00 * EXP ( -t00/a + ( (t00/a)**2 - 2.*g*nht(i,j)/a/r_d ) **0.5 )
1182 npb(i,k,j) = zn(k)*(p_surf - p_top) + p_top
1187 ! Loop over each j-index on this tile for the nested domain.
1189 j_loop : DO nj = njts, MIN(njde-jstag,njte)
1191 ! This is the lower-left j-index of the CG.
1193 ! Example is 3:1 ratio, mass-point staggering. We have listed six CG values
1194 ! as an example: A, B, C, D, E, F. For a 3:1 ratio, each of these CG cells has
1195 ! nine associated FG points.
1196 ! |=========|=========|=========|
1197 ! | - - - | - - - | - - - |
1199 ! | - D - | - E - | - F - |
1201 ! | 1 2 3 | 4 5 6 | 7 8 9 |
1202 ! |=========|=========|=========|
1203 ! | - - - | - - - | - - - |
1205 ! | - A - | - B - | - C - |
1207 ! | - - - | - - - | - - - |
1208 ! |=========|=========|=========|
1209 ! To interpolate to FG point 4, we will use CG points: A, B, D, E. It is adequate to
1210 ! find the lower left point. The lower left (LL) point for "4" is "A". Below
1211 ! are a few more points.
1218 ! We want an equation that returns the CG LL:
1219 ! CG LL = ipos (the starting point of the nest in the CG)
1220 ! + (ni-1)/nri (gives us the CG cell, based on the nri-groups of FG cells
1221 ! - istag (a correction term, this is either zero for u in the x-dir,
1222 ! since we are doing an "i" example, or 1 for anything else)
1223 ! + (MOD(ni-1,nri)+1 + nri/2)/nri (gives us specifically related CG point for each of the nri
1224 ! FG points, for example, we want points "1", "4", and "7" all
1225 ! to point to the CG at the left for the LL point)
1226 ! For grid points 4, 5, 6, we want the CG LL (sans the first two terms) to be -1, 0, 0 (which
1227 ! means that the CG point for "4" is to the left, and the CG LL point for "5" and "6"
1228 ! is in the current CG index.
1230 cj = jpos + (nj-1)/nrj - jstag + (MOD(nj-1,nrj)+1 + nrj/2)/nrj
1233 ! What is the weighting for this CG point to the FG point, j-weight only.
1236 wy = 1. - ( REAL(MOD(nj+(nrj-1)/2,nrj)) / REAL(nrj) + 1. / REAL (2 * nrj) )
1238 wy = 1. - ( REAL(MOD(nj+(nrj-1)/2,nrj)) / REAL(nrj) )
1241 ! Vertical dim of the nest domain.
1243 k_loop : DO nk = nkts, nkte
1245 ! Loop over each i-index on this tile for the nested domain.
1247 i_loop : DO ni = nits, MIN(nide-istag,nite)
1249 ! The coarse grid location that is to the lower left of the FG point.
1251 ci = ipos + (ni-1)/nri - istag + (MOD(ni-1,nri)+1 + nri/2)/nri
1253 ! Weights in the x-direction.
1256 wx = 1. - ( REAL(MOD(ni+(nri-1)/2,nri)) / REAL(nri) + 1. / REAL (2 * nri) )
1258 wx = 1. - ( REAL(MOD(ni+(nri-1)/2,nri)) / REAL(nri) )
1261 ! The pressure of the FG point.
1263 IF ( ( .NOT. xstag ) .AND. ( .NOT. ystag ) ) THEN
1264 nprs = npb( ni , nk , nj )
1265 ELSE IF ( xstag ) THEN
1266 nprs = ( npb( ni-1, nk , nj ) + npb( ni , nk , nj ) ) * 0.5
1267 ELSE IF ( ystag ) THEN
1268 nprs = ( npb( ni , nk , nj-1) + npb( ni , nk , nj ) ) * 0.5
1271 ! The four surrounding CG values.
1273 IF ( ( .NOT. xstag ) .AND. ( .NOT. ystag ) ) THEN
1274 cprs(:) = cpb(ci ,:,cj )
1275 cfld_ll = v_interp_col ( cfld(ci ,:,cj ) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci , cj , &
1276 cfld_max_p(ci ,cj ) , cmax_p(ci ,cj ) , cfld_min_p(ci ,cj ) , cmin_p(ci ,cj ) )
1277 cprs(:) = cpb(ci+1,:,cj )
1278 cfld_lr = v_interp_col ( cfld(ci+1,:,cj ) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci+1, cj , &
1279 cfld_max_p(ci+1,cj ) , cmax_p(ci+1,cj ) , cfld_min_p(ci+1,cj ) , cmin_p(ci+1,cj ) )
1280 cprs(:) = cpb(ci ,:,cj+1)
1281 cfld_ul = v_interp_col ( cfld(ci ,:,cj+1) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci , cj+1, &
1282 cfld_max_p(ci ,cj+1) , cmax_p(ci ,cj+1) , cfld_min_p(ci ,cj+1) , cmin_p(ci ,cj+1) )
1283 cprs(:) = cpb(ci+1,:,cj+1)
1284 cfld_ur = v_interp_col ( cfld(ci+1,:,cj+1) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci+1, cj+1, &
1285 cfld_max_p(ci+1,cj+1) , cmax_p(ci+1,cj+1) , cfld_min_p(ci+1,cj+1) , cmin_p(ci+1,cj+1) )
1287 ELSE IF ( xstag ) THEN
1288 cprs(:) = ( cpb(ci ,:,cj ) + cpb(ci-1,:,cj ) )*0.5
1289 cfld_ll = v_interp_col ( cfld(ci ,:,cj ) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci , cj , &
1290 cfld_max_p(ci ,cj ) , cmax_p(ci ,cj ) , cfld_min_p(ci ,cj ) , cmin_p(ci ,cj ) )
1291 cprs(:) = ( cpb(ci+1,:,cj ) + cpb(ci ,:,cj ) )*0.5
1292 cfld_lr = v_interp_col ( cfld(ci+1,:,cj ) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci+1, cj , &
1293 cfld_max_p(ci+1,cj ) , cmax_p(ci+1,cj ) , cfld_min_p(ci+1,cj ) , cmin_p(ci+1,cj ) )
1294 cprs(:) = ( cpb(ci ,:,cj+1) + cpb(ci-1,:,cj+1) )*0.5
1295 cfld_ul = v_interp_col ( cfld(ci ,:,cj+1) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci , cj+1, &
1296 cfld_max_p(ci ,cj+1) , cmax_p(ci ,cj+1) , cfld_min_p(ci ,cj+1) , cmin_p(ci ,cj+1) )
1297 cprs(:) = ( cpb(ci+1,:,cj+1) + cpb(ci ,:,cj+1) )*0.5
1298 cfld_ur = v_interp_col ( cfld(ci+1,:,cj+1) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci+1, cj+1, &
1299 cfld_max_p(ci+1,cj+1) , cmax_p(ci+1,cj+1) , cfld_min_p(ci+1,cj+1) , cmin_p(ci+1,cj+1) )
1300 ELSE IF ( ystag ) THEN
1301 cprs(:) = ( cpb(ci ,:,cj ) + cpb(ci ,:,cj-1) )*0.5
1302 cfld_ll = v_interp_col ( cfld(ci ,:,cj ) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci , cj , &
1303 cfld_max_p(ci ,cj ) , cmax_p(ci ,cj ) , cfld_min_p(ci ,cj ) , cmin_p(ci ,cj ) )
1304 cprs(:) = ( cpb(ci+1,:,cj ) + cpb(ci+1,:,cj-1) )*0.5
1305 cfld_lr = v_interp_col ( cfld(ci+1,:,cj ) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci+1, cj , &
1306 cfld_max_p(ci+1,cj ) , cmax_p(ci+1,cj ) , cfld_min_p(ci+1,cj ) , cmin_p(ci+1,cj ) )
1307 cprs(:) = ( cpb(ci ,:,cj+1) + cpb(ci ,:,cj ) )*0.5
1308 cfld_ul = v_interp_col ( cfld(ci ,:,cj+1) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci , cj+1, &
1309 cfld_max_p(ci ,cj+1) , cmax_p(ci ,cj+1) , cfld_min_p(ci ,cj+1) , cmin_p(ci ,cj+1) )
1310 cprs(:) = ( cpb(ci+1,:,cj+1) + cpb(ci+1,:,cj ) )*0.5
1311 cfld_ur = v_interp_col ( cfld(ci+1,:,cj+1) , cprs(:) , ckms , ckme , ckte, nprs, ni, nj, nk, ci+1, cj+1, &
1312 cfld_max_p(ci+1,cj+1) , cmax_p(ci+1,cj+1) , cfld_min_p(ci+1,cj+1) , cmin_p(ci+1,cj+1) )
1315 ! Bilinear interpolation in horizontal with vertically corrected CG field values.
1317 nfld( ni , nk , nj ) = wy * ( cfld_ll * wx + cfld_lr * (1.-wx) ) + &
1318 (1.-wy) * ( cfld_ul * wx + cfld_ur * (1.-wx) )
1324 ! If this is ph_2, make the values at k=1 all zero
1326 IF ( ckme .EQ. ckte ) THEN
1329 nfld(ni,nkts,nj) = 0.0
1334 END SUBROUTINE interp_fcn_bl
1336 !==================================
1338 FUNCTION v_interp_col ( cfld_orig , cprs_orig , ckms , ckme , ckte , nprs, ni, nj, nk, ci, cj, &
1339 cfld_max_p , cmax_p , cfld_min_p , cmin_p ) RESULT ( cfld_interp )
1343 INTEGER , INTENT(IN) :: ni, nj, nk, ci, cj
1344 INTEGER , INTENT(IN) :: ckms , ckme , ckte
1345 REAL , DIMENSION(ckms:ckme) , INTENT(IN) :: cfld_orig , cprs_orig
1346 REAL , INTENT(IN) :: cfld_max_p , cmax_p , cfld_min_p , cmin_p
1347 REAL , INTENT(IN) :: nprs
1354 CHARACTER(LEN=256) :: joe_mess
1355 REAL , DIMENSION(ckms:ckme+1+1) :: cfld , cprs
1359 cfld(1) = cfld_max_p
1362 cfld(ckte+2) = cfld_min_p
1363 cprs(ckte+2) = cmin_p
1366 cfld(ck+1) = cfld_orig(ck)
1367 cprs(ck+1) = cprs_orig(ck)
1372 IF ( cprs(ckms) .LT. nprs ) THEN
1373 cfld_interp = cfld(ckms)
1375 ELSE IF ( cprs(ckte+2) .GE. nprs ) THEN
1376 cfld_interp = cfld(ckte+2)
1380 DO ck = ckms , ckte+1
1381 IF ( ( cprs(ck ) .GE. nprs ) .AND. &
1382 ( cprs(ck+1) .LT. nprs ) ) THEN
1383 cfld_interp = ( cfld(ck ) * ( nprs - cprs(ck+1) ) + &
1384 cfld(ck+1) * ( cprs(ck) - nprs ) ) / &
1385 ( cprs(ck) - cprs(ck+1) )
1390 CALL wrf_error_fatal ( 'ERROR -- vertical interpolation for nest interp cannot find trapping pressures' )
1392 END FUNCTION v_interp_col
1394 !==================================
1395 ! this is the default function used in feedback.
1397 SUBROUTINE copy_fcn ( cfld, & ! CD field
1398 cids, cide, ckds, ckde, cjds, cjde, &
1399 cims, cime, ckms, ckme, cjms, cjme, &
1400 cits, cite, ckts, ckte, cjts, cjte, &
1402 nids, nide, nkds, nkde, njds, njde, &
1403 nims, nime, nkms, nkme, njms, njme, &
1404 nits, nite, nkts, nkte, njts, njte, &
1405 shw, & ! stencil half width for interp
1406 imask, & ! interpolation mask
1407 xstag, ystag, & ! staggering of field
1408 ipos, jpos, & ! Position of lower left of nest in CD
1409 nri, nrj ) ! nest ratios
1410 USE module_configure
1414 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
1415 cims, cime, ckms, ckme, cjms, cjme, &
1416 cits, cite, ckts, ckte, cjts, cjte, &
1417 nids, nide, nkds, nkde, njds, njde, &
1418 nims, nime, nkms, nkme, njms, njme, &
1419 nits, nite, nkts, nkte, njts, njte, &
1423 LOGICAL, INTENT(IN) :: xstag, ystag
1425 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ), INTENT(OUT) :: cfld
1426 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ),INTENT(IN) :: nfld
1427 INTEGER, DIMENSION ( nims:nime, njms:njme ),INTENT(IN) :: imask
1431 INTEGER ci, cj, ck, ni, nj, nk, ip, jp, ioff, joff, ioffa, joffa
1432 INTEGER :: icmin,icmax,jcmin,jcmax
1433 INTEGER :: istag,jstag, ipoints,jpoints,ijpoints
1434 INTEGER , PARAMETER :: passes = 2
1437 ! Loop over the coarse grid in the area of the fine mesh. Do not
1438 ! process the coarse grid values that are along the lateral BC
1439 ! provided to the fine grid. Since that is in the specified zone
1440 ! for the fine grid, it should not be used in any feedback to the
1441 ! coarse grid as it should not have changed.
1443 ! Due to peculiarities of staggering, it is simpler to handle the feedback
1444 ! for the staggerings based upon whether it is a even ratio (2::1, 4::1, etc.) or
1445 ! an odd staggering ratio (3::1, 5::1, etc.).
1447 ! Though there are separate grid ratios for the i and j directions, this code
1448 ! is not general enough to handle aspect ratios .NE. 1 for the fine grid cell.
1450 ! These are local integer increments in the looping. Basically, istag=1 means
1451 ! that we will assume one less point in the i direction. Note that ci and cj
1452 ! have a maximum value that is decreased by istag and jstag, respectively.
1454 ! Horizontal momentum feedback is along the face, not within the cell. For a
1455 ! 3::1 ratio, temperature would use 9 pts for feedback, while u and v use
1456 ! only 3 points for feedback from the nest to the parent.
1458 CALL nl_get_spec_zone( 1 , spec_zone )
1459 istag = 1 ; jstag = 1
1460 IF ( xstag ) istag = 0
1461 IF ( ystag ) jstag = 0
1463 IF( MOD(nrj,2) .NE. 0) THEN ! odd refinement ratio
1465 IF ( ( .NOT. xstag ) .AND. ( .NOT. ystag ) ) THEN
1466 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1467 nj = (cj-jpos)*nrj + nrj/2 + 1
1470 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1471 ni = (ci-ipos)*nri + nri/2 + 1
1472 cfld( ci, ck, cj ) = 0.
1473 DO ijpoints = 1 , nri * nrj
1474 ipoints = MOD((ijpoints-1),nri) + 1 - nri/2 - 1
1475 jpoints = (ijpoints-1)/nri + 1 - nrj/2 - 1
1476 cfld( ci, ck, cj ) = cfld( ci, ck, cj ) + &
1477 1./REAL(nri*nrj) * nfld( ni+ipoints , nk , nj+jpoints )
1479 ! cfld( ci, ck, cj ) = 1./9. * &
1480 ! ( nfld( ni-1, nk , nj-1) + &
1481 ! nfld( ni , nk , nj-1) + &
1482 ! nfld( ni+1, nk , nj-1) + &
1483 ! nfld( ni-1, nk , nj ) + &
1484 ! nfld( ni , nk , nj ) + &
1485 ! nfld( ni+1, nk , nj ) + &
1486 ! nfld( ni-1, nk , nj+1) + &
1487 ! nfld( ni , nk , nj+1) + &
1488 ! nfld( ni+1, nk , nj+1) )
1489 ! cfld( ci, ck, cj ) = 1./25. * &
1490 ! ( nfld( ni-2, nk , nj-2) + &
1491 ! nfld( ni-2, nk , nj-1) + &
1492 ! nfld( ni-2, nk , nj-0) + &
1493 ! nfld( ni-2, nk , nj+1) + &
1494 ! nfld( ni-2, nk , nj+2) + &
1495 ! nfld( ni-1, nk , nj-2) + &
1496 ! nfld( ni-1, nk , nj-1) + &
1497 ! nfld( ni-1, nk , nj-0) + &
1498 ! nfld( ni-1, nk , nj+1) + &
1499 ! nfld( ni-1, nk , nj+2) + &
1500 ! nfld( ni-0, nk , nj-2) + &
1501 ! nfld( ni-0, nk , nj-1) + &
1502 ! nfld( ni-0, nk , nj-0) + &
1503 ! nfld( ni-0, nk , nj+1) + &
1504 ! nfld( ni-0, nk , nj+2) + &
1505 ! nfld( ni+1, nk , nj-2) + &
1506 ! nfld( ni+1, nk , nj-1) + &
1507 ! nfld( ni+1, nk , nj-0) + &
1508 ! nfld( ni+1, nk , nj+1) + &
1509 ! nfld( ni+1, nk , nj+2) + &
1510 ! nfld( ni+2, nk , nj-2) + &
1511 ! nfld( ni+2, nk , nj-1) + &
1512 ! nfld( ni+2, nk , nj-0) + &
1513 ! nfld( ni+2, nk , nj+1) + &
1514 ! nfld( ni+2, nk , nj+2) )
1519 ELSE IF ( ( xstag ) .AND. ( .NOT. ystag ) ) THEN
1520 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1521 nj = (cj-jpos)*nrj + nrj/2 + 1
1524 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1525 ni = (ci-ipos)*nri + 1
1526 cfld( ci, ck, cj ) = 0.
1527 DO ijpoints = (nri+1)/2 , (nri+1)/2 + nri*(nri-1) , nri
1528 ipoints = MOD((ijpoints-1),nri) + 1 - nri/2 - 1
1529 jpoints = (ijpoints-1)/nri + 1 - nrj/2 - 1
1530 cfld( ci, ck, cj ) = cfld( ci, ck, cj ) + &
1531 1./REAL(nri ) * nfld( ni+ipoints , nk , nj+jpoints )
1533 ! cfld( ci, ck, cj ) = 1./3. * &
1534 ! ( nfld( ni , nk , nj-1) + &
1535 ! nfld( ni , nk , nj ) + &
1536 ! nfld( ni , nk , nj+1) )
1541 ELSE IF ( ( .NOT. xstag ) .AND. ( ystag ) ) THEN
1542 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1543 nj = (cj-jpos)*nrj + 1
1546 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1547 ni = (ci-ipos)*nri + nri/2 + 1
1548 cfld( ci, ck, cj ) = 0.
1549 DO ijpoints = ( nrj*nrj +1 )/2 - nrj/2 , ( nrj*nrj +1 )/2 - nrj/2 + nrj-1
1550 ipoints = MOD((ijpoints-1),nri) + 1 - nri/2 - 1
1551 jpoints = (ijpoints-1)/nri + 1 - nrj/2 - 1
1552 cfld( ci, ck, cj ) = cfld( ci, ck, cj ) + &
1553 1./REAL( nrj) * nfld( ni+ipoints , nk , nj+jpoints )
1555 ! cfld( ci, ck, cj ) = 1./3. * &
1556 ! ( nfld( ni-1, nk , nj ) + &
1557 ! nfld( ni , nk , nj ) + &
1558 ! nfld( ni+1, nk , nj ) )
1565 ! Even refinement ratio
1567 ELSE IF ( MOD(nrj,2) .EQ. 0) THEN
1568 IF ( ( .NOT. xstag ) .AND. ( .NOT. ystag ) ) THEN
1570 ! This is a simple schematic of the feedback indexing used in the even
1571 ! ratio nests. For simplicity, a 2::1 ratio is depicted. Only the
1572 ! mass variable staggering is shown.
1574 ! the boxes with a "T" and four small "t" represents a coarse grid (CG)
1575 ! cell, that is composed of four (2::1 ratio) fine grid (FG) cells.
1577 ! Shown below is the area of the CG that is in the area of the FG. The
1578 ! first grid point of the depicted CG is the starting location of the nest
1579 ! in the parent domain (ipos,jpos = i_parent_start and j_parent_start from
1582 ! For each of the CG points, the feedback loop is over each of the FG points
1583 ! within the CG cell. For a 2::1 ratio, there are four total points (this is
1584 ! the ijpoints loop). The feedback value to the CG is the arithmetic mean of
1585 ! all of the FG values within each CG cell.
1587 ! |-------------||-------------| |-------------||-------------|
1588 ! | t t || t t | | t t || t t |
1589 ! jpos+ | || | | || |
1590 ! (njde-njds)- | T || T | | T || T |
1591 ! jstag | || | | || |
1592 ! | t t || t t | | t t || t t |
1593 ! |-------------||-------------| |-------------||-------------|
1594 ! |-------------||-------------| |-------------||-------------|
1595 ! | t t || t t | | t t || t t |
1597 ! | T || T | | T || T |
1599 ! | t t || t t | | t t || t t |
1600 ! |-------------||-------------| |-------------||-------------|
1608 ! |-------------||-------------| |-------------||-------------|
1609 ! jpoints = 1 | t t || t t | | t t || t t |
1611 ! | T || T | | T || T |
1613 ! jpoints = 0, | t t || t t | | t t || t t |
1614 ! nj=3 |-------------||-------------| |-------------||-------------|
1615 ! |-------------||-------------| |-------------||-------------|
1616 ! jpoints = 1 | t t || t t | | t t || t t |
1618 ! jpos --> | T || T | ... | T || T |
1620 ! jpoints = 0, | t t || t t | ... | t t || t t |
1621 ! nj=1 |-------------||-------------| |-------------||-------------|
1626 ! ni = 1 3 (nide-nids)/nri
1627 ! ipoints= 0 1 0 1 -istag
1630 ! For performance benefits, users can comment out the inner most loop (and cfld=0) and
1631 ! hardcode the loop feedback. For example, it is set up to run a 2::1 ratio
1632 ! if uncommented. This lacks generality, but is likely to gain timing benefits
1633 ! with compilers unable to unroll inner loops that do not have parameterized sizes.
1635 ! The extra +1 ---------/ and the extra -1 ----\ (both for ci and cj)
1636 ! / \ keeps the feedback out of the
1637 ! / \ outer row/col, since that CG data
1638 ! / \ specified the nest boundary originally
1641 ! / \ a sentence to not end a line
1642 ! / \ with a stupid backslash
1643 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1644 nj = (cj-jpos)*nrj + jstag
1647 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1648 ni = (ci-ipos)*nri + istag
1649 cfld( ci, ck, cj ) = 0.
1650 DO ijpoints = 1 , nri * nrj
1651 ipoints = MOD((ijpoints-1),nri)
1652 jpoints = (ijpoints-1)/nri
1653 cfld( ci, ck, cj ) = cfld( ci, ck, cj ) + &
1654 1./REAL(nri*nrj) * nfld( ni+ipoints , nk , nj+jpoints )
1656 ! cfld( ci, ck, cj ) = 1./4. * &
1657 ! ( nfld( ni , nk , nj ) + &
1658 ! nfld( ni+1, nk , nj ) + &
1659 ! nfld( ni , nk , nj+1) + &
1660 ! nfld( ni+1, nk , nj+1) )
1667 ELSE IF ( ( xstag ) .AND. ( .NOT. ystag ) ) THEN
1674 ! jpoints = 0, u u |
1683 ! jpoints = 0, u u |
1695 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1696 nj = (cj-jpos)*nrj + 1
1699 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1700 ni = (ci-ipos)*nri + 1
1701 cfld( ci, ck, cj ) = 0.
1702 DO ijpoints = 1 , nri*nrj , nri
1703 ipoints = MOD((ijpoints-1),nri)
1704 jpoints = (ijpoints-1)/nri
1705 cfld( ci, ck, cj ) = cfld( ci, ck, cj ) + &
1706 1./REAL(nri ) * nfld( ni+ipoints , nk , nj+jpoints )
1708 ! cfld( ci, ck, cj ) = 1./2. * &
1709 ! ( nfld( ni , nk , nj ) + &
1710 ! nfld( ni , nk , nj+1) )
1717 ELSE IF ( ( .NOT. xstag ) .AND. ( ystag ) ) THEN
1718 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1719 nj = (cj-jpos)*nrj + 1
1722 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1723 ni = (ci-ipos)*nri + 1
1724 cfld( ci, ck, cj ) = 0.
1725 DO ijpoints = 1 , nri
1726 ipoints = MOD((ijpoints-1),nri)
1727 jpoints = (ijpoints-1)/nri
1728 cfld( ci, ck, cj ) = cfld( ci, ck, cj ) + &
1729 1./REAL(nri ) * nfld( ni+ipoints , nk , nj+jpoints )
1731 ! cfld( ci, ck, cj ) = 1./2. * &
1732 ! ( nfld( ni , nk , nj ) + &
1733 ! nfld( ni+1, nk , nj ) )
1742 END SUBROUTINE copy_fcn
1744 !==================================
1745 ! this is the 1pt function used in feedback.
1747 SUBROUTINE copy_fcnm ( cfld, & ! CD field
1748 cids, cide, ckds, ckde, cjds, cjde, &
1749 cims, cime, ckms, ckme, cjms, cjme, &
1750 cits, cite, ckts, ckte, cjts, cjte, &
1752 nids, nide, nkds, nkde, njds, njde, &
1753 nims, nime, nkms, nkme, njms, njme, &
1754 nits, nite, nkts, nkte, njts, njte, &
1755 shw, & ! stencil half width for interp
1756 imask, & ! interpolation mask
1757 xstag, ystag, & ! staggering of field
1758 ipos, jpos, & ! Position of lower left of nest in CD
1759 nri, nrj ) ! nest ratios
1760 USE module_configure
1761 USE module_wrf_error
1765 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
1766 cims, cime, ckms, ckme, cjms, cjme, &
1767 cits, cite, ckts, ckte, cjts, cjte, &
1768 nids, nide, nkds, nkde, njds, njde, &
1769 nims, nime, nkms, nkme, njms, njme, &
1770 nits, nite, nkts, nkte, njts, njte, &
1774 LOGICAL, INTENT(IN) :: xstag, ystag
1776 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ), INTENT(OUT) :: cfld
1777 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ), INTENT(IN) :: nfld
1778 INTEGER, DIMENSION ( nims:nime, njms:njme ), INTENT(IN) :: imask
1782 INTEGER ci, cj, ck, ni, nj, nk, ip, jp, ioff, joff, ioffa, joffa
1783 INTEGER :: icmin,icmax,jcmin,jcmax
1784 INTEGER :: istag,jstag, ipoints,jpoints,ijpoints
1785 INTEGER , PARAMETER :: passes = 2
1788 CALL nl_get_spec_zone( 1, spec_zone )
1789 istag = 1 ; jstag = 1
1790 IF ( xstag ) istag = 0
1791 IF ( ystag ) jstag = 0
1793 IF( MOD(nrj,2) .NE. 0) THEN ! odd refinement ratio
1795 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1796 nj = (cj-jpos)*nrj + jstag + 1
1799 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1800 ni = (ci-ipos)*nri + istag + 1
1801 cfld( ci, ck, cj ) = nfld( ni , nk , nj )
1806 ELSE ! even refinement ratio, pick nearest neighbor on SW corner
1807 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1808 nj = (cj-jpos)*nrj + 1
1811 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1812 ni = (ci-ipos)*nri + 1
1815 cfld( ci, ck, cj ) = nfld( ni+ipoints , nk , nj+jpoints )
1824 END SUBROUTINE copy_fcnm
1826 !==================================
1827 ! this is the 1pt function used in feedback for integers
1829 SUBROUTINE copy_fcni ( cfld, & ! CD field
1830 cids, cide, ckds, ckde, cjds, cjde, &
1831 cims, cime, ckms, ckme, cjms, cjme, &
1832 cits, cite, ckts, ckte, cjts, cjte, &
1834 nids, nide, nkds, nkde, njds, njde, &
1835 nims, nime, nkms, nkme, njms, njme, &
1836 nits, nite, nkts, nkte, njts, njte, &
1837 shw, & ! stencil half width for interp
1838 imask, & ! interpolation mask
1839 xstag, ystag, & ! staggering of field
1840 ipos, jpos, & ! Position of lower left of nest in CD
1841 nri, nrj ) ! nest ratios
1842 USE module_configure
1843 USE module_wrf_error
1847 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
1848 cims, cime, ckms, ckme, cjms, cjme, &
1849 cits, cite, ckts, ckte, cjts, cjte, &
1850 nids, nide, nkds, nkde, njds, njde, &
1851 nims, nime, nkms, nkme, njms, njme, &
1852 nits, nite, nkts, nkte, njts, njte, &
1856 LOGICAL, INTENT(IN) :: xstag, ystag
1858 INTEGER, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ), INTENT(OUT) :: cfld
1859 INTEGER, DIMENSION ( nims:nime, nkms:nkme, njms:njme ), INTENT(IN) :: nfld
1860 INTEGER, DIMENSION ( nims:nime, njms:njme ), INTENT(IN) :: imask
1864 INTEGER ci, cj, ck, ni, nj, nk, ip, jp, ioff, joff, ioffa, joffa
1865 INTEGER :: icmin,icmax,jcmin,jcmax
1866 INTEGER :: istag,jstag, ipoints,jpoints,ijpoints
1867 INTEGER , PARAMETER :: passes = 2
1870 CALL nl_get_spec_zone( 1, spec_zone )
1871 istag = 1 ; jstag = 1
1872 IF ( xstag ) istag = 0
1873 IF ( ystag ) jstag = 0
1875 IF( MOD(nrj,2) .NE. 0) THEN ! odd refinement ratio
1877 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1878 nj = (cj-jpos)*nrj + jstag + 1
1881 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1882 ni = (ci-ipos)*nri + istag + 1
1883 cfld( ci, ck, cj ) = nfld( ni , nk , nj )
1888 ELSE ! even refinement ratio
1889 DO cj = MAX(jpos+spec_zone,cjts),MIN(jpos+(njde-njds)/nrj-jstag-spec_zone,cjte)
1890 nj = (cj-jpos)*nrj + 1
1893 DO ci = MAX(ipos+spec_zone,cits),MIN(ipos+(nide-nids)/nri-istag-spec_zone,cite)
1894 ni = (ci-ipos)*nri + 1
1897 cfld( ci, ck, cj ) = nfld( ni+ipoints , nk , nj+jpoints )
1906 END SUBROUTINE copy_fcni
1908 !==================================
1910 SUBROUTINE vert_interp_vert_nesting ( cfld, & ! CD field
1911 ids, ide, kds, kde, jds, jde, &
1912 ims, ime, kms, kme, jms, jme, &
1913 its, ite, kts, kte, jts, jte, &
1914 pgrid_s_vert, pgrid_e_vert, & ! vertical dimensions of parent grid
1915 cf1_c, cf2_c, cf3_c, cfn_c, cfn1_c, & ! coarse grid extrapolation constants
1918 !KAL vertical interpolation for u, v, and mass points (w is below in a different subroutine) for vertical nesting
1921 REAL, DIMENSION ( ims:ime, kms:kme, jms:jme ), INTENT(INOUT) :: cfld
1922 INTEGER, INTENT(IN) :: ids, ide, kds, kde, jds, jde, &
1923 ims, ime, kms, kme, jms, jme, &
1924 its, ite, kts, kte, jts, jte
1925 INTEGER, INTENT(IN) :: pgrid_s_vert, pgrid_e_vert ! vertical dimensions of the parent grid
1926 REAL, INTENT(IN) :: cf1_c, cf2_c, cf3_c, cfn_c, cfn1_c
1927 REAL, DIMENSION(pgrid_s_vert:pgrid_e_vert+1), INTENT(IN) :: alt_u_c
1928 REAL, DIMENSION(kde+1), INTENT(IN) :: alt_u_n
1934 REAL, DIMENSION(pgrid_s_vert:pgrid_e_vert+1) :: pro_u_c ! variable in 1D on the coarse grid
1935 REAL, DIMENSION(kde+1) :: pro_u_n
1940 ! pro_u_c is u on the 1D coarse grid
1942 do k = pgrid_s_vert,pgrid_e_vert-1
1943 pro_u_c(k+1) = cfld(i,k,j)
1946 !KAL fill in the surface value and the top value using extrapolation
1948 pro_u_c(1 ) = cf1_c*cfld(i,1,j) &
1949 + cf2_c*cfld(i,2,j) &
1952 pro_u_c(pgrid_e_vert+1) = cfn_c *cfld(i,pgrid_e_vert-1,j) &
1953 + cfn1_c*cfld(i,pgrid_e_vert-2,j)
1955 call inter_wrf_copy(pro_u_c, alt_u_c, pgrid_e_vert+1, pro_u_n, alt_u_n, kde+1)
1958 cfld(i,k,j) = pro_u_n(k+1)
1965 END SUBROUTINE vert_interp_vert_nesting
1967 !==================================
1969 SUBROUTINE vert_interp_vert_nesting_w ( cfld, & ! CD field
1970 ids, ide, kds, kde, jds, jde, &
1971 ims, ime, kms, kme, jms, jme, &
1972 its, ite, kts, kte, jts, jte, &
1973 pgrid_s_vert, pgrid_e_vert, & ! vertical dimensions of parent grid
1976 !KAL vertical interpolation at w points for vertical nesting
1979 REAL, DIMENSION ( ims:ime, kms:kme, jms:jme ), INTENT(INOUT) :: cfld
1980 INTEGER, INTENT(IN) :: ids, ide, kds, kde, jds, jde, &
1981 ims, ime, kms, kme, jms, jme, &
1982 its, ite, kts, kte, jts, jte
1983 INTEGER, INTENT(IN) :: pgrid_s_vert, pgrid_e_vert ! vertical dimensions of the parent grid
1984 REAL, DIMENSION(pgrid_s_vert:pgrid_e_vert), INTENT(IN) :: alt_w_c
1985 REAL, DIMENSION(kde), INTENT(IN) :: alt_w_n
1991 REAL, DIMENSION(pgrid_s_vert:pgrid_e_vert) :: pro_w_c ! variable in 1D on the coarse grid
1992 REAL, DIMENSION(kde) :: pro_w_n
1997 ! pro_w_c is w on the 1D coarse grid
1999 do k = pgrid_s_vert,pgrid_e_vert
2000 pro_w_c(k) = cfld(i,k,j)
2003 call inter_wrf_copy(pro_w_c, alt_w_c, pgrid_e_vert, pro_w_n, alt_w_n, kde)
2006 cfld(i,k,j) = pro_w_n(k)
2013 END SUBROUTINE vert_interp_vert_nesting_w
2015 !-----------------------------------------------------------------------------------------
2017 SUBROUTINE vert_interp_vert_nesting_1d ( cfld, & ! CD field
2018 ids, ide, kds, kde, jds, jde, &
2019 ims, ime, kms, kme, jms, jme, &
2020 its, ite, kts, kte, jts, jte, &
2021 pgrid_s_vert, pgrid_e_vert, & ! vertical dimensions of parent grid
2022 cf1_c, cf2_c, cf3_c, cfn_c, cfn1_c, & ! coarse grid extrapolation constants
2025 !KAL vertical interpolation for u, v, and mass points (w is below in a different subroutine) for vertical nesting
2028 REAL, DIMENSION (kms:kme),INTENT(INOUT) :: cfld
2029 INTEGER, INTENT(IN) :: ids, ide, kds, kde, jds, jde, &
2030 ims, ime, kms, kme, jms, jme, &
2031 its, ite, kts, kte, jts, jte
2032 INTEGER, INTENT(IN) :: pgrid_s_vert, pgrid_e_vert ! vertical dimensions of the parent grid
2033 REAL, INTENT(IN) :: cf1_c, cf2_c, cf3_c, cfn_c, cfn1_c
2034 REAL, DIMENSION(pgrid_s_vert:pgrid_e_vert+1), INTENT(IN) :: alt_u_c
2035 REAL, DIMENSION(kde+1), INTENT(IN) :: alt_u_n
2041 REAL, DIMENSION(pgrid_s_vert:pgrid_e_vert+1) :: pro_u_c ! variable in 1D on the coarse grid
2042 REAL, DIMENSION(kde+1) :: pro_u_n
2045 ! pro_u_c is u on the 1D coarse grid
2047 do k = pgrid_s_vert,pgrid_e_vert-1
2048 pro_u_c(k+1) = cfld(k)
2051 !KAL fill in the surface value and the top value using extrapolation
2053 pro_u_c(1 ) = cf1_c*cfld(1) &
2057 pro_u_c(pgrid_e_vert+1) = cfn_c *cfld(pgrid_e_vert-1) &
2058 + cfn1_c*cfld(pgrid_e_vert-2)
2060 call inter_wrf_copy(pro_u_c, alt_u_c, pgrid_e_vert+1, pro_u_n, alt_u_n, kde+1)
2063 cfld(k) = pro_u_n(k+1)
2067 END SUBROUTINE vert_interp_vert_nesting_1d
2070 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2071 !KAL this is a direct copy of a subroutine from ndown, but a dependency on ndown will not work because it is not always compiled (for ideal cases), and most likely not compliled in the order needed.
2073 SUBROUTINE inter_wrf_copy(pro_c,alt_c,kde_c,pro_n,alt_n,kde_n)
2075 !KAL this routine has been added for vertical nesting
2078 INTEGER , INTENT(IN) :: kde_c,kde_n
2079 REAL , DIMENSION(kde_c) , INTENT(IN ) :: pro_c,alt_c
2080 REAL , DIMENSION(kde_n) , INTENT(IN ) :: alt_n
2081 REAL , DIMENSION(kde_n) , INTENT(OUT) :: pro_n
2083 real ,dimension(kde_c) :: a,b,c,d
2088 call coeff_mon_wrf_copy(alt_c,pro_c,a,b,c,d,kde_c)
2094 if ( (alt_n(i) .ge. alt_c(j)).and.(alt_n(i) .lt. alt_c(j+1)) ) then
2095 p = alt_n(i)-alt_c(j)
2096 pro_n(i) = p*( p*(a(j)*p+b(j))+c(j)) + d(j)
2103 pro_n(kde_n) = pro_c(kde_c)
2106 END SUBROUTINE inter_wrf_copy
2108 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11
2109 !KAL this is a direct copy of a subroutine from ndown, but a dependency on ndown will not work because it is not always compiled (for ideal cases), and most likely not compliled in the order needed.
2111 subroutine coeff_mon_wrf_copy(x,y,a,b,c,d,n)
2113 !KAL this routine has been added for vertical nesting
2118 real ,dimension(n) :: x,y,a,b,c,d
2119 real ,dimension(n) :: h,s,p,yp
2125 h(i) = (x(i+1)-x(i))
2126 s(i) = (y(i+1)-y(i)) / h(i)
2130 p(i) = (s(i-1)*h(i)+s(i)*h(i-1)) / (h(i-1)+h(i))
2139 !!!!!!!!!!!!!!!!!!!!!
2142 yp(i) = (sign(1.,s(i-1))+sign(1.,s(i)))* min( abs(s(i-1)),abs(s(i)),0.5*abs(p(i)))
2146 a(i) = (yp(i)+yp(i+1)-2.*s(i))/(h(i)*h(i))
2147 b(i) = (3.*s(i)-2.*yp(i)-yp(i+1))/h(i)
2152 end subroutine coeff_mon_wrf_copy
2154 !-----------------------------------------------------------------------------------------
2157 !==================================
2159 SUBROUTINE p2c ( cfld, & ! CD field
2160 cids, cide, ckds, ckde, cjds, cjde, &
2161 cims, cime, ckms, ckme, cjms, cjme, &
2162 cits, cite, ckts, ckte, cjts, cjte, &
2164 nids, nide, nkds, nkde, njds, njde, &
2165 nims, nime, nkms, nkme, njms, njme, &
2166 nits, nite, nkts, nkte, njts, njte, &
2167 shw, & ! stencil half width
2168 imask, & ! interpolation mask
2169 xstag, ystag, & ! staggering of field
2170 ipos, jpos, & ! Position of lower left of nest in CD
2171 nri, nrj & ! nest ratios
2173 USE module_configure
2176 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2177 cims, cime, ckms, ckme, cjms, cjme, &
2178 cits, cite, ckts, ckte, cjts, cjte, &
2179 nids, nide, nkds, nkde, njds, njde, &
2180 nims, nime, nkms, nkme, njms, njme, &
2181 nits, nite, nkts, nkte, njts, njte, &
2186 LOGICAL, INTENT(IN) :: xstag, ystag
2188 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
2189 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
2190 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2192 CALL interp_fcn (cfld, & ! CD field
2193 cids, cide, ckds, ckde, cjds, cjde, &
2194 cims, cime, ckms, ckme, cjms, cjme, &
2195 cits, cite, ckts, ckte, cjts, cjte, &
2197 nids, nide, nkds, nkde, njds, njde, &
2198 nims, nime, nkms, nkme, njms, njme, &
2199 nits, nite, nkts, nkte, njts, njte, &
2200 shw, & ! stencil half width for interp
2201 imask, & ! interpolation mask
2202 xstag, ystag, & ! staggering of field
2203 ipos, jpos, & ! Position of lower left of nest in CD
2204 nri, nrj ) ! nest ratios
2208 !==================================
2210 SUBROUTINE c2f_interp ( cfld, & ! CD field
2211 cids, cide, ckds, ckde, cjds, cjde, &
2212 cims, cime, ckms, ckme, cjms, cjme, &
2213 cits, cite, ckts, ckte, cjts, cjte, &
2215 nids, nide, nkds, nkde, njds, njde, &
2216 nims, nime, nkms, nkme, njms, njme, &
2217 nits, nite, nkts, nkte, njts, njte, &
2218 shw, & ! stencil half width
2219 imask, & ! interpolation mask
2220 xstag, ystag, & ! staggering of field
2221 ipos, jpos, & ! Position of lower left of nest in CD
2222 nri, nrj, & ! nest ratios
2223 ! cbdy_xs, nbdy_xs, &
2224 ! cbdy_xe, nbdy_xe, &
2225 ! cbdy_ys, nbdy_ys, &
2226 ! cbdy_ye, nbdy_ye, &
2227 ! cbdy_txs, nbdy_txs, &
2228 ! cbdy_txe, nbdy_txe, &
2229 ! cbdy_tys, nbdy_tys, &
2230 ! cbdy_tye, nbdy_tye, &
2231 parent_id,nest_id &!cyl
2233 USE module_configure
2236 !------------------------------------------------------------
2237 ! Subroutine c2f_interp interpolate field from coarse resolution domain
2238 ! to its nested domain. It is written by Dave Gill in NCAR for the purpose
2239 ! running phys/module_sf_oml.F-DPWP in only d01 and d02
2240 ! Chiaying Lee RSMAS/UM
2241 !------------------------------------------------------------
2243 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2244 cims, cime, ckms, ckme, cjms, cjme, &
2245 cits, cite, ckts, ckte, cjts, cjte, &
2246 nids, nide, nkds, nkde, njds, njde, &
2247 nims, nime, nkms, nkme, njms, njme, &
2248 nits, nite, nkts, nkte, njts, njte, &
2251 nri, nrj,parent_id,nest_id !cyl
2253 LOGICAL, INTENT(IN) :: xstag, ystag
2255 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
2256 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
2257 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2258 ! REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_xs, cbdy_txs, nbdy_xs, nbdy_txs
2259 ! REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_xe, cbdy_txe, nbdy_xe, nbdy_txe
2260 ! REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_ys, cbdy_tys, nbdy_ys, nbdy_tys
2261 ! REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_ye, cbdy_tye, nbdy_ye, nbdy_tye
2266 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
2268 ! Iterate over the ND tile and compute the values
2271 !write(0,'("mask cits:cite, ckts:ckte, cjts:cjte ",6i4)')cits,cite, ckts,ckte, cjts,cjte
2272 !write(0,'("mask nits:nite, nkts:nkte, njts:njte ",6i4)')nits,nite, nkts,nkte, njts,njte
2273 ! write(0,*)'cyl parentid',parent_id
2274 ! write(0,*)'cyl nestid',nest_id
2275 ! If ( nest_id .le. 2 .and. (1.0/rdx .ge. 3000.0 .and. 1.0/rdy .ge. 3000.0) ) then ! cyl: only run it in the nest domain with dx, dy < 3 km
2276 If ( nest_id .eq. 3 ) then
2279 cj = jpos + (nj-1) / nrj ! j coord of CD point
2280 jp = mod ( nj , nrj ) ! coord of ND w/i CD point
2284 ci = ipos + (ni-1) / nri ! j coord of CD point
2285 ip = mod ( ni , nri ) ! coord of ND w/i CD point
2286 ! This is a trivial implementation of the interp_fcn; just copies
2287 ! the values from the CD into the ND
2288 nfld( ni, nk, nj ) = cfld( ci , ck , cj )
2295 END SUBROUTINE c2f_interp
2297 !==================================
2299 SUBROUTINE bdy_interp ( cfld, & ! CD field
2300 cids, cide, ckds, ckde, cjds, cjde, &
2301 cims, cime, ckms, ckme, cjms, cjme, &
2302 cits, cite, ckts, ckte, cjts, cjte, &
2304 nids, nide, nkds, nkde, njds, njde, &
2305 nims, nime, nkms, nkme, njms, njme, &
2306 nits, nite, nkts, nkte, njts, njte, &
2307 shw, & ! stencil half width
2308 imask, & ! interpolation mask
2309 xstag, ystag, & ! staggering of field
2310 ipos, jpos, & ! Position of lower left of nest in CD
2311 nri, nrj, & ! nest ratios
2312 cbdy_xs, nbdy_xs, & ! Boundary components, for the CG and FG,
2313 cbdy_xe, nbdy_xe, & ! for each of the four sides (x start, e end, y start, y end)
2314 cbdy_ys, nbdy_ys, & ! and also for the two components of the LBC:
2315 cbdy_ye, nbdy_ye, & ! the "starting" value and the tendency
2316 cbdy_txs, nbdy_txs, &
2317 cbdy_txe, nbdy_txe, & ! The CG is at a parent time step ahead of the FG
2318 cbdy_tys, nbdy_tys, &
2319 cbdy_tye, nbdy_tye, &
2320 cdt, ndt ) ! Time step size for CG and FG
2322 USE module_interp_info
2326 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2327 cims, cime, ckms, ckme, cjms, cjme, &
2328 cits, cite, ckts, ckte, cjts, cjte, &
2329 nids, nide, nkds, nkde, njds, njde, &
2330 nims, nime, nkms, nkme, njms, njme, &
2331 nits, nite, nkts, nkte, njts, njte, &
2336 LOGICAL, INTENT(IN) :: xstag, ystag
2338 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
2339 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
2340 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2341 REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_xs, cbdy_txs, nbdy_xs, nbdy_txs
2342 REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_xe, cbdy_txe, nbdy_xe, nbdy_txe
2343 REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_ys, cbdy_tys, nbdy_ys, nbdy_tys
2344 REAL, DIMENSION( * ), INTENT(INOUT) :: cbdy_ye, cbdy_tye, nbdy_ye, nbdy_tye
2349 INTEGER nijds, nijde, spec_bdy_width
2351 nijds = min(nids, njds)
2352 nijde = max(nide, njde)
2353 CALL nl_get_spec_bdy_width( 1, spec_bdy_width )
2355 IF ( interp_method_type .EQ. NOT_DEFINED_YET ) THEN
2356 interp_method_type = SINT
2359 IF ( interp_method_type .EQ. SINT ) THEN
2360 CALL bdy_interp1( cfld, & ! CD field
2361 cids, cide, ckds, ckde, cjds, cjde, &
2362 cims, cime, ckms, ckme, cjms, cjme, &
2363 cits, cite, ckts, ckte, cjts, cjte, &
2365 nijds, nijde , & ! start and end of nest LBC size in the LONG direction
2366 spec_bdy_width , & ! width of the LBC, the SHORT direction
2367 nids, nide, nkds, nkde, njds, njde, &
2368 nims, nime, nkms, nkme, njms, njme, &
2369 nits, nite, nkts, nkte, njts, njte, &
2371 xstag, ystag, & ! staggering of field
2372 ipos, jpos, & ! Position of lower left of nest in CD
2374 cbdy_xs, nbdy_xs, & ! Boundary components, for the CG and FG,
2375 cbdy_xe, nbdy_xe, & ! for each of the four sides (x start, e end, y start, y end)
2376 cbdy_ys, nbdy_ys, & ! and also for the two components of the LBC:
2377 cbdy_ye, nbdy_ye, & ! the "starting" value and the tendency
2378 cbdy_txs, nbdy_txs, &
2379 cbdy_txe, nbdy_txe, & ! The CG is at a parent time step ahead of the FG
2380 cbdy_tys, nbdy_tys, &
2381 cbdy_tye, nbdy_tye, &
2382 cdt, ndt & ! Time step size for CG and FG
2385 ELSE IF ( ( interp_method_type .EQ. BILINEAR ) .OR. &
2386 ( interp_method_type .EQ. NEAREST_NEIGHBOR ) .OR. &
2387 ( interp_method_type .EQ. QUADRATIC ) .OR. &
2388 ( interp_method_type .EQ. SPLINE ) .OR. &
2389 ( interp_method_type .EQ. SINT_NEW ) ) THEN
2390 CALL bdy_interp2( cfld, & ! CD field
2391 cids, cide, ckds, ckde, cjds, cjde, &
2392 cims, cime, ckms, ckme, cjms, cjme, &
2393 cits, cite, ckts, ckte, cjts, cjte, &
2395 nijds, nijde , & ! start and end of nest LBC size in the LONG direction
2396 spec_bdy_width , & ! width of the LBC, the SHORT direction
2397 nids, nide, nkds, nkde, njds, njde, &
2398 nims, nime, nkms, nkme, njms, njme, &
2399 nits, nite, nkts, nkte, njts, njte, &
2401 xstag, ystag, & ! staggering of field
2402 ipos, jpos, & ! Position of lower left of nest in CD
2404 cbdy_xs, nbdy_xs, & ! Boundary components, for the CG and FG,
2405 cbdy_xe, nbdy_xe, & ! for each of the four sides (x start, e end, y start, y end)
2406 cbdy_ys, nbdy_ys, & ! and also for the two components of the LBC:
2407 cbdy_ye, nbdy_ye, & ! the "starting" value and the tendency
2408 cbdy_txs, nbdy_txs, &
2409 cbdy_txe, nbdy_txe, & ! The CG is at a parent time step ahead of the FG
2410 cbdy_tys, nbdy_tys, &
2411 cbdy_tye, nbdy_tye, &
2412 cdt, ndt & ! Time step size for CG and FG
2416 CALL wrf_error_fatal ('Hold on there cowboy #2, we need to know which nested lateral boundary interpolation option you want')
2419 END SUBROUTINE bdy_interp
2421 !==================================
2423 SUBROUTINE bdy_interp1( cfld, & ! CD field
2424 cids, cide, ckds, ckde, cjds, cjde, &
2425 cims, cime, ckms, ckme, cjms, cjme, &
2426 cits, cite, ckts, ckte, cjts, cjte, &
2428 nijds, nijde, spec_bdy_width , &
2429 nids, nide, nkds, nkde, njds, njde, &
2430 nims, nime, nkms, nkme, njms, njme, &
2431 nits, nite, nkts, nkte, njts, njte, &
2433 imask, & ! interpolation mask
2434 xstag, ystag, & ! staggering of field
2435 ipos, jpos, & ! Position of lower left of nest in CD
2441 cbdy_txs, bdy_txs, &
2442 cbdy_txe, bdy_txe, &
2443 cbdy_tys, bdy_tys, &
2444 cbdy_tye, bdy_tye, &
2448 ! USE module_configure , ONLY : nl_get_spec_zone, nl_get_relax_zone
2449 USE module_state_description
2453 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2454 cims, cime, ckms, ckme, cjms, cjme, &
2455 cits, cite, ckts, ckte, cjts, cjte, &
2456 nids, nide, nkds, nkde, njds, njde, &
2457 nims, nime, nkms, nkme, njms, njme, &
2458 nits, nite, nkts, nkte, njts, njte, &
2462 INTEGER, INTENT(IN) :: nijds, nijde, spec_bdy_width
2463 LOGICAL, INTENT(IN) :: xstag, ystag
2465 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ), INTENT(INOUT) :: cfld
2466 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ), INTENT(INOUT) :: nfld
2467 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2468 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_xs, cbdy_txs ! not used
2469 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_xe, cbdy_txe ! not used
2470 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_ys, cbdy_tys ! not used
2471 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_ye, cbdy_tye ! not used
2473 REAL, DIMENSION ( njms:njme, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_xs, bdy_txs
2474 REAL, DIMENSION ( njms:njme, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_xe, bdy_txe
2475 REAL, DIMENSION ( nims:nime, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_ys, bdy_tys
2476 REAL, DIMENSION ( nims:nime, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_ye, bdy_tye
2481 INTEGER ci, cj, ck, ni, nj, nk, ni1, nj1, nk1, ip, jp, ioff, joff
2485 REAL psca1(cims:cime,cjms:cjme,nri*nrj)
2486 REAL psca(cims:cime,cjms:cjme,nri*nrj)
2487 LOGICAL icmask( cims:cime, cjms:cjme )
2496 ! statement functions for converting a nest index to coarse
2497 n2ci(n) = (n+ipos*nri-1)/nri
2498 n2cj(n) = (n+jpos*nrj-1)/nrj
2506 ioff = MAX((nri-1)/2,1)
2509 joff = MAX((nrj-1)/2,1)
2512 ! Iterate over the ND tile and compute the values
2515 CALL nl_get_spec_zone( 1, spec_zone )
2516 CALL nl_get_relax_zone( 1, relax_zone )
2517 sz = MIN(MAX( spec_zone, relax_zone + 1 ),spec_bdy_width)
2522 !$OMP PRIVATE ( i,j,k,ni,nj,ni1,nj1,ci,cj,ip,jp,nk,ck,nf,icmask,psca,psca1 )
2527 nj = (j-jpos) * nrj + ( nrj / 2 + 1 ) ! j point on nest
2529 ni = (i-ipos) * nri + ( nri / 2 + 1 ) ! i point on nest
2530 psca1(i,j,nf) = cfld(i,k,j)
2534 ! hopefully less ham handed but still correct and more efficient
2535 ! sintb ignores icmask so it does not matter that icmask is not set
2538 IF ( njts .ge. njds .and. njts .le. njds + sz + joff ) THEN
2539 CALL sintb( psca1, psca, &
2540 cims, cime, cjms, cjme, icmask, &
2541 n2ci(nits)-1, n2ci(nite)+1, n2cj(MAX(njts,njds)), n2cj(MIN(njte,njds+sz+joff)), nrj*nri, xstag, ystag )
2544 IF ( njte .le. njde .and. njte .ge. njde - sz - joff ) THEN
2545 CALL sintb( psca1, psca, &
2546 cims, cime, cjms, cjme, icmask, &
2547 n2ci(nits)-1, n2ci(nite)+1, n2cj(MAX(njts,njde-sz-joff)), n2cj(MIN(njte,njde-1+joff)), nrj*nri, xstag, ystag )
2550 IF ( nits .ge. nids .and. nits .le. nids + sz + ioff ) THEN
2551 CALL sintb( psca1, psca, &
2552 cims, cime, cjms, cjme, icmask, &
2553 n2ci(MAX(nits,nids)), n2ci(MIN(nite,nids+sz+ioff)), n2cj(njts)-1, n2cj(njte)+1, nrj*nri, xstag, ystag )
2556 IF ( nite .le. nide .and. nite .ge. nide - sz - ioff ) THEN
2557 CALL sintb( psca1, psca, &
2558 cims, cime, cjms, cjme, icmask, &
2559 n2ci(MAX(nits,nide-sz-ioff)), n2ci(MIN(nite,nide-1+ioff)), n2cj(njts)-1, n2cj(njte)+1, nrj*nri, xstag, ystag )
2562 DO nj1 = MAX(njds,njts-1), MIN(njde+joff,njte+joff+1)
2563 cj = jpos + (nj1-1) / nrj ! j coord of CD point
2564 jp = mod ( nj1-1 , nrj ) ! coord of ND w/i CD point
2567 DO ni1 = MAX(nids,nits-1), MIN(nide+ioff,nite+ioff+1)
2568 ci = ipos + (ni1-1) / nri ! j coord of CD point
2569 ip = mod ( ni1-1 , nri ) ! coord of ND w/i CD point
2574 IF ( ( ni.LT.nids) .OR. (nj.LT.njds) ) THEN
2578 !bdy contains the value at t-dt. psca contains the value at t
2579 !compute dv/dt and store in bdy_t
2580 !afterwards store the new value of v at t into bdy
2582 IF ( ni .ge. nids .and. ni .lt. nids + sz ) THEN
2583 bdy_txs( nj,k,ni ) = rdt*(psca(ci+shw,cj+shw,ip+1+(jp)*nri)-nfld(ni,k,nj))
2584 bdy_xs( nj,k,ni ) = nfld(ni,k,nj)
2588 IF ( nj .ge. njds .and. nj .lt. njds + sz ) THEN
2589 bdy_tys( ni,k,nj ) = rdt*(psca(ci+shw,cj+shw,ip+1+(jp)*nri)-nfld(ni,k,nj))
2590 bdy_ys( ni,k,nj ) = nfld(ni,k,nj)
2595 IF ( ni .ge. nide - sz + 1 .AND. ni .le. nide ) THEN
2596 bdy_txe( nj,k,nide-ni+1 ) = rdt*(psca(ci+shw,cj+shw,ip+1+(jp)*nri)-nfld(ni,k,nj))
2597 bdy_xe( nj,k,nide-ni+1 ) = nfld(ni,k,nj)
2600 IF ( ni .ge. nide - sz .AND. ni .le. nide-1 ) THEN
2601 bdy_txe( nj,k,nide-ni ) = rdt*(psca(ci+shw,cj+shw,ip+1+(jp)*nri)-nfld(ni,k,nj))
2602 bdy_xe( nj,k,nide-ni ) = nfld(ni,k,nj)
2608 IF ( nj .ge. njde - sz + 1 .AND. nj .le. njde ) THEN
2609 bdy_tye( ni,k,njde-nj+1 ) = rdt*(psca(ci+shw,cj+shw,ip+1+(jp)*nri)-nfld(ni,k,nj))
2610 bdy_ye( ni,k,njde-nj+1 ) = nfld(ni,k,nj)
2613 IF ( nj .ge. njde - sz .AND. nj .le. njde-1 ) THEN
2614 bdy_tye(ni,k,njde-nj ) = rdt*(psca(ci+shw,cj+shw,ip+1+(jp)*nri)-nfld(ni,k,nj))
2615 bdy_ye( ni,k,njde-nj ) = nfld(ni,k,nj)
2622 !$OMP END PARALLEL DO
2626 END SUBROUTINE bdy_interp1
2628 !==================================
2630 SUBROUTINE bdy_interp2( cfld, & ! CD field
2631 cids, cide, ckds, ckde, cjds, cjde, &
2632 cims, cime, ckms, ckme, cjms, cjme, &
2633 cits, cite, ckts, ckte, cjts, cjte, &
2635 nijds, nijde, spec_bdy_width , &
2636 nids, nide, nkds, nkde, njds, njde, &
2637 nims, nime, nkms, nkme, njms, njme, &
2638 nits, nite, nkts, nkte, njts, njte, &
2640 imask, & ! interpolation mask
2641 xstag, ystag, & ! staggering of field
2642 ipos, jpos, & ! Position of lower left of nest in CD
2648 cbdy_txs, bdy_txs, &
2649 cbdy_txe, bdy_txe, &
2650 cbdy_tys, bdy_tys, &
2651 cbdy_tye, bdy_tye, &
2655 ! USE module_configure , ONLY : nl_get_spec_zone, nl_get_relax_zone
2656 ! USE module_state_description
2657 USE module_interp_info
2661 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2662 cims, cime, ckms, ckme, cjms, cjme, &
2663 cits, cite, ckts, ckte, cjts, cjte, &
2664 nids, nide, nkds, nkde, njds, njde, &
2665 nims, nime, nkms, nkme, njms, njme, &
2666 nits, nite, nkts, nkte, njts, njte, &
2670 INTEGER, INTENT(IN) :: nijds, nijde, spec_bdy_width
2671 LOGICAL, INTENT(IN) :: xstag, ystag
2673 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ), INTENT(INOUT) :: cfld
2674 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ), INTENT(INOUT) :: nfld
2675 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2676 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_xs, cbdy_txs ! not used
2677 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_xe, cbdy_txe ! not used
2678 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_ys, cbdy_tys ! not used
2679 REAL, DIMENSION ( * ), INTENT(INOUT) :: cbdy_ye, cbdy_tye ! not used
2681 REAL, DIMENSION ( njms:njme, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_xs, bdy_txs
2682 REAL, DIMENSION ( njms:njme, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_xe, bdy_txe
2683 REAL, DIMENSION ( nims:nime, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_ys, bdy_tys
2684 REAL, DIMENSION ( nims:nime, nkms:nkme, spec_bdy_width ), INTENT(INOUT) :: bdy_ye, bdy_tye
2688 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld_horiz_interp ! mem dimensioned on purpose
2689 ! to allow interpolating routine
2690 ! to assume this is a mem
2692 INTEGER ni, nj, nk, istag, jstag
2699 shw = 0 ! dummy, not used, but needed for the calling interface
2701 ! Horizontally interpolate the CG to the FG, store in nfld_horiz_interp
2703 CALL interp_fcn ( cfld, & ! CD field
2704 cids, cide, ckds, ckde, cjds, cjde, &
2705 cims, cime, ckms, ckme, cjms, cjme, &
2706 cits, cite, ckts, ckte, cjts, cjte, &
2707 nfld_horiz_interp, & ! ND field
2708 nids, nide, nkds, nkde, njds, njde, &
2709 nims, nime, nkms, nkme, njms, njme, &
2710 MAX(nits-nri,nids),MIN(nite+nri,nide),&
2712 MAX(njts-nrj,njds),MIN(njte+nrj,njde),&
2713 shw, & ! stencil half width for interp
2714 imask, & ! interpolation mask
2715 xstag, ystag, & ! staggering of field
2716 ipos, jpos, & ! Position of lower left of nest in CD
2717 ! ipos-1, jpos-1, & ! Position of lower left of nest in CD
2718 nri, nrj ) ! Nest ratio, i- and j-directions
2720 ! Staggering, to determine loop indexes
2733 ! CG time step reciprocal, for computing tendencies.
2737 CALL nl_get_spec_zone( 1, spec_zone )
2738 CALL nl_get_relax_zone( 1, relax_zone )
2740 ! Belt and suspenders ... sz is just spec_bdy_width.
2742 sz = MIN(MAX( spec_zone, relax_zone + 1 ),spec_bdy_width)
2745 !$OMP PRIVATE ( ni,nj,nk )
2747 DO nj = MAX ( njts-nrj, njds ) , MIN ( njte+nrj, njde-jstag )
2749 DO ni = MAX( nits-nri, nids ) , MIN ( nite+nri, nide-istag )
2753 IF ( ni .LT. nids + sz ) THEN
2754 bdy_txs(nj,nk,ni) = rdt*(nfld_horiz_interp(ni,nk,nj)-nfld(ni,nk,nj))
2755 bdy_xs (nj,nk,ni) = nfld(ni,nk,nj)
2760 IF ( nj .LT. njds + sz ) THEN
2761 bdy_tys(ni,nk,nj) = rdt*(nfld_horiz_interp(ni,nk,nj)-nfld(ni,nk,nj))
2762 bdy_ys (ni,nk,nj) = nfld(ni,nk,nj)
2768 IF ( ( ni .GE. nide - sz + 1 ) .AND. ( ni .LE. nide ) ) THEN
2769 bdy_txe(nj,nk,nide-ni+1) = rdt*(nfld_horiz_interp(ni,nk,nj)-nfld(ni,nk,nj))
2770 bdy_xe (nj,nk,nide-ni+1) = nfld(ni,nk,nj)
2773 IF ( ( ni .GE. nide - sz ) .AND. ( ni .LE. nide-1 ) ) THEN
2774 bdy_txe(nj,nk,nide-ni ) = rdt*(nfld_horiz_interp(ni,nk,nj)-nfld(ni,nk,nj))
2775 bdy_xe (nj,nk,nide-ni ) = nfld(ni,nk,nj)
2782 IF ( ( nj .GE. njde - sz + 1 ) .AND. ( nj .LE. njde ) ) THEN
2783 bdy_tye(ni,nk,njde-nj+1) = rdt*(nfld_horiz_interp(ni,nk,nj)-nfld(ni,nk,nj))
2784 bdy_ye (ni,nk,njde-nj+1) = nfld(ni,nk,nj)
2787 IF ( ( nj .GE. njde - sz ) .AND. ( nj .LE. njde-1 ) ) THEN
2788 bdy_tye(ni,nk,njde-nj ) = rdt*(nfld_horiz_interp(ni,nk,nj)-nfld(ni,nk,nj))
2789 bdy_ye (ni,nk,njde-nj ) = nfld(ni,nk,nj)
2797 !$OMP END PARALLEL DO
2799 END SUBROUTINE bdy_interp2
2801 !==================================
2803 SUBROUTINE interp_fcni( cfld, & ! CD field
2804 cids, cide, ckds, ckde, cjds, cjde, &
2805 cims, cime, ckms, ckme, cjms, cjme, &
2806 cits, cite, ckts, ckte, cjts, cjte, &
2808 nids, nide, nkds, nkde, njds, njde, &
2809 nims, nime, nkms, nkme, njms, njme, &
2810 nits, nite, nkts, nkte, njts, njte, &
2811 shw, & ! stencil half width
2812 imask, & ! interpolation mask
2813 xstag, ystag, & ! staggering of field
2814 ipos, jpos, & ! Position of lower left of nest in CD
2815 nri, nrj ) ! nest ratios
2816 USE module_configure
2820 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2821 cims, cime, ckms, ckme, cjms, cjme, &
2822 cits, cite, ckts, ckte, cjts, cjte, &
2823 nids, nide, nkds, nkde, njds, njde, &
2824 nims, nime, nkms, nkme, njms, njme, &
2825 nits, nite, nkts, nkte, njts, njte, &
2829 LOGICAL, INTENT(IN) :: xstag, ystag
2831 INTEGER, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
2832 INTEGER, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
2833 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2837 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
2839 ! Iterate over the ND tile and compute the values
2842 !write(0,'("cits:cite, ckts:ckte, cjts:cjte ",6i4)')cits,cite, ckts,ckte, cjts,cjte
2843 !write(0,'("nits:nite, nkts:nkte, njts:njte ",6i4)')nits,nite, nkts,nkte, njts,njte
2846 cj = jpos + (nj-1) / nrj ! j coord of CD point
2847 jp = mod ( nj , nrj ) ! coord of ND w/i CD point
2851 if ( imask(ni,nj) .NE. 1 ) cycle
2852 ci = ipos + (ni-1) / nri ! j coord of CD point
2853 ip = mod ( ni , nri ) ! coord of ND w/i CD point
2854 ! This is a trivial implementation of the interp_fcn; just copies
2855 ! the values from the CD into the ND
2856 nfld( ni, nk, nj ) = cfld( ci , ck , cj )
2863 END SUBROUTINE interp_fcni
2865 SUBROUTINE interp_fcnm( cfld, & ! CD field
2866 cids, cide, ckds, ckde, cjds, cjde, &
2867 cims, cime, ckms, ckme, cjms, cjme, &
2868 cits, cite, ckts, ckte, cjts, cjte, &
2870 nids, nide, nkds, nkde, njds, njde, &
2871 nims, nime, nkms, nkme, njms, njme, &
2872 nits, nite, nkts, nkte, njts, njte, &
2873 shw, & ! stencil half width
2874 imask, & ! interpolation mask
2875 xstag, ystag, & ! staggering of field
2876 ipos, jpos, & ! Position of lower left of nest in CD
2877 nri, nrj ) ! nest ratios
2878 USE module_configure
2882 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2883 cims, cime, ckms, ckme, cjms, cjme, &
2884 cits, cite, ckts, ckte, cjts, cjte, &
2885 nids, nide, nkds, nkde, njds, njde, &
2886 nims, nime, nkms, nkme, njms, njme, &
2887 nits, nite, nkts, nkte, njts, njte, &
2891 LOGICAL, INTENT(IN) :: xstag, ystag
2893 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
2894 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
2895 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2899 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
2901 ! Iterate over the ND tile and compute the values
2904 !write(0,'("mask cits:cite, ckts:ckte, cjts:cjte ",6i4)')cits,cite, ckts,ckte, cjts,cjte
2905 !write(0,'("mask nits:nite, nkts:nkte, njts:njte ",6i4)')nits,nite, nkts,nkte, njts,njte
2908 cj = jpos + (nj-1) / nrj ! j coord of CD point
2909 jp = mod ( nj , nrj ) ! coord of ND w/i CD point
2913 ci = ipos + (ni-1) / nri ! j coord of CD point
2914 ip = mod ( ni , nri ) ! coord of ND w/i CD point
2915 ! This is a trivial implementation of the interp_fcn; just copies
2916 ! the values from the CD into the ND
2917 nfld( ni, nk, nj ) = cfld( ci , ck , cj )
2924 END SUBROUTINE interp_fcnm
2926 SUBROUTINE interp_fcnm_lu( cfld, & ! CD field
2927 cids, cide, ckds, ckde, cjds, cjde, &
2928 cims, cime, ckms, ckme, cjms, cjme, &
2929 cits, cite, ckts, ckte, cjts, cjte, &
2931 nids, nide, nkds, nkde, njds, njde, &
2932 nims, nime, nkms, nkme, njms, njme, &
2933 nits, nite, nkts, nkte, njts, njte, &
2934 shw, & ! stencil half width
2935 imask, & ! interpolation mask
2936 xstag, ystag, & ! staggering of field
2937 ipos, jpos, & ! Position of lower left of nest in CD
2938 nri, nrj, & ! nest ratios
2943 USE module_configure
2948 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
2949 cims, cime, ckms, ckme, cjms, cjme, &
2950 cits, cite, ckts, ckte, cjts, cjte, &
2951 nids, nide, nkds, nkde, njds, njde, &
2952 nims, nime, nkms, nkme, njms, njme, &
2953 nits, nite, nkts, nkte, njts, njte, &
2958 LOGICAL, INTENT(IN) :: xstag, ystag
2960 REAL, INTENT(IN) :: cdx, ndx
2962 REAL, INTENT(IN), DIMENSION ( cims:cime, cjms:cjme ) :: cxlat, cxlong
2963 REAL, INTENT(IN), DIMENSION ( nims:nime, njms:njme ) :: nxlat, nxlong
2966 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
2967 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
2968 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
2972 INTEGER i, ci, cj, ck, ni, nj, nk, ip, jp, ierr
2974 #ifdef TERRAIN_AND_LANDUSE
2975 INTEGER, DIMENSION(256) :: ipath ! array for integer coded ascii for passing path down to get_landuse
2977 REAL , ALLOCATABLE, DIMENSION(:,:) :: xlat_g, xlon_g, landuse_g
2978 CHARACTER*256 :: message
2979 CHARACTER*256 :: rsmas_data_path
2981 LOGICAL :: input_from_hires, input_from_file
2983 INTEGER, EXTERNAL :: get_landuse
2984 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
2986 CALL nl_get_input_from_hires( nid , input_from_hires)
2987 CALL nl_get_input_from_file ( nid , input_from_file )
2989 IF ( input_from_file .AND. input_from_hires ) THEN
2990 Write(message, '(a,i3,a)') &
2991 "Warning : input_from_file turned on for domain ", nid, ", input_from_hires disabled"
2992 CALL wrf_message(message)
2995 IF ( .NOT. input_from_file .AND. input_from_hires ) THEN
2997 allocate(xlat_g(nids:nide,njds:njde))
2998 allocate(xlon_g(nids:nide,njds:njde))
2999 allocate(landuse_g(nids:nide,njds:njde))
3001 CALL nl_get_rsmas_data_path(1,rsmas_data_path)
3003 DO i = 1, LEN(TRIM(rsmas_data_path))
3004 ipath(i) = ICHAR(rsmas_data_path(i:i))
3007 #if ( defined( DM_PARALLEL ) && ( ! defined( STUBMPI ) ) )
3008 CALL wrf_patch_to_global_real ( nxlat, xlat_g , nid, ' ' , 'xy' , &
3009 nids, nide-1 , njds , njde-1 , 1 , 1 , &
3010 nims, nime , njms , njme , 1 , 1 , &
3011 nits, nite , njts , njte , 1 , 1 )
3012 CALL wrf_patch_to_global_real ( nxlong, xlon_g, nid, ' ' , 'xy' , &
3013 nids, nide-1 , njds , njde-1 , 1 , 1 , &
3014 nims, nime , njms , njme , 1 , 1 , &
3015 nits, nite , njts , njte , 1 , 1 )
3016 IF ( wrf_dm_on_monitor() ) THEN
3017 ierr = get_landuse ( ndx/1000., xlat_g, xlon_g, &
3019 nide-nids+1,njde-njds+1,nide-nids+1,njde-njds+1, &
3020 ipath, LEN(TRIM(rsmas_data_path)) )
3021 IF ( ierr == 1 ) THEN
3022 WRITE(message,fmt='(a)') 'get_landuse : aborted!'
3023 CALL wrf_error_fatal(TRIM(message))
3027 CALL wrf_global_to_patch_real ( landuse_g , nfld(:,1,:), nid, ' ' , 'xy' , &
3028 nids, nide-1 , njds , njde-1 , 1 , 1 , &
3029 nims, nime , njms , njme , 1 , 1 , &
3030 nits, nite , njts , njte , 1 , 1 )
3033 ierr = get_landuse ( ndx/1000., nxlat(nids:nide,njds:njde), nxlong(nids:nide,njds:njde), &
3034 nfld(nids:nide,1,njds:njde), &
3035 nide-nids+1,njde-njds+1,nide-nids+1,njde-njds+1, &
3036 ipath, LEN(TRIM(rsmas_data_path)) )
3040 deallocate(landuse_g)
3043 ! Iterate over the ND tile and compute the values
3046 cj = jpos + (nj-1) / nrj ! j coord of CD point
3047 jp = mod ( nj , nrj ) ! coord of ND w/i CD point
3051 ci = ipos + (ni-1) / nri ! j coord of CD point
3052 ip = mod ( ni , nri ) ! coord of ND w/i CD point
3053 ! This is a trivial implementation of the interp_fcn; just copies
3054 ! the values from the CD into the ND
3055 if ( imask(ni,nj) .eq. 1 ) then
3056 nfld( ni, nk, nj ) = cfld( ci , ck , cj )
3061 #ifdef TERRAIN_AND_LANDUSE
3066 END SUBROUTINE interp_fcnm_lu
3069 SUBROUTINE interp_fcnm_imask( cfld, & ! CD field
3070 cids, cide, ckds, ckde, cjds, cjde, &
3071 cims, cime, ckms, ckme, cjms, cjme, &
3072 cits, cite, ckts, ckte, cjts, cjte, &
3074 nids, nide, nkds, nkde, njds, njde, &
3075 nims, nime, nkms, nkme, njms, njme, &
3076 nits, nite, nkts, nkte, njts, njte, &
3077 shw, & ! stencil half width
3078 imask, & ! interpolation mask
3079 xstag, ystag, & ! staggering of field
3080 ipos, jpos, & ! Position of lower left of nest in CD
3081 nri, nrj ) ! nest ratios
3082 USE module_configure
3086 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
3087 cims, cime, ckms, ckme, cjms, cjme, &
3088 cits, cite, ckts, ckte, cjts, cjte, &
3089 nids, nide, nkds, nkde, njds, njde, &
3090 nims, nime, nkms, nkme, njms, njme, &
3091 nits, nite, nkts, nkte, njts, njte, &
3095 LOGICAL, INTENT(IN) :: xstag, ystag
3097 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
3098 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
3099 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
3103 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
3105 ! Iterate over the ND tile and compute the values
3108 !write(0,'("mask cits:cite, ckts:ckte, cjts:cjte ",6i4)')cits,cite, ckts,ckte,cjts,cjte
3109 !write(0,'("mask nits:nite, nkts:nkte, njts:njte ",6i4)')nits,nite, nkts,nkte,njts,njte
3112 cj = jpos + (nj-1) / nrj ! j coord of CD point
3113 jp = mod ( nj , nrj ) ! coord of ND w/i CD point
3117 ci = ipos + (ni-1) / nri ! j coord of CD point
3118 ip = mod ( ni , nri ) ! coord of ND w/i CD point
3119 ! This is a trivial implementation of the interp_fcn; just copies
3120 ! the values from the CD into the ND
3121 if ( imask(ni,nj) .eq. 1 ) then
3122 nfld( ni, nk, nj ) = cfld( ci , ck , cj )
3130 END SUBROUTINE interp_fcnm_imask
3131 ! end of first block of ARW-only routines
3133 SUBROUTINE interp_mask_land_field ( enable, & ! says whether to allow interpolation or just the bcasts
3135 cids, cide, ckds, ckde, cjds, cjde, &
3136 cims, cime, ckms, ckme, cjms, cjme, &
3137 cits, cite, ckts, ckte, cjts, cjte, &
3139 nids, nide, nkds, nkde, njds, njde, &
3140 nims, nime, nkms, nkme, njms, njme, &
3141 nits, nite, nkts, nkte, njts, njte, &
3142 shw, & ! stencil half width
3143 imask, & ! interpolation mask
3144 xstag, ystag, & ! staggering of field
3145 ipos, jpos, & ! Position of lower left of nest in CD
3146 nri, nrj, & ! nest ratios
3149 USE module_configure
3150 USE module_wrf_error
3151 USE module_dm, only : wrf_dm_sum_reals, wrf_dm_sum_integers
3156 LOGICAL, INTENT(IN) :: enable
3157 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
3158 cims, cime, ckms, ckme, cjms, cjme, &
3159 cits, cite, ckts, ckte, cjts, cjte, &
3160 nids, nide, nkds, nkde, njds, njde, &
3161 nims, nime, nkms, nkme, njms, njme, &
3162 nits, nite, nkts, nkte, njts, njte, &
3166 LOGICAL, INTENT(IN) :: xstag, ystag
3168 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
3169 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
3170 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
3172 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: clu
3173 REAL, DIMENSION ( nims:nime, njms:njme ) :: nlu
3177 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
3178 INTEGER :: icount , ii , jj , ist , ien , jst , jen , iswater, ierr
3179 REAL :: avg , sum , dx , dy
3180 INTEGER , PARAMETER :: max_search = 5
3181 CHARACTER(LEN=255) :: message
3182 INTEGER :: icount_n(nkts:nkte), idummy(nkts:nkte)
3183 REAL :: avg_n(nkts:nkte), sum_n(nkts:nkte), dummy(nkts:nkte)
3185 ! Find out what the water value is.
3187 CALL nl_get_iswater(1,iswater)
3189 ! Right now, only mass point locations permitted.
3191 IF ( ( .NOT. xstag) .AND. ( .NOT. ystag ) ) THEN
3193 ! Loop over each i,k,j in the nested domain.
3198 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3199 cj = ( nj + (nrj/2)-1 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3201 cj = ( nj + (nrj-1)/2 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3206 IF ( imask(ni, nj) .NE. 1 ) cycle
3207 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3208 ci = ( ni + (nri/2)-1 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3210 ci = ( ni + (nri-1)/2 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3217 ! (ci,cj+1) (ci+1,cj+1)
3231 ! For odd ratios, at (nri+1)/2, we are on the coarse grid point, so dx = 0
3233 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3234 dx = ( REAL ( MOD ( ni+(nri-1)/2 , nri ) ) + 0.5 ) / REAL ( nri )
3236 dx = REAL ( MOD ( ni+(nri-1)/2 , nri ) ) / REAL ( nri )
3238 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3239 dy = ( REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) + 0.5 ) / REAL ( nrj )
3241 dy = REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) / REAL ( nrj )
3244 ! This is a "land only" field. If this is a water point, no operations required.
3246 IF ( ( NINT(nlu(ni ,nj )) .EQ. iswater ) ) THEN
3247 nfld(ni,nk,nj) = cfld(ci ,ck,cj )
3249 ! If this is a nested land point, and the surrounding coarse values are all land points,
3250 ! then this is a simple 4-pt interpolation.
3252 ELSE IF ( ( NINT(nlu(ni ,nj )) .NE. iswater ) .AND. &
3253 ( NINT(clu(ci ,cj )) .NE. iswater ) .AND. &
3254 ( NINT(clu(ci+1,cj )) .NE. iswater ) .AND. &
3255 ( NINT(clu(ci ,cj+1)) .NE. iswater ) .AND. &
3256 ( NINT(clu(ci+1,cj+1)) .NE. iswater ) ) THEN
3257 nfld(ni,nk,nj) = ( 1. - dx ) * ( ( 1. - dy ) * cfld(ci ,ck,cj ) + &
3258 dy * cfld(ci ,ck,cj+1) ) + &
3259 dx * ( ( 1. - dy ) * cfld(ci+1,ck,cj ) + &
3260 dy * cfld(ci+1,ck,cj+1) )
3262 ! If this is a nested land point and there are NO coarse land values surrounding,
3263 ! we temporarily punt.
3265 ELSE IF ( ( NINT(nlu(ni ,nj )) .NE. iswater ) .AND. &
3266 ( NINT(clu(ci ,cj )) .EQ. iswater ) .AND. &
3267 ( NINT(clu(ci+1,cj )) .EQ. iswater ) .AND. &
3268 ( NINT(clu(ci ,cj+1)) .EQ. iswater ) .AND. &
3269 ( NINT(clu(ci+1,cj+1)) .EQ. iswater ) ) THEN
3272 ! If there are some water points and some land points, take an average.
3274 ELSE IF ( NINT(nlu(ni ,nj )) .NE. iswater ) THEN
3277 IF ( NINT(clu(ci ,cj )) .NE. iswater ) THEN
3279 sum = sum + cfld(ci ,ck,cj )
3281 IF ( NINT(clu(ci+1,cj )) .NE. iswater ) THEN
3283 sum = sum + cfld(ci+1,ck,cj )
3285 IF ( NINT(clu(ci ,cj+1)) .NE. iswater ) THEN
3287 sum = sum + cfld(ci ,ck,cj+1)
3289 IF ( NINT(clu(ci+1,cj+1)) .NE. iswater ) THEN
3291 sum = sum + cfld(ci+1,ck,cj+1)
3293 nfld(ni,nk,nj) = sum / REAL ( icount )
3300 ! Get an average of the whole domain for problem locations.
3307 IF ( nfld(ni,nk,nj) .NE. -1 ) THEN
3308 IF ( NINT(nlu(ni,nj)) .NE. iswater ) THEN
3309 icount_n(nk) = icount_n(nk) + 1
3310 sum_n(nk) = sum_n(nk) + nfld(ni,nk,nj)
3317 CALL wrf_dm_sum_reals( sum_n(nkts:nkte), dummy(nkts:nkte))
3319 CALL wrf_dm_sum_integers(icount_n(nkts:nkte), idummy(nkts:nkte))
3322 IF ( icount_n(nk) .GT. 0 ) &
3323 avg_n(nk) = sum_n(nk) / icount_n(nk)
3328 IF ( ANY(nfld .EQ. -1) ) THEN
3330 ! OK, if there were any of those island situations, we try to search a bit broader
3331 ! of an area in the coarse grid.
3336 IF ( imask(ni, nj) .NE. 1 ) cycle
3337 IF ( nfld(ni,nk,nj) .EQ. -1 ) THEN
3338 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3339 cj = ( nj + (nrj/2)-1 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3341 cj = ( nj + (nrj-1)/2 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3343 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3344 ci = ( ni + (nri/2)-1 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3346 ci = ( ni + (nri-1)/2 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3348 ist = MAX (ci-max_search,cits)
3349 ien = MIN (ci+max_search,cite,cide-1)
3350 jst = MAX (cj-max_search,cjts)
3351 jen = MIN (cj+max_search,cjte,cjde-1)
3356 IF ( NINT(clu(ii,jj)) .NE. iswater ) THEN
3358 sum = sum + cfld(ii,nk,jj)
3362 IF ( icount .GT. 0 ) THEN
3363 nfld(ni,nk,nj) = sum / REAL ( icount )
3365 Write(message,fmt='(a,i4,a,i4,a,f10.4)') &
3366 'horizontal interp error - island (', ni, ',', nj, '), using average ', avg_n(nk)
3367 CALL wrf_message ( message )
3368 nfld(ni,nk,nj) = avg_n(nk)
3377 CALL wrf_error_fatal ( "only unstaggered fields right now" )
3380 END SUBROUTINE interp_mask_land_field
3382 SUBROUTINE interp_mask_water_field ( enable, & ! says whether to allow interpolation or just the bcasts
3384 cids, cide, ckds, ckde, cjds, cjde, &
3385 cims, cime, ckms, ckme, cjms, cjme, &
3386 cits, cite, ckts, ckte, cjts, cjte, &
3388 nids, nide, nkds, nkde, njds, njde, &
3389 nims, nime, nkms, nkme, njms, njme, &
3390 nits, nite, nkts, nkte, njts, njte, &
3391 shw, & ! stencil half width
3392 imask, & ! interpolation mask
3393 xstag, ystag, & ! staggering of field
3394 ipos, jpos, & ! Position of lower left of nest in CD
3395 nri, nrj, & ! nest ratios
3396 clu, nlu, cflag, nflag )
3398 USE module_configure
3399 USE module_wrf_error
3400 USE module_dm, only : wrf_dm_sum_reals, wrf_dm_sum_integers
3405 LOGICAL, INTENT(IN) :: enable
3406 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
3407 cims, cime, ckms, ckme, cjms, cjme, &
3408 cits, cite, ckts, ckte, cjts, cjte, &
3409 nids, nide, nkds, nkde, njds, njde, &
3410 nims, nime, nkms, nkme, njms, njme, &
3411 nits, nite, nkts, nkte, njts, njte, &
3414 nri, nrj, cflag, nflag
3415 LOGICAL, INTENT(IN) :: xstag, ystag
3417 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
3418 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
3419 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
3421 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: clu
3422 REAL, DIMENSION ( nims:nime, njms:njme ) :: nlu
3426 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
3427 INTEGER :: icount , ii , jj , ist , ien , jst , jen, ierr
3428 REAL :: avg , sum , dx , dy
3429 INTEGER , PARAMETER :: max_search = 5
3430 INTEGER :: icount_n(nkts:nkte), idummy(nkts:nkte)
3431 REAL :: avg_n(nkts:nkte), sum_n(nkts:nkte), dummy(nkts:nkte)
3432 CHARACTER(LEN=255) :: message
3434 ! Right now, only mass point locations permitted.
3436 IF ( ( .NOT. xstag) .AND. ( .NOT. ystag ) ) THEN
3439 ! Loop over each i,k,j in the nested domain.
3442 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3443 cj = ( nj + (nrj/2)-1 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3445 cj = ( nj + (nrj-1)/2 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3450 !dave IF ( imask(ni, nj) .NE. 1 ) cycle
3451 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3452 ci = ( ni + (nri/2)-1 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3454 ci = ( ni + (nri-1)/2 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3461 ! (ci,cj+1) (ci+1,cj+1)
3475 ! At ni=2, we are on the coarse grid point, so dx = 0
3477 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3478 dx = ( REAL ( MOD ( ni+(nri-1)/2 , nri ) ) + 0.5 ) / REAL ( nri )
3480 dx = REAL ( MOD ( ni+(nri-1)/2 , nri ) ) / REAL ( nri )
3482 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3483 dy = ( REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) + 0.5 ) / REAL ( nrj )
3485 dy = REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) / REAL ( nrj )
3488 ! This is a "water only" field. If this is a land point, no operations required.
3490 IF ( ( NINT(nlu(ni ,nj )) .NE. nflag ) ) THEN
3491 nfld(ni,nk,nj) = cfld(ci ,ck,cj )
3493 ! If this is a nested water point, and the surrounding coarse values are all water points,
3494 ! then this is a simple 4-pt interpolation.
3496 ELSE IF ( ( NINT(nlu(ni ,nj )) .EQ. nflag ) .AND. &
3497 ( NINT(clu(ci ,cj )) .EQ. nflag ) .AND. &
3498 ( NINT(clu(ci+1,cj )) .EQ. nflag ) .AND. &
3499 ( NINT(clu(ci ,cj+1)) .EQ. nflag ) .AND. &
3500 ( NINT(clu(ci+1,cj+1)) .EQ. nflag ) ) THEN
3501 nfld(ni,nk,nj) = ( 1. - dx ) * ( ( 1. - dy ) * cfld(ci ,ck,cj ) + &
3502 dy * cfld(ci ,ck,cj+1) ) + &
3503 dx * ( ( 1. - dy ) * cfld(ci+1,ck,cj ) + &
3504 dy * cfld(ci+1,ck,cj+1) )
3506 ! If this is a nested water point and there are NO coarse water values surrounding,
3507 ! we temporarily punt.
3509 ELSE IF ( ( NINT(nlu(ni ,nj )) .EQ. nflag ) .AND. &
3510 ( NINT(clu(ci ,cj )) .NE. nflag ) .AND. &
3511 ( NINT(clu(ci+1,cj )) .NE. nflag ) .AND. &
3512 ( NINT(clu(ci ,cj+1)) .NE. nflag ) .AND. &
3513 ( NINT(clu(ci+1,cj+1)) .NE. nflag ) ) THEN
3516 ! If there are some land points and some water points, take an average.
3518 ELSE IF ( NINT(nlu(ni ,nj )) .EQ. nflag ) THEN
3521 IF ( NINT(clu(ci ,cj )) .EQ. nflag ) THEN
3523 sum = sum + cfld(ci ,ck,cj )
3525 IF ( NINT(clu(ci+1,cj )) .EQ. nflag ) THEN
3527 sum = sum + cfld(ci+1,ck,cj )
3529 IF ( NINT(clu(ci ,cj+1)) .EQ. nflag ) THEN
3531 sum = sum + cfld(ci ,ck,cj+1)
3533 IF ( NINT(clu(ci+1,cj+1)) .EQ. nflag ) THEN
3535 sum = sum + cfld(ci+1,ck,cj+1)
3537 nfld(ni,nk,nj) = sum / REAL ( icount )
3543 ! Get an average of the whole domain for problem locations.
3550 IF ( nfld(ni,nk,nj) .NE. -1 ) THEN
3551 IF ( NINT(nlu(ni,nj)) .EQ. nflag ) THEN
3552 icount_n(nk) = icount_n(nk) + 1
3553 sum_n(nk) = sum_n(nk) + nfld(ni,nk,nj)
3560 CALL wrf_dm_sum_reals( sum_n(nkts:nkte), dummy(nkts:nkte))
3562 CALL wrf_dm_sum_integers(icount_n(nkts:nkte), idummy(nkts:nkte))
3565 IF ( icount_n(nk) .GT. 0 ) &
3566 avg_n(nk) = sum_n(nk) / icount_n(nk)
3571 IF ( ANY(nfld .EQ. -4) ) THEN
3573 ! OK, if there were any of those lake situations, we try to search a bit broader
3574 ! of an area in the coarse grid.
3579 !dave IF ( imask(ni, nj) .NE. 1 ) cycle
3580 IF ( nfld(ni,nk,nj) .EQ. -4 ) THEN
3581 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3582 cj = ( nj + (nrj/2)-1 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3584 cj = ( nj + (nrj-1)/2 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3586 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3587 ci = ( ni + (nri/2)-1 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3589 ci = ( ni + (nri-1)/2 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3591 ist = MAX (ci-max_search,cits)
3592 ien = MIN (ci+max_search,cite,cide-1)
3593 jst = MAX (cj-max_search,cjts)
3594 jen = MIN (cj+max_search,cjte,cjde-1)
3599 IF ( NINT(clu(ii,jj)) .EQ. nflag ) THEN
3601 sum = sum + cfld(ii,nk,jj)
3605 IF ( icount .GT. 0 ) THEN
3606 nfld(ni,nk,nj) = sum / REAL ( icount )
3608 Write(message,fmt='(a,i4,a,i4,a,f10.4)') &
3609 'horizontal interp error - lake (', ni, ',', nj, '), using average ', avg_n(nk)
3610 CALL wrf_message ( message )
3611 nfld(ni,nk,nj) = avg_n(nk)
3620 CALL wrf_error_fatal ( "only unstaggered fields right now" )
3623 END SUBROUTINE interp_mask_water_field
3625 SUBROUTINE p2c_mask ( cfld, & ! CD field
3626 cids, cide, ckds, ckde, cjds, cjde, &
3627 cims, cime, ckms, ckme, cjms, cjme, &
3628 cits, cite, ckts, ckte, cjts, cjte, &
3630 nids, nide, nkds, nkde, njds, njde, &
3631 nims, nime, nkms, nkme, njms, njme, &
3632 nits, nite, nkts, nkte, njts, njte, &
3633 shw, & ! stencil half width
3634 imask, & ! interpolation mask
3635 xstag, ystag, & ! staggering of field
3636 ipos, jpos, & ! Position of lower left of nest in CD
3637 nri, nrj, & ! nest ratios
3638 clu, nlu, & ! land use categories
3639 ctslb,ntslb, & ! soil temps
3640 cnum_soil_layers,nnum_soil_layers, & ! number of soil layers for tslb
3641 ciswater, niswater ) ! iswater category
3643 USE module_configure
3644 USE module_wrf_error
3648 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
3649 cims, cime, ckms, ckme, cjms, cjme, &
3650 cits, cite, ckts, ckte, cjts, cjte, &
3651 nids, nide, nkds, nkde, njds, njde, &
3652 nims, nime, nkms, nkme, njms, njme, &
3653 nits, nite, nkts, nkte, njts, njte, &
3657 cnum_soil_layers, nnum_soil_layers, &
3660 LOGICAL, INTENT(IN) :: xstag, ystag
3662 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
3663 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
3664 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
3666 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: clu
3667 REAL, DIMENSION ( nims:nime, njms:njme ) :: nlu
3669 REAL, DIMENSION ( cims:cime, 1:cnum_soil_layers, cjms:cjme ) :: ctslb
3670 REAL, DIMENSION ( nims:nime, 1:nnum_soil_layers, njms:njme ) :: ntslb
3674 INTEGER ci, cj, ck, ni, nj, nk
3676 REAL :: sum , dx , dy
3678 ! Right now, only mass point locations permitted.
3680 IF ( ( .NOT. xstag) .AND. ( .NOT. ystag ) ) THEN
3682 ! Loop over each i,k,j in the nested domain.
3684 DO nj = njts, MIN(njde-1,njte)
3685 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3686 cj = ( nj + (nrj/2)-1 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3688 cj = ( nj + (nrj-1)/2 ) / nrj + jpos -1 ! first coarse position equal to or below nest point
3692 DO ni = nits, MIN(nide-1,nite)
3693 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3694 ci = ( ni + (nri/2)-1 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3696 ci = ( ni + (nri-1)/2 ) / nri + ipos -1 ! first coarse position equal to or to the left of nest point
3700 ! (ci,cj+1) (ci+1,cj+1)
3714 ! At ni=2, we are on the coarse grid point, so dx = 0
3716 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
3717 dx = ( REAL ( MOD ( ni+(nri-1)/2 , nri ) ) + 0.5 ) / REAL ( nri )
3719 dx = REAL ( MOD ( ni+(nri-1)/2 , nri ) ) / REAL ( nri )
3721 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
3722 dy = ( REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) + 0.5 ) / REAL ( nrj )
3724 dy = REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) / REAL ( nrj )
3727 ! This is a "water only" field. If this is a land point, no operations required.
3729 IF ( ( NINT(nlu(ni ,nj )) .NE. niswater ) ) THEN
3730 nfld(ni,nk,nj) = 273.18
3732 ! If this is a nested water point, and the surrounding coarse values are all water points,
3733 ! then this is a simple 4-pt interpolation.
3735 ELSE IF ( ( NINT(nlu(ni ,nj )) .EQ. niswater ) .AND. &
3736 ( NINT(clu(ci ,cj )) .EQ. niswater ) .AND. &
3737 ( NINT(clu(ci+1,cj )) .EQ. niswater ) .AND. &
3738 ( NINT(clu(ci ,cj+1)) .EQ. niswater ) .AND. &
3739 ( NINT(clu(ci+1,cj+1)) .EQ. niswater ) ) THEN
3740 nfld(ni,nk,nj) = ( 1. - dx ) * ( ( 1. - dy ) * cfld(ci ,ck,cj ) + &
3741 dy * cfld(ci ,ck,cj+1) ) + &
3742 dx * ( ( 1. - dy ) * cfld(ci+1,ck,cj ) + &
3743 dy * cfld(ci+1,ck,cj+1) )
3745 ! If this is a nested water point and there are NO coarse water values surrounding,
3746 ! we manufacture something from the deepest CG soil temp.
3748 ELSE IF ( ( NINT(nlu(ni ,nj )) .EQ. niswater ) .AND. &
3749 ( NINT(clu(ci ,cj )) .NE. niswater ) .AND. &
3750 ( NINT(clu(ci+1,cj )) .NE. niswater ) .AND. &
3751 ( NINT(clu(ci ,cj+1)) .NE. niswater ) .AND. &
3752 ( NINT(clu(ci+1,cj+1)) .NE. niswater ) ) THEN
3753 nfld(ni,nk,nj) = ( 1. - dx ) * ( ( 1. - dy ) * ctslb(ci ,cnum_soil_layers,cj ) + &
3754 dy * ctslb(ci ,cnum_soil_layers,cj+1) ) + &
3755 dx * ( ( 1. - dy ) * ctslb(ci+1,cnum_soil_layers,cj ) + &
3756 dy * ctslb(ci+1,cnum_soil_layers,cj+1) )
3758 ! If there are some land points and some water points, take an average of the water points.
3760 ELSE IF ( NINT(nlu(ni ,nj )) .EQ. niswater ) THEN
3763 IF ( NINT(clu(ci ,cj )) .EQ. niswater ) THEN
3765 sum = sum + cfld(ci ,ck,cj )
3767 IF ( NINT(clu(ci+1,cj )) .EQ. niswater ) THEN
3769 sum = sum + cfld(ci+1,ck,cj )
3771 IF ( NINT(clu(ci ,cj+1)) .EQ. niswater ) THEN
3773 sum = sum + cfld(ci ,ck,cj+1)
3775 IF ( NINT(clu(ci+1,cj+1)) .EQ. niswater ) THEN
3777 sum = sum + cfld(ci+1,ck,cj+1)
3779 nfld(ni,nk,nj) = sum / REAL ( icount )
3786 CALL wrf_error_fatal ( "only unstaggered fields right now" )
3789 END SUBROUTINE p2c_mask
3794 SUBROUTINE smoother ( cfld , &
3795 cids, cide, ckds, ckde, cjds, cjde, &
3796 cims, cime, ckms, ckme, cjms, cjme, &
3797 cits, cite, ckts, ckte, cjts, cjte, &
3798 nids, nide, nkds, nkde, njds, njde, &
3799 nims, nime, nkms, nkme, njms, njme, &
3800 nits, nite, nkts, nkte, njts, njte, &
3801 xstag, ystag, & ! staggering of field
3802 ipos, jpos, & ! Position of lower left of nest in
3806 USE module_configure
3809 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
3810 cims, cime, ckms, ckme, cjms, cjme, &
3811 cits, cite, ckts, ckte, cjts, cjte, &
3812 nids, nide, nkds, nkde, njds, njde, &
3813 nims, nime, nkms, nkme, njms, njme, &
3814 nits, nite, nkts, nkte, njts, njte, &
3817 LOGICAL, INTENT(IN) :: xstag, ystag
3818 INTEGER :: smooth_option, feedback , spec_zone
3820 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
3822 ! If there is no feedback, there can be no smoothing.
3824 CALL nl_get_feedback ( 1, feedback )
3825 IF ( feedback == 0 ) RETURN
3826 CALL nl_get_spec_zone ( 1, spec_zone )
3828 ! These are the 2d smoothers used on the fedback data. These filters
3829 ! are run on the coarse grid data (after the nested info has been
3830 ! fedback). Only the area of the nest in the coarse grid is filtered.
3832 CALL nl_get_smooth_option ( 1, smooth_option )
3834 IF ( smooth_option == 0 ) THEN
3836 ELSE IF ( smooth_option == 1 ) THEN
3837 CALL sm121 ( cfld , &
3838 cids, cide, ckds, ckde, cjds, cjde, &
3839 cims, cime, ckms, ckme, cjms, cjme, &
3840 cits, cite, ckts, ckte, cjts, cjte, &
3841 xstag, ystag, & ! staggering of field
3842 nids, nide, nkds, nkde, njds, njde, &
3843 nims, nime, nkms, nkme, njms, njme, &
3844 nits, nite, nkts, nkte, njts, njte, &
3846 ipos, jpos & ! Position of lower left of nest in
3848 ELSE IF ( smooth_option == 2 ) THEN
3849 CALL smdsm ( cfld , &
3850 cids, cide, ckds, ckde, cjds, cjde, &
3851 cims, cime, ckms, ckme, cjms, cjme, &
3852 cits, cite, ckts, ckte, cjts, cjte, &
3853 xstag, ystag, & ! staggering of field
3854 nids, nide, nkds, nkde, njds, njde, &
3855 nims, nime, nkms, nkme, njms, njme, &
3856 nits, nite, nkts, nkte, njts, njte, &
3858 ipos, jpos & ! Position of lower left of nest in
3862 END SUBROUTINE smoother
3864 SUBROUTINE sm121 ( cfld , &
3865 cids, cide, ckds, ckde, cjds, cjde, &
3866 cims, cime, ckms, ckme, cjms, cjme, &
3867 cits, cite, ckts, ckte, cjts, cjte, &
3868 xstag, ystag, & ! staggering of field
3869 nids, nide, nkds, nkde, njds, njde, &
3870 nims, nime, nkms, nkme, njms, njme, &
3871 nits, nite, nkts, nkte, njts, njte, &
3873 ipos, jpos & ! Position of lower left of nest in
3876 USE module_configure
3879 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
3880 cims, cime, ckms, ckme, cjms, cjme, &
3881 cits, cite, ckts, ckte, cjts, cjte, &
3882 nids, nide, nkds, nkde, njds, njde, &
3883 nims, nime, nkms, nkme, njms, njme, &
3884 nits, nite, nkts, nkte, njts, njte, &
3887 LOGICAL, INTENT(IN) :: xstag, ystag
3889 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
3890 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: cfldnew
3892 INTEGER :: i , j , k , loop
3893 INTEGER :: istag,jstag
3895 INTEGER, PARAMETER :: smooth_passes = 1 ! More passes requires a larger stencil (currently 48 pt)
3897 istag = 1 ; jstag = 1
3898 IF ( xstag ) istag = 0
3899 IF ( ystag ) jstag = 0
3901 ! Simple 1-2-1 smoother.
3903 smoothing_passes : DO loop = 1 , smooth_passes
3907 ! Initialize dummy cfldnew
3909 DO i = MAX(ipos,cits-3) , MIN(ipos+(nide-nids)/nri,cite+3)
3910 DO j = MAX(jpos,cjts-3) , MIN(jpos+(njde-njds)/nrj,cjte+3)
3911 cfldnew(i,j) = cfld(i,k,j)
3915 ! 1-2-1 smoothing in the j direction first,
3917 DO i = MAX(ipos+2,cits-2) , MIN(ipos+(nide-nids)/nri-2-istag,cite+2)
3918 DO j = MAX(jpos+2,cjts-2) , MIN(jpos+(njde-njds)/nrj-2-jstag,cjte+2)
3919 cfldnew(i,j) = 0.25 * ( cfld(i,k,j+1) + 2.*cfld(i,k,j) + cfld(i,k,j-1) )
3923 ! then 1-2-1 smoothing in the i direction last
3925 DO j = MAX(jpos+2,cjts-2) , MIN(jpos+(njde-njds)/nrj-2-jstag,cjte+2)
3926 DO i = MAX(ipos+2,cits-2) , MIN(ipos+(nide-nids)/nri-2-istag,cite+2)
3927 cfld(i,k,j) = 0.25 * ( cfldnew(i+1,j) + 2.*cfldnew(i,j) + cfldnew(i-1,j) )
3933 END DO smoothing_passes
3935 END SUBROUTINE sm121
3937 SUBROUTINE smdsm ( cfld , &
3938 cids, cide, ckds, ckde, cjds, cjde, &
3939 cims, cime, ckms, ckme, cjms, cjme, &
3940 cits, cite, ckts, ckte, cjts, cjte, &
3941 xstag, ystag, & ! staggering of field
3942 nids, nide, nkds, nkde, njds, njde, &
3943 nims, nime, nkms, nkme, njms, njme, &
3944 nits, nite, nkts, nkte, njts, njte, &
3946 ipos, jpos & ! Position of lower left of nest in
3949 USE module_configure
3952 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
3953 cims, cime, ckms, ckme, cjms, cjme, &
3954 cits, cite, ckts, ckte, cjts, cjte, &
3955 nids, nide, nkds, nkde, njds, njde, &
3956 nims, nime, nkms, nkme, njms, njme, &
3957 nits, nite, nkts, nkte, njts, njte, &
3960 LOGICAL, INTENT(IN) :: xstag, ystag
3962 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
3963 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: cfldnew
3965 REAL , DIMENSION ( 2 ) :: xnu
3966 INTEGER :: i , j , k , loop , n
3967 INTEGER :: istag,jstag
3969 INTEGER, PARAMETER :: smooth_passes = 1 ! More passes requires a larger stencil (currently 48 pt)
3971 xnu = (/ 0.50 , -0.52 /)
3973 istag = 1 ; jstag = 1
3974 IF ( xstag ) istag = 0
3975 IF ( ystag ) jstag = 0
3977 ! The odd number passes of this are the "smoother", the even
3978 ! number passes are the "de-smoother" (note the different signs on xnu).
3980 smoothing_passes : DO loop = 1 , smooth_passes * 2
3982 n = 2 - MOD ( loop , 2 )
3986 DO i = MAX(ipos+2,cits-2) , MIN(ipos+(nide-nids)/nri-2-istag,cite+2)
3987 DO j = MAX(jpos+2,cjts-2) , MIN(jpos+(njde-njds)/nrj-2-jstag,cjte+2)
3988 cfldnew(i,j) = cfld(i,k,j) + xnu(n) * ((cfld(i,k,j+1) + cfld(i,k,j-1)) * 0.5-cfld(i,k,j))
3992 DO i = MAX(ipos+2,cits-2) , MIN(ipos+(nide-nids)/nri-2-istag,cite+2)
3993 DO j = MAX(jpos+2,cjts-2) , MIN(jpos+(njde-njds)/nrj-2-jstag,cjte+2)
3994 cfld(i,k,j) = cfldnew(i,j)
3998 DO j = MAX(jpos+2,cjts-2) , MIN(jpos+(njde-njds)/nrj-2-jstag,cjte+2)
3999 DO i = MAX(ipos+2,cits-2) , MIN(ipos+(nide-nids)/nri-2-istag,cite+2)
4000 cfldnew(i,j) = cfld(i,k,j) + xnu(n) * ((cfld(i+1,k,j) + cfld(i-1,k,j)) * 0.5-cfld(i,k,j))
4004 DO j = MAX(jpos+2,cjts-2) , MIN(jpos+(njde-njds)/nrj-2-jstag,cjte+2)
4005 DO i = MAX(ipos+2,cits-2) , MIN(ipos+(nide-nids)/nri-2-istag,cite+2)
4006 cfld(i,k,j) = cfldnew(i,j)
4012 END DO smoothing_passes
4014 END SUBROUTINE smdsm
4016 !==================================
4017 ! this is used to modify a field over the nest so we can see where the nest is
4019 SUBROUTINE mark_domain ( cfld, & ! CD field
4020 cids, cide, ckds, ckde, cjds, cjde, &
4021 cims, cime, ckms, ckme, cjms, cjme, &
4022 cits, cite, ckts, ckte, cjts, cjte, &
4024 nids, nide, nkds, nkde, njds, njde, &
4025 nims, nime, nkms, nkme, njms, njme, &
4026 nits, nite, nkts, nkte, njts, njte, &
4027 shw, & ! stencil half width for interp
4028 imask, & ! interpolation mask
4029 xstag, ystag, & ! staggering of field
4030 ipos, jpos, & ! Position of lower left of nest in CD
4031 nri, nrj ) ! nest ratios
4032 USE module_configure
4033 USE module_wrf_error
4037 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
4038 cims, cime, ckms, ckme, cjms, cjme, &
4039 cits, cite, ckts, ckte, cjts, cjte, &
4040 nids, nide, nkds, nkde, njds, njde, &
4041 nims, nime, nkms, nkme, njms, njme, &
4042 nits, nite, nkts, nkte, njts, njte, &
4046 LOGICAL, INTENT(IN) :: xstag, ystag
4048 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ), INTENT(OUT) :: cfld
4049 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ), INTENT(IN) :: nfld
4050 INTEGER, DIMENSION ( nims:nime, njms:njme ), INTENT(IN) :: imask
4054 INTEGER ci, cj, ck, ni, nj, nk, ip, jp, ioff, joff, ioffa, joffa
4055 INTEGER :: icmin,icmax,jcmin,jcmax
4056 INTEGER :: istag,jstag, ipoints,jpoints,ijpoints
4058 istag = 1 ; jstag = 1
4059 IF ( xstag ) istag = 0
4060 IF ( ystag ) jstag = 0
4062 DO cj = MAX(jpos+1,cjts),MIN(jpos+(njde-njds)/nrj-jstag-1,cjte)
4063 nj = (cj-jpos)*nrj + jstag + 1
4066 DO ci = MAX(ipos+1,cits),MIN(ipos+(nide-nids)/nri-istag-1,cite)
4067 ni = (ci-ipos)*nri + istag + 1
4068 cfld( ci, ck, cj ) = 9021000. !magic number: Beverly Hills * 100.
4073 END SUBROUTINE mark_domain
4075 SUBROUTINE interp_mask_field ( enable, & ! says whether to allow interpolation or just the bcasts
4077 cids, cide, ckds, ckde, cjds, cjde, &
4078 cims, cime, ckms, ckme, cjms, cjme, &
4079 cits, cite, ckts, ckte, cjts, cjte, &
4081 nids, nide, nkds, nkde, njds, njde, &
4082 nims, nime, nkms, nkme, njms, njme, &
4083 nits, nite, nkts, nkte, njts, njte, &
4084 shw, & ! stencil half width
4085 imask, & ! interpolation mask
4086 xstag, ystag, & ! staggering of field
4087 ipos, jpos, & ! Position of lower left of nest in CD
4088 nri, nrj, & ! nest ratios
4089 clu, nlu, cflag, nflag )
4091 USE module_configure
4092 USE module_wrf_error
4093 USE module_dm , only : wrf_dm_sum_reals, wrf_dm_sum_integers
4098 LOGICAL, INTENT(IN) :: enable
4099 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
4100 cims, cime, ckms, ckme, cjms, cjme, &
4101 cits, cite, ckts, ckte, cjts, cjte, &
4102 nids, nide, nkds, nkde, njds, njde, &
4103 nims, nime, nkms, nkme, njms, njme, &
4104 nits, nite, nkts, nkte, njts, njte, &
4105 shw, & ! stencil half width
4107 nri, nrj, cflag, nflag
4108 LOGICAL, INTENT(IN) :: xstag, ystag
4110 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
4111 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
4112 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
4114 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: clu
4115 REAL, DIMENSION ( nims:nime, njms:njme ) :: nlu
4119 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
4120 INTEGER :: icount, ii , jj , ist , ien , jst , jen , iswater, ierr
4121 REAL :: avg, sum, dx , dy
4122 INTEGER :: icount_water(nkts:nkte), icount_land(nkts:nkte), idummy(nkts:nkte)
4123 REAL :: avg_water(nkts:nkte), avg_land(nkts:nkte), sum_water(nkts:nkte), sum_land(nkts:nkte), dummy(nkts:nkte)
4124 CHARACTER (len=256) :: message
4125 CHARACTER (len=256) :: a_mess
4127 ! Find out what the water value is.
4129 !CALL nl_get_iswater(1,iswater)
4132 ! Right now, only mass point locations permitted.
4134 IF ( ( .NOT. xstag) .AND. ( .NOT. ystag ) ) THEN
4136 ! Loop over each i,k,j in the nested domain.
4140 ! first coarse position equal to or below nest point
4141 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
4142 cj = ( nj + (nrj/2)-1 ) / nrj + jpos -1
4144 cj = ( nj + (nrj-1)/2 ) / nrj + jpos -1
4149 IF ( imask(ni, nj) .NE. 1 ) cycle
4150 ! first coarse position equal to or to the left of nest point
4151 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
4152 ci = ( ni + (nri/2)-1 ) / nri + ipos -1
4154 ci = ( ni + (nri-1)/2 ) / nri + ipos -1
4158 ! (ci,cj+1) (ci+1,cj+1)
4171 ! For odd ratios, at (nri+1)/2, we are on the coarse grid point, so dx = 0
4173 IF ( MOD ( nri , 2 ) .EQ. 0 ) THEN
4174 dx = ( REAL ( MOD ( ni+(nri-1)/2 , nri ) ) + 0.5 ) / REAL ( nri )
4176 dx = REAL ( MOD ( ni+(nri-1)/2 , nri ) ) / REAL ( nri )
4178 IF ( MOD ( nrj , 2 ) .EQ. 0 ) THEN
4179 dy = ( REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) + 0.5 ) / REAL ( nrj )
4181 dy = REAL ( MOD ( nj+(nrj-1)/2 , nrj ) ) / REAL ( nrj )
4184 ! Nested cell is a water cell.
4185 IF ( ( NINT(nlu(ni, nj)) .EQ. iswater ) ) THEN
4187 ! If the surrounding coarse values are all WATER points,
4188 ! i.e. open water, this is a simple 4-pt interpolation.
4189 ! If the surrounding coarse values are all LAND points,
4190 ! i.e. this is a 1-cell lake, we have no better way to
4191 ! come up with the value than to do a simple 4-pt interpolation.
4193 IF ( ALL( clu(ci:ci+1,cj:cj+1) == iswater ) .OR. &
4194 ALL( clu(ci:ci+1,cj:cj+1) /= iswater ) ) THEN
4196 nfld(ni,nk,nj) = ( 1. - dx ) * ( ( 1. - dy ) * cfld(ci ,ck,cj ) + &
4197 dy * cfld(ci ,ck,cj+1) ) + &
4198 dx * ( ( 1. - dy ) * cfld(ci+1,ck,cj ) + &
4199 dy * cfld(ci+1,ck,cj+1) )
4201 ! If there are some land points and some water points, take an average.
4205 IF ( NINT(clu(ci ,cj )) .EQ. iswater ) THEN
4207 sum = sum + cfld(ci ,ck,cj )
4209 IF ( NINT(clu(ci+1,cj )) .EQ. iswater ) THEN
4211 sum = sum + cfld(ci+1,ck,cj )
4213 IF ( NINT(clu(ci ,cj+1)) .EQ. iswater ) THEN
4215 sum = sum + cfld(ci ,ck,cj+1)
4217 IF ( NINT(clu(ci+1,cj+1)) .EQ. iswater ) THEN
4219 sum = sum + cfld(ci+1,ck,cj+1)
4221 nfld(ni,nk,nj) = sum / REAL ( icount )
4224 ! Nested cell is a land cell.
4225 ELSE IF ( ( NINT(nlu(ni, nj)) .NE. iswater ) ) THEN
4227 ! If the surrounding coarse values are all LAND points,
4228 ! this is a simple 4-pt interpolation.
4229 ! If the surrounding coarse values are all WATER points,
4230 ! i.e. this is a 1-cell island, we have no better way to
4231 ! come up with the value than to do a simple 4-pt interpolation.
4233 IF ( ALL( clu(ci:ci+1,cj:cj+1) == iswater ) .OR. &
4234 ALL( clu(ci:ci+1,cj:cj+1) /= iswater ) ) THEN
4236 nfld(ni,nk,nj) = ( 1. - dx ) * ( ( 1. - dy ) * cfld(ci ,ck,cj ) + &
4237 dy * cfld(ci ,ck,cj+1) ) + &
4238 dx * ( ( 1. - dy ) * cfld(ci+1,ck,cj ) + &
4239 dy * cfld(ci+1,ck,cj+1) )
4241 ! If there are some water points and some land points, take an average.
4245 IF ( NINT(clu(ci ,cj )) .NE. iswater ) THEN
4247 sum = sum + cfld(ci ,ck,cj )
4249 IF ( NINT(clu(ci+1,cj )) .NE. iswater ) THEN
4251 sum = sum + cfld(ci+1,ck,cj )
4253 IF ( NINT(clu(ci ,cj+1)) .NE. iswater ) THEN
4255 sum = sum + cfld(ci ,ck,cj+1)
4257 IF ( NINT(clu(ci+1,cj+1)) .NE. iswater ) THEN
4259 sum = sum + cfld(ci+1,ck,cj+1)
4261 nfld(ni,nk,nj) = sum / REAL ( icount )
4272 CALL wrf_error_fatal ( "only unstaggered fields right now" )
4275 END SUBROUTINE interp_mask_field
4278 SUBROUTINE interp_mask_soil ( enable, & ! says whether to allow interpolation or just the bcasts
4280 cids, cide, ckds, ckde, cjds, cjde, &
4281 cims, cime, ckms, ckme, cjms, cjme, &
4282 cits, cite, ckts, ckte, cjts, cjte, &
4284 nids, nide, nkds, nkde, njds, njde, &
4285 nims, nime, nkms, nkme, njms, njme, &
4286 nits, nite, nkts, nkte, njts, njte, &
4287 shw, & ! stencil half width
4288 imask, & ! interpolation mask
4289 xstag, ystag, & ! staggering of field
4290 ipos, jpos, & ! Position of lower left of nest in CD
4291 nri, nrj, & ! nest ratios
4294 USE module_configure
4295 USE module_wrf_error
4296 USE module_dm , only : wrf_dm_sum_real, wrf_dm_sum_integer
4301 LOGICAL, INTENT(IN) :: enable
4302 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
4303 cims, cime, ckms, ckme, cjms, cjme, &
4304 cits, cite, ckts, ckte, cjts, cjte, &
4305 nids, nide, nkds, nkde, njds, njde, &
4306 nims, nime, nkms, nkme, njms, njme, &
4307 nits, nite, nkts, nkte, njts, njte, &
4308 shw, & ! stencil half width
4311 LOGICAL, INTENT(IN) :: xstag, ystag
4313 INTEGER, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld
4314 INTEGER, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
4315 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
4317 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: clu
4318 REAL, DIMENSION ( nims:nime, njms:njme ) :: nlu
4322 INTEGER ci, cj, ck, ni, nj, nk, ip, jp
4323 INTEGER :: icount, ii , jj , ist , ien , jst , jen , iswater, num_soil_cat, ierr
4324 REAL :: avg, sum, dx , dy
4325 INTEGER , ALLOCATABLE :: icount_water(:,: ), icount_land(:,:)
4326 INTEGER , PARAMETER :: max_search = 5
4327 CHARACTER*120 message
4328 INTEGER, PARAMETER :: isoilwater = 14
4330 CALL nl_get_iswater(1,iswater)
4331 CALL nl_get_num_soil_cat(1,num_soil_cat)
4333 allocate (icount_water(nkms:nkme,1:num_soil_cat))
4334 allocate ( icount_land(nkms:nkme,1:num_soil_cat))
4336 ! Right now, only mass point locations permitted.
4338 IF ( ( .NOT. xstag) .AND. ( .NOT. ystag ) ) THEN
4340 ! Loop over each i,k,j in the nested domain.
4345 cj = jpos + (nj-1) / nrj ! j coord of CD point
4349 ci = ipos + (ni-1) / nri ! j coord of CD point
4351 IF ( imask(ni, nj) .NE. 1 ) cycle
4353 IF ( ( NINT(nlu(ni, nj)) .EQ. iswater ) ) then
4355 IF ( ( NINT(clu(ci ,cj )) .EQ. iswater ) ) then
4356 nfld(ni,nk,nj) = cfld(ci,ck,cj)
4361 ELSE IF ( ( NINT(nlu(ni, nj)) .NE. iswater ) ) THEN
4363 IF ( ( NINT(clu(ci ,cj )) .NE. iswater ) ) THEN
4364 nfld(ni,nk,nj) = cfld(ci,ck,cj)
4377 IF ( imask(ni, nj) .NE. 1 ) cycle
4378 IF ( nfld(ni,nk,nj) .EQ. -1 ) THEN
4379 IF ( NINT(nlu(ni,nj)) .EQ. iswater ) THEN
4380 nfld(ni,nk,nj) = isoilwater
4387 IF ( ANY(nfld .EQ. -1) ) THEN
4389 ! Get an average of the whole domain for problem locations.
4399 cj = jpos + (nj-1) / nrj ! j coord of CD point
4402 ci = ipos + (ni-1) / nri ! j coord of CD point
4403 IF ( imask(ni, nj) .NE. 1 ) cycle
4404 IF ( nfld(ni,nk,nj) .EQ. -1 ) THEN
4405 ist = MAX (ci-max_search,cits)
4406 ien = MIN (ci+max_search,cite,cide-1)
4407 jst = MAX (cj-max_search,cjts)
4408 jen = MIN (cj+max_search,cjte,cjde-1)
4411 IF ( NINT(clu(ii,jj)) .NE. iswater ) THEN
4412 icount_land(nk,cfld(ii,nk,jj)) = icount_land(nk,cfld(ii,nk,jj)) +1
4416 IF ( maxval(icount_land(nk,:)) .GT. 0 .and. maxloc(icount_land(nk,:)) .ne. isoilwater ) then
4417 nfld(ni,nk,nj) = maxloc(icount_land(nk,:))
4427 IF ( ANY(nfld .EQ. -1) ) THEN
4438 IF ( nlu(ni,nj ) .NE. iswater ) THEN
4439 icount_land(nk,nfld(ni,nk,nj)) = icount_land(nk,nfld(ni,nk,nj)) +1
4448 IF ( imask(ni, nj) .NE. 1 ) cycle
4449 IF ( nfld(ni,nk,nj) .EQ. -1 .and. maxloc(icount_land(nk,:)) .ne. isoilwater) THEN
4450 nfld(ni,nk,nj) = MAXLOC(icount_land(nk,:))
4458 IF ( ANY(nfld .EQ. -1) ) THEN
4462 IF ( imask(ni, nj) .NE. 1 ) cycle
4463 IF ( nfld(ni,nk,nj) .EQ. -1 ) THEN
4473 CALL wrf_error_fatal ( "only unstaggered fields right now" )
4477 deallocate (icount_water)
4478 deallocate (icount_land)
4480 END SUBROUTINE interp_mask_soil
4482 !=========================================================================
4484 ! Lagrange interpolating polynomials, set up as a quadratic, with an average of
4485 ! the overlap. Specifically for longitude near the date line.
4487 SUBROUTINE interp_fcn_lagr_ll ( cfld_inp, & ! CD field
4488 cids, cide, ckds, ckde, cjds, cjde, &
4489 cims, cime, ckms, ckme, cjms, cjme, &
4490 cits, cite, ckts, ckte, cjts, cjte, &
4492 nids, nide, nkds, nkde, njds, njde, &
4493 nims, nime, nkms, nkme, njms, njme, &
4494 nits, nite, nkts, nkte, njts, njte, &
4495 shw, & ! stencil half width for interp
4496 imask, & ! interpolation mask
4497 xstag, ystag, & ! staggering of field
4498 ipos, jpos, & ! Position of lower left of nest in CD
4499 nri, nrj, & ! Nest ratio, i- and j-directions
4500 clat_in, nlat_in, & ! CG, FG latitude
4501 cinput_from_file, ninput_from_file ) ! CG, FG T/F input from file
4505 INTEGER, INTENT(IN) :: cids, cide, ckds, ckde, cjds, cjde, &
4506 cims, cime, ckms, ckme, cjms, cjme, &
4507 cits, cite, ckts, ckte, cjts, cjte, &
4508 nids, nide, nkds, nkde, njds, njde, &
4509 nims, nime, nkms, nkme, njms, njme, &
4510 nits, nite, nkts, nkte, njts, njte, &
4514 LOGICAL, INTENT(IN) :: xstag, ystag
4516 REAL, DIMENSION ( cims:cime, ckms:ckme, cjms:cjme ) :: cfld_inp, cfld
4517 REAL, DIMENSION ( nims:nime, nkms:nkme, njms:njme ) :: nfld
4518 REAL, DIMENSION ( cims:cime, cjms:cjme ) :: clat_in
4519 REAL, DIMENSION ( nims:nime, njms:njme ) :: nlat_in
4520 INTEGER, DIMENSION ( nims:nime, njms:njme ) :: imask
4521 LOGICAL :: cinput_from_file, ninput_from_file
4525 INTEGER ci, cj, ck, ni, nj, nk, istag, jstag, i, j, k
4526 REAL :: nx, x0, x1, x2, x3, x
4527 REAL :: ny, y0, y1, y2, y3
4528 REAL :: cxm1, cxp0, cxp1, cxp2, nfld_m1, nfld_p0, nfld_p1, nfld_p2
4529 REAL :: cym1, cyp0, cyp1, cyp2
4530 INTEGER :: ioff, joff
4531 LOGICAL :: probably_by_dateline
4532 REAL :: max_lon, min_lon
4533 LOGICAL :: probably_by_pole
4534 REAL :: max_lat, min_lat
4536 ! Fortran functions.
4538 REAL, EXTERNAL :: lagrange_quad_avg
4539 REAL, EXTERNAL :: nest_loc_of_cg
4540 INTEGER, EXTERNAL :: compute_CGLL
4542 ! This stag stuff is to keep us away from the outer most row
4543 ! and column for the unstaggered directions. We are going to
4544 ! consider "U" an xstag variable and "V" a ystag variable. The
4545 ! vertical staggering is handled in the actual arguments. The
4546 ! ckte and nkte are the ending vertical dimensions for computations
4547 ! for this particular variable.
4549 ! The ioff and joff are offsets due to the staggering. It is a lot
4550 ! simpler with ioff and joff if
4554 ! Note that is OPPOSITE of the istag, jstag vars. The stag variables are
4555 ! used for the domain dimensions, the offset guys are used in the
4556 ! determination of grid points between the CG and FG
4574 ! If this is a projection where the nest is over the pole, and
4575 ! we are using the parent to interpolate the longitudes, then
4576 ! we are going to have longitude troubles. If this is the case,
4577 ! stop the model right away.
4579 probably_by_pole = .FALSE.
4582 DO nj = njts, MIN(njde-jstag,njte)
4583 DO ni = nits, MIN(nide-istag,nite)
4584 max_lat = MAX ( nlat_in(ni,nj) , max_lat )
4585 min_lat = MIN ( nlat_in(ni,nj) , min_lat )
4589 IF ( ( max_lat .GT. 85 ) .OR. ( ABS(min_lat) .GT. 85 ) ) THEN
4590 probably_by_pole = .TRUE.
4593 IF ( ( probably_by_pole ) .AND. ( .NOT. ninput_from_file ) ) THEN
4594 CALL wrf_error_fatal ( 'Nest over the pole, single input domain, longitudes will be wrong' )
4597 ! Initialize to NOT being by dateline.
4599 probably_by_dateline = .FALSE.
4602 DO nj = njts, MIN(njde-jstag,njte)
4603 cj = compute_CGLL ( nj , jpos , nrj , jstag )
4604 DO ni = nits, MIN(nide-istag,nite)
4605 ci = compute_CGLL ( ni , ipos , nri , istag )
4606 max_lon = MAX ( cfld_inp(ci,1,cj) , max_lon )
4607 min_lon = MIN ( cfld_inp(ci,1,cj) , min_lon )
4611 IF ( max_lon - min_lon .GT. 300 ) THEN
4612 probably_by_dateline = .TRUE.
4615 ! Load "continuous" longitude across the date line
4617 DO cj = MIN(cjts-1,cjms), MAX(cjte+1,cjme)
4618 DO ci = MIN(cits-1,cims), MAX(cite+1,cime)
4619 IF ( ( cfld_inp(ci,ckts,cj) .LT. 0 ) .AND. ( probably_by_dateline ) ) THEN
4620 cfld(ci,ckts,cj) = 360 + cfld_inp(ci,ckts,cj)
4622 cfld(ci,ckts,cj) = cfld_inp(ci,ckts,cj)
4627 ! Loop over each j-index on this tile for the nested domain.
4629 j_loop : DO nj = njts, MIN(njde-jstag,njte)
4631 ! This is the lower-left j-index of the CG.
4633 ! Example is 3:1 ratio, mass-point staggering. We have listed sixteen CG values
4634 ! as an example: A through P. For a 3:1 ratio, each of these CG cells has
4635 ! nine associated FG points.
4637 ! |=========|=========|=========|=========|
4638 ! | - - - | - - - | - - - | - - - |
4640 ! | - M - | - N d | - O - | - P - |
4642 ! | - - - | - - - | - - - | - - - |
4643 ! |=========|=========|=========|=========|
4644 ! | - - - | - - - | - - - | - - - |
4646 ! | - I - | - J c | - K - | - L - |
4648 ! | - - - | - - - | - - - | - - - |
4649 ! |=========|=========|=========|=========|
4650 ! | - 1 2 | 3 4 5 | 6 7 8 | - - - |
4652 ! | - E - | - F b | - G - | - H - |
4654 ! | - - - | - - - | - - - | - - - |
4655 ! |=========|=========|=========|=========|
4656 ! | - - - | - - - | - - - | - - - |
4658 ! | - A - | - B a | - C - | - D - |
4660 ! | - - - | - - - | - - - | - - - |
4661 ! |=========|=========|=========|=========|
4663 ! To interpolate to FG point 4, 5, or 6 we will use CG points: A through P. It is
4664 ! sufficient to find the lower left corner of a 4-point interpolation, and then extend
4665 ! each side by one unit.
4667 ! Here are the lower left hand corners of the following FG points:
4677 cj = compute_CGLL ( nj , jpos , nrj , jstag )
4679 ! Vertical dim of the nest domain.
4681 k_loop : DO nk = nkts, nkte
4683 ! Loop over each i-index on this tile for the nested domain.
4685 i_loop : DO ni = nits, MIN(nide-istag,nite)
4687 ! The coarse grid location that is to the lower left of the FG point.
4689 ci = compute_CGLL ( ni , ipos , nri , istag )
4691 ! To interpolate to point "*" (look in grid cell "F"):
4692 ! 1. Use ABC to get a quadratic valid at "a"
4693 ! Use BCD to get a quadratic valid at "a"
4694 ! Average these to get the final value for "a"
4695 ! 2. Use EFG to get a quadratic valid at "b"
4696 ! Use FGH to get a quadratic valid at "b"
4697 ! Average these to get the final value for "b"
4698 ! 3. Use IJK to get a quadratic valid at "c"
4699 ! Use JKL to get a quadratic valid at "c"
4700 ! Average these to get the final value for "c"
4701 ! 4. Use MNO to get a quadratic valid at "d"
4702 ! Use NOP to get a quadratic valid at "d"
4703 ! Average these to get the final value for "d"
4704 ! 5. Use abc to get a quadratic valid at "*"
4705 ! Use bcd to get a quadratic valid at "*"
4706 ! Average these to get the final value for "*"
4708 ! |=========|=========|=========|=========|
4709 ! | - - - | - - - | - - - | - - - |
4711 ! | - M - | - N d | - O - | - P - |
4713 ! | - - - | - - - | - - - | - - - |
4714 ! |=========|=========|=========|=========|
4715 ! | - - - | - - - | - - - | - - - |
4717 ! | - I - | - J c | - K - | - L - |
4719 ! | - - - | - - - | - - - | - - - |
4720 ! |=========|=========|=========|=========|
4721 ! | - - - | - - * | - - - | - - - |
4723 ! | - E - | - F b | - G - | - H - |
4725 ! | - - - | - - - | - - - | - - - |
4726 ! |=========|=========|=========|=========|
4727 ! | - - - | - - - | - - - | - - - |
4729 ! | - A - | - B a | - C - | - D - |
4731 ! | - - - | - - - | - - - | - - - |
4732 ! |=========|=========|=========|=========|
4734 ! Overlapping quadratic interpolation.
4736 IF ( imask ( ni, nj ) .EQ. 1 ) THEN
4738 ! I-direction location of "*"
4742 ! I-direction location of "A", "E", "I", "M"
4744 cxm1 = nest_loc_of_cg ( ci-1 , ipos , nri , ioff )
4746 ! I-direction location of "B", "F", "J", "N"
4748 cxp0 = nest_loc_of_cg ( ci , ipos , nri , ioff )
4750 ! I-direction location of "C", "G", "K", "O"
4752 cxp1 = nest_loc_of_cg ( ci+1 , ipos , nri , ioff )
4754 ! I-direction location of "D", "H", "L", "P"
4756 cxp2 = nest_loc_of_cg ( ci+2 , ipos , nri , ioff )
4760 nfld_m1 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, &
4761 cfld(ci-1,nk,cj-1), cfld(ci+0,nk,cj-1), &
4762 cfld(ci+1,nk,cj-1), cfld(ci+2,nk,cj-1) )
4766 nfld_p0 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, &
4767 cfld(ci-1,nk,cj+0), cfld(ci+0,nk,cj+0), &
4768 cfld(ci+1,nk,cj+0), cfld(ci+2,nk,cj+0) )
4772 nfld_p1 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, &
4773 cfld(ci-1,nk,cj+1), cfld(ci+0,nk,cj+1), &
4774 cfld(ci+1,nk,cj+1), cfld(ci+2,nk,cj+1) )
4778 nfld_p2 = lagrange_quad_avg ( nx, cxm1, cxp0, cxp1, cxp2, &
4779 cfld(ci-1,nk,cj+2), cfld(ci+0,nk,cj+2), &
4780 cfld(ci+1,nk,cj+2), cfld(ci+2,nk,cj+2) )
4782 ! J-direction location of "*"
4786 ! J-direction location of "A", "B", "C", "D"
4788 cym1 = nest_loc_of_cg ( cj-1 , jpos , nrj , joff )
4790 ! J-direction location of "E", "F", "G", "H"
4792 cyp0 = nest_loc_of_cg ( cj , jpos , nrj , joff )
4794 ! J-direction location of "I", "J", "K", "L"
4796 cyp1 = nest_loc_of_cg ( cj+1 , jpos , nrj , joff )
4798 ! J-direction location of "M", "N", "O", "P"
4800 cyp2 = nest_loc_of_cg ( cj+2 , jpos , nrj , joff )
4804 nfld(ni,nk,nj) = lagrange_quad_avg ( ny, cym1, cyp0, cyp1, &
4805 cyp2, nfld_m1, nfld_p0, nfld_p1, nfld_p2 )
4813 ! Put nested longitude back into the -180 to 180 range.
4815 DO nj = njts, MIN(njde-jstag,njte)
4816 DO ni = nits, MIN(nide-istag,nite)
4817 IF ( nfld(ni,nkts,nj) .GT. 180 ) THEN
4818 nfld(ni,nkts,nj) = -360 + nfld(ni,nkts,nj)
4823 END SUBROUTINE interp_fcn_lagr_ll