bdyini.F90 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774
  1. MODULE bdyini
  2. !!======================================================================
  3. !! *** MODULE bdyini ***
  4. !! Unstructured open boundaries : initialisation
  5. !!======================================================================
  6. !! History : 1.0 ! 2005-01 (J. Chanut, A. Sellar) Original code
  7. !! - ! 2007-01 (D. Storkey) Update to use IOM module
  8. !! - ! 2007-01 (D. Storkey) Tidal forcing
  9. !! 3.0 ! 2008-04 (NEMO team) add in the reference version
  10. !! 3.3 ! 2010-09 (E.O'Dea) updates for Shelf configurations
  11. !! 3.3 ! 2010-09 (D.Storkey) add ice boundary conditions
  12. !! 3.4 ! 2011 (D. Storkey) rewrite in preparation for OBC-BDY merge
  13. !! 3.4 ! 2012 (J. Chanut) straight open boundary case update
  14. !! 3.5 ! 2012 (S. Mocavero, I. Epicoco) Updates for the
  15. !! optimization of BDY communications
  16. !!----------------------------------------------------------------------
  17. #if defined key_bdy
  18. !!----------------------------------------------------------------------
  19. !! 'key_bdy' Unstructured Open Boundary Conditions
  20. !!----------------------------------------------------------------------
  21. !! bdy_init : Initialization of unstructured open boundaries
  22. !!----------------------------------------------------------------------
  23. USE wrk_nemo ! Memory Allocation
  24. USE timing ! Timing
  25. USE oce ! ocean dynamics and tracers variables
  26. USE dom_oce ! ocean space and time domain
  27. USE bdy_oce ! unstructured open boundary conditions
  28. USE in_out_manager ! I/O units
  29. USE lbclnk ! ocean lateral boundary conditions (or mpp link)
  30. USE lib_mpp ! for mpp_sum
  31. USE iom ! I/O
  32. USE sbctide, ONLY: lk_tide ! Tidal forcing or not
  33. USE phycst, ONLY: rday
  34. IMPLICIT NONE
  35. PRIVATE
  36. PUBLIC bdy_init ! routine called in nemo_init
  37. INTEGER, PARAMETER :: jp_nseg = 100
  38. INTEGER, PARAMETER :: nrimmax = 20 ! maximum rimwidth in structured
  39. ! open boundary data files
  40. ! Straight open boundary segment parameters:
  41. INTEGER :: nbdysege, nbdysegw, nbdysegn, nbdysegs
  42. INTEGER, DIMENSION(jp_nseg) :: jpieob, jpjedt, jpjeft, npckge
  43. INTEGER, DIMENSION(jp_nseg) :: jpiwob, jpjwdt, jpjwft, npckgw
  44. INTEGER, DIMENSION(jp_nseg) :: jpjnob, jpindt, jpinft, npckgn
  45. INTEGER, DIMENSION(jp_nseg) :: jpjsob, jpisdt, jpisft, npckgs
  46. !!----------------------------------------------------------------------
  47. !! NEMO/OPA 4.0 , NEMO Consortium (2011)
  48. !! $Id: bdyini.F90 4990 2014-12-15 16:42:49Z timgraham $
  49. !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
  50. !!----------------------------------------------------------------------
  51. CONTAINS
  52. SUBROUTINE bdy_init
  53. !!----------------------------------------------------------------------
  54. !! *** ROUTINE bdy_init ***
  55. !!
  56. !! ** Purpose : Initialization of the dynamics and tracer fields with
  57. !! unstructured open boundaries.
  58. !!
  59. !! ** Method : Read initialization arrays (mask, indices) to identify
  60. !! an unstructured open boundary
  61. !!
  62. !! ** Input : bdy_init.nc, input file for unstructured open boundaries
  63. !!----------------------------------------------------------------------
  64. ! namelist variables
  65. !-------------------
  66. CHARACTER(LEN=80),DIMENSION(jpbgrd) :: clfile
  67. CHARACTER(LEN=1) :: ctypebdy
  68. INTEGER :: nbdyind, nbdybeg, nbdyend
  69. ! local variables
  70. !-------------------
  71. INTEGER :: ib_bdy, ii, ij, ik, igrd, ib, ir, iseg ! dummy loop indices
  72. INTEGER :: icount, icountr, ibr_max, ilen1, ibm1 ! local integers
  73. INTEGER :: iwe, ies, iso, ino, inum, id_dummy ! - -
  74. INTEGER :: igrd_start, igrd_end, jpbdta ! - -
  75. INTEGER :: jpbdtau, jpbdtas ! - -
  76. INTEGER :: ib_bdy1, ib_bdy2, ib1, ib2 ! - -
  77. INTEGER :: i_offset, j_offset ! - -
  78. INTEGER, POINTER :: nbi, nbj, nbr ! short cuts
  79. REAL(wp), POINTER :: flagu, flagv ! - -
  80. REAL(wp), POINTER, DIMENSION(:,:) :: pmask ! pointer to 2D mask fields
  81. REAL(wp) :: zefl, zwfl, znfl, zsfl ! local scalars
  82. INTEGER, DIMENSION (2) :: kdimsz
  83. INTEGER, DIMENSION(jpbgrd,jp_bdy) :: nblendta ! Length of index arrays
  84. INTEGER, ALLOCATABLE, DIMENSION(:,:,:) :: nbidta, nbjdta ! Index arrays: i and j indices of bdy dta
  85. INTEGER, ALLOCATABLE, DIMENSION(:,:,:) :: nbrdta ! Discrete distance from rim points
  86. CHARACTER(LEN=1),DIMENSION(jpbgrd) :: cgrid
  87. INTEGER :: com_east, com_west, com_south, com_north ! Flags for boundaries sending
  88. INTEGER :: com_east_b, com_west_b, com_south_b, com_north_b ! Flags for boundaries receiving
  89. INTEGER :: iw_b(4), ie_b(4), is_b(4), in_b(4) ! Arrays for neighbours coordinates
  90. REAL(wp), POINTER, DIMENSION(:,:) :: zfmask ! temporary fmask array excluding coastal boundary condition (shlat)
  91. !!
  92. NAMELIST/nambdy/ nb_bdy, ln_coords_file, cn_coords_file, &
  93. & ln_mask_file, cn_mask_file, cn_dyn2d, nn_dyn2d_dta, &
  94. & cn_dyn3d, nn_dyn3d_dta, cn_tra, nn_tra_dta, &
  95. & ln_tra_dmp, ln_dyn3d_dmp, rn_time_dmp, rn_time_dmp_out, &
  96. & cn_ice_lim, nn_ice_lim_dta, &
  97. & rn_ice_tem, rn_ice_sal, rn_ice_age, &
  98. & ln_vol, nn_volctl, nn_rimwidth
  99. !!
  100. NAMELIST/nambdy_index/ ctypebdy, nbdyind, nbdybeg, nbdyend
  101. INTEGER :: ios ! Local integer output status for namelist read
  102. !!----------------------------------------------------------------------
  103. IF( nn_timing == 1 ) CALL timing_start('bdy_init')
  104. IF(lwp) WRITE(numout,*)
  105. IF(lwp) WRITE(numout,*) 'bdy_init : initialization of open boundaries'
  106. IF(lwp) WRITE(numout,*) '~~~~~~~~'
  107. !
  108. IF( jperio /= 0 ) CALL ctl_stop( 'Cyclic or symmetric,', &
  109. & ' and general open boundary condition are not compatible' )
  110. cgrid= (/'t','u','v'/)
  111. ! ------------------------
  112. ! Read namelist parameters
  113. ! ------------------------
  114. REWIND( numnam_ref ) ! Namelist nambdy in reference namelist :Unstructured open boundaries
  115. READ ( numnam_ref, nambdy, IOSTAT = ios, ERR = 901)
  116. 901 IF( ios /= 0 ) CALL ctl_nam ( ios , 'nambdy in reference namelist', lwp )
  117. REWIND( numnam_cfg ) ! Namelist nambdy in configuration namelist :Unstructured open boundaries
  118. READ ( numnam_cfg, nambdy, IOSTAT = ios, ERR = 902 )
  119. 902 IF( ios /= 0 ) CALL ctl_nam ( ios , 'nambdy in configuration namelist', lwp )
  120. IF(lwm) WRITE ( numond, nambdy )
  121. ! -----------------------------------------
  122. ! Check and write out namelist parameters
  123. ! -----------------------------------------
  124. ! ! control prints
  125. IF(lwp) WRITE(numout,*) ' nambdy'
  126. IF( nb_bdy .eq. 0 ) THEN
  127. IF(lwp) WRITE(numout,*) 'nb_bdy = 0, NO OPEN BOUNDARIES APPLIED.'
  128. ELSE
  129. IF(lwp) WRITE(numout,*) 'Number of open boundary sets : ',nb_bdy
  130. ENDIF
  131. DO ib_bdy = 1,nb_bdy
  132. IF(lwp) WRITE(numout,*) ' '
  133. IF(lwp) WRITE(numout,*) '------ Open boundary data set ',ib_bdy,'------'
  134. IF( ln_coords_file(ib_bdy) ) THEN
  135. IF(lwp) WRITE(numout,*) 'Boundary definition read from file '//TRIM(cn_coords_file(ib_bdy))
  136. ELSE
  137. IF(lwp) WRITE(numout,*) 'Boundary defined in namelist.'
  138. ENDIF
  139. IF(lwp) WRITE(numout,*)
  140. IF(lwp) WRITE(numout,*) 'Boundary conditions for barotropic solution: '
  141. SELECT CASE( cn_dyn2d(ib_bdy) )
  142. CASE('none')
  143. IF(lwp) WRITE(numout,*) ' no open boundary condition'
  144. dta_bdy(ib_bdy)%ll_ssh = .false.
  145. dta_bdy(ib_bdy)%ll_u2d = .false.
  146. dta_bdy(ib_bdy)%ll_v2d = .false.
  147. CASE('frs')
  148. IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme'
  149. dta_bdy(ib_bdy)%ll_ssh = .false.
  150. dta_bdy(ib_bdy)%ll_u2d = .true.
  151. dta_bdy(ib_bdy)%ll_v2d = .true.
  152. CASE('flather')
  153. IF(lwp) WRITE(numout,*) ' Flather radiation condition'
  154. dta_bdy(ib_bdy)%ll_ssh = .true.
  155. dta_bdy(ib_bdy)%ll_u2d = .true.
  156. dta_bdy(ib_bdy)%ll_v2d = .true.
  157. CASE('orlanski')
  158. IF(lwp) WRITE(numout,*) ' Orlanski (fully oblique) radiation condition with adaptive nudging'
  159. dta_bdy(ib_bdy)%ll_ssh = .false.
  160. dta_bdy(ib_bdy)%ll_u2d = .true.
  161. dta_bdy(ib_bdy)%ll_v2d = .true.
  162. CASE('orlanski_npo')
  163. IF(lwp) WRITE(numout,*) ' Orlanski (NPO) radiation condition with adaptive nudging'
  164. dta_bdy(ib_bdy)%ll_ssh = .false.
  165. dta_bdy(ib_bdy)%ll_u2d = .true.
  166. dta_bdy(ib_bdy)%ll_v2d = .true.
  167. CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for cn_dyn2d' )
  168. END SELECT
  169. IF( cn_dyn2d(ib_bdy) /= 'none' ) THEN
  170. SELECT CASE( nn_dyn2d_dta(ib_bdy) ) !
  171. CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data'
  172. CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file'
  173. CASE( 2 ) ; IF(lwp) WRITE(numout,*) ' tidal harmonic forcing taken from file'
  174. CASE( 3 ) ; IF(lwp) WRITE(numout,*) ' boundary data AND tidal harmonic forcing taken from files'
  175. CASE DEFAULT ; CALL ctl_stop( 'nn_dyn2d_dta must be between 0 and 3' )
  176. END SELECT
  177. IF (( nn_dyn2d_dta(ib_bdy) .ge. 2 ).AND.(.NOT.lk_tide)) THEN
  178. CALL ctl_stop( 'You must activate key_tide to add tidal forcing at open boundaries' )
  179. ENDIF
  180. ENDIF
  181. IF(lwp) WRITE(numout,*)
  182. IF(lwp) WRITE(numout,*) 'Boundary conditions for baroclinic velocities: '
  183. SELECT CASE( cn_dyn3d(ib_bdy) )
  184. CASE('none')
  185. IF(lwp) WRITE(numout,*) ' no open boundary condition'
  186. dta_bdy(ib_bdy)%ll_u3d = .false.
  187. dta_bdy(ib_bdy)%ll_v3d = .false.
  188. CASE('frs')
  189. IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme'
  190. dta_bdy(ib_bdy)%ll_u3d = .true.
  191. dta_bdy(ib_bdy)%ll_v3d = .true.
  192. CASE('specified')
  193. IF(lwp) WRITE(numout,*) ' Specified value'
  194. dta_bdy(ib_bdy)%ll_u3d = .true.
  195. dta_bdy(ib_bdy)%ll_v3d = .true.
  196. CASE('zero')
  197. IF(lwp) WRITE(numout,*) ' Zero baroclinic velocities (runoff case)'
  198. dta_bdy(ib_bdy)%ll_u3d = .false.
  199. dta_bdy(ib_bdy)%ll_v3d = .false.
  200. CASE('orlanski')
  201. IF(lwp) WRITE(numout,*) ' Orlanski (fully oblique) radiation condition with adaptive nudging'
  202. dta_bdy(ib_bdy)%ll_u3d = .true.
  203. dta_bdy(ib_bdy)%ll_v3d = .true.
  204. CASE('orlanski_npo')
  205. IF(lwp) WRITE(numout,*) ' Orlanski (NPO) radiation condition with adaptive nudging'
  206. dta_bdy(ib_bdy)%ll_u3d = .true.
  207. dta_bdy(ib_bdy)%ll_v3d = .true.
  208. CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for cn_dyn3d' )
  209. END SELECT
  210. IF( cn_dyn3d(ib_bdy) /= 'none' ) THEN
  211. SELECT CASE( nn_dyn3d_dta(ib_bdy) ) !
  212. CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data'
  213. CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file'
  214. CASE DEFAULT ; CALL ctl_stop( 'nn_dyn3d_dta must be 0 or 1' )
  215. END SELECT
  216. ENDIF
  217. IF ( ln_dyn3d_dmp(ib_bdy) ) THEN
  218. IF ( cn_dyn3d(ib_bdy) == 'none' ) THEN
  219. IF(lwp) WRITE(numout,*) 'No open boundary condition for baroclinic velocities: ln_dyn3d_dmp is set to .false.'
  220. ln_dyn3d_dmp(ib_bdy)=.false.
  221. ELSEIF ( cn_dyn3d(ib_bdy) == 'frs' ) THEN
  222. CALL ctl_stop( 'Use FRS OR relaxation' )
  223. ELSE
  224. IF(lwp) WRITE(numout,*) ' + baroclinic velocities relaxation zone'
  225. IF(lwp) WRITE(numout,*) ' Damping time scale: ',rn_time_dmp(ib_bdy),' days'
  226. IF((lwp).AND.rn_time_dmp(ib_bdy)<0) CALL ctl_stop( 'Time scale must be positive' )
  227. dta_bdy(ib_bdy)%ll_u3d = .true.
  228. dta_bdy(ib_bdy)%ll_v3d = .true.
  229. ENDIF
  230. ELSE
  231. IF(lwp) WRITE(numout,*) ' NO relaxation on baroclinic velocities'
  232. ENDIF
  233. IF(lwp) WRITE(numout,*)
  234. IF(lwp) WRITE(numout,*) 'Boundary conditions for temperature and salinity: '
  235. SELECT CASE( cn_tra(ib_bdy) )
  236. CASE('none')
  237. IF(lwp) WRITE(numout,*) ' no open boundary condition'
  238. dta_bdy(ib_bdy)%ll_tem = .false.
  239. dta_bdy(ib_bdy)%ll_sal = .false.
  240. CASE('frs')
  241. IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme'
  242. dta_bdy(ib_bdy)%ll_tem = .true.
  243. dta_bdy(ib_bdy)%ll_sal = .true.
  244. CASE('specified')
  245. IF(lwp) WRITE(numout,*) ' Specified value'
  246. dta_bdy(ib_bdy)%ll_tem = .true.
  247. dta_bdy(ib_bdy)%ll_sal = .true.
  248. CASE('neumann')
  249. IF(lwp) WRITE(numout,*) ' Neumann conditions'
  250. dta_bdy(ib_bdy)%ll_tem = .false.
  251. dta_bdy(ib_bdy)%ll_sal = .false.
  252. CASE('runoff')
  253. IF(lwp) WRITE(numout,*) ' Runoff conditions : Neumann for T and specified to 0.1 for salinity'
  254. dta_bdy(ib_bdy)%ll_tem = .false.
  255. dta_bdy(ib_bdy)%ll_sal = .false.
  256. CASE('orlanski')
  257. IF(lwp) WRITE(numout,*) ' Orlanski (fully oblique) radiation condition with adaptive nudging'
  258. dta_bdy(ib_bdy)%ll_tem = .true.
  259. dta_bdy(ib_bdy)%ll_sal = .true.
  260. CASE('orlanski_npo')
  261. IF(lwp) WRITE(numout,*) ' Orlanski (NPO) radiation condition with adaptive nudging'
  262. dta_bdy(ib_bdy)%ll_tem = .true.
  263. dta_bdy(ib_bdy)%ll_sal = .true.
  264. CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for cn_tra' )
  265. END SELECT
  266. IF( cn_tra(ib_bdy) /= 'none' ) THEN
  267. SELECT CASE( nn_tra_dta(ib_bdy) ) !
  268. CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data'
  269. CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file'
  270. CASE DEFAULT ; CALL ctl_stop( 'nn_tra_dta must be 0 or 1' )
  271. END SELECT
  272. ENDIF
  273. IF ( ln_tra_dmp(ib_bdy) ) THEN
  274. IF ( cn_tra(ib_bdy) == 'none' ) THEN
  275. IF(lwp) WRITE(numout,*) 'No open boundary condition for tracers: ln_tra_dmp is set to .false.'
  276. ln_tra_dmp(ib_bdy)=.false.
  277. ELSEIF ( cn_tra(ib_bdy) == 'frs' ) THEN
  278. CALL ctl_stop( 'Use FRS OR relaxation' )
  279. ELSE
  280. IF(lwp) WRITE(numout,*) ' + T/S relaxation zone'
  281. IF(lwp) WRITE(numout,*) ' Damping time scale: ',rn_time_dmp(ib_bdy),' days'
  282. IF(lwp) WRITE(numout,*) ' Outflow damping time scale: ',rn_time_dmp_out(ib_bdy),' days'
  283. IF((lwp).AND.rn_time_dmp(ib_bdy)<0) CALL ctl_stop( 'Time scale must be positive' )
  284. dta_bdy(ib_bdy)%ll_tem = .true.
  285. dta_bdy(ib_bdy)%ll_sal = .true.
  286. ENDIF
  287. ELSE
  288. IF(lwp) WRITE(numout,*) ' NO T/S relaxation'
  289. ENDIF
  290. IF(lwp) WRITE(numout,*)
  291. #if defined key_lim2
  292. IF(lwp) WRITE(numout,*) 'Boundary conditions for sea ice: '
  293. SELECT CASE( cn_ice_lim(ib_bdy) )
  294. CASE('none')
  295. IF(lwp) WRITE(numout,*) ' no open boundary condition'
  296. dta_bdy(ib_bdy)%ll_frld = .false.
  297. dta_bdy(ib_bdy)%ll_hicif = .false.
  298. dta_bdy(ib_bdy)%ll_hsnif = .false.
  299. CASE('frs')
  300. IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme'
  301. dta_bdy(ib_bdy)%ll_frld = .true.
  302. dta_bdy(ib_bdy)%ll_hicif = .true.
  303. dta_bdy(ib_bdy)%ll_hsnif = .true.
  304. CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for cn_ice_lim' )
  305. END SELECT
  306. IF( cn_ice_lim(ib_bdy) /= 'none' ) THEN
  307. SELECT CASE( nn_ice_lim_dta(ib_bdy) ) !
  308. CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data'
  309. CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file'
  310. CASE DEFAULT ; CALL ctl_stop( 'nn_ice_lim_dta must be 0 or 1' )
  311. END SELECT
  312. ENDIF
  313. IF(lwp) WRITE(numout,*)
  314. #elif defined key_lim3
  315. IF(lwp) WRITE(numout,*) 'Boundary conditions for sea ice: '
  316. SELECT CASE( cn_ice_lim(ib_bdy) )
  317. CASE('none')
  318. IF(lwp) WRITE(numout,*) ' no open boundary condition'
  319. dta_bdy(ib_bdy)%ll_a_i = .false.
  320. dta_bdy(ib_bdy)%ll_ht_i = .false.
  321. dta_bdy(ib_bdy)%ll_ht_s = .false.
  322. CASE('frs')
  323. IF(lwp) WRITE(numout,*) ' Flow Relaxation Scheme'
  324. dta_bdy(ib_bdy)%ll_a_i = .true.
  325. dta_bdy(ib_bdy)%ll_ht_i = .true.
  326. dta_bdy(ib_bdy)%ll_ht_s = .true.
  327. CASE DEFAULT ; CALL ctl_stop( 'unrecognised value for cn_ice_lim' )
  328. END SELECT
  329. IF( cn_ice_lim(ib_bdy) /= 'none' ) THEN
  330. SELECT CASE( nn_ice_lim_dta(ib_bdy) ) !
  331. CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' initial state used for bdy data'
  332. CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' boundary data taken from file'
  333. CASE DEFAULT ; CALL ctl_stop( 'nn_ice_lim_dta must be 0 or 1' )
  334. END SELECT
  335. ENDIF
  336. IF(lwp) WRITE(numout,*)
  337. IF(lwp) WRITE(numout,*) ' tem of bdy sea-ice = ', rn_ice_tem(ib_bdy)
  338. IF(lwp) WRITE(numout,*) ' sal of bdy sea-ice = ', rn_ice_sal(ib_bdy)
  339. IF(lwp) WRITE(numout,*) ' age of bdy sea-ice = ', rn_ice_age(ib_bdy)
  340. #endif
  341. IF(lwp) WRITE(numout,*) ' Width of relaxation zone = ', nn_rimwidth(ib_bdy)
  342. IF(lwp) WRITE(numout,*)
  343. ENDDO
  344. IF (nb_bdy .gt. 0) THEN
  345. IF( ln_vol ) THEN ! check volume conservation (nn_volctl value)
  346. IF(lwp) WRITE(numout,*) 'Volume correction applied at open boundaries'
  347. IF(lwp) WRITE(numout,*)
  348. SELECT CASE ( nn_volctl )
  349. CASE( 1 ) ; IF(lwp) WRITE(numout,*) ' The total volume will be constant'
  350. CASE( 0 ) ; IF(lwp) WRITE(numout,*) ' The total volume will vary according to the surface E-P flux'
  351. CASE DEFAULT ; CALL ctl_stop( 'nn_volctl must be 0 or 1' )
  352. END SELECT
  353. IF(lwp) WRITE(numout,*)
  354. ELSE
  355. IF(lwp) WRITE(numout,*) 'No volume correction applied at open boundaries'
  356. IF(lwp) WRITE(numout,*)
  357. ENDIF
  358. ENDIF
  359. ! -------------------------------------------------
  360. ! Initialise indices arrays for open boundaries
  361. ! -------------------------------------------------
  362. ! Work out global dimensions of boundary data
  363. ! ---------------------------------------------
  364. REWIND( numnam_cfg )
  365. !!----------------------------------------------------------------------
  366. nblendta(:,:) = 0
  367. nbdysege = 0
  368. nbdysegw = 0
  369. nbdysegn = 0
  370. nbdysegs = 0
  371. icount = 0 ! count user defined segments
  372. ! Dimensions below are used to allocate arrays to read external data
  373. jpbdtas = 1 ! Maximum size of boundary data (structured case)
  374. jpbdtau = 1 ! Maximum size of boundary data (unstructured case)
  375. DO ib_bdy = 1, nb_bdy
  376. IF( .NOT. ln_coords_file(ib_bdy) ) THEN ! Work out size of global arrays from namelist parameters
  377. icount = icount + 1
  378. ! No REWIND here because may need to read more than one nambdy_index namelist.
  379. ! Read only namelist_cfg to avoid unseccessfull overwrite
  380. !! REWIND( numnam_ref ) ! Namelist nambdy_index in reference namelist : Open boundaries indexes
  381. !! READ ( numnam_ref, namrun, IOSTAT = ios, ERR = 903)
  382. !!903 IF( ios /= 0 ) CALL ctl_nam ( ios , 'nambdy_index in reference namelist', lwp )
  383. !! REWIND( numnam_cfg ) ! Namelist nambdy_index in configuration namelist : Open boundaries indexes
  384. READ ( numnam_cfg, nambdy_index, IOSTAT = ios, ERR = 904 )
  385. 904 IF( ios /= 0 ) CALL ctl_nam ( ios , 'nambdy_index in configuration namelist', lwp )
  386. IF(lwm) WRITE ( numond, nambdy_index )
  387. SELECT CASE ( TRIM(ctypebdy) )
  388. CASE( 'N' )
  389. IF( nbdyind == -1 ) THEN ! Automatic boundary definition: if nbdysegX = -1
  390. nbdyind = jpjglo - 2 ! set boundary to whole side of model domain.
  391. nbdybeg = 2
  392. nbdyend = jpiglo - 1
  393. ENDIF
  394. nbdysegn = nbdysegn + 1
  395. npckgn(nbdysegn) = ib_bdy ! Save bdy package number
  396. jpjnob(nbdysegn) = nbdyind
  397. jpindt(nbdysegn) = nbdybeg
  398. jpinft(nbdysegn) = nbdyend
  399. !
  400. CASE( 'S' )
  401. IF( nbdyind == -1 ) THEN ! Automatic boundary definition: if nbdysegX = -1
  402. nbdyind = 2 ! set boundary to whole side of model domain.
  403. nbdybeg = 2
  404. nbdyend = jpiglo - 1
  405. ENDIF
  406. nbdysegs = nbdysegs + 1
  407. npckgs(nbdysegs) = ib_bdy ! Save bdy package number
  408. jpjsob(nbdysegs) = nbdyind
  409. jpisdt(nbdysegs) = nbdybeg
  410. jpisft(nbdysegs) = nbdyend
  411. !
  412. CASE( 'E' )
  413. IF( nbdyind == -1 ) THEN ! Automatic boundary definition: if nbdysegX = -1
  414. nbdyind = jpiglo - 2 ! set boundary to whole side of model domain.
  415. nbdybeg = 2
  416. nbdyend = jpjglo - 1
  417. ENDIF
  418. nbdysege = nbdysege + 1
  419. npckge(nbdysege) = ib_bdy ! Save bdy package number
  420. jpieob(nbdysege) = nbdyind
  421. jpjedt(nbdysege) = nbdybeg
  422. jpjeft(nbdysege) = nbdyend
  423. !
  424. CASE( 'W' )
  425. IF( nbdyind == -1 ) THEN ! Automatic boundary definition: if nbdysegX = -1
  426. nbdyind = 2 ! set boundary to whole side of model domain.
  427. nbdybeg = 2
  428. nbdyend = jpjglo - 1
  429. ENDIF
  430. nbdysegw = nbdysegw + 1
  431. npckgw(nbdysegw) = ib_bdy ! Save bdy package number
  432. jpiwob(nbdysegw) = nbdyind
  433. jpjwdt(nbdysegw) = nbdybeg
  434. jpjwft(nbdysegw) = nbdyend
  435. !
  436. CASE DEFAULT ; CALL ctl_stop( 'ctypebdy must be N, S, E or W' )
  437. END SELECT
  438. ! For simplicity we assume that in case of straight bdy, arrays have the same length
  439. ! (even if it is true that last tangential velocity points
  440. ! are useless). This simplifies a little bit boundary data format (and agrees with format
  441. ! used so far in obc package)
  442. nblendta(1:jpbgrd,ib_bdy) = (nbdyend - nbdybeg + 1) * nn_rimwidth(ib_bdy)
  443. jpbdtas = MAX(jpbdtas, (nbdyend - nbdybeg + 1))
  444. IF (lwp.and.(nn_rimwidth(ib_bdy)>nrimmax)) &
  445. & CALL ctl_stop( 'rimwidth must be lower than nrimmax' )
  446. ELSE ! Read size of arrays in boundary coordinates file.
  447. CALL iom_open( cn_coords_file(ib_bdy), inum )
  448. DO igrd = 1, jpbgrd
  449. id_dummy = iom_varid( inum, 'nbi'//cgrid(igrd), kdimsz=kdimsz )
  450. !clem nblendta(igrd,ib_bdy) = kdimsz(1)
  451. !clem jpbdtau = MAX(jpbdtau, kdimsz(1))
  452. nblendta(igrd,ib_bdy) = MAXVAL(kdimsz)
  453. jpbdtau = MAX(jpbdtau, MAXVAL(kdimsz))
  454. ENDDO
  455. CALL iom_close( inum )
  456. ENDIF
  457. ENDDO ! ib_bdy
  458. IF (nb_bdy>0) THEN
  459. jpbdta = MAXVAL(nblendta(1:jpbgrd,1:nb_bdy))
  460. ! Allocate arrays
  461. !---------------
  462. ALLOCATE( nbidta(jpbdta, jpbgrd, nb_bdy), nbjdta(jpbdta, jpbgrd, nb_bdy), &
  463. & nbrdta(jpbdta, jpbgrd, nb_bdy) )
  464. ALLOCATE( dta_global(jpbdtau, 1, jpk) )
  465. IF ( icount>0 ) ALLOCATE( dta_global2(jpbdtas, nrimmax, jpk) )
  466. !
  467. ENDIF
  468. ! Now look for crossings in user (namelist) defined open boundary segments:
  469. !--------------------------------------------------------------------------
  470. IF ( icount>0 ) CALL bdy_ctl_seg
  471. ! Calculate global boundary index arrays or read in from file
  472. !------------------------------------------------------------
  473. ! 1. Read global index arrays from boundary coordinates file.
  474. DO ib_bdy = 1, nb_bdy
  475. IF( ln_coords_file(ib_bdy) ) THEN
  476. CALL iom_open( cn_coords_file(ib_bdy), inum )
  477. DO igrd = 1, jpbgrd
  478. CALL iom_get( inum, jpdom_unknown, 'nbi'//cgrid(igrd), dta_global(1:nblendta(igrd,ib_bdy),:,1) )
  479. DO ii = 1,nblendta(igrd,ib_bdy)
  480. nbidta(ii,igrd,ib_bdy) = INT( dta_global(ii,1,1) )
  481. END DO
  482. CALL iom_get( inum, jpdom_unknown, 'nbj'//cgrid(igrd), dta_global(1:nblendta(igrd,ib_bdy),:,1) )
  483. DO ii = 1,nblendta(igrd,ib_bdy)
  484. nbjdta(ii,igrd,ib_bdy) = INT( dta_global(ii,1,1) )
  485. END DO
  486. CALL iom_get( inum, jpdom_unknown, 'nbr'//cgrid(igrd), dta_global(1:nblendta(igrd,ib_bdy),:,1) )
  487. DO ii = 1,nblendta(igrd,ib_bdy)
  488. nbrdta(ii,igrd,ib_bdy) = INT( dta_global(ii,1,1) )
  489. END DO
  490. ibr_max = MAXVAL( nbrdta(:,igrd,ib_bdy) )
  491. IF(lwp) WRITE(numout,*)
  492. IF(lwp) WRITE(numout,*) ' Maximum rimwidth in file is ', ibr_max
  493. IF(lwp) WRITE(numout,*) ' nn_rimwidth from namelist is ', nn_rimwidth(ib_bdy)
  494. IF (ibr_max < nn_rimwidth(ib_bdy)) &
  495. CALL ctl_stop( 'nn_rimwidth is larger than maximum rimwidth in file',cn_coords_file(ib_bdy) )
  496. END DO
  497. CALL iom_close( inum )
  498. ENDIF
  499. ENDDO
  500. ! 2. Now fill indices corresponding to straight open boundary arrays:
  501. ! East
  502. !-----
  503. DO iseg = 1, nbdysege
  504. ib_bdy = npckge(iseg)
  505. !
  506. ! ------------ T points -------------
  507. igrd=1
  508. icount=0
  509. DO ir = 1, nn_rimwidth(ib_bdy)
  510. DO ij = jpjedt(iseg), jpjeft(iseg)
  511. icount = icount + 1
  512. nbidta(icount, igrd, ib_bdy) = jpieob(iseg) + 2 - ir
  513. nbjdta(icount, igrd, ib_bdy) = ij
  514. nbrdta(icount, igrd, ib_bdy) = ir
  515. ENDDO
  516. ENDDO
  517. !
  518. ! ------------ U points -------------
  519. igrd=2
  520. icount=0
  521. DO ir = 1, nn_rimwidth(ib_bdy)
  522. DO ij = jpjedt(iseg), jpjeft(iseg)
  523. icount = icount + 1
  524. nbidta(icount, igrd, ib_bdy) = jpieob(iseg) + 1 - ir
  525. nbjdta(icount, igrd, ib_bdy) = ij
  526. nbrdta(icount, igrd, ib_bdy) = ir
  527. ENDDO
  528. ENDDO
  529. !
  530. ! ------------ V points -------------
  531. igrd=3
  532. icount=0
  533. DO ir = 1, nn_rimwidth(ib_bdy)
  534. ! DO ij = jpjedt(iseg), jpjeft(iseg) - 1
  535. DO ij = jpjedt(iseg), jpjeft(iseg)
  536. icount = icount + 1
  537. nbidta(icount, igrd, ib_bdy) = jpieob(iseg) + 2 - ir
  538. nbjdta(icount, igrd, ib_bdy) = ij
  539. nbrdta(icount, igrd, ib_bdy) = ir
  540. ENDDO
  541. nbidta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  542. nbjdta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  543. ENDDO
  544. ENDDO
  545. !
  546. ! West
  547. !-----
  548. DO iseg = 1, nbdysegw
  549. ib_bdy = npckgw(iseg)
  550. !
  551. ! ------------ T points -------------
  552. igrd=1
  553. icount=0
  554. DO ir = 1, nn_rimwidth(ib_bdy)
  555. DO ij = jpjwdt(iseg), jpjwft(iseg)
  556. icount = icount + 1
  557. nbidta(icount, igrd, ib_bdy) = jpiwob(iseg) + ir - 1
  558. nbjdta(icount, igrd, ib_bdy) = ij
  559. nbrdta(icount, igrd, ib_bdy) = ir
  560. ENDDO
  561. ENDDO
  562. !
  563. ! ------------ U points -------------
  564. igrd=2
  565. icount=0
  566. DO ir = 1, nn_rimwidth(ib_bdy)
  567. DO ij = jpjwdt(iseg), jpjwft(iseg)
  568. icount = icount + 1
  569. nbidta(icount, igrd, ib_bdy) = jpiwob(iseg) + ir - 1
  570. nbjdta(icount, igrd, ib_bdy) = ij
  571. nbrdta(icount, igrd, ib_bdy) = ir
  572. ENDDO
  573. ENDDO
  574. !
  575. ! ------------ V points -------------
  576. igrd=3
  577. icount=0
  578. DO ir = 1, nn_rimwidth(ib_bdy)
  579. ! DO ij = jpjwdt(iseg), jpjwft(iseg) - 1
  580. DO ij = jpjwdt(iseg), jpjwft(iseg)
  581. icount = icount + 1
  582. nbidta(icount, igrd, ib_bdy) = jpiwob(iseg) + ir - 1
  583. nbjdta(icount, igrd, ib_bdy) = ij
  584. nbrdta(icount, igrd, ib_bdy) = ir
  585. ENDDO
  586. nbidta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  587. nbjdta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  588. ENDDO
  589. ENDDO
  590. !
  591. ! North
  592. !-----
  593. DO iseg = 1, nbdysegn
  594. ib_bdy = npckgn(iseg)
  595. !
  596. ! ------------ T points -------------
  597. igrd=1
  598. icount=0
  599. DO ir = 1, nn_rimwidth(ib_bdy)
  600. DO ii = jpindt(iseg), jpinft(iseg)
  601. icount = icount + 1
  602. nbidta(icount, igrd, ib_bdy) = ii
  603. nbjdta(icount, igrd, ib_bdy) = jpjnob(iseg) + 2 - ir
  604. nbrdta(icount, igrd, ib_bdy) = ir
  605. ENDDO
  606. ENDDO
  607. !
  608. ! ------------ U points -------------
  609. igrd=2
  610. icount=0
  611. DO ir = 1, nn_rimwidth(ib_bdy)
  612. ! DO ii = jpindt(iseg), jpinft(iseg) - 1
  613. DO ii = jpindt(iseg), jpinft(iseg)
  614. icount = icount + 1
  615. nbidta(icount, igrd, ib_bdy) = ii
  616. nbjdta(icount, igrd, ib_bdy) = jpjnob(iseg) + 2 - ir
  617. nbrdta(icount, igrd, ib_bdy) = ir
  618. ENDDO
  619. nbidta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  620. nbjdta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  621. ENDDO
  622. !
  623. ! ------------ V points -------------
  624. igrd=3
  625. icount=0
  626. DO ir = 1, nn_rimwidth(ib_bdy)
  627. DO ii = jpindt(iseg), jpinft(iseg)
  628. icount = icount + 1
  629. nbidta(icount, igrd, ib_bdy) = ii
  630. nbjdta(icount, igrd, ib_bdy) = jpjnob(iseg) + 1 - ir
  631. nbrdta(icount, igrd, ib_bdy) = ir
  632. ENDDO
  633. ENDDO
  634. ENDDO
  635. !
  636. ! South
  637. !-----
  638. DO iseg = 1, nbdysegs
  639. ib_bdy = npckgs(iseg)
  640. !
  641. ! ------------ T points -------------
  642. igrd=1
  643. icount=0
  644. DO ir = 1, nn_rimwidth(ib_bdy)
  645. DO ii = jpisdt(iseg), jpisft(iseg)
  646. icount = icount + 1
  647. nbidta(icount, igrd, ib_bdy) = ii
  648. nbjdta(icount, igrd, ib_bdy) = jpjsob(iseg) + ir - 1
  649. nbrdta(icount, igrd, ib_bdy) = ir
  650. ENDDO
  651. ENDDO
  652. !
  653. ! ------------ U points -------------
  654. igrd=2
  655. icount=0
  656. DO ir = 1, nn_rimwidth(ib_bdy)
  657. ! DO ii = jpisdt(iseg), jpisft(iseg) - 1
  658. DO ii = jpisdt(iseg), jpisft(iseg)
  659. icount = icount + 1
  660. nbidta(icount, igrd, ib_bdy) = ii
  661. nbjdta(icount, igrd, ib_bdy) = jpjsob(iseg) + ir - 1
  662. nbrdta(icount, igrd, ib_bdy) = ir
  663. ENDDO
  664. nbidta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  665. nbjdta(icount, igrd, ib_bdy) = -ib_bdy ! Discount this point
  666. ENDDO
  667. !
  668. ! ------------ V points -------------
  669. igrd=3
  670. icount=0
  671. DO ir = 1, nn_rimwidth(ib_bdy)
  672. DO ii = jpisdt(iseg), jpisft(iseg)
  673. icount = icount + 1
  674. nbidta(icount, igrd, ib_bdy) = ii
  675. nbjdta(icount, igrd, ib_bdy) = jpjsob(iseg) + ir - 1
  676. nbrdta(icount, igrd, ib_bdy) = ir
  677. ENDDO
  678. ENDDO
  679. ENDDO
  680. ! Deal with duplicated points
  681. !-----------------------------
  682. ! We assign negative indices to duplicated points (to remove them from bdy points to be updated)
  683. ! if their distance to the bdy is greater than the other
  684. ! If their distance are the same, just keep only one to avoid updating a point twice
  685. DO igrd = 1, jpbgrd
  686. DO ib_bdy1 = 1, nb_bdy
  687. DO ib_bdy2 = 1, nb_bdy
  688. IF (ib_bdy1/=ib_bdy2) THEN
  689. DO ib1 = 1, nblendta(igrd,ib_bdy1)
  690. DO ib2 = 1, nblendta(igrd,ib_bdy2)
  691. IF ((nbidta(ib1, igrd, ib_bdy1)==nbidta(ib2, igrd, ib_bdy2)).AND. &
  692. & (nbjdta(ib1, igrd, ib_bdy1)==nbjdta(ib2, igrd, ib_bdy2))) THEN
  693. ! IF ((lwp).AND.(igrd==1)) WRITE(numout,*) ' found coincident point ji, jj:', &
  694. ! & nbidta(ib1, igrd, ib_bdy1), &
  695. ! & nbjdta(ib2, igrd, ib_bdy2)
  696. ! keep only points with the lowest distance to boundary:
  697. IF (nbrdta(ib1, igrd, ib_bdy1)<nbrdta(ib2, igrd, ib_bdy2)) THEN
  698. nbidta(ib2, igrd, ib_bdy2) =-ib_bdy2
  699. nbjdta(ib2, igrd, ib_bdy2) =-ib_bdy2
  700. ELSEIF (nbrdta(ib1, igrd, ib_bdy1)>nbrdta(ib2, igrd, ib_bdy2)) THEN
  701. nbidta(ib1, igrd, ib_bdy1) =-ib_bdy1
  702. nbjdta(ib1, igrd, ib_bdy1) =-ib_bdy1
  703. ! Arbitrary choice if distances are the same:
  704. ELSE
  705. nbidta(ib1, igrd, ib_bdy1) =-ib_bdy1
  706. nbjdta(ib1, igrd, ib_bdy1) =-ib_bdy1
  707. ENDIF
  708. END IF
  709. END DO
  710. END DO
  711. ENDIF
  712. END DO
  713. END DO
  714. END DO
  715. ! Work out dimensions of boundary data on each processor
  716. ! ------------------------------------------------------
  717. ! Rather assume that boundary data indices are given on global domain
  718. ! TO BE DISCUSSED ?
  719. ! iw = mig(1) + 1 ! if monotasking and no zoom, iw=2
  720. ! ie = mig(1) + nlci-1 - 1 ! if monotasking and no zoom, ie=jpim1
  721. ! is = mjg(1) + 1 ! if monotasking and no zoom, is=2
  722. ! in = mjg(1) + nlcj-1 - 1 ! if monotasking and no zoom, in=jpjm1
  723. iwe = mig(1) - jpizoom + 2 ! if monotasking and no zoom, iw=2
  724. ies = mig(1) + nlci - jpizoom - 1 ! if monotasking and no zoom, ie=jpim1
  725. iso = mjg(1) - jpjzoom + 2 ! if monotasking and no zoom, is=2
  726. ino = mjg(1) + nlcj - jpjzoom - 1 ! if monotasking and no zoom, in=jpjm1
  727. ALLOCATE( nbondi_bdy(nb_bdy))
  728. ALLOCATE( nbondj_bdy(nb_bdy))
  729. nbondi_bdy(:)=2
  730. nbondj_bdy(:)=2
  731. ALLOCATE( nbondi_bdy_b(nb_bdy))
  732. ALLOCATE( nbondj_bdy_b(nb_bdy))
  733. nbondi_bdy_b(:)=2
  734. nbondj_bdy_b(:)=2
  735. ! Work out dimensions of boundary data on each neighbour process
  736. IF(nbondi .eq. 0) THEN
  737. iw_b(1) = jpizoom + nimppt(nowe+1)
  738. ie_b(1) = jpizoom + nimppt(nowe+1)+nlcit(nowe+1)-3
  739. is_b(1) = jpjzoom + njmppt(nowe+1)
  740. in_b(1) = jpjzoom + njmppt(nowe+1)+nlcjt(nowe+1)-3
  741. iw_b(2) = jpizoom + nimppt(noea+1)
  742. ie_b(2) = jpizoom + nimppt(noea+1)+nlcit(noea+1)-3
  743. is_b(2) = jpjzoom + njmppt(noea+1)
  744. in_b(2) = jpjzoom + njmppt(noea+1)+nlcjt(noea+1)-3
  745. ELSEIF(nbondi .eq. 1) THEN
  746. iw_b(1) = jpizoom + nimppt(nowe+1)
  747. ie_b(1) = jpizoom + nimppt(nowe+1)+nlcit(nowe+1)-3
  748. is_b(1) = jpjzoom + njmppt(nowe+1)
  749. in_b(1) = jpjzoom + njmppt(nowe+1)+nlcjt(nowe+1)-3
  750. ELSEIF(nbondi .eq. -1) THEN
  751. iw_b(2) = jpizoom + nimppt(noea+1)
  752. ie_b(2) = jpizoom + nimppt(noea+1)+nlcit(noea+1)-3
  753. is_b(2) = jpjzoom + njmppt(noea+1)
  754. in_b(2) = jpjzoom + njmppt(noea+1)+nlcjt(noea+1)-3
  755. ENDIF
  756. IF(nbondj .eq. 0) THEN
  757. iw_b(3) = jpizoom + nimppt(noso+1)
  758. ie_b(3) = jpizoom + nimppt(noso+1)+nlcit(noso+1)-3
  759. is_b(3) = jpjzoom + njmppt(noso+1)
  760. in_b(3) = jpjzoom + njmppt(noso+1)+nlcjt(noso+1)-3
  761. iw_b(4) = jpizoom + nimppt(nono+1)
  762. ie_b(4) = jpizoom + nimppt(nono+1)+nlcit(nono+1)-3
  763. is_b(4) = jpjzoom + njmppt(nono+1)
  764. in_b(4) = jpjzoom + njmppt(nono+1)+nlcjt(nono+1)-3
  765. ELSEIF(nbondj .eq. 1) THEN
  766. iw_b(3) = jpizoom + nimppt(noso+1)
  767. ie_b(3) = jpizoom + nimppt(noso+1)+nlcit(noso+1)-3
  768. is_b(3) = jpjzoom + njmppt(noso+1)
  769. in_b(3) = jpjzoom + njmppt(noso+1)+nlcjt(noso+1)-3
  770. ELSEIF(nbondj .eq. -1) THEN
  771. iw_b(4) = jpizoom + nimppt(nono+1)
  772. ie_b(4) = jpizoom + nimppt(nono+1)+nlcit(nono+1)-3
  773. is_b(4) = jpjzoom + njmppt(nono+1)
  774. in_b(4) = jpjzoom + njmppt(nono+1)+nlcjt(nono+1)-3
  775. ENDIF
  776. DO ib_bdy = 1, nb_bdy
  777. DO igrd = 1, jpbgrd
  778. icount = 0
  779. icountr = 0
  780. idx_bdy(ib_bdy)%nblen(igrd) = 0
  781. idx_bdy(ib_bdy)%nblenrim(igrd) = 0
  782. DO ib = 1, nblendta(igrd,ib_bdy)
  783. ! check that data is in correct order in file
  784. ibm1 = MAX(1,ib-1)
  785. IF(lwp) THEN ! Since all procs read global data only need to do this check on one proc...
  786. IF( nbrdta(ib,igrd,ib_bdy) < nbrdta(ibm1,igrd,ib_bdy) ) THEN
  787. CALL ctl_stop('bdy_init : ERROR : boundary data in file must be defined ', &
  788. & ' in order of distance from edge nbr A utility for re-ordering ', &
  789. & ' boundary coordinates and data files exists in the TOOLS/OBC directory')
  790. ENDIF
  791. ENDIF
  792. ! check if point is in local domain
  793. IF( nbidta(ib,igrd,ib_bdy) >= iwe .AND. nbidta(ib,igrd,ib_bdy) <= ies .AND. &
  794. & nbjdta(ib,igrd,ib_bdy) >= iso .AND. nbjdta(ib,igrd,ib_bdy) <= ino ) THEN
  795. !
  796. icount = icount + 1
  797. !
  798. IF( nbrdta(ib,igrd,ib_bdy) == 1 ) icountr = icountr+1
  799. ENDIF
  800. ENDDO
  801. idx_bdy(ib_bdy)%nblenrim(igrd) = icountr !: length of rim boundary data on each proc
  802. idx_bdy(ib_bdy)%nblen (igrd) = icount !: length of boundary data on each proc
  803. ENDDO ! igrd
  804. ! Allocate index arrays for this boundary set
  805. !--------------------------------------------
  806. ilen1 = MAXVAL(idx_bdy(ib_bdy)%nblen(:))
  807. ALLOCATE( idx_bdy(ib_bdy)%nbi(ilen1,jpbgrd) )
  808. ALLOCATE( idx_bdy(ib_bdy)%nbj(ilen1,jpbgrd) )
  809. ALLOCATE( idx_bdy(ib_bdy)%nbr(ilen1,jpbgrd) )
  810. ALLOCATE( idx_bdy(ib_bdy)%nbd(ilen1,jpbgrd) )
  811. ALLOCATE( idx_bdy(ib_bdy)%nbdout(ilen1,jpbgrd) )
  812. ALLOCATE( idx_bdy(ib_bdy)%nbmap(ilen1,jpbgrd) )
  813. ALLOCATE( idx_bdy(ib_bdy)%nbw(ilen1,jpbgrd) )
  814. ALLOCATE( idx_bdy(ib_bdy)%flagu(ilen1,jpbgrd) )
  815. ALLOCATE( idx_bdy(ib_bdy)%flagv(ilen1,jpbgrd) )
  816. ! Dispatch mapping indices and discrete distances on each processor
  817. ! -----------------------------------------------------------------
  818. com_east = 0
  819. com_west = 0
  820. com_south = 0
  821. com_north = 0
  822. com_east_b = 0
  823. com_west_b = 0
  824. com_south_b = 0
  825. com_north_b = 0
  826. DO igrd = 1, jpbgrd
  827. icount = 0
  828. ! Loop on rimwidth to ensure outermost points come first in the local arrays.
  829. DO ir=1, nn_rimwidth(ib_bdy)
  830. DO ib = 1, nblendta(igrd,ib_bdy)
  831. ! check if point is in local domain and equals ir
  832. IF( nbidta(ib,igrd,ib_bdy) >= iwe .AND. nbidta(ib,igrd,ib_bdy) <= ies .AND. &
  833. & nbjdta(ib,igrd,ib_bdy) >= iso .AND. nbjdta(ib,igrd,ib_bdy) <= ino .AND. &
  834. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  835. !
  836. icount = icount + 1
  837. ! Rather assume that boundary data indices are given on global domain
  838. ! TO BE DISCUSSED ?
  839. ! idx_bdy(ib_bdy)%nbi(icount,igrd) = nbidta(ib,igrd,ib_bdy)- mig(1)+1
  840. ! idx_bdy(ib_bdy)%nbj(icount,igrd) = nbjdta(ib,igrd,ib_bdy)- mjg(1)+1
  841. idx_bdy(ib_bdy)%nbi(icount,igrd) = nbidta(ib,igrd,ib_bdy)- mig(1)+jpizoom
  842. idx_bdy(ib_bdy)%nbj(icount,igrd) = nbjdta(ib,igrd,ib_bdy)- mjg(1)+jpjzoom
  843. ! check if point has to be sent
  844. ii = idx_bdy(ib_bdy)%nbi(icount,igrd)
  845. ij = idx_bdy(ib_bdy)%nbj(icount,igrd)
  846. if((com_east .ne. 1) .and. (ii .eq. (nlci-1)) .and. (nbondi .le. 0)) then
  847. com_east = 1
  848. elseif((com_west .ne. 1) .and. (ii .eq. 2) .and. (nbondi .ge. 0) .and. (nbondi .ne. 2)) then
  849. com_west = 1
  850. endif
  851. if((com_south .ne. 1) .and. (ij .eq. 2) .and. (nbondj .ge. 0) .and. (nbondj .ne. 2)) then
  852. com_south = 1
  853. elseif((com_north .ne. 1) .and. (ij .eq. (nlcj-1)) .and. (nbondj .le. 0)) then
  854. com_north = 1
  855. endif
  856. idx_bdy(ib_bdy)%nbr(icount,igrd) = nbrdta(ib,igrd,ib_bdy)
  857. idx_bdy(ib_bdy)%nbmap(icount,igrd) = ib
  858. ENDIF
  859. ! check if point has to be received from a neighbour
  860. IF(nbondi .eq. 0) THEN
  861. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(1) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(1) .AND. &
  862. & nbjdta(ib,igrd,ib_bdy) >= is_b(1) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(1) .AND. &
  863. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  864. ii = nbidta(ib,igrd,ib_bdy)- iw_b(1)+2
  865. if((com_west_b .ne. 1) .and. (ii .eq. (nlcit(nowe+1)-1))) then
  866. ij = nbjdta(ib,igrd,ib_bdy) - is_b(1)+2
  867. if((ij .eq. 2) .and. (nbondj .eq. 0 .or. nbondj .eq. 1)) then
  868. com_south = 1
  869. elseif((ij .eq. nlcjt(nowe+1)-1) .and. (nbondj .eq. 0 .or. nbondj .eq. -1)) then
  870. com_north = 1
  871. endif
  872. com_west_b = 1
  873. endif
  874. ENDIF
  875. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(2) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(2) .AND. &
  876. & nbjdta(ib,igrd,ib_bdy) >= is_b(2) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(2) .AND. &
  877. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  878. ii = nbidta(ib,igrd,ib_bdy)- iw_b(2)+2
  879. if((com_east_b .ne. 1) .and. (ii .eq. 2)) then
  880. ij = nbjdta(ib,igrd,ib_bdy) - is_b(2)+2
  881. if((ij .eq. 2) .and. (nbondj .eq. 0 .or. nbondj .eq. 1)) then
  882. com_south = 1
  883. elseif((ij .eq. nlcjt(noea+1)-1) .and. (nbondj .eq. 0 .or. nbondj .eq. -1)) then
  884. com_north = 1
  885. endif
  886. com_east_b = 1
  887. endif
  888. ENDIF
  889. ELSEIF(nbondi .eq. 1) THEN
  890. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(1) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(1) .AND. &
  891. & nbjdta(ib,igrd,ib_bdy) >= is_b(1) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(1) .AND. &
  892. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  893. ii = nbidta(ib,igrd,ib_bdy)- iw_b(1)+2
  894. if((com_west_b .ne. 1) .and. (ii .eq. (nlcit(nowe+1)-1))) then
  895. ij = nbjdta(ib,igrd,ib_bdy) - is_b(1)+2
  896. if((ij .eq. 2) .and. (nbondj .eq. 0 .or. nbondj .eq. 1)) then
  897. com_south = 1
  898. elseif((ij .eq. nlcjt(nowe+1)-1) .and. (nbondj .eq. 0 .or. nbondj .eq. -1)) then
  899. com_north = 1
  900. endif
  901. com_west_b = 1
  902. endif
  903. ENDIF
  904. ELSEIF(nbondi .eq. -1) THEN
  905. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(2) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(2) .AND. &
  906. & nbjdta(ib,igrd,ib_bdy) >= is_b(2) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(2) .AND. &
  907. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  908. ii = nbidta(ib,igrd,ib_bdy)- iw_b(2)+2
  909. if((com_east_b .ne. 1) .and. (ii .eq. 2)) then
  910. ij = nbjdta(ib,igrd,ib_bdy) - is_b(2)+2
  911. if((ij .eq. 2) .and. (nbondj .eq. 0 .or. nbondj .eq. 1)) then
  912. com_south = 1
  913. elseif((ij .eq. nlcjt(noea+1)-1) .and. (nbondj .eq. 0 .or. nbondj .eq. -1)) then
  914. com_north = 1
  915. endif
  916. com_east_b = 1
  917. endif
  918. ENDIF
  919. ENDIF
  920. IF(nbondj .eq. 0) THEN
  921. IF(com_north_b .ne. 1 .AND. (nbidta(ib,igrd,ib_bdy) == iw_b(4)-1 &
  922. & .OR. nbidta(ib,igrd,ib_bdy) == ie_b(4)+1) .AND. &
  923. & nbjdta(ib,igrd,ib_bdy) == is_b(4) .AND. nbrdta(ib,igrd,ib_bdy) == ir) THEN
  924. com_north_b = 1
  925. ENDIF
  926. IF(com_south_b .ne. 1 .AND. (nbidta(ib,igrd,ib_bdy) == iw_b(3)-1 &
  927. &.OR. nbidta(ib,igrd,ib_bdy) == ie_b(3)+1) .AND. &
  928. & nbjdta(ib,igrd,ib_bdy) == in_b(3) .AND. nbrdta(ib,igrd,ib_bdy) == ir) THEN
  929. com_south_b = 1
  930. ENDIF
  931. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(3) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(3) .AND. &
  932. & nbjdta(ib,igrd,ib_bdy) >= is_b(3) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(3) .AND. &
  933. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  934. ij = nbjdta(ib,igrd,ib_bdy)- is_b(3)+2
  935. if((com_south_b .ne. 1) .and. (ij .eq. (nlcjt(noso+1)-1))) then
  936. com_south_b = 1
  937. endif
  938. ENDIF
  939. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(4) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(4) .AND. &
  940. & nbjdta(ib,igrd,ib_bdy) >= is_b(4) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(4) .AND. &
  941. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  942. ij = nbjdta(ib,igrd,ib_bdy)- is_b(4)+2
  943. if((com_north_b .ne. 1) .and. (ij .eq. 2)) then
  944. com_north_b = 1
  945. endif
  946. ENDIF
  947. ELSEIF(nbondj .eq. 1) THEN
  948. IF( com_south_b .ne. 1 .AND. (nbidta(ib,igrd,ib_bdy) == iw_b(3)-1 .OR. &
  949. & nbidta(ib,igrd,ib_bdy) == ie_b(3)+1) .AND. &
  950. & nbjdta(ib,igrd,ib_bdy) == in_b(3) .AND. nbrdta(ib,igrd,ib_bdy) == ir) THEN
  951. com_south_b = 1
  952. ENDIF
  953. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(3) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(3) .AND. &
  954. & nbjdta(ib,igrd,ib_bdy) >= is_b(3) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(3) .AND. &
  955. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  956. ij = nbjdta(ib,igrd,ib_bdy)- is_b(3)+2
  957. if((com_south_b .ne. 1) .and. (ij .eq. (nlcjt(noso+1)-1))) then
  958. com_south_b = 1
  959. endif
  960. ENDIF
  961. ELSEIF(nbondj .eq. -1) THEN
  962. IF(com_north_b .ne. 1 .AND. (nbidta(ib,igrd,ib_bdy) == iw_b(4)-1 &
  963. & .OR. nbidta(ib,igrd,ib_bdy) == ie_b(4)+1) .AND. &
  964. & nbjdta(ib,igrd,ib_bdy) == is_b(4) .AND. nbrdta(ib,igrd,ib_bdy) == ir) THEN
  965. com_north_b = 1
  966. ENDIF
  967. IF( nbidta(ib,igrd,ib_bdy) >= iw_b(4) .AND. nbidta(ib,igrd,ib_bdy) <= ie_b(4) .AND. &
  968. & nbjdta(ib,igrd,ib_bdy) >= is_b(4) .AND. nbjdta(ib,igrd,ib_bdy) <= in_b(4) .AND. &
  969. & nbrdta(ib,igrd,ib_bdy) == ir ) THEN
  970. ij = nbjdta(ib,igrd,ib_bdy)- is_b(4)+2
  971. if((com_north_b .ne. 1) .and. (ij .eq. 2)) then
  972. com_north_b = 1
  973. endif
  974. ENDIF
  975. ENDIF
  976. ENDDO
  977. ENDDO
  978. ENDDO
  979. ! definition of the i- and j- direction local boundaries arrays
  980. ! used for sending the boudaries
  981. IF((com_east .eq. 1) .and. (com_west .eq. 1)) THEN
  982. nbondi_bdy(ib_bdy) = 0
  983. ELSEIF ((com_east .eq. 1) .and. (com_west .eq. 0)) THEN
  984. nbondi_bdy(ib_bdy) = -1
  985. ELSEIF ((com_east .eq. 0) .and. (com_west .eq. 1)) THEN
  986. nbondi_bdy(ib_bdy) = 1
  987. ENDIF
  988. IF((com_north .eq. 1) .and. (com_south .eq. 1)) THEN
  989. nbondj_bdy(ib_bdy) = 0
  990. ELSEIF ((com_north .eq. 1) .and. (com_south .eq. 0)) THEN
  991. nbondj_bdy(ib_bdy) = -1
  992. ELSEIF ((com_north .eq. 0) .and. (com_south .eq. 1)) THEN
  993. nbondj_bdy(ib_bdy) = 1
  994. ENDIF
  995. ! definition of the i- and j- direction local boundaries arrays
  996. ! used for receiving the boudaries
  997. IF((com_east_b .eq. 1) .and. (com_west_b .eq. 1)) THEN
  998. nbondi_bdy_b(ib_bdy) = 0
  999. ELSEIF ((com_east_b .eq. 1) .and. (com_west_b .eq. 0)) THEN
  1000. nbondi_bdy_b(ib_bdy) = -1
  1001. ELSEIF ((com_east_b .eq. 0) .and. (com_west_b .eq. 1)) THEN
  1002. nbondi_bdy_b(ib_bdy) = 1
  1003. ENDIF
  1004. IF((com_north_b .eq. 1) .and. (com_south_b .eq. 1)) THEN
  1005. nbondj_bdy_b(ib_bdy) = 0
  1006. ELSEIF ((com_north_b .eq. 1) .and. (com_south_b .eq. 0)) THEN
  1007. nbondj_bdy_b(ib_bdy) = -1
  1008. ELSEIF ((com_north_b .eq. 0) .and. (com_south_b .eq. 1)) THEN
  1009. nbondj_bdy_b(ib_bdy) = 1
  1010. ENDIF
  1011. ! Compute rim weights for FRS scheme
  1012. ! ----------------------------------
  1013. DO igrd = 1, jpbgrd
  1014. DO ib = 1, idx_bdy(ib_bdy)%nblen(igrd)
  1015. nbr => idx_bdy(ib_bdy)%nbr(ib,igrd)
  1016. idx_bdy(ib_bdy)%nbw(ib,igrd) = 1.- TANH( FLOAT( nbr - 1 ) *0.5 ) ! tanh formulation
  1017. ! idx_bdy(ib_bdy)%nbw(ib,igrd) = (FLOAT(nn_rimwidth(ib_bdy)+1-nbr)/FLOAT(nn_rimwidth(ib_bdy)))**2. ! quadratic
  1018. ! idx_bdy(ib_bdy)%nbw(ib,igrd) = FLOAT(nn_rimwidth(ib_bdy)+1-nbr)/FLOAT(nn_rimwidth(ib_bdy)) ! linear
  1019. END DO
  1020. END DO
  1021. ! Compute damping coefficients
  1022. ! ----------------------------
  1023. DO igrd = 1, jpbgrd
  1024. DO ib = 1, idx_bdy(ib_bdy)%nblen(igrd)
  1025. nbr => idx_bdy(ib_bdy)%nbr(ib,igrd)
  1026. idx_bdy(ib_bdy)%nbd(ib,igrd) = 1. / ( rn_time_dmp(ib_bdy) * rday ) &
  1027. & *(FLOAT(nn_rimwidth(ib_bdy)+1-nbr)/FLOAT(nn_rimwidth(ib_bdy)))**2. ! quadratic
  1028. idx_bdy(ib_bdy)%nbdout(ib,igrd) = 1. / ( rn_time_dmp_out(ib_bdy) * rday ) &
  1029. & *(FLOAT(nn_rimwidth(ib_bdy)+1-nbr)/FLOAT(nn_rimwidth(ib_bdy)))**2. ! quadratic
  1030. END DO
  1031. END DO
  1032. ENDDO
  1033. ! ------------------------------------------------------
  1034. ! Initialise masks and find normal/tangential directions
  1035. ! ------------------------------------------------------
  1036. ! Read global 2D mask at T-points: bdytmask
  1037. ! -----------------------------------------
  1038. ! bdytmask = 1 on the computational domain AND on open boundaries
  1039. ! = 0 elsewhere
  1040. IF( ln_mask_file ) THEN
  1041. CALL iom_open( cn_mask_file, inum )
  1042. CALL iom_get ( inum, jpdom_data, 'bdy_msk', bdytmask(:,:) )
  1043. CALL iom_close( inum )
  1044. ! Derive mask on U and V grid from mask on T grid
  1045. bdyumask(:,:) = 0.e0
  1046. bdyvmask(:,:) = 0.e0
  1047. DO ij=1, jpjm1
  1048. DO ii=1, jpim1
  1049. bdyumask(ii,ij)=bdytmask(ii,ij)*bdytmask(ii+1, ij )
  1050. bdyvmask(ii,ij)=bdytmask(ii,ij)*bdytmask(ii ,ij+1)
  1051. END DO
  1052. END DO
  1053. CALL lbc_lnk( bdyumask(:,:), 'U', 1. ) ; CALL lbc_lnk( bdyvmask(:,:), 'V', 1. ) ! Lateral boundary cond.
  1054. ! Mask corrections
  1055. ! ----------------
  1056. DO ik = 1, jpkm1
  1057. DO ij = 1, jpj
  1058. DO ii = 1, jpi
  1059. tmask(ii,ij,ik) = tmask(ii,ij,ik) * bdytmask(ii,ij)
  1060. umask(ii,ij,ik) = umask(ii,ij,ik) * bdyumask(ii,ij)
  1061. vmask(ii,ij,ik) = vmask(ii,ij,ik) * bdyvmask(ii,ij)
  1062. bmask(ii,ij) = bmask(ii,ij) * bdytmask(ii,ij)
  1063. END DO
  1064. END DO
  1065. END DO
  1066. DO ik = 1, jpkm1
  1067. DO ij = 2, jpjm1
  1068. DO ii = 2, jpim1
  1069. fmask(ii,ij,ik) = fmask(ii,ij,ik) * bdytmask(ii,ij ) * bdytmask(ii+1,ij ) &
  1070. & * bdytmask(ii,ij+1) * bdytmask(ii+1,ij+1)
  1071. END DO
  1072. END DO
  1073. END DO
  1074. tmask_i (:,:) = ssmask(:,:) * tmask_i(:,:)
  1075. ENDIF ! ln_mask_file=.TRUE.
  1076. bdytmask(:,:) = ssmask(:,:)
  1077. IF( .not. ln_mask_file ) THEN
  1078. ! If .not. ln_mask_file then we need to derive mask on U and V grid
  1079. ! from mask on T grid here.
  1080. bdyumask(:,:) = 0.e0
  1081. bdyvmask(:,:) = 0.e0
  1082. DO ij=1, jpjm1
  1083. DO ii=1, jpim1
  1084. bdyumask(ii,ij)=bdytmask(ii,ij)*bdytmask(ii+1, ij )
  1085. bdyvmask(ii,ij)=bdytmask(ii,ij)*bdytmask(ii ,ij+1)
  1086. END DO
  1087. END DO
  1088. CALL lbc_lnk( bdyumask(:,:), 'U', 1. ) ; CALL lbc_lnk( bdyvmask(:,:), 'V', 1. ) ! Lateral boundary cond.
  1089. ENDIF
  1090. ! bdy masks and bmask are now set to zero on boundary points:
  1091. igrd = 1 ! In the free surface case, bmask is at T-points
  1092. DO ib_bdy = 1, nb_bdy
  1093. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1094. bmask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0
  1095. ENDDO
  1096. ENDDO
  1097. !
  1098. igrd = 1
  1099. DO ib_bdy = 1, nb_bdy
  1100. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1101. bdytmask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0
  1102. ENDDO
  1103. ENDDO
  1104. !
  1105. igrd = 2
  1106. DO ib_bdy = 1, nb_bdy
  1107. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1108. bdyumask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0
  1109. ENDDO
  1110. ENDDO
  1111. !
  1112. igrd = 3
  1113. DO ib_bdy = 1, nb_bdy
  1114. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1115. bdyvmask(idx_bdy(ib_bdy)%nbi(ib,igrd), idx_bdy(ib_bdy)%nbj(ib,igrd)) = 0.e0
  1116. ENDDO
  1117. ENDDO
  1118. ! For the flagu/flagv calculation below we require a version of fmask without
  1119. ! the land boundary condition (shlat) included:
  1120. CALL wrk_alloc(jpi,jpj,zfmask)
  1121. DO ij = 2, jpjm1
  1122. DO ii = 2, jpim1
  1123. zfmask(ii,ij) = tmask(ii,ij ,1) * tmask(ii+1,ij ,1) &
  1124. & * tmask(ii,ij+1,1) * tmask(ii+1,ij+1,1)
  1125. END DO
  1126. END DO
  1127. ! Lateral boundary conditions
  1128. CALL lbc_lnk( zfmask , 'F', 1. )
  1129. CALL lbc_lnk( fmask , 'F', 1. ) ; CALL lbc_lnk( bdytmask(:,:), 'T', 1. )
  1130. CALL lbc_lnk( bdyumask(:,:), 'U', 1. ) ; CALL lbc_lnk( bdyvmask(:,:), 'V', 1. )
  1131. DO ib_bdy = 1, nb_bdy ! Indices and directions of rim velocity components
  1132. idx_bdy(ib_bdy)%flagu(:,:) = 0.e0
  1133. idx_bdy(ib_bdy)%flagv(:,:) = 0.e0
  1134. icount = 0
  1135. ! Calculate relationship of U direction to the local orientation of the boundary
  1136. ! flagu = -1 : u component is normal to the dynamical boundary and its direction is outward
  1137. ! flagu = 0 : u is tangential
  1138. ! flagu = 1 : u is normal to the boundary and is direction is inward
  1139. DO igrd = 1,jpbgrd
  1140. SELECT CASE( igrd )
  1141. CASE( 1 )
  1142. pmask => umask(:,:,1)
  1143. i_offset = 0
  1144. CASE( 2 )
  1145. pmask => bdytmask
  1146. i_offset = 1
  1147. CASE( 3 )
  1148. pmask => zfmask(:,:)
  1149. i_offset = 0
  1150. END SELECT
  1151. icount = 0
  1152. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1153. nbi => idx_bdy(ib_bdy)%nbi(ib,igrd)
  1154. nbj => idx_bdy(ib_bdy)%nbj(ib,igrd)
  1155. zefl = pmask(nbi+i_offset-1,nbj)
  1156. zwfl = pmask(nbi+i_offset,nbj)
  1157. ! This error check only works if you are using the bdyXmask arrays
  1158. IF( i_offset == 1 .and. zefl + zwfl == 2 ) THEN
  1159. icount = icount + 1
  1160. IF(lwp) WRITE(numout,*) 'Problem with igrd = ',igrd,' at (global) nbi, nbj : ',mig(nbi),mjg(nbj)
  1161. ELSE
  1162. idx_bdy(ib_bdy)%flagu(ib,igrd) = -zefl + zwfl
  1163. ENDIF
  1164. END DO
  1165. IF( icount /= 0 ) THEN
  1166. IF(lwp) WRITE(numout,*)
  1167. IF(lwp) WRITE(numout,*) ' E R R O R : Some ',cgrid(igrd),' grid points,', &
  1168. ' are not boundary points (flagu calculation). Check nbi, nbj, indices for boundary set ',ib_bdy
  1169. IF(lwp) WRITE(numout,*) ' ========== '
  1170. IF(lwp) WRITE(numout,*)
  1171. nstop = nstop + 1
  1172. ENDIF
  1173. END DO
  1174. ! Calculate relationship of V direction to the local orientation of the boundary
  1175. ! flagv = -1 : v component is normal to the dynamical boundary but its direction is outward
  1176. ! flagv = 0 : v is tangential
  1177. ! flagv = 1 : v is normal to the boundary and is direction is inward
  1178. DO igrd = 1,jpbgrd
  1179. SELECT CASE( igrd )
  1180. CASE( 1 )
  1181. pmask => vmask(:,:,1)
  1182. j_offset = 0
  1183. CASE( 2 )
  1184. pmask => zfmask(:,:)
  1185. j_offset = 0
  1186. CASE( 3 )
  1187. pmask => bdytmask
  1188. j_offset = 1
  1189. END SELECT
  1190. icount = 0
  1191. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1192. nbi => idx_bdy(ib_bdy)%nbi(ib,igrd)
  1193. nbj => idx_bdy(ib_bdy)%nbj(ib,igrd)
  1194. znfl = pmask(nbi,nbj+j_offset-1 )
  1195. zsfl = pmask(nbi,nbj+j_offset)
  1196. ! This error check only works if you are using the bdyXmask arrays
  1197. IF( j_offset == 1 .and. znfl + zsfl == 2 ) THEN
  1198. IF(lwp) WRITE(numout,*) 'Problem with igrd = ',igrd,' at (global) nbi, nbj : ',mig(nbi),mjg(nbj)
  1199. icount = icount + 1
  1200. ELSE
  1201. idx_bdy(ib_bdy)%flagv(ib,igrd) = -znfl + zsfl
  1202. END IF
  1203. END DO
  1204. IF( icount /= 0 ) THEN
  1205. IF(lwp) WRITE(numout,*)
  1206. IF(lwp) WRITE(numout,*) ' E R R O R : Some ',cgrid(igrd),' grid points,', &
  1207. ' are not boundary points (flagv calculation). Check nbi, nbj, indices for boundary set ',ib_bdy
  1208. IF(lwp) WRITE(numout,*) ' ========== '
  1209. IF(lwp) WRITE(numout,*)
  1210. nstop = nstop + 1
  1211. ENDIF
  1212. END DO
  1213. END DO
  1214. ! Compute total lateral surface for volume correction:
  1215. ! ----------------------------------------------------
  1216. ! JC: this must be done at each time step with key_vvl
  1217. bdysurftot = 0.e0
  1218. IF( ln_vol ) THEN
  1219. igrd = 2 ! Lateral surface at U-points
  1220. DO ib_bdy = 1, nb_bdy
  1221. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1222. nbi => idx_bdy(ib_bdy)%nbi(ib,igrd)
  1223. nbj => idx_bdy(ib_bdy)%nbj(ib,igrd)
  1224. flagu => idx_bdy(ib_bdy)%flagu(ib,igrd)
  1225. bdysurftot = bdysurftot + hu (nbi , nbj) &
  1226. & * e2u (nbi , nbj) * ABS( flagu ) &
  1227. & * tmask_i(nbi , nbj) &
  1228. & * tmask_i(nbi+1, nbj)
  1229. ENDDO
  1230. ENDDO
  1231. igrd=3 ! Add lateral surface at V-points
  1232. DO ib_bdy = 1, nb_bdy
  1233. DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
  1234. nbi => idx_bdy(ib_bdy)%nbi(ib,igrd)
  1235. nbj => idx_bdy(ib_bdy)%nbj(ib,igrd)
  1236. flagv => idx_bdy(ib_bdy)%flagv(ib,igrd)
  1237. bdysurftot = bdysurftot + hv (nbi, nbj ) &
  1238. & * e1v (nbi, nbj ) * ABS( flagv ) &
  1239. & * tmask_i(nbi, nbj ) &
  1240. & * tmask_i(nbi, nbj+1)
  1241. ENDDO
  1242. ENDDO
  1243. !
  1244. IF( lk_mpp ) CALL mpp_sum( bdysurftot ) ! sum over the global domain
  1245. END IF
  1246. !
  1247. ! Tidy up
  1248. !--------
  1249. IF (nb_bdy>0) THEN
  1250. DEALLOCATE(nbidta, nbjdta, nbrdta)
  1251. ENDIF
  1252. CALL wrk_dealloc(jpi,jpj,zfmask)
  1253. IF( nn_timing == 1 ) CALL timing_stop('bdy_init')
  1254. END SUBROUTINE bdy_init
  1255. SUBROUTINE bdy_ctl_seg
  1256. !!----------------------------------------------------------------------
  1257. !! *** ROUTINE bdy_ctl_seg ***
  1258. !!
  1259. !! ** Purpose : Check straight open boundary segments location
  1260. !!
  1261. !! ** Method : - Look for open boundary corners
  1262. !! - Check that segments start or end on land
  1263. !!----------------------------------------------------------------------
  1264. INTEGER :: ib, ib1, ib2, ji ,jj, itest
  1265. INTEGER, DIMENSION(jp_nseg,2) :: icorne, icornw, icornn, icorns
  1266. REAL(wp), DIMENSION(2) :: ztestmask
  1267. !!----------------------------------------------------------------------
  1268. !
  1269. IF (lwp) WRITE(numout,*) ' '
  1270. IF (lwp) WRITE(numout,*) 'bdy_ctl_seg: Check analytical segments'
  1271. IF (lwp) WRITE(numout,*) '~~~~~~~~~~~~'
  1272. !
  1273. IF(lwp) WRITE(numout,*) 'Number of east segments : ', nbdysege
  1274. IF(lwp) WRITE(numout,*) 'Number of west segments : ', nbdysegw
  1275. IF(lwp) WRITE(numout,*) 'Number of north segments : ', nbdysegn
  1276. IF(lwp) WRITE(numout,*) 'Number of south segments : ', nbdysegs
  1277. ! 1. Check bounds
  1278. !----------------
  1279. DO ib = 1, nbdysegn
  1280. IF (lwp) WRITE(numout,*) '**check north seg bounds pckg: ', npckgn(ib)
  1281. IF ((jpjnob(ib).ge.jpjglo-1).or.&
  1282. &(jpjnob(ib).le.1)) CALL ctl_stop( 'nbdyind out of domain' )
  1283. IF (jpindt(ib).ge.jpinft(ib)) CALL ctl_stop( 'Bdy start index is greater than end index' )
  1284. IF (jpindt(ib).le.1 ) CALL ctl_stop( 'Start index out of domain' )
  1285. IF (jpinft(ib).ge.jpiglo) CALL ctl_stop( 'End index out of domain' )
  1286. END DO
  1287. !
  1288. DO ib = 1, nbdysegs
  1289. IF (lwp) WRITE(numout,*) '**check south seg bounds pckg: ', npckgs(ib)
  1290. IF ((jpjsob(ib).ge.jpjglo-1).or.&
  1291. &(jpjsob(ib).le.1)) CALL ctl_stop( 'nbdyind out of domain' )
  1292. IF (jpisdt(ib).ge.jpisft(ib)) CALL ctl_stop( 'Bdy start index is greater than end index' )
  1293. IF (jpisdt(ib).le.1 ) CALL ctl_stop( 'Start index out of domain' )
  1294. IF (jpisft(ib).ge.jpiglo) CALL ctl_stop( 'End index out of domain' )
  1295. END DO
  1296. !
  1297. DO ib = 1, nbdysege
  1298. IF (lwp) WRITE(numout,*) '**check east seg bounds pckg: ', npckge(ib)
  1299. IF ((jpieob(ib).ge.jpiglo-1).or.&
  1300. &(jpieob(ib).le.1)) CALL ctl_stop( 'nbdyind out of domain' )
  1301. IF (jpjedt(ib).ge.jpjeft(ib)) CALL ctl_stop( 'Bdy start index is greater than end index' )
  1302. IF (jpjedt(ib).le.1 ) CALL ctl_stop( 'Start index out of domain' )
  1303. IF (jpjeft(ib).ge.jpjglo) CALL ctl_stop( 'End index out of domain' )
  1304. END DO
  1305. !
  1306. DO ib = 1, nbdysegw
  1307. IF (lwp) WRITE(numout,*) '**check west seg bounds pckg: ', npckgw(ib)
  1308. IF ((jpiwob(ib).ge.jpiglo-1).or.&
  1309. &(jpiwob(ib).le.1)) CALL ctl_stop( 'nbdyind out of domain' )
  1310. IF (jpjwdt(ib).ge.jpjwft(ib)) CALL ctl_stop( 'Bdy start index is greater than end index' )
  1311. IF (jpjwdt(ib).le.1 ) CALL ctl_stop( 'Start index out of domain' )
  1312. IF (jpjwft(ib).ge.jpjglo) CALL ctl_stop( 'End index out of domain' )
  1313. ENDDO
  1314. !
  1315. !
  1316. ! 2. Look for segment crossings
  1317. !------------------------------
  1318. IF (lwp) WRITE(numout,*) '**Look for segments corners :'
  1319. !
  1320. itest = 0 ! corner number
  1321. !
  1322. ! flag to detect if start or end of open boundary belongs to a corner
  1323. ! if not (=0), it must be on land.
  1324. ! if a corner is detected, save bdy package number for further tests
  1325. icorne(:,:)=0. ; icornw(:,:)=0. ; icornn(:,:)=0. ; icorns(:,:)=0.
  1326. ! South/West crossings
  1327. IF ((nbdysegw > 0).AND.(nbdysegs > 0)) THEN
  1328. DO ib1 = 1, nbdysegw
  1329. DO ib2 = 1, nbdysegs
  1330. IF (( jpisdt(ib2)<=jpiwob(ib1)).AND. &
  1331. & ( jpisft(ib2)>=jpiwob(ib1)).AND. &
  1332. & ( jpjwdt(ib1)<=jpjsob(ib2)).AND. &
  1333. & ( jpjwft(ib1)>=jpjsob(ib2))) THEN
  1334. IF ((jpjwdt(ib1)==jpjsob(ib2)).AND.(jpisdt(ib2)==jpiwob(ib1))) THEN
  1335. ! We have a possible South-West corner
  1336. ! WRITE(numout,*) ' Found a South-West corner at (i,j): ', jpisdt(ib2), jpjwdt(ib1)
  1337. ! WRITE(numout,*) ' between segments: ', npckgw(ib1), npckgs(ib2)
  1338. icornw(ib1,1) = npckgs(ib2)
  1339. icorns(ib2,1) = npckgw(ib1)
  1340. ELSEIF ((jpisft(ib2)==jpiwob(ib1)).AND.(jpjwft(ib1)==jpjsob(ib2))) THEN
  1341. IF(lwp) WRITE(numout,*)
  1342. IF(lwp) WRITE(numout,*) ' E R R O R : Found an acute open boundary corner at point (i,j)= ', &
  1343. & jpisft(ib2), jpjwft(ib1)
  1344. IF(lwp) WRITE(numout,*) ' ========== Not allowed yet'
  1345. IF(lwp) WRITE(numout,*) ' Crossing problem with West segment: ',npckgw(ib1), &
  1346. & ' and South segment: ',npckgs(ib2)
  1347. IF(lwp) WRITE(numout,*)
  1348. nstop = nstop + 1
  1349. ELSE
  1350. IF(lwp) WRITE(numout,*)
  1351. IF(lwp) WRITE(numout,*) ' E R R O R : Check South and West Open boundary indices'
  1352. IF(lwp) WRITE(numout,*) ' ========== Crossing problem with West segment: ',npckgw(ib1) , &
  1353. & ' and South segment: ',npckgs(ib2)
  1354. IF(lwp) WRITE(numout,*)
  1355. nstop = nstop+1
  1356. END IF
  1357. END IF
  1358. END DO
  1359. END DO
  1360. END IF
  1361. !
  1362. ! South/East crossings
  1363. IF ((nbdysege > 0).AND.(nbdysegs > 0)) THEN
  1364. DO ib1 = 1, nbdysege
  1365. DO ib2 = 1, nbdysegs
  1366. IF (( jpisdt(ib2)<=jpieob(ib1)+1).AND. &
  1367. & ( jpisft(ib2)>=jpieob(ib1)+1).AND. &
  1368. & ( jpjedt(ib1)<=jpjsob(ib2) ).AND. &
  1369. & ( jpjeft(ib1)>=jpjsob(ib2) )) THEN
  1370. IF ((jpjedt(ib1)==jpjsob(ib2)).AND.(jpisft(ib2)==jpieob(ib1)+1)) THEN
  1371. ! We have a possible South-East corner
  1372. ! WRITE(numout,*) ' Found a South-East corner at (i,j): ', jpisft(ib2), jpjedt(ib1)
  1373. ! WRITE(numout,*) ' between segments: ', npckge(ib1), npckgs(ib2)
  1374. icorne(ib1,1) = npckgs(ib2)
  1375. icorns(ib2,2) = npckge(ib1)
  1376. ELSEIF ((jpjeft(ib1)==jpjsob(ib2)).AND.(jpisdt(ib2)==jpieob(ib1)+1)) THEN
  1377. IF(lwp) WRITE(numout,*)
  1378. IF(lwp) WRITE(numout,*) ' E R R O R : Found an acute open boundary corner at point (i,j)= ', &
  1379. & jpisdt(ib2), jpjeft(ib1)
  1380. IF(lwp) WRITE(numout,*) ' ========== Not allowed yet'
  1381. IF(lwp) WRITE(numout,*) ' Crossing problem with East segment: ',npckge(ib1), &
  1382. & ' and South segment: ',npckgs(ib2)
  1383. IF(lwp) WRITE(numout,*)
  1384. nstop = nstop + 1
  1385. ELSE
  1386. IF(lwp) WRITE(numout,*)
  1387. IF(lwp) WRITE(numout,*) ' E R R O R : Check South and East Open boundary indices'
  1388. IF(lwp) WRITE(numout,*) ' ========== Crossing problem with East segment: ',npckge(ib1), &
  1389. & ' and South segment: ',npckgs(ib2)
  1390. IF(lwp) WRITE(numout,*)
  1391. nstop = nstop + 1
  1392. END IF
  1393. END IF
  1394. END DO
  1395. END DO
  1396. END IF
  1397. !
  1398. ! North/West crossings
  1399. IF ((nbdysegn > 0).AND.(nbdysegw > 0)) THEN
  1400. DO ib1 = 1, nbdysegw
  1401. DO ib2 = 1, nbdysegn
  1402. IF (( jpindt(ib2)<=jpiwob(ib1) ).AND. &
  1403. & ( jpinft(ib2)>=jpiwob(ib1) ).AND. &
  1404. & ( jpjwdt(ib1)<=jpjnob(ib2)+1).AND. &
  1405. & ( jpjwft(ib1)>=jpjnob(ib2)+1)) THEN
  1406. IF ((jpjwft(ib1)==jpjnob(ib2)+1).AND.(jpindt(ib2)==jpiwob(ib1))) THEN
  1407. ! We have a possible North-West corner
  1408. ! WRITE(numout,*) ' Found a North-West corner at (i,j): ', jpindt(ib2), jpjwft(ib1)
  1409. ! WRITE(numout,*) ' between segments: ', npckgw(ib1), npckgn(ib2)
  1410. icornw(ib1,2) = npckgn(ib2)
  1411. icornn(ib2,1) = npckgw(ib1)
  1412. ELSEIF ((jpjwdt(ib1)==jpjnob(ib2)+1).AND.(jpinft(ib2)==jpiwob(ib1))) THEN
  1413. IF(lwp) WRITE(numout,*)
  1414. IF(lwp) WRITE(numout,*) ' E R R O R : Found an acute open boundary corner at point (i,j)= ', &
  1415. & jpinft(ib2), jpjwdt(ib1)
  1416. IF(lwp) WRITE(numout,*) ' ========== Not allowed yet'
  1417. IF(lwp) WRITE(numout,*) ' Crossing problem with West segment: ',npckgw(ib1), &
  1418. & ' and North segment: ',npckgn(ib2)
  1419. IF(lwp) WRITE(numout,*)
  1420. nstop = nstop + 1
  1421. ELSE
  1422. IF(lwp) WRITE(numout,*)
  1423. IF(lwp) WRITE(numout,*) ' E R R O R : Check North and West Open boundary indices'
  1424. IF(lwp) WRITE(numout,*) ' ========== Crossing problem with West segment: ',npckgw(ib1), &
  1425. & ' and North segment: ',npckgn(ib2)
  1426. IF(lwp) WRITE(numout,*)
  1427. nstop = nstop + 1
  1428. END IF
  1429. END IF
  1430. END DO
  1431. END DO
  1432. END IF
  1433. !
  1434. ! North/East crossings
  1435. IF ((nbdysegn > 0).AND.(nbdysege > 0)) THEN
  1436. DO ib1 = 1, nbdysege
  1437. DO ib2 = 1, nbdysegn
  1438. IF (( jpindt(ib2)<=jpieob(ib1)+1).AND. &
  1439. & ( jpinft(ib2)>=jpieob(ib1)+1).AND. &
  1440. & ( jpjedt(ib1)<=jpjnob(ib2)+1).AND. &
  1441. & ( jpjeft(ib1)>=jpjnob(ib2)+1)) THEN
  1442. IF ((jpjeft(ib1)==jpjnob(ib2)+1).AND.(jpinft(ib2)==jpieob(ib1)+1)) THEN
  1443. ! We have a possible North-East corner
  1444. ! WRITE(numout,*) ' Found a North-East corner at (i,j): ', jpinft(ib2), jpjeft(ib1)
  1445. ! WRITE(numout,*) ' between segments: ', npckge(ib1), npckgn(ib2)
  1446. icorne(ib1,2) = npckgn(ib2)
  1447. icornn(ib2,2) = npckge(ib1)
  1448. ELSEIF ((jpjedt(ib1)==jpjnob(ib2)+1).AND.(jpindt(ib2)==jpieob(ib1)+1)) THEN
  1449. IF(lwp) WRITE(numout,*)
  1450. IF(lwp) WRITE(numout,*) ' E R R O R : Found an acute open boundary corner at point (i,j)= ', &
  1451. & jpindt(ib2), jpjedt(ib1)
  1452. IF(lwp) WRITE(numout,*) ' ========== Not allowed yet'
  1453. IF(lwp) WRITE(numout,*) ' Crossing problem with East segment: ',npckge(ib1), &
  1454. & ' and North segment: ',npckgn(ib2)
  1455. IF(lwp) WRITE(numout,*)
  1456. nstop = nstop + 1
  1457. ELSE
  1458. IF(lwp) WRITE(numout,*)
  1459. IF(lwp) WRITE(numout,*) ' E R R O R : Check North and East Open boundary indices'
  1460. IF(lwp) WRITE(numout,*) ' ========== Crossing problem with East segment: ',npckge(ib1), &
  1461. & ' and North segment: ',npckgn(ib2)
  1462. IF(lwp) WRITE(numout,*)
  1463. nstop = nstop + 1
  1464. END IF
  1465. END IF
  1466. END DO
  1467. END DO
  1468. END IF
  1469. !
  1470. ! 3. Check if segment extremities are on land
  1471. !--------------------------------------------
  1472. !
  1473. ! West segments
  1474. DO ib = 1, nbdysegw
  1475. ! get mask at boundary extremities:
  1476. ztestmask(1:2)=0.
  1477. DO ji = 1, jpi
  1478. DO jj = 1, jpj
  1479. IF (((ji + nimpp - 1) == jpiwob(ib)).AND. &
  1480. & ((jj + njmpp - 1) == jpjwdt(ib))) ztestmask(1)=tmask(ji,jj,1)
  1481. IF (((ji + nimpp - 1) == jpiwob(ib)).AND. &
  1482. & ((jj + njmpp - 1) == jpjwft(ib))) ztestmask(2)=tmask(ji,jj,1)
  1483. END DO
  1484. END DO
  1485. IF( lk_mpp ) CALL mpp_sum( ztestmask, 2 ) ! sum over the global domain
  1486. IF (ztestmask(1)==1) THEN
  1487. IF (icornw(ib,1)==0) THEN
  1488. IF(lwp) WRITE(numout,*)
  1489. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckgw(ib)
  1490. IF(lwp) WRITE(numout,*) ' ========== does not start on land or on a corner'
  1491. IF(lwp) WRITE(numout,*)
  1492. nstop = nstop + 1
  1493. ELSE
  1494. ! This is a corner
  1495. IF(lwp) WRITE(numout,*) 'Found a South-West corner at (i,j): ', jpiwob(ib), jpjwdt(ib)
  1496. CALL bdy_ctl_corn(npckgw(ib), icornw(ib,1))
  1497. itest=itest+1
  1498. ENDIF
  1499. ENDIF
  1500. IF (ztestmask(2)==1) THEN
  1501. IF (icornw(ib,2)==0) THEN
  1502. IF(lwp) WRITE(numout,*)
  1503. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckgw(ib)
  1504. IF(lwp) WRITE(numout,*) ' ========== does not end on land or on a corner'
  1505. IF(lwp) WRITE(numout,*)
  1506. nstop = nstop + 1
  1507. ELSE
  1508. ! This is a corner
  1509. IF(lwp) WRITE(numout,*) 'Found a North-West corner at (i,j): ', jpiwob(ib), jpjwft(ib)
  1510. CALL bdy_ctl_corn(npckgw(ib), icornw(ib,2))
  1511. itest=itest+1
  1512. ENDIF
  1513. ENDIF
  1514. END DO
  1515. !
  1516. ! East segments
  1517. DO ib = 1, nbdysege
  1518. ! get mask at boundary extremities:
  1519. ztestmask(1:2)=0.
  1520. DO ji = 1, jpi
  1521. DO jj = 1, jpj
  1522. IF (((ji + nimpp - 1) == jpieob(ib)+1).AND. &
  1523. & ((jj + njmpp - 1) == jpjedt(ib))) ztestmask(1)=tmask(ji,jj,1)
  1524. IF (((ji + nimpp - 1) == jpieob(ib)+1).AND. &
  1525. & ((jj + njmpp - 1) == jpjeft(ib))) ztestmask(2)=tmask(ji,jj,1)
  1526. END DO
  1527. END DO
  1528. IF( lk_mpp ) CALL mpp_sum( ztestmask, 2 ) ! sum over the global domain
  1529. IF (ztestmask(1)==1) THEN
  1530. IF (icorne(ib,1)==0) THEN
  1531. IF(lwp) WRITE(numout,*)
  1532. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckge(ib)
  1533. IF(lwp) WRITE(numout,*) ' ========== does not start on land or on a corner'
  1534. IF(lwp) WRITE(numout,*)
  1535. nstop = nstop + 1
  1536. ELSE
  1537. ! This is a corner
  1538. IF(lwp) WRITE(numout,*) 'Found a South-East corner at (i,j): ', jpieob(ib)+1, jpjedt(ib)
  1539. CALL bdy_ctl_corn(npckge(ib), icorne(ib,1))
  1540. itest=itest+1
  1541. ENDIF
  1542. ENDIF
  1543. IF (ztestmask(2)==1) THEN
  1544. IF (icorne(ib,2)==0) THEN
  1545. IF(lwp) WRITE(numout,*)
  1546. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckge(ib)
  1547. IF(lwp) WRITE(numout,*) ' ========== does not end on land or on a corner'
  1548. IF(lwp) WRITE(numout,*)
  1549. nstop = nstop + 1
  1550. ELSE
  1551. ! This is a corner
  1552. IF(lwp) WRITE(numout,*) 'Found a North-East corner at (i,j): ', jpieob(ib)+1, jpjeft(ib)
  1553. CALL bdy_ctl_corn(npckge(ib), icorne(ib,2))
  1554. itest=itest+1
  1555. ENDIF
  1556. ENDIF
  1557. END DO
  1558. !
  1559. ! South segments
  1560. DO ib = 1, nbdysegs
  1561. ! get mask at boundary extremities:
  1562. ztestmask(1:2)=0.
  1563. DO ji = 1, jpi
  1564. DO jj = 1, jpj
  1565. IF (((jj + njmpp - 1) == jpjsob(ib)).AND. &
  1566. & ((ji + nimpp - 1) == jpisdt(ib))) ztestmask(1)=tmask(ji,jj,1)
  1567. IF (((jj + njmpp - 1) == jpjsob(ib)).AND. &
  1568. & ((ji + nimpp - 1) == jpisft(ib))) ztestmask(2)=tmask(ji,jj,1)
  1569. END DO
  1570. END DO
  1571. IF( lk_mpp ) CALL mpp_sum( ztestmask, 2 ) ! sum over the global domain
  1572. IF ((ztestmask(1)==1).AND.(icorns(ib,1)==0)) THEN
  1573. IF(lwp) WRITE(numout,*)
  1574. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckgs(ib)
  1575. IF(lwp) WRITE(numout,*) ' ========== does not start on land or on a corner'
  1576. IF(lwp) WRITE(numout,*)
  1577. nstop = nstop + 1
  1578. ENDIF
  1579. IF ((ztestmask(2)==1).AND.(icorns(ib,2)==0)) THEN
  1580. IF(lwp) WRITE(numout,*)
  1581. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckgs(ib)
  1582. IF(lwp) WRITE(numout,*) ' ========== does not end on land or on a corner'
  1583. IF(lwp) WRITE(numout,*)
  1584. nstop = nstop + 1
  1585. ENDIF
  1586. END DO
  1587. !
  1588. ! North segments
  1589. DO ib = 1, nbdysegn
  1590. ! get mask at boundary extremities:
  1591. ztestmask(1:2)=0.
  1592. DO ji = 1, jpi
  1593. DO jj = 1, jpj
  1594. IF (((jj + njmpp - 1) == jpjnob(ib)+1).AND. &
  1595. & ((ji + nimpp - 1) == jpindt(ib))) ztestmask(1)=tmask(ji,jj,1)
  1596. IF (((jj + njmpp - 1) == jpjnob(ib)+1).AND. &
  1597. & ((ji + nimpp - 1) == jpinft(ib))) ztestmask(2)=tmask(ji,jj,1)
  1598. END DO
  1599. END DO
  1600. IF( lk_mpp ) CALL mpp_sum( ztestmask, 2 ) ! sum over the global domain
  1601. IF ((ztestmask(1)==1).AND.(icornn(ib,1)==0)) THEN
  1602. IF(lwp) WRITE(numout,*)
  1603. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckgn(ib)
  1604. IF(lwp) WRITE(numout,*) ' ========== does not start on land'
  1605. IF(lwp) WRITE(numout,*)
  1606. nstop = nstop + 1
  1607. ENDIF
  1608. IF ((ztestmask(2)==1).AND.(icornn(ib,2)==0)) THEN
  1609. IF(lwp) WRITE(numout,*)
  1610. IF(lwp) WRITE(numout,*) ' E R R O R : Open boundary segment ', npckgn(ib)
  1611. IF(lwp) WRITE(numout,*) ' ========== does not end on land'
  1612. IF(lwp) WRITE(numout,*)
  1613. nstop = nstop + 1
  1614. ENDIF
  1615. END DO
  1616. !
  1617. IF ((itest==0).AND.(lwp)) WRITE(numout,*) 'NO open boundary corner found'
  1618. !
  1619. ! Other tests TBD:
  1620. ! segments completly on land
  1621. ! optimized open boundary array length according to landmask
  1622. ! Nudging layers that overlap with interior domain
  1623. !
  1624. END SUBROUTINE bdy_ctl_seg
  1625. SUBROUTINE bdy_ctl_corn( ib1, ib2 )
  1626. !!----------------------------------------------------------------------
  1627. !! *** ROUTINE bdy_ctl_corn ***
  1628. !!
  1629. !! ** Purpose : Check numerical schemes consistency between
  1630. !! segments having a common corner
  1631. !!
  1632. !! ** Method :
  1633. !!----------------------------------------------------------------------
  1634. INTEGER, INTENT(in) :: ib1, ib2
  1635. INTEGER :: itest
  1636. !!----------------------------------------------------------------------
  1637. itest = 0
  1638. IF (cn_dyn2d(ib1)/=cn_dyn2d(ib2)) itest = itest + 1
  1639. IF (cn_dyn3d(ib1)/=cn_dyn3d(ib2)) itest = itest + 1
  1640. IF (cn_tra(ib1)/=cn_tra(ib2)) itest = itest + 1
  1641. !
  1642. IF (nn_dyn2d_dta(ib1)/=nn_dyn2d_dta(ib2)) itest = itest + 1
  1643. IF (nn_dyn3d_dta(ib1)/=nn_dyn3d_dta(ib2)) itest = itest + 1
  1644. IF (nn_tra_dta(ib1)/=nn_tra_dta(ib2)) itest = itest + 1
  1645. !
  1646. IF (nn_rimwidth(ib1)/=nn_rimwidth(ib2)) itest = itest + 1
  1647. !
  1648. IF ( itest>0 ) THEN
  1649. IF(lwp) WRITE(numout,*) ' E R R O R : Segments ', ib1, 'and ', ib2
  1650. IF(lwp) WRITE(numout,*) ' ========== have different open bdy schemes'
  1651. IF(lwp) WRITE(numout,*)
  1652. nstop = nstop + 1
  1653. ENDIF
  1654. !
  1655. END SUBROUTINE bdy_ctl_corn
  1656. #else
  1657. !!---------------------------------------------------------------------------------
  1658. !! Dummy module NO open boundaries
  1659. !!---------------------------------------------------------------------------------
  1660. CONTAINS
  1661. SUBROUTINE bdy_init ! Dummy routine
  1662. END SUBROUTINE bdy_init
  1663. #endif
  1664. !!=================================================================================
  1665. END MODULE bdyini