Skip to content
Snippets Groups Projects
bdyini.F90 109 KiB
Newer Older
Guillaume Samson's avatar
Guillaume Samson committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
MODULE bdyini
   !!======================================================================
   !!                       ***  MODULE  bdyini  ***
   !! Unstructured open boundaries : initialisation
   !!======================================================================
   !! History :  1.0  !  2005-01  (J. Chanut, A. Sellar)  Original code
   !!             -   !  2007-01  (D. Storkey) Update to use IOM module
   !!             -   !  2007-01  (D. Storkey) Tidal forcing
   !!            3.0  !  2008-04  (NEMO team)  add in the reference version
   !!            3.3  !  2010-09  (E.O'Dea) updates for Shelf configurations
   !!            3.3  !  2010-09  (D.Storkey) add ice boundary conditions
   !!            3.4  !  2011     (D. Storkey) rewrite in preparation for OBC-BDY merge
   !!            3.4  !  2012     (J. Chanut) straight open boundary case update
   !!            3.5  !  2012     (S. Mocavero, I. Epicoco) optimization of BDY communications
   !!            3.7  !  2016     (T. Lovato) Remove bdy macro, call here init for dta and tides
   !!----------------------------------------------------------------------
   !!   bdy_init      : Initialization of unstructured open boundaries
   !!----------------------------------------------------------------------
   USE oce            ! ocean dynamics and tracers variables
   USE dom_oce        ! ocean space and time domain
   USE sbc_oce , ONLY: nn_ice
   USE bdy_oce        ! unstructured open boundary conditions
   USE bdydta         ! open boundary cond. setting   (bdy_dta_init routine)
   USE bdytides       ! open boundary cond. setting   (bdytide_init routine)
   USE tide_mod, ONLY: ln_tide ! tidal forcing
   USE phycst  , ONLY: rday
   !
   USE in_out_manager ! I/O units
   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
   USE lib_mpp        ! for mpp_sum  
   USE iom            ! I/O

   IMPLICIT NONE
   PRIVATE

   PUBLIC   bdy_init    ! routine called in nemo_init
   PUBLIC   find_neib   ! routine called in bdy_nmn

   INTEGER, PARAMETER ::   jp_nseg = 100   ! 
   ! Straight open boundary segment parameters:
   INTEGER  ::   nbdysege, nbdysegw, nbdysegn, nbdysegs 
   INTEGER, DIMENSION(jp_nseg) ::   jpieob, jpjedt, jpjeft, npckge   !
   INTEGER, DIMENSION(jp_nseg) ::   jpiwob, jpjwdt, jpjwft, npckgw   !
   INTEGER, DIMENSION(jp_nseg) ::   jpjnob, jpindt, jpinft, npckgn   !
   INTEGER, DIMENSION(jp_nseg) ::   jpjsob, jpisdt, jpisft, npckgs   !
   
   !! * Substitutions
#  include "do_loop_substitute.h90"
   !!----------------------------------------------------------------------
   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
   !! $Id: bdyini.F90 15368 2021-10-14 08:25:34Z smasson $ 
   !! Software governed by the CeCILL license (see ./LICENSE)
   !!----------------------------------------------------------------------
CONTAINS

   SUBROUTINE bdy_init
      !!----------------------------------------------------------------------
      !!                 ***  ROUTINE bdy_init  ***
      !!
      !! ** Purpose :   Initialization of the dynamics and tracer fields with
      !!              unstructured open boundaries.
      !!
      !! ** Method  :   Read initialization arrays (mask, indices) to identify
      !!              an unstructured open boundary
      !!
      !! ** Input   :  bdy_init.nc, input file for unstructured open boundaries
      !!----------------------------------------------------------------------
      NAMELIST/nambdy/ ln_bdy, nb_bdy, ln_coords_file, cn_coords_file,         &
         &             ln_mask_file, cn_mask_file, cn_dyn2d, nn_dyn2d_dta,     &
         &             cn_dyn3d, nn_dyn3d_dta, cn_tra, nn_tra_dta,             &
         &             ln_tra_dmp, ln_dyn3d_dmp, rn_time_dmp, rn_time_dmp_out, &
         &             cn_ice, nn_ice_dta,                                     &
         &             ln_vol, nn_volctl, nn_rimwidth
         !
      INTEGER  ::   ios                 ! Local integer output status for namelist read
      !!----------------------------------------------------------------------

      ! ------------------------
      ! Read namelist parameters
      ! ------------------------
      READ  ( numnam_ref, nambdy, IOSTAT = ios, ERR = 901)
901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'nambdy in reference namelist' )
      ! make sur that all elements of the namelist variables have a default definition from namelist_ref
      ln_coords_file (2:jp_bdy) = ln_coords_file (1)
      cn_coords_file (2:jp_bdy) = cn_coords_file (1)
      cn_dyn2d       (2:jp_bdy) = cn_dyn2d       (1)
      nn_dyn2d_dta   (2:jp_bdy) = nn_dyn2d_dta   (1)
      cn_dyn3d       (2:jp_bdy) = cn_dyn3d       (1)
      nn_dyn3d_dta   (2:jp_bdy) = nn_dyn3d_dta   (1)
      cn_tra         (2:jp_bdy) = cn_tra         (1)
      nn_tra_dta     (2:jp_bdy) = nn_tra_dta     (1)    
      ln_tra_dmp     (2:jp_bdy) = ln_tra_dmp     (1)
      ln_dyn3d_dmp   (2:jp_bdy) = ln_dyn3d_dmp   (1)
      rn_time_dmp    (2:jp_bdy) = rn_time_dmp    (1)
      rn_time_dmp_out(2:jp_bdy) = rn_time_dmp_out(1)
      cn_ice         (2:jp_bdy) = cn_ice         (1)
      nn_ice_dta     (2:jp_bdy) = nn_ice_dta     (1)
      READ  ( numnam_cfg, nambdy, IOSTAT = ios, ERR = 902 )
