! $Id$
!
! This module integrates drag forces between particles and gas.
!
! Reference:
! Yang, C.-C., & Johansen, A. 2016, ApJS, in press (arXiv:1603.08523)
!
!** AUTOMATIC CPARAM.INC GENERATION ****************************
!
! Declare (for generation of cparam.inc) the number of f array
! variables and auxiliary variables added by this module
!
! CPARAM logical, parameter :: lparticles_drag = .true.
!
!***************************************************************
module Particles_drag
!
use Cdata
use Cparam
use Messages
use Particles_cdata
use Particles_map
!
implicit none
!
include 'particles_drag.h'
!
! Initialization parameters
!
logical :: ldrag_equilibrium_global = .false. ! Set global/local drag equilibrium when lset_drag_equilibrium = .true.
logical :: ldrag_on_gas = .false. ! Turn on/off drag on gas
logical :: ldrag_on_par = .false. ! Turn on/off drag on particles
logical :: lset_drag_equilibrium = .false. ! Initialize the velocities of the particles and the gas under equilibrium
real :: gx_gas = 0.0 ! Background acceleration of gas in x direction
real :: gz_par_coeff = 0.0 ! Coefficient for background acceleration of a particle in z direction
real :: taus = 0.0 ! Dimensionless stopping time: Omega * tdrag
real :: tdrag = 0.0 ! Drag timescale
!
namelist /particles_drag_init_pars/ &
ldrag_equilibrium_global, ldrag_on_gas, ldrag_on_par, lset_drag_equilibrium, gx_gas, gz_par_coeff, taus, tdrag
!
! Runtime parameters
!
logical :: ldrag_pm_back_reaction = .true. ! Couple the gas by particle-meshing back reaction from particles
!
namelist /particles_drag_run_pars/ ldrag_on_gas, ldrag_on_par, ldrag_pm_back_reaction, gx_gas, gz_par_coeff, taus, tdrag
!
! Module variables
!
real :: dv_gas = 0.0
real :: epicycle_freq = 0.0
real :: epicycle_ratio = 0.0
real :: gzpc = 0.0
real :: oneplustaus2inv = 0.0
real :: taus2 = 0.0
real :: twominusqtaus = 0.0
real :: twotaus = 0.0
real :: twoomega1 = 0.0
!
contains
!***********************************************************************
subroutine register_particles_drag()
!
! Register this module.
!
! 14-dec-14/ccyang: coded.
!
if (lroot) call svn_id("$Id$")
!
endsubroutine register_particles_drag
!***********************************************************************
subroutine initialize_particles_drag()
!
! Perform any post-parameter-read initialization, i.e., calculate
! derived parameters.
!
! 11-dec-15/ccyang: coded.
!
! Sanity checks.
!
if (coord_system /= 'cartesian' .and. Omega /= 0.0) &
call fatal_error('initialize_particles_drag', 'non-inertial curvilinear system is not implemented. ')
if (ldrag_on_gas .and. iuu == 0) call fatal_error('initialize_particles_drag', 'drag on gas requires uu. ')
!
! Check the drag timescale.
!
drag: if (ldrag_on_par) then
settdrag: if (tdrag == 0.0) then
if (taus == 0.0) call fatal_error('initialize_particles_drag', 'tdrag = 0')
if (Omega == 0.0) call fatal_error('initialize_particles_drag', 'Omega = 0')
tdrag = taus / Omega
elseif (taus == 0.0) then settdrag
taus = Omega * tdrag
endif settdrag
endif drag
taus2 = 2.0 * (2.0 - qshear) * taus**2
twotaus = 2.0 * taus
twominusqtaus = (2.0 - qshear) * taus
oneplustaus2inv = 1.0 / (1.0 + taus2)
if (lroot) print *, 'initialize_particles_drag: tdrag = ', tdrag
!
! Find the frequency and aspect ratio of the epicycles.
!
epicycle_freq = sqrt(2.0 * (2.0 - qshear)) * Omega
epicycle_ratio = sqrt(2.0 / (2.0 - qshear))
!
! Get the velocity reduction of the gas.
!
dv: if (gx_gas /= 0.0) then
if (Omega == 0.0) call fatal_error('initialize_particles_drag', 'Omega = 0')
if (.not. ldrag_on_gas .and. .not. ldrag_on_par) call fatal_error('initialize_particles_drag', 'gx_gas has no effect. ')
twoomega1 = 0.5 / Omega
dv_gas = twoomega1 * gx_gas
endif dv
!
! Initialization for particle_zaccel().
!
gzpc = gz_par_coeff**2
!
! Calculate and overwrite mp_swarm and rhop_swarm.
!
mprhop: if (eps_dtog > 0.0) then
mp_swarm = find_mp_swarm(eps_dtog)
rhop_swarm = mp_swarm / product((/dx,dy,dz/), lactive_dimension)
info: if (lroot) then
print *, 'initialize_particles_drag: reset mp_swarm = ', mp_swarm
print *, 'initialize_particles_drag: reset rhop_swarm = ', rhop_swarm
endif info
endif mprhop
!
endsubroutine initialize_particles_drag
!***********************************************************************
subroutine init_particles_drag(f, fp)
!
! Set some initial conditions for the gas and the particles, if any.
!
! 08-may-16/ccyang: coded.
!
real, dimension(mx,my,mz,mfarray), intent(inout) :: f
real, dimension(mpar_loc,mparray), intent(inout) :: fp
!
type(pic), dimension(nx,ny,nz) :: cell
type(particle), dimension(:), pointer :: ghost
integer, dimension(:), pointer :: sendlist
integer, dimension(0:nproc_comm) :: ngp_send, ngp_recv
integer :: npsend
!
real :: ux, uy, vx, vy
!
! Initialize the gas and the particle velocities with drag equilibrium, if requested.
!
init: if (lset_drag_equilibrium) then
global: if (ldrag_equilibrium_global) then
if (lroot) print *, 'init_particles_drag: Set global drag equilibrium. '
call get_nsh_solution(dv_gas, eps_dtog, ux, uy, vx, vy)
f(l1:l2,m1:m2,n1:n2,iux) = f(l1:l2,m1:m2,n1:n2,iux) + ux
f(l1:l2,m1:m2,n1:n2,iuy) = f(l1:l2,m1:m2,n1:n2,iuy) + uy
fp(1:npar_loc,ivpx) = fp(1:npar_loc,ivpx) + vx
fp(1:npar_loc,ivpy) = fp(1:npar_loc,ivpy) + vy
else global
if (lroot) print *, 'init_particles_drag: Set local drag equilibrium. '
if (lparticles_blocks) call fatal_error('init_particles_drag', 'particles_blocks version is not implemented yet. ')
nullify(ghost)
call distribute_particles(f, fp, npsend, sendlist, ghost, cell, ngp_send, ngp_recv)
call set_drag_equilibrium(cell)
call collect_particles(f, fp, npsend, sendlist, ghost, cell, ngp_send, ngp_recv, &
ldrag_on_par, ldrag_on_gas .or. Omega /= 0.0, .false.)
endif global
endif init
!
endsubroutine init_particles_drag
!***********************************************************************
subroutine read_particles_drag_init_pars(iostat)
!
! Read initialization parameters from namelist particles_drag_init_pars.
!
! 27-aug-15/ccyang: coded.
!
use File_io, only: parallel_unit
!
integer, intent(out) :: iostat
!
read(parallel_unit, NML=particles_drag_init_pars, IOSTAT=iostat)
!
endsubroutine read_particles_drag_init_pars
!***********************************************************************
subroutine write_particles_drag_init_pars(unit)
!
! Write initialization parameters to namelist particles_drag_init_pars.
!
! 14-dec-15/ccyang: coded.
!
integer, intent(in) :: unit
!
integer :: stat
!
write(unit, NML=particles_drag_init_pars, IOSTAT=stat)
if (stat /= 0) call fatal_error('write_particles_drag_init_pars', 'cannot write particles_drag_init_pars. ', force=.true.)
!
endsubroutine write_particles_drag_init_pars
!***********************************************************************
subroutine read_particles_drag_run_pars(iostat)
!
! Read runtime parameters from namelist particles_drag_run_pars.
!
! 27-aug-15/ccyang: coded.
!
use File_io, only: parallel_unit
!
integer, intent(out) :: iostat
!
read(parallel_unit, NML=particles_drag_run_pars, IOSTAT=iostat)
!
endsubroutine read_particles_drag_run_pars
!***********************************************************************
subroutine write_particles_drag_run_pars(unit)
!
! Write runtime parameters to namelist particles_drag_run_pars.
!
! 14-dec-15/ccyang: coded.
!
integer, intent(in) :: unit
!
integer :: stat
!
write(unit, NML=particles_drag_run_pars, IOSTAT=stat)
if (stat /= 0) call fatal_error('write_particles_drag_run_pars', 'cannot write particles_drag_run_pars. ', force=.true.)
!
endsubroutine write_particles_drag_run_pars
!***********************************************************************
subroutine integrate_drag(f, fp, dt)
!
! Wrapper for the integration of the drag force between particles and
! gas.
!
! 08-may-16/ccyang: coded.
!
real, dimension(mx,my,mz,mfarray), intent(inout) :: f
real, dimension(mpar_loc,mparray), intent(inout) :: fp
real, intent(in) :: dt
!
type(pic), dimension(nx,ny,nz) :: cell
type(particle), dimension(:), pointer :: ghost
integer, dimension(:), pointer :: sendlist
integer, dimension(0:nproc_comm) :: ngp_send, ngp_recv
integer :: npsend
!
if (lparticles_blocks) call fatal_error('integrate_drag', 'particles_blocks version is not implemented yet. ')
!
! Distribute particles to the cells.
!
nullify(ghost)
call distribute_particles(f, fp, npsend, sendlist, ghost, cell, ngp_send, ngp_recv)
!
! Locally integrate the drag force as well as other source terms.
!
if (ldrag_on_par .and. ldrag_on_gas) then
call drag_on_both(cell, dt)
elseif (ldrag_on_par) then
call drag_on_particles(cell, dt)
elseif (ldrag_on_gas) then
call fatal_error('integrate_drag', 'drag on gas only is not implemented. ')
endif
!
! Assign the properties of the particles onto the grid.
!
call map_particles(f, cell)
!
! Collect the change in velocities.
!
call collect_particles(f, fp, npsend, sendlist, ghost, cell, ngp_send, ngp_recv, &
ldrag_on_par, ldrag_on_gas .or. Omega /= 0.0, ldrag_on_gas .and. ldrag_pm_back_reaction)
!
endsubroutine integrate_drag
!***********************************************************************
!***********************************************************************
! LOCAL SUBROUTINES START BELOW HERE.
!***********************************************************************
!***********************************************************************
elemental subroutine drag_on_particles(cell, dt)
!
! Finds the change in velocity for the particles under the drag.
!
! 11-dec-15/ccyang: coded.
!
type(pic), intent(inout) :: cell
real, intent(in) :: dt
!
! Find the velocity change.
!
rotation: if (Omega /= 0.0) then
if (cell%np > 0) call drag_particle_omega(cell%p%v(1), cell%p%v(2), cell%u(1), cell%u(2), dt, cell%p%dv(1), cell%p%dv(2))
call gas_epicycle(cell%u(1), cell%u(2), dt, cell%du(1), cell%du(2))
else rotation
call drag_particle(cell%p%v(1), cell%u(1), dt, cell%p%dv(1))
call drag_particle(cell%p%v(2), cell%u(2), dt, cell%p%dv(2))
endif rotation
!
if (gz_par_coeff /= 0.0) then
call drag_particle(cell%p%v(3), cell%u(3), dt, cell%p%dv(3), particle_zaccel(cell%p%x(3)))
else
call drag_particle(cell%p%v(3), cell%u(3), dt, cell%p%dv(3))
endif
!
endsubroutine drag_on_particles
!***********************************************************************
elemental subroutine drag_on_both(cell, dt)
!
! Finds the change in velocity for the gas and the particles under
! mutual drags as well as other source terms.
!
! 13-sep-15/ccyang: coded.
!
type(pic), intent(inout) :: cell
real, intent(in) :: dt
!
rotation: if (Omega /= 0.0) then
call drag_mutual_omega(cell%p%eps, cell%p%v(1), cell%p%v(2), cell%u(1), cell%u(2), dt, &
cell%p%dv(1), cell%p%dv(2), cell%du(1), cell%du(2))
else rotation
if (gx_gas /= 0.0) then
call drag_mutual(cell%p%eps, cell%p%v(1), cell%u(1), dt, cell%p%dv(1), cell%du(1), agas=gx_gas)
else
call drag_mutual(cell%p%eps, cell%p%v(1), cell%u(1), dt, cell%p%dv(1), cell%du(1))
endif
call drag_mutual(cell%p%eps, cell%p%v(2), cell%u(2), dt, cell%p%dv(2), cell%du(2))
endif rotation
!
if (gz_par_coeff /= 0.0) then
call drag_mutual(cell%p%eps, cell%p%v(3), cell%u(3), dt, cell%p%dv(3), cell%du(3), apar=particle_zaccel(cell%p%x(3)))
else
call drag_mutual(cell%p%eps, cell%p%v(3), cell%u(3), dt, cell%p%dv(3), cell%du(3))
endif
!
endsubroutine drag_on_both
!***********************************************************************
elemental subroutine drag_particle(v, u, dt, dv, ap)
!
! Calculates the velocity change of each particle under the gas drag.
!
! 18-jun-15/ccyang: coded.
!
! Input Arguments:
! v Initial particle velocity.
! u Gas velocity.
! dt Time step.
! Output Arguments:
! dv Change in particle velocity in time dt.
! Optional Argument:
! ap Background acceleration on the particle.
!
use Sub, only: one_minus_exp
!
real, intent(in) :: v, u, dt
real, intent(out) :: dv
real, intent(in), optional :: ap
!
real :: t
!
t = dt / tdrag
getdv: if (present(ap)) then
if (t * t > epsilon(1.0)) then
dv = (u - v + ap * tdrag) * (1.0 - exp(-t))
else
dv = ((u - v) / tdrag + ap) * (1.0 - 0.5 * t) * dt
endif
else getdv
dv = (u - v) * one_minus_exp(t)
endif getdv
!
endsubroutine drag_particle
!***********************************************************************
pure subroutine drag_particle_omega(vx, vy, ux, uy, dt, dvx, dvy)
!
! Calculates the velocity change of each particle under the gas drag
! and rotation.
!
! 05-may-18/ccyang: coded.
!
! Input Arguments:
! vx x-component of the initial velocities of the particles.
! vy y-component of the initial velocities of the particles.
! ux x-component of the gas velocity.
! uy y-component of the gas velocity.
! dt Time step.
! Output Arguments:
! dvx Changes in x-component of particle velocities in time dt.
! dvy Changes in y-component of particle velocities in time dt.
!
real, dimension(:), intent(in) :: vx, vy
real, intent(in) :: ux, uy, dt
real, dimension(:), intent(out) :: dvx, dvy
!
real :: cosot, sinot1, sinot2
real :: x, y, vxe, vye, vx0, vy0
!
! Find the epicycle.
!
x = epicycle_freq * dt
cosot = cos(x)
y = sin(x)
sinot1 = epicycle_ratio * y
sinot2 = y / epicycle_ratio
!
! Find the decay factor.
!
y = exp(-dt / tdrag)
x = 1.0 - y
!
! Find the terminal velocity.
!
vye = -oneplustaus2inv * dv_gas
vxe = twotaus * vye
!
vx0 = vxe + (x * ux - y * vxe) * cosot + (x * (uy + dv_gas) - y * vye) * sinot1
vy0 = vye + (x * (uy + dv_gas) - y * vye) * cosot - (x * ux - y * vxe) * sinot2
!
! Find the velocity changes of the particles.
!
x = 1.0 - y * cosot
sinot1 = y * sinot1
sinot2 = y * sinot2
!
dvx = vx0 - (x * vx - vy * sinot1)
dvy = vy0 - (x * vy + vx * sinot2)
!
endsubroutine drag_particle_omega
!***********************************************************************
pure subroutine drag_mutual(eps, v, u, dt, dv, du, apar, agas)
!
! Calculates the velocity change of the gas and the particles under
! mutual drag interaction.
!
! 13-sep-15/ccyang: coded.
!
! Input Arguments:
! eps Particle-to-gas density ratio of each particle.
! v Initial particle velocity.
! u Initial gas velocity.
! dt Time step.
! Output Arguments:
! dv Change in particle velocity in time dt.
! du Change in gas velocity in time dt, if
! ldrag_pm_back_reaction = .false.; (1 + sum(eps)) times the
! change in center-of-mass velocity, otherwise.
! Optional Arguments:
! apar External acceleration of each of the particles.
! agas External acceleartion of the gas.
!
use Sub, only: one_minus_exp
!
real, dimension(:), intent(in) :: eps
real, dimension(size(eps)), intent(in) :: v
real, intent(in) :: u, dt
real, dimension(size(eps)), intent(out) :: dv
real, intent(out) :: du
real, dimension(size(eps)), intent(in), optional :: apar
real, intent(in), optional :: agas
!
real :: epstot, norm, ucm, du0, acm, dag
real :: t, x, y, z
!
! Find weights.
!
epstot = sum(eps)
norm = 1.0 / (1.0 + epstot)
!
! Find exponential decays.
!
t = dt / tdrag
x = one_minus_exp(t)
if (.not. ldrag_pm_back_reaction) y = one_minus_exp((1.0 + epstot) * t)
z = exp(-t) * one_minus_exp(epstot * t) / epstot
!
! Find center-of-mass velocity.
!
ucm = norm * (u + sum(eps * v))
du0 = ucm - u
!
! Find the velocity changes due to mutual drag.
!
dv = (ucm - v) * x - du0 * z
if (ldrag_pm_back_reaction) then
if (.not. present(apar) .and. .not. present(agas)) du = 0.0
else
du = du0 * y
endif
!
! Add the velocity changes due to external accelerations.
!
accel: if (present(apar) .or. present(agas)) then
! Find center-of-mass acceleration.
if (present(apar)) then
acm = sum(eps * apar)
else
acm = 0.0
endif
if (present(agas)) acm = acm + agas
if (ldrag_pm_back_reaction) du = acm * dt
acm = norm * tdrag * acm
! Find the velocity changes.
if (present(apar)) dv = dv + (apar * tdrag - acm) * x
if (present(agas)) then
dag = norm * (agas * tdrag - acm)
else
dag = -norm * acm
endif
du0 = acm * t
dv = dv + (du0 + dag * (x - z))
if (.not. ldrag_pm_back_reaction) du = du + (du0 + dag * y)
endif accel
!
endsubroutine drag_mutual
!***********************************************************************
pure subroutine drag_mutual_omega(eps, vx, vy, ux, uy, dt, dvx, dvy, dux, duy, agx)
!
! Calculates the change in the horizontal components of velocity for
! the gas and the particles under mutual drag interaction, shear,
! Coriolis force, and background gas pressure gradient.
!
! 12-jun-15/ccyang: coded
!
! Input Arguments:
! eps Particle-to-gas density ratio of each particle.
! vx x-component of the initial velocity of each particle.
! vy y-component of the initial velocity of each particle.
! ux x-component of the initial gas velocity.
! uy y-component of the initial gas velocity.
! dt Time step.
! Output Arguments:
! dvx Change in x-component of particle velocity in time dt.
! dvy Change in y-component of particle velocity in time dt.
! dux Change in x-component of gas velocity in time dt, if
! ldrag_pm_back_reaction = .false.; (1 + sum(eps)) times the
! change in center-of-mass velocity, otherwise.
! duy Change in y-component of gas velocity in time dt, if
! ldrag_pm_back_reaction = .false.; (1 + sum(eps)) times the
! change in center-of-mass velocity, otherwise.
! Optional Argument:
! agx x-component of the acceleartion of the gas.
!
use Sub, only: one_minus_exp
!
real, dimension(:), intent(in) :: eps
real, dimension(size(eps)), intent(in) :: vx, vy
real, intent(in) :: ux, uy, dt
real, dimension(size(eps)), intent(out) :: dvx, dvy
real, intent(out) :: dux, duy
real, intent(in), optional :: agx
!
real, dimension(size(eps)) :: vx0, vy0
real :: epstot, dvg
real :: ux0, uy0, uxe, uye, vxe, vye, vxcm, vycm
real :: cosot, sinot1, sinot2
real :: ot, t, ts, a0, a1, a2, a3, a4
!
! Get the total solid-to-gas ratio.
!
epstot = sum(eps)
!
! Get the velocity reduction of the gas.
!
if (present(agx)) then
dvg = twoomega1 * (gx_gas + agx)
else
dvg = dv_gas
endif
!
! Get the deviation from the NSH solution.
!
call get_nsh_solution(dvg, epstot, uxe, uye, vxe, vye)
ux0 = ux - uxe
uy0 = uy - uye
vx0 = vx - vxe
vy0 = vy - vye
!
! Find the center-of-mass velocity of the particles.
!
vcm: if (epstot > 0.0) then
vxcm = sum(eps * vx0) / epstot
vycm = sum(eps * vy0) / epstot
else vcm
vxcm = 0.0
vycm = 0.0
endif vcm
!
! Get the epicycle motions.
!
ot = epicycle_freq * dt
cosot = cos(ot)
a0 = sin(ot)
sinot1 = a0 * epicycle_ratio
sinot2 = a0 / epicycle_ratio
!
uxe = ux0 * cosot + uy0 * sinot1
uye = uy0 * cosot - ux0 * sinot2
!
vxe = vxcm * cosot + vycm * sinot1
vye = vycm * cosot - vxcm * sinot2
!
! Find the velocity change for the particles.
!
t = dt / tdrag
a0 = exp(-t)
a3 = 1.0 + epstot
ts = a3 * t
a4 = exp(-ts)
if (abs(ts**4) > epsilon(1.0)) then
a1 = (epstot + a4) / a3 - a0
else
a1 = 0.5 * epstot * t**2 * (1.0 - (t + ts) / 3.0)
endif
a2 = one_minus_exp(ts) / a3
!
dvx = a1 * vxe + a2 * uxe + (a0 * (vx0 * cosot + vy0 * sinot1) - vx0)
dvy = a1 * vye + a2 * uye + (a0 * (vy0 * cosot - vx0 * sinot2) - vy0)
!
! Find the velocity change for the gas.
!
gas: if (ldrag_pm_back_reaction) then
uxe = ux0 + epstot * vxcm
uye = uy0 + epstot * vycm
a0 = ot * ot
if (abs(a0) > epsilon(1.0)) then
a0 = 1.0 - cosot
else
a0 = 0.5 * a0 * (1.0 - a0 / 12.0)
endif
dux = -a0 * uxe + sinot1 * uye
duy = -a0 * uye - sinot2 * uxe
else gas
if (abs(ts * ts) > epsilon(1.0)) then
a1 = (1.0 + epstot * a4) / a3
else
a1 = 1.0 - epstot * t
endif
a2 = epstot * a2
dux = a1 * uxe + a2 * vxe - ux0
duy = a1 * uye + a2 * vye - uy0
endif gas
!
endsubroutine drag_mutual_omega
!***********************************************************************
pure subroutine gas_epicycle(ux, uy, dt, dux, duy)
!
! Find the change in gas velocity due to rotation.
!
! 14-dec-15/ccyang: coded
!
! Input Arguments
! ux x-component of the initial velocity of the gas.
! uy y-component of the initial velocity of the gas.
! dt Time step.
! Output Arguments
! dux Change in x-component of the gas velocity in time dt.
! duy Change in y-component of the gas velocity in time dt.
!
real, intent(in) :: ux, uy, dt
real, intent(out) :: dux, duy
!
real :: x, y, z
!
! Find the epicycle.
!
z = epicycle_freq * dt
epicycle: if (z**4 > epsilon(1.0)) then
x = 1.0 - cos(z)
y = sin(z)
else epicycle
y = z**2
x = 0.5 * y * (1.0 - y / 12.0)
y = z * (1.0 - y / 6.0)
endif epicycle
!
! Find the velocity change of the gas.
!
z = uy + dv_gas
dux = -x * ux + y * epicycle_ratio * z
duy = -x * z - y / epicycle_ratio * ux
!
endsubroutine gas_epicycle
!***********************************************************************
elemental subroutine get_nsh_solution(dv_gas, eps, ux, uy, vx, vy)
!
! Finds the Nakagawa-Sekiya-Hayashi (1986) solution.
!
! 17-may-15/ccyang: coded.
!
! Input Arguments
! dv_gas Velocity reduction of the gas due to radial pressure
! gradient.
! eps Solid-to-gas mass ratio.
!
! Output Arguments
! ux x-component of the velocity of the gas.
! uy y-component of the velocity of the gas.
! vx x-component of the velocity of the solids.
! vy y-component of the velocity of the solids.
!
real, intent(in) :: dv_gas, eps
real, intent(out) :: ux, uy, vx, vy
!
real :: a, b
!
a = 1.0 + eps
b = dv_gas / (a**2 + taus2)
vx = -twotaus * b
vy = -a * b
ux = -eps * vx
uy = -(a + taus2) * b
!
endsubroutine get_nsh_solution
!***********************************************************************
elemental subroutine set_drag_equilibrium(cell)
!
! Set the state of drag equilibrium to du and dv.
!
! 11-dec-15/ccyang: coded.
!
type(pic), intent(inout) :: cell
!
real, dimension(3) :: u, v
integer :: i
real :: eps
!
! Find the equilibrium according to the drag type.
!
u = 0.0
v = 0.0
eq: if (ldrag_on_par) then
if (ldrag_on_gas) then
eps = sum(cell%p%eps)
else
eps = 0.0
endif
call get_nsh_solution(dv_gas, eps, u(1), u(2), v(1), v(2))
v = v + cell%u
endif eq
!
! Assign the solution to the velocity change.
!
cell%du = u
forall(i = 1:3) cell%p%dv(i) = v(i)
!
endsubroutine set_drag_equilibrium
!***********************************************************************
!***********************************************************************
! LOCAL FUNCTIONS START BELOW HERE.
!***********************************************************************
!***********************************************************************
function find_mp_swarm(eps_dtog) result(mp_swarm)
!
! Finds the mass mp_swarm of each super-particle given the global dust-
! to-gas density ratio eps_dtog.
!
! 13-sep-15/ccyang: coded.
!
use EquationOfState, only: gamma, rho0, cs0
!
real :: mp_swarm
real, intent(in) :: eps_dtog
!
real :: mass
!
! Find the total gas mass.
!
gasmass: if (gz_par_coeff > 0.0) then
! For stratified gas
if (gamma /= 1.0) call fatal_error('find_mp_swarm', 'polytropic gas is not considered. ')
mass = sqrt(twopi) * (cs0 / Omega) * product(lxyz(1:2), lactive_dimension(1:2))
else gasmass
! For uniform gas
mass = product(lxyz, lactive_dimension)
endif gasmass
mass = rho0 * mass
!
! Uniformly distribute the mass to the particles.
!
mp_swarm = eps_dtog * mass / real(npar)
!
endfunction find_mp_swarm
!***********************************************************************
elemental real function particle_zaccel(zp) result(gz)
!
! Returns the z-acceleration of a particle.
!
! 22-jun-15/ccyang: coded.
!
! Currently, only supports -gz_par_coeff^2 * zp.
!
! Input Argument:
! zp Vertical position of the particle.
!
real, intent(in) :: zp
!
gz = -gzpc * zp
!
endfunction particle_zaccel
!***********************************************************************
endmodule Particles_drag