kochergin1987_entrainment.F90 Source File


This file depends on

sourcefile~~kochergin1987_entrainment.f90~~EfferentGraph sourcefile~kochergin1987_entrainment.f90 kochergin1987_entrainment.F90 sourcefile~entrainment.f90 entrainment.F90 sourcefile~kochergin1987_entrainment.f90->sourcefile~entrainment.f90

Contents


Source Code

!
!  kochergin1987_entrainment.f90
!  This file is part of ISOFT.
!  
!  Copyright 2018 Chris MacMackin <cmacmackin@physics.ox.ac.uk>
!  
!  This program is free software; you can redistribute it and/or modify
!  it under the terms of the GNU General Public License as published by
!  the Free Software Foundation; either version 2 of the License, or
!  (at your option) any later version.
!  
!  This program is distributed in the hope that it will be useful,
!  but WITHOUT ANY WARRANTY; without even the implied warranty of
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!  GNU General Public License for more details.
!  
!  You should have received a copy of the GNU General Public License
!  along with this program; if not, write to the Free Software
!  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
!  MA 02110-1301, USA.
!  

#ifdef DEBUG
#define pure 
#define elemental 
#endif

module kochergin1987_entrainment_mod
  !* Author: Christopher MacMackin
  !  Date: October 2016
  !  License: GPLv3
  !
  ! Provides a concrete implementation of [[abstract_entrainment]]
  ! in the form of the parameterisation described by Kochergin (1987).
  !
  use iso_fortran_env, only: r8 => real64
  use factual_mod!, only: scalar_field, vector_field, abs
  use entrainment_mod, only: abstract_entrainment
  implicit none
  private

  type, extends(abstract_entrainment), public :: kochergin1987_entrainment
    !* Author: Christopher MacMackin
    !  Date: Feburary 2018
    !
    ! A parameterisation of entrainment (\(e\)) as described by
    ! Kochergin (1987): $$e =
    ! \frac{c_L^2}{S_m}\sqrt{|\vec{U}|^2+\frac{g'D}{S_m}}.$$ Here,
    ! \(c_L\) is an entrainment coefficient, \(\vec{U}\) is the
    ! velocity of the plume, \(g'\) is the reduced gravity, and
    ! \(S_m\) is the turbulent Schmidt number. The latter-most can be
    ! expressed as $$ S_m = \frac{Ri}{0.0725(Ri + 0.186 -
    ! \sqrt{Ri^2 - 0.316Ri + 0.0346})} $$, where \(Ri =
    ! g'D/|\vec{U}|^2\) is the Richardson number.
    !
    private
    real(r8) :: coefficient = 1.0_r8
      !! The entrainment coefficient \(c_L^2x_0/D_0\)
    real(r8) :: delta = 0.036_r8
      !! The ratio \(D_0/h_0\)
  contains
    procedure :: entrainment_rate => kochergin1987_rate
      !! Returns the entrainment rate for ambient water into the plume.
  end type kochergin1987_entrainment

  interface kochergin1987_entrainment
    module procedure constructor
  end interface kochergin1987_entrainment

contains

  pure function constructor(coefficient, delta) result(this)
    real(r8), intent(in) :: coefficient
      !! The entrainment coefficient \(c_L^2x_0/D_0\)
    real(r8), intent(in) :: delta
      !! The ratio \(D_0/h_0\)
    type(kochergin1987_entrainment) :: this
      !! A new entrainment object
    this%coefficient = coefficient
    this%delta = delta
  end function constructor

  function kochergin1987_rate(this, velocity, thickness, depth, density_diff, time) &
                                                result(entrainment)
    !* Author: Christopher MacMackin
    !  Date: Feburary 2018
    !
    ! $$e = \frac{c_L^2}{S_m}\sqrt{|\vec{U}|^2+\frac{g'D}{S_m}}.$$
    ! Here, \(c_L\) is an entrainment coefficient, \(\vec{U}\) is the
    ! velocity of the plume, \(g'\) is the reduced gravity, and
    ! \(S_m\) is the turbulent Schmidt number. The Schmidt number is a
    ! function of the Richardson number \(Ri = g'D/|\vec{U}|^2\):
    ! $$ S_m = \frac{Ri}{0.0725(Ri + 0.186 -
    ! \sqrt{Ri^2 - 0.316Ri + 0.0346})}. $$
    !
    class(kochergin1987_entrainment), intent(in) :: this
    class(vector_field), intent(in)            :: velocity
      !! The velocity field of the plume into which fluid is being 
      !! entrained.
    class(scalar_field), intent(in)            :: thickness
      !! The thickness of the plume into which fluid is being
      !! entrained
    class(scalar_field), intent(in)            :: depth
      !! The depth of the upper surface of the plume into which
      !! fluid is being entrained
    class(scalar_field), intent(in)            :: density_diff
      !! The difference between the ambient density and the density of
      !! the plume into which the ambient fluid is being entrained.
    real(r8), intent(in), optional             :: time
      !! The time at which the entrainment is being calculated. If not
      !! present then assumed to be same as previous value passed.
    class(scalar_field), pointer               :: entrainment
      !! The value of the entrainment
    class(scalar_field), pointer               :: Ri, Sm
    call velocity%guard_temp(); call thickness%guard_temp() 
    call depth%guard_temp(); call density_diff%guard_temp()
    call depth%allocate_scalar_field(entrainment)
    call entrainment%unset_temp()
    call depth%allocate_scalar_field(Ri)
    call depth%allocate_scalar_field(Sm)
    call Ri%guard_temp(); call Sm%guard_temp()
    entrainment = velocity%norm() ! Have to awkwardly split this operation to prevent ICE
    Ri = this%delta*density_diff*thickness/(entrainment**2)
    Sm = Ri/(0.0725_r8*(Ri + 0.186_r8 - sqrt(Ri**2 - 0.316_r8*Ri + 0.0346_r8)))
    entrainment = this%coefficient*entrainment/Sm * sqrt(1._r8 + Ri/Sm)
    call velocity%clean_temp(); call thickness%clean_temp()
    call depth%clean_temp(); call density_diff%clean_temp()
    call Ri%clean_temp(); call Sm%clean_temp()
    call entrainment%set_temp()
  end function kochergin1987_rate

end module kochergin1987_entrainment_mod