Skip to content

Commit

Permalink
Added boundary nudging of scalar fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco de Bruine committed Sep 1, 2020
1 parent 12dd3e3 commit 36730a8
Showing 1 changed file with 111 additions and 15 deletions.
126 changes: 111 additions & 15 deletions src/modnudgeboundary.f90
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ module modnudgeboundary

public :: initnudgeboundary, nudgeboundary, exitnudgeboundary
save
logical :: lnudge_boundary = .false. ! Switch boundary nudging
logical :: lperturb_boundary = .false. ! Switch perturbation of thl near boundary
logical :: lnudge_boundary = .false. ! Switch boundary nudging of thermodynamics
logical :: lnudge_boundary_sv = .false. ! Switch boundary nudging of scalars
logical :: lperturb_boundary = .false. ! Switch perturbation of thl near boundary
logical :: lnudge_w = .true. ! Nudge w to zero or not

real, dimension(:,:), allocatable :: nudge_factor ! Nudging factor (0-1) near lateral boundaries
real, dimension(:,:), allocatable :: perturb_factor ! Perturbing factor (0-1) near lateral boundaries

real, dimension(:,:,:,:), allocatable :: lbc_u, lbc_v, lbc_thl, lbc_qt ! Input for nudging to external field
real, dimension(:,:,:,:), allocatable :: lbc_u, lbc_v, lbc_thl, lbc_qt ! Input for nudging to external field
real, dimension(:,:,:,:,:), allocatable :: lbc_sv ! Input for nudging scalars to external field

! Boundary nudging settings:
real :: nudge_offset=0, nudge_width=0, nudge_radius=0, nudge_tau=-1
Expand All @@ -47,6 +49,9 @@ module modnudgeboundary
real :: dt_input_lbc=-1
integer :: lbc_index=1

real :: dt_input_lbc_sv=-1
integer :: lbc_index_sv=1


contains

Expand Down Expand Up @@ -112,17 +117,17 @@ end subroutine calc_weighting_factor
subroutine initnudgeboundary

use modmpi, only : myid, mpierr, comm3d, mpi_logical, mpi_int, my_real
use modglobal, only : ifnamopt, fname_options, imax, jmax, dx, dy, i1, j1, k1, ih, jh, lwarmstart, kmax, zf, checknamelisterror
use modglobal, only : ifnamopt, fname_options, imax, jmax, dx, dy, i1, j1, k1, ih, jh, lwarmstart, kmax, zf, checknamelisterror, nsv
use modboundary, only : boundary
implicit none

integer :: ierr, k

! Read namelist settings
namelist /NAMNUDGEBOUNDARY/ lnudge_boundary, lperturb_boundary, lnudge_w, &
namelist /NAMNUDGEBOUNDARY/ lnudge_boundary, lnudge_boundary_sv, lperturb_boundary, lnudge_w, &
& nudge_offset, nudge_width, nudge_radius, nudge_tau, &
& perturb_offset, perturb_width, perturb_radius, perturb_ampl, perturb_zmax, &
& dt_input_lbc, perturb_blocksize
& dt_input_lbc, dt_input_lbc_sv, perturb_blocksize

if (myid==0) then
open(ifnamopt, file=fname_options, status='old', iostat=ierr)
Expand All @@ -133,6 +138,7 @@ subroutine initnudgeboundary
end if

call MPI_BCAST(lnudge_boundary, 1, mpi_logical, 0, comm3d, mpierr)
call MPI_BCAST(lnudge_boundary_sv,1, mpi_logical, 0, comm3d, mpierr)
call MPI_BCAST(lperturb_boundary, 1, mpi_logical, 0, comm3d, mpierr)
call MPI_BCAST(lnudge_w, 1, mpi_logical, 0, comm3d, mpierr)

Expand All @@ -150,6 +156,7 @@ subroutine initnudgeboundary
call MPI_BCAST(perturb_zmax, 1, my_real, 0, comm3d, mpierr)

call MPI_BCAST(dt_input_lbc, 1, my_real, 0, comm3d, mpierr)
call MPI_BCAST(dt_input_lbc_sv, 1, my_real, 0, comm3d, mpierr)

