Skip to content

Symmetric and open BC: corner points missing  #1311

@matzegoebel

Description

@matzegoebel

Describe the bug
In idealized simulations, the routine set_physical_bc3d sets the boundary zone points for periodic, symmetric, and open boundary conditions:

WRF/share/module_bc.F

Lines 747 to 1096 in f311cd5

periodicity_x: IF( ( config_flags%periodic_x ) ) THEN
IF ( ( ids == ips ) .and. ( ide == ipe ) ) THEN ! test if both east and west on-processor
IF ( its == ids ) THEN
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = 0,-(bdyzone-1),-1
dat(ids+i-1,k,j) = dat(ide+i-1,k,j)
ENDDO
ENDDO
ENDDO
ENDIF
IF ( ite == ide ) THEN
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = -istag , bdyzone
dat(ide+i+istag,k,j) = dat(ids+i+istag,k,j)
ENDDO
ENDDO
ENDDO
ENDIF
ENDIF
ELSE
symmetry_xs: IF( ( config_flags%symmetric_xs ) .and. &
( its == ids ) ) THEN
IF ( (variable /= 'u') .and. (variable /= 'x') ) THEN
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = 1, bdyzone
dat(ids-i,k,j) = dat(ids+i-1,k,j) ! here, dat(0) = dat(1), etc
ENDDO ! symmetry about dat(0.5) (u = 0 pt)
ENDDO
ENDDO
ELSE
IF ( variable == 'u' ) THEN
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = 1, bdyzone
dat(ids-i,k,j) = - dat(ids+i,k,j) ! here, u(0) = - u(2), etc
ENDDO ! normal b.c symmetry at u(1)
ENDDO
ENDDO
ELSE
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = 1, bdyzone
dat(ids-i,k,j) = dat(ids+i,k,j) ! here, phi(0) = phi(2), etc
ENDDO ! normal b.c symmetry at phi(1)
ENDDO
ENDDO
END IF
ENDIF
ENDIF symmetry_xs
! now the symmetry boundary at xe
symmetry_xe: IF( ( config_flags%symmetric_xe ) .and. &
( ite == ide ) ) THEN
IF ( (variable /= 'u') .and. (variable /= 'x') ) THEN
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = 1, bdyzone
dat(ide+i-1,k,j) = dat(ide-i,k,j) ! sym. about dat(ide-0.5)
ENDDO
ENDDO
ENDDO
ELSE
IF (variable == 'u') THEN
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = 1, bdyzone
dat(ide+i,k,j) = - dat(ide-i,k,j) ! u(ide+1) = - u(ide-1), etc.
ENDDO
ENDDO
ENDDO
ELSE
DO j = MAX(jds,jts-1), MIN(jte+1,jde+jstag)
DO k = kts, k_end
DO i = 1, bdyzone
dat(ide+i,k,j) = dat(ide-i,k,j) ! phi(ide+1) = - phi(ide-1), etc.
ENDDO
ENDDO
ENDDO
END IF
END IF
END IF symmetry_xe
! set open b.c in X copy into boundary zone here. WCS, 19 March 2000
open_xs: IF( ( config_flags%open_xs .or. &
config_flags%specified .or. &
config_flags%nested ) .and. &
( its == ids ) .and. open_bc_copy ) THEN
DO j = jts-bdyzone, MIN(jte,jde+jstag)+bdyzone
#if defined(INTEL_ALIGN64)
!DEC$ ASSUME_ALIGNED dat:64
!DEC$ UNROLL(4)
!DEC$ IVDEP
#endif
DO k = kts, k_end
dat(ids-1,k,j) = dat(ids,k,j) ! here, dat(0) = dat(1), etc
dat(ids-2,k,j) = dat(ids,k,j)
dat(ids-3,k,j) = dat(ids,k,j)
ENDDO
ENDDO
ENDIF open_xs
! now the open_xe boundary copy
open_xe: IF( ( config_flags%open_xe .or. &
config_flags%specified .or. &
config_flags%nested ) .and. &
( ite == ide ) .and. open_bc_copy ) THEN
IF (variable /= 'u' .and. variable /= 'x' ) THEN
DO j = jts-bdyzone, MIN(jte,jde+jstag)+bdyzone
#if defined(INTEL_ALIGN64)
!DEC$ ASSUME_ALIGNED dat:64
!DEC$ UNROLL(4)
!DEC$ IVDEP
#endif
DO k = kts, k_end
dat(ide ,k,j) = dat(ide-1,k,j)
dat(ide+1,k,j) = dat(ide-1,k,j)
dat(ide+2,k,j) = dat(ide-1,k,j)
ENDDO
ENDDO
ELSE
!!!!!!! I am not sure about this one! JM 20020402
DO j = MAX(jds,jts-1)-bdyzone, MIN(jte+1,jde+jstag)+bdyzone
DO k = kts, k_end
dat(ide+1,k,j) = dat(ide,k,j)
dat(ide+2,k,j) = dat(ide,k,j)
dat(ide+3,k,j) = dat(ide,k,j)
ENDDO
ENDDO
END IF
END IF open_xe
! end open b.c in X copy into boundary zone addition. WCS, 19 March 2000
END IF periodicity_x
! same procedure in y
periodicity_y: IF( ( config_flags%periodic_y ) ) THEN
IF ( ( jds == jps ) .and. ( jde == jpe ) ) THEN ! test if both north and south on processor
IF( jts == jds ) then
DO j = 0, -(bdyzone-1), -1
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jds+j-1) = dat(i,k,jde+j-1)
ENDDO
ENDDO
ENDDO
END IF
IF( jte == jde ) then
DO j = -jstag, bdyzone
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jde+j+jstag) = dat(i,k,jds+j+jstag)
ENDDO
ENDDO
ENDDO
END IF
END IF
ELSE
symmetry_ys: IF( ( config_flags%symmetric_ys ) .and. &
( jts == jds) ) THEN
IF ( (variable /= 'v') .and. (variable /= 'y') ) THEN
DO j = 1, bdyzone
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jds-j) = dat(i,k,jds+j-1)
ENDDO
ENDDO
ENDDO
ELSE
IF (variable == 'v') THEN
DO j = 1, bdyzone
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jds-j) = - dat(i,k,jds+j)
ENDDO
ENDDO
ENDDO
ELSE
DO j = 1, bdyzone
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jds-j) = dat(i,k,jds+j)
ENDDO
ENDDO
ENDDO
END IF
ENDIF
ENDIF symmetry_ys
! now the symmetry boundary at ye
symmetry_ye: IF( ( config_flags%symmetric_ye ) .and. &
( jte == jde ) ) THEN
IF ( (variable /= 'v') .and. (variable /= 'y') ) THEN
DO j = 1, bdyzone
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jde+j-1) = dat(i,k,jde-j)
ENDDO
ENDDO
ENDDO
ELSE
IF ( variable == 'v' ) THEN
DO j = 1, bdyzone
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jde+j) = - dat(i,k,jde-j)
ENDDO
ENDDO
ENDDO
ELSE
DO j = 1, bdyzone
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jde+j) = dat(i,k,jde-j)
ENDDO
ENDDO
ENDDO
END IF
ENDIF
END IF symmetry_ye
! set open b.c in Y copy into boundary zone here. WCS, 19 March 2000
open_ys: IF( ( config_flags%open_ys .or. &
config_flags%polar .or. &
config_flags%specified .or. &
config_flags%nested ) .and. &
( jts == jds) .and. open_bc_copy ) THEN
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jds-1) = dat(i,k,jds)
dat(i,k,jds-2) = dat(i,k,jds)
dat(i,k,jds-3) = dat(i,k,jds)
ENDDO
ENDDO
ENDIF open_ys
! now the open boundary copy at ye
open_ye: IF( ( config_flags%open_ye .or. &
config_flags%polar .or. &
config_flags%specified .or. &
config_flags%nested ) .and. &
( jte == jde ) .and. open_bc_copy ) THEN
IF (variable /= 'v' .and. variable /= 'y' ) THEN
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jde ) = dat(i,k,jde-1)
dat(i,k,jde+1) = dat(i,k,jde-1)
dat(i,k,jde+2) = dat(i,k,jde-1)
ENDDO
ENDDO
ELSE
DO k = kts, k_end
DO i = MAX(ids,its-1), MIN(ite+1,ide+istag)
dat(i,k,jde+1) = dat(i,k,jde)
dat(i,k,jde+2) = dat(i,k,jde)
dat(i,k,jde+3) = dat(i,k,jde)
ENDDO
ENDDO
ENDIF
END IF open_ye
! end open b.c in Y copy into boundary zone addition. WCS, 19 March 2000
END IF periodicity_y

