| Class | vdiffusion_my |
| In: |
vdiffusion/vdiffusion_my.f90
|
Note that Japanese and English are described in parallel.
鉛直拡散フラックスを計算します.
Vertical diffusion flux is calculated.
| VDiffusion : | 鉛直拡散フラックスの計算 |
| VDiffusionOutPut : | フラックスの出力 |
| ———— : | ———— |
| VDiffusion : | Calculate vertical diffusion fluxes |
| VDiffusionOutPut : | Output fluxes |
| Subroutine : | |||
| xyz_U(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyz_V(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) : | real(DP), intent(in)
| ||
| xyz_Temp(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Temp(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_VirTemp(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_VirTemp(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_Press(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xy_SurfHeight(0:imax-1,1:jmax) : | real(DP), intent(in)
| ||
| xyz_Height(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Height(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_Exner(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Exner(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_MomFluxX(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_MomFluxY(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_HeatFlux(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax) : | real(DP), intent(out)
| ||
| xyr_VelTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
|
鉛直拡散フラックスを計算します.
Vertical diffusion flux is calculated by use of MY2 model.
subroutine VDiffusion( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_Temp, xyz_VirTemp, xyr_VirTemp, xyr_Press, xy_SurfHeight, xyz_Height, xyr_Height, xyz_Exner, xyr_Exner, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef )
!
! 鉛直拡散フラックスを計算します.
!
! Vertical diffusion flux is calculated by use of MY2 model.
!
! モジュール引用 ; USE statements
!
! 物理定数設定
! Physical constants settings
!
use constants, only: FKarm, Grav
! $ g $ [m s-2].
! 重力加速度.
! Gravitational acceleration
! 時刻管理
! Time control
!
use timeset, only: TimeN, TimesetClockStart, TimesetClockStop
! ヒストリデータ出力
! History data output
!
use gtool_historyauto, only: HistoryAutoPut
! 宣言文 ; Declaration statements
!
implicit none
real(DP), intent(in):: xyz_U (0:imax-1, 1:jmax, 1:kmax)
! $ u $ . 東西風速. Eastward wind
real(DP), intent(in):: xyz_V (0:imax-1, 1:jmax, 1:kmax)
! $ v $ . 南北風速. Northward wind
real(DP), intent(in):: xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
! $ q $ . 質量混合比. Mass mixing ratio
real(DP), intent(in):: xyz_Temp (0:imax-1, 1:jmax, 1:kmax)
! $ T $ . 温度. Temperature
real(DP), intent(in):: xyr_Temp (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{T} $ . 温度 (半整数レベル).
! Temperature (half level)
real(DP), intent(in):: xyz_VirTemp (0:imax-1, 1:jmax, 1:kmax)
! $ T_v $ . 仮温度. Virtual temperature
real(DP), intent(in):: xyr_VirTemp (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{T}_v $ . 仮温度 (半整数レベル).
! Virtual temperature (half level)
real(DP), intent(in):: xyr_Press (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{p} $ . 気圧 (半整数レベル).
! Air pressure (half level)
real(DP), intent(in):: xy_SurfHeight (0:imax-1,1:jmax)
! $ z_s $ . 地表面高度.
! Surface height.
real(DP), intent(in):: xyz_Height (0:imax-1, 1:jmax, 1:kmax)
! 高度 (整数レベル).
! Height (full level)
real(DP), intent(in):: xyr_Height (0:imax-1, 1:jmax, 0:kmax)
! 高度 (半整数レベル).
! Height (half level)
real(DP), intent(in):: xyz_Exner (0:imax-1, 1:jmax, 1:kmax)
! Exner 関数 (整数レベル).
! Exner function (full level)
real(DP), intent(in):: xyr_Exner (0:imax-1, 1:jmax, 0:kmax)
! Exner 関数 (半整数レベル).
! Exner function (half level)
real(DP), intent(out):: xyr_MomFluxX (0:imax-1, 1:jmax, 0:kmax)
! 東西方向運動量フラックス.
! Eastward momentum flux
real(DP), intent(out):: xyr_MomFluxY (0:imax-1, 1:jmax, 0:kmax)
! 南北方向運動量フラックス.
! Northward momentum flux
real(DP), intent(out):: xyr_HeatFlux (0:imax-1, 1:jmax, 0:kmax)
! 熱フラックス.
! Heat flux
real(DP), intent(out):: xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax)
! 質量フラックス.
! Mass flux of compositions
real(DP), intent(out):: xyr_VelTransCoef (0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:運動量.
! Transfer coefficient: velocity
real(DP), intent(out):: xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:温度.
! Transfer coefficient: temperature
real(DP), intent(out):: xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:質量.
! Transfer coefficient: mass (composition)
! 作業変数
! Work variables
!
real(DP) :: xyr_DVelDz (0:imax-1, 1:jmax, 0:kmax)
! $ \DD{|\Dvect{v}|}{z} $
real(DP) :: xyr_BulkRiNum (0:imax-1, 1:jmax, 0:kmax)
! バルク $ R_i $ 数.
! Bulk $ R_i $
real(DP) :: xyr_VelDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:運動量.
! Diffusion coefficient: velocity
real(DP) :: xyr_TempDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:温度.
! Transfer coefficient: temperature
real(DP) :: xyr_QMixDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:比湿.
! Diffusion coefficient: specific humidity
integer:: k ! 鉛直方向に回る DO ループ用作業変数
! Work variables for DO loop in vertical direction
integer:: n ! 組成方向に回る DO ループ用作業変数
! Work variables for DO loop in dimension of constituents
! 実行文 ; Executable statement
!
! 初期化確認
! Initialization check
!
if ( .not. vdiffusion_my_inited ) then
call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
end if
! 計算時間計測開始
! Start measurement of computation time
!
call TimesetClockStart( module_name )
! 拡散係数の計算
! Calculation of diffusion coefficient
!
if ( FlagConstDiffCoef ) then
xyr_VelDiffCoef (:,:,0 ) = 0.0d0
xyr_VelDiffCoef (:,:,1:kmax-1) = ConstDiffCoefM
xyr_VelDiffCoef (:,:,kmax ) = 0.0d0
xyr_TempDiffCoef(:,:,0 ) = 0.0d0
xyr_TempDiffCoef(:,:,1:kmax-1) = ConstDiffCoefH
xyr_TempDiffCoef(:,:,kmax ) = 0.0d0
xyr_QMixDiffCoef(:,:,0 ) = 0.0d0
xyr_QMixDiffCoef(:,:,1:kmax-1) = ConstDiffCoefH
xyr_QMixDiffCoef(:,:,kmax ) = 0.0d0
else
! バルク $ R_i $ 数算出
! Calculate bulk $ R_i $
!
xyr_DVelDz(:,:,0) = 0.
xyr_DVelDz(:,:,kmax) = 0.
xyr_BulkRiNum(:,:,0) = 0.
xyr_BulkRiNum(:,:,kmax) = 0.
do k = 1, kmax-1
xyr_DVelDz(:,:,k) = sqrt( max( SquareVelMin , ( xyz_U(:,:,k+1) - xyz_U(:,:,k) )**2 + ( xyz_V(:,:,k+1) - xyz_V(:,:,k) )**2 ) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
xyr_BulkRiNum(:,:,k) = Grav / ( xyr_VirTemp(:,:,k) / xyr_Exner(:,:,k) ) * ( xyz_VirTemp(:,:,k+1) / xyz_Exner(:,:,k+1) - xyz_VirTemp(:,:,k ) / xyz_Exner(:,:,k ) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) ) / xyr_DVelDz(:,:,k)**2
xyr_BulkRiNum(:,:,k) = max( xyr_BulkRiNum(:,:,k) , BulkRiNumMin )
end do
! 拡散係数の計算
! Calculate diffusion coefficients
!
call VDiffCoefficient( xy_SurfHeight, xyr_Height, xyr_DVelDz, xyr_BulkRiNum, xyr_VelDiffCoef, xyr_TempDiffCoef, xyr_QMixDiffCoef )
end if
! 浅い積雲対流
! Shallow cumulus convection
!
! (AGCM5 から導入予定)
! 拡散係数の出力
! Output diffusion coefficients
!
! (上記の「浅い積雲対流」導入後に作成)
! 拡散係数出力
! Diffusion coeffficients output
!
call HistoryAutoPut( TimeN, 'VelDiffCoef', xyr_VelDiffCoef )
call HistoryAutoPut( TimeN, 'TempDiffCoef', xyr_TempDiffCoef )
call HistoryAutoPut( TimeN, 'QVapDiffCoef', xyr_QMixDiffCoef )
! 輸送係数とフラックスの計算
! Calculate transfer coefficient and flux
!
call VDiffusionTransCoefAndFlux( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_VirTemp, xyr_Press, xyz_Height, xyz_Exner, xyr_Exner, xyr_VelDiffCoef, xyr_TempDiffCoef, xyr_QMixDiffCoef, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef )
! 計算時間計測一時停止
! Pause measurement of computation time
!
call TimesetClockStop( module_name )
end subroutine VDiffusion
| Subroutine : | |||
| xyr_Press(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in )
| ||
| xyr_MomFluxX(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in ), optional
| ||
| xyr_MomFluxY(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in ), optional
| ||
| xyr_HeatFlux(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in ), optional
| ||
| xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax) : | real(DP), intent(in ), optional
| ||
| xyz_DUDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(out), optional
| ||
| xyz_DVDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(out), optional
| ||
| xyz_DTempDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(out), optional
| ||
| xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) : | real(DP), intent(out), optional
|
時間変化率の計算を行います.
Calculate tendencies.
subroutine VDiffusionExpTendency( xyr_Press, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyz_DUDt, xyz_DVDt, xyz_DTempDt, xyzf_DQMixDt )
!
! 時間変化率の計算を行います.
!
! Calculate tendencies.
!
! モジュール引用 ; USE statements
!
! 物理定数設定
! Physical constants settings
!
use constants, only: Grav, CpDry
! $ C_p $ [J kg-1 K-1].
! 乾燥大気の定圧比熱.
! Specific heat of air at constant pressure
! 宣言文 ; Declaration statements
!
implicit none
real(DP), intent(in ):: xyr_Press (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{p} $ . 気圧 (半整数レベル).
! Air pressure (half level)
real(DP), intent(in ), optional :: xyr_MomFluxX (0:imax-1, 1:jmax, 0:kmax)
! 東西方向運動量フラックス.
! Eastward momentum flux
real(DP), intent(in ), optional :: xyr_MomFluxY (0:imax-1, 1:jmax, 0:kmax)
! 南北方向運動量フラックス.
! Northward momentum flux
real(DP), intent(in ), optional :: xyr_HeatFlux (0:imax-1, 1:jmax, 0:kmax)
! 熱フラックス.
! Heat flux
real(DP), intent(in ), optional :: xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax)
! 比湿フラックス.
! Specific humidity flux
real(DP), intent(out), optional :: xyz_DUDt (0:imax-1, 1:jmax, 1:kmax)
! $ \DP{u}{t} $ . 東西風速変化.
! Eastward wind tendency
real(DP), intent(out), optional :: xyz_DVDt (0:imax-1, 1:jmax, 1:kmax)
! $ \DP{v}{t} $ . 南北風速変化.
! Northward wind tendency
real(DP), intent(out), optional :: xyz_DTempDt (0:imax-1, 1:jmax, 1:kmax)
! $ \DP{T}{t} $ . 温度変化.
! Temperature tendency
real(DP), intent(out), optional :: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
! $ \DP{q}{t} $ . 質量混合比変化.
! Mass mixing ratio tendency
! 作業変数
! Work variables
!
integer:: k ! 鉛直方向に回る DO ループ用作業変数
! Work variables for DO loop in vertical direction
integer:: n ! 組成方向に回る DO ループ用作業変数
! Work variables for DO loop in dimension of constituents
! 実行文 ; Executable statement
!
! 初期化確認
! Initialization check
!
if ( .not. vdiffusion_my_inited ) then
call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
end if
! Check arguments
!
if ( present( xyz_DUDt ) ) then
if ( .not. present( xyr_MomFluxX ) ) then
call MessageNotify( 'E', module_name, 'xyr_MomFluxX has to be present.' )
end if
end if
if ( present( xyz_DVDt ) ) then
if ( .not. present( xyr_MomFluxY ) ) then
call MessageNotify( 'E', module_name, 'xyr_MomFluxY has to be present.' )
end if
end if
if ( present( xyz_DTempDt ) ) then
if ( .not. present( xyr_HeatFlux ) ) then
call MessageNotify( 'E', module_name, 'xyr_HeatFlux has to be present.' )
end if
end if
if ( present( xyzf_DQMixDt ) ) then
if ( .not. present( xyrf_QMixFlux ) ) then
call MessageNotify( 'E', module_name, 'xyrf_QMixFlux has to be present.' )
end if
end if
if ( present( xyz_DUDt ) ) then
do k = 1, kmax
xyz_DUDt(:,:,k) = + Grav * ( xyr_MomFluxX(:,:,k) - xyr_MomFluxX(:,:,k-1) ) / ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) )
end do
end if
if ( present( xyz_DVDt ) ) then
do k = 1, kmax
xyz_DVDt(:,:,k) = + Grav * ( xyr_MomFluxY(:,:,k) - xyr_MomFluxY(:,:,k-1) ) / ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) )
end do
end if
if ( present( xyz_DTempDt ) ) then
do k = 1, kmax
xyz_DTempDt(:,:,k) = + Grav / CpDry * ( xyr_HeatFlux(:,:,k) - xyr_HeatFlux(:,:,k-1) ) / ( xyr_Press (:,:,k) - xyr_Press (:,:,k-1) )
end do
end if
if ( present( xyzf_DQMixDt ) ) then
do n = 1, ncmax
do k = 1, kmax
xyzf_DQMixDt(:,:,k,n) = + Grav * ( xyrf_QMixFlux(:,:,k,n) - xyrf_QMixFlux(:,:,k-1,n) ) / ( xyr_Press (:,:,k) - xyr_Press (:,:,k-1) )
end do
end do
end if
end subroutine VDiffusionExpTendency
| Subroutine : |
vdiffusion_my モジュールの初期化を行います. NAMELIST#vdiffusion_my_nml の読み込みはこの手続きで行われます.
"vdiffusion_my" module is initialized. "NAMELIST#vdiffusion_my_nml" is loaded in this procedure.
This procedure input/output NAMELIST#vdiffusion_my_nml .
subroutine VDiffusionInit
!
! vdiffusion_my モジュールの初期化を行います.
! NAMELIST#vdiffusion_my_nml の読み込みはこの手続きで行われます.
!
! "vdiffusion_my" module is initialized.
! "NAMELIST#vdiffusion_my_nml" is loaded in this procedure.
!
! モジュール引用 ; USE statements
!
! NAMELIST ファイル入力に関するユーティリティ
! Utilities for NAMELIST file input
!
use namelist_util, only: namelist_filename, NmlutilMsg, NmlutilAryValid
! ファイル入出力補助
! File I/O support
!
use dc_iounit, only: FileOpen
! 種別型パラメタ
! Kind type parameter
!
use dc_types, only: STDOUT ! 標準出力の装置番号. Unit number of standard output
! 文字列操作
! Character handling
!
use dc_string, only: StoA
! ヒストリデータ出力
! History data output
!
use gtool_historyauto, only: HistoryAutoAddVariable
! 座標データ設定
! Axes data settings
!
use axesset, only: AxnameX, AxnameY, AxnameZ, AxnameR, AxnameT
! 宣言文 ; Declaration statements
!
implicit none
integer:: unit_nml ! NAMELIST ファイルオープン用装置番号.
! Unit number for NAMELIST file open
integer:: iostat_nml ! NAMELIST 読み込み時の IOSTAT.
! IOSTAT of NAMELIST read
! NAMELIST 変数群
! NAMELIST group name
!
namelist /vdiffusion_my_nml/ FlagConstDiffCoef, ConstDiffCoefM, ConstDiffCoefH, SquareVelMin, BulkRiNumMin, MixLengthMax, ShMin, SmMin, VelDiffCoefMin, TempDiffCoefMin, VelDiffCoefMax, TempDiffCoefMax, MYConstA1, MYConstB1, MYConstA2, MYConstB2, MYConstC1
!
! デフォルト値については初期化手続 "vdiffusion_my#VDiffInit"
! のソースコードを参照のこと.
!
! Refer to source codes in the initialization procedure
! "vdiffusion_my#VDiffInit" for the default values.
!
! 実行文 ; Executable statement
!
if ( vdiffusion_my_inited ) return
! デフォルト値の設定
! Default values settings
!
FlagConstDiffCoef = .false.
ConstDiffCoefM = 0.0d0
ConstDiffCoefH = 0.0d0
SquareVelMin = 0.1
BulkRiNumMin = - 100.
MixLengthMax = 300.
ShMin = 0.
SmMin = 0.
VelDiffCoefMin = 0.1
TempDiffCoefMin = 0.1
VelDiffCoefMax = 10000.
TempDiffCoefMax = 10000.
! Parameters proposed by Mellor and Yamada (1982).
!
MYConstA1 = 0.92
MYConstB1 = 16.6
MYConstA2 = 0.74
MYConstB2 = 10.1
MYConstC1 = 0.08
! NAMELIST の読み込み
! NAMELIST is input
!
if ( trim(namelist_filename) /= '' ) then
call FileOpen( unit_nml, namelist_filename, mode = 'r' ) ! (in)
rewind( unit_nml )
read( unit_nml, nml = vdiffusion_my_nml, iostat = iostat_nml ) ! (out)
close( unit_nml )
call NmlutilMsg( iostat_nml, module_name ) ! (in)
if ( iostat_nml == 0 ) write( STDOUT, nml = vdiffusion_my_nml )
end if
! ヒストリデータ出力のためのへの変数登録
! Register of variables for history data output
!
call HistoryAutoAddVariable( 'VelDiffCoef', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'diffusion coef. momentum', 'm2 s-1' )
call HistoryAutoAddVariable( 'TempDiffCoef', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'diffusion coef. heat ', 'm2 s-1' )
call HistoryAutoAddVariable( 'QVapDiffCoef', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'diffusion coef. moisture', 'm2 s-1' )
call HistoryAutoAddVariable( 'MomFluxX', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'eastward momentum flux', 'N m-2' )
call HistoryAutoAddVariable( 'MomFluxY', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'northward momentum flux', 'N m-2' )
call HistoryAutoAddVariable( 'HeatFlux', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'heat flux', 'W m-2' )
call HistoryAutoAddVariable( 'QVapFlux', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'moisture flux', 'W m-2' )
call HistoryAutoAddVariable( 'DUDtVDiff', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'tendency of zonal wind by vertical diffusion', 'm s-2' )
call HistoryAutoAddVariable( 'DVDtVDiff', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'tendency of meridional wind by vertical diffusion', 'm s-2' )
call HistoryAutoAddVariable( 'DTempDtVDiff', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'tendency of temperature by vertical diffusion', 'K s-1' )
call HistoryAutoAddVariable( 'DQVapDtVDiff', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'tendency of specific humidity by vertical diffusion', 's-1' )
call HistoryAutoAddVariable( 'TurKinEne', (/ AxNameX, AxNameY, AxNameR, AxNameT /), 'turbulent kinetic energy', 'm2 s-2' )
call HistoryAutoAddVariable( 'TKEPShear', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'turbulent kinetic energy production rate by shear', 'm2 s-3' )
call HistoryAutoAddVariable( 'TKEPBuoy', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'turbulent kinetic energy production rate by buoyancy', 'm2 s-3' )
call HistoryAutoAddVariable( 'TKEDiss', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'turbulent kinetic energy dissipation rate', 'm2 s-3' )
call HistoryAutoAddVariable( 'MixLength', (/ AxNameX, AxNameY, AxNameZ, AxNameT /), 'mixing length', 'm' )
! 印字 ; Print
!
call MessageNotify( 'M', module_name, '----- Initialization Messages -----' )
call MessageNotify( 'M', module_name, 'For vertical diffusion flux:' )
call MessageNotify( 'M', module_name, ' FlagConstDiffCoef = %b', l = (/ FlagConstDiffCoef /) )
call MessageNotify( 'M', module_name, ' ConstDiffCoefM = %f', d = (/ ConstDiffCoefM /) )
call MessageNotify( 'M', module_name, ' ConstDiffCoefH = %f', d = (/ ConstDiffCoefH /) )
call MessageNotify( 'M', module_name, ' SquareVelMin = %f', d = (/ SquareVelMin /) )
call MessageNotify( 'M', module_name, ' BulkRiNumMin = %f', d = (/ BulkRiNumMin /) )
call MessageNotify( 'M', module_name, 'For diffusion coefficients:' )
call MessageNotify( 'M', module_name, ' MixLengthMax = %f', d = (/ MixLengthMax /) )
call MessageNotify( 'M', module_name, ' ShMin = %f', d = (/ ShMin /) )
call MessageNotify( 'M', module_name, ' SmMin = %f', d = (/ SmMin /) )
call MessageNotify( 'M', module_name, ' VelDiffCoefMin = %f', d = (/ VelDiffCoefMin /) )
call MessageNotify( 'M', module_name, ' TempDiffCoefMin = %f', d = (/ TempDiffCoefMin /) )
call MessageNotify( 'M', module_name, ' VelDiffCoefMax = %f', d = (/ VelDiffCoefMax /) )
call MessageNotify( 'M', module_name, ' TempDiffCoefMax = %f', d = (/ TempDiffCoefMax /) )
call MessageNotify( 'M', module_name, ' MYConstA1 = %f', d = (/ MYConstA1 /) )
call MessageNotify( 'M', module_name, ' MYConstB1 = %f', d = (/ MYConstB1 /) )
call MessageNotify( 'M', module_name, ' MYConstA2 = %f', d = (/ MYConstA2 /) )
call MessageNotify( 'M', module_name, ' MYConstB2 = %f', d = (/ MYConstB2 /) )
call MessageNotify( 'M', module_name, ' MYConstC1 = %f', d = (/ MYConstC1 /) )
call MessageNotify( 'M', module_name, '-- version = %c', c1 = trim(version) )
vdiffusion_my_inited = .true.
end subroutine VDiffusionInit
| Subroutine : | |||
| xyz_U(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyz_V(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) : | real(DP), intent(in)
| ||
| xyz_Temp(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Temp(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_VirTemp(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_VirTemp(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_Press(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xy_SurfHeight(0:imax-1,1:jmax) : | real(DP), intent(in)
| ||
| xyz_Height(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Height(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_Exner(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Exner(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_TurKinEne(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xy_SurfMomFluxX(0:imax-1, 1:jmax) : | real(DP), intent(in)
| ||
| xy_SurfMomFluxY(0:imax-1, 1:jmax) : | real(DP), intent(in)
| ||
| xyr_MomFluxX(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_MomFluxY(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_HeatFlux(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax) : | real(DP), intent(out)
| ||
| xyr_VelTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyz_DTurKinEneDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(out)
|
鉛直拡散フラックスを計算します.
Vertical diffusion flux is calculated by use of MY2.5 model.
subroutine VDiffusionMY25( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_Temp, xyz_VirTemp, xyr_VirTemp, xyr_Press, xy_SurfHeight, xyz_Height, xyr_Height, xyz_Exner, xyr_Exner, xyz_TurKinEne, xy_SurfMomFluxX, xy_SurfMomFluxY, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef, xyz_DTurKinEneDt )
!
! 鉛直拡散フラックスを計算します.
!
! Vertical diffusion flux is calculated by use of MY2.5 model.
!
! モジュール引用 ; USE statements
!
! 物理定数設定
! Physical constants settings
!
use constants, only: FKarm, Grav, GasRDry, CpDry
! $ C_p $ [J kg-1 K-1].
! 乾燥大気の定圧比熱.
! Specific heat of air at constant pressure
! 時刻管理
! Time control
!
use timeset, only: DelTime, TimeN, TimesetClockStart, TimesetClockStop
! ヒストリデータ出力
! History data output
!
use gtool_historyauto, only: HistoryAutoPut
! MPI 関連ルーチン
! MPI related routines
!
use mpi_wrapper, only : MPIWrapperChkTrue
! 陰解法による時間積分のためのルーチン
! Routines for time integration with implicit scheme
!
use phy_implicit_utils, only : PhyImplLUDecomp3, PhyImplLUSolve3
! 宣言文 ; Declaration statements
!
implicit none
real(DP), intent(in):: xyz_U (0:imax-1, 1:jmax, 1:kmax)
! $ u $ . 東西風速. Eastward wind
real(DP), intent(in):: xyz_V (0:imax-1, 1:jmax, 1:kmax)
! $ v $ . 南北風速. Northward wind
real(DP), intent(in):: xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
! $ q $ . 質量混合比. Mass mixing ratio
real(DP), intent(in):: xyz_Temp (0:imax-1, 1:jmax, 1:kmax)
! $ T $ . 温度. Temperature
real(DP), intent(in):: xyr_Temp (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{T} $ . 温度 (半整数レベル).
! Temperature (half level)
real(DP), intent(in):: xyz_VirTemp (0:imax-1, 1:jmax, 1:kmax)
! $ T_v $ . 仮温度. Virtual temperature
real(DP), intent(in):: xyr_VirTemp (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{T}_v $ . 仮温度 (半整数レベル).
! Virtual temperature (half level)
real(DP), intent(in):: xyr_Press (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{p} $ . 気圧 (半整数レベル).
! Air pressure (half level)
real(DP), intent(in):: xy_SurfHeight (0:imax-1,1:jmax)
! $ z_s $ . 地表面高度.
! Surface height.
real(DP), intent(in):: xyz_Height (0:imax-1, 1:jmax, 1:kmax)
! 高度 (整数レベル).
! Height (full level)
real(DP), intent(in):: xyr_Height (0:imax-1, 1:jmax, 0:kmax)
! 高度 (半整数レベル).
! Height (half level)
real(DP), intent(in):: xyz_Exner (0:imax-1, 1:jmax, 1:kmax)
! Exner 関数 (整数レベル).
! Exner function (full level)
real(DP), intent(in):: xyr_Exner (0:imax-1, 1:jmax, 0:kmax)
! Exner 関数 (半整数レベル).
! Exner function (half level)
real(DP), intent(in):: xyz_TurKinEne(0:imax-1, 1:jmax, 1:kmax)
!
! Turbulent kinetic energy (m2 s-2)
real(DP), intent(in):: xy_SurfMomFluxX (0:imax-1, 1:jmax)
!
! Eastward momentum flux at surface
real(DP), intent(in):: xy_SurfMomFluxY (0:imax-1, 1:jmax)
!
! Northward momentum flux at surface
real(DP), intent(out):: xyr_MomFluxX (0:imax-1, 1:jmax, 0:kmax)
! 東西方向運動量フラックス.
! Eastward momentum flux
real(DP), intent(out):: xyr_MomFluxY (0:imax-1, 1:jmax, 0:kmax)
! 南北方向運動量フラックス.
! Northward momentum flux
real(DP), intent(out):: xyr_HeatFlux (0:imax-1, 1:jmax, 0:kmax)
! 熱フラックス.
! Heat flux
real(DP), intent(out):: xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax)
! 質量フラックス.
! Mass flux of compositions
real(DP), intent(out):: xyr_VelTransCoef (0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:運動量.
! Transfer coefficient: velocity
real(DP), intent(out):: xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:温度.
! Transfer coefficient: temperature
real(DP), intent(out):: xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:質量.
! Transfer coefficient: mass (composition)
real(DP), intent(out):: xyz_DTurKinEneDt (0:imax-1, 1:jmax, 1:kmax)
!
! Tendency of turbulent kinetic energy
! 作業変数
! Work variables
!
real(DP) :: xyz_MixLength(0:imax-1, 1:jmax, 1:kmax)
! 混合距離.
! Mixing length
real(DP) :: xyz_DVelDzSq(0:imax-1, 1:jmax, 1:kmax)
!
! Vertical shear squared (s-2)
real(DP) :: xyz_StatStab(0:imax-1, 1:jmax, 1:kmax)
!
! Static stability (s-2)
real(DP) :: GhMin
!
! Minimum of G_h
real(DP) :: GhMax
!
! Maximum of G_h
real(DP) :: xyz_Gm(0:imax-1, 1:jmax, 1:kmax)
!
! G_m
real(DP) :: xyz_Gh(0:imax-1, 1:jmax, 1:kmax)
!
! G_h
!!$ real(DP) :: xyz_SmHat(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! \hat{S}_M
!!$ real(DP) :: xyz_ShHat(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! \hat{S}_h
!!$ real(DP) :: xyz_DSmHatDTKE(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! derivative of \hat{S}_M
!!$ real(DP) :: xyz_DShHatDTKE(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! derivative of \hat{S}_h
real(DP) :: xyz_Sm(0:imax-1, 1:jmax, 1:kmax)
!
! S_M
real(DP) :: xyz_Sh(0:imax-1, 1:jmax, 1:kmax)
!
! S_h
real(DP), parameter :: Stke = 0.2_DP
!
! S_{TKE} = 0.2
real(DP) :: xyz_VelDiffCoef (0:imax-1, 1:jmax, 1:kmax)
! 拡散係数:運動量.
! Diffusion coefficient: velocity
real(DP) :: xyz_TempDiffCoef (0:imax-1, 1:jmax, 1:kmax)
! 拡散係数:温度.
! Transfer coefficient: temperature
real(DP) :: xyr_VelDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:運動量.
! Diffusion coefficient: velocity
real(DP) :: xyr_TempDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:温度.
! Transfer coefficient: temperature
real(DP) :: xyr_QMixDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:比湿.
! Diffusion coefficient: specific humidity
real(DP) :: xyr_TurKinEneDiffCoef (0:imax-1, 1:jmax, 0:kmax)
!
! Diffusion coefficient: turbulent kinetic energy
real(DP) :: xyz_TurKinEneDiffCoef (0:imax-1, 1:jmax, 1:kmax)
!
! Diffusion coefficient: turbulent kinetic energy
real(DP) :: xyr_TurKinEneTransCoef(0:imax-1, 1:jmax, 0:kmax)
!
! Transfer coefficient: turbulent kinetic energy
real(DP) :: xyr_TurKinEneFlux(0:imax-1, 1:jmax, 0:kmax)
!
! Turbulent energy flux
real(DP) :: xyz_CShe1(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CShe2(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CBuo1(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CBuo2(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CDis1(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CDis2(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_TurKinEneProShear(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_TurKinEneProBuoya(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xy_FricVelSq (0:imax-1, 1:jmax)
real(DP) :: xy_TurKinEneAtLB(0:imax-1, 1:jmax)
real(DP) :: xyza_TurKinEneMtx(0:imax-1, 1:jmax, 1:kmax, -1:1)
!
! Implicit matrix for turbulent kinetic energy
real(DP) :: xyz_TurKinEneVec(0:imax-1, 1:jmax, 1:kmax)
!
! Implicit vector for turbulent kinetic energy
real(DP) :: xyza_TurKinEneLUMtx (0:imax-1, 1:jmax, 1:kmax, -1:1)
! LU 行列.
! LU matrix
real(DP) :: xyz_DelTurKinEneLUVec(0:imax-1, 1:jmax, 1:kmax)
!
! Tendency of turbulent kinetic energy
real(DP) :: xyz_TurKinEneDiss(0:imax-1, 1:jmax, 1:kmax)
!
! Dissipation rate of turbulent kinetic energy (m2 s-3)
real(DP) :: xyz_TurKinEneNonZero(0:imax-1, 1:jmax, 1:kmax)
!
! Turbulent kinetic energy with offset (m2 s-2)
real(DP), parameter :: TurKinEneOffset = ( 1.0d-3 )**2 / 2.0_DP
logical :: FlagReCalc
!
! Flag for recalculation
logical :: a_FlagReCalcLocal (1)
logical :: a_FlagReCalcGlobal(1)
integer :: iloop
integer :: nloop
integer:: i ! 経度方向に回る DO ループ用作業変数
! Work variables for DO loop in longitude
integer:: j ! 緯度方向に回る DO ループ用作業変数
! Work variables for DO loop in latitude
integer:: k ! 鉛直方向に回る DO ループ用作業変数
! Work variables for DO loop in vertical direction
integer:: n ! 組成方向に回る DO ループ用作業変数
! Work variables for DO loop in dimension of constituents
! 実行文 ; Executable statement
!
! 初期化確認
! Initialization check
!
if ( .not. vdiffusion_my_inited ) then
call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
end if
! 計算時間計測開始
! Start measurement of computation time
!
call TimesetClockStart( module_name )
! Calculate turbulent kinetic energy with offset
!
xyz_TurKinEneNonZero = xyz_TurKinEne + TurKinEneOffset
!
! Calculation of vertical shear squared
do k = 1, kmax
if ( k == 1 ) then
xyz_DVelDzSq(:,:,k) = ( ( xyz_U(:,:,k+1) - xyz_U(:,:,k ) )**2 + ( xyz_V(:,:,k+1) - xyz_V(:,:,k ) )**2 ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k ) )**2
!!$ xyz_DVelDzSq(:,:,k) = &
!!$ & ( ( xyz_U(:,:,k+1) - 0.0_DP )**2 &
!!$ & + ( xyz_V(:,:,k+1) - 0.0_DP )**2 ) &
!!$ & / ( xyz_Height(:,:,k+1) - xy_SurfHeight )**2
else if ( k == kmax ) then
xyz_DVelDzSq(:,:,k) = ( ( xyz_U(:,:,k ) - xyz_U(:,:,k-1) )**2 + ( xyz_V(:,:,k ) - xyz_V(:,:,k-1) )**2 ) / ( xyz_Height(:,:,k ) - xyz_Height(:,:,k-1) )**2
else
xyz_DVelDzSq(:,:,k) = ( ( xyz_U(:,:,k+1) - xyz_U(:,:,k-1) )**2 + ( xyz_V(:,:,k+1) - xyz_V(:,:,k-1) )**2 ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k-1) )**2
end if
end do
! Calculation of static stability
do k = 1, kmax
if ( k == 1 ) then
xyz_StatStab(:,:,k) = Grav / ( xyz_VirTemp(:,:,k) / xyz_Exner(:,:,k) ) * ( xyz_VirTemp(:,:,k+1) / xyz_Exner(:,:,k+1) - xyz_VirTemp(:,:,k ) / xyz_Exner(:,:,k ) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k ) )
else if ( k == kmax ) then
xyz_StatStab(:,:,k) = Grav / ( xyz_VirTemp(:,:,k) / xyz_Exner(:,:,k) ) * ( xyz_VirTemp(:,:,k ) / xyz_Exner(:,:,k ) - xyz_VirTemp(:,:,k-1) / xyz_Exner(:,:,k-1) ) / ( xyz_Height(:,:,k ) - xyz_Height(:,:,k-1) )
else
xyz_StatStab(:,:,k) = Grav / ( xyz_VirTemp(:,:,k) / xyz_Exner(:,:,k) ) * ( xyz_VirTemp(:,:,k+1) / xyz_Exner(:,:,k+1) - xyz_VirTemp(:,:,k-1) / xyz_Exner(:,:,k-1) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k-1) )
end if
end do
! 混合距離の算出
! Calculate mixing length
!
do k = 1, kmax
xyz_MixLength(:,:,k) = FKarm * ( xyz_Height(:,:,k) - xy_SurfHeight ) / (1.0_DP + FKarm * ( xyz_Height(:,:,k) - xy_SurfHeight ) / MixLengthMax )
end do
! Limit mixing length and avoid zero
xyz_MixLength = min( xyz_MixLength, 0.53_DP * sqrt( 2.0_DP * xyz_TurKinEneNonZero / max( xyz_StatStab, 1.0d-10 ) ) ) + 1.0d-10
xyz_Gh = - xyz_MixLength**2 / ( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_StatStab
! Actually, xyz_Gm is not used below.
xyz_Gm = xyz_MixLength**2 / ( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_DVelDzSq
! Limit Gh
GhMin = - 0.53d0**2
GhMax = 1.0_DP / ( MYConstA2 * ( 12.0_DP * MYConstA1 + MYConstB1 + 3.0_DP * MYConstB2 ) )
xyz_Gh = max( GhMin, min( xyz_Gh, GhMax ) )
xyz_Sh = MYConstA2 * ( 1.0_DP - 6.0_DP * MYConstA1 / MYConstB1 ) / ( 1.0_DP - 3.0_DP * MYConstA2 * ( 6.0_DP * MYConstA1 + MYConstB2 ) * xyz_Gh )
xyz_Sm = ( MYConstA1 * ( 1.0_DP - 3.0_DP * MYConstC1 - 6.0_DP * MYConstA1 / MYConstB1 ) + 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) * xyz_Gh * xyz_Sh ) / ( 1.0_DP - 9.0_DP * MYConstA1 * MYConstA2 * xyz_Gh )
!!$ xyz_DShHatDTKE = &
!!$ & - 2.0_DP * MYConstA2 * ( 1.0_DP - 6.0_DP * MYConstA1 / MYConstB1 ) &
!!$ & / ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 3.0_DP * MYConstA2 * ( 6.0_DP * MYConstA1 + MYConstB2 ) * xyz_GhPrime )**2
!!$ xyz_DSmHatDTKE = &
!!$ & ( &
!!$ & 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) &
!!$ & * xyz_GhPrime * xyz_DShHatDTKE &
!!$ & * ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 9.0_DP * MYConstA1 * MYConstA2 * xyz_GhPrime ) &
!!$ & - 2.0_DP &
!!$ & * ( &
!!$ & MYConstA1 * ( 1.0_DP - 3.0_DP * MYConstC1 &
!!$ & - 6.0_DP * MYConstA1 / MYConstB1 ) &
!!$ & + 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) &
!!$ & * xyz_GhPrime * xyz_ShHat &
!!$ & ) &
!!$ & ) &
!!$ & / ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 9.0_DP * MYConstA1 * MYConstA2 * xyz_GhPrime )**2
! 拡散係数の計算
! Calculation of diffusion coefficient
!
xyz_VelDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_Sm
xyz_TempDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_Sh
!
do k = 0, kmax
if ( ( k == 0 ) .or. ( k == kmax ) ) then
xyr_VelDiffCoef (:,:,k) = 0.0_DP
xyr_TempDiffCoef(:,:,k) = 0.0_DP
else
xyr_VelDiffCoef (:,:,k) = ( xyz_VelDiffCoef (:,:,k) + xyz_VelDiffCoef (:,:,k+1) ) / 2.0_DP
xyr_TempDiffCoef(:,:,k) = ( xyz_TempDiffCoef(:,:,k) + xyz_TempDiffCoef(:,:,k+1) ) / 2.0_DP
end if
end do
!
do k = 1, kmax-1
do j = 1, jmax
do i = 0, imax-1
xyr_VelDiffCoef(i,j,k) = max( min( xyr_VelDiffCoef(i,j,k), VelDiffCoefMax ), VelDiffCoefMin )
xyr_TempDiffCoef(i,j,k) = max( min( xyr_TempDiffCoef(i,j,k), TempDiffCoefMax ), TempDiffCoefMin )
end do
end do
end do
!
xyr_QMixDiffCoef = xyr_TempDiffCoef
! 輸送係数とフラックスの計算
! Calculate transfer coefficient and flux
!
call VDiffusionTransCoefAndFlux( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_VirTemp, xyr_Press, xyz_Height, xyz_Exner, xyr_Exner, xyr_VelDiffCoef, xyr_TempDiffCoef, xyr_QMixDiffCoef, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef )
! Calculate tendency of turbulent kinetic energy
! Set diffusion coefficient for turbulent kinetic energy
xyz_TurKinEneDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * Stke
!
do k = 0, kmax
if ( k == 0 ) then
xyr_TurKinEneDiffCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,1)
else if ( k == kmax ) then
xyr_TurKinEneDiffCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,kmax)
else
xyr_TurKinEneDiffCoef(:,:,k) = ( xyz_TurKinEneDiffCoef(:,:,k) + xyz_TurKinEneDiffCoef(:,:,k+1) ) / 2.0_DP
end if
end do
! Calculate turbulent kinetic energy at lower boundary
!
xy_FricVelSq = sqrt( xy_SurfMomFluxX**2 + xy_SurfMomFluxY**2 ) / ( xyr_Press(:,:,0) / ( GasRDry * xyr_VirTemp(:,:,0) ) )
xy_TurKinEneAtLB = MYConstB1**(2.0_DP/3.0_DP) / 2.0_DP * xy_FricVelSq
xy_TurKinEneAtLB = xy_TurKinEneAtLB + TurKinEneOffset
! Calculate transfer coefficient and flux of turbulent kinetic energy
!
! When transfer coefficient at lower boundary is calculated,
! diffusion coefficient at mid-point of 1st layer is used.
! In addition, transfer coefficient at upper boundary is assumed
! to be zero.
k = 0
xyr_TurKinEneTransCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,1) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,1) - xy_SurfHeight )
do k = 1, kmax-1
xyr_TurKinEneTransCoef(:,:,k) = xyr_TurKinEneDiffCoef(:,:,k) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
end do
k = kmax
xyr_TurKinEneTransCoef(:,:,k) = 0.0_DP
!
do k = 1, kmax-1
xyr_TurKinEneFlux(:,:,k) = - xyr_TurKinEneTransCoef(:,:,k) * ( xyz_TurKinEneNonZero(:,:,k+1) - xyz_TurKinEneNonZero(:,:,k) )
end do
k = 0
xyr_TurKinEneFlux(:,:,k) = - xyr_TurKinEneTransCoef(:,:,k) * ( xyz_TurKinEneNonZero(:,:,k+1) - xy_TurKinEneAtLB )
k = kmax
xyr_TurKinEneFlux(:,:,k) = 0.0_DP
!!$ xyz_CShe1 = 2.0d0**1.5 * xyz_MixLength * xyz_SmHat &
!!$ & * xyz_DVelDzSq &
!!$! & * xyz_TurKinEne**1.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**1.5
!!$ xyz_CShe2 = 1.5_DP * 2.0d0**1.5 * xyz_MixLength * xyz_SmHat &
!!$ & * xyz_DVelDzSq &
!!$! & * xyz_TurKinEne**0.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**0.5
!!$ xyz_CBuo1 = - 2.0d0**1.5 * xyz_MixLength * xyz_ShHat &
!!$ & * xyz_StatStab &
!!$! & * xyz_TurKinEne**1.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**1.5
!!$ xyz_CBuo2 = - 1.5_DP * 2.0d0**1.5 * xyz_MixLength * xyz_ShHat &
!!$ & * xyz_StatStab &
!!$! & * xyz_TurKinEne**0.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**0.5
!!$ xyz_CDis1 = 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) &
!!$! & * xyz_TurKinEne**1.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**1.5
!!$ xyz_CDis2 = 1.5_DP * 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) &
!!$! & * xyz_TurKinEne**0.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**0.5
!!$! xyz_CShe1 = 2.0d0**1.5 * xyz_MixLength * xyz_SmHat &
!!$! & * xyz_DVelDzSq &
!!$!! & * xyz_TurKinEne**1.5
!!$! & * ( xyz_TurKinEne + TurKinEneNonZero )**1.5
!!$ xyz_CShe1 = 2.0d0**1.5 * xyz_MixLength * xyz_Sm &
!!$ & * xyz_DVelDzSq &
!!$! & * xyz_TurKinEne**1.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**0.5
!!$ xyz_CShe2 = 0.0_DP
!!$! xyz_CBuo1 = - 2.0d0**1.5 * xyz_MixLength * xyz_ShHat &
!!$! & * xyz_StatStab &
!!$!! & * xyz_TurKinEne**1.5
!!$! & * ( xyz_TurKinEne + TurKinEneNonZero )**1.5
!!$ xyz_CBuo1 = - 2.0d0**1.5 * xyz_MixLength * xyz_Sh &
!!$ & * xyz_StatStab &
!!$! & * xyz_TurKinEne**1.5
!!$ & * ( xyz_TurKinEne + TurKinEneNonZero )**0.5
!!$ xyz_CBuo2 = 0.0_DP
!!$ xyz_CDis1 = 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) &
!!$ & * xyz_TurKinEne**1.5
!!$! & * ( xyz_TurKinEne + TurKinEneNonZero )**1.5
!!$ xyz_CDis2 = 1.5_DP * 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) &
!!$ & * xyz_TurKinEne**0.5
!!$! & * ( xyz_TurKinEne + TurKinEneNonZero )**0.5
!!$ xyz_CShe1 = 2.0d0**1.5 * xyz_MixLength * xyz_DVelDzSq &
!!$ & * xyz_SmHat &
!!$ & * xyz_TurKinEneNonZero**1.5
!!$ xyz_CShe2 = 2.0d0**1.5 * xyz_MixLength * xyz_DVelDzSq &
!!$ & * ( xyz_DSmHatDTKE &
!!$ & * xyz_TurKinEneNonZero**1.5 &
!!$ & + 1.5_DP * xyz_SmHat &
!!$ & * xyz_TurKinEneNonZero**0.5 &
!!$ & )
!!$ xyz_CBuo1 = - 2.0d0**1.5 * xyz_MixLength * xyz_StatStab &
!!$ & * xyz_ShHat &
!!$ & * xyz_TurKinEneNonZero**1.5
!!$ xyz_CBuo2 = - 2.0d0**1.5 * xyz_MixLength * xyz_StatStab &
!!$ & * ( xyz_DShHatDTKE &
!!$ & * xyz_TurKinEneNonZero**1.5 &
!!$ & + 1.5_DP * xyz_ShHat &
!!$ & * xyz_TurKinEneNonZero**0.5 &
!!$ & )
!!$ xyz_CDis1 = 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) &
!!$ & * xyz_TurKinEneNonZero**1.5
!!$ xyz_CDis2 = 1.5_DP * 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) &
!!$ & * xyz_TurKinEneNonZero**0.5
xyz_CShe1 = sqrt( 2.0_DP ) * xyz_MixLength * xyz_DVelDzSq * xyz_Sm * sqrt( xyz_TurKinEneNonZero )
!!$ xyz_CShe2 = 0.5_DP * sqrt( 2.0_DP ) * xyz_MixLength * xyz_DVelDzSq &
!!$ & * xyz_Sm &
!!$ & / sqrt( xyz_TurKinEneNonZero )
xyz_CShe2 = 0.0_DP
xyz_CBuo1 = - sqrt( 2.0_DP ) * xyz_MixLength * xyz_StatStab * xyz_Sh * sqrt( xyz_TurKinEneNonZero )
!!$ xyz_CBuo2 = - 0.5_DP * sqrt( 2.0_DP ) * xyz_MixLength * xyz_StatStab &
!!$ & * xyz_Sh &
!!$ & / sqrt( xyz_TurKinEneNonZero )
xyz_CBuo2 = 0.0_DP
xyz_CDis1 = 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) * xyz_TurKinEneNonZero**1.5
xyz_CDis2 = 1.5_DP * 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) * xyz_TurKinEneNonZero**0.5
nloop = kmax
loop_solve : do iloop = 1, nloop
!
! Construct implicit matrix from transfer coefficient of vertical
! diffusion scheme (turbulent kinetic energy)
!
k = 1
xyza_TurKinEneMtx(:,:,k,-1) = 0.0_DP
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k ) + ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav * ( xyz_CShe2(:,:,k) + xyz_CBuo2(:,:,k) - xyz_CDis2(:,:,k) )
xyza_TurKinEneMtx(:,:,k, 1) = - xyr_TurKinEneTransCoef(:,:,k )
!
do k = 2, kmax-1
xyza_TurKinEneMtx(:,:,k,-1) = - xyr_TurKinEneTransCoef(:,:,k-1)
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k ) + ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav * ( xyz_CShe2(:,:,k) + xyz_CBuo2(:,:,k) - xyz_CDis2(:,:,k) )
xyza_TurKinEneMtx(:,:,k, 1) = - xyr_TurKinEneTransCoef(:,:,k )
end do
!
k = kmax
xyza_TurKinEneMtx(:,:,k,-1) = - xyr_TurKinEneTransCoef(:,:,k-1)
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k ) + ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav * ( xyz_CShe2(:,:,k) + xyz_CBuo2(:,:,k) - xyz_CDis2(:,:,k) )
xyza_TurKinEneMtx(:,:,k, 1) = 0.0_DP
do k = 1, kmax
xyz_TurKinEneVec(:,:,k) = - ( xyr_TurKinEneFlux(:,:,k) - xyr_TurKinEneFlux(:,:,k-1) ) - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav * ( xyz_CShe1(:,:,k) + xyz_CBuo1(:,:,k) - xyz_CDis1(:,:,k) )
end do
!
! Solve simultaneous linear equations by use of LU decomposition technique
!
xyza_TurKinEneLUMtx = xyza_TurKinEneMtx
!
call PhyImplLUDecomp3( xyza_TurKinEneLUMtx, imax * jmax, kmax )
xyz_DelTurKinEneLUVec = xyz_TurKinEneVec
!
call PhyImplLUSolve3( xyz_DelTurKinEneLUVec, xyza_TurKinEneLUMtx, 1, imax * jmax , kmax )
xyz_DTurKinEneDt = xyz_DelTurKinEneLUVec / ( 2.0_DP * DelTime )
! Calculation of dissipation rate of turbulent kinetic energy
!
! Calculate production rate of turbulent kinetic energy
! by shear and buoyancy
xyz_TurKinEneProShear = xyz_CShe1 + xyz_CShe2 * xyz_DTurKinEneDt * 2.0_DP * DelTime
xyz_TurKinEneProBuoya = xyz_CBuo1 + xyz_CBuo2 * xyz_DTurKinEneDt * 2.0_DP * DelTime
xyz_TurKinEneDiss = xyz_CDis1 + xyz_CDis2 * xyz_DTurKinEneDt * 2.0_DP * DelTime
! Check of turbulent kinetic energy dissipation rate
! If it is negative, tendency is recalculated without dissipation.
!
FlagReCalc = .false.
do k = 1, kmax
do j = 1, jmax
do i = 0, imax-1
if ( xyz_TurKinEneDiss(i,j,k) < 0.0_DP ) then
xyz_CDis1(i,j,k) = 0.0_DP
xyz_CDis2(i,j,k) = 0.0_DP
FlagReCalc = .true.
end if
end do
end do
end do
! Check convergence
a_FlagReCalcLocal = FlagReCalc
call MPIWrapperChkTrue( 1, a_FlagReCalcLocal, a_FlagReCalcGlobal )
if ( .not. a_FlagReCalcGlobal(1) ) exit loop_solve
end do loop_solve
!!$ write( 6, * ) TimeN, iloop
!!$ write( 6, * ) xyz_TurKinEne(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TempDiffCoef(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TurKinEneProShear(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TurKinEneProBuoya(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TurKinEneDiss(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_DTurKinEneDt(0,jmax/2+1,1:4)
! 拡散係数の出力
! Output diffusion coefficients
!
! 拡散係数出力
! Diffusion coeffficients output
!
call HistoryAutoPut( TimeN, 'VelDiffCoef', xyr_VelDiffCoef )
call HistoryAutoPut( TimeN, 'TempDiffCoef', xyr_TempDiffCoef )
call HistoryAutoPut( TimeN, 'QVapDiffCoef', xyr_QMixDiffCoef )
call HistoryAutoPut( TimeN, 'TKEPShear', xyz_TurKinEneProShear )
call HistoryAutoPut( TimeN, 'TKEPBuoy' , xyz_TurKinEneProBuoya )
call HistoryAutoPut( TimeN, 'TKEDiss' , xyz_TurKinEneDiss )
call HistoryAutoPut( TimeN, 'MixLength' , xyz_MixLength )
! 計算時間計測一時停止
! Pause measurement of computation time
!
call TimesetClockStop( module_name )
end subroutine VDiffusionMY25
| Subroutine : | |||
| xyr_MomFluxX(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_MomFluxY(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_HeatFlux(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax) : | real(DP), intent(in)
| ||
| xyz_DUDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyz_DVDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyz_DTempDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) : | real(DP), intent(in)
| ||
| xyz_Exner(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Exner(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_VelTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
|
フラックス (xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux). について, その他の引数を用いて補正し, 出力を行う.
Fluxes (xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux) are corrected by using other arguments, and the corrected values are output.
subroutine VDiffusionOutPut( xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyz_DUDt, xyz_DVDt, xyz_DTempDt, xyzf_DQMixDt, xyz_Exner, xyr_Exner, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef )
!
! フラックス (xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux).
! について, その他の引数を用いて補正し, 出力を行う.
!
! Fluxes (xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux) are
! corrected by using other arguments, and the corrected values are output.
!
! モジュール引用 ; USE statements
!
! 物理定数設定
! Physical constants settings
!
use constants, only: CpDry, LatentHeat
! $ L $ [J kg-1] .
! 凝結の潜熱.
! Latent heat of condensation
! 時刻管理
! Time control
!
use timeset, only: DelTime, TimeN, TimesetClockStart, TimesetClockStop
! ヒストリデータ出力
! History data output
!
use gtool_historyauto, only: HistoryAutoPut
! 宣言文 ; Declaration statements
!
implicit none
real(DP), intent(in):: xyr_MomFluxX (0:imax-1, 1:jmax, 0:kmax)
! 東西方向運動量フラックス.
! Eastward wind flux
real(DP), intent(in):: xyr_MomFluxY (0:imax-1, 1:jmax, 0:kmax)
! 南北方向運動量フラックス.
! Northward momentum flux
real(DP), intent(in):: xyr_HeatFlux (0:imax-1, 1:jmax, 0:kmax)
! 熱フラックス.
! Heat flux
real(DP), intent(in):: xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax)
! 質量フラックス.
! Mass flux of constituents
real(DP), intent(in):: xyz_DUDt (0:imax-1, 1:jmax, 1:kmax)
! $ \DP{u}{t} $ . 東西風速変化.
! Eastward wind tendency
real(DP), intent(in):: xyz_DVDt (0:imax-1, 1:jmax, 1:kmax)
! $ \DP{v}{t} $ . 南北風速変化.
! Northward wind tendency
real(DP), intent(in):: xyz_DTempDt (0:imax-1, 1:jmax, 1:kmax)
! $ \DP{T}{t} $ . 温度変化.
! Temperature tendency
real(DP), intent(in):: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
! $ \DP{q}{t} $ . 混合比変化.
! Mass mixing ratio tendency
real(DP), intent(in):: xyz_Exner (0:imax-1, 1:jmax, 1:kmax)
! Exner 関数 (整数レベル).
! Exner function (full level)
real(DP), intent(in):: xyr_Exner (0:imax-1, 1:jmax, 0:kmax)
! Exner 関数 (半整数レベル).
! Exner function (half level)
real(DP), intent(in):: xyr_VelTransCoef (0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:運動量.
! Transfer coefficient: velocity
real(DP), intent(in):: xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:温度.
! Transfer coefficient: temperature
real(DP), intent(in):: xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:質量.
! Transfer coefficient: mass of constituents
! 出力のための作業変数
! Work variables for output
!
real(DP):: xyr_MomFluxXCor (0:imax-1, 1:jmax, 0:kmax)
! 東西方向運動量フラックス.
! Eastward momentum flux
real(DP):: xyr_MomFluxYCor (0:imax-1, 1:jmax, 0:kmax)
! 南北方向運動量フラックス.
! Northward momentum flux
real(DP):: xyr_HeatFluxCor (0:imax-1, 1:jmax, 0:kmax)
! 熱フラックス.
! Heat flux
real(DP):: xyrf_QMixFluxCor(0:imax-1, 1:jmax, 0:kmax, 1:ncmax)
! 質量フラックス.
! Mass flux of constituents
! 作業変数
! Work variables
!
integer:: i ! 経度方向に回る DO ループ用作業変数
! Work variables for DO loop in longitude
integer:: j ! 緯度方向に回る DO ループ用作業変数
! Work variables for DO loop in latitude
integer:: k ! 鉛直方向に回る DO ループ用作業変数
! Work variables for DO loop in vertical direction
integer:: n ! 組成方向に回る DO ループ用作業変数
! Work variables for DO loop in dimension of constituents
real(DP):: LCp
! $ L / C_p $ [K].
! 実行文 ; Executable statement
!
! 初期化確認
! Initialization check
!
if ( .not. vdiffusion_my_inited ) then
call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
end if
! 計算時間計測開始
! Start measurement of computation time
!
call TimesetClockStart( module_name )
! 風速, 温度, 比湿フラックス補正
! Correct fluxes of wind, temperature, specific humidity
!
LCp = LatentHeat / CpDry
do k = 1, kmax-1
do j = 1, jmax
do i = 0, imax-1
xyr_MomFluxXCor( i,j,k ) = xyr_MomFluxX( i,j,k ) + ( xyz_DUDt( i,j,k ) - xyz_DUDt( i,j,k+1 ) ) * xyr_VelTransCoef( i,j,k ) * DelTime
xyr_MomFluxYCor( i,j,k ) = xyr_MomFluxY( i,j,k ) + ( xyz_DVDt( i,j,k ) - xyz_DVDt( i,j,k+1 ) ) * xyr_VelTransCoef( i,j,k ) * DelTime
xyr_HeatFluxCor( i,j,k ) = xyr_HeatFlux( i,j,k ) + ( xyz_DTempDt( i,j,k ) / xyz_Exner( i,j,k ) - xyz_DTempDt( i,j,k+1 ) / xyz_Exner( i,j,k+1 ) ) * CpDry * xyr_TempTransCoef( i,j,k ) * xyr_Exner( i,j,k ) * DelTime
end do
end do
end do
do n = 1, ncmax
do k = 1, kmax-1
do j = 1, jmax
do i = 0, imax-1
xyrf_QMixFluxCor( i,j,k,n ) = xyrf_QMixFlux( i,j,k,n ) + ( xyzf_DQMixDt( i,j,k,n ) - xyzf_DQMixDt( i,j,k+1,n ) ) * CpDry * xyr_QMixTransCoef( i,j,k ) * LCp * DelTime
end do
end do
end do
end do
xyr_MomFluxXCor (:,:,0) = 0.
xyr_MomFluxXCor (:,:,kmax) = 0.
xyr_MomFluxYCor (:,:,0) = 0.
xyr_MomFluxYCor (:,:,kmax) = 0.
xyr_HeatFluxCor (:,:,0) = 0.
xyr_HeatFluxCor (:,:,kmax) = 0.
do n = 1, ncmax
xyrf_QMixFluxCor(:,:,0,n) = 0.
xyrf_QMixFluxCor(:,:,kmax,n) = 0.
end do
! MEMO
! Output values of surface fluxes in MomFluxX, MomFluxY, HeatFlux, and QVapFlux
! are not correct. (YOT, 2009/08/14)
! Please refer to output variables, 'TauX', 'TauY', 'Sens', and 'Evap' for those
! values. (YOT, 2011/05/28)
! ヒストリデータ出力
! History data output
!
call HistoryAutoPut( TimeN, 'MomFluxX', xyr_MomFluxXCor )
call HistoryAutoPut( TimeN, 'MomFluxY', xyr_MomFluxYCor )
call HistoryAutoPut( TimeN, 'HeatFlux', xyr_HeatFluxCor )
call HistoryAutoPut( TimeN, 'QVapFlux', xyrf_QMixFluxCor )
call HistoryAutoPut( TimeN, 'DUDtVDiff' , xyz_DUDt )
call HistoryAutoPut( TimeN, 'DVDtVDiff' , xyz_DVDt )
call HistoryAutoPut( TimeN, 'DTempDtVDiff', xyz_DTempDt )
call HistoryAutoPut( TimeN, 'DQVapDtVDiff', xyzf_DQMixDt(:,:,:,IndexH2OVap) )
! 計算時間計測一時停止
! Pause measurement of computation time
!
call TimesetClockStop( module_name )
end subroutine VDiffusionOutPut
| Variable : | |||
| BulkRiNumMin : | real(DP), save
|
| Variable : | |||
| ConstDiffCoefH : | real(DP), save
|
| Variable : | |||
| ConstDiffCoefM : | real(DP), save
|
| Variable : | |||
| FlagConstDiffCoef : | logical , save
|
| Variable : | |||
| TempDiffCoefMax : | real(DP), save
|
| Variable : | |||
| TempDiffCoefMin : | real(DP), save
|
| Subroutine : | |||
| xy_SurfHeight(0:imax-1,1:jmax) : | real(DP), intent(in)
| ||
| xyr_Height(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_DVelDz(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_BulkRiNum(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_VelDiffCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_TempDiffCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_QMixDiffCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
|
鉛直拡散フラックスを計算します.
Vertical diffusion flux is calculated.
subroutine VDiffCoefficient( xy_SurfHeight, xyr_Height, xyr_DVelDz, xyr_BulkRiNum, xyr_VelDiffCoef, xyr_TempDiffCoef, xyr_QMixDiffCoef )
!
! 鉛直拡散フラックスを計算します.
!
! Vertical diffusion flux is calculated.
!
! モジュール引用 ; USE statements
!
! 時刻管理
! Time control
!
use timeset, only: TimeN, TimesetClockStart, TimesetClockStop
! 物理定数設定
! Physical constants settings
!
use constants, only: FKarm
! $ k $ .
! カルマン定数.
! Karman constant
! ヒストリデータ出力
! History data output
!
use gtool_historyauto, only: HistoryAutoPut
! 宣言文 ; Declaration statements
!
implicit none
real(DP), intent(in):: xy_SurfHeight (0:imax-1,1:jmax)
! $ z_s $ . 地表面高度.
! Surface height.
real(DP), intent(in):: xyr_Height (0:imax-1, 1:jmax, 0:kmax)
! 高度 (半整数レベル).
! Height (half level)
real(DP), intent(in):: xyr_DVelDz (0:imax-1, 1:jmax, 0:kmax)
! $ \DD{|\Dvect{v}|}{z} $
real(DP), intent(in):: xyr_BulkRiNum (0:imax-1, 1:jmax, 0:kmax)
! バルク $ R_i $ 数.
! Bulk $ R_i $
real(DP), intent(out):: xyr_VelDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:運動量.
! Diffusion coefficient: velocity
real(DP), intent(out):: xyr_TempDiffCoef(0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:温度.
! Transfer coefficient: temperature
real(DP), intent(out):: xyr_QMixDiffCoef(0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:質量
! Diffusion coefficient: mass of constituents
! 作業変数
! Work variables
!
real(DP):: xyr_FluxRiNum (0:imax-1, 1:jmax, 0:kmax)
! フラックス $ R_i $ 数.
! Flux $ R_i $ number
real(DP):: xyr_Sh (0:imax-1, 1:jmax, 0:kmax)
! $ S_h $ (温度, 比湿).
! $ S_h $ (temperature, specific humidity)
real(DP):: xyr_Sm (0:imax-1, 1:jmax, 0:kmax)
! $ S_m $ (運動量).
! $ S_m $ (momentum)
real(DP):: xyr_MixLength (0:imax-1, 1:jmax, 0:kmax)
! 混合距離.
! Mixing length
real(DP):: Alpha1, Alpha2
real(DP):: Beta1, Beta2, Beta3, Beta4
real(DP):: Gamma1, Gamma2
real(DP):: CrtlFluxRiNum
real(DP):: xyr_TurKinEne(0:imax-1, 1:jmax, 0:kmax)
!
! Turbulent kinetic energy
integer:: i ! 経度方向に回る DO ループ用作業変数
! Work variables for DO loop in longitude
integer:: j ! 緯度方向に回る DO ループ用作業変数
! Work variables for DO loop in latitude
integer:: k ! 鉛直方向に回る DO ループ用作業変数
! Work variables for DO loop in vertical direction
! 実行文 ; Executable statement
!
! 初期化確認
! Initialization check
!
if ( .not. vdiffusion_my_inited ) then
call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
end if
! 定数計算
! Calculate constants
!
Gamma1 = ( 1. / 3. ) - ( 2. * MYConstA1 / MYConstB1 )
Gamma2 = ( MYConstB2 / MYConstB1 ) + ( 6. * MYConstA1 / MYConstB1 )
Alpha1 = 3. * MYConstA2 * Gamma1
Alpha2 = 3. * MYConstA2 * ( Gamma1 + Gamma2 )
Beta1 = MYConstA1 * MYConstB1 * ( Gamma1 - MYConstC1 )
Beta2 = MYConstA1 * ( MYConstB1 * ( Gamma1 - MYConstC1 ) + 6. * MYConstA1 + 3. * MYConstA2 )
Beta3 = MYConstA2 * MYConstB1 * Gamma1
Beta4 = MYConstA2 * ( MYConstB1 * ( Gamma1 + Gamma2 ) - 3. * MYConstA1 )
CrtlFluxRiNum = Gamma1 / ( Gamma1 + Gamma2 )
! フラックス $ R_i $ 数の算出
! Calculate flux $ R_i $ number
!
xyr_FluxRiNum = ( Beta1 + Beta4 * xyr_BulkRiNum - sqrt( ( Beta1 + Beta4 * xyr_BulkRiNum )**2 - 4. * Beta2 * Beta3 * xyr_BulkRiNum ) ) / ( 2. * Beta2 )
! $ \tilde{S_h} $ と $ \tilde{S_m} $ の算出
! Calculate $ \tilde{S_h} $ and $ \tilde{S_m} $
!
xyr_Sh(:,:,kmax) = 0.
xyr_Sm(:,:,kmax) = 0.
do k = 0, kmax-1
do i = 0, imax-1
do j = 1, jmax
if ( xyr_FluxRiNum(i,j,k) < CrtlFluxRiNum ) then
xyr_Sh(i,j,k) = ( Alpha1 - Alpha2 * xyr_FluxRiNum(i,j,k) ) / ( 1. - 1. * xyr_FluxRiNum(i,j,k) )
xyr_Sm(i,j,k) = ( Beta1 - Beta2 * xyr_FluxRiNum(i,j,k) ) / ( Beta3 - Beta4 * xyr_FluxRiNum(i,j,k) ) * xyr_Sh(i,j,k)
xyr_Sh(i,j,k) = max( xyr_Sh(i,j,k), ShMin )
xyr_Sm(i,j,k) = max( xyr_Sm(i,j,k), SmMin )
else
xyr_Sh(i,j,k) = ShMin
xyr_Sm(i,j,k) = SmMin
end if
end do
end do
end do
! 混合距離の算出
! Calculate mixing length
!
do k = 0, kmax
xyr_MixLength(:,:,k) = FKarm * ( xyr_Height(:,:,k) - xy_SurfHeight(:,:) ) / (1. + FKarm * ( xyr_Height(:,:,k) - xy_SurfHeight(:,:) ) / MixLengthMax )
end do
! 拡散係数の算出
! Calculate diffusion constants
!
xyr_VelDiffCoef = xyr_MixLength**2 * xyr_DVelDz * sqrt ( MYConstB1 * ( 1. - xyr_FluxRiNum ) * xyr_Sm ) * xyr_Sm
xyr_TempDiffCoef = xyr_MixLength ** 2 * xyr_DVelDz * sqrt ( MYConstB1 * ( 1. - xyr_FluxRiNum ) * xyr_Sm ) * xyr_Sh
do k = 0, kmax-1
do i = 0, imax-1
do j = 1, jmax
xyr_VelDiffCoef(i,j,k) = max( min( xyr_VelDiffCoef(i,j,k), VelDiffCoefMax ), VelDiffCoefMin )
xyr_TempDiffCoef(i,j,k) = max( min( xyr_TempDiffCoef(i,j,k), TempDiffCoefMax ), TempDiffCoefMin )
end do
end do
end do
xyr_QMixDiffCoef = xyr_TempDiffCoef
xyr_VelDiffCoef (:,:,0) = 0.
xyr_VelDiffCoef (:,:,kmax) = 0.
xyr_TempDiffCoef(:,:,0) = 0.
xyr_TempDiffCoef(:,:,kmax) = 0.
xyr_QMixDiffCoef(:,:,0) = 0.
xyr_QMixDiffCoef(:,:,kmax) = 0.
! Calculation of turbulent kinetic energy
! Turbulent kinetic energy is diagnosed.
xyr_TurKinEne = MYConstB1 * xyr_MixLength**2 * ( 1.0_DP - xyr_FluxRiNum ) * xyr_Sm * xyr_DVelDz**2 / 2.0_DP
xyr_TurKinEne(:,:,0 ) = 0.0_DP
xyr_TurKinEne(:,:,kmax) = 0.0_DP
! ヒストリデータ出力
! History data output
!
call HistoryAutoPut( TimeN, 'TurKinEne', xyr_TurKinEne )
end subroutine VDiffCoefficient
| Subroutine : | |||
| xyz_U(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyz_V(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) : | real(DP), intent(in)
| ||
| xyz_Temp(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Temp(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_VirTemp(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_VirTemp(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_Press(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xy_SurfHeight(0:imax-1,1:jmax) : | real(DP), intent(in)
| ||
| xyz_Height(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Height(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_Exner(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Exner(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_TurKinEne(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xy_SurfMomFluxX(0:imax-1, 1:jmax) : | real(DP), intent(in)
| ||
| xy_SurfMomFluxY(0:imax-1, 1:jmax) : | real(DP), intent(in)
| ||
| xyr_MomFluxX(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_MomFluxY(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_HeatFlux(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax) : | real(DP), intent(out)
| ||
| xyr_VelTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyz_DTurKinEneDt(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(out)
|
鉛直拡散フラックスを計算します.
Vertical diffusion flux is calculated by use of MY2.5 model.
subroutine VDiffusionMY25Testing( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_Temp, xyz_VirTemp, xyr_VirTemp, xyr_Press, xy_SurfHeight, xyz_Height, xyr_Height, xyz_Exner, xyr_Exner, xyz_TurKinEne, xy_SurfMomFluxX, xy_SurfMomFluxY, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef, xyz_DTurKinEneDt )
!
! 鉛直拡散フラックスを計算します.
!
! Vertical diffusion flux is calculated by use of MY2.5 model.
!
! モジュール引用 ; USE statements
!
! 物理定数設定
! Physical constants settings
!
use constants, only: FKarm, Grav, GasRDry, CpDry
! $ C_p $ [J kg-1 K-1].
! 乾燥大気の定圧比熱.
! Specific heat of air at constant pressure
! 時刻管理
! Time control
!
use timeset, only: DelTime, TimeN, TimesetClockStart, TimesetClockStop
! ヒストリデータ出力
! History data output
!
use gtool_historyauto, only: HistoryAutoPut
! MPI 関連ルーチン
! MPI related routines
!
use mpi_wrapper, only : MPIWrapperChkTrue
! 陰解法による時間積分のためのルーチン
! Routines for time integration with implicit scheme
!
use phy_implicit_utils, only : PhyImplLUDecomp3, PhyImplLUSolve3
! 宣言文 ; Declaration statements
!
implicit none
real(DP), intent(in):: xyz_U (0:imax-1, 1:jmax, 1:kmax)
! $ u $ . 東西風速. Eastward wind
real(DP), intent(in):: xyz_V (0:imax-1, 1:jmax, 1:kmax)
! $ v $ . 南北風速. Northward wind
real(DP), intent(in):: xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
! $ q $ . 質量混合比. Mass mixing ratio
real(DP), intent(in):: xyz_Temp (0:imax-1, 1:jmax, 1:kmax)
! $ T $ . 温度. Temperature
real(DP), intent(in):: xyr_Temp (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{T} $ . 温度 (半整数レベル).
! Temperature (half level)
real(DP), intent(in):: xyz_VirTemp (0:imax-1, 1:jmax, 1:kmax)
! $ T_v $ . 仮温度. Virtual temperature
real(DP), intent(in):: xyr_VirTemp (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{T}_v $ . 仮温度 (半整数レベル).
! Virtual temperature (half level)
real(DP), intent(in):: xyr_Press (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{p} $ . 気圧 (半整数レベル).
! Air pressure (half level)
real(DP), intent(in):: xy_SurfHeight (0:imax-1,1:jmax)
! $ z_s $ . 地表面高度.
! Surface height.
real(DP), intent(in):: xyz_Height (0:imax-1, 1:jmax, 1:kmax)
! 高度 (整数レベル).
! Height (full level)
real(DP), intent(in):: xyr_Height (0:imax-1, 1:jmax, 0:kmax)
! 高度 (半整数レベル).
! Height (half level)
real(DP), intent(in):: xyz_Exner (0:imax-1, 1:jmax, 1:kmax)
! Exner 関数 (整数レベル).
! Exner function (full level)
real(DP), intent(in):: xyr_Exner (0:imax-1, 1:jmax, 0:kmax)
! Exner 関数 (半整数レベル).
! Exner function (half level)
real(DP), intent(in):: xyz_TurKinEne(0:imax-1, 1:jmax, 1:kmax)
!
! Turbulent kinetic energy (m2 s-2)
real(DP), intent(in):: xy_SurfMomFluxX (0:imax-1, 1:jmax)
!
! Eastward momentum flux at surface
real(DP), intent(in):: xy_SurfMomFluxY (0:imax-1, 1:jmax)
!
! Northward momentum flux at surface
real(DP), intent(out):: xyr_MomFluxX (0:imax-1, 1:jmax, 0:kmax)
! 東西方向運動量フラックス.
! Eastward momentum flux
real(DP), intent(out):: xyr_MomFluxY (0:imax-1, 1:jmax, 0:kmax)
! 南北方向運動量フラックス.
! Northward momentum flux
real(DP), intent(out):: xyr_HeatFlux (0:imax-1, 1:jmax, 0:kmax)
! 熱フラックス.
! Heat flux
real(DP), intent(out):: xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax)
! 質量フラックス.
! Mass flux of compositions
real(DP), intent(out):: xyr_VelTransCoef (0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:運動量.
! Transfer coefficient: velocity
real(DP), intent(out):: xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:温度.
! Transfer coefficient: temperature
real(DP), intent(out):: xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:質量.
! Transfer coefficient: mass (composition)
real(DP), intent(out):: xyz_DTurKinEneDt (0:imax-1, 1:jmax, 1:kmax)
!
! Tendency of turbulent kinetic energy
! 作業変数
! Work variables
!
real(DP) :: xyz_MixLength(0:imax-1, 1:jmax, 1:kmax)
! 混合距離.
! Mixing length
real(DP) :: xyz_DVelDzSq(0:imax-1, 1:jmax, 1:kmax)
!
! Vertical shear squared (s-2)
real(DP) :: xyz_StatStab(0:imax-1, 1:jmax, 1:kmax)
!
! Static stability (s-2)
real(DP) :: GhMin
!
! Minimum of G_h
real(DP) :: GhMax
!
! Maximum of G_h
real(DP) :: xyz_Gm(0:imax-1, 1:jmax, 1:kmax)
!
! G_m
real(DP) :: xyz_Gh(0:imax-1, 1:jmax, 1:kmax)
!
! G_h
!!$ real(DP) :: xyz_SmHat(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! \hat{S}_M
!!$ real(DP) :: xyz_ShHat(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! \hat{S}_h
!!$ real(DP) :: xyz_DSmHatDTKE(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! derivative of \hat{S}_M
!!$ real(DP) :: xyz_DShHatDTKE(0:imax-1, 1:jmax, 1:kmax)
!!$ !
!!$ ! derivative of \hat{S}_h
real(DP) :: xyz_Sm(0:imax-1, 1:jmax, 1:kmax)
!
! S_M
real(DP) :: xyz_Sh(0:imax-1, 1:jmax, 1:kmax)
!
! S_h
real(DP), parameter :: Stke = 0.2_DP
!
! S_{TKE} = 0.2
real(DP) :: xyz_VelDiffCoef (0:imax-1, 1:jmax, 1:kmax)
! 拡散係数:運動量.
! Diffusion coefficient: velocity
real(DP) :: xyz_TempDiffCoef (0:imax-1, 1:jmax, 1:kmax)
! 拡散係数:温度.
! Transfer coefficient: temperature
real(DP) :: xyr_VelDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:運動量.
! Diffusion coefficient: velocity
real(DP) :: xyr_TempDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:温度.
! Transfer coefficient: temperature
real(DP) :: xyr_QMixDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:比湿.
! Diffusion coefficient: specific humidity
real(DP) :: xyr_TurKinEneDiffCoef (0:imax-1, 1:jmax, 0:kmax)
!
! Diffusion coefficient: turbulent kinetic energy
real(DP) :: xyz_TurKinEneDiffCoef (0:imax-1, 1:jmax, 1:kmax)
!
! Diffusion coefficient: turbulent kinetic energy
real(DP) :: xyr_TurKinEneTransCoef(0:imax-1, 1:jmax, 0:kmax)
!
! Transfer coefficient: turbulent kinetic energy
real(DP) :: xyr_TurKinEneFlux(0:imax-1, 1:jmax, 0:kmax)
!
! Turbulent energy flux
real(DP) :: xyz_DTurKinEneDtVDiff(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CShe1(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CShe2(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CBuo1(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CBuo2(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CDis1(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_CDis2(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_TurKinEneProShear(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xyz_TurKinEneProBuoya(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: xy_FricVelSq (0:imax-1, 1:jmax)
real(DP) :: xy_TurKinEneAtLB(0:imax-1, 1:jmax)
real(DP) :: xyza_TurKinEneMtx(0:imax-1, 1:jmax, 1:kmax, -1:1)
!
! Implicit matrix for turbulent kinetic energy
real(DP) :: xyz_TurKinEneVec(0:imax-1, 1:jmax, 1:kmax)
!
! Implicit vector for turbulent kinetic energy
real(DP) :: xyza_TurKinEneLUMtx (0:imax-1, 1:jmax, 1:kmax, -1:1)
! LU 行列.
! LU matrix
real(DP) :: xyz_DelTurKinEneLUVec(0:imax-1, 1:jmax, 1:kmax)
!
! Tendency of turbulent kinetic energy
real(DP) :: xyz_TurKinEneDiss(0:imax-1, 1:jmax, 1:kmax)
!
! Dissipation rate of turbulent kinetic energy (m2 s-3)
real(DP) :: xyz_TurKinEneNonZero(0:imax-1, 1:jmax, 1:kmax)
!
! Turbulent kinetic energy with offset (m2 s-2)
real(DP), parameter :: TurKinEneOffset = ( 1.0d-3 )**2 / 2.0_DP
logical :: FlagReCalc
!
! Flag for recalculation
logical :: a_FlagReCalcLocal (1)
logical :: a_FlagReCalcGlobal(1)
integer :: iloop
integer :: nloop
integer:: i ! 経度方向に回る DO ループ用作業変数
! Work variables for DO loop in longitude
integer:: j ! 緯度方向に回る DO ループ用作業変数
! Work variables for DO loop in latitude
integer:: k ! 鉛直方向に回る DO ループ用作業変数
! Work variables for DO loop in vertical direction
integer:: n ! 組成方向に回る DO ループ用作業変数
! Work variables for DO loop in dimension of constituents
real(DP) :: xyz_TurKinEneTentative(0:imax-1, 1:jmax, 1:kmax)
real(DP) :: DelTimeSubStep
! 実行文 ; Executable statement
!
! 初期化確認
! Initialization check
!
if ( .not. vdiffusion_my_inited ) then
call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
end if
! 計算時間計測開始
! Start measurement of computation time
!
call TimesetClockStart( module_name )
! Calculate turbulent kinetic energy with offset
!
xyz_TurKinEneNonZero = xyz_TurKinEne + TurKinEneOffset
!
! Calculation of vertical shear squared
do k = 1, kmax
if ( k == 1 ) then
xyz_DVelDzSq(:,:,k) = ( ( xyz_U(:,:,k+1) - xyz_U(:,:,k ) )**2 + ( xyz_V(:,:,k+1) - xyz_V(:,:,k ) )**2 ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k ) )**2
!!$ xyz_DVelDzSq(:,:,k) = &
!!$ & ( ( xyz_U(:,:,k+1) - 0.0_DP )**2 &
!!$ & + ( xyz_V(:,:,k+1) - 0.0_DP )**2 ) &
!!$ & / ( xyz_Height(:,:,k+1) - xy_SurfHeight )**2
else if ( k == kmax ) then
xyz_DVelDzSq(:,:,k) = ( ( xyz_U(:,:,k ) - xyz_U(:,:,k-1) )**2 + ( xyz_V(:,:,k ) - xyz_V(:,:,k-1) )**2 ) / ( xyz_Height(:,:,k ) - xyz_Height(:,:,k-1) )**2
else
xyz_DVelDzSq(:,:,k) = ( ( xyz_U(:,:,k+1) - xyz_U(:,:,k-1) )**2 + ( xyz_V(:,:,k+1) - xyz_V(:,:,k-1) )**2 ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k-1) )**2
end if
end do
! Calculation of static stability
do k = 1, kmax
if ( k == 1 ) then
xyz_StatStab(:,:,k) = Grav / ( xyz_VirTemp(:,:,k) / xyz_Exner(:,:,k) ) * ( xyz_VirTemp(:,:,k+1) / xyz_Exner(:,:,k+1) - xyz_VirTemp(:,:,k ) / xyz_Exner(:,:,k ) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k ) )
else if ( k == kmax ) then
xyz_StatStab(:,:,k) = Grav / ( xyz_VirTemp(:,:,k) / xyz_Exner(:,:,k) ) * ( xyz_VirTemp(:,:,k ) / xyz_Exner(:,:,k ) - xyz_VirTemp(:,:,k-1) / xyz_Exner(:,:,k-1) ) / ( xyz_Height(:,:,k ) - xyz_Height(:,:,k-1) )
else
xyz_StatStab(:,:,k) = Grav / ( xyz_VirTemp(:,:,k) / xyz_Exner(:,:,k) ) * ( xyz_VirTemp(:,:,k+1) / xyz_Exner(:,:,k+1) - xyz_VirTemp(:,:,k-1) / xyz_Exner(:,:,k-1) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k-1) )
end if
end do
! 混合距離の算出
! Calculate mixing length
!
do k = 1, kmax
xyz_MixLength(:,:,k) = FKarm * ( xyz_Height(:,:,k) - xy_SurfHeight ) / (1.0_DP + FKarm * ( xyz_Height(:,:,k) - xy_SurfHeight ) / MixLengthMax )
end do
! Limit mixing length and avoid zero
xyz_MixLength = min( xyz_MixLength, 0.53_DP * sqrt( 2.0_DP * xyz_TurKinEneNonZero / max( xyz_StatStab, 1.0d-10 ) ) ) + 1.0d-10
xyz_Gh = - xyz_MixLength**2 / ( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_StatStab
! Actually, xyz_Gm is not used below.
xyz_Gm = xyz_MixLength**2 / ( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_DVelDzSq
! Limit Gh
GhMin = - 0.53d0**2
GhMax = 1.0_DP / ( MYConstA2 * ( 12.0_DP * MYConstA1 + MYConstB1 + 3.0_DP * MYConstB2 ) )
xyz_Gh = max( GhMin, min( xyz_Gh, GhMax ) )
xyz_Sh = MYConstA2 * ( 1.0_DP - 6.0_DP * MYConstA1 / MYConstB1 ) / ( 1.0_DP - 3.0_DP * MYConstA2 * ( 6.0_DP * MYConstA1 + MYConstB2 ) * xyz_Gh )
xyz_Sm = ( MYConstA1 * ( 1.0_DP - 3.0_DP * MYConstC1 - 6.0_DP * MYConstA1 / MYConstB1 ) + 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) * xyz_Gh * xyz_Sh ) / ( 1.0_DP - 9.0_DP * MYConstA1 * MYConstA2 * xyz_Gh )
!!$ xyz_DShHatDTKE = &
!!$ & - 2.0_DP * MYConstA2 * ( 1.0_DP - 6.0_DP * MYConstA1 / MYConstB1 ) &
!!$ & / ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 3.0_DP * MYConstA2 * ( 6.0_DP * MYConstA1 + MYConstB2 ) * xyz_GhPrime )**2
!!$ xyz_DSmHatDTKE = &
!!$ & ( &
!!$ & 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) &
!!$ & * xyz_GhPrime * xyz_DShHatDTKE &
!!$ & * ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 9.0_DP * MYConstA1 * MYConstA2 * xyz_GhPrime ) &
!!$ & - 2.0_DP &
!!$ & * ( &
!!$ & MYConstA1 * ( 1.0_DP - 3.0_DP * MYConstC1 &
!!$ & - 6.0_DP * MYConstA1 / MYConstB1 ) &
!!$ & + 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) &
!!$ & * xyz_GhPrime * xyz_ShHat &
!!$ & ) &
!!$ & ) &
!!$ & / ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 9.0_DP * MYConstA1 * MYConstA2 * xyz_GhPrime )**2
! 拡散係数の計算
! Calculation of diffusion coefficient
!
xyz_VelDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_Sm
xyz_TempDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_Sh
!
do k = 0, kmax
if ( ( k == 0 ) .or. ( k == kmax ) ) then
xyr_VelDiffCoef (:,:,k) = 0.0_DP
xyr_TempDiffCoef(:,:,k) = 0.0_DP
else
xyr_VelDiffCoef (:,:,k) = ( xyz_VelDiffCoef (:,:,k) + xyz_VelDiffCoef (:,:,k+1) ) / 2.0_DP
xyr_TempDiffCoef(:,:,k) = ( xyz_TempDiffCoef(:,:,k) + xyz_TempDiffCoef(:,:,k+1) ) / 2.0_DP
end if
end do
!
do k = 1, kmax-1
do j = 1, jmax
do i = 0, imax-1
xyr_VelDiffCoef(i,j,k) = max( min( xyr_VelDiffCoef(i,j,k), VelDiffCoefMax ), VelDiffCoefMin )
xyr_TempDiffCoef(i,j,k) = max( min( xyr_TempDiffCoef(i,j,k), TempDiffCoefMax ), TempDiffCoefMin )
end do
end do
end do
!
xyr_QMixDiffCoef = xyr_TempDiffCoef
! 輸送係数とフラックスの計算
! Calculate transfer coefficient and flux
!
call VDiffusionTransCoefAndFlux( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_VirTemp, xyr_Press, xyz_Height, xyz_Exner, xyr_Exner, xyr_VelDiffCoef, xyr_TempDiffCoef, xyr_QMixDiffCoef, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef )
! Calculate tendency of turbulent kinetic energy
! Set diffusion coefficient for turbulent kinetic energy
xyz_TurKinEneDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * Stke
!
do k = 0, kmax
if ( k == 0 ) then
xyr_TurKinEneDiffCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,1)
else if ( k == kmax ) then
xyr_TurKinEneDiffCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,kmax)
else
xyr_TurKinEneDiffCoef(:,:,k) = ( xyz_TurKinEneDiffCoef(:,:,k) + xyz_TurKinEneDiffCoef(:,:,k+1) ) / 2.0_DP
end if
end do
! Calculate turbulent kinetic energy at lower boundary
!
xy_FricVelSq = sqrt( xy_SurfMomFluxX**2 + xy_SurfMomFluxY**2 ) / ( xyr_Press(:,:,0) / ( GasRDry * xyr_VirTemp(:,:,0) ) )
xy_TurKinEneAtLB = MYConstB1**(2.0_DP/3.0_DP) / 2.0_DP * xy_FricVelSq
xy_TurKinEneAtLB = xy_TurKinEneAtLB + TurKinEneOffset
! Calculate transfer coefficient and flux of turbulent kinetic energy
!
! When transfer coefficient at lower boundary is calculated,
! diffusion coefficient at mid-point of 1st layer is used.
! In addition, transfer coefficient at upper boundary is assumed
! to be zero.
k = 0
xyr_TurKinEneTransCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,1) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,1) - xy_SurfHeight )
do k = 1, kmax-1
xyr_TurKinEneTransCoef(:,:,k) = xyr_TurKinEneDiffCoef(:,:,k) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
end do
k = kmax
xyr_TurKinEneTransCoef(:,:,k) = 0.0_DP
!
do k = 1, kmax-1
xyr_TurKinEneFlux(:,:,k) = - xyr_TurKinEneTransCoef(:,:,k) * ( xyz_TurKinEneNonZero(:,:,k+1) - xyz_TurKinEneNonZero(:,:,k) )
end do
k = 0
xyr_TurKinEneFlux(:,:,k) = - xyr_TurKinEneTransCoef(:,:,k) * ( xyz_TurKinEneNonZero(:,:,k+1) - xy_TurKinEneAtLB )
k = kmax
xyr_TurKinEneFlux(:,:,k) = 0.0_DP
! Calculation of vertical mixing
!
! Construct implicit matrix from transfer coefficient of vertical
! diffusion scheme (turbulent kinetic energy)
!
k = 1
xyza_TurKinEneMtx(:,:,k,-1) = 0.0_DP
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k )
xyza_TurKinEneMtx(:,:,k, 1) = - xyr_TurKinEneTransCoef(:,:,k )
!
do k = 2, kmax-1
xyza_TurKinEneMtx(:,:,k,-1) = - xyr_TurKinEneTransCoef(:,:,k-1)
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k )
xyza_TurKinEneMtx(:,:,k, 1) = - xyr_TurKinEneTransCoef(:,:,k )
end do
!
k = kmax
xyza_TurKinEneMtx(:,:,k,-1) = - xyr_TurKinEneTransCoef(:,:,k-1)
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k )
xyza_TurKinEneMtx(:,:,k, 1) = 0.0_DP
do k = 1, kmax
xyz_TurKinEneVec(:,:,k) = - ( xyr_TurKinEneFlux(:,:,k) - xyr_TurKinEneFlux(:,:,k-1) )
end do
!
! Solve simultaneous linear equations by use of LU decomposition technique
!
xyza_TurKinEneLUMtx = xyza_TurKinEneMtx
!
call PhyImplLUDecomp3( xyza_TurKinEneLUMtx, imax * jmax, kmax )
xyz_DelTurKinEneLUVec = xyz_TurKinEneVec
!
call PhyImplLUSolve3( xyz_DelTurKinEneLUVec, xyza_TurKinEneLUMtx, 1, imax * jmax , kmax )
xyz_DTurKinEneDtVDiff = xyz_DelTurKinEneLUVec / ( 2.0_DP * DelTime )
! Calculation tendency including source and dissipation terms
xyz_CShe1 = sqrt( 2.0_DP ) * xyz_MixLength * xyz_DVelDzSq * xyz_Sm * sqrt( xyz_TurKinEneNonZero )
!!$ xyz_CShe2 = 0.5_DP * sqrt( 2.0_DP ) * xyz_MixLength * xyz_DVelDzSq &
!!$ & * xyz_Sm &
!!$ & / sqrt( xyz_TurKinEneNonZero )
xyz_CShe2 = 0.0_DP
xyz_CBuo1 = - sqrt( 2.0_DP ) * xyz_MixLength * xyz_StatStab * xyz_Sh * sqrt( xyz_TurKinEneNonZero )
!!$ xyz_CBuo2 = - 0.5_DP * sqrt( 2.0_DP ) * xyz_MixLength * xyz_StatStab &
!!$ & * xyz_Sh &
!!$ & / sqrt( xyz_TurKinEneNonZero )
xyz_CBuo2 = 0.0_DP
xyz_CDis1 = 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) * xyz_TurKinEneNonZero**1.5
xyz_CDis2 = 1.5_DP * 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) * xyz_TurKinEneNonZero**0.5
! Calculation of dissipation rate of turbulent kinetic energy
!
! Calculate production rate of turbulent kinetic energy
! by shear and buoyancy
xyz_TurKinEneProShear = xyz_CShe1 !+ xyz_CShe2 * xyz_DTurKinEneDt * 2.0_DP * DelTime
xyz_TurKinEneProBuoya = xyz_CBuo1 !+ xyz_CBuo2 * xyz_DTurKinEneDt * 2.0_DP * DelTime
xyz_TurKinEneDiss = xyz_CDis1 !+ xyz_CDis2 * xyz_DTurKinEneDt * 2.0_DP * DelTime
xyz_TurKinEneTentative = xyz_TurKinEne
DelTimeSubStep = 0.25_DP
nloop = 2.0_DP * DelTime / DelTimeSubStep + 1
DelTimeSubStep = 2.0_DP * DelTime / dble( nloop )
nloop = kmax
loop_solve : do iloop = 1, nloop
!!$ xyz_TurKinEneProShear = &
!!$ & sqrt( 2.0_DP ) * xyz_MixLength * xyz_DVelDzSq &
!!$ & * xyz_Sm &
!!$ & * sqrt( xyz_TurKinEneTentative )
!!$ xyz_TurKinEneProBuoya = &
!!$ & - sqrt( 2.0_DP ) * xyz_MixLength * xyz_StatStab &
!!$ & * xyz_Sh &
!!$ & * sqrt( xyz_TurKinEneTentative )
xyz_TurKinEneDiss = 2.0_DP**1.5 / ( MYConstB1 * xyz_MixLength ) * xyz_TurKinEneTentative**1.5
!!$ xyz_TurKinEneTentative = &
!!$ & xyz_TurKinEneTentative &
!!$ & + ( xyz_DTurKinEneDtVDiff &
!!$ & + xyz_TurKinEneProShear &
!!$ & + xyz_TurKinEneProBuoya &
!!$ & - xyz_TurKinEneDiss ) &
!!$ & * DelTimeSubStep
xyz_TurKinEneTentative = xyz_TurKinEneTentative + ( xyz_TurKinEneProShear + xyz_TurKinEneProBuoya - xyz_TurKinEneDiss ) * DelTimeSubStep
xyz_TurKinEneTentative = max( xyz_TurKinEneTentative, 0.0_DP )
!!$ ! Check of turbulent kinetic energy dissipation rate
!!$ ! If it is negative, tendency is recalculated without dissipation.
!!$ !
!!$ FlagReCalc = .false.
!!$ do k = 1, kmax
!!$ do j = 1, jmax
!!$ do i = 0, imax-1
!!$ if ( xyz_TurKinEneDiss(i,j,k) < 0.0_DP ) then
!!$ xyz_CDis1(i,j,k) = 0.0_DP
!!$ xyz_CDis2(i,j,k) = 0.0_DP
!!$ FlagReCalc = .true.
!!$ end if
!!$ end do
!!$ end do
!!$ end do
!!$
!!$ ! Check convergence
!!$ a_FlagReCalcLocal = FlagReCalc
!!$ call MPIWrapperChkTrue( &
!!$ & 1, a_FlagReCalcLocal, & ! (in)
!!$ & a_FlagReCalcGlobal & ! (out)
!!$ & )
!!$ if ( .not. a_FlagReCalcGlobal(1) ) exit loop_solve
end do loop_solve
xyz_DTurKinEneDt = ( xyz_TurKinEneTentative - xyz_TurKinEne ) / ( 2.0_DP * DelTime )
!=========================================================================
! Calculate turbulent kinetic energy with offset
!
xyz_TurKinEneNonZero = xyz_TurKinEne + TurKinEneOffset
!!$ xyz_TurKinEneNonZero = xyz_TurKinEneTentative + TurKinEneOffset
! 混合距離の算出
! Calculate mixing length
!
do k = 1, kmax
xyz_MixLength(:,:,k) = FKarm * ( xyz_Height(:,:,k) - xy_SurfHeight ) / (1.0_DP + FKarm * ( xyz_Height(:,:,k) - xy_SurfHeight ) / MixLengthMax )
end do
! Limit mixing length and avoid zero
xyz_MixLength = min( xyz_MixLength, 0.53_DP * sqrt( 2.0_DP * xyz_TurKinEneNonZero / max( xyz_StatStab, 1.0d-10 ) ) ) + 1.0d-10
xyz_Gh = - xyz_MixLength**2 / ( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_StatStab
! Actually, xyz_Gm is not used below.
xyz_Gm = xyz_MixLength**2 / ( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_DVelDzSq
! Limit Gh
GhMin = - 0.53d0**2
GhMax = 1.0_DP / ( MYConstA2 * ( 12.0_DP * MYConstA1 + MYConstB1 + 3.0_DP * MYConstB2 ) )
xyz_Gh = max( GhMin, min( xyz_Gh, GhMax ) )
xyz_Sh = MYConstA2 * ( 1.0_DP - 6.0_DP * MYConstA1 / MYConstB1 ) / ( 1.0_DP - 3.0_DP * MYConstA2 * ( 6.0_DP * MYConstA1 + MYConstB2 ) * xyz_Gh )
xyz_Sm = ( MYConstA1 * ( 1.0_DP - 3.0_DP * MYConstC1 - 6.0_DP * MYConstA1 / MYConstB1 ) + 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) * xyz_Gh * xyz_Sh ) / ( 1.0_DP - 9.0_DP * MYConstA1 * MYConstA2 * xyz_Gh )
!!$ xyz_DShHatDTKE = &
!!$ & - 2.0_DP * MYConstA2 * ( 1.0_DP - 6.0_DP * MYConstA1 / MYConstB1 ) &
!!$ & / ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 3.0_DP * MYConstA2 * ( 6.0_DP * MYConstA1 + MYConstB2 ) * xyz_GhPrime )**2
!!$ xyz_DSmHatDTKE = &
!!$ & ( &
!!$ & 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) &
!!$ & * xyz_GhPrime * xyz_DShHatDTKE &
!!$ & * ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 9.0_DP * MYConstA1 * MYConstA2 * xyz_GhPrime ) &
!!$ & - 2.0_DP &
!!$ & * ( &
!!$ & MYConstA1 * ( 1.0_DP - 3.0_DP * MYConstC1 &
!!$ & - 6.0_DP * MYConstA1 / MYConstB1 ) &
!!$ & + 9.0_DP * MYConstA1 * ( 2.0_DP * MYConstA1 + MYConstA2 ) &
!!$ & * xyz_GhPrime * xyz_ShHat &
!!$ & ) &
!!$ & ) &
!!$ & / ( 2.0_DP * xyz_TurKinEneNonZero &
!!$ & - 9.0_DP * MYConstA1 * MYConstA2 * xyz_GhPrime )**2
! 拡散係数の計算
! Calculation of diffusion coefficient
!
xyz_VelDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_Sm
xyz_TempDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * xyz_Sh
!
do k = 0, kmax
if ( ( k == 0 ) .or. ( k == kmax ) ) then
xyr_VelDiffCoef (:,:,k) = 0.0_DP
xyr_TempDiffCoef(:,:,k) = 0.0_DP
else
xyr_VelDiffCoef (:,:,k) = ( xyz_VelDiffCoef (:,:,k) + xyz_VelDiffCoef (:,:,k+1) ) / 2.0_DP
xyr_TempDiffCoef(:,:,k) = ( xyz_TempDiffCoef(:,:,k) + xyz_TempDiffCoef(:,:,k+1) ) / 2.0_DP
end if
end do
!
do k = 1, kmax-1
do j = 1, jmax
do i = 0, imax-1
xyr_VelDiffCoef(i,j,k) = max( min( xyr_VelDiffCoef(i,j,k), VelDiffCoefMax ), VelDiffCoefMin )
xyr_TempDiffCoef(i,j,k) = max( min( xyr_TempDiffCoef(i,j,k), TempDiffCoefMax ), TempDiffCoefMin )
end do
end do
end do
!
xyr_QMixDiffCoef = xyr_TempDiffCoef
! 輸送係数とフラックスの計算
! Calculate transfer coefficient and flux
!
call VDiffusionTransCoefAndFlux( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_VirTemp, xyr_Press, xyz_Height, xyz_Exner, xyr_Exner, xyr_VelDiffCoef, xyr_TempDiffCoef, xyr_QMixDiffCoef, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef )
! Calculate tendency of turbulent kinetic energy
! Set diffusion coefficient for turbulent kinetic energy
xyz_TurKinEneDiffCoef = xyz_MixLength * sqrt( 2.0_DP * xyz_TurKinEneNonZero ) * Stke
!
do k = 0, kmax
if ( k == 0 ) then
xyr_TurKinEneDiffCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,1)
else if ( k == kmax ) then
xyr_TurKinEneDiffCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,kmax)
else
xyr_TurKinEneDiffCoef(:,:,k) = ( xyz_TurKinEneDiffCoef(:,:,k) + xyz_TurKinEneDiffCoef(:,:,k+1) ) / 2.0_DP
end if
end do
! Calculate turbulent kinetic energy at lower boundary
!
xy_FricVelSq = sqrt( xy_SurfMomFluxX**2 + xy_SurfMomFluxY**2 ) / ( xyr_Press(:,:,0) / ( GasRDry * xyr_VirTemp(:,:,0) ) )
xy_TurKinEneAtLB = MYConstB1**(2.0_DP/3.0_DP) / 2.0_DP * xy_FricVelSq
xy_TurKinEneAtLB = xy_TurKinEneAtLB + TurKinEneOffset
! Calculate transfer coefficient and flux of turbulent kinetic energy
!
! When transfer coefficient at lower boundary is calculated,
! diffusion coefficient at mid-point of 1st layer is used.
! In addition, transfer coefficient at upper boundary is assumed
! to be zero.
k = 0
xyr_TurKinEneTransCoef(:,:,k) = xyz_TurKinEneDiffCoef(:,:,1) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,1) - xy_SurfHeight )
do k = 1, kmax-1
xyr_TurKinEneTransCoef(:,:,k) = xyr_TurKinEneDiffCoef(:,:,k) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
end do
k = kmax
xyr_TurKinEneTransCoef(:,:,k) = 0.0_DP
!
do k = 1, kmax-1
xyr_TurKinEneFlux(:,:,k) = - xyr_TurKinEneTransCoef(:,:,k) * ( xyz_TurKinEneNonZero(:,:,k+1) - xyz_TurKinEneNonZero(:,:,k) )
end do
k = 0
xyr_TurKinEneFlux(:,:,k) = - xyr_TurKinEneTransCoef(:,:,k) * ( xyz_TurKinEneNonZero(:,:,k+1) - xy_TurKinEneAtLB )
k = kmax
xyr_TurKinEneFlux(:,:,k) = 0.0_DP
! Calculation of vertical mixing
!
! Construct implicit matrix from transfer coefficient of vertical
! diffusion scheme (turbulent kinetic energy)
!
k = 1
xyza_TurKinEneMtx(:,:,k,-1) = 0.0_DP
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k )
xyza_TurKinEneMtx(:,:,k, 1) = - xyr_TurKinEneTransCoef(:,:,k )
!
do k = 2, kmax-1
xyza_TurKinEneMtx(:,:,k,-1) = - xyr_TurKinEneTransCoef(:,:,k-1)
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k )
xyza_TurKinEneMtx(:,:,k, 1) = - xyr_TurKinEneTransCoef(:,:,k )
end do
!
k = kmax
xyza_TurKinEneMtx(:,:,k,-1) = - xyr_TurKinEneTransCoef(:,:,k-1)
xyza_TurKinEneMtx(:,:,k, 0) = - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav / ( 2. * DelTime ) + xyr_TurKinEneTransCoef(:,:,k-1) + xyr_TurKinEneTransCoef(:,:,k )
xyza_TurKinEneMtx(:,:,k, 1) = 0.0_DP
do k = 1, kmax
xyz_TurKinEneVec(:,:,k) = - ( xyr_TurKinEneFlux(:,:,k) - xyr_TurKinEneFlux(:,:,k-1) ) - ( xyr_Press(:,:,k) - xyr_Press(:,:,k-1) ) / Grav * xyz_DTurKinEneDt(:,:,k)
end do
!
! Solve simultaneous linear equations by use of LU decomposition technique
!
xyza_TurKinEneLUMtx = xyza_TurKinEneMtx
!
call PhyImplLUDecomp3( xyza_TurKinEneLUMtx, imax * jmax, kmax )
xyz_DelTurKinEneLUVec = xyz_TurKinEneVec
!
call PhyImplLUSolve3( xyz_DelTurKinEneLUVec, xyza_TurKinEneLUMtx, 1, imax * jmax , kmax )
xyz_DTurKinEneDt = xyz_DelTurKinEneLUVec / ( 2.0_DP * DelTime )
!!$ write( 6, * ) TimeN, iloop
!!$ write( 6, * ) xyz_TurKinEne(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TempDiffCoef(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TurKinEneProShear(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TurKinEneProBuoya(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_TurKinEneDiss(0,jmax/2+1,1:4)
!!$ write( 6, * ) xyz_DTurKinEneDt(0,jmax/2+1,1:4)
! 拡散係数の出力
! Output diffusion coefficients
!
! 拡散係数出力
! Diffusion coeffficients output
!
call HistoryAutoPut( TimeN, 'VelDiffCoef', xyr_VelDiffCoef )
call HistoryAutoPut( TimeN, 'TempDiffCoef', xyr_TempDiffCoef )
call HistoryAutoPut( TimeN, 'QVapDiffCoef', xyr_QMixDiffCoef )
call HistoryAutoPut( TimeN, 'TKEPShear', xyz_TurKinEneProShear )
call HistoryAutoPut( TimeN, 'TKEPBuoy' , xyz_TurKinEneProBuoya )
call HistoryAutoPut( TimeN, 'TKEDiss' , xyz_TurKinEneDiss )
call HistoryAutoPut( TimeN, 'MixLength' , xyz_MixLength )
! 計算時間計測一時停止
! Pause measurement of computation time
!
call TimesetClockStop( module_name )
end subroutine VDiffusionMY25Testing
| Subroutine : | |||
| xyz_U(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyz_V(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax) : | real(DP), intent(in)
| ||
| xyz_Temp(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_VirTemp(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_Press(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyz_Height(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyz_Exner(0:imax-1, 1:jmax, 1:kmax) : | real(DP), intent(in)
| ||
| xyr_Exner(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_VelDiffCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_TempDiffCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_QMixDiffCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(in)
| ||
| xyr_MomFluxX(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_MomFluxY(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_HeatFlux(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax) : | real(DP), intent(out)
| ||
| xyr_VelTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
| ||
| xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax) : | real(DP), intent(out)
|
鉛直拡散フラックスを計算します.
Vertical diffusion flux is calculated.
subroutine VDiffusionTransCoefAndFlux( xyz_U, xyz_V, xyzf_QMix, xyz_Temp, xyr_VirTemp, xyr_Press, xyz_Height, xyz_Exner, xyr_Exner, xyr_VelDiffCoef, xyr_TempDiffCoef, xyr_QMixDiffCoef, xyr_MomFluxX, xyr_MomFluxY, xyr_HeatFlux, xyrf_QMixFlux, xyr_VelTransCoef, xyr_TempTransCoef, xyr_QMixTransCoef )
!
! 鉛直拡散フラックスを計算します.
!
! Vertical diffusion flux is calculated.
!
! モジュール引用 ; USE statements
!
! 物理定数設定
! Physical constants settings
!
use constants, only: FKarm, GasRDry, CpDry
! $ C_p $ [J kg-1 K-1].
! 乾燥大気の定圧比熱.
! Specific heat of air at constant pressure
! 時刻管理
! Time control
!
use timeset, only: TimeN, TimesetClockStart, TimesetClockStop
! ヒストリデータ出力
! History data output
!
use gtool_historyauto, only: HistoryAutoPut
! 宣言文 ; Declaration statements
!
implicit none
real(DP), intent(in):: xyz_U (0:imax-1, 1:jmax, 1:kmax)
! $ u $ . 東西風速. Eastward wind
real(DP), intent(in):: xyz_V (0:imax-1, 1:jmax, 1:kmax)
! $ v $ . 南北風速. Northward wind
real(DP), intent(in):: xyzf_QMix(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
! $ q $ . 質量混合比. Mass mixing ratio
real(DP), intent(in):: xyz_Temp (0:imax-1, 1:jmax, 1:kmax)
! $ T $ . 温度. Temperature
real(DP), intent(in):: xyr_VirTemp (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{T}_v $ . 仮温度 (半整数レベル).
! Virtual temperature (half level)
real(DP), intent(in):: xyr_Press (0:imax-1, 1:jmax, 0:kmax)
! $ \hat{p} $ . 気圧 (半整数レベル).
! Air pressure (half level)
real(DP), intent(in):: xyz_Height (0:imax-1, 1:jmax, 1:kmax)
! 高度 (整数レベル).
! Height (full level)
real(DP), intent(in):: xyz_Exner (0:imax-1, 1:jmax, 1:kmax)
! Exner 関数 (整数レベル).
! Exner function (full level)
real(DP), intent(in):: xyr_Exner (0:imax-1, 1:jmax, 0:kmax)
! Exner 関数 (半整数レベル).
! Exner function (half level)
real(DP), intent(in):: xyr_VelDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:運動量.
! Diffusion coefficient: velocity
real(DP), intent(in):: xyr_TempDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:温度.
! Transfer coefficient: temperature
real(DP), intent(in):: xyr_QMixDiffCoef (0:imax-1, 1:jmax, 0:kmax)
! 拡散係数:比湿.
! Diffusion coefficient: specific humidity
real(DP), intent(out):: xyr_MomFluxX (0:imax-1, 1:jmax, 0:kmax)
! 東西方向運動量フラックス.
! Eastward momentum flux
real(DP), intent(out):: xyr_MomFluxY (0:imax-1, 1:jmax, 0:kmax)
! 南北方向運動量フラックス.
! Northward momentum flux
real(DP), intent(out):: xyr_HeatFlux (0:imax-1, 1:jmax, 0:kmax)
! 熱フラックス.
! Heat flux
real(DP), intent(out):: xyrf_QMixFlux(0:imax-1, 1:jmax, 0:kmax, 1:ncmax)
! 質量フラックス.
! Mass flux of compositions
real(DP), intent(out):: xyr_VelTransCoef (0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:運動量.
! Transfer coefficient: velocity
real(DP), intent(out):: xyr_TempTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:温度.
! Transfer coefficient: temperature
real(DP), intent(out):: xyr_QMixTransCoef(0:imax-1, 1:jmax, 0:kmax)
! 輸送係数:質量.
! Transfer coefficient: mass (composition)
! 作業変数
! Work variables
!
integer:: k ! 鉛直方向に回る DO ループ用作業変数
! Work variables for DO loop in vertical direction
integer:: n ! 組成方向に回る DO ループ用作業変数
! Work variables for DO loop in dimension of constituents
! 実行文 ; Executable statement
!
! 初期化確認
! Initialization check
!
if ( .not. vdiffusion_my_inited ) then
call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
end if
! 輸送係数の計算
! Calculate transfer coefficient
!
xyr_VelTransCoef (:,:,0) = 0.
xyr_VelTransCoef (:,:,kmax) = 0.
xyr_TempTransCoef(:,:,0) = 0.
xyr_TempTransCoef(:,:,kmax) = 0.
xyr_QMixTransCoef(:,:,0) = 0.
xyr_QMixTransCoef(:,:,kmax) = 0.
do k = 1, kmax-1
!!$ xyr_VelTransCoef(:,:,k) = &
!!$ & xyr_VelDiffCoef(:,:,k) &
!!$ & * xyr_Press(:,:,k) / GasRDry / xyr_Temp(:,:,k) &
!!$ & / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
!!$
!!$ xyr_TempTransCoef(:,:,k) = &
!!$ & xyr_TempDiffCoef(:,:,k) &
!!$ & * xyr_Press(:,:,k) / GasRDry / xyr_Temp(:,:,k) &
!!$ & / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
!!$
!!$ xyr_QMixTransCoef(:,:,k) = &
!!$ & xyr_QMixDiffCoef(:,:,k) &
!!$ & * xyr_Press(:,:,k) / GasRDry / xyr_Temp(:,:,k) &
!!$ & / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
xyr_VelTransCoef(:,:,k) = xyr_VelDiffCoef(:,:,k) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
xyr_TempTransCoef(:,:,k) = xyr_TempDiffCoef(:,:,k) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
xyr_QMixTransCoef(:,:,k) = xyr_QMixDiffCoef(:,:,k) * xyr_Press(:,:,k) / ( GasRDry * xyr_VirTemp(:,:,k) ) / ( xyz_Height(:,:,k+1) - xyz_Height(:,:,k) )
end do
! フラックスの計算
! Calculate fluxes
!
xyr_MomFluxX(:,:,0) = 0.
xyr_MomFluxX(:,:,kmax) = 0.
xyr_MomFluxY(:,:,0) = 0.
xyr_MomFluxY(:,:,kmax) = 0.
xyr_HeatFlux(:,:,0) = 0.
xyr_HeatFlux(:,:,kmax) = 0.
do n = 1, ncmax
xyrf_QMixFlux(:,:,0,n) = 0.
xyrf_QMixFlux(:,:,kmax,n) = 0.
end do
do k = 1, kmax-1
xyr_MomFluxX(:,:,k) = - xyr_VelTransCoef(:,:,k) * ( xyz_U(:,:,k+1) - xyz_U(:,:,k) )
xyr_MomFluxY(:,:,k) = - xyr_VelTransCoef(:,:,k) * ( xyz_V(:,:,k+1) - xyz_V(:,:,k) )
xyr_HeatFlux(:,:,k) = - CpDry * xyr_TempTransCoef(:,:,k) * xyr_Exner(:,:,k) * ( xyz_Temp(:,:,k+1) / xyz_Exner(:,:,k+1) - xyz_Temp(:,:,k) / xyz_Exner(:,:,k) )
end do
do n = 1, ncmax
do k = 1, kmax-1
xyrf_QMixFlux(:,:,k,n) = - xyr_QMixTransCoef(:,:,k) * ( xyzf_QMix(:,:,k+1,n) - xyzf_QMix(:,:,k,n) )
end do
end do
end subroutine VDiffusionTransCoefAndFlux
| Variable : | |||
| VelDiffCoefMax : | real(DP), save
|
| Variable : | |||
| VelDiffCoefMin : | real(DP), save
|
| Constant : | |||
| module_name = ‘vdiffusion_my‘ : | character(*), parameter
|
| Variable : | |||
| vdiffusion_my_inited = .false. : | logical, save
|
| Constant : | |||
| version = ’$Name: dcpam5-20131008 $’ // ’$Id: vdiffusion_my.f90,v 1.1 2013-09-16 12:01:19 yot Exp $’ : | character(*), parameter
|