XBeach
|
00001 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00002 ! Copyright (C) 2007 UNESCO-IHE, WL|Delft Hydraulics and Delft University ! 00003 ! Dano Roelvink, Ap van Dongeren, Ad Reniers, Jamie Lescinski, ! 00004 ! Jaap van Thiel de Vries, Robert McCall ! 00005 ! ! 00006 ! d.roelvink@unesco-ihe.org ! 00007 ! UNESCO-IHE Institute for Water Education ! 00008 ! P.O. Box 3015 ! 00009 ! 2601 DA Delft ! 00010 ! The Netherlands ! 00011 ! ! 00012 ! This library is free software; you can redistribute it and/or ! 00013 ! modify it under the terms of the GNU Lesser General Public ! 00014 ! License as published by the Free Software Foundation; either ! 00015 ! version 2.1 of the License, or (at your option) any later version. ! 00016 ! ! 00017 ! This library is distributed in the hope that it will be useful, ! 00018 ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! 00019 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 00020 ! Lesser General Public License for more details. ! 00021 ! ! 00022 ! You should have received a copy of the GNU Lesser General Public ! 00023 ! License along with this library; if not, write to the Free Software ! 00024 ! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ! 00025 ! USA ! 00026 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00027 module bedroughness_module 00028 00029 implicit none 00030 save 00031 private 00032 real*8,dimension(:,:),allocatable,private :: kru,krv,kru50,krv50,kru90,krv90 00033 real*8,dimension(:,:),allocatable,private :: urms_upd,u2_upd 00034 real*8,dimension(:,:),allocatable,private :: facbl,blphi,infilb,Ubed,Ventilation 00035 real*8,dimension(:,:),allocatable,private :: ueuf,uevf,vevf,veuf 00036 real*8,dimension(:,:),allocatable,private :: ueuold,uevold,vevold,veuold 00037 real*8,dimension(:,:),allocatable,private :: dudtsmooth,dvdtsmooth 00038 real*8,dimension(:,:),allocatable,private :: shieldsu,shieldsv 00039 real*8,dimension(2), private :: dtold 00040 real*8, private :: delta,rhogdelta 00041 logical,dimension(:,:),allocatable,private :: isveggie 00042 double precision,dimension(:,:),allocatable,private :: nman0 00043 00044 double precision, private :: nmanmin = -123 00045 public bedroughness_init 00046 public bedroughness_update 00047 00048 00049 contains 00050 00051 subroutine bedroughness_init(s,par) 00052 use params, only: parameters 00053 use spaceparamsdef, only: spacepars 00054 use paramsconst 00055 00056 implicit none 00057 00058 type(parameters),intent(in) :: par 00059 type(spacepars),target :: s 00060 integer :: i,j 00061 00062 !include 's.ind' 00063 !include 's.inp' 00064 00065 s%taubx_add = 0.d0 00066 s%tauby_add = 0.d0 00067 00068 select case (par%bedfriction) 00069 00070 case(BEDFRICTION_CHEZY) 00071 s%cfu = par%g/s%bedfriccoef**2 00072 s%cfv = par%g/s%bedfriccoef**2 00073 case(BEDFRICTION_CF) 00074 s%cfu = s%bedfriccoef 00075 s%cfv = s%bedfriccoef 00076 case (BEDFRICTION_MANNING) 00077 00078 if ( par%dynamrough .eq. 1 ) then 00079 allocate (nman0(s%nx+1,s%ny+1)) 00080 allocate (isveggie(s%nx+1,s%ny+1)) 00081 nman0=s%bedfriccoef 00082 nmanmin=minval( s%bedfriccoef ) 00083 where (s%bedfriccoef>nmanmin) 00084 isveggie=.true. 00085 elsewhere 00086 isveggie=.false. 00087 endwhere 00088 endif 00089 00090 where(s%wetu==1) 00091 s%cfu = par%g*s%bedfriccoef**2/s%hu**(1.d0/3) 00092 s%cfu = min(s%cfu,par%maxcf) 00093 elsewhere 00094 s%cfu = par%maxcf 00095 endwhere 00096 where(s%wetv==1) 00097 s%cfv = par%g*s%bedfriccoef**2/s%hv**(1.d0/3) 00098 s%cfv= min(s%cfv,par%maxcf) 00099 elsewhere 00100 s%cfv = par%maxcf 00101 endwhere 00102 case (BEDFRICTION_WHITE_COLEBROOK_GRAINSIZE) 00103 allocate (kru(s%nx+1,s%ny+1)) 00104 allocate (krv(s%nx+1,s%ny+1)) 00105 ! compute initial D90 at cell interface 00106 if (par%ngd==1) then 00107 kru = 3.d0*s%D90top 00108 krv = 3.d0*s%D90top 00109 else 00110 ! Rougness height in u-points 00111 do j=1,s%ny+1 00112 do i=1,s%nx 00113 kru(i,j) = 1.5d0*(s%D90top(i,j)+s%D90top(i+1,j)) 00114 enddo 00115 enddo 00116 kru(s%nx+1,:) = kru(s%nx,:) 00117 ! Roughness height in v-points 00118 if (par%ny==0) then 00119 ! v-point is central on top of z-point 00120 krv = 3*s%D90top 00121 else 00122 do j=1,s%ny 00123 do i=1,s%nx+1 00124 krv(i,j) = 1.5d0*(s%D90top(i,j)+s%D90top(i,j+1)) 00125 enddo 00126 enddo 00127 krv(:,s%ny+1) = krv(:,s%ny) 00128 endif 00129 endif 00130 where(s%wetu==1) 00131 s%cfu = par%g/(18*log10(12*max(s%hu,kru)/kru))**2 00132 s%cfu = min(s%cfu,par%maxcf) 00133 elsewhere 00134 s%cfu = par%maxcf 00135 endwhere 00136 where(s%wetv==1) 00137 s%cfv = par%g/(18*log10(12*max(s%hv,krv)/krv))**2 00138 s%cfv = min(s%cfv,par%maxcf) 00139 elsewhere 00140 s%cfv = par%maxcf 00141 endwhere 00142 case (BEDFRICTION_WHITE_COLEBROOK) 00143 allocate (kru(s%nx+1,s%ny+1)) 00144 allocate (krv(s%nx+1,s%ny+1)) 00145 kru = s%bedfriccoef 00146 krv = s%bedfriccoef 00147 where(s%wetu==1) 00148 s%cfu = par%g/(18*log10(12*max(s%hu,kru)/kru))**2 00149 s%cfu = min(s%cfu,par%maxcf) 00150 elsewhere 00151 s%cfu = par%maxcf 00152 endwhere 00153 where(s%wetv==1) 00154 s%cfv = par%g/(18*log10(12*max(s%hv,krv)/krv))**2 00155 s%cfv = min(s%cfv,par%maxcf) 00156 elsewhere 00157 s%cfv = par%maxcf 00158 endwhere 00159 end select 00160 00161 00162 00163 end subroutine bedroughness_init 00164 00165 00166 subroutine bedroughness_update(s,par) 00167 00168 use params, only: parameters 00169 use spaceparamsdef, only: spacepars 00170 use paramsconst 00171 00172 implicit none 00173 00174 type(parameters),intent(in) :: par 00175 type(spacepars),target :: s 00176 integer :: i,j 00177 00178 00179 00180 select case (par%bedfriction) 00181 00182 case(BEDFRICTION_CHEZY) 00183 ! do nothing, this is constant bed roughness, already set in initialise 00184 case(BEDFRICTION_CF) 00185 ! do nothing, this is constant bed roughness, already set in initialise 00186 case (BEDFRICTION_MANNING) 00187 ! C = H**(1/6)/n 00188 ! cf = g/C**2 = g/(hu**(1/6)/n)**2 = g*n**2/hu**(1/3) 00189 00190 if (par%dynamrough .eq. 1) then 00191 ! ML 2 KN changed back to one where loop instead of 3 separate to ensure just 1 of the 3 statements is executed per cell. 00192 where ((isveggie) .and. (s%sedero .gt. 0d0)) ! linear function do to deposition ( sedero > 0 ) 00193 s%bedfriccoef = nmanmin + min( max( (par%dstem-s%sedero)/par%dstem , 0.d0), 1.0d0) * (nman0 - nmanmin) 00194 elsewhere ((isveggie) .and. (s%sedero .lt. (par%droot*-1) ) ) ! step function do to erosion larger than root than always minimum ( sedero < -droot ) 00195 s%bedfriccoef = nmanmin 00196 isveggie = .false. 00197 elsewhere ! linear function do to deposition ( -droot < sedero < 0 ) 00198 s%bedfriccoef = nmanmin + min( max( (par%droot+s%sedero)/par%droot , 0.d0), 1.0d0) * (nman0 - nmanmin) 00199 endwhere 00200 endif 00201 00202 where(s%wetu==1) 00203 s%cfu = par%g*s%bedfriccoef**2/s%hu**(1.d0/3) 00204 s%cfu = min(s%cfu,par%maxcf) 00205 elsewhere 00206 s%cfu = par%maxcf 00207 endwhere 00208 where(s%wetv==1) 00209 s%cfv = par%g*s%bedfriccoef**2/s%hv**(1.d0/3) 00210 s%cfv = min(s%cfv,par%maxcf) 00211 elsewhere 00212 s%cfv = par%maxcf 00213 endwhere 00214 case (BEDFRICTION_WHITE_COLEBROOK_GRAINSIZE) 00215 if (par%ngd>1) then 00216 ! Rougness height in u-points 00217 do j=1,s%ny+1 00218 do i=1,s%nx 00219 if (s%wetu(i,j)==1) then 00220 kru(i,j) = 1.5d0*(s%D90top(i,j)+s%D90top(i+1,j)) 00221 endif 00222 enddo 00223 enddo 00224 kru(s%nx+1,:) = kru(s%nx,:) 00225 ! Roughness height in v-points 00226 if (par%ny==0) then 00227 ! v-point is central on top of z-point 00228 where (s%wetv==1) 00229 krv = 3*s%D90top 00230 endwhere 00231 else 00232 do j=1,s%ny 00233 do i=1,s%nx+1 00234 if (s%wetv(i,j)==1) then 00235 krv(i,j) = 1.5d0*(s%D90top(i,j)+s%D90top(i,j+1)) 00236 endif 00237 enddo 00238 enddo 00239 krv(:,s%ny+1) = krv(:,s%ny) 00240 endif 00241 endif 00242 where(s%wetu==1) 00243 s%cfu = par%g/(18*log10(12*max(s%hu,kru)/kru))**2 00244 s%cfu = min(s%cfu,0.1d0) 00245 elsewhere 00246 s%cfu = par%maxcf 00247 endwhere 00248 where(s%wetv==1) 00249 s%cfv = par%g/(18*log10(12*max(s%hv,krv)/krv))**2 00250 s%cfv = min(s%cfv,par%maxcf) 00251 elsewhere 00252 s%cfv = par%maxcf 00253 endwhere 00254 case (BEDFRICTION_WHITE_COLEBROOK) 00255 where(s%wetu==1) 00256 s%cfu = par%g/(18*log10(12*max(s%hu,kru)/kru))**2 00257 s%cfu = min(s%cfu,par%maxcf) 00258 elsewhere 00259 s%cfu = par%maxcf 00260 endwhere 00261 where(s%wetv==1) 00262 s%cfv = par%g/(18*log10(12*max(s%hv,krv)/krv))**2 00263 s%cfv = min(s%cfv,par%maxcf) 00264 elsewhere 00265 s%cfv = par%maxcf 00266 endwhere 00267 end select 00268 00269 ! Additional bed friction terms due to acceleration 00270 s%taubx_add = 0.d0 00271 s%tauby_add = 0.d0 00272 00273 ! Increased bed shear due to acceleration terms (phase-shift type or Morison type) 00274 if (par%friction_acceleration==CF_ACC_NIELSEN) then 00275 call acceleration_boundary_layer_effect_Nielsen(s,par) 00276 elseif (par%friction_acceleration==CF_ACC_MCCALL) then 00277 call acceleration_boundary_layer_effect(s,par) 00278 endif 00279 00280 ! turbulence and acceleration add to shear stress, but do 00281 ! not necessarily also need enhanced cf from infiltration 00282 if (par%friction_turbulence==1) then 00283 call turbulence_boundary_layer_effect(s,par) 00284 endif 00285 00286 ! Infiltration enhances normal bed shear stress through 00287 ! increase of cfu and cfv 00288 if (par%friction_infiltration==1) then 00289 call infiltration_boundary_layer_effect(s,par) 00290 endif 00291 00292 00293 s%cfu = min(s%cfu,1.d0) ! check why needed 00294 s%cfv = min(s%cfv,1.d0) 00295 00296 00297 end subroutine bedroughness_update 00298 00299 subroutine infiltration_boundary_layer_effect(s,par) 00300 00301 use params, only: parameters 00302 use spaceparamsdef, only: spacepars 00303 00304 IMPLICIT NONE 00305 00306 type(parameters),intent(in) :: par 00307 type(spacepars) :: s 00308 integer :: i,j 00309 real*8,parameter :: epsVentilation = 1.d0 00310 real*8,parameter :: maxEnhancement1 = 3.d0 ! Pers. Corr. Conley 2014 00311 real*8,parameter :: maxEnhancement2 = 0.1d0 ! Pers. Corr. Conley 2014 00312 00313 00314 if (.not.allocated(facbl)) then 00315 ! arrays available in bed friction module only 00316 allocate (facbl(s%nx+1,s%ny+1)) 00317 allocate (blphi(s%nx+1,s%ny+1)) 00318 allocate (infilb(s%nx+1,s%ny+1)) 00319 allocate (Ubed(s%nx+1,s%ny+1)) 00320 allocate (Ventilation(s%nx+1,s%ny+1)) 00321 endif 00322 00323 00324 ! Include infiltration effect on boundary layer thinning 00325 ! Taken from eq 13 Butt, Russell, Turner 2001, based on 00326 ! Conley and Inman 1994 00327 ! In C&I derivation f = 2*cf and w is positive up, and b=0.9-2.0 so modified to: 00328 ! Tau_w/Tau_0 = C/(2*cf) * -infil/abs(u) 00329 ! where C is a constant of ~2 00330 ! 00331 ! Can re-write to taubx_total = taubx + taubx_add 00332 ! 00333 ! Tau ~ cf 00334 ! cf_w/cf_0 = Tau_w/Tau_0 00335 ! 00336 ! Therefore: taubx_total = cf_0*rho*u*abs(u) + (1-cf_w/cf_0)*cf*rho*u*abs(u) 00337 ! (here we neglect the urms part to the drag in taubx_add for surf-beat, as intrawave velocities and intrawave infiltration 00338 ! not resolved in surf-beat/stationary type approach) 00339 00340 ! U-points 00341 do j=1,s%ny+1 00342 do i=1,s%nx 00343 if(s%wetu(i,j)==1) then 00344 infilb(i,j) = 0.5d0*(s%infil(i,j)+s%infil(i+1,j)) 00345 else 00346 infilb(i,j) = 0.d0 00347 endif 00348 enddo 00349 enddo 00350 infilb(s%nx+1,:) = infilb(s%nx,:) 00351 where(s%wetu==1) 00352 !!!Ubed = sqrt(cfu)*abs(vmageu) older 00353 !Ubed = abs(s%uu) ! original XBeach-G 00354 Ubed = abs(s%vmageu) 00355 Ventilation = -infilb/max(Ubed,1.d-6) 00356 Ventilation = max(min(Ventilation,epsVentilation),-epsVentilation) 00357 blphi = 0.9d0/2/s%cfu*Ventilation 00358 ! need to account for devision by zero 00359 where(infilb>=0.d0) 00360 blphi = min(blphi,-1d-4) 00361 facbl = blphi/(exp(blphi)-1.d0) 00362 facbl = min(facbl,maxEnhancement1) 00363 elsewhere 00364 blphi = max(blphi,1d-4) 00365 facbl = blphi/(exp(blphi)-1.d0) 00366 facbl = max(facbl,maxEnhancement2) 00367 endwhere 00368 !s%cfu = s%cfu*facbl 00369 !s%cfu = min(s%cfu,1.d0) 00370 ! backward compatibility maximum value (almost never met) 00371 facbl = min(facbl,1.d0/s%cfu) ! maximizes cfu at 1.0 (=huge) 00372 s%taubx_add = s%taubx_add + (facbl-1.d0)*s%cfu*par%rho*s%ueu*s%vmageu 00373 endwhere 00374 00375 00376 ! V-points 00377 if(par%ny>0) then 00378 do j=1,s%ny 00379 do i=1,s%nx+1 00380 if(s%wetv(i,j)==1) then 00381 infilb(i,j) = 0.5d0*(s%infil(i,j)+s%infil(i,j+1)) 00382 else 00383 infilb(i,j) = 0.d0 00384 endif 00385 enddo 00386 enddo 00387 infilb(:,s%ny+1) = s%infil(:,s%ny) 00388 else 00389 ! v-points centered on cell centre 00390 infilb = s%infil 00391 endif 00392 where(s%wetv==1) 00393 !!!Ubed = sqrt(cfv)*abs(vmagev) ! older 00394 ! Ubed = abs(vv) ! orginal XBeach-G 00395 Ubed = abs(s%vmagev) 00396 Ventilation = -infilb/max(Ubed,1.d-6) 00397 Ventilation = max(min(Ventilation,epsVentilation),-epsVentilation) 00398 blphi = 0.9d0/2/s%cfv*Ventilation 00399 ! need to account for devision by zero 00400 where(infilb>=0.d0) 00401 blphi = min(blphi,-1d-4) 00402 facbl = blphi/(exp(blphi)-1.d0) 00403 facbl = min(facbl,maxEnhancement1) 00404 elsewhere 00405 blphi = max(blphi,1d-4) 00406 facbl = blphi/(exp(blphi)-1.d0) 00407 facbl = max(facbl,maxEnhancement2) 00408 endwhere 00409 !s%cfv = s%cfv*facbl 00410 !s%cfv = min(s%cfv,1.d0) 00411 facbl = min(facbl,1.d0/s%cfv) 00412 s%tauby_add = s%tauby_add + (facbl-1.d0)*s%cfv*par%rho*s%vev*s%vmagev 00413 endwhere 00414 00415 end subroutine infiltration_boundary_layer_effect 00416 00417 subroutine acceleration_boundary_layer_effect(s,par) 00418 00419 use params, only: parameters 00420 use spaceparamsdef, only: spacepars 00421 use paramsconst 00422 00423 IMPLICIT NONE 00424 00425 type(parameters),intent(in) :: par 00426 type(spacepars) :: s 00427 00428 real*8 :: Tsmooth,factime 00429 real*8,dimension(:,:),allocatable,save :: Fi 00430 00431 00432 if(.not.allocated(dudtsmooth)) then 00433 ! arrays available in bed friction module only 00434 allocate (dudtsmooth(s%nx+1,s%ny+1)) 00435 allocate (dvdtsmooth(s%nx+1,s%ny+1)) 00436 allocate (ueuold (s%nx+1,s%ny+1)) 00437 allocate (uevold (s%nx+1,s%ny+1)) 00438 allocate (vevold (s%nx+1,s%ny+1)) 00439 allocate (veuold (s%nx+1,s%ny+1)) 00440 allocate (ueuf (s%nx+1,s%ny+1)) 00441 allocate (uevf (s%nx+1,s%ny+1)) 00442 allocate (vevf (s%nx+1,s%ny+1)) 00443 allocate (veuf (s%nx+1,s%ny+1)) 00444 allocate (Fi (s%nx+1,s%ny+1)) 00445 ueuold = 0.d0 00446 uevold = 0.d0 00447 vevold = 0.d0 00448 veuold = 0.d0 00449 ueuf = 0.d0 00450 uevf = 0.d0 00451 vevf = 0.d0 00452 veuf = 0.d0 00453 dtold = par%dt 00454 endif 00455 00456 ! Problem with derivation of DUdt in U and V points 00457 ! ueu and veu are not known until end of flow timestep, so 00458 ! both are based on previous time step. The temporal gradient 00459 ! can only be found by going back one more time step. 00460 ! We need to keep track of par%dt so the correct time step for 00461 ! the gradient is used: 00462 ! 00463 ! i-2 i-1 i (now) i+1 (future) 00464 ! dtold(1) dtold(2) par%dt 00465 ! ueuold ueuf unknown 00466 ! 00467 ! Note that this assumes that the acceleration term does not change significantly 00468 ! over 2 timesteps and that the location mask wetu can still be used, 00469 ! even though it is not the wetu mask of 2 timesteps ago. 00470 Tsmooth = par%Trep/20 00471 factime = min(dtold(1)/Tsmooth,1.d0) 00472 00473 where(s%wetu==1) 00474 ueuf = (1-factime)*ueuf + factime*s%ueu ! note, because taub_add has linear relation with total acceleration (dvmag/dt) 00475 ! the x-component taubx_add can be computed from only the u-component of the 00476 ! acceleration 00477 dudtsmooth = (ueuf-ueuold)/dtold(1) 00478 !dudtsmooth = (ueuf-ueuold)/dtold(1)+ududx*wetu_ududx ! Following Baldock attempt to correct du/dt to dp/dx 00479 ! cut off rediculous values 00480 where (dudtsmooth>100*par%g) 00481 dudtsmooth = 100*par%g 00482 elsewhere (dudtsmooth<-100*par%g) 00483 dudtsmooth = -100*par%g 00484 endwhere 00485 s%taubx_add = s%taubx_add + par%ci*par%rho*min(s%D50top,s%hu)*dudtsmooth 00486 elsewhere 00487 ueuf = 0.d0 00488 veuf = 0.d0 00489 endwhere 00490 00491 ! now set the old variable to the i-1 variables 00492 ueuold = ueuf 00493 veuold = veuf 00494 00495 ! in some cases we don't need to compute v-acceleration 00496 ! - 1D non-h has only u components 00497 ! - 1D surfbeat / stationary has no v-components if boundary set to wall 00498 if (par%ny==0 .and. ((par%left==LR_WALL .and. par%right==LR_WALL) .or. par%swave==0)) then 00499 ! do nothing (don't change tauby_add) 00500 else 00501 where(s%wetv==1) 00502 vevf = (1-factime)*vevf + factime*s%vev 00503 dvdtsmooth = (vevf-vevold)/dtold(1) 00504 where (dvdtsmooth>100*par%g) 00505 dvdtsmooth = 100*par%g 00506 elsewhere (dvdtsmooth<-100*par%g) 00507 dvdtsmooth = -100*par%g 00508 endwhere 00509 s%tauby_add = s%tauby_add + par%ci*par%rho*min(s%D50top,s%hv)*dvdtsmooth 00510 elsewhere 00511 vevf = 0.d0 00512 uevf = 0.d0 00513 endwhere 00514 00515 ! now set the old variable to the i-1 variables 00516 uevold = uevf 00517 vevold = vevf 00518 endif 00519 00520 ! update timekeeping 00521 dtold(1) = dtold(2) 00522 dtold(2) = par%dt 00523 00524 end subroutine acceleration_boundary_layer_effect 00525 00526 subroutine acceleration_boundary_layer_effect_Nielsen(s,par) 00527 00528 use params, only: parameters 00529 use spaceparamsdef, only: spacepars 00530 use constants, only: pi 00531 use paramsconst 00532 00533 IMPLICIT NONE 00534 00535 type(parameters),intent(in) :: par 00536 type(spacepars) :: s 00537 real*8 :: omegap,Tsmooth,factime,iomegap 00538 real*8,save :: phirad 00539 00540 00541 if(.not.allocated(dudtsmooth)) then 00542 allocate (dudtsmooth(s%nx+1,s%ny+1)) 00543 allocate (dvdtsmooth(s%nx+1,s%ny+1)) 00544 allocate (ueuold (s%nx+1,s%ny+1)) 00545 !allocate (uevold (s%nx+1,s%ny+1)) 00546 allocate (vevold (s%nx+1,s%ny+1)) 00547 !allocate (veuold (s%nx+1,s%ny+1)) 00548 allocate (ueuf (s%nx+1,s%ny+1)) 00549 !allocate (uevf (s%nx+1,s%ny+1)) 00550 allocate (vevf (s%nx+1,s%ny+1)) 00551 !allocate (veuf (s%nx+1,s%ny+1)) 00552 ueuold = 0.d0 00553 !uevold = 0.d0 00554 vevold = 0.d0 00555 !veuold = 0.d0 00556 ueuf = 0.d0 00557 !uevf = 0.d0 00558 vevf = 0.d0 00559 !veuf = 0.d0 00560 dtold = par%dt 00561 phirad = par%phit/180*par%px 00562 endif 00563 00564 omegap = 2*par%px/par%Trep 00565 iomegap = 1/omegap 00566 ! Problem with derivation of DUdt in U and V points 00567 ! ueu and veu are not known until end of flow timestep, so 00568 ! both are based on previous time step. The temporal gradient 00569 ! can only be found by going back one more time step. 00570 ! We need to keep track of par%dt so the correct time step for 00571 ! the gradient is used: 00572 ! 00573 ! i-2 i-1 i (now) i+1 (future) 00574 ! dtold(1) dtold(2) par%dt 00575 ! ueuold ueuf unknown 00576 ! 00577 ! Note that this assumes that the acceleration term does not change significantly 00578 ! over 2 timesteps and that the location mask wetu can still be used, 00579 ! even though it is not the wetu mask of 2 timesteps ago. 00580 Tsmooth = par%Trep/20 00581 factime = min(dtold(1)/Tsmooth,1.d0) 00582 where(s%wetu==1) 00583 !ueuf = (1-factime)*ueuf + factime*s%ueu 00584 !veuf = (1-factime)*veuf + factime*s%veu 00585 !dudtsmooth = sqrt(((ueuf-ueuold)/dtold(1))**2 + & 00586 ! ((veuf-veuold)/dtold(1))**2) 00587 ! 00588 ! Robert: stick to 1D approach, similar to acceleration_boundary_layer_effect subroutine 00589 ueuf = (1-factime)*ueuf + factime*s%ueu 00590 dudtsmooth = (ueuf-ueuold)/dtold(1) 00591 elsewhere 00592 ueuf = 0.d0 00593 !veuf = 0.d0 00594 dudtsmooth = 0.d0 00595 endwhere 00596 00597 ! in some cases we don't need to compute v-acceleration 00598 ! - 1D cases without short wave forcing (e.g., non-h) has only u components 00599 ! - 1D surfbeat / stationary with short wave forcing has no v-components if boundary set to wall 00600 if (par%ny==0 .and. ((par%left==LR_WALL .and. par%right==LR_WALL) .or. par%swave==0)) then 00601 dvdtsmooth = 0.d0 00602 else 00603 where(s%wetv==1) 00604 vevf = (1-factime)*vevf + factime*s%vev 00605 dvdtsmooth = (vevf-vevold)/dtold(1) 00606 !uevf = (1-factime)*uevf + factime*uev 00607 !dvdtsmooth = sqrt(((vevf-vevold)/dtold(1))**2 + & 00608 ! ((uevf-uevold)/dtold(1))**2) 00609 elsewhere 00610 vevf = 0.d0 00611 !uevf = 0.d0 00612 dvdtsmooth = 0.d0 00613 endwhere 00614 endif 00615 ! now set the old variable to the i-1 variables 00616 ueuold = ueuf 00617 !uevold = uevf 00618 vevold = vevf 00619 !veuold = veuf 00620 dtold(1) = dtold(2) 00621 dtold(2) = par%dt 00622 ! New approach: 00623 ! we want to use Nielsen to compute bed shear stress (taubx_total): 00624 ! taubx_total = cf*rho*(cos(phi)*ue + 1/w*sin(phi)*dudt)^2*sign(u) 00625 ! 00626 ! in flow timestep the "regular" taubx is computed 00627 ! (note, here we again ignore urms component, Nielsen not meant for wave-averaged approach): 00628 ! taubx = cf*rho*ueu*umageu 00629 ! 00630 ! therefore: 00631 ! taubx_add = taubx_total-taubx = cf*rho*((cos(phi)*ue + 1/w*sin(phi)*dudt)^2*sign(u)-ueu*umageu) 00632 ! 00633 ! there is inconsistency in definitions of ue and umageu (v-component), which is not resolved in Nielsen paper, but if we 00634 ! rewrite to maintain consistency for stationary case (phi = 0 and dudt = 0) then: 00635 ! 00636 ! taubx_total = cf*rho* (cos^2(phi)*ueu*vmageu + 2*cos(phi)*ueu*sin(phi)*1/w*dudt + (sin(phi)*1/w*dudt)^2*sign(ueu)) 00637 ! and 00638 ! taubx_add = cf*rho * ((cos^2(phi)-1)*ueu*vmageu + 2*cos(phi)*ueu*sin(phi)*1/w*dudt + (sin(phi)*1/w*dudt)^2*sign(ueu)) 00639 ! (ignoring urms component in taubx) 00640 where(s%wetu==1) 00641 s%taubx_add = s%taubx_add + s%cfu*par%rho*( ((cos(phirad))**2-1)*s%ueu*s%vmageu & 00642 + 2*cos(phirad)*s%ueu*sin(phirad)*iomegap*dudtsmooth & 00643 + (sin(phirad)*iomegap*dudtsmooth)**2*sign(1.d0,s%ueu) & 00644 ) 00645 endwhere 00646 if (par%ny==0 .and. ((par%left==LR_WALL .and. par%right==LR_WALL) .or. par%swave==0)) then 00647 ! do nothing, leave tauby_add as is 00648 else 00649 where(s%wetv==1) 00650 s%tauby_add = s%tauby_add + s%cfv*par%rho*( ((cos(phirad))**2-1)*s%vev*s%vmagev & 00651 + 2*cos(phirad)*s%vev*sin(phirad)*iomegap*dvdtsmooth & 00652 + (sin(phirad)*iomegap*dvdtsmooth)**2*sign(1.d0,s%vev) & 00653 ) 00654 endwhere 00655 endif 00656 00657 00658 end subroutine acceleration_boundary_layer_effect_Nielsen 00659 00660 subroutine turbulence_boundary_layer_effect(s,par) 00661 00662 use params, only: parameters 00663 use spaceparamsdef, only: spacepars 00664 00665 IMPLICIT NONE 00666 00667 type(parameters),intent(in) :: par 00668 type(spacepars) :: s 00669 real*8,dimension(:,:),allocatable,save :: kbl 00670 integer :: i,j 00671 00672 ! Following Reniers et al (2004) 00673 ! ubed_turb = sqrt(ubed^2+gamma*kb) :: gamma ~ 1 00674 ! 00675 ! New way: compute taubx_add and tauby_add 00676 ! taubx_total = cf*rho*(ubed^2+gamma*kb) 00677 ! taubx = cf*rho*(ubed^2) 00678 ! taubx_add = cf*rho*(gamma*kb) 00679 00680 if (.not.allocated(kbl)) then 00681 allocate (kbl(s%nx+1,s%ny+1)) 00682 endif 00683 00684 ! U-points 00685 do j=1,s%ny+1 00686 do i=1,s%nx 00687 if(s%wetu(i,j)==1) then 00688 kbl(i,j) = 0.5d0*(s%kb(i,j)+s%kb(i+1,j)) 00689 else 00690 kbl(i,j) = 0.d0 00691 endif 00692 enddo 00693 enddo 00694 kbl(s%nx+1,:) = kbl(s%nx,:) 00695 where(s%wetu==1 .and. kbl>0.d0) 00696 ! New way: 00697 s%taubx_add = s%taubx_add + s%cfu*par%rho*par%gamma_turb*kbl*sign(1.d0,s%ue) 00698 00699 ! Old way: 00700 !cfu = cfu*(1.d0+(kbl/max(uu**2,1.d-6))) 00701 !cfu = cfu*(1.d0+(2.d0**(1.25d0)*sqrt(kbl))/max(abs(uu),1.d-6)+(sqrt(2.d0)*kbl)/max(uu**2,1.d-6)) 00702 endwhere 00703 ! V-points 00704 if(par%ny>0) then 00705 do j=1,s%ny 00706 do i=1,s%nx+1 00707 if(s%wetv(i,j)==1) then 00708 kbl(i,j) = 0.5d0*(s%kb(i,j)+s%kb(i,j+1)) 00709 else 00710 kbl(i,j) = 0.d0 00711 endif 00712 enddo 00713 enddo 00714 kbl(:,s%ny+1) = kbl(:,s%ny) 00715 else 00716 ! v-points centered on cell centre 00717 kbl = s%kb 00718 endif 00719 where(s%wetv==1 .and. kbl>0.d0) 00720 ! New way: 00721 s%tauby_add = s%tauby_add + s%cfv*par%rho*par%gamma_turb*kbl*sign(1.d0,s%ve) 00722 00723 ! Old way: 00724 !cfv = cfv*(1.d0+(kbl/max(vv**2,1.d-6))) 00725 !cfv = cfv*(1.d0+(2.d0**(1.25d0)*sqrt(kbl))/max(abs(vv),1.d-6)+(sqrt(2.d0)*kbl)/max(vv**2,1.d-6)) 00726 endwhere 00727 00728 end subroutine turbulence_boundary_layer_effect 00729 00730 00731 end module bedroughness_module