!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer, 
!                     version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms 
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer 
!version 3 or (at your option) any later version that should be found at: 
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html 
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software; 
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec), 
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
***s/r itf_phy_slb - Computes the physical tendencies
*
#include "model_macros_f.h"
*

      subroutine  itf_phy_slb( F_cpu,   F_step, F_obusval, F_cobusval, 1
     $                      F_pvptr, F_cvptrp,F_cvptrm,
     $                      NPTR, NCPTR, F_trp, F_trm, 
     $                      F_tdu, F_tdv,  F_tdt, F_kmm, F_ktm,
     $                      DIST_DIM, Nk )
*
      implicit none
*
      integer F_cpu, F_step, nvvv, nvov, DIST_DIM, Nk, NPTR,NCPTR
      integer*8 F_pvptr(NPTR)
      integer*8 F_cvptrp(NCPTR),F_cvptrm(NCPTR)
*
      real F_tdu     (DIST_SHAPE,Nk)
      real F_tdv     (DIST_SHAPE,Nk)
      real F_tdt     (DIST_SHAPE,Nk)
      real F_trp     (DIST_SHAPE,Nk,*)
      real F_trm     (DIST_SHAPE,Nk,*)
      real F_kmm     (DIST_SHAPE,Nk)
      real F_ktm     (DIST_SHAPE,Nk)
      real F_obusval (*)
      real F_cobusval(*)

