10#include "scaleFElib.h"
35 real(rp) :: wdamp_height
36 logical :: hveldamp_flag
39 procedure :: final => atm_dyn_dgm_spongelayer_final
40 procedure :: addtend => atm_dyn_dgm_spongelayer_add_tend
52 private :: calc_wdampcoef
58 use scale_prc,
only: prc_abort
64 class(
meshbase3d),
target,
intent(in) :: mesh3D
65 real(RP),
intent(in) :: dtsec
67 real(RP) :: SL_WDAMP_TAU = -1.0_rp
68 real(RP) :: SL_WDAMP_HEIGHT = -1.0_rp
69 integer :: SL_WDAMP_LAYER = -1
70 logical :: SL_HORIVELDAMP_FLAG = .false.
72 namelist /param_atmos_dyn_spongelayer/ &
86 read(io_fid_conf,nml=param_atmos_dyn_spongelayer,iostat=ierr)
88 log_info(
"ATMOS_DYN_setup_spongelayer",*)
'Not found namelist. Default used.'
89 else if( ierr > 0 )
then
90 log_error(
"ATMOS_DYN_setup_spongelayer",*)
'Not appropriate names in namelist PARAM_ATMOS_DYN_SPONGELAYER. Check!'
93 log_nml(param_atmos_dyn_spongelayer)
95 this%wdamp_tau = sl_wdamp_tau
96 this%wdamp_height = sl_wdamp_height
98 lcmesh3d => mesh3d%lcmesh_list(1)
99 elem3d => lcmesh3d%refElem3D
107 if ( sl_wdamp_layer > negz )
then
108 log_error(
"ATMOS_DYN_setup_spongelayer",*)
'SL_wdamp_layer should be less than total of vertical elements (NeGZ). Check!'
110 else if( sl_wdamp_layer > 0 )
then
111 this%wdamp_height = lcmesh3d%pos_en(1,1+(sl_wdamp_layer-1)*lcmesh3d%NeX*lcmesh3d%NeY,3)
113 if ( this%wdamp_tau < 0.0_rp )
then
114 this%wdamp_tau = dtsec * 10.0_rp
115 else if ( this%wdamp_tau < dtsec )
then
116 log_error(
"ATMOS_DYN_setup_spongelayer",*)
'SL_wdamp_tau should be larger than TIME_DT (ATMOS_DYN). Check!'
120 this%hveldamp_flag = sl_horiveldamp_flag
126 subroutine atm_dyn_dgm_spongelayer_final( this )
132 end subroutine atm_dyn_dgm_spongelayer_final
134 subroutine atm_dyn_dgm_spongelayer_add_tend( this, MOMX_dt, MOMY_dt, MOMZ_dt, &
135 MOMX_, MOMY_, MOMZ_, &
143 real(RP),
intent(inout) :: MOMX_dt(elem%Np,lmesh%NeA)
144 real(RP),
intent(inout) :: MOMY_dt(elem%Np,lmesh%NeA)
145 real(RP),
intent(inout) :: MOMZ_dt(elem%Np,lmesh%NeA)
146 real(RP),
intent(in) :: MOMX_(elem%Np,lmesh%NeA)
147 real(RP),
intent(in) :: MOMY_(elem%Np,lmesh%NeA)
148 real(RP),
intent(in) :: MOMZ_(elem%Np,lmesh%NeA)
151 integer :: ke_x, ke_y, ke_z
153 real(RP) :: wdamp_coef(elem%Np)
154 real(RP) :: zTop(elem%Nnode_h1D**2)
158 if ( this%hveldamp_flag )
then
165 do ke_z = 1, lmesh%NeZ
166 do ke_y = 1, lmesh%NeY
167 do ke_x = 1, lmesh%NeX
168 ke = ke_x + (ke_y-1)*lmesh%NeX + (ke_z-1)*lmesh%NeX*lmesh%NeY
169 keztop = ke_x + (ke_y-1)*lmesh%NeX + (lmesh%NeZ-1)*lmesh%NeX*lmesh%NeY
170 ztop(:) = lmesh%pos_en(elem%Hslice(:,elem%Nnode_v),keztop,3)
172 call calc_wdampcoef( &
173 this%wdamp_tau, this%wdamp_height, lmesh%pos_en(:,ke,3), ztop(:), &
174 elem%Nnode_h1D, elem%Nnode_v, &
177 momx_dt(:,ke) = momx_dt(:,ke) - s * wdamp_coef(:) * momx_(:,ke)
178 momy_dt(:,ke) = momy_dt(:,ke) - s * wdamp_coef(:) * momy_(:,ke)
179 momz_dt(:,ke) = momz_dt(:,ke) - wdamp_coef(:) * momz_(:,ke)
185 end subroutine atm_dyn_dgm_spongelayer_add_tend
190 subroutine calc_wdampcoef( &
191 wdamp_tau, wdamp_height, z, zTop, Nnode_h1D, Nnode_v, & ! (in)
194 use scale_const,
only: &
198 integer,
intent(in) :: Nnode_h1D
199 integer,
intent(in) :: Nnode_v
200 real(RP),
intent(out) :: wdamp_coef(Nnode_h1D**2,Nnode_v)
201 real(RP),
intent(in) :: wdamp_tau
202 real(RP),
intent(in) :: wdamp_height
203 real(RP),
intent(in) :: z(Nnode_h1D**2,Nnode_v)
204 real(RP),
intent(in) :: zTop(Nnode_h1D**2)
207 real(RP) :: sw(Nnode_h1D**2)
208 real(RP) :: r_wdamp_tau
211 r_wdamp_tau = 1.0_rp / wdamp_tau
213 wdamp_coef(:,p_z) = 0.25_rp * r_wdamp_tau &
214 * ( 1.0_rp + sign( 1.0_rp, z(:,p_z) - wdamp_height ) ) &
215 * ( 1.0_rp - cos( pi * (z(:,p_z) - wdamp_height)/(ztop(:) - wdamp_height) ) )
219 end subroutine calc_wdampcoef
221end module scale_atm_dyn_dgm_spongelayer
module FElib / Fluid dyn solver / Atmosphere / Common
subroutine atm_dyn_dgm_spongelayer_init(this, mesh3d, dtsec)
module FElib / Element / Base
module FElib / Mesh / Local 3D
module FElib / Mesh / Local, Base
module FElib / Mesh / Base 3D
module FElib / Mesh / Cubic 3D domain
module FElib / Mesh / Cubed-sphere 3D domain