XBeach
|
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