!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| module surface_hgt 2,10 !BOP ! !MODULE: surface_hgt ! ! !DESCRIPTION: ! Contains routine for computing change in surface height. ! ! !REVISION HISTORY: ! SVN:$Id: surface_hgt.F90 18264 2009-09-11 23:46:02Z njn01 $ ! !USES: use kinds_mod, only: int_kind, r8 use blocks, only: nx_block, ny_block, block, get_block ! use distribution, only: use domain_size use domain, only: nblocks_clinic, blocks_clinic use constants, only: grav, c0 use prognostic, only: max_blocks_clinic, PSURF, GRADPX, GRADPY, newtime, & curtime, oldtime use forcing_fields, only: FW, FW_OLD use grid, only: sfc_layer_type, sfc_layer_varthick, sfc_layer_rigid, & sfc_layer_oldfree, CALCU, tgrid_to_ugrid use time_management, only: mix_pass, dtp use tavg, only: define_tavg_field, tavg_requested, accumulate_tavg_field use movie, only: define_movie_field, movie_requested, update_movie_field implicit none private save ! !PUBLIC MEMBER FUNCTIONS: public :: init_surface_hgt, & dhdt !EOP !BOC !----------------------------------------------------------------------- ! ! tavg ids for surface height diagnostics ! !----------------------------------------------------------------------- integer (int_kind) :: & tavg_SSH, &! tavg id for sea surface height tavg_SSH2, &! tavg id for sea surface height squared (formerly H2) tavg_H3 ! tavg id for (Dx(SSH))**2 + (Dy(SSH))**2 !----------------------------------------------------------------------- ! ! movie ids for surface height diagnostics ! !----------------------------------------------------------------------- integer (int_kind) :: & movie_SSH ! movie id for sea surface height !EOC !*********************************************************************** contains !*********************************************************************** !BOP ! !IROUTINE: init_surface_hgt ! !INTERFACE: subroutine init_surface_hgt 1,4 ! !DESCRIPTION: ! Initialized quantities related to SSH, namely some tavg diagnostic ! ids. ! ! !REVISION HISTORY: ! same as module !EOP !BOC !----------------------------------------------------------------------- ! ! define tavg diagnostic fields ! !----------------------------------------------------------------------- call define_tavg_field(tavg_SSH,'SSH',2, & long_name='Sea Surface Height', & units='centimeter', grid_loc='2110', & coordinates='TLONG TLAT time') ! formerly H2 call define_tavg_field(tavg_SSH2,'SSH2',2, & long_name='SSH**2', & units='cm^2', grid_loc='2110', & coordinates='TLONG TLAT time') call define_tavg_field(tavg_H3,'H3',2, & long_name='(Dx(SSH))**2 + (Dy(SSH))**2', & units='----', grid_loc='2110', & coordinates='TLONG TLAT time') !----------------------------------------------------------------------- ! ! define movie diagnostic fields ! !----------------------------------------------------------------------- call define_movie_field(movie_SSH,'SSH',0, & long_name='Sea Surface Height', & units='cm', grid_loc='2110') !----------------------------------------------------------------------- !EOC end subroutine init_surface_hgt !*********************************************************************** !BOP ! !IROUTINE: dhdt ! !INTERFACE: subroutine dhdt(DH,DHU) 1,10 ! !DESCRIPTION: ! This routine calculates the change in surface height ! $d\eta/dt$ from surface pressure and including freshwater ! flux for a variable-thickness surface layer ! $(d\eta/dt - F_W)$. ! ! The surface pressure contribution at T points is ! \begin{equation} ! {{d\eta}\over{dt}} = {{(p^n - p^{n-1})}\over{g\Delta t}}. ! \end{equation} ! At U points, the change in surface height is the area-weighted ! average of its value at surrounding T points. ! ! In the advection routines, the vertical velocity $w = w_t,w_u$ in ! T,U columns is determined by integrating the continuity equation ! $L(1) = 0$ from the surface down to level k. Depending on surface ! layer type, the integration starts with: ! \begin{equation}\begin{array}{llll} ! w &=& 0 &{\rm (rigid\ lid)} \\ ! w &=& d\eta/dt &{\rm (old\ free\ surface)}\\ ! w &=& d\eta/dt - F_W &{\rm (variable\ thickness\ surface\ layer)} ! \end{array}\end{equation} ! ! At the surface, the time change of the surface height ! in T columns satisfies the barotropic continuity equation: ! \begin{equation} ! d\eta/dt + \nabla\cdot(H{\bf U}) = 0, ! \end{equation} ! where ${\bf U} = (U,V)$ is the barotropic velocity. ! ! On the second pass of a matsuno timestep, the predicted pressure ! from the 1st pass is contained in array PSURF(:,:,newtime) ! (PSURF(:,:,curtime) is not updated until the end of the matsuno ! step). ! ! Note that DH, DHU represents $d\eta/dt - F_W$ at ! T, U points in variable thickness surface layer ! ! !REVISION HISTORY: ! same as module ! !OUTPUT PARAMETERS: real (r8), dimension(nx_block,ny_block,max_blocks_clinic), & intent(out) :: & DH, DHU ! change in surface height (-Fw) at T,U points !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (int_kind) :: & iblock ! block index type (block) :: & this_block ! block information for current block real (r8), dimension(nx_block,ny_block) :: & WORK ! temporary work space ! real (r8), dimension(nx_block,ny_block) :: WORKX,WORKY ! real (r8) :: div_error, div_mag, dh_dt,dfw,dhtot !----------------------------------------------------------------------- ! ! calculate dh/dt or dh/dt - Fw at T points ! !----------------------------------------------------------------------- !$OMP PARALLEL DO PRIVATE(iblock, this_block, WORK) do iblock = 1,nblocks_clinic this_block = get_block(blocks_clinic(iblock),iblock) select case (sfc_layer_type) case (sfc_layer_varthick) if (mix_pass == 2) then DH(:,:,iblock) = (PSURF(:,:,newtime,iblock) - & PSURF(:,:,curtime,iblock))/(grav*dtp) - & FW(:,:,iblock) else DH(:,:,iblock) = (PSURF(:,:,curtime,iblock) - & PSURF(:,:,oldtime,iblock))/(grav*dtp) - & FW_OLD(:,:,iblock) endif case (sfc_layer_rigid) DH(:,:,iblock) = c0 case (sfc_layer_oldfree) if (mix_pass == 2) then DH(:,:,iblock) = (PSURF(:,:,newtime,iblock) - & PSURF(:,:,curtime,iblock))/(grav*dtp) else DH(:,:,iblock) = (PSURF(:,:,curtime,iblock) - & PSURF(:,:,oldtime,iblock))/(grav*dtp) endif end select !----------------------------------------------------------------------- ! ! Some debugging diagnostics ! ...check barotropic continuity equation: ! !----------------------------------------------------------------------- ! ! WORKX = HU(:,:,iblock)*UBTROP(:,:,curtime,iblock) ! WORKY = HU(:,:,iblock)*VBTROP(:,:,curtime,iblock) ! call div(1,WORK,WORKX,WORKY,this_block) ! WORKX = (DH(:,:,iblock)*TAREA(:,:,iblock) + WORK)**2 ! WORKY = TAREA(:,:,iblock)**2 ! div_error = sqrt(global_sum(WORKX,distrb_clinic,field_loc_center,RCALCT)/& ! global_sum(WORKY,distrb_clinic,field_loc_center,RCALCT)) ! WORKX = (DH(:,:,iblock)*TAREA(:,:,iblock))**2 ! WORKY = TAREA(:,:,iblock)**2 ! div_mag=sqrt(global_sum(WORKX,distrb_clinic,field_loc_center,RCALCT)/& ! global_sum(WORKY,distrb_clinic,field_loc_center,RCALCT)) ! if (my_task == master_task) then ! write(stdout,*) ' div error: ', div_error, div_mag ! endif ! WORK = -WORK/TAREA(:,:,iblock) ! ! WORKX = TAREA(:,:,iblock)*(PSURF(:,:,curtime,iblock) - & ! PSURF(:,:,oldtime,iblock))/grav ! WORKY = dtp*TAREA(:,:,iblock)*FW_OLD(:,:,iblock) ! WORK = TAREA(:,:,iblock)*PSURF(:,:,curtime,iblock)/grav ! dh_dt = global_sum(WORKX,distrb_clinic,field_loc_center,RCALCT)/area_t ! dfw = global_sum(WORKY,distrb_clinic,field_loc_center,RCALCT)/area_t ! dhtot = global_sum(WORK ,distrb_clinic,field_loc_center,RCALCT)/area_t ! if (my_task == master_task) then ! write(stdout,*) ' ' ! write(stdout,*) 'mean surface height ', dhtot ! write(stdout,*) 'mean change in surface height ', dh_dt ! write(stdout,*) 'mean change from freshwater ', dfw ! endif ! !----------------------------------------------------------------------- !----------------------------------------------------------------------- ! ! calculate dh/dt (or dh/dt - Fw) at U points as the area-weighted ! average of value at T points. ! !----------------------------------------------------------------------- call tgrid_to_ugrid(DHU(:,:,iblock),DH(:,:,iblock), iblock) where (.not. CALCU(:,:,iblock)) DHU(:,:,iblock) = c0 ! zero on land !----------------------------------------------------------------------- ! ! accumulate surface height tavg diagnostics if requested ! !----------------------------------------------------------------------- if (tavg_requested(tavg_SSH) .and. mix_pass /= 1) then WORK = PSURF(:,:,curtime,iblock)/grav call accumulate_tavg_field(WORK, tavg_SSH, iblock, 1) endif if (tavg_requested(tavg_SSH2) .and. mix_pass /= 1) then WORK = (PSURF(:,:,curtime,iblock)/grav)**2 call accumulate_tavg_field(WORK, tavg_SSH2, iblock, 1) endif if (tavg_requested(tavg_H3) .and. mix_pass /= 1) then WORK = ((GRADPX(:,:,curtime,iblock)/grav)**2 + & (GRADPY(:,:,curtime,iblock)/grav)**2) call accumulate_tavg_field(WORK, tavg_H3, iblock, 1) endif !----------------------------------------------------------------------- ! ! accumulate surface height movie diagnostics if requested ! !----------------------------------------------------------------------- if (movie_requested(movie_SSH) .and. mix_pass /= 1) then WORK = PSURF(:,:,curtime,iblock)/grav call update_movie_field(WORK, movie_SSH, iblock, 1) endif end do ! block loop !$OMP END PARALLEL DO !----------------------------------------------------------------------- end subroutine dhdt !*********************************************************************** end module surface_hgt !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||