902   IF( ios >  0 )   CALL ctl_nam ( ios , 'nambdy in configuration namelist' )
      IF(lwm) WRITE ( numond, nambdy )

      IF( .NOT. Agrif_Root() ) ln_bdy = .FALSE.   ! forced for Agrif children

      IF( nb_bdy == 0 ) ln_bdy = .FALSE.
      
      ! -----------------------------------------
      ! unstructured open boundaries use control
      ! -----------------------------------------
      IF ( ln_bdy ) THEN
         IF(lwp) WRITE(numout,*)
         IF(lwp) WRITE(numout,*) 'bdy_init : initialization of open boundaries'
         IF(lwp) WRITE(numout,*) '~~~~~~~~'
         !
         ! Open boundaries definition (arrays and masks)
         CALL bdy_def
         IF( ln_meshmask )   CALL bdy_meshwri()
         !
         ! Open boundaries initialisation of external data arrays
         CALL bdy_dta_init
         !
         ! Open boundaries initialisation of tidal harmonic forcing
         IF( ln_tide ) CALL bdytide_init
         !
      ELSE
         IF(lwp) WRITE(numout,*)
         IF(lwp) WRITE(numout,*) 'bdy_init : open boundaries not used (ln_bdy = F)'
         IF(lwp) WRITE(numout,*) '~~~~~~~~'
         !
      ENDIF
      !
   END SUBROUTINE bdy_init


   SUBROUTINE bdy_def
      !!----------------------------------------------------------------------
      !!                 ***  ROUTINE bdy_init  ***
      !!         
      !! ** Purpose :   Definition of unstructured open boundaries.
      !!
      !! ** Method  :   Read initialization arrays (mask, indices) to identify 
      !!              an unstructured open boundary
      !!
      !! ** Input   :  bdy_init.nc, input file for unstructured open boundaries
      !!----------------------------------------------------------------------      
      INTEGER  ::   ji, jj                                 ! dummy loop indices
      INTEGER  ::   ib_bdy, ii, ij, igrd, ib, ir, iseg     ! dummy loop indices
      INTEGER  ::   icount, icountr, icountr0, ibr_max     ! local integers
      INTEGER  ::   ilen1                           !   -       -
      INTEGER  ::   iiRst, iiRnd, iiSst, iiSnd, iiSstdiag, iiSnddiag, iiSstsono, iiSndsono
      INTEGER  ::   ijRst, ijRnd, ijSst, ijSnd, ijSstdiag, ijSnddiag, ijSstsono, ijSndsono
      INTEGER  ::   iiout, ijout, iioutdir, ijoutdir, icnt
      INTEGER  ::   iRnei, iRdiag, iRsono
      INTEGER  ::   iSnei, iSdiag, iSsono                  !   -       -
      INTEGER  ::   iwe, ies, iso, ino, inum, id_dummy     !   -       -
      INTEGER  ::   jpbdta                                 !   -       -
      INTEGER  ::   ib_bdy1, ib_bdy2, ib1, ib2             !   -       -
      INTEGER  ::   ii1, ii2, ii3, ij1, ij2, ij3           !   -       -
      INTEGER  ::   iibe, ijbe, iibi, ijbi                 !   -       -
      INTEGER  ::   flagu, flagv                           ! short cuts
      INTEGER  ::   nbdyind, nbdybeg, nbdyend
      INTEGER              , DIMENSION(4)             ::   kdimsz
      INTEGER              , DIMENSION(jpbgrd,jp_bdy) ::   nblendta          ! Length of index arrays 
      INTEGER,  ALLOCATABLE, DIMENSION(:,:,:)         ::   nbidta, nbjdta    ! Index arrays: i and j indices of bdy dta
      INTEGER,  ALLOCATABLE, DIMENSION(:,:,:)         ::   nbrdta            ! Discrete distance from rim points
      CHARACTER(LEN=1)     , DIMENSION(jpbgrd)        ::   cgrid
      REAL(wp), ALLOCATABLE, DIMENSION(:,:)     ::   zz_read                 ! work space for 2D global boundary data
      REAL(wp), POINTER    , DIMENSION(:,:)     ::   zmask                   ! pointer to 2D mask fields
      REAL(wp)             , DIMENSION(jpi,jpj) ::   zfmask   ! temporary fmask array excluding coastal boundary condition (shlat)
      REAL(wp)             , DIMENSION(jpi,jpj) ::   ztmask, zumask, zvmask  ! temporary u/v mask array
      REAL(wp)             , DIMENSION(jpi,jpj) ::   zzbdy
      !!----------------------------------------------------------------------
      !
      cgrid = (/'t','u','v'/)

      ! -----------------------------------------
      ! Check and write out namelist parameters
      ! -----------------------------------------
      
      IF(lwp) WRITE(numout,*) 'Number of open boundary sets : ', nb_bdy

      DO ib_bdy = 1,nb_bdy

         IF(lwp) THEN
            WRITE(numout,*) ' ' 
            WRITE(numout,*) '------ Open boundary data set ',ib_bdy,' ------' 
            IF( ln_coords_file(ib_bdy) ) THEN
               WRITE(numout,*) 'Boundary definition read from file '//TRIM(cn_coords_file(ib_bdy))
            ELSE
               WRITE(numout,*) 'Boundary defined in namelist.'
            ENDIF
            WRITE(numout,*)
         ENDIF

         ! barotropic bdy
         !----------------
         IF(lwp) THEN
            WRITE(numout,*) 'Boundary conditions for barotropic solution:  '
            SELECT CASE( cn_dyn2d(ib_bdy) )                  
            CASE( 'none' )           ;   WRITE(numout,*) '      no open boundary condition'        
            CASE( 'frs' )            ;   WRITE(numout,*) '      Flow Relaxation Scheme'
            CASE( 'flather' )        ;   WRITE(numout,*) '      Flather radiation condition'
            CASE( 'orlanski' )       ;   WRITE(numout,*) '      Orlanski (fully oblique) radiation condition with adaptive nudging'
            CASE( 'orlanski_npo' )   ;   WRITE(numout,*) '      Orlanski (NPO) radiation condition with adaptive nudging'
            CASE DEFAULT             ;   CALL ctl_stop( 'unrecognised value for cn_dyn2d' )
            END SELECT
         ENDIF

         dta_bdy(ib_bdy)%lneed_ssh   = cn_dyn2d(ib_bdy) == 'flather'
         dta_bdy(ib_bdy)%lneed_dyn2d = cn_dyn2d(ib_bdy) /= 'none'

         IF( lwp .AND. dta_bdy(ib_bdy)%lneed_dyn2d ) THEN
            SELECT CASE( nn_dyn2d_dta(ib_bdy) )                   ! 
            CASE( 0 )      ;   WRITE(numout,*) '      initial state used for bdy data'        
            CASE( 1 )      ;   WRITE(numout,*) '      boundary data taken from file'
            CASE( 2 )      ;   WRITE(numout,*) '      tidal harmonic forcing taken from file'
            CASE( 3 )      ;   WRITE(numout,*) '      boundary data AND tidal harmonic forcing taken from files'
            CASE DEFAULT   ;   CALL ctl_stop( 'nn_dyn2d_dta must be between 0 and 3' )
            END SELECT
         ENDIF
         IF ( dta_bdy(ib_bdy)%lneed_dyn2d .AND. nn_dyn2d_dta(ib_bdy) .GE. 2  .AND. .NOT.ln_tide ) THEN
            CALL ctl_stop( 'You must activate with ln_tide to add tidal forcing at open boundaries' )
         ENDIF
         IF(lwp) WRITE(numout,*)

         ! baroclinic bdy
         !----------------
         IF(lwp) THEN
            WRITE(numout,*) 'Boundary conditions for baroclinic velocities:  '
            SELECT CASE( cn_dyn3d(ib_bdy) )                  
            CASE('none')           ;   WRITE(numout,*) '      no open boundary condition'        
            CASE('frs')            ;   WRITE(numout,*) '      Flow Relaxation Scheme'
            CASE('specified')      ;   WRITE(numout,*) '      Specified value'
            CASE('neumann')        ;   WRITE(numout,*) '      Neumann conditions'
            CASE('zerograd')       ;   WRITE(numout,*) '      Zero gradient for baroclinic velocities'
            CASE('zero')           ;   WRITE(numout,*) '      Zero baroclinic velocities (runoff case)'
            CASE('orlanski')       ;   WRITE(numout,*) '      Orlanski (fully oblique) radiation condition with adaptive nudging'
            CASE('orlanski_npo')   ;   WRITE(numout,*) '      Orlanski (NPO) radiation condition with adaptive nudging'
            CASE DEFAULT   ;   CALL ctl_stop( 'unrecognised value for cn_dyn3d' )
            END SELECT
         ENDIF

         dta_bdy(ib_bdy)%lneed_dyn3d = cn_dyn3d(ib_bdy) == 'frs'      .OR. cn_dyn3d(ib_bdy) == 'specified'   &
            &                     .OR. cn_dyn3d(ib_bdy) == 'orlanski' .OR. cn_dyn3d(ib_bdy) == 'orlanski_npo'

         IF( lwp .AND. dta_bdy(ib_bdy)%lneed_dyn3d ) THEN
            SELECT CASE( nn_dyn3d_dta(ib_bdy) )                   ! 
            CASE( 0 )      ;   WRITE(numout,*) '      initial state used for bdy data'        
            CASE( 1 )      ;   WRITE(numout,*) '      boundary data taken from file'
            CASE DEFAULT   ;   CALL ctl_stop( 'nn_dyn3d_dta must be 0 or 1' )
            END SELECT
         END IF

         IF ( ln_dyn3d_dmp(ib_bdy) ) THEN
            IF ( cn_dyn3d(ib_bdy) == 'none' ) THEN
               IF(lwp) WRITE(numout,*) 'No open boundary condition for baroclinic velocities: ln_dyn3d_dmp is set to .false.'
               ln_dyn3d_dmp(ib_bdy) = .false.
            ELSEIF ( cn_dyn3d(ib_bdy) == 'frs' ) THEN
               CALL ctl_stop( 'Use FRS OR relaxation' )
            ELSE
               IF(lwp) WRITE(numout,*) '      + baroclinic velocities relaxation zone'
               IF(lwp) WRITE(numout,*) '      Damping time scale: ',rn_time_dmp(ib_bdy),' days'
               IF(rn_time_dmp(ib_bdy)<0) CALL ctl_stop( 'Time scale must be positive' )
               dta_bdy(ib_bdy)%lneed_dyn3d = .TRUE.
            ENDIF
         ELSE
            IF(lwp) WRITE(numout,*) '      NO relaxation on baroclinic velocities'
         ENDIF
         IF(lwp) WRITE(numout,*)

         !    tra bdy
         !----------------
         IF(lwp) THEN
            WRITE(numout,*) 'Boundary conditions for temperature and salinity:  '
            SELECT CASE( cn_tra(ib_bdy) )                  
            CASE('none')           ;   WRITE(numout,*) '      no open boundary condition'        
            CASE('frs')            ;   WRITE(numout,*) '      Flow Relaxation Scheme'
            CASE('specified')      ;   WRITE(numout,*) '      Specified value'
            CASE('neumann')        ;   WRITE(numout,*) '      Neumann conditions'
            CASE('runoff')         ;   WRITE(numout,*) '      Runoff conditions : Neumann for T and specified to 0.1 for salinity'
            CASE('orlanski')       ;   WRITE(numout,*) '      Orlanski (fully oblique) radiation condition with adaptive nudging'
            CASE('orlanski_npo')   ;   WRITE(numout,*) '      Orlanski (NPO) radiation condition with adaptive nudging'
            CASE DEFAULT           ;   CALL ctl_stop( 'unrecognised value for cn_tra' )
            END SELECT
         ENDIF

         dta_bdy(ib_bdy)%lneed_tra = cn_tra(ib_bdy) == 'frs'       .OR. cn_tra(ib_bdy) == 'specified'   &
            &                   .OR. cn_tra(ib_bdy) == 'orlanski'  .OR. cn_tra(ib_bdy) == 'orlanski_npo' 

         IF( lwp .AND. dta_bdy(ib_bdy)%lneed_tra ) THEN
            SELECT CASE( nn_tra_dta(ib_bdy) )                   ! 
            CASE( 0 )      ;   WRITE(numout,*) '      initial state used for bdy data'        
            CASE( 1 )      ;   WRITE(numout,*) '      boundary data taken from file'
            CASE DEFAULT   ;   CALL ctl_stop( 'nn_tra_dta must be 0 or 1' )
            END SELECT
         ENDIF

         IF ( ln_tra_dmp(ib_bdy) ) THEN
            IF ( cn_tra(ib_bdy) == 'none' ) THEN
               IF(lwp) WRITE(numout,*) 'No open boundary condition for tracers: ln_tra_dmp is set to .false.'
               ln_tra_dmp(ib_bdy) = .false.
            ELSEIF ( cn_tra(ib_bdy) == 'frs' ) THEN
               CALL ctl_stop( 'Use FRS OR relaxation' )
            ELSE
               IF(lwp) WRITE(numout,*) '      + T/S relaxation zone'
               IF(lwp) WRITE(numout,*) '      Damping time scale: ',rn_time_dmp(ib_bdy),' days'
               IF(lwp) WRITE(numout,*) '      Outflow damping time scale: ',rn_time_dmp_out(ib_bdy),' days'
               IF(lwp.AND.rn_time_dmp(ib_bdy)<0) CALL ctl_stop( 'Time scale must be positive' )
               dta_bdy(ib_bdy)%lneed_tra = .TRUE.
            ENDIF
         ELSE
            IF(lwp) WRITE(numout,*) '      NO T/S relaxation'
         ENDIF
         IF(lwp) WRITE(numout,*)

