solmat.F90 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. MODULE solmat
  2. !!======================================================================
  3. !! *** MODULE solmat ***
  4. !! solver : construction of the matrix
  5. !!======================================================================
  6. !! History : 1.0 ! 1988-04 (G. Madec) Original code
  7. !! ! 1993-03 (M. Guyon) symetrical conditions
  8. !! ! 1993-06 (M. Guyon) suppress pointers
  9. !! ! 1996-05 (G. Madec) merge sor and pcg formulations
  10. !! ! 1996-11 (A. Weaver) correction to preconditioning
  11. !! NEMO 1.0 ! 1902-08 (G. Madec) F90: Free form
  12. !! - ! 1902-11 (C. Talandier, A-M. Treguier) Free surface & Open boundaries
  13. !! 2.0 ! 2005-09 (R. Benshila) add sol_exd for extra outer halo
  14. !! - ! 2005-11 (V. Garnier) Surface pressure gradient organization
  15. !! 3.2 ! 2009-06 (S. Masson) distributed restart using iom
  16. !! - ! 2009-07 (R. Benshila) suppression of rigid-lid option
  17. !! 3.3 ! 2010-09 (D. Storkey) update for BDY module.
  18. !!----------------------------------------------------------------------
  19. !!----------------------------------------------------------------------
  20. !! sol_mat : Construction of the matrix of used by the elliptic solvers
  21. !! sol_exd :
  22. !!----------------------------------------------------------------------
  23. USE oce ! ocean dynamics and active tracers
  24. USE dom_oce ! ocean space and time domain
  25. USE sol_oce ! ocean solver
  26. USE phycst ! physical constants
  27. USE bdy_oce ! unstructured open boundary conditions
  28. USE lbclnk ! lateral boudary conditions
  29. USE lib_mpp ! distributed memory computing
  30. USE c1d ! 1D vertical configuration
  31. USE in_out_manager ! I/O manager
  32. USE timing ! timing
  33. IMPLICIT NONE
  34. PRIVATE
  35. PUBLIC sol_mat ! routine called by inisol.F90
  36. !!----------------------------------------------------------------------
  37. !! NEMO/OPA 3.3 , NEMO Consortium (2010)
  38. !! $Id: solmat.F90 4328 2013-12-06 10:25:13Z davestorkey $
  39. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  40. !!----------------------------------------------------------------------
  41. CONTAINS
  42. SUBROUTINE sol_mat( kt )
  43. !!----------------------------------------------------------------------
  44. !! *** ROUTINE sol_mat ***
  45. !!
  46. !! ** Purpose : Construction of the matrix of used by the elliptic
  47. !! solvers (either sor or pcg methods).
  48. !!
  49. !! ** Method : The matrix is built for the divergence of the transport
  50. !! system. a diagonal preconditioning matrix is also defined.
  51. !!
  52. !! ** Action : - gcp : extra-diagonal elements of the matrix
  53. !! - gcdmat : preconditioning matrix (diagonal elements)
  54. !! - gcdprc : inverse of the preconditioning matrix
  55. !!----------------------------------------------------------------------
  56. INTEGER, INTENT(in) :: kt
  57. !!
  58. INTEGER :: ji, jj ! dummy loop indices
  59. REAL(wp) :: zcoefs, zcoefw, zcoefe, zcoefn ! temporary scalars
  60. REAL(wp) :: z2dt, zcoef
  61. !!----------------------------------------------------------------------
  62. !
  63. IF( nn_timing == 1 ) CALL timing_start('sol_mat')
  64. !
  65. ! 1. Construction of the matrix
  66. ! -----------------------------
  67. zcoef = 0.e0 ! initialize to zero
  68. gcp(:,:,1) = 0.e0
  69. gcp(:,:,2) = 0.e0
  70. gcp(:,:,3) = 0.e0
  71. gcp(:,:,4) = 0.e0
  72. !
  73. gcdprc(:,:) = 0.e0
  74. gcdmat(:,:) = 0.e0
  75. !
  76. IF( neuler == 0 .AND. kt == nit000 ) THEN ; z2dt = rdt
  77. ELSE ; z2dt = 2. * rdt
  78. ENDIF
  79. #if defined key_dynspg_flt && ! defined key_bdy
  80. DO jj = 2, jpjm1 ! matrix of free surface elliptic system
  81. DO ji = 2, jpim1
  82. zcoef = z2dt * z2dt * grav * bmask(ji,jj)
  83. zcoefs = -zcoef * hv(ji ,jj-1) * e1v(ji ,jj-1) / e2v(ji ,jj-1) ! south coefficient
  84. zcoefw = -zcoef * hu(ji-1,jj ) * e2u(ji-1,jj ) / e1u(ji-1,jj ) ! west coefficient
  85. zcoefe = -zcoef * hu(ji ,jj ) * e2u(ji ,jj ) / e1u(ji ,jj ) ! east coefficient
  86. zcoefn = -zcoef * hv(ji ,jj ) * e1v(ji ,jj ) / e2v(ji ,jj ) ! north coefficient
  87. gcp(ji,jj,1) = zcoefs
  88. gcp(ji,jj,2) = zcoefw
  89. gcp(ji,jj,3) = zcoefe
  90. gcp(ji,jj,4) = zcoefn
  91. gcdmat(ji,jj) = e1t(ji,jj) * e2t(ji,jj) * bmask(ji,jj) & ! diagonal coefficient
  92. & - zcoefs -zcoefw -zcoefe -zcoefn
  93. END DO
  94. END DO
  95. # elif defined key_dynspg_flt && defined key_bdy
  96. ! defined gcdmat in the case of unstructured open boundaries
  97. DO jj = 2, jpjm1
  98. DO ji = 2, jpim1
  99. zcoef = z2dt * z2dt * grav * bmask(ji,jj)
  100. ! south coefficient
  101. zcoefs = -zcoef * hv(ji,jj-1) * e1v(ji,jj-1)/e2v(ji,jj-1)
  102. zcoefs = zcoefs * bdyvmask(ji,jj-1)
  103. gcp(ji,jj,1) = zcoefs
  104. ! west coefficient
  105. zcoefw = -zcoef * hu(ji-1,jj) * e2u(ji-1,jj)/e1u(ji-1,jj)
  106. zcoefw = zcoefw * bdyumask(ji-1,jj)
  107. gcp(ji,jj,2) = zcoefw
  108. ! east coefficient
  109. zcoefe = -zcoef * hu(ji,jj) * e2u(ji,jj)/e1u(ji,jj)
  110. zcoefe = zcoefe * bdyumask(ji,jj)
  111. gcp(ji,jj,3) = zcoefe
  112. ! north coefficient
  113. zcoefn = -zcoef * hv(ji,jj) * e1v(ji,jj)/e2v(ji,jj)
  114. zcoefn = zcoefn * bdyvmask(ji,jj)
  115. gcp(ji,jj,4) = zcoefn
  116. ! diagonal coefficient
  117. gcdmat(ji,jj) = e1t(ji,jj)*e2t(ji,jj)*bmask(ji,jj) &
  118. - zcoefs -zcoefw -zcoefe -zcoefn
  119. END DO
  120. END DO
  121. #endif
  122. IF( .NOT. Agrif_Root() ) THEN
  123. !
  124. IF( nbondi == -1 .OR. nbondi == 2 ) bmask(2 ,: ) = 0.e0
  125. IF( nbondi == 1 .OR. nbondi == 2 ) bmask(nlci-1,: ) = 0.e0
  126. IF( nbondj == -1 .OR. nbondj == 2 ) bmask(: ,2 ) = 0.e0
  127. IF( nbondj == 1 .OR. nbondj == 2 ) bmask(: ,nlcj-1) = 0.e0
  128. !
  129. DO jj = 2, jpjm1
  130. DO ji = 2, jpim1
  131. zcoef = z2dt * z2dt * grav * bmask(ji,jj)
  132. ! south coefficient
  133. IF( ( nbondj == -1 .OR. nbondj == 2 ) .AND. ( jj == 3 ) ) THEN
  134. zcoefs = -zcoef * hv(ji,jj-1) * e1v(ji,jj-1)/e2v(ji,jj-1)*(1.-vmask(ji,jj-1,1))
  135. ELSE
  136. zcoefs = -zcoef * hv(ji,jj-1) * e1v(ji,jj-1)/e2v(ji,jj-1)
  137. END IF
  138. gcp(ji,jj,1) = zcoefs
  139. !
  140. ! west coefficient
  141. IF( ( nbondi == -1 .OR. nbondi == 2 ) .AND. ( ji == 3 ) ) THEN
  142. zcoefw = -zcoef * hu(ji-1,jj) * e2u(ji-1,jj)/e1u(ji-1,jj)*(1.-umask(ji-1,jj,1))
  143. ELSE
  144. zcoefw = -zcoef * hu(ji-1,jj) * e2u(ji-1,jj)/e1u(ji-1,jj)
  145. END IF
  146. gcp(ji,jj,2) = zcoefw
  147. !
  148. ! east coefficient
  149. IF( ( nbondi == 1 .OR. nbondi == 2 ) .AND. ( ji == nlci-2 ) ) THEN
  150. zcoefe = -zcoef * hu(ji,jj) * e2u(ji,jj)/e1u(ji,jj)*(1.-umask(ji,jj,1))
  151. ELSE
  152. zcoefe = -zcoef * hu(ji,jj) * e2u(ji,jj)/e1u(ji,jj)
  153. END IF
  154. gcp(ji,jj,3) = zcoefe
  155. !
  156. ! north coefficient
  157. IF( ( nbondj == 1 .OR. nbondj == 2 ) .AND. ( jj == nlcj-2 ) ) THEN
  158. zcoefn = -zcoef * hv(ji,jj) * e1v(ji,jj)/e2v(ji,jj)*(1.-vmask(ji,jj,1))
  159. ELSE
  160. zcoefn = -zcoef * hv(ji,jj) * e1v(ji,jj)/e2v(ji,jj)
  161. END IF
  162. gcp(ji,jj,4) = zcoefn
  163. !
  164. ! diagonal coefficient
  165. gcdmat(ji,jj) = e1t(ji,jj)*e2t(ji,jj)*bmask(ji,jj) &
  166. & - zcoefs -zcoefw -zcoefe -zcoefn
  167. END DO
  168. END DO
  169. !
  170. ENDIF
  171. ! 2. Boundary conditions
  172. ! ----------------------
  173. ! Cyclic east-west boundary conditions
  174. ! ji=2 is the column east of ji=jpim1 and reciprocally,
  175. ! ji=jpim1 is the column west of ji=2
  176. ! all the coef are already set to zero as bmask is initialized to
  177. ! zero for ji=1 and ji=jpj in dommsk.
  178. ! Symetrical conditions
  179. ! free surface: no specific action
  180. ! bsf system: n-s gradient of bsf = 0 along j=2 (perhaps a bug !!!!!!)
  181. ! the diagonal coefficient of the southern grid points must be modify to
  182. ! account for the existence of the south symmetric bassin.
  183. ! North fold boundary condition
  184. ! all the coef are already set to zero as bmask is initialized to
  185. ! zero on duplicated lignes and portion of lignes
  186. ! 3. Preconditioned matrix
  187. ! ------------------------
  188. ! SOR and PCG solvers
  189. IF( lk_c1d ) CALL lbc_lnk( gcdmat, 'T', 1._wp ) ! 1D case bmask =/0 but gcdmat not define everywhere
  190. DO jj = 1, jpj
  191. DO ji = 1, jpi
  192. IF( bmask(ji,jj) /= 0.e0 ) gcdprc(ji,jj) = 1.e0 / gcdmat(ji,jj)
  193. END DO
  194. END DO
  195. gcp(:,:,1) = gcp(:,:,1) * gcdprc(:,:)
  196. gcp(:,:,2) = gcp(:,:,2) * gcdprc(:,:)
  197. gcp(:,:,3) = gcp(:,:,3) * gcdprc(:,:)
  198. gcp(:,:,4) = gcp(:,:,4) * gcdprc(:,:)
  199. IF( nn_solv == 2 ) gccd(:,:) = rn_sor * gcp(:,:,2)
  200. IF( nn_solv == 2 .AND. MAX( jpr2di, jpr2dj ) > 0) THEN
  201. CALL lbc_lnk_e( gcp (:,:,1), c_solver_pt, 1., jpr2di, jpr2dj ) ! lateral boundary conditions
  202. CALL lbc_lnk_e( gcp (:,:,2), c_solver_pt, 1., jpr2di, jpr2dj ) ! lateral boundary conditions
  203. CALL lbc_lnk_e( gcp (:,:,3), c_solver_pt, 1., jpr2di, jpr2dj ) ! lateral boundary conditions
  204. CALL lbc_lnk_e( gcp (:,:,4), c_solver_pt, 1., jpr2di, jpr2dj ) ! lateral boundary conditions
  205. CALL lbc_lnk_e( gcdprc(:,:) , c_solver_pt, 1., jpr2di, jpr2dj ) ! lateral boundary conditions
  206. CALL lbc_lnk_e( gcdmat(:,:) , c_solver_pt, 1., jpr2di, jpr2dj ) ! lateral boundary conditions
  207. IF( npolj /= 0 ) CALL sol_exd( gcp , c_solver_pt ) ! switch northernelements
  208. END IF
  209. ! 4. Initialization the arrays used in pcg
  210. ! ----------------------------------------
  211. gcb (:,:) = 0.e0
  212. gcr (:,:) = 0.e0
  213. gcdes(:,:) = 0.e0
  214. gccd (:,:) = 0.e0
  215. !
  216. IF( nn_timing == 1 ) CALL timing_stop('sol_mat')
  217. !
  218. END SUBROUTINE sol_mat
  219. SUBROUTINE sol_exd( pt3d, cd_type )
  220. !!----------------------------------------------------------------------
  221. !! *** routine sol_exd ***
  222. !!
  223. !! ** Purpose : Reorder gcb coefficient on the extra outer halo
  224. !! at north fold in case of T or F pivot
  225. !!
  226. !! ** Method : Perform a circular permutation of the coefficients on
  227. !! the total area strictly above the pivot point,
  228. !! and on the semi-row of the pivot point
  229. !!----------------------------------------------------------------------
  230. CHARACTER(len=1) , INTENT( in ) :: cd_type ! define the nature of pt2d array grid-points
  231. ! ! = T , U , V , F , W
  232. ! ! = S : T-point, north fold treatment
  233. ! ! = G : F-point, north fold treatment
  234. ! ! = I : sea-ice velocity at F-point with index shift
  235. REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj,4), INTENT(inout) :: pt3d ! 2D field to be treated
  236. !!
  237. INTEGER :: ji, jk ! dummy loop indices
  238. INTEGER :: iloc ! local integers
  239. REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: ztab ! workspace allocated one for all
  240. !!----------------------------------------------------------------------
  241. IF( .NOT. ALLOCATED( ztab ) ) THEN
  242. ALLOCATE( ztab(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj,4), STAT=iloc )
  243. IF( lk_mpp ) CALL mpp_sum ( iloc )
  244. IF( iloc /= 0 ) CALL ctl_stop('STOP', 'sol_exd: failed to allocate array')
  245. ENDIF
  246. ztab = pt3d
  247. SELECT CASE ( npolj ) ! north fold type
  248. !
  249. CASE ( 3 , 4 ) !== T pivot ==!
  250. iloc = jpiglo/2 +1
  251. !
  252. SELECT CASE ( cd_type )
  253. !
  254. CASE ( 'T' , 'U', 'W' )
  255. DO jk = 1, 4
  256. DO ji = 1-jpr2di, nlci+jpr2di
  257. pt3d(ji,nlcj:nlcj+jpr2dj,jk) = ztab(ji,nlcj:nlcj+jpr2dj,jk+3-2*MOD(jk+3,4))
  258. END DO
  259. END DO
  260. DO jk =1, 4
  261. DO ji = nlci+jpr2di, 1-jpr2di, -1
  262. IF( ( ji .LT. mi0(iloc) .AND. mi0(iloc) /= 1 ) &
  263. & .OR. ( mi0(iloc) == jpi+1 ) ) EXIT
  264. pt3d(ji,nlcj-1,jk) = ztab(ji,nlcj-1,jk+3-2*MOD(jk+3,4))
  265. END DO
  266. END DO
  267. !
  268. CASE ( 'F' , 'I', 'V' )
  269. DO jk =1, 4
  270. DO ji = 1-jpr2di, nlci+jpr2di
  271. pt3d(ji,nlcj-1:nlcj+jpr2dj,jk) = ztab(ji,nlcj-1:nlcj+jpr2dj,jk+3-2*MOD(jk+3,4))
  272. END DO
  273. END DO
  274. !
  275. END SELECT ! cd_type
  276. !
  277. CASE ( 5 , 6 ) !== F pivot ==!
  278. iloc=jpiglo/2
  279. !
  280. SELECT CASE (cd_type )
  281. !
  282. CASE ( 'T' , 'U', 'W')
  283. DO jk =1, 4
  284. DO ji = 1-jpr2di, nlci+jpr2di
  285. pt3d(ji,nlcj:nlcj+jpr2dj,jk) = ztab(ji,nlcj:nlcj+jpr2dj,jk+3-2*MOD(jk+3,4))
  286. END DO
  287. END DO
  288. !
  289. CASE ( 'F' , 'I', 'V' )
  290. DO jk =1, 4
  291. DO ji = 1-jpr2di, nlci+jpr2di
  292. pt3d(ji,nlcj:nlcj+jpr2dj,jk) = ztab(ji,nlcj:nlcj+jpr2dj,jk+3-2*MOD(jk+3,4))
  293. END DO
  294. END DO
  295. DO jk =1, 4
  296. DO ji = nlci+jpr2di, 1-jpr2di, -1
  297. IF( ( ji .LT. mi0(iloc) .AND. mi0(iloc) /= 1 ) .OR. ( mi0(iloc) == jpi+1 ) ) EXIT
  298. pt3d(ji,nlcj-1,jk) = ztab(ji,nlcj-1,jk+3-2*MOD(jk+3,4))
  299. END DO
  300. END DO
  301. !
  302. END SELECT ! cd_type
  303. !
  304. END SELECT ! npolj
  305. !
  306. END SUBROUTINE sol_exd
  307. !!======================================================================
  308. END MODULE solmat