XBeach
C:/repositories/XBeach/trunk/src/xbeachlibrary/waveparams.F90
Go to the documentation of this file.
00001 module waveparams
00002    use constants, only: pi, compi
00003    implicit none
00004    save
00005    private
00006    public makebcf
00007    type waveparameters
00008 
00009       integer                                 :: K, Npy, Nr
00010       integer*4                               :: listline
00011       integer, dimension(:), pointer          :: index_vector
00012 
00013       real*8                                  :: mainang,dang, scoeff                    !scoeff is now a wp
00014       real*8                                  :: h0t0
00015       real*8                                  :: hm0gew, df
00016       real*8                                  :: Ly, dt, rt
00017       real*8,dimension(:),pointer             :: S0, dthetafin, fgen, theta0
00018       real*8,dimension(:),pointer             :: Sf, Dd, f, theta, window
00019       real*8,dimension(:,:),pointer           :: S_array
00020 
00021       double complex,dimension(:,:),pointer   :: CompFn
00022 
00023    end type waveparameters
00024 
00025 contains
00026 
00027    ! --------------------------------------------------------------
00028    ! ------------- Sorting for calling functions ------------------
00029    ! --------------------------------------------------------------
00030 
00037    subroutine makebcf(par,s,wp)
00038 
00039       use params,         only: parameters
00040       use spaceparamsdef, only: spacepars
00041       use readkey_module, only: readkey_dbl
00042       use xmpi_module,    only: xmaster
00043       use typesandkinds,  only: slen
00044       use paramsconst
00045       IMPLICIT NONE
00046 
00047       ! Input / output variables
00048       type(parameters), INTENT(INOUT)             :: par
00049       type(spacepars), intent(IN)                 :: s
00050 
00051       type(waveparameters), intent(inout)         :: wp
00052       real*8,save                                 :: bcendtime
00053       character(len=slen)                         :: fname,Ebcfname,qbcfname
00054       character*8                                 :: testc
00055       logical                                     :: makefile
00056       integer,save                                :: reuse  ! = 0 used to be in code
00057       integer,save                                :: counter
00058 
00059       ! Flag that determines whether new BCF files are created or not
00060       makefile=.false.
00061 
00062       ! Check whether this is the first time step
00063       if (abs(par%t-par%dt)<1.d-6) then
00064          bcendtime=0
00065          wp%listline=0
00066          counter=0
00067          wp%scoeff=-1
00068 
00069          if(xmaster) then
00070             open(74,file=par%bcfile,form='formatted')
00071             if (par%wbctype/=WBCTYPE_JONS_TABLE) read(74,*)testc
00072          endif
00073 
00074          if(xmaster) then
00075             ! Create new BCF files, if in master process
00076             open(53,file='ebcflist.bcf',form='formatted',status='replace')
00077             open(54,file='qbcflist.bcf',form='formatted',status='replace')
00078             close(53)
00079             close(54)
00080          endif
00081 
00082          ! Check whether BCF files should be reused
00083          if (testc=='FILELIST' .or. par%wbctype==WBCTYPE_JONS_TABLE) then
00084             reuse=0
00085          else
00086             reuse=1
00087             if(xmaster) then
00088                close(74) ! only close if this is not the list of files
00089             endif
00090          end if
00091       end if
00092 
00093       ! Check whether this is the last time step
00094       if (par%t>(par%tstop-par%dt)) then
00095          ! Prevent recalculation of boundary conditions for last timestep
00096          return
00097          close(74)
00098       end if
00099 
00100       ! wp%listline is not increased, therefore, first line of current bcf
00101       ! is used (i.e. all zeros)
00102 
00103       ! Check whether BCF files should be reused
00104       if (reuse==0) then
00105 
00106          ! Read rt and dt values
00107          if(xmaster) then
00108             if (par%wbctype/=WBCTYPE_JONS_TABLE) then
00109                read(74,*)wp%rt,wp%dt,fname
00110                if (par%morfacopt==1) wp%rt = wp%rt / max(par%morfac,1.d0)
00111             endif
00112          endif
00113 
00114 #ifdef USEMPI
00115          !Dano call xmpi_bcast(wp%rt)
00116          !Dano call xmpi_bcast(wp%dt)
00117          !Dano call xmpi_bcast(fname)
00118 #endif
00119 
00120          ! Create filenames for BCF files
00121          if (par%wbctype/=WBCTYPE_JONS_TABLE) then
00122             Ebcfname='E_'//trim(fname)
00123             qbcfname='q_'//trim(fname)
00124          else
00125             counter=counter+1
00126             write(Ebcfname, '(A,I0.6,A)') 'Ejonsw', counter, '.bcf'
00127             write(qbcfname, '(A,I0.6,A)') 'qjonsw', counter, '.bcf'
00128          endif
00129       else
00130 
00131          ! Read rt and dt values in first timestep
00132          if (abs(par%t-par%dt)<1.d-6) then
00133             wp%rt = readkey_dbl ('params.txt', 'rt', 3600.d0, 1200.d0, 7200.d0, bcast=.false.)
00134             if (par%morfacopt==1) wp%rt = wp%rt / max(par%morfac,1.d0)
00135             wp%dt = readkey_dbl ('params.txt', 'dtbc', 0.1d0, 0.01d0, 1.0d0, bcast=.false.)
00136          end if
00137 
00138          ! Create filenames for BCF files
00139          fname=par%bcfile
00140          Ebcfname='E_reuse.bcf'
00141          qbcfname='q_reuse.bcf'
00142       end if
00143 
00144       ! (Re)create BCF files if this is the first time step or it is explicitly
00145       ! requested
00146       if (abs(par%t-par%dt)<1.d-6) then
00147          makefile=.true.
00148       else
00149          if (reuse==0) then
00150             makefile=.true.
00151          end if
00152       end if
00153 
00154       ! (Re)create BCF files, if requested
00155       if (makefile) then
00156 
00157          ! Calculate weighed average water depth at offshore boundary
00158          if (s%ny>0) then
00159             wp%h0t0=sum(s%hh(1,2:s%ny)*s%dnv(1,2:s%ny))/sum(s%dnv(1,2:s%ny))
00160          else
00161             wp%h0t0 = s%hh(1,1)
00162          endif
00163 
00164          if (par%wbctype==WBCTYPE_PARAMETRIC .or. par%wbctype==WBCTYPE_JONS_TABLE) then
00165             ! Use JONSWAP spectrum
00166             call build_jonswap(par,s,wp,fname)
00167             call build_etdir(par,s,wp,Ebcfname)
00168             call build_boundw(par,s,wp,qbcfname)
00169          elseif (par%wbctype==WBCTYPE_SWAN) then
00170             ! Use SWAN data
00171             call swanreader(par,s,wp,fname)
00172             call build_etdir(par,s,wp,Ebcfname)
00173             call build_boundw(par,s,wp,qbcfname)
00174          elseif (par%wbctype==WBCTYPE_VARDENS) then
00175             ! Use variance density spectrum
00176             call vardensreader(par,s,wp,fname)
00177             call build_etdir(par,s,wp,Ebcfname)
00178             call build_boundw(par,s,wp,qbcfname)
00179          endif
00180       end if
00181 
00182       ! Define line counter for boundaryconditions.f90
00183       wp%listline=wp%listline+1
00184 
00185       ! Define endtime for boundary conditions, boundaryconditions.f90 should
00186       ! recreate BCF files after this moment
00187       bcendtime=bcendtime+wp%rt
00188 
00189       if(xmaster) then
00190 
00191          ! Write lists with BCF information
00192          open(53,file='ebcflist.bcf',form='formatted',position='append')
00193          open(54,file='qbcflist.bcf',form='formatted',position='append')
00194          write(53,'(f12.3,a,f12.3,a,f9.3,a,f9.5,a,f11.5,a)') &
00195          & bcendtime,' ',wp%rt,' ',wp%dt,' ',par%Trep,' ',wp%mainang,' '//trim(Ebcfname)
00196          write(54,'(f12.3,a,f12.3,a,f9.3,a,f9.5,a,f11.5,a)') &
00197          & bcendtime,' ',wp%rt,' ',wp%dt,' ',par%Trep,' ',wp%mainang,' '//trim(qbcfname)
00198          close(53)
00199          close(54)
00200       endif
00201 
00202    end subroutine makebcf
00203 
00204    ! --------------------------------------------------------------
00205    ! ----------------------Read spectrum files --------------------
00206    ! --------------------------------------------------------------
00207    subroutine build_jonswap(par,s,wp,fname)
00208 
00209       use readkey_module, only: readkey_dbl, readkey
00210       use params,         only: parameters
00211       use spaceparamsdef
00212       use xmpi_module
00213       use logging_module, only: writelog
00214       use paramsconst
00215 
00216       IMPLICIT NONE
00217 
00218       ! Input / output variables
00219       type(parameters), INTENT(INout)         :: par
00220       type(spacepars), intent(IN)             :: s
00221       type(waveparameters), INTENT(INOUT)     :: wp
00222       character(len=*)                        :: fname
00223 
00224       ! Internal variables
00225       integer                                 :: i=0,ii,nang,nfreq,ier
00226       integer                                 :: firstp, lastp
00227       real*8,dimension(:),allocatable         :: temp, x, y
00228       real*8                                  :: dfj, fnyq, fp
00229       real*8                                  :: gam
00230       character(len=80)                       :: dummystring
00231 
00232       fnyq = -123
00233       dfj  = -123
00234       ! Read JONSWAP data
00235       if(xmaster) then
00236 
00237          ! Check whether spectrum characteristics or table should be used
00238          if (par%wbctype /= WBCTYPE_JONS_TABLE) then
00239 
00240             ! Use spectrum characteristics
00241             call writelog('sl','','waveparams: Reading from ',trim(fname),' ...')
00242          else
00243 
00244             ! Use spectrum table
00245             call readkey('params.txt','bcfile',fname)
00246             call writelog('sl','','waveparams: Reading from table',fname,' ...')
00247             read(74,*,iostat=ier)wp%hm0gew,fp,wp%mainang,gam,wp%scoeff,wp%rt,wp%dt
00248             if (par%morfacopt==1) wp%rt = wp%rt/max(par%morfac,1.d0)
00249 
00250             ! Set extra parameters
00251             fp=1.d0/fp
00252             fnyq=3.d0*fp
00253             dfj=fp/20.d0
00254          endif
00255       endif
00256 
00257       ! Read JONSWAP characteristics
00258       if (par%wbctype/=WBCTYPE_JONS_TABLE) then
00259          !                                      Input file   Keyword     Default     Minimum     Maximum
00260          wp%hm0gew           = readkey_dbl (fname,       'Hm0',      0.0d0,      0.00d0,     5.0d0,      bcast=.false. )
00261          fp                  = readkey_dbl (fname,       'fp',       0.08d0,     0.0625d0,   0.4d0,      bcast=.false. )
00262          fnyq                = readkey_dbl (fname,       'fnyq',     max(0.3d0,3.d0*fp),    0.2d0,      1.0d0, bcast=.false. )
00263          dfj                 = readkey_dbl (fname,       'dfj',      fnyq/200,   fnyq/1000,  fnyq/20,    bcast=.false. )
00264          gam                 = readkey_dbl (fname,       'gammajsp', 3.3d0,      1.0d0,      5.0d0,      bcast=.false. )
00265          wp%scoeff           = readkey_dbl (fname,       's',        10.0d0,     1.0d0,      1000.0d0,   bcast=.false. )
00266          wp%mainang          = readkey_dbl (fname,       'mainang',  270.0d0,    0.0d0,      360.0d0,    bcast=.false. )
00267          !
00268          if(xmaster) then
00269             call readkey(fname,'checkparams',dummystring)
00270          endif
00271       endif
00272 
00273       ! Determine number of nodes in y-direction
00274       wp%Npy=s%ny+1
00275 
00276       ! Print JONSWAP characteristics to screen
00277       call writelog('sl','(a,f0.3,a,f0.3,a,f0.3,a,f0.3)','Input checked: Hm0 = ',wp%hm0gew,' Tp = ',1.d0/fp, &
00278       ' dir = ',wp%mainang,' duration = ',wp%rt)
00279 
00280       ! approximation from Coastal Engineering: Processes, Theory and Design Practice
00281       ! Dominic Reeve, Andrew Chadwick 2004
00282       ! par%Trep=0.8345d0*(1/fp)
00283 
00284       ! Make the sample resoltion depending on the time record length, thus
00285       ! discarding the input parameter dfj. The base frequency now perfectly fits the
00286       ! given time record and the calculation of the number of wave components will
00287       ! result in an integer value.
00288       ! dfj = 1/wp%rt
00289 
00290       ! Define number of frequency bins by defining an array of the necessary length
00291       ! using the Nyquist frequency and frequency step size
00292       allocate(temp(ceiling((fnyq-dfj)/dfj)))
00293       temp=(/(i,i=1,size(temp))/)
00294 
00295       ! Define array with actual eqidistant frequency bins
00296       allocate(wp%f(size(temp)))
00297       wp%f=temp*dfj
00298       deallocate (temp)
00299 
00300       ! Determine frequency bins relative to peak frequency
00301       allocate(x(size(wp%f)))
00302       x=wp%f/fp
00303 
00304       ! Calculate unscaled and non-directional JONSWAP spectrum using
00305       ! peak-enhancement factor and pre-determined frequency bins
00306       allocate(y(size(wp%f)))
00307       call jonswapgk(x,gam,y)
00308 
00309       ! Determine scaled and non-directional JONSWAP spectrum using the JONSWAP
00310       ! characteristics
00311       y=(wp%hm0gew/(4.d0*sqrt(sum(y)*dfj)))**2*y
00312       deallocate (x)
00313 
00314       ! Define 200 directions relative to main angle running from -pi to pi
00315       allocate(temp(201))
00316       allocate(wp%theta(201))
00317       temp=(/(i,i=0,200)/)
00318       wp%theta=temp*((2*par%px)/200.d0)-par%px
00319       deallocate (temp)
00320 
00321       ! Define pi/2
00322       !t1=-(par%px)/2.d0
00323 
00324       ! Define 100 directions relative to main angle running from -pi/2 to pi/2
00325       !allocate(temp(101))
00326       !allocate(wp%theta(101))
00327       !temp=(/(i,i=0,100)/)
00328       !wp%theta=temp*((par%px)/100.d0)+t1
00329       !deallocate (temp)
00330 
00331       ! Determine directional step size: pi/200
00332       wp%dang=wp%theta(2)-wp%theta(1)
00333 
00334       ! Define 200 directional bins accordingly
00335       allocate (wp%Dd(size(wp%theta)))
00336 
00337       ! Convert main angle from degrees to radians and from nautical convention to
00338       ! internal grid
00339       wp%mainang=(1.5d0*par%px)-wp%mainang*par%px/180.d0
00340 
00341       ! Make sure the main angle is defined between 0 and 2*pi
00342       !do while (wp%mainang>2*par%px .or. wp%mainang<0.d0)
00343       !    if (wp%mainang>2*par%px) then
00344       !        wp%mainang=wp%mainang-2*par%px
00345       !    elseif (wp%mainang<0.d0*par%px) then
00346       !        wp%mainang=wp%mainang+2*par%px
00347       !    endif
00348       !enddo
00349 
00350       do while (wp%mainang>par%px .or. wp%mainang<-par%px) !Robert en Ap
00351          if (wp%mainang>par%px) then
00352             wp%mainang=wp%mainang-2*par%px
00353          elseif (wp%mainang<-par%px) then
00354             wp%mainang=wp%mainang+2*par%px
00355          endif
00356       enddo
00357 
00358       ! Convert 200 directions relative to main angle to directions relative to
00359       ! internal grid                                                                ! Bas: apparently division by 2 for cosine law happens already here
00360       allocate(temp(size(wp%theta)))
00361       temp = (wp%theta-wp%mainang)/2.d0
00362 
00363       ! Make sure all directions around the main angle are defined between 0 and 2*pi
00364       do while (any(temp>2*par%px) .or. any(temp<0.d0))
00365          where (temp>2*par%px)
00366             temp=temp-2*par%px
00367          elsewhere (temp<0.d0*par%px)
00368             temp=temp+2*par%px
00369          endwhere
00370       enddo
00371 
00372       ! Calculate directional spreading based on cosine law
00373       wp%Dd = dcos(temp)**(2*nint(wp%scoeff))                                            ! Robert: apparently nint is needed here, else MATH domain error
00374       deallocate(temp)
00375 
00376       ! Scale directional spreading to have a surface of unity by dividing by it's
00377       ! own surface
00378       wp%Dd = wp%Dd / (sum(wp%Dd)*wp%dang)
00379 
00380       ! Define number of directional and frequency bins
00381       nang=size(wp%theta)
00382       nfreq=size(y)
00383 
00384       ! Define two-dimensional variance density spectrum array and distribute
00385       ! variance density for each frequency over directional bins
00386       allocate(wp%S_array(nfreq,nang))
00387       do i=1,nang
00388          do ii=1,nfreq
00389             wp%S_array(ii,i)=y(ii)*wp%Dd(i)
00390          end do
00391       end do
00392       deallocate (y)
00393 
00394       ! Back integrate two-dimensional variance density spectrum over directions
00395       allocate(wp%Sf(size(wp%f)))
00396       wp%Sf = sum(wp%S_array, DIM = 2)*wp%dang
00397 
00398       ! Calculate mean wave period based on one-dimensional non-directional variance
00399       ! density spectrum and factor trepfac
00400       call tpDcalc(wp%Sf,wp%f,par%Trep,par%trepfac,par%Tm01switch)
00401       call writelog('sl','(a,f0.3)','Derived Trep = ',par%Trep)
00402       ! par%Trep=1.d0/par%Trep
00403       ! Jaap try Tm-1,0
00404       ! par%Trep = 1/fp/1.1d0
00405 
00406       ! Determine frequencies around peak frequency of one-dimensional
00407       ! non-directional variance density spectrum, based on factor sprdthr, which
00408       ! should be included in the determination of the wave boundary conditions
00409       allocate(temp(size(wp%Sf)))
00410       temp=0.d0
00411       call frange(par,wp%Sf,firstp,lastp,temp)
00412       deallocate (temp)
00413 
00414       ! Calculate number of wave components to be included in determination of the
00415       ! wave boundary conditions based on the wave record length and width of the
00416       ! wave frequency range
00417       wp%K=ceiling(wp%rt*(wp%f(lastp)-wp%f(firstp))+1)                               ! ja/ap: changed wp%K=max(100,ceiling(wp%rt*(wp%f(lastp)-wp%f(firstp))+1))
00418       !wp%K=max(256*s%ntheta,wp%K)
00419 
00420       return
00421 
00422    end subroutine build_jonswap
00423 
00424    ! --------------------------------------------------------------
00425    ! ----------------------Read SWAN files ------------------------
00426    ! --------------------------------------------------------------
00427    subroutine swanreader(par,s,wp,fname)
00428 
00429       use params,         only: parameters
00430       use spaceparams
00431       use readkey_module, only: readkey_dbl
00432       use math_tools
00433       use logging_module, only: writelog
00434       use math_tools,     only: flipa, flipv
00435 
00436       IMPLICIT NONE
00437 
00438       ! Input / output variables
00439       type(parameters), INTENT(INout)         :: par
00440       type(spacepars), intent(IN)             :: s
00441       type(waveparameters), INTENT(INOUT)     :: wp
00442       character(len=*), INTENT(IN)            :: fname
00443 
00444       ! Internal variables
00445       character(6)                            :: rtext
00446       real*8                                  :: factor,exc,m0,dthetaS_XB
00447       integer                                 :: nfreq, ndir, switch, i, flipped
00448       integer                                 :: firstp,lastp,nt,Ashift
00449       real*8, dimension(:),allocatable        :: temp, findline
00450       real*8, dimension(:,:),allocatable      :: tempA
00451 
00452       dthetaS_XB = readkey_dbl ('params.txt','dthetaS_XB', 0.0d0, -360.0d0, 360.0d0,bcast=.false.)
00453 
00454       flipped=0
00455       wp%Npy=s%ny+1
00456 
00457       switch = 0
00458       if(xmaster) then
00459          call writelog('sl','','Reading from SWAN file: ',fname,' ...')
00460          open(44,file=fname,form='formatted',status='old')
00461 
00462 
00463          ! Read file until RFREQ or AFREQ is found
00464 
00465          do while (switch==0)
00466             read(44,'(a)')rtext
00467             if (rtext == 'RFREQ ') then
00468                switch = 1
00469             elseif (rtext == 'AFREQ ') then
00470                switch = 2
00471             end if
00472          end do
00473 
00474          ! Read nfreq and f
00475 
00476          read(44,*)nfreq
00477       endif
00478 #ifdef USEMPI
00479       !Dano call xmpi_bcast(nfreq)
00480       !Dano call xmpi_bcast(switch)
00481 #endif
00482       allocate(wp%f(nfreq))
00483       if(xmaster) then
00484          do i=1,nfreq
00485             read(44,*)wp%f(i)
00486          end do
00487       endif
00488 #ifdef USEMPI
00489       !Dano call xmpi_bcast(wp%f)
00490 #endif
00491 
00492       ! Convert to absolute frequencies
00493 
00494       if (switch == 1) then
00495          wp%f = wp%f
00496       else
00497          wp%f = wp%f
00498       end if
00499 
00500       ! Read CDIR or NDIR
00501 
00502       if(xmaster) then
00503          read(44,'(a)')rtext
00504          if (rtext == 'NDIR  ') then
00505             switch = 1
00506          elseif (rtext == 'CDIR  ') then
00507             switch = 2
00508          else
00509             call writelog('els','', 'SWAN directional bins keyword not found')
00510 #ifdef USEMPI
00511             call halt_program
00512 #else
00513             stop
00514 #endif
00515          end if
00516 
00517          ! Read ndir, theta
00518 
00519          read(44,*)ndir
00520       endif
00521 #ifdef USEMPI
00522       !Dano call xmpi_bcast(ndir)
00523 #endif
00524       allocate(wp%theta(ndir))
00525 
00526       if(xmaster) then
00527          do i=1,ndir
00528             read(44,*)wp%theta(i)
00529          end do
00530       endif
00531 
00532 #ifdef USEMPI
00533       !Dano call xmpi_bcast(wp%theta)
00534 #endif
00535 
00536       ! Convert angles to XBeach angles and radians
00537 
00538       if (switch == 1) then
00539          wp%theta = 270-wp%theta
00540       else
00541          wp%theta = wp%theta-dthetaS_XB                  ! dthetaS_XB is the angle in the degrees to rotate the x-axis in SWAN to the
00542          ! x-axis in XBeach (in Cartesian terms) (Have Fun :-))
00543       end if
00544 
00545       ! Ensure angles are increasing instead of decreasing
00546       if ((wp%theta(2)-wp%theta(1))<0) then
00547          call flipv(wp%theta,size(wp%theta))
00548          flipped=1
00549       end if
00550 
00551       nt = 0
00552       Ashift = 0
00553       ! Make sure that all angles are in -180 to 180 degrees
00554       if(minval(wp%theta)<-180)then
00555          allocate (temp(ndir))
00556          Ashift=-1
00557          temp=0
00558          do i=1,ndir
00559             if (wp%theta(i)<-180) then
00560                wp%theta(i)=wp%theta(i)+360.0d0
00561                nt = nt+1
00562             endif
00563          enddo
00564          !temp(1:ndir-nt) = wp%theta(nt+1:ndir)
00565          !temp(ndir-nt+1:ndir) = wp%theta(1:nt)
00566          !  temp(1:nt) = wp%theta(ndir-nt+1:ndir)
00567          !  temp(nt+1:ndir) = wp%theta(1:ndir-nt)
00568          temp(1:ndir-nt)=wp%theta(nt+1:ndir)
00569          temp(ndir-nt+1:ndir)=wp%theta(1:nt)
00570          wp%theta=temp
00571          deallocate(temp)
00572       elseif(maxval(wp%theta)>180.0d0)then
00573          allocate(temp(ndir))
00574          Ashift=1
00575          temp=0
00576          do i=1,ndir
00577             if (wp%theta(i)>180.0d0) then
00578                wp%theta(i)=wp%theta(i)-360.0d0
00579                nt = nt+1
00580             endif
00581          enddo
00582          !temp(1:ndir-nt) = wp%theta(nt+1:ndir)
00583          !temp(ndir-nt+1:ndir) = wp%theta(1:nt)
00584          !temp(1:nt) = wp%theta(ndir-nt+1:ndir)
00585          !temp(nt+1:ndir) = wp%theta(1:ndir-nt)
00586          temp(nt+1:ndir)=wp%theta(1:ndir-nt)
00587          temp(1:nt)=wp%theta(ndir-nt+1:ndir)
00588          wp%theta=temp
00589          deallocate(temp)
00590       endif
00591 
00592       wp%theta=wp%theta*par%px/180
00593       wp%dang=wp%theta(2)-wp%theta(1)
00594 
00595       ! Skip Quant, next line, read VaDens or EnDens
00596       if(xmaster) then
00597          read(44,'(a)')rtext
00598          read(44,'(a)')rtext
00599          read(44,'(a)')rtext
00600          if (rtext == 'VaDens') then
00601             switch = 1
00602          elseif (rtext == 'EnDens') then
00603             switch = 2
00604          else
00605             call writelog('sle','', 'SWAN VaDens/EnDens keyword not found')
00606 #ifdef USEMPI
00607             call halt_program
00608 #else
00609             stop
00610 #endif
00611          end if
00612       endif
00613 #ifdef USEMPI
00614       !Dano call xmpi_bcast(switch)
00615 #endif
00616 
00617       if(xmaster) then
00618          read(44,'(a)')rtext
00619          read(44,*)exc
00620       endif
00621 
00622 #ifdef USEMPI
00623       !Dano call xmpi_bcast(rtext)
00624       !Dano call xmpi_bcast(exc)
00625 #endif
00626 
00627       if(xmaster) then
00628          i=0
00629          ! Find FACTOR keyword
00630          do while (i==0)
00631             read(44,'(a)')rtext
00632             if (rtext == 'FACTOR') then
00633                i=1
00634             elseif (rtext == 'ZERO  ') then
00635                call writelog('lse','','Zero energy density input for this point')
00636 #ifdef USEMPI
00637                call halt_program
00638 #else
00639                stop
00640 #endif
00641             elseif (rtext == 'NODATA') then
00642                call writelog('lse','','SWAN file has no data for this point')
00643 #ifdef USEMPI
00644                call halt_program
00645 #else
00646                stop
00647 #endif
00648             end if
00649          end do
00650          read(44,*)factor
00651       endif
00652 
00653 #ifdef USEMPI
00654       !Dano call xmpi_bcast(factor)
00655 #endif
00656       ! Read S_array
00657       allocate(wp%S_array(nfreq,ndir))
00658 
00659       if(xmaster) then
00660          do i=1,nfreq
00661             read(44,*)wp%S_array(i,:)
00662          end do
00663       endif
00664 
00665 #ifdef USEMPI
00666       !Dano call xmpi_bcast(wp%S_array)
00667 #endif
00668 
00669       where (wp%S_array == exc)
00670          wp%S_array =0
00671       endwhere
00672 
00673       ! If angles were decreasing, flip S_array as also dir is flipped
00674       if (flipped == 1) then
00675          flipped=2
00676          call flipa(wp%S_array,nfreq,ndir,flipped)
00677       end if
00678 
00679 
00680       ! Make sure that all wave variance is between -180 to 180 degrees range
00681       if(Ashift==-1)then
00682          allocate(tempA(nfreq,ndir))
00683          tempA=0
00684          !   tempA(:,ndir-nt+1:ndir) = wp%S_array(:,1:nt)
00685          !   tempA(:,1:ndir-nt) = wp%S_array(:,nt+1:ndir)
00686          !    tempA(:,1:nt) = wp%S_array(:,ndir-nt+1:ndir)
00687          !    tempA(:,nt+1:ndir) = wp%S_array(:,1:ndir-nt)
00688          tempA(:,1:ndir-nt)=wp%S_array(:,nt+1:ndir)
00689          tempA(:,ndir-nt+1:ndir)=wp%S_array(:,1:nt)
00690          wp%S_array=tempA
00691          deallocate(tempA)
00692       elseif (Ashift==1) then
00693          allocate(tempA(nfreq,ndir))
00694          tempA=0
00695          !   tempA(:,ndir-nt+1:ndir) = wp%S_array(:,1:nt)
00696          !   tempA(:,1:ndir-nt) = wp%S_array(:,nt+1:ndir)
00697          !    tempA(:,1:nt) = wp%S_array(:,ndir-nt+1:ndir)
00698          !    tempA(:,nt+1:ndir) = wp%S_array(:,1:ndir-nt)
00699          !        tempA(:,nt+1:ndir)=wp%S_array(:,1:ndir-nt)
00700          !    tempA(:,ndir-nt+1:ndir)=wp%S_array(:,1:nt)
00701          tempA(:,nt+1:ndir)=wp%S_array(:,1:ndir-nt)
00702          tempA(:,1:nt)=wp%S_array(:,ndir-nt+1:ndir)
00703          wp%S_array=tempA
00704          deallocate(tempA)
00705       endif
00706 
00707       wp%S_array=wp%S_array*factor
00708 
00709       if(xmaster) then
00710          close(44)                               ! Finished reading file
00711       endif
00712 
00713       ! Convert to m2/Hz/rad
00714 
00715       wp%S_array=wp%S_array*180/par%px
00716 
00717       ! Convert from energy density to variance density
00718 
00719       if (switch == 2) then
00720          wp%S_array=wp%S_array/(par%rho*par%g)
00721       end if
00722 
00723       allocate(wp%Sf(nfreq))
00724       wp%Sf = sum(wp%S_array, DIM = 2)*wp%dang
00725 
00726       ! Find main wave direction
00727       allocate (temp(ndir))
00728       temp=sum(wp%S_array, DIM = 1)
00729       i=maxval(maxloc(temp))
00730       wp%mainang=wp%theta(i)
00731       deallocate(temp)
00732 
00733       allocate (temp(nfreq+1))
00734       temp(1)=0
00735       temp(2:nfreq)=0.5*wp%f(1:nfreq-1)+0.5*wp%f(2:nfreq)
00736       temp(nfreq+1)=wp%f(nfreq)
00737       ! Calculate zero-order moment
00738       m0=0
00739       !m1=0
00740       do i=1,nfreq
00741          m0=m0+wp%Sf(i)*(temp(i+1)-temp(i))
00742          !    m1=m1+wp%f(i)*wp%Sf(i)*(temp(i+1)-temp(i))
00743       end do
00744       deallocate (temp)
00745 
00746       wp%hm0gew=4*sqrt(m0)
00747       !par%Trep=1/(m1/m0)
00748 
00749       call tpDcalc(wp%Sf,wp%f,par%Trep,par%trepfac,par%Tm01switch)
00750       call writelog('sl','','Trep = ',par%Trep,'s')
00751       call writelog('sl','','Hm0  = ',wp%hm0gew,'m')
00752       call writelog('sl','','Peak dir  = ',wp%mainang*180/par%px,' Cartesian degrees relative to x-axis')
00753       call writelog('sl','','Peak dir  = ',270-wp%mainang*180/par%px,' Nautical degrees')
00754 
00755       allocate(findline(size(wp%Sf)))
00756 
00757       firstp=0
00758       lastp=0
00759       call frange(par, wp%Sf,firstp,lastp,findline)
00760       deallocate(findline)
00761 
00762 
00763       !!!!! ja/ap wp%K=max(100,ceiling(wp%rt*(wp%f(lastp)-wp%f(firstp))+1))
00764 
00765       wp%K=ceiling(wp%rt*(wp%f(lastp)-wp%f(firstp))+1)  !!! this has changed
00766       !wp%K=max(2048,wp%K)
00767 
00768       allocate(wp%Dd(ndir))
00769 
00770       wp%Dd=sum(wp%S_array, DIM = 1)
00771 
00772    end subroutine swanreader
00773 
00774    ! --------------------------------------------------------------
00775    ! -----------------Read variance density files -----------------
00776    ! --------------------------------------------------------------
00777    subroutine vardensreader(par,s,wp,fname)
00778 
00779       use params,         only: parameters
00780       use spaceparams
00781       use xmpi_module
00782       use logging_module, only: writelog
00783       use readkey_module
00784 
00785       IMPLICIT NONE
00786 
00787       ! Input / output variables
00788       type(parameters), INTENT(INout)         :: par
00789       type(spacepars), intent(IN)             :: s
00790       type(waveparameters), INTENT(INOUT)     :: wp
00791       character(len=*), INTENT(IN)            :: fname
00792 
00793       ! Internal variables
00794       real*8                                  :: m0
00795       integer                                 :: nfreq, ndir,i
00796       integer                                 :: firstp,lastp
00797       real*8, dimension(:),allocatable        :: temp, findline
00798 
00799       wp%Npy=s%ny+1
00800 
00801       if(xmaster) then
00802          call writelog('ls','','Reading from VarDens file ',fname,' ...')
00803          open(44,file=fname,form='formatted',status='old')
00804 
00805          read(44,*)nfreq
00806       endif
00807 #ifdef USEMPI
00808       !Dano call xmpi_bcast(nfreq)
00809 #endif
00810       allocate(wp%f(nfreq))
00811 
00812       if(xmaster) then
00813          do i=1,nfreq
00814             read(44,*)wp%f(i)
00815          end do
00816 
00817          read(44,*)ndir
00818       endif
00819 #ifdef USEMPI
00820       !Dano call xmpi_bcast(wp%f)
00821       !Dano call xmpi_bcast(ndir)
00822 #endif
00823       allocate(wp%theta(ndir))
00824 
00825       if(xmaster) then
00826          do i=1,ndir
00827             read(44,*)wp%theta(i)
00828          end do
00829       endif
00830 #ifdef USEMPI
00831       !Dano call xmpi_bcast(wp%theta)
00832 #endif
00833 
00834       wp%theta=wp%theta*par%px/180
00835       wp%dang=wp%theta(2)-wp%theta(1)
00836 
00837       ! Read S_array
00838       allocate(wp%S_array(nfreq,ndir))
00839 
00840       if(xmaster) then
00841          do i=1,nfreq
00842             read(44,*)wp%S_array(i,:)
00843          end do
00844 
00845          close(44)                               ! Finished reading file
00846       endif
00847 
00848 #ifdef USEMPI
00849       !Dano call xmpi_bcast(wp%S_array)
00850 #endif
00851 
00852       ! Convert to m2/Hz/rad
00853 
00854       wp%S_array=wp%S_array*180/par%px
00855 
00856       allocate(wp%Sf(nfreq))
00857       wp%Sf = sum(wp%S_array, DIM = 2)*wp%dang
00858 
00859       allocate (temp(nfreq+1))
00860       temp(1)=0
00861       temp(2:nfreq)=0.5*wp%f(1:nfreq-1)+0.5*wp%f(2:nfreq)
00862       temp(nfreq+1)=wp%f(nfreq)
00863       ! Calculate zero-order moment
00864       m0=0.0d0
00865       !m1=0.0d0
00866       do i=1,nfreq
00867          m0=m0+wp%Sf(i)*(temp(i+1)-temp(i))
00868          !    m1=m1+wp%f(i)*wp%Sf(i)*(temp(i+1)-temp(i))
00869       end do
00870       deallocate (temp)
00871 
00872       ! Find main wave direction
00873       allocate (temp(ndir))
00874       temp=sum(wp%S_array, DIM = 1)
00875       i=maxval(maxloc(temp))
00876       wp%mainang=wp%theta(i)
00877       deallocate(temp)
00878 
00879       wp%hm0gew=4*sqrt(m0)
00880       !par%Trep=1/(m1/m0)
00881       call tpDcalc(wp%Sf,wp%f,par%Trep,par%trepfac,par%Tm01switch)
00882       call writelog('sl','','Trep = ',par%Trep,'s')
00883       call writelog('sl','','Hm0  = ',wp%hm0gew,'m')
00884       call writelog('sl','','Peak dir  = ',wp%mainang*180/par%px,' Cartesian degrees relative to x-axis')
00885       !
00886       allocate(findline(size(wp%Sf)))
00887       firstp=0
00888       lastp=0
00889       call frange(par, wp%Sf,firstp,lastp,findline)
00890       deallocate(findline)
00891 
00892       !!!!! ja/ap wp%K=max(100,ceiling(wp%rt*(wp%f(lastp)-wp%f(firstp))+1))
00893 
00894       wp%K=ceiling(wp%rt*(wp%f(lastp)-wp%f(firstp))+1)  !!! this has changed
00895       !wp%K=max(2048,wp%K)
00896 
00897 
00898       allocate(wp%Dd(ndir))
00899 
00900       wp%Dd=sum(wp%S_array, DIM = 1)
00901 
00902    end subroutine vardensreader
00903 
00904    ! --------------------------------------------------------------
00905    ! ---------------------- Build E_tdir file ---------------------
00906    ! --------------------------------------------------------------
00907    subroutine build_etdir(par,s,wp,Ebcfname)
00908 
00909       use params,         only: parameters
00910       use math_tools,     only: fftkind, random, fft, flipiv, hilbert
00911       use spaceparams
00912       use interp,         only: linear_interp
00913       use xmpi_module
00914       use logging_module, only: writelog
00915       use paramsconst
00916 
00917       IMPLICIT NONE
00918 
00919       ! Input / output variables
00920       type(parameters), INTENT(IN)            :: par
00921       type(waveparameters), INTENT(INOUT)     :: wp
00922       type(spacepars), INTENT(IN)             :: s
00923 
00924       character(len=*), INTENT(IN)            :: Ebcfname
00925 
00926       ! Internal variables
00927 
00928       ! Help integers
00929       integer                                 :: Ns ! Number of theta bins
00930       integer                                 :: reclen
00931       logical                                 :: disptext
00932 
00933       ! Counters
00934       integer                                 :: i, ii, iii, stepf, stepang, index2
00935       integer                                 :: firstp, lastp, M
00936 
00937       ! Nothings
00938       integer                                 :: F2
00939       real*8                                  :: pp
00940 
00941       ! Help single variables with meaning
00942       real*8                                  :: TT, kmax
00943       real*8                                  :: hm0now, s1, s2, modf, modang
00944       real*8                                  :: stdeta,stdzeta
00945 
00946       ! Help vectors
00947       integer, dimension(wp%K)                :: Nbin
00948       real*8,dimension(size(wp%Sf))           :: findline
00949       real*8,dimension(size(wp%Dd))           :: Dmean, P
00950       real*8,dimension(wp%K)                  :: P0, k,phase, Sf0, A, Sf0org,S0org
00951       real*8,dimension(wp%K*2)                                :: randummy
00952       real*8,dimension(:),allocatable         :: temp, temp2, t, Nbox,rD
00953       real*8,dimension(1:401)                 :: ktemp, ftemp
00954 
00955       ! Help arrays
00956       real*8,dimension(:,:), allocatable      :: D
00957       real*8,dimension(:,:,:), allocatable    :: zeta, Ampzeta, E_tdir
00958       real*8,dimension(:,:), allocatable      :: eta, Amp
00959 
00960       ! Complex help variables
00961       ! double complex                          :: ctemp
00962       ! wwvv double complex,dimension(:),allocatable :: Gn, Comptemp
00963       complex(fftkind),dimension(:),allocatable   :: Gn, Comptemp
00964 
00965       ! Check whether maximum frequency is smaller than the Nyquist frequency,
00966       ! otherwise limit the time step to fit this frequency
00967       pp=maxval(wp%f)*2.d0
00968       if (wp%dt>(1.d0/pp)) then
00969          wp%dt=1.d0/pp
00970          if (xmaster) then
00971             call writelog('ls','(a)','Changing dtbc in wave boundary conditions to satisfy Nyquist condition:')
00972             call writelog('ls','(a,f0.4,a)','New dtbc = ',wp%dt,' s.')
00973          endif
00974       endif
00975 
00976       ! Print message to screen
00977       if(xmaster) then
00978          call writelog('ls','','Calculating wave energy at boundary')
00979       endif
00980 
00981       ! Determine frequencies around peak frequency of one-dimensional
00982       ! non-directional variance density spectrum, based on factor sprdthr, which
00983       ! should be included in the determination of the wave boundary conditions
00984       findline=0.0d0
00985       call frange(par,wp%Sf,firstp,lastp,findline)
00986 
00987       ! Determine number of frequencies in discrete variance density spectrum to be
00988       ! included (not equal to wp%K)
00989       M=int(sum(findline))
00990 
00991       ! Define one-dimensional non-directional variance density spectrum array       ! Bas: I guess this is unnecessary
00992       allocate (temp(size(wp%Sf)))
00993       temp=1.0d0
00994 
00995       ! Define two-dimensional spectrum array to be used to fill with directional
00996       ! spreading information in the next step
00997       allocate (D(size(findline),size(wp%Dd)))
00998       D=0.0d0
00999 
01000       ! Copy directional spreading array into two-dimensional spectrum array for each
01001       ! frequency
01002       do i=1,size(wp%Dd)
01003          do ii=1,size(findline)
01004             D(ii,i)=temp(ii)*wp%Dd(i)                                              ! Bas: temp(ii) is always unity here
01005          end do
01006       end do                                                                         ! Bas: D is filled with copies of the same row, which is wp%Dd
01007 
01008       deallocate (temp)
01009 
01010       ! Discard directional spreading information for frequencies that are outside
01011       ! the range around the peak frequency determined by sprdthr
01012       do i=1,size(wp%Dd)
01013          D(:,i)=D(:,i)*findline
01014       end do                                                                         ! Bas: D is still filled with copies of the same row, but about 90% of the values is zero now
01015 
01016       ! Determine the average contribution of a certain frequency for each direction
01017       Dmean=sum(D, DIM=1)/M                                                          ! Bas: D is still filled with copies of the same row, averaging in the first dimension thus results in that specific row again, still containing 90% zeros... so, Dmean=wp%Dd*findline
01018 
01019       ! Define number of wave components to be used
01020       allocate (temp(wp%K))
01021       temp=(/(i,i=0,wp%K-1)/)
01022 
01023       ! Select equidistant wave components between the earlier selected range of
01024       ! frequencies around the peak frequency based on sprdthr
01025       allocate(wp%fgen(wp%K))
01026       wp%fgen=temp*((wp%f(lastp)-wp%f(firstp))/(wp%K-1))+wp%f(firstp)
01027       deallocate(temp)
01028 
01029       ! Determine equidistant frequency step size
01030       wp%df=(wp%fgen(wp%K)-wp%fgen(1))/(dble(wp%K)-1.d0)
01031       ! Avoid leakage
01032       ! Pieter, Jaap and Ap 28/5: wp%fgen=floor(wp%fgen/wp%df)*wp%df taken out because this gives double values of fgen
01033 
01034       ! Determine equidistant period step size, which approximately equals wp%rt due
01035       ! to the dependence of wp%K on wp%rt
01036       TT=1/wp%df                                                                     ! Bas: because of ceiling statement in wp%K definition TT can deviate from wp%rt
01037 
01038       ! Determine maximum wave number based on maximum frequency and dispersion
01039       ! relation w^2 = g*k*tanh(k*d) and max(tanh(k*d))=1
01040       kmax=((2*(par%px)*wp%f(lastp))**2)/par%g
01041 
01042       ! Determine frequency array with 400 frequencies corresponding to wave numbers
01043       ! running from 0 to 2*kmax using the dispersion relation w^2 = g*k*tanh(k*d)
01044       allocate(temp(401))
01045       temp=(/(i,i=0,400)/)
01046       ktemp=temp*(kmax/200)
01047       ftemp=sqrt((par%g)*ktemp*tanh(ktemp*wp%h0t0))/(2*par%px)
01048       deallocate (temp)
01049 
01050       ! Determine all wave numbers of the selected frequencies around the peak
01051       ! frequency by linear interpolation
01052       do i=1,size(wp%fgen)
01053          call LINEAR_INTERP(ftemp,ktemp,401,wp%fgen(i),pp,F2)
01054          k(i)=pp
01055       end do
01056 
01057       ! Define normalization factor for wave variance
01058       pp=1/(sum(Dmean)*wp%dang)
01059 
01060       ! Determine normalized wave variance for each directional bin to be used as
01061       ! probability density function, so surface is equal to unity
01062       do i=1,size(wp%theta)
01063          ! P(i)=(sum(Dmean(1:i))-Dmean(i)/2)*wp%dang*pp                                            ! Bas: this is equal to P(i)=sum(Dmean(1:i))/sum(Dmean)
01064          P(i)=sum(Dmean(1:i))*wp%dang*pp
01065       end do
01066 
01067       ! Update random seed, if requested
01068       if (par%random==1) CALL init_seed
01069 
01070       ! Define random number between 0.025 and 0975 for each wave component
01071       !call random_number(randummy)
01072       ! wwvvrandom
01073       do i=1,wp%K*2
01074          randummy(i) = random(0)
01075       enddo
01076 
01077       P0=randummy(1:wp%K)
01078       !P0=0.95*P0+0.05/2                                                             ! Bas: do not crop cdf, only needed in Matlab to ensure monotonicity
01079 
01080       ! Define direction for each wave component based on random number and linear
01081       ! interpolation of the probability density function
01082       allocate(wp%theta0(wp%K))
01083 
01084       if (wp%scoeff >= 1000.d0) then
01085          wp%theta0 = wp%mainang
01086          !Ap longcrested waves
01087       else
01088          do i=1,size(P0)
01089             !call LINEAR_INTERP(P(1:size(P)-1),wp%theta(1:size(P)-1),size(P)-1,P0(i),pp,F2)
01090             call LINEAR_INTERP(P(1:size(P)),wp%theta(1:size(P)),size(P),P0(i),pp,F2)   ! Bas: do not crop cdf, only needed in Matlab to ensure monotonicity
01091             wp%theta0(i)=pp
01092          end do
01093       end if
01094 
01095       ! Determine number of time steps in wave record and make it even
01096       F2=nint(TT/wp%dt)                                                              ! Bas: why not simply use nint(wp%rt/wp%dt) ??
01097       if (mod(F2,2)/=0) then
01098          F2=F2+1
01099       end if
01100 
01101       ! Define time axis based on time steps
01102       allocate(t(F2))
01103       do i=1,F2
01104          t(i)=wp%dt*i
01105       end do
01106 
01107       ! Determine number of time steps in wave record and make it even               ! Bas: redundant with above, use wp%Nr = F2
01108       wp%Nr=nint(TT/wp%dt)
01109       if (mod(wp%Nr,2)/=0) then
01110          wp%Nr=wp%Nr+1
01111       end if
01112 
01113       ! Define a random phase for each wave component based on a subsequent series of
01114       ! random numbers
01115       phase=randummy(wp%K+1:2*wp%K)
01116       phase=2*phase*par%px
01117 
01118       ! Determine variance density spectrum values for all relevant wave components
01119       ! around the peak frequency by interpolation of two-dimensional variance
01120       ! density spectrum array. This is done by looping through the corresponding
01121       ! frequencies and find for each component the two-dimensional
01122       ! frequency/directional bin where it is located
01123       allocate(wp%S0(wp%K))
01124       do i=1,size(wp%fgen)
01125 
01126          ! Define frequency indices of frequencies that are equal or larger than the
01127          ! currently selected component around the peak frequency
01128          allocate(temp(size(wp%f)))
01129          allocate(temp2(size(wp%f)))
01130          temp2=(/(ii,ii=1,size(wp%f))/)
01131          temp=1
01132          where (wp%f < wp%fgen(i))
01133             temp=0
01134          endwhere
01135          temp=temp*temp2
01136 
01137          ! Check whether any indices are defined. If so, select the first selected
01138          ! index. Otherwise, select the last but one from all frequencies
01139          if (sum(temp)==0) then
01140             stepf=size(wp%f)-1
01141          else
01142             stepf=max(nint(minval(temp, MASK = temp .gt. 0)-1),1)
01143          end if
01144 
01145          ! Determine relative location of the currently selected component in the
01146          ! selected frequency bin
01147          modf=(wp%fgen(i)-wp%f(stepf))/(wp%f(stepf+1)-wp%f(stepf))
01148          deallocate(temp,temp2)
01149 
01150          ! Define directional indices of directions that are equal or larger than
01151          ! the currently selected component around the peak frequency
01152          allocate(temp(size(wp%theta)))
01153          allocate(temp2(size(wp%theta)))
01154          temp2=(/(ii,ii=1,size(wp%theta))/)
01155          temp=1
01156          where (wp%theta < wp%theta0(i) )
01157             temp=0
01158          endwhere
01159          temp=temp*temp2
01160 
01161          ! Check whether any indices are defined. If so, select the first selected
01162          ! index. Otherwise, select the first from all directions
01163          if (wp%theta0(i)==wp%theta(1)) then
01164             stepang=1
01165          else
01166             stepang=nint(minval(temp, MASK = temp .gt. 0) -1)
01167          end if
01168 
01169          ! Determine relative location of the currently selected component in the
01170          ! selected directional bin
01171          modang=(wp%theta0(i)-wp%theta(stepang))/(wp%theta(stepang+1)-wp%theta(stepang))
01172          deallocate(temp,temp2)
01173 
01174          ! Determine variance density spectrum values at frequency boundaries of
01175          ! selected two-dimensional bin by linear interpolation in the directional
01176          ! dimension along these two boundaries
01177          s1=(1.d0-modang)*wp%S_array(stepf,stepang)+modang*wp%S_array(stepf,stepang+1)
01178          s2=(1.d0-modang)*wp%S_array(stepf+1,stepang)+modang*wp%S_array(stepf+1,stepang+1)
01179 
01180          ! Determine variance density spectrum value at currently selected component
01181          ! around peak frequency by linear interpolation of variance density
01182          ! spectrum values at frequency boundaries in frequency direction
01183          wp%S0(i)=max(tiny(0.d0),0.00000001d0,(1.d0-modf)*s1+modf*s2)               ! Robert: limit to positive values only in case no energy is drawn
01184       end do
01185 
01186       ! Determine the variance density spectrum values for all relevant wave
01187       ! components around the peak frequency again, but now using the one-dimensional
01188       ! non-directional variance density spectrum only
01189       do i=1,size(wp%fgen)
01190          call Linear_interp(wp%f,wp%Sf,size(wp%f),wp%fgen(i),pp,F2)
01191          Sf0(i)=pp
01192       end do
01193 
01194       ! Determine significant wave height using Hm0 = 4*sqrt(m0) using the
01195       ! one-dimensional non-directional variance density spectrum
01196       hm0now = 4*sqrt(sum(Sf0)*wp%df)
01197 
01198       ! Backup original spectra just calculated
01199       Sf0org=Sf0
01200       S0org=wp%S0
01201 
01202       ! Correct spectra for wave height
01203       if (par%correctHm0 == 1) then
01204          wp%S0 = (wp%hm0gew/hm0now)**2*wp%S0                                            ! Robert: back on ?
01205          Sf0 = (wp%hm0gew/hm0now)**2*Sf0                                                ! Robert: back on ?
01206       endif
01207 
01208       ! Determine directional step size
01209       allocate(wp%dthetafin(wp%K))
01210       wp%dthetafin = Sf0/wp%S0
01211 
01212       ! Determine amplitude of components from two-dimensional variance density
01213       ! spectrum using Var = 1/2*a^2
01214       A = sqrt(2*wp%S0*wp%df*wp%dthetafin)
01215 
01216       ! Restore original spectra just calculated
01217       Sf0=Sf0org
01218       wp%S0=S0org
01219 
01220       ! Allocate Fourier coefficients for each y-position at the seaside border and
01221       ! each time step
01222       allocate(wp%CompFn(wp%Npy,wp%Nr))
01223       wp%CompFn=0.d0
01224 
01225       ! Determine indices of relevant wave components around peak frequencies in
01226       ! Fourier transform result
01227       allocate(wp%index_vector(wp%K))
01228       wp%index_vector = floor(wp%f(firstp)/wp%df)+1+nint((wp%fgen-wp%f(firstp))/wp%df)    ! Bas: too complex ?? 1+nint((wp%fgen-wp%f(firstp))/wp%df) equals 1:size(wp%fgen)
01229 
01230       ! Determine first half of complex Fourier coefficients of relevant wave
01231       ! components for first y-coordinate using random phase and amplitudes from
01232       ! sampled spectrum until Nyquist frequency. The amplitudes are represented in a
01233       ! two-sided spectrum, which results in the factor 1/2.
01234       do i=1,wp%K
01235          wp%CompFn(1,wp%index_vector(i)) = A(i)/2*exp(compi*phase(i))           ! Bas: wp%index_vector used in time dimension because t=j*dt in frequency space
01236       enddo
01237 
01238       ! Determine Fourier coefficients beyond Nyquist frequency (equal to
01239       ! coefficients at negative frequency axis) of relevant wave components for
01240       ! first y-coordinate by mirroring
01241       allocate(Comptemp(size(wp%CompFn(1,wp%Nr/2+2:wp%Nr))))                         ! Bas: too complex ?? size(wp%CompFn(1,wp%Nr/2+2:wp%Nr)) equals (1,size(wp%Nr)/2-2)
01242       Comptemp = conjg(wp%CompFn(1,2:wp%Nr/2))
01243       call flipiv(Comptemp,size(Comptemp))
01244       wp%CompFn(1,wp%Nr/2+2:wp%Nr)=Comptemp
01245 
01246       ! Determine Fourier coefficients for all other y-coordinates along seaside
01247       ! border in the same manner
01248       do index2=2,wp%Npy
01249          wp%CompFn(index2,wp%index_vector)=wp%CompFn(1,wp%index_vector)* &
01250             exp(-compi*k*(dsin(wp%theta0)*(s%yz(1,index2)-s%yz(1,1)) &
01251          +dcos(wp%theta0)*(s%xz(1,index2)-s%xz(1,1))) )
01252 
01253          Comptemp = conjg(wp%CompFn(index2,2:wp%Nr/2))
01254          call flipiv(Comptemp,size(Comptemp))
01255          wp%CompFn(index2,wp%Nr/2+2:wp%Nr)=Comptemp
01256       end do
01257 
01258       deallocate(Comptemp)
01259 
01260       ! Determine directional bins in computation (not spectrum) ensuring that
01261       ! s%thetamax is included in the range
01262       Ns=s%ntheta
01263       !allocate(temp(Ns+1))
01264       !temp=(/(i,i=0,Ns)/)
01265       !temp(Ns+1)=temp(Ns+1)+epsilon(1.d0)
01266       allocate(Nbox(Ns+1))
01267       allocate(rD(Ns))
01268       do i=1,Ns+1
01269          Nbox(i)=s%thetamin+(i-1)*s%dtheta
01270       enddo
01271 
01272       if (par%wbctype==WBCTYPE_PARAMETRIC .or. par%wbctype==WBCTYPE_JONS_TABLE) then
01273          rD = dcos(0.5d0*(Nbox(1:Ns)+Nbox(2:Ns+1))-wp%mainang)**(2*nint(wp%scoeff))
01274          rD = rD/sum(rD)
01275       endif
01276 
01277 
01278       !deallocate (temp)
01279 
01280       ! try to put all wave directions between thetamax and thetamin
01281       do i=1,size(wp%theta0)
01282          if (wp%theta0(i)>s%thetamax) then
01283             F2=1
01284          elseif (wp%theta0(i)<s%thetamin) then
01285             F2=-1
01286          else
01287             F2=0
01288          endif
01289          ! now turn over 2pi
01290          if (F2==1) then
01291             do while (F2==1)
01292                wp%theta0(i)=wp%theta0(i)-2*par%px
01293                if (wp%theta0(i)<=s%thetamax) then
01294                   F2=0
01295                endif
01296             enddo
01297          elseif (F2==-1) then
01298             do while (F2==-1)
01299                wp%theta0(i)=wp%theta0(i)+2*par%px
01300                if (wp%theta0(i)>=s%thetamin) then
01301                   F2=0
01302                endif
01303             enddo
01304          endif
01305       enddo
01306 
01307       ! Determine computational directional bin for each wave component
01308       do i=1,size(wp%theta0)
01309          do ii=1,Ns
01310             if (wp%theta0(i)>=Nbox(ii) .and. wp%theta0(i)<Nbox(ii+1)) then
01311                Nbin(i)=ii
01312             endif
01313          enddo
01314       enddo
01315 
01316       !    Nbin(i)=ceiling((wp%theta0(i)-Nbox(1))/(par%dtheta*par%px/180.d0))
01317       !
01318       !    ! Ensure lower bin boundaries to be part of succeeding bin
01319       !    if (mod((wp%theta0(i)-Nbox(1)),(par%dtheta*par%px/180.d0))==0) then
01320       !        Nbin(i)=Nbin(i)+1
01321       !    end if
01322       !end do
01323 
01324       ! Determine highest bin containing energy
01325       i=(maxval(Nbin))                                                               ! Bas: not used
01326 
01327       ! Add wave components outside computational directional bins to outer bins, if
01328       ! nspr parameter is set to one
01329       if (par%nspr==1) then
01330          do i=1,wp%K
01331             if (Nbin(i)<=0) then
01332                Nbin(i)=1
01333             elseif (Nbin(i)>Ns) then
01334                Nbin(i)=Ns
01335             endif
01336             wp%theta0(i)=s%theta(Nbin(i))
01337          enddo
01338       endif
01339 
01340       ! deallocate(Nbox)
01341 
01342       ! Define time window that gradually increases and decreases energy input over
01343       ! the wave time record according to tanh(fc*t/max(t))^2*tanh(fc*(1-t/max(t)))^2
01344       allocate(wp%window(size(t)))
01345       allocate(temp(size(t)))
01346       temp=t
01347       where (t>wp%rt)
01348          temp=0                                                         ! Bas: skip time steps that exceed wp%rt, might not be necessary when wp%Nr, F2 and t are defined well, see above
01349       endwhere
01350       wp%window=1
01351       wp%window=wp%window*(tanh(192.d0*temp/maxval(temp))**2)*(tanh(192.d0*(1.d0-temp/maxval(temp)))**2)
01352       !wp%window=wp%window*(tanh(192.d0*t/maxval(t))**2)*(tanh(192.d0*(1.d0-t/maxval(t)))**2)      ! Bas: array t matches wp%rt, so truncating via temp is not necessary anymore
01353       deallocate(temp)
01354 
01355       ! Allocate variables for water level exitation and amplitude with and without
01356       ! directional spreading dependent envelope
01357       allocate(zeta(wp%Npy,wp%Nr,Ns))
01358       allocate(Ampzeta(wp%Npy,wp%Nr,Ns))
01359       zeta=0
01360       Ampzeta=0
01361 
01362       allocate(eta(wp%Npy,wp%Nr))
01363       allocate(Amp(wp%Npy,wp%Nr))
01364       eta=0
01365       Amp=0
01366 
01367       ! Calculate wave energy for each computational directional bin
01368       do ii=1,Ns
01369 
01370          ! Print message to screen
01371          if(xmaster) then
01372             call writelog('ls','(A,I0,A,I0)','Calculating wave energy for theta bin ',ii,' of ',Ns)
01373          endif
01374 
01375          ! Calculate wave energy for each y-coordinate along seaside boundary for
01376          ! current computational directional bin
01377          disptext = .true.
01378          do index2=1,wp%Npy
01379 
01380             ! Select wave components that are in the current computational
01381             ! directional bin
01382             allocate(Gn(wp%Nr))
01383             Gn=0
01384             allocate(temp(size(Nbin)))
01385             temp=0
01386             where (Nbin==ii)
01387                temp=1.
01388             end where
01389 
01390             ! Determine number of wave components that are in the current
01391             ! computational directional bin
01392             F2=nint(sum(temp))
01393 
01394             ! Check whether any wave components are in the current computational
01395             ! directional bin
01396             if (F2/=0) then
01397 
01398                ! Determine for each wave component in the current computational
01399                ! directional bin it's index in the Fourier coefficients array
01400                ! ordered from hight to low frequency
01401                allocate(temp2(F2))
01402                temp2=0
01403                do i=1,F2
01404                   iii=maxval(maxloc(temp))
01405                   temp(iii)=0
01406                   temp2(i)=wp%index_vector(iii)
01407                end do
01408 
01409                ! Determine Fourier coefficients of all wave components for current
01410                ! y-coordinate in the current computational directional bin
01411                Gn(int(temp2))=wp%CompFn(index2,int(temp2))
01412                deallocate(temp2)
01413                allocate(Comptemp(size(Gn(wp%Nr/2+2:wp%Nr))))
01414                Comptemp = conjg(Gn(2:wp%Nr/2))
01415                call flipiv(Comptemp,size(Comptemp))
01416                Gn(wp%Nr/2+2:wp%Nr)=Comptemp
01417                deallocate(Comptemp)
01418 
01419                ! Inverse Discrete Fourier transformation to transform back to time
01420                ! domain from frequency domain
01421                allocate(Comptemp(size(Gn)))
01422                Comptemp=Gn
01423                F2=0
01424                Comptemp=fft(Comptemp,inv=.true.,stat=F2)
01425 
01426                ! Scale result
01427                Comptemp=Comptemp/sqrt(real(size(Comptemp)))
01428 
01429                ! Superimpose gradual increase and decrease of energy input for
01430                ! current y-coordinate and computational diretional bin on
01431                ! instantaneous water level excitation
01432                zeta(index2,:,ii)=dble(Comptemp*wp%Nr)*wp%window
01433                Comptemp(:)=zeta(index2,:,ii)
01434                !
01435                ! Hilbert tranformation to determine envelope for each directional bin seperately
01436                call hilbert(Comptemp,size(Comptemp))
01437 
01438                ! Integrate instantaneous water level excitation of wave
01439                ! components over directions
01440                eta(index2,:) = sum(zeta(index2,:,:),2)
01441                Comptemp=eta(index2,:)
01442                !
01443                ! Hilbert transformation to determine envelope of all total non-directional wave components
01444                call hilbert(Comptemp,size(Comptemp))
01445                !
01446                ! Determine amplitude of water level envelope by calculating
01447                ! the absolute value of the complex wave envelope descriptions
01448                Amp(index2,:)=abs(Comptemp)
01449                !
01450                ! Calculate standard deviations of directional and
01451                ! non-directional instantaneous water level excitation of all
01452                ! wave components to be used as weighing factor
01453                stdzeta = sqrt(sum(zeta(index2,:,ii)**2)/(size(zeta(index2,:,ii)-1)))
01454                stdeta = sqrt(sum(eta(index2,:)**2)/(size(eta(index2,:)-1)))
01455                !
01456                ! Calculate amplitude of directional wave envelope
01457                Ampzeta(index2,:,ii)= Amp(index2,:)*stdzeta/stdeta
01458                !
01459                ! Print status message to screen
01460                !
01461                if(xmaster) then
01462                   if (F2/=0) then
01463                      call writelog('ls','(A,I0,A,I0,A,I0)','Y-point ',index2,' of ',wp%Npy,' done. Error code: ',F2)
01464                   else
01465                      call writelog('s','(A,I0,A,I0,A)','Y-point ',index2,' of ',wp%Npy,' done.')
01466                   end if
01467                endif
01468 
01469                deallocate(Comptemp)
01470             else
01471                ! Current computational directional bin does not contain any wave
01472                ! components, so print message to screen
01473                if(xmaster) then
01474                   if (disptext) then
01475                      call writelog('ls','(A,I0,A)','Theta bin ',ii,' empty at this point. Continuing to next point')
01476                      disptext = .false.
01477                   endif
01478                endif
01479             end if
01480 
01481             deallocate(temp)
01482             deallocate(Gn)
01483          end do
01484       end do
01485 
01486 
01487 
01488       ! Print message to screen
01489       if(xmaster) then
01490          call writelog('ls','','writing wave energy to ',trim(Ebcfname),' ...')
01491       endif
01492 
01493       ! Determine energy distribution over y-coordinates, computational directional
01494       ! bins and time using E = 1/2*rho*g*a^2
01495       allocate(E_tdir(wp%Npy,wp%Nr,Ns))
01496 
01497       ! Jaap: apply symmetric distribution in case of jons or jons_table
01498       ! REMARK: in this case printing messages to screen can be erroneous
01499       if (par%wbctype==WBCTYPE_PARAMS .or. par%wbctype==WBCTYPE_JONS_TABLE) then
01500          call writelog('ls','','Apply symmetric energy distribution w.r.t mean wave direction')
01501          do ii=1,Ns
01502             do index2=1,wp%Npy
01503                E_tdir(index2,:,ii)=0.0d0
01504                E_tdir(index2,:,ii)=0.5d0*(par%rho)*(par%g)*Amp(index2,:)**2*rD(ii)
01505             enddo
01506          enddo
01507       else
01508          E_tdir=0.0d0
01509          E_tdir=0.5d0*(par%rho)*(par%g)*Ampzeta**2
01510       endif
01511       E_tdir=E_tdir/s%dtheta
01512 
01513 
01514       deallocate(Nbox)
01515       deallocate(rD)
01516 
01517       ! Write energy distribution to BCF file
01518       if(xmaster) then
01519          inquire(iolength=reclen) 1.d0
01520          reclen=reclen*(wp%Npy)*(Ns)
01521          write(*,*) 'Opening', trim(Ebcfname)
01522          open(12,file=trim(Ebcfname),form='unformatted',access='direct',recl=reclen)
01523          do i=1,wp%Nr+4                                                             ! Bas: why add 4 ??
01524             write(12,rec=i)E_tdir(:,min(i,wp%Nr),:)
01525          end do
01526          close(12)
01527          call writelog('sl','','file done')
01528       endif
01529 
01530       deallocate (D,t,zeta,Ampzeta,E_tdir, Amp, eta)
01531 
01532       return
01533 
01534    end subroutine build_etdir
01535 
01536    ! --------------------------------------------------------------
01537    ! ----------------------- Bound long wave ----------------------
01538    ! --------------------------------------------------------------
01539    subroutine build_boundw(par,s,wp,qbcfname)
01540 
01541       use params,         only: parameters
01542       use spaceparams
01543       use math_tools,     only: fftkind, fft, flipiv
01544       use xmpi_module
01545       use logging_module, only: writelog
01546 
01547       IMPLICIT NONE
01548 
01549 
01550       ! Input / output variables
01551 
01552       type(parameters), INTENT(IN)            :: par
01553       type(spacepars), INTENT(IN)             :: s
01554       type(waveparameters), INTENT(INOUT)     :: wp
01555       character(len=*), INTENT(IN)            :: qbcfname
01556 
01557       ! Internal variables
01558       integer                                 :: K, m, index1, Npy, Nr, i=0, jj
01559       integer                                 :: reclen
01560       integer,dimension(:),allocatable        :: index2
01561 
01562       logical                                 :: firsttime
01563 
01564       real*8                                  :: g
01565       real*8                                  :: df, deltaf
01566       real*8,dimension(:), allocatable        :: w1, k1
01567       real*8,dimension(:), allocatable        :: Ebnd
01568       real*8,dimension(:), allocatable        :: term1, term2, term2new, dif, chk1, chk2
01569       real*8,dimension(:,:),allocatable       :: Eforc, D, deltheta, KKx, KKy, theta3
01570       real*8,dimension(:,:),allocatable       :: dphi3, k3, cg3, Abnd
01571       real*8,dimension(:,:,:),allocatable     :: q
01572 
01573       double complex,dimension(:),allocatable       :: Comptemp, Comptemp2
01574       complex(fftkind),dimension(:,:),  allocatable :: Gn, Ftemp2
01575       complex(fftkind),dimension(:,:,:),allocatable :: Ftemp
01576       character(4),dimension(4)               :: qstr
01577 
01578       g=par%g
01579       K=wp%K
01580       df=wp%df
01581       index1=wp%index_vector(1)
01582       Npy=wp%Npy
01583       Nr=wp%Nr
01584 
01585       ! Print message to screen
01586       if(xmaster) then
01587          call writelog('sl','', 'Calculating flux at boundary')
01588       endif
01589 
01590       ! Allocate two-dimensional variables for all combinations of interacting wave
01591       ! components to be filled triangular
01592       allocate(Eforc(K-1,K),D(K-1,K),deltheta(K-1,K),KKx(K-1,K),KKy(K-1,K))
01593       allocate(dphi3(K-1,K),k3(K-1,K),cg3(K-1,K))
01594 
01595       ! Initialize variables as zero
01596       Eforc = 0
01597       D = 0
01598       deltheta = 0
01599       KKx = 0
01600       KKy = 0
01601       dphi3 = 0
01602       k3 = 0
01603       cg3 = 0
01604 
01605       ! Allocate variables for angular velocity and wave numbers for wave components
01606       allocate(w1(size(wp%fgen)),k1(size(wp%fgen)))
01607 
01608       ! Initialize variables as zero
01609       w1=0
01610       k1=0
01611 
01612       ! Determine for each wave component interactions with all other wave components
01613       ! as far as not processed yet (each loop step the number of interactions thus
01614       ! decrease with one)
01615 
01616       ! First time is set true for each time new wave bc are generated
01617       firsttime = .true.
01618 
01619       do m=1,K-1
01620 
01621          ! Determine difference frequency
01622          deltaf=m*df
01623 
01624          ! Determine angular velocity of primary waves
01625          w1=2*par%px*wp%fgen
01626 
01627          ! Determine wave numbers of primary waves
01628          call bc_disper(k1,w1,size(w1),wp%h0t0,g)
01629 
01630          ! Determine difference angles (pi already added)
01631          deltheta(m,1:K-m) = abs(wp%theta0(m+1:K)-wp%theta0(1:K-m))+par%px
01632 
01633          ! Determine x- and y-components of wave numbers of difference waves
01634          KKy(m,1:K-m)=k1(m+1:K)*dsin(wp%theta0(m+1:K))-k1(1:K-m)*dsin(wp%theta0(1:K-m))
01635          KKx(m,1:K-m)=k1(m+1:K)*dcos(wp%theta0(m+1:K))-k1(1:K-m)*dcos(wp%theta0(1:K-m))
01636 
01637          ! Determine difference wave numbers according to Van Dongeren et al. 2003
01638          ! eq. 19
01639          k3(m,1:K-m) =sqrt(k1(1:K-m)**2+k1(m+1:K)**2+2*k1(1:K-m)*k1(m+1:K)*dcos(deltheta(m,1:K-m)))
01640 
01641          ! Determine group velocity of difference waves
01642          cg3(m,1:K-m)= 2.d0*par%px*deltaf/k3(m,1:K-m)
01643 
01644          ! Ideetje Robert Jaap: make sure that we don't blow up bound long wave
01645          !                      when offshore boundary is too close to shore
01646          ! cg3 = min(cg3,par%nmax*sqrt(par%g*wp%h0t0))
01647          cg3(m,1:K-m) = min(cg3(m,1:K-m),par%nmax*sqrt(g/k3(m,1:K-m)*tanh(k3(m,1:K-m)*wp%h0t0)))
01648 
01649          ! Determine difference-interaction coefficient according to Herbers 1994
01650          ! eq. A5
01651          allocate(term1(K-m),term2(K-m),term2new(K-m),dif(K-m),chk1(K-m),chk2(K-m))
01652 
01653          term1 = (-w1(1:K-m))*w1(m+1:K)
01654          term2 = (-w1(1:K-m))+w1(m+1:K)
01655          term2new = cg3(m,1:K-m)*k3(m,1:K-m)
01656          dif = (abs(term2-term2new))
01657          if (any(dif>0.01*term2 .and. firsttime .eqv. .true.)) then
01658             firsttime = .false.
01659             call writelog('lws','','Warning: shallow water so long wave variance is reduced using par%nmax');
01660          endif
01661 
01662          chk1  = cosh(k1(1:K-m)*wp%h0t0)
01663          chk2  = cosh(k1(m+1:K)*wp%h0t0)
01664 
01665          D(m,1:K-m) = -g*k1(1:K-m)*k1(m+1:K)*dcos(deltheta(m,1:K-m))/2.d0/term1+g*term2*(chk1*chk2)/ &
01666          ((g*k3(m,1:K-m)*tanh(k3(m,1:K-m)*wp%h0t0)-(term2new)**2)*term1*cosh(k3(m,1:K-m)*wp%h0t0))* &
01667          (term2*((term1)**2/g/g - k1(1:K-m)*k1(m+1:K)*dcos(deltheta(m,1:K-m))) &
01668          - 0.50d0*((-w1(1:K-m))*k1(m+1:K)**2/(chk2**2)+w1(m+1:K)*k1(1:K-m)**2/(chk1**2)))
01669 
01670          deallocate(term1,term2,term2new,dif,chk1,chk2)
01671 
01672          ! Correct for surface elevation input and output instead of bottom pressure
01673          ! so it is consistent with Van Dongeren et al 2003 eq. 18
01674          D(m,1:K-m) = D(m,1:K-m)*cosh(k3(m,1:K-m)*wp%h0t0)/(cosh(k1(1:K-m)*wp%h0t0)*cosh(k1(m+1:K)*wp%h0t0))
01675 
01676          ! Exclude interactions with components smaller than or equal to current
01677          ! component according to lower limit Herbers 1994 eq. 1
01678          where(wp%fgen<=m*df)
01679             D(m,:)=0.d0                                           ! Bas: redundant with initial determination of D ??
01680          endwhere
01681 
01682          ! Exclude interactions with components that are cut-off by the fcutoff
01683          ! parameter
01684          if (m*df<=par%fcutoff) D(m,:)=0.d0
01685 
01686          ! Determine energy of bound long wave according to Herbers 1994 eq. 1 based
01687          ! on difference-interaction coefficient and energy density spectra of
01688          ! primary waves
01689          Eforc(m,1:K-m) = 2*D(m,1:K-m)**2*wp%S0(1:K-m)*wp%S0(m+1:K)*wp%dthetafin(1:K-m)*wp%dthetafin(m+1:K)*df
01690 
01691          ! Determine phase of bound long wave assuming a local equilibrium with
01692          ! forcing of interacting primary waves according to Van Dongeren et al.
01693          ! 2003 eq. 21 (the angle is the imaginary part of the natural log of a
01694          ! complex number as long as the complex number is not zero)
01695          allocate(Comptemp(K-m),Comptemp2(K-m))
01696          Comptemp=conjg(wp%CompFn(1,index1+m:index1+K-1))
01697          Comptemp2=conjg(wp%CompFn(1,index1:index1+K-m-1))
01698          dphi3(m,1:K-m) = par%px+imag(log(Comptemp))-imag(log(Comptemp2))
01699          deallocate (Comptemp,Comptemp2)
01700 
01701       end do
01702 
01703       ! Determine angle of bound long wave according to Van Dongeren et al. 2003 eq. 22
01704       allocate(theta3(K-1,K))
01705       where (abs(KKx)>0.00001d0)
01706          theta3 = atan(KKy/KKx)
01707       elsewhere
01708          theta3 = atan(KKy/sign(0.00001d0,KKx))
01709       endwhere
01710 
01711       ! Allocate variables for amplitude and Fourier coefficients of bound long wave
01712       allocate(Gn(Npy,Nr))
01713       allocate(Abnd(K-1,K))
01714       allocate(Ebnd(K-1))
01715 
01716       Ebnd = sum(Eforc,2)
01717 
01718       Abnd = sqrt(2*Eforc*df)
01719 
01720       allocate(index2(K-1))
01721       index2=(/(i,i=1,K-1)/)
01722 
01723       ! Determine complex description of bound long wave per interaction pair of
01724       ! primary waves for first y-coordinate along seaside boundary
01725       allocate(Ftemp(K-1,K,4)) ! Jaap qx, qy qtot
01726       Ftemp(:,:,1) = Abnd/2*exp(-1*compi*dphi3)*cg3*dcos(theta3) ! qx
01727       Ftemp(:,:,2) = Abnd/2*exp(-1*compi*dphi3)*cg3*dsin(theta3) ! qy
01728       Ftemp(:,:,3) = Abnd/2*exp(-1*compi*dphi3)*cg3              ! qtot
01729       Ftemp(:,:,4) = Abnd/2*exp(-1*compi*dphi3)                  ! eta
01730 
01731       allocate(q(Npy,Nr,4))           ! qx qy qtot eta
01732       allocate(Comptemp(Nr/2-1))
01733       allocate(Comptemp2(Nr))         ! Allocate mass flux as function of time
01734       allocate(Ftemp2(K-1,K))
01735 
01736       q=0.0d0
01737 
01738       qstr = (/'qx  ','qy  ','qtot','eta '/)
01739 
01740       do m=1,4
01741          ! Determine complex description of bound long wave per primary wave component
01742          ! for first y-coordinate along seaside boundary
01743          Gn=0
01744          Gn(1,index2+1)=(sum(Ftemp(:,:,m),DIM=2))
01745 
01746          ! Determine Fourier coefficients
01747 
01748          Comptemp=conjg(Gn(1,2:Nr/2))
01749          call flipiv(Comptemp,Nr/2-1)
01750          Gn(1,Nr/2+2:Nr)=Comptemp
01751 
01752          ! Fourier transformation
01753          Comptemp2=fft(Gn(1,:),inv=.true.)
01754 
01755          ! Determine mass flux as function of time and let the flux gradually increase
01756          ! and decrease in and out the wave time record using the earlier specified
01757          ! window
01758          Comptemp2=Comptemp2/sqrt(real(Nr))
01759          q(1,:,m)=real(Comptemp2*Nr)*wp%window
01760 
01761          ! Determine mass flux of bound long wave for every y-coordinate at the seaside
01762          ! boundary
01763 
01764          do jj=2,Npy
01765 
01766             ! Determine phase shift due to y-coordinate and y-component wave number
01767             ! with respect to first y-coordinate alogn seaside boundary
01768             Ftemp2 = Ftemp(:,:,m)*exp(-1*compi*(KKy*(s%yz(1,jj)-s%yz(1,1))+KKx*(s%xz(1,jj)-s%xz(1,1))))
01769 
01770             ! Determine Fourier coefficients
01771             Gn(jj,index2+1) = (sum(Ftemp2,DIM=2))
01772             Comptemp = conjg(Gn(jj,2:Nr/2))
01773             call flipiv(Comptemp,Nr/2-1)
01774             Gn(jj,Nr/2+2:Nr) = Comptemp
01775 
01776             ! Inverse Discrete Fourier transformation to transform back to time space
01777             ! from frequency space
01778             Comptemp2=fft(Gn(jj,:),inv=.true.)
01779 
01780             ! Determine mass flux as function of time and let the flux gradually
01781             ! increase and decrease in and out the wave time record using the earlier
01782             ! specified window
01783             Comptemp2=Comptemp2/sqrt(real(Nr))    ! u-direction
01784             q(jj,:,m)=real(Comptemp2*Nr)*wp%window
01785 
01786          end do !jj loop
01787       end do !m loop
01788 
01789       ! Jaap and Bas: Fix for curvi-grids
01790       ! REMARK: Need to do something about Ftemp?
01791       do jj=2,Npy
01792          q(jj,:,1) = dcos(datan(q(jj,:,2)/max(q(jj,:,1),par%eps))-s%alfaz(1,jj))*q(jj,:,3)
01793          q(jj,:,2) = dsin(datan(q(jj,:,2)/max(q(jj,:,1),par%eps))-s%alfaz(1,jj))*q(jj,:,3)
01794       end do
01795 
01796       deallocate(Comptemp)
01797       deallocate(Comptemp2)
01798       deallocate(Ftemp)
01799       deallocate(Ftemp2)
01800       deallocate(index2)
01801 
01802       ! Write bound long wave flux to BCF file
01803       if(xmaster) then
01804          call writelog('ls','','writing long wave mass flux to ',trim(qbcfname),' ...')
01805          inquire(iolength=reclen) 1.d0
01806          reclen=reclen*(Npy*4)
01807          open(21,file=qbcfname,form='unformatted',access='direct',recl=reclen)
01808          do i=1,wp%Nr+4                                                             ! Bas: why add 4 ??
01809             write(21,rec=i)q(:,min(i,wp%Nr),:)
01810          end do
01811          close(21)
01812          call writelog('sl','','file done')
01813       endif
01814 
01815       deallocate(wp%index_vector,wp%S0,wp%dthetafin,wp%fgen,wp%theta0,wp%window)
01816       deallocate(wp%Sf,wp%Dd,wp%f,wp%theta,wp%S_array,wp%CompFn)
01817 
01818    end subroutine build_boundw
01819 
01820 
01821 
01822 
01823    ! -----------------------------------------------------------
01824    ! --------- JONSWAP  unscaled JONSWAP spectrum --------------
01825    ! ----------------(used by build_jonswap)--------------------
01826    subroutine jonswapgk(x,gam,y)
01827 
01828       IMPLICIT NONE
01829       ! Required input: - x           : nondimensional frequency, divided by the peak frequency
01830       !                 - gam         : peak enhancement factor, optional parameter (DEFAULT 3.3)
01831       !                 - y is output : nondimensional relative spectral density, equal to one at the peak
01832 
01833       real*8, INTENT(IN)                  :: gam
01834       real*8,dimension(:), INTENT(IN)     :: x
01835       real*8,dimension(:), INTENT(INOUT)  :: y
01836 
01837       ! Internal variables
01838       real*8,dimension(size(x))           :: xa, sigma, fac1, fac2, fac3, temp
01839 
01840       xa=abs(x)
01841 
01842       where (xa==0)
01843          xa=1e-20
01844       end where
01845 
01846       sigma=xa
01847 
01848       where (sigma<1.)
01849          sigma=0.07
01850       end where
01851 
01852       where (sigma>=1.)
01853          sigma=0.09
01854       end where
01855 
01856       temp=0*xa+1
01857 
01858       fac1=xa**(-5)
01859       fac2=exp(-1.25*(xa**(-4)))
01860       fac3=(gam*temp)**(exp(-((xa-1)**2)/(2*(sigma**2))))
01861 
01862       y=fac1*fac2*fac3
01863       y=y/maxval(y)
01864 
01865       return
01866 
01867    end subroutine jonswapgk
01868 
01869    ! -----------------------------------------------------------
01870    ! ---- Small subroutine to determine f-range round peak -----
01871    ! ----(used by build_jonswap, swanreader, vardensreader)-----
01872    subroutine frange(par,Sf,firstp,lastp,findlineout)
01873 
01874       use params,   only: parameters
01875 
01876       implicit none
01877 
01878       type(parameters)                        :: par
01879 
01880 
01881       real*8, dimension(:), intent(in)        :: Sf
01882       integer, intent(out)                    :: firstp, lastp
01883 
01884       real*8, dimension(:), intent(out)       :: findlineout
01885       real*8, dimension(:),allocatable        :: temp, findline
01886       integer                                 :: i = 0
01887 
01888       allocate(findline(size(Sf)))
01889       findline=0*Sf                           ! find frequency range around peak
01890 
01891       where (Sf>par%sprdthr*maxval(Sf))
01892          findline=1
01893       end where
01894 
01895 
01896       firstp=maxval(maxloc(findline))         ! Picks the first "1" in temp
01897 
01898       allocate (temp(size(findline)))
01899       temp=(/(i,i=1,size(findline))/)
01900       lastp=maxval(maxloc(temp*findline))     ! Picks the last "1" in temp
01901 
01902       findlineout=findline
01903       deallocate(temp, findline)
01904 
01905    end subroutine frange
01906 
01907 
01908    ! -----------------------------------------------------------
01909    ! ----------- Small subroutine to determine tpD -------------
01910    ! ----(used by build_jonswap, swanreader, vardensreader)-----
01911    subroutine tpDcalc(Sf,f,Trep,trepfac,switch)
01912 
01913       implicit none
01914 
01915       real*8, dimension(:), intent(in)        :: Sf, f
01916       real*8, intent(out)                     :: Trep
01917       real*8, intent(in)                      :: trepfac
01918       integer, intent(in)                     :: switch
01919 
01920       real*8, dimension(:),allocatable        :: temp
01921 
01922       allocate(temp(size(Sf)))
01923       temp=0.d0
01924       where (Sf>=trepfac*maxval(Sf))
01925          temp=1.d0
01926       end where
01927 
01928       if (switch == 1) then
01929          Trep=sum(temp*Sf)/sum(temp*Sf*f)    ! Tm01
01930       else
01931          Trep = sum(temp*Sf/f)/sum(temp*Sf)    ! Tm-1,0
01932       endif
01933 
01934    end subroutine tpDcalc
01935 
01936 
01937    ! --------------------------------------------------------------
01938    ! --------------------- Dispersion relation --------------------
01939    ! ----------------- (used only by build_boundw) ----------------
01940    subroutine bc_disper(k1,w1,m,h,g)
01941       !          k  = wave number             (2 * pi / wave length)
01942       !          w  = wave angular frequency  (2 * pi / wave period)
01943       !          m  = size k and w vectors
01944       !          h  = water depth
01945       !          g  = gravitational acceleration constant, optional (DEFAULT 9.81)
01946       !
01947       !          absolute error in k*h < 5.0e-16 for all k*h
01948       !
01949       !
01950       !          original Matlab code by: G. Klopman, Delft Hydraulics, 6 Dec 1994
01951 
01952       integer, intent(in)                     :: m
01953       real*8,dimension(m),intent(in)          :: w1
01954       real*8,dimension(m),intent(out)         :: k1
01955       real*8, intent(in)                      :: h, g
01956 
01957       ! internal variables
01958 
01959       real*8,dimension(m)                     :: w2,q,thq,thq2,a,b,c,arg,sign
01960       integer                                 :: j
01961       real*8                                  :: hu
01962 
01963       w2 = w1**2*(h/g)
01964       q = w2/(1.0d0-exp(-(w2**(5.0d0/4.0d0))))**(2.0d0/5.0d0)
01965 
01966       do j=1,4
01967          thq  = tanh(q)
01968          thq2 = 1.0d0-thq**2
01969          a    = (1.0d0-q*thq)*thq2
01970          b    = thq + q*thq2
01971          c    = q*thq-w2
01972          where (abs(a*c)<(b**2*1.0e-8))
01973             arg = -c/b
01974          elsewhere
01975             arg  = (b**2)-4.0d0*a*c
01976             arg  = (-b + sqrt(arg))/(2.0d0*a)
01977          endwhere
01978          q    = q+arg
01979       end do
01980 
01981       where (w1>0.0d0)
01982          sign=1.0d0
01983       endwhere
01984 
01985       where (w1==0.0d0)
01986          sign=0.0d0
01987       endwhere
01988 
01989       where (w1<0.0d0)
01990          sign=-1.0d0
01991       endwhere
01992 
01993       k1 = sign*q/h
01994 
01995       where (k1==huge(hu))
01996          k1=0.0d0
01997       endwhere
01998 
01999       where (k1==-1.0d0*huge(hu))
02000          k1=0.0d0
02001       endwhere
02002 
02003       return
02004 
02005    end subroutine bc_disper
02006 
02007 
02008 
02009    subroutine init_seed   ! based on usage of random  wwvv
02010       use math_tools, only: random
02011       integer clock
02012       real*8 dummy
02013       call system_clock(count=clock)
02014       dummy = random(clock)
02015       return
02016    end subroutine init_seed
02017 
02018 end module waveparams
 All Classes Files Functions Variables Defines