!= è³ªé‡ã®è£œæ£
!
!= Mass fixer
!
! Authors::   Yasuhiro Morikawa, Yukiko Yamada, Yoshiyuki O. Takahashi
! Version::   $Id: mass_fixer.f90,v 1.14 2014/06/29 07:20:43 yot Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2008. All rights reserved.
! License::   See COPYRIGHT[link:../../../COPYRIGHT]
!

module mass_fixer
  !
  != è³ªé‡ã®è£œæ£
  !
  != Mass fixer
  !
  ! <b>Note that Japanese and English are described in parallel.</b>
  !
  ! è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
  !
  ! Fix masses
  !
  !== Procedures List
  !
  ! MassFixer   :: è³ªé‡ã®è£œæ£
  ! ----------  :: ---------------
  ! MassFixer   :: Fix masses
  !
  !--
  !== NAMELIST
  !
  ! NAMELIST#mass_fixer_nml
  !
  !== References
  !
  ! Williamson, D. L., and J. G. Olson (1994), Climte simulations with a
  ! semi-Lagrangian version of the NCAR community climate model, 122,
  ! 1594-1610.
  !
  !++

  ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
  !

  ! æ ¼åç‚¹è¨å®š
  ! Grid points settings
  !
  use gridset, only: imax, & ! çµŒåº¦æ ¼åç‚¹æ•°.
                             ! Number of grid points in longitude
    &                jmax, & ! ç·¯åº¦æ ¼åç‚¹æ•°.
                             ! Number of grid points in latitude
    &                kmax    ! é‰›ç›´å±¤æ•°.
                             ! Number of vertical level

  ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
  ! Settings of array for atmospheric composition
  !
  use composition, only: &
    &                    ncmax
                              ! æˆåˆ†ã®æ•°
                              ! Number of composition

  ! ç¨®åˆ¥åž‹ãƒ‘ãƒ©ãƒ¡ã‚¿
  ! Kind type parameter
  !
  use dc_types, only: DP, &      ! å€ç²¾åº¦å®Ÿæ•°åž‹. Double precision.
    &                 STRING     ! æ–‡å—åˆ—.       Strings.

  ! ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸å‡ºåŠ›
  ! Message output
  !
  use dc_message, only: MessageNotify

  ! å®£è¨€æ–‡ ; Declaration statements
  !
  implicit none
  private

  ! å…¬é–‹æ‰‹ç¶šã
  ! Public procedure
  !
  public :: MassFixerBC02
  public :: MassFixerBC02Layer
  public :: MassFixerBC02Column
  public :: MassFixerR95
  public :: MassFixerR95Layer
  public :: MassFixerR95Column
  public :: MassFixerWO94
  public :: MassFixer
  public :: MassFixerLayer
  public :: MassFixerColumn
  public :: MassFixerInit

  ! å…¬é–‹å¤‰æ•°
  ! Public variables
  !

  ! éžå…¬é–‹å¤‰æ•°
  ! Private variables
  !
  real(DP), save :: ThresholdForMessage

  logical, save :: mass_fixer_inited = .false.
                              ! åˆæœŸè¨å®šãƒ•ãƒ©ã‚°.
                              ! Initialization flag

  character(*), parameter:: module_name = 'mass_fixer'
                              ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®åç§°.
                              ! Module name
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id: mass_fixer.f90,v 1.14 2014/06/29 07:20:43 yot Exp $'
                              ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³
                              ! Module version

contains

  !--------------------------------------------------------------------------------------

  subroutine MassFixerBC02(    &
    & xyr_Press,               & ! (in)
    & xyzf_QMix,               & ! (inout)
    & xyzf_QMixLin,            & ! (in)
    & xyr_PressRef,            & ! (in)
    & xyzf_QMixRef,            & ! (in)
    & xyzf_DQMixDt             & ! (out) optional
    & )
    !
    ! Bermejo and Conde (2002) ã®æ–¹æ³•ã«å¾“ã„, æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! See also Diamantakis and Flemming (2014).
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fix masses of constituents following a method proposed by
    ! Bermejo and Conde (2002).
    ! See also Diamantakis and Flemming (2014).
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: IntLonLat_xy

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   )          :: xyzf_QMixLin(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ) :: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ) :: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyzf_QMixRefLV(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ . å±¤å†…ã®æˆåˆ†ã®æ··åˆæ¯”.
                              ! Reference specific mass of constituent (local value)

    real(DP):: xyzf_QMixBefCor   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !

    real(DP):: xyz_Weight       (0:imax-1, 1:jmax, 1:kmax)
    real(DP), parameter:: FactBeta = 1.0_DP ! see Diamantakis and Flemming (2014)

    real(DP):: Sum
    real(DP):: xy_Sum (0:imax-1, 1:jmax)
    real(DP):: xy_SumB(0:imax-1, 1:jmax)
    real(DP):: xy_SumA(0:imax-1, 1:jmax)
    real(DP):: f_SumB(1:ncmax)
    real(DP):: f_SumA(1:ncmax)
    real(DP), parameter:: MissingValue = -1.0e100_DP
    real(DP):: f_DelMassTentative(1:ncmax)

    real(DP):: Lambda

    real(DP):: SumB
    real(DP):: SumA
    real(DP):: Factor

    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
!!$    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
!!$      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
!!$        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
!!$      end if
!!$    end if

    ! Backup of a variable
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_QMixBefCor = xyzf_QMix
    end if

    ! Preparation of variable for reference
!!$    if ( present( xyzf_QMixRef ) ) then
      xyzf_QMixRefLV = xyzf_QMixRef
!!$    else
!!$      xyzf_QMixRefLV = xyzf_QMix
!!$    end if

    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

!!$    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = &
          & ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
!!$    else
!!$      xyz_DelMassRef = xyz_DelMass
!!$    end if

    ! Fill grids with negative values
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
      end if
    end do

    ! Globally integrated mass
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xy_SumB = 0.0_DP
        xy_SumA = 0.0_DP
        do k = kmax, 1, -1
          xy_SumB = xy_SumB + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k)
          xy_SumA = xy_SumA + xyzf_QMix     (:,:,k,n) * xyz_DelMass   (:,:,k)
        end do
        f_SumB(n) = IntLonLat_xy( xy_SumB )
        f_SumA(n) = IntLonLat_xy( xy_SumA )
      else
        f_SumB(n) = MissingValue
        f_SumA(n) = MissingValue
      end if
    end do

    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        f_DelMassTentative(n) = f_SumA(n) - f_SumB(n)
      else
        f_DelMassTentative(n) = MissingValue
      end if
    end do

    ! loop for constituents
    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        ! Calculation of weight
        xyz_Weight(:,:,:) =                              &
          & max( 0.0_DP,                                 &
          &      sign( 1.0_DP, f_DelMassTentative(n) )   &
          &        * ( xyzf_QMix(:,:,:,n) - xyzf_QMixLin(:,:,:,n) )**FactBeta )

        !
        ! Calculation of factor, lambda
        !
        xy_Sum = 0.0_DP
        do k = kmax, 1, -1
          xy_Sum = xy_Sum + xyz_Weight(:,:,k) * xyz_DelMass(:,:,k)
        end do
        Sum = IntLonLat_xy( xy_Sum )
!!$        if ( abs( Sum ) < 1.0e-100_DP ) then
        if ( abs( Sum ) /= 0.0_DP ) then
          Lambda = f_DelMassTentative(n) / Sum
        else
          Lambda = 0.0_DP
        end if

        xyzf_QMix(:,:,:,n) = xyzf_QMix(:,:,:,n) - Lambda * xyz_Weight

      end if

    end do

    ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
    ! Calculate specific humidity variance
    !
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_DQMixDt = ( xyzf_QMix - xyzf_QMixBefCor ) / ( 2.0_DP * DelTime )
    end if

    ! Ensure non-negative values
