! $Id$
!
! MODULE_DOC: Calculates pressure gradient term for
! MODULE_DOC: polytropic equation of state $p=\text{const}\rho^{\Gamma}$.
!
!** 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 :: lentropy = .false.
! CPARAM logical, parameter :: ltemperature = .false.
! CPARAM logical, parameter :: lthermal_energy = .false.
!
! MVAR CONTRIBUTION 0
! MAUX CONTRIBUTION 0
!
! PENCILS PROVIDED Ma2; fpres(3); tcond; sglnTT(3)
! PENCILS PROVIDED uglnTT
!
!***************************************************************
module Energy
!
use Cparam
use Cdata
use General, only: keep_compiler_quiet
use Messages
!
implicit none
!
include 'energy.h'
!
logical, pointer :: lpressuregradient_gas
logical :: lviscosity_heat=.false.
logical, pointer :: lffree, lrelativistic_eos, lconservative
real, pointer :: profx_ffree(:),profy_ffree(:),profz_ffree(:)
!
integer :: idiag_dtc=0 ! DIAG_DOC: $\delta t/[c_{\delta t}\,\delta_x
! DIAG_DOC: /\max c_{\rm s}]$
! DIAG_DOC: \quad(time step relative to
! DIAG_DOC: acoustic time step;
! DIAG_DOC: see \S~\ref{time-step})
integer :: idiag_ugradpm=0
integer :: idiag_thermalpressure=0
integer :: idiag_ethm=0 ! DIAG_DOC: $\left<\varrho e\right>$
! DIAG_DOC: \quad(mean thermal
! DIAG_DOC: [=internal] energy)
integer :: idiag_pdivum=0 ! DIAG_DOC: $\left
$
integer :: idiag_ufpresm=0
integer :: idiag_csm=0 ! DIAG_DOC: $\left$
integer :: pushpars2c, pushdiags2c ! should be procedure pointer (F2003)
!
contains
!***********************************************************************
subroutine register_energy
!
! No energy equation is being solved; use polytropic equation of state.
!
! 28-mar-02/axel: dummy routine, adapted from entropy.f of 6-nov-01.
!
use SharedVariables, only: get_shared_variable
!
! Logical variable lpressuregradient_gas shared with hydro modules.
!
call get_shared_variable('lpressuregradient_gas', &
lpressuregradient_gas, caller='register_energy')
!
! Check if we are solving the relativistic eos equations.
! In that case we'd need to get lrelativistic_eos from density.
!
if (ldensity) &
call get_shared_variable('lrelativistic_eos', lrelativistic_eos)
!
! Check if we are solving for relativistic bulk motions, not just EoS.
!
if (lhydro) then
call get_shared_variable('lconservative', lconservative)
else
allocate(lconservative)
lconservative=.false.
endif
!
! Identify version number.
!
if (lroot) call svn_id( &
"$Id$")
!
endsubroutine register_energy
!***********************************************************************
subroutine initialize_energy(f)
!
! Perform any post-parameter-read initialization i.e. calculate derived
! parameters.
!
! 24-nov-02/tony: coded
!
use Density, only: beta_glnrho_global, beta_glnrho_scaled
use EquationOfState, only: cs0, select_eos_variable,gamma_m1
use Mpicomm, only: stop_it
use SharedVariables, only: put_shared_variable,get_shared_variable
!
real, dimension (mx,my,mz,mfarray) :: f
!
integer :: ierr
!
! Tell the equation of state that we're here and what f variable we use.
!
if (llocal_iso) then
if (lroot) call warning('initialize_energy',&
'llocal_iso=T. Make sure you have the appropriate ' // &
'INITIAL_CONDITION in Makefile.local.')
call select_eos_variable('cs2',-2) !special local isothermal
else
if (gamma_m1 == 0.) then
call select_eos_variable('cs2',-1) !isothermal
else
call select_eos_variable('ss',-1) !isentropic => polytropic
endif
endif
!
! For global density gradient beta=H/r*dlnrho/dlnr, calculate actual
! gradient dlnrho/dr = beta/H.
!
if (any(beta_glnrho_global /= 0.)) then
beta_glnrho_scaled=beta_glnrho_global*Omega/cs0
if (lroot) print*, 'initialize_energy: Global density gradient '// &
'with beta_glnrho_global=', beta_glnrho_global
endif
!
call put_shared_variable('lviscosity_heat',lviscosity_heat,ierr)
if (ierr/=0) call stop_it("initialize_energy: "//&
"there was a problem when putting lviscosity_heat")
!
! Check that cs0 is set correctly when lrelativistic_eos=.true.
!
if (ldensity.and.lrelativistic_eos) then
if (abs(cs0**2-onethird)>0.01) then
if (lroot) write(*,*) &
'WARNING: consider putting cs0=1/sqrt(3) for relativistic EoS'
endif
endif
!
! check if we are solving the force-free equations in parts of domain
! AB: I suspect the following lines won't work here and need
! AB: do be moved directly to register.
!
if (ldensity) then
call get_shared_variable('lffree',lffree,ierr)
if (ierr/=0) call fatal_error('initialize_energy:',&
'failed to get lffree from density')
if (lffree) then
call get_shared_variable('profx_ffree',profx_ffree,caller='initialize_energy')
call get_shared_variable('profy_ffree',profy_ffree,caller='initialize_energy')
call get_shared_variable('profz_ffree',profz_ffree,caller='initialize_energy')
endif
endif
!
TT_spec=.false.; ss_spec=.false.
call keep_compiler_quiet(f)
!
endsubroutine initialize_energy
!***********************************************************************
subroutine update_char_vel_energy(f)
!
! Updates characteristic velocity for slope-limited diffusion.
!
! 25-sep-15/MR+joern: coded
!
use EquationOfState, only: cs20
!
real, dimension(mx,my,mz,mfarray), intent(INOUT) :: f
!
if (lslope_limit_diff) f(2:mx-2,2:my-2,2:mz-2,iFF_char_c) &
=max(f(2:mx-2,2:my-2,2:mz-2,iFF_char_c), w_sldchar_ene*sqrt(cs20))
!
endsubroutine update_char_vel_energy
!***********************************************************************
subroutine init_energy(f)
!
! Initialise energy; called from start.f90.
!
real, dimension (mx,my,mz,mfarray) :: f
!
call keep_compiler_quiet(f)
!
endsubroutine init_energy
!***********************************************************************
subroutine pencil_criteria_energy
!
! All pencils that the Energy module depends on are specified here.
!
! 20-11-04/anders: coded
!
use Density, only: beta_glnrho_scaled
!
if (lhydro.and.lpressuregradient_gas.and..not.lconservative) lpenc_requested(i_fpres)=.true.
if (leos.and.ldensity.and.lhydro.and.ldt) lpenc_requested(i_cs2)=.true.
if (any(beta_glnrho_scaled /= 0.)) lpenc_requested(i_cs2)=.true.
!
if (idiag_ugradpm/=0) then
lpenc_diagnos(i_rho)=.true.
lpenc_diagnos(i_uglnrho)=.true.
endif
!
if (idiag_thermalpressure/=0) then
lpenc_diagnos(i_rho)=.true.
lpenc_diagnos(i_cs2)=.true.
lpenc_diagnos(i_rcyl_mn)=.true.
endif
!
if (idiag_ethm/=0) then
lpenc_diagnos(i_rho)=.true.
lpenc_diagnos(i_ee)=.true.
endif
!
if (idiag_pdivum/=0) then
lpenc_diagnos(i_pp)=.true.
lpenc_diagnos(i_divu)=.true.
endif
!
if (idiag_csm/=0) lpenc_diagnos(i_cs2)=.true.
!
endsubroutine pencil_criteria_energy
!***********************************************************************
subroutine pencil_interdep_energy(lpencil_in)
!
! Interdependency among pencils from the Energy module is specified here.
!
! 20-nov-04/anders: coded
!
use EquationOfState, only: gamma_m1
!
logical, dimension (npencils) :: lpencil_in
!
if (lpencil_in(i_Ma2)) then
lpencil_in(i_u2)=.true.
lpencil_in(i_cs2)=.true.
endif
if (lpencil_in(i_fpres)) then
lpencil_in(i_cs2)=.true.
if (lstratz) then
lpencil_in(i_glnrhos)=.true.
else
if (.not.lconservative) then
lpencil_in(i_glnrho)=.true.
endif
endif
if (llocal_iso) lpencil_in(i_glnTT)=.true.
endif
if (lpencil_in(i_TT1) .and. gamma_m1/=0.) lpencil_in(i_cs2)=.true.
if (lpencil_in(i_cs2) .and. gamma_m1/=0.) lpencil_in(i_lnrho)=.true.
!
endsubroutine pencil_interdep_energy
!***********************************************************************
subroutine calc_pencils_energy(f,p)
!
! Calculate Energy pencils.
! Most basic pencils should come first, as others may depend on them.
!
! 20-nov-04/anders: coded
!
real, dimension (mx,my,mz,mfarray) :: f
type (pencil_case) :: p
!
integer :: j
!
intent(in) :: f
intent(inout) :: p
! Ma2
if (lpencil(i_Ma2)) p%Ma2=p%u2/p%cs2
!
! fpres (=pressure gradient force)
!
fpres: if (lpencil(i_fpres)) then
strat: if (lstratz) then
p%fpres = -spread(p%cs2,2,3) * p%glnrhos
else strat
do j=1,3
if (llocal_iso) then
p%fpres(:,j)=-p%cs2*(p%glnrho(:,j)+p%glnTT(:,j))
else
!
! The relativistic EoS works ok even if cs2 is not 1/3, but
! it may still be a good idea to put cs0=1/sqrt(3)=0.57735
!
if (ldensity.and.lrelativistic_eos) then
if (.not.lconservative) then
p%fpres(:,j)=-.75*p%cs2*p%glnrho(:,j)
endif
else
p%fpres(:,j)=-p%cs2*p%glnrho(:,j)
endif
endif
!
! multiply previous p%fpres pencil with profiles
!
if (ldensity) then
if (lffree) p%fpres(:,j)=p%fpres(:,j) &
*profx_ffree*profy_ffree(m)*profz_ffree(n)
endif
enddo
endif strat
endif fpres
!
! tcond (dummy)
!
if (lpencil(i_tcond)) p%tcond=0.
! sglnTT (dummy)
if (lpencil(i_sglnTT)) p%sglnTT=0.
!
call keep_compiler_quiet(f)
!
endsubroutine calc_pencils_energy
!***********************************************************************
subroutine energy_before_boundary(f)
!
! 03-apr-20/joern: restructured and fixed slope-limited diffusion
!
use EquationOfState, only: cs0
!
real, dimension (mx,my,mz,mfarray), intent(INOUT) :: f
!
! Slope limited diffusion: update characteristic speed
! Not staggered yet
!
if (lslope_limit_diff .and. llast .and. ldensity) then
! if (lslope_limit_diff) then
do m=1,my
do n=1,mz
f(:,m,n,isld_char)=f(:,m,n,isld_char)+w_sldchar_ene*cs0
enddo
enddo
endif
!
endsubroutine energy_before_boundary
!***********************************************************************
subroutine energy_after_boundary(f)
!
! Dummy routine.
!
real, dimension (mx,my,mz,mfarray), intent(IN) :: f
!
call keep_compiler_quiet(f)
endsubroutine energy_after_boundary
!***********************************************************************
subroutine denergy_dt(f,df,p)
!
! Calculate pressure gradient term for isothermal/polytropic equation
! of state.
!
use Density, only: beta_glnrho_global, beta_glnrho_scaled
!
real, dimension (mx,my,mz,mfarray) :: f
real, dimension (mx,my,mz,mvar) :: df
type (pencil_case) :: p
!
integer :: j
!
intent(in) :: f,p
intent(inout) :: df
!
! ``cs2/dx^2'' for timestep - but only if we are evolving hydrodynamics.
!
if (.not.ldt) advec_cs2=0.0
if (leos.and.ldensity.and.lhydro) then
if (lfirst.and.ldt) advec_cs2=p%cs2*dxyz_2
if (headtt.or.ldebug) &
print*, 'denergy_dt: max(advec_cs2) =', maxval(advec_cs2)
endif
!
! Add isothermal/polytropic pressure term in momentum equation.
!
if (lhydro.and.lpressuregradient_gas.and..not.lconservative) then
df(l1:l2,m,n,iux:iuz)=df(l1:l2,m,n,iux:iuz)+p%fpres
!
! Add pressure force from global density gradient.
!
if (any(beta_glnrho_global /= 0.)) then
if (headtt) print*, 'denergy_dt: adding global pressure gradient force'
do j=1,3
df(l1:l2,m,n,(iux-1)+j) = df(l1:l2,m,n,(iux-1)+j) &
- p%cs2*beta_glnrho_scaled(j)
enddo
endif
endif
call calc_diagnostics_energy(f,p)
!
call keep_compiler_quiet(f)
!
endsubroutine denergy_dt
!***********************************************************************
subroutine calc_diagnostics_energy(f,p)
use Diagnostics
real, dimension (mx,my,mz,mfarray) :: f
type(pencil_case) :: p
real, dimension(nx) :: ufpres
integer :: i
!
call keep_compiler_quiet(f)
!
! Calculate energy related diagnostics.
!
if (ldiagnos) then
if (idiag_dtc/=0) &
call max_mn_name(sqrt(advec_cs2)/cdt,idiag_dtc,l_dt=.true.)
if (idiag_ugradpm/=0) &
call sum_mn_name(p%rho*p%cs2*p%uglnrho,idiag_ugradpm)
if (idiag_thermalpressure/=0) &
call sum_lim_mn_name(p%rho*p%cs2,idiag_thermalpressure,p)
if (idiag_ethm/=0) call sum_mn_name(p%rho*p%ee,idiag_ethm)
if (idiag_pdivum/=0) call sum_mn_name(p%pp*p%divu,idiag_pdivum)
if (idiag_csm/=0) call sum_mn_name(p%cs2,idiag_csm,lsqrt=.true.)
if (idiag_ufpresm/=0) then
ufpres=0
do i = 1, 3
ufpres=ufpres+p%uu(:,i)*p%fpres(:,i)
enddo
call sum_mn_name(p%rho*ufpres,idiag_ufpresm)
endif
endif
endsubroutine calc_diagnostics_energy
!***********************************************************************
subroutine get_slices_energy(f,slices)
!
real, dimension (mx,my,mz,mfarray) :: f
type (slice_data) :: slices
!
call keep_compiler_quiet(f)
call keep_compiler_quiet(slices%ready)
!
endsubroutine get_slices_energy
!***********************************************************************
subroutine fill_farray_pressure(f)
!
! 18-feb-10/anders: dummy
!
real, dimension (mx,my,mz,mfarray) :: f
!
call keep_compiler_quiet(f)
!
endsubroutine fill_farray_pressure
!***********************************************************************
subroutine impose_energy_floor(f)
!
! Dummy subroutine
!
real, dimension(mx,my,mz,mfarray) :: f
!
call keep_compiler_quiet(f)
!
endsubroutine impose_energy_floor
!***********************************************************************
subroutine dynamical_thermal_diffusion(uc)
!
! Dummy subroutine
!
real, intent(in) :: uc
!
call keep_compiler_quiet(uc)
!
endsubroutine dynamical_thermal_diffusion
!***********************************************************************
subroutine read_energy_init_pars(iostat)
!
integer, intent(out) :: iostat
!
iostat = 0
!
endsubroutine read_energy_init_pars
!***********************************************************************
subroutine write_energy_init_pars(unit)
!
integer, intent(in) :: unit
!
call keep_compiler_quiet(unit)
!
endsubroutine write_energy_init_pars
!***********************************************************************
subroutine read_energy_run_pars(iostat)
!
integer, intent(out) :: iostat
!
iostat = 0
!
endsubroutine read_energy_run_pars
!***********************************************************************
subroutine write_energy_run_pars(unit)
!
integer, intent(in) :: unit
!
call keep_compiler_quiet(unit)
!
endsubroutine write_energy_run_pars
!***********************************************************************
subroutine rprint_energy(lreset,lwrite)
!
! Reads and registers print parameters relevant to energy.
!
use Diagnostics, only: parse_name
!
integer :: iname
logical :: lreset
logical, optional :: lwrite
!
! Reset everything in case of reset
! (this needs to be consistent with what is defined above!)
!
if (lreset) then
idiag_dtc=0; idiag_ugradpm=0; idiag_thermalpressure=0; idiag_ethm=0;
idiag_pdivum=0; idiag_ufpresm=0; idiag_csm=0
endif
!
do iname=1,nname
call parse_name(iname,cname(iname),cform(iname),'dtc',idiag_dtc)
call parse_name(iname,cname(iname),cform(iname),'ugradpm',idiag_ugradpm)
call parse_name(iname,cname(iname),cform(iname),'TTp',idiag_thermalpressure)
call parse_name(iname,cname(iname),cform(iname),'ethm',idiag_ethm)
call parse_name(iname,cname(iname),cform(iname),'pdivum',idiag_pdivum)
call parse_name(iname,cname(iname),cform(iname),'ufpresm',idiag_ufpresm)
call parse_name(iname,cname(iname),cform(iname),'csm',idiag_csm)
enddo
call keep_compiler_quiet(present(lwrite))
!
endsubroutine rprint_energy
!***********************************************************************
subroutine energy_after_timestep(f,df,dtsub)
!
real, dimension(mx,my,mz,mfarray) :: f
real, dimension(mx,my,mz,mvar) :: df
real :: dtsub
!
call keep_compiler_quiet(f,df)
call keep_compiler_quiet(dtsub)
!
endsubroutine energy_after_timestep
!***********************************************************************
subroutine split_update_energy(f)
!
! Dummy subroutine
!
real, dimension(mx,my,mz,mfarray), intent(inout) :: f
!
call keep_compiler_quiet(f)
!
endsubroutine split_update_energy
!***********************************************************************
subroutine expand_shands_energy
!
! Dummy
!
endsubroutine expand_shands_energy
!***********************************************************************
endmodule Energy