! $Id$ ! ! This module can replace the energy module by using lnT or T (with ! ltemperature_nolog=.true.) as dependent variable. ! !** 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 = .true. ! CPARAM logical, parameter :: lthermal_energy = .false. ! ! MVAR CONTRIBUTION 1 ! MAUX CONTRIBUTION 0 ! ! PENCILS PROVIDED Ma2; uglnTT; ugTT; cvspec(nchemspec); fpres(3); tcond; sglnTT(3) ! !*************************************************************** module Energy ! use Cparam use Cdata use General, only: keep_compiler_quiet use Messages ! implicit none ! include 'energy.h' ! real :: radius_lnTT=0.1,ampl_lnTT=0.,widthlnTT=2*epsi real :: lnTT_left=1.0,lnTT_right=1.0,lnTT_const=0.0,TT_const=1.0 real :: kx_lnTT=1.0,ky_lnTT=1.0,kz_lnTT=1.0 real :: chi=0.0,heat_uniform=0.0,chi_hyper3=0.0 real :: chi_shock=0.0 real :: zbot=0.0,ztop=0.0 real :: tau_heat_cor=-1.0,tau_damp_cor=-1.0,zcor=0.0,TT_cor=0.0 real :: zheat_uniform_range=0. real :: heat_source_offset=0., heat_source_sigma=1.0, heat_source=0.0 real :: pthresh=0., pbackground=0., pthreshnorm real, pointer :: reduce_cs2 logical, pointer :: lreduced_sound_speed, lscale_to_cs2top logical, pointer :: lpressuregradient_gas logical :: lheat_source logical :: ladvection_temperature=.true. logical :: lviscosity_heat=.true. logical :: lupw_lnTT=.false.,lcalc_heat_cool=.false.,lcalc_TTmean=.false. logical :: lheatc_chiconst=.false.,lheatc_chiconst_accurate=.false. logical :: lheatc_hyper3=.false. logical :: lheatc_shock=.false. integer, parameter :: nheatc_max=3 logical :: lenergy_slope_limited=.false. character (len=labellen), dimension(ninit) :: initlnTT='nothing' character (len=labellen), dimension(nheatc_max) :: iheatcond='nothing' character (len=intlen) :: iinit_str ! namelist /entropy_init_pars/ & initlnTT,radius_lnTT,ampl_lnTT,widthlnTT, & lnTT_left,lnTT_right,lnTT_const,TT_const, & kx_lnTT,ky_lnTT,kz_lnTT,ltemperature_nolog ! namelist /entropy_run_pars/ & lupw_lnTT, ladvection_temperature, lviscosity_heat, & heat_uniform,chi,tau_heat_cor,tau_damp_cor,zcor,TT_cor, & lheatc_chiconst_accurate,lheatc_hyper3,chi_hyper3, & iheatcond, zheat_uniform_range, heat_source_offset, & heat_source_sigma, heat_source, lheat_source, & pthresh, pbackground,chi_shock ! integer :: idiag_TTmax=0 ! DIAG_DOC: $\max (T)$ integer :: idiag_TTmin=0 ! DIAG_DOC: $\min (T)$ integer :: idiag_TTm=0 ! DIAG_DOC: $\left< T \right>$ integer :: idiag_yHmax=0 ! DIAG_DOC: integer :: idiag_yHmin=0 ! DIAG_DOC: integer :: idiag_yHm=0 ! DIAG_DOC: integer :: idiag_ethm=0 ! DIAG_DOC: $\left< e_{\text{th}}\right> = ! DIAG_DOC: \left< c_v \rho T \right> $ ! DIAG_DOC: \quad(mean thermal energy) integer :: idiag_ssm=0 ! DIAG_DOC: integer :: idiag_cv=0 integer :: idiag_cp=0 integer :: idiag_dtchi=0 integer :: idiag_dtc=0 ! DIAG_DOC: integer :: idiag_eem=0 ! DIAG_DOC: $\left< e \right> $ ! DIAG_DOC: \quad(mean internal energy) integer :: idiag_ppm=0 ! DIAG_DOC: $\left< p \right> $ integer :: idiag_Tppm=0 ! DIAG_DOC: $\left<\max(p_{\rm thresh}-p,0)_{\rm norm}\right> $ integer :: idiag_csm=0 integer :: idiag_mum=0 ! DIAG_DOC: integer :: idiag_ppmax=0 ! DIAG_DOC: integer :: idiag_ppmin=0 ! DIAG_DOC: ! ! xy averaged diagnostics given in xyaver.in written every it1d timestep ! integer :: idiag_puzmz=0 ! XYAVG_DOC: $\left

_{xy}$ integer :: idiag_pr1mz=0 ! XYAVG_DOC: $\left