!!$    ! This procedure is not included in Rasch et al. (1995).
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
        xy_SumB = 0.0_DP
        xy_SumA = 0.0_DP
        do k = kmax, 1, -1
          xy_SumB = xy_SumB + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k)
          xy_SumA = xy_SumA + xyzf_QMix     (:,:,k,n) * xyz_DelMass   (:,:,k)
        end do
        SumB = IntLonLat_xy( xy_SumB )
        SumA = IntLonLat_xy( xy_SumA )
        if ( SumA == 0.0_DP ) then
          Factor = 0.0_DP
        else if ( SumA < 0.0_DP ) then
          call MessageNotify( 'M', module_name,      &
            & 'BC02: n = %d, SumA is negative, %f.', &
            & i = (/ n /), d = (/ SumA /) )
          Factor = 0.0_DP
        else
          if ( SumB < 0.0_DP ) then
            call MessageNotify( 'M', module_name,      &
              & 'BC02: n = %d, SumB is negative, %f.', &
              & i = (/ n /), d = (/ SumB /) )
            Factor = 0.0_DP
          else
            Factor = SumB / SumA
          end if
        end if
        xyzf_QMix(:,:,:,n) = Factor * xyzf_QMix(:,:,:,n)
      end if
    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerBC02

  !--------------------------------------------------------------------------------------

  subroutine MassFixerBC02Layer(    &
    & xyr_Press,               & ! (in)
    & xyzf_QMix,               & ! (inout)
    & xyzf_QMixLin,            & ! (in)
    & xyr_PressRef,            & ! (in)
    & xyzf_QMixRef,            & ! (in)
    & xyzf_DQMixDt             & ! (out) optional
    & )
    !
    ! Bermejo and Conde (2002) ã®æ–¹æ³•ã«å¾“ã„, æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! See also Diamantakis and Flemming (2014).
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fix masses of constituents following a method proposed by
    ! Bermejo and Conde (2002).
    ! See also Diamantakis and Flemming (2014).
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: a_IntLonLat_xya

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   )          :: xyzf_QMixLin(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ) :: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ) :: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyzf_QMixRefLV(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ . å±¤å†…ã®æˆåˆ†ã®æ··åˆæ¯”.
                              ! Reference specific mass of constituent (local value)

    real(DP):: xyzf_QMixBefCor   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !

    real(DP):: xyz_Weight       (0:imax-1, 1:jmax, 1:kmax)
    real(DP), parameter:: FactBeta = 1.0_DP ! see Diamantakis and Flemming (2014)

    real(DP):: z_Sum(1:kmax)
    real(DP):: zf_SumB(1:kmax, 1:ncmax)
    real(DP):: zf_SumA(1:kmax, 1:ncmax)
    real(DP), parameter:: MissingValue = -1.0e100_DP
    real(DP):: zf_DelMassTentative(1:kmax, 1:ncmax)

    real(DP):: z_Lambda(1:kmax)

    real(DP):: z_SumB(1:kmax)
    real(DP):: z_SumA(1:kmax)
    real(DP):: Factor

    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
!!$    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
!!$      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
!!$        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
!!$      end if
!!$    end if

    ! Backup of a variable
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_QMixBefCor = xyzf_QMix
    end if

    ! Preparation of variable for reference
!!$    if ( present( xyzf_QMixRef ) ) then
      xyzf_QMixRefLV = xyzf_QMixRef
!!$    else
!!$      xyzf_QMixRefLV = xyzf_QMix
!!$    end if

    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

!!$    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = &
          & ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
!!$    else
!!$      xyz_DelMassRef = xyz_DelMass
!!$    end if

    ! Fill grids with negative values
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
      end if
    end do

    ! Horizontally integrated mass
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        zf_SumB(:,n) = a_IntLonLat_xya( xyzf_QMixRefLV(:,:,:,n) * xyz_DelMassRef )
        zf_SumA(:,n) = a_IntLonLat_xya( xyzf_QMix     (:,:,:,n) * xyz_DelMass    )
      else
        zf_SumB(:,n) = MissingValue
        zf_SumA(:,n) = MissingValue
      end if
    end do

    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        zf_DelMassTentative(:,n) = zf_SumA(:,n) - zf_SumB(:,n)
      else
        zf_DelMassTentative(:,n) = MissingValue
      end if
    end do

    ! loop for constituents
    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        ! Calculation of weight
        do k = 1, kmax
          xyz_Weight(:,:,k) =                              &
            & max( 0.0_DP,                                 &
            &      sign( 1.0_DP, zf_DelMassTentative(k,n) )   &
            &        * ( xyzf_QMix(:,:,k,n) - xyzf_QMixLin(:,:,k,n) )**FactBeta )
        end do

        !
        ! Calculation of factor, lambda
        !
        z_Sum = a_IntLonLat_xya( xyz_Weight * xyz_DelMass )

!!$        if ( abs( Sum ) < 1.0e-100_DP ) then
        do k = 1, kmax
          if ( abs( z_Sum(k) ) /= 0.0_DP ) then
            z_Lambda(k) = zf_DelMassTentative(k,n) / z_Sum(k)
          else
            z_Lambda(k) = 0.0_DP
          end if
        end do

        do k = 1, kmax
          xyzf_QMix(:,:,k,n) = xyzf_QMix(:,:,k,n) - z_Lambda(k) * xyz_Weight(:,:,k)
        end do

      end if

    end do

    ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
    ! Calculate specific humidity variance
    !
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_DQMixDt = ( xyzf_QMix - xyzf_QMixBefCor ) / ( 2.0_DP * DelTime )
    end if

    ! Ensure non-negative values
!!$    ! This procedure is not included in Rasch et al. (1995).
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
        z_SumB = a_IntLonLat_xya( xyzf_QMixRefLV(:,:,:,n) * xyz_DelMassRef )
        z_SumA = a_IntLonLat_xya( xyzf_QMix     (:,:,:,n) * xyz_DelMass    )
        do k = 1, kmax
          if ( z_SumA(k) == 0.0_DP ) then
            Factor = 0.0_DP
          else if ( z_SumA(k) < 0.0_DP ) then
            call MessageNotify( 'M', module_name,      &
              & 'BC02Layer: n = %d, k = %d, SumA is negative, %f.', &
              & i = (/ n, k /), d = (/ z_SumA(k) /) )
            Factor = 0.0_DP
          else
            if ( z_SumB(k) < 0.0_DP ) then
              call MessageNotify( 'M', module_name,      &
                & 'BC02Layer: n = %d, k = %d, SumB is negative, %f.', &
                & i = (/ n, k /), d = (/ z_SumB(k) /) )
              Factor = 0.0_DP
            else
              Factor = z_SumB(k) / z_SumA(k)
            end if
          end if
          xyzf_QMix(:,:,k,n) = Factor * xyzf_QMix(:,:,k,n)
        end do
      end if
    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerBC02Layer

  !--------------------------------------------------------------------------------------

  subroutine MassFixerBC02Column(    &
    & xyr_Press,               & ! (in)
    & xyzf_QMix,               & ! (inout)
    & xyzf_QMixLin,            & ! (in)
    & xyr_PressRef,            & ! (in)
    & xyzf_QMixRef,            & ! (in)
    & xyzf_DQMixDt             & ! (out) optional
    & )
    !
    ! Bermejo and Conde (2002) ã®æ–¹æ³•ã«å¾“ã„, æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! See also Diamantakis and Flemming (2014).
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fix masses of constituents following a method proposed by
    ! Bermejo and Conde (2002).
    ! See also Diamantakis and Flemming (2014).
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: IntLonLat_xy

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   )          :: xyzf_QMixLin(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ) :: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ) :: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyzf_QMixRefLV(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ . å±¤å†…ã®æˆåˆ†ã®æ··åˆæ¯”.
                              ! Reference specific mass of constituent (local value)

    real(DP):: xyzf_QMixBefCor   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !

    real(DP):: xyz_Weight       (0:imax-1, 1:jmax, 1:kmax)
    real(DP), parameter:: FactBeta = 1.0_DP ! see Diamantakis and Flemming (2014)

    real(DP):: xy_Sum (0:imax-1, 1:jmax)
    real(DP):: xyf_SumB(0:imax-1, 1:jmax, 1:ncmax)
    real(DP):: xyf_SumA(0:imax-1, 1:jmax, 1:ncmax)
    real(DP):: xy_SumB(0:imax-1, 1:jmax)
    real(DP):: xy_SumA(0:imax-1, 1:jmax)
    real(DP), parameter:: MissingValue = -1.0e100_DP
    real(DP):: xyf_DelMassTentative(0:imax-1, 1:jmax, 1:ncmax)

    real(DP):: xy_Lambda(0:imax-1, 1:jmax)

    real(DP):: Factor

    integer:: i               ! çµŒåº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! ç·¯åº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in latitudinal direction
    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
!!$    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
!!$      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
!!$        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
!!$      end if
!!$    end if

    ! Backup of a variable
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_QMixBefCor = xyzf_QMix
    end if

    ! Preparation of variable for reference
!!$    if ( present( xyzf_QMixRef ) ) then
      xyzf_QMixRefLV = xyzf_QMixRef
!!$    else
!!$      xyzf_QMixRefLV = xyzf_QMix
!!$    end if

    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

!!$    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = &
          & ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
!!$    else
!!$      xyz_DelMassRef = xyz_DelMass
!!$    end if

    ! Fill grids with negative values
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
      end if
    end do

    ! Vertically integrated mass
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyf_SumB(:,:,n) = 0.0_DP
        xyf_SumA(:,:,n) = 0.0_DP
        do k = kmax, 1, -1
          xyf_SumB(:,:,n) = xyf_SumB(:,:,n) + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k)
          xyf_SumA(:,:,n) = xyf_SumA(:,:,n) + xyzf_QMix     (:,:,k,n) * xyz_DelMass   (:,:,k)
        end do
      else
        xyf_SumB(:,:,n) = MissingValue
        xyf_SumA(:,:,n) = MissingValue
      end if
    end do

    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyf_DelMassTentative(:,:,n) = xyf_SumA(:,:,n) - xyf_SumB(:,:,n)
      else
        xyf_DelMassTentative(:,:,n) = MissingValue
      end if
    end do

    ! loop for constituents
    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        ! Calculation of weight
        do k = 1, kmax
          xyz_Weight(:,:,k) =                              &
            & max( 0.0_DP,                                 &
            &      sign( 1.0_DP, xyf_DelMassTentative(:,:,n) )   &
            &        * ( xyzf_QMix(:,:,k,n) - xyzf_QMixLin(:,:,k,n) )**FactBeta )
        end do

        !
        ! Calculation of factor, lambda
        !
        xy_Sum = 0.0_DP
        do k = kmax, 1, -1
          xy_Sum = xy_Sum + xyz_Weight(:,:,k) * xyz_DelMass(:,:,k)
        end do
