! $Id$ ! ! This modules contains the routines for simulation with ! simple hydrogen ionization. ! !** 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 :: leos = .true., leos_ionization = .true., leos_temperature_ionization=.false. ! CPARAM logical, parameter :: leos_idealgas = .false., leos_chemistry = .false. ! ! MVAR CONTRIBUTION 0 ! MAUX CONTRIBUTION 2 ! COMMUNICATED AUXILIARIES 1 ! ! PENCILS PROVIDED ss; gss(3); ee; pp; lnTT; cs2; cp; cp1; cp1tilde ! PENCILS PROVIDED glnTT(3); TT; TT1; gTT(3); yH; hss(3,3); hlnTT(3,3); del2TT; del6TT; del6lnTT ! PENCILS PROVIDED del2ss; del6ss; del2lnTT; cv; cv1; glnmumol(3); ppvap; csvap2 ! PENCILS PROVIDED rho_anel; rho1gpp(3) ! !*************************************************************** module EquationOfState ! use Cdata use General, only: keep_compiler_quiet use Messages ! implicit none ! include 'eos.h' include 'eos_params.h' ! secondary parameters calculated in initialize real :: TT_ion,lnTT_ion,TT_ion_,lnTT_ion_ real :: ss_ion,ee_ion,kappa0,xHe_term,ss_ion1,Srad0 real :: lnrho_e,lnrho_e_,lnrho_H,lnrho_He,Rgas,mu1yHxHe ! namelist parameters real, parameter :: yHmin=tiny(TT_ion), yHmax=1-epsilon(TT_ion) real :: xHe=0.1 real :: yMetals=0 real :: yHacc=1e-5 !ajwm Moved here from Density.f90 !ajwm Completely irrelevant to eos_ionization but density and entropy need !ajwm reworking to be independent of these things first !ajwm can't use impossible else it breaks reading param.nml !ajwm SHOULDN'T BE HERE... But can wait till fully unwrapped real :: cs0=impossible, rho0=impossible real :: cs20=impossible, lnrho0=impossible logical :: lpp_as_aux=.false., lcp_as_aux=.false. real :: gamma=impossible real :: lnTT0=impossible, TT0=impossible real :: cs2bot=impossible, cs2top=impossible ! input parameters namelist /eos_init_pars/ xHe,yMetals,yHacc,lpp_as_aux,lcp_as_aux ! run parameters namelist /eos_run_pars/ xHe,yMetals,yHacc,lpp_as_aux,lcp_as_aux ! integer :: imass=0, ivars_mod ! real :: Cp_const=impossible real :: Pr_number=0.7 logical :: lpres_grad=.false. ! contains !*********************************************************************** subroutine register_eos ! ! 2-feb-03/axel: adapted from Interstellar module ! 13-jun-03/tobi: re-adapted from visc_shock module ! use FArrayManager use Sub use SharedVariables,only: put_shared_variable ! ! Set indices for auxiliary variables. ! !call farray_register_auxiliary('yH',iyH,communicated=.true.) call farray_register_auxiliary('yH',iyH) if (.not.ltemperature.or.ltemperature_nolog) & call farray_register_auxiliary('lnTT',ilnTT,communicated=.true.) ! ! Identify version number (generated automatically by SVN). ! if (lroot) call svn_id( & "$Id$") ! ! Writing files for use with IDL. ! aux_var(aux_count)=',yh $' aux_count=aux_count+1 if (naux < maux) aux_var(aux_count)=',lnTT $' if (naux == maux) aux_var(aux_count)=',lnTT' aux_count=aux_count+1 if (lroot) then write(15,*) 'yH = fltarr(mx,my,mz)*one' write(15,*) 'lnTT = fltarr(mx,my,mz)*one' endif call put_shared_variable('gamma',gamma,caller='register_eos') if (.not.ldensity) then call put_shared_variable('rho0',rho0) call put_shared_variable('lnrho0',lnrho0) endif ! endsubroutine register_eos !*********************************************************************** subroutine units_eos ! ! If unit_temperature hasn't been specified explictly in start.in, ! set it to 1 (Kelvin). ! ! 24-jun-06/tobi: coded ! ! 11-feb-23/fred lfix_unit_std seeks to adopt a numerically stable value ! as in ideal gas, yet to explore here ! if (unit_temperature==impossible) then if (lfix_unit_std) then unit_temperature=unit_density*unit_velocity**2/k_B_cgs*13.6 else unit_temperature=1. endif endif if (lroot) print*,'unit temperature',unit_temperature ! endsubroutine units_eos !*********************************************************************** subroutine initialize_eos(f) ! ! Perform any post-parameter-read initialization, e.g. set derived ! parameters. ! ! 2-feb-03/axel: adapted from Interstellar module ! use General use Sub, only: register_report_aux ! real, dimension (mx,my,mz,mfarray),intent(INOUT):: f if (lroot) print*,'initialize_eos: ENTER' ! ! ionization parameters ! since m_e and chiH, as well as hbar are all very small ! it is better to divide m_e and chiH separately by hbar. ! if (pretend_lnTT) then call warning('initialize_eos','pretend_lnTT is not used with ionization') pretend_lnTT=.false. endif Rgas=k_B/m_p mu1yHxHe=1+3.97153*xHe TT_ion=chiH/k_B lnTT_ion=log(TT_ion) TT_ion_=chiH_/k_B lnTT_ion_=log(chiH_/k_B) lnrho_e=1.5*log((m_e/hbar)*(chiH/hbar)/2./pi)+log(m_H)+log(mu1yHxHe) lnrho_H=1.5*log((m_H/hbar)*(chiH/hbar)/2./pi)+log(m_H)+log(mu1yHxHe) lnrho_He=1.5*log((m_He/hbar)*(chiH/hbar)/2./pi)+log(m_H)+log(mu1yHxHe) lnrho_e_=1.5*log((m_e/hbar)*(chiH_/hbar)/2./pi)+log(m_H)+log(mu1yHxHe) ss_ion=k_B/m_H/mu1yHxHe ss_ion1=1/ss_ion ee_ion=ss_ion*TT_ion kappa0=sigmaH_/m_H/mu1yHxHe/4.0 Srad0=sigmaSB*TT_ion**4.0D0/pi ! if (xHe>0) then xHe_term=xHe*(log(xHe)-lnrho_He) elseif (xHe<0) then call fatal_error('initialize_eos','xHe < 0 makes no sense') else xHe_term=0 endif ! ! pressure and cp as optional auxiliary variable ! if (lpp_as_aux) call register_report_aux('pp',ipp) if (lcp_as_aux) call register_report_aux('cp',icp) ! if (lrun) call init_eos(f) if (lroot.and.ip<14) then print*,'initialize_eos: reference values for ionization' print*,'initialize_eos: yHmin,yHmax,yMetals=',yHmin,yHmax,yMetals print*,'initialize_eos: TT_ion,ss_ion,kappa0=', & TT_ion,ss_ion,kappa0 print*,'initialize_eos: lnrho_e,lnrho_H,lnrho_He,lnrho_e_=', & lnrho_e,lnrho_H,lnrho_He,lnrho_e_ endif ! ! write scale non-free constants to file; to be read by idl ! if (lroot) then open (1,file=trim(datadir)//'/pc_constants.pro',position="append") write (1,*) 'TT_ion=',TT_ion write (1,*) 'lnTT_ion=',lnTT_ion write (1,*) 'TT_ion_=',TT_ion_ write (1,*) 'lnTT_ion_=',lnTT_ion_ write (1,*) 'lnrho_e=',lnrho_e write (1,*) 'lnrho_H=',lnrho_H write (1,*) 'lnrho_p=',lnrho_H write (1,*) 'lnrho_He=',lnrho_He write (1,*) 'lnrho_e_=',lnrho_e_ write (1,*) 'ss_ion=',ss_ion write (1,*) 'ee_ion=',ee_ion write (1,*) 'kappa0=',kappa0 write (1,*) 'Srad0=',Srad0 write (1,*) 'k_B=',k_B write (1,*) 'm_H=',m_H close (1) endif ! endsubroutine initialize_eos !*********************************************************************** subroutine select_eos_variable(variable,findex) ! ! Calculate average particle mass in the gas relative to ! ! 02-apr-06/tony: implemented ! character (len=*), intent(in) :: variable integer, intent(in) :: findex ! call keep_compiler_quiet(variable) call keep_compiler_quiet(findex) ! DUMMY ideagas version below !! integer :: this_var=0 !! integer, save :: ieosvar=0 !! integer, save :: ieosvar_selected=0 !! integer, parameter :: ieosvar_lnrho = 1 !! integer, parameter :: ieosvar_rho = 2 !! integer, parameter :: ieosvar_ss = 4 !! integer, parameter :: ieosvar_lnTT = 8 !! integer, parameter :: ieosvar_TT = 16 !! integer, parameter :: ieosvar_cs2 = 32 !! integer, parameter :: ieosvar_pp = 64 !!! !! if (ieosvar>=2) & !! call fatal_error("select_eos_variable", & !! "2 thermodynamic quantities have already been defined while attempting to add a 3rd: ") !//variable) !! !! ieosvar=ieosvar+1 !! !!! select case (variable) !! if (variable=='ss') then !! this_var=ieosvar_ss !! if (findex<0) then !! leos_isentropic=.true. !! endif !! elseif (variable=='cs2') then !! this_var=ieosvar_cs2 !! if (findex==-2) then !! leos_localisothermal=.true. !! elseif (findex<0) then !! leos_isothermal=.true. !! endif !! elseif (variable=='lnTT') then !! this_var=ieosvar_lnTT !! if (findex<0) then !! leos_isothermal=.true. !! endif !! elseif (variable=='lnrho') then !! this_var=ieosvar_lnrho !! if (findex<0) then !! leos_isochoric=.true. !! endif !! elseif (variable=='rho') then !! this_var=ieosvar_rho !! if (findex<0) then !! leos_isochoric=.true. !! endif !! elseif (variable=='pp') then !! this_var=ieosvar_pp !! if (findex<0) then !! leos_isobaric=.true. !! endif !! else !! call fatal_error("select_eos_variable", & !! "unknown thermodynamic variable") !! endif !! if (ieosvar==1) then !! ieosvar1=findex !! ieosvar_selected=ieosvar_selected+this_var !! return !! endif !!! !!! Ensure the indexes are in the correct order. !!! !! if (this_var abs(dyHold*dff) ) ! ! Bisection ! dyHold=dyH dyH=0.5*(yHhigh-yHlow) yH=yHhigh-dyH elsewhere ! ! Newton-Raphson ! dyHold=dyH dyH=ff/dff ! Apply floor to dyH (necessary to avoid negative yH in samples ! /0d-tests/heating_ionize) dyH=min(dyH,yH-yHmin) dyH=max(dyH,yH-yHmax) ! plausibly needed as well yH=yH-dyH endwhere endwhere where (abs(dyH)>max(yHacc,1e-31)*max(yH,1e-31)) ! use max to avoid underflow fractions1=1/(1+yH+xHe) lnTT_=(2.0/3.0)*((ss/ss_ion+(1-yH)*(log(1-yH+epsi)-lnrho_H) & +yH*(2*log(yH)-lnrho_e-lnrho_H) & +xHe_term)*fractions1+lnrho-2.5) TT1_=exp(-lnTT_) ff=lnrho_e-lnrho+1.5*lnTT_-TT1_+log(1-yH+epsi)-2*log(yH) dlnTT_=((2.0/3.0)*(-ff-TT1_)-1)*fractions1 dff=dlnTT_*(1.5+TT1_)-1/(1-yH+epsi)-2/yH where (ff<0) yHhigh=yH elsewhere yHlow=yH endwhere elsewhere found=.true. endwhere if (all(found)) return enddo ! endsubroutine rtsafe_pencil !*********************************************************************** subroutine rtsafe(ivars,var1,var2,yHlb,yHub,yH,rterror,rtdebug) ! ! safe newton raphson algorithm (adapted from NR) ! ! 09-apr-03/tobi: changed to subroutine ! integer, intent(in) :: ivars real, intent(in) :: var1,var2 real, intent(in) :: yHlb,yHub real, intent(inout) :: yH logical, intent(out), optional :: rterror logical, intent(in), optional :: rtdebug ! real :: dyHold,dyH,yHl,yHh,f,df,temp integer :: i integer, parameter :: maxit=1000 ! if (present(rterror)) rterror=.false. if (present(rtdebug)) then if (rtdebug) print*,'rtsafe: i,yH=',0,yH endif ! yHl=yHlb yHh=yHub dyH=1 dyHold=dyH ! call saha(ivars,var1,var2,yH,f,df) ! do i=1,maxit if (present(rtdebug)) then if (rtdebug) print*,'rtsafe: i,yH=',i,yH endif if ( sign(1.,((yH-yHl)*df-f)) & == sign(1.,((yH-yHh)*df-f)) & .or. abs(2*f) > abs(dyHold*df) ) then dyHold=dyH dyH=0.5*(yHl-yHh) yH=yHh+dyH if (yHh==yH) return else dyHold=dyH dyH=f/df temp=yH yH=yH-dyH if (temp==yH) return endif if (abs(dyH) abs(dyHold*df) ) then dyHold=dyH dyH=0.5*(yHl-yHh) yH=yHh+dyH if (yHh==yH) return else dyHold=dyH dyH=f/df temp=yH yH=yH-dyH if (temp==yH) return endif if (abs(dyH)0) yH_term=yH*(2*log(yH)-lnrho_e-lnrho_H) elsewhere yH_term=0 endwhere ! where (yH<1) one_yH_term=(1-yH)*(log(1-yH+epsi)-lnrho_H) elsewhere one_yH_term=0 endwhere ! ss_arr(l1:l2,m,n)=ss_ion*((1+yH+xHe)*(1.5*log(T0/TT_ion)-lnrho+2.5)-yH_term-one_yH_term-xHe_term) ! enddo enddo ! endsubroutine isothermal_entropy !*********************************************************************** subroutine bc_ss_flux(f,topbot,lone_sided) ! ! constant flux boundary condition for entropy (called when bcz='c1') ! ! 23-jan-2002/wolf: coded ! 11-jun-2002/axel: moved into the entropy module ! 8-jul-2002/axel: split old bc_ss into two ! 26-aug-2003/tony: distributed across ionization modules ! 3-oct-16/MR: added new optional switch lone_sided ! use Gravity use SharedVariables,only: get_shared_variable ! real, pointer :: Fbot,Ftop,FtopKtop,FbotKbot,hcond0,hcond1,chi logical, pointer :: lmultilayer, lheatc_chiconst ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f logical, optional :: lone_sided real, dimension (size(f,1),size(f,2)) :: tmp_xy,TT_xy,rho_xy,yH_xy integer :: i ! ! Do the `c1' boundary condition (constant heat flux) for entropy. ! check whether we want to do top or bottom (this is precessor dependent) ! ! Get the shared variables ! call get_shared_variable('hcond0',hcond0,caller='bc_ss_flux') call get_shared_variable('hcond1',hcond1) call get_shared_variable('Fbot',Fbot) call get_shared_variable('Ftop',Ftop) call get_shared_variable('FbotKbot',FbotKbot) call get_shared_variable('FtopKtop',FtopKtop) call get_shared_variable('chi',chi) call get_shared_variable('lmultilayer',lmultilayer) call get_shared_variable('lheatc_chiconst',lheatc_chiconst) ! select case (topbot) ! ! bottom boundary ! --------------- ! case(BOT) if (lmultilayer) then if (headtt) print*,'bc_ss_flux: Fbot,hcond=',Fbot,hcond0*hcond1 else if (headtt) print*,'bc_ss_flux: Fbot,hcond=',Fbot,hcond0 endif ! ! calculate Fbot/(K*cs2) ! rho_xy=exp(f(:,:,n1,ilnrho)) TT_xy=exp(f(:,:,n1,ilnTT)) ! ! check whether we have chi=constant at bottom, in which case ! we have the nonconstant rho_xy*chi in tmp_xy. ! if (lheatc_chiconst) then tmp_xy=Fbot/(rho_xy*chi*TT_xy) else tmp_xy=FbotKbot/TT_xy endif ! ! get ionization fraction at bottom boundary ! yH_xy=f(:,:,n1,iyH) ! ! enforce ds/dz + gamma_m1/gamma*dlnrho/dz = - gamma_m1/gamma*Fbot/(K*cs2) ! do i=1,nghost f(:,:,n1-i,iss)=f(:,:,n1+i,iss)+ss_ion*(1+yH_xy+xHe)* & (f(:,:,n1+i,ilnrho)-f(:,:,n1-i,ilnrho)+3*i*dz*tmp_xy) enddo ! ! top boundary ! ------------ ! case(TOP) if (lmultilayer) then if (headtt) print*,'bc_ss_flux: Ftop,hcond=',Ftop,hcond0*hcond1 else if (headtt) print*,'bc_ss_flux: Ftop,hcond=',Ftop,hcond0 endif ! ! calculate Fbot/(K*cs2) ! rho_xy=exp(f(:,:,n2,ilnrho)) TT_xy=exp(f(:,:,n2,ilnTT)) ! ! check whether we have chi=constant at bottom, in which case ! we have the nonconstant rho_xy*chi in tmp_xy. ! if (lheatc_chiconst) then tmp_xy=Ftop/(rho_xy*chi*TT_xy) else tmp_xy=FtopKtop/TT_xy endif ! ! get ionization fraction at top boundary ! yH_xy=f(:,:,n2,iyH) ! ! enforce ds/dz + gamma_m1/gamma*dlnrho/dz = - gamma_m1/gamma*Fbot/(K*cs2) ! do i=1,nghost f(:,:,n2+i,iss)= f(:,:,n2-i,iss)+ss_ion*(1+yH_xy+xHe)* & (f(:,:,n2-i,ilnrho)-f(:,:,n2+i,ilnrho)-3*i*dz*tmp_xy) enddo ! case default call fatal_error("bc_ss_flux","topbot should be BOT or TOP") endselect call keep_compiler_quiet(present(lone_sided)) ! endsubroutine bc_ss_flux !*********************************************************************** subroutine bc_ss_flux_turb(f,topbot) ! ! dummy routine ! ! 4-may-2009/axel: dummy routine ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_flux_turb","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_flux_turb !*********************************************************************** subroutine bc_ss_flux_turb_x(f,topbot) ! ! dummy routine ! ! 31-may-2010/pete: dummy routine ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_flux_turb_x","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_flux_turb_x !*********************************************************************** subroutine bc_ss_flux_condturb_x(f,topbot) ! ! 23-apr-2014/pete: dummy ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_flux_condturb_x","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_flux_condturb_x !*********************************************************************** subroutine bc_ss_flux_condturb_mean_x(f,topbot) ! ! 07-jan-2015/pete: dummy ! integer, intent(IN) :: topbot real, dimension (mx,my,mz,mfarray) :: f ! call not_implemented("bc_ss_flux_condturb_z_mean_x","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_flux_condturb_mean_x !*********************************************************************** subroutine bc_ss_flux_condturb_z(f,topbot) ! ! 15-jul-2014/pete: dummy ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_flux_condturb_z","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_flux_condturb_z !*********************************************************************** subroutine bc_ss_temp_old(f,topbot) ! ! boundary condition for entropy: constant temperature ! ! 23-jan-2002/wolf: coded ! 11-jun-2002/axel: moved into the entropy module ! 8-jul-2002/axel: split old bc_ss into two ! 23-jun-2003/tony: implemented for leos_fixed_ionization ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_temp_old","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_temp_old !*********************************************************************** subroutine bc_ss_temp_x(f,topbot) ! ! boundary condition for entropy: constant temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_temp_x","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_temp_x !*********************************************************************** subroutine bc_ss_temp_y(f,topbot) ! ! boundary condition for entropy: constant temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_temp_y","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_temp_y !*********************************************************************** subroutine bc_ss_temp_z(f,topbot,lone_sided) ! ! boundary condition for entropy: constant temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f logical, optional :: lone_sided ! call not_implemented("bc_ss_temp_z","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) call keep_compiler_quiet(present(lone_sided)) ! endsubroutine bc_ss_temp_z !*********************************************************************** subroutine bc_lnrho_temp_z(f,topbot) ! ! boundary condition for density: constant temperature ! ! 19-aug-2005/tobi: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_lnrho_temp_z","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_lnrho_temp_z !*********************************************************************** subroutine bc_lnrho_pressure_z(f,topbot) ! ! boundary condition for density: constant pressure ! ! 19-aug-2005/tobi: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_lnrho_pressure_z","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_lnrho_pressure_z !*********************************************************************** subroutine bc_ss_temp2_z(f,topbot) ! ! boundary condition for entropy: constant temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_temp2_z","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_temp2_z !*********************************************************************** subroutine bc_ss_temp3_z(f,topbot) ! ! 31-jan-2013/axel: coded to impose cs2bot and dcs2bot at bottom ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented('bc_ss_temp3_z','in eos_ionization') ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_temp3_z !*********************************************************************** subroutine bc_ss_stemp_x(f,topbot) ! ! boundary condition for entropy: symmetric temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_stemp_x","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_stemp_x !*********************************************************************** subroutine bc_ss_stemp_y(f,topbot) ! ! boundary condition for entropy: symmetric temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_stemp_y","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_stemp_y !*********************************************************************** subroutine bc_ss_stemp_z(f,topbot) ! ! boundary condition for entropy: symmetric temperature ! ! 26-sep-2003/tony: coded ! use Gravity ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f real, dimension (size(f,1),size(f,2),nghost) :: lnrho,ss,yH,lnTT,TT,K,sqrtK,yH_term,one_yH_term integer :: i ! ! Symmetric temperature/sound speed for entropy. ! This assumes that the density is already set (ie density _must_ register ! first!) ! ! check whether we want to do top or bottom (this is processor dependent) ! select case (topbot) ! ! bottom boundary ! case(BOT) do i=1,nghost f(:,:,n1-i,ilnTT) = f(:,:,n1+i,ilnTT) enddo ! lnrho=f(:,:,1:n1-1,ilnrho) lnTT=f(:,:,1:n1-1,ilnTT) TT=exp(lnTT) ! K=exp(lnrho_e-lnrho-TT_ion/TT)*(TT/TT_ion)**1.5 sqrtK=sqrt(K) yH=2*sqrtK/(sqrtK+sqrt(4+K)) ! where (yH>0) yH_term=yH*(2*log(yH)-lnrho_e-lnrho_H) elsewhere yH_term=0 endwhere ! where (yH<1) one_yH_term=(1-yH)*(log(1-yH+epsi)-lnrho_H) elsewhere one_yH_term=0 endwhere ! ss=ss_ion*((1+yH+xHe)*(1.5*log(TT/TT_ion)-lnrho+2.5) & -yH_term-one_yH_term-xHe_term) ! f(:,:,1:n1-1,iyH)=yH f(:,:,1:n1-1,iss)=ss ! ! top boundary ! case(TOP) do i=1,nghost f(:,:,n2+i,ilnTT) = f(:,:,n2-i,ilnTT) enddo ! lnrho=f(:,:,n2+1:,ilnrho) lnTT =f(:,:,n2+1:,ilnTT) TT=exp(lnTT) ! K=exp(lnrho_e-lnrho-TT_ion/TT)*(TT/TT_ion)**1.5 sqrtK=sqrt(K) yH=2*sqrtK/(sqrtK+sqrt(4+K)) ! where (yH>0) yH_term=yH*(2*log(yH)-lnrho_e-lnrho_H) elsewhere yH_term=0 endwhere ! where (yH<1) one_yH_term=(1-yH)*(log(1-yH+epsi)-lnrho_H) elsewhere one_yH_term=0 endwhere ! ss=ss_ion*((1+yH+xHe)*(1.5*log(TT/TT_ion)-lnrho+2.5) & -yH_term-one_yH_term-xHe_term) ! f(:,:,n2+1:,iyH)=yH f(:,:,n2+1:,iss)=ss ! case default call fatal_error('bc_ss_stemp_z','topbot should be BOT or TOP') endselect ! endsubroutine bc_ss_stemp_z !*********************************************************************** subroutine bc_ss_a2stemp_x(f,topbot) ! ! boundary condition for entropy: symmetric temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_a2stemp_x","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_a2stemp_x !*********************************************************************** subroutine bc_ss_a2stemp_y(f,topbot) ! ! boundary condition for entropy: symmetric temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_a2stemp_y","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_a2stemp_y !*********************************************************************** subroutine bc_ss_a2stemp_z(f,topbot) ! ! boundary condition for entropy: symmetric temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_ss_a2stemp_z","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_a2stemp_z !*********************************************************************** subroutine bc_ss_energy(f,topbot) ! ! boundary condition for entropy ! ! may-2002/nils: coded ! 11-jul-2002/nils: moved into the entropy module ! 26-aug-2003/tony: distributed across ionization modules ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! ! The 'ce' boundary condition for entropy makes the energy constant at ! the boundaries. ! This assumes that the density is already set (ie density must register ! first!) ! call not_implemented("bc_ss_stemp_y","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_ss_energy !*********************************************************************** subroutine bc_stellar_surface(f,topbot) ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_stellar_surface","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_stellar_surface !*********************************************************************** subroutine bc_lnrho_cfb_r_iso(f,topbot) ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_lnrho_cfb_r_iso","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_lnrho_cfb_r_iso !*********************************************************************** subroutine bc_lnrho_hds_z_iso(f,topbot) ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_lnrho_hds_z_iso","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_lnrho_hds_z_iso !*********************************************************************** subroutine bc_lnrho_hdss_z_iso(f,topbot) ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f ! call not_implemented("bc_lnrho_hdss_z_iso","in eos_ionization") ! call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_lnrho_hdss_z_iso !*********************************************************************** subroutine bc_ism(f,topbot,j) ! ! 30-nov-15/fred: Replaced bc_ctz and bc_cdz. ! Apply observed scale height locally from Reynolds 1991, Manchester & Taylor ! 1981 for warm ionized gas - dominant scale height above 500 parsecs. ! Apply constant local temperature across boundary for entropy. ! Motivation to prevent numerical spikes in shock fronts, which cannot be ! absorbed in only three ghost cells, but boundary thermodynamics still ! responsive to interior dynamics. ! 06-jun-22/fred update to allow setting scale height in start.in or run.in ! default is density_scale_factor=impossible so that scale_factor is 0.9, assuming ! unit_length = 1 kpc and scale is 400 pc. To change scale height add to ! start_pars or run_pars density_scale_factor=... in dimensionless units ! integer, intent(IN) :: topbot real, dimension (:,:,:,:) :: f integer :: j,k,stat real :: density_scale1, density_scale real, dimension (:,:), allocatable :: cv,cp ! if (density_scale_factor==impossible) then density_scale=density_scale_cgs/unit_length else density_scale=density_scale_factor endif density_scale1=1./density_scale ! if (j==iss.and..not.ltemperature) then allocate(cp(size(f,1),size(f,2)),stat=stat) if (stat>0) call fatal_error('bc_ism','could not allocate cp') allocate(cv(size(f,1),size(f,2)),stat=stat) if (stat>0) call fatal_error('bc_ism','could not allocate cv') endif ! select case (topbot) ! case(BOT) ! bottom boundary do k=1,nghost if (j==irho .or. j==ilnrho) then if (ldensity_nolog) then f(:,:,k,j)=f(:,:,n1,j)*exp(-(z(n1)-z(k))*density_scale1) else f(:,:,k,j)=f(:,:,n1,j) - (z(n1)-z(k))*density_scale1 endif else if (j==iss) then if (.not.ltemperature) then !case for entropy cp=(2.5+f(:,:,n1,iyH)*(1-f(:,:,n1,iyH))/((2-f(:,:,n1,iyH))*xHe+2)* & (2.5+TT_ion/exp(f(:,:,n1,ilnTT)))**2)* & Rgas*mu1yHxHe/(1+xHe+f(:,:,n1,iyH)) cv=(1.5+f(:,:,n1,iyH)*(1-f(:,:,n1,iyH))/((2-f(:,:,n1,iyH))* & (1+f(:,:,n1,iyH)+xHe))*(1.5+TT_ion/exp(f(:,:,n1,ilnTT)))**2)* & Rgas*mu1yHxHe/(1+xHe+f(:,:,n1,iyH)) if (ldensity_nolog) then f(:,:,n1-k,j)=f(:,:,n1,j)+(cp-cv) * & (log(f(:,:,n1,j-1))-log(f(:,:,n1-k,j-1))) + & cv*log((z(n1)-z(n1-k))*density_scale+1.) else f(:,:,n1-k,j)=f(:,:,n1,j)+(cp-cv)*& (f(:,:,n1,j-1)-f(:,:,n1-k,j-1))+& cv*log((z(n1)-z(n1-k))*density_scale+1.) endif else !case for lnTT f(:,:,n1-k,j)=f(:,:,n1,j)+log((z(n1)-z(n1-k))*density_scale+1.) endif else call fatal_error('bc_ism','only for irho, ilnrho, iuz or iss') endif enddo ! case(TOP) ! top boundary do k=1,nghost if (j==irho .or. j==ilnrho) then if (ldensity_nolog) then f(:,:,n2+k,j)=f(:,:,n2,j)*exp(-(z(n2+k)-z(n2))*density_scale1) else f(:,:,n2+k,j)=f(:,:,n2,j) - (z(n2+k)-z(n2))*density_scale1 endif else if (j==iss) then if (.not.ltemperature) then !case for entropy cp=(2.5+f(:,:,n2,iyH)*(1-f(:,:,n2,iyH))/((2-f(:,:,n2,iyH))*xHe+2)* & (2.5+TT_ion/exp(f(:,:,n2,ilnTT)))**2)* & Rgas*mu1yHxHe/(1+xHe+f(:,:,n2,iyH)) cv=(1.5+f(:,:,n2,iyH)*(1-f(:,:,n2,iyH))/((2-f(:,:,n2,iyH))* & (1+f(:,:,n2,iyH)+xHe))*(1.5+TT_ion/exp(f(:,:,n2,ilnTT)))**2)* & Rgas*mu1yHxHe/(1+xHe+f(:,:,n2,iyH)) if (ldensity_nolog) then f(:,:,n2+k,j)=f(:,:,n2,j)+(cp-cv)*& (log(f(:,:,n2,j-1))-log(f(:,:,n2+k,j-1)))+& cv*log((z(n2+k)-z(n2))*density_scale+1.) else f(:,:,n2+k,j)=f(:,:,n2,j)+(cp-cv)*& (f(:,:,n2,j-1)-f(:,:,n2+k,j-1))+& cv*log((z(n2+k)-z(n2))*density_scale+1.) endif else !case for lnTT f(:,:,n1-k,j)=f(:,:,n1,j)+log((z(n1)-z(n1-k))*density_scale+1.) endif else call fatal_error('bc_ism','only for irho, ilnrho, iuz or iss') endif enddo ! case default call fatal_error("bc_ism","topbot should be BOT or TOP") ! endselect ! endsubroutine bc_ism !*********************************************************************** 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(cs20,p_par(1)) endsubroutine pushpars2c !*********************************************************************** !******************************************************************** !******************************************************************** !************ DO NOT DELETE THE FOLLOWING ************* !******************************************************************** !** This is an automatically generated include file that creates ** !** copies dummy routines from nospecial.f90 for any Special ** !** routines not implemented in this file ** !** ** include 'eos_dummies.inc' !*********************************************************************** endmodule EquationOfState