_{xy}$ integer :: idiag_eruzmz=0 ! XYAVG_DOC: $\left_{xy}$ integer :: idiag_ffakez=0 ! XYAVG_DOC: $\left<\varrho u_z c_p T \right>_{xy}$ integer :: idiag_mumz=0 ! XYAVG_DOC: $\left<\mu\right>_{xy}$ integer :: idiag_TTmz=0 ! XYAVG_DOC: $\left< T \right>_{xy}$ integer :: idiag_ssmz=0 ! XYAVG_DOC: $\left< s \right>_{xy}$ integer :: idiag_eemz=0 ! XYAVG_DOC: $\left< e \right>_{xy}$ integer :: idiag_ppmz=0 ! XYAVG_DOC: $\left< p \right>_{xy}$ ! ! Auxiliaries ! real, dimension (nx) :: diffus_chi,diffus_chi3 ! contains !*********************************************************************** subroutine register_energy ! ! initialise variables which should know that we solve an energy ! equation: ilnTT, etc; increase nvar accordingly ! ! 6-nov-01/wolf: coded ! use FArrayManager use SharedVariables, only: get_shared_variable ! integer :: ierr ! if (ltemperature_nolog) then call farray_register_pde('TT',iTT) ilnTT=iTT else call farray_register_pde('lnTT',ilnTT) endif ! call get_shared_variable('lpressuregradient_gas',lpressuregradient_gas,ierr) if (ierr/=0) call fatal_error('register_energy','lpressuregradient_gas') ! ! Identify version number. ! if (lroot) call svn_id( & "$Id$") ! ! Writing files for use with IDL ! if (lroot) then if (maux == 0) then if (nvar < mvar) write(4,*) ',lnTT $' if (nvar == mvar) write(4,*) ',lnTT' else write(4,*) ',lnTT $' endif write(15,*) 'lnTT = fltarr(mx,my,mz)*one' endif ! endsubroutine register_energy !*********************************************************************** subroutine initialize_energy(f) ! ! called by run.f90 after reading parameters, but before the time loop ! ! 21-jul-2002/wolf: coded ! use Mpicomm, only: stop_it use SharedVariables, only: put_shared_variable, get_shared_variable use EquationOfState, only : select_eos_variable ! real, dimension (mx,my,mz,mfarray) :: f integer :: ierr,i ! ! Set iTT requal to ilnTT if we are considering non-logarithmic temperature. ! ! if (ltemperature_nolog) iTT=ilnTT ! if (ltemperature_nolog) then call select_eos_variable('TT',iTT) else call select_eos_variable('lnTT',ilnTT) endif ! ! Check any module dependencies ! if (.not.leos_temperature_ionization) then if (.not.leos_chemistry) then call fatal_error('initialize_energy','EOS/=noeos but'//& 'temperature_ionization already include'//& 'an EQUATION OF STATE for the fluid') endif endif ! ! Check whether we want heating/cooling ! lcalc_heat_cool = (heat_uniform/=0.0.or.tau_heat_cor>0.or.lheat_source) ! ! Define bottom and top z positions ! (TH: This should really be global variables IMHO) ! zbot = xyz0(3) ztop = xyz0(3) + Lxyz(3) ! ! Check whether we want heat conduction ! lheatc_chiconst = (chi > tiny(chi)) lheatc_hyper3 = (chi_hyper3 > tiny(chi_hyper3)) ! ! put lviscosity_heat as shared variable for viscosity module ! 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") if (lsolid_cells) then call put_shared_variable('ladvection_temperature',ladvection_temperature) call put_shared_variable('lheatc_chiconst',lheatc_chiconst) call put_shared_variable('lupw_lnTT',lupw_lnTT) endif ! do i=1,nheatc_max select case (iheatcond(i)) case ('chi-const') lheatc_chiconst=.true. if (lroot) call information('initialize_energy', & ' heat conduction: constant chi') case ('chi-hyper3') lheatc_hyper3=.true. if (lroot) call information('initialize_energy','hyper conductivity') case ('chi-shock') lheatc_shock=.true. if (lroot) call information('initialize_energy','shock conductivity') case ('nothing') if (lroot) print*,'heat conduction: nothing' case default if (lroot) then write(unit=errormsg,fmt=*) & 'No such value iheatcond = ', trim(iheatcond(i)) call fatal_error('initialize_energy',errormsg) endif endselect enddo ! if (lheatc_chiconst .and. chi==0.0) then call warning('initialize_energy','chi is zero!') endif if (lheatc_hyper3 .and. chi_hyper3==0.0) then call warning('initialize_energy', & 'Conductivity coefficient chi_hyper3 is zero!') endif if (lheatc_shock .and. chi_shock==0.0) then call warning('initialize_energy','chi_shock is zero!') endif ! ! Check if reduced sound speed is used ! if (ldensity) then call get_shared_variable('lreduced_sound_speed',& lreduced_sound_speed,ierr) if (ierr/=0) call fatal_error('initialize_energy:',& 'failed to get lreduced_sound_speed from density') if (lreduced_sound_speed) then call get_shared_variable('reduce_cs2',reduce_cs2,ierr) if (ierr/=0) call fatal_error('initialize_energy:',& 'failed to get reduce_cs2 from density') call get_shared_variable('lscale_to_cs2top',lscale_to_cs2top,ierr) if (ierr/=0) call fatal_error('initialize_energy:',& 'failed to get lscale_to_cs2top from density') endif endif ! if (llocal_iso) & call fatal_error('initialize_energy', & 'llocal_iso switches on the local isothermal approximation. ' // & 'Use ENERGY=energy in src/Makefile.local') ! ! For diagnostics of pressure shock propagation ! Tppm = max(pthresh-p,0)/(pthresh-pbackground) ! pthreshnorm=pthresh-pbackground if (pthreshnorm==0.) then pthreshnorm=1. else pthreshnorm=1./pthreshnorm endif ! call keep_compiler_quiet(f) ! endsubroutine initialize_energy !*********************************************************************** subroutine read_energy_init_pars(iostat) ! use File_io, only: parallel_unit ! integer, intent(out) :: iostat ! read(parallel_unit, NML=entropy_init_pars, IOSTAT=iostat) ! endsubroutine read_energy_init_pars !*********************************************************************** subroutine write_energy_init_pars(unit) ! integer, intent(in) :: unit ! write(unit, NML=entropy_init_pars) ! endsubroutine write_energy_init_pars !*********************************************************************** subroutine read_energy_run_pars(iostat) ! use File_io, only: parallel_unit ! integer, intent(out) :: iostat ! read(parallel_unit, NML=entropy_run_pars, IOSTAT=iostat) ! endsubroutine read_energy_run_pars !*********************************************************************** subroutine write_energy_run_pars(unit) ! integer, intent(in) :: unit ! write(unit, NML=entropy_run_pars) ! endsubroutine write_energy_run_pars !*********************************************************************** subroutine init_energy(f) ! ! initialise energy; called from start.f90 ! 07-nov-2001/wolf: coded ! 24-nov-2002/tony: renamed for consistancy (i.e. init_[variable name]) ! use General, only: itoa use Sub, only: blob use Initcond, only: jump, gaunoise use InitialCondition, only: initial_condition_ss ! real, dimension (mx,my,mz,mfarray), intent (inout) :: f ! integer :: j logical :: lnothing=.true. ! do j=1,ninit ! if (initlnTT(j)/='nothing') then ! lnothing=.false. ! iinit_str=itoa(j) ! ! select different initial conditions ! select case (initlnTT(j)) ! case ('zero', '0'); f(:,:,:,ilnTT) = 0. case ('const_lnTT'); f(:,:,:,ilnTT)=f(:,:,:,ilnTT)+lnTT_const case ('const_TT'); f(:,:,:,ilnTT)=f(:,:,:,ilnTT)+log(TT_const) case ('blob'); call blob(ampl_lnTT,f,ilnTT,radius_lnTT,0.,0.,0.) case ('xwave') do n=n1,n2; do m=m1,m2 f(l1:l2,m,n,ilnTT)=f(l1:l2,m,n,ilnTT)+ampl_lnTT*sin(kx_lnTT*x(l1:l2)) enddo; enddo case ('ywave') do n=n1,n2; do m=m1,m2 f(l1:l2,m,n,ilnTT)=f(l1:l2,m,n,ilnTT)+ampl_lnTT*sin(ky_lnTT*y(m)) enddo; enddo case ('zwave') do n=n1,n2; do m=m1,m2 f(l1:l2,m,n,ilnTT)=f(l1:l2,m,n,ilnTT)+ampl_lnTT*sin(kz_lnTT*z(n)) enddo; enddo case ('xjump'); call jump(f,ilnTT,lnTT_left,lnTT_right,widthlnTT,'x') case ('yjump'); call jump(f,ilnTT,lnTT_left,lnTT_right,widthlnTT,'y') case ('zjump'); call jump(f,ilnTT,lnTT_left,lnTT_right,widthlnTT,'z') case ('gaussian-noise'); call gaunoise(ampl_lnTT,f,ilnTT) ! case default ! ! Catch unknown values ! write(unit=errormsg,fmt=*) 'No such value for initss(' & //trim(iinit_str)//'): ',trim(initlnTT(j)) call fatal_error('init_energy',errormsg) ! endselect ! if (lroot) print*,'init_energy: initss(' & //trim(iinit_str)//') = ',trim(initlnTT(j)) ! endif ! enddo ! ! Interface for user's own initial condition ! if (linitial_condition) call initial_condition_ss(f) ! ! If unlogarithmic temperature considered, take exp of lnTT resulting from ! initlnTT ! if (ltemperature_nolog) f(:,:,:,iTT)=exp(f(:,:,:,ilnTT)) ! if (lnothing.and.lroot) print*,'init_energy: nothing' ! endsubroutine init_energy !*********************************************************************** subroutine pencil_criteria_energy ! ! All pencils that the Energy module depends on are specified here. ! ! 20-11-04/anders: coded ! if (ldt) lpenc_requested(i_cs2)=.true. ! if (ldensity) then if (.not. lchemistry) then lpenc_requested(i_gamma_m1)=.true. lpenc_requested(i_delta)=.true. endif lpenc_requested(i_divu)=.true. endif ! if (linterstellar) then lpenc_requested(i_lnTT)=.true. lpenc_requested(i_TT1)=.true. lpenc_requested(i_ee)=.true. endif ! if (lpressuregradient_gas) then lpenc_requested(i_rho1gpp)=.true. endif ! if (lviscosity) then lpenc_requested(i_cv1)=.true. lpenc_requested(i_TT1)=.true. if (lviscosity_heat) lpenc_requested(i_visc_heat)=.true. endif ! if (lcalc_heat_cool) then lpenc_requested(i_rho1)=.true. lpenc_requested(i_cv1)=.true. lpenc_requested(i_TT1)=.true. if (tau_heat_cor>0) lpenc_requested(i_TT)=.true. endif ! if (ladvection_temperature) then if (ltemperature_nolog) then lpenc_requested(i_ugTT)=.true. else lpenc_requested(i_uglnTT)=.true. endif endif ! if (lheatc_chiconst) then lpenc_requested(i_del2lnTT)=.true. if (lheatc_chiconst_accurate) then lpenc_requested(i_cp1)=.true. lpenc_requested(i_gradcp)=.true. lpenc_requested(i_gamma)=.true. endif endif ! if (lheatc_hyper3) lpenc_requested(i_del6lnTT)=.true. ! if (lheatc_shock) then lpenc_requested(i_glnrho)=.true. lpenc_requested(i_del2lnTT)=.true. lpenc_requested(i_gshock)=.true. lpenc_requested(i_shock)=.true. lpenc_requested(i_glnTT)=.true. lpenc_requested(i_del2lnrho)=.true. lpenc_requested(i_gamma)=.true. endif ! if (ltemperature_nolog) lpenc_requested(i_TT)=.true. ! if (lparticles_temperature) lpenc_requested(i_tcond)=.true. ! ! if (lchemistry) then ! lpenc_requested(i_lnTT)=.true. ! lpenc_requested(i_TT)=.true. ! lpenc_requested(i_TT1)=.true. ! lpenc_requested(i_glnTT)=.true. ! lpenc_requested(i_del2lnTT)=.true. ! endif ! ! Diagnostics ! if (idiag_puzmz/=0) then lpenc_diagnos(i_uu)=.true. lpenc_diagnos(i_pp)=.true. endif ! if (idiag_pr1mz/=0) then lpenc_diagnos(i_pp)=.true. lpenc_diagnos(i_rho1)=.true. endif ! if (idiag_eruzmz/=0) then lpenc_diagnos(i_ee)=.true. lpenc_diagnos(i_rho)=.true. lpenc_diagnos(i_uu)=.true. endif ! if (idiag_ffakez/=0) then lpenc_diagnos(i_rho)=.true. lpenc_diagnos(i_uu)=.true. lpenc_diagnos(i_cp)=.true. lpenc_diagnos(i_TT)=.true. endif ! if (idiag_TTmax/=0) lpenc_diagnos(i_TT)=.true. if (idiag_TTmin/=0) lpenc_diagnos(i_TT)=.true. if (idiag_TTmz/=0) lpenc_diagnos(i_TT)=.true. if (idiag_ssmz/=0) lpenc_diagnos(i_ss)=.true. if (idiag_eemz/=0) lpenc_diagnos(i_ee)=.true. if (idiag_ppmz/=0) lpenc_diagnos(i_pp)=.true. if (idiag_TTm/=0) lpenc_diagnos(i_TT)=.true. if (idiag_yHmax/=0) lpenc_diagnos(i_yH)=.true. if (idiag_yHmin/=0) lpenc_diagnos(i_yH)=.true. if (idiag_yHm/=0) lpenc_diagnos(i_yH)=.true. if (idiag_ethm/=0) then lpenc_diagnos(i_rho1)=.true. lpenc_diagnos(i_ee)=.true. endif if (idiag_ssm/=0) lpenc_diagnos(i_ss)=.true. if (idiag_cv/=0) lpenc_diagnos(i_cv)=.true. if (idiag_cp/=0) lpenc_diagnos(i_cp)=.true. if (idiag_dtchi/=0) then lpenc_diagnos(i_rho1)=.true. lpenc_diagnos(i_cv1)=.true. endif if (idiag_dtchi/=0) lpenc_diagnos(i_cs2)=.true. if (idiag_csm/=0) lpenc_diagnos(i_cs2)=.true. if (idiag_eem/=0) lpenc_diagnos(i_ee)=.true. if (idiag_ppm/=0) lpenc_diagnos(i_pp)=.true. if (idiag_Tppm/=0) lpenc_diagnos(i_pp)=.true. if (idiag_ppmax/=0) lpenc_diagnos(i_pp)=.true. if (idiag_ppmin/=0) lpenc_diagnos(i_pp)=.true. if (idiag_mum/=0 .or. idiag_mumz/=0) lpenc_diagnos(i_mu1)=.true. ! endsubroutine pencil_criteria_energy !*********************************************************************** subroutine pencil_interdep_energy(lpencil_in) ! ! Interdependency among pencils from the Energy module is specified here. ! ! 20-11-04/anders: coded ! 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_uglnTT)) then lpencil_in(i_glnTT)=.true. endif if (lpencil_in(i_ugTT)) then lpencil_in(i_gTT)=.true. endif ! 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-11-04/anders: coded ! 16-05-12/MR: dead branch for calculation of pressure force added ! use Sub, only: u_dot_grad ! real, dimension (mx,my,mz,mfarray), intent (in) :: f type (pencil_case), intent (inout) :: p ! ! Mach Speed ! if (lpencil(i_Ma2)) p%Ma2=p%u2/p%cs2 ! ! Temperature advection ! (Needs to be here because of lupw_lnTT) ! if (lpencil(i_uglnTT)) then call u_dot_grad(f,ilnTT,p%glnTT,p%uu,p%uglnTT,UPWIND=lupw_lnTT) endif ! if (lpencil(i_ugTT)) then call u_dot_grad(f,iTT,p%gTT,p%uu,p%ugTT,UPWIND=lupw_lnTT) endif ! tcond if (lpencil(i_tcond)) then if (lchemistry) then p%tcond=p%lambda else if (lheatc_chiconst) then p%tcond=chi*p%rho/p%cp1 else call fatal_error('calc_pencils_energy', & 'This heatcond is not implemented to work with lpencil(i_cond)!') endif endif endif ! if (lpencil(i_fpres)) & call fatal_error('calc_pencils_energy', & 'calculation of pressure force not yet implemented'//& ' for temperature_ionization') ! sglnTT if (lpencil(i_sglnTT)) & call fatal_error('calc_pencils_energy', & 'Pencil sglnTT not yet implemented for temperature_ionization') ! endsubroutine calc_pencils_energy !*********************************************************************** subroutine denergy_dt(f,df,p) ! ! calculate right hand side of energy equation ! heat condution is currently disabled until old stuff, ! which in now in calc_heatcond, has been reinstalled. ! ! 17-sep-01/axel: coded ! 9-jun-02/axel: pressure gradient added to du/dt already here ! 2-feb-03/axel: added possibility of ionization ! 29-jul-14/axel: imported reduced sound speed from entropy module ! use Special, only: special_calc_energy use Sub, only: cubic_step,identify_bcs use Viscosity, only: calc_viscous_heat use Interstellar, only: calc_heat_cool_interstellar ! real, dimension (mx,my,mz,mfarray), intent (inout) :: f real, dimension (mx,my,mz,mvar), intent (out) :: df type (pencil_case) :: p ! real, dimension (nx,3) :: damp real, dimension (nx) :: Hmax real :: prof ! ! Initialize maximum heating to zero ! Hmax = 0.0 ! ! Identify module and boundary conditions ! if (headtt.or.ldebug) print*,'denergy_dt: SOLVE denergy_dt' if (headtt) call identify_bcs('lnTT',ilnTT) ! ! Calculate cs2 in a separate routine ! if (headtt) print*,'denergy_dt: cs2 =', p%cs2(1) ! ! ``cs2/dx^2'' for timestep ! if (ldensity.and.lhydro.and.lfirst.and.ldt) then if (lreduced_sound_speed) then if (lscale_to_cs2top) then call fatal_error('denergy_dt','lscale_to_cs2top not possible') !AB: because cs2top is undefined in this module !-- advec_cs2=reduce_cs2*cs2top*dxyz_2 else advec_cs2=reduce_cs2*p%cs2*dxyz_2 endif else advec_cs2=p%cs2*dxyz_2 endif endif ! if (headtt.or.ldebug) & print*, 'denergy_dt: max(advec_cs2) =', maxval(advec_cs2) ! ! Pressure term in momentum equation (setting lpressuregradient_gas to ! .false. allows suppressing pressure term for test purposes) ! if (lpressuregradient_gas) then df(l1:l2,m,n,iux:iuz) = df(l1:l2,m,n,iux:iuz) - p%rho1gpp endif ! ! velocity damping in the coronal heating zone ! if (lhydro.and.tau_damp_cor>0) then prof = cubic_step(z(n),(ztop+zcor)/2,(ztop-zcor)/2) damp = prof*f(l1:l2,m,n,iux:iuz)/tau_damp_cor df(l1:l2,m,n,iux:iuz) = df(l1:l2,m,n,iux:iuz) - damp endif ! ! Advection term ! if (ladvection_temperature) then if (ltemperature_nolog) then df(l1:l2,m,n,iTT) = df(l1:l2,m,n,iTT) - p%ugTT else df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) - p%uglnTT endif endif ! ! Calculate viscous contribution to temperature ! if (lviscosity .and. lviscosity_heat) call calc_viscous_heat(df,p,Hmax) ! ! Various heating/cooling mechanisms ! if (lcalc_heat_cool) call calc_heat_cool(df,p) ! ! Thermal conduction ! diffus_chi=0.; diffus_chi3=0. if (lheatc_chiconst) call calc_heatcond_constchi(df,p) if (lheatc_hyper3) call calc_heatcond_hyper3(df,p) if (lheatc_shock) call calc_heatcond_shock(df,p) ! ! Natalia: thermal conduction for the chemistry case: lheatc_chemistry=true ! ! if (lheatc_chemistry) call calc_heatcond_chemistry(f,df,p) ! ! Interstellar radiative cooling and UV heating ! if (linterstellar) call calc_heat_cool_interstellar(f,df,p,Hmax) ! ! Need to add left-hand-side of the continuity equation (see manual) ! if (ldensity) then if (.not. lchemistry) then df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) - p%gamma_m1*p%divu/p%delta else ! df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) - p%gamma_m1*p%divu ! sum_DYDt=0. ! do k=1,nchemspec ! sum_DYDt=sum_DYDt+p%cvspec(:,k)*(p%DYDt_reac(:,k)+p%DYDt_diff(:,k)) ! enddo ! df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT)- & ! f(l1:l2,m,n,ilnTT)*p%cv1(:)*sum_DYDt(:) endif endif ! if (lspecial) call special_calc_energy(f,df,p) ! if (lfirst.and.ldt) then maxdiffus=max(maxdiffus,diffus_chi) maxdiffus3=max(maxdiffus3,diffus_chi3) endif call calc_diagnostics_energy(f,p) ! endsubroutine denergy_dt !*********************************************************************** subroutine calc_diagnostics_energy(f,p) use Diagnostics, only: max_mn_name,sum_mn_name,xysum_mn_name_z real, dimension (mx,my,mz,mfarray) :: f type(pencil_case) :: p ! ! Calculate temperature related diagnostics ! call keep_compiler_quiet(f) if (ldiagnos) then call max_mn_name(p%TT,idiag_TTmax) if (idiag_TTmin/=0) call max_mn_name(-p%TT,idiag_TTmin,lneg=.true.) call sum_mn_name(p%TT,idiag_TTm) call max_mn_name(p%yH,idiag_yHmax) if (idiag_yHmin/=0) call max_mn_name(-p%yH,idiag_yHmin,lneg=.true.) call sum_mn_name(p%yH,idiag_yHm) if (idiag_ethm/=0) call sum_mn_name(p%ee/p%rho1,idiag_ethm) call sum_mn_name(p%ss,idiag_ssm) call sum_mn_name(p%cv,idiag_cv) call sum_mn_name(p%cp,idiag_cp) if (idiag_dtc/=0) & call max_mn_name(sqrt(advec_cs2)/cdt,idiag_dtc,l_dt=.true.) call sum_mn_name(p%ee,idiag_eem) call sum_mn_name(p%pp,idiag_ppm) if (idiag_Tppm/=0) call sum_mn_name(max(pthresh-p%pp,0.)*pthreshnorm,idiag_Tppm) call max_mn_name(p%pp,idiag_ppmax) if (idiag_ppmin/=0) call max_mn_name(-p%pp,idiag_ppmin,lneg=.true.) call sum_mn_name(p%cs2,idiag_csm,lsqrt=.true.) if (idiag_mum/=0) call sum_mn_name(1/p%mu1,idiag_mum) endif ! ! 1-D averages. ! if (l1davgfirst) then call xysum_mn_name_z(p%rho*p%uu(:,3)*p%cp*p%TT,idiag_ffakez) call xysum_mn_name_z(p%ee*p%rho*p%uu(:,3),idiag_eruzmz) call xysum_mn_name_z(p%pp*p%uu(:,3),idiag_puzmz) call xysum_mn_name_z(p%pp*p%rho1,idiag_pr1mz) call xysum_mn_name_z(1/p%mu1,idiag_mumz) call xysum_mn_name_z(p%TT,idiag_TTmz) call xysum_mn_name_z(p%ss,idiag_ssmz) call xysum_mn_name_z(p%ee,idiag_eemz) call xysum_mn_name_z(p%pp,idiag_ppmz) endif endsubroutine calc_diagnostics_energy !*********************************************************************** subroutine energy_before_boundary(f) ! ! Actions to take before boundary conditions are set. ! ! 1-apr-20/joern: coded ! use EquationOfState, only : gamma_m1, get_cp1 ! real, dimension (mx,my,mz,mfarray), intent(inout) :: f real, dimension (mx) :: cs2 real :: cp1 ! ! Slope limited diffusion: update characteristic speed ! Not staggered yet ! if (lslope_limit_diff .and. llast) then call get_cp1(cp1) cs2=0. do m=1,my do n=1,mz if (ltemperature_nolog) then cs2 = gamma_m1/cp1*f(:,m,n,iTT) else cs2 = gamma_m1/cp1*exp(f(:,m,n,ilnTT)) endif f(:,m,n,isld_char)=f(:,m,n,isld_char)+w_sldchar_ene*sqrt(cs2) enddo enddo endif ! endsubroutine energy_before_boundary !*********************************************************************** subroutine energy_after_boundary(f) ! ! dummy routine ! real, dimension (mx,my,mz,mfarray), intent(inout) :: f ! call keep_compiler_quiet(f) ! endsubroutine energy_after_boundary !*********************************************************************** subroutine calc_heatcond_constchi(df,p) ! ! calculate chi*grad(rho*T*glnTT)/(rho*TT) ! =chi*(g2.glnTT+g2lnTT), ! where g2=glnrho+glnTT ! use Diagnostics, only: max_mn_name use Sub, only: dot,multsv ! real, dimension (mx,my,mz,mvar) :: df type (pencil_case) :: p ! real, dimension (nx) :: g2,gamma real, dimension (nx,3) :: gradlncp ! ! g2 ! if (lheatc_chiconst_accurate) then call multsv(p%cp1,p%gradcp,gradlncp) call dot(p%glnTT+p%glnrho+gradlncp,p%glnTT,g2) gamma = p%gamma else call dot(p%glnTT+p%glnrho,p%glnTT,g2) gamma = 5.0/3.0 endif ! ! Add heat conduction to RHS of temperature equation ! df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) + gamma*chi*(g2 + p%del2lnTT) ! ! check maximum diffusion from thermal diffusion ! if (lfirst.and.ldt) then diffus_chi=diffus_chi+gamma*chi*dxyz_2 if (ldiagnos.and.idiag_dtchi/=0) then call max_mn_name(diffus_chi/cdtv,idiag_dtchi,l_dt=.true.) endif endif ! endsubroutine calc_heatcond_constchi !*********************************************************************** subroutine calc_heatcond_hyper3(df,p) ! use Diagnostics, only: max_mn_name ! real, dimension (mx,my,mz,mvar) :: df type (pencil_case) :: p ! ! Add heat conduction to RHS of temperature equation ! df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) + chi_hyper3*p%del6lnTT ! ! check maximum diffusion from thermal diffusion ! if (lfirst.and.ldt) then diffus_chi=diffus_chi+chi_hyper3*dxyz_6 if (ldiagnos.and.idiag_dtchi/=0) then call max_mn_name(diffus_chi/cdtv,idiag_dtchi,l_dt=.true.) endif endif ! endsubroutine calc_heatcond_hyper3 !*********************************************************************** subroutine calc_heatcond_shock(df,p) ! ! Adds in shock entropy diffusion. There is potential for ! recycling some quantities from previous calculations. ! Ds/Dt = ... + 1/(rho*T) grad(flux), where ! flux = chi_shock*rho*T*grads ! (in comments we say chi_shock, but in the code this is "chi_shock*shock") ! This routine should be ok with ionization. ! ! 20-jul-03/axel: adapted from calc_heatcond_constchi ! 07-jun-19/joern: copied from entropy.f90 ! use Diagnostics, only: max_mn_name use EquationOfState, only: gamma use Sub, only: dot ! real, dimension (mx,my,mz,mvar) :: df type (pencil_case) :: p real, dimension (nx) :: thdiff,g2,gshockglnTT ! intent(in) :: p intent(inout) :: df ! ! Check that chi is ok. ! if (headtt) print*,'calc_heatcond_shock: chi_shock=',chi_shock ! ! Calculate terms for shock diffusion: ! Ds/Dt = ... + chi_shock*[del2ss + (glnchi_shock+glnpp).gss] ! call dot(p%gshock,p%glnTT,gshockglnTT) call dot(p%glnrho+p%glnTT,p%glnTT,g2) ! Shock entropy diffusivity. ! Write: chi_shock = chi_shock0*shock, and gshock=grad(shock), so ! Ds/Dt = ... + chi_shock0*[shock*(del2ss+glnpp.gss) + gshock.gss] ! if (headtt) print*,'calc_heatcond_shock: use shock diffusion' if (lheatc_shock) then thdiff=p%gamma*chi_shock*(p%shock*(p%del2lnrho+g2)+gshockglnTT) endif ! ! Add heat conduction to entropy equation. ! df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) + thdiff if (headtt) print*,'calc_heatcond_shock: added thdiff' ! ! Check maximum diffusion from thermal diffusion. ! With heat conduction, the second-order term for entropy is ! gamma*chi*del2ss. ! if (lfirst.and.ldt) then diffus_chi=diffus_chi+(p%gamma*chi_shock*p%shock)*dxyz_2 endif ! endsubroutine calc_heatcond_shock !*********************************************************************** subroutine calc_heat_cool(df,p) ! use Sub, only: cubic_step ! real, dimension (mx,my,mz,mvar) :: df type (pencil_case) :: p ! real, dimension (nx) :: heat real :: prof real :: fnorm ! ! Initialize ! heat=0 ! ! Add spatially uniform heating. ! if (heat_uniform/=0.0) then if (zheat_uniform_range/=0.) then if (abs(z(n)) <= zheat_uniform_range) heat=heat+heat_uniform else heat=heat+heat_uniform endif endif ! ! Add heat profile ! if (lheat_source) then fnorm=(2.*pi*heat_source_sigma**2)**1.5 heat=heat+(heat_source/fnorm)*exp(-.5*((x(l1:l2)-heat_source_offset)/heat_source_sigma)**2) endif ! ! add "coronal" heating (to simulate a hot corona) ! assume a linearly increasing reference profile ! This 1/rho1 business is clumpsy, but so would be obvious alternatives... ! if (tau_heat_cor>0) then prof = cubic_step(z(n),(ztop+zcor)/2,(ztop-zcor)/2) df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) & - prof*(1-TT_cor/p%TT)/tau_heat_cor endif ! ! Add to RHS of temperature equation ! df(l1:l2,m,n,ilnTT) = df(l1:l2,m,n,ilnTT) + p%rho1*p%cv1*p%TT1*heat ! endsubroutine calc_heat_cool !*********************************************************************** subroutine rprint_energy(lreset,lwrite) ! ! reads and registers print parameters relevant to energy ! ! 1-jun-02/axel: adapted from magnetic fields ! use Diagnostics, only: parse_name use FArrayManager, only: farray_index_append ! integer :: iname, inamez logical :: lreset,lwr logical, optional :: lwrite ! lwr = .false. if (present(lwrite)) lwr=lwrite ! ! reset everything in case of reset ! (this needs to be consistent with what is defined above!) ! if (lreset) then idiag_TTmax=0; idiag_TTmin=0; idiag_TTm=0 idiag_yHmax=0; idiag_yHmin=0; idiag_yHm=0 idiag_ethm=0; idiag_ssm=0; idiag_cv=0; idiag_cp=0 idiag_dtchi=0; idiag_dtc=0 idiag_eem=0; idiag_ppm=0; idiag_Tppm=0; idiag_csm=0; idiag_ppmax=0; idiag_ppmin=0 idiag_mum=0; idiag_mumz=0; idiag_TTmz=0; idiag_ssmz=0 idiag_eemz=0; idiag_ppmz=0 idiag_puzmz=0; idiag_pr1mz=0; idiag_eruzmz=0; idiag_ffakez=0 endif ! ! iname runs through all possible names that may be listed in print.in ! do iname=1,nname call parse_name(iname,cname(iname),cform(iname),'TTmax',idiag_TTmax) call parse_name(iname,cname(iname),cform(iname),'TTmin',idiag_TTmin) call parse_name(iname,cname(iname),cform(iname),'TTm',idiag_TTm) call parse_name(iname,cname(iname),cform(iname),'yHmax',idiag_yHmax) call parse_name(iname,cname(iname),cform(iname),'yHmin',idiag_yHmin) call parse_name(iname,cname(iname),cform(iname),'yHm',idiag_yHm) call parse_name(iname,cname(iname),cform(iname),'ethm',idiag_ethm) call parse_name(iname,cname(iname),cform(iname),'ssm',idiag_ssm) call parse_name(iname,cname(iname),cform(iname),'cv',idiag_cv) call parse_name(iname,cname(iname),cform(iname),'cp',idiag_cp) call parse_name(iname,cname(iname),cform(iname),'dtchi',idiag_dtchi) call parse_name(iname,cname(iname),cform(iname),'dtc',idiag_dtc) call parse_name(iname,cname(iname),cform(iname),'eem',idiag_eem) call parse_name(iname,cname(iname),cform(iname),'ppm',idiag_ppm) call parse_name(iname,cname(iname),cform(iname),'Tppm',idiag_Tppm) call parse_name(iname,cname(iname),cform(iname),'ppmax',idiag_ppmax) call parse_name(iname,cname(iname),cform(iname),'ppmin',idiag_ppmin) call parse_name(iname,cname(iname),cform(iname),'csm',idiag_csm) call parse_name(iname,cname(iname),cform(iname),'mum',idiag_mum) enddo ! ! Check for those quantities for which we want xy-averages. ! do inamez=1,nnamez call parse_name(inamez,cnamez(inamez),cformz(inamez),'ffakez',idiag_ffakez) call parse_name(inamez,cnamez(inamez),cformz(inamez),'eruzmz',idiag_eruzmz) call parse_name(inamez,cnamez(inamez),cformz(inamez),'puzmz',idiag_puzmz) call parse_name(inamez,cnamez(inamez),cformz(inamez),'pr1mz',idiag_pr1mz) call parse_name(inamez,cnamez(inamez),cformz(inamez),'mumz',idiag_mumz) call parse_name(inamez,cnamez(inamez),cformz(inamez),'TTmz',idiag_TTmz) call parse_name(inamez,cnamez(inamez),cformz(inamez),'ssmz',idiag_ssmz) call parse_name(inamez,cnamez(inamez),cformz(inamez),'eemz',idiag_eemz) call parse_name(inamez,cnamez(inamez),cformz(inamez),'ppmz',idiag_ppmz) enddo ! ! check for those quantities for which we want video slices ! if (lwrite_slices) then where(cnamev=='TT'.or.cnamev=='lnTT') cformv='DEFINED' endif ! ! write column where which variable is stored ! if (lwr) then if (ltemperature_nolog) then call farray_index_append('ilnTT', 0) else call farray_index_append('iTT', 0) endif call farray_index_append('iyH', iyH) call farray_index_append('iss', iss) endif ! endsubroutine rprint_energy !*********************************************************************** subroutine get_slices_energy(f,slices) ! use Slices_methods, only: assign_slices_scal, process_slices, exp2d, log2d ! real, dimension (mx,my,mz,mfarray) :: f type (slice_data) :: slices ! ! Loop over slices ! if (trim(slices%name)=='TT'.or.trim(slices%name)=='lnTT') then ! ! Temperature. ! call assign_slices_scal(slices,f,ilnTT) ! index ilnTT is always valid if (ltemperature_nolog) then if (trim(slices%name)=='lnTT') call process_slices(slices,log2d) else if (trim(slices%name)=='TT') call process_slices(slices,exp2d) endif ! endif ! 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; may not be necessary for lnTT ! 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) call fatal_error('dynamical_thermal_diffusion', 'not implemented yet') ! endsubroutine dynamical_thermal_diffusion !*********************************************************************** subroutine split_update_energy(f) ! ! Dummy subroutine ! real, dimension(mx,my,mz,mfarray), intent(inout) :: f ! call keep_compiler_quiet(f) ! endsubroutine !*********************************************************************** subroutine expand_shands_energy ! ! Presently dummy, for possible use ! endsubroutine expand_shands_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 update_char_vel_energy(f) ! ! TB implemented. ! ! 25-sep-15/MR+joern: coded ! real, dimension (mx,my,mz,mfarray), intent(in) :: f call keep_compiler_quiet(f) call warning('update_char_vel_energy', & 'characteristic velocity not yet implemented for temperature_ionization') endsubroutine update_char_vel_energy !*********************************************************************** subroutine pushdiags2c(p_diag) integer, parameter :: n_diags=0 integer(KIND=ikind8), dimension(:) :: p_diag call keep_compiler_quiet(p_diag) endsubroutine pushdiags2c !*********************************************************************** subroutine pushpars2c(p_par) use Syscalls, only: copy_addr integer, parameter :: n_pars=1 integer(KIND=ikind8), dimension(n_pars) :: p_par call copy_addr(chi,p_par(1)) endsubroutine pushpars2c !*********************************************************************** endmodule Energy