!!$        if ( abs( Sum ) < 1.0e-100_DP ) then
        do j = 1, jmax
          do i = 0, imax-1
            if ( abs( xy_Sum(i,j) ) /= 0.0_DP ) then
              xy_Lambda(i,j) = xyf_DelMassTentative(i,j,n) / xy_Sum(i,j)
            else
              xy_Lambda(i,j) = 0.0_DP
            end if
          end do
        end do

        do k = 1, kmax
          xyzf_QMix(:,:,k,n) = xyzf_QMix(:,:,k,n) - xy_Lambda * xyz_Weight(:,:,k)
        end do

      end if

    end do

    ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
    ! Calculate specific humidity variance
    !
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_DQMixDt = ( xyzf_QMix - xyzf_QMixBefCor ) / ( 2.0_DP * DelTime )
    end if

    ! Ensure non-negative values
!!$    ! This procedure is not included in Rasch et al. (1995).
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
        xy_SumB = 0.0_DP
        xy_SumA = 0.0_DP
        do k = kmax, 1, -1
          xy_SumB = xy_SumB + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k)
          xy_SumA = xy_SumA + xyzf_QMix     (:,:,k,n) * xyz_DelMass   (:,:,k)
        end do
        do j = 1, jmax
          do i = 0, imax-1
            if ( xy_SumA(i,j) == 0.0_DP ) then
              Factor = 0.0_DP
            else if ( xy_SumA(i,j) < 0.0_DP ) then
              call MessageNotify( 'M', module_name,      &
                & 'BC02Column: n = %d, (i,j) = (%d,%d), SumA is negative, %f.', &
                & i = (/ n, i, j /), d = (/ xy_SumA(i,j) /) )
              Factor = 0.0_DP
            else
              if ( xy_SumB(i,j) < 0.0_DP ) then
                call MessageNotify( 'M', module_name,      &
                  & 'BC02Column: n = %d, (i,j) = (%d,%d), SumB is negative, %f.', &
                  & i = (/ n, i, j /), d = (/ xy_SumB(i,j) /) )
                Factor = 0.0_DP
              else
                Factor = xy_SumB(i,j) / xy_SumA(i,j)
              end if
            end if
            do k = 1, kmax
              xyzf_QMix(i,j,k,n) = Factor * xyzf_QMix(i,j,k,n)
            end do
          end do
        end do
      end if
    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerBC02Column

  !--------------------------------------------------------------------------------------

  subroutine MassFixerR95(     &
    & xyr_Press,               & ! (in)
    & xyzf_QMix,               & ! (inout)
    & xyr_PressRef,            & ! (in) optional
    & xyzf_QMixRef,            & ! (in) optional
    & xyzf_DQMixDt             & ! (out) optional
    & )
    !
    ! Rasch et al. (1995) ã®æ–¹æ³•ã«å¾“ã„, æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒ *xyzf_QMixRef* ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚Œãªã„å ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒè£œæ£å‰ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fix masses of constituents following a method proposed by
    ! Rasch et al. (1995).
    ! If *xyzf_QMixRef* is given, the mass is fixed to match its global
    ! integrated value is the same as that of *xyzf_QMixRef*.
    ! If *xyzf_QMixRef* is not given, the mass is fixed to match its global
    ! integrated value is the same as that of pre-fixed value.
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: IntLonLat_xy

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ), optional:: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ), optional:: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyzf_QMixRefLV(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ . å±¤å†…ã®æˆåˆ†ã®æ··åˆæ¯”.
                              ! Reference specific mass of constituent (local value)

    real(DP):: xyzf_QMixBefCor   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !

    real(DP):: xyz_Weight       (0:imax-1, 1:jmax, 1:kmax)
    real(DP):: xy_FactAlphaNumer(0:imax-1, 1:jmax)
    real(DP):: xy_FactAlphaDenom(0:imax-1, 1:jmax)
    real(DP):: FactAlphaNumer
    real(DP):: FactAlphaDenom
    real(DP):: FactAlpha
    real(DP), parameter:: FactBeta = 1.0_DP ! for Rasch et al. (1994)

    real(DP):: xy_SumB(0:imax-1, 1:jmax)
    real(DP):: xy_SumA(0:imax-1, 1:jmax)
    real(DP):: SumB
    real(DP):: SumA
    real(DP):: Factor

    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
      end if
    end if

    ! Backup of a variable
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_QMixBefCor = xyzf_QMix
    end if

    ! Preparation of variable for reference
    if ( present( xyzf_QMixRef ) ) then
      xyzf_QMixRefLV = xyzf_QMixRef
    else
      xyzf_QMixRefLV = xyzf_QMix
    end if

    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = &
          & ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
    else
      xyz_DelMassRef = xyz_DelMass
    end if

    ! Fill grids with negative values
    xyzf_QMix = max( xyzf_QMix, 0.0_DP )

    ! Calculation of weight (pressure)
    do k = 1, kmax
      xyz_Weight(:,:,k) = ( xyr_Press(:,:,k-1) + xyr_Press(:,:,k) ) / 2.0_DP
    end do

    ! loop for constituents
    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        !
        ! Calculation of factor, alpha
        !
        xy_FactAlphaNumer = 0.0_DP
        xy_FactAlphaDenom = 0.0_DP
        do k = kmax, 1, -1
          xy_FactAlphaNumer = xy_FactAlphaNumer                 &
            & + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k) &
            & - xyzf_QMix     (:,:,k,n) * xyz_DelMass     (:,:,k)
          xy_FactAlphaDenom = xy_FactAlphaDenom                               &
            & + xyz_Weight  (:,:,k)                                           &
            & * xyzf_QMix   (:,:,k,n)                                         &
            & * abs( xyzf_QMix(:,:,k,n) - xyzf_QMixRefLV(:,:,k,n) )**FactBeta &
            & * xyz_DelMass(:,:,k)
        end do
        FactAlphaNumer = IntLonLat_xy( xy_FactAlphaNumer )
        FactAlphaDenom = IntLonLat_xy( xy_FactAlphaDenom )
        if ( FactAlphaDenom /= 0.0_DP ) then
          FactAlpha = FactAlphaNumer / FactAlphaDenom
        else
          FactAlpha = 0.0_DP
        end if

        xyzf_QMix(:,:,:,n) = xyzf_QMix(:,:,:,n) &
          & + FactAlpha * xyz_Weight * xyzf_QMix(:,:,:,n)    &
          &     * abs( xyzf_QMix(:,:,:,n) - xyzf_QMixRefLV(:,:,:,n) )**FactBeta

      end if

    end do

    ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
    ! Calculate specific humidity variance
    !
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_DQMixDt = ( xyzf_QMix - xyzf_QMixBefCor ) / ( 2.0_DP * DelTime )
    end if

    ! Ensure non-negative values
    ! This procedure is not included in Rasch et al. (1995).
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
        xy_SumB = 0.0_DP
        xy_SumA = 0.0_DP
        do k = kmax, 1, -1
          xy_SumB = xy_SumB + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k)
          xy_SumA = xy_SumA + xyzf_QMix     (:,:,k,n) * xyz_DelMass   (:,:,k)
        end do
        SumB = IntLonLat_xy( xy_SumB )
        SumA = IntLonLat_xy( xy_SumA )
        if ( SumA == 0.0_DP ) then
          Factor = 0.0_DP
        else if ( SumA < 0.0_DP ) then
          call MessageNotify( 'M', module_name,      &
            & 'R95: n = %d, SumA is negative, %f.', &
            & i = (/ n /), d = (/ SumA /) )
          Factor = 0.0_DP
        else
          if ( SumB < 0.0_DP ) then
            call MessageNotify( 'M', module_name,      &
              & 'R95: n = %d, SumB is negative, %f.', &
              & i = (/ n /), d = (/ SumB /) )
            Factor = 0.0_DP
          else
            Factor = SumB / SumA
          end if
        end if
        xyzf_QMix(:,:,:,n) = Factor * xyzf_QMix(:,:,:,n)
      end if
    end do

