!============================================================================== ! FLOW_SECONDORDER_MODULE !============================================================================== ! ! DATE AUTHOR CHANGES ! ! october 2009 Pieter Bart Smit New module ! !****************************************************************************** ! INTERFACE !****************************************************************************** module flow_secondorder_module implicit none save private !----------------------------- PARAMETERS ----------------------------------- include 'nh_pars.inc' !Default precision etc. !----------------------------- VARIABLES ----------------------------------- real(kind=rKind),dimension(:,:),allocatable :: wrk1 !Temporary storage for: ! (i ) du-velocity at i ,j+1/2 ! (ii) dv-velocity at i ,j+1/2 ! (iii) dqx at i+1/2,j real(kind=rKind),dimension(:,:),allocatable :: wrk2 !Temporary storage for: ! (i ) du-velocity at i+1/2,j ! (ii) dv-velocity at i+1/2,j ! (iii) dqx at i ,j+1/2 logical :: initialized = .false. public flow_secondorder_advUV public flow_secondorder_advW public flow_secondorder_con public minmod ! !****************************************************************************** ! SUBROUTINES/FUNCTIONS !****************************************************************************** contains subroutine flow_secondorder_init(s,iUnit) ! !------------------------------------------------------------------------------- ! DECLARATIONS !------------------------------------------------------------------------------- ! !-------------------------- PURPOSE ---------------------------- ! ! Initializes the resources needed for the second order mcCormack scheme ! ! !-------------------------- DEPENDENCIES ---------------------------- ! ! ! -- MODULES -- use spaceparams use params use xmpi_module, only: Halt_Program ! ! !-------------------------- ARGUMENTS ---------------------------- ! type(spacepars) ,intent(inout) :: s integer(kind=iKind),intent(in) :: iUnit !Unit number for error messages ! iUnit>0 : write to indicated unit ! iUnit<=0 : write to screen ! !-------------------------- LOCAL VARIABLES ---------------------------- ! integer(kind=iKind) :: iAllocErr ! Error code returned (if /=0) integer(kind=iKind) :: iWriteUnit ! Write unit (see also iUnit) ! !------------------------------------------------------------------------------- ! IMPLEMENTATION !------------------------------------------------------------------------------- ! if (iAllocErr /= 0) call Halt_program !Allocate resources allocate ( wrk1(s%nx+1,s%ny+1),stat=iAllocErr); if (iAllocErr /= 0) goto 10 allocate ( wrk2(s%nx+1,s%ny+1),stat=iAllocErr); if (iAllocErr /= 0) goto 10 wrk1 = 0.0_rKind wrk2 = 0.0_rKind 10 if (iAllocErr /=0) then if (iUnit > 0 ) then iWriteUnit = iUnit else iWriteUnit = iScreen endif write(iWriteUnit,'(a,i8)') 'Could not allocate array in flow_secondorder_init, error code returned: ', iAllocErr call Halt_program endif initialized = .true. end subroutine flow_secondorder_init ! !============================================================================== subroutine flow_secondorder_advUV(s,par,uu_old,vv_old) !============================================================================== ! ! DATE AUTHOR CHANGES ! ! November 2010 Pieter Bart Smit New Subroutine !------------------------------------------------------------------------------- ! DECLARATIONS !------------------------------------------------------------------------------- ! !-------------------------- PURPOSE ---------------------------- ! ! Calculates second order correction to the advection terms for U and V ! ! !-------------------------- DEPENDENCIES ---------------------------- ! use spaceparams use params ! !-------------------------- METHOD ---------------------------- ! ! First a prediction for the velocity on the new timelevel is done in flow_timestep ! using an explicit first order euler step. We use this prediction (s%uu,s%vv), and the velocity ! at the beginning of the step (uu_old, vv_old), to do a slope limited correction. ! ! !-------------------------- ARGUMENTS ---------------------------- ! type(spacepars) ,intent(inout) :: s type(parameters) ,intent(in) :: par real(kind=rkind),dimension(s%nx+1,s%ny+1),intent(in) :: vv_old !"Old" v-velocity real(kind=rkind),dimension(s%nx+1,s%ny+1),intent(in) :: uu_old !"Old" u-velocity ! !-------------------------- LOCAL VARIABLES ---------------------------- ! integer(kind=iKind) :: iww !i-2 :Two points 'west' of current point i integer(kind=iKind) :: iw !i-1 :One ... integer(kind=iKind) :: i !Current point integer(kind=iKind) :: ie !i+1 integer(kind=iKind) :: iee !i+2 integer(kind=iKind) :: jnn !j-2 integer(kind=iKind) :: jn !j-1 integer(kind=iKind) :: j !Current point integer(kind=iKind) :: js !j+1 integer(kind=iKind) :: jss !j+2 real(kind=rKind) :: mindepth ! Near the dry/wet interface the higher order interpolations ! can cause unwanted effects. To avoid this any extrapolation/interpolation ! is disabled when the lowest surface elevation within the molecule is lower then ! the highers bottom elevation. real(kind=rKind) :: delta1 ! "Central" difference real(kind=rKind) :: delta2 ! "Upwind" difference real(kind=rKind) :: qe !discharge east real(kind=rKind) :: qw !discharge west real(kind=rKind) :: qn !discharge north real(kind=rKind) :: qs !discharge south !------------------------------------------------------------------------------- ! IMPLEMENTATION !------------------------------------------------------------------------------- !== SECOND ORDER EXPLICIT CORRECTION TO U == !Initialize/allocate arrays on first entry if (.not. initialized) then call flow_secondorder_init(s,0) endif !-- calculate du in z-points -- do j=2,s%ny do i=2,s%nx wrk1(i,j) = 0.0_rKind ie = min(i+1,s%nx) iee = min(i+2,s%nx) iw = max(i-1,1) iww = max(i-2,1) mindepth = minval(s%zs(iww:iee,j))-maxval(s%zb(iww:iee,j)) if (mindepth > par%eps) then if ((s%qx(i,j)+s%qx(iw,j) > 0.d0) .and. (i>2)) then delta1 = (s%uu(i,j) -uu_old(iw ,j)) / (s%xu(i) -s%xu(iw)) delta2 = (s%uu(iw,j)-uu_old(iww,j)) / (s%xu(iw)-s%xu(iww)) wrk1(i,j) = (s%xz(i)-s%xu(iw)) *minmod(delta1,delta2) elseif (s%qx(i,j)+s%qx(iw,j) < 0.d0 .and. (i par%eps)) then if ((s%qy(i+1,j) + s%qy(i,j) > 0.d0) .and. j>2) then delta1 = (s%uu(i,js) -uu_old(i ,j )) / (s%yz(js)-s%yz(j )) delta2 = (s%uu(i,j) -uu_old(i ,jn)) / (s%yz(j )-s%yz(jn)) wrk2(i,j) = (s%yv(j)-s%yz(j))*minmod(delta1,delta2) elseif ( s%qy(i+1,j) + s%qy(i,j) < 0.d0 .and. j2) then do j=2,s%ny do i=2,s%nx wrk1(i,j) = 0. js = min(j+1,s%ny) jss = min(j+2,s%ny) jn = max(j-1,1) jnn = max(j-2,1) mindepth = minval(s%zs(i,jnn:jss))-maxval(s%zb(i,jnn:jss)) if (mindepth > par%eps) then if ((s%qy(i,j)+s%qy(i,jn) > par%Umin) .and. (j>2)) then delta1 = (s%vv(i,j ) - vv_old(i ,jn )) / (s%yv(j )-s%yv(jn )) delta2 = (s%vv(i,jn) - vv_old(i ,jnn)) / (s%yv(jn)-s%yv(jnn)) wrk1(i,j) = (s%yz(j)-s%yv(jn))*minmod(delta1,delta2) elseif (s%qy(i,j)+s%qy(i,jn) < -par%Umin .and. j par%eps) then if (s%qx(i,j+1) + s%qx(i,j) > par%Umin .and. i>2) then delta1 = (s%vv(ie,j) - vv_old(i ,j )) / (s%xz(ie)-s%xz(i )) delta2 = (s%vv(i ,j) - vv_old(iw,j)) / (s%xz(i )-s%xz(iw)) wrk2(i,j) = (s%xu(i)-s%xz(i))*minmod(delta1,delta2) elseif (s%qx(i,j+1) + s%qx(i,j) < -par%Umin .and. i par%eps) then if (s%qx(i,j) > 0.0_rKind .and. i>2) then delta1 = (w(ie,j ) - w_old(i ,j )) / (s%xz(ie )-s%xz(i )) delta2 = (w(i,j ) - w_old(iw ,j )) / (s%xz(i) -s%xz(iw)) wrk1(i,j) = (s%xu(i)-s%xz(i))*minmod(delta1,delta2) elseif (s%qx(i,j) < 0.0_rKind .and. i par%eps) then if (s%qy(i,j) > 0.0_rKind .and. j>2) then delta1 = (w(i,js ) - w_old(i ,j )) / (s%yz(js)-s%yz(j )) delta2 = (w(i,j ) - w_old(i ,jn)) / (s%yz(j )-s%yz(jn)) wrk2(i,j) = (s%yv(j)-s%yz(j))*minmod(delta1,delta2) elseif (s%qy(i,j) < 0.0_rKind .and. jpar%eps) then if (s%uu(i,j) > par%umin .and. i>2 ) then delta1 = (s%zs(ie,j)- zs_old(i,j ))/(s%xz(i+1)-s%xz(i)) delta2 = (s%zs(i,j) - zs_old(iw,j))/(s%xz(i) -s%xz(i-1)) wrk1(i,j) = s%uu(i,j)*(s%xu(i)-s%xz(i))*minmod(delta1,delta2) elseif (s%uu(i,j) < -par%umin .and. i 2) then do j=2,s%ny-1 do i=2,s%nx wrk2(i,j) = 0.0_rKind js = min(j+1,s%ny) jss = min(j+2,s%ny) jn = max(j-1,2) mindepth = minval(s%zs(i,jn:jss))-maxval(s%zb(i,jn:jss)) if (mindepth> par%eps) then if (s%vv(i,j) > par%Umin .and. j>2) then delta1 = (s%zs(i,js) - zs_old(i,j ))/(s%yz(j+1)-s%yz(j)) delta2 = (s%zs(i,j) - zs_old(i,jn))/(s%yz(j) -s%yz(j-1)) wrk2(i,j) = s%vv(i,j)*(s%yv(j)-s%yz(j))*minmod(delta1,delta2) elseif (s%vv(i,j) < -par%Umin .and. j 0.0_rKind) then minmod = min(delta1,delta2) elseif (delta1 < 0.0_rKind) then minmod = max(delta1,delta2) else minmod = 0.0_rKind endif end function minmod end module flow_secondorder_module