if (lnudge_boundary) then
if (myid==0) then
Expand All @@ -168,12 +175,20 @@ subroutine initnudgeboundary
allocate( lbc_v (2-ih:i1+ih, 2-jh:j1+jh, k1, 2) )
allocate( lbc_thl(2-ih:i1+ih, 2-jh:j1+jh, k1, 2) )
allocate( lbc_qt (2-ih:i1+ih, 2-jh:j1+jh, k1, 2) )
if (lnudge_boundary_sv) allocate( lbc_sv (2-ih:i1+ih, 2-jh:j1+jh, k1, nsv, 2) )

! Read the first two input times
call read_new_LBCs(0.)
call read_new_LBCs(dt_input_lbc)
lbc_index = 1

if (lnudge_boundary_sv) then
! Read the first two input times for scalars
call read_new_LBCs_sv(0.)
call read_new_LBCs_sv(dt_input_lbc_sv)
lbc_index_sv = 1
end if

! Hack - read full initial 3D field
if (.not. lwarmstart) call read_initial_fields

Expand Down Expand Up @@ -205,14 +220,18 @@ end subroutine initnudgeboundary
subroutine read_initial_fields

! BvS - this should really go somewhere else, probably modstartup...
use modfields, only : u0, v0, um, vm, thlm, thl0, qtm, qt0
use modfields, only : u0, v0, um, vm, thlm, thl0, qtm, qt0, sv0, svm
use modsurfdata, only : tskin
use modglobal, only : i1, j1, iexpnr, kmax
use modglobal, only : i1, j1, iexpnr, kmax, nsv
use modmpi, only : myidx, myidy

implicit none

integer :: isv

character(80) :: input_file = 'lbc000h00m_x___y___.___'
character(80) :: input_file_sv = 'lbcsv000h00m_x___y___.___'

write(input_file(13:15), '(i3.3)') myidx
write(input_file(17:19), '(i3.3)') myidy
write(input_file(21:23), '(i3.3)') iexpnr
Expand All @@ -232,6 +251,23 @@ subroutine read_initial_fields
thlm (2:i1,2:j1,1:kmax) = thl0 (2:i1,2:j1,1:kmax)
qtm (2:i1,2:j1,1:kmax) = qt0 (2:i1,2:j1,1:kmax)

if (lnudge_boundary_sv) then

write(input_file_sv(15:17), '(i3.3)') myidx
write(input_file_sv(19:21), '(i3.3)') myidy
write(input_file_sv(23:25), '(i3.3)') iexpnr

print*,'Reading initial field: ', input_file_sv

open(777, file=input_file_sv, form='unformatted', status='unknown', action='read', access='stream')
do isv = 1,nsv
read(777) sv0(2:i1,2:j1,1:kmax,isv)
end do
close(777)

svm (2:i1,2:j1,1:kmax,1:nsv) = sv0(2:i1,2:j1,1:kmax,1:nsv)
endif

end subroutine read_initial_fields


Expand Down Expand Up @@ -277,21 +313,59 @@ subroutine read_new_LBCs(time)

end subroutine read_new_LBCs

subroutine read_new_LBCs_sv(time)

use modglobal, only : i1, j1, iexpnr, kmax, nsv
use modmpi, only : myidx, myidy, nprocx, nprocy

implicit none
real, intent(in) :: time !< Input: time to read (seconds)
integer :: ihour, imin, isv

character(80) :: input_file = 'lbcsv___h__m_x___y___.___'

! Only the MPI tasks at the domain edges read the LBCs:
if (myidx == 0 .or. myidx == nprocx-1 .or. myidy == 0 .or. myidy == nprocy-1) then

! File name to read
ihour = floor(time/3600)
imin = floor((time-ihour*3600)/3600.*60.)
write(input_file( 6: 8), '(i3.3)') ihour
write(input_file(10:11), '(i2.2)') imin
write(input_file(15:17), '(i3.3)') myidx
write(input_file(19:21), '(i3.3)') myidy
write(input_file(23:25), '(i3.3)') iexpnr

print*,'Processing LBC for scalars: ', input_file

! Copy old second time to new first time
lbc_sv(:,:,:,:,1) = lbc_sv(:,:,:,:,2)