#if defined key_si3
         IF(lwp) THEN
            WRITE(numout,*) 'Boundary conditions for sea ice:  '
            SELECT CASE( cn_ice(ib_bdy) )                  
            CASE('none')   ;   WRITE(numout,*) '      no open boundary condition'        
            CASE('frs')    ;   WRITE(numout,*) '      Flow Relaxation Scheme'
            CASE DEFAULT   ;   CALL ctl_stop( 'unrecognised value for cn_ice' )
            END SELECT
         ENDIF

         dta_bdy(ib_bdy)%lneed_ice = cn_ice(ib_bdy) /= 'none'

         IF( dta_bdy(ib_bdy)%lneed_ice .AND. nn_ice /= 2 ) THEN
            WRITE(ctmp1,*) 'bdy number ', ib_bdy,', needs ice model but nn_ice = ', nn_ice
            CALL ctl_stop( ctmp1 )
         ENDIF

         IF( lwp .AND. dta_bdy(ib_bdy)%lneed_ice ) THEN 
            SELECT CASE( nn_ice_dta(ib_bdy) )                   ! 
            CASE( 0 )      ;   WRITE(numout,*) '      initial state used for bdy data'        
            CASE( 1 )      ;   WRITE(numout,*) '      boundary data taken from file'
            CASE DEFAULT   ;   CALL ctl_stop( 'nn_ice_dta must be 0 or 1' )
            END SELECT
         ENDIF
#else
         dta_bdy(ib_bdy)%lneed_ice = .FALSE.
