PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/WPS/geogrid/src/smooth_module.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 587 lines | 369 code | 118 blank | 100 comment | 36 complexity | ff2d7589f6ce247a17e013d503336c7d MD5 | raw file
Possible License(s): AGPL-1.0
  1. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2. ! MODULE SMOOTH_MODULE
  3. !
  4. ! This module provides routines for smoothing.
  5. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  6. module smooth_module
  7. use parallel_module
  8. contains
  9. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  10. ! Name: one_two_one
  11. !
  12. ! Purpose: Apply the 1-2-1 smoother from the MM5 program TERRAIN
  13. ! (found in smth121.F) to array.
  14. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  15. subroutine one_two_one(array, start_dom_x, end_dom_x, start_dom_y, end_dom_y, &
  16. start_x, end_x, start_y, end_y, start_z, end_z, npass, msgval)
  17. implicit none
  18. ! Arguments
  19. integer, intent(in) :: start_dom_x, start_dom_y, start_x, start_y, start_z
  20. integer, intent(in) :: end_dom_x, end_dom_y, end_x, end_y, end_z
  21. integer, intent(in) :: npass
  22. real, intent(in) :: msgval
  23. real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), intent(inout) :: array
  24. ! Local variables
  25. integer :: ix, iy, iz, ipass
  26. real, pointer, dimension(:,:,:) :: scratch
  27. allocate(scratch(start_x+1:end_x-1, start_y:end_y, start_z:end_z))
  28. do ipass=1,npass
  29. do iy=start_y,end_y
  30. do ix=start_x+1,end_x-1
  31. do iz=start_z,end_z
  32. scratch(ix,iy,iz) = 0.50*array(ix,iy,iz)+0.25*(array(ix-1,iy,iz)+array(ix+1,iy,iz))
  33. end do
  34. end do
  35. end do
  36. do iy=start_y+1,end_y-1
  37. do ix=start_x+1,end_x-1
  38. do iz=start_z,end_z
  39. array(ix,iy,iz) = 0.50*scratch(ix,iy,iz)+0.25*(scratch(ix,iy-1,iz)+scratch(ix,iy+1,iz))
  40. end do
  41. end do
  42. end do
  43. call exchange_halo_r(array, &
  44. start_x, end_x, start_y, end_y, start_z, end_z, &
  45. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  46. end do
  47. deallocate(scratch)
  48. end subroutine one_two_one
  49. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  50. ! Name: smth_desmth
  51. !
  52. ! Purpose: Apply the smoother-desmoother from the MM5 program TERRAIN
  53. ! (found in smther.F) to array.
  54. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  55. subroutine smth_desmth(array, start_dom_x, end_dom_x, start_dom_y, end_dom_y, &
  56. start_x, end_x, start_y, end_y, start_z, end_z, npass, msgval)
  57. implicit none
  58. ! Arguments
  59. integer, intent(in) :: start_dom_x, start_dom_y, start_x, start_y, start_z
  60. integer, intent(in) :: end_dom_x, end_dom_y, end_x, end_y, end_z
  61. integer, intent(in) :: npass
  62. real, intent(in) :: msgval
  63. real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), intent(inout) :: array
  64. ! Local variables
  65. integer :: ix, iy, iz, ipass
  66. real, pointer, dimension(:,:,:) :: scratch
  67. allocate(scratch(start_x+1:end_x-1, start_y:end_y, start_z:end_z))
  68. do ipass=1,npass
  69. !
  70. ! Smoothing pass
  71. !
  72. do iy=start_y,end_y
  73. do ix=start_x+1,end_x-1
  74. do iz=start_z,end_z
  75. scratch(ix,iy,iz) = 0.5*array(ix,iy,iz) + 0.25*(array(ix-1,iy,iz)+array(ix+1,iy,iz))
  76. end do
  77. end do
  78. end do
  79. do iy=start_y+1,end_y-1
  80. do ix=start_x+1,end_x-1
  81. do iz=start_z,end_z
  82. array(ix,iy,iz) = 0.5*scratch(ix,iy,iz) + 0.25*(scratch(ix,iy-1,iz)+scratch(ix,iy+1,iz))
  83. end do
  84. end do
  85. end do
  86. call exchange_halo_r(array, &
  87. start_x, end_x, start_y, end_y, start_z, end_z, &
  88. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  89. !
  90. ! Desmoothing pass
  91. !
  92. do iy=start_y,end_y
  93. do ix=start_x+1,end_x-1
  94. do iz=start_z,end_z
  95. scratch(ix,iy,iz) = 1.52*array(ix,iy,iz) - 0.26*(array(ix-1,iy,iz)+array(ix+1,iy,iz))
  96. end do
  97. end do
  98. end do
  99. do iy=start_y+1,end_y-1
  100. do ix=start_x+1,end_x-1
  101. do iz=start_z,end_z
  102. array(ix,iy,iz) = 1.52*scratch(ix,iy,iz) - 0.26*(scratch(ix,iy-1,iz)+scratch(ix,iy+1,iz))
  103. end do
  104. end do
  105. end do
  106. call exchange_halo_r(array, &
  107. start_x, end_x, start_y, end_y, start_z, end_z, &
  108. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  109. end do
  110. deallocate(scratch)
  111. end subroutine smth_desmth
  112. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  113. ! Name: smth_desmth_special
  114. !
  115. ! Purpose: Apply the smoother-desmoother from the MM5 program TERRAIN
  116. ! (found in smther.F) to array; however, any grid points that were not
  117. ! originally negative but which have been smoothed to a negative value
  118. ! will be restored to their original values.
  119. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  120. subroutine smth_desmth_special(array, start_dom_x, end_dom_x, start_dom_y, end_dom_y, &
  121. start_x, end_x, start_y, end_y, start_z, end_z, npass, msgval)
  122. implicit none
  123. ! Arguments
  124. integer, intent(in) :: start_dom_x, start_dom_y, start_x, start_y, start_z
  125. integer, intent(in) :: end_dom_x, end_dom_y, end_x, end_y, end_z
  126. integer, intent(in) :: npass
  127. real, intent(in) :: msgval
  128. real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), intent(inout) :: array
  129. ! Local variables
  130. integer :: ix, iy, iz, ipass
  131. real, pointer, dimension(:,:,:) :: scratch, orig_array
  132. allocate(scratch(start_x+1:end_x-1, start_y:end_y, start_z:end_z))
  133. allocate(orig_array(start_x:end_x, start_y:end_y, start_z:end_z))
  134. orig_array = array
  135. do ipass=1,npass
  136. !
  137. ! Smoothing pass
  138. !
  139. do iy=start_y,end_y
  140. do ix=start_x+1,end_x-1
  141. do iz=start_z,end_z
  142. scratch(ix,iy,iz) = 0.5*array(ix,iy,iz) + 0.25*(array(ix-1,iy,iz)+array(ix+1,iy,iz))
  143. end do
  144. end do
  145. end do
  146. do iy=start_y+1,end_y-1
  147. do ix=start_x+1,end_x-1
  148. do iz=start_z,end_z
  149. array(ix,iy,iz) = 0.5*scratch(ix,iy,iz) + 0.25*(scratch(ix,iy-1,iz)+scratch(ix,iy+1,iz))
  150. end do
  151. end do
  152. end do
  153. call exchange_halo_r(array, &
  154. start_x, end_x, start_y, end_y, start_z, end_z, &
  155. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  156. !
  157. ! Desmoothing pass
  158. !
  159. do iy=start_y,end_y
  160. do ix=start_x+1,end_x-1
  161. do iz=start_z,end_z
  162. scratch(ix,iy,iz) = 1.52*array(ix,iy,iz) - 0.26*(array(ix-1,iy,iz)+array(ix+1,iy,iz))
  163. end do
  164. end do
  165. end do
  166. do iy=start_y+1,end_y-1
  167. do ix=start_x+1,end_x-1
  168. do iz=start_z,end_z
  169. array(ix,iy,iz) = 1.52*scratch(ix,iy,iz) - 0.26*(scratch(ix,iy-1,iz)+scratch(ix,iy+1,iz))
  170. end do
  171. end do
  172. end do
  173. call exchange_halo_r(array, &
  174. start_x, end_x, start_y, end_y, start_z, end_z, &
  175. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  176. end do
  177. ! Remove artificially negative values
  178. do iy=start_y,end_y
  179. do ix=start_x,end_x
  180. do iz=start_z,end_z
  181. if (array(ix,iy,iz) < 0. .and. orig_array(ix,iy,iz) >= 0.) then
  182. array(ix,iy,iz) = orig_array(ix,iy,iz)
  183. end if
  184. end do
  185. end do
  186. end do
  187. deallocate(scratch)
  188. deallocate(orig_array)
  189. end subroutine smth_desmth_special
  190. !
  191. ! Smoothing routines for E-grid, contributed by Matthew Pyle
  192. !
  193. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  194. ! Name: one_two_one_egrid
  195. !
  196. ! Purpose: Apply the 1-2-1 smoother from the MM5 program TERRAIN
  197. ! (found in smth121.F) to array.
  198. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  199. subroutine one_two_one_egrid(array, start_dom_x, end_dom_x, start_dom_y, end_dom_y, &
  200. start_x, end_x, start_y, end_y, start_z, end_z, npass, msgval, hflag)
  201. implicit none
  202. ! Arguments
  203. integer, intent(in) :: start_dom_x, start_dom_y, start_x, start_y, start_z
  204. integer, intent(in) :: end_dom_x, end_dom_y, end_x, end_y, end_z
  205. integer, intent(in) :: npass
  206. real, intent(in) :: msgval, hflag
  207. real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), intent(inout) :: array
  208. ! Local variables
  209. integer :: ix, iy, iz, ipass
  210. real, pointer, dimension(:,:,:) :: scratch
  211. integer, dimension(start_y:end_y) :: ihe, ihw, istart
  212. allocate(scratch(start_x:end_x, start_y:end_y, start_z:end_z))
  213. do iy=start_y,end_y
  214. if (hflag == 1.0) then
  215. ihe(iy) = abs(mod(iy+1,2))
  216. ihw(iy) = ihe(iy)-1
  217. else
  218. ! assign ive,ivw equivs to ihe,ihw
  219. ihe(iy) = abs(mod(iy,2))
  220. ihw(iy) = ihe(iy)-1
  221. end if
  222. end do
  223. do iy=start_y,end_y
  224. if (hflag == 1.0) then
  225. if (mod(iy,2) == 0) then
  226. istart(iy) = start_x
  227. else
  228. istart(iy) = start_x+1
  229. end if
  230. else ! v points
  231. if (abs(mod(iy,2)) == 1) then
  232. istart(iy) = start_x
  233. else
  234. istart(iy) = start_x+1
  235. end if
  236. end if
  237. end do
  238. do ipass=1,npass
  239. do iy=start_y,end_y
  240. do ix=start_x,end_x
  241. scratch(ix,iy,1) = array(ix,iy,1) ! for points used in 2nd computation but not defined in 1st computation
  242. end do
  243. end do
  244. ! SW-NE direction
  245. do iy=start_y+1,end_y-1
  246. do ix=istart(iy),end_x-1
  247. do iz=start_z,end_z
  248. if ( (msgval == 1.0 .and. array(ix,iy,iz) /= 0.) .or. msgval /= 1.0) then
  249. scratch(ix,iy,iz) = 0.50*array(ix,iy,iz)+ &
  250. 0.25*(array(ix+ihw(iy),iy-1,iz)+array(ix+ihe(iy),iy+1,iz))
  251. end if
  252. end do
  253. end do
  254. end do
  255. ! NW-SE direction
  256. do iy=start_y+1,end_y-1
  257. do ix=istart(iy),end_x-1
  258. do iz=start_z,end_z
  259. if ( (msgval == 1.0 .and. array(ix,iy,iz) /= 0.) .or. msgval /= 1.0) then
  260. array(ix,iy,iz) = 0.50*scratch(ix,iy,iz)+ &
  261. 0.25*(scratch(ix+ihe(iy),iy-1,iz)+scratch(ix+ihw(iy),iy+1,iz))
  262. end if
  263. end do
  264. end do
  265. end do
  266. call exchange_halo_r(array, &
  267. start_x, end_x, start_y, end_y, start_z, end_z, &
  268. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  269. end do
  270. deallocate(scratch)
  271. end subroutine one_two_one_egrid
  272. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  273. ! Name: smth_desmth_egrid_old
  274. !
  275. ! Purpose: Apply the smoother-desmoother for E grid
  276. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  277. subroutine smth_desmth_egrid_old(array, start_dom_x, end_dom_x, start_dom_y, end_dom_y, &
  278. start_x, end_x, start_y, end_y, start_z, end_z, npass, msgval, hflag)
  279. implicit none
  280. ! Arguments
  281. integer, intent(in) :: start_dom_x, start_dom_y, start_x, start_y, start_z
  282. integer, intent(in) :: end_dom_x, end_dom_y, end_x, end_y, end_z
  283. integer, intent(in) :: npass
  284. real, intent(in) :: msgval, hflag
  285. real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
  286. intent(inout) :: array
  287. ! Local variables
  288. integer :: ix, iy, iz, ipass
  289. real, pointer, dimension(:,:,:) :: scratch
  290. integer, dimension(start_y:end_y) :: ihe, ihw, istart
  291. real, parameter:: cenwgt = 1.52
  292. real, parameter:: endwgt = 0.13
  293. allocate(scratch(start_x:end_x, start_y:end_y, start_z:end_z))
  294. do iy=start_y,end_y
  295. if (hflag == 1.0) then
  296. ihe(iy) = abs(mod(iy+1,2))
  297. ihw(iy) = ihe(iy)-1
  298. else
  299. ! assign ive,ivw equivs to ihe,ihw
  300. ihe(iy) = abs(mod(iy,2))
  301. ihw(iy) = ihe(iy)-1
  302. end if
  303. end do
  304. do iy=start_y,end_y
  305. if (hflag == 1.0) then
  306. if (mod(iy,2) == 0) then
  307. istart(iy) = start_x
  308. else
  309. istart(iy) = start_x+1
  310. endif
  311. else ! v points
  312. if (abs(mod(iy,2)) == 1) then
  313. istart(iy) = start_x
  314. else
  315. istart(iy) = start_x+1
  316. endif
  317. endif
  318. end do
  319. do ipass=1,npass
  320. !
  321. ! Smoothing pass
  322. !
  323. do iy=start_y,end_y
  324. do ix=start_x,end_x
  325. scratch(ix,iy,1) = array(ix,iy,1)
  326. end do
  327. end do
  328. do iy=start_y+1,end_y-1
  329. do ix=istart(iy),end_x-1
  330. do iz=start_z,end_z
  331. if ( (msgval == 1.0 .and. array(ix,iy,iz) /= 0.) .or. msgval /= 1.0) then
  332. scratch(ix,iy,iz) = 0.50*array(ix,iy,iz)+ &
  333. 0.125*(array(ix+ihw(iy),iy-1,iz)+array(ix+ihe(iy),iy+1,iz)+ &
  334. array(ix+ihw(iy),iy+1,iz)+array(ix+ihe(iy),iy-1,iz))
  335. end if
  336. end do
  337. end do
  338. end do
  339. !
  340. ! Desmoothing pass
  341. !
  342. do iy=start_y+2,end_y-2
  343. do ix=istart(iy),end_x-1
  344. do iz=start_z,end_z
  345. if ( (msgval == 1.0 .and. scratch(ix,iy,iz) /= 0.) .or. msgval /= 1.0) then
  346. array(ix,iy,iz) = cenwgt*scratch(ix,iy,iz) - &
  347. endwgt*(scratch(ix+ihw(iy),iy-1,iz)+scratch(ix+ihe(iy),iy+1,iz) + &
  348. scratch(ix+ihw(iy),iy+1,iz)+scratch(ix+ihe(iy),iy-1,iz))
  349. end if
  350. end do
  351. end do
  352. end do
  353. end do
  354. deallocate(scratch)
  355. end subroutine smth_desmth_egrid_old
  356. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  357. ! Name: smth_desmth_egrid
  358. !
  359. ! Purpose: Apply the smoother-desmoother for E grid
  360. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  361. subroutine smth_desmth_egrid(array, start_dom_x, end_dom_x, start_dom_y, end_dom_y, &
  362. start_x, end_x, start_y, end_y, start_z, end_z, npass, msgval, hflag)
  363. implicit none
  364. ! Arguments
  365. integer, intent(in) :: start_dom_x, start_dom_y, start_x, start_y, start_z
  366. integer, intent(in) :: end_dom_x, end_dom_y, end_x, end_y, end_z
  367. integer, intent(in) :: npass
  368. real, intent(in) :: msgval, hflag
  369. real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
  370. intent(inout) :: array
  371. ! Local variables
  372. integer :: ix, iy, iz, ipass
  373. real, pointer, dimension(:,:,:) :: scratch
  374. integer, dimension(start_y:end_y) :: ihe, ihw, istart
  375. real, parameter :: cenwgt = 1.52
  376. real, parameter :: endwgt = 0.26
  377. allocate(scratch(start_x:end_x, start_y:end_y, start_z:end_z))
  378. do iy=start_y,end_y
  379. if (hflag .eq. 1.0) then
  380. ihe(iy)=abs(mod(iy+1,2))
  381. ihw(iy)=ihe(iy)-1
  382. ! assign ive,ivw equivs to ihe,ihw
  383. else
  384. ihe(iy)=abs(mod(iy,2))
  385. ihw(iy)=ihe(iy)-1
  386. end if
  387. end do
  388. do iy=start_y,end_y
  389. if (hflag .eq. 1.0) then
  390. if (mod(iy,2) .eq. 0) then
  391. istart(iy)=start_x
  392. else
  393. istart(iy)=start_x+1
  394. endif
  395. else ! v points
  396. if (abs(mod(iy,2)) .eq. 1) then
  397. istart(iy)=start_x
  398. else
  399. istart(iy)=start_x+1
  400. end if
  401. end if
  402. end do
  403. do ipass=1,npass
  404. !
  405. ! Smoothing pass
  406. !
  407. do iy=start_y,end_y
  408. do ix=start_x,end_x
  409. scratch(ix,iy,1)=array(ix,iy,1) ! for points used in 2nd computation but
  410. ! not defined in 1st
  411. end do
  412. end do
  413. ! SW-NE direction
  414. do iy=start_y+1,end_y-1
  415. do ix=istart(iy),end_x-1
  416. do iz=start_z,end_z
  417. if ( (msgval .eq. 1.0 .and. array(ix,iy,iz) .ne. 0.) .or. msgval .ne. 1.0) then
  418. scratch(ix,iy,iz) = 0.50*array(ix,iy,iz)+ &
  419. 0.25*(array(ix+ihw(iy),iy-1,iz)+array(ix+ihe(iy),iy+1,iz))
  420. end if
  421. end do
  422. end do
  423. end do
  424. ! NW-SE direction
  425. do iy=start_y+1,end_y-1
  426. do ix=istart(iy),end_x-1
  427. do iz=start_z,end_z
  428. if ( (msgval .eq. 1.0 .and. array(ix,iy,iz) .ne. 0.) .or. msgval .ne. 1.0) then
  429. array(ix,iy,iz) = 0.50*scratch(ix,iy,iz)+ &
  430. 0.25*(scratch(ix+ihe(iy),iy-1,iz)+scratch(ix+ihw(iy),iy+1,iz))
  431. end if
  432. end do
  433. end do
  434. end do
  435. call exchange_halo_r(array, &
  436. start_x, end_x, start_y, end_y, start_z, end_z, &
  437. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  438. !
  439. ! Desmoothing pass
  440. !
  441. ! SW-NE direction
  442. do iy=start_y+2,end_y-2
  443. do ix=istart(iy),end_x-1
  444. do iz=start_z,end_z
  445. if ( (msgval .eq. 1.0 .and. array(ix,iy,iz) .ne. 0.) .or. msgval .ne. 1.0) then
  446. scratch(ix,iy,iz) = cenwgt*array(ix,iy,iz) - &
  447. endwgt*(array(ix+ihw(iy),iy-1,iz)+array(ix+ihe(iy),iy+1,iz))
  448. end if
  449. end do
  450. end do
  451. end do
  452. ! NW-SE direction
  453. do iy=start_y+2,end_y-2
  454. do ix=istart(iy),end_x-1
  455. do iz=start_z,end_z
  456. if ( (msgval .eq. 1.0 .and. array(ix,iy,iz) .ne. 0.) .or. msgval .ne. 1.0) then
  457. array(ix,iy,iz) = cenwgt*scratch(ix,iy,iz) - &
  458. endwgt*(scratch(ix+ihe(iy),iy-1,iz)+scratch(ix+ihw(iy),iy+1,iz))
  459. end if
  460. end do
  461. end do
  462. end do
  463. call exchange_halo_r(array, &
  464. start_x, end_x, start_y, end_y, start_z, end_z, &
  465. start_dom_x, end_dom_x, start_dom_y, end_dom_y, start_z, end_z)
  466. end do
  467. deallocate(scratch)
  468. end subroutine smth_desmth_egrid
  469. end module smooth_module