! $Id$ ! ! 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 ! ! CPARAM logical, parameter :: leos = .true. ! ! MVAR 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; del6ss; del2lnTT; cv; cv1; del6lnTT; gamma ! PENCILS PROVIDED del2TT; del6TT; glnmumol(3); ppvap; csvap2 ! PENCILS PROVIDED TTb; rho_anel; eth; geth(3); del2eth; heth(3,3) ! PENCILS PROVIDED eths; geths(3); rho1gpp(3) ! !*************************************************************** module EquationOfState ! use Cparam use Cdata use General, only: keep_compiler_quiet use Messages use DensityMethods, only: getlnrho,getrho,getrho_s use SharedVariables, only: get_shared_variable ! implicit none ! include 'eos.h' ! 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 integer, parameter :: irho_eth=13, ilnrho_eth=14 integer :: iglobal_cs2, iglobal_glnTT, ics real :: lnTT0=impossible, TT0=impossible real :: xHe=0.0 real :: mu=1.0 real :: cs0=1.0, cs20=1.0, cs20t, rho0=1., lnrho0=0., rho01=1.0, pp0=1.0 real :: gamma=5.0/3.0 real :: Rgas_cgs=0.0, Rgas, error_cp=1.0e-6 real :: gamma_m1 !(=gamma-1) real :: gamma1 !(=1/gamma) real :: cp=impossible, cp1=impossible, cv=impossible, cv1=impossible real :: pres_corr=0.1 real :: cs2bot=impossible, cs2top=impossible real :: fac_cs=1.0, cs20_tdep_rate=1.0 real, pointer :: mpoly real :: sigmaSBt=1.0 integer :: imass=1 integer :: isothmid=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. logical :: leos_localisothermal=.false. logical :: lanelastic_lin=.false., lcs_as_aux=.false., lcs_as_comaux=.false. logical :: lcs_tdep=.false. ! character (len=labellen) :: meanfield_Beq_profile real, pointer :: meanfield_Beq, chit_quenching, uturb real, dimension(:), pointer :: B_ext ! real, dimension(nchemspec,18):: species_constants ! real :: Cp_const=impossible real :: Pr_number=0.7 logical :: lpres_grad=.false. ! ! Background stratification data ! character(len=labellen) :: gztype = 'zero' real :: gz_coeff = 0.0 ! ! Input parameters. ! namelist /eos_init_pars/ & xHe, mu, cp, cs0, rho0, gamma, error_cp, & sigmaSBt, lanelastic_lin, lcs_as_aux, lcs_as_comaux,& fac_cs,isothmid, lstratz, gztype, gz_coeff, lpres_grad, & lcs_tdep, cs20_tdep_rate ! ! Run parameters. ! namelist /eos_run_pars/ & xHe, mu, cp, cs0, rho0, gamma, error_cp, & pres_corr, sigmaSBt, & lanelastic_lin, lcs_as_aux, lcs_as_comaux, & lcs_tdep, cs20_tdep_rate ! ! Module variables ! real, dimension(mz) :: rho0z = 0.0 real, dimension(mz) :: dlnrho0dz = 0.0 real, dimension(mz) :: eth0z = 0.0 logical :: lstratset = .false. integer, parameter :: BOT=1, TOP=nx ! contains !*********************************************************************** subroutine register_eos ! ! Register variables from the EquationOfState module. ! ! 14-jun-03/axel: adapted from register_eos ! 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$') ! 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 Sub, only: erfunc ! real :: Rgas_unit_sys, cp_reference ! ! Set gamma_m1, cs20, and lnrho0, and rho01. ! (used currently for non-dimensional equation of state) ! gamma_m1=gamma-1.0 gamma1=1/gamma lnrho0=log(rho0) rho01 = 1./rho0 ! ! Avoid floating overflow if cs0 was not set. ! cs20=cs0**2 ! ! 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 elseif (unit_system=='set') then if (gamma_m1==0.0) then Rgas_unit_sys=mu*cp_set else Rgas_unit_sys=mu*gamma_m1*gamma1*cp_set endif endif ! if (unit_temperature==impossible) then if (lfix_unit_std) then !Fred: sets optimal unit temperature lnTT0=0 Rgas=mu*gamma1 if (cp==impossible) then if (gamma_m1==0.0) then cp=Rgas/mu else cp=Rgas/(mu*gamma_m1*gamma1) endif endif unit_temperature=unit_velocity**2*Rgas/Rgas_unit_sys else if (cp==impossible) cp=cp_set if (gamma_m1==0.0) then Rgas=mu*cp else Rgas=mu*(1.0-gamma1)*cp endif unit_temperature=unit_velocity**2*Rgas/Rgas_unit_sys endif 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*gamma1) 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*gamma1) endif ! ! Check against reference. ! if (abs(cp-cp_reference)/cp > error_cp) then if (lroot) print*,'Rgas,mu=', Rgas, mu if (lroot) print*,'units_eos: consistency: cp=', cp, & 'while: cp_reference=', cp_reference if (lroot) print*,'also caused when changing gamma btw start/run!' call fatal_error('units_eos','cp is not correctly calculated') endif endif endif cp1=1/cp cv=gamma1*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 TT0=exp(lnTT0) ! ! Shared variables ! call put_shared_variable('cs20',cs20,caller='units_eos') call put_shared_variable('gamma',gamma) ! ! Check that everything is OK. ! if (lroot) then print*, 'units_eos: unit_temperature=', unit_temperature print*, 'units_eos: cp, lnTT0, cs0, pp0, Rgas=', cp, lnTT0, cs0, pp0, Rgas endif ! endsubroutine units_eos !*********************************************************************** subroutine initialize_eos ! use FArrayManager use SharedVariables, only: put_shared_variable use Sub, only: register_report_aux ! ! 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 ! ! cs as optional auxiliary variable ! if (lcs_as_aux .or. lcs_as_comaux) & call register_report_aux('cs',ics,communicated=lcs_as_comaux) ! call put_shared_variable('cp',cp,caller='initialize_eos') call put_shared_variable('cv',cv) call put_shared_variable('isothmid',isothmid) call put_shared_variable('fac_cs',fac_cs) ! if (.not.ldensity) then call put_shared_variable('rho0',rho0) call put_shared_variable('lnrho0',lnrho0) endif ! if (lanelastic) & call put_shared_variable('lanelastic_lin',lanelastic_lin) ! ! Set background stratification, if any. ! if (lstratz) call set_stratz lstratset = .true. ! if (lfargo_advection.and.(pretend_lnTT.or.ltemperature)) & call fatal_error("initialize_eos","fargo advection not "//& "implemented for the temperature equation") ! ! Register gradient of pressure ! if (lpres_grad) then call farray_register_auxiliary('gpx',igpx) ! ! Writing files for use with IDL ! aux_count = aux_count+1 ! call farray_register_auxiliary('gpy',igpy) ! ! Writing files for use with IDL ! aux_count = aux_count+1 endif ! endsubroutine initialize_eos !*********************************************************************** subroutine select_eos_variable(variable,findex) ! ! Select eos variable. ! ! 02-apr-06/tony: implemented ! use FArrayManager, only: farray_register_global ! character (len=*), intent(in) :: variable integer, intent(in) :: findex integer :: this_var=-1 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 integer, parameter :: ieosvar_eth = 2**7 ! 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==-2) then leos_localisothermal=.true. call farray_register_global('cs2',iglobal_cs2) call farray_register_global('glnTT',iglobal_glnTT,vector=3) 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=='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 elseif (variable=='eth') then this_var=ieosvar_eth 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_var1.or.nprocz>1) then call mpiallreduce_sum(lnrmx,lnrmx_tmp,2*nghost+1,idir=23) call mpiallreduce_sum(cs2mx,cs2mx_tmp,idir=23) lnrmx=lnrmx_tmp cs2mx=cs2mx_tmp endif ! do i=1,nghost; lnrmx(-i)=2.*lnrmx(0)-lnrmx(i); enddo !??? ! ! Compute x-derivative of mean lnrho ! dlnrmxdx= coeffs_1_x(1,1)*(lnrmx(1)-lnrmx(-1)) & +coeffs_1_x(2,1)*(lnrmx(2)-lnrmx(-2)) & +coeffs_1_x(3,1)*(lnrmx(3)-lnrmx(-3)) ! ! Set ghost zones such that -chi_t*rho*T*grads -hcond*gTT = Fbot, i.e. ! enforce: ! ds/dx = -(cp*gamma_m1*Fbot/cs2 + K*gamma_m1*glnrho)/(gamma*K+chi_t*rho) ! dsdx_yz=(-cp*gamma_m1*Fbot/cs2mx)/ & (chit_prof1*chi_t*exp(lnrmx(0)) + hcondxbot*gamma) - & gamma_m1/gamma*dlnrmxdx ! if (lreference_state) & dsdx_yz = dsdx_yz - reference_state(BOT,iref_gs) ! do i=1,nghost f(l1-i,:,:,iss)=f(l1+i,:,:,iss)-dx2_bound(-i)*dsdx_yz enddo endif ! ! top boundary ! ============ ! case ('top') ! call stop_it("bc_ss_flux_condturb_mean_x: not implemented for the top boundary") ! ! capture undefined entries ! case default call fatal_error('bc_ss_flux_condturb_mean_x','invalid argument') endselect ! endsubroutine bc_ss_flux_condturb_mean_x !*********************************************************************** subroutine bc_ss_flux_condturb_z(f,topbot) ! ! Constant conductive + turbulent flux through the surface ! ! 15-jul-2014/pete: adapted from bc_ss_flux_condturb_x ! 4-jun-2015/MR: added missing factor cp in RB ! added branches for Kramers heat conductivity ! use Mpicomm, only: stop_it use DensityMethods, only: getdlnrho_z ! real, pointer :: chi, hcondzbot, hcondztop real, pointer :: chi_t, chit_prof1, chit_prof2 real, pointer :: Fbot, Ftop logical, pointer :: lheatc_chiconst ! character (len=3) :: topbot real, dimension (mx,my,mz,mfarray) :: f real, dimension (mx,my) :: dsdz_xy, TT_xy, rho_xy integer :: i real, pointer :: hcond0_kramers, nkramers logical, pointer :: lheatc_kramers real, dimension(:,:), pointer :: reference_state ! if (ldebug) print*,'bc_ss_flux_turb: ENTER - cs20,cs0=',cs20,cs0 ! ! Get the shared variables ! call get_shared_variable('chi_t',chi_t,caller='bc_ss_flux_condturb_z') call get_shared_variable('chit_prof1',chit_prof1) call get_shared_variable('chit_prof2',chit_prof2) call get_shared_variable('hcondzbot',hcondzbot) call get_shared_variable('hcondztop',hcondztop) call get_shared_variable('lheatc_chiconst',lheatc_chiconst) call get_shared_variable('chi',chi) call get_shared_variable('Fbot',Fbot) call get_shared_variable('Ftop',Ftop) call get_shared_variable('lheatc_kramers',lheatc_kramers) if (lheatc_kramers) then call get_shared_variable('hcond0_kramers',hcond0_kramers) call get_shared_variable('nkramers',nkramers) endif if (lreference_state) & call get_shared_variable('reference_state',reference_state) ! select case (topbot) ! ! Check whether we want to do top or bottom (this is precessor dependent) ! ! bottom boundary ! =============== ! case ('bot') ! ! Do the pretend_lnTT=T case first ! if (pretend_lnTT) then call stop_it("bc_ss_flux_condturb_z: not implemented for pretend_lnTT=T") else ! ! Set ghost zones such that -chi_t*rho*T*grads -hcond*gTT = Fbot ! call getlnrho(f(:,:,n1,ilnrho),rho_xy) ! here rho_xy = ln(rho) TT_xy=f(:,:,n1,iss) ! here TT_xy = entropy if (lreference_state) & TT_xy(l1:l2,:) = TT_xy(l1:l2,:) + spread(reference_state(:,iref_s),2,my) TT_xy=cs20*exp(gamma_m1*(rho_xy-lnrho0)+cv1*TT_xy) ! here TT_xy = cs2 TT_xy=TT_xy/(cp*gamma_m1) ! here TT_xy temperature ! call getrho(f(:,:,n1,ilnrho),rho_xy) ! here rho_xy = rho ! !fac=(1./60)*dz_1(n1) !dlnrhodz_xy=fac*(+ 45.0*(f(:,:,n1+1,ilnrho)-f(:,:,n1-1,ilnrho)) & ! - 9.0*(f(:,:,n1+2,ilnrho)-f(:,:,n1-2,ilnrho)) & ! + (f(:,:,n1+3,ilnrho)-f(:,:,n1-3,ilnrho))) ! if (lheatc_kramers) then dsdz_xy=gamma1*(Fbot/hcond0_kramers)*rho_xy**(2.*nkramers)/TT_xy**(6.5*nkramers+1.) ! no turbulent diffusivity considered here! rho_xy=1.-gamma1 ! not efficient elseif (lheatc_chiconst) then dsdz_xy= (Fbot/TT_xy)/(rho_xy*(chit_prof1*chi_t + cp*gamma*chi)) rho_xy = chi*gamma_m1/(chit_prof1*chi_t/cp+gamma*chi) else dsdz_xy= (Fbot/TT_xy)/(chit_prof1*chi_t*rho_xy + hcondzbot*gamma) rho_xy = hcondzbot*gamma_m1/(chit_prof1*chi_t*rho_xy+gamma*hcondzbot) endif ! ! Enforce ds/dz = -(cp*gamma_m1*Fbot/cs2 + K*gamma_m1*glnrho)/(gamma*K+chi_t*rho) ! do i=1,nghost call getdlnrho_z(f(:,:,:,ilnrho),n1,i,TT_xy) ! here TT_xy = d_z ln(rho) f(:,:,n1-i,iss)=f(:,:,n1+i,iss) + cp*(rho_xy*TT_xy+dz2_bound(-i)*dsdz_xy) enddo ! endif ! ! top boundary ! ============ ! case ('top') ! call stop_it("bc_ss_flux_condturb_z: not implemented for the top boundary") ! ! capture undefined entries ! case default call fatal_error('bc_ss_flux_condturb_z','invalid argument') endselect ! 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 ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f real, dimension (size(f,1),size(f,2)) :: tmp_xy integer :: i real, dimension(:,:), pointer :: reference_state ! if (ldebug) print*,'bc_ss_temp_old: ENTER - cs20,cs0=',cs20,cs0 ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_temp_old') ! ! Do the `c2' boundary condition (fixed temperature/sound speed) for entropy. ! This assumes that the density is already set (ie density must register ! first!) ! tmp_xy = s(x,y) on the boundary. ! gamma*s/cp = [ln(cs2/cs20)-(gamma-1)ln(rho/rho0)] ! ! check whether we want to do top or bottom (this is processor dependent) ! select case (topbot) ! ! bottom boundary ! case ('bot') if ((bcz12(ilnrho,1) /= 'a2') .and. (bcz12(ilnrho,1) /= 'a3')) & call fatal_error('bc_ss_temp_old','Inconsistent boundary conditions 3.') if (ldebug) print*, 'bc_ss_temp_old: set bottom temperature: cs2bot=',cs2bot if (cs2bot<=0.) print*,'bc_ss_temp_old: cannot have cs2bot = ', cs2bot, ' <= 0' ! call getlnrho(f(:,:,n1,ilnrho),tmp_xy) ! here tmp_xy = log(rho) tmp_xy = (-gamma_m1*(tmp_xy-lnrho0) + log(cs2bot/cs20)) / gamma ! if (lreference_state) & tmp_xy(l1:l2,:) = tmp_xy(l1:l2,:) - spread(reference_state(:,iref_s),2,my) f(:,:,n1,iss) = tmp_xy ! do i=1,nghost f(:,:,n1-i,iss) = 2*tmp_xy - f(:,:,n1+i,iss) ! reference_state? enddo ! ! top boundary ! case ('top') if ((bcz12(ilnrho,2) /= 'a2') .and. (bcz12(ilnrho,2) /= 'a3')) & call fatal_error('bc_ss_temp_old','Inconsistent boundary conditions 3.') if (ldebug) print*, 'bc_ss_temp_old: set top temperature - cs2top=',cs2top if (cs2top<=0.) print*, 'bc_ss_temp_old: cannot have cs2top = ',cs2top, ' <= 0' ! ! if (bcz12(ilnrho,1) /= 'a2') & ! call fatal_error('bc_ss_temp_old','Inconsistent boundary conditions 4.') call getlnrho(f(:,:,n2,ilnrho),tmp_xy) tmp_xy = (-gamma_m1*(tmp_xy-lnrho0) + log(cs2top/cs20)) / gamma ! if (lreference_state) & tmp_xy(l1:l2,:) = tmp_xy(l1:l2,:) - spread(reference_state(:,iref_s),2,my) f(:,:,n2,iss) = tmp_xy ! do i=1,nghost f(:,:,n2+i,iss) = 2*tmp_xy - f(:,:,n2-i,iss) ! reference_state? enddo ! case default call fatal_error('bc_ss_temp_old','invalid argument') endselect ! 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 ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f real :: tmp real, dimension(my,mz) :: lnrho_yz integer :: i real, dimension(:,:), pointer :: reference_state ! if (ldebug) print*,'bc_ss_temp_x: cs20,cs0=',cs20,cs0 ! ! Get the shared variables ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_temp_x') ! ! Constant temperature/sound speed for entropy, i.e. antisymmetric ! ln(cs2) relative to cs2top/cs2bot. ! 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') if (ldebug) print*, 'bc_ss_temp_x: set x bottom temperature: cs2bot=',cs2bot if (cs2bot<=0.) print*, 'bc_ss_temp_x: cannot have cs2bot<=0' ! if (lentropy .and. .not. pretend_lnTT) then tmp = 2*cv*log(cs2bot/cs20) call getlnrho(f(l1,:,:,ilnrho),BOT,lnrho_yz) f(l1,:,:,iss) = 0.5*tmp - (cp-cv)*(lnrho_yz - lnrho0) ! if (lreference_state) & f(l1,:,:,iss) = f(l1,:,:,iss) - reference_state(BOT,iref_s) ! if (ldensity_nolog) then do i=1,nghost if (lreference_state) then ! ! Reference state assumed symmetric about boundary point. ! f(l1-i,:,:,iss) = - f(l1+i,:,:,iss) + tmp - 2*reference_state(i,iref_s) & - (cp-cv)*(log( (f(l1+i,:,:,irho)+reference_state(i,iref_rho)) & *(f(l1-i,:,:,irho)+reference_state(i,iref_rho)) ) - 2*lnrho0) else f(l1-i,:,:,iss) = - f(l1+i,:,:,iss) + tmp & - (cp-cv)*(log(f(l1+i,:,:,irho)*f(l1-i,:,:,irho)) - 2*lnrho0) endif enddo else do i=1,nghost f(l1-i,:,:,iss) = - f(l1+i,:,:,iss) + tmp & - (cp-cv)*(f(l1+i,:,:,ilnrho)+f(l1-i,:,:,ilnrho)-2*lnrho0) enddo endif ! elseif (lentropy .and. pretend_lnTT) then f(l1,:,:,iss) = log(cs2bot/gamma_m1) do i=1,nghost; f(l1-i,:,:,iss)=2*f(l1,:,:,iss)-f(l1+i,:,:,iss); enddo elseif (ltemperature) then f(l1,:,:,ilnTT) = log(cs2bot/gamma_m1) do i=1,nghost; f(l1-i,:,:,ilnTT)=2*f(l1,:,:,ilnTT)-f(l1+i,:,:,ilnTT); enddo endif ! ! top boundary ! case ('top') if (ldebug) print*, 'bc_ss_temp_x: set x top temperature: cs2top=',cs2top if (cs2top<=0.) print*, 'bc_ss_temp_x: cannot have cs2top<=0' ! if (lentropy .and. .not. pretend_lnTT) then ! tmp = 2*cv*log(cs2top/cs20) call getlnrho(f(l2,:,:,ilnrho),TOP,lnrho_yz) f(l2,:,:,iss) = 0.5*tmp - (cp-cv)*(lnrho_yz - lnrho0) ! if (lreference_state) & f(l2,:,:,iss) = f(l2,:,:,iss) - reference_state(TOP,iref_s) ! ! Distinguish cases for linear and logarithmic density ! if (ldensity_nolog) then do i=1,nghost if (lreference_state) then ! ! Reference state assumed symmetric about boundary point. ! f(l2+i,:,:,iss) =-f(l2-i,:,:,iss) + tmp - 2.*reference_state(nx-i,iref_s) & - (cp-cv)*(log((f(l2-i,:,:,irho)+reference_state(TOP-i,iref_rho)) & *(f(l2+i,:,:,irho)+reference_state(TOP-i,iref_rho)))-2*lnrho0) else f(l2+i,:,:,iss) = -f(l2-i,:,:,iss) + tmp & -(cp-cv)*(log(f(l2-i,:,:,irho)*f(l2+i,:,:,irho))-2*lnrho0) endif enddo else do i=1,nghost f(l2+i,:,:,iss) = -f(l2-i,:,:,iss) + tmp & - (cp-cv)*(f(l2-i,:,:,ilnrho)+f(l2+i,:,:,ilnrho)-2*lnrho0) enddo endif elseif (lentropy .and. pretend_lnTT) then f(l2,:,:,iss) = log(cs2top/gamma_m1) do i=1,nghost; f(l2+i,:,:,iss)=2*f(l2,:,:,iss)-f(l2-i,:,:,iss); enddo elseif (ltemperature) then f(l2,:,:,ilnTT) = log(cs2top/gamma_m1) do i=1,nghost; f(l2+i,:,:,ilnTT)=2*f(l2,:,:,ilnTT)-f(l2-i,:,:,ilnTT); enddo endif ! case default call fatal_error('bc_ss_temp_x','invalid argument') endselect ! 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 ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f real :: tmp integer :: i real, dimension(mx,mz) :: lnrho_xz real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_temp_y') ! if (ldebug) print*,'bc_ss_temp_y: cs20,cs0=',cs20,cs0 ! ! Constant temperature/sound speed for entropy, i.e. antisymmetric ! ln(cs2) relative to cs2top/cs2bot. ! This assumes that the density is already set (ie density _must_ register ! first!) ! ! check whether we want to do top or bottom (this is precessor dependent) ! select case (topbot) ! ! bottom boundary ! case ('bot') if (ldebug) print*, & 'bc_ss_temp_y: set y bottom temperature - cs2bot=',cs2bot if (cs2bot<=0.) print*, 'bc_ss_temp_y: cannot have cs2bot<=0' ! tmp = 2*cv*log(cs2bot/cs20) call getlnrho(f(:,m1,:,ilnrho),lnrho_xz) ! f(:,m1,:,iss) = 0.5*tmp - (cp-cv)*(lnrho_xz-lnrho0) if (lreference_state) & f(l1:l2,m1,:,iss) = f(l1:l2,m1,:,iss) - spread(reference_state(:,iref_s),2,mz) ! do i=1,nghost if (ldensity_nolog) then if (lreference_state) then ! not yet fully implemented f(l1:l2,m1-i,:,iss) =- f(l1:l2,m1+i,:,iss) + tmp & - (cp-cv)*(log((f(l1:l2,m1+i,:,irho)+spread(reference_state(:,iref_rho),2,mz))* & (f(l1:l2,m1-i,:,irho)+spread(reference_state(:,iref_rho),2,mz)))-2*lnrho0) else f(:,m1-i,:,iss) =- f(:,m1+i,:,iss) + tmp & - (cp-cv)*(log(f(:,m1+i,:,irho)*f(:,m1-i,:,irho))-2*lnrho0) endif else f(:,m1-i,:,iss) =- f(:,m1+i,:,iss) + tmp & - (cp-cv)*(f(:,m1+i,:,ilnrho)+f(:,m1-i,:,ilnrho)-2*lnrho0) endif enddo ! ! top boundary ! case ('top') if (ldebug) print*, & 'bc_ss_temp_y: set y top temperature - cs2top=',cs2top if (cs2top<=0.) print*, 'bc_ss_temp_y: cannot have cs2top<=0' ! tmp = 2*cv*log(cs2top/cs20) call getlnrho(f(:,m2,:,ilnrho),lnrho_xz) ! f(:,m2,:,iss) = 0.5*tmp - (cp-cv)*(lnrho_xz-lnrho0) if (lreference_state) & f(l1:l2,m2,:,iss) = f(l1:l2,m2,:,iss) - spread(reference_state(:,iref_s),2,mz) ! do i=1,nghost if (ldensity_nolog) then if (lreference_state) then ! not yet fully implemented f(l1:l2,m2+i,:,iss) =- f(l1:l2,m2-i,:,iss) + tmp & - (cp-cv)*(log((f(l1:l2,m2-i,:,irho)+spread(reference_state(:,iref_rho),2,mz))* & (f(l1:l2,m2+i,:,irho)+spread(reference_state(:,iref_rho),2,mz)))-2*lnrho0) else f(:,m2+i,:,iss) = -f(:,m2-i,:,iss) + tmp & - (cp-cv)*(log(f(:,m2-i,:,irho)*f(:,m2+i,:,irho))-2*lnrho0) endif else f(:,m2+i,:,iss) = -f(:,m2-i,:,iss) + tmp & - (cp-cv)*(f(:,m2-i,:,ilnrho)+f(:,m2+i,:,ilnrho)-2*lnrho0) endif enddo ! case default call fatal_error('bc_ss_temp_y','invalid argument') endselect ! 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 ! 11-oct-2016/MR: changes for use of one-sided BC formulation (chosen by setting new optional switch lone_sided) ! use General, only: loptest use Deriv, only: set_ghosts_for_onesided_ders ! real, dimension (:,:,:,:) :: f character (len=3) :: topbot logical, optional :: lone_sided ! real :: tmp integer :: i real, dimension(mx,my) :: lnrho_xy real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_temp_z') ! if (ldebug) print*,'bc_ss_temp_z: cs20,cs0=',cs20,cs0 ! ! Constant temperature/sound speed for entropy, i.e. antisymmetric ! ln(cs2) relative to cs2top/cs2bot. ! 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') if (ldebug) print*, & 'bc_ss_temp_z: set z bottom temperature: cs2bot=',cs2bot if (cs2bot<=0.) print*, & 'bc_ss_temp_z: cannot have cs2bot = ', cs2bot, ' <= 0' if (lentropy .and. .not. pretend_lnTT) then ! tmp = 2*cv*log(cs2bot/cs20) call getlnrho(f(:,:,n1,ilnrho),lnrho_xy) f(:,:,n1,iss) = 0.5*tmp - (cp-cv)*(lnrho_xy-lnrho0) ! if (lreference_state) & f(l1:l2,:,n1,iss) = f(l1:l2,:,n1,iss) - spread(reference_state(:,iref_s),2,my) ! ! Distinguish cases for linear and logarithmic density ! if (loptest(lone_sided)) then call set_ghosts_for_onesided_ders(f,topbot,iss,3,.true.) else if (ldensity_nolog) then ! do i=1,nghost f(:,:,n1-i,iss) = -f(:,:,n1+i,iss) + tmp & ! - (cp-cv)*(log(f(:,:,n1+i,irho)*f(:,:,n1-i,irho))-2*lnrho0) !AB: this could be better !MR: but is not equivalent ! Why anyway different from cases below, which set *s* antisymmtric w.r.t. boundary value? - 2*(cp-cv)*(lnrho_xy-lnrho0) enddo else do i=1,nghost f(:,:,n1-i,iss) = -f(:,:,n1+i,iss) + tmp & - (cp-cv)*(f(:,:,n1+i,ilnrho)+f(:,:,n1-i,ilnrho)-2*lnrho0) enddo endif endif ! elseif (lentropy .and. pretend_lnTT) then f(:,:,n1,iss) = log(cs2bot/gamma_m1) if (loptest(lone_sided)) then call set_ghosts_for_onesided_ders(f,topbot,iss,3,.true.) else do i=1,nghost; f(:,:,n1-i,iss)=2*f(:,:,n1,iss)-f(:,:,n1+i,iss); enddo endif elseif (ltemperature) then if (ltemperature_nolog) then f(:,:,n1,iTT) = cs2bot/gamma_m1 else f(:,:,n1,ilnTT) = log(cs2bot/gamma_m1) endif if (loptest(lone_sided)) then call set_ghosts_for_onesided_ders(f,topbot,ilnTT,3,.true.) else do i=1,nghost; f(:,:,n1-i,ilnTT)=2*f(:,:,n1,ilnTT)-f(:,:,n1+i,ilnTT); enddo endif endif ! ! top boundary ! case ('top') if (ldebug) print*, & 'bc_ss_temp_z: set z top temperature: cs2top=',cs2top if (cs2top<=0.) print*, & 'bc_ss_temp_z: cannot have cs2top = ', cs2top, ' <= 0' !DM+PC next two lines need to be looked into. !AB: This was implemented in revision: 17029 dhruba.mitra, but it works! if (lread_oldsnap) & cs2top=cs20*exp(gamma*f(l2,m2,n2,iss)/cp+gamma_m1*(f(l2,m2,n2,ilnrho)-lnrho0)) ! if (lentropy .and. .not. pretend_lnTT) then tmp = 2*cv*log(cs2top/cs20) call getlnrho(f(:,:,n2,ilnrho),lnrho_xy) f(:,:,n2,iss) = 0.5*tmp - (cp-cv)*(lnrho_xy-lnrho0) if (lreference_state) & f(l1:l2,:,n2,iss) = f(l1:l2,:,n2,iss) - spread(reference_state(:,iref_s),2,my) ! if (loptest(lone_sided)) then call set_ghosts_for_onesided_ders(f,topbot,iss,3,.true.) else ! ! Distinguish cases for linear and logarithmic density ! if (ldensity_nolog) then do i=1,nghost f(:,:,n2+i,iss) = -f(:,:,n2-i,iss) + tmp & !- (cp-cv)*(log(f(:,:,n2-i,irho)*f(:,:,n2+i,irho))-2*lnrho0) !AB: this could be better - 2*(cp-cv)*(lnrho_xy-lnrho0) enddo else do i=1,nghost f(:,:,n2+i,iss) = -f(:,:,n2-i,iss) + tmp & - (cp-cv)*(f(:,:,n2-i,ilnrho)+f(:,:,n2+i,ilnrho)-2*lnrho0) enddo endif endif elseif (lentropy .and. pretend_lnTT) then f(:,:,n2,iss) = log(cs2top/gamma_m1) if (loptest(lone_sided)) then call set_ghosts_for_onesided_ders(f,topbot,iss,3,.true.) else do i=1,nghost; f(:,:,n2+i,iss)=2*f(:,:,n2,iss)-f(:,:,n2-i,iss); enddo endif elseif (ltemperature) then if (ltemperature_nolog) then f(:,:,n2,iTT) = cs2top/gamma_m1 else f(:,:,n2,ilnTT) = log(cs2top/gamma_m1) endif if (loptest(lone_sided)) then call set_ghosts_for_onesided_ders(f,topbot,ilnTT,3,.true.) else do i=1,nghost; f(:,:,n2+i,ilnTT)=2*f(:,:,n2,ilnTT)-f(:,:,n2-i,ilnTT); enddo endif endif ! case default call fatal_error('bc_ss_temp_z','invalid argument') endselect ! endsubroutine bc_ss_temp_z !*********************************************************************** subroutine bc_lnrho_temp_z(f,topbot) ! ! boundary condition for lnrho *and* ss: constant temperature ! ! 27-sep-2002/axel: coded ! 19-aug-2005/tobi: distributed across ionization modules ! use Gravity, only: gravz ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f real :: tmp integer :: i real, dimension(mx,my) :: lnrho_xy real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_lnrho_temp_z') ! if (ldebug) print*,'bc_lnrho_temp_z: cs20,cs0=',cs20,cs0 ! ! Constant temperature/sound speed for entropy, i.e. antisymmetric ! ln(cs2) relative to cs2top/cs2bot. ! 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') if (ldebug) print*, & 'bc_lnrho_temp_z: set z bottom temperature: cs2bot=',cs2bot if (cs2bot<=0. .and. lroot) print*, & 'bc_lnrho_temp_z: cannot have cs2bot<=0' tmp = 2*cv*log(cs2bot/cs20) ! ! set boundary value for entropy, then extrapolate ghost pts by antisymmetry ! call getlnrho(f(:,:,n1,ilnrho),lnrho_xy) f(:,:,n1,iss) = 0.5*tmp - (cp-cv)*(lnrho_xy-lnrho0) if (lreference_state) & f(l1:l2,:,n1,iss) = f(l1:l2,:,n1,iss) - spread(reference_state(:,iref_s),2,my) ! do i=1,nghost; f(:,:,n1-i,iss) = 2*f(:,:,n1,iss)-f(:,:,n1+i,iss); enddo ! ! set density in the ghost zones so that dlnrho/dz + ds/dz = gz/cs2bot ! for the time being, we don't worry about lnrho0 (assuming that it is 0) ! tmp=-gravz/cs2bot do i=1,nghost f(:,:,n1-i,ilnrho)= f(:,:,n1+i,ilnrho) & + cp1*(f(:,:,n1+i,iss)-f(:,:,n1-i,iss))+dz2_bound(-i)*tmp enddo ! ! top boundary ! case ('top') if (ldebug) print*, & 'bc_lnrho_temp_z: set z top temperature: cs2top=',cs2top if (cs2top<=0. .and. lroot) print*, & 'bc_lnrho_temp_z: cannot have cs2top<=0' tmp = 2*cv*log(cs2top/cs20) ! ! set boundary value for entropy, then extrapolate ghost pts by antisymmetry ! call getlnrho(f(:,:,n2,ilnrho),lnrho_xy) f(:,:,n2,iss) = 0.5*tmp - (cp-cv)*(lnrho_xy-lnrho0) if (lreference_state) & f(l1:l2,:,n2,iss) = f(l1:l2,:,n2,iss) - spread(reference_state(:,iref_s),2,my) ! do i=1,nghost; f(:,:,n2+i,iss) = 2*f(:,:,n2,iss)-f(:,:,n2-i,iss); enddo ! ! set density in the ghost zones so that dlnrho/dz + ds/dz = gz/cs2top ! for the time being, we don't worry about lnrho0 (assuming that it is 0) ! tmp=gravz/cs2top do i=1,nghost f(:,:,n2+i,ilnrho)= f(:,:,n2-i,ilnrho) & + cp1*(f(:,:,n2-i,iss)-f(:,:,n2+i,iss))+dz2_bound(i)*tmp enddo ! case default call fatal_error('bc_lnrho_temp_z','invalid argument') endselect ! endsubroutine bc_lnrho_temp_z !*********************************************************************** subroutine bc_lnrho_pressure_z(f,topbot) ! ! boundary condition for lnrho: constant pressure ! ! 4-apr-2003/axel: coded ! 1-may-2003/axel: added the same for top boundary ! 19-aug-2005/tobi: distributed across ionization modules ! use Gravity, only: lnrho_bot,lnrho_top,ss_bot,ss_top ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f integer :: i real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_lnrho_pressure_z') ! if (ldebug) print*,'bc_lnrho_pressure_z: cs20,cs0=',cs20,cs0 ! ! Constant pressure, i.e. antisymmetric ! This assumes that the entropy is already set (ie density _must_ register ! first!) ! ! check whether we want to do top or bottom (this is processor dependent) ! select case (topbot) ! ! top boundary ! case ('top') if (ldebug) print*,'bc_lnrho_pressure_z: lnrho_top,ss_top=',lnrho_top,ss_top ! ! fix entropy if inflow (uz>0); otherwise leave s unchanged ! afterwards set s antisymmetrically about boundary value ! if (lentropy) then ! do m=m1,m2 ! do l=l1,l2 ! if (f(l,m,n1,iuz)>=0) then ! f(l,m,n1,iss)=ss_bot ! else ! f(l,m,n1,iss)=f(l,m,n1+1,iss) ! endif ! enddo ! enddo f(:,:,n2,iss)=ss_top if (lreference_state) & f(l1:l2,:,n2,iss) = f(l1:l2,:,n2,iss) - spread(reference_state(:,iref_s),2,my) ! do i=1,nghost; f(:,:,n2+i,iss)=2*f(:,:,n2,iss)-f(:,:,n2-i,iss); enddo ! ! set density value such that pressure is constant at the bottom ! f(:,:,n2,ilnrho)=lnrho_top+cp1*(ss_top-f(:,:,n2,iss)) else f(:,:,n2,ilnrho)=lnrho_top endif ! ! make density antisymmetric about boundary ! another possibility might be to enforce hydrostatics ! ie to set dlnrho/dz=-g/cs^2, assuming zero entropy gradient ! do i=1,nghost f(:,:,n2+i,ilnrho)=2*f(:,:,n2,ilnrho)-f(:,:,n2-i,ilnrho) enddo ! ! bottom boundary ! case ('bot') if (ldebug) print*,'bc_lnrho_pressure_z: lnrho_bot,ss_bot=',lnrho_bot,ss_bot ! ! fix entropy if inflow (uz>0); otherwise leave s unchanged ! afterwards set s antisymmetrically about boundary value ! if (lentropy) then ! do m=m1,m2 ! do l=l1,l2 ! if (f(l,m,n1,iuz)>=0) then ! f(l,m,n1,iss)=ss_bot ! else ! f(l,m,n1,iss)=f(l,m,n1+1,iss) ! endif ! enddo ! enddo f(:,:,n1,iss)=ss_bot if (lreference_state) & f(l1:l2,:,n1,iss) = f(l1:l2,:,n1,iss) - spread(reference_state(:,iref_s),2,my) ! do i=1,nghost; f(:,:,n1-i,iss)=2*f(:,:,n1,iss)-f(:,:,n1+i,iss); enddo ! ! set density value such that pressure is constant at the bottom ! f(:,:,n1,ilnrho)=lnrho_bot+ss_bot-f(:,:,n1,iss) else f(:,:,n1,ilnrho)=lnrho_bot endif ! ! make density antisymmetric about boundary ! another possibility might be to enforce hydrostatics ! ie to set dlnrho/dz=-g/cs^2, assuming zero entropy gradient ! do i=1,nghost f(:,:,n1-i,ilnrho)=2*f(:,:,n1,ilnrho)-f(:,:,n1+i,ilnrho) enddo ! case default call fatal_error('bc_lnrho_pressure_z','invalid argument') endselect ! 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 ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f ! real :: tmp real, dimension(mx,my) :: lnrho_xy integer :: i real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_temp2_z') ! if (ldebug) print*,'bc_ss_temp2_z: cs20,cs0=',cs20,cs0 ! ! Constant temperature/sound speed for entropy, i.e. antisymmetric ! ln(cs2) relative to cs2top/cs2bot. ! 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') if (ldebug) print*, & 'bc_ss_temp2_z: set z bottom temperature: cs2bot=',cs2bot if (cs2bot<=0.) print*, 'bc_ss_temp2_z: cannot have cs2bot<=0' ! tmp = cv*log(cs2bot/cs20) do i=0,nghost call getlnrho(f(:,:,n1-i,ilnrho),lnrho_xy) f(:,:,n1-i,iss) = tmp - (cp-cv)*(lnrho_xy-lnrho0) enddo ! ! top boundary ! case ('top') if (ldebug) print*, & 'bc_ss_temp2_z: set z top temperature: cs2top=',cs2top if (cs2top<=0.) print*,'bc_ss_temp2_z: cannot have cs2top<=0' ! tmp = cv*log(cs2top/cs20) do i=0,nghost call getlnrho(f(:,:,n2+i,ilnrho),lnrho_xy) f(:,:,n2+i,iss) = tmp - (cp-cv)*(lnrho_xy-lnrho0) enddo case default call fatal_error('bc_ss_temp2_z','invalid argument') endselect ! endsubroutine bc_ss_temp2_z !*********************************************************************** subroutine bc_ss_temp3_z(f,topbot) ! ! boundary condition for entropy: constant temperature ! ! 22-jan-2013/axel: coded to impose cs2bot and dcs2bot at bottom ! use Gravity, only: gravz ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f ! real :: tmp,dcs2bot integer :: i real, dimension(mx,my) :: lnrho_xy real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_temp3_z') ! if (ldensity.and..not.lstratz) then call get_shared_variable('mpoly',mpoly) else if (lroot) call warning('initialize_eos','mpoly not obtained from density,'// & 'set impossible') allocate(mpoly); mpoly=impossible endif ! if (ldebug) print*,'bc_ss_temp3_z: cs20,cs0=',cs20,cs0 ! ! Constant temperature/sound speed for entropy, i.e. antisymmetric ! ln(cs2) relative to cs2top/cs2bot. ! 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) ! ! Not yet adapted to reference_state ! select case (topbot) ! ! bottom boundary ! case ('bot') dcs2bot=gamma*gravz/(mpoly+1.) if (ldebug) print*, 'bc_ss_temp3_z: set cs2bot,dcs2bot=',cs2bot,dcs2bot if (cs2bot<=0.) print*, 'bc_ss_temp3_z: cannot have cs2bot<=0' ! do i=0,nghost call getlnrho(f(:,:,n1-i,ilnrho),lnrho_xy) f(:,:,n1-i,iss) = cv*log((cs2bot-0.5*dz2_bound(-i)*dcs2bot)/cs20) & -(cp-cv)*(lnrho_xy-lnrho0) enddo ! ! top boundary ! case ('top') if (ldebug) print*, 'bc_ss_temp3_z: set z top temperature: cs2top=',cs2top if (cs2top<=0.) print*,'bc_ss_temp3_z: cannot have cs2top<=0' ! tmp = cv*log(cs2top/cs20) do i=0,nghost call getlnrho(f(:,:,n2+i,ilnrho),lnrho_xy) f(:,:,n2+i,iss) = tmp - (cp-cv)*(lnrho_xy-lnrho0) enddo ! case default call fatal_error('bc_ss_temp3_z','invalid argument') endselect ! 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 ! use DensityMethods, only: getdlnrho_x ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f integer :: i real, dimension(:,:), allocatable :: rho_yz,dlnrho real, dimension(:,:), pointer :: reference_state ! if (ldebug) print*,'bc_ss_stemp_x: cs20,cs0=',cs20,cs0 ! ! Symmetric temperature/sound speed for entropy. ! This assumes that the density is already set (ie density _must_ register ! first!) ! if (lreference_state) then call get_shared_variable('reference_state',reference_state,caller='bc_ss_stemp_x') allocate(dlnrho(my,mz),rho_yz(my,mz)) endif ! ! check whether we want to do top or bottom (this is precessor dependent) ! select case (topbot) ! ! bottom boundary ! case ('bot') if (cs2bot<=0.) print*, 'bc_ss_stemp_x: cannot have cs2bot<=0' ! if (lreference_state) call getrho(f(l1,:,:,ilnrho),BOT,rho_yz) ! do i=1,nghost if (ldensity_nolog) then ! if (lreference_state) then call getdlnrho_x(f(:,:,:,ilnrho),l1,i,rho_yz,dlnrho) ! dlnrho = d_x ln(rho) f(l1-i,:,:,iss) = f(l1+i,:,:,iss) + dx2_bound(-i)*reference_state(BOT,iref_gs) & + (cp-cv)*dlnrho else f(l1-i,:,:,iss) = f(l1+i,:,:,iss) & + (cp-cv)*(log(f(l1+i,:,:,irho)/f(l1-i,:,:,irho))) endif else f(l1-i,:,:,iss) = f(l1+i,:,:,iss) & + (cp-cv)*(f(l1+i,:,:,ilnrho)-f(l1-i,:,:,ilnrho)) endif enddo ! ! top boundary ! case ('top') if (cs2top<=0.) print*, 'bc_ss_stemp_x: cannot have cs2top<=0' ! if (lreference_state) call getrho(f(l2,:,:,ilnrho),TOP,rho_yz) ! do i=1,nghost if (ldensity_nolog) then if (lreference_state) then call getdlnrho_x(f(:,:,:,ilnrho),l2,i,rho_yz,dlnrho) ! dlnrho = d_x ln(rho) f(l2+i,:,:,iss) = f(l2-i,:,:,iss) - dx2_bound(i)*reference_state(TOP,iref_gs) & - (cp-cv)*dlnrho else f(l2+i,:,:,iss) = f(l2-i,:,:,iss) & + (cp-cv)*log(f(l2-i,:,:,irho)/f(l2+i,:,:,irho)) endif else f(l2+i,:,:,iss) = f(l2-i,:,:,iss) & + (cp-cv)*(f(l2-i,:,:,ilnrho)-f(l2+i,:,:,ilnrho)) endif enddo ! case default call fatal_error('bc_ss_stemp_x','invalid argument') endselect ! 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 ! use DensityMethods, only: getdlnrho_y ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f ! integer :: i real, dimension(mx,mz) :: dlnrho real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_stemp_y') ! if (ldebug) print*,'bc_ss_stemp_y: cs20,cs0=',cs20,cs0 ! ! 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') if (cs2bot<=0.) print*, & 'bc_ss_stemp_y: cannot have cs2bot<=0' do i=1,nghost call getdlnrho_y(f(:,:,:,ilnrho),m1,i,dlnrho) ! dlnrho = d_y ln(rho) f(:,m1-i,:,iss) = f(:,m1+i,:,iss) + (cp-cv)*dlnrho enddo ! ! top boundary ! case ('top') if (cs2top<=0.) print*, & 'bc_ss_stemp_y: cannot have cs2top<=0' do i=1,nghost call getdlnrho_y(f(:,:,:,ilnrho),m2,i,dlnrho) ! dlnrho = d_y ln(rho) f(:,m2+i,:,iss) = f(:,m2-i,:,iss) - (cp-cv)*dlnrho enddo ! case default call fatal_error('bc_ss_stemp_y','invalid argument') endselect ! endsubroutine bc_ss_stemp_y !*********************************************************************** subroutine bc_ss_stemp_z(f,topbot) ! ! boundary condition for entropy: symmetric temperature ! ! 3-aug-2002/wolf: coded ! 26-aug-2003/tony: distributed across ionization modules ! use DensityMethods, only: getdlnrho_z ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f integer :: i real, dimension(mx,my) :: dlnrho real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_stemp_z') ! if (ldebug) print*,'bc_ss_stemp_z: cs20,cs0=',cs20,cs0 ! ! 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') if (cs2bot<=0.) print*, 'bc_ss_stemp_z: cannot have cs2bot<=0' do i=1,nghost call getdlnrho_z(f(:,:,:,ilnrho),n1,i,dlnrho) ! dlnrho = d_z ln(rho) f(:,:,n1-i,iss) = f(:,:,n1+i,iss) + (cp-cv)*dlnrho enddo ! ! top boundary ! case ('top') if (cs2top<=0.) print*, 'bc_ss_stemp_z: cannot have cs2top<=0' do i=1,nghost call getdlnrho_z(f(:,:,:,ilnrho),n2,i,dlnrho) ! dlnrho = d_z ln(rho) f(:,:,n2+i,iss) = f(:,:,n2-i,iss) - (cp-cv)*dlnrho enddo case default call fatal_error('bc_ss_stemp_z','invalid argument') endselect ! endsubroutine bc_ss_stemp_z !*********************************************************************** subroutine bc_ss_a2stemp_x(f,topbot) ! ! Boundary condition for entropy: adopt boundary value for temperature in ! the ghost zone to handle shock profiles in interstellar with steep +ve ! 1st derivative in cooled remnant shells, followed by steep -ve 1st ! derivative inside remnant. ! s or a2 for temperature both unstable and unphysical as the unshocked ! exterior ISM will be comparatively homogeneous, hence allowing the ghost ! zone to fluctuate matching the boundary values is a reasonable approx ! of the physical flow, whilst avoiding unphysical spikes to wreck the ! calculation. ! ! 25-2010/fred: adapted from bc_ss_stemp_z ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f integer :: i real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_a2stemp_x') ! if (ldebug) print*,'bc_ss_a2stemp_z: cs20,cs0=',cs20,cs0 ! ! Uniform temperature/sound speed condition 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 precessor dependent) ! select case (topbot) ! ! bottom boundary ! case ('bot') if (cs2bot<=0.) print*, & 'bc_ss_a2stemp_x: cannot have cs2bot<=0' do i=1,nghost f(l1-i,:,:,iss) = f(l1+1-i,:,:,iss)+(cp-cv)* & (f(l1+1-i,:,:,ilnrho)-f(l1-i,:,:,ilnrho)) enddo ! ! top boundary ! case ('top') if (cs2top<=0.) print*, & 'bc_ss_a2stemp_x: cannot have cs2top<=0' do i=1,nghost f(l2+i,:,:,iss) = f(l2-1+i,:,:,iss)+(cp-cv)* & (f(l2-1+i,:,:,ilnrho)-f(l2+i,:,:,ilnrho)) enddo ! case default call fatal_error('bc_ss_a2stemp_x','invalid argument') endselect ! endsubroutine bc_ss_a2stemp_x !*********************************************************************** subroutine bc_ss_a2stemp_y(f,topbot) ! ! Boundary condition for entropy: adopt boundary value for temperature in ! the ghost zone to handle shock profiles in interstellar with steep +ve ! 1st derivative in cooled remnant shells, followed by steep -ve 1st ! derivative inside remnant. ! s or a2 for temperature both unstable and unphysical as the unshocked ! exterior ISM will be comparatively homogeneous, hence allowing the ghost ! zone to fluctuate matching the boundary values is a reasonable approx ! of the physical flow, whilst avoiding unphysical spikes to wreck the ! calculation. ! ! 25-2010/fred: adapted from bc_ss_stemp_z ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f integer :: i real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_a2stemp_y') ! if (ldebug) print*,'bc_ss_a2stemp_z: cs20,cs0=',cs20,cs0 ! ! Uniform temperature/sound speed condition 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 precessor dependent) ! select case (topbot) ! ! bottom boundary ! case ('bot') if (cs2bot<=0.) print*, & 'bc_ss_a2stemp_y: cannot have cs2bot<=0' do i=1,nghost f(:,m1-i,:,iss) = f(:,m1+1-i,:,iss)+(cp-cv)* & (f(:,m1+1-i,:,ilnrho)-f(:,m1-i,:,ilnrho)) enddo ! ! top boundary ! case ('top') if (cs2top<=0.) print*, & 'bc_ss_a2stemp_y: cannot have cs2top<=0' do i=1,nghost f(:,m2+i,:,iss) = f(:,m2-1+i,:,iss)+(cp-cv)* & (f(:,m2-1+i,:,ilnrho)-f(:,m2+i,:,ilnrho)) enddo ! case default call fatal_error('bc_ss_a2stemp_y','invalid argument') endselect ! endsubroutine bc_ss_a2stemp_y !*********************************************************************** subroutine bc_ss_a2stemp_z(f,topbot) ! ! Boundary condition for entropy: adopt boundary value for temperature in ! the ghost zone to handle shock profiles in interstellar with steep +ve ! 1st derivative in cooled remnant shells, followed by steep -ve 1st ! derivative inside remnant. ! s or a2 for temperature both unstable and unphysical as the unshocked ! exterior ISM will be comparatively homogeneous, hence allowing the ghost ! zone to fluctuate matching the boundary values is a reasonable approx ! of the physical flow, whilst avoiding unphysical spikes to wreck the ! calculation. ! ! 25-2010/fred: adapted from bc_ss_stemp_z ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f integer :: i real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_ss_a2stemp_z') ! if (ldebug) print*,'bc_ss_a2stemp_z: cs20,cs0=',cs20,cs0 ! ! Uniform temperature/sound speed condition 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') if (cs2bot<=0.) print*, & 'bc_ss_a2stemp_z: cannot have cs2bot<=0' do i=1,nghost f(:,:,n1-i,iss) = f(:,:,n1+1-i,iss) + (cp-cv)* & (f(:,:,n1+1-i,ilnrho)-f(:,:,n1-i,ilnrho)) enddo ! ! top boundary ! case ('top') if (cs2top<=0.) print*, & 'bc_ss_a2stemp_z: cannot have cs2top<=0' do i=1,nghost f(:,:,n2+i,iss) = f(:,:,n2-1+i,iss) + (cp-cv)* & (f(:,:,n2-1+i,ilnrho)-f(:,:,n2+i,ilnrho)) enddo case default call fatal_error('bc_ss_a2stemp_z','invalid argument') endselect ! 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 ! ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f real, dimension (size(f,1),size(f,2)) :: cs2_2d integer :: i ! ! 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!) ! select case (topbot) ! ! Bottom boundary ! case ('bot') ! Set cs2 (temperature) in the ghost points to the value on ! the boundary ! cs2_2d=cs20*exp(gamma_m1*f(:,:,n1,ilnrho)+cv1*f(:,:,n1,iss)) do i=1,nghost f(:,:,n1-i,iss)=cv*(-gamma_m1*f(:,:,n1-i,ilnrho)-log(cs20)& +log(cs2_2d)) enddo ! ! Top boundary ! case ('top') ! Set cs2 (temperature) in the ghost points to the value on ! the boundary ! cs2_2d=cs20*exp(gamma_m1*f(:,:,n2,ilnrho)+cv1*f(:,:,n2,iss)) do i=1,nghost f(:,:,n2+i,iss)=cv*(-gamma_m1*f(:,:,n2+i,ilnrho)-log(cs20)& +log(cs2_2d)) enddo case default call fatal_error('bc_ss_energy','invalid argument') endselect ! endsubroutine bc_ss_energy !*********************************************************************** subroutine bc_stellar_surface(f,topbot) ! use Mpicomm, only: stop_it ! character (len=3) :: topbot real, dimension (:,:,:,:) :: f ! call stop_it("bc_stellar_surface: NOT IMPLEMENTED IN EOS_IDEALGAS") call keep_compiler_quiet(f) call keep_compiler_quiet(topbot) ! endsubroutine bc_stellar_surface !*********************************************************************** subroutine bc_lnrho_cfb_r_iso(f,topbot) ! ! Boundary condition for radial centrifugal balance ! ! This sets ! \partial_{r} \ln\rho ! such that ! (\partial_{r} p)/\rho = cs^2 \partial_{r} \ln\rho} = uphi**2/rad - \partial_{r} Phi ! where Phi is the gravitational potential ! ! i.e. it enforces centrifugal balance at the boundary. ! ! As it is, works only for isobaric, isothermal and cylindrical coordinates ! ! 21-aug-2006/wlad: coded ! use Gravity, only: potential use Sub, only: div ! real, dimension (:,:,:,:), intent (inout) :: f character (len=3), intent (in) :: topbot real, dimension (size(f,2),size(f,3)) :: cs2,gravterm,centterm,uphi,rho real :: potp,potm,rad,step integer :: i real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_lnrho_cfb_r_iso') ! select case (topbot) ! ! Bottom boundary ! case ('bot') ! if (ldensity_nolog) call getrho(f(l1,:,:,irho),BOT,rho) ! do i=1,nghost ! cs2 = cs20 call potential(R=x(l1-i),pot=potm) call potential(R=x(l1+i),pot=potp) ! gravterm= -(potm-potp)/cs2 ! step=-dx2_bound(-i) rad=x(l1-i) uphi=f(l1-i,:,:,iuy) ! centterm= uphi**2 * step/(rad*cs2) !??? if (ldensity_nolog) then f(l1-i,:,:,irho) = f(l1+i,:,:,irho) + rho*(gravterm + centterm) if (lreference_state) & f(l1-i,:,:,irho)= f(l1-i,:,:,irho) & + dx2_bound(-i)*reference_state(BOT,iref_grho) else f(l1-i,:,:,ilnrho)=f(l1+i,:,:,ilnrho) + gravterm + centterm endif ! !print*,'potentials',potm,potp,-(potm-potp) !print*,'centrifugal',f(l1-i,mpoint,npoint,iuy)**2 *step/rad !stop ! enddo ! ! Top boundary ! case ('top') ! if (ldensity_nolog) call getrho(f(l2,:,:,irho),TOP,rho) ! do i=1,nghost ! cs2 = cs20 call potential(R=x(l2+i),pot=potp) call potential(R=x(l2-i),pot=potm) ! gravterm= -(potp-potm)/cs2 ! step=dx2_bound(i) rad=x(l2+i) uphi=f(l2+i,:,:,iuy) ! centterm= uphi**2 * step/(rad*cs2) if (ldensity_nolog) then ! f(l2+i,:,:,irho) = f(l2-i,:,:,irho) + rho*(gravterm + centterm) if (lreference_state) & f(l2+i,:,:,irho)= f(l2+i,:,:,irho) & - dx2_bound(i)*reference_state(TOP,iref_grho) else f(l2+i,:,:,ilnrho) = f(l2-i,:,:,ilnrho) + gravterm + centterm endif ! !if (i==nghost) then ! print*,'potentials',potp,potm,-potp+potm,-(potp-potm) ! print*,'centrifugal',f(l2+i,mpoint,npoint,iuy)**2 *step/rad ! stop !endif enddo ! case default ! endselect ! endsubroutine bc_lnrho_cfb_r_iso !*********************************************************************** subroutine bc_lnrho_hds_z_iso(f,topbot) ! ! Boundary condition for density *and* entropy. ! ! This sets ! \partial_{z} \ln\rho ! such that ! \partial_{z} p = \rho g_{z}, ! i.e. it enforces hydrostatic equlibrium at the boundary. ! ! Currently this is only correct if ! \partial_{z} lnT = 0 ! at the boundary. ! ! 12-Juil-2006/dintrans: coded ! use Gravity, only: potential, gravz use Sub, only: div ! real, dimension (:,:,:,:), intent (inout) :: f character (len=3), intent (in) :: topbot ! real, dimension (size(f,1),size(f,2)) :: cs2 real, dimension (l2-l1+1) :: divu real :: rho,ss,dlnrhodz, dssdz, cs2_point real :: potp,potm integer :: i real, dimension(:,:), pointer :: reference_state ! if (lreference_state) & call get_shared_variable('reference_state',reference_state,caller='bc_lnrho_hds_z_iso') ! select case (topbot) ! ! Bottom boundary ! case ('bot') ! if (lentropy) then ! ! The following might work for anelastic ! if (ldensity) then if (bcz12(iss,1)/='hs') then call fatal_error("bc_lnrho_hds_z_iso", & "This boundary condition for density is "// & "currently only correct for bcz1(iss)='hs'") endif if (bcz12(ilnrho,1)/='nil') then call fatal_error("bc_lnrho_hds_z_iso", & "To avoid a double computation, this boundary condition "// & "should be used only with bcz1(ilnrho)='nil' for density.") endif ! rho=getrho_s(f(l1,m1,n1,ilnrho),l1) ss=f(l1,m1,n1,iss) if (lreference_state) ss=ss+reference_state(BOT,iref_s) call eoscalc(irho_ss,rho,ss, cs2=cs2_point) ! dlnrhodz = gamma *gravz/cs2_point if (ldensity_nolog) dlnrhodz=dlnrhodz*rho ! now dlnrhodz = d rho/d z ! dssdz = -gamma_m1*gravz/cs2_point ! do i=1,nghost f(:,:,n1-i,ilnrho) = f(:,:,n1+i,ilnrho) - dz2_bound(-i)*dlnrhodz f(:,:,n1-i,iss ) = f(:,:,n1+i,iss ) - dz2_bound(-i)*dssdz enddo elseif (lanelastic) then if (bcz12(iss_b,1)/='hs') then call fatal_error("bc_lnrho_hds_z_iso", & "This boundary condition for density is "// & "currently only correct for bcz1(iss)='hs'") endif if (bcz12(irho_b,1)/='nil') then call fatal_error("bc_lnrho_hds_z_iso", & "To avoid a double computation, this boundary condition "// & "should be used only with bcz1(irho_b)='nil' for density.") endif call eoscalc(ipp_ss,log(f(l1,m1,n1,irho_b)),f(l1,m1,n1,iss_b), & cs2=cs2_point) ! dlnrhodz = gamma *gravz/cs2_point dssdz = gamma_m1*gravz/cs2_point ! do i=1,nghost f(:,:,n1-i,irho_b) = f(:,:,n1+i,irho_b) - dz2_bound(-i)*dlnrhodz*f(:,:,n1+1,irho_b) f(:,:,n1-i,iss_b ) = f(:,:,n1+i,iss_b ) - dz2_bound(-i)*dssdz enddo else call fatal_error("bc_lnrho_hds_z_iso", & "This boundary condition is at bottom only implemented for ldensity=T or lanelastic=T") endif ! elseif (ltemperature) then ! ! Energy equation formulated in logarithmic temperature. ! if (ltemperature_nolog) then if (bcz12(iTT,1)/='s') then call fatal_error("bc_lnrho_hds_z_iso", & "This boundary condition for density is "// & "currently only correct for bcz1(iTT)='s'") endif call eoscalc(ilnrho_TT,f(l1,m1,n1,ilnrho),f(l1,m1,n1,iTT), & cs2=cs2_point) else if (bcz12(ilnTT,1)/='s') then call fatal_error("bc_lnrho_hds_z_iso", & "This boundary condition for density is "// & "currently only correct for bcz1(ilnTT)='s'") endif call eoscalc(ilnrho_lnTT,f(l1,m1,n1,ilnrho),f(l1,m1,n1,ilnTT), & cs2=cs2_point) endif dlnrhodz = gamma *gravz/cs2_point ! do i=1,nghost f(:,:,n1-i,ilnrho) = f(:,:,n1+i,ilnrho) - dz2_bound(-i)*dlnrhodz enddo ! else ! ! Isothermal or polytropic equations of state. ! do i=1,nghost call potential(z=z(n1-i),pot=potm) call potential(z=z(n1+i),pot=potp) cs2 = cs2bot ! if (.false.) then ! Note: Since boundconds_x and boundconds_y are called first, ! this doesn't set the corners properly. However, this is ! not a problem since cross derivatives of density are never ! needed. n = n1+i do m = m1,m2 call div(f,iuu,divu) cs2(l1:l2,m) = cs2bot - f(l1:l2,m,n,ishock)*divu enddo endif ! if (ldensity_nolog) then f(:,:,n1-i,irho) = f(:,:,n1+i,irho)*exp(-(potm-potp)/cs2) else f(:,:,n1-i,ilnrho) = f(:,:,n1+i,ilnrho) - (potm-potp)/cs2 endif ! enddo ! endif ! ! Top boundary ! case ('top') ! if (lentropy) then ! if (ldensity) then ! if (bcz12(iss,2)/='hs') then call fatal_error("bc_lnrho_hds_z_iso", & "This boundary condition for density is "//& "currently only correct for bcz2(iss)='hs'") endif if (bcz12(ilnrho,2)/='nil') then call fatal_error("bc_lnrho_hds_z_iso", & "To avoid a double computation, this boundary condition "// & "should be used only with bcz2(ilnrho)='nil' for density.") endif ! rho=getrho_s(f(l2,m2,n2,ilnrho),l2) ss=f(l2,m2,n2,iss) if (lreference_state) ss=ss+reference_state(TOP,iref_s) call eoscalc(irho_ss,rho,ss,cs2=cs2_point) ! dlnrhodz = gamma *gravz/cs2_point if (ldensity_nolog) dlnrhodz=dlnrhodz*rho ! now dlnrhodz = d rho/d z ! dssdz = -gamma_m1*gravz/cs2_point ! do i=1,nghost f(:,:,n2+i,ilnrho) = f(:,:,n2-i,ilnrho) + dz2_bound(i)*dlnrhodz f(:,:,n2+i,iss ) = f(:,:,n2-i,iss ) + dz2_bound(i)*dssdz enddo else call fatal_error("bc_lnrho_hds_z_iso", & "This boundary condition is at top only implemented for ldensity=T") endif ! elseif (ltemperature) then ! ! Energy equation formulated in logarithmic temperature. ! if (ltemperature_nolog) then if (bcz12(iTT,2)/='s') then call fatal_error("bc_lnrho_hydrostatic_z", & "This boundary condition for density is "//& "currently only correct for bcz2(iTT)='s'") endif call eoscalc(ilnrho_TT,f(l2,m2,n2,ilnrho),f(l2,m2,n2,iTT), & cs2=cs2_point) else if (bcz12(ilnTT,2)/='s') then call fatal_error("bc_lnrho_hydrostatic_z", & "This boundary condition for density is "//& "currently only correct for bcz2(ilnTT)='s'") endif call eoscalc(ilnrho_lnTT,f(l2,m2,n2,ilnrho),f(l2,m2,n2,ilnTT), & cs2=cs2_point) endif dlnrhodz = gamma *gravz/cs2_point ! do i=1,nghost f(:,:,n2+i,ilnrho) = f(:,:,n2-i,ilnrho) + dz2_bound(i)*dlnrhodz enddo ! else ! ! Isothermal or polytropic equations of state. ! do i=1,nghost call potential(z=z(n2+i),pot=potp) call potential(z=z(n2-i),pot=potm) cs2 = cs2bot if (.false.) then ! Note: Since boundconds_x and boundconds_y are called first, ! this doesn't set the corners properly. However, this is ! not a problem since cross derivatives of density are never ! needed. n = n2-i do m = m1,m2 call div(f,iuu,divu) cs2(l1:l2,m) = cs2top - f(l1:l2,m,n,ishock)*divu enddo else endif if (ldensity_nolog) then f(:,:,n2+i,irho) = f(:,:,n2-i,irho)*exp(-(potp-potm)/cs2) else f(:,:,n2+i,ilnrho) = f(:,:,n2-i,ilnrho) - (potp-potm)/cs2 endif enddo ! endif ! case default ! endselect ! endsubroutine bc_lnrho_hds_z_iso !*********************************************************************** subroutine bc_lnrho_hdss_z_iso(f,topbot) ! ! Smooth out density perturbations with respect to hydrostatic ! stratification in Fourier space. ! ! Note: Since boundconds_x and boundconds_y are called first, ! this doesn't set the corners properly. However, this is ! not a problem since cross derivatives of density are never ! needed. ! ! 05-jul-07/tobi: Adapted from bc_aa_pot3 ! use Fourier, only: fourier_transform_xy_xy, fourier_transform_other, kx_fft, ky_fft use Gravity, only: potential ! real, dimension (:,:,:,:), intent (inout) :: f character (len=3), intent (in) :: topbot ! real, dimension (nx,ny) :: kx,ky,kappa,exp_fact real, dimension (nx,ny) :: tmp_re,tmp_im real :: pot integer :: i ! ! Get local wave numbers ! kx = spread(kx_fft(ipx*nx+1:ipx*nx+nx),2,ny) ky = spread(ky_fft(ipy*ny+1:ipy*ny+ny),1,nx) ! ! Calculate 1/k^2, zero mean ! if (lshear) then kappa = sqrt((kx+ky*deltay/Lx)**2+ky**2) else kappa = sqrt(kx**2 + ky**2) endif ! ! Check whether we want to do top or bottom (this is processor dependent) ! select case (topbot) ! ! Potential field condition at the bottom ! case ('bot') ! do i=1,nghost ! ! Calculate delta_z based on z(), not on dz to improve behavior for ! non-equidistant grid (still not really correct, but could be OK) ! exp_fact = exp(-kappa*(z(n1+i)-z(n1-i))) ! ! Determine potential field in ghost zones ! ! Fourier transforms of x- and y-components on the boundary call potential(z=z(n1+i),pot=pot) if (ldensity_nolog) then tmp_re = f(l1:l2,m1:m2,n1+i,irho)*exp(+pot/cs2bot) else tmp_re = f(l1:l2,m1:m2,n1+i,ilnrho) + pot/cs2bot endif tmp_im = 0.0 if (nxgrid>1 .and. nygrid>1) then call fourier_transform_xy_xy(tmp_re,tmp_im) else call fourier_transform_other(tmp_re,tmp_im) endif tmp_re = tmp_re*exp_fact tmp_im = tmp_im*exp_fact ! Transform back if (nxgrid>1 .and. nygrid>1) then call fourier_transform_xy_xy(tmp_re,tmp_im,linv=.true.) else call fourier_transform_other(tmp_re,tmp_im,linv=.true.) endif call potential(z=z(n1-i),pot=pot) if (ldensity_nolog) then f(l1:l2,m1:m2,n1-i,irho) = tmp_re*exp(-pot/cs2bot) else f(l1:l2,m1:m2,n1-i,ilnrho) = tmp_re - pot/cs2bot endif ! enddo ! ! Potential field condition at the top ! case ('top') ! do i=1,nghost ! ! Calculate delta_z based on z(), not on dz to improve behavior for ! non-equidistant grid (still not really correct, but could be OK) ! exp_fact = exp(-kappa*(z(n2+i)-z(n2-i))) ! ! Determine potential field in ghost zones ! ! Fourier transforms of x- and y-components on the boundary call potential(z=z(n2-i),pot=pot) if (ldensity_nolog) then tmp_re = f(l1:l2,m1:m2,n2-i,irho)*exp(+pot/cs2top) else tmp_re = f(l1:l2,m1:m2,n2-i,ilnrho) + pot/cs2top endif tmp_im = 0.0 if (nxgrid>1 .and. nygrid>1) then call fourier_transform_xy_xy(tmp_re,tmp_im) else call fourier_transform_other(tmp_re,tmp_im) endif tmp_re = tmp_re*exp_fact tmp_im = tmp_im*exp_fact ! Transform back if (nxgrid>1 .and. nygrid>1) then call fourier_transform_xy_xy(tmp_re,tmp_im,linv=.true.) else call fourier_transform_other(tmp_re,tmp_im,linv=.true.) endif call potential(z=z(n2+i),pot=pot) if (ldensity_nolog) then f(l1:l2,m1:m2,n2+i,irho) = tmp_re*exp(-pot/cs2top) else f(l1:l2,m1:m2,n2+i,ilnrho) = tmp_re - pot/cs2top endif ! enddo ! case default ! if (lroot) print*,"bc_lnrho_hydrostatic_z_smooth: invalid argument" ! endselect ! endsubroutine bc_lnrho_hdss_z_iso !*********************************************************************** subroutine write_thermodyn ! endsubroutine write_thermodyn !*********************************************************************** subroutine read_thermodyn(input_file) ! character (len=*), intent(in) :: input_file ! call keep_compiler_quiet(input_file) ! endsubroutine read_thermodyn !*********************************************************************** subroutine read_species(input_file) ! character (len=*) :: input_file ! call keep_compiler_quiet(input_file) ! endsubroutine read_species !*********************************************************************** subroutine find_species_index(species_name,ind_glob,ind_chem,found_specie) ! integer, intent(out) :: ind_glob integer, intent(inout) :: ind_chem character (len=*), intent(in) :: species_name logical, intent(out) :: found_specie ! call keep_compiler_quiet(ind_glob) call keep_compiler_quiet(ind_chem) call keep_compiler_quiet(species_name) call keep_compiler_quiet(found_specie) ! endsubroutine find_species_index !*********************************************************************** subroutine find_mass(element_name,MolMass) ! character (len=*), intent(in) :: element_name real, intent(out) :: MolMass ! call keep_compiler_quiet(element_name) call keep_compiler_quiet(MolMass) ! endsubroutine find_mass !*********************************************************************** subroutine get_stratz(z, rho0z, dlnrho0dz, eth0z) ! ! Get background stratification in z direction. ! ! 13-oct-14/ccyang: coded. ! real, dimension(:), intent(in) :: z real, dimension(:), intent(out), optional :: rho0z, dlnrho0dz, eth0z ! real, dimension(size(z)) :: rho, dlnrhodz logical :: info real :: h ! info = lroot .and. .not. lstratset ! gz: select case (gztype) ! ! No stratification ! case ('zero', 'none') gz rho = rho0 dlnrhodz = 0.0 ! ! Linear acceleration: -gz_coeff^2 * z ! case ('linear') gz if (gz_coeff == 0.0) call fatal_error('set_stratz', 'gz_coeff = 0') if (info) print *, 'Set z stratification: g_z = -gz_coeff^2 * z' h = cs0 / gz_coeff rho = rho0 * exp(-0.5 * (z / h)**2) dlnrhodz = -z / h**2 ! case default gz call fatal_error('set_stratz', 'unknown type of stratification; gztype = ' // trim(gztype)) ! endselect gz ! if (present(rho0z)) rho0z = rho if (present(dlnrho0dz)) dlnrho0dz = dlnrhodz ! ! Energy stratification ! if (lthermal_energy .and. present(eth0z)) eth0z = cs20 / (gamma * gamma_m1) * rho ! endsubroutine get_stratz !*********************************************************************** subroutine set_stratz ! ! Set background stratification in z direction. ! ! 13-oct-14/ccyang: coded. ! call get_stratz(z, rho0z, dlnrho0dz, eth0z) ! endsubroutine set_stratz !*********************************************************************** 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=6 integer(KIND=ikind8), dimension(n_pars) :: p_par ! call copy_addr(cs20,p_par(1)) call copy_addr(gamma,p_par(2)) call copy_addr(cv,p_par(3)) call copy_addr(cp,p_par(4)) call copy_addr(lnrho0,p_par(5)) call copy_addr(lnTT0,p_par(6)) ! endsubroutine pushpars2c !*********************************************************************** endmodule EquationOfState