-
Notifications
You must be signed in to change notification settings - Fork 827
Symmetric and open BC: corner points missing #1311
Description
Describe the bug
In idealized simulations, the routine set_physical_bc3d sets the boundary zone points for periodic, symmetric, and open boundary conditions:
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:
WRF/dyn_em/module_diffusion_em.F
Lines 5511 to 5517 in f311cd5
| 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.