PageRenderTime 61ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/wrfv2_fire/share/module_bc.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 3400 lines | 2558 code | 521 blank | 321 comment | 148 complexity | 29e913f4d91363971266041ed6c69a14 MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. !WRF:MODEL_LAYER:BOUNDARY
  2. !
  3. MODULE module_bc
  4. USE module_configure
  5. USE module_wrf_error
  6. USE module_model_constants
  7. IMPLICIT NONE
  8. ! TYPE bcs
  9. !
  10. ! LOGICAL :: periodic_x
  11. ! LOGICAL :: symmetric_xs
  12. ! LOGICAL :: symmetric_xe
  13. ! LOGICAL :: open_xs
  14. ! LOGICAL :: open_xe
  15. ! LOGICAL :: periodic_y
  16. ! LOGICAL :: symmetric_ys
  17. ! LOGICAL :: symmetric_ye
  18. ! LOGICAL :: open_ys
  19. ! LOGICAL :: open_ye
  20. ! LOGICAL :: nested
  21. ! LOGICAL :: specified
  22. ! LOGICAL :: top_radiation
  23. !
  24. ! END TYPE bcs
  25. ! set the bdyzone. We are hardwiring this here and we'll
  26. ! decide later where it should be set and stored
  27. INTEGER, PARAMETER :: bdyzone = 4
  28. INTEGER, PARAMETER :: bdyzone_x = bdyzone
  29. INTEGER, PARAMETER :: bdyzone_y = bdyzone
  30. INTERFACE stuff_bdy
  31. MODULE PROCEDURE stuff_bdy_new , stuff_bdy_old
  32. END INTERFACE
  33. INTERFACE stuff_bdytend
  34. MODULE PROCEDURE stuff_bdytend_new , stuff_bdytend_old
  35. END INTERFACE
  36. CONTAINS
  37. SUBROUTINE boundary_condition_check ( config_flags, bzone, error, gn )
  38. ! this routine checks the boundary condition logicals
  39. ! to make sure that the boundary conditions are not over
  40. ! or under specified. The routine also checks that the
  41. ! boundary zone is sufficiently sized for the specified
  42. ! boundary conditions
  43. IMPLICIT NONE
  44. TYPE( grid_config_rec_type ) config_flags
  45. INTEGER, INTENT(IN ) :: bzone, gn
  46. INTEGER, INTENT(INOUT) :: error
  47. ! local variables
  48. INTEGER :: xs_bc, xe_bc, ys_bc, ye_bc, bzone_min
  49. INTEGER :: nprocx, nprocy
  50. CALL wrf_debug( 100 , ' checking boundary conditions for grid ' )
  51. error = 0
  52. xs_bc = 0
  53. xe_bc = 0
  54. ys_bc = 0
  55. ye_bc = 0
  56. ! sum the number of conditions specified for each lateral boundary.
  57. ! obviously, this number should be 1
  58. IF( config_flags%periodic_x ) THEN
  59. xs_bc = xs_bc+1
  60. xe_bc = xe_bc+1
  61. ENDIF
  62. IF( config_flags%periodic_y ) THEN
  63. ys_bc = ys_bc+1
  64. ye_bc = ye_bc+1
  65. ENDIF
  66. IF( config_flags%symmetric_xs ) xs_bc = xs_bc + 1
  67. IF( config_flags%symmetric_xe ) xe_bc = xe_bc + 1
  68. IF( config_flags%open_xs ) xs_bc = xs_bc + 1
  69. IF( config_flags%open_xe ) xe_bc = xe_bc + 1
  70. IF( config_flags%symmetric_ys ) ys_bc = ys_bc + 1
  71. IF( config_flags%symmetric_ye ) ye_bc = ye_bc + 1
  72. IF( config_flags%open_ys ) ys_bc = ys_bc + 1
  73. IF( config_flags%open_ye ) ye_bc = ye_bc + 1
  74. IF( config_flags%nested ) THEN
  75. xs_bc = xs_bc + 1
  76. xe_bc = xe_bc + 1
  77. ys_bc = ys_bc + 1
  78. ye_bc = ye_bc + 1
  79. ENDIF
  80. IF( config_flags%specified ) THEN
  81. IF( .NOT. config_flags%periodic_x)xs_bc = xs_bc + 1
  82. IF( .NOT. config_flags%periodic_x)xe_bc = xe_bc + 1
  83. ys_bc = ys_bc + 1
  84. ye_bc = ye_bc + 1
  85. ENDIF
  86. IF( config_flags%polar ) THEN
  87. ys_bc = ys_bc + 1
  88. ye_bc = ye_bc + 1
  89. ENDIF
  90. ! check the number of conditions for each boundary
  91. IF( (xs_bc /= 1) .or. &
  92. (xe_bc /= 1) .or. &
  93. (ys_bc /= 1) .or. &
  94. (ye_bc /= 1) ) THEN
  95. error = 1
  96. write( wrf_err_message ,*) ' *** Error in boundary condition specification '
  97. CALL wrf_message ( wrf_err_message )
  98. write( wrf_err_message ,*) ' boundary conditions at xs ', xs_bc
  99. CALL wrf_message ( wrf_err_message )
  100. write( wrf_err_message ,*) ' boundary conditions at xe ', xe_bc
  101. CALL wrf_message ( wrf_err_message )
  102. write( wrf_err_message ,*) ' boundary conditions at ys ', ys_bc
  103. CALL wrf_message ( wrf_err_message )
  104. write( wrf_err_message ,*) ' boundary conditions at ye ', ye_bc
  105. CALL wrf_message ( wrf_err_message )
  106. write( wrf_err_message ,*) ' boundary conditions logicals are '
  107. CALL wrf_message ( wrf_err_message )
  108. write( wrf_err_message ,*) ' periodic_x ',config_flags%periodic_x
  109. CALL wrf_message ( wrf_err_message )
  110. write( wrf_err_message ,*) ' periodic_y ',config_flags%periodic_y
  111. CALL wrf_message ( wrf_err_message )
  112. write( wrf_err_message ,*) ' symmetric_xs ',config_flags%symmetric_xs
  113. CALL wrf_message ( wrf_err_message )
  114. write( wrf_err_message ,*) ' symmetric_xe ',config_flags%symmetric_xe
  115. CALL wrf_message ( wrf_err_message )
  116. write( wrf_err_message ,*) ' symmetric_ys ',config_flags%symmetric_ys
  117. CALL wrf_message ( wrf_err_message )
  118. write( wrf_err_message ,*) ' symmetric_ye ',config_flags%symmetric_ye
  119. CALL wrf_message ( wrf_err_message )
  120. write( wrf_err_message ,*) ' open_xs ',config_flags%open_xs
  121. CALL wrf_message ( wrf_err_message )
  122. write( wrf_err_message ,*) ' open_xe ',config_flags%open_xe
  123. CALL wrf_message ( wrf_err_message )
  124. write( wrf_err_message ,*) ' open_ys ',config_flags%open_ys
  125. CALL wrf_message ( wrf_err_message )
  126. write( wrf_err_message ,*) ' open_ye ',config_flags%open_ye
  127. CALL wrf_message ( wrf_err_message )
  128. write( wrf_err_message ,*) ' polar ',config_flags%polar
  129. CALL wrf_message ( wrf_err_message )
  130. write( wrf_err_message ,*) ' nested ',config_flags%nested
  131. CALL wrf_message ( wrf_err_message )
  132. write( wrf_err_message ,*) ' specified ',config_flags%specified
  133. CALL wrf_message ( wrf_err_message )
  134. CALL wrf_error_fatal( ' *** Error in boundary condition specification ' )
  135. ENDIF
  136. ! now check to see if boundary zone size is sufficient.
  137. ! we could have the necessary boundary zone size be returned
  138. ! to the calling routine.
  139. IF( config_flags%periodic_x .or. &
  140. config_flags%periodic_y .or. &
  141. config_flags%symmetric_xs .or. &
  142. config_flags%symmetric_xe .or. &
  143. config_flags%symmetric_ys .or. &
  144. config_flags%symmetric_ye ) THEN
  145. bzone_min = MAX( 1, &
  146. (config_flags%h_mom_adv_order+1)/2, &
  147. (config_flags%h_sca_adv_order+1)/2 )
  148. IF( bzone < bzone_min) THEN
  149. error = 2
  150. WRITE ( wrf_err_message , * ) ' boundary zone not large enough '
  151. CALL wrf_message ( wrf_err_message )
  152. WRITE ( wrf_err_message , * ) ' boundary zone specified ',bzone
  153. CALL wrf_message ( wrf_err_message )
  154. WRITE ( wrf_err_message , * ) ' minimum boundary zone needed ',bzone_min
  155. CALL wrf_error_fatal ( wrf_err_message )
  156. ENDIF
  157. ENDIF
  158. CALL wrf_debug ( 100 , ' boundary conditions OK for grid ' )
  159. END subroutine boundary_condition_check
  160. !--------------------------------------------------------------------------
  161. SUBROUTINE set_physical_bc2d( dat, variable_in, &
  162. config_flags, &
  163. ids,ide, jds,jde, & ! domain dims
  164. ims,ime, jms,jme, & ! memory dims
  165. ips,ipe, jps,jpe, & ! patch dims
  166. its,ite, jts,jte )
  167. ! This subroutine sets the data in the boundary region, by direct
  168. ! assignment if possible, for periodic and symmetric (wall)
  169. ! boundary conditions. Currently, we are only doing 1 variable
  170. ! at a time - lots of overhead, so maybe this routine can be easily
  171. ! inlined later or we could pass multiple variables -
  172. ! would probably want a largestep and smallstep version.
  173. ! 15 Jan 99, Dave
  174. ! Modified the incoming its,ite,jts,jte to truly be the tile size.
  175. ! This required modifying the loop limits when the "istag" or "jstag"
  176. ! is used, as this is only required at the end of the domain.
  177. IMPLICIT NONE
  178. INTEGER, INTENT(IN ) :: ids,ide, jds,jde
  179. INTEGER, INTENT(IN ) :: ims,ime, jms,jme
  180. INTEGER, INTENT(IN ) :: ips,ipe, jps,jpe
  181. INTEGER, INTENT(IN ) :: its,ite, jts,jte
  182. CHARACTER, INTENT(IN ) :: variable_in
  183. CHARACTER :: variable
  184. REAL, DIMENSION( ims:ime , jms:jme ) :: dat
  185. TYPE( grid_config_rec_type ) config_flags
  186. INTEGER :: i, j, istag, jstag, itime
  187. LOGICAL :: debug, open_bc_copy
  188. !------------
  189. debug = .false.
  190. open_bc_copy = .false.
  191. variable = variable_in
  192. IF ( variable_in .ge. 'A' .and. variable_in .le. 'Z' ) THEN
  193. variable = CHAR( ICHAR(variable_in) - ICHAR('A') + ICHAR('a') )
  194. ENDIF
  195. IF ((variable == 'u') .or. (variable == 'v') .or. &
  196. (variable == 'w') .or. (variable == 't') .or. &
  197. (variable == 'x') .or. (variable == 'y') .or. &
  198. (variable == 'r') .or. (variable == 'p') ) open_bc_copy = .true.
  199. ! begin, first set a staggering variable
  200. istag = -1
  201. jstag = -1
  202. IF ((variable == 'u') .or. (variable == 'x')) istag = 0
  203. IF ((variable == 'v') .or. (variable == 'y')) jstag = 0
  204. if(debug) then
  205. write(6,*) ' in bc2d, var is ',variable, istag, jstag
  206. write(6,*) ' b.cs are ', &
  207. config_flags%periodic_x, &
  208. config_flags%periodic_y
  209. end if
  210. IF ( variable == 'd' ) then !JDM
  211. istag = 0
  212. jstag = 0
  213. ENDIF
  214. IF ( variable == 'e' ) then !JDM
  215. istag = 0
  216. ENDIF
  217. IF ( variable == 'f' ) then !JDM
  218. jstag = 0
  219. ENDIF
  220. ! periodic conditions.
  221. ! note, patch must cover full range in periodic dir, or else
  222. ! its intra-patch communication that is handled elsewheres.
  223. ! symmetry conditions can always be handled here, because no
  224. ! outside patch communication is needed
  225. periodicity_x: IF( ( config_flags%periodic_x ) ) THEN
  226. IF ( ( ids == ips ) .and. ( ide == ipe ) ) THEN ! test if east and west both on-processor
  227. IF ( its == ids ) THEN
  228. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  229. DO i = 0,-(bdyzone-1),-1
  230. dat(ids+i-1,j) = dat(ide+i-1,j)
  231. ENDDO
  232. ENDDO
  233. ENDIF
  234. IF ( ite == ide ) THEN
  235. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  236. !! DO i = 1 , bdyzone
  237. DO i = -istag , bdyzone
  238. dat(ide+i+istag,j) = dat(ids+i+istag,j)
  239. ENDDO
  240. ENDDO
  241. ENDIF
  242. ENDIF
  243. ELSE
  244. symmetry_xs: IF( ( config_flags%symmetric_xs ) .and. &
  245. ( its == ids ) ) THEN
  246. IF ( (variable /= 'u') .and. (variable /= 'x') ) THEN
  247. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  248. DO i = 1, bdyzone
  249. dat(ids-i,j) = dat(ids+i-1,j) ! here, dat(0) = dat(1), etc
  250. ENDDO ! symmetry about dat(0.5) (u=0 pt)
  251. ENDDO
  252. ELSE
  253. IF( variable == 'u' ) THEN
  254. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  255. DO i = 0, bdyzone-1
  256. dat(ids-i,j) = - dat(ids+i,j) ! here, u(0) = - u(2), etc
  257. ENDDO ! normal b.c symmetry at u(1)
  258. ENDDO
  259. ELSE
  260. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  261. DO i = 0, bdyzone-1
  262. dat(ids-i,j) = dat(ids+i,j) ! here, phi(0) = phi(2), etc
  263. ENDDO ! normal b.c symmetry at phi(1)
  264. ENDDO
  265. END IF
  266. ENDIF
  267. ENDIF symmetry_xs
  268. ! now the symmetry boundary at xe
  269. symmetry_xe: IF( ( config_flags%symmetric_xe ) .and. &
  270. ( ite == ide ) ) THEN
  271. IF ( (variable /= 'u') .and. (variable /= 'x') ) THEN
  272. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  273. DO i = 1, bdyzone
  274. dat(ide+i-1,j) = dat(ide-i,j) ! sym. about dat(ide-0.5)
  275. ENDDO
  276. ENDDO
  277. ELSE
  278. IF (variable == 'u' ) THEN
  279. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  280. DO i = 0, bdyzone-1
  281. dat(ide+i,j) = - dat(ide-i,j) ! u(ide+1) = - u(ide-1), etc.
  282. ENDDO
  283. ENDDO
  284. ELSE
  285. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  286. DO i = 0, bdyzone-1
  287. dat(ide+i,j) = dat(ide-i,j) ! phi(ide+1) = phi(ide-1), etc.
  288. ENDDO
  289. ENDDO
  290. END IF
  291. END IF
  292. END IF symmetry_xe
  293. ! set open b.c in X copy into boundary zone here. WCS, 19 March 2000
  294. open_xs: IF( ( config_flags%open_xs .or. &
  295. config_flags%specified .or. &
  296. config_flags%nested ) .and. &
  297. ( its == ids ) .and. open_bc_copy ) THEN
  298. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  299. dat(ids-1,j) = dat(ids,j) ! here, dat(0) = dat(1)
  300. dat(ids-2,j) = dat(ids,j)
  301. dat(ids-3,j) = dat(ids,j)
  302. ENDDO
  303. ENDIF open_xs
  304. ! now the open boundary copy at xe
  305. open_xe: IF( ( config_flags%open_xe .or. &
  306. config_flags%specified .or. &
  307. config_flags%nested ) .and. &
  308. ( ite == ide ) .and. open_bc_copy ) THEN
  309. IF ( variable /= 'u' .and. variable /= 'x') THEN
  310. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  311. dat(ide ,j) = dat(ide-1,j)
  312. dat(ide+1,j) = dat(ide-1,j)
  313. dat(ide+2,j) = dat(ide-1,j)
  314. ENDDO
  315. ELSE
  316. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  317. dat(ide+1,j) = dat(ide,j)
  318. dat(ide+2,j) = dat(ide,j)
  319. dat(ide+3,j) = dat(ide,j)
  320. ENDDO
  321. END IF
  322. END IF open_xe
  323. ! end open b.c in X copy into boundary zone addition. WCS, 19 March 2000
  324. END IF periodicity_x
  325. ! same procedure in y
  326. periodicity_y: IF( ( config_flags%periodic_y ) ) THEN
  327. IF ( ( jds == jps ) .and. ( jde == jpe ) ) THEN ! test of both north and south on processor
  328. IF( jts == jds ) then
  329. DO j = 0, -(bdyzone-1), -1
  330. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  331. dat(i,jds+j-1) = dat(i,jde+j-1)
  332. ENDDO
  333. ENDDO
  334. END IF
  335. IF( jte == jde ) then
  336. DO j = -jstag, bdyzone
  337. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  338. dat(i,jde+j+jstag) = dat(i,jds+j+jstag)
  339. ENDDO
  340. ENDDO
  341. END IF
  342. END IF
  343. ELSE
  344. symmetry_ys: IF( ( config_flags%symmetric_ys ) .and. &
  345. ( jts == jds) ) THEN
  346. IF ( (variable /= 'v') .and. (variable /= 'y') ) THEN
  347. DO j = 1, bdyzone
  348. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  349. dat(i,jds-j) = dat(i,jds+j-1)
  350. ENDDO
  351. ENDDO
  352. ELSE
  353. IF (variable == 'v') THEN
  354. DO j = 1, bdyzone
  355. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  356. dat(i,jds-j) = - dat(i,jds+j)
  357. ENDDO
  358. ENDDO
  359. ELSE
  360. DO j = 1, bdyzone
  361. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  362. dat(i,jds-j) = dat(i,jds+j)
  363. ENDDO
  364. ENDDO
  365. END IF
  366. ENDIF
  367. ENDIF symmetry_ys
  368. ! now the symmetry boundary at ye
  369. symmetry_ye: IF( ( config_flags%symmetric_ye ) .and. &
  370. ( jte == jde ) ) THEN
  371. IF ( (variable /= 'v') .and. (variable /= 'y') ) THEN
  372. DO j = 1, bdyzone
  373. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  374. dat(i,jde+j-1) = dat(i,jde-j)
  375. ENDDO
  376. ENDDO
  377. ELSE
  378. IF (variable == 'v' ) THEN
  379. DO j = 1, bdyzone
  380. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  381. dat(i,jde+j) = - dat(i,jde-j) ! bugfix: changed jds on rhs to jde , JM 20020410
  382. ENDDO
  383. ENDDO
  384. ELSE
  385. DO j = 1, bdyzone
  386. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  387. dat(i,jde+j) = dat(i,jde-j)
  388. ENDDO
  389. ENDDO
  390. END IF
  391. ENDIF
  392. END IF symmetry_ye
  393. ! set open b.c in Y copy into boundary zone here. WCS, 19 March 2000
  394. open_ys: IF( ( config_flags%open_ys .or. &
  395. config_flags%polar .or. &
  396. config_flags%specified .or. &
  397. config_flags%nested ) .and. &
  398. ( jts == jds) .and. open_bc_copy ) THEN
  399. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  400. dat(i,jds-1) = dat(i,jds)
  401. dat(i,jds-2) = dat(i,jds)
  402. dat(i,jds-3) = dat(i,jds)
  403. ENDDO
  404. ENDIF open_ys
  405. ! now the open boundary copy at ye
  406. open_ye: IF( ( config_flags%open_ye .or. &
  407. config_flags%polar .or. &
  408. config_flags%specified .or. &
  409. config_flags%nested ) .and. &
  410. ( jte == jde ) .and. open_bc_copy ) THEN
  411. IF (variable /= 'v' .and. variable /= 'y' ) THEN
  412. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  413. dat(i,jde ) = dat(i,jde-1)
  414. dat(i,jde+1) = dat(i,jde-1)
  415. dat(i,jde+2) = dat(i,jde-1)
  416. ENDDO
  417. ELSE
  418. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  419. dat(i,jde+1) = dat(i,jde)
  420. dat(i,jde+2) = dat(i,jde)
  421. dat(i,jde+3) = dat(i,jde)
  422. ENDDO
  423. ENDIF
  424. END IF open_ye
  425. ! end open b.c in Y copy into boundary zone addition. WCS, 19 March 2000
  426. END IF periodicity_y
  427. ! fix corners for doubly periodic domains
  428. IF ( config_flags%periodic_x .and. config_flags%periodic_y &
  429. .and. (ids == ips) .and. (ide == ipe) &
  430. .and. (jds == jps) .and. (jde == jpe) ) THEN
  431. IF ( (its == ids) .and. (jts == jds) ) THEN ! lower left corner fill
  432. DO j = 0, -(bdyzone-1), -1
  433. DO i = 0, -(bdyzone-1), -1
  434. dat(ids+i-1,jds+j-1) = dat(ide+i-1,jde+j-1)
  435. ENDDO
  436. ENDDO
  437. END IF
  438. IF ( (ite == ide) .and. (jts == jds) ) THEN ! lower right corner fill
  439. DO j = 0, -(bdyzone-1), -1
  440. DO i = 1, bdyzone
  441. dat(ide+i+istag,jds+j-1) = dat(ids+i+istag,jde+j-1)
  442. ENDDO
  443. ENDDO
  444. END IF
  445. IF ( (ite == ide) .and. (jte == jde) ) THEN ! upper right corner fill
  446. DO j = 1, bdyzone
  447. DO i = 1, bdyzone
  448. dat(ide+i+istag,jde+j+jstag) = dat(ids+i+istag,jds+j+jstag)
  449. ENDDO
  450. ENDDO
  451. END IF
  452. IF ( (its == ids) .and. (jte == jde) ) THEN ! upper left corner fill
  453. DO j = 1, bdyzone
  454. DO i = 0, -(bdyzone-1), -1
  455. dat(ids+i-1,jde+j+jstag) = dat(ide+i-1,jds+j+jstag)
  456. ENDDO
  457. ENDDO
  458. END IF
  459. END IF
  460. END SUBROUTINE set_physical_bc2d
  461. !-----------------------------------
  462. SUBROUTINE set_physical_bc3d( dat, variable_in, &
  463. config_flags, &
  464. ids,ide, jds,jde, kds,kde, & ! domain dims
  465. ims,ime, jms,jme, kms,kme, & ! memory dims
  466. ips,ipe, jps,jpe, kps,kpe, & ! patch dims
  467. its,ite, jts,jte, kts,kte )
  468. ! This subroutine sets the data in the boundary region, by direct
  469. ! assignment if possible, for periodic and symmetric (wall)
  470. ! boundary conditions. Currently, we are only doing 1 variable
  471. ! at a time - lots of overhead, so maybe this routine can be easily
  472. ! inlined later or we could pass multiple variables -
  473. ! would probably want a largestep and smallstep version.
  474. ! 15 Jan 99, Dave
  475. ! Modified the incoming its,ite,jts,jte to truly be the tile size.
  476. ! This required modifying the loop limits when the "istag" or "jstag"
  477. ! is used, as this is only required at the end of the domain.
  478. IMPLICIT NONE
  479. INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
  480. INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
  481. INTEGER, INTENT(IN ) :: ips,ipe, jps,jpe, kps,kpe
  482. INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
  483. CHARACTER, INTENT(IN ) :: variable_in
  484. CHARACTER :: variable
  485. REAL, DIMENSION( ims:ime , kms:kme , jms:jme ) :: dat
  486. TYPE( grid_config_rec_type ) config_flags
  487. INTEGER :: i, j, k, istag, jstag, itime, k_end
  488. LOGICAL :: debug, open_bc_copy
  489. !------------
  490. debug = .false.
  491. open_bc_copy = .false.
  492. variable = variable_in
  493. IF ( variable_in .ge. 'A' .and. variable_in .le. 'Z' ) THEN
  494. variable = CHAR( ICHAR(variable_in) - ICHAR('A') + ICHAR('a') )
  495. ENDIF
  496. IF ((variable == 'u') .or. (variable == 'v') .or. &
  497. (variable == 'w') .or. (variable == 't') .or. &
  498. (variable == 'd') .or. (variable == 'e') .or. &
  499. (variable == 'x') .or. (variable == 'y') .or. &
  500. (variable == 'f') .or. (variable == 'r') .or. &
  501. (variable == 'p') ) open_bc_copy = .true.
  502. ! begin, first set a staggering variable
  503. istag = -1
  504. jstag = -1
  505. k_end = max(1,min(kde-1,kte))
  506. IF ((variable == 'u') .or. (variable == 'x')) istag = 0
  507. IF ((variable == 'v') .or. (variable == 'y')) jstag = 0
  508. IF ((variable == 'd') .or. (variable == 'xy')) then
  509. istag = 0
  510. jstag = 0
  511. ENDIF
  512. IF ((variable == 'e') ) then
  513. istag = 0
  514. k_end = min(kde,kte)
  515. ENDIF
  516. IF ((variable == 'f') ) then
  517. jstag = 0
  518. k_end = min(kde,kte)
  519. ENDIF
  520. IF ( variable == 'w') k_end = min(kde,kte)
  521. ! k_end = kte
  522. if(debug) then
  523. write(6,*) ' in bc, var is ',variable, istag, jstag, kte, k_end
  524. write(6,*) ' b.cs are ', &
  525. config_flags%periodic_x, &
  526. config_flags%periodic_y
  527. end if
  528. ! periodic conditions.
  529. ! note, patch must cover full range in periodic dir, or else
  530. ! its intra-patch communication that is handled elsewheres.
  531. ! symmetry conditions can always be handled here, because no
  532. ! outside patch communication is needed
  533. periodicity_x: IF( ( config_flags%periodic_x ) ) THEN
  534. IF ( ( ids == ips ) .and. ( ide == ipe ) ) THEN ! test if both east and west on-processor
  535. IF ( its == ids ) THEN
  536. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  537. DO k = kts, k_end
  538. DO i = 0,-(bdyzone-1),-1
  539. dat(ids+i-1,k,j) = dat(ide+i-1,k,j)
  540. ENDDO
  541. ENDDO
  542. ENDDO
  543. ENDIF
  544. IF ( ite == ide ) THEN
  545. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  546. DO k = kts, k_end
  547. DO i = -istag , bdyzone
  548. dat(ide+i+istag,k,j) = dat(ids+i+istag,k,j)
  549. ENDDO
  550. ENDDO
  551. ENDDO
  552. ENDIF
  553. ENDIF
  554. ELSE
  555. symmetry_xs: IF( ( config_flags%symmetric_xs ) .and. &
  556. ( its == ids ) ) THEN
  557. IF ( (variable /= 'u') .and. (variable /= 'x') ) THEN
  558. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  559. DO k = kts, k_end
  560. DO i = 1, bdyzone
  561. dat(ids-i,k,j) = dat(ids+i-1,k,j) ! here, dat(0) = dat(1), etc
  562. ENDDO ! symmetry about dat(0.5) (u = 0 pt)
  563. ENDDO
  564. ENDDO
  565. ELSE
  566. IF ( variable == 'u' ) THEN
  567. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  568. DO k = kts, k_end
  569. DO i = 1, bdyzone
  570. dat(ids-i,k,j) = - dat(ids+i,k,j) ! here, u(0) = - u(2), etc
  571. ENDDO ! normal b.c symmetry at u(1)
  572. ENDDO
  573. ENDDO
  574. ELSE
  575. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  576. DO k = kts, k_end
  577. DO i = 1, bdyzone
  578. dat(ids-i,k,j) = dat(ids+i,k,j) ! here, phi(0) = phi(2), etc
  579. ENDDO ! normal b.c symmetry at phi(1)
  580. ENDDO
  581. ENDDO
  582. END IF
  583. ENDIF
  584. ENDIF symmetry_xs
  585. ! now the symmetry boundary at xe
  586. symmetry_xe: IF( ( config_flags%symmetric_xe ) .and. &
  587. ( ite == ide ) ) THEN
  588. IF ( (variable /= 'u') .and. (variable /= 'x') ) THEN
  589. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  590. DO k = kts, k_end
  591. DO i = 1, bdyzone
  592. dat(ide+i-1,k,j) = dat(ide-i,k,j) ! sym. about dat(ide-0.5)
  593. ENDDO
  594. ENDDO
  595. ENDDO
  596. ELSE
  597. IF (variable == 'u') THEN
  598. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  599. DO k = kts, k_end
  600. DO i = 1, bdyzone
  601. dat(ide+i,k,j) = - dat(ide-i,k,j) ! u(ide+1) = - u(ide-1), etc.
  602. ENDDO
  603. ENDDO
  604. ENDDO
  605. ELSE
  606. DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
  607. DO k = kts, k_end
  608. DO i = 1, bdyzone
  609. dat(ide+i,k,j) = dat(ide-i,k,j) ! phi(ide+1) = - phi(ide-1), etc.
  610. ENDDO
  611. ENDDO
  612. ENDDO
  613. END IF
  614. END IF
  615. END IF symmetry_xe
  616. ! set open b.c in X copy into boundary zone here. WCS, 19 March 2000
  617. open_xs: IF( ( config_flags%open_xs .or. &
  618. config_flags%specified .or. &
  619. config_flags%nested ) .and. &
  620. ( its == ids ) .and. open_bc_copy ) THEN
  621. DO j = jts-bdyzone, MIN(jte,jde+jstag)+bdyzone
  622. DO k = kts, k_end
  623. dat(ids-1,k,j) = dat(ids,k,j) ! here, dat(0) = dat(1), etc
  624. dat(ids-2,k,j) = dat(ids,k,j)
  625. dat(ids-3,k,j) = dat(ids,k,j)
  626. ENDDO
  627. ENDDO
  628. ENDIF open_xs
  629. ! now the open_xe boundary copy
  630. open_xe: IF( ( config_flags%open_xe .or. &
  631. config_flags%specified .or. &
  632. config_flags%nested ) .and. &
  633. ( ite == ide ) .and. open_bc_copy ) THEN
  634. IF (variable /= 'u' .and. variable /= 'x' ) THEN
  635. DO j = jts-bdyzone, MIN(jte,jde+jstag)+bdyzone
  636. DO k = kts, k_end
  637. dat(ide ,k,j) = dat(ide-1,k,j)
  638. dat(ide+1,k,j) = dat(ide-1,k,j)
  639. dat(ide+2,k,j) = dat(ide-1,k,j)
  640. ENDDO
  641. ENDDO
  642. ELSE
  643. !!!!!!! I am not sure about this one! JM 20020402
  644. DO j = MAX(jds,jts-1)-bdyzone, MIN(jte+1,jde+jstag)+bdyzone
  645. DO k = kts, k_end
  646. dat(ide+1,k,j) = dat(ide,k,j)
  647. dat(ide+2,k,j) = dat(ide,k,j)
  648. dat(ide+3,k,j) = dat(ide,k,j)
  649. ENDDO
  650. ENDDO
  651. END IF
  652. END IF open_xe
  653. ! end open b.c in X copy into boundary zone addition. WCS, 19 March 2000
  654. END IF periodicity_x
  655. ! same procedure in y
  656. periodicity_y: IF( ( config_flags%periodic_y ) ) THEN
  657. IF ( ( jds == jps ) .and. ( jde == jpe ) ) THEN ! test if both north and south on processor
  658. IF( jts == jds ) then
  659. DO j = 0, -(bdyzone-1), -1
  660. DO k = kts, k_end
  661. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  662. dat(i,k,jds+j-1) = dat(i,k,jde+j-1)
  663. ENDDO
  664. ENDDO
  665. ENDDO
  666. END IF
  667. IF( jte == jde ) then
  668. DO j = -jstag, bdyzone
  669. DO k = kts, k_end
  670. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  671. dat(i,k,jde+j+jstag) = dat(i,k,jds+j+jstag)
  672. ENDDO
  673. ENDDO
  674. ENDDO
  675. END IF
  676. END IF
  677. ELSE
  678. symmetry_ys: IF( ( config_flags%symmetric_ys ) .and. &
  679. ( jts == jds) ) THEN
  680. IF ( (variable /= 'v') .and. (variable /= 'y') ) THEN
  681. DO j = 1, bdyzone
  682. DO k = kts, k_end
  683. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  684. dat(i,k,jds-j) = dat(i,k,jds+j-1)
  685. ENDDO
  686. ENDDO
  687. ENDDO
  688. ELSE
  689. IF (variable == 'v') THEN
  690. DO j = 1, bdyzone
  691. DO k = kts, k_end
  692. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  693. dat(i,k,jds-j) = - dat(i,k,jds+j)
  694. ENDDO
  695. ENDDO
  696. ENDDO
  697. ELSE
  698. DO j = 1, bdyzone
  699. DO k = kts, k_end
  700. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  701. dat(i,k,jds-j) = dat(i,k,jds+j)
  702. ENDDO
  703. ENDDO
  704. ENDDO
  705. END IF
  706. ENDIF
  707. ENDIF symmetry_ys
  708. ! now the symmetry boundary at ye
  709. symmetry_ye: IF( ( config_flags%symmetric_ye ) .and. &
  710. ( jte == jde ) ) THEN
  711. IF ( (variable /= 'v') .and. (variable /= 'y') ) THEN
  712. DO j = 1, bdyzone
  713. DO k = kts, k_end
  714. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  715. dat(i,k,jde+j-1) = dat(i,k,jde-j)
  716. ENDDO
  717. ENDDO
  718. ENDDO
  719. ELSE
  720. IF ( variable == 'v' ) THEN
  721. DO j = 1, bdyzone
  722. DO k = kts, k_end
  723. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  724. dat(i,k,jde+j) = - dat(i,k,jde-j)
  725. ENDDO
  726. ENDDO
  727. ENDDO
  728. ELSE
  729. DO j = 1, bdyzone
  730. DO k = kts, k_end
  731. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  732. dat(i,k,jde+j) = dat(i,k,jde-j)
  733. ENDDO
  734. ENDDO
  735. ENDDO
  736. END IF
  737. ENDIF
  738. END IF symmetry_ye
  739. ! set open b.c in Y copy into boundary zone here. WCS, 19 March 2000
  740. open_ys: IF( ( config_flags%open_ys .or. &
  741. config_flags%polar .or. &
  742. config_flags%specified .or. &
  743. config_flags%nested ) .and. &
  744. ( jts == jds) .and. open_bc_copy ) THEN
  745. DO k = kts, k_end
  746. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  747. dat(i,k,jds-1) = dat(i,k,jds)
  748. dat(i,k,jds-2) = dat(i,k,jds)
  749. dat(i,k,jds-3) = dat(i,k,jds)
  750. ENDDO
  751. ENDDO
  752. ENDIF open_ys
  753. ! now the open boundary copy at ye
  754. open_ye: IF( ( config_flags%open_ye .or. &
  755. config_flags%polar .or. &
  756. config_flags%specified .or. &
  757. config_flags%nested ) .and. &
  758. ( jte == jde ) .and. open_bc_copy ) THEN
  759. IF (variable /= 'v' .and. variable /= 'y' ) THEN
  760. DO k = kts, k_end
  761. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  762. dat(i,k,jde ) = dat(i,k,jde-1)
  763. dat(i,k,jde+1) = dat(i,k,jde-1)
  764. dat(i,k,jde+2) = dat(i,k,jde-1)
  765. ENDDO
  766. ENDDO
  767. ELSE
  768. DO k = kts, k_end
  769. DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
  770. dat(i,k,jde+1) = dat(i,k,jde)
  771. dat(i,k,jde+2) = dat(i,k,jde)
  772. dat(i,k,jde+3) = dat(i,k,jde)
  773. ENDDO
  774. ENDDO
  775. ENDIF
  776. END IF open_ye
  777. ! end open b.c in Y copy into boundary zone addition. WCS, 19 March 2000
  778. END IF periodicity_y
  779. ! fix corners for doubly periodic domains
  780. IF ( config_flags%periodic_x .and. config_flags%periodic_y &
  781. .and. (ids == ips) .and. (ide == ipe) &
  782. .and. (jds == jps) .and. (jde == jpe) ) THEN
  783. IF ( (its == ids) .and. (jts == jds) ) THEN ! lower left corner fill
  784. DO j = 0, -(bdyzone-1), -1
  785. DO k = kts, k_end
  786. DO i = 0, -(bdyzone-1), -1
  787. dat(ids+i-1,k,jds+j-1) = dat(ide+i-1,k,jde+j-1)
  788. ENDDO
  789. ENDDO
  790. ENDDO
  791. END IF
  792. IF ( (ite == ide) .and. (jts == jds) ) THEN ! lower right corner fill
  793. DO j = 0, -(bdyzone-1), -1
  794. DO k = kts, k_end
  795. DO i = 1, bdyzone
  796. dat(ide+i+istag,k,jds+j-1) = dat(ids+i+istag,k,jde+j-1)
  797. ENDDO
  798. ENDDO
  799. ENDDO
  800. END IF
  801. IF ( (ite == ide) .and. (jte == jde) ) THEN ! upper right corner fill
  802. DO j = 1, bdyzone
  803. DO k = kts, k_end
  804. DO i = 1, bdyzone
  805. dat(ide+i+istag,k,jde+j+jstag) = dat(ids+i+istag,k,jds+j+jstag)
  806. ENDDO
  807. ENDDO
  808. ENDDO
  809. END IF
  810. IF ( (its == ids) .and. (jte == jde) ) THEN ! upper left corner fill
  811. DO j = 1, bdyzone
  812. DO k = kts, k_end
  813. DO i = 0, -(bdyzone-1), -1
  814. dat(ids+i-1,k,jde+j+jstag) = dat(ide+i-1,k,jds+j+jstag)
  815. ENDDO
  816. ENDDO
  817. ENDDO
  818. END IF
  819. END IF
  820. END SUBROUTINE set_physical_bc3d
  821. SUBROUTINE init_module_bc
  822. END SUBROUTINE init_module_bc
  823. !------------------------------------------------------------------------
  824. ! a couple versions of this call to allow a smaller-than-memory dimensioned field (e.g. tile sized)
  825. ! to be passed in as the first argument. Both of these call the _core version defined below.
  826. SUBROUTINE relax_bdytend ( field, field_tend, &
  827. field_bdy_xs, field_bdy_xe, &
  828. field_bdy_ys, field_bdy_ye, &
  829. field_bdy_tend_xs, field_bdy_tend_xe, &
  830. field_bdy_tend_ys, field_bdy_tend_ye, &
  831. variable_in, config_flags, &
  832. spec_bdy_width, spec_zone, relax_zone, &
  833. dtbc, fcx, gcx, &
  834. ids,ide, jds,jde, kds,kde, & ! domain dims
  835. ims,ime, jms,jme, kms,kme, & ! memory dims
  836. ips,ipe, jps,jpe, kps,kpe, & ! patch dims
  837. its,ite, jts,jte, kts,kte &
  838. )
  839. IMPLICIT NONE
  840. INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
  841. INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
  842. INTEGER, INTENT(IN ) :: ips,ipe, jps,jpe, kps,kpe
  843. INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
  844. INTEGER, INTENT(IN ) :: spec_bdy_width, spec_zone, relax_zone
  845. REAL, INTENT(IN ) :: dtbc
  846. CHARACTER, INTENT(IN ) :: variable_in
  847. REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(IN ) :: field
  848. REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(INOUT) :: field_tend
  849. REAL, DIMENSION( jms:jme , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_xs, field_bdy_xe
  850. REAL, DIMENSION( ims:ime , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_ys, field_bdy_ye
  851. REAL, DIMENSION( jms:jme , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_tend_xs, field_bdy_tend_xe
  852. REAL, DIMENSION( ims:ime , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_tend_ys, field_bdy_tend_ye
  853. REAL, DIMENSION( spec_bdy_width ), INTENT(IN ) :: fcx, gcx
  854. TYPE( grid_config_rec_type ) config_flags
  855. CALL relax_bdytend_core ( field, field_tend, &
  856. field_bdy_xs, field_bdy_xe, &
  857. field_bdy_ys, field_bdy_ye, &
  858. field_bdy_tend_xs, field_bdy_tend_xe, &
  859. field_bdy_tend_ys, field_bdy_tend_ye, &
  860. variable_in, config_flags, &
  861. spec_bdy_width, spec_zone, relax_zone, &
  862. dtbc, fcx, gcx, &
  863. ids,ide, jds,jde, kds,kde, & ! domain dims
  864. ims,ime, jms,jme, kms,kme, & ! memory dims
  865. ips,ipe, jps,jpe, kps,kpe, & ! patch dims
  866. its,ite, jts,jte, kts,kte, & ! patch dims
  867. ims,ime, jms,jme, kms,kme ) ! dimension of the field argument
  868. END SUBROUTINE relax_bdytend
  869. ! version that allows tile-sized version of field. Note, caller should define the
  870. ! field to be -+1 of tile size in each dimension because routine is going off onto halo
  871. ! for example, see relax_bdytend in dyn_em/module_bc_em.F
  872. SUBROUTINE relax_bdytend_tile ( field, field_tend, &
  873. field_bdy_xs, field_bdy_xe, &
  874. field_bdy_ys, field_bdy_ye, &
  875. field_bdy_tend_xs, field_bdy_tend_xe, &
  876. field_bdy_tend_ys, field_bdy_tend_ye, &
  877. variable_in, config_flags, &
  878. spec_bdy_width, spec_zone, relax_zone, &
  879. dtbc, fcx, gcx, &
  880. ids,ide, jds,jde, kds,kde, & ! domain dims
  881. ims,ime, jms,jme, kms,kme, & ! memory dims
  882. ips,ipe, jps,jpe, kps,kpe, & ! patch dims
  883. its,ite, jts,jte, kts,kte, &
  884. iXs,iXe, jXs,jXe, kXs,kXe & ! dims of first argument
  885. )
  886. INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
  887. INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
  888. INTEGER, INTENT(IN ) :: ips,ipe, jps,jpe, kps,kpe
  889. INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
  890. INTEGER, INTENT(IN ) :: iXs,iXe, jXs,jXe, kXs,kXe
  891. INTEGER, INTENT(IN ) :: spec_bdy_width, spec_zone, relax_zone
  892. REAL, INTENT(IN ) :: dtbc
  893. CHARACTER, INTENT(IN ) :: variable_in
  894. REAL, DIMENSION( iXs:iXe , kXs:kXe , jXs:jXe ), INTENT(IN ) :: field
  895. REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(INOUT) :: field_tend
  896. REAL, DIMENSION( jms:jme , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_xs, field_bdy_xe
  897. REAL, DIMENSION( ims:ime , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_ys, field_bdy_ye
  898. REAL, DIMENSION( jms:jme , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_tend_xs, field_bdy_tend_xe
  899. REAL, DIMENSION( ims:ime , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_tend_ys, field_bdy_tend_ye
  900. REAL, DIMENSION( spec_bdy_width ), INTENT(IN ) :: fcx, gcx
  901. TYPE( grid_config_rec_type ) config_flags
  902. CALL relax_bdytend_core ( field, field_tend, &
  903. field_bdy_xs, field_bdy_xe, &
  904. field_bdy_ys, field_bdy_ye, &
  905. field_bdy_tend_xs, field_bdy_tend_xe, &
  906. field_bdy_tend_ys, field_bdy_tend_ye, &
  907. variable_in, config_flags, &
  908. spec_bdy_width, spec_zone, relax_zone, &
  909. dtbc, fcx, gcx, &
  910. ids,ide, jds,jde, kds,kde, & ! domain dims
  911. ims,ime, jms,jme, kms,kme, & ! memory dims
  912. ips,ipe, jps,jpe, kps,kpe, & ! patch dims
  913. its,ite, jts,jte, kts,kte, &
  914. iXs,iXe, jXs,jXe, kXs,kXe ) ! dimension of the field argument
  915. END SUBROUTINE relax_bdytend_tile
  916. SUBROUTINE relax_bdytend_core ( field, field_tend, &
  917. field_bdy_xs, field_bdy_xe, &
  918. field_bdy_ys, field_bdy_ye, &
  919. field_bdy_tend_xs, field_bdy_tend_xe, &
  920. field_bdy_tend_ys, field_bdy_tend_ye, &
  921. variable_in, config_flags, &
  922. spec_bdy_width, spec_zone, relax_zone, &
  923. dtbc, fcx, gcx, &
  924. ids,ide, jds,jde, kds,kde, & ! domain dims
  925. ims,ime, jms,jme, kms,kme, & ! memory dims
  926. ips,ipe, jps,jpe, kps,kpe, & ! patch dims
  927. its,ite, jts,jte, kts,kte, & ! patch dims
  928. iXs,iXe, jXs,jXe, kXs,kXe & ! field (1st arg) dims; might be tile or patch
  929. )
  930. ! This subroutine adds the tendencies in the boundary relaxation region, for specified
  931. ! boundary conditions.
  932. ! spec_bdy_width is only used to dimension the boundary arrays.
  933. ! relax_zone is the inner edge of the boundary relaxation zone treated here.
  934. ! spec_zone is the width of the outer specified b.c.s that are not changed here.
  935. ! (JD July 2000)
  936. IMPLICIT NONE
  937. INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
  938. INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
  939. INTEGER, INTENT(IN ) :: ips,ipe, jps,jpe, kps,kpe
  940. INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
  941. INTEGER, INTENT(IN ) :: iXs,iXe, jXs,jXe, kXs,kXe
  942. INTEGER, INTENT(IN ) :: spec_bdy_width, spec_zone, relax_zone
  943. REAL, INTENT(IN ) :: dtbc
  944. CHARACTER, INTENT(IN ) :: variable_in
  945. REAL, DIMENSION( iXs:iXe , kXs:kXe , jXs:jXe ), INTENT(IN ) :: field
  946. REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(INOUT) :: field_tend
  947. REAL, DIMENSION( jms:jme , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_xs, field_bdy_xe
  948. REAL, DIMENSION( ims:ime , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_ys, field_bdy_ye
  949. REAL, DIMENSION( jms:jme , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_tend_xs, field_bdy_tend_xe
  950. REAL, DIMENSION( ims:ime , kds:kde , spec_bdy_width ), INTENT(IN ) :: field_bdy_tend_ys, field_bdy_tend_ye
  951. REAL, DIMENSION( spec_bdy_width ), INTENT(IN ) :: fcx, gcx
  952. TYPE( grid_config_rec_type ) config_flags
  953. CHARACTER :: variable
  954. INTEGER :: i, j, k, ibs, ibe, jbs, jbe, itf, jtf, ktf, im1, ip1
  955. INTEGER :: b_dist, b_limit
  956. REAL :: fls0, fls1, fls2, fls3, fls4
  957. LOGICAL :: periodic_x
  958. periodic_x = config_flags%periodic_x
  959. variable = variable_in
  960. IF (variable == 'U') variable = 'u'
  961. IF (variable == 'V') variable = 'v'
  962. IF (variable == 'M') variable = 'm'
  963. IF (variable == 'H') variable = 'h'
  964. ibs = ids
  965. ibe = ide-1
  966. itf = min(ite,ide-1)
  967. jbs = jds
  968. jbe = jde-1
  969. jtf = min(jte,jde-1)
  970. ktf = kde-1
  971. IF (variable == 'u') ibe = ide
  972. IF (variable == 'u') itf = min(ite,ide)
  973. IF (variable == 'v') jbe = jde
  974. IF (variable == 'v') jtf = min(jte,jde)
  975. IF (variable == 'm') ktf = kte
  976. IF (variable == 'h') ktf = kte
  977. IF (jts - jbs .lt. relax_zone) THEN
  978. ! Y-start boundary
  979. DO j = max(jts,jbs+spec_zone), min(jtf,jbs+relax_zone-1)
  980. b_dist = j - jbs
  981. b_limit = b_dist
  982. IF(periodic_x)b_limit = 0
  983. DO k = kts, ktf
  984. DO i = max(its,b_limit+ibs), min(itf,ibe-b_limit)
  985. im1 = max(i-1,ibs)
  986. ip1 = min(i+1,ibe)
  987. fls0 = field_bdy_ys(i, k, b_dist+1) &
  988. + dtbc * field_bdy_tend_ys(i, k, b_dist+1) &
  989. - field(i,k,j)
  990. fls1 = field_bdy_ys(im1, k, b_dist+1) &
  991. + dtbc * field_bdy_tend_ys(im1, k, b_dist+1) &
  992. - field(im1,k,j)
  993. fls2 = field_bdy_ys(ip1, k, b_dist+1) &
  994. + dtbc * field_bdy_tend_ys(ip1, k, b_dist+1) &
  995. - field(ip1,k,j)
  996. fls3 = field_bdy_ys(i, k, b_dist) &
  997. + dtbc * field_bdy_tend_ys(i, k, b_dist) &
  998. - field(i,k,j-1)
  999. fls4 = field_bdy_ys(i, k, b_dist+2) &
  1000. + dtbc * field_bdy_tend_ys(i, k, b_dist+2) &
  1001. - field(i,k,j+1)
  1002. field_tend(i,k,j) = field_tend(i,k,j) &
  1003. + fcx(b_dist+1)*fls0 &
  1004. - gcx(b_dist+1)*(fls1+fls2+fls3+fls4-4.*fls0)
  1005. ENDDO
  1006. ENDDO
  1007. ENDDO
  1008. ENDIF
  1009. IF (jbe - jtf .lt. relax_zone) THEN
  1010. ! Y-end boundary
  1011. DO j = max(jts,jbe-relax_zone+1), min(jtf,jbe-spec_zone)
  1012. b_dist = jbe - j
  1013. b_limit = b_dist
  1014. IF(periodic_x)b_limit = 0
  1015. DO k = kts, ktf
  1016. DO i = max(its,b_limit+ibs), min(itf,ibe-b_limit)
  1017. im1 = max(i-1,ibs)
  1018. ip1 = min(i+1,ibe)
  1019. fls0 = field_bdy_ye(i, k, b_dist+1) &
  1020. + dtbc * field_bdy_tend_ye(i, k, b_dist+1) &
  1021. - field(i,k,j)
  1022. fls1 = field_bdy_ye(im1, k, b_dist+1) &
  1023. + dtbc * field_bdy_tend_ye(im1, k, b_dist+1) &
  1024. - field(im1,k,j)
  1025. fls2 = field_bdy_ye(ip1, k, b_dist+1) &
  1026. + dtbc * field_bdy_tend_ye(ip1, k, b_dist+1) &
  1027. - field(ip1,k,j)
  1028. fls3 = field_bdy_ye(i, k, b_dist) &
  1029. + dtbc * field_bdy_tend_ye(i, k, b_dist) &
  1030. - field(i,k,j+1)
  1031. fls4 = field_bdy_ye(i, k, b_dist+2) &
  1032. + dtbc * field_bdy_tend_ye(i, k, b_dist+2) &
  1033. - field(i,k,j-1)
  1034. field_tend(i,k,j) = field_tend(i,k,j) &
  1035. + fcx(b_dist+1)*fls0 &
  1036. - gcx(b_dist+1)*(fls1+fls2+fls3+fls4-4.*fls0)
  1037. ENDDO
  1038. ENDDO
  1039. ENDDO
  1040. ENDIF
  1041. IF(.NOT.periodic_x)THEN
  1042. IF (its - ibs .lt. relax_zone) THEN
  1043. ! X-start boundary
  1044. DO i = max(its,ibs+spec_zone), min(itf,ibs+relax_zone-1)
  1045. b_dist = i - ibs
  1046. DO k = kts, ktf
  1047. DO j = max(jts,b_dist+jbs+1), min(jtf,jbe-b_dist-1)
  1048. fls0 = field_bdy_xs(j, k, b_dist+1) &
  1049. + dtbc * field_bdy_tend_xs(j, k, b_dist+1) &
  1050. - field(i,k,j)
  1051. fls1 = field_bdy_xs(j-1, k, b_dist+1) &
  1052. + dtbc * field_bdy_tend_xs(j-1, k, b_dist+1) &
  1053. - field(i,k,j-1)
  1054. fls2 = field_bdy_xs(j+1, k, b_dist+1) &
  1055. + dtbc * field_bdy_tend_xs(j+1, k, b_dist+1) &
  1056. - field(i,k,j+1)
  1057. fls3 = field_bdy_xs(j, k, b_dist) &
  1058. + dtbc * field_bdy_tend_xs(j, k, b_dist) &
  1059. - field(i-1,k,j)
  1060. fls4 = field_bdy_xs(j, k, b_dist+2) &
  1061. + dtbc * field_bdy_tend_xs(j, k, b_dist+2) &
  1062. - field(i+1,k,j)
  1063. field_tend(i,k,j) = field_tend(i,k,j) &
  1064. + fcx(b_dist+1)*fls0 &
  1065. - gcx(b_dist+1)*(fls1+fls2+fls3+fls4-4.*fls0)
  1066. ENDDO
  1067. ENDDO
  1068. ENDDO
  1069. ENDIF
  1070. IF (ibe - itf .lt. relax_zone) THEN
  1071. ! X-end boundary
  1072. DO i = max(its,ibe-relax_zone+1), min(itf,ibe-spec_zone)
  1073. b_dist = ibe - i
  1074. DO k = kts, ktf
  1075. DO j = max(jts,b_dist+jbs+1), min(jtf,jbe-b_dist-1)
  1076. fls0 = field_bdy_xe(j, k, b_dist+1) &
  1077. + dtbc * field_bdy_tend_xe(j, k, b_dist+1) &
  1078. - field(i,k,j)
  1079. fls1 = field_bdy_xe(j-1, k, b_dist+1) &
  1080. + dtbc * field_bdy_tend_xe(j-1, k, b_dist+1) &
  1081. - field(i,k,j-1)
  1082. fls2 = field_bdy_xe(j+1, k, b_dist+1) &
  1083. + dtbc * field_bdy_tend_xe(j+1, k, b_dist+1) &
  1084. - field(i,k,j+1)
  1085. fls3 = field_bdy_xe(j, k, b_dist) &
  1086. + dtbc * field_bdy_tend_xe(j, k, b_dist) &
  1087. - field(i+1,k,j)
  1088. fls4 = field_bdy_xe(j, k, b_dist+2) &
  1089. + dtbc * field_bdy_tend_xe(j, k, b_dist+2) &
  1090. - field(i-1,k,j)
  1091. field_tend(i,k,j) = field_tend(i,k,j) &
  1092. + fcx(b_dist+1)*fls0 &
  1093. - gcx(b_dist+1)*(fls1+fls2+fls3+fls4-4.*fls0)
  1094. ENDDO
  1095. ENDDO
  1096. ENDDO
  1097. ENDIF
  1098. ENDIF
  1099. END SUBROUTINE relax_bdytend_core
  1100. !------------------------------------------------------------------------
  1101. SUBROUTINE spec_bdytend ( field_tend, &
  1102. field_bdy_xs, field_bdy_xe, &

Large files files are truncated, but you can click here to view the full file