Index: branches/2016/dev_CMCC_2016/NEMOGCM/NEMO/TOP_SRC/trcbdy.F90
===================================================================
--- branches/2016/dev_CMCC_2016/NEMOGCM/NEMO/TOP_SRC/trcbdy.F90	(revision 7291)
+++ branches/2016/dev_CMCC_2016/NEMOGCM/NEMO/TOP_SRC/trcbdy.F90	(revision 7299)
@@ -9,11 +9,9 @@
    !!            3.5  !  2012     (S. Mocavero, I. Epicoco) Optimization of BDY communications
    !!            3.6  !  2015     (T. Lovato) Adapt BDY for tracers in TOP component
+   !!            4.0  !  2016     (T. Lovato) Generalize OBC structure
    !!----------------------------------------------------------------------
-#if defined key_bdy && key_top
+#if defined key_top
    !!----------------------------------------------------------------------
-   !!   'key_bdy'                     Unstructured Open Boundary Conditions
-   !!----------------------------------------------------------------------
-   !!   trc_bdy            : Apply open boundary conditions to T and S
-   !!   trc_bdy_frs        : Apply Flow Relaxation Scheme
+   !!   trc_bdy       : Apply open boundary conditions & damping to tracers
    !!----------------------------------------------------------------------
    USE timing                       ! Timing
@@ -24,5 +22,5 @@
    USE lbclnk                       ! ocean lateral boundary conditions (or mpp link)
    USE in_out_manager               ! I/O manager
-   USE bdy_oce, only: idx_bdy, OBC_INDEX, BDYTMASK, lk_bdy       ! ocean open boundary conditions
+   USE bdy_oce, only: idx_bdy       ! ocean open boundary conditions
 
    IMPLICIT NONE
@@ -33,5 +31,5 @@
 
    !!----------------------------------------------------------------------
-   !! NEMO/OPA 3.6 , NEMO Consortium (2015)
+   !! NEMO/OPA 4.0 , NEMO Consortium (2016)
    !! $Id$ 
    !! Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt)
@@ -43,194 +41,40 @@
       !!                  ***  SUBROUTINE trc_bdy  ***
       !!
-      !! ** Purpose : - Apply open boundary conditions for tracers in TOP component
-      !!                and scale the tracer data
+      !! ** Purpose : - Apply open boundary conditions for TOP tracers
       !!
       !!----------------------------------------------------------------------
       INTEGER, INTENT( in ) :: kt     ! Main time step counter
       !!
-      INTEGER               :: ib_bdy, jn ! Loop indeces
+      INTEGER                           :: ib_bdy, jn ! Loop indeces
+      REAL(wp), POINTER, DIMENSION(:,:) ::  ztrc
+      REAL(wp), POINTER                 ::  zfac
       !!----------------------------------------------------------------------
       !
       IF( nn_timing == 1 ) CALL timing_start('trc_bdy')
       !
-      DO jn = 1, jptra
-         DO ib_bdy=1, nb_bdy
-
-            SELECT CASE( trcdta_bdy(jn,ib_bdy)%cn_obc )
-            CASE('none')
-               CYCLE
-            CASE('frs')
-               CALL bdy_trc_frs( jn, idx_bdy(ib_bdy), trcdta_bdy(jn,ib_bdy), kt )
-            CASE('specified')
-               CALL bdy_trc_spe( jn, idx_bdy(ib_bdy), trcdta_bdy(jn,ib_bdy), kt )
-            CASE('neumann')
-               CALL bdy_trc_nmn( jn, idx_bdy(ib_bdy), trcdta_bdy(jn,ib_bdy), kt )
-            CASE('orlanski')
-               CALL bdy_trc_orlanski( jn, idx_bdy(ib_bdy), trcdta_bdy(jn,ib_bdy), ll_npo=.false. )
-            CASE('orlanski_npo')
-               CALL bdy_trc_orlanski( jn, idx_bdy(ib_bdy), trcdta_bdy(jn,ib_bdy), ll_npo=.true. )
-            CASE DEFAULT
-               CALL ctl_stop( 'trc_bdy : unrecognised option for open boundaries for passive tracers' )
+      DO ib_bdy=1, nb_bdy
+         DO jn = 1, jptra
+            !
+            ztrc => trcdta_bdy(jn,ib_bdy)%trc 
+            zfac => trcdta_bdy(jn,ib_bdy)%rn_fac
+            !
+            SELECT CASE( TRIM(trcdta_bdy(jn,ib_bdy)%cn_obc) )
+            CASE('none'        )   ;   CYCLE
+            CASE('frs'         )   ;   CALL bdy_frs( idx_bdy(ib_bdy),                tra(:,:,:,jn), ztrc*zfac )
+            CASE('specified'   )   ;   CALL bdy_spe( idx_bdy(ib_bdy),                tra(:,:,:,jn), ztrc*zfac )
+            CASE('neumann'     )   ;   CALL bdy_nmn( idx_bdy(ib_bdy),                tra(:,:,:,jn) )
+            CASE('orlanski'    )   ;   CALL bdy_orl( idx_bdy(ib_bdy), trb(:,:,:,jn), tra(:,:,:,jn), ztrc*zfac, ll_npo=.false. )
+            CASE('orlanski_npo')   ;   CALL bdy_orl( idx_bdy(ib_bdy), trb(:,:,:,jn), tra(:,:,:,jn), ztrc*zfac, ll_npo=.true. )
+            CASE DEFAULT           ;   CALL ctl_stop( 'trc_bdy : unrecognised option for open boundaries for passive tracers' )
             END SELECT
