!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| module topostress !BOP ! !MODULE: topostress ! !DESCRIPTION: ! This module contains routines necessary for computing stress ! due to bottom topography. ! ! !REVISION HISTORY: ! SVN:$Id: topostress.F90 12674 2008-10-31 22:21:32Z njn01 $ ! !USES: use POP_KindsMod use POP_ErrorMod use POP_FieldMod use POP_GridHorzMod use POP_HaloMod use domain use blocks use distribution use constants use io use grid use broadcast use exit_mod implicit none private save ! !PUBLIC MEMBER FUNCTIONS: public :: init_topostress ! !PUBLIC DATA MEMBERS: logical (POP_logical), public :: & ltopostress ! true if topographic stress desired real (POP_r8), dimension(:,:,:), allocatable, public :: & TSU, TSV ! topographic stress velocities !EOP !BOC !EOC !*********************************************************************** contains !*********************************************************************** !BOP ! !IROUTINE: init_topostress ! !INTERFACE: subroutine init_topostress(errorCode) ! !DESCRIPTION: ! This routine allocates stress arrays if topographic stress is ! chosen and initializes topo stress parameters. ! ! !REVISION HISTORY: ! same as module ! ! !OUTPUT PARAMETERS: integer (POP_i4), intent(out) :: & errorCode !EOP !BOC !----------------------------------------------------------------------- ! ! input namelist to choose topostress ! !----------------------------------------------------------------------- integer (POP_i4) :: & nsmooth_topo ! number of passes of topography smoother integer (POP_i4) :: nml_error ! namelist i/o error flag namelist /topostress_nml/ltopostress, nsmooth_topo !----------------------------------------------------------------------- ! ! read namelist to see if topostress desired ! !----------------------------------------------------------------------- errorCode = POP_Success ltopostress = .false. nsmooth_topo= 0 if (my_task == master_task) then open (nml_in, file=nml_filename, status='old',iostat=nml_error) if (nml_error /= 0) then nml_error = -1 else nml_error = 1 endif do while (nml_error > 0) read(nml_in, nml=topostress_nml,iostat=nml_error) end do if (nml_error == 0) close(nml_in) endif call broadcast_scalar(nml_error, master_task) if (nml_error /= 0) then call exit_POP(sigAbort,'ERROR reading topostress_nml') endif if (my_task == master_task) then write(stdout,blank_fmt) write(stdout,ndelim_fmt) write(stdout,blank_fmt) write(stdout,'(a27)') ' Topographic stress options' write(stdout,blank_fmt) write(stdout,delim_fmt) if (ltopostress) then write(stdout,'(a27)') ' Topographic stress enabled' if (nsmooth_topo > 0) then write(stdout,'(a26,i2,a8)') ' Topography smoothed with ', & nsmooth_topo,' passes.' else write(stdout,'(a25)') ' Topography not smoothed.' endif else write(stdout,'(a28)') ' Topographic stress disabled' endif endif call broadcast_scalar(ltopostress, master_task) call broadcast_scalar(nsmooth_topo, master_task) !----------------------------------------------------------------------- ! ! allocate the topographic stress velocity arrays if required ! !----------------------------------------------------------------------- if (ltopostress) then allocate (TSU(nx_block,ny_block,nblocks_clinic), & TSV(nx_block,ny_block,nblocks_clinic)) call topo_stress(nsmooth_topo, errorCode) if (errorCode /= POP_Success) then call POP_ErrorSet(errorCode, & 'init_topostress: error in topo_stress') return endif endif !----------------------------------------------------------------------- !EOC end subroutine init_topostress !*********************************************************************** !BOP ! !IROUTINE: topo_stress ! !INTERFACE: subroutine topo_stress(nsmooth_topo, errorCode) ! !DESCRIPTION: ! Calculate topographic stress (maximum entropy) velocities. These ! are time-independent 2d fields given by: ! \begin{eqnarray} ! \Psi^* &=& -f L^2 H \\ ! H U^* &=& -\nabla_y(\Psi^*) \\ ! H V^* &=& +\nabla_x(\Psi^*) ! \end{eqnarray} ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: integer (POP_i4), intent(in) :: & nsmooth_topo ! number of passes of topography smoother ! !OUTPUT PARAMETERS: integer (POP_i4), intent(out) :: & errorCode ! returned error code !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (POP_i4) :: & i,j,iter,iblock ! local iteration counters real (POP_r8), dimension(nx_block,ny_block) :: & TSP, &! topo stress streamfunction SCALE, &! scale length HTOLD ! old topography real (POP_r8), dimension(nx_block,ny_block,nblocks_clinic) :: & HTNEW ! smoothed topography real (POP_r8), parameter :: & tslse = 12.0e5_POP_r8, &! tslsp = 3.0e5_POP_r8 ! type (block) :: & this_block ! block information for current block !----------------------------------------------------------------------- ! ! smooth topography if requested ! !----------------------------------------------------------------------- errorCode = POP_Success do iblock = 1,nblocks_clinic HTNEW(:,:,iblock) = HT(:,:,iblock) ! initialize end do do iter = 1, nsmooth_topo do iblock = 1,nblocks_clinic this_block = get_block(blocks_clinic(iblock),iblock) HTOLD = HTNEW(:,:,iblock) call smooth_topo2(HTOLD,HTNEW(:,:,iblock),this_block) end do call POP_HaloUpdate(HTNEW, POP_haloClinic, & POP_gridHorzLocCenter, POP_fieldKindScalar, & errorCode, fillValue = 0.0_POP_r8) if (errorCode /= POP_Success) then call POP_ErrorSet(errorCode, & 'topo_stress: error updating halo for htnew') return endif enddo !----------------------------------------------------------------------- ! ! calculate the topographic stress equilibrium stream function. ! !----------------------------------------------------------------------- do iblock = 1,nblocks_clinic this_block = get_block(blocks_clinic(iblock),iblock) SCALE = tslsp + (tslse - tslsp)* & (p5 + p5*cos(c2*TLAT(:,:,iblock))) where (KMT(:,:,iblock) /= 0) TSP = -FCORT(:,:,iblock)*SCALE*SCALE*HTNEW(:,:,iblock) elsewhere TSP = c0 end where !----------------------------------------------------------------------- ! ! calculate the topographic stress velocities from stream function. ! compute gradient with 4 point stencil ! !----------------------------------------------------------------------- TSU(:,:,iblock) = c0 TSV(:,:,iblock) = c0 do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie TSV(i,j,iblock) = DXUR(i,j,iblock)*p5*HUR(i,j,iblock)* & (TSP(i+1,j+1) - TSP(i ,j) - & TSP(i ,j+1) + TSP(i+1,j)) TSU(i,j,iblock) = -DYUR(i,j,iblock)*p5*HUR(i,j,iblock)* & (TSP(i+1,j+1) - TSP(i ,j) + & TSP(i ,j+1) - TSP(i+1,j)) end do end do where (KMU(:,:,iblock) == 0) TSV(:,:,iblock) = c0 ! zero at land points TSU(:,:,iblock) = c0 endwhere ! apply only in 'deep' water ! where (KMU(:,:,iblock) <= 3) ! TSU(:,:,iblock) = c0 ! TSV(:,:,iblock) = c0 ! endwhere end do ! block loop call POP_HaloUpdate(TSU, POP_haloClinic, & POP_gridHorzLocNECorner, POP_fieldKindVector, & errorCode, fillValue = 0.0_POP_r8) if (errorCode /= POP_Success) then call POP_ErrorSet(errorCode, & 'topo_stress: error updating halo for tsu') return endif call POP_HaloUpdate(TSV, POP_haloClinic, & POP_gridHorzLocNECorner, POP_fieldKindVector, & errorCode, fillValue = 0.0_POP_r8) if (errorCode /= POP_Success) then call POP_ErrorSet(errorCode, & 'topo_stress: error updating halo for tsv') return endif !----------------------------------------------------------------------- !EOC end subroutine topo_stress !*********************************************************************** !BOP ! !IROUTINE: smooth_topo2 ! !INTERFACE: subroutine smooth_topo2(HTOLD,HTNEW,this_block) ! !DESCRIPTION: ! This routine smooths topography using a 9-point averaging stencil ! given by ! \begin{equation} ! \begin{array}{ccccc} ! 1 & -- & 2 & -- & 1 \\ ! | & & | & & | \\ ! 2 & -- & 4 & -- & 2 \\ ! | & & | & & | \\ ! 1 & -- & 2 & -- & 1 ! \end{array} \nonumber ! \end{equation} ! Land points are not included in the smoothing, and the ! stencil is modified to include only ocean points in the ! averaging. This routine is nearly identical to the smooth ! topography routine in the grid module. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: real (POP_r8), dimension(nx_block,ny_block), intent(in) :: & HTOLD ! old HT field to be smoothed type (block), intent(in) :: & this_block ! block info for this sub block ! !OUTPUT PARAMETERS: real (POP_r8), dimension(nx_block,ny_block), intent(out) :: & HTNEW ! smoothed HT field !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (POP_i4) :: & i,j, &! loop counters bid ! local block index integer (POP_i4), dimension(nx_block,ny_block) :: & NB, &! array to compute number of ocean neighbors IWORK ! local work space real (POP_r8), dimension(nx_block,ny_block) :: & WORK ! local work space !----------------------------------------------------------------------- ! ! smooth topography ! !----------------------------------------------------------------------- bid = this_block%local_id where (KMT(:,:,bid) > 0) IWORK = 1 HTNEW = HTOLD elsewhere IWORK = 0 HTNEW = c0 endwhere do j=this_block%jb,this_block%je do i=this_block%ib,this_block%ie WORK(i,j) = c4*HTNEW(i,j) + & c2*HTNEW(i+1,j ) + c2*HTNEW(i-1,j ) + & c2*HTNEW(i ,j+1) + c2*HTNEW(i ,j-1) + & HTNEW(i+1,j+1) + HTNEW(i+1,j-1) + & HTNEW(i-1,j+1) + HTNEW(i-1,j-1) NB(i,j) = c4*IWORK(i,j) + & c2*IWORK(i+1,j ) + c2*IWORK(i-1,j ) + & c2*IWORK(i ,j+1) + c2*IWORK(i ,j-1) + & IWORK(i+1,j+1) + IWORK(i+1,j-1) + & IWORK(i-1,j+1) + IWORK(i-1,j-1) end do end do !----------------------------------------------------------------------- ! ! new depth field ! !----------------------------------------------------------------------- where ((KMT(:,:,bid) /= 0) .and. (NB /= 0)) HTNEW = WORK/real(NB) elsewhere HTNEW = c0 endwhere !----------------------------------------------------------------------- !EOC end subroutine smooth_topo2 !*********************************************************************** end module topostress !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||