!!$    ! This is not required.
!!$    do n = 1, ncmax
!!$      if ( CompositionInqFlagMassFix( n ) ) then
!!$        do k = 1, kmax
!!$          do j = 1, jmax
!!$            do i = 0, imax-1
!!$              if ( xyzf_QMix(i,j,k,n) < 0.0_DP ) then
!!$                call MessageNotify( 'M', module_name, &
!!$                  & 'R95: Negative at (%f,%f,%f,%d), Val = %f.', &
!!$                  & d = (/ x_Lon(i)*180.0_DP/PI,  y_Lat(j)*180.0_DP/PI, &
!!$                  &        z_Sigma(k), xyzf_QMix(i,j,k,n) /), &
!!$                  & i = (/ n /) )
!!$              end if
!!$            end do
!!$          end do
!!$        end do
!!$      end if
!!$    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerR95

  !--------------------------------------------------------------------------------------

  subroutine MassFixerR95Layer(     &
    & xyr_Press,               & ! (in)
    & xyzf_QMix,               & ! (inout)
    & xyr_PressRef,            & ! (in) optional
    & xyzf_QMixRef,            & ! (in) optional
    & xyzf_DQMixDt             & ! (out) optional
    & )
    !
    ! Rasch et al. (1995) ã®æ–¹æ³•ã«å¾“ã„, æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒ *xyzf_QMixRef* ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚Œãªã„å ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒè£œæ£å‰ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fix masses of constituents following a method proposed by
    ! Rasch et al. (1995).
    ! If *xyzf_QMixRef* is given, the mass is fixed to match its global
    ! integrated value is the same as that of *xyzf_QMixRef*.
    ! If *xyzf_QMixRef* is not given, the mass is fixed to match its global
    ! integrated value is the same as that of pre-fixed value.
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: a_IntLonLat_xya

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ), optional:: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ), optional:: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyzf_QMixRefLV(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ . å±¤å†…ã®æˆåˆ†ã®æ··åˆæ¯”.
                              ! Reference specific mass of constituent (local value)

    real(DP):: xyzf_QMixBefCor   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !

    real(DP):: xyz_Weight       (0:imax-1, 1:jmax, 1:kmax)
    real(DP):: xyz_FactAlphaNumer(0:imax-1, 1:jmax, 1:kmax)
    real(DP):: xyz_FactAlphaDenom(0:imax-1, 1:jmax, 1:kmax)
    real(DP):: z_FactAlphaNumer(1:kmax)
    real(DP):: z_FactAlphaDenom(1:kmax)
    real(DP):: z_FactAlpha     (1:kmax)
    real(DP), parameter:: FactBeta = 1.0_DP ! for Rasch et al. (1994)

    real(DP):: xyz_SumB(0:imax-1, 1:jmax, 1:kmax)
    real(DP):: xyz_SumA(0:imax-1, 1:jmax, 1:kmax)
    real(DP):: z_SumB(1:kmax)
    real(DP):: z_SumA(1:kmax)
    real(DP):: z_Factor(1:kmax)

    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
      end if
    end if

    ! Backup of a variable
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_QMixBefCor = xyzf_QMix
    end if

    ! Preparation of variable for reference
    if ( present( xyzf_QMixRef ) ) then
      xyzf_QMixRefLV = xyzf_QMixRef
    else
      xyzf_QMixRefLV = xyzf_QMix
    end if

    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = &
          & ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
    else
      xyz_DelMassRef = xyz_DelMass
    end if

    ! Fill grids with negative values
    xyzf_QMix = max( xyzf_QMix, 0.0_DP )

    ! Calculation of weight (pressure)
    do k = 1, kmax
      xyz_Weight(:,:,k) = ( xyr_Press(:,:,k-1) + xyr_Press(:,:,k) ) / 2.0_DP
    end do

    ! loop for constituents
    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        !
        ! Calculation of factor, alpha
        !
        xyz_FactAlphaNumer = &
          & + xyzf_QMixRefLV(:,:,:,n) * xyz_DelMassRef &
          & - xyzf_QMix     (:,:,:,n) * xyz_DelMass
        xyz_FactAlphaDenom = &
          & + xyz_Weight                                                    &
          & * xyzf_QMix   (:,:,:,n)                                         &
          & * abs( xyzf_QMix(:,:,:,n) - xyzf_QMixRefLV(:,:,:,n) )**FactBeta &
          & * xyz_DelMass
        z_FactAlphaNumer = a_IntLonLat_xya( xyz_FactAlphaNumer )
        z_FactAlphaDenom = a_IntLonLat_xya( xyz_FactAlphaDenom )
        do k = 1, kmax
          if ( z_FactAlphaDenom(k) /= 0.0_DP ) then
            z_FactAlpha(k) = z_FactAlphaNumer(k) / z_FactAlphaDenom(k)
          else
            z_FactAlpha(k) = 0.0_DP
          end if
        end do

        do k = 1, kmax
          xyzf_QMix(:,:,k,n) = xyzf_QMix(:,:,k,n)                          &
            & + z_FactAlpha(k) * xyz_Weight(:,:,k) * xyzf_QMix(:,:,k,n)    &
            &   * abs( xyzf_QMix(:,:,k,n) - xyzf_QMixRefLV(:,:,k,n) )**FactBeta
        end do

      end if

    end do

    ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
    ! Calculate specific humidity variance
    !
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_DQMixDt = ( xyzf_QMix - xyzf_QMixBefCor ) / ( 2.0_DP * DelTime )
    end if

    ! Ensure non-negative values
    ! This procedure is not included in Rasch et al. (1995).
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
        xyz_SumB = xyzf_QMixRefLV(:,:,:,n) * xyz_DelMassRef
        xyz_SumA = xyzf_QMix     (:,:,:,n) * xyz_DelMass
        z_SumB = a_IntLonLat_xya( xyz_SumB )
        z_SumA = a_IntLonLat_xya( xyz_SumA )
        do k = 1, kmax
          if ( z_SumA(k) == 0.0_DP ) then
            z_Factor(k) = 0.0_DP
          else if ( z_SumA(k) < 0.0_DP ) then
            call MessageNotify( 'M', module_name,      &
              & 'R95: n = %d, SumA is negative, %f.', &
              & i = (/ n /), d = (/ z_SumA(k) /) )
            z_Factor(k) = 0.0_DP
          else
            if ( z_SumB(k) < 0.0_DP ) then
              call MessageNotify( 'M', module_name,      &
                & 'R95: n = %d, SumB is negative, %f.', &
                & i = (/ n /), d = (/ z_SumB(k) /) )
              z_Factor(k) = 0.0_DP
            else
              z_Factor(k) = z_SumB(k) / z_SumA(k)
            end if
          end if
        end do
        do k = 1, kmax
          xyzf_QMix(:,:,k,n) = z_Factor(k) * xyzf_QMix(:,:,k,n)
        end do
      end if
    end do

!!$    ! This is not required.
!!$    do n = 1, ncmax
!!$      if ( CompositionInqFlagMassFix( n ) ) then
!!$        do k = 1, kmax
!!$          do j = 1, jmax
!!$            do i = 0, imax-1
!!$              if ( xyzf_QMix(i,j,k,n) < 0.0_DP ) then
!!$                call MessageNotify( 'M', module_name, &
!!$                  & 'R95: Negative at (%f,%f,%f,%d), Val = %f.', &
!!$                  & d = (/ x_Lon(i)*180.0_DP/PI,  y_Lat(j)*180.0_DP/PI, &
!!$                  &        z_Sigma(k), xyzf_QMix(i,j,k,n) /), &
!!$                  & i = (/ n /) )
!!$              end if
!!$            end do
!!$          end do
!!$        end do
!!$      end if
!!$    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerR95Layer

  !--------------------------------------------------------------------------------------

  subroutine MassFixerR95Column(     &
    & xyr_Press,               & ! (in)
    & xyzf_QMix,               & ! (inout)
    & xyr_PressRef,            & ! (in) optional
    & xyzf_QMixRef,            & ! (in) optional
    & xyzf_DQMixDt             & ! (out) optional
    & )
    !
    ! Rasch et al. (1995) ã®æ–¹æ³•ã«å¾“ã„, æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒ *xyzf_QMixRef* ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚Œãªã„å ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒè£œæ£å‰ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fix masses of constituents following a method proposed by
    ! Rasch et al. (1995).
    ! If *xyzf_QMixRef* is given, the mass is fixed to match its global
    ! integrated value is the same as that of *xyzf_QMixRef*.
    ! If *xyzf_QMixRef* is not given, the mass is fixed to match its global
    ! integrated value is the same as that of pre-fixed value.
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ), optional:: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ), optional:: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyzf_QMixRefLV(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ . å±¤å†…ã®æˆåˆ†ã®æ··åˆæ¯”.
                              ! Reference specific mass of constituent (local value)

    real(DP):: xyzf_QMixBefCor   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !

    real(DP):: xyz_Weight       (0:imax-1, 1:jmax, 1:kmax)
    real(DP):: xy_FactAlphaNumer(0:imax-1, 1:jmax)
    real(DP):: xy_FactAlphaDenom(0:imax-1, 1:jmax)
    real(DP):: xy_FactAlpha(0:imax-1, 1:jmax)
    real(DP), parameter:: FactBeta = 1.0_DP ! for Rasch et al. (1994)

    real(DP):: xy_SumB(0:imax-1, 1:jmax)
    real(DP):: xy_SumA(0:imax-1, 1:jmax)
    real(DP):: xy_Factor(0:imax-1, 1:jmax)

    integer:: i               ! çµŒåº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! ç·¯åº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in latitudinal direction
    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
      end if
    end if

    ! Backup of a variable
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_QMixBefCor = xyzf_QMix
    end if

    ! Preparation of variable for reference
    if ( present( xyzf_QMixRef ) ) then
      xyzf_QMixRefLV = xyzf_QMixRef
    else
      xyzf_QMixRefLV = xyzf_QMix
    end if

    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = &
          & ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
    else
      xyz_DelMassRef = xyz_DelMass
    end if

    ! Fill grids with negative values
    xyzf_QMix = max( xyzf_QMix, 0.0_DP )

    ! Calculation of weight (pressure)
    do k = 1, kmax
      xyz_Weight(:,:,k) = ( xyr_Press(:,:,k-1) + xyr_Press(:,:,k) ) / 2.0_DP
    end do

    ! loop for constituents
    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        !
        ! Calculation of factor, alpha
        !
        xy_FactAlphaNumer = 0.0_DP
        xy_FactAlphaDenom = 0.0_DP
        do k = kmax, 1, -1
          xy_FactAlphaNumer = xy_FactAlphaNumer                 &
            & + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k) &
            & - xyzf_QMix     (:,:,k,n) * xyz_DelMass     (:,:,k)
          xy_FactAlphaDenom = xy_FactAlphaDenom                               &
            & + xyz_Weight  (:,:,k)                                           &
            & * xyzf_QMix   (:,:,k,n)                                         &
            & * abs( xyzf_QMix(:,:,k,n) - xyzf_QMixRefLV(:,:,k,n) )**FactBeta &
            & * xyz_DelMass(:,:,k)
        end do
        do j = 1, jmax
          do i = 0, imax-1
            if ( xy_FactAlphaDenom(i,j) /= 0.0_DP ) then
              xy_FactAlpha(i,j) = xy_FactAlphaNumer(i,j) / xy_FactAlphaDenom(i,j)
            else
              xy_FactAlpha(i,j) = 0.0_DP
            end if
          end do
        end do

        do k = 1, kmax
          xyzf_QMix(:,:,k,n) = xyzf_QMix(:,:,k,n) &
          & + xy_FactAlpha * xyz_Weight(:,:,k) * xyzf_QMix(:,:,k,n)    &
          &     * abs( xyzf_QMix(:,:,k,n) - xyzf_QMixRefLV(:,:,k,n) )**FactBeta
        end do

      end if

    end do

    ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
    ! Calculate specific humidity variance
    !
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_DQMixDt = ( xyzf_QMix - xyzf_QMixBefCor ) / ( 2.0_DP * DelTime )
    end if

    ! Ensure non-negative values
    ! This procedure is not included in Rasch et al. (1995).
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
        xy_SumB = 0.0_DP
        xy_SumA = 0.0_DP
        do k = kmax, 1, -1
          xy_SumB = xy_SumB + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k)
          xy_SumA = xy_SumA + xyzf_QMix     (:,:,k,n) * xyz_DelMass   (:,:,k)
        end do
        do j = 1, jmax
          do i = 0, imax-1
            if ( xy_SumA(i,j) == 0.0_DP ) then
              xy_Factor(i,j) = 0.0_DP
            else if ( xy_SumA(i,j) < 0.0_DP ) then
              call MessageNotify( 'M', module_name,      &
                & 'R95: n = %d, SumA is negative, %f.', &
                & i = (/ n /), d = (/ xy_SumA(i,j) /) )
              xy_Factor(i,j) = 0.0_DP
            else
              if ( xy_SumB(i,j) < 0.0_DP ) then
                call MessageNotify( 'M', module_name,      &
                  & 'R95: n = %d, SumB is negative, %f.', &
                  & i = (/ n /), d = (/ xy_SumB(i,j) /) )
                xy_Factor(i,j) = 0.0_DP
              else
                xy_Factor(i,j) = xy_SumB(i,j) / xy_SumA(i,j)
              end if
            end if
          end do
        end do
        do k = 1, kmax
          xyzf_QMix(:,:,k,n) = xy_Factor * xyzf_QMix(:,:,k,n)
        end do
      end if
    end do