*
*author 
*     Michel Roch - rpn - june 1993
*
*revision
* v2_00 - Desgagne M.       - initial MPI version
* v2_20 - Pellerin P.       - adapt to physics 3.66 with entry bus
* v2_21 - Dugas B.          - activate climate mode
* v2_21 - J. P. Toviessi    - (#) slab output
* v2_31 - Dugas B.          - re-activate zonal diagnostics
* v2_32 - Desgagne M.       - connection to physics 3.72
* v3_00 - Laroche S.        - adaptation for v4d
* v3_02 - Dugas B.          - account for a possible second call to the physics
*                             and add optional call to dump full physics buses
* v3_10 - Corbeil & Desgagne & Lee - AIXport+Opti+OpenMP
* v3_11 - Dugas B.          - Correct DUMPBUS mechanism for OpenMP
* v3_12 - Leduc A-M.        - Add arguments gzm and topo
* v3_20 - Lee V             - replace slab Output with FST file output
* v3_20 - Pellerin P.       - Add busvol in itf_phy_fillbus
* v3_20 - Desgagne/Pellerin S.- Replaced Mem_pslic with jdo in test for last slice.
* v3_20 - Lee/Kallaur       - Add coding and data structures to support chemistry.
* v3_21 - Valcke, S.        - Modified CALL to c_getbus and c_fillbus
* v3_30 - Spacek, L.        - New total tendecies uphytd,vphytd,tphytd,
*                             huphytd,qcphytd,qrphytd,qgphytd,qiphytd
*                             Eliminations of processus specific physics
*                             tendencies.
* v3_31 - Desgagne M.       - new coupling interface to OASIS
* v3_31 - Desgagne M.       - restart with physics BUSPER
*
*object
*     See above id.
*	
*arguments
*  Name       I/O                 Description
*----------------------------------------------------------------
* F_cpu        I    - cpu number
* F_step       I    - current time step number
* F_obusval    O    - physics output bus
* F_cobusval   O    - chemistry output bus
* F_pvptr      I    - dynamic pointers
* F_cpvptrp    I    - chemistry pointers at time t+
* F_cpvptrm    I    - chemistry pointers at time t-
* NPTR,NCPTR   I    - number of dynamic,chemistry pointers
* F_trp        I    - tracer concentration at time t+ (for each species)
* F_trm        I    - tracer concentration at time t- (for each species)
*              O    - total tracer tendency (for each species)
* F_tdu        O    - total wind image tendency in x direction
* F_tdv        O    - total wind image tendency in y direction
* F_tdt        O    - total virtual temperatur tndency
* F_kmm        O    - momentum vertical diffusion coefficients
* F_ktm        O    - thermodynamic vertical diffusion coefficients
*----------------------------------------------------------------
*
*implicits
#include "glb_ld.cdk"
#include "ptopo.cdk"
#include "lun.cdk"
#include "mult.cdk"
#include "schm.cdk"
#include "mem.cdk"
#include "cstv.cdk"
#include "dcst.cdk"
#include "geomg.cdk"
#include "itf_phy_buses.cdk"
#include "itf_chm_bus.cdk"
#include "obus.cdk"
#include "clim.cdk"
#include "itf_chm_obus.cdk"
#include "itf_phy_config.cdk"
#include "itf_phy_busind.cdk"
#include "itf_chm_busind.cdk"
#include "v4dg.cdk"
#include "itf_cpl.cdk"
*
*modules
*
      integer accum,nnc
      parameter (accum = 0 )
      character*2 accum_s
      data    accum_s / ' ' /
*
      logical dumpbus_L
      integer jdo, i, j, k, n, ii, indx, err
      integer busaddr,offbo,offbb,mult,cnt
      real dt,con
*
      real busdyn(max(1,p_bdyn_siz)), busvol(max(1,p_bvol_siz)),
     $     busent(max(1,p_bent_siz)), busper, busper2(max(1,p_bper_siz))
      pointer (pabusper,busper(*))
*
*     Declarations for chemistry buses.
*
      real chmbusdyn(max(1,chm_bdyn_siz))
      real chmbusvol(max(1,chm_bvol_siz))
      real chmbusent(max(1,chm_bent_siz))
      real chmbusper, chmbusper2(max(1,chm_bper_siz))
      pointer (pachmbusper,chmbusper(*))
**
*     ---------------------------------------------------------------
*
      if ((Lun_out.gt.0).and.(F_cpu.eq.1)) then
         write(Lun_out,1000) 'PHYSICS STEP: CMC/RPN PHYSICS',F_step
         if (Schm_chems_L) write(Lun_out,1000) 'CHEMISTRY STEP',F_step
      endif
*
      dumpbus_L = .false.
      if (P_pbd_dumpbus.gt.0) then
          dumpbus_L = (mod( F_step,P_pbd_dumpbus ).eq.0)
!$omp critical (lock_dumpini2)
          call dumpini2( p_bdyn_siz,p_bper_siz,p_bvol_siz,
     $                   Ptopo_numproc,p_ni,p_nj, G_ni,G_nj )
!$omp end critical (lock_dumpini2)
      endif
*
      if (F_step.eq.0) busent = 0.
*
      busdyn = 0.0
*
      dt  = Cstv_dt_8
      jdo = 0
*
*     Initialize chemical buses
*
      if (Schm_chems_L) then
*         chmbusdyn   = 0.0
         if (F_step.eq.0) chmbusent = 0.0
      endif
*
 100  continue
*

!$omp critical      
      Mem_pslic = Mem_pslic + 1
      jdo  = Mem_pslic
      if ( Mem_pslic .le. p_nj ) then
*
         pabusper    = loc (Phy_busper3D((jdo-1)*p_bper_siz+1))
         if (Schm_chems_L) pachmbusper = 
     *                 loc(chm_busper3D((jdo-1)*chm_bper_siz+1))
*
         call zongopr( +3, jdo )
*
      endif
!$omp end critical

*
*C    Stop if last slice has been completed
*
      if ( jdo .gt. p_nj ) goto 650
*
*     Fill physics buses with jdo row in subroutine itf_phy_fillbus
*
      busvol = 0.0
      j = jdo + p_offj
*
      call itf_phy_fillbus ( busdyn, busper ,busent, busvol,
     $         F_pvptr, NPTR, F_trm,F_trp, j, F_step, LDIST_DIM, l_nk )
*
*     Fill buses with fields produced by coupling
*
      if (C_coupling_L) call itf_cpl_fillbus ( busdyn,busper,busvol,j)
*
*     Run physics on row jdo
*      
*     If active chemical scheme, fill chemical buses with jdo row.
*
      if (Schm_chems_L) then
         chmbusvol = 0.0
         call itf_chm_fillbus (chmbusdyn,chmbusper,chmbusent,chmbusvol,
     $                     F_cvptrp ,F_cvptrm,j,F_step,LDIST_DIM,l_nk)
      endif
*
*     Run physics on row jdo
*
      if ( .NOT. P_pset_second_L ) then
         call phy_exe
     $             (busent ,busdyn ,busper ,busvol ,
     $              p_bent_siz, p_bdyn_siz, p_bper_siz, p_bvol_siz,
     $              dt, jdo, F_step, F_cpu, p_ni, Nk)
      else
        call itf_phy_exe
     $             (busent ,busdyn ,busper ,busvol ,
     $              p_bent_siz, p_bdyn_siz, p_bper_siz, p_bvol_siz,
     $              dt, jdo, F_step, F_cpu, p_ni, Nk)
      endif

      if (Schm_chems_L) then
*
*     Call chosen chemical solver package on row j 
*
         call chm_exe(chmbusent   ,chmbusper    ,chmbusdyn    ,chmbusvol   ,
     *                chm_bent_siz,chm_bdyn_siz ,chm_bper_siz ,chm_bvol_siz,
     $                chm_bdyn_top,chm_bper_top  ,chm_bvol_top,chm_bent_top,
     *                busent      ,busdyn       ,busper       ,busvol      ,
     *                p_bent_siz  ,p_bdyn_siz   ,p_bper_siz   ,p_bvol_siz  ,
     *                dt,jdo,F_step,F_cpu,p_ni,chm_ni,Nk)
*
*     Put back 2D slabs to 3D tracer space 
*
         call itf_chm_apply (chmbusdyn,chmbusper,chmbusent,chmbusvol,
     $                     F_cvptrp,F_cvptrm,j,F_step,LDIST_DIM,l_nk)
*
*     Load the output buses for chemical species (and related fields) that have been
*     chosen for output.
* 
!$omp critical
         call itf_chm_fillobus(chmbusent   ,chmbusper    ,chmbusdyn    ,chmbusvol   ,
     *                     chm_bent_siz,chm_bdyn_siz ,chm_bper_siz ,chm_bvol_siz,
     *                     F_cobusval  ,J)
!$omp end critical
      endif
*
      if (dumpbus_L) call dumpbus2( busdyn,busper,busvol, jdo )
*
*C  Combine tendencies of row jdo and store back in 3D space
*
      con = cos(geomg_y_8(j)) / Dcst_rayt_8
      do k = 1, l_nk
      do i = 1, p_ni
         indx = (k-1)*p_ni+i-1
         ii = i + p_offi
         F_tdu(ii,j,k) = busvol(uphytd +indx)*con
         F_tdv(ii,j,k) = busvol(vphytd +indx)*con
         F_tdt(ii,j,k) = busvol(tphytd +indx)
      end do
      end do
*
*C  Prepare surface variables for the coupling
*
      if (C_coupling_L) call itf_cpl_getbus (busdyn, busper, busvol, j)
*
      do n=1,phyt_ntr
         if (phyt_ind(3,n).gt.0) then
         do k= 1,Nk
         do i= 1, p_ni
            indx = (k-1)*p_ni+i-1
            ii = i + p_offi
            F_trm(ii,j,k,n) = busvol(phyt_ind(3,n)+indx)
         end do
         end do
         endif
      end do
*
*     Save vertical diffusion coefficients
*
      if ( V4dg_conf.ne.0 ) then 
        do k = 1, Nk-2
        do i = 1, p_ni
           indx = (k-1)*p_ni+i-1
           ii = i + p_offi
           F_kmm(ii,j,k) = busvol(km + indx)
           F_ktm(ii,j,k) = busvol(kt + indx)
        end do
        end do
        do i= 1, p_ni
           indx = i-1
           ii = i + p_offi
           F_kmm(ii,j,Nk-1) = busvol(bm + indx)
           F_ktm(ii,j,Nk-1) = busvol(bt + indx)
        end do
      endif
* 
*     Perform physic slices output
*
!$omp critical

      do ii=1,Obus_top
             offbo= (obus_offset(ii)-1)*l_ni*l_nj
             offbb= obus_addr(ii)
         if (obus_bus_S(ii).eq.'P'.and.obus_var_S(ii).eq.'LO') then
             do mult=1,obus_mult(ii)
                do k=1,obus_shp(ii)
                do i=1,p_ni
                   F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                                (j-1)*l_ni + i+ p_offi)=
     $             busper(offbb+(k*mult-1)*p_ni + i - 1)
                   if (F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                           (j-1)*l_ni + i+ p_offi) .gt. Dcst_pi_8)
     $            F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                                (j-1)*l_ni + i+ p_offi)=
     $            F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                           (j-1)*l_ni + i+ p_offi)-2.0*Dcst_pi_8
                enddo
                enddo
             enddo
         else if (obus_bus_S(ii).eq.'P') then
             do mult=1,obus_mult(ii)
                do k=1,obus_shp(ii)
                do i=1,p_ni
                   F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                                       (j-1)*l_ni + i+ p_offi)=
     $             busper(offbb+(k*mult-1)*p_ni + i - 1)
                enddo
                enddo
             enddo
         else if (obus_bus_S(ii).eq.'D') then
             do mult=1,obus_mult(ii)
                do k=1,obus_shp(ii)
                do i=1,p_ni
                   F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                                       (j-1)*l_ni + i+ p_offi)=
     $             busdyn(offbb+(k*mult-1)*p_ni + i - 1)
                enddo
                enddo
             enddo
         else if (obus_bus_S(ii).eq.'V') then
             do mult=1,obus_mult(ii)
                do k=1,obus_shp(ii)
                do i=1,p_ni
                   F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                                       (j-1)*l_ni + i+ p_offi)=
     $             busvol(offbb+(k*mult-1)*p_ni + i - 1)
                enddo
                enddo
             enddo
         else if (obus_bus_S(ii).eq.'E') then
             do mult=1,obus_mult(ii)
                do k=1,obus_shp(ii)
                do i=1,p_ni
                   F_obusval(offbo+(k*mult-1)*l_ni*l_nj +
     $                                       (j-1)*l_ni + i+ p_offi)=
     $             busent(offbb+(k*mult-1)*p_ni + i - 1)
                enddo
                enddo
             enddo
         endif
      enddo
*     
*     In climate mode, zero out the physic accumulators after
*     saving them, i.e. when output is greater than zero.
*
      if ( Clim_climat_L .and. Obus_top.gt.0) then
         if (P_out_moyhr.eq.0) then
            call phy_zeracc( busper,accum_s,accum )
         else if (mod( F_step*(Cstv_dt_8/3600.),P_out_moyhr*1d0 ).eq.0) then
            call phy_zeracc( busper,accum_s,accum )
         endif
      endif
      call zongopr( -3, jdo )
*
!$omp end critical
*
*
      goto 100
*
 650  continue
*
 1000 format(/'PERFORM A ',a,' (step= ',i6,')'/52('='))
*
*     ---------------------------------------------------------------
*
      return
      end