! $Id: eos_idealgas.f90 13598 2010-04-06 10:26:10Z tavo.buk $ ! ! Equation of state for an ideal gas without ionization. ! !** AUTOMATIC CPARAM.INC GENERATION **************************** ! Declare (for generation of cparam.inc) the number of f array ! variables and auxiliary variables added by this module ! ! MVAR CONTRIBUTION 0 ! MAUX CONTRIBUTION 0 ! ! 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) ! PENCILS PROVIDED del2ss; del2lnTT; cv1; gamma ! PENCILS PROVIDED del2TT; glnmumol(3); ppvap; csvap2 ! !*************************************************************** module EquationOfState ! use Cdata use Cparam use Messages use Sub, only: keep_compiler_quiet ! implicit none ! include 'eos.h' ! interface eoscalc ! Overload subroutine `eoscalc' function module procedure eoscalc_pencil ! explicit f implicit m,n module procedure eoscalc_point ! explicit lnrho, ss module procedure eoscalc_farray ! explicit lnrho, ss end interface ! interface pressure_gradient ! Overload subroutine `pressure_gradient' module procedure pressure_gradient_farray ! explicit f implicit m,n module procedure pressure_gradient_point ! explicit lnrho, ss end interface ! integer, parameter :: ilnrho_ss=1, ilnrho_ee=2, ilnrho_pp=3 integer, parameter :: ilnrho_lnTT=4, ilnrho_cs2=5 integer, parameter :: irho_cs2=6, irho_ss=7, irho_lnTT=8, ilnrho_TT=9 integer, parameter :: irho_TT=10, ipp_ss=11, ipp_cs2=12 real, dimension(mz) :: profz_eos=1.0,dprofz_eos=0.0 real, dimension(3) :: beta_glnrho_global=0.0, beta_glnrho_scaled=0.0 real :: lnTT0=impossible real :: xHe=0.0 real :: mu=1.0 real :: cs0=1.0, rho0=1.0, pp0=1.0 real :: cs20=1.0, lnrho0=0.0 real :: ptlaw=0.0 real :: gamma=5.0/3.0 real :: Rgas_cgs=0.0, Rgas, error_cp=1.0e-6 real :: gamma_m1 !(=gamma-1) real :: gamma_inv !(=1/gamma) real :: cp=impossible, cp1=impossible, cv=impossible, cv1=impossible real :: pres_corr=0.1 real :: cs2top_ini=impossible, dcs2top_ini=impossible real :: cs2bot=1.0, cs2top=1.0 real :: cs2cool=0.0 real :: mpoly=1.5, mpoly0=1.5, mpoly1=1.5, mpoly2=1.5 real :: width_eos_prof=0.2 integer :: isothtop=0 integer :: ieosvars=-1, ieosvar1=-1, ieosvar2=-1, ieosvar_count=0 logical :: leos_isothermal=.false., leos_isentropic=.false. logical :: leos_isochoric=.false., leos_isobaric=.false. character (len=labellen) :: ieos_profile='nothing' ! ! Input parameters. ! namelist /eos_init_pars/ & xHe, mu, cp, cs0, rho0, gamma, error_cp, ptlaw, cs2top_ini, dcs2top_ini ! ! Run parameters. ! namelist /eos_run_pars/ & xHe, mu, cp, cs0, rho0, gamma, error_cp, ptlaw, cs2top_ini, & dcs2top_ini, ieos_profile, width_eos_prof,pres_corr ! contains !*********************************************************************** subroutine register_eos() ! ! Register variables from the EquationOfState module. ! ! 14-jun-03/axel: adapted from register_eos ! leos=.true. leos_idealgas=.true. ! if ((ip<=8) .and. lroot) then print*, 'register_eos: ionization nvar = ', nvar endif ! ! Identify version number. ! if (lroot) call svn_id( & '$Id: eos_idealgas.f90 13598 2010-04-06 10:26:10Z tavo.buk $') ! endsubroutine register_eos !*********************************************************************** subroutine units_eos() ! ! This routine calculates things related to units and must be called ! before the rest of the units are being calculated. ! ! 22-jun-06/axel: adapted from initialize_eos ! 4-aug-09/axel: added possibility of vertical profile function ! use SharedVariables, only: put_shared_variable use Mpicomm, only: stop_it use Sub, only: erfunc ! real :: Rgas_unit_sys, cp_reference integer :: ierr ! ! Set gamma_m1, cs20, and lnrho0. ! (used currently for non-dimensional equation of state) ! gamma_m1=gamma-1.0 gamma_inv=1/gamma ! ! Avoid floating overflow if cs0 was not set. ! cs20=cs0**2 lnrho0=log(rho0) ! ! Initialize variable selection code (needed for RELOADing). ! ieosvars=-1 ieosvar_count=0 ! ! Unless unit_temperature is set, calculate by default with cp=1. ! If unit_temperature is set, cp must follow from this. ! Conversely, if cp is set, then unit_temperature must follow from this. ! If unit_temperature and cp are set, the problem is overdetermined, ! but it may still be correct, so this will be checked here. ! When gamma=1.0 (gamma_m1=0.0), write Rgas=mu*cp or cp=Rgas/mu. ! if (unit_system=='cgs') then Rgas_unit_sys=k_B_cgs/m_u_cgs elseif (unit_system=='SI') then Rgas_unit_sys=k_B_cgs/m_u_cgs*1.0e-4 endif ! if (unit_temperature==impossible) then if (cp==impossible) cp=1.0 if (gamma_m1==0.0) then Rgas=mu*cp else Rgas=mu*(1.0-gamma_inv)*cp endif unit_temperature=unit_velocity**2*Rgas/Rgas_unit_sys else Rgas=Rgas_unit_sys*unit_temperature/unit_velocity**2 if (cp==impossible) then if (gamma_m1==0.0) then cp=Rgas/mu else cp=Rgas/(mu*gamma_m1*gamma_inv) endif else ! ! Checking whether the units are overdetermined. ! This is assumed to be the case when the two differ by error_cp. ! if (gamma_m1==0.0) then cp_reference=Rgas/mu else cp_reference=Rgas/(mu*gamma_m1*gamma_inv) endif if (abs(cp-cp_reference)/cp > error_cp) then if (lroot) print*,'initialize_eos: consistency: cp=', cp , & 'while: cp_reference=', cp_reference call fatal_error('initialize_eos','') endif endif endif cp1=1/cp cv=gamma_inv*cp cv1=gamma*cp1 ! ! Need to calculate the equivalent of cs0. ! Distinguish between gamma=1 case and not. ! if (gamma_m1/=0.0) then lnTT0=log(cs20/(cp*gamma_m1)) !(general case) else lnTT0=log(cs20/cp) !(isothermal/polytropic cases: check!) endif pp0=Rgas*exp(lnTT0)*rho0 ! ! Shared variables ! call put_shared_variable('cs20',cs20,ierr) if (ierr/=0) call fatal_error('units_eos','problem when putting cs20') ! call put_shared_variable('mpoly',mpoly,ierr) if (ierr/=0) call fatal_error('units_eos','problem when putting mpoly') ! call put_shared_variable('gamma',gamma,ierr) if (ierr/=0) call fatal_error('units_eos','problem when putting gamma') ! ! Check that everything is OK. ! if (lroot) then print*, 'initialize_eos: unit_temperature=', unit_temperature print*, 'initialize_eos: cp, lnTT0, cs0, pp0=', cp, lnTT0, cs0, pp0 endif ! ! Calculate profile functions (used as prefactors to turn off pressure ! gradient term). ! if (ieos_profile=='nothing') then profz_eos=1.0 dprofz_eos=0.0 elseif (ieos_profile=='surface_z') then profz_eos=0.5*(1.0-erfunc(z/width_eos_prof)) dprofz_eos=-exp(-(z/width_eos_prof)**2)/(sqrtpi*width_eos_prof) endif ! endsubroutine units_eos !*********************************************************************** subroutine initialize_eos() ! ! Perform any post-parameter-read initialization ! ! Initialize variable selection code (needed for RELOADing). ! ieosvars=-1 ieosvar_count=0 ! ! Write constants to disk. In future we may want to deal with this ! using an include file or another module. ! if (lroot) then open (1,file=trim(datadir)//'/pc_constants.pro',position="append") write (1,'(a,1pd26.16)') 'k_B=',k_B write (1,'(a,1pd26.16)') 'm_H=',m_H write (1,*) 'lnrho0=',lnrho0 write (1,*) 'lnTTO=',lnTT0 write (1,*) 'cs20=',cs20 write (1,*) 'cp=',cp close (1) endif ! endsubroutine initialize_eos !*********************************************************************** subroutine select_eos_variable(variable,findex) ! ! Select eos variable. ! ! 02-apr-06/tony: implemented ! use FArrayManager ! character (len=*), intent(in) :: variable integer, intent(in) :: findex integer :: this_var integer, save :: ieosvar_selected=0 integer, parameter :: ieosvar_lnrho = 2**0 integer, parameter :: ieosvar_rho = 2**1 integer, parameter :: ieosvar_ss = 2**2 integer, parameter :: ieosvar_lnTT = 2**3 integer, parameter :: ieosvar_TT = 2**4 integer, parameter :: ieosvar_cs2 = 2**5 integer, parameter :: ieosvar_pp = 2**6 ! if (ieosvar_count==0) ieosvar_selected=0 ! if (ieosvar_count>=2) & call fatal_error('select_eos_variable', & '2 thermodynamic quantities have already been defined '// & 'while attempting to add a 3rd') ! ieosvar_count=ieosvar_count+1 ! 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<0) then leos_isothermal=.true. endif elseif (variable=='lnTT') then this_var=ieosvar_lnTT if (findex<0) then leos_isothermal=.true. endif elseif (variable=='TT') then this_var=ieosvar_TT 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_count==1) then ieosvar1=findex ieosvar_selected=ieosvar_selected+this_var return endif ! ! Ensure the indexes are in the correct order. ! if (this_var