At first, the routine does not set the corner points (e.g., (ids-1,jds-1)): For the y-boundaries it iterates i only from MAX(ids,its-1) to MIN(ite+1,ide+istag) and analogously for the x-boundaries (note that for open BC it actually also tries to set the corner points (see line 896), but not effectively, because the RHS values in lines 903-905 are still 0 there, as the y-BC has not been applied yet).

For doubly-periodic BC, the corner points are set correctly afterwards, starting at line 1100. In any other case, however, it seems that the corner points are not assigned and appear as zeros.
At least that's what I see, when debugging the code with gdb.

These corner points are later used, e.g. in the diffusion module:

DO j = j_start, j_end
DO k = kts, ktf
DO i = i_start, i_end
xkxavg(i,k,j) = 0.25 * ( xkx(i-1,k,j ) + xkx(i,k,j ) + &
xkx(i-1,k,j-1) + xkx(i,k,j-1) )
xkxavg(i,k,j) = xkxavg(i,k,j) * .25 * ( rho(i-1,k,j ) + rho(i,k,j ) + &
rho(i-1,k,j-1) + rho(i,k,j-1) )

Thus, because rho(i_start-1,k,j_start-1)=0, xkxavg(i_start, k, j_start) is much smaller than at the other locations.
Inaccuracies must obviously arise.

Suggested solution
The corner points should be set also for non-doubly-periodic boundary conditions. This should be easy to achieve by applying lines 747-1096 in module_bc.F twice, the second time only for the corner points. But someone needs to look at this in more detail.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions