XBeach
C:/repositories/XBeach/trunk/src/xbeachlibrary/wave_directions.F90
Go to the documentation of this file.
00001 module wave_directions_module
00002    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00003    ! Copyright (C) 2007 UNESCO-IHE, WL|Delft Hydraulics and Delft University !
00004    ! Dano Roelvink, Ap van Dongeren, Ad Reniers, Jamie Lescinski,            !
00005    ! Jaap van Thiel de Vries, Robert McCall                                  !
00006    !                                                                         !
00007    ! d.roelvink@unesco-ihe.org                                               !
00008    ! UNESCO-IHE Institute for Water Education                                !
00009    ! P.O. Box 3015                                                           !
00010    ! 2601 DA Delft                                                           !
00011    ! The Netherlands                                                         !
00012    !                                                                         !
00013    ! This library is free software; you can redistribute it and/or           !
00014    ! modify it under the terms of the GNU Lesser General Public              !
00015    ! License as published by the Free Software Foundation; either            !
00016    ! version 2.1 of the License, or (at your option) any later version.      !
00017    !                                                                         !
00018    ! This library is distributed in the hope that it will be useful,         !
00019    ! but WITHOUT ANY WARRANTY; without even the implied warranty of          !
00020    ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU        !
00021    ! Lesser General Public License for more details.                         !
00022    !                                                                         !
00023    ! You should have received a copy of the GNU Lesser General Public        !
00024    ! License along with this library; if not, write to the Free Software     !
00025    ! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307     !
00026    ! USA                                                                     !
00027    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00028    implicit none
00029    save
00030 
00031    private
00032    public wave_directions
00033 contains
00034 
00035    subroutine wave_directions(s,par)
00036       use params,                only: parameters
00037       use spaceparams
00038       use roelvink_module,       only: roelvink, baldock, janssen_battjes
00039       use wave_functions_module, only: slope2d, advecthetaho, advecxho, advecyho, compute_wave_direction_velocities
00040       use xmpi_module
00041       use logging_module,        only: writelog, progress_indicator
00042       use paramsconst
00043 
00044       ! wwvv in my testcase, this routine was not called, so it is not
00045       ! tested. Nevertheless, I put in code for the parallel version.
00046 
00047       IMPLICIT NONE
00048 
00049       type(spacepars), target     :: s
00050       type(parameters)            :: par
00051 
00052       integer                     :: i,imax,i1
00053       integer                     :: j
00054       integer                     :: itheta,iter,itermax
00055       integer,save                :: scheme_local,scheme_local_yadvec
00056       real*8,dimension(:),allocatable,save        :: dist,factor,e01
00057       real*8 , dimension(:,:)  ,allocatable,save  :: dhdx,dhdy,dudx,dudy,dvdx,dvdy
00058       real*8 , dimension(:,:)  ,allocatable,save  :: uorb
00059       real*8 , dimension(:,:)  ,allocatable,save  :: sinh2kh ! ,wm
00060       real*8 , dimension(:,:,:),allocatable,save  :: xadvec,yadvec,thetaadvec,dd
00061       real*8 , dimension(:),allocatable,save      :: Hprev,thetaprev
00062       real*8                                      :: Herr,thetaerr,thetaerr_cyc,dtw
00063       logical                                     :: stopiterate
00064 
00065       if (.not. allocated(e01)) then
00066          allocate(e01(1:s%ntheta_s))
00067          allocate(dist(1:s%ntheta_s))
00068          allocate(factor(1:s%ntheta_s))
00069          allocate(xadvec    (s%nx+1,s%ny+1,s%ntheta_s))
00070          allocate(yadvec    (s%nx+1,s%ny+1,s%ntheta_s))
00071          allocate(thetaadvec(s%nx+1,s%ny+1,s%ntheta_s))
00072          allocate(dd        (s%nx+1,s%ny+1,s%ntheta_s))
00073 
00074 
00075          allocate(dhdx(s%nx+1,s%ny+1))
00076          allocate(dhdy(s%nx+1,s%ny+1))
00077          allocate(dudx(s%nx+1,s%ny+1))
00078          allocate(dudy(s%nx+1,s%ny+1))
00079          allocate(dvdx(s%nx+1,s%ny+1))
00080          allocate(dvdy(s%nx+1,s%ny+1))
00081          allocate(uorb(s%nx+1,s%ny+1))
00082          allocate(sinh2kh(s%nx+1,s%ny+1))
00083          allocate(Hprev(s%ny+1))
00084          allocate(thetaprev(s%ny+1))
00085 
00086 
00087          if(par%scheme==SCHEME_WARMBEAM) then
00088             scheme_local = SCHEME_UPWIND_2 ! note, this is already stated as warning in log file during read of params.txt
00089          else
00090             scheme_local = par%scheme
00091          endif
00092          if(par%cyclic==1 .and. scheme_local .ne. SCHEME_UPWIND_1) then
00093             scheme_local_yadvec = SCHEME_UPWIND_1
00094             call writelog('lws','(a)', 'Warning: y-advection in stationary wave solver set to upwind_1 for convergence')
00095          else
00096             scheme_local_yadvec = scheme_local
00097          endif
00098       endif
00099 
00100 
00101       xadvec      = 0.0d0
00102       yadvec      = 0.0d0
00103       thetaadvec  = 0.0d0
00104       dd          = 0.0d0
00105       dhdx        = 0.0d0
00106       dhdy        = 0.0d0
00107       dudx        = 0.0d0
00108       dudy        = 0.0d0
00109       dvdx        = 0.0d0
00110       dvdy        = 0.0d0
00111       sinh2kh     = 0.0d0
00112 
00113 
00114       ! Slopes of water depth
00115       call slope2D(s%hhws,s%nx,s%ny,s%dsu,s%dnv,dhdx,dhdy,s%wete)
00116       ! Dano limit slopes used in refraction to avoid unrealistic refraction speeds
00117       dhdx=sign(1.d0,dhdx)*min(abs(dhdx),0.1d0)
00118       dhdy=sign(1.d0,dhdy)*min(abs(dhdy),0.1d0)
00119       if (par%wci==1) then
00120          call slope2D(s%uws,s%nx,s%ny,s%dsu,s%dnv,dudx,dudy,s%wete)
00121          call slope2D(s%vws,s%nx,s%ny,s%dsu,s%dnv,dvdx,dvdy,s%wete)
00122       else
00123          dudx = 0.d0
00124          dudy = 0.d0
00125          dvdx = 0.d0
00126          dvdy = 0.d0
00127       endif
00128       ! wwvv these slope routines are in wave_timestep, and are
00129       !   MPI-aware
00130       !
00131       ! Calculate once sinh(2kh)
00132 
00133       where(s%wete==1 .and. 2*s%hhws*s%k<=3000.d0)
00134          sinh2kh=sinh(min(2*s%k*s%hhws,10.0d0))
00135       elsewhere
00136          sinh2kh = 3000.d0
00137       endwhere
00138       
00139       ! all dry cells have zero energy
00140       do itheta=1,s%ntheta_s
00141          where(s%wete==0)
00142             s%ee_s(:,:,itheta) = 0.d0
00143         endwhere
00144       enddo
00145       where(s%wete==0)
00146           s%E=0.d0
00147           s%H=0.d0
00148       endwhere
00149 
00150       forall (i=1:s%nx+1,j=1:s%ny+1,s%wete(i,j)==1)
00151          s%thetamean(i,j)=(sum(s%ee_s(i,j,:)*s%thet_s(i,j,:))/s%ntheta_s)/(max(sum(s%ee_s(i,j,:)),0.00001d0)/s%ntheta_s)
00152       endforall
00153 
00154       !
00155       ! split wave velocities in wave grid directions theta
00156       call compute_wave_direction_velocities(s,par,2,dhdx,dhdy,dudx,dudy,dvdx,dvdy,sinh2kh)
00157 
00158       !dtw=.9*minval(xz(2:nx+1)-xz(1:nx))/maxval(cgx_s)
00159       
00160       ! Initialize at the boundary
00161       s%E(1,:)=max(sum(s%ee_s(1,:,:),2)*s%dtheta_s,0.d0)
00162       s%H(1,:)=sqrt(s%E(1,:)/par%rhog8)
00163 
00164       imax=s%nx
00165       !Dano  This is ok, since we will set mpiboundary to y in stationary mode
00166       !
00167       ! write to screen that waves are updated
00168       if(xmaster) call writelog('ls','(a,f0.2,a)','Computing wave directions at t = ',par%t,' s')
00169       call progress_indicator(.true.,0.d0,5.d0,2.d0)
00170       itermax = 0
00171       do i=2,imax
00172          call progress_indicator(.false.,dble(i)/imax*100,5.d0,2.d0)
00173 
00174          if(par%wci==0) then
00175             dtw=        .5d0*minval(s%dsu(i-1:i+1,jmin_ee:jmax_ee))/max(1.0d-6,maxval(abs(s%cgx_s(i-1:i+1,jmin_ee:jmax_ee,:))))
00176             dtw=min(dtw,.5d0*minval(s%dnv(i,jmin_ee:jmax_ee))      /max(1.0d-6,maxval(abs(s%cgy_s(i,jmin_ee:jmax_ee,:)      ))) )
00177             dtw=min(dtw,.5d0*s%dtheta_s                            /max(1.0d-6,maxval(abs(s%ctheta_s(i,jmin_ee:jmax_ee,:)   ))) )
00178             !Dano: need to make sure all processes use the same dtw, min of all processes
00179 #ifdef USEMPI
00180             call xmpi_allreduce(dtw,MPI_MIN)
00181 #endif
00182          else
00183             dtw = par%dt
00184          endif
00185 
00186          Herr=huge(1.d0)
00187          thetaerr = 2*par%px
00188          iter=0
00189          stopiterate=.false.
00190          do while (stopiterate .eqv. .false.)
00191             iter=iter+1
00192             Hprev=s%H(i,:)
00193             thetaprev = s%thetamean(i,:)
00194             !
00195             ! transform to wave action
00196             !
00197             i1=max(i-2,1)
00198             do itheta=1,s%ntheta_s
00199                where(s%wete(i1:i+1,:)==1)
00200                   s%ee_s(i1:i+1,:,itheta) = s%ee_s(i1:i+1,:,itheta)/s%sigm(i1:i+1,:)
00201                endwhere
00202             enddo
00203             !
00204             ! Upwind Euler timestep propagation
00205             !
00206             ! Robert: can we also use WARMBEAM here? [Robert: answer is no!]
00207             if  (i>2.and. scheme_local==SCHEME_UPWIND_2) then
00208                call advecxho(s%ee_s(i-2:i+1,:,:),s%cgx_s(i-2:i+1,:,:),xadvec(i-2:i+1,:,:),    &
00209                3,s%ny,s%ntheta_s,s%dnu(i-2:i+1,:),s%dsu(i-2:i+1,:),s%dsdnzi(i-2:i+1,:),SCHEME_UPWIND_2, &
00210                s%wete(i-2:i+1,:),dtw,s%dsz)
00211             else
00212                call advecxho(s%ee_s(i-1:i+1,:,:),s%cgx_s(i-1:i+1,:,:),xadvec(i-1:i+1,:,:),    &
00213                2,s%ny,s%ntheta_s,s%dnu(i-1:i+1,:),s%dsu(i-1:i+1,:),s%dsdnzi(i-1:i+1,:),SCHEME_UPWIND_1,&
00214                s%wete(i-1:i+1,:),dtw,s%dsz)
00215             endif
00216             ! Robert: could this also be warm-beam?
00217             if (s%ny>0) then
00218                call advecyho(s%ee_s(i,:,:),s%cgy_s(i,:,:),yadvec(i,:,:),                                  &
00219                0,s%ny,s%ntheta_s,s%dsv(i,:),s%dnv(i,:),s%dsdnzi(i,:),scheme_local_yadvec,s%wete(i,:),dtw,s%dnz)
00220             endif
00221             ! Robert: could this also be warm-beam?
00222             call advecthetaho(s%ee_s(i,:,:),s%ctheta_s(i,:,:),thetaadvec(i,:,:),0,s%ny,s%ntheta_s, &
00223             s%dtheta_s,scheme_local,s%wete(i,:))
00224 
00225             s%ee_s(i,:,:)=s%ee_s(i,:,:)-dtw*(xadvec(i,:,:) + yadvec(i,:,:) + thetaadvec(i,:,:))
00226             !
00227             ! transform back to wave energy
00228             !
00229             do itheta=1,s%ntheta_s
00230                where(s%wete(i1:i+1,:)==1)
00231                   s%ee_s(i1:i+1,:,itheta) = s%ee_s(i1:i+1,:,itheta)*s%sigm(i1:i+1,:)
00232                   s%ee_s(i1:i+1,:,itheta)=max(s%ee_s(i1:i+1,:,itheta),0.0d0)
00233                endwhere
00234             enddo
00235 #ifdef USEMPI
00236             call xmpi_shift(s%ee_s(i-1:i+1,:,:),SHIFT_Y_R,1,2)
00237             call xmpi_shift(s%ee_s(i-1:i+1,:,:),SHIFT_Y_L,3,4)
00238 #endif            
00239             !
00240             ! Energy integrated over wave directions,Hrms
00241             !
00242             forall(j=1:s%ny+1,s%wete(i,j)==1)
00243                s%E(i,j)=sum(s%ee_s(i,j,:))*s%dtheta_s
00244             endforall
00245             where(s%wete(i,:)==1)
00246                s%H(i,:)=sqrt(s%E(i,:)/par%rhog8)
00247             endwhere
00248             ! check with gammax
00249             do j=1,s%ny+1
00250                if (s%wete(i,j)==1 .and. s%H(i,j)>par%gammax*s%hhws(i,j)) then
00251                   do itheta=1,s%ntheta_s
00252                      s%ee_s(i,j,itheta)=s%ee_s(i,j,itheta)/(s%H(i,j)/(par%gammax*s%hhws(i,j)))**2
00253                   enddo
00254                   s%H(i,j)=par%gammax*s%hhws(i,j)
00255                   s%E(i,j)=par%rhog8*s%H(i,j)**2
00256                endif
00257             enddo
00258             !
00259             if (par%snells==0) then !Dano not for SNellius
00260                where(s%wete(i,:)==1)
00261                   s%thetamean(i,:) = (sum(s%ee_s(i,:,:)*s%thet_s(i,:,:),2)/s%ntheta_s)/ &
00262                   (max(sum(s%ee_s(i,:,:),2),0.000010d0)/s%ntheta_s)
00263                endwhere
00264             endif
00265             !
00266             ! Total dissipation
00267 
00268             select case(par%break)
00269              case(BREAK_ROELVINK1,BREAK_ROELVINK2)
00270                call roelvink       (par,s,i)
00271              case(BREAK_BALDOCK)
00272                call baldock        (par,s,i)
00273              case(BREAK_JANSSEN)
00274                call janssen_battjes(par,s,i)
00275             end select
00276 
00277 
00278             ! Dissipation by bed friction
00279             where(s%fw(i,:)>0.d0 .and. s%wete(i,:)==1 .and. s%hhws(i,:)<=par%fwcutoff)
00280                uorb(i,:)=par%px*s%H(i,:)/par%Trep/sinh(min(max(s%k(i,:),0.01d0)*s%hhws(i,:),10.0d0))
00281                s%Df(i,:)=0.6666666d0/par%px*par%rho*s%fw(i,:)*uorb(i,:)**3
00282             elsewhere
00283                s%Df(i,:) = 0.d0
00284             end where
00285             !
00286             ! Distribution of dissipation over directions and frequencies
00287             !
00288             do itheta=1,s%ntheta_s
00289                where(s%wete(i,:)==1)
00290                   dd(i,:,itheta)=s%ee_s(i,:,itheta)*(s%D(i,:)+s%Df(i,:))/max(s%E(i,:),0.00001d0) ! Robert: missing Dveg here!
00291                elsewhere
00292                   dd(i,:,itheta)=0.d0
00293                endwhere
00294             end do
00295             !
00296             ! Euler step dissipation
00297             !
00298             do j=jmin_ee,jmax_ee
00299                do itheta=1,s%ntheta_s
00300                   if (dtw*dd(i,j,itheta)>s%ee_s(i,j,itheta) .and. s%wete(i,j)==1) then
00301                      dtw=min(dtw,.5*s%ee_s(i,j,itheta)/dd(i,j,itheta))
00302                   endif
00303                enddo
00304             enddo
00305             !Dano: need to make sure all processes use the same dtw, min of all processes
00306 #ifdef USEMPI
00307             call xmpi_allreduce(dtw,MPI_MIN)
00308 #endif
00309             do j=1,s%ny+1
00310                do itheta=1,s%ntheta_s
00311                   if(s%wete(i,j)==1) then
00312                      s%ee_s(i,j,itheta)=s%ee_s(i,j,itheta)-dtw*dd(i,j,itheta)
00313                      s%ee_s(i,j,itheta)=max(s%ee_s(i,j,itheta),0.0d0)
00314                   else
00315                      s%ee_s(i,j,itheta)=0.0d0
00316                   end if
00317                end do
00318             end do
00319             ! Lateral boundary condition
00320             if (xmpi_isleft .and. s%ny>0) then
00321                do itheta=1,s%ntheta_s
00322                   !if (s%sinth_s(i,1,itheta)>=0.) then  ! Robert: this is different to wave_stationary
00323                      s%ee_s(i,1,itheta)=s%ee_s(i,2,itheta)
00324                   !endif
00325                enddo
00326                s%k(:,1)=s%k(:,2)
00327                s%sigm(:,1)=s%sigm(:,2)
00328             endif
00329             if (xmpi_isright .and. s%ny>0) then
00330                do itheta=1,s%ntheta_s
00331                   !if (s%sinth_s(i,s%ny+1,itheta)<=0.) then
00332                      s%ee_s(i,s%ny+1,itheta)=s%ee_s(i,s%ny,itheta)
00333                   !endif
00334                end do
00335                s%k(:,s%ny+1)=s%k(:,s%ny)
00336                s%sigm(:,s%ny+1)=s%sigm(:,s%ny)
00337             endif
00338             !
00339             ! Compute mean wave direction
00340             !
00341             if (par%snells==0) then
00342                where(s%wete(i,:)==1)
00343                   s%thetamean(i,:)=(sum(s%ee_s(i,:,:)*s%thet_s(i,:,:),2)/size(s%ee_s(i,:,:),2)) &
00344                   /(max(sum(s%ee_s(i,:,:),2),0.000010d0) /size(s%ee_s(i,:,:),2))
00345                elsewhere
00346                   ! forward-copy wave directions on dry cells in case they flood before the next wave update
00347                   s%thetamean(i,:) = s%thetamean(i-1,:)
00348                endwhere
00349             endif
00350             !
00351             ! Energy integrated over wave directions,Hrms
00352             !
00353             where(s%wete(i,:)==1)
00354                s%E(i,:)=sum(s%ee_s(i,:,:),2)*s%dtheta_s
00355                s%H(i,:)=sqrt(s%E(i,:)/par%rhog8)
00356             elsewhere
00357                s%E(i,:)=0.d0
00358                s%H(i,:)=0.d0
00359             endwhere
00360             Herr=maxval(abs(Hprev(jmin_ee:jmax_ee)-s%H(i,jmin_ee:jmax_ee)),mask=s%wete(i,:)==1)
00361 
00362             thetaerr = 0.d0
00363             do j=jmin_ee,jmax_ee
00364                thetaerr_cyc = minval( (/ abs(thetaprev(j)-(s%thetamean(i,j)-2*par%px)) , &
00365                abs(thetaprev(j)-(s%thetamean(i,j)         )) , &
00366                abs(thetaprev(j)-(s%thetamean(i,j)+2*par%px)) /) )
00367                thetaerr = max(thetaerr,thetaerr_cyc)
00368             enddo
00369 
00370 #ifdef USEMPI
00371             call xmpi_allreduce(Herr,MPI_MAX)
00372             call xmpi_allreduce(thetaerr,MPI_MAX)
00373 #endif
00374 
00375             ! Stopping criteria
00376             if (iter<par%maxiter) then
00377                if (Herr<par%maxerror .and. thetaerr<par%maxerror_angle) then
00378                   stopiterate=.true.
00379                   !if(xmaster) call writelog('ls','(a,i4,a,i4)','Wave propagation row ',i,', iteration ',iter)
00380                endif
00381             else
00382                stopiterate=.true.
00383                if(xmaster) call writelog('ls','(a,i4,a,i4,a,f5.4)','Wave propagation row ',i,', iteration ',iter,', error: ',Herr)
00384             endif
00385          enddo ! End while loop
00386          itermax = max(itermax,iter)
00387       enddo ! End do i=2:s%nx loop
00388       call writelog('ls','(a,i4)','Maximum number of iterations: ',itermax)
00389 
00390       s%ee_s(s%nx+1,:,:) = s%ee_s(s%nx,:,:)
00391       s%E(s%nx+1,:)    = s%E(s%nx,:)
00392       s%H(s%nx+1,:)    = s%H(s%nx,:)
00393       s%k(s%nx+1,:)   = s%k(s%nx,:)
00394       s%sigm(s%nx+1,:) = s%sigm(s%nx,:)
00395       s%cg(s%nx+1,:)   = s%cg(s%nx,:)
00396       s%c(s%nx+1,:)    = s%c(s%nx,:)
00397       s%thet_s(s%nx+1,:,:) = s%thet_s(s%nx,:,:)
00398 
00399    end subroutine wave_directions
00400 end module wave_directions_module
 All Classes Files Functions Variables Defines