XBeach
|
00001 !============================================================================== 00002 ! MODULE NH_MAIN 00003 !============================================================================== 00004 00005 ! DATE AUTHOR CHANGES 00006 ! 00007 ! october 2009 Pieter Bart Smit New module 00008 ! october 2014 Pieter Bart Smit Included an updated pressure correction scheme/general maintenance 00009 00010 ! -- REMARKS -- 00011 ! There are "two" mutually exclusive implementations of the non-hydrostatic model 00012 ! in this file. The first is the original non-hydrostatic code (see Draft report) 00013 ! which has been left untouched (except for fixing some consistency errors). The 00014 ! second implementation is the reduced two-layer formulation. The new implementation 00015 ! uses two-layers in the vertical (controlled by a thickness parameter) and should 00016 ! give better results for shorter wave components. Moreover, it contains the previous 00017 ! code as a special case (thickness of the lower layer is set to 0). 00018 ! 00019 ! INCLUDED SUBROUTINES 00020 ! + nonh_cor 00021 ! This is the entry routine for the nonhydrostatic code when called from 00022 ! flowtimestep. Depending on the parameter nh_red it calls the old nh-routines 00023 ! or the new reduced routines. 00024 ! 00025 ! + nonh_init 00026 ! Initializes the various resources required. 00027 ! 00028 ! + nonh_1lay_cor 00029 ! The "old" non-hydrostatic correction routine, calculates the new dynamic 00030 ! pressure. 00031 ! 00032 ! + nonh_1lay_pred 00033 ! 00034 ! 00035 module nonh_module 00036 00037 implicit none 00038 save 00039 private 00040 00041 00042 ! If mpi is defined, the non-hydrostatic module is NOT included in the compilation 00043 ! to avoid unwanted side effects. 00044 00045 !****************************************************************************** 00046 ! INTERFACE 00047 !****************************************************************************** 00048 00049 00050 !----------------------------- PARAMETERS ----------------------------------- 00051 00052 include 'nh_pars.inc' !Default precision etc. 00053 00054 !----------------------------- VARIABLES ----------------------------------- 00055 00056 logical :: initialized = .false. !Indicates whether or not the nh_module has been initialized 00057 00058 ! 00059 ! -- Numerical parameter -- 00060 ! 00061 real (kind=rKind), allocatable, dimension(:,:) :: wcoef !The relative thickness of the lower layer in the reduced 00062 !two-layer model at z-points (optimisation parameter in "old model") 00063 ! 00064 ! -- Additional physical variables -- 00065 ! 00066 real (kind=rKind), allocatable, dimension(:,:) :: dp !Change in pressure between the old and 00067 !new timestep 00068 real (kind=rKind), allocatable, dimension(:,:) :: Wm !The mean vertical velocity in the top 00069 !layer (nonhq3d) 00070 real (kind=rKind), allocatable, dimension(:,:) :: Wm_old !The mean vertical velocity in the top 00071 !layer on the previous timestep (nonhq3d) 00072 real (kind=rKind), allocatable, dimension(:,:) :: Wm0 !The mean vertical velocity in the bottom 00073 !layer (nonhq3d) 00074 real (kind=rKind), allocatable, dimension(:,:) :: dU0 !The velocity (s-dir) difference between the top 00075 !and bottom layers at the previous timestep 00076 real (kind=rKind), allocatable, dimension(:,:) :: dV0 !The velocity (n-dir) difference between the top 00077 !and bottom layers at the previous timestep 00078 real (kind=rKind), allocatable, dimension(:,:) :: omega !The velocity vertical transport velocity 00079 00080 ! 00081 ! -- Arrays used for building the Poisson equation -- 00082 ! 00083 real (kind=rKind), allocatable, dimension(:,:,:) :: au !Pressure coeficients for u(i,j), au(0,i,j) refers to 00084 !s%nhpres(i,j) and au(1,i,j) to s%nhpres(i+1,j) 00085 real (kind=rKind), allocatable, dimension(:,:,:) :: av !Pressure coeficients for v(i,j), av(0,i,j) refers to 00086 !s%nhpres(i,j) and av(1,i,j) to s%nhpres(i,j+1) 00087 real (kind=rKind), allocatable, dimension(:,:,:) :: adu !Pressure coeficients for du(i,j), adu(0,i,j) refers to 00088 !s%nhpres(i,j) and au(1,i,j) to s%nhpres(i+1,j) 00089 real (kind=rKind), allocatable, dimension(:,:,:) :: adv !Pressure coeficients for dv(i,j), adv(0,i,j) refers to 00090 !s%nhpres(i,j) and adv(1,i,j) to s%nhpres(i,j+1) 00091 real (kind=rKind), allocatable, dimension(:,:,:) :: mat !5-diagonal Pressure matrix. 00092 ! Diagonal Pressure Point 00093 ! 1 i ,j 00094 ! 2 i-1,j 00095 ! 3 i+1,j 00096 ! 4 i ,j-1 00097 ! 5 i ,j+1 00098 real (kind=rKind), allocatable, dimension(:,:) :: rhs !RHS of the pressure matrix 00099 00100 real (kind=rKind), allocatable, dimension(:,:,:) :: aws !Pressure coeficients for ws(k,i,j) !**OBSOLETE IN nonhq3d** 00101 real (kind=rKind), allocatable, dimension(:,:,:) :: awb !Pressure coeficients for wb(k,i,j) !**OBSOLETE IN nonhq3d** 00102 real (kind=rKind), allocatable, dimension(:,:) :: aur !RHS for du(i,j) !**OBSOLETE IN nonhq3d** 00103 real (kind=rKind), allocatable, dimension(:,:) :: avr !RHS for dv(i,j) !**OBSOLETE IN nonhq3d** 00104 real (kind=rKind), allocatable, dimension(:,:) :: awbr !Pressure coeficients for wb(k,i,j) !**OBSOLETE IN nonhq3d** 00105 real (kind=rKind), allocatable, dimension(:,:) :: awsr !Pressure coeficients for ws(k,i,j) !**OBSOLETE IN nonhq3d** 00106 00107 ! 00108 ! -- Additional grid parameters -- 00109 ! 00110 real (kind=rKind), allocatable, dimension(:,:) :: zsu !free surface-level in u-velocity points 00111 real (kind=rKind), allocatable, dimension(:,:) :: zsv !free surface-level in v-velocity points 00112 real (kind=rKind), allocatable, dimension(:,:) :: zbu !free bed-level in u-velocity points 00113 real (kind=rKind), allocatable, dimension(:,:) :: zbv !free bed-level in v-velocity points 00114 00115 real (kind=rKind), allocatable, dimension(:) :: dxz !**OBSOLETE IN nonhq3d** 00116 real (kind=rKind), allocatable, dimension(:) :: dyz !**OBSOLETE IN nonhq3d** 00117 real (kind=rKind), allocatable, dimension(:) :: dxu !**OBSOLETE IN nonhq3d** 00118 real (kind=rKind), allocatable, dimension(:) :: dyv !**OBSOLETE IN nonhq3d** 00119 real (kind=rKind), allocatable, dimension(:) :: ddxz !**OBSOLETE IN nonhq3d** 00120 real (kind=rKind), allocatable, dimension(:) :: ddyz !**OBSOLETE IN nonhq3d** 00121 real (kind=rKind), allocatable, dimension(:) :: ddxu !**OBSOLETE IN nonhq3d** 00122 real (kind=rKind), allocatable, dimension(:) :: ddyv !**OBSOLETE IN nonhq3d** 00123 00124 integer(kind=iKind),allocatable,dimension(:,:) :: nonhU 00125 integer(kind=iKind),allocatable,dimension(:,:) :: nonhV 00126 integer(kind=iKind),allocatable,dimension(:,:) :: nonhZ 00127 real (kind=rKind), allocatable, dimension(:,:) :: lbreakcond 00128 00129 !--- PUBLIC SUBROUTINES --- 00130 public nonh_init 00131 public nonh_cor 00132 public nonh_init_wcoef 00133 00134 !--- PRIVATE SUBROUTINES 00135 00136 ! NONE 00137 contains 00138 ! 00139 !****************************************************************************** 00140 ! SUBROUTINES/FUNCTIONS 00141 !****************************************************************************** 00142 ! 00143 00144 ! 00145 !============================================================================== 00146 subroutine nonh_cor(s,par,ipredcor,uu0,vv0) 00147 !============================================================================== 00148 ! 00149 ! 00150 ! DATE AUTHOR CHANGES 00151 ! 00152 ! October 2014 Pieter Bart Smit new subroutine 00153 ! 00154 !------------------------------------------------------------------------------- 00155 ! DECLARATIONS 00156 !------------------------------------------------------------------------------- 00157 00158 !-------------------------- PURPOSE ---------------------------- 00159 00160 ! This is the new entry routine for the non-hydrostatic module. It is called twice during each timestep by the 00161 ! flow module, (I) (withe path=0) before the second-order corrections are applied (if applicable) to include the known pressure 00162 ! explicitly in the momentum equations, and (II) (path=1) just after the second order advection correction to calculate 00163 ! the new pressures implicitly. The codepath taken is specified with the path parameter (path=0 for step I, and path=1 for 00164 ! step II). 00165 ! 00166 ! Moreover, depending on the parameter nonhq3d, which activates the new reduced 2 layer model, again different codepaths 00167 ! are taken: 00168 ! 00169 ! IF nonhq3d=0 00170 ! call the "old" versions of the non-hydrostatic routines 00171 ! (path=0) nonh_1lay_pred (renamed from nonh_explicit) 00172 ! (path=1) nonh_1lay_cor (renamed from nonh_cor) 00173 ! IF nonhq3d=1 00174 ! call the "old" versions of the non-hydrostatic routine 00175 ! IF 1D 00176 ! (path=0) nonh_2lay_pred_2DV (renamed from nonh_explicit) 00177 ! (path=1) nonh_2lay_cor_2DV (renamed from nonh_cor) 00178 ! ELSE 00179 ! (path=0) nonh_2lay_pred_3D (renamed from nonh_explicit) 00180 ! (path=1) nonh_2lay_cor_3D (renamed from nonh_cor) 00181 ! 00182 !-------------------------- DEPENDENCIES ---------------------------- 00183 00184 use spaceparams 00185 use params, only: parameters 00186 use xmpi_module 00187 00188 !-------------------------- ARGUMENTS ---------------------------- 00189 00190 type(spacepars) ,intent(inout) :: s 00191 type(parameters),intent(in) :: par 00192 integer ,intent(in) :: ipredcor !Select if we want to apply the explicit predicition / or the implicit correction 00193 00194 real(kind=rkind),dimension(s%nx+1,s%ny+1),intent(in) :: uu0 00195 real(kind=rkind),dimension(s%nx+1,s%ny+1),intent(in) :: vv0 00196 00197 !------------------------------------------------------------------------------- 00198 ! IMPLEMENTATION 00199 !------------------------------------------------------------------------------- 00200 00201 select case ( par%nonhq3d ) 00202 ! 00203 case (1) 00204 ! 00205 ! The "new" reduced two-layer formulations are used 00206 ! 00207 if ( ipredcor == 0 ) then 00208 ! -- Predictor 00209 if ( s%ny == 0 ) then 00210 ! -- 2dv code path 00211 call nonh_2lay_pred_2dV(s,par,uu0) 00212 ! 00213 else 00214 ! -- "3d" code path 00215 call nonh_2lay_pred_3d(s,par,uu0,vv0) 00216 ! 00217 endif 00218 ! 00219 else 00220 ! 00221 if ( s%ny == 0 ) then 00222 ! 00223 call nonh_2lay_cor_2dV(s,par) 00224 ! 00225 else 00226 ! 00227 call nonh_2lay_cor_3d(s,par) 00228 ! 00229 endif 00230 ! 00231 endif 00232 ! 00233 case default 00234 ! 00235 ! The "old" code is used 00236 ! 00237 if ( ipredcor == 0 ) then 00238 ! -- Predictor 00239 call nonh_1lay_pred(s,par) 00240 ! 00241 else 00242 ! -- Corrector 00243 call nonh_1lay_cor(s,par) 00244 ! 00245 endif 00246 ! 00247 end select 00248 ! 00249 end subroutine nonh_cor 00250 00251 00252 ! 00253 !============================================================================== 00254 subroutine nonh_init(s,par) 00255 !============================================================================== 00256 ! 00257 00258 ! DATE AUTHOR CHANGES 00259 ! 00260 ! October 2010 Pieter Bart Smit New Subroutine 00261 00262 !------------------------------------------------------------------------------- 00263 ! DECLARATIONS 00264 !------------------------------------------------------------------------------- 00265 00266 ! 00267 !-------------------------- PURPOSE ---------------------------- 00268 ! 00269 ! Initializes nh subroutines 00270 ! 00271 !-------------------------- DEPENDENCIES ---------------------------- 00272 00273 use spaceparams 00274 use params, only: parameters 00275 00276 !-------------------------- ARGUMENTS ---------------------------- 00277 ! 00278 type(spacepars) ,intent(inout) :: s 00279 type(parameters),intent(in) :: par 00280 ! 00281 00282 !------------------------------------------------------------------------------- 00283 ! IMPLEMENTATION 00284 !------------------------------------------------------------------------------- 00285 00286 ! open(unit=PrintFileUnit,file=trim(PrintFileName)) 00287 00288 if(.not. xcompute) return 00289 00290 allocate(au (0:1,s%nx+1,s%ny+1)); au = 0.0_rKind 00291 allocate(av (0:1,s%nx+1,s%ny+1)); av = 0.0_rKind 00292 allocate(mat(5,s%nx+1,s%ny+1)) ; mat = 0.0_rKind 00293 allocate(rhs( s%nx+1,s%ny+1)) ; rhs = 0.0_rKind 00294 allocate(zbu( s%nx+1,s%ny+1)) ; zbu = 0.0_rKind 00295 allocate(zbv( s%nx+1,s%ny+1)) ; zbv = 0.0_rKind 00296 allocate(zsu( s%nx+1,s%ny+1)) ; zsu = 0.0_rKind 00297 allocate(zsv( s%nx+1,s%ny+1)) ; zsv = 0.0_rKind 00298 allocate(nonhU( s%nx+1,s%ny+1)); nonhU = 1 00299 allocate(nonhV( s%nx+1,s%ny+1)); nonhV = 1 00300 allocate(nonhZ( s%nx+1,s%ny+1)); nonhZ = 1 00301 allocate(lbreakcond(s%nx+1,s%ny+1)); lbreakcond = par%maxbrsteep 00302 allocate(dp(s%nx+1,s%ny+1)) ; dp = 0.0_rKind 00303 allocate(Wm(s%nx+1,s%ny+1)) ;Wm = 0.0_rKind 00304 allocate(Wm_old(s%nx+1,s%ny+1)) ;Wm_old = 0.0_rKind 00305 allocate(Wcoef(s%nx+1,s%ny+1)) ;Wcoef = 1.0_rKind 00306 allocate(aws (5,s%nx+1,s%ny+1)) ; aws = 0.0_rKind 00307 ! 00308 ! The reduced two-layer model 00309 ! 00310 if ( par%nonhq3d == 1 ) then 00311 ! 00312 allocate(omega(s%nx+1,s%ny+1)); omega = 0.0_rKind 00313 allocate(adu (0:1,s%nx+1,s%ny+1)); adu = 0.0_rKind 00314 allocate(adv (0:1,s%nx+1,s%ny+1)); adv = 0.0_rKind 00315 allocate(Wm0(s%nx+1,s%ny+1)) ;Wm0 = 0.0_rKind 00316 allocate(dU0(s%nx+1,s%ny+1)) ;dU0 = 0.0_rKind 00317 allocate(dV0(s%nx+1,s%ny+1)) ;dV0 = 0.0_rKind 00318 ! 00319 else 00320 ! 00321 ! These grid variables are obsolete in the new reduced model 00322 ! 00323 allocate(dxz ( s%nx+1)) ; dxz = 0.0_rKind 00324 allocate(dyz ( s%ny+1)) ; dyz = 0.0_rKind 00325 allocate(dxu ( s%nx+1)) ; dxu = 0.0_rKind 00326 allocate(dyv ( s%ny+1)) ; dyv = 0.0_rKind 00327 00328 allocate(ddxz ( s%nx+1)) ; ddxz = 0.0_rKind 00329 allocate(ddyz ( s%ny+1)) ; ddyz = 0.0_rKind 00330 allocate(ddxu ( s%nx+1)) ; ddxu = 0.0_rKind 00331 allocate(ddyv ( s%ny+1)) ; ddyv = 0.0_rKind 00332 allocate(awb (5,s%nx+1,s%ny+1)) ; awb = 0.0_rKind 00333 allocate(aur( s%nx+1,s%ny+1)) ; aur = 0.0_rKind 00334 allocate(avr( s%nx+1,s%ny+1)) ; avr = 0.0_rKind 00335 allocate(awbr(s%nx+1,s%ny+1)) ; awbr = 0.0_rKind 00336 allocate(awsr(s%nx+1,s%ny+1)) ; awsr = 0.0_rKind 00337 00338 !Initialize grid variables 00339 dyz = s%dnz(1,:) 00340 dyv = s%dnv(1,:) 00341 ddyz = 1.0_rKind/dyz 00342 ddyv = 1.0_rKind/dyv 00343 00344 dxu = s%dsu(:,1) 00345 dxz = s%dsz(:,1) 00346 ddxu = 1.0_rKind/dxu 00347 ddxz = 1.0_rKind/dxz 00348 ! 00349 endif 00350 00351 mat(1,1,:) = 1.0_rKind 00352 mat(1,s%nx+1,:) = 1.0_rKind 00353 mat(1,:,1) = 1.0_rKind 00354 mat(1,:,s%ny+1) = 1.0_rKind 00355 00356 initialized = .true. 00357 00358 if ( par%nonhq3d == 1 ) then 00359 ! 00360 wcoef = par%nhlay 00361 ! 00362 else 00363 ! 00364 call nonh_init_wcoef(s,par) 00365 ! 00366 endif 00367 ! 00368 00369 !Initialize levels at u/v points (zu,zbu etc.) 00370 call zuzv(s) 00371 00372 end subroutine nonh_init 00373 00374 00375 00376 00377 !============================================================================== 00378 ! "ORIGINAL" NON-HYDROSTATIC ROUTINES 00379 !============================================================================== 00380 ! 00381 ! 00382 ! 00383 !============================================================================== 00384 subroutine nonh_1lay_cor(s,par) 00385 !============================================================================== 00386 ! 00387 00388 ! DATE AUTHOR CHANGES 00389 ! 00390 ! October 2010 Pieter Bart Smit New Subroutine 00391 ! November 2010 Pieter Bart Smit Added explicit prediction for 2nd order scheme 00392 00393 !------------------------------------------------------------------------------- 00394 ! DECLARATIONS 00395 !------------------------------------------------------------------------------- 00396 00397 !-------------------------- PURPOSE ---------------------------- 00398 00399 ! Releases resources 00400 00401 !-------------------------- DEPENDENCIES ---------------------------- 00402 use spaceparams 00403 use params, only: parameters 00404 use solver_module, only: solver_solvemat 00405 use xmpi_module 00406 !-------------------------- ARGUMENTS ---------------------------- 00407 00408 type(spacepars) ,intent(inout) :: s 00409 type(parameters),intent(in) :: par 00410 00411 !-------------------------- LOCAL VARIABLES ---------------------------- 00412 00413 !Indices 00414 integer(kind=iKind) :: i !Index variables 00415 integer(kind=iKind) :: j !Index variables 00416 integer(kind=iKind) :: jmin,jmax !Index variables for superfast1D 00417 00418 ! logical 00419 logical :: sf1d !Switch for superfast1D 00420 00421 !Work 00422 00423 real(kind=rKind) :: dzs_e,dzs_w 00424 real(kind=rKind) :: dzs_s,dzs_n 00425 real(kind=rKind) :: dzb_e,dzb_w 00426 real(kind=rKind) :: dzb_n,dzb_s 00427 00428 00429 ! 00430 !------------------------------------------------------------------------------- 00431 ! IMPLEMENTATION 00432 !------------------------------------------------------------------------------- 00433 ! 00434 dzs_e = 0 00435 dzs_w = 0 00436 dzs_s = 0 00437 dzs_n = 0 00438 dzb_e = 0 00439 dzb_w = 0 00440 dzb_n = 0 00441 dzb_s = 0 00442 if (s%ny>0) then 00443 sf1d = .false. 00444 jmin = 2 00445 jmax = s%ny 00446 else 00447 sf1d = .true. 00448 jmin = 1 00449 jmax = 1 00450 endif 00451 00452 !call timer_start(timer_flow_nonh) 00453 if (.not. initialized) then 00454 call nonh_init(s,par) 00455 endif 00456 00457 call zuzv(s) 00458 00459 !Built pressure coefficients U 00460 aur = s%uu 00461 avr = s%vv 00462 00463 00464 aur(1,:) = s%uu(1,:) 00465 aur(s%nx,:) = s%uu(s%nx,:) 00466 00467 avr(:,1) = s%vv(:,1) 00468 if (s%ny>0) avr(:,s%ny) = s%vv(:,s%ny) 00469 00470 !Built pressure coefficients for W 00471 00472 !AW Bottom 00473 if (sf1d) then 00474 do i=2,s%nx 00475 if (nonhZ(i,1) == 1) then 00476 if (nonhU(i,1)*nonhU(i-1,1) == 1) then 00477 dzb_e = .5_rKind*(zbu(i,1)-zbu(i-1,1))*ddxz(i) 00478 dzb_w = dzb_e 00479 elseif (nonhU(i ,1) == 0) then 00480 dzb_e = .0_rKind 00481 dzb_w = .5_rKind*(s%zb(i,1)-zbu(i-1,1))*ddxz(i) 00482 elseif (nonhU(i-1,1) == 0) then 00483 dzb_e = .5_rKind*(zbu(i,1)-s%zb(i,1)) *ddxz(i) 00484 dzb_w = .0_rKind 00485 endif 00486 00487 if (nonhV(i,1) == 1) then 00488 dzb_s = .0_rKind 00489 dzb_n = dzb_s 00490 elseif (nonhV(i ,1 ) == 0) then 00491 dzb_s = .0_rKind 00492 dzb_n = .5_rKind*(s%zb(i,1)-zbv(i,1))*ddyz(1) 00493 endif 00494 00495 awb(1,i,1) = dzb_e * au(0,i ,1 )+dzb_w*au(1,i-1,1 ) & !main diagonal 00496 + dzb_s * av(0,i ,1 )+dzb_n*av(1,i ,1) 00497 awb(2,i,1) = dzb_w * au(0,i-1,1 ) !west 00498 awb(3,i,1) = dzb_e * au(1,i ,1 ) !east 00499 awb(4,i,1) = dzb_n * av(0,i ,1 ) !south 00500 awb(5,i,1) = dzb_s * av(1,i ,1 ) !north 00501 00502 awbr(i,1) = dzb_e*s%uu(i,1)+dzb_w*s%uu(i-1,1 ) & 00503 + dzb_s*s%vv(i,1)+dzb_n*s%vv(i ,1 ) 00504 else 00505 awb(:,i,1) = 0.0_rKind 00506 awbr(i,1) = 0.0_rKind 00507 endif 00508 enddo 00509 else 00510 do j=2,s%ny 00511 do i=2,s%nx 00512 if (nonhZ(i,j) == 1) then 00513 if (nonhU(i,j)*nonhU(i-1,j) == 1) then 00514 dzb_e = .5_rKind*(zbu(i,j)-zbu(i-1,j))*ddxz(i) 00515 ! FB: this was dzs_e, which was not defined. Assumed it was a typo. TODO: check. 00516 dzb_w = dzb_e 00517 elseif (nonhU(i ,j) == 0) then 00518 dzb_e = .0_rKind 00519 dzb_w = .5_rKind*(s%zb(i,j)-zbu(i-1,j))*ddxz(i) 00520 elseif (nonhU(i-1,j) == 0) then 00521 dzb_e = .5_rKind*(zbu(i,j)-s%zb(i,j)) *ddxz(i) 00522 dzb_w = .0_rKind 00523 endif 00524 00525 if (nonhV(i,j)*nonhV(i,j-1) == 1) then 00526 dzb_s = .5_rKind*(zbv(i,j)-zbv(i,j-1))*ddyz(j) 00527 dzb_n = dzb_s 00528 elseif (nonhV(i ,j ) == 0) then 00529 dzb_s = .0_rKind 00530 dzb_n = .5_rKind*(s%zb(i,j)-zbv(i,j-1))*ddyz(j) 00531 elseif (nonhV(i ,j-1) == 0) then 00532 dzb_s = .5_rKind*(zbv(i,j)-s%zb(i,j)) *ddyz(j) 00533 dzb_n = .0_rKind 00534 endif 00535 00536 awb(1,i,j) = dzb_e * au(0,i ,j )+dzb_w*au(1,i-1,j ) & !main diagonal 00537 + dzb_s * av(0,i ,j )+dzb_n*av(1,i ,j-1) 00538 awb(2,i,j) = dzb_w * au(0,i-1,j ) !west 00539 awb(3,i,j) = dzb_e * au(1,i ,j ) !east 00540 awb(4,i,j) = dzb_n * av(0,i ,j-1) !south 00541 awb(5,i,j) = dzb_s * av(1,i ,j ) !north 00542 00543 awbr(i,j) = dzb_e*s%uu(i,j)+dzb_w*s%uu(i-1,j ) & 00544 + dzb_s*s%vv(i,j)+dzb_n*s%vv(i ,j-1) 00545 else 00546 awb(:,i,j) = 0.0_rKind 00547 awbr(i,j) = 0.0_rKind 00548 endif 00549 enddo 00550 enddo 00551 endif 00552 00553 do j=jmin,jmax 00554 do i=2,s%nx 00555 if (nonhZ(i,j) == 1) then 00556 aws(1,i,j) = wcoef(i,j)*par%dt*2.0_rKind/s%hh(i,j)-awb(1,i,j) 00557 aws(2:5,i,j) = -awb(2:5,i,j) 00558 awsr(i,j) = 2.0_rKind * Wm(i,j)-awbr(i,j) 00559 else 00560 aws(:,i,j) = 0.0_rKind 00561 awsr(i,j) = 0.0_rKind 00562 endif 00563 enddo 00564 enddo 00565 00566 !Substitute in the continuity equation 00567 if (sf1d) then 00568 do i=2,s%nx 00569 if (nonhZ(i,1)==1) then 00570 if (nonhU(i,1)*nonhU(i-1,1) == 1) then 00571 dzs_e = .5_rKind*(zsu(i,1)-zsu(i-1,1))*dyz(1) 00572 dzs_w = dzs_e 00573 elseif (nonhU(i ,1) == 0) then 00574 dzs_e = .0_rKind 00575 dzs_w = .5_rKind*(s%zs(i,1)-zsu(i-1,1))*dyz(1) 00576 elseif (nonhU(i-1,1) == 0) then 00577 dzs_e = .5_rKind*(zsu(i,1)-s%zs(i,1)) *dyz(1) 00578 dzs_w = .0_rKind 00579 endif 00580 00581 ! wwvv problem the following construction make it impossible 00582 ! wwvv to determine if dzs_s gets a value 00583 ! wwvv (What other values than 0 and 1 can nonhV have) 00584 ! wwvv I put this kind of varibles to zero at the start 00585 ! wwvv of the subroutine 00586 if (nonhV(i,1) == 1) then 00587 dzs_s = .0_rKind 00588 dzs_n = dzs_s 00589 elseif (nonhV(i ,1 ) == 0) then 00590 dzs_s = .0_rKind 00591 dzs_n = .5_rKind*(s%zs(i,1)-zsv(i,1))*dxz(i) 00592 endif 00593 00594 00595 mat(1,i,1) = dyz(1)*( s%hu(i,1)*au(0,i,1) - s%hu(i-1,1 )*au(1,i-1, 1) ) & !subs U left/right face 00596 + dxz(i)*( s%hv(i,1)*av(0,i,1) - s%hv(i ,1 )*av(1,i , 1) ) & !subs V left/rigth face 00597 - dzs_e*au(0,i,1) - dzs_w*au(1,i-1,1) & !kin. boun. top 00598 - dzs_s*av(0,i,1) - dzs_n*av(1,i-1,1) & !kin. boun. top 00599 + dxz(i)*dyz(1)*aws(1,i,1) 00600 00601 mat(2,i,1) = - dyz(1)*s%hu(i-1,1)*au(0,i-1, 1) & 00602 - dzs_w*au(0,i-1,1) + dxz(i)*dyz(1)*aws(2,i,1) 00603 00604 mat(3,i,1) = dyz(1)*s%hu(i,1) * au(1,i, 1) & 00605 - dzs_e*au(1,i ,1) + dxz(i)*dyz(1)*aws(3,i,1) 00606 00607 mat(4,i,1) = - dxz(i)*s%hv(i,1) *av(0,i,1) & 00608 - dzs_n*av(0,i,1) + dxz(i)*dyz(1)*aws(4,i,1) 00609 00610 mat(5,i,1) = dxz(i)*s%hv(i,1) * av(1,i,1) & 00611 - dzs_s*av(1,i,1) + dxz(i)*dyz(1)*aws(5,i,1) 00612 00613 rhs(i,1) = - dyz(1)*( s%hu(i,1)*aur(i,1) - s%hu(i-1,1 )*aur(i-1, 1) ) & !subs U left/right face 00614 - dxz(i)*( s%hv(i,1)*avr(i,1) - s%hv(i ,1 )*avr(i , 1) ) & !subs V left/rigth face 00615 + dzs_e*aur(i,1) + dzs_w*aur(i-1,1) & !kin. boun. top 00616 + dzs_s*avr(i,1) + dzs_n*avr(i, 1) & !kin. boun. top 00617 - dxz(i)*dyz(1)*awsr(i,1) 00618 else 00619 mat(1 ,i,1) = 1.0_rKind 00620 mat(2:5,i,1) = 0.0_rKind 00621 rhs(i,1) = 0.0_rKind 00622 endif 00623 enddo 00624 else 00625 do j=2,s%ny 00626 do i=2,s%nx 00627 if (nonhZ(i,j)==1) then 00628 if (nonhU(i,j)*nonhU(i-1,j) == 1) then 00629 dzs_e = .5_rKind*(zsu(i,j)-zsu(i-1,j))*dyz(j) 00630 dzs_w = dzs_e 00631 elseif (nonhU(i ,j) == 0) then 00632 dzs_e = .0_rKind 00633 dzs_w = .5_rKind*(s%zs(i,j)-zsu(i-1,j))*dyz(j) 00634 elseif (nonhU(i-1,j) == 0) then 00635 dzs_e = .5_rKind*(zsu(i,j)-s%zs(i,j)) *dyz(j) 00636 dzs_w = .0_rKind 00637 endif 00638 00639 if (nonhV(i,j)*nonhV(i,j-1) == 1) then 00640 dzs_s = .5_rKind*(zsv(i,j)-zsv(i,j-1))*dxz(i) 00641 dzs_n = dzs_s 00642 elseif (nonhV(i ,j ) == 0) then 00643 dzs_s = .0_rKind 00644 dzs_n = .5_rKind*(s%zs(i,j)-zsv(i,j-1))*dxz(i) 00645 elseif (nonhV(i ,j-1) == 0) then 00646 dzs_s = .5_rKind*(zsv(i,j)-s%zs(i,j)) *dxz(i) 00647 dzs_n = .0_rKind 00648 endif 00649 00650 00651 mat(1,i,j) = dyz(j)*( s%hu(i,j)*au(0,i,j) - s%hu(i-1,j )*au(1,i-1, j) ) & !subs U left/right face 00652 + dxz(i)*( s%hv(i,j)*av(0,i,j) - s%hv(i ,j-1)*av(1,i ,j-1) ) & !subs V left/rigth face 00653 - dzs_e*au(0,i,j) - dzs_w*au(1,i-1,j) & !kin. boun. top 00654 - dzs_s*av(0,i,j) - dzs_n*av(1,i,j-1) & !kin. boun. top 00655 + dxz(i)*dyz(j)*aws(1,i,j) 00656 00657 mat(2,i,j) = - dyz(j)*s%hu(i-1,j)*au(0,i-1, j) & 00658 - dzs_w*au(0,i-1,j) + dxz(i)*dyz(j)*aws(2,i,j) 00659 00660 mat(3,i,j) = dyz(j)*s%hu(i,j) * au(1,i, j) & 00661 - dzs_e*au(1,i ,j) + dxz(i)*dyz(j)*aws(3,i,j) 00662 00663 mat(4,i,j) = - dxz(i)*s%hv(i,j-1) *av(0,i,j-1) & 00664 - dzs_n*av(0,i,j-1) + dxz(i)*dyz(j)*aws(4,i,j) 00665 00666 mat(5,i,j) = dxz(i)*s%hv(i,j) * av(1,i,j) & 00667 - dzs_s*av(1,i,j) + dxz(i)*dyz(j)*aws(5,i,j) 00668 00669 rhs(i,j) = - dyz(j)*( s%hu(i,j)*aur(i,j) - s%hu(i-1,j )*aur(i-1, j) ) & !subs U left/right face 00670 - dxz(i)*( s%hv(i,j)*avr(i,j) - s%hv(i ,j-1)*avr(i ,j-1) ) & !subs V left/rigth face 00671 + dzs_e*aur(i,j) + dzs_w*aur(i-1,j) & !kin. boun. top 00672 + dzs_s*avr(i,j) + dzs_n*avr(i,j-1) & !kin. boun. top 00673 - dxz(i)*dyz(j)*awsr(i,j) 00674 else 00675 mat(1 ,i,j) = 1.0_rKind 00676 mat(2:5,i,j) = 0.0_rKind 00677 rhs(i,j) = 0.0_rKind 00678 endif 00679 enddo 00680 enddo 00681 endif 00682 00683 !Solve matrix 00684 !call timer_start(timer_flow_nonh_solv) 00685 dp = 0.0_rKind 00686 call solver_solvemat( mat , rhs , dp , s%nx, s%ny,par) 00687 !call timer_stop(timer_flow_nonh_solv) 00688 00689 00690 s%pres = s%pres + dp 00691 00692 !Correct u/v/w 00693 00694 !U 00695 do j=jmin_uu,jmax_uu 00696 do i=imin_uu,imax_uu 00697 s%uu(i,j) = aur(i,j) + au(1,i,j)*dp(i+1,j)+au(0,i,j)*dp(i,j) 00698 enddo 00699 enddo 00700 00701 !v 00702 if (sf1d) then 00703 do i=imin_vv,imax_vv 00704 s%vv(i,1) = avr(i,1) + av(1,i,1)*dp(i,1)+av(0,i,1)*dp(i,1) 00705 enddo 00706 else 00707 do j=jmin_vv,jmax_vv 00708 do i=imin_vv,imax_vv 00709 s%vv(i,j) = avr(i,j) + av(1,i,j)*dp(i,j+1)+av(0,i,j)*dp(i,j) 00710 enddo 00711 enddo 00712 endif 00713 00714 !W 00715 if (sf1d) then 00716 do i=imin_zs,imax_zs 00717 if (nonhZ(i,1) == 1) then 00718 s%ws(i,1) = awsr(i,1) + dp(i , 1) * aws(1,i,1) & 00719 + dp(i-1,1) * aws(2,i,1) + dp(i+1,1 ) * aws(3,i,1) & 00720 + dp(i ,1) * aws(4,i,1) + dp(i , 1) * aws(5,i,1) 00721 00722 else 00723 !If the point is excluded in nh then get ws from the kinematic boundary condition 00724 if (s%wetU(i,1)*s%wetU(i-1,1) == 1) then 00725 dzs_e = .5_rKind*(zsu(i,1)-zsu(i-1,1))*ddxz(i) 00726 dzs_w = dzs_e 00727 elseif (s%wetU(i ,1) == 0) then 00728 dzs_e = .0_rKind 00729 dzs_w = .5_rKind*(s%zs(i,1)-zsu(i-1,1))*ddxz(i) 00730 elseif (s%wetU(i-1,1) == 0) then 00731 dzs_e = .5_rKind*(zsu(i,1)-s%zs(i,1)) *ddxz(i) 00732 dzs_w = .0_rKind 00733 else 00734 dzs_e = .0_rKind 00735 dzs_w = .0_rKind 00736 endif 00737 00738 if (s%wetV(i,1) == 1) then 00739 dzs_s = .0_rKind 00740 dzs_n = dzb_s 00741 elseif (s%wetV(i ,1 ) == 0) then 00742 dzs_s = .0_rKind 00743 dzs_n = .5_rKind*(s%zs(i,1)-zsv(i,1))*ddyz(1) 00744 endif 00745 00746 s%ws(i,1) = - (s%hu(i,1)*s%uu(i,1)-s%hu(i-1,1 )*s%uu(i-1,1 ))*ddxz(i) & 00747 - (s%hv(i,1)*s%vv(i,1)-s%hv(i ,1 )*s%vv(i ,1 ))*ddyz(1) & 00748 + dzs_e*s%uu(i,1)+dzs_w*s%uu(i-1,1) & 00749 + dzs_s*s%vv(i,1)+dzs_n*s%vv(i, 1) 00750 endif 00751 enddo 00752 do i=imin_zs,imax_zs 00753 if (nonhZ(i,1) == 1) then 00754 s%wb(i,1) = awbr(i,1) + dp(i , 1) * awb(1,i,1) & 00755 + dp(i-1,1) * awb(2,i,1) + dp(i+1,1 ) * awb(3,i,1) & 00756 + dp(i ,1) * awb(4,i,1) + dp(i ,1 ) * awb(5,i,1) 00757 else 00758 if (s%wetU(i,1)*s%wetU(i-1,1) == 1) then 00759 dzb_e = .5_rKind*(zbu(i,1)-zbu(i-1,1))*ddxz(i) 00760 dzb_w = dzs_e 00761 elseif (s%wetU(i ,1) == 0) then 00762 dzb_e = .0_rKind 00763 dzb_w = .5_rKind*(s%zb(i,1)-zbu(i-1,1))*ddxz(i) 00764 elseif (s%wetU(i-1,1) == 0) then 00765 dzb_e = .5_rKind*(zbu(i,1)-s%zb(i,1)) *ddxz(i) 00766 dzb_w = .0_rKind 00767 else 00768 dzb_e = .0_rKind 00769 dzb_w = .0_rKind 00770 endif 00771 00772 if (s%wetV(i,1) == 1) then 00773 dzb_s = .0_rKind 00774 dzb_n = dzb_s 00775 elseif (s%wetV(i ,1 ) == 0) then 00776 dzb_s = .0_rKind 00777 dzb_n = .5_rKind*(s%zb(i,1)-zbv(i,1))*ddyz(1) 00778 endif 00779 00780 s%wb(i,1) = + dzb_e*s%uu(i,1)+dzb_w*s%uu(i-1,1) & 00781 + dzb_s*s%vv(i,1)+dzb_n*s%vv(i,1) 00782 endif 00783 enddo 00784 !Assign boundaries 00785 #ifdef USEMPI 00786 call xmpi_shift_ee(s%wb) 00787 call xmpi_shift_ee(s%ws) 00788 if (xmpi_istop) then 00789 s%wb(1,:) = s%wb(2,:) 00790 endif 00791 if (xmpi_isbot) then 00792 s%ws(s%nx+1,:) = s%ws(s%nx,:) 00793 s%wb(s%nx+1,:) = s%wb(s%nx,:) 00794 endif 00795 #else 00796 s%ws(s%nx+1,:) = s%ws(s%nx,:) 00797 s%wb(1,:) = s%wb(2,:) 00798 s%wb(s%nx+1,:) = s%wb(s%nx,:) 00799 #endif 00800 else 00801 do j=jmin_zs,jmax_zs 00802 do i=imin_zs,imax_zs 00803 if (nonhZ(i,j) == 1) then 00804 s%ws(i,j) = awsr(i,j) + dp(i , j) * aws(1,i,j) & 00805 + dp(i-1,j) * aws(2,i,j) + dp(i+1,j ) * aws(3,i,j) & 00806 + dp(i ,j-1)* aws(4,i,j) + dp(i ,j+1) * aws(5,i,j) 00807 00808 else 00809 !If the point is excluded in nh then get ws from the kinematic boundary condition 00810 if (s%wetU(i,j)*s%wetU(i-1,j) == 1) then 00811 dzs_e = .5_rKind*(zsu(i,j)-zsu(i-1,j))*ddxz(i) 00812 dzs_w = dzs_e 00813 elseif (s%wetU(i ,j) == 0) then 00814 dzs_e = .0_rKind 00815 dzs_w = .5_rKind*(s%zs(i,j)-zsu(i-1,j))*ddxz(i) 00816 elseif (s%wetU(i-1,j) == 0) then 00817 dzs_e = .5_rKind*(zsu(i,j)-s%zs(i,j)) *ddxz(i) 00818 dzs_w = .0_rKind 00819 else 00820 dzs_e = .0_rKind 00821 dzs_w = .0_rKind 00822 endif 00823 00824 if (s%wetV(i,j)*s%wetV(i,j-1) == 1) then 00825 dzs_s = .5_rKind*(zsv(i,j)-zsv(i,j-1))*ddyz(j) 00826 dzs_n = dzb_s 00827 elseif (s%wetV(i ,j ) == 0) then 00828 dzs_s = .0_rKind 00829 dzs_n = .5_rKind*(s%zs(i,j)-zsv(i,j-1))*ddyz(j) 00830 elseif (s%wetV(i ,j-1) == 0) then 00831 dzs_s = .5_rKind*(zsv(i,j)-s%zs(i,j)) *ddyz(j) 00832 dzs_n = .0_rKind 00833 else 00834 dzs_e = .0_rKind 00835 dzs_w = .0_rKind 00836 endif 00837 00838 s%ws(i,j) = - (s%hu(i,j)*s%uu(i,j)-s%hu(i-1,j )*s%uu(i-1,j ))*ddxz(i) & 00839 - (s%hv(i,j)*s%vv(i,j)-s%hv(i ,j-1)*s%vv(i ,j-1))*ddyz(j) & 00840 + dzs_e*s%uu(i,j)+dzs_w*s%uu(i-1,j) & 00841 + dzs_s*s%vv(i,j)+dzs_n*s%vv(i,j-1) 00842 endif 00843 enddo 00844 enddo 00845 00846 do j=jmin_zs,jmax_zs 00847 do i=imin_zs,imax_zs 00848 if (nonhZ(i,j) == 1) then 00849 s%wb(i,j) = awbr(i,j) + dp(i , j) * awb(1,i,j) & 00850 + dp(i-1,j) * awb(2,i,j) + dp(i+1,j ) * awb(3,i,j) & 00851 + dp(i ,j-1)* awb(4,i,j) + dp(i ,j+1) * awb(5,i,j) 00852 else 00853 if (s%wetU(i,j)*s%wetU(i-1,j) == 1) then 00854 dzb_e = .5_rKind*(zbu(i,j)-zbu(i-1,j))*ddxz(i) 00855 dzb_w = dzs_e 00856 elseif (s%wetU(i ,j) == 0) then 00857 dzb_e = .0_rKind 00858 dzb_w = .5_rKind*(s%zb(i,j)-zbu(i-1,j))*ddxz(i) 00859 elseif (s%wetU(i-1,j) == 0) then 00860 dzb_e = .5_rKind*(zbu(i,j)-s%zb(i,j)) *ddxz(i) 00861 dzb_w = .0_rKind 00862 else 00863 dzb_e = .0_rKind 00864 dzb_w = .0_rKind 00865 endif 00866 00867 if (s%wetV(i,j)*s%wetV(i,j-1) == 1) then 00868 dzb_s = .5_rKind*(zbv(i,j)-zbv(i,j-1))*ddyz(j) 00869 dzb_n = dzb_s 00870 elseif (s%wetV(i ,j ) == 0) then 00871 dzb_s = .0_rKind 00872 dzb_n = .5_rKind*(s%zb(i,j)-zbv(i,j-1))*ddyz(j) 00873 elseif (s%wetV(i ,j-1) == 0) then 00874 dzb_s = .5_rKind*(zbv(i,j)-s%zb(i,j)) *ddyz(j) 00875 dzb_n = .0_rKind 00876 else 00877 dzb_e = .0_rKind 00878 dzb_w = .0_rKind 00879 endif 00880 00881 s%wb(i,j) = + dzb_e*s%uu(i,j)+dzb_w*s%uu(i-1,j) & 00882 + dzb_s*s%vv(i,j)+dzb_n*s%vv(i,j-1) 00883 endif 00884 enddo 00885 enddo 00886 #ifdef USEMPI 00887 call xmpi_shift_ee(s%wb) 00888 call xmpi_shift_ee(s%ws) 00889 if (xmpi_istop) then 00890 s%wb(1,:) = s%wb(2,:) 00891 endif 00892 if (xmpi_isbot) then 00893 s%ws(s%nx+1,:) = s%ws(s%nx,:) 00894 s%wb(s%nx+1,:) = s%wb(s%nx,:) 00895 endif 00896 if (xmpi_isleft) then 00897 s%ws(:,1) = s%ws(:,2) 00898 s%wb(:,1) = s%wb(:,2) 00899 endif 00900 if (xmpi_isright) then 00901 s%wb(:,s%ny+1) = s%wb(:,s%ny) 00902 s%ws(:,s%ny+1) = s%ws(:,s%ny) 00903 endif 00904 #else 00905 !Assign boundaries 00906 s%ws(:,1) = s%ws(:,2) 00907 s%ws(:,s%ny+1) = s%ws(:,s%ny) 00908 !s%ws(1,:) = s%ws(2,:) 00909 s%ws(s%nx+1,:) = s%ws(s%nx,:) 00910 00911 s%wb(:,1) = s%wb(:,2) 00912 s%wb(:,s%ny+1) = s%wb(:,s%ny) 00913 s%wb(1,:) = s%wb(2,:) 00914 s%wb(s%nx+1,:) = s%wb(s%nx,:) 00915 #endif 00916 endif 00917 00918 Wm_old = .5_rKind*(s%ws+s%wb) 00919 end subroutine nonh_1lay_cor 00920 00921 subroutine nonh_1lay_pred(s,par) 00922 !============================================================================== 00923 ! 00924 00925 ! DATE AUTHOR CHANGES 00926 ! 00927 ! November 2010 Pieter Bart Smit New Subroutine 00928 00929 00930 !------------------------------------------------------------------------------ 00931 ! DECLARATIONS 00932 !------------------------------------------------------------------------------ 00933 00934 !-------------------------- PURPOSE ---------------------------- 00935 ! 00936 ! Include the pressure explicitly in the predictor step 00937 ! 00938 !-------------------------- DEPENDENCIES ---------------------------- 00939 use spaceparams 00940 use params, only: parameters 00941 use flow_secondorder_module, only: flow_secondorder_advw 00942 !-------------------------- ARGUMENTS ---------------------------- 00943 00944 type(spacepars) ,intent(inout) :: s 00945 type(parameters),intent(in) :: par 00946 00947 !-------------------------- LOCAL VARIABLES ---------------------------- 00948 00949 !Indices 00950 integer(kind=iKind) :: i,ie,iee,iw !Index variables 00951 integer(kind=iKind) :: j,js 00952 integer(kind=iKind) :: jmin,jmax 00953 00954 real(kind=rKind) :: dwdx1 !Gradient of vertical velocity in x-dir at i+1/2,j 00955 real(kind=rKind) :: dwdx2 !Gradient of vertical velocity in x-dir at i-1/2,j 00956 real(kind=rKind) :: dwdy1 !Gradient of vertical velocity in x-dir at i ,j+1/2 00957 real(kind=rKind) :: dwdy2 !Gradient of vertical velocity in x-dir at i ,j-1/2 00958 real(kind=rKind) :: Vol 00959 real(kind=rKind) :: wmax,reformfac 00960 00961 if (.not. initialized) then 00962 call nonh_init(s,par) 00963 endif 00964 00965 if (s%ny>0) then 00966 jmin = 2 00967 jmax = s%ny 00968 else 00969 jmin = 1 00970 jmax = 1 00971 endif 00972 00973 ! 00974 ! Determine whether or not to use the nh correction method (dry/wet/breaking etc.) 00975 ! 00976 if(par%useXBeachGSettings==0 .or. par%nhbreaker<=1) then 00977 call nonh_break( s , par ) 00978 else 00979 ! (1) The point is dry 00980 ! (2) The relative wave length kd of the smallest possible wave (L=2dx) is smaller than kdmin 00981 ! (3) The interpolated waterlevel zs is below the bottom (steep cliffs with overwash situations) 00982 ! (4) Where Miche breaker criterium applies -> bores are hydrostatic 00983 ! max steepness = H/L = maxbrsteep 00984 ! dz/dx = maxbrsteep 00985 ! dz/dx = dz/dt/c = w/c = w/sqrt(gh) 00986 ! wmax = maxbrsteep*sqrt(gh) 00987 do j=1,s%ny+1 00988 do i=1,s%nx+1 00989 iw = max(i,i-1) 00990 ie = min(s%nx,i+1) 00991 iee = min(s%nx,i+2) 00992 00993 if ( (s%wetU(i,j)==1 ) & 00994 .and. (0.5_rKind*(s%zs(i,j) + s%zs(ie,j)) > zbu(i,j) ) & 00995 .and. ( s%dsu(i,1)*par%kdmin/par%px < s%hum(i,j) ) ) then 00996 nonhU(i,j) = 1 00997 else 00998 nonhU(i,j) = 0 00999 endif 01000 enddo 01001 enddo 01002 01003 if (s%ny>2) then 01004 do j=1,s%ny+1 01005 js = min(s%ny,j+1) 01006 do i=1,s%nx+1 01007 if ( (s%wetV(i,j)==1 ) & 01008 .and. (0.5_rKind*(s%zs(i,j) + s%zs(i,js)) > zbv(i,j) ) & 01009 .and. ( s%dnv(1,j)*par%kdmin/par%px < s%hvm(i,j) ) ) then 01010 nonhV(i,j) = 1 01011 else 01012 nonhV(i,j) = 0 01013 endif 01014 enddo 01015 enddo 01016 else 01017 nonhV = 0 01018 endif 01019 ! 01020 ! Determine if a velocity point will be included in the nonh pressure matrix, include if 01021 ! any of the surrounding velocity points is included. 01022 ! 01023 if (s%ny>0) then 01024 do j=2,s%ny 01025 do i=2,s%nx 01026 if (max(nonhV(i,j),nonhV(i,j-1),nonhU(i,j),nonhU(i-1,j)) > 0) then 01027 nonhZ(i,j) = 1 01028 else 01029 nonhZ(i,j) = 0 01030 endif 01031 enddo 01032 enddo 01033 else 01034 do i=2,s%nx 01035 if (max(nonhU(i,1),nonhU(i-1,1)) > 0) then 01036 nonhZ(i,1) = 1 01037 else 01038 nonhZ(i,1) = 0 01039 endif 01040 enddo 01041 endif 01042 01043 if (par%nhbreaker == 2) then 01044 ! First determine local breaker criterion 01045 lbreakcond = par%maxbrsteep 01046 if (s%ny==0) then 01047 do i=2,s%nx 01048 if (s%breaking(i,1)==1) then 01049 lbreakcond(i-1:i+1,1) = par%secbrsteep 01050 endif 01051 enddo 01052 else 01053 do j=jmin,jmax 01054 do i=2,s%nx 01055 if (s%breaking(i,j)==1) then 01056 lbreakcond(i-1:i+1,j-1:j+1) = par%secbrsteep 01057 endif 01058 enddo 01059 enddo 01060 endif 01061 #ifdef USEMPI 01062 call xmpi_shift_ee(lbreakcond) 01063 #endif 01064 ! Now find areas where main breaking criterion is exceeded 01065 do j=jmin,jmax 01066 do i=2,s%nx 01067 if (s%breaking(i,j)==1) then 01068 if(s%ws(i,j)<=0.d0) then 01069 s%breaking(i,j) = 0 01070 endif 01071 else 01072 wmax = lbreakcond(i,j)*sqrt(par%g*s%hh(i,j)) ! add current term in here too 01073 if (s%ws(i,j)>=wmax) then 01074 s%breaking(i,j) = 1 01075 endif 01076 endif 01077 enddo 01078 enddo 01079 ! turn off non-hydrostatic pressure correction in areas with breaking and increase viscosity 01080 do j=jmin,jmax 01081 do i=2,s%nx 01082 if (s%breaking(i,j)==1) then 01083 nonhZ(i,j) = 0 01084 s%pres(i,j) = 0.d0 01085 endif 01086 enddo 01087 enddo 01088 elseif (par%nhbreaker == 3) then 01089 ! First determine local breaker criterion 01090 lbreakcond = par%maxbrsteep 01091 if (s%ny==0) then 01092 do i=2,s%nx 01093 if (s%breaking(i,1)==1) then 01094 lbreakcond(i-1:i+1,1) = par%secbrsteep 01095 endif 01096 enddo 01097 else 01098 do j=jmin,jmax 01099 do i=2,s%nx 01100 if (s%breaking(i,j)==1) then 01101 lbreakcond(i-1:i+1,j-1:j+1) = par%secbrsteep 01102 endif 01103 enddo 01104 enddo 01105 endif 01106 ! Now find areas where main breaking criterion is exceeded 01107 do j=jmin,jmax 01108 do i=2,s%nx 01109 s%wscrit(i,j) = lbreakcond(i,j)*sqrt(par%g*s%hh(i,j)) ! add current term in here too 01110 if (s%breaking(i,j)==1) then 01111 if(s%ws(i,j)<=s%wscrit(i,j)) then 01112 s%breaking(i,j) = 0 01113 endif 01114 else 01115 if (s%ws(i,j)>=s%wscrit(i,j)) then 01116 s%breaking(i,j) = 1 01117 endif 01118 endif 01119 enddo 01120 enddo 01121 ! turn off non-hydrostatic pressure correction in areas with breaking and increase viscosity 01122 do j=jmin,jmax 01123 do i=2,s%nx 01124 if (s%breaking(i,j)==1) then 01125 nonhZ(i,j) = 0 01126 s%pres(i,j) = 0.d0 01127 endif 01128 enddo 01129 enddo 01130 endif 01131 endif 01132 01133 !Calculate explicit part average vertical momentum (advection) 01134 if (s%ny>0) then 01135 do j=2,s%ny 01136 do i=2,s%nx 01137 if (nonhZ(i,j) == 1) then 01138 Wm(i,j) = Wm_old(i,j) - par%dt*( ddxu(i-1)*max(s%qx(i-1,j ),0.0_rKind)*(Wm_old(i ,j ) & 01139 - Wm_old(i-1,j ))/s%hh(i,j) & 01140 + ddxu(i) *min(s%qx(i ,j ),0.0_rKind)*(Wm_old(i+1,j )-Wm_old(i ,j ))/s%hh(i,j) & 01141 + ddyv(j-1)*max(s%qy(i ,j-1),0.0_rKind)*(Wm_old(i ,j )-Wm_old(i ,j-1))/s%hh(i,j) & 01142 + ddyv(j )*min(s%qy(i ,j ),0.0_rKind)*(Wm_old(i ,j+1)-Wm_old(i ,j ))/s%hh(i,j) ) 01143 else 01144 Wm(i,j) = 0.0_rKind 01145 Wm_old(i,j) = 0.0_rKind 01146 s%ws(i,j) = 0.0_rKind 01147 s%wb(i,j) = 0.0_rKind 01148 s%pres(i,j) = 0.0_rKind 01149 endif 01150 enddo 01151 enddo 01152 else 01153 do i=2,s%nx 01154 if (nonhZ(i,1) == 1) then 01155 Wm(i,1) = Wm_old(i,1) - par%dt*( ddxu(i-1)*max(s%qx(i-1,1 ),0.0_rKind)*(Wm_old(i ,1 ) & 01156 -Wm_old(i-1,1 ))/s%hh(i,1) & 01157 + ddxu(i) *min(s%qx(i ,1 ),0.0_rKind)*(Wm_old(i+1,1 )-Wm_old(i ,1 ))/s%hh(i,1) ) 01158 else 01159 Wm(i,1) = 0.0_rKind 01160 Wm_old(i,1) = 0.0_rKind 01161 s%ws(i,1) = 0.0_rKind 01162 s%wb(i,1) = 0.0_rKind 01163 s%pres(i,1) = 0.0_rKind 01164 endif 01165 enddo 01166 endif 01167 01168 !Calculate explicit part vertical viscocity 01169 if (s%ny>0) then 01170 do j=2,s%ny 01171 do i=2,s%nx 01172 dwdx1 = .5d0*(s%nuh(i-1,j )+s%nuh(i,j ))*s%hu(i-1,j )*(Wm_old(i ,j )-Wm_old(i-1,j ))*ddxu(i-1) 01173 dwdx2 = .5d0*(s%nuh(i+1,j )+s%nuh(i,j ))*s%hu(i ,j )*(Wm_old(i+1,j )-Wm_old(i ,j ))*ddxu(i) 01174 dwdy1 = s%nuh(i ,j-1)*s%hu(i ,j-1)*(Wm_old(i ,j )-Wm_old(i ,j-1))*ddyv(j-1) 01175 dwdy2 = s%nuh(i ,j )*s%hu(i ,j )*(Wm_old(i ,j+1)-Wm_old(i ,j ))*ddyv(j) 01176 Wm(i,j) = Wm(i,j) + (1.0_rKind/s%hh(i,j))*par%dt*(dwdx2-dwdx1)*ddxz(i)*real(s%wetu(i,j)*s%wetu(i-1,j),rKind) 01177 + (1.0_rKind/s%hh(i,j))*par%dt*(dwdy2-dwdy1)*ddyz(j)*real(s%wetv(i,j)*s%wetv(i,j-1),rKind) 01178 enddo 01179 enddo 01180 else 01181 do i=2,s%nx 01182 dwdx1 = .5d0*(s%nuh(i-1,1 )+s%nuh(i,1 ))*s%hu(i-1,1 )*(Wm_old(i ,1 )-Wm_old(i-1,1 ))*ddxu(i-1) 01183 dwdx2 = .5d0*(s%nuh(i+1,1 )+s%nuh(i,1 ))*s%hu(i ,1 )*(Wm_old(i+1,1 )-Wm_old(i ,1 ))*ddxu(i) 01184 dwdy1 = 0.d0 01185 dwdy2 = 0.d0 01186 Wm(i,1) = Wm(i,1) + (1.0_rKind/s%hh(i,1))*par%dt*(dwdx2-dwdx1)*ddxz(i)*real(s%wetu(i,1)*s%wetu(i-1,1),rKind) 01187 enddo 01188 endif 01189 01190 do j=jmin,jmax 01191 do i=2,s%nx 01192 if (nonhU(i,j)==1) then 01193 vol = 0.5_rKind*par%dt/(s%hum(i,j)*dxu(i)) 01194 au(1,i,j) = - (s%zs(i+1,j) - s%zb(i ,j))*vol 01195 au(0,i,j) = + (s%zs(i ,j) - s%zb(i+1,j))*vol 01196 else 01197 au(1,i,j) = 0.0_rKind 01198 au(0,i,j) = 0.0_rKind 01199 endif 01200 enddo 01201 enddo 01202 if (xmpi_istop) then !wwvv: added test on istop 01203 au(:,1,:) = 0.0_rKind 01204 endif 01205 if (xmpi_isbot) then !wwvv: added test on isbot 01206 au(:,s%nx+1,:) = 0.0_rKind 01207 endif 01208 01209 01210 !Built pressure coefficients V 01211 !call timer_start(timer_flow_nonh_av) 01212 if (s%ny>2) then 01213 do j=2,s%ny 01214 do i=2,s%nx 01215 if (nonhV(i,j)==1)then 01216 vol = 0.5_rKind*par%dt/(s%hvm(i,j)*dyv(j)) 01217 av(1,i,j) = -(s%zs(i ,j+1) - s%zb(i ,j ))*vol 01218 av(0,i,j) = +(s%zs(i ,j ) - s%zb(i ,j+1))*vol 01219 avr(i,j) = s%vv(i,j) 01220 else 01221 av(1,i,j) = 0.0_rKind 01222 av(0,i,j) = 0.0_rKind 01223 endif 01224 enddo 01225 enddo 01226 if (xmpi_isleft) then !wwvv: added test on isleft 01227 av(:,:,1) = 0.0_rKind 01228 endif 01229 if (xmpi_isright) then !wwvv: added test on isright 01230 av(:,:,s%ny+1) = 0.0_rKind 01231 endif 01232 endif 01233 01234 !Include explicit approximation for pressure in s%uu and s%vv and Wm 01235 if (par%secorder == 1) then 01236 do j=jmin,jmax 01237 do i=imin_uu,imax_uu 01238 s%uu(i,j) = s%uu(i,j) + au(1,i,j) * s%pres(i+1,j) + au(0,i,j) * s%pres(i ,j) 01239 enddo 01240 enddo 01241 01242 if (s%ny>0) then 01243 do j=jmin_vv,jmax_vv 01244 do i=imin_vv,imax_vv 01245 s%vv(i,j) = s%vv(i,j) + av(1,i,j) * s%pres(i,j+1) + av(0,i,j) * s%pres(i,j ) 01246 enddo 01247 enddo 01248 else 01249 do i=imin_vv,imax_vv 01250 s%vv(i,1) = s%vv(i,1) + av(1,i,1) * s%pres(i,1) + av(0,i,1) * s%pres(i,1 ) 01251 enddo 01252 endif 01253 01254 do j=jmin_zs,jmax_zs 01255 do i=imin_zs,imax_zs 01256 if (nonhZ(i,j) == 1) then 01257 Wm(i,j) = Wm(i,j) + Wcoef(i,j)*par%dt * s%pres(i,j)/s%hh(i,j) 01258 endif 01259 enddo 01260 enddo 01261 call flow_secondorder_advW(s,par,Wm,Wm_old, nonhZ) 01262 endif 01263 01264 end subroutine nonh_1lay_pred 01265 01266 01267 01268 01269 !============================================================================== 01270 ! REDUCED NON-HYDROSTATIC ROUTINES 2DV 01271 !============================================================================== 01272 ! 01273 ! 01274 !============================================================================== 01275 subroutine nonh_2lay_cor_2dV(s,par) 01276 !============================================================================== 01277 ! 01278 01279 ! DATE AUTHOR CHANGES 01280 ! 01281 ! October 2014 Pieter Bart Smit New subroutine 01282 ! 01283 !------------------------------------------------------------------------------- 01284 ! DECLARATIONS 01285 !------------------------------------------------------------------------------- 01286 01287 !-------------------------- PURPOSE ---------------------------- 01288 01289 ! In this subroutine we calculate the nonh-hydrostatic pressures by solving 01290 ! a discrete poisson equation, and subsequently correct the velocity field 01291 ! so that the velocities at the new timelevel are divergence free. 01292 ! 01293 ! This subroutine uses the pressure coeficients calculated previously in 01294 ! the routine nonh_2lay_pred_2dV, and for each of the velocity components all 01295 ! processes have been accounted for (advection, bed-friction etc), including 01296 ! an explict estimation of the nonh press known from the previous timestep 01297 ! (unless we are calculating with first order accuracy). 01298 ! 01299 ! Subsequently we will take the following steps: 01300 ! 01301 ! 1) Calculate the water and bed levels at u-points (subroutine call to zuzv). 01302 ! 2) Built the poisson matrix by substituting the pressure dependencies of the 01303 ! momentum equations into the continuity equation. 01304 ! 3) Solve the resulting system (call to solver_solvemat). 01305 ! 4) Update the non-hydrostatic pressure. If second-order is active, dp is the 01306 ! difference between the old and the new pressure, so in that case we have 01307 ! 01308 ! s%press = s%press + dp 01309 ! 01310 ! else, it represents the new pressure directly, s%press = dp. 01311 ! 5) Correct the velocity components with the nonhydrostatic pressures. The 01312 ! new velocity field will be divergence free. 01313 ! 01314 ! After these steps, control is returned to flow_timestep. 01315 ! 01316 !-------------------------- DEPENDENCIES ---------------------------- 01317 ! 01318 use spaceparams 01319 use params, only: parameters 01320 use solver_module, only: solver_solvemat 01321 use xmpi_module 01322 ! 01323 !-------------------------- ARGUMENTS ---------------------------- 01324 ! 01325 type(spacepars) ,intent(inout) :: s 01326 type(parameters),intent(in) :: par 01327 ! 01328 !-------------------------- LOCAL PARAMETERS ---------------------------- 01329 ! 01330 integer(kind=iKind),parameter :: j = 1 !Index variables 01331 ! 01332 !-------------------------- LOCAL VARIABLES ---------------------------- 01333 ! 01334 01335 !Indices 01336 integer(kind=iKind) :: i,k !Index variables 01337 01338 !Work 01339 real(kind=rKind) :: dzsdx ! Free surface gradient (s-dir) 01340 real(kind=rKind) :: dzbdx ! Bed level gradient (s-dir) 01341 real(kind=rKind) :: alpha ! Parameter controlling how the velocity at the 01342 ! layer interface is determined ( =-wcoef for energy 01343 ! conservative behaviour). 01344 real(kind=rKind) :: alpha_u(0:1) ! The layer distribution parameter interpolated at 01345 ! the east (=1) and west (=0) faces. 01346 real(kind=rKind) :: hfU(0:1) ! Coefficient of the west U(i-1,j) (=0) or east U(i,j) (=1) velocity 01347 ! in the reduced continuity equation. 01348 real(kind=rKind) :: hfdU(0:1) ! Coefficient of the west dU(i-1,j) (=0) or east dU(i,j) (=1) velocity 01349 ! 01350 !------------------------------------------------------------------------------- 01351 ! IMPLEMENTATION 01352 !------------------------------------------------------------------------------- 01353 ! 01354 01355 ! 01356 ! ------ Substitute in the continuity equation ------ 01357 ! 01358 do i=2,s%nx 01359 ! 01360 if (nonhZ(i,j)==1) then 01361 ! 01362 do k = 0,1 01363 ! 01364 alpha_u(k) = .5d0 * (wcoef(i+k,j) + wcoef(i-1+k,j)) 01365 01366 hfU(k) = s%hu(i-1+k ,j) * ( 1.0d0 + alpha_u(k) ) 01367 hfdU(k) = s%hu(i-1+k ,j) * alpha_u(k) * ( 1.0d0 - alpha_u(k) ) 01368 ! 01369 enddo 01370 ! 01371 dzsdx = .5*( zsu(i,j) - zsu(i-1,j) ) 01372 dzbdx = .5*( zbu(i,j) + alpha_u(1) * s%hu(i,j) - zbu(i-1,j) - alpha_u(0) * s%hu(i-1,j) ) 01373 ! 01374 01375 01376 ! 01377 alpha = -wcoef(i,j) 01378 ! 01379 mat(1,i,j) = 2.0d0* s%dsz(i,j) * aws(1,i,j) & 01380 + hfU( 1)*au( 0,i,j) - hfU( 0)*au(1, i-1,j) & 01381 + hfdU(1)*adU(0,i,j) - hfdU(0)*adU(1,i-1,j) & 01382 - dzsdx * ( au(0,i,j) + au(1,i-1,j) - ( adU(0,i,j) + adU(1,i-1,j) )* wcoef(i,j) ) & 01383 - dzbdx * ( au(0,i,j) + au(1,i-1,j) + ( adU(0,i,j) + adU(1,i-1,j) )* alpha ) 01384 ! 01385 mat(2,i,j) = - hfU( 0)*au (0, i-1,j) - hfdU( 0)*adU(0, i-1,j) & 01386 - dzsdx * ( au(0,i-1,j) - adU(0,i-1,j) * wcoef(i,j) ) & 01387 - dzbdx * ( au(0,i-1,j) + adU(0,i-1,j) * alpha ) 01388 ! 01389 mat(3,i,j) = hfU(1)*au (1,i ,j) + hfdU(1)*adU(1,i,j) & 01390 - dzsdx * ( au(1,i,j) - adU(1,i,j) * wcoef(i,j) ) & 01391 - dzbdx * ( au(1,i,j) + adU(1,i,j) * alpha ) 01392 ! 01393 rhs(i,j) = - 2.0d0 * s%dsz(i,j) * Wm(i,j) & 01394 - hfU( 1)*s%uu( i ,j) + hfU( 0)*s%uu( i-1 ,j) & 01395 - hfdU(1)*s%dU( i ,j) + hfdU(0)*s%dU( i-1 ,j) & 01396 + dzsdx * ( s%uu(i,j) + s%uu(i-1,j) - ( s%dU(i,j) + s%dU(i-1,j) )* wcoef(i,j) ) & 01397 + dzbdx * ( s%uu(i,j) + s%uu(i-1,j) + ( s%dU(i,j) + s%dU(i-1,j) )* alpha ) 01398 else 01399 ! 01400 mat(1 ,i,j) = 1.0_rKind 01401 mat(2:5,i,j) = 0.0_rKind 01402 rhs(i,j) = 0.0_rKind 01403 ! 01404 endif 01405 ! 01406 enddo 01407 01408 ! 01409 !---------------- Solve Linear System ----------------- 01410 ! 01411 dp = 0.0_rKind 01412 call solver_solvemat( mat , rhs , dp , s%nx, s%ny,par) 01413 ! 01414 if (par%secorder == 1) then 01415 ! 01416 s%pres = s%pres + dp 01417 ! 01418 else 01419 ! 01420 s%pres = dp 01421 ! 01422 endif 01423 01424 ! 01425 !------------------ Correct u/v/w ------------------- 01426 ! 01427 !U 01428 do i=2,s%nx-1 01429 ! 01430 s%uu(i,j) = s%uu(i,j) + au(1,i,j)*dp(i+1,j)+au(0,i,j)*dp(i,j) 01431 ! 01432 enddo 01433 01434 !dU 01435 if (par%nhlay > 0. ) then 01436 ! 01437 do i=2,s%nx-1 01438 ! 01439 s%dU(i,j) = s%dU(i,j) + adU(1,i,j)*dp(i+1,j)+adU(0,i,j)*dp(i,j) 01440 ! 01441 enddo 01442 ! 01443 endif 01444 ! 01445 01446 #ifdef USEMPI 01447 ! Communicate velocities 01448 call xmpi_shift_ee(s%uu) 01449 call xmpi_shift_ee(s%dU) 01450 #endif 01451 01452 ! 01453 ! Calculate the surface vertical velocity from the kinematic condition 01454 ! 01455 ! 01456 do i=2,s%nx 01457 ! 01458 if ( s%wetz(i,j)==1 ) then 01459 ! 01460 dzsdx = .5*( zsu(i,j) - zsu(i-1,j ) ) / s%dsz(i,j) 01461 01462 s%ws(i,j) = - (s%hu(i,j)*s%uu(i,j) -s%hu(i-1,j )*s%uu(i-1,j )) / s%dsz(i,j) & 01463 + dzsdx * ( s%uu(i,j) + s%uu(i-1,j ) - ( s%dU(i,j) + s%dU(i-1,j ) ) * wcoef(i,j) ) 01464 ! 01465 else 01466 ! 01467 s%ws(i,j) = 0.0d0 01468 ! 01469 endif 01470 ! 01471 enddo 01472 ! 01473 01474 ! 01475 ! Calculate the bottom velocity from the kinematic condition 01476 ! 01477 ! 01478 do i=2,s%nx 01479 ! 01480 if ( s%wetz(i,j)==1 ) then 01481 ! 01482 dzbdx = .5*( zbu(i,j) - zbu(i-1,j ) ) / s%dsz(i,j) 01483 ! 01484 s%wb(i,j) = + dzbdx * ( s%uu(i,j) + s%uu(i-1,j ) + ( s%dU(i,j) + s%dU(i-1,j ) ) * (1-wcoef(i,j)) ) 01485 ! 01486 else 01487 ! 01488 s%wb(i,j) = 0.0d0 01489 ! 01490 endif 01491 ! 01492 enddo 01493 ! 01494 01495 ! 01496 do i=2,s%nx 01497 ! 01498 ! 01499 if ( nonhZ(i,j) == 1) then 01500 ! 01501 Wm(i,j) = Wm(i,j) + aws(1,i,j)*dp(i,j) 01502 ! 01503 else 01504 ! 01505 Wm(i,j) = 0.0d0 01506 ! 01507 endif 01508 ! 01509 enddo 01510 ! 01511 01512 if (par%nhlay > 0. ) then 01513 ! 01514 01515 do i=2,s%nx 01516 ! 01517 ! 01518 if ( nonhZ(i,j) == 1 ) then 01519 ! 01520 Wm0(i,j) = Wm(i,j) + 0.5d0* ( s%wb(i,j) - s%ws(i,j) ) 01521 ! 01522 else 01523 ! 01524 Wm0(i,j) = 0. 01525 ! 01526 endif 01527 ! 01528 enddo 01529 ! 01530 endif 01531 01532 01533 01534 #ifdef USEMPI 01535 call xmpi_shift_ee(Wm) 01536 call xmpi_shift_ee(s%dU) 01537 01538 if (xmpi_istop) then 01539 Wm(1,:) = Wm(2,:) 01540 endif 01541 if (xmpi_isbot) then 01542 Wm(s%nx+1,:) = Wm(s%nx,:) 01543 endif 01544 #else 01545 !Assign boundaries 01546 Wm(1,:) = Wm(2,:) 01547 Wm(s%nx+1,:) = Wm(s%nx,:) 01548 01549 #endif 01550 01551 ! 01552 ! Calculate the relative vertical advection 01553 ! 01554 do i=2,s%nx 01555 ! 01556 if (s%wetz(i,j) == 1) then 01557 ! 01558 omega(i,j) = - ( s%hu(i ,j) * dU0(i ,j) - s%hu(i-1,j) * dU0(i-1,j) ) / s%dsz( i , j ) 01559 ! 01560 else 01561 ! 01562 omega(i,j) = 0.0d0 01563 ! 01564 endif 01565 ! 01566 enddo 01567 01568 ! 01569 Wm_old = Wm 01570 !s%ws = s%dU 01571 dU0 = s%dU 01572 !1111111 01573 end subroutine nonh_2lay_cor_2dv 01574 01575 ! 01576 subroutine nonh_2lay_pred_2dV(s,par,uu0) 01577 !============================================================================== 01578 ! 01579 01580 ! DATE AUTHOR CHANGES 01581 ! 01582 ! October 2014 Pieter Bart Smit New Subroutine 01583 01584 01585 !------------------------------------------------------------------------------ 01586 ! DECLARATIONS 01587 !------------------------------------------------------------------------------ 01588 01589 !-------------------------- PURPOSE ---------------------------- 01590 ! 01591 ! Include the pressure explicitly in the predictor step. In this subroutine 01592 ! the following steps are taken: 01593 ! 01594 ! 1) Calculate whether or not breaking is active (handled in subroutine 01595 ! nonh_break ). 01596 ! 2) Calculate the coeficients of the nonh. pres. as they occur in the momentum 01597 ! equations. (these are use to calculate the explicit pressure contributions 01598 ! here, and the implicit contributions in the correction routine later). 01599 ! 3) Calculate the first order additional contributions to the advection due to 01600 ! the reduced two-layer formulation (if applicable). 01601 ! 4) Include an explicit estimate for the nonh press. in the momentum equations 01602 ! using the earlier calculated coef. (if second-order approximations for the 01603 ! advection are used, else this step is not necessary). 01604 ! 5) Include the contributions due to internal stress terms and bottom friction 01605 ! in the equation for the velocity difference (implicitly for stability). 01606 ! 01607 ! After these steps, control flows back to flow_timestep, and - if active - 01608 ! second-order approximations are calculated. Consequently, flow_timestep calls 01609 ! nonh_cor again and the nonhydrostatic computations are continued in 01610 ! nonh_2lay_cor. 01611 ! 01612 !-------------------------- DEPENDENCIES ---------------------------- 01613 use spaceparams 01614 use params, only: parameters 01615 use flow_secondorder_module, only: flow_secondorder_advw 01616 !-------------------------- ARGUMENTS ---------------------------- 01617 01618 type(spacepars) ,intent(inout) :: s 01619 type(parameters),intent(in) :: par 01620 real(kind=rkind),dimension(s%nx+1,s%ny+1),intent(in) :: uu0 !The velocity at the previous timestep 01621 01622 !-------------------------- LOCAL PARAMETERS ---------------------------- 01623 01624 integer(kind=iKind), parameter :: j = 1 !Y-index, constant in 1d 01625 01626 !-------------------------- LOCAL VARIABLES ---------------------------- 01627 !General 01628 real(kind=rKind) :: fac !A factor 01629 01630 !Indices 01631 integer(kind=iKind) :: i,k !Loop indices 01632 01633 !Used in calculation of pressure gradients 01634 real(kind=rKind) :: Vol !The volume of a momentum cell 01635 01636 !Used in calculation of advection 01637 real(kind=rKind) :: qx(0:1) !Discharge through the faces of a momentum cell (0: left face 01638 !1: right face) 01639 real(kind=rKind) :: faceval(0:1) !Value of dU at the faces of a momentum cell (0: left face 01640 !1: right face) 01641 01642 !Used in calculation of vertical exchange of momentum 01643 real(kind=rKind) :: fric !Bottom friction coeficient (= dt * cf * |U| / h) 01644 real(kind=rKind) :: stress !Coeficient used in calculation of stress 01645 real(kind=rKind) :: ub !The (Eulerian) velocity at the bottom 01646 real(kind=rKind) :: umag !The (Eulerian) magnitude of the velocity vector at the bottom 01647 real(kind=rKind) :: ve !The eddy viscosity used for vertical mixing 01648 real(kind=rKind) :: advec !Coeficient used in calculation of vertical advection 01649 real(kind=rKind) :: Amat,rhs !The 1*1 "matrix" and RHS of the vertical "system". 01650 01651 !------------------------------------------------------------------------------ 01652 ! IMPLEMENTATION 01653 !------------------------------------------------------------------------------ 01654 01655 ! 01656 ! Determine whether or not to use the nh correction method (dry/wet/breaking etc.) 01657 ! 01658 call nonh_break( s , par ) 01659 call zuzv(s) 01660 ! 01661 ! -- Calculate the pressure dependencies for U -- 01662 ! 01663 do i=2,s%nx 01664 ! 01665 if (nonhU(i,j)==1) then 01666 ! 01667 vol = 0.5d0 * par%dt/(s%hum(i,j)*s%dsu(i,j)) 01668 fac = (s%zb(i+1,j) - s%zb(i ,j)) * vol 01669 ! 01670 au(1,i,j) = - vol * (1.d0 + wcoef(i+1,j) ) * s%hh(i+1,j) - fac 01671 au(0,i,j) = + vol * (1.d0 + wcoef(i ,j) ) * s%hh(i,j) - fac 01672 ! 01673 else 01674 ! 01675 au(1,i,j) = 0.0_rKind 01676 au(0,i,j) = 0.0_rKind 01677 ! 01678 endif 01679 ! 01680 enddo 01681 01682 ! 01683 ! -- Calculate the pressure dependencies for dU -- 01684 ! 01685 01686 if ( par%nhlay > 0. ) then 01687 ! 01688 do i=2,s%nx 01689 ! 01690 if (nonhU(i,j)*(1-s%breaking(i,j))*(1-s%breaking(i-1,j))==1 ) then 01691 ! 01692 vol = 0.5_rKind*par%dt/(s%hum(i,j)*s%dsu(i,j)) 01693 ! 01694 fac = ( s%zs( i+1,j ) - s%zs(i,j) ) * vol / ( 1.0d0 - .5d0*wcoef(i,j) - .5d0*wcoef(i+1,j) ) & 01695 - ( wcoef( i+1,j ) - wcoef(i,j) ) * s%hum(i,j) * vol / (2.0d0 - wcoef(i,j) - wcoef(i+1,j) ) 01696 ! 01697 adU(1,i,j) = - s%hh(i+1,j)*vol + fac 01698 adU(0,i,j) = + s%hh(i,j)*vol + fac 01699 ! 01700 else 01701 ! 01702 adU(1,i,j) = 0.0_rKind 01703 adU(0,i,j) = 0.0_rKind 01704 ! 01705 endif 01706 ! 01707 enddo 01708 ! 01709 endif 01710 01711 ! 01712 ! -- Calculate the pressure dependencies for Wm -- 01713 ! 01714 01715 do i=2,s%nx 01716 ! 01717 01718 if (nonhZ(i,j) == 1) then 01719 ! 01720 aws(1,i,j) = par%dt/( s%hh(i,j) * ( 1.0d0 - wcoef( i , j ) ) ) 01721 ! 01722 else 01723 ! 01724 aws(1,i,j) = 0.0_rKind 01725 ! 01726 endif 01727 enddo 01728 ! 01729 ! 01730 !----------------- Advection Wm (FOU) ------------------- 01731 ! 01732 do i=2,s%nx 01733 ! 01734 if ( nonhZ(i,j) == 1) then 01735 ! 01736 01737 do k = 0,1 01738 ! 01739 qx(k) = ( s%qx(i - 1 + k , j ) ) 01740 01741 if (qx(k) > 0.) then 01742 ! 01743 faceval(k) = Wm_old( i - 1 + k ,j ) * real( nonhZ(i - 1 + k,j) , kind=rKind ) 01744 ! 01745 else 01746 ! 01747 faceval(k) = Wm_old( i + k ,j ) * real( nonhZ(i + k,j) , kind=rKind ) 01748 ! 01749 endif 01750 ! 01751 enddo 01752 01753 fac = par%dt / s%hh(i,j) / s%dsz(i,j) 01754 01755 Wm(i,j) = Wm_old(i,j) + fac * Wm_old(i,j)*( s%qx(i,j) - s%qx(i-1,j) ) - fac*( qx(1) * faceval(1) - qx(0) * faceval(0) ) 01756 ! 01757 else 01758 ! 01759 Wm(i,j) = 0.0_rKind 01760 Wm_old(i,j) = 0.0_rKind 01761 s%pres(i,j) = 0.0_rKind 01762 ! 01763 endif 01764 ! 01765 enddo 01766 ! 01767 !----------------- Advection dU (FOU) ------------------- 01768 ! 01769 if ( par%nhlay > 0. ) then 01770 ! 01771 do i=2,s%nx-1 01772 ! 01773 if ( s%wetu( i,j) == 1) then 01774 ! 01775 do k = 0,1 01776 ! 01777 qx(k) = .5 * ( s%qx(i - 1 + k , j ) + s%qx(i + k , j ) ) 01778 01779 if (qx(k) > 0.) then 01780 ! 01781 faceval(k) = dU0( i - 1 + k , j ) 01782 ! 01783 else 01784 ! 01785 faceval(k) = dU0( i+ k , j ) 01786 ! 01787 endif 01788 ! 01789 enddo 01790 01791 fac = par%dt / s%hum(i,j) / s%dsu(i,j) 01792 01793 s%dU(i,j) = dU0(i,j) + .5 * fac *dU0(i,j) * ( s%qx(i+1,j) - s%qx(i-1,j) ) & 01794 - fac * ( qx(1)*faceval(1) - qx(0)*faceval(0) ) 01795 ! 01796 else 01797 ! 01798 s%dU(i,j) = 0.0 01799 ! 01800 endif 01801 ! 01802 enddo 01803 ! 01804 endif 01805 ! 01806 01807 ! 01808 if (xmpi_istop) then 01809 ! 01810 au(:,1,:) = 0.0_rKind 01811 adU(:,1,:) = 0.0_rKind 01812 ! 01813 endif 01814 ! 01815 if (xmpi_isbot) then 01816 ! 01817 au(:,s%nx,:) = 0.0_rKind 01818 adU(:,s%nx,:) = 0.0_rKind 01819 ! 01820 endif 01821 ! 01822 if (par%nhlay > 0.) then 01823 ! 01824 do i=2,s%nx 01825 ! 01826 if ( nonhZ(i,j) == 1 ) then 01827 ! 01828 ! Vertical advection (First order upwind) 01829 ! 01830 01831 if ( omega(i,j) > 0.) then 01832 ! 01833 s%wm(i,j) = s%wm(i,j) + par%dt * omega(i,j) * wm0(i,j)/s%hh(i,j) * wcoef(i,j) 01834 ! 01835 else 01836 ! 01837 s%wm(i,j) = s%wm(i,j) + par%dt * omega(i,j) * wm_old(i,j)/s%hh(i,j) * wcoef(i,j) 01838 endif 01839 endif 01840 01841 enddo 01842 endif 01843 01844 !Include explicit approximation for pressure in s%uu du and Wm 01845 if (par%secorder == 1) then 01846 ! 01847 do i=2,s%nx-1 01848 ! 01849 s%uu(i,j) = s%uu(i,j) + au(1,i,j) * s%pres(i+1,j) + au(0,i,j) * s%pres(i ,j) 01850 ! 01851 enddo 01852 ! 01853 01854 if ( par%nhlay > 0. ) then 01855 ! 01856 do i=2,s%nx-1 01857 ! 01858 s%dU(i,j) = s%dU(i,j) + adU(1,i,j) * s%pres(i+1,j) + adU(0,i,j) * s%pres(i ,j) 01859 ! 01860 enddo 01861 ! 01862 endif 01863 01864 ! 01865 do i=2,s%nx 01866 ! 01867 Wm(i,j) = Wm(i,j) + aws(1,i,j) * s%pres(i,j) 01868 ! 01869 enddo 01870 ! 01871 01872 #ifdef USEMPI 01873 ! 01874 call xmpi_shift_ee(Wm) 01875 #endif 01876 ! 01877 call flow_secondorder_advW(s,par,Wm,Wm_old, nonhZ) 01878 ! 01879 #ifdef USEMPI 01880 ! 01881 call xmpi_shift_ee(Wm) 01882 ! 01883 #endif 01884 endif 01885 ! 01886 01887 if (par%nhlay > 0.) then 01888 ! 01889 ! 01890 ! 01891 ! 01892 !----------------- Bottom stress, internal stresses and vertical advection ------------------- 01893 ! 01894 ! Integration of these terms occurs 01895 ! implicity to ensure that they do not introduce any additional stability 01896 ! concerns. 01897 ! 01898 ! Moreover, the vertical exchange of momentum due to advection between the 01899 ! layers also influences dU (but not U), so we have 01900 ! 01901 ! the equation reads dU - dU* 01902 ! -------- = dU ( fric + stress ) + s%uu * fric - omega * U_face 01903 ! dt 01904 ! 01905 do i=2,s%nx-1 01906 ! 01907 if ( s%wetu(i,j) == 1 ) then 01908 ! 01909 ! 01910 ! Bottom friction 01911 ! 01912 ub = uu0(i,j) + (1.-par%nhlay) * dU0(i,j) 01913 umag = abs(ub) 01914 fric = par%dt * s%cfu(i,j) * umag / s%hu(i,j) 01915 01916 ! 01917 ! Internal stresses 01918 ! 01919 ve = 1.0e-4 !Vertical eddy viscocity 01920 stress = 2.* par%dt * ve / ( s%hum(i,j)**2 * (par%nhlay - par%nhlay**2) ) 01921 01922 ! 01923 ! Vertical advection 01924 ! 01925 advec = 0.5d0* ( omega(i,j) + omega(i+1,j) )* par%dt / s%hum(i,j) 01926 01927 ! 01928 ! Built rhs/diagonal 01929 ! 01930 fac = 0.5d0*( wcoef(i,j) + wcoef(i+1,j) ) 01931 rhs = s%dU(i,j) - uu0(i,j) * ( fric + advec ) 01932 Amat = 1.0d0 + (1.0d0-fac) * fric + stress & 01933 + (1.0d0 - fac) * max( advec , 0. ) & 01934 - fac * min( advec , 0. ) 01935 01936 ! 01937 ! "Solve" system 01938 ! 01939 s%dU(i,j) = rhs / Amat 01940 ! 01941 endif 01942 ! 01943 enddo 01944 ! 01945 endif 01946 01947 #ifdef USEMPI 01948 ! 01949 call xmpi_shift_ee(s%dU) 01950 call xmpi_shift_ee(s%dV) 01951 ! 01952 #endif 01953 ! 01954 end subroutine nonh_2lay_pred_2dv 01955 01956 01957 !============================================================================== 01958 ! REDUCED NON-HYDROSTATIC ROUTINES 3D 01959 !============================================================================== 01960 ! 01961 01962 01963 ! 01964 !============================================================================== 01965 subroutine nonh_2lay_cor_3d(s,par) 01966 !============================================================================== 01967 ! 01968 01969 ! DATE AUTHOR CHANGES 01970 ! 01971 ! October 2010 Pieter Bart Smit New Subroutine 01972 ! November 2010 Pieter Bart Smit Added explicit prediction for 2nd order scheme 01973 01974 !------------------------------------------------------------------------------- 01975 ! DECLARATIONS 01976 !------------------------------------------------------------------------------- 01977 01978 !-------------------------- PURPOSE ---------------------------- 01979 01980 ! In this subroutine we calculate the nonh-hydrostatic pressures by solving 01981 ! a discrete poisson equation, and subsequently correct the velocity field 01982 ! so that the velocities at the new timelevel are divergence free. 01983 ! 01984 ! This subroutine uses the pressure coeficients calculated previously in 01985 ! the routine nonh_2lay_pred_3d, and for each of the velocity components all 01986 ! processes have been accounted for (advection, bed-friction etc), including 01987 ! an explict estimation of the nonh press known from the previous timestep 01988 ! (unless we are calculating with first order accuracy). 01989 ! 01990 ! Subsequently we will take the following steps: 01991 ! 01992 ! 1) Calculate the water and bed levels at u-points (subroutine call to zuzv). 01993 ! 2) Built the poisson matrix by substituting the pressure dependencies of the 01994 ! momentum equations into the continuity equation. 01995 ! 3) Solve the resulting system (call to solver_solvemat). 01996 ! 4) Update the non-hydrostatic pressure. If second-order is active, dp is the 01997 ! difference between the old and the new pressure, so in that case we have 01998 ! 01999 ! s%press = s%press + dp 02000 ! 02001 ! else, it represents the new pressure directly, s%press = dp. 02002 ! 5) Correct the velocity components with the nonhydrostatic pressures. The 02003 ! new velocity field will be divergence free. 02004 ! 02005 ! After these steps, control is returned to flow_timestep. 02006 ! 02007 !-------------------------- DEPENDENCIES ---------------------------- 02008 use spaceparams 02009 use params, only: parameters 02010 use solver_module, only: solver_solvemat 02011 use xmpi_module 02012 !-------------------------- ARGUMENTS ---------------------------- 02013 02014 type(spacepars) ,intent(inout) :: s 02015 type(parameters),intent(in) :: par 02016 02017 !-------------------------- LOCAL VARIABLES ---------------------------- 02018 02019 !Indices 02020 integer(kind=iKind) :: i,j,k !Index variables 02021 02022 !Work 02023 real(kind=rKind) :: dzsdx ! Free surface gradient (s-dir) 02024 real(kind=rKind) :: dzbdx ! Bed level gradient (s-dir) 02025 real(kind=rKind) :: dzsdy ! Free surface gradient (n-dir) 02026 real(kind=rKind) :: dzbdy ! Bed level gradient (n-dir) 02027 real(kind=rKind) :: alpha ! Parameter controlling how the velocity at the 02028 ! layer interface is determined ( =-wcoef for energy 02029 ! conservative behaviour). 02030 real(kind=rKind) :: alpha_u(0:1) ! The layer distribution parameter interpolated at 02031 ! the east (=1) and west (=0) faces. 02032 real(kind=rKind) :: alpha_v(0:1) ! The layer distribution parameter interpolated at 02033 ! the north (=1) and south (=0) faces. 02034 real(kind=rKind) :: hfU(0:1) ! Coefficient of the west U(i-1,j) (=0) or east U(i,j) (=1) velocity 02035 ! in the reduced continuity equation. 02036 real(kind=rKind) :: hfdU(0:1) ! Coefficient of the west dU(i-1,j) (=0) or east dU(i,j) (=1) velocity 02037 ! difference in the reduced continuity equation. 02038 real(kind=rKind) :: hfV(0:1) ! Coefficient of the south V(i,j-1) (=0) or North V(i,j) (=1) velocity 02039 ! in the reduced continuity equation. 02040 real(kind=rKind) :: hfdV(0:1) ! Coefficient of the south dV(i,j-1) (=0) or North dV(i,j) (=1) velocity 02041 ! difference in the reduced continuity equation. 02042 02043 ! 02044 !------------------------------------------------------------------------------- 02045 ! IMPLEMENTATION 02046 !------------------------------------------------------------------------------- 02047 ! 02048 02049 ! 02050 !Substitute in the continuity equation 02051 ! 02052 do j=2,s%ny 02053 ! 02054 do i=2,s%nx 02055 ! 02056 if (nonhZ(i,j)==1) then 02057 ! 02058 do k = 0,1 02059 ! 02060 alpha_u(k) = .5d0 * (wcoef(i+k,j) + wcoef(i-1+k,j)) 02061 02062 hfU(k) = s%dsdnzi(i,j) * s%dnu(i-1+k,j) * s%hu(i-1+k ,j) * ( 1.0d0 + alpha_u(k) ) 02063 hfdU(k) = s%dsdnzi(i,j) * s%dnu(i-1+k,j) * s%hu(i-1+k ,j) * alpha_u(k) * ( 1.0d0 - alpha_u(k) ) 02064 ! 02065 enddo 02066 02067 do k = 0,1 02068 ! 02069 alpha_v(k) = .5d0 * (wcoef(i,j+k) + wcoef(i,j-1+k)) 02070 02071 hfV(k) = s%dsdnzi(i,j) * s%dsv(i,j-1+k) * s%hv(i,j-1+k ) * ( 1.0d0 + alpha_v(k) ) 02072 hfdV(k) = s%dsdnzi(i,j) * s%dsv(i,j-1+k) * s%hv(i,j-1+k ) * alpha_v(k) * ( 1.0d0 - alpha_v(k) ) 02073 ! 02074 enddo 02075 ! 02076 02077 if (nonhu(i,j)*nonhu(i-1,j) == 1 ) then 02078 ! 02079 dzsdx = .5*( zsu(i,j) - zsu(i-1,j ) ) / s%dsz(i,j) 02080 dzbdx = .5*( zbu(i,j) + alpha_u(1) * s%hu(i,j) - zbu(i-1,j ) - alpha_u(0) * s%hu(i-1,j ) ) / s%dsz(i,j) 02081 ! 02082 else 02083 dzsdx = 0.0d0 02084 dzbdx = 0.0 02085 endif 02086 02087 if (nonhv(i,j)*nonhv(i,j-1) == 1 ) then 02088 ! 02089 dzsdy = .5*( zsv(i,j) - zsv(i ,j-1) ) / s%dnz(i,j) 02090 dzbdy = .5*( zbv(i,j) + alpha_v(1) * s%hv(i,j) - zbv(i ,j-1) - alpha_v(0) * s%hv(i ,j-1) ) / s%dnz(i,j) 02091 else 02092 ! 02093 dzsdy = 0.0d0 02094 dzbdy = 0.0d0 02095 ! 02096 endif 02097 02098 alpha = -wcoef(i,j) 02099 ! 02100 ! Main diagonal ( i,j ) 02101 ! 02102 mat(1,i,j) = 2.0d0 * aws(1,i,j) & 02103 + hfU(1) * au(0, i ,j) - hfU(0) * au(1, i-1,j ) & 02104 + hfV(1) * av(0, i ,j) - hfV(0) * av(1, i ,j-1) & 02105 + hfdU(1) * adU(0,i ,j) - hfdU(0) * adU(1,i-1 ,j ) & 02106 + hfdV(1) * adV(0,i ,j) - hfdV(0) * adV(1,i ,j-1) & 02107 - dzsdx * ( au( 0,i,j) + au( 1,i-1,j ) - ( adU(0,i,j) + adU(1,i-1,j ) ) * wcoef(i,j) ) & 02108 - dzsdy * ( av( 0,i,j) + av( 1,i ,j-1) - ( adV(0,i,j) + adV(1,i ,j-1) ) * wcoef(i,j) ) & 02109 - dzbdx * ( au( 0,i,j) + au( 1,i-1,j ) + ( adU(0,i,j) + adU(1,i-1,j ) ) * alpha ) & 02110 - dzbdy * ( av( 0,i,j) + av( 1,i ,j-1) + ( adV(0,i,j) + adV(1,i ,j-1) ) * alpha ) 02111 ! 02112 ! West diagonal ( i-1,j ) 02113 ! 02114 mat(2,i,j) = - hfU(0) * au (0, i-1,j) & 02115 - hfdU(0) * adU(0, i-1,j) & 02116 - dzsdx * ( au(0,i-1,j) - adU(0,i-1,j) * wcoef(i,j) ) & 02117 - dzbdx * ( au(0,i-1,j) + adU(0,i-1,j) * alpha ) 02118 ! 02119 ! South diagonal (i,j-1 ) 02120 ! 02121 mat(4,i,j) = - hfV(0) * av (0, i,j-1) & 02122 - hfdV(0) * adV(0, i,j-1) & 02123 - dzsdy * ( av(0,i,j-1) - adV(0,i,j-1) * wcoef(i,j) ) & 02124 - dzbdy * ( av(0,i,j-1) + adV(0,i,j-1) * alpha ) 02125 ! 02126 ! East diagonal ( i+1,j ) 02127 ! 02128 mat(3,i,j) = hfU(1) * au (1,i ,j) & 02129 + hfdU(1) * adU(1,i ,j) & 02130 - dzsdx * ( au(1,i,j) - adU(1,i,j) * wcoef(i,j) ) & 02131 - dzbdx * ( au(1,i,j) + adU(1,i,j) * alpha ) 02132 ! 02133 ! North diagonal ( i,j+1 ) 02134 ! 02135 mat(5,i,j) = hfV(1) * av (1,i ,j) & 02136 + hfdV(1) * adV(1,i ,j) & 02137 - dzsdy * ( av(1,i,j) - adV(1,i,j) * wcoef(i,j) ) & 02138 - dzbdy * ( av(1,i,j) + adV(1,i,j) * alpha ) 02139 ! 02140 ! RHS 02141 ! 02142 rhs(i,j) = - 2.0d0 * Wm(i,j) & 02143 - hfU( 1 ) * s%uu( i ,j) + hfU( 0 ) * s%uu( i-1 ,j ) & 02144 - hfdU( 1 ) * s%dU( i ,j) + hfdU( 0 ) * s%dU( i-1 ,j ) & 02145 - hfV( 1 ) * s%vv( i ,j) + hfV( 0 ) * s%vv( i ,j-1) & 02146 - hfdV( 1 ) * s%dV( i ,j) + hfdV( 0 ) * s%dV( i ,j-1) & 02147 + dzsdx * ( s%uu(i,j) + s%uu(i-1,j ) - ( s%dU(i,j) + s%dU(i-1,j ) ) * wcoef(i,j) ) & 02148 + dzsdy * ( s%vv(i,j) + s%vv(i ,j-1) - ( s%dV(i,j) + s%dV(i ,j-1) ) * wcoef(i,j) ) & 02149 + dzbdx * ( s%uu(i,j) + s%uu(i-1,j ) + ( s%dU(i,j) + s%dU(i-1,j ) ) * alpha ) & 02150 + dzbdy * ( s%vv(i,j) + s%vv(i ,j-1) + ( s%dV(i,j) + s%dV(i ,j-1) ) * alpha ) 02151 ! 02152 else 02153 ! 02154 mat(1 ,i,j) = 1.0_rKind 02155 mat(2:5,i,j) = 0.0_rKind 02156 rhs(i,j) = 0.0_rKind 02157 ! 02158 endif 02159 enddo 02160 enddo 02161 02162 !------------------ Solve matrix ----------------- 02163 dp = 0.0_rKind 02164 call solver_solvemat( mat , rhs , dp , s%nx, s%ny,par) 02165 02166 if ( par%secorder == 1 ) then 02167 ! 02168 ! If second-order is active, we are calculating with the pressure difference 02169 ! 02170 s%pres = s%pres + dp 02171 ! 02172 else 02173 ! 02174 s%pres = dp 02175 ! 02176 endif 02177 02178 02179 !Correct u/v/w 02180 02181 !U 02182 do j=jmin_uu,jmax_uu 02183 ! 02184 do i=imin_uu,imax_uu 02185 ! 02186 s%uu(i,j) = s%uu(i,j) + au(1,i,j)*dp(i+1,j)+au(0,i,j)*dp(i,j) 02187 ! 02188 enddo 02189 ! 02190 enddo 02191 02192 !V 02193 do j=jmin_vv,jmax_vv 02194 ! 02195 do i=imin_vv,imax_vv 02196 ! 02197 s%vv(i,j) = s%vv(i,j) + av(1,i,j)*dp(i,j+1)+av(0,i,j)*dp(i,j) 02198 ! 02199 enddo 02200 ! 02201 enddo 02202 ! 02203 02204 ! 02205 if (par%nhlay > 0.) then 02206 ! 02207 !dU 02208 ! 02209 do j=jmin_uu,jmax_uu 02210 ! 02211 do i=imin_uu,imax_uu 02212 ! 02213 s%dU(i,j) = s%dU(i,j) + adU(1,i,j)*dp(i+1,j)+adU(0,i,j)*dp(i,j) 02214 ! 02215 enddo 02216 ! 02217 enddo 02218 ! 02219 !dV 02220 ! 02221 do j=jmin_vv,jmax_vv 02222 ! 02223 do i=imin_vv,imax_vv 02224 ! 02225 s%dV(i,j) = s%dV(i,j) + adV(1,i,j)*dp(i,j+1)+adV(0,i,j)*dp(i,j) 02226 ! 02227 enddo 02228 ! 02229 enddo 02230 ! 02231 endif 02232 ! 02233 02234 ! 02235 ! Communicate results... 02236 ! 02237 #ifdef USEMPI 02238 call xmpi_shift_ee(s%uu) 02239 call xmpi_shift_ee(s%vv) 02240 call xmpi_shift_ee(s%dU) 02241 call xmpi_shift_ee(s%dV) 02242 #endif 02243 02244 ! 02245 ! Calculate the surface vertical velocity from the kinematic condition 02246 ! 02247 do j=jmin_zs,jmax_zs 02248 ! 02249 do i=imin_zs,imax_zs 02250 ! 02251 if ( s%wetz(i,j)==1 ) then 02252 ! 02253 dzsdx = .5*( zsu(i,j) - zsu(i-1,j ) ) / s%dsz(i,j) 02254 dzsdy = .5*( zsv(i,j) - zsv(i ,j-1) ) / s%dnz(i,j) 02255 ! 02256 s%ws(i,j) = - (s%dnu(i,j)*s%hu(i,j)*s%uu(i,j) -s%dnu(i-1,j)*s%hu(i-1,j )*s%uu(i-1,j )) * s%dsdnzi(i,j) & 02257 - (s%dsv(i,j)*s%hv(i,j)*s%vv(i,j) -s%dsv(i,j-1)*s%hv( i,j-1)*s%vv(i ,j-1)) * s%dsdnzi(i,j) & 02258 + dzsdx * ( s%uu(i,j) + s%uu(i-1,j ) - ( s%dU(i,j) + s%dU(i-1,j ) ) * wcoef(i,j) ) & 02259 + dzsdy * ( s%vv(i,j) + s%vv(i ,j-1) - ( s%dV(i,j) + s%dV(i ,j-1) ) * wcoef(i,j) ) 02260 ! 02261 else 02262 ! 02263 s%ws(i,j) = 0.0d0 02264 ! 02265 endif 02266 ! 02267 enddo 02268 ! 02269 enddo 02270 02271 ! 02272 ! Calculate the bottom velocity from the kinematic condition 02273 ! 02274 do j=jmin_zs,jmax_zs 02275 ! 02276 do i=imin_zs,imax_zs 02277 ! 02278 if ( s%wetz(i,j)==1 ) then 02279 ! 02280 dzbdx = .5*( zbu(i,j) - zbu(i-1,j ) ) 02281 dzbdy = .5*( zbv(i,j) - zbv(i ,j-1) ) 02282 02283 s%wb(i,j) = + dzbdx * ( s%uu(i,j) + s%uu(i-1,j ) + ( s%dU(i,j) + s%dU(i-1,j ) ) * (1- wcoef(i,j)) ) / s%dsz(i,j) & 02284 + dzbdy * ( s%vv(i,j) + s%vv(i ,j-1) + ( s%dV(i,j) + s%dV(i ,j-1) ) * (1- wcoef(i,j)) ) / s%dnz(i,j) 02285 ! 02286 else 02287 ! 02288 s%wb(i,j) = 0.0d0 02289 ! 02290 endif 02291 ! 02292 enddo 02293 ! 02294 enddo 02295 02296 ! 02297 ! Calculate the mean vertical velocity in the top layer 02298 ! 02299 do j=jmin_zs,jmax_zs 02300 ! 02301 do i=imin_zs,imax_zs 02302 ! 02303 if ( nonhZ(i,j) == 1) then 02304 ! 02305 Wm(i,j) = Wm(i,j) + aws(1,i,j)*dp(i,j) 02306 ! 02307 else 02308 ! 02309 Wm(i,j) = 0.0d0 02310 ! 02311 endif 02312 ! 02313 enddo 02314 ! 02315 enddo 02316 02317 ! 02318 ! Calculate the relative vertical advection 02319 ! 02320 do j=jmin_zs,jmax_zs 02321 ! 02322 do i=imin_zs,imax_zs 02323 ! 02324 if (s%wetz(i,j)==1) then 02325 ! 02326 omega(i,j) = - ( s%dnu(i,j) * s%hu(i ,j) * dU0(i ,j) - s%dnu(i-1,j) * s%hu(i-1,j) * dU0(i-1,j) & 02327 + s%dsv(i,j) * s%hv(i ,j) * dV0(i ,j) - s%dsv(i,j-1) * s%hv(i,j-1) * dV0(i,j-1) ) * s%dsdnzi( i , j ) 02328 ! 02329 else 02330 ! 02331 omega(i,j) = 0.0d0 02332 ! 02333 endif 02334 ! 02335 enddo 02336 ! 02337 enddo 02338 02339 ! 02340 ! Calculate the mean vertical velocity in the lower layer 02341 ! 02342 do j=jmin_zs,jmax_zs 02343 ! 02344 do i=imin_zs,imax_zs 02345 ! 02346 ! 02347 if ( s%wetz(i,j)==1 ) then 02348 ! 02349 Wm0(i,j) = Wm(i,j) + .5d0 * ( s%wb(i,j) - s%ws(i,j) ) 02350 ! 02351 else 02352 ! 02353 Wm0(i,j) = 0. 02354 ! 02355 endif 02356 ! 02357 enddo 02358 ! 02359 enddo 02360 02361 02362 #ifdef USEMPI 02363 if (xmpi_istop) then 02364 Wm(1,:) = Wm(2,:) 02365 endif 02366 if (xmpi_isbot) then 02367 Wm(s%nx+1,:) = Wm(s%nx,:) 02368 endif 02369 if (xmpi_isleft) then 02370 Wm(1,:) = Wm(2,:) 02371 endif 02372 if (xmpi_isright) then 02373 Wm(:,s%ny+1) = Wm(:,s%ny) 02374 endif 02375 ! 02376 call xmpi_shift_ee(Wm) 02377 ! 02378 #else 02379 !Assign boundaries 02380 Wm(1,:) = Wm(2,:) 02381 Wm(s%nx+1,:) = Wm(s%nx,:) 02382 Wm(:,1) = Wm(:,2) 02383 Wm(:,s%ny+1) = Wm(:,s%ny) 02384 02385 #endif 02386 Wm_old = Wm 02387 dU0 = s%dU 02388 dV0 = s%dV 02389 ! 02390 end subroutine nonh_2lay_cor_3d 02391 02392 02393 subroutine nonh_2lay_pred_3d(s,par,uu0,vv0) 02394 !============================================================================== 02395 ! 02396 02397 ! DATE AUTHOR CHANGES 02398 ! 02399 ! October 2014 Pieter Bart Smit New Subroutine 02400 02401 02402 !------------------------------------------------------------------------------ 02403 ! DECLARATIONS 02404 !------------------------------------------------------------------------------ 02405 02406 !-------------------------- PURPOSE ---------------------------- 02407 ! 02408 ! Include the pressure explicitly in the predictor step. In this subroutine 02409 ! the following steps are taken: 02410 ! 02411 ! 1) Calculate whether or not breaking is active (handled in subroutine 02412 ! nonh_break ). 02413 ! 2) Calculate the coeficients of the nonh. pres. as they occur in the momentum 02414 ! equations. (these are use to calculate the explicit pressure contributions 02415 ! here, and the implicit contributions in the correction routine later). 02416 ! 3) Calculate the first order additional contributions to the advection due to 02417 ! the reduced two-layer formulation (if applicable). 02418 ! 4) Include an explicit estimate for the nonh press. in the momentum equations 02419 ! using the earlier calculated coef. (if second-order approximations for the 02420 ! advection are used, else this step is not necessary). 02421 ! 5) Include the contributions due to internal stress terms and bottom friction 02422 ! in the equation for the velocity difference (implicitly for stability). 02423 ! 02424 ! After these steps, control flows back to flow_timestep, and - if active - 02425 ! second-order approximations are calculated. Consequently, flow_timestep calls 02426 ! nonh_cor again and the nonhydrostatic computations are continued in 02427 ! nonh_2lay_cor. 02428 ! 02429 !-------------------------- DEPENDENCIES ---------------------------- 02430 use spaceparams 02431 use params, only: parameters 02432 use flow_secondorder_module, only: flow_secondorder_advw 02433 !-------------------------- ARGUMENTS ---------------------------- 02434 02435 type(spacepars) ,intent(inout) :: s 02436 type(parameters),intent(in) :: par 02437 real(kind=rkind),dimension(s%nx+1,s%ny+1),intent(in) :: uu0 02438 real(kind=rkind),dimension(s%nx+1,s%ny+1),intent(in) :: vv0 02439 02440 !-------------------------- VARIABLES ---------------------------- 02441 02442 !General 02443 real(kind=rKind) :: Fac !A factor 02444 02445 !Indices 02446 integer(kind=iKind) :: i,j,k !Loop indices 02447 02448 !Used in calculation of pressure gradients 02449 real(kind=rKind) :: Vol !The volume of a momentum cell 02450 02451 !Used in calculation of advection dU/dV/Wm 02452 real(kind=rKind) :: qx(0:1) !Discharge through the faces of a momentum cell (0: left face 02453 !1: right face) 02454 real(kind=rKind) :: qy(0:1) !Discharge through the faces of a momentum cell (0: bottom face 02455 !1: top face) 02456 real(kind=rKind) :: faceval_x(0:1) !Value of dU at the faces of a momentum cell (0: left face 02457 !1: right face) 02458 real(kind=rKind) :: faceval_y(0:1) !Value of dU at the faces of a momentum cell (0: left face 02459 !1: right face) 02460 real(kind=rKind) :: DU_face 02461 real(kind=rKind) :: DV_face 02462 real(kind=rKind) :: cosd,sind !cosine or sine of the difference angle 02463 real(kind=rKind) :: sig(0:1) !sign function 02464 02465 !Used in calculation of vertical exchange of momentum 02466 real(kind=rKind) :: fric !Bottom friction coeficient (= dt * cf * |U| / h) 02467 real(kind=rKind) :: stress !Coeficient used in calculation of stress 02468 real(kind=rKind) :: ub !The (Eulerian) u-velocity at the bottom 02469 real(kind=rKind) :: vb !The (Eulerian) v-velocity at the bottom 02470 real(kind=rKind) :: umag !The (Eulerian) magnitude of the velocity vector at the bottom 02471 real(kind=rKind) :: ve !The eddy viscosity used for vertical mixing 02472 real(kind=rKind) :: advec !Coeficient used in calculation of vertical advection 02473 real(kind=rKind) :: Amat,rhs !The 1*1 "matrix" and RHS of the vertical "system". 02474 02475 !------------------------------------------------------------------------------ 02476 ! IMPLEMENTATION 02477 !------------------------------------------------------------------------------ 02478 02479 ! 02480 ! Determine whether or not to use the nh correction method (dry/wet/breaking etc.) 02481 ! 02482 call nonh_break( s , par ) 02483 call zuzv(s) 02484 02485 ! 02486 ! Calculate the pressure dependencies for U 02487 ! 02488 do j=2,s%ny 02489 ! 02490 do i=1,s%nx 02491 ! 02492 if (nonhU(i,j)==1) then 02493 ! 02494 vol = 0.5d0 * par%dt/(s%hum(i,j)*s%dsu(i,j)) 02495 Fac = (s%zb(i+1,j) - s%zb(i ,j)) * vol 02496 au(1,i,j) = - vol * (1.d0 + wcoef(i,j) ) * s%hh(i+1,j) - Fac 02497 au(0,i,j) = + vol * (1.d0 + wcoef(i,j) ) * s%hh(i,j) - Fac 02498 ! 02499 else 02500 ! 02501 au(1,i,j) = 0.0_rKind 02502 au(0,i,j) = 0.0_rKind 02503 ! 02504 endif 02505 ! 02506 enddo 02507 ! 02508 enddo 02509 ! 02510 ! Calculate the pressure dependencies for V 02511 ! 02512 do j=1,s%ny 02513 ! 02514 do i=2,s%nx 02515 ! 02516 if (nonhV(i,j)==1) then 02517 ! 02518 vol = 0.5d0 * par%dt/(s%hvm(i,j)*s%dnv(i,j)) 02519 Fac = (s%zb(i,j+1) - s%zb(i ,j)) * vol 02520 av(1,i,j) = - vol * (1.d0 + wcoef(i,j+1) ) * s%hh(i,j+1) - Fac 02521 av(0,i,j) = + vol * (1.d0 + wcoef(i,j ) ) * s%hh(i,j) - Fac 02522 ! 02523 else 02524 ! 02525 av(1,i,j) = 0.0_rKind 02526 av(0,i,j) = 0.0_rKind 02527 ! 02528 endif 02529 ! 02530 enddo 02531 ! 02532 enddo 02533 02534 if ( par%nhlay > 0.0d0 ) then 02535 ! 02536 ! Calculate the pressure dependencies for dU 02537 ! 02538 do j=2,s%ny 02539 ! 02540 do i=1,s%nx 02541 ! 02542 if (nonhU(i,j)*(1-s%breaking(i,j))*(1-s%breaking(max(i-1,1),j))==1 ) then 02543 ! 02544 vol = 0.5_rKind*par%dt/(s%hum(i,j)*s%dsu(i,j)) 02545 02546 fac = ( s%zs( i+1,j ) - s%zs(i,j) ) * vol / ( 1.0d0 - .5d0*wcoef(i,j) - .5d0*wcoef(i+1,j) ) & 02547 - ( wcoef( i+1,j ) - wcoef(i,j) ) * s%hum(i,j) * vol / (2.0d0 - wcoef(i,j) - wcoef(i+1,j) ) 02548 02549 adU(1,i,j) = - s%hh(i+1,j)*vol + Fac 02550 adU(0,i,j) = + s%hh(i,j)*vol + Fac 02551 ! 02552 else 02553 ! 02554 adU(1,i,j) = 0.0_rKind 02555 adU(0,i,j) = 0.0_rKind 02556 ! 02557 endif 02558 ! 02559 enddo 02560 ! 02561 enddo 02562 ! 02563 ! Calculate the pressure dependencies for dV 02564 ! 02565 do j=1,s%ny 02566 ! 02567 do i=2,s%nx 02568 ! 02569 if (nonhV(i,j)*(1-s%breaking(i,j))*(1-s%breaking(i,max(j-1,1)))==1 ) then 02570 ! 02571 vol = 0.5_rKind*par%dt/(s%hvm(i,j)*s%dnv(i,j)) 02572 fac = ( s%zs( i,j ) - s%zs(i,j+1) ) * vol / ( 1.0d0 - .5d0*wcoef(i,j) - .5d0*wcoef(i,j+1) ) & 02573 - ( wcoef( i,j ) - wcoef(i,j+1) ) * s%hvm(i,j) * vol / (2.0d0 - wcoef(i,j) - wcoef(i,j+1) ) 02574 adV(1,i,j) = - s%hh(i,j+1)*vol + Fac 02575 adV(0,i,j) = + s%hh(i,j)*vol + Fac 02576 ! 02577 else 02578 ! 02579 adV(1,i,j) = 0.0_rKind 02580 adV(0,i,j) = 0.0_rKind 02581 ! 02582 endif 02583 ! 02584 enddo 02585 ! 02586 enddo 02587 ! 02588 endif 02589 02590 ! 02591 !Built pressure coefficients W 02592 ! 02593 do j=2,s%ny 02594 ! 02595 do i=2,s%nx 02596 ! 02597 if (nonhZ(i,j) == 1) then 02598 ! 02599 aws(1,i,j) = par%dt/( s%hh(i,j) * ( 1 - wcoef(i,j) ) ) 02600 ! 02601 else 02602 ! 02603 aws(1,i,j) = 0.0_rKind 02604 ! 02605 endif 02606 ! 02607 enddo 02608 ! 02609 enddo 02610 ! 02611 02612 ! 02613 if (xmpi_istop) then 02614 ! 02615 au(:,1,:) = 0.0_rKind 02616 adU(:,1,:) = 0.0_rKind 02617 ! 02618 endif 02619 ! 02620 if (xmpi_isbot) then 02621 ! 02622 au(:,s%nx,:) = 0.0_rKind 02623 adU(:,s%nx,:) = 0.0_rKind 02624 ! 02625 endif 02626 ! 02627 02628 ! 02629 if (xmpi_isleft) then 02630 ! 02631 av(:,:,1) = 0.0_rKind 02632 adV(:,:,1) = 0.0_rKind 02633 ! 02634 endif 02635 ! 02636 02637 ! 02638 if (xmpi_isright) then 02639 ! 02640 av(:,:,s%ny) = 0.0_rKind 02641 adV(:,:,s%ny) = 0.0_rKind 02642 ! 02643 endif 02644 02645 ! 02646 !----------------- Advection Wm (FOU) ------------------- 02647 ! 02648 ! d ( h U Wm ) d ( h V Wm ) 02649 ! ------------ + ------------ 02650 ! ds dn 02651 ! 02652 ! Advection according to Stelling & Duinmeijer 2003, momentum conservative 02653 ! 02654 do j=jmin_zs,jmax_zs 02655 ! 02656 do i=imin_zs,imax_zs 02657 ! 02658 if ( nonhZ(i,j)==1 ) then 02659 ! 02660 do k = 0,1 02661 ! 02662 qx(k) = s%qx(i - 1 + k , j ) * s%dnu(i - 1 + k , j ) 02663 qy(k) = s%qy(i , j - 1 + k) * s%dsv(i , j - 1 + k ) 02664 02665 if (qx(k) > 0.) then 02666 ! 02667 faceval_x(k) = Wm_old( i - 1 + k ,j ) * real( nonhZ(i - 1 + k,j) , kind=rKind ) 02668 ! 02669 else 02670 ! 02671 faceval_x(k) = Wm_old( i + k ,j ) * real( nonhZ(i + k,j) , kind=rKind ) 02672 ! 02673 endif 02674 02675 if (qy(k) > 0.) then 02676 ! 02677 faceval_y(k) = Wm_old( i ,j - 1 + k ) * real( nonhZ(i,j - 1 + k) , kind=rKind ) 02678 ! 02679 else 02680 ! 02681 faceval_y(k) = Wm_old( i,j + k ) * real( nonhZ(i,j + k) , kind=rKind ) 02682 ! 02683 endif 02684 ! 02685 enddo 02686 02687 fac = par%dt / s%hh(i,j) * s%dsdnzi(i,j) 02688 02689 Wm(i,j) = Wm_old(i,j) + fac * Wm_old(i,j) * ( qx(1) + qy(1) - qx(0) - qy(0) ) & 02690 - fac * ( qx(1) * faceval_x(1) + qy(1) * faceval_y(1) & 02691 - qx(0) * faceval_x(0) - qy(0) * faceval_y(0) ) 02692 ! 02693 else 02694 ! 02695 Wm(i,j) = 0.0_rKind 02696 Wm_old(i,j) = 0.0_rKind 02697 s%pres(i,j) = 0.0_rKind 02698 ! 02699 endif 02700 ! 02701 enddo 02702 ! 02703 enddo 02704 02705 if ( par%nhlay > 0.0d0 ) then 02706 ! 02707 ! 02708 !----------------- Advection dU (FOU) ------------------- 02709 ! 02710 ! d ( h U dU ) d ( h V dU ) 02711 ! ---------- + ---------- 02712 ! dx dy 02713 ! 02714 ! Advection according to Stelling & Duinmeijer 2003, momentum conservative (second term in their equation 24) 02715 ! 02716 sig(0) = -1 02717 sig(1) = 1 02718 ! 02719 do j=jmin_uu,jmax_uu 02720 ! 02721 do i=imin_uu,imax_uu 02722 ! 02723 if ( s%wetu( i,j) == 1) then 02724 ! 02725 ! Calculate transport velocities / face values 02726 ! 02727 do k = 0,1 02728 ! 02729 qx(k) = .5 * ( s%qx(i - 1 + k , j ) + s%qx(i + k , j ) ) * s%dnz(i+k,j) 02730 qy(k) = .5 * ( s%qy(i+1, j - 1 + k ) + s%qy(i, j - 1 + k ) ) * s%dsc(i,j+k) 02731 ! 02732 02733 dv_face = 0.5d0* ( dV0( i + k , j - 1 ) + dV0( i + k , j ) ) 02734 02735 cosd = cos( s%alfau(i+k,j) - s%alfau(i+k-1,j) ) 02736 sind = sig(k)*sin( s%alfau(i+k,j) - s%alfaz(i+k-1,j) ) 02737 ! 02738 if (qx(k) > 0.) then 02739 ! 02740 faceval_x(k) = dU0( i - 1 + k , j ) * cosd + dV_face * sind 02741 ! 02742 else 02743 ! 02744 faceval_x(k) = dU0( i+ k , j ) * cosd + dV_face * sind 02745 ! 02746 endif 02747 ! 02748 02749 ! 02750 cosd = cos( s%alfau(i,j+k-1) - s%alfau(i,j+k) ) 02751 sind = sig(k)*sin( s%alfau(i,j+k-1) - s%alfau(i,j+k) ) 02752 02753 dV_face = 0.5d0* ( dV0( i , j + k - 1) + dV0( i + 1 , j + k - 1 ) ) 02754 if (qy(k) > 0.) then 02755 ! 02756 faceval_y(k) = dU0( i , j -1 + k ) * cosd + dV_face*sind 02757 ! 02758 else 02759 ! 02760 faceval_y(k) = dU0( i , j + k) * cosd + dV_face*sind 02761 ! 02762 endif 02763 ! 02764 enddo 02765 02766 fac = par%dt / s%hum(i,j) * s%dsdnui(i,j) 02767 02768 s%dU(i,j) = dU0(i,j) + fac *dU0(i,j) * ( qx(1) + qy(1) - qx(0) - qy(0) ) & 02769 - fac *( qx(1)*faceval_x(1) + qy(1)*faceval_y(1) & 02770 - qx(0)*faceval_x(0) - qy(0)*faceval_y(0) ) 02771 ! 02772 else 02773 ! 02774 s%dU(i,j) = 0.0 02775 ! 02776 endif 02777 ! 02778 enddo 02779 ! 02780 enddo 02781 02782 ! 02783 !----------------- Advection dV (FOU) ------------------- 02784 ! 02785 ! d ( h V dV ) d ( h U dV ) 02786 ! ---------- + ---------- 02787 ! dy dx 02788 ! 02789 ! 02790 ! Advection according to Stelling & Duinmeijer 2003, momentum conservative (second term in their equation 25) 02791 ! 02792 do j=jmin_vv,jmax_vv 02793 ! 02794 do i=imin_vv,imax_vv 02795 ! 02796 if ( s%wetv( i,j) == 1) then 02797 ! 02798 ! Calculate transport velocities / face values 02799 ! 02800 do k = 0,1 02801 ! 02802 qy(k) = .5 * ( s%qy(i , j- 1 + k ) + s%qy(i , j + k ) ) * s%dsz(i,j+k) 02803 qx(k) = .5 * ( s%qx(i- 1 + k, j +1 ) + s%qx(i - 1 + k , j) ) * s%dnc(i+k,j) 02804 ! 02805 02806 cosd = cos( s%alfav(i+k-1,j) - s%alfav(i+k,j) ) 02807 sind = sig(k)*sin( s%alfav(i+k-1,j) - s%alfav(i+k,j) ) 02808 02809 dU_face = 0.5d0* ( dU0( i - 1 + k , j ) + dU0( i - 1 + k , j +1 ) ) 02810 if (qx(k) > 0.) then 02811 ! 02812 faceval_x(k) = dV0( i- 1 + k, j ) * cosd + dU_face * sind 02813 ! 02814 else 02815 ! 02816 faceval_x(k) = dV0( i + k, j ) *cosd + dU_face * sind 02817 ! 02818 endif 02819 ! 02820 02821 cosd = cos( s%alfav(i,j+k) - s%alfav(i,j+k-1) ) 02822 sind = sig(k)*sin( s%alfav(i,j+k) - s%alfav(i,j+k-1) ) 02823 ! 02824 dU_face = 0.5d0* ( dU0( i - 1 , j + k ) + dU0( i , j + k ) ) 02825 if (qy(k) > 0.) then 02826 ! 02827 faceval_y(k) = dV0( i , j -1 + k ) * cosd+ dU_face * sind 02828 ! 02829 else 02830 ! 02831 faceval_y(k) = dV0( i , j + k) * cosd + dU_face * sind 02832 ! 02833 endif 02834 ! 02835 enddo 02836 02837 fac = par%dt / s%hvm(i,j) * s%dsdnvi(i,j) 02838 02839 s%dV(i,j) = dV0(i,j) + fac *dV0(i,j) * ( qx(1) + qy(1) - qx(0) - qy(0) ) & 02840 - fac *( qx(1)*faceval_x(1) + qy(1)*faceval_y(1) & 02841 - qx(0)*faceval_x(0) - qy(0)*faceval_y(0) ) 02842 ! 02843 else 02844 ! 02845 s%dV(i,j) = 0.0 02846 ! 02847 endif 02848 ! 02849 enddo 02850 ! 02851 enddo 02852 ! 02853 endif 02854 02855 ! 02856 ! ------------- Include explicit approximations -------------------- 02857 ! 02858 if (par%secorder == 1) then 02859 ! 02860 ! Use explicit estimate for the nonhydrostatic pressure in U-momentum 02861 ! 02862 do j=jmin_uu,jmax_uu 02863 ! 02864 do i=imin_uu,imax_uu 02865 ! 02866 s%uu(i,j) = s%uu(i,j) + au(1,i,j) * s%pres(i+1,j) + au(0,i,j) * s%pres(i ,j) 02867 ! 02868 enddo 02869 ! 02870 enddo 02871 ! 02872 ! Use explicit estimate for the nonhydrostatic pressure in V-momentum 02873 ! 02874 do j=jmin_vv,jmax_vv 02875 ! 02876 do i=imin_vv,imax_vv 02877 ! 02878 s%vv(i,j) = s%vv(i,j) + av(1,i,j) * s%pres(i,j+1) + av(0,i,j) * s%pres(i ,j) 02879 ! 02880 enddo 02881 ! 02882 enddo 02883 02884 ! 02885 ! Use explicit estimate for the nonhydrostatic pressure in dU-momentum 02886 ! 02887 if ( par%nhlay > 0.0d0 ) then 02888 ! 02889 do j=jmin_uu,jmax_uu 02890 ! 02891 do i=imin_uu,imax_uu 02892 ! 02893 s%dU(i,j) = s%dU(i,j) + adU(1,i,j) * s%pres(i+1,j) + adU(0,i,j) * s%pres(i ,j) 02894 ! 02895 enddo 02896 ! 02897 enddo 02898 ! 02899 ! Use explicit estimate for the nonhydrostatic pressure in dV-momentum 02900 ! 02901 do j=jmin_vv,jmax_vv 02902 ! 02903 do i=imin_vv,imax_vv 02904 ! 02905 s%dV(i,j) = s%dV(i,j) + adV(1,i,j) * s%pres(i,j+1) + adV(0,i,j) * s%pres(i ,j) 02906 ! 02907 enddo 02908 ! 02909 enddo 02910 ! 02911 endif 02912 ! 02913 ! 02914 ! Use explicit estimate for the nonhydrostatic pressure in Wm-momentum 02915 ! 02916 do j=jmin_zs,jmax_zs 02917 ! 02918 do i=imin_zs,imax_zs 02919 ! 02920 Wm(i,j) = Wm(i,j) + aws(1,i,j) * s%pres(i,j) 02921 ! 02922 enddo 02923 ! 02924 enddo 02925 ! 02926 02927 #ifdef USEMPI 02928 ! 02929 call xmpi_shift_ee(Wm) 02930 #endif 02931 ! 02932 call flow_secondorder_advW(s,par,Wm,Wm_old, nonhZ) 02933 02934 #ifdef USEMPI 02935 call xmpi_shift_ee(Wm) 02936 #endif 02937 ! 02938 endif 02939 02940 ! 02941 if (par%nhlay > 0.) then 02942 ! 02943 ! 02944 ! 02945 ! 02946 !----------------- Bottom stress, internal stresses and vertical advection ------------------- 02947 ! 02948 ! Integration of bottom stress and internal stress terms occurs implicity to ensure that they 02949 ! do not introduce any additional stability concerns. 02950 ! 02951 ! Moreover, the vertical exchange of momentum due to advection between the 02952 ! layers also influences dU (but not U), so we have 02953 ! 02954 ! the equation reads dU - dU* 02955 ! -------- = dU ( fric + stress ) + s%uu * fric - omega * U_face 02956 ! dt 02957 ! To ensure that the system is solvable, we approximate U_face by it's upwind value. 02958 ! 02959 do j=jmin_uu,jmax_uu ! Robert: was do j=2,s%ny-1 02960 ! 02961 do i=imin_uu,imax_uu 02962 ! 02963 if ( s%wetu(i,j) == 1 .and. wcoef(i,j) > 0.0d0 ) then 02964 ! 02965 ! 02966 ! Bottom friction 02967 ! 02968 ub = uu0(i,j) + (1.- wcoef(i,j)) * s%dU(i,j) 02969 vb = s%vu(i,j) + .25 * (1.- wcoef(i,j)) * ( dV0(i,j) + dV0(i+1,j) + dV0(i,j-1) + dV0(i+1,j-1) ) 02970 umag = sqrt( ub**2 + vb**2 ) 02971 fric = par%dt * s%cfu(i,j) * umag / s%hu(i,j) 02972 02973 ! 02974 ! Internal stresses 02975 ! 02976 ve = 0.0001 !Vertical eddy viscocity 02977 stress = 2.* par%dt * ve / ( s%hum(i,j)**2 * (par%nhlay - par%nhlay**2) ) 02978 02979 ! 02980 ! Vertical advection 02981 ! 02982 advec = .5d0 * ( omega(i,j) + omega(i+1,j) ) * par%dt / s%hum(i,j) 02983 02984 ! 02985 ! Built rhs/diagonal 02986 ! 02987 fac = 0.5d0*( wcoef(i,j) + wcoef(i+1,j) ) 02988 rhs = s%dU(i,j) - uu0(i,j) * ( fric + advec ) 02989 02990 Amat = 1.0d0 + (1.0d0-fac) * fric + stress & 02991 + (1.0d0 - fac) * max( advec , 0. ) & 02992 - fac * min( advec , 0. ) 02993 02994 ! 02995 ! "Solve" system 02996 ! 02997 s%dU(i,j) = rhs / Amat 02998 ! 02999 endif 03000 ! 03001 enddo 03002 ! 03003 enddo 03004 ! 03005 03006 ! 03007 do j=jmin_vv,jmax_vv 03008 ! 03009 do i=imin_vv,imax_vv 03010 ! 03011 ! Velocity in the lower layer at u-point 03012 ! 03013 if (s%wetv(i,j) == 1 .and. wcoef(i,j) > 0.0d0 ) then 03014 ! 03015 ! Bottom friction 03016 ! 03017 vb = vv0(i,j) + (1.- wcoef(i,j)) * s%dV(i,j) 03018 ub = s%uv(i,j) + .25 * (1.- wcoef(i,j)) * ( dU0(i,j) + dU0(i,j+1) + dU0(i-1,j) + dU0(i-1,j+1) ) 03019 umag = sqrt( ub**2 + vb**2 ) 03020 fric = par%dt * s%cfu(i,j) * umag / s%hv(i,j) 03021 03022 ! 03023 ! Internal stresses 03024 ! 03025 ve = 0.0001 !Vertical eddy viscocity 03026 stress = 2.* par%dt * ve / ( s%hvm(i,j)**2 * (par%nhlay - par%nhlay**2) ) 03027 03028 ! 03029 ! Vertical advection 03030 ! 03031 advec = .5d0 * ( omega(i,j) + omega(i,j+1) ) * par%dt / s%hvm(i,j) 03032 03033 ! 03034 ! Built rhs/diagonal 03035 ! 03036 fac = 0.5d0*( wcoef(i,j) + wcoef(i+1,j) ) 03037 rhs = s%dV(i,j) - vv0(i,j) * ( fric + advec ) 03038 03039 Amat = 1.0d0 + (1.0d0-fac) * fric + stress & 03040 + (1.0d0 - fac) * max( advec , 0. ) & 03041 - fac * min( advec , 0. ) 03042 03043 ! 03044 ! "Solve" system 03045 ! 03046 s%dV(i,j) = rhs / Amat 03047 ! 03048 endif 03049 ! 03050 enddo 03051 ! 03052 enddo 03053 ! 03054 endif 03055 03056 #ifdef USEMPI 03057 !ARRAYS DU and DV need to be communicated 03058 call xmpi_shift_ee(s%dU) 03059 call xmpi_shift_ee(s%dV) 03060 #endif 03061 ! 03062 end subroutine nonh_2lay_pred_3d 03063 03064 subroutine nonh_break( s , par ) 03065 !-------------------------- PURPOSE ---------------------------- 03066 ! 03067 ! Include the pressure explicitly in the predictor step 03068 ! 03069 !-------------------------- DEPENDENCIES ---------------------------- 03070 use spaceparams 03071 use params 03072 use flow_secondorder_module 03073 use xmpi_module 03074 !-------------------------- ARGUMENTS ---------------------------- 03075 03076 type(spacepars) ,intent(inout) :: s 03077 type(parameters),intent(in) :: par 03078 03079 !-------------------------- LOCAL VARIABLES ---------------------------- 03080 03081 !Indices 03082 integer(kind=iKind) :: i,ie 03083 integer(kind=iKind) :: j,js 03084 integer(kind=iKind) :: jmin,jmax,ineighbour 03085 real(kind=rKind) :: wmax,dzdt 03086 03087 03088 if (s%ny>0) then 03089 jmin = 2 03090 jmax = s%ny 03091 else 03092 jmin = 1 03093 jmax = 1 03094 endif 03095 03096 ! 03097 ! Determine if a velocity point will be included in the nonh pressure matrix, do not include if: 03098 ! 03099 ! (1) The point is dry 03100 ! (2) The relative wave length kd of the smallest possible wave (L=2dx) is smaller than kdmin 03101 ! (3) The interpolated waterlevel zs is below the bottom (steep cliffs with overwash situations) 03102 ! (4) Where Miche breaker criterium applies -> bores are hydrostatic 03103 ! max steepness = H/L = maxbrsteep 03104 ! dz/dx = maxbrsteep 03105 ! dz/dx = dz/dt/c = w/c = w/sqrt(gh) 03106 ! wmax = maxbrsteep*sqrt(gh) 03107 03108 ! 03109 do j=1,s%ny+1 03110 ! 03111 do i=1,s%nx+1 03112 ! 03113 ie = min(s%nx,i+1) 03114 ! 03115 if ( (s%wetU(i,j)==1 ) .and. ( 0.5_rKind*( s%zs(i,j) + s%zs(ie,j) ) > zbu(i,j) ) ) then 03116 ! 03117 nonhU(i,j) = 1 03118 ! 03119 else 03120 ! 03121 nonhU(i,j) = 0 03122 ! 03123 endif 03124 ! 03125 enddo 03126 ! 03127 enddo 03128 03129 ! 03130 if (s%ny>2) then 03131 ! 03132 do j=1,s%ny+1 03133 ! 03134 js = min(s%ny,j+1) 03135 ! 03136 do i=1,s%nx+1 03137 ! 03138 if ( (s%wetV(i,j)==1 ) .and. (0.5_rKind*(s%zs(i,j) + s%zs(i,js)) > zbv(i,j) ) ) then 03139 ! 03140 nonhV(i,j) = 1 03141 ! 03142 else 03143 ! 03144 nonhV(i,j) = 0 03145 ! 03146 endif 03147 ! 03148 enddo 03149 ! 03150 enddo 03151 ! 03152 else 03153 ! 03154 nonhV = 0 03155 ! 03156 endif 03157 ! 03158 ! Determine if a velocity point will be included in the nonh pressure matrix, include if 03159 ! any of the surrounding velocity points is included. 03160 ! 03161 03162 ! 03163 do j=jmin_zs,jmax_zs 03164 ! 03165 js = max( j-1 , 1 ) 03166 ! 03167 do i=imin_zs,imax_zs 03168 ! 03169 if (max( nonhV(i,j) , nonhV(i,js) ,nonhU(i,j), nonhU(i-1,j)) > 0) then 03170 ! 03171 nonhZ(i,j) = 1 03172 ! 03173 else 03174 ! 03175 nonhZ(i,j) = 0 03176 ! 03177 endif 03178 ! 03179 enddo 03180 ! 03181 enddo 03182 ! 03183 03184 if (par%nhbreaker == 1) then 03185 ! 03186 ! Breaking is active 03187 ! 03188 do j = jmin_zs,jmax_zs 03189 ! 03190 js = max( j-1 , 1 ) 03191 ! 03192 do i =imin_zs,imax_zs 03193 ! 03194 dzdt = - ( s%uu(i,j) * s%hu(i,j) - s%uu(i-1,j) * s%hu(i-1,j) ) / s%dsz(i,j) 03195 ! 03196 ineighbour = 0 03197 if ( s%breaking(i-1,j)==1 .or. s%breaking(i+1,j) == 1 ) then 03198 ! 03199 ineighbour = 1 03200 ! 03201 endif 03202 03203 if ( s%ny > 1 ) then 03204 ! 03205 dzdt = dzdt - ( s%vv(i,j) * s%hv(i,j) - s%vv(i,j-1) * s%hv(i,j-1) ) / s%dnz(i,j) 03206 03207 if ( s%breaking(i,j-1) == 1 .or. s%breaking(i,j+1) == 1 ) then 03208 ! 03209 ineighbour = 1 03210 ! 03211 endif 03212 ! 03213 endif 03214 ! 03215 03216 03217 03218 wmax = sqrt(par%g*s%hh(i,j)) 03219 03220 if ( s%breaking(i,j) == 0 ) then 03221 ! 03222 if ( dzdt > par%maxbrsteep*wmax ) then 03223 ! 03224 s%breaking(i,j) = 2 03225 ! 03226 elseif (dzdt > par%reformsteep*wmax .and. ineighbour == 1) then 03227 ! 03228 s%breaking(i,j) = 2 03229 ! 03230 endif 03231 ! 03232 elseif ( s%breaking(i,j) == 1 ) then 03233 ! 03234 if ( dzdt < 0.0d0 ) then 03235 ! 03236 s%breaking(i,j) = -1 03237 ! 03238 endif 03239 ! 03240 endif 03241 ! 03242 enddo 03243 ! 03244 enddo 03245 03246 where (s%breaking==2) 03247 s%breaking = 1 03248 endwhere 03249 03250 where (s%breaking==-1) 03251 s%breaking = 0 03252 endwhere 03253 #ifdef USEMPI 03254 !ARRAYS communication 03255 call xmpi_shift_ee(s%breaking) 03256 #endif 03257 ! turn off non-hydrostatic pressure correction in areas with breaking and increase viscosity 03258 where (s%breaking/=0) 03259 nonhZ = 0 03260 s%pres = 0 03261 endwhere 03262 ! 03263 endif 03264 ! 03265 end subroutine nonh_break 03266 03267 ! 03268 !============================================================================== 03269 subroutine nonh_init_wcoef(s,par) 03270 !============================================================================== 03271 ! 03272 03273 ! DATE AUTHOR CHANGES 03274 ! 03275 ! March 2013 Robert McCall Move computation of wcoef to own function so callable separately 03276 03277 !------------------------------------------------------------------------------- 03278 ! DECLARATIONS 03279 !------------------------------------------------------------------------------- 03280 03281 !-------------------------- PURPOSE ---------------------------- 03282 03283 ! Recompute wcoef optimisation 03284 03285 !-------------------------- DEPENDENCIES ---------------------------- 03286 use spaceparams 03287 use params, only: parameters 03288 use wave_functions_module, only: dispersion 03289 03290 !-------------------------- ARGUMENTS ---------------------------- 03291 03292 type(spacepars) ,intent(in) :: s 03293 type(parameters),intent(in) :: par 03294 03295 !-------------------------- LOCAL VARIABLES ---------------------------- 03296 03297 integer(kind=iKind) :: i,j 03298 real (kind=rKind) :: d,sigma,k 03299 03300 03301 ! 03302 !------------------------------------------------------------------------------- 03303 ! IMPLEMENTATION 03304 !------------------------------------------------------------------------------- 03305 ! 03306 03307 if (allocated(wcoef)) then 03308 if ( par%nonhq3d == 1 ) then 03309 wcoef = par%nhlay 03310 else 03311 sigma = 2.0_rkind*par%px/par%Topt 03312 if (par%dispc <= 0.0_rKind) then 03313 !Calculate the optimum value of the dispersion coeficiant. 03314 do j=1,s%ny+1 03315 do i=1,s%nx+1 03316 d = max(s%zs0(i,j)-s%zb(i,j),par%eps) 03317 k = disper(sigma,d,par%g,2.0_rKind*par%px,0.0001_rKind) 03318 if (d>0.0_rKind) then 03319 wcoef(i,j) = 1.0_rKind / ( 4.0_rKind*par%g / (d*sigma**2) - 4.0_rKind / ((k*d)**2) ) 03320 else 03321 wcoef(i,j) = 1.d0 03322 endif 03323 enddo 03324 enddo 03325 else 03326 wcoef = par%dispc 03327 endif 03328 endif 03329 endif 03330 03331 03332 end subroutine nonh_init_wcoef 03333 ! 03334 03335 03336 03337 03338 subroutine zuzv(s) 03339 !============================================================================== 03340 ! 03341 03342 ! DATE AUTHOR CHANGES 03343 ! 03344 ! November 2010 Pieter Bart Smit New Subroutine 03345 03346 03347 !------------------------------------------------------------------------------ 03348 ! DECLARATIONS 03349 !------------------------------------------------------------------------------ 03350 03351 !-------------------------- PURPOSE ---------------------------- 03352 ! 03353 ! Interpolate bottom and free surface location to u/v points 03354 ! 03355 !-------------------------- DEPENDENCIES ---------------------------- 03356 use spaceparams 03357 use xmpi_module 03358 !-------------------------- ARGUMENTS ---------------------------- 03359 03360 type(spacepars) ,intent(inout) :: s 03361 !-------------------------- LOCAL VARIABLES ---------------------------- 03362 03363 integer(kind=iKind) :: i 03364 integer(kind=iKind) :: j 03365 03366 !------------------------------------------------------------------------------- 03367 ! IMPLEMENTATION 03368 !------------------------------------------------------------------------------- 03369 !Bottom location in U point 03370 do j=1,s%ny+1 03371 do i=1,s%nx 03372 zbu(i,j) = max(s%zb(i,j),s%zb(min(s%nx,i)+1,j)) 03373 enddo 03374 enddo 03375 #ifdef USEMPI 03376 if (xmpi_isbot) then 03377 zbu(s%nx+1,:) = s%zb(s%nx+1,:) 03378 endif 03379 #else 03380 zbu(s%nx+1,:) = s%zb(s%nx+1,:) 03381 #endif 03382 !Bottom location in V point 03383 if (s%ny>2) then 03384 do j=1,s%ny 03385 do i=1,s%nx+1 03386 zbv(i,j) = max(s%zb(i,j),s%zb(i,min(s%ny,j)+1)) 03387 enddo 03388 enddo 03389 zbv(:,s%ny+1) = s%zb(:,s%ny+1) 03390 else 03391 zbv = s%zb 03392 endif 03393 03394 !Free surface location in u-point 03395 do j=1,s%ny+1 03396 do i=1,s%nx 03397 ! 03398 zsu(i,j) = s%hu(i,j) + zbu(i,j) 03399 ! 03400 enddo 03401 enddo 03402 03403 !Free surface location in v-point 03404 if (s%ny>2) then 03405 do j=1,s%ny 03406 do i=1,s%nx+1 03407 zsv(i,j) = s%hv(i,j) + zbv(i,j) 03408 enddo 03409 enddo 03410 else 03411 do j=1,s%ny+1 03412 zsv(:,j) = s%zs(:,min(2,s%ny+1)) 03413 enddo 03414 endif 03415 ! 03416 end subroutine zuzv 03417 03418 ! 03419 !============================================================================== 03420 real(kind=rKind) function disper(w,d,g,pi2,accuracy) 03421 !============================================================================== 03422 ! 03423 03424 03425 !------------------------------------------------------------------------------- 03426 ! DECLARATIONS 03427 !------------------------------------------------------------------------------- 03428 03429 !-------------------------- PURPOSE ---------------------------- 03430 03431 ! Calculate k for a given intrinsic frequency w and depth d. First use the fenton 03432 ! approximation and then iterate for better accuracy (when necessary) 03433 03434 03435 !-------------------------- ARGUMENTS ---------------------------- 03436 03437 real(kind=rKind),intent(in) :: w 03438 real(kind=rKind),intent(in) :: d 03439 real(kind=rKind),intent(in) :: g 03440 real(kind=rKind),intent(in) :: pi2 03441 real(kind=rKind),intent(in) :: accuracy 03442 03443 !-------------------------- LOCAL VARIABLES ---------------------------- 03444 03445 real(kind=rKind) :: k 03446 real(kind=rKind) :: alpha 03447 real(kind=rKind) :: L,Ldeep,pi2d,w2 03448 real(kind=rKind) :: error 03449 03450 !------------------------------------------------------------------------------- 03451 ! IMPLEMENTATION 03452 !------------------------------------------------------------------------------- 03453 w2 = w**2 03454 alpha = d*w2/g 03455 k = alpha*(1.0_rKind/sqrt(tanh(alpha)))/d 03456 L = pi2/k 03457 Ldeep = g*pi2/(w2) 03458 pi2d = pi2*d 03459 03460 error = abs(g*k*tanh(k*d)-w2)/w2 03461 do while (error > accuracy) 03462 L = Ldeep*tanh(pi2d/L) 03463 k = pi2/L 03464 error = abs(g*k*tanh(k*d)-w2)/w2 03465 enddo 03466 03467 disper = k 03468 end function disper 03469 03470 03471 end module nonh_module