! Read new LBC for next time
open(777, file=input_file, form='unformatted', status='unknown', action='read', access='stream')
do isv = 1,nsv
read(777) lbc_sv (2:i1,2:j1,1:kmax,isv,2)
end do
close(777)

end if

end subroutine read_new_LBCs_sv

subroutine nudgeboundary

use modglobal, only : i1, j1, imax, jmax, kmax, rdt, cu, cv, eps1, rtimee
use modfields, only : u0, up, v0, vp, w0, wp, thl0, thlp, qt0, qtp
use modglobal, only : i1, j1, imax, jmax, kmax, rdt, cu, cv, eps1, rtimee, nsv
use modfields, only : u0, up, v0, vp, w0, wp, thl0, thlp, qt0, qtp, sv0, svp
use modmpi, only : myidx, myidy, nprocx, nprocy

!#ifdef __INTEL_COMPILER
!use ifport
use ifport
!#endif
implicit none

integer :: i, j, k, blocki, blockj, subi, subj
real :: tau_i, perturbation, t0, t1, tfac
real :: lbc_u_int, lbc_v_int, lbc_w_int, lbc_t_int, lbc_q_int
integer :: i, j, k, blocki, blockj, subi, subj, isv
real :: tau_i, perturbation, t0, t1, tfac, tfac_sv
real :: lbc_u_int, lbc_v_int, lbc_w_int, lbc_t_int, lbc_q_int, lbc_sv_int

if (lnudge_boundary) then

Expand All @@ -307,11 +381,25 @@ subroutine nudgeboundary
call read_new_LBCs(lbc_index*dt_input_lbc)
end if

! Read new LBC for scalars (if required)
if (lnudge_boundary_sv) then
if (rtimee > lbc_index_sv*dt_input_lbc_sv) then
lbc_index_sv = lbc_index_sv + 1
call read_new_LBCs_sv(lbc_index_sv*dt_input_lbc_sv)
end if
end if

! Calculate time interpolation factor
t0 = (lbc_index - 1) * dt_input_lbc ! Time of previous boundary
t1 = (lbc_index ) * dt_input_lbc ! Time of next boundary
tfac = 1.-(rtimee - t0) / (t1 - t0) ! Interpolation factor

if (lnudge_boundary_sv) then
t0 = (lbc_index_sv - 1) * dt_input_lbc_sv ! Time of previous boundary
t1 = (lbc_index_sv ) * dt_input_lbc_sv ! Time of next boundary
tfac_sv = 1.-(rtimee - t0) / (t1 - t0) ! Interpolation factor
end if

if (myidx == 0 .or. myidx == nprocx-1 .or. myidy ==0 .or. myidy == nprocy-1) then
do k=1,kmax
do j=2,j1
Expand All @@ -324,6 +412,13 @@ subroutine nudgeboundary
lbc_q_int = tfac * lbc_qt (i,j,k,1) + (1.-tfac) * lbc_qt (i,j,k,2)
lbc_w_int = 0.

if (lnudge_boundary_sv) then
do isv = 1,nsv
lbc_sv_int = tfac_sv * lbc_sv (i,j,k,isv,1) + (1.-tfac_sv) * lbc_sv (i,j,k,isv,2)
svp(i,j,k,isv) = svp(i,j,k,isv) + nudge_factor(i,j) * tau_i * (lbc_sv_int - sv0(i,j,k,isv))
end do
end if

! Nudge the boundaries
up(i,j,k) = up(i,j,k) + nudge_factor(i,j) * tau_i * (lbc_u_int - (u0(i,j,k)+cu))
vp(i,j,k) = vp(i,j,k) + nudge_factor(i,j) * tau_i * (lbc_v_int - (v0(i,j,k)+cv))
Expand Down Expand Up @@ -374,7 +469,8 @@ subroutine exitnudgeboundary
implicit none
if (lnudge_boundary) then
deallocate( nudge_factor, lbc_u, lbc_v, lbc_thl, lbc_qt )
if (lperturb_boundary) deallocate( perturb_factor )
if (lnudge_boundary_sv) deallocate( lbc_sv )
if (lperturb_boundary) deallocate( perturb_factor )
end if

end subroutine exitnudgeboundary
Expand Down

0 comments on commit 36730a8

Please sign in to comment.