!!$    ! This is not required.
!!$    do n = 1, ncmax
!!$      if ( CompositionInqFlagMassFix( n ) ) then
!!$        do k = 1, kmax
!!$          do j = 1, jmax
!!$            do i = 0, imax-1
!!$              if ( xyzf_QMix(i,j,k,n) < 0.0_DP ) then
!!$                call MessageNotify( 'M', module_name, &
!!$                  & 'R95: Negative at (%f,%f,%f,%d), Val = %f.', &
!!$                  & d = (/ x_Lon(i)*180.0_DP/PI,  y_Lat(j)*180.0_DP/PI, &
!!$                  &        z_Sigma(k), xyzf_QMix(i,j,k,n) /), &
!!$                  & i = (/ n /) )
!!$              end if
!!$            end do
!!$          end do
!!$        end do
!!$      end if
!!$    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerR95Column

  !--------------------------------------------------------------------------------------

  subroutine MassFixerWO94(    &
    & xyr_Press,               & ! (in)
    & xyzf_QMix,               & ! (inout)
    & xyr_PressRef,            & ! (in) optional
    & xyzf_QMixRef,            & ! (in) optional
    & xyzf_DQMixDt             & ! (out) optional
    & )
    !
    ! Williamson and Olson (1994) ã®æ–¹æ³•ã«å¾“ã„, æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒ *xyzf_QMixRef* ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚Œãªã„å ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒè£œæ£å‰ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fix masses of constituents following a method proposed by
    ! Williamson and Olson (1994).
    ! If *xyzf_QMixRef* is given, the mass is fixed to match its global
    ! integrated value is the same as that of *xyzf_QMixRef*.
    ! If *xyzf_QMixRef* is not given, the mass is fixed to match its global
    ! integrated value is the same as that of pre-fixed value.
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration
    ! åº§æ¨™ãƒ‡ãƒ¼ã‚¿è¨å®š
    ! Axes data settings
    !
    use axesset, only: &
      & x_Lon,         &
      & y_Lat,         &
      & z_Sigma

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: IntLonLat_xy

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ), optional:: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ), optional:: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyzf_QMixRefLV(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ . å±¤å†…ã®æˆåˆ†ã®æ··åˆæ¯”.
                              ! Reference specific mass of constituent (local value)

    real(DP):: xyzf_QMixBefCor   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !

    real(DP):: xy_FactAlphaNumer(0:imax-1, 1:jmax)
    real(DP):: xy_FactAlphaDenom(0:imax-1, 1:jmax)
    real(DP):: FactAlphaNumer
    real(DP):: FactAlphaDenom
    real(DP):: FactAlpha
    real(DP), parameter:: FactBeta = 1.5_DP

    real(DP):: xy_SumB(0:imax-1, 1:jmax)
    real(DP):: xy_SumA(0:imax-1, 1:jmax)
    real(DP):: SumB
    real(DP):: SumA
    real(DP):: Factor

    integer:: i               ! çµŒåº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! ç·¯åº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in latitudinal direction
    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
      end if
    end if

    ! Backup of a variable
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_QMixBefCor = xyzf_QMix
    end if

    ! Preparation of variable for reference
    if ( present( xyzf_QMixRef ) ) then
      xyzf_QMixRefLV = xyzf_QMixRef
    else
      xyzf_QMixRefLV = xyzf_QMix
    end if

    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = &
          & ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
    else
      xyz_DelMassRef = xyz_DelMass
    end if

    ! Fill grids with negative values
    xyzf_QMix = max( xyzf_QMix, 0.0_DP )

    ! loop for constituents
    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        !
        ! Calculation of factor, alpha
        !
        xy_FactAlphaNumer = 0.0_DP
        xy_FactAlphaDenom = 0.0_DP
        do k = kmax, 1, -1
          xy_FactAlphaNumer = xy_FactAlphaNumer                 &
            & + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k) &
            & - xyzf_QMix     (:,:,k,n) * xyz_DelMass     (:,:,k)
          xy_FactAlphaDenom = xy_FactAlphaDenom                               &
            & + xyzf_QMix   (:,:,k,n)                                         &
            & * abs( xyzf_QMix(:,:,k,n) - xyzf_QMixRefLV(:,:,k,n) )**FactBeta &
            & * xyz_DelMass(:,:,k)
        end do
        FactAlphaNumer = IntLonLat_xy( xy_FactAlphaNumer )
        FactAlphaDenom = IntLonLat_xy( xy_FactAlphaDenom )
        if ( FactAlphaDenom /= 0.0_DP ) then
          FactAlpha = FactAlphaNumer / FactAlphaDenom
        else
          FactAlpha = 0.0_DP
        end if

        xyzf_QMix(:,:,:,n) = xyzf_QMix(:,:,:,n) &
          & + FactAlpha * xyzf_QMix(:,:,:,n)    &
          &     * abs( xyzf_QMix(:,:,:,n) - xyzf_QMixRefLV(:,:,:,n) )**FactBeta

      end if

    end do

    ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
    ! Calculate specific humidity variance
    !
    if ( present( xyzf_DQMixDt ) ) then
      xyzf_DQMixDt = ( xyzf_QMix - xyzf_QMixBefCor ) / ( 2.0_DP * DelTime )
    end if

    ! Ensure non-negative values
    ! This procedure is not included in Williams and Olson (1994).
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )
        xy_SumB = 0.0_DP
        xy_SumA = 0.0_DP
        do k = kmax, 1, -1
          xy_SumB = xy_SumB + xyzf_QMixRefLV(:,:,k,n) * xyz_DelMassRef(:,:,k)
          xy_SumA = xy_SumA + xyzf_QMix     (:,:,k,n) * xyz_DelMass   (:,:,k)
        end do
        SumB = IntLonLat_xy( xy_SumB )
        SumA = IntLonLat_xy( xy_SumA )
        if ( SumA == 0.0_DP ) then
          Factor = 0.0_DP
        else if ( SumA < 0.0_DP ) then
          call MessageNotify( 'M', module_name,      &
            & 'WO94: n = %d, SumA is negative, %f.', &
            & i = (/ n /), d = (/ SumA /) )
          Factor = 0.0_DP
        else
          if ( SumB < 0.0_DP ) then
            call MessageNotify( 'M', module_name,      &
              & 'WO94: n = %d, SumB is negative, %f.', &
              & i = (/ n /), d = (/ SumB /) )
            Factor = 0.0_DP
          else
            Factor = SumB / SumA
          end if
        end if
        xyzf_QMix(:,:,:,n) = Factor * xyzf_QMix(:,:,:,n)
      end if
    end do

    ! This is not required.
    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        do k = 1, kmax
          do j = 1, jmax
            do i = 0, imax-1
              if ( xyzf_QMix(i,j,k,n) < 0.0_DP ) then
                if ( xyzf_QMix(i,j,k,n) < ThresholdForMessage ) then
                  call MessageNotify( 'M', module_name, &
                    & 'WO94: Negative at (%f,%f,%f,%d), Val = %f.', &
                    & d = (/ x_Lon(i)*180.0_DP/PI,  y_Lat(j)*180.0_DP/PI, &
                    &        z_Sigma(k), xyzf_QMix(i,j,k,n) /), &
                    & i = (/ n /) )
                end if
              end if
            end do
          end do
        end do
      end if
    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerWO94

  !--------------------------------------------------------------------------------------

  subroutine MassFixer(           &
    & xyr_Press,                  & ! (in)
    & xyzf_QMix,                  & ! (inout)
    & xyr_PressRef,               & ! (in) optional
    & xyzf_QMixRef,               & ! (in) optional
    & xyzf_DQMixDt                & ! (out) optional
    & )
    !
    ! æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒ *xyzf_QMixRef* ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚Œãªã„å ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒè£œæ£å‰ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fixes masses of constituents.
    ! If *xyzf_QMixRef* is given, the mass is fixed to match its global
    ! integrated value is the same as that of *xyzf_QMixRef*.
    ! If *xyzf_QMixRef* is not given, the mass is fixed to match its global
    ! integrated value is the same as that of pre-fixed value.
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! åº§æ¨™ãƒ‡ãƒ¼ã‚¿è¨å®š
    ! Axes data settings
    !
    use axesset, only: &
      & x_Lon,         &
      & y_Lat,         &
      & z_Sigma

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: IntLonLat_xy

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ), optional:: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ), optional:: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyz_QMixBefCor    (0:imax-1, 1:jmax, 1:kmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !
    real(DP):: xyz_DelConsMass   (0:imax-1, 1:jmax, 1:kmax)
                              ! å„å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Mass of constituents in a layer.
    real(DP):: xyz_DelConsMassRef(0:imax-1, 1:jmax, 1:kmax)
                              ! ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å„å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference mass of constituents.
    real(DP):: xy_ConsMass          (0:imax-1, 1:jmax)
                              ! æˆåˆ†ã®ã‚«ãƒ©ãƒ è³ªé‡.
                              ! Mass of constituents in a layer.
    real(DP):: xy_ConsMassRef       (0:imax-1, 1:jmax)
                              ! ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹æˆåˆ†ã®ã‚«ãƒ©ãƒ è³ªé‡.
                              ! Reference mass of constituents in a layer.
    real(DP):: ConsMass
                              ! å…¨çƒã®å„æˆåˆ†ã®è³ªé‡
                              ! Total mass of constituents
    real(DP):: ConsMassRef
                              ! ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å…¨çƒã®å„æˆåˆ†ã®è³ªé‡
                              ! Reference total mass of constituents.
                              !

    integer:: i               ! çµŒåº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! ç·¯åº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in latitudinal direction
    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
      end if
    end if

    ! $ \Delta p / g $ ã®è¨ˆç®—
    ! Calculate $ \Delta p / g $
    !
    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
    end if

    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        ! Calculate mass of constituents
        !
        xyz_DelConsMass = xyzf_QMix(:,:,:,n) * xyz_DelMass

        if ( present( xyzf_QMixRef ) ) then
          xyz_DelConsMassRef = xyzf_QMixRef(:,:,:,n) * xyz_DelMassRef
        else
          xyz_DelConsMassRef = xyz_DelConsMass
        end if
        if ( present( xyzf_DQMixDt ) ) then
          xyz_QMixBefCor = xyzf_QMix(:,:,:,n)
        end if

        ! è² ã®è³ªé‡ã‚’ç›´ä¸‹ã®å±¤ã®è³ªé‡ã§åŸ‹ã‚åˆã‚ã›.
        ! Negative mass is removed by filling it with the mass in a layer just below.
        !
        do k = kmax, 2, -1
          do j = 1, jmax
            do i = 0, imax-1
              if ( xyz_DelConsMass(i,j,k) < 0.0_DP ) then
                xyz_DelConsMass(i,j,k-1) = xyz_DelConsMass(i,j,k-1) &
                  & + xyz_DelConsMass(i,j,k)
                xyz_DelConsMass(i,j,k  ) = 0.0_DP
              end if
            end do
          end do
        end do

        k = 1
        do j = 1, jmax
          do i = 0, imax-1
            if ( xyz_DelConsMass(i,j,k) < 0.0_DP ) then
              xyz_DelConsMass(i,j,k) = 0.0_DP
            end if
          end do
        end do

        ! å…¨çƒã§ã®è£œæ£
        ! Correction in globe
        !   è³ªé‡ä¿å˜ã®ãŸã‚ã«å…¨ä½“ã®è³ªé‡ã‚’æ¸›å°‘ã•ã›ã‚‹.
        !   Total mass is decreased to conserve mass.
        !
        xy_ConsMass    = 0.0_DP
        xy_ConsMassRef = 0.0_DP
        do k = kmax, 1, -1
          xy_ConsMass    = xy_ConsMass    + xyz_DelConsMass   (:,:,k)
          xy_ConsMassRef = xy_ConsMassRef + xyz_DelConsMassRef(:,:,k)
        end do
        ConsMass    = IntLonLat_xy( xy_ConsMass    )
        ConsMassRef = IntLonLat_xy( xy_ConsMassRef )

        if ( ConsMassRef < 0.0_DP ) then
          if ( ConsMassRef < ThresholdForMessage ) then
            call MessageNotify( 'M', module_name, 'ConsMassRef is less than %f. ' &
              & // 'ConsMassRef is reset to zero, n = %d, ConsMassRef = %f.', &
              & i = (/ n /), d = (/ ThresholdForMessage, ConsMassRef /) )
          end if
          ConsMassRef = 0.0_DP
!!$        call MessageNotify( 'E', module_name, 'ConsMassRef is negative, n = %d.', i = (/ n /) )
        end if
        if ( ConsMass /= 0.0_DP ) then
          xyz_DelConsMass = ConsMassRef / ConsMass * xyz_DelConsMass
        else
          xyz_DelConsMass = 0.0_DP
        end if

        xyzf_QMix(:,:,:,n) = xyz_DelConsMass / xyz_DelMass

        ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
        ! Calculate specific humidity variance
        !
        if ( present( xyzf_DQMixDt ) ) then
          xyzf_DQMixDt(:,:,:,n) =     &
            &  ( xyzf_QMix(:,:,:,n) - xyz_QMixBefCor ) / ( 2.0_DP * DelTime )
        end if

      else

        if ( present( xyzf_DQMixDt ) ) then
          xyz_QMixBefCor = xyzf_QMix(:,:,:,n)
        end if

        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )

        ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
        ! Calculate specific humidity variance
        !
        if ( present( xyzf_DQMixDt ) ) then
          xyzf_DQMixDt(:,:,:,n) =     &
            &  ( xyzf_QMix(:,:,:,n) - xyz_QMixBefCor ) / ( 2.0_DP * DelTime )
        end if

      end if

    end do

    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        do k = 1, kmax
          do j = 1, jmax
            do i = 0, imax-1
              if ( xyzf_QMix(i,j,k,n) < 0.0_DP ) then
                if ( xyzf_QMix(i,j,k,n) < ThresholdForMessage ) then
                  call MessageNotify( 'M', module_name, &
                    & 'Negative at (%f,%f,%f,%d), Val = %f.', &
                    & d = (/ x_Lon(i)*180.0_DP/PI, y_Lat(j)*180.0_DP/PI, &
                    &        z_Sigma(k), xyzf_QMix(i,j,k,n) /), &
                    & i = (/ n /) )
                end if
              end if
            end do
          end do
        end do
      end if
    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixer

  !--------------------------------------------------------------------------------------

  subroutine MassFixerLayer(      &
    & xyr_Press,                  & ! (in)
    & xyzf_QMix,                  & ! (inout)
    & xyr_PressRef,               & ! (in) optional
    & xyzf_QMixRef,               & ! (in) optional
    & xyzf_DQMixDt                & ! (out) optional
    & )
    !
    ! é‰›ç›´å±¤å†…ã§æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒ *xyzf_QMixRef* ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚Œãªã„å ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒè£œæ£å‰ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fixes masses of constituents in each vertical layer.
    ! If *xyzf_QMixRef* is given, the mass is fixed to match its global
    ! integrated value is the same as that of *xyzf_QMixRef*.
    ! If *xyzf_QMixRef* is not given, the mass is fixed to match its global
    ! integrated value is the same as that of pre-fixed value.
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! åº§æ¨™ãƒ‡ãƒ¼ã‚¿è¨å®š
    ! Axes data settings
    !
    use axesset, only: &
      & x_Lon,         &
      & y_Lat,         &
      & z_Sigma

    ! ç©åˆ†ã¨å¹³å‡ã®æ“ä½œ
    ! Operation for integral and average
    !
    use intavr_operate, only: a_IntLonLat_xya

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ), optional:: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ), optional:: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyz_QMixBefCor    (0:imax-1, 1:jmax, 1:kmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !
    real(DP):: xyz_DelConsMass   (0:imax-1, 1:jmax, 1:kmax)
                              ! å„å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Mass of constituents in a layer.
    real(DP):: xyz_DelConsMassRef(0:imax-1, 1:jmax, 1:kmax)
                              ! ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å„å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference mass of constituents.
    real(DP):: z_ConsMass   (1:kmax)
                              ! å…¨çƒã®å„æˆåˆ†ã®è³ªé‡
                              ! Total mass of constituents
    real(DP):: z_ConsMassRef(1:kmax)
                              ! ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å…¨çƒã®å„æˆåˆ†ã®è³ªé‡
                              ! Reference total mass of constituents.
                              !

    integer:: i               ! çµŒåº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! ç·¯åº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in latitudinal direction
    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
      end if
    end if

    ! $ \Delta p / g $ ã®è¨ˆç®—
    ! Calculate $ \Delta p / g $
    !
    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
    end if

    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        ! Calculate mass of constituents
        !
        xyz_DelConsMass = xyzf_QMix(:,:,:,n) * xyz_DelMass

        if ( present( xyzf_QMixRef ) ) then
          xyz_DelConsMassRef = xyzf_QMixRef(:,:,:,n) * xyz_DelMassRef
        else
          xyz_DelConsMassRef = xyz_DelConsMass
        end if
        if ( present( xyzf_DQMixDt ) ) then
          xyz_QMixBefCor = xyzf_QMix(:,:,:,n)
        end if

        do k = 1, kmax
          do j = 1, jmax
            do i = 0, imax-1
              if ( xyz_DelConsMass(i,j,k) < 0.0_DP ) then
                xyz_DelConsMass(i,j,k) = 0.0_DP
              end if
            end do
          end do
        end do

        ! å„å±¤ã§ã®è£œæ£
        ! Correction in each layer
        !   è³ªé‡ä¿å˜ã®ãŸã‚ã«å…¨ä½“ã®è³ªé‡ã‚’æ¸›å°‘ã•ã›ã‚‹.
        !   Total mass is decreased to conserve mass.
        !
        z_ConsMass    = a_IntLonLat_xya( xyz_DelConsMass    )
        z_ConsMassRef = a_IntLonLat_xya( xyz_DelConsMassRef )

        do k = 1, kmax

          if ( z_ConsMassRef(k) < 0.0_DP ) then
            if ( z_ConsMassRef(k) < ThresholdForMessage ) then
              call MessageNotify( 'M', module_name,                             &
                & 'z_ConsMassRef(%f) is less than %f. '                         &
                & // 'z_ConsMassRef is reset to zero, n = %d, z_ConsMassRef = %f.', &
                & d = (/ z_Sigma(k), ThresholdForMessage, z_ConsMassRef(k) /), i = (/ n /) )
            end if
            z_ConsMassRef(k) = 0.0_DP
!!$        call MessageNotify( 'E', module_name, 'ConsMassRef is negative, n = %d.', i = (/ n /) )
          end if
          if ( z_ConsMass(k) /= 0.0_DP ) then
            xyz_DelConsMass(:,:,k) = z_ConsMassRef(k) / z_ConsMass(k) * xyz_DelConsMass(:,:,k)
          else
            xyz_DelConsMass(:,:,k) = 0.0_DP
          end if

        end do

        xyzf_QMix(:,:,:,n) = xyz_DelConsMass / xyz_DelMass

        ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
        ! Calculate specific humidity variance
        !
        if ( present( xyzf_DQMixDt ) ) then
          xyzf_DQMixDt(:,:,:,n) =     &
            &   xyzf_DQMixDt(:,:,:,n) &
            & + ( xyzf_QMix(:,:,:,n) - xyz_QMixBefCor ) / ( 2.0_DP * DelTime )
        end if

      else

        if ( present( xyzf_DQMixDt ) ) then
          xyz_QMixBefCor = xyzf_QMix(:,:,:,n)
        end if

        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )

        ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
        ! Calculate specific humidity variance
        !
        if ( present( xyzf_DQMixDt ) ) then
          xyzf_DQMixDt(:,:,:,n) =     &
            &  ( xyzf_QMix(:,:,:,n) - xyz_QMixBefCor ) / ( 2.0_DP * DelTime )
        end if

      end if

    end do

    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        do k = 1, kmax
          do j = 1, jmax
            do i = 0, imax-1
              if ( xyzf_QMix(i,j,k,n) < 0.0_DP ) then
                if ( xyzf_QMix(i,j,k,n) < ThresholdForMessage ) then
                  call MessageNotify( 'M', module_name, &
                    & 'Layer: Negative at (%f,%f,%f,%d), Val = %f.', &
                    & d = (/ x_Lon(i)*180.0_DP/PI, y_Lat(j)*180.0_DP/PI, &
                    &        z_Sigma(k), xyzf_QMix(i,j,k,n)/), &
                    & i = (/ n /) )
                end if
              end if
            end do
          end do
        end do
      end if
    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerLayer

  !--------------------------------------------------------------------------------------

  subroutine MassFixerColumn(     &
    & xyr_Press,                  & ! (in)
    & xyzf_QMix,                  & ! (inout)
    & xyr_PressRef,               & ! (in) optional
    & xyzf_QMixRef,               & ! (in) optional
    & xyzf_DQMixDt                & ! (out) optional
    & )
    !
    ! é‰›ç›´ã‚«ãƒ©ãƒ å†…ã§æˆåˆ†ã®è³ªé‡ã‚’è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆã«ã¯, ã‚«ãƒ©ãƒ ç©åˆ†å€¤ãŒ *xyzf_QMixRef* ã®
    ! ãã‚Œã¨åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_QMixRef* ãŒä¸Žãˆã‚‰ã‚Œãªã„å ´åˆã«ã¯, å…¨çƒç©åˆ†å€¤ãŒè£œæ£å‰ã®ãã‚Œã¨
    ! åŒã˜ã«ãªã‚‹ã‚ˆã†ã«è£œæ£ã—ã¾ã™.
    ! *xyzf_DQMixDt* ã«ã¯ *xyz_QMix* ã®å¤‰åŒ–é‡ãŒè¿”ã‚Šã¾ã™.
    !
    ! This routine fixes masses of constituents in each vertical column.
    ! If *xyzf_QMixRef* is given, the mass is fixed to match its column
    ! integrated value is the same as that of *xyzf_QMixRef*.
    ! If *xyzf_QMixRef* is not given, the mass is fixed to match its column
    ! integrated value is the same as that of pre-fixed value.
    ! Variation of *xyzf_QMix* is returned to *xyz_DQMixDt*.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! ç‰©ç†ãƒ»æ•°å¦å®šæ•°è¨å®š
    ! Physical and mathematical constants settings
    !
    use constants0, only: &
      & PI                    ! $ \pi $.
                              ! å††å‘¨çŽ‡. Circular constant

    ! ç‰©ç†å®šæ•°è¨å®š
    ! Physical constants settings
    !
    use constants, only: Grav ! $ g $ [m s-2].
                              ! é‡åŠ›åŠ é€Ÿåº¦.
                              ! Gravitational acceleration

    ! åº§æ¨™ãƒ‡ãƒ¼ã‚¿è¨å®š
    ! Axes data settings
    !
    use axesset, only: &
      & x_Lon,         &
      & y_Lat,         &
      & z_Sigma

    ! æ™‚åˆ»ç®¡ç†
    ! Time control
    !
    use timeset, only: DelTime, &  ! $ \Delta t $
      & TimesetClockStart, TimesetClockStop

    ! çµ„æˆã«é–¢ã‚ã‚‹é…åˆ—ã®è¨å®š
    ! Settings of array for atmospheric composition
    !
    use composition, only: CompositionInqFlagMassFix

    ! å®£è¨€æ–‡ ; 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(inout)          :: xyzf_QMix   (0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q $ .     æ¯”æ¹¿. Specific humidity
    real(DP), intent(in   ), optional:: xyr_PressRef(0:imax-1, 1:jmax, 0:kmax)
                              ! $ \hat{p} $ . æ°—åœ§ (åŠæ•´æ•°ãƒ¬ãƒ™ãƒ«).
                              ! Air pressure (half level)
    real(DP), intent(in   ), optional:: xyzf_QMixRef(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ q \Delta p / g $ . ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference specific mass of constituent in a layer
    real(DP), intent(out  ), optional:: xyzf_DQMixDt(0:imax-1, 1:jmax, 1:kmax, 1:ncmax)
                              ! $ \DP{q}{t} $ .  æ¯”æ¹¿è£œæ£çŽ‡.
                              ! Specific humidity correction

    ! ä½œæ¥å¤‰æ•°
    ! Work variables
    !
    real(DP):: xyz_QMixBefCor    (0:imax-1, 1:jmax, 1:kmax)
                              ! ä¿®æ£å‰ã®æ¯”æ¹¿.
                              ! Specific humidity before correction.
    real(DP):: xyz_DelMass       (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $
                              !
    real(DP):: xyz_DelMassRef    (0:imax-1, 1:jmax, 1:kmax)
                              ! $ \Delta p / g $ of reference
                              !
    real(DP):: xyz_DelConsMass   (0:imax-1, 1:jmax, 1:kmax)
                              ! å„å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Mass of constituents in a layer.
    real(DP):: xyz_DelConsMassRef(0:imax-1, 1:jmax, 1:kmax)
                              ! ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹å„å±¤å†…ã®æˆåˆ†ã®è³ªé‡.
                              ! Reference mass of constituents.
    real(DP):: xy_ConsMass          (0:imax-1, 1:jmax)
                              ! æˆåˆ†ã®ã‚«ãƒ©ãƒ è³ªé‡.
                              ! Mass of constituents in a layer.
    real(DP):: xy_ConsMassRef       (0:imax-1, 1:jmax)
                              ! ç©åˆ†å€¤ã‚’åˆã‚ã›ã‚‹æˆåˆ†ã®ã‚«ãƒ©ãƒ è³ªé‡.
                              ! Reference mass of constituents in a layer.

    integer:: i               ! çµŒåº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in longitudinal direction
    integer:: j               ! ç·¯åº¦æ–¹å‘ã«å›žã‚‹ DO ãƒ«ãƒ¼ãƒ—ç”¨ä½œæ¥å¤‰æ•°
                              ! Work variables for DO loop in latitudinal direction
    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. mass_fixer_inited ) then
      call MessageNotify( 'E', module_name, 'This module has not been initialized.' )
    end if

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬é–‹å§‹
    ! Start measurement of computation time
    !
    call TimesetClockStart( module_name )

    ! Check arguments
    !
    if ( present( xyr_PressRef ) .or. present( xyzf_QMixRef ) ) then
      if ( .not. ( present( xyr_PressRef ) .and. present( xyzf_QMixRef ) ) ) then
        call MessageNotify( 'E', module_name, 'If xyr_PressRef or xyzf_QMixRef is given, both have to be given.' )
      end if
    end if

    ! $ \Delta p / g $ ã®è¨ˆç®—
    ! Calculate $ \Delta p / g $
    !
    do k = 1, kmax
      xyz_DelMass(:,:,k) = ( xyr_Press(:,:,k-1) - xyr_Press(:,:,k) ) / Grav
    end do

    if ( present( xyr_PressRef ) ) then
      do k = 1, kmax
        xyz_DelMassRef(:,:,k) = ( xyr_PressRef(:,:,k-1) - xyr_PressRef(:,:,k) ) / Grav
      end do
    end if

    do n = 1, ncmax

      if ( CompositionInqFlagMassFix( n ) ) then

        ! Calculate mass of constituents
        !
        xyz_DelConsMass = xyzf_QMix(:,:,:,n) * xyz_DelMass

        if ( present( xyzf_QMixRef ) ) then
          xyz_DelConsMassRef = xyzf_QMixRef(:,:,:,n) * xyz_DelMassRef
        else
          xyz_DelConsMassRef = xyz_DelConsMass
        end if
        if ( present( xyzf_DQMixDt ) ) then
          xyz_QMixBefCor = xyzf_QMix(:,:,:,n)
        end if

        ! è² ã®è³ªé‡ã‚’ç›´ä¸‹ã®å±¤ã®è³ªé‡ã§åŸ‹ã‚åˆã‚ã›.
        ! Negative mass is removed by filling it with the mass in a layer just below.
        !
        do k = kmax, 2, -1
          do j = 1, jmax
            do i = 0, imax-1
              if ( xyz_DelConsMass(i,j,k) < 0.0_DP ) then
                xyz_DelConsMass(i,j,k-1) = xyz_DelConsMass(i,j,k-1) &
                  & + xyz_DelConsMass(i,j,k)
                xyz_DelConsMass(i,j,k  ) = 0.0_DP
              end if
            end do
          end do
        end do

        k = 1
        do j = 1, jmax
          do i = 0, imax-1
            if ( xyz_DelConsMass(i,j,k) < 0.0_DP ) then
              xyz_DelConsMass(i,j,k) = 0.0_DP
            end if
          end do
        end do

        ! å…¨çƒã§ã®è£œæ£
        ! Correction in globe
        !   è³ªé‡ä¿å˜ã®ãŸã‚ã«å…¨ä½“ã®è³ªé‡ã‚’æ¸›å°‘ã•ã›ã‚‹.
        !   Total mass is decreased to conserve mass.
        !
        xy_ConsMass    = 0.0_DP
        xy_ConsMassRef = 0.0_DP
        do k = kmax, 1, -1
          xy_ConsMass    = xy_ConsMass    + xyz_DelConsMass   (:,:,k)
          xy_ConsMassRef = xy_ConsMassRef + xyz_DelConsMassRef(:,:,k)
        end do

        do j = 1, jmax
          do i = 0, imax-1

            if ( xy_ConsMassRef(i,j) < 0.0_DP ) then
              if ( xy_ConsMassRef(i,j) < ThresholdForMessage ) then
                call MessageNotify( 'M', module_name,                  &
                  & 'xy_ConsMassRef(%f,%f) is less than %f. '          &
                  & // 'The value, %f, is reset to zero, n = %d.',     &
                  & d = (/ x_Lon(i)*180.0_DP/PI, y_Lat(j)*180.0_DP/PI, &
                  &        ThresholdForMessage,                        &
                  &        xy_ConsMassRef(i,j) /),                     &
                  & i = (/ n /) )
              end if
              xy_ConsMassRef(i,j) = 0.0_DP
!!$        call MessageNotify( 'E', module_name, 'ConsMassRef is negative, n = %d.', i = (/ n /) )
            end if
            if ( xy_ConsMass(i,j) /= 0.0_DP ) then
              do k = 1, kmax
                xyz_DelConsMass(i,j,k) = xy_ConsMassRef(i,j) / xy_ConsMass(i,j) * xyz_DelConsMass(i,j,k)
              end do
            else
              do k = 1, kmax
                xyz_DelConsMass(i,j,k) = 0.0_DP
              end do
            end if

          end do
        end do

        xyzf_QMix(:,:,:,n) = xyz_DelConsMass / xyz_DelMass

        ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
        ! Calculate specific humidity variance
        !
        if ( present( xyzf_DQMixDt ) ) then
          xyzf_DQMixDt(:,:,:,n) =     &
            &   xyzf_DQMixDt(:,:,:,n) &
            & + ( xyzf_QMix(:,:,:,n) - xyz_QMixBefCor ) / ( 2.0_DP * DelTime )
        end if

      else

        if ( present( xyzf_DQMixDt ) ) then
          xyz_QMixBefCor = xyzf_QMix(:,:,:,n)
        end if

        xyzf_QMix(:,:,:,n) = max( xyzf_QMix(:,:,:,n), 0.0_DP )

        ! æ¯”æ¹¿å¤‰åŒ–ã®ç®—å‡º
        ! Calculate specific humidity variance
        !
        if ( present( xyzf_DQMixDt ) ) then
          xyzf_DQMixDt(:,:,:,n) =     &
            &  ( xyzf_QMix(:,:,:,n) - xyz_QMixBefCor ) / ( 2.0_DP * DelTime )
        end if

      end if

    end do

    do n = 1, ncmax
      if ( CompositionInqFlagMassFix( n ) ) then
        do k = 1, kmax
          do j = 1, jmax
            do i = 0, imax-1
              if ( xyzf_QMix(i,j,k,n) < 0.0_DP ) then
                if ( xyzf_QMix(i,j,k,n) < ThresholdForMessage ) then
                  call MessageNotify( 'M', module_name, &
                    & 'Column: Negative at (%f,%f,%f,%d), Val = %f.', &
                    & d = (/ x_Lon(i)*180.0_DP/PI, y_Lat(j)*180.0_DP/PI, &
                    &        z_Sigma(k), xyzf_QMix(i,j,k,n) /), &
                    & i = (/ n /) )
                end if
              end if
            end do
          end do
        end do
      end if
    end do

    ! è¨ˆç®—æ™‚é–“è¨ˆæ¸¬ä¸€æ™‚åœæ¢
    ! Pause measurement of computation time
    !
    call TimesetClockStop( module_name )

  end subroutine MassFixerColumn

  !--------------------------------------------------------------------------------------

  subroutine MassFixerInit
    !
    ! mass_fixer ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®åˆæœŸåŒ–ã‚’è¡Œã„ã¾ã™.
    ! NAMELIST#mass_fixer_nml ã®èªã¿è¾¼ã¿ã¯ã“ã®æ‰‹ç¶šãã§è¡Œã‚ã‚Œã¾ã™.
    !
    ! "mass_fixer" module is initialized.
    ! "NAMELIST#mass_fixer_nml" is loaded in this procedure.
    !

    ! ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«å¼•ç”¨ ; USE statements
    !

    ! NAMELIST ãƒ•ã‚¡ã‚¤ãƒ«å…¥åŠ›ã«é–¢ã™ã‚‹ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£
    ! Utilities for NAMELIST file input
    !
    use namelist_util, only: namelist_filename, NmlutilMsg

    ! ãƒ•ã‚¡ã‚¤ãƒ«å…¥å‡ºåŠ›è£œåŠ©
    ! 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

    ! å®£è¨€æ–‡ ; 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 /mass_fixer_nml/ &
      & ThresholdForMessage
          !
          ! ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã«ã¤ã„ã¦ã¯åˆæœŸåŒ–æ‰‹ç¶š "mass_fixer#MassFixerInit"
          ! ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’å‚ç…§ã®ã“ã¨.
          !
          ! Refer to source codes in the initialization procedure
          ! "mass_fixer#MassFixerInit" for the default values.
          !

    ! å®Ÿè¡Œæ–‡ ; Executable statement
    !

    if ( mass_fixer_inited ) return

    ! ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã®è¨å®š
    ! Default values settings
    !
    ThresholdForMessage = 0.0_DP

    ! NAMELIST ã®èªã¿è¾¼ã¿
    ! NAMELIST is input
    !
    if ( trim(namelist_filename) /= '' ) then
      call FileOpen( unit_nml, &          ! (out)
        & namelist_filename, mode = 'r' ) ! (in)

      rewind( unit_nml )
      read( unit_nml, &           ! (in)
        & nml = mass_fixer_nml, &  ! (out)
        & iostat = iostat_nml )   ! (out)
      close( unit_nml )

      call NmlutilMsg( iostat_nml, module_name ) ! (in)
    end if

    ! å°å— ; Print
    !
    call MessageNotify( 'M', module_name, '----- Initialization Messages -----' )
    call MessageNotify( 'M', module_name, '  ThresholdForMessage = %f', d = (/ ThresholdForMessage /) )
    call MessageNotify( 'M', module_name, '-- version = %c', c1 = trim(version) )

    mass_fixer_inited = .true.

  end subroutine MassFixerInit

  !--------------------------------------------------------------------------------------

end module mass_fixer