XBeach
|
00001 module wave_functions_module 00002 00003 00004 implicit none 00005 save 00006 private 00007 public:: dispersion, slope2d, breakerdelay, & 00008 & advecthetaho, advecxho, advecyho, iteratedispersion, advecqy, advecwy, & 00009 & advecwx, advecqx, wave_dispersion, update_means_wave_flow, compute_wave_direction_velocities, compute_stokes_drift, compute_wave_forces 00010 00011 contains 00012 00013 subroutine update_means_wave_flow(s,par) 00014 use params, only: parameters 00015 use spaceparams 00016 use paramsconst 00017 implicit none 00018 00019 type(spacepars), target :: s 00020 type(parameters) :: par 00021 real*8 :: factime 00022 00023 00024 ! For the "stationary" part: 00025 if (par%wavemodel == WAVEMODEL_SURFBEAT .and. par%single_dir == 1) then 00026 ! we need smoothed "stationary" values for the wave directions 00027 factime = 1.d0/(par%wavint*2)*par%dt 00028 s%hhws = max(factime*s%hhw + (1-factime)*s%hhws,par%eps) 00029 if (par%wci==1) then 00030 s%uws = factime*s%u + (1-factime)*s%uws 00031 s%vws = factime*s%v + (1-factime)*s%vws 00032 endif 00033 endif 00034 00035 ! for the instationary part 00036 if (par%wavemodel == WAVEMODEL_SURFBEAT .and. par%wci==1) then 00037 ! we need smoothed water depth and velocities for wci in wave instationary 00038 if (par%single_dir == 1) then 00039 ! maintain consistency with stationary wave directions model 00040 factime = 1.d0/(par%wavint*2)*par%dt 00041 else 00042 ! maintain consistency with boundary conditions smoothing 00043 factime = 1.d0/par%cats/par%Trep*par%dt 00044 endif 00045 s%hhwcins = max(factime*s%hhw + (1-factime)*s%hhwcins,par%eps) 00046 s%uwcins = factime*s%u + (1-factime)*s%uwcins 00047 s%vwcins = factime*s%v + (1-factime)*s%vwcins 00048 endif 00049 00050 end subroutine update_means_wave_flow 00051 00052 subroutine slope2D(h,nx,ny,dsu,dnv,dhdx,dhdy,wete) 00053 use xmpi_module 00054 implicit none 00055 00056 integer :: i,j,nx,ny 00057 real*8, dimension(nx+1,ny+1) :: h,dhdx,dhdy 00058 real*8, dimension(nx+1,ny+1) :: dsu 00059 real*8, dimension(nx+1,ny+1) :: dnv 00060 integer, dimension(nx+1,ny+1),intent(in) :: wete 00061 00062 00063 ! wwvv dhdx(2:nx,:) is computed, dhdx(1,:) and dhdx(nx+1,:) 00064 ! get boundary values, so in the parallel case, we need 00065 ! to do something about that: get the boundaries from 00066 ! upper and lower neighbours 00067 00068 ! u-gradients 00069 if(nx+1>=2) then 00070 forall(i=2:nx,j=1:ny+1,wete(i,j)==1) 00071 dhdx(i,j)=(h(i+1,j)-h(i-1,j))/(dsu(i,j)+dsu(i-1,j)) 00072 endforall 00073 forall(j=1:ny+1,wete(1,j)==1) 00074 dhdx(1,j)=(h(2,j)-h(1,j))/dsu(1,j) 00075 endforall 00076 forall(j=1:ny+1,wete(nx+1,j)==1) 00077 dhdx(nx+1,j)=(h(nx+1,j)-h(nx,j))/dsu(nx,j) 00078 endforall 00079 where(wete==0) 00080 dhdx=0.d0 00081 endwhere 00082 else 00083 dhdx=0.d0 00084 endif 00085 !#ifdef USEMPI 00086 ! call xmpi_shift(dhdx,SHIFT_X_U,3,4) 00087 ! call xmpi_shift(dhdx,SHIFT_X_D,1,2) 00088 !#endif 00089 ! 00090 ! v-gradients 00091 if(ny+1>=2) then 00092 forall(i=1:nx+1,j=2:ny,wete(i,j)==1) 00093 dhdy(i,j)=(h(i,j+1)-h(i,j-1))/(dnv(i,j)+dnv(i,j-1)) 00094 endforall 00095 forall(i=1:nx+1,wete(i,1)==1) 00096 dhdy(i,1)=(h(i,2)-h(i,1))/dnv(i,1) 00097 endforall 00098 forall(i=1:nx+1,wete(i,ny+1)==1) 00099 dhdy(i,ny+1)=(h(i,ny+1)-h(i,ny))/dnv(i,ny) 00100 endforall 00101 where(wete==0) 00102 dhdy=0.d0 00103 endwhere 00104 else 00105 dhdy=0.d0 00106 endif 00107 !#ifdef USEMPI 00108 ! call xmpi_shift(dhdy,SHIFT_Y_R,1,2) 00109 ! call xmpi_shift(dhdy,SHIFT_Y_L,3,4) 00110 !#endif 00111 00112 end subroutine slope2D 00113 00114 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00115 00116 subroutine advecxho(ee,cgx,xadvec,nx,ny,ntheta,dnu,dsu,dsdnzi,scheme,wete,dt,dsz) 00117 use spaceparams 00118 !use xmpi_module 00119 use paramsconst 00120 00121 implicit none 00122 00123 integer :: i,j,nx,ny,ntheta 00124 integer, intent(in) :: scheme 00125 integer, dimension(nx+1,ny+1),intent(in) :: wete 00126 real*8, intent(in) :: dt 00127 integer :: itheta 00128 real*8 , dimension(nx+1,ny+1) :: dnu,dsu,dsz,dsdnzi,fluxx 00129 real*8 , dimension(nx+1,ny+1,ntheta) :: xadvec,ee,cgx 00130 real*8 :: cgxu,eupw 00131 00132 integer :: scheme_now 00133 integer :: imin_local,imax_local 00134 00135 if(nx>3) then 00136 imin_local = imin_ee 00137 imax_local = imax_ee 00138 else 00139 ! Need nx here in case of stationary wave solver (nx=3 given in subroutine call; arrays from (i-2:i+1), need to fill 00140 ! 3rd place in the arrays (i) ) 00141 imin_local = nx 00142 imax_local = nx 00143 endif 00144 00145 xadvec = 0.d0 00146 fluxx = 0.d0 00147 00148 00149 ! split into schemes first, less split loops -> more efficiency 00150 scheme_now=scheme 00151 select case(scheme_now) 00152 case(SCHEME_UPWIND_1) 00153 do itheta=1,ntheta 00154 do j=1,ny+1 00155 do i=1,nx ! Whole domain 00156 if(wete(i,j)==1) then 00157 cgxu=.5*(cgx(i+1,j,itheta)+cgx(i,j,itheta)) 00158 if (cgxu>0) then 00159 fluxx(i,j)=ee(i,j,itheta)*cgxu*dnu(i,j) 00160 else 00161 fluxx(i,j)=ee(i+1,j,itheta)*cgxu*dnu(i,j) 00162 endif 00163 endif 00164 enddo 00165 enddo 00166 !do j=1,ny+1 ! 00167 do j=jmin_ee,jmax_ee 00168 do i=imin_local,imax_local 00169 if(wete(i,j)==1) then 00170 xadvec(i,j,itheta)=(fluxx(i,j)-fluxx(i-1,j))*dsdnzi(i,j) 00171 endif 00172 enddo 00173 enddo 00174 enddo 00175 case(SCHEME_UPWIND_2,SCHEME_WARMBEAM) 00176 do itheta=1,ntheta 00177 do j=1,ny+1 00178 do i=2,nx-1 00179 if(wete(i,j)==1) then 00180 cgxu=.5*(cgx(i+1,j,itheta)+cgx(i,j,itheta)) 00181 if (cgxu>0) then 00182 ! eupw=((dsu(i,j)+.5*dsu(i-1,j))*ee(i,j,itheta)-.5*dsu(i-1,j)*ee(i-1,j,itheta))/dsu(i-1,j) 00183 eupw=((dsu(i-1,j)+.5*dsu(i,j))*ee(i,j,itheta)-.5*dsu(i,j)*ee(i-1,j,itheta))/dsu(i-1,j) 00184 if (eupw<0.d0) eupw=ee(i,j,itheta) 00185 fluxx(i,j)=eupw*cgxu*dnu(i,j) 00186 else 00187 ! eupw=((dsu(i+1,j)+.5*dsu(i+2,j))*ee(i+1,j,itheta)-.5*dsu(i+2,j)*ee(i+2,j,itheta))/dsu(i+1,j) 00188 eupw=((dsu(i+1,j)+.5*dsu(i,j))*ee(i+1,j,itheta)-.5*dsu(i,j)*ee(i+2,j,itheta))/dsu(i+1,j) 00189 if (eupw<0.d0) eupw=ee(i+1,j,itheta) 00190 fluxx(i,j)=eupw*cgxu*dnu(i,j) 00191 endif 00192 endif 00193 enddo 00194 if (xmpi_istop) then 00195 i=1 ! only compute for i==1 00196 if(wete(i,j)==1) then 00197 cgxu=.5*(cgx(i+1,j,itheta)+cgx(i,j,itheta)) 00198 if (cgxu>0) then 00199 fluxx(i,j)=ee(i,j,itheta)*cgxu*dnu(i,j) 00200 else 00201 ! eupw=((dsu(i+1,j)+.5*dsu(i+2,j))*ee(i+1,j,itheta)-.5*dsu(i+2,j)*ee(i+2,j,itheta))/dsu(i+1,j) 00202 eupw=((dsu(i+1,j)+.5*dsu(i,j))*ee(i+1,j,itheta)-.5*dsu(i,j)*ee(i+2,j,itheta))/dsu(i+1,j) 00203 if (eupw<0.d0) eupw=ee(i+1,j,itheta) 00204 fluxx(i,j)=eupw*cgxu*dnu(i,j) 00205 endif 00206 endif 00207 endif 00208 if (xmpi_isbot) then 00209 i=nx ! only compute for i==nx0 00210 if(wete(i,j)==1) then 00211 cgxu=.5*(cgx(i+1,j,itheta)+cgx(i,j,itheta)) 00212 if (cgxu>0) then 00213 ! eupw=((dsu(i,j)+.5*dsu(i-1,j))*ee(i,j,itheta)-.5*dsu(i-1,j)*ee(i-1,j,itheta))/dsu(i-1,j) 00214 eupw=((dsu(i-1,j)+.5*dsu(i,j))*ee(i,j,itheta)-.5*dsu(i,j)*ee(i-1,j,itheta))/dsu(i-1,j) 00215 if (eupw<0.d0) eupw=ee(i,j,itheta) 00216 fluxx(i,j)=eupw*cgxu*dnu(i,j) 00217 else 00218 fluxx(i,j)=ee(i+1,j,itheta)*cgxu*dnu(i,j) 00219 endif 00220 endif 00221 endif 00222 enddo 00223 do j=jmin_ee,jmax_ee 00224 !do i=2,nx 00225 do i=imin_local,imax_local 00226 if(wete(i,j)==1) then 00227 xadvec(i,j,itheta)=(fluxx(i,j)-fluxx(i-1,j))*dsdnzi(i,j) 00228 endif 00229 enddo 00230 enddo 00231 enddo 00232 end select 00233 if (scheme_now==SCHEME_WARMBEAM) then 00234 do itheta=1,ntheta 00235 do j=jmin_ee,jmax_ee 00236 !do i=2,nx 00237 do i=imin_local,imax_local 00238 if(wete(i,j)==1) then 00239 xadvec(i,j,itheta)= xadvec(i,j,itheta) & 00240 -((ee(i+1,j,itheta)-ee(i ,j,itheta))/dsu(i ,j) & 00241 -(ee(i ,j,itheta)-ee(i-1,j,itheta))/dsu(i-1,j))/ & 00242 dsz(i,j)*dt/2*cgx(i,j,itheta)**2 00243 endif 00244 enddo 00245 enddo 00246 enddo 00247 endif 00248 00249 end subroutine advecxho 00250 00251 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00252 00253 subroutine advecthetaho(ee,ctheta,thetaadvec,nx,ny,ntheta,dtheta,scheme,wete) 00254 use spaceparams 00255 !use xmpi_module 00256 use paramsconst 00257 00258 implicit none 00259 00260 integer :: i,j,nx,ny,ntheta 00261 integer, intent(in) :: scheme 00262 integer, dimension(nx+1,ny+1),intent(in) :: wete 00263 integer :: itheta 00264 real*8 , dimension(ntheta) :: fluxtheta 00265 real*8 , dimension(nx+1,ny+1,ntheta) :: thetaadvec,ee,ctheta 00266 real*8 :: dtheta,ctheta_between,eupw 00267 00268 integer :: scheme_now 00269 integer :: imin_local,imax_local 00270 00271 if(nx>0) then 00272 imin_local = imin_ee 00273 imax_local = imax_ee 00274 else 00275 ! Need from 1 here in case of stationary wave solver (nx=0 given in subroutine call) 00276 imin_local = 1 00277 imax_local = 1 00278 endif 00279 00280 thetaadvec = 0.d0 00281 fluxtheta = 0.d0 00282 00283 ! No refraction caan take place if ntheta==1 00284 if (ntheta>1) then 00285 00286 ! split into schemes first, less split loops -> more efficiency 00287 scheme_now=scheme 00288 select case(scheme_now) 00289 case(SCHEME_UPWIND_1) 00290 do j=jmin_ee,jmax_ee 00291 do i=imin_local,imax_local 00292 if(wete(i,j)==1) then 00293 do itheta=1,ntheta-1 00294 ctheta_between=.5*(ctheta(i,j,itheta+1)+ctheta(i,j,itheta)) 00295 if (ctheta_between>0) then 00296 fluxtheta(itheta)=ee(i,j,itheta)*ctheta_between 00297 else 00298 fluxtheta(itheta)=ee(i,j,itheta+1)*ctheta_between 00299 endif 00300 enddo 00301 thetaadvec(i,j,1)=(fluxtheta(1)-0.d0)/dtheta ! No flux across lower boundary theta grid 00302 do itheta=2,ntheta-1 00303 thetaadvec(i,j,itheta)=(fluxtheta(itheta)-fluxtheta(itheta-1))/dtheta 00304 enddo 00305 thetaadvec(i,j,ntheta)=(0.d0-fluxtheta(ntheta-1))/dtheta ! No flux across upper boundary theta grid 00306 endif 00307 enddo 00308 enddo 00309 case(SCHEME_UPWIND_2,SCHEME_WARMBEAM) 00310 do j=jmin_ee,jmax_ee 00311 do i=imin_local,imax_local 00312 if(wete(i,j)==1) then 00313 do itheta=2,ntheta-2 00314 ctheta_between=.5*(ctheta(i,j,itheta+1)+ctheta(i,j,itheta)) 00315 if (ctheta_between>0) then 00316 eupw=1.5d0*ee(i,j,itheta)-.5*ee(i,j,itheta-1) 00317 if (eupw<0.d0) eupw=ee(i,j,itheta) 00318 fluxtheta(itheta)=eupw*ctheta_between 00319 else 00320 eupw=1.5d0*ee(i,j,itheta+1)-.5*ee(i,j,itheta+2) 00321 if (eupw<0.d0) eupw=ee(i,j,itheta+1) 00322 fluxtheta(itheta)=eupw*ctheta_between 00323 endif 00324 enddo 00325 itheta=1 ! only compute for itheta==1 00326 ctheta_between=.5*(ctheta(i,j,itheta+1)+ctheta(i,j,itheta)) 00327 if (ctheta_between>0) then 00328 fluxtheta(itheta)=ee(i,j,itheta)*ctheta_between 00329 else 00330 eupw=1.5d0*ee(i,j,itheta+1)-.5*ee(i,j,itheta+2) 00331 if (eupw<0.d0) eupw=ee(i,j,itheta+1) 00332 fluxtheta(itheta)=eupw*ctheta_between 00333 endif 00334 itheta=ntheta-1 ! only compute for itheta==ntheta-1 00335 ctheta_between=.5*(ctheta(i,j,itheta+1)+ctheta(i,j,itheta)) 00336 if (ctheta_between>0) then 00337 eupw=1.5d0*ee(i,j,itheta)-.5*ee(i,j,itheta-1) 00338 if (eupw<0.d0) eupw=ee(i,j,itheta) 00339 fluxtheta(itheta)=eupw*ctheta_between 00340 else 00341 eupw=ee(i,j,itheta+1) 00342 fluxtheta(itheta)=eupw*ctheta_between 00343 endif 00344 thetaadvec(i,j,1)=(fluxtheta(1)-0.d0)/dtheta ! No flux across lower boundary theta grid 00345 do itheta=2,ntheta-1 00346 thetaadvec(i,j,itheta)=(fluxtheta(itheta)-fluxtheta(itheta-1))/dtheta 00347 enddo 00348 thetaadvec(i,j,ntheta)=(0.d0-fluxtheta(ntheta-1))/dtheta ! No flux across upper boundary theta grid 00349 endif 00350 enddo 00351 enddo 00352 end select 00353 !if (scheme_now==SCHEME_WARMBEAM) then 00354 ! do itheta=2,ntheta-1 00355 ! do j=jmin_ee,jmax_ee 00356 ! do i=imin_local,imax_local 00357 ! if(wete(i,j)==1) then 00358 ! thetaadvec(i,j,itheta)= thetaadvec(i,j,itheta) & 00359 ! - (ee(i,j,itheta+1)-2*ee(i,j,itheta)+ee(i,j,itheta-1))/ & 00360 ! dtheta**2*dt/2*ctheta(i,j,itheta)**2 00361 ! endif 00362 ! enddo 00363 ! enddo 00364 ! enddo 00365 !endif 00366 00367 00368 endif !ntheta>1 00369 end subroutine advecthetaho 00370 00371 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00372 00373 subroutine advecyho(ee,cgy,yadvec,nx,ny,ntheta,dsv,dnv,dsdnzi,scheme,wete,dt,dnz) 00374 00375 use spaceparams 00376 use paramsconst 00377 00378 implicit none 00379 00380 integer :: i,j,nx,ny,ntheta 00381 integer, intent(in) :: scheme 00382 integer, dimension(nx+1,ny+1),intent(in) :: wete 00383 real*8, intent(in) :: dt 00384 integer :: itheta 00385 real*8 , dimension(nx+1,ny+1) :: dsv,dnv,dnz,dsdnzi,fluxy 00386 real*8 , dimension(nx+1,ny+1,ntheta) :: yadvec,ee,cgy 00387 real*8 :: cgyv,eupw 00388 00389 integer :: scheme_now 00390 integer :: imin_local,imax_local 00391 00392 if(nx>0) then 00393 imin_local = imin_ee 00394 imax_local = imax_ee 00395 else 00396 ! Need from 1 here in case of stationary wave solver (nx=0 given in subroutine call) 00397 imin_local = 1 00398 imax_local = 1 00399 endif 00400 00401 yadvec = 0.d0 00402 fluxy = 0.d0 00403 00404 ! split into schemes first, less split loops -> more efficiency 00405 scheme_now=scheme 00406 select case(scheme_now) 00407 case(SCHEME_UPWIND_1) 00408 do itheta=1,ntheta 00409 do j=1,ny 00410 do i=1,nx+1 ! Whole domain 00411 if(wete(i,j)==1) then 00412 cgyv=.5*(cgy(i,j+1,itheta)+cgy(i,j,itheta)) 00413 if (cgyv>0) then 00414 fluxy(i,j)=ee(i,j,itheta)*cgyv*dsv(i,j) 00415 else 00416 fluxy(i,j)=ee(i,j+1,itheta)*cgyv*dsv(i,j) 00417 endif 00418 endif 00419 enddo 00420 enddo 00421 do j=jmin_ee,jmax_ee 00422 do i=imin_local,imax_local 00423 if(wete(i,j)==1) then 00424 yadvec(i,j,itheta)=(fluxy(i,j)-fluxy(i,j-1))*dsdnzi(i,j) 00425 endif 00426 enddo 00427 enddo 00428 enddo 00429 case(SCHEME_UPWIND_2,SCHEME_WARMBEAM) 00430 do itheta=1,ntheta 00431 do j=2,ny-1 00432 do i=1,nx+1 00433 if(wete(i,j)==1) then 00434 cgyv=.5*(cgy(i,j+1,itheta)+cgy(i,j,itheta)) 00435 if (cgyv>0) then 00436 ! eupw=((dnv(i,j)+.5*dnv(i,j-1))*ee(i,j,itheta)-.5*dnv(i,j-1)*ee(i,j-1,itheta))/dnv(i,j-1) 00437 eupw=((dnv(i,j-1)+.5*dnv(i,j))*ee(i,j,itheta)-.5*dnv(i,j)*ee(i,j-1,itheta))/dnv(i,j-1) 00438 if (eupw<0.d0) eupw=ee(i,j,itheta) 00439 fluxy(i,j)=eupw*cgyv*dsv(i,j) 00440 else 00441 ! eupw=((dnv(i,j+1)+.5*dnv(i,j+2))*ee(i,j+1,itheta)-.5*dnv(i,j+2)*ee(i,j+2,itheta))/dnv(i,j+1) 00442 eupw=((dnv(i,j+1)+.5*dnv(i,j))*ee(i,j+1,itheta)-.5*dnv(i,j)*ee(i,j+2,itheta))/dnv(i,j+1) 00443 if (eupw<0.d0) eupw=ee(i,j+1,itheta) 00444 fluxy(i,j)=eupw*cgyv*dsv(i,j) 00445 endif 00446 endif 00447 enddo 00448 enddo 00449 if (xmpi_isleft) then 00450 j=1 ! only compute for j==1 00451 do i=1,nx+1 00452 if(wete(i,j)==1) then 00453 cgyv=.5*(cgy(i,j+1,itheta)+cgy(i,j,itheta)) 00454 if (cgyv>0) then 00455 fluxy(i,j)=ee(i,j,itheta)*cgyv*dsv(i,j) 00456 else 00457 ! eupw=((dnv(i,j+1)+.5*dnv(i,j+2))*ee(i,j+1,itheta)-.5*dnv(i,j+2)*ee(i,j+2,itheta))/dnv(i,j+1) 00458 eupw=((dnv(i,j+1)+.5*dnv(i,j))*ee(i,j+1,itheta)-.5*dnv(i,j)*ee(i,j+2,itheta))/dnv(i,j+1) 00459 if (eupw<0.d0) eupw=ee(i,j+1,itheta) 00460 fluxy(i,j)=eupw*cgyv*dsv(i,j) 00461 endif 00462 endif 00463 enddo 00464 endif 00465 if (xmpi_isright) then 00466 j=ny ! only compute for j==ny 00467 do i=1,nx+1 00468 if(wete(i,j)==1) then 00469 cgyv=.5*(cgy(i,j+1,itheta)+cgy(i,j,itheta)) 00470 if (cgyv>0) then 00471 ! eupw=((dnv(i,j)+.5*dnv(i,j-1))*ee(i,j,itheta)-.5*dnv(i,j-1)*ee(i,j-1,itheta))/dnv(i,j-1) 00472 eupw=((dnv(i,j-1)+.5*dnv(i,j))*ee(i,j,itheta)-.5*dnv(i,j)*ee(i,j-1,itheta))/dnv(i,j-1) 00473 if (eupw<0.d0) eupw=ee(i,j,itheta) 00474 fluxy(i,j)=eupw*cgyv*dsv(i,j) 00475 else 00476 fluxy(i,j)=ee(i,j+1,itheta)*cgyv*dsv(i,j) 00477 endif 00478 endif 00479 enddo 00480 endif 00481 do j=2,ny 00482 do i=imin_local,imax_local 00483 if(wete(i,j)==1) then 00484 yadvec(i,j,itheta)=(fluxy(i,j)-fluxy(i,j-1))*dsdnzi(i,j) 00485 endif 00486 enddo 00487 enddo 00488 enddo 00489 end select 00490 if (scheme_now==SCHEME_WARMBEAM) then 00491 do itheta=1,ntheta 00492 do j=jmin_ee,jmax_ee 00493 do i=imin_local,imax_local 00494 if(wete(i,j)==1) then 00495 yadvec(i,j,itheta) = yadvec(i,j,itheta) & 00496 -((ee(i,j+1,itheta)-ee(i,j ,itheta))/dnv(i,j ) & 00497 -(ee(i,j ,itheta)-ee(i,j-1,itheta))/dnv(i,j-1))/ & 00498 dnz(i,j)*dt/2*cgy(i,j,itheta)**2 00499 endif 00500 enddo 00501 enddo 00502 enddo 00503 endif 00504 end subroutine advecyho 00505 00506 00507 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00508 00509 subroutine advecwx(arrin2d,xwadvec,kmx,nx,ny,dsu,wete) 00510 use xmpi_module 00511 00512 implicit none 00513 00514 integer :: i,nx,ny 00515 integer :: j 00516 real*8 , dimension(nx+1,ny+1) :: dsu 00517 real*8 , dimension(nx+1,ny+1) :: xwadvec,arrin2d,kmx 00518 integer, dimension(nx+1,ny+1),intent(in) :: wete 00519 00520 xwadvec = 0.d0 00521 00522 do j=2,ny 00523 do i=2,nx 00524 if(wete(i,j)==1) then 00525 if (kmx(i,j)>0) then 00526 xwadvec(i,j)=(arrin2d(i,j)-arrin2d(i-1,j))/dsu(i-1,j) 00527 elseif (kmx(i,j)<0) then 00528 xwadvec(i,j)=(arrin2d(i+1,j)-arrin2d(i,j))/dsu(i,j) 00529 else 00530 xwadvec(i,j)=(arrin2d(i+1,j)-arrin2d(i-1,j))/(dsu(i,j)+dsu(i-1,j)) 00531 endif 00532 endif 00533 end do 00534 end do 00535 00536 ! wwvv here we miss the computations of the first and last columns and rows, 00537 ! in the parallel case we shift these in form neighbours 00538 00539 end subroutine advecwx 00540 00541 00542 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 00543 00544 subroutine advecwy(arrin2d,ywadvec,kmy,nx,ny,dnv,wete) 00545 use xmpi_module 00546 use xmpi_module 00547 implicit none 00548 00549 integer :: i,nx,ny 00550 integer :: j 00551 real*8 , dimension(nx+1,ny+1) :: dnv 00552 real*8 , dimension(nx+1,ny+1) :: ywadvec,arrin2d,kmy 00553 integer, dimension(nx+1,ny+1),intent(in) :: wete 00554 00555 ywadvec = 0.d0 00556 00557 do j=2,ny 00558 do i=2,nx 00559 if(wete(i,j)==1) then 00560 if (kmy(i,j)>0) then 00561 ywadvec(i,j)=(arrin2d(i,j)-arrin2d(i,j-1))/dnv(i,j-1) 00562 elseif (kmy(i,j)<0) then 00563 ywadvec(i,j)=(arrin2d(i,j+1)-arrin2d(i,j))/dnv(i,j) 00564 else 00565 ywadvec(i,j)=(arrin2d(i,j+1)-arrin2d(i,j-1))/(dnv(i,j)+dnv(i,j-1)) 00566 endif 00567 endif 00568 end do 00569 end do 00570 00571 if(ny>0) then 00572 where(wete(:,1)==1) 00573 ywadvec(:,1)= ywadvec(:,2) !Ap 00574 endwhere 00575 where(wete(:,ny+1)==1) 00576 ywadvec(:,ny+1) = ywadvec(:,ny) !Ap 00577 endwhere 00578 endif 00579 00580 00581 end subroutine advecwy 00582 00583 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00584 00585 subroutine advecqx(c,arrin2d,xwadvec,nx,ny,dsu,wete) 00586 use xmpi_module 00587 00588 implicit none 00589 00590 integer :: i,nx,ny 00591 integer :: j 00592 real*8 , dimension(nx+1,ny+1) :: dsu 00593 real*8 , dimension(nx+1,ny+1) :: xwadvec,arrin2d,c 00594 integer, dimension(nx+1,ny+1),intent(in) :: wete 00595 00596 xwadvec = 0.d0 00597 00598 do j=2,ny 00599 do i=2,nx 00600 if(wete(i,j)==1) then 00601 if (c(i,j)>0) then 00602 xwadvec(i,j)=c(i,j)*(arrin2d(i,j)-arrin2d(i-1,j))/dsu(i-1,j) 00603 elseif (c(i,j)<0) then 00604 xwadvec(i,j)=c(i,j)*(arrin2d(i+1,j)-arrin2d(i,j))/dsu(i,j) 00605 else 00606 xwadvec(i,j)=c(i,j)*(arrin2d(i+1,j)-arrin2d(i-1,j))/(dsu(i,j)+dsu(i-1,j)) 00607 endif 00608 endif 00609 end do 00610 end do 00611 00612 if(ny>0) then 00613 where(wete(:,1)==1) 00614 xwadvec(:,1)= xwadvec(:,2) !Ap 00615 endwhere 00616 where(wete(:,ny+1)==1) 00617 xwadvec(:,ny+1) = xwadvec(:,ny) !Ap 00618 endwhere 00619 endif 00620 00621 00622 end subroutine advecqx 00623 00624 00625 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 00626 00627 subroutine advecqy(c,arrin2d,ywadvec,nx,ny,dnv,wete) 00628 use xmpi_module 00629 use xmpi_module 00630 implicit none 00631 00632 integer :: i,nx,ny 00633 integer :: j 00634 real*8 , dimension(nx+1,ny+1) :: dnv 00635 real*8 , dimension(nx+1,ny+1) :: ywadvec,arrin2d,c 00636 integer, dimension(nx+1,ny+1),intent(in) :: wete 00637 00638 ywadvec = 0.d0 00639 00640 do j=2,ny 00641 do i=2,nx 00642 if(wete(i,j)==1) then 00643 if (c(i,j)>0) then 00644 ywadvec(i,j)=c(i,j)*(arrin2d(i,j)-arrin2d(i,j-1))/dnv(i,j-1) 00645 elseif (c(i,j)<0) then 00646 ywadvec(i,j)=c(i,j)*(arrin2d(i,j+1)-arrin2d(i,j))/dnv(i,j) 00647 else 00648 ywadvec(i,j)=c(i,j)*(arrin2d(i,j+1)-arrin2d(i,j-1))/(dnv(i,j)+dnv(i,j-1)) 00649 endif 00650 endif 00651 end do 00652 end do 00653 00654 end subroutine advecqy 00655 00656 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00657 00658 subroutine dispersion(par,s,h) 00659 use params, only: parameters 00660 use spaceparams 00661 use logging_module, only: writelog 00662 00663 ! Robert: iteration along L=L0tanh(2pih/L) 00664 00665 implicit none 00666 00667 type(spacepars) :: s 00668 type(parameters) :: par 00669 real*8, dimension(1:s%nx+1,1:s%ny+1),intent(in) :: h ! water depth for dispersion can vary for stationary, single_dir and 00670 ! instationary computations, with and without wci 00671 00672 ! Robert: for some reason, MPI version does not like the "allocatable" version 00673 ! of this subroutine. 00674 real*8, dimension(1:s%nx+1,1:s%ny+1) :: L0,kh,Ltemp 00675 integer :: i,j,j1,j2 00676 real*8 :: backdis,disfac 00677 integer :: index 00678 00679 if (s%ny==0) then 00680 j1=1 00681 j2=1 00682 else 00683 j1=1 00684 j2=s%ny+1 00685 endif 00686 ! 00687 ! 00688 where(s%wete==1) 00689 L0 = par%g*par%Trep**2/(2*par%px) 00690 elsewhere 00691 L0=par%eps 00692 endwhere 00693 00694 if (.not. associated(s%L1)) then 00695 allocate(s%L1(s%nx+1,s%ny+1)) 00696 s%L1=L0 00697 endif 00698 Ltemp = L0 00699 00700 do j = j1,j2 00701 do i = 1,s%nx+1 00702 if(s%wete(i,j)==1) then 00703 Ltemp(i,j) = iteratedispersion(L0(i,j),Ltemp(i,j),par%px,h(i,j)) 00704 if (Ltemp(i,j)<0.d0) then ! this is an error from iteratedispersion 00705 Ltemp(i,j) = -Ltemp(i,j) 00706 call writelog('lws','','Warning: no convergence in dispersion relation iteration at t = ', & 00707 par%t*max(par%morfac*par%morfacopt,1.d0)) 00708 endif 00709 endif 00710 end do 00711 end do 00712 if (par%shoaldelay==1) then 00713 ! find Lmod looking back over distance par%facsd*L1 00714 ! presumes sigma direction is shore normal 00715 s%L1 = 0.d0 ! modified wave length, initially set to L1 00716 do j = j1,j2 00717 do i = 2,s%nx+1 00718 if(s%wete(i,j)==1) then 00719 index = i ! start index 00720 backdis = 0.d0 ! relative distance backward 00721 do while (backdis<1.d0) 00722 ! use average wavelength over distance dsc 00723 disfac = s%dsc(index,j)/(par%facsd*0.5d0*(Ltemp(index,j)+Ltemp(max(index-1,1),j))) 00724 disfac = min(disfac,1.d0-backdis) 00725 00726 00727 s%L1(i,j) = s%L1(i,j)+disfac*0.5d0*(Ltemp(index,j)+Ltemp(max(index-1,1),j)) 00728 backdis = backdis+disfac 00729 00730 index = max(index-1,1) 00731 enddo 00732 endif 00733 enddo 00734 enddo 00735 where(s%wete(1,:)==1) 00736 s%L1(1,:) = Ltemp(1,:) 00737 endwhere 00738 else 00739 where(s%wete==1) 00740 s%L1 = Ltemp 00741 endwhere 00742 endif 00743 00744 ! boundary copies for non superfast 1D 00745 if (s%ny>0) then 00746 if (xmpi_isleft) then 00747 where(s%wete(:,1)==1) 00748 s%L1(:,1)=s%L1(:,2) 00749 endwhere 00750 endif 00751 if (xmpi_isright) then 00752 where(s%wete(:,s%ny+1)==1) 00753 s%L1(:,s%ny+1)=s%L1(:,s%ny) 00754 endwhere 00755 endif 00756 endif 00757 where(s%wete==1) 00758 s%k = 2*par%px/s%L1 00759 s%c = s%sigm/s%k 00760 kh = min(s%k*h,10.0d0) 00761 s%n=0.5d0+kh/sinh(2*kh) 00762 s%cg=s%c*s%n 00763 elsewhere 00764 s%k = 25.d0 00765 s%c = sqrt(par%g*par%eps) 00766 s%n = 1.d0 00767 s%cg= sqrt(par%g*par%eps) 00768 endwhere 00769 00770 00771 end subroutine dispersion 00772 00773 elemental function iteratedispersion(L0,Lestimate,px,h) result(L) 00774 00775 implicit none 00776 ! input 00777 real*8,intent(in) :: L0 00778 real*8,intent(in) :: Lestimate 00779 real*8,intent(in) :: px 00780 real*8,intent(in) :: h 00781 ! output 00782 real*8 :: L 00783 ! internal 00784 real*8 :: L1,L2 00785 integer :: iter 00786 real*8 :: err 00787 real*8,parameter :: aphi = 1.d0/(((1.0d0 + sqrt(5.0d0))/2)+1) 00788 real*8,parameter :: bphi = ((1.0d0 + sqrt(5.0d0))/2)/(((1.0d0 + sqrt(5.0d0))/2)+1) 00789 integer,parameter :: itermax = 150 00790 real*8,parameter :: errmax = 0.00001d0 00791 00792 00793 err = huge(0.0d0) 00794 iter = 0 00795 L1 = Lestimate 00796 do while (err > errmax .and. iter < itermax) 00797 iter = iter+1 00798 L2 = L0*tanh(2*px*h/L1) 00799 L1 = (L1*aphi + L2*bphi) ! Golden ratio 00800 err = abs(L2 - L1) 00801 end do 00802 00803 if (iter<=itermax) then 00804 L = L1 00805 else 00806 ! signal this went wrong 00807 L = -L1 00808 endif 00809 00810 end function iteratedispersion 00811 00812 subroutine breakerdelay(par,s) 00813 !!! Dano: this routine is not MPI compliant and assumes xz to be in cross-shore; TBD 00814 !!! -------------------------------------------------------------------------------- 00815 use params, only: parameters 00816 use spaceparams 00817 use xmpi_module 00818 00819 implicit none 00820 00821 type(spacepars),target :: s 00822 type(parameters) :: par 00823 00824 real*8 :: Lbr 00825 real*8, dimension(s%nx+1) :: utemp 00826 integer :: jx,jy,i,j1,nbr,tempxid 00827 integer, dimension(s%nx+1) :: ibr 00828 00829 !include 's.ind' 00830 !include 's.inp' 00831 00832 ! Superfast 1D 00833 if (s%ny>0) then 00834 j1 = 2 00835 else 00836 j1 = 1 00837 endif 00838 00839 do jy = j1,max(1,s%ny) 00840 s%usd(1,jy) = s%ustr(1,jy) 00841 00842 do jx = 2,s%nx+1 00843 if(s%wete(jx,jy)==1) then 00844 nbr = 0 00845 Lbr = sqrt(par%g*s%hhw(jx,jy))*par%Trep*par%breakerdelay 00846 i = jx-1 00847 do while (abs(s%xz(i,jy)-s%xz(jx,jy))<=Lbr .and. i>1) 00848 nbr = nbr+1 00849 i = i-1 00850 end do 00851 00852 if(nbr.gt.1) then 00853 do i = 1,nbr+1 00854 ibr(i) = i 00855 tempxid = jx-nbr+i-1 00856 utemp(i) = s%ustr(tempxid,jy) 00857 enddo 00858 00859 s%usd(jx,jy) = sum(ibr(1:nbr+1)*utemp(1:nbr+1))/sum(ibr(1:nbr+1)) 00860 else 00861 s%usd(jx,jy) = s%ustr(jx,jy) 00862 end if 00863 endif 00864 end do 00865 end do 00866 00867 ! lateral boundaries 00868 if (xmpi_istop ) then 00869 where(s%wete(1,:)==1) 00870 s%usd(1,:) = s%usd(2,:) 00871 endwhere 00872 endif 00873 if (xmpi_isbot ) then 00874 where(s%wete(s%nx+1,:)==1) 00875 s%usd(s%nx+1,:) = s%usd(s%nx,:) 00876 endwhere 00877 endif 00878 if (xmpi_isleft .and. s%ny>0) then 00879 where(s%wete(:,1)==1) 00880 s%usd(:,1) = s%usd(:,2) 00881 endwhere 00882 endif 00883 if (xmpi_isright .and. s%ny>0) then 00884 where(s%wete(:,s%ny+1)==1) 00885 s%usd(:,s%ny+1) = s%usd(:,s%ny) 00886 endwhere 00887 endif 00888 00889 ! wwvv for the parallel version, shift in the columns and rows 00890 00891 end subroutine breakerdelay 00892 00893 subroutine wave_dispersion(s,par,useAverageDepthSwitch) 00894 00895 use params, only: parameters 00896 use spaceparams 00897 00898 implicit none 00899 00900 type(spacepars), target :: s 00901 type(parameters) :: par 00902 integer,intent(in),optional :: useAverageDepthSwitch 00903 00904 real*8,dimension(:,:),allocatable,save :: km,kmx,kmy 00905 real*8,dimension(:,:),allocatable,save :: hhlocal,ulocal,vlocal,relangle 00906 real*8,dimension(:,:),allocatable,save :: arg,fac 00907 real*8,dimension(:,:),allocatable,save :: cgym,cgxm 00908 real*8,dimension(:,:),allocatable,save :: dkmxdx,dkmxdy,dkmydx,dkmydy 00909 real*8,dimension(:,:),allocatable,save :: xwadvec,ywadvec 00910 real*8,dimension(:),allocatable,save :: L0,L1 00911 real*8,save :: Trepold 00912 integer :: itheta 00913 integer :: luseAverageDepthSwitch 00914 00915 if(.not.allocated(km)) then 00916 allocate(km(s%nx+1,s%ny+1)) 00917 allocate(kmx(s%nx+1,s%ny+1)) 00918 allocate(kmy(s%nx+1,s%ny+1)) 00919 allocate(arg(s%nx+1,s%ny+1)) 00920 allocate(fac(s%nx+1,s%ny+1)) 00921 allocate(cgym(s%nx+1,s%ny+1)) 00922 allocate(cgxm(s%nx+1,s%ny+1)) 00923 allocate(dkmxdx(s%nx+1,s%ny+1)) 00924 allocate(dkmxdy(s%nx+1,s%ny+1)) 00925 allocate(dkmydx(s%nx+1,s%ny+1)) 00926 allocate(dkmydy(s%nx+1,s%ny+1)) 00927 allocate(xwadvec(s%nx+1,s%ny+1)) 00928 allocate(ywadvec(s%nx+1,s%ny+1)) 00929 allocate(hhlocal(s%nx+1,s%ny+1)) 00930 if (par%wci==1) then 00931 allocate(ulocal(s%nx+1,s%ny+1)) 00932 allocate(vlocal(s%nx+1,s%ny+1)) 00933 allocate(relangle(s%nx+1,s%ny+1)) 00934 allocate(L0(s%ny+1)) 00935 allocate(L1(s%ny+1)) 00936 L0 = 0.d0 00937 L1 = -huge(0.d0) 00938 endif 00939 Trepold = 0.d0 00940 call dispersion(par,s,s%hhw) ! at initialisation, water depth is always s%hhw 00941 km=s%k 00942 endif 00943 00944 ! water depth and velocities to use depends on wave mode and presence of wci 00945 00946 ! default to use instantaneous water depth and velocities 00947 if (present(useAverageDepthSwitch)) then 00948 luseAverageDepthSwitch = useAverageDepthSwitch 00949 else 00950 luseAverageDepthSwitch = 0 00951 endif 00952 00953 if (luseAverageDepthSwitch==0) then ! default: use instantaneous depth and velocities 00954 hhlocal = s%hhw 00955 if (par%wci==1) then 00956 ulocal = s%u 00957 vlocal = s%v 00958 endif 00959 elseif (luseAverageDepthSwitch==1) then ! used averaged depths for single_dir computation 00960 hhlocal = s%hhws 00961 if (par%wci==1) then 00962 ulocal = s%uws 00963 vlocal = s%vws 00964 endif 00965 elseif (luseAverageDepthSwitch==2) then ! used averaged depths for instationary computation with wci 00966 hhlocal = s%hhwcins 00967 ulocal = s%uwcins 00968 vlocal = s%vwcins 00969 else 00970 ! this should never occur 00971 endif 00972 00973 00974 if(par%wci==1) then 00975 ! Dano NEED TO CHECK THIS FOR CURVI 00976 !if (xmpi_istop) then 00977 ! ! requires boundary condition at the offshore boundary, where we assume zero flow 00978 ! L0 = par%g*par%Trep**2/(2*par%px) 00979 ! if (any(L1<=0.d0)) then 00980 ! L1 = L0 00981 ! endif 00982 ! do j=1,s%ny+1 00983 ! L1(j) = iteratedispersion(L0(j),L1(j),par%px,s%hhw(1,j)) 00984 ! enddo 00985 ! km(1,:) = 2*par%px/max(L1,0.00001d0) 00986 !endif 00987 arg = min(100.0d0,km*hhlocal) 00988 fac = ( 1.d0 + ((km*s%H/2.d0)**2)) ! use deep water correction 00989 s%sigm(1,:) = sqrt( par%g*km(1,:)*tanh(arg(1,:))) ! *( 1.d0+ ((km(1,:)*s%H(1,:)/2.d0)**2))) 00990 ! calculate change in intrinsic frequency 00991 relangle = s%thetamean-s%alfaz 00992 kmx = km*dcos(relangle) 00993 kmy = km*dsin(relangle) 00994 s%wm = s%sigm+kmx*ulocal*min(& 00995 min(hhlocal/par%hwci,1.d0), & 00996 min(1.d0,(1.d0-hhlocal/par%hwcimax)) & 00997 )+ & 00998 kmy*vlocal*min( & 00999 min(hhlocal/par%hwci,1.d0), & 01000 min(1.d0,(1.d0-hhlocal/par%hwcimax)) & 01001 ) 01002 01003 where(km>0.01d0) 01004 s%c = s%sigm/km 01005 ! cg = c*(0.5d0+arg/sinh(2.0d0*arg)) ! Linear 01006 s%cg = s%c*(0.5d0+arg/sinh(2*arg))*sqrt(fac) ! & to include more 01007 ! + km*(H/2)**2*sqrt(max(par%g*km*tanh(arg),0.001d0))/sqrt(max(fac,0.001d0)) ! include wave steepness 01008 s%n=0.5d0+km*hhlocal/sinh(2*max(km,0.00001d0)*hhlocal) 01009 elsewhere 01010 s%c = 0.01d0 01011 s%cg = 0.01d0 01012 s%n = 1.d0 01013 endwhere 01014 01015 cgym = s%cg*dsin(relangle)+vlocal*min(min(hhlocal/par%hwci,1.d0),min(1.d0,(1.d0-hhlocal/par%hwcimax))) 01016 cgxm = s%cg*dcos(relangle)+ulocal*min(min(hhlocal/par%hwci,1.d0),min(1.d0,(1.d0-hhlocal/par%hwcimax))) 01017 01018 call slope2D(kmx,s%nx,s%ny,s%dsu,s%dnv,dkmxdx,dkmxdy,s%wete) 01019 call slope2D(kmy,s%nx,s%ny,s%dsu,s%dnv,dkmydx,dkmydy,s%wete) 01020 call advecwx(s%wm,xwadvec,kmx,s%nx,s%ny,s%dsu,s%wete) ! cjaap: s%xz or s%xu? kmx = kmx -par%dt*xwadvec -par%dt*cgym*(dkmydx-dkmxdy) 01021 kmx = kmx -par%dt*xwadvec -par%dt*cgym*(dkmydx-dkmxdy) 01022 if (s%ny>0) then 01023 if (xmpi_isright) kmx(:,s%ny+1) = kmx(:,s%ny) ! lateral bc 01024 if (xmpi_isleft) kmx(:,1) = kmx(:,2) ! lateral bc 01025 endif 01026 01027 call advecwy(s%wm,ywadvec,kmy,s%nx,s%ny,s%dnv,s%wete) ! cjaap: s%yz or s%yv? 01028 kmy = kmy-par%dt*ywadvec + par%dt*cgxm*(dkmydx-dkmxdy) 01029 if (s%ny>0) then 01030 if (xmpi_isright) kmy(:,s%ny+1) = kmy(:,s%ny) ! lateral bc 01031 if (xmpi_isleft) kmy(:,1) = kmy(:,2) ! lateral bc 01032 endif 01033 01034 #ifdef USEMPI 01035 call xmpi_shift_ee(kmx) 01036 call xmpi_shift_ee(kmy) 01037 #endif 01038 01039 ! update km 01040 km = sqrt(kmx**2+kmy**2) 01041 km = min(km,25.d0) ! limit to gravity waves 01042 ! non-linear dispersion 01043 arg = min(100.0d0,km*hhlocal) 01044 arg = max(arg,0.0001) 01045 ! fac = ( 1.d0 + ((km*H/2.d0)**2)*( (8.d0+(cosh(min(4.d0*arg,10.0d0)))**1.d0-2.d0*(tanh(arg))**2.d0 ) /(8.d0*(sinh(arg))**4.d0) ) ) 01046 fac = ( 1.d0 + ((km*s%H/2.d0)**2)) ! use deep water correction instead of expression above (waves are short near blocking point anyway) 01047 ! fac = 1.d0 ! Linear 01048 s%sigm = sqrt( par%g*km*tanh(arg)*fac) 01049 s%sigm = max(s%sigm,0.010d0) 01050 ! update intrinsic frequency 01051 do itheta=1,s%ntheta 01052 s%sigt(:,:,itheta) = s%sigm 01053 enddo 01054 ! 01055 ! update k 01056 s%k = km 01057 else 01058 ! check if we need to recompute sigm and sigt 01059 if (abs(par%Trep-Trepold)/par%Trep > 0.0001d0) then 01060 Trepold = par%Trep 01061 do itheta=1,s%ntheta 01062 s%sigt(:,:,itheta) = 2*par%px/par%Trep 01063 end do 01064 s%sigm = 2*par%px/par%Trep 01065 endif 01066 call dispersion(par,s,hhlocal) 01067 endif ! end wave current interaction 01068 01069 01070 end subroutine wave_dispersion 01071 01072 subroutine compute_wave_direction_velocities(s,par,flavour,dhdx,dhdy,dudx,dudy,dvdx,dvdy,sinh2kh) 01073 01074 use params, only: parameters 01075 use spaceparams 01076 01077 implicit none 01078 01079 type(spacepars), target :: s 01080 type(parameters) :: par 01081 integer,intent(in) :: flavour ! 0 for stationary, 1 for instationary, 2 for directions part of single_dir 01082 real*8,dimension(s%nx+1,s%ny+1),intent(in) :: dhdx,dhdy,dudx,dudy,dvdx,dvdy,sinh2kh 01083 01084 real*8,dimension(:,:,:),allocatable,save :: cgx,cgy,cx,cy,ctheta 01085 real*8,dimension(:,:),allocatable,save :: uwci,vwci 01086 01087 integer :: nthetalocal,nthetamax 01088 integer :: itheta,j,i 01089 real*8 :: cs,sn 01090 01091 if(.not. allocated(cgx)) then 01092 if (par%single_dir==1) then 01093 nthetamax = max(s%ntheta,s%ntheta_s) 01094 else 01095 nthetamax = s%ntheta 01096 endif 01097 allocate(cgx(s%nx+1,s%ny+1,nthetamax)) 01098 allocate(cgy(s%nx+1,s%ny+1,nthetamax)) 01099 allocate(cx(s%nx+1,s%ny+1,nthetamax)) 01100 allocate(cy(s%nx+1,s%ny+1,nthetamax)) 01101 allocate(ctheta(s%nx+1,s%ny+1,nthetamax)) 01102 if (par%wci==1) then 01103 allocate(uwci(s%nx+1,s%ny+1)) 01104 allocate(vwci(s%nx+1,s%ny+1)) 01105 endif 01106 endif 01107 01108 ! set local variables according to flavour 01109 select case (flavour) 01110 case (0) 01111 nthetalocal = s%ntheta 01112 if (par%wci==1) then 01113 uwci = s%u 01114 vwci = s%v 01115 endif 01116 case (1) 01117 nthetalocal = s%ntheta 01118 if (par%wci==1) then 01119 uwci = s%uwcins 01120 vwci = s%vwcins 01121 endif 01122 case (2) 01123 nthetalocal = s%ntheta_s 01124 if (par%wci==1) then 01125 uwci = s%uws 01126 vwci = s%vws 01127 endif 01128 end select 01129 ! 01130 ! split wave velocities in wave grid directions theta 01131 do itheta=1,nthetalocal 01132 do j=1,s%ny+1 01133 do i=1,s%nx+1 01134 if (s%wete(i,j) == 1) then 01135 ! wave grid directions theta with respect to spatial grid s,n 01136 if (flavour == 2) then 01137 cs=s%costh_s(i,j,itheta) 01138 sn=s%sinth_s(i,j,itheta) 01139 else 01140 cs=s%costh(i,j,itheta) 01141 sn=s%sinth(i,j,itheta) 01142 endif 01143 01144 ! split wave velocities over theta bins 01145 ! note: cg is already correct for each flavour, as long as wave_dispersion is called before this subroutine 01146 if (par%wci==1) then 01147 cgx(i,j,itheta)= s%cg(i,j)*cs+uwci(i,j) 01148 cgy(i,j,itheta)= s%cg(i,j)*sn+vwci(i,j) 01149 cx(i,j,itheta) = s%c(i,j)*cs+uwci(i,j) 01150 cy(i,j,itheta) = s%c(i,j)*sn+vwci(i,j) 01151 else 01152 cgx(i,j,itheta)= s%cg(i,j)*cs 01153 cgy(i,j,itheta)= s%cg(i,j)*sn 01154 cx(i,j,itheta) = s%c(i,j)*cs 01155 cy(i,j,itheta) = s%c(i,j)*sn 01156 endif 01157 01158 ! compute refraction velocity 01159 ! note: sigm is already correct for each flavour, as long as wave_dispersion is called before this subroutine 01160 if (par%wci==1) then 01161 ctheta(i,j,itheta)= s%sigm(i,j)/sinh2kh(i,j)*(dhdx(i,j)*sn-dhdy(i,j)*cs) + & 01162 (cs*(sn*dudx(i,j)-cs*dudy(i,j)) + sn*(sn*dvdx(i,j)-cs*dvdy(i,j))) 01163 else 01164 ctheta(i,j,itheta)= s%sigm(i,j)/sinh2kh(i,j)*(dhdx(i,j)*sn-dhdy(i,j)*cs) 01165 endif 01166 else 01167 cgx(i,j,itheta) = 0.d0 01168 cgy(i,j,itheta) = 0.d0 01169 cx(i,j,itheta) = 0.d0 01170 cy(i,j,itheta) = 0.d0 01171 ctheta(i,j,itheta) = 0.d0 01172 endif 01173 enddo 01174 enddo 01175 enddo 01176 01177 ! Dano Limit unrealistic refraction speed to 1/2 pi per wave period 01178 ctheta=sign(1.d0,ctheta)*min(abs(ctheta),.5*par%px/par%Trep) 01179 01180 ! return to the right parts in s 01181 if (flavour == 2) then 01182 s%cgx_s(:,:,1:s%ntheta_s) = cgx(:,:,1:s%ntheta_s) 01183 s%cgy_s(:,:,1:s%ntheta_s) = cgy(:,:,1:s%ntheta_s) 01184 s%ctheta_s(:,:,1:s%ntheta_s) = ctheta(:,:,1:s%ntheta_s) 01185 ! no cx and cy needed for roller energy 01186 else 01187 s%cgx(:,:,1:s%ntheta) = cgx(:,:,1:s%ntheta) 01188 s%cgy(:,:,1:s%ntheta) = cgy(:,:,1:s%ntheta) 01189 s%ctheta(:,:,1:s%ntheta) = ctheta(:,:,1:s%ntheta) 01190 s%cx(:,:,1:s%ntheta) = cx(:,:,1:s%ntheta) 01191 s%cy(:,:,1:s%ntheta) = cy(:,:,1:s%ntheta) 01192 endif 01193 01194 end subroutine compute_wave_direction_velocities 01195 01196 subroutine compute_wave_forces(s) 01197 use spaceparams 01198 01199 implicit none 01200 01201 type(spacepars), target :: s 01202 01203 integer :: i,j 01204 01205 ! 01206 ! wave radiation stress 01207 s%Sxx=(s%n*sum((1.d0+s%costh**2)*s%ee,3)-.5d0*sum(s%ee,3))*s%dtheta 01208 s%Syy=(s%n*sum((1.d0+s%sinth**2)*s%ee,3)-.5d0*sum(s%ee,3))*s%dtheta 01209 s%Sxy=s%n*sum(s%sinth*s%costh*s%ee,3)*s%dtheta 01210 ! 01211 ! 01212 ! add roller contribution 01213 s%Sxx = s%Sxx + sum((s%costh**2)*s%rr,3)*s%dtheta 01214 s%Syy = s%Syy + sum((s%sinth**2)*s%rr,3)*s%dtheta 01215 s%Sxy = s%Sxy + sum(s%sinth*s%costh*s%rr,3)*s%dtheta 01216 ! 01217 ! 01218 ! Wave forces 01219 if (s%ny>0) then 01220 do j=2,s%ny 01221 do i=1,s%nx 01222 s%Fx(i,j)=-(s%Sxx(i+1,j)-s%Sxx(i,j))/s%dsu(i,j) & 01223 -(s%Sxy(i,j+1)+s%Sxy(i+1,j+1)-s%Sxy(i,j-1)-s%Sxy(i+1,j-1))/ & 01224 (s%dnv(i,j-1)+s%dnv(i,j)+s%dnv(i+1,j-1)+s%dnv(i+1,j)) 01225 enddo 01226 enddo 01227 01228 do j=1,s%ny 01229 do i=2,s%nx 01230 s%Fy(i,j)=-(s%Syy(i,j+1)-s%Syy(i,j))/s%dnv(i,j) & 01231 -(s%Sxy(i+1,j)+s%Sxy(i+1,j+1)-s%Sxy(i-1,j)-s%Sxy(i-1,j+1))/ & 01232 (s%dsu(i-1,j)+s%dsu(i,j)+s%dsu(i-1,j+1)+s%dsu(i,j+1)) 01233 enddo 01234 enddo 01235 else 01236 j=1 01237 do i=1,s%nx 01238 s%Fx(i,j)=-(s%Sxx(i+1,j)-s%Sxx(i,j))/s%dsu(i,j) 01239 enddo 01240 do i=2,s%nx 01241 s%Fy(i,j)=-(s%Sxy(i+1,j)-s%Sxy(i-1,j))/ (s%dsu(i-1,j)+s%dsu(i,j)) 01242 enddo 01243 endif 01244 ! wwvv in the previous, Fx and Fy are computed. The missing elements 01245 ! elements are Fx(:,1), Fx(nx+1,:), Fx(:,ny+1) 01246 ! Fy(1,:), Fy(nx+1,:), Fy(:,ny+1) 01247 01248 ! wwvv so, Fx(:ny+1) and Fy(:ny+1) are left zero and Fx(nx+1,:) and Fy(nx+1,:) 01249 ! are made zero. In the parallel case, Fx(:,1) and Fy(1,:) don't get a 01250 ! value if the submatrices are not on suitable border. 01251 ! I guess that it is necessary to communicate with neighbours the values of these elements 01252 01253 ! wwvv todo the following has consequences for // version 01254 if(xmpi_istop) then 01255 s%Fy(1,:)=s%Fy(2,:) 01256 endif 01257 if(xmpi_isbot) then 01258 s%Fx(s%nx+1,:) = 0.0d0 01259 s%Fy(s%nx+1,:) = 0.0d0 01260 endif 01261 if(xmpi_isleft .and. s%ny>0) then 01262 s%Fx(:,1)=s%Fx(:,2) 01263 ! Fy(:,1)=Fy(:,2) 01264 ! ! where (Fy(:,1)>0.d0) Fy(:,1)=0.d0; !Jaap + Bas: Don't do this before calling Dano :-) 01265 endif 01266 if (xmpi_isright .and. s%ny>0) then 01267 ! Fy(:,ny+1)=Fy(:,ny) ! only a dummy point in non mpi 01268 s%Fx(:,s%ny+1)=s%Fx(:,s%ny) ! only a dummy point in non mpi 01269 ! ! where (Fy(:,ny+1)<0.d0) Fy(:,ny+1)=0.d0; !Jaap + Bas: Don't do this before calling Dano :-) 01270 endif 01271 01272 end subroutine compute_wave_forces 01273 01274 subroutine compute_stokes_drift(s,par) 01275 use params 01276 use spaceparams 01277 01278 implicit none 01279 01280 type(spacepars), target :: s 01281 type(parameters) :: par 01282 01283 real*8 , dimension(:,:) ,allocatable,save :: ustw 01284 01285 if (.not. allocated(ustw)) then 01286 allocate(ustw (s%nx+1,s%ny+1)) 01287 endif 01288 01289 where(s%wete==1) 01290 ! wave induced mass flux 01291 ustw=s%E/s%c/par%rho/s%hstokes ! Jaap (Robert: used in wave instationary) 01292 ! ustw=s%E*s%k/s%sigm/par%rho/max(s%hh,.001d0) ! Robert: old version used in wave stationary. Superceded? 01293 s%uwf = ustw*cos(s%thetamean-s%alfaz) 01294 s%vwf = ustw*sin(s%thetamean-s%alfaz) 01295 ! 01296 ! roller contribution 01297 s%ustr=2*s%R/s%c/par%rho/s%hstokes ! Jaap (Robert: used in wave instationary) 01298 !s%ustr = 0.d0 01299 !s%ustr=2*s%R*s%k/s%sigm/par%rho/max(s%hh,.001d0) ! Robert: old version used in wave stationary. Superceded? 01300 elsewhere 01301 ustw = 0.d0 01302 s%uwf = 0.d0 01303 s%vwf = 0.d0 01304 s%ustr = 0.d0 01305 endwhere 01306 ! 01307 ! introduce breaker delay 01308 if (par%breakerdelay == 1) then 01309 call breakerdelay(par,s) 01310 s%ust = ustw+s%usd 01311 else 01312 s%ust = ustw+s%ustr 01313 endif 01314 ! 01315 ! boundary conditions 01316 if(xmpi_istop) then 01317 s%ust(1,:) = s%ust(2,:) 01318 endif 01319 if(xmpi_isleft.and.s%ny>0) then 01320 s%ust(:,1) = s%ust(:,2) 01321 endif 01322 if(xmpi_isright.and. s%ny>0) then 01323 s%ust(:,s%ny+1) = s%ust(:,s%ny) 01324 endif 01325 01326 end subroutine compute_stokes_drift 01327 01328 end module wave_functions_module