#endif
         !
         IF(lwp) WRITE(numout,*)
         IF(lwp) WRITE(numout,*) '      Width of relaxation zone = ', nn_rimwidth(ib_bdy)
         IF(lwp) WRITE(numout,*)
         !
      END DO   ! nb_bdy

      IF( lwp ) THEN
         IF( ln_vol ) THEN                     ! check volume conservation (nn_volctl value)
            WRITE(numout,*) 'Volume correction applied at open boundaries'
            WRITE(numout,*)
            SELECT CASE ( nn_volctl )
            CASE( 1 )      ;   WRITE(numout,*) '      The total volume will be constant'
            CASE( 0 )      ;   WRITE(numout,*) '      The total volume will vary according to the surface E-P flux'
            CASE DEFAULT   ;   CALL ctl_stop( 'nn_volctl must be 0 or 1' )
            END SELECT
            WRITE(numout,*)
            !
            ! sanity check if used with tides        
            IF( ln_tide ) THEN 
               WRITE(numout,*) ' The total volume correction is not working with tides. '
               WRITE(numout,*) ' Set ln_vol to .FALSE. '
               WRITE(numout,*) ' or '
               WRITE(numout,*) ' equilibriate your bdy input files '
               CALL ctl_stop( 'The total volume correction is not working with tides.' )
            END IF
         ELSE
            WRITE(numout,*) 'No volume correction applied at open boundaries'
            WRITE(numout,*)
         ENDIF
      ENDIF

      ! -------------------------------------------------
      ! Initialise indices arrays for open boundaries
      ! -------------------------------------------------

      nblendta(:,:) = 0
      nbdysege = 0
      nbdysegw = 0
      nbdysegn = 0
      nbdysegs = 0

      ! Define all boundaries 
      ! ---------------------
      DO ib_bdy = 1, nb_bdy
         !
         IF( .NOT. ln_coords_file(ib_bdy) ) THEN     ! build bdy coordinates with segments defined in namelist

            CALL bdy_read_seg( ib_bdy, nblendta(:,ib_bdy) )

         ELSE                                        ! Read size of arrays in boundary coordinates file.
            
            CALL iom_open( cn_coords_file(ib_bdy), inum )
            DO igrd = 1, jpbgrd
               id_dummy = iom_varid( inum, 'nbi'//cgrid(igrd), kdimsz=kdimsz )  
               nblendta(igrd,ib_bdy) = MAXVAL(kdimsz)
            END DO
            CALL iom_close( inum )
         ENDIF
         !
      END DO ! ib_bdy

      ! Now look for crossings in user (namelist) defined open boundary segments:
      IF( nbdysege > 0 .OR. nbdysegw > 0 .OR. nbdysegn > 0 .OR. nbdysegs > 0)   CALL bdy_ctl_seg
      
      ! Allocate arrays
      !---------------
      jpbdta = MAXVAL(nblendta(1:jpbgrd,1:nb_bdy))
      ALLOCATE( nbidta(jpbdta, jpbgrd, nb_bdy), nbjdta(jpbdta, jpbgrd, nb_bdy), nbrdta(jpbdta, jpbgrd, nb_bdy) )
      nbrdta(:,:,:) = 0   ! initialize nbrdta as it may not be completely defined for each bdy
      
      ! Calculate global boundary index arrays or read in from file
      !------------------------------------------------------------               
      ! 1. Read global index arrays from boundary coordinates file.
      DO ib_bdy = 1, nb_bdy
         !
         IF( ln_coords_file(ib_bdy) ) THEN
            !
            ALLOCATE( zz_read( MAXVAL(nblendta), 1 ) )          
            CALL iom_open( cn_coords_file(ib_bdy), inum )
            !
            DO igrd = 1, jpbgrd
               CALL iom_get( inum, jpdom_unknown, 'nbi'//cgrid(igrd), zz_read(1:nblendta(igrd,ib_bdy),:) )
               DO ii = 1,nblendta(igrd,ib_bdy)
                  nbidta(ii,igrd,ib_bdy) = NINT( zz_read(ii,1) ) + nn_hls
               END DO
               CALL iom_get( inum, jpdom_unknown, 'nbj'//cgrid(igrd), zz_read(1:nblendta(igrd,ib_bdy),:) )
               DO ii = 1,nblendta(igrd,ib_bdy)
                  nbjdta(ii,igrd,ib_bdy) = NINT( zz_read(ii,1) ) + nn_hls
               END DO
               CALL iom_get( inum, jpdom_unknown, 'nbr'//cgrid(igrd), zz_read(1:nblendta(igrd,ib_bdy),:) )
               DO ii = 1,nblendta(igrd,ib_bdy)
                  nbrdta(ii,igrd,ib_bdy) = NINT( zz_read(ii,1) )
               END DO
               !
               ibr_max = MAXVAL( nbrdta(:,igrd,ib_bdy) )
               IF(lwp) WRITE(numout,*)
               IF(lwp) WRITE(numout,*) ' Maximum rimwidth in file is ', ibr_max
               IF(lwp) WRITE(numout,*) ' nn_rimwidth from namelist is ', nn_rimwidth(ib_bdy)
               IF (ibr_max < nn_rimwidth(ib_bdy))   &
                  CALL ctl_stop( 'nn_rimwidth is larger than maximum rimwidth in file',cn_coords_file(ib_bdy) )
            END DO
            !
            CALL iom_close( inum )
            DEALLOCATE( zz_read )
            !
         ENDIF
         !
      END DO

      ! 2. Now fill indices corresponding to straight open boundary arrays:
      CALL bdy_coords_seg( nbidta, nbjdta, nbrdta )

      !  Deal with duplicated points
      !-----------------------------
      ! We assign negative indices to duplicated points (to remove them from bdy points to be updated)
      ! if their distance to the bdy is greater than the other
      ! If their distance are the same, just keep only one to avoid updating a point twice
      DO igrd = 1, jpbgrd
         DO ib_bdy1 = 1, nb_bdy
            DO ib_bdy2 = 1, nb_bdy
               IF (ib_bdy1/=ib_bdy2) THEN
                  DO ib1 = 1, nblendta(igrd,ib_bdy1)
                     DO ib2 = 1, nblendta(igrd,ib_bdy2)
                        IF ((nbidta(ib1, igrd, ib_bdy1)==nbidta(ib2, igrd, ib_bdy2)).AND. &
                           &   (nbjdta(ib1, igrd, ib_bdy1)==nbjdta(ib2, igrd, ib_bdy2))) THEN
                           !                           IF ((lwp).AND.(igrd==1)) WRITE(numout,*) ' found coincident point ji, jj:', & 
                           !                                                       &              nbidta(ib1, igrd, ib_bdy1),      & 
                           !                                                       &              nbjdta(ib2, igrd, ib_bdy2)
                           ! keep only points with the lowest distance to boundary:
                           IF (nbrdta(ib1, igrd, ib_bdy1)<nbrdta(ib2, igrd, ib_bdy2)) THEN
                              nbidta(ib2, igrd, ib_bdy2) =-ib_bdy2
                              nbjdta(ib2, igrd, ib_bdy2) =-ib_bdy2
                           ELSEIF (nbrdta(ib1, igrd, ib_bdy1)>nbrdta(ib2, igrd, ib_bdy2)) THEN
                              nbidta(ib1, igrd, ib_bdy1) =-ib_bdy1
                              nbjdta(ib1, igrd, ib_bdy1) =-ib_bdy1
                              ! Arbitrary choice if distances are the same:
                           ELSE
                              nbidta(ib1, igrd, ib_bdy1) =-ib_bdy1
                              nbjdta(ib1, igrd, ib_bdy1) =-ib_bdy1
                           ENDIF
                        END IF
                     END DO
                  END DO
               ENDIF
            END DO
         END DO
      END DO
      !
      ! Find lenght of boundaries and rim on local mpi domain
      !------------------------------------------------------
      !
      iwe = mig(1)
      ies = mig(jpi)
      iso = mjg(1) 
      ino = mjg(jpj) 
      !
      DO ib_bdy = 1, nb_bdy
         DO igrd = 1, jpbgrd
            icount   = 0   ! initialization of local bdy length
            icountr  = 0   ! initialization of local rim 0 and rim 1 bdy length
            icountr0 = 0   ! initialization of local rim 0 bdy length
            idx_bdy(ib_bdy)%nblen(igrd)     = 0
            idx_bdy(ib_bdy)%nblenrim(igrd)  = 0
            idx_bdy(ib_bdy)%nblenrim0(igrd) = 0
            DO ib = 1, nblendta(igrd,ib_bdy)
               ! check that data is in correct order in file
               IF( ib > 1 ) THEN
                  IF( nbrdta(ib,igrd,ib_bdy) < nbrdta(ib-1,igrd,ib_bdy) ) THEN
                     CALL ctl_stop('bdy_segs : ERROR : boundary data in file must be defined ', &
                        &        ' in order of distance from edge nbr A utility for re-ordering ', &
                        &        ' boundary coordinates and data files exists in the TOOLS/OBC directory')
                  ENDIF
               ENDIF
               ! check if point is in local domain
               IF(  nbidta(ib,igrd,ib_bdy) >= iwe .AND. nbidta(ib,igrd,ib_bdy) <= ies .AND.   &
                  & nbjdta(ib,igrd,ib_bdy) >= iso .AND. nbjdta(ib,igrd,ib_bdy) <= ino      ) THEN
                  !
                  icount = icount + 1
                  IF( nbrdta(ib,igrd,ib_bdy) == 1 .OR. nbrdta(ib,igrd,ib_bdy) == 0 )   icountr = icountr + 1
                  IF( nbrdta(ib,igrd,ib_bdy) == 0 )   icountr0 = icountr0 + 1
               ENDIF
            END DO
            idx_bdy(ib_bdy)%nblen    (igrd) = icount   !: length of boundary data on each proc
            idx_bdy(ib_bdy)%nblenrim (igrd) = icountr  !: length of rim 0 and rim 1 boundary data on each proc   
            idx_bdy(ib_bdy)%nblenrim0(igrd) = icountr0 !: length of rim 0 boundary data on each proc     
         END DO   ! igrd

         ! Allocate index arrays for this boundary set
         !--------------------------------------------
         ilen1 = MAXVAL( idx_bdy(ib_bdy)%nblen(:) )
         ALLOCATE( idx_bdy(ib_bdy)%nbi   (ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%nbj   (ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%nbr   (ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%nbd   (ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%nbdout(ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%ntreat(ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%nbmap (ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%nbw   (ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%flagu (ilen1,jpbgrd) ,   &
            &      idx_bdy(ib_bdy)%flagv (ilen1,jpbgrd) )

         ! Dispatch mapping indices and discrete distances on each processor
         ! -----------------------------------------------------------------
         DO igrd = 1, jpbgrd
            icount  = 0
            ! Outer loop on rimwidth to ensure outermost points come first in the local arrays.
            DO ir = 0, nn_rimwidth(ib_bdy)
               DO ib = 1, nblendta(igrd,ib_bdy)
                  ! check if point is in local domain and equals ir
                  IF(  nbidta(ib,igrd,ib_bdy) >= iwe .AND. nbidta(ib,igrd,ib_bdy) <= ies .AND.   &
                     & nbjdta(ib,igrd,ib_bdy) >= iso .AND. nbjdta(ib,igrd,ib_bdy) <= ino .AND.   &
                     & nbrdta(ib,igrd,ib_bdy) == ir  ) THEN
                     !
                     icount = icount  + 1
                     idx_bdy(ib_bdy)%nbi(icount,igrd)   = nbidta(ib,igrd,ib_bdy) - mig(1) + 1   ! global to local indexes
                     idx_bdy(ib_bdy)%nbj(icount,igrd)   = nbjdta(ib,igrd,ib_bdy) - mjg(1) + 1   ! global to local indexes
                     idx_bdy(ib_bdy)%nbr(icount,igrd)   = nbrdta(ib,igrd,ib_bdy)
                     idx_bdy(ib_bdy)%nbmap(icount,igrd) = ib
                  ENDIF
               END DO
            END DO
         END DO   ! igrd

      END DO   ! ib_bdy

      ! Initialize array indicating communications in bdy
      ! -------------------------------------------------
      ALLOCATE( lsend_bdyolr(nb_bdy,jpbgrd,8,0:1), lrecv_bdyolr(nb_bdy,jpbgrd,8,0:1) )
      lsend_bdyolr(:,:,:,:) = .false.
      lrecv_bdyolr(:,:,:,:) = .false. 

      DO ib_bdy = 1, nb_bdy
         DO igrd = 1, jpbgrd
            DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)   ! only the rim triggers communications, see bdy routines
               ii = idx_bdy(ib_bdy)%nbi(ib,igrd)
               ij = idx_bdy(ib_bdy)%nbj(ib,igrd)
               IF( ib .LE. idx_bdy(ib_bdy)%nblenrim0(igrd) ) THEN   ;   ir = 0
               ELSE                                                 ;   ir = 1
               END IF
               !
               ! check if point has to be sent     to   a neighbour
               IF( ii >= Nis0 .AND. ii < Nis0 + nn_hls .AND. ij >= Njs0 .AND. ij <= Nje0         ) THEN   ! we inner side
                  IF( mpiSnei(nn_hls,jpwe) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpwe,ir) = .TRUE.
               ENDIF
               IF( ii <= Nie0 .AND. ii > Nie0 - nn_hls .AND. ij >= Njs0 .AND. ij <= Nje0         ) THEN   ! ea inner side
                  IF( mpiSnei(nn_hls,jpea) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpea,ir) = .TRUE.
               ENDIF
               IF( ii >= Nis0 .AND. ii <= Nie0         .AND. ij >= Njs0 .AND. ij < Njs0 + nn_hls ) THEN   ! so inner side
                  IF( mpiSnei(nn_hls,jpso) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpso,ir) = .TRUE.
               ENDIF
               IF( ii  < Nis0                          .AND. ij >= Njs0 .AND. ij < Njs0 + nn_hls ) THEN   ! so side we-halo
                  IF( mpiSnei(nn_hls,jpso) > -1 .AND. nn_comm == 1 )   lsend_bdyolr(ib_bdy,igrd,jpso,ir) = .TRUE.
               ENDIF
               IF( ii  > Nie0                          .AND. ij >= Njs0 .AND. ij < Njs0 + nn_hls ) THEN   ! so side ea-halo 
                  IF( mpiSnei(nn_hls,jpso) > -1 .AND. nn_comm == 1 )   lsend_bdyolr(ib_bdy,igrd,jpso,ir) = .TRUE.
               ENDIF
               IF( ii >= Nis0 .AND. ii <= Nie0         .AND. ij <= Nje0 .AND. ij > Nje0 - nn_hls ) THEN   ! no inner side
                  IF( mpiSnei(nn_hls,jpno) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpno,ir) = .TRUE.
               ENDIF
               IF( ii  < Nis0                          .AND. ij <= Nje0 .AND. ij > Nje0 - nn_hls ) THEN   ! no side we-halo
                  IF( mpiSnei(nn_hls,jpno) > -1 .AND. nn_comm == 1 )   lsend_bdyolr(ib_bdy,igrd,jpno,ir) = .TRUE.
               ENDIF
               IF( ii  > Nie0                          .AND. ij <= Nje0 .AND. ij > Nje0 - nn_hls ) THEN   ! no side ea-halo
                  IF( mpiSnei(nn_hls,jpno) > -1 .AND. nn_comm == 1 )   lsend_bdyolr(ib_bdy,igrd,jpno,ir) = .TRUE.
               ENDIF
               IF( ii >= Nis0 .AND. ii < Nis0 + nn_hls .AND. ij >= Njs0 .AND. ij < Njs0 + nn_hls ) THEN   ! sw inner corner
                  IF( mpiSnei(nn_hls,jpsw) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpsw,ir) = .TRUE.
               ENDIF
               IF( ii <= Nie0 .AND. ii > Nie0 - nn_hls .AND. ij >= Njs0 .AND. ij < Njs0 + nn_hls ) THEN   ! se inner corner
                  IF( mpiSnei(nn_hls,jpse) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpse,ir) = .TRUE.
               ENDIF
               IF( ii >= Nis0 .AND. ii < Nis0 + nn_hls .AND. ij <= Nje0 .AND. ij > Nje0 - nn_hls ) THEN   ! nw inner corner
                  IF( mpiSnei(nn_hls,jpnw) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpnw,ir) = .TRUE.
               ENDIF
               IF( ii <= Nie0 .AND. ii > Nie0 - nn_hls .AND. ij <= Nje0 .AND. ij > Nje0 - nn_hls ) THEN   ! ne inner corner
                  IF( mpiSnei(nn_hls,jpne) > -1                    )   lsend_bdyolr(ib_bdy,igrd,jpne,ir) = .TRUE.
               ENDIF
               !
               ! check if point has to be received from a neighbour
               IF( ii  < Nis0                  .AND. ij >= Njs0 .AND. ij <= Nje0 ) THEN   ! we side
                  IF( mpiRnei(nn_hls,jpwe) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpwe,ir) = .TRUE.
               ENDIF
               IF( ii  > Nie0                  .AND. ij >= Njs0 .AND. ij <= Nje0 ) THEN   ! ea side
                  IF( mpiRnei(nn_hls,jpea) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpea,ir) = .TRUE.
               ENDIF
               IF( ii >= Nis0 .AND. ii <= Nie0 .AND. ij  < Njs0                  ) THEN   ! so side
                  IF( mpiRnei(nn_hls,jpso) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpso,ir) = .TRUE.
               ENDIF
               IF( ii >= Nis0 .AND. ii <= Nie0 .AND. ij  > Nje0                  ) THEN   ! no side
                  IF( mpiRnei(nn_hls,jpno) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpno,ir) = .TRUE.
               ENDIF
               IF( ii  < Nis0                  .AND. ij  < Njs0                  ) THEN   ! sw corner
                  IF( mpiRnei(nn_hls,jpsw) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpsw,ir) = .TRUE.
                  IF( mpiRnei(nn_hls,jpso) > -1 .AND. nn_comm == 1 )   lrecv_bdyolr(ib_bdy,igrd,jpso,ir) = .TRUE.
               ENDIF
               IF( ii  > Nie0                  .AND. ij  < Njs0                  ) THEN   ! se corner
                  IF( mpiRnei(nn_hls,jpse) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpse,ir) = .TRUE.
                  IF( mpiRnei(nn_hls,jpso) > -1 .AND. nn_comm == 1 )   lrecv_bdyolr(ib_bdy,igrd,jpso,ir) = .TRUE.
               ENDIF
               IF( ii  < Nis0                  .AND. ij  > Nje0                  ) THEN   ! nw corner
                  IF( mpiRnei(nn_hls,jpnw) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpnw,ir) = .TRUE.
                  IF( mpiRnei(nn_hls,jpno) > -1 .AND. nn_comm == 1 )   lrecv_bdyolr(ib_bdy,igrd,jpno,ir) = .TRUE.
               ENDIF
               IF( ii  > Nie0                  .AND. ij  > Nje0                  ) THEN   ! ne corner
                  IF( mpiRnei(nn_hls,jpne) > -1                    )   lrecv_bdyolr(ib_bdy,igrd,jpne,ir) = .TRUE.
                  IF( mpiRnei(nn_hls,jpno) > -1 .AND. nn_comm == 1 )   lrecv_bdyolr(ib_bdy,igrd,jpno,ir) = .TRUE.
               ENDIF
               !
            END DO
         END DO   !   igrd
         
         ! Comment out for debug
!!$         DO ir = 0,1
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'T', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyolr(ib_bdy,1,:,ir), lrecv = lrecv_bdyolr(ib_bdy,1,:,ir) )
!!$            IF(lwp) WRITE(numout,*) ' seb bdy debug olr T', ir ; CALL FLUSH(numout)
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'U', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyolr(ib_bdy,2,:,ir), lrecv = lrecv_bdyolr(ib_bdy,2,:,ir) )
!!$            IF(lwp) WRITE(numout,*) ' seb bdy debug olr U', ir ; CALL FLUSH(numout)
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'V', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyolr(ib_bdy,3,:,ir), lrecv = lrecv_bdyolr(ib_bdy,3,:,ir) )    
!!$            IF(lwp) WRITE(numout,*) ' seb bdy debug olr V', ir ; CALL FLUSH(numout)
!!$         END DO
         
         ! Compute rim weights for FRS scheme
         ! ----------------------------------
         DO igrd = 1, jpbgrd
            DO ib = 1, idx_bdy(ib_bdy)%nblen(igrd)
               ir = MAX( 1, idx_bdy(ib_bdy)%nbr(ib,igrd) )   ! both rim 0 and rim 1 have the same weights
               idx_bdy(ib_bdy)%nbw(ib,igrd) = 1.- TANH( REAL( ir - 1 ) *0.5 )      ! tanh formulation
               !               idx_bdy(ib_bdy)%nbw(ib,igrd) = (REAL(nn_rimwidth(ib_bdy)+1-ir)/REAL(nn_rimwidth(ib_bdy)))**2.  ! quadratic
               !               idx_bdy(ib_bdy)%nbw(ib,igrd) =  REAL(nn_rimwidth(ib_bdy)+1-ir)/REAL(nn_rimwidth(ib_bdy))       ! linear
            END DO
         END DO

         ! Compute damping coefficients
         ! ----------------------------
         DO igrd = 1, jpbgrd
            DO ib = 1, idx_bdy(ib_bdy)%nblen(igrd)
               ir = MAX( 1, idx_bdy(ib_bdy)%nbr(ib,igrd) )   ! both rim 0 and rim 1 have the same damping coefficients
               idx_bdy(ib_bdy)%nbd(ib,igrd) = 1. / ( rn_time_dmp(ib_bdy) * rday ) & 
                  & *(REAL(nn_rimwidth(ib_bdy)+1-ir)/REAL(nn_rimwidth(ib_bdy)))**2.   ! quadratic
               idx_bdy(ib_bdy)%nbdout(ib,igrd) = 1. / ( rn_time_dmp_out(ib_bdy) * rday ) & 
                  & *(REAL(nn_rimwidth(ib_bdy)+1-ir)/REAL(nn_rimwidth(ib_bdy)))**2.   ! quadratic
            END DO
         END DO

      END DO ! ib_bdy

      ! ------------------------------------------------------
      ! Initialise masks and find normal/tangential directions
      ! ------------------------------------------------------

      ! ------------------------------------------
      ! handle rim0, do as if rim 1 was free ocean
      ! ------------------------------------------

      ztmask(:,:) = tmask(:,:,1)   ;   zumask(:,:) = umask(:,:,1)   ;   zvmask(:,:) = vmask(:,:,1)
      ! For the flagu/flagv calculation below we require a version of fmask without
      ! the land boundary condition (shlat) included:
      DO_2D( 0, 0, 0, 0 )
         zfmask(ji,jj) =  ztmask(ji,jj  ) * ztmask(ji+1,jj  )   &
            &           * ztmask(ji,jj+1) * ztmask(ji+1,jj+1)
      END_2D
      CALL lbc_lnk( 'bdyini', zfmask, 'F', 1.0_wp )

      ! Read global 2D mask at T-points: bdytmask
      ! -----------------------------------------
      ! bdytmask = 1  on the computational domain but not on open boundaries
      !          = 0  elsewhere   

      bdytmask(:,:) = ssmask(:,:)

      ! Derive mask on U and V grid from mask on T grid
      DO_2D( 0, 0, 0, 0 )
            bdyumask(ji,jj) = bdytmask(ji,jj) * bdytmask(ji+1,jj  )
            bdyvmask(ji,jj) = bdytmask(ji,jj) * bdytmask(ji  ,jj+1)  
      END_2D
      CALL lbc_lnk( 'bdyini', bdyumask, 'U', 1.0_wp , bdyvmask, 'V', 1.0_wp )   ! Lateral boundary cond. 

      ! bdy masks are now set to zero on rim 0 points:
      DO ib_bdy = 1, nb_bdy
         DO ib = 1, idx_bdy(ib_bdy)%nblenrim0(1)   ! extent of rim 0
            bdytmask(idx_bdy(ib_bdy)%nbi(ib,1), idx_bdy(ib_bdy)%nbj(ib,1)) = 0._wp
         END DO
         DO ib = 1, idx_bdy(ib_bdy)%nblenrim0(2)   ! extent of rim 0
            bdyumask(idx_bdy(ib_bdy)%nbi(ib,2), idx_bdy(ib_bdy)%nbj(ib,2)) = 0._wp
         END DO
         DO ib = 1, idx_bdy(ib_bdy)%nblenrim0(3)   ! extent of rim 0
            bdyvmask(idx_bdy(ib_bdy)%nbi(ib,3), idx_bdy(ib_bdy)%nbj(ib,3)) = 0._wp
         END DO
      END DO

      CALL bdy_rim_treat( zumask, zvmask, zfmask, .true. )   ! compute flagu, flagv, ntreat on rim 0

      ! ------------------------------------
      ! handle rim1, do as if rim 0 was land
      ! ------------------------------------
      
      ! z[tuv]mask are now set to zero on rim 0 points:
      DO ib_bdy = 1, nb_bdy
         DO ib = 1, idx_bdy(ib_bdy)%nblenrim0(1)   ! extent of rim 0
            ztmask(idx_bdy(ib_bdy)%nbi(ib,1), idx_bdy(ib_bdy)%nbj(ib,1)) = 0._wp
         END DO
         DO ib = 1, idx_bdy(ib_bdy)%nblenrim0(2)   ! extent of rim 0
            zumask(idx_bdy(ib_bdy)%nbi(ib,2), idx_bdy(ib_bdy)%nbj(ib,2)) = 0._wp
         END DO
         DO ib = 1, idx_bdy(ib_bdy)%nblenrim0(3)   ! extent of rim 0
            zvmask(idx_bdy(ib_bdy)%nbi(ib,3), idx_bdy(ib_bdy)%nbj(ib,3)) = 0._wp
         END DO
      END DO

      ! Recompute zfmask
      DO_2D( 0, 0, 0, 0 )
         zfmask(ji,jj) =  ztmask(ji,jj  ) * ztmask(ji+1,jj  )   &
            &           * ztmask(ji,jj+1) * ztmask(ji+1,jj+1)
      END_2D
      CALL lbc_lnk( 'bdyini', zfmask, 'F', 1.0_wp )

      ! bdy masks are now set to zero on rim1 points:
      DO ib_bdy = 1, nb_bdy
         DO ib = idx_bdy(ib_bdy)%nblenrim0(1) + 1,  idx_bdy(ib_bdy)%nblenrim(1)   ! extent of rim 1
            bdytmask(idx_bdy(ib_bdy)%nbi(ib,1), idx_bdy(ib_bdy)%nbj(ib,1)) = 0._wp
         END DO
         DO ib = idx_bdy(ib_bdy)%nblenrim0(2) + 1,  idx_bdy(ib_bdy)%nblenrim(2)   ! extent of rim 1
            bdyumask(idx_bdy(ib_bdy)%nbi(ib,2), idx_bdy(ib_bdy)%nbj(ib,2)) = 0._wp
         END DO
         DO ib = idx_bdy(ib_bdy)%nblenrim0(3) + 1,  idx_bdy(ib_bdy)%nblenrim(3)   ! extent of rim 1
            bdyvmask(idx_bdy(ib_bdy)%nbi(ib,3), idx_bdy(ib_bdy)%nbj(ib,3)) = 0._wp
         END DO
      END DO

      CALL bdy_rim_treat( zumask, zvmask, zfmask, .false. )   ! compute flagu, flagv, ntreat on rim 1
      !
      ! Check which boundaries might need communication
      ALLOCATE( lsend_bdyint(nb_bdy,jpbgrd,8,0:1), lrecv_bdyint(nb_bdy,jpbgrd,8,0:1) )
      lsend_bdyint(:,:,:,:) = .false.
      lrecv_bdyint(:,:,:,:) = .false. 
      ALLOCATE( lsend_bdyext(nb_bdy,jpbgrd,8,0:1), lrecv_bdyext(nb_bdy,jpbgrd,8,0:1) )
      lsend_bdyext(:,:,:,:) = .false.
      lrecv_bdyext(:,:,:,:) = .false.
      !
      DO ib_bdy = 1, nb_bdy
         DO igrd = 1, jpbgrd
            DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
               IF( idx_bdy(ib_bdy)%ntreat(ib,igrd) == -1 ) CYCLE
               ii = idx_bdy(ib_bdy)%nbi(ib,igrd)
               ij = idx_bdy(ib_bdy)%nbj(ib,igrd)
               ir = idx_bdy(ib_bdy)%nbr(ib,igrd)
               flagu = NINT(idx_bdy(ib_bdy)%flagu(ib,igrd))
               flagv = NINT(idx_bdy(ib_bdy)%flagv(ib,igrd))
               iibe = ii - flagu   ! neighbouring point towards the exterior of the computational domain
               ijbe = ij - flagv
               iibi = ii + flagu   ! neighbouring point towards the interior of the computational domain
               ijbi = ij + flagv
               CALL find_neib( ii, ij, idx_bdy(ib_bdy)%ntreat(ib,igrd), ii1, ij1, ii2, ij2, ii3, ij3 )   ! free ocean neighbours
               !
               !  take care of the 4 sides
               !
               DO icnt = 1, 4
                  SELECT CASE( icnt )
                     !                                           ... _____
                  CASE( 1 )   ! x: rim on rcvwe/sndea-side         o|  :
                     !          o: potential neighbour(s)          o|x :
                     !             outside of the MPI domain     ..o|__:__
                     iRnei    = jpwe             ;   iSnei    = jpea
                     iiRst    = 1                ;   ijRst    = Njs0            ! Rcv we-side starting point, excluding sw-corner
                     iiRnd    = nn_hls           ;   ijRnd    = Nje0            ! Rcv we-side   ending point, excluding nw-corner
                     iiSst    = Nie0-nn_hls+1    ;   ijSst    = Njs0            ! Snd ea-side starting point, excluding se-corner
                     iiSnd    = Nie0             ;   ijSnd    = Nje0            ! Snd ea-side   ending point, excluding ne-corner
                     iioutdir = -1               ;   ijoutdir = -999            ! outside MPI domain: westward
                     !                                           ______....
                  CASE( 2 )   ! x: rim on rcvea/sndwe-side          :  |o
                     !          o: potential neighbour(s)           : x|o
                     !             outside of the MPI domain     ___:__|o..
                     iRnei    = jpea             ;   iSnei    = jpwe
                     iiRst    = Nie0+1           ;   ijRst    =  Njs0            ! Rcv ea-side starting point, excluding se-corner
                     iiRnd    = jpi              ;   ijRnd    =  Nje0            ! Rcv ea-side   ending point, excluding ne-corner
                     iiSst    = Nis0             ;   ijSst    =  Njs0            ! Snd we-side starting point, excluding sw-corner
                     iiSnd    = Nis0+nn_hls-1    ;   ijSnd    =  Nje0            ! Snd we-side   ending point, excluding nw-corner
                     iioutdir = 1                ;   ijoutdir = -999             ! outside MPI domain: eastward
                     !
                  CASE( 3 )   ! x: rim on rcvso/sndno-side       |       |
                     !          o: potential neighbour(s)        |¨¨¨¨¨¨¨|
                     !             outside of the MPI domain     |___x___|
                     !                                           : o o o :
                     !                                           :       :
                     iRnei    = jpso             ;   iSnei    = jpno
                     iiRst    = Nis0             ;   ijRst    = 1                ! Rcv so-side starting point, excluding sw-corner
                     iiRnd    = Nie0             ;   ijRnd    = nn_hls           ! Rcv so-side   ending point, excluding se-corner
                     iiSst    = Nis0             ;   ijSst    = Nje0-nn_hls+1    ! Snd no-side starting point, excluding nw-corner
                     iiSnd    = Nie0             ;   ijSnd    = Nje0             ! Snd no-side   ending point, excluding ne-corner
                     iioutdir = -999             ;   ijoutdir = -1               ! outside MPI domain: southward
                     !                                           :       :
                  CASE( 4 )   ! x: rim on rcvno/sndso-side       :_o_o_o_:
                     !          o: potential neighbour(s)        |   x   |
                     !             outside of the MPI domain     |       |
                     !                                           |¨¨¨¨¨¨¨|
                     iRnei    = jpno             ;   iSnei    = jpso
                     iiRst    = Nis0             ;   ijRst    = Nje0+1           ! Rcv no-side starting point, excluding nw-corner
                     iiRnd    = Nie0             ;   ijRnd    = jpj              ! Rcv no-side   ending point, excluding ne-corner
                     iiSst    = Nis0             ;   ijSst    = Njs0             ! Snd so-side starting point, excluding sw-corner
                     iiSnd    = Nie0             ;   ijSnd    = Njs0+nn_hls-1    ! Snd so-side   ending point, excluding se-corner
                     iioutdir = -999             ;   ijoutdir = 1                ! outside MPI domain: northward
                  END SELECT
                  !
                  IF( ii >= iiRst .AND. ii <= iiRnd .AND. ij >= ijRst .AND. ij <= ijRnd ) THEN   ! rim point in recv side
                     iiout = ii+iioutdir ; ijout = ij+ijoutdir        ! in which direction do we go outside of the MPI domain?
                     ! take care of neighbourg(s) in the interior of the computational domain
                     IF(  iibi==iiout .OR. ii1==iiout .OR. ii2==iiout .OR. ii3==iiout .OR.   &   ! Neib outside of the MPI domain
                        & ijbi==ijout .OR. ij1==ijout .OR. ij2==ijout .OR. ij3==ijout ) THEN     ! -> I cannot compute it -> recv it
                        IF( mpiRnei(nn_hls,iRnei) > -1 )   lrecv_bdyint(ib_bdy,igrd,iRnei,ir) = .TRUE.
                     ENDIF
                     ! take care of neighbourg in the exterior of the computational domain
                     IF(  iibe==iiout .OR. ijbe==ijout ) THEN   ! Neib outside of the MPI domain -> I cannot compute it -> recv it
                        IF( mpiRnei(nn_hls,iRnei) > -1 )   lrecv_bdyext(ib_bdy,igrd,iRnei,ir) = .TRUE.
                     ENDIF
                  ENDIF
                  
                  IF( ii >= iiSst .AND. ii <= iiSnd .AND. ij >= ijSst .AND. ij <= ijSnd ) THEN   ! rim point in send side
                     iiout = ii+iioutdir ; ijout = ij+ijoutdir        ! in which direction do we go outside of the nei MPI domain?
                     ! take care of neighbourg(s) in the interior of the computational domain
                     IF(  iibi==iiout .OR. ii1==iiout .OR. ii2==iiout .OR. ii3==iiout .OR.   &   ! Neib outside of nei MPI domain
                        & ijbi==ijout .OR. ij1==ijout .OR. ij2==ijout .OR. ij3==ijout ) THEN     ! -> nei cannot compute it
                        IF( mpiSnei(nn_hls,iSnei) > -1 )   lsend_bdyint(ib_bdy,igrd,iSnei,ir) = .TRUE.   ! -> send to nei
                     ENDIF
                     ! take care of neighbourg in the exterior of the computational domain
                     IF( iibe == iiout .OR. ijbe == ijout ) THEN   ! Neib outside of the nei MPI domain -> nei cannot compute it
                        IF( mpiSnei(nn_hls,iSnei) > -1 )   lsend_bdyext(ib_bdy,igrd,iSnei,ir) = .TRUE.   ! -> send to nei
                     ENDIF
                  END IF

               END DO   ! 4 sides
               !
               ! specific treatment for the corners
               !
               DO icnt = 1, 4
                  SELECT CASE( icnt )
                     !                                       ...|....
                  CASE( 1 )   ! x: rim on sw-corner            o|   :
                     !          o: potential neighbour(s)      o|x__:__
                     !             outside of the MPI domain   o o o:
                     !                                              :
                     iRdiag    = jpsw            ;   iRsono    = jpso            ! Recv: for sw or so
                     iSdiag    = jpne            ;   iSsono    = jpno            ! Send: to ne or no
                     iiRst     = 1               ;   ijRst     = 1               ! Rcv sw-corner starting point
                     iiRnd     = nn_hls          ;   ijRnd     = nn_hls          ! Rcv sw-corner   ending point
                     iiSstdiag = Nie0-nn_hls+1   ;   ijSstdiag = Nje0-nn_hls+1   ! send to sw-corner of ne neighbourg
                     iiSnddiag = Nie0            ;   ijSnddiag = Nje0            ! send to sw-corner of ne neighbourg
                     iiSstsono = 1               ;   ijSstsono = Nje0-nn_hls+1   ! send to sw-corner of no neighbourg
                     iiSndsono = nn_hls          ;   ijSndsono = Nje0            ! send to sw-corner of no neighbourg
                     iioutdir  = -1              ;   ijoutdir  = -1              ! outside MPI domain: westward or southward
                     !                                          ....|...
                  CASE( 2 )   ! x: rim on se-corner             :   |o
                     !          o: potential neighbour(s)     __:__x|o
                     !             outside of the MPI domain    :o o o
                     !                                          :    
                     iRdiag    = jpse            ;   iRsono    = jpso            ! Recv: for se or so
                     iSdiag    = jpnw            ;   iSsono    = jpno            ! Send: to nw or no
                     iiRst     = Nie0+1          ;   ijRst     = 1               ! Rcv se-corner starting point
                     iiRnd     = jpi             ;   ijRnd     = nn_hls          ! Rcv se-corner   ending point
                     iiSstdiag = Nis0            ;   ijSstdiag = Nje0-nn_hls+1   ! send to se-corner of nw neighbourg
                     iiSnddiag = Nis0+nn_hls-1   ;   ijSnddiag = Nje0            ! send to se-corner of nw neighbourg
                     iiSstsono = Nie0+1          ;   ijSstsono = Nje0-nn_hls+1   ! send to se-corner of no neighbourg
                     iiSndsono = jpi             ;   ijSndsono = Nje0            ! send to se-corner of no neighbourg
                     iioutdir  = 1               ;   ijoutdir  = -1              ! outside MPI domain: eastward or southward
                     !                                              :       
                     !                                         o o_o:___
                  CASE( 3 )   ! x: rim on nw-corner            o|x  :
                     !          o: potential neighbour(s)    ..o|...:
                     !             outside of the MPI domain    |
                     iRdiag    = jpnw            ;   iRsono    = jpno            ! Recv: for nw or no
                     iSdiag    = jpse            ;   iSsono    = jpso            ! Send: to se or so
                     iiRst     = 1               ;   ijRst     = Nje0+1          ! Rcv nw-corner starting point
                     iiRnd     = nn_hls          ;   ijRnd     = jpj             ! Rcv nw-corner   ending point
                     iiSstdiag = Nie0-nn_hls+1   ;   ijSstdiag = Njs0            ! send to nw-corner of se neighbourg
                     iiSnddiag = Nie0            ;   ijSnddiag = Njs0+nn_hls-1   ! send to nw-corner of se neighbourg
                     iiSstsono = 1               ;   ijSstsono = Njs0            ! send to nw-corner of so neighbourg
                     iiSndsono = nn_hls          ;   ijSndsono = Njs0+nn_hls-1   ! send to nw-corner of so neighbourg
                     iioutdir  = -1              ;   ijoutdir  =  1              ! outside MPI domain: westward or northward
                     !                                          :       
                     !                                       ___:o_o o
                  CASE( 4 )   ! x: rim on ne-corner             :  x|o
                     !          o: potential neighbour(s)       :...|o...
                     !             outside of the MPI domain        |
                     iRdiag    = jpne            ;   iRsono    = jpno            ! Recv: for ne or no
                     iSdiag    = jpsw            ;   iSsono    = jpso            ! Send: to sw or so
                     iiRst     = Nie0+1          ;   ijRst     = Nje0+1          ! Rcv ne-corner starting point
                     iiRnd     = jpi             ;   ijRnd     = jpj             ! Rcv ne-corner   ending point
                     iiSstdiag = Nis0            ;   ijSstdiag = Njs0            ! send to ne-corner of sw neighbourg
                     iiSnddiag = Nis0+nn_hls-1   ;   ijSnddiag = Njs0+nn_hls-1   ! send to ne-corner of sw neighbourg
                     iiSstsono = Nie0+1          ;   ijSstsono = Njs0            ! send to ne-corner of so neighbourg
                     iiSndsono = jpi             ;   ijSndsono = Njs0+nn_hls-1   ! send to ne-corner of so neighbourg
                     iioutdir  = 1               ;   ijoutdir  = 1               ! outside MPI domain: eastward or southward
                  END SELECT
                  !
                  ! Check if we need to receive data for this rim point
                  IF( ii >= iiRst .AND. ii <= iiRnd .AND. ij >= ijRst .AND. ij <= ijRnd ) THEN   ! rim point on the corner
                     iiout = ii+iioutdir ; ijout = ij+ijoutdir        ! in which direction do we go outside of the MPI domain?
                     ! take care of neighbourg(s) in the interior of the computational domain
                     IF(  iibi==iiout .OR. ii1==iiout .OR. ii2==iiout .OR. ii3==iiout .OR.   &   ! Neib outside of the MPI domain
                        & ijbi==ijout .OR. ij1==ijout .OR. ij2==ijout .OR. ij3==ijout ) THEN     ! -> I cannot compute it -> recv it
                        IF( mpiRnei(nn_hls,iRdiag) > -1                    )   lrecv_bdyint(ib_bdy,igrd,iRdiag,ir) = .TRUE.   ! Receive directly from diagonal neighbourg
                        IF( mpiRnei(nn_hls,iRsono) > -1 .AND. nn_comm == 1 )   lrecv_bdyint(ib_bdy,igrd,iRsono,ir) = .TRUE.   ! Receive through the South/North neighbourg
                     ENDIF
                     ! take care of neighbourg in the exterior of the computational domain
                     IF(  iibe==iiout .OR. ijbe==ijout ) THEN   ! Neib outside of the MPI domain -> I cannot compute it -> recv it
                        IF( mpiRnei(nn_hls,iRdiag) > -1                    )   lrecv_bdyext(ib_bdy,igrd,iRdiag,ir) = .TRUE.   ! Receive directly from diagonal neighbourg
                        IF( mpiRnei(nn_hls,iRsono) > -1 .AND. nn_comm == 1 )   lrecv_bdyext(ib_bdy,igrd,iRsono,ir) = .TRUE.   ! Receive through the South/North neighbourg
                     ENDIF
                  ENDIF
                  !
                  ! Check if this rim point corresponds to the corner of one neighbourg. if yes, do we need to send data?
                  ! Direct send to diag: Is this rim point the corner point of a diag neighbour with which we communicate?
                  IF( ii >= iiSstdiag .AND. ii <= iiSnddiag .AND. ij >= ijSstdiag .AND. ij <= ijSnddiag   &
                     &                .AND. mpiSnei(nn_hls,iSdiag) > -1 ) THEN
                     iiout = ii+iioutdir ; ijout = ij+ijoutdir        ! in which direction do we go outside of the nei MPI domain?
                     ! take care of neighbourg(s) in the interior of the computational domain
                     IF(  iibi==iiout .OR. ii1==iiout .OR. ii2==iiout .OR. ii3==iiout .OR.   &   ! Neib outside of diag nei MPI 
                        & ijbi==ijout .OR. ij1==ijout .OR. ij2==ijout .OR. ij3==ijout )      &   ! domain -> nei cannot compute it
                        &    lsend_bdyint(ib_bdy,igrd,iSdiag,ir) = .TRUE.                        ! send rim point data to diag nei
                     ! take care of neighbourg in the exterior of the computational domain
                     IF(  iibe==iiout .OR. ijbe==ijout )   &                                 
                        &    lsend_bdyext(ib_bdy,igrd,iSdiag,ir) = .TRUE.
                  ENDIF
                  ! Indirect send to diag (through so/no): rim point is the corner point of a so/no nei with which we communicate
                  IF( ii >= iiSstsono .AND. ii <= iiSndsono .AND. ij >= ijSstsono .AND. ij <= ijSndsono   &
                     &                .AND. mpiSnei(nn_hls,iSsono) > -1 .AND. nn_comm == 1 ) THEN
                     iiout = ii+iioutdir ; ijout = ij+ijoutdir        ! in which direction do we go outside of the nei MPI domain?
                     ! take care of neighbourg(s) in the interior of the computational domain
                     IF(  iibi==iiout .OR. ii1==iiout .OR. ii2==iiout .OR. ii3==iiout .OR.   &   ! Neib outside of so/no nei MPI
                        & ijbi==ijout .OR. ij1==ijout .OR. ij2==ijout .OR. ij3==ijout )      &   ! domain -> nei cannot compute it
                        &    lsend_bdyint(ib_bdy,igrd,iSsono,ir) = .TRUE.                        ! send rim point data to so/no nei
                     ! take care of neighbourg in the exterior of the computational domain
                     IF(  iibe==iiout .OR. ijbe==ijout )   &
                        &    lsend_bdyext(ib_bdy,igrd,iSsono,ir) = .TRUE.
                  ENDIF
                  !
               END DO   ! 4 corners
            END DO   ! ib
         END DO   ! igrd

         ! Comment out for debug
!!$         DO ir = 0,1
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'T', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyint(ib_bdy,1,:,ir), lrecv = lrecv_bdyint(ib_bdy,1,:,ir) )
!!$            IF(lwp) WRITE(numout,*) ' bdy debug int T', ir ; CALL FLUSH(numout)
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'U', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyint(ib_bdy,2,:,ir), lrecv = lrecv_bdyint(ib_bdy,2,:,ir) )
!!$            IF(lwp) WRITE(numout,*) ' bdy debug int U', ir ; CALL FLUSH(numout)
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'V', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyint(ib_bdy,3,:,ir), lrecv = lrecv_bdyint(ib_bdy,3,:,ir) )    
!!$            IF(lwp) WRITE(numout,*) ' bdy debug int V', ir ; CALL FLUSH(numout)
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'T', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyext(ib_bdy,1,:,ir), lrecv = lrecv_bdyext(ib_bdy,1,:,ir) )
!!$            IF(lwp) WRITE(numout,*) ' bdy debug ext T', ir ; CALL FLUSH(numout)
!!$            zzbdy(:,:) = narea ; CALL lbc_lnk('bdy debug', zzbdy, 'U', 1._wp, kfillmode = jpfillnothing,   &
!!$               &                              lsend = lsend_bdyext(ib_bdy,2,:,ir), lrecv = lrecv_bdyext(ib_bdy,2,:,ir) )