-
             ! Boundary points should be updated
             CALL lbc_bdy_lnk( tra(:,:,:,jn), 'T', 1., ib_bdy )
-
-         ENDDO
-      ENDDO
+            !
+         END DO
+      END DO
       !
       IF( nn_timing == 1 ) CALL timing_stop('trc_bdy')
 
    END SUBROUTINE trc_bdy
-
-   SUBROUTINE bdy_trc_frs( jn, idx, dta, kt )
-      !!----------------------------------------------------------------------
-      !!                 ***  SUBROUTINE bdy_trc_frs  ***
-      !!                    
-      !! ** Purpose : Apply the Flow Relaxation Scheme for tracers at open boundaries.
-      !! 
-      !! Reference : Engedahl H., 1995, Tellus, 365-382.
-      !!----------------------------------------------------------------------
-      INTEGER,         INTENT(in) ::   kt
-      INTEGER,         INTENT(in) ::   jn   ! Tracer index
-      TYPE(OBC_INDEX), INTENT(in) ::   idx  ! OBC indices
-      TYPE(OBC_DATA),  INTENT(in) ::   dta  ! OBC external data
-      !! 
-      REAL(wp) ::   zwgt           ! boundary weight
-      INTEGER  ::   ib, ik, igrd   ! dummy loop indices
-      INTEGER  ::   ii, ij         ! 2D addresses
-      !!----------------------------------------------------------------------
-      !
-      IF( nn_timing == 1 ) CALL timing_start('bdy_trc_frs')
-      ! 
-      igrd = 1                       ! Everything is at T-points here
-      DO ib = 1, idx%nblen(igrd)
-         DO ik = 1, jpkm1
-            ii = idx%nbi(ib,igrd)
-            ij = idx%nbj(ib,igrd)
-            zwgt = idx%nbw(ib,igrd)
-            tra(ii,ij,ik,jn) = ( tra(ii,ij,ik,jn) + zwgt * ( ( dta%trc(ib,ik) * dta%rn_fac)  & 
-                        &  - tra(ii,ij,ik,jn) ) ) * tmask(ii,ij,ik)
-         END DO
-      END DO 
-      !
-      IF( kt .eq. nit000 ) CLOSE( unit = 102 )
-      !
-      IF( nn_timing == 1 ) CALL timing_stop('bdy_trc_frs')
-      !
-   END SUBROUTINE bdy_trc_frs
-  
-   SUBROUTINE bdy_trc_spe( jn, idx, dta, kt )
-      !!----------------------------------------------------------------------
-      !!                 ***  SUBROUTINE bdy_trc_frs  ***
-      !!                    
-      !! ** Purpose : Apply a specified value for tracers at open boundaries.
-      !! 
-      !!----------------------------------------------------------------------
-      INTEGER,         INTENT(in) ::   kt
-      INTEGER,         INTENT(in) ::   jn   ! Tracer index
-      TYPE(OBC_INDEX), INTENT(in) ::   idx  ! OBC indices
-      TYPE(OBC_DATA),  INTENT(in) ::   dta  ! OBC external data
-      !! 
-      REAL(wp) ::   zwgt           ! boundary weight
-      INTEGER  ::   ib, ik, igrd   ! dummy loop indices
-      INTEGER  ::   ii, ij         ! 2D addresses
-      !!----------------------------------------------------------------------
-      !
-      IF( nn_timing == 1 ) CALL timing_start('bdy_trc_spe')
-      !
-      igrd = 1                       ! Everything is at T-points here
-      DO ib = 1, idx%nblenrim(igrd)
-         ii = idx%nbi(ib,igrd)
-         ij = idx%nbj(ib,igrd)
-         DO ik = 1, jpkm1
-            tra(ii,ij,ik,jn) = dta%trc(ib,ik) * dta%rn_fac * tmask(ii,ij,ik)
-         END DO
-      END DO
-      !
-      IF( kt .eq. nit000 ) CLOSE( unit = 102 )
-      !
-      IF( nn_timing == 1 ) CALL timing_stop('bdy_trc_spe')
-      !
-   END SUBROUTINE bdy_trc_spe
-
-   SUBROUTINE bdy_trc_nmn( jn, idx, dta, kt )
-      !!----------------------------------------------------------------------
-      !!                 ***  SUBROUTINE bdy_trc_nmn  ***
-      !!                    
-      !! ** Purpose : Duplicate the value for tracers at open boundaries.
-      !! 
-      !!----------------------------------------------------------------------
-      INTEGER,         INTENT(in) ::   kt
-      INTEGER,         INTENT(in) ::   jn   ! Tracer index
-      TYPE(OBC_INDEX), INTENT(in) ::   idx  ! OBC indices
-      TYPE(OBC_DATA),  INTENT(in) ::   dta  ! OBC external data
-      !! 
-      REAL(wp) ::   zwgt           ! boundary weight
-      INTEGER  ::   ib, ik, igrd   ! dummy loop indices
-      INTEGER  ::   ii, ij, zcoef, zcoef1, zcoef2, ip, jp   ! 2D addresses
-      !!----------------------------------------------------------------------
-      !
-      IF( nn_timing == 1 ) CALL timing_start('bdy_trc_nmn')
-      !
-      igrd = 1                       ! Everything is at T-points here
-      DO ib = 1, idx%nblenrim(igrd)
-         ii = idx%nbi(ib,igrd)
-         ij = idx%nbj(ib,igrd)
-         DO ik = 1, jpkm1
-            ! search the sense of the gradient
-            zcoef1 = bdytmask(ii-1,ij  ) +  bdytmask(ii+1,ij  )
-            zcoef2 = bdytmask(ii  ,ij-1) +  bdytmask(ii  ,ij+1)
-            IF ( zcoef1+zcoef2 == 0) THEN
-               ! corner
-               zcoef = tmask(ii-1,ij,ik) + tmask(ii+1,ij,ik) +  tmask(ii,ij-1,ik) +  tmask(ii,ij+1,ik)
-               tra(ii,ij,ik,jn) = tra(ii-1,ij  ,ik,jn) * tmask(ii-1,ij  ,ik) + &
-                 &                tra(ii+1,ij  ,ik,jn) * tmask(ii+1,ij  ,ik) + &
-                 &                tra(ii  ,ij-1,ik,jn) * tmask(ii  ,ij-1,ik) + &
-                 &                tra(ii  ,ij+1,ik,jn) * tmask(ii  ,ij+1,ik)
-               tra(ii,ij,ik,jn) = ( tra(ii,ij,ik,jn) / MAX( 1, zcoef) ) * tmask(ii,ij,ik)
-            ELSE
-               ip = bdytmask(ii+1,ij  ) - bdytmask(ii-1,ij  )
-               jp = bdytmask(ii  ,ij+1) - bdytmask(ii  ,ij-1)
-               tra(ii,ij,ik,jn) = tra(ii+ip,ij+jp,ik,jn) * tmask(ii+ip,ij+jp,ik)
-            ENDIF
-         END DO
-      END DO
-      !
-      IF( kt .eq. nit000 ) CLOSE( unit = 102 )
-      !
-      IF( nn_timing == 1 ) CALL timing_stop('bdy_trc_nmn')
-      !
-   END SUBROUTINE bdy_trc_nmn
- 
-
-   SUBROUTINE bdy_trc_orlanski( jn, idx, dta, ll_npo )
-      !!----------------------------------------------------------------------
-      !!                 ***  SUBROUTINE bdy_trc_orlanski  ***
-      !!             
-      !!              - Apply Orlanski radiation to tracers of TOP component. 
-      !!              - Wrapper routine for bdy_orlanski_3d
-      !! 
-      !!
-      !! References:  Marchesiello, McWilliams and Shchepetkin, Ocean Modelling vol. 3 (2001)    
-      !!----------------------------------------------------------------------
-      INTEGER,                      INTENT(in) ::   jn      ! Tracer index
-      TYPE(OBC_INDEX),              INTENT(in) ::   idx     ! OBC indices
-      TYPE(OBC_DATA),               INTENT(in) ::   dta     ! OBC external data
-      LOGICAL,                      INTENT(in) ::   ll_npo  ! switch for NPO version
-
-      INTEGER  ::   igrd                                    ! grid index
-      !!----------------------------------------------------------------------
-
-      IF( nn_timing == 1 ) CALL timing_start('bdy_trc_orlanski')
-      !
-      igrd = 1      ! Orlanski bc on tracers; 
-      !            
-      CALL bdy_orlanski_3d( idx, igrd, trb(:,:,:,jn), tra(:,:,:,jn), (dta%trc * dta%rn_fac), ll_npo )
-      !
-      IF( nn_timing == 1 ) CALL timing_stop('bdy_trc_orlanski')
-      !
-
-   END SUBROUTINE bdy_trc_orlanski
 
    SUBROUTINE trc_bdy_dmp( kt )
