diff --git a/scripts/test_analysis_ce.sh b/scripts/test_analysis_ce.sh index a149860b8..cd718ce17 100755 --- a/scripts/test_analysis_ce.sh +++ b/scripts/test_analysis_ce.sh @@ -29,6 +29,7 @@ SEP no 2 1.667 +0.6182 0.6984 0.0142 BOUND @@ -38,4 +39,5 @@ BOUND no 2 1.667 +0.6182 ENERGIES diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 0bb572586..610acb7c2 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -69,13 +69,11 @@ subroutine init_cooling(id,master,iprint,ierr) use cooling_ism, only:init_cooling_ism,abund_default use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver - use eos_stamatellos, only:read_optab,eos_file use cooling_radapprox, only:init_star,od_method use viscosity, only:irealvisc integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr - logical :: ex cooling_in_step = .true. ierr = 0 @@ -90,10 +88,6 @@ subroutine init_cooling(id,master,iprint,ierr) var='ieos',ival=ieos) if (irealvisc > 0 .and. od_method == 4) call warning('cooling',& 'Using real viscosity will affect optical depth estimate',var='irealvisc',ival=irealvisc) - inquire(file=eos_file,exist=ex) - if (.not. ex ) call fatal('cooling','file not found',var=eos_file) - if (ieos == 2) call read_optab(eos_file,ierr) - if (ierr > 0) call fatal('cooling','Failed to read EOS file',var='ierr',ival=ierr) call init_star() case(6) call init_cooling_KI02(ierr) @@ -132,7 +126,7 @@ end subroutine init_cooling ! !----------------------------------------------------------------------- -subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,abund_in,ipart) +subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,abund_in,duhydro,ipart) use io, only:fatal use dim, only:nabundances use eos, only:gmw,gamma,ieos,get_temperature_from_u @@ -143,12 +137,12 @@ subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2 use cooling_solver, only:energ_cooling_solver use cooling_koyamainutsuka, only:cooling_KoyamaInutsuka_explicit,& cooling_KoyamaInutsuka_implicit - use cooling_radapprox, only:radcool_update_energ + use cooling_radapprox, only:radcool_update_du real(kind=4), intent(in) :: divv ! in code units real, intent(in) :: xi,yi,zi,ui,rho,dt ! in code units real, intent(in), optional :: Tdust_in,mu_in,gamma_in,K2_in,kappa_in ! in cgs - real, intent(in), optional :: abund_in(nabn) + real, intent(in), optional :: abund_in(nabn),duhydro integer,intent(in),optional:: ipart real, intent(out) :: dudt ! in code units real :: mui,gammai,Tgas,Tdust,K2,kappa @@ -187,7 +181,7 @@ subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2 case (7) call cooling_Gammie_PL_explicit(xi,yi,zi,ui,dudt) case (9) - call radcool_update_energ(ipart,xi,yi,zi,rho,ui,Tfloor,dt,dudt) + call radcool_update_du(ipart,xi,yi,zi,rho,ui,duhydro,Tfloor) case default call energ_cooling_solver(ui,dudt,rho,dt,mui,gammai,Tdust,K2,kappa) end select diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 0e83f7f81..3b7bc7701 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -25,8 +25,8 @@ module cooling_radapprox integer :: isink_star ! index of sink to use as illuminating star integer :: od_method = 4 ! default = Modified Lombardi method (Young et al. 2024) integer :: fld_opt = 1 ! by default FLD is switched on - public :: radcool_update_energ,write_options_cooling_radapprox,read_options_cooling_radapprox - public :: init_star, radcool_update_energ_loop + public :: radcool_update_du,write_options_cooling_radapprox,read_options_cooling_radapprox + public :: init_star,radcool_evolve_ui contains @@ -59,22 +59,66 @@ subroutine init_star() "at (xyz)",xyzmh_ptmass(1:3,isink_star)!"as illuminating star." end subroutine init_star +subroutine radcool_evolve_ui(ui,dt,i,Tfloor,h,uout) + use eos_stamatellos, only:ttherm_store,ueqi_store,getintenerg_opdep + use io, only:warning + use units, only:unit_density,unit_ergg + use part, only:rhoh,massoftype,igas + real, intent(inout) :: ui + real, intent(in) :: dt,Tfloor,h + integer,intent(in) :: i + real,optional,intent(out) :: uout + real :: tthermi,ueqi,utemp,ufloor_cgs,rhoi_cgs + real :: expdtonttherm + + tthermi = ttherm_store(i) + ueqi = ueqi_store(i) + utemp = ui + rhoi_cgs = rhoh(h,massoftype(igas))*unit_density + call getintenerg_opdep(Tfloor**(1.0/4.0),rhoi_cgs,ufloor_cgs) + + if (tthermi > epsilon(tthermi) .and. ui /= ueqi) then + if (dt > 0d0) then + ! evolve energy + expdtonttherm = exp(-dt/tthermi) + utemp = ui*expdtonttherm + ueqi*(1.d0-expdtonttherm) + elseif (dt < 0d0) then + ! i.e. for the backwards step in the leapfrog integrator + expdtonttherm = exp(dt/tthermi) + utemp = (ui - ueqi*(1-expdtonttherm))/expdtonttherm + endif + + ! if tthermi ==0 or dt/thermi is neglible then ui doesn't change + if (isnan(utemp) .or. utemp < epsilon(utemp)) then + utemp = ui + endif + endif + if (utemp < ufloor_cgs/unit_ergg) utemp = ufloor_cgs/unit_ergg + if (utemp < 0d0) print *, "ERROR! i=",i, ui,ueqi + + if (present(uout)) then + uout = utemp + else + ui = utemp + endif + +end subroutine radcool_evolve_ui + ! ! Do cooling calculation ! ! update energy to return evolved energy array. Called from substep -subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) +subroutine radcool_update_du(i,xi,yi,zi,rhoi,ui,duhydro,Tfloor) use io, only:warning use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh,piontwo,rpiontwo use units, only:umass,udist,unit_density,unit_ergg,utime,unit_pressure use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool,& - duFLD,doFLD,ttherm_store,teqi_store,opac_store,duSPH - use part, only:xyzmh_ptmass,igas + duFLD,doFLD,ttherm_store,ueqi_store,opac_store + use part, only:xyzmh_ptmass,igas,eos_vars,iTemp integer,intent(in) :: i - real,intent(in) :: xi,yi,zi,rhoi,Tfloor - real,intent(in) :: ui,dt - real,intent(out)::dudti_cool + real,intent(in) :: xi,yi,zi,rhoi + real,intent(in) :: ui,duhydro,Tfloor real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot real :: cs2,Om2,Hmod2,rhoi_cgs,ui_cgs @@ -103,6 +147,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) rhoi_cgs = rhoi*unit_density call getopac_opdep(ui_cgs,rhoi_cgs,kappaBari,kappaParti,& Ti,gmwi) + eos_vars(iTemp,i) = Ti ! save temperature presi = kb_on_mh*rhoi*unit_density*Ti/gmwi ! cgs presi = presi/unit_pressure !code units @@ -156,39 +201,25 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) dudti_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opaci/unit_ergg*utime! code units if (doFLD) then - du_tot = duSPH(i) + du_FLDi + du_tot = duhydro + du_FLDi else - du_tot = duSPH(i) - endif - - ! If radiative cooling is negligible compared to hydrodynamical heating - ! don't use this method to update energy, just use hydro du/dt. Does it conserve u alright? - - if (abs(du_tot) > epsilon(du_tot) .and. abs(dudti_rad/du_tot) < dtcool_crit) then - ! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& - ! dusph(i) - dudti_cool = du_tot - if ( (dudti_cool*dt + ui) < umini) then - dudti_cool = (umini - ui)/dt - endif - return + du_tot = duhydro endif Teqi = du_tot * opaci*unit_ergg/utime ! physical units Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini4 du_tot = du_tot + dudti_rad + !Check if we need to use the temperature floor if (Teqi < Tmini4) then Teqi = Tmini4**(1.0/4.0) else Teqi = Teqi**(1.0/4.0) endif - teqi_store(i) = Teqi if (Teqi > 9e5) then - print *,"i=",i, "duSPH(i)=", duSPH(i), "duradi=", dudti_rad, "Ti=", Ti, & - "Tmini=", Tmini4**(1.0/4.0),du_tot,Hcomb, "r=",sqrt(ri2), "ui=", ui, & - "dudt_sph * dti=", dusph(i)*dt + print *,"i=",i, "duhydro=", duhydro, "duradi=", dudti_rad, "Ti=", Ti, & + "Tmini=", Tmini4**(1.0/4.0),du_tot,Hcomb, "r=",sqrt(ri2), "ui=", ui elseif (Teqi < epsilon(Teqi)) then print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& "Ti=", Ti, "poti=",poti, "rhoi=", rhoi @@ -200,7 +231,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) rhoi_cgs = rhoi*unit_density call getintenerg_opdep(Teqi,rhoi_cgs,ueqi) ueqi = ueqi/unit_ergg - + ueqi_store(i) = ueqi ! calculate thermalization timescale if ((du_tot) == 0.d0) then tthermi = 0d0 @@ -210,220 +241,19 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) ttherm_store(i) = tthermi - ! evolve energy - if (tthermi == 0d0) then - dudti_cool = 0d0 ! condition if denominator above is zero - elseif ( (dt/tthermi) < TINY(ui) ) then - dudti_cool = 0d0 - else - dudti_cool = ( ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) - ui) / dt !code units - endif - if (isnan(dudti_cool)) then + if (isnan(tthermi) .or. isnan(ueqi)) then ! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti print *, "rhoi=",rhoi*unit_density, "Ti=", Ti, "Teqi=", Teqi print *, "Tmini=",Tmini4**(1.0/4.0), "ri=", ri2**(0.5) - print *, "opaci=",opaci,"coldensi=",coldensi,"dusph(i)",duSPH(i) - print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini + print *, "opaci=",opaci,"coldensi=",coldensi,"duhydro",duhydro + print *, "tthermi=", tthermi,"umini=", umini print *, "dudti_rad=", dudti_rad ,"dudt_fld=",du_fldi,"ueqi=",ueqi,"ui=",ui call warning("In Stamatellos cooling","energ=NaN or 0. ui=",val=ui) stop endif -end subroutine radcool_update_energ - - -! -! Do cooling calculation -! -! update energy to return evolved energy array. Called from evolve.F90 -subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) - use io, only:warning - use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh,piontwo,rpiontwo - use units, only:umass,udist,unit_density,unit_ergg,utime,unit_pressure - use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool,& - duFLD,doFLD,ttherm_store,teqi_store,opac_store - use part, only:xyzmh_ptmass,rhoh,massoftype,igas,iactive,isdead_or_accreted - use part, only:iphase,maxphase,maxp,iamtype,ibin - use timestep_ind, only:get_dt - integer,intent(in) :: npart - real,intent(in) :: xyzh(:,:),dtsph,Tfloor - real,intent(inout) :: energ(:),dudt_sph(:) - real :: ui,rhoi,coldensi,kappaBari,kappaParti,ri2,dti - real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot - real :: cs2,Om2,Hmod2,ui_cgs,rhoi_cgs - real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi - integer :: i,ratefile,n_uevo - - coldensi = huge(coldensi) -! write (temp,'(E5.2)') dt - print *, "radcool min/maxGpot", minval(Gpot_cool),maxval(Gpot_cool) - print *, "radcool min/max", minval(gradP_cool),maxval(gradP_cool) - n_uevo = 0 - !$omp parallel do default(none) schedule(runtime) & - !$omp shared(npart,duFLD,xyzh,energ,massoftype,xyzmh_ptmass,unit_density,Gpot_cool) & - !$omp shared(isink_star,doFLD,ttherm_store,teqi_store,od_method,unit_pressure,ratefile) & - !$omp shared(opac_store,Tfloor,dtsph,dudt_sph,utime,udist,umass,unit_ergg,gradP_cool,Lstar) & - !$omp private(i,poti,du_FLDi,ui,rhoi,ri2,coldensi,kappaBari,Ti,iphase) & - !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot,ui_cgs) & - !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,dti,rhoi_cgs) & - !$omp shared(maxp,maxphase,ibin) reduction(+:n_uevo) - - overpart: do i=1,npart - if (maxphase==maxp) then - if (iamtype(iphase(i)) /= igas) cycle - if (isdead_or_accreted(xyzh(4,i))) cycle - if (.not. iactive(iphase(i)) ) then - n_uevo = n_uevo + 1 - cycle - endif - endif - - dti = get_dt(dtsph,ibin(i)) - poti = Gpot_cool(i) - du_FLDi = duFLD(i) - ui = energ(i) - if (abs(ui) < epsilon(ui)) print *, "ui zero", i - rhoi = rhoh(xyzh(4,i),massoftype(igas)) - - if (isink_star > 0) then - ri2 = (xyzh(1,i)-xyzmh_ptmass(1,isink_star))**2d0 & - + (xyzh(2,i)-xyzmh_ptmass(2,isink_star))**2d0 & - + (xyzh(3,i)-xyzmh_ptmass(3,isink_star))**2d0 - else - ri2 = xyzh(1,i)**2d0 + xyzh(2,i)**2d0 + xyzh(3,i)**2d0 - endif - - ! get opacities & Ti for ui - ui_cgs = ui*unit_ergg - rhoi_cgs = rhoi*unit_density - call getopac_opdep(ui_cgs,rhoi_cgs,kappaBari,kappaParti,& - Ti,gmwi) - presi = kb_on_mh*rhoi*unit_density*Ti/gmwi ! cgs - presi = presi/unit_pressure !code units - - select case (od_method) - case (1) - ! Stamatellos+ 2007 method - coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) ! G cancels out as G=1 in code - coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 - coldensi = coldensi*umass/udist/udist ! physical units - case (2) - ! Lombardi+ 2015 method of estimating the mean column density - coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) - coldensi = coldensi *umass/udist/udist ! physical units - case (3) - ! Combined method - HStam = sqrt(abs(poti*rhoi)/4.0d0/pi)*0.368d0/rhoi - HLom = 1.014d0*presi/abs(gradP_cool(i))/rhoi - Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/HStam)**2.0d0) - coldensi = Hcomb*rhoi - coldensi = coldensi*umass/udist/udist ! physical units - case (4) - ! Modified Lombardi method - HLom = presi/abs(gradP_cool(i))/rhoi - cs2 = presi/rhoi - if (isink_star > 0 .and. ri2 > 0d0) then - Om2 = xyzmh_ptmass(4,isink_star)/(ri2**(1.5)) !NB we are using spherical radius here - else - Om2 = 0d0 - endif - Hmod2 = cs2 * piontwo / (Om2 + 8d0*rpiontwo*rhoi) - Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/Hmod2)) - coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units - case default - print *, "no case!" - stop - end select - -! Tfloor is from input parameters and is background heating -! Stellar heating - if (isink_star > 0 .and. Lstar > 0.d0) then - Tmini4 = Tfloor**4d0 + exp(-coldensi*kappaBari)*(Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) - else - Tmini4 = Tfloor**4d0 - endif - - opaci = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units - opac_store(i) = opaci - dudti_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opaci/unit_ergg*utime! code units - - if (doFLD) then - du_tot = dudt_sph(i) + du_FLDi - else - du_tot = dudt_sph(i) - endif - !If radiative cooling is negligible compared to hydrodynamical heating - ! don't use this method to update energy, just use hydro du/dt - if (abs(dudti_rad/du_tot) < dtcool_crit) then - ! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& - ! dudt_sph(i) - energ(i) = ui + du_tot*dti - cycle - endif - - Teqi = du_tot * opaci*unit_ergg/utime ! physical units - du_tot = du_tot + dudti_rad - Teqi = Teqi/4.d0/steboltz - Teqi = Teqi + Tmini4 - if (Teqi < Tmini4) then - Teqi = Tmini4**(1.0/4.0) - else - Teqi = Teqi**(1.0/4.0) - endif - teqi_store(i) = Teqi - - if (Teqi > 9e5) then - print *,"i=",i, "dudt_sph(i)=", dudt_sph(i), "duradi=", dudti_rad, "Ti=", Ti, & - "Tmini=", Tmini4**(1.0/4.0),du_tot,Hcomb, "r=",sqrt(ri2), "ui=", ui, & - "dudt_sph * dti=", dudt_sph(i)*dti - elseif (Teqi < epsilon(Teqi)) then - print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& - "Ti=", Ti, "poti=",poti, "rhoi=", rhoi - endif - - rhoi_cgs = rhoi*unit_density - call getintenerg_opdep(Teqi,rhoi_cgs,ueqi) - ueqi = ueqi/unit_ergg - - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi_cgs,umini) - umini = umini/unit_ergg - - ! calculate thermalization timescale - if ((du_tot) == 0.d0) then - tthermi = 0d0 - else - tthermi = abs((ueqi - ui)/(du_tot)) - endif - - ttherm_store(i) = tthermi - - ! evolve energy - if (tthermi == 0d0) then - energ(i) = ui ! condition if denominator above is zero - elseif ( (dti/tthermi) < TINY(ui) ) then - energ(i) = ui - else - energ(i) = ui*exp(-dti/tthermi) + ueqi*(1.d0-exp(-dti/tthermi)) !code units - endif - - if (isnan(energ(i)) .or. energ(i) < epsilon(ui)) then - ! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "rhoi=",rhoi*unit_density, "Ti=", Ti, "Teqi=", Teqi - print *, "Tmini=",Tmini4**(1.0/4.0), "ri=", ri2**(0.5) - print *, "opaci=",opaci,"coldensi=",coldensi,"dudt_sphi",dudt_sph(i) - print *, "dt=",dti,"tthermi=", tthermi,"umini=", umini - print *, "dudti_rad=", dudti_rad ,"dudt_fld=",du_fldi,"ueqi=",ueqi,"ui=",ui - call warning("In Stamatellos cooling","energ=NaN or 0. ui",val=ui) - stop - endif - - enddo overpart - !$omp end parallel do - - print *, "radcool min/max u():", minval(energ(1:npart)), maxval(energ(1:npart)) - print *, "radcool min/max Teqi():", minval(Teqi_store(1:npart)), maxval(Teqi_store(1:npart)) -end subroutine radcool_update_energ_loop +end subroutine radcool_update_du subroutine write_options_cooling_radapprox(iunit) diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 771e28de4..64134425d 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -353,7 +353,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad,apr_level) if (icooling==9 .and. doFLD .and. icall==1) then - call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) endif if (do_export) then @@ -389,7 +389,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad,apr_level) if (icooling==9 .and. doFLD) then - call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) endif if (do_export) then @@ -462,7 +462,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad,apr_level) if (icooling==9 .and. doFLD) then - call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) endif remote_export = .false. @@ -523,10 +523,9 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol enddo call reserve_stack(stack_redo,cell%waiting_index) call send_cell(cell,remote_export,irequestsend,xsendbuf,cell_counters,mpitype) ! send the cell to remote - call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad,apr_level) if (icooling==9 .and. doFLD) then - call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) endif call write_cell(stack_redo,cell) @@ -1293,7 +1292,6 @@ pure subroutine compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu, cell%nneightry = nneigh cell%nneigh(i) = nneighi - enddo over_parts end subroutine compute_cell @@ -1708,7 +1706,7 @@ subroutine store_results(icall,cell,getdv,getdb,realviscosity,stressmax,xyzh,& end subroutine store_results -subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda,urad_FLD) +subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,vxyzu,iphase,gradh,lambda,urad_FLD) use io, only:error use dim, only:maxp use kernel,only:get_kernel,wab0 @@ -1725,7 +1723,6 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra integer, intent(in) :: listneigh(:) integer, intent(in) :: nneigh real, intent(in) :: xyzh(:,:) - real, intent(in) :: xyzcache(:,:) real, intent(in) :: vxyzu(:,:) integer(kind=1), intent(in) :: iphase(:) real(kind=4), intent(in) :: gradh(:,:) diff --git a/src/main/eos.f90 b/src/main/eos.f90 index 8c0af1ce8..a058d34cb 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -635,6 +635,7 @@ subroutine get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi,spsoundi,gammai, endif if (maxvxyzu==4) then + if (vxyzui(4) < 0d0) print *, "ui NEGATIVE in eos" if (use_gamma) then call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,vxyzui(4),& gamma_local=gammai,mu_local=mu,Xlocal=X,Zlocal=Z) @@ -868,7 +869,7 @@ end subroutine calc_rec_ene !+ !----------------------------------------------------------------------- subroutine calc_temp_and_ene(eos_type,rho,pres,ene,temp,ierr,guesseint,mu_local,X_local,Z_local) - use physcon, only:kb_on_mh + use physcon, only:Rg use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_enfromtemp use eos_mesa, only:get_eos_eT_from_rhop_mesa use eos_gasradrec, only:calc_uT_from_rhoP_gasradrec @@ -889,7 +890,7 @@ subroutine calc_temp_and_ene(eos_type,rho,pres,ene,temp,ierr,guesseint,mu_local, if (present(Z_local)) Z = Z_local select case(eos_type) case(2,5,17) ! Ideal gas - temp = pres / (rho * kb_on_mh) * mu + temp = pres / (rho * Rg) * mu ene = pres / ( (gamma-1.) * rho) case(12) ! Ideal gas + radiation call get_idealgasplusrad_tempfrompres(pres,rho,mu,temp) @@ -917,7 +918,7 @@ end subroutine calc_temp_and_ene !+ !----------------------------------------------------------------------- subroutine calc_rho_from_PT(eos_type,pres,temp,rho,ierr,mu_local,X_local,Z_local) - use physcon, only:kb_on_mh + use physcon, only:Rg use eos_idealplusrad, only:get_idealplusrad_rhofrompresT use eos_mesa, only:get_eos_eT_from_rhop_mesa use eos_gasradrec, only:calc_uT_from_rhoP_gasradrec @@ -938,7 +939,7 @@ subroutine calc_rho_from_PT(eos_type,pres,temp,rho,ierr,mu_local,X_local,Z_local if (present(Z_local)) Z = Z_local select case(eos_type) case(2) ! Ideal gas - rho = pres / (temp * kb_on_mh) * mu + rho = pres / (temp * Rg) * mu case(12) ! Ideal gas + radiation call get_idealplusrad_rhofrompresT(pres,temp,mu,rho) case default @@ -953,36 +954,48 @@ end subroutine calc_rho_from_PT ! up to an additive integration constant, from density and pressure. !+ !----------------------------------------------------------------------- -function entropy(rho,pres,mu_in,ientropy,eint_in,ierr) +function entropy(rho,pres,mu_in,ientropy,eint_in,ierr,T_in,Trad_in) use io, only:fatal,warning - use physcon, only:radconst,kb_on_mh + use physcon, only:radconst,kb_on_mh,Rg use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres use eos_mesa, only:get_eos_eT_from_rhop_mesa use mesa_microphysics, only:getvalue_mesa real, intent(in) :: rho,pres,mu_in - real, intent(in), optional :: eint_in + real, intent(in), optional :: eint_in,T_in,Trad_in integer, intent(in) :: ientropy integer, intent(out), optional :: ierr - real :: mu,entropy,logentropy,temp,eint + real :: mu,entropy,logentropy,temp,Trad,eint if (present(ierr)) ierr=0 mu = mu_in - select case(ientropy) - case(1) ! Include only gas entropy (up to additive constants) - temp = pres * mu / (rho * kb_on_mh) - entropy = kb_on_mh / mu * log(temp**1.5/rho) + if (present(T_in)) then ! is gas temperature specified? + temp = T_in + else + temp = pres * mu / (rho * Rg) ! used as initial guess for case 2 + endif + select case(ientropy) + case(1) ! Only include gas contribution ! check temp if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') + entropy = kb_on_mh / mu * log(temp**1.5/rho) - case(2) ! Include both gas and radiation entropy (up to additive constants) - temp = pres * mu / (rho * kb_on_mh) ! Guess for temp - call get_idealgasplusrad_tempfrompres(pres,rho,mu,temp) ! First solve for temp from rho and pres - entropy = kb_on_mh / mu * log(temp**1.5/rho) + 4.*radconst*temp**3 / (3.*rho) - + case(2) ! Include both gas and radiation contributions (up to additive constants) + if (present(T_in)) then + temp = T_in + if (present(Trad_in)) then + Trad = Trad_in + else + Trad = temp + endif + else + call get_idealgasplusrad_tempfrompres(pres,rho,mu,temp) ! First solve for temp from rho and pres + Trad = temp + endif ! check temp if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') + entropy = kb_on_mh / mu * log(temp**1.5/rho) + 4.*radconst*Trad**3 / (3.*rho) case(3) ! Get entropy from MESA tables if using MESA EoS if (ieos /= 10 .and. ieos /= 20) call fatal('eos','Using MESA tables to calculate S from rho and pres, but not using MESA EoS') @@ -1067,7 +1080,7 @@ end subroutine get_rho_from_p_s !+ !----------------------------------------------------------------------- subroutine get_p_from_rho_s(ieos,S,rho,mu,P,temp) - use physcon, only:kb_on_mh,radconst,rg,mass_proton_cgs,kboltz + use physcon, only:radconst,Rg,mass_proton_cgs,kboltz use io, only:fatal use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_pres use units, only:unit_density,unit_pressure,unit_ergg @@ -1088,7 +1101,7 @@ subroutine get_p_from_rho_s(ieos,S,rho,mu,P,temp) select case (ieos) case (2,5,17) temp = (cgsrho * exp(mu*cgss*mass_proton_cgs))**(2./3.) - cgsP = cgsrho*kb_on_mh*temp / mu + cgsP = cgsrho*Rg*temp / mu case (12) corr = huge(corr) do while (abs(corr) > eoserr .and. niter < nitermax) diff --git a/src/main/eos_idealplusrad.f90 b/src/main/eos_idealplusrad.f90 index e2a6c10aa..72ecc22db 100644 --- a/src/main/eos_idealplusrad.f90 +++ b/src/main/eos_idealplusrad.f90 @@ -24,7 +24,7 @@ module eos_idealplusrad public :: get_idealplusrad_temp,get_idealplusrad_pres,get_idealplusrad_spsoundi,& get_idealgasplusrad_tempfrompres,get_idealplusrad_enfromtemp,& - get_idealplusrad_rhofrompresT + get_idealplusrad_rhofrompresT,egas_from_rhoT,erad_from_rhoT private @@ -125,11 +125,37 @@ subroutine get_idealplusrad_enfromtemp(densi,tempi,mu,eni) real, intent(in) :: densi,tempi,mu real, intent(out) :: eni - eni = 1.5*Rg*tempi/mu + radconst*tempi**4/densi + eni = egas_from_rhoT(tempi,mu) + erad_from_rhoT(densi,tempi,mu) end subroutine get_idealplusrad_enfromtemp +!---------------------------------------------------------------- +!+ +! Calculates specific gas energy from density and temperature +!+ +!---------------------------------------------------------------- +real function egas_from_rhoT(tempi,mu) result(egasi) + real, intent(in) :: tempi,mu + + egasi = 1.5*Rg*tempi/mu + +end function egas_from_rhoT + + +!---------------------------------------------------------------- +!+ +! Calculates specific radiation energy from density and temperature +!+ +!---------------------------------------------------------------- +real function erad_from_rhoT(densi,tempi,mu) result(eradi) + real, intent(in) :: densi,tempi,mu + + eradi = radconst*tempi**4/densi + +end function erad_from_rhoT + + !---------------------------------------------------------------- !+ ! Calculates density from pressure and temperature diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 932ef9894..63da59067 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -20,7 +20,7 @@ module eos_stamatellos implicit none real,allocatable,public :: optable(:,:,:) real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_FLD(:),urad_FLD(:) !gradP_cool=gradP/rho - real,allocatable,public :: ttherm_store(:),teqi_store(:),opac_store(:),duSPH(:) + real,allocatable,public :: ttherm_store(:),ueqi_store(:),opac_store(:),duSPH(:) character(len=25), public :: eos_file= 'eos_lom.dat' !default name of tabulated EOS file logical,public :: doFLD = .True., floor_energy = .False. integer,public :: iunitst=19 @@ -32,28 +32,29 @@ module eos_stamatellos contains subroutine init_S07cool() - use part, only:npart,maxradprop + use dim, only:maxp use allocutils, only:allocate_array - print *, "Allocating cooling arrays" - call allocate_array('gradP_cool',gradP_cool,npart) - call allocate_array('Gpot_cool',Gpot_cool,npart) - call allocate_array('duFLD',duFLD,npart) - call allocate_array('lambda_fld',lambda_fld,npart) - call allocate_array('urad_FLD',urad_FLD,npart) - call allocate_array('ttherm_store',ttherm_store,npart) - call allocate_array('teqi_store',teqi_store,npart) - call allocate_array('opac_store',opac_store,npart) - call allocate_array('duSPH',duSPH,npart) + print *, "Allocating cooling arrays for maxp=",maxp + call allocate_array('gradP_cool',gradP_cool,maxp) + call allocate_array('Gpot_cool',Gpot_cool,maxp) + call allocate_array('duFLD',duFLD,maxp) + call allocate_array('lambda_fld',lambda_fld,maxp) + call allocate_array('urad_FLD',urad_FLD,maxp) + call allocate_array('ttherm_store',ttherm_store,maxp) + call allocate_array('ueqi_store',ueqi_store,maxp) + call allocate_array('opac_store',opac_store,maxp) + call allocate_array('duSPH',duSPH,maxp) + Gpot_cool(:) = 0d0 gradP_cool(:) = 0d0 urad_FLD(:) = 0d0 duFLD(:) = 0d0 - teqi_store(:) = 0d0 + ueqi_store(:) = 0d0 ttherm_store(:) = 0d0 opac_store(:) = 0d0 duSPH(:) = 0d0 - open (unit=iunitst,file='EOSinfo.dat',status='replace') + !open (unit=iunitst,file='EOSinfo.dat',status='replace') if (doFLD) then print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" else @@ -62,17 +63,17 @@ subroutine init_S07cool() end subroutine init_S07cool subroutine finish_S07cool() - deallocate(optable) + if (allocated(optable)) deallocate(optable) if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) if (allocated(duFLD)) deallocate(duFLD) if (allocated(lambda_fld)) deallocate(lambda_fld) if (allocated(urad_FLD)) deallocate(urad_FLD) if (allocated(ttherm_store)) deallocate(ttherm_store) - if (allocated(teqi_store)) deallocate(teqi_store) + if (allocated(ueqi_store)) deallocate(ueqi_store) if (allocated(opac_store)) deallocate(opac_store) if (allocated(duSPH)) deallocate(duSPH) - close(iunitst) +! close(iunitst) end subroutine finish_S07cool subroutine read_optab(eos_file,ierr) @@ -89,6 +90,7 @@ subroutine read_optab(eos_file,ierr) if (ierr > 0) return do read(10,'(A120)') junk + print *, junk if (len(trim(adjustl(junk))) == 0) cycle ! blank line if ((index(adjustl(junk),"::") == 0) .and. (index(adjustl(junk),"#") .ne. 1 )) then !ignore comment lines junk = adjustl(junk) @@ -128,6 +130,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) ! check values are in range of tables if (rhoi > OPTABLE(nx,1,1) .or. rhoi < OPTABLE(1,1,1)) then + print *, "optable rho min =", rhomin call fatal('getopac_opdep','rhoi out of range. Collapsing clump?',var='rhoi',val=rhoi) elseif (ui > OPTABLE(1,ny,3) .or. ui < OPTABLE(1,1,3)) then call fatal('getopac_opdep','ui out of range',var='ui',val=ui) diff --git a/src/main/force.F90 b/src/main/force.F90 index 452f0dd81..976009c63 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -3042,25 +3042,28 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv !fxyzu(4,i) = 0. else if (maxvxyzu >= 4) fxyzu(4,i) = fxyz4 - if (icooling == 9) duSPH(i) = fxyz4 + if (icooling == 9) then + call energ_cooling(xi,yi,zi,vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,duhydro=fxyz4,ipart=i) + dusph(i) = fxyz4 + endif endif endif if (mhd) then ! - ! sum returns d(B/rho)/dt, just what we want! + ! sum returns d(b/rho)/dt, just what we want! ! - dBevol(1,i) = fsum(idBevolxi) - dBevol(2,i) = fsum(idBevolyi) - dBevol(3,i) = fsum(idBevolzi) + dbevol(1,i) = fsum(idbevolxi) + dbevol(2,i) = fsum(idbevolyi) + dbevol(3,i) = fsum(idbevolzi) ! - ! hyperbolic/parabolic cleaning terms (dpsi/dt) from Tricco & Price (2012) + ! hyperbolic/parabolic cleaning terms (dpsi/dt) from tricco & price (2012) ! if (psidecayfac > 0.) then vcleani = overcleanfac*vwavei dtau = psidecayfac*vcleani*hi1 ! - ! we clean using the difference operator for div B + ! we clean using the difference operator for div b ! psii = xpartveci(ipsi) diff --git a/src/main/inject_rochelobe.f90 b/src/main/inject_rochelobe.f90 index 96cd13aca..ab2861afe 100644 --- a/src/main/inject_rochelobe.f90 +++ b/src/main/inject_rochelobe.f90 @@ -165,7 +165,6 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& h = hfact*sw_chi/udist !add the particle call add_or_update_particle(part_type, xyzi, vxyz, h, u, i_part, npart, npartoftype, xyzh, vxyzu) - enddo ! !-- no constraint on timestep diff --git a/src/main/inject_windtunnel.f90 b/src/main/inject_windtunnel.f90 index 62cdf2f33..07f1fa166 100644 --- a/src/main/inject_windtunnel.f90 +++ b/src/main/inject_windtunnel.f90 @@ -17,6 +17,7 @@ module inject ! - BHL_radius : *radius of the wind cylinder (in star radii)* ! - Rstar : *sphere radius (code units)* ! - handled_layers : *(integer) number of handled BHL wind layers* +! - hold_star : *1: subtract CM velocity of star particles at each timestep* ! - lattice_type : *0: cubic distribution, 1: closepacked distribution* ! - nstar : *No. of particles making up sphere* ! - pres_inf : *ambient pressure (code units)* @@ -32,10 +33,13 @@ module inject character(len=*), parameter, public :: inject_type = 'windtunnel' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject,update_injected_par + set_default_options_inject,update_injected_par,windonly ! !--runtime settings for this module ! + + logical :: windonly = .false. + ! Main parameters: model MS6 from Ruffert & Arnett (1994) real, public :: v_inf = 1. real, public :: rho_inf = 1. @@ -44,6 +48,7 @@ module inject integer, public :: nstar = 0 ! Particle-related parameters + integer, public :: hold_star = 0 integer, public :: lattice_type = 1 integer, public :: handled_layers = 4 real, public :: wind_radius = 30. @@ -53,7 +58,7 @@ module inject private real :: wind_rad,wind_x,psep,distance_between_layers,& time_between_layers,h_inf,u_inf - integer :: max_layers,max_particles,nodd,neven + integer :: max_layers,max_particles,nodd,neven,nstarpart logical :: first_run = .true. real, allocatable :: layer_even(:,:),layer_odd(:,:) @@ -77,6 +82,12 @@ subroutine init_inject(ierr) ierr = 0 + if (windonly) then + nstarpart = 0 + else + nstarpart = nstar + endif + u_inf = pres_inf / (rho_inf*(gamma-1.)) cs_inf = sqrt(gamma*pres_inf/rho_inf) mach = v_inf/cs_inf @@ -148,11 +159,11 @@ subroutine init_inject(ierr) endif h_inf = hfact*(pmass/rho_inf)**(1./3.) max_layers = int(wind_length*Rstar/distance_between_layers) - max_particles = int(max_layers*(nodd+neven)/2) + nstar + max_particles = int(max_layers*(nodd+neven)/2) + nstarpart time_between_layers = distance_between_layers/v_inf call print_summary(v_inf,cs_inf,rho_inf,pres_inf,mach,pmass,distance_between_layers,& - time_between_layers,max_layers,nstar,max_particles) + time_between_layers,max_layers,nstarpart,max_particles) if (max_particles > maxp) call fatal('windtunnel', 'maxp too small for this simulation, please increase MAXP!') @@ -217,13 +228,15 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& endif print *, np, ' particles (npart=', npart, '/', max_particles, ')' endif - call inject_or_update_particles(i_part+nstar+1, np, xyz, vxyz, h, u, .false.) + call inject_or_update_particles(i_part+nstarpart+1, np, xyz, vxyz, h, u, .false.) deallocate(xyz, vxyz, h, u) enddo irrational_number_close_to_one = 3./pi dtinject = (irrational_number_close_to_one*time_between_layers)/utime + if ((hold_star>0) .and. (.not. windonly)) call subtract_star_vcom(nstarpart,xyzh,vxyzu) + end subroutine inject_particles ! @@ -260,6 +273,39 @@ subroutine update_injected_par ! -- does not do anything and will never be used end subroutine update_injected_par +!----------------------------------------------------------------------- +!+ +! Subtracts centre-of-mass motion of star particles +! Assumes star particles have particle IDs 1 to nsphere +!+ +!----------------------------------------------------------------------- +subroutine subtract_star_vcom(nsphere,xyzh,vxyzu) + integer, intent(in) :: nsphere + real, intent(in) :: xyzh(:,:) + real, intent(inout) :: vxyzu(:,:) + real :: vstar(3) + integer :: i,nbulk + +! vstar = (/ sum(vxyzu(1,1:nsphere)), sum(vxyzu(2,1:nsphere)), sum(vxyzu(3,1:nsphere)) /) / real(nsphere) + nbulk = 0 + vstar = 0. + do i=1,nsphere + if (xyzh(1,i) < 2.*Rstar) then + vstar = vstar + vxyzu(1:3,i) + nbulk = nbulk + 1 + endif + enddo + vstar = vstar/real(nbulk) + + do i=1,nsphere + if (xyzh(1,i) < 2.*Rstar) then + vxyzu(1:3,i) = vxyzu(1:3,i) - vstar + endif +enddo + +end subroutine subtract_star_vcom + + !----------------------------------------------------------------------- !+ ! Print summary of wind properties (assumes inputs are in code units) @@ -303,9 +349,10 @@ subroutine write_options_inject(iunit) call write_inopt(pres_inf,'pres_inf','ambient pressure (code units)',iunit) call write_inopt(rho_inf,'rho_inf','ambient density (code units)',iunit) call write_inopt(Rstar,'Rstar','sphere radius (code units)',iunit) - call write_inopt(nstar,'nstar','No. of particles making up sphere',iunit) + call write_inopt(nstar,'nstar','No. of particles making up sphere',iunit) ! need to write actual no. of particles, not nstar_in call write_inopt(lattice_type,'lattice_type','0: cubic distribution, 1: closepacked distribution',iunit) call write_inopt(handled_layers,'handled_layers','(integer) number of handled BHL wind layers',iunit) + call write_inopt(hold_star,'hold_star','1: subtract CM velocity of star particles at each timestep',iunit) call write_inopt(wind_radius,'BHL_radius','radius of the wind cylinder (in star radii)',iunit) call write_inopt(wind_injection_x,'wind_injection_x','x position of the wind injection boundary (in star radii)',iunit) call write_inopt(wind_length,'wind_length','crude wind length (in star radii)',iunit) @@ -368,9 +415,12 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) read(valstring,*,iostat=ierr) wind_length ngot = ngot + 1 if (wind_length <= 0.) call fatal(label,'wind_length must be positive') + case('hold_star') + read(valstring,*,iostat=ierr) hold_star + ngot = ngot + 1 end select - igotall = (ngot >= 10) + igotall = (ngot >= 11) end subroutine read_options_inject subroutine set_default_options_inject(flag) diff --git a/src/main/ionization.f90 b/src/main/ionization.f90 index 02691af62..7141b2d2f 100644 --- a/src/main/ionization.f90 +++ b/src/main/ionization.f90 @@ -339,7 +339,7 @@ end subroutine get_erec_components ! gas particle. Inputs and outputs in code units !+ !---------------------------------------------------------------- -subroutine calc_thermal_energy(particlemass,ieos,xyzh,vxyzu,presi,tempi,ethi,radprop) +subroutine calc_thermal_energy(particlemass,ieos,xyzh,vxyzu,presi,tempi,ethi,rad) use dim, only:do_radiation use part, only:rhoh,iradxi use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_enfromtemp @@ -347,20 +347,19 @@ subroutine calc_thermal_energy(particlemass,ieos,xyzh,vxyzu,presi,tempi,ethi,rad use units, only:unit_density,unit_pressure,unit_ergg,unit_pressure integer, intent(in) :: ieos real, intent(in) :: particlemass,presi,tempi,xyzh(4),vxyzu(4) - real, intent(in), optional :: radprop(:) + real, intent(in), optional :: rad(:) real, intent(out) :: ethi - real :: hi,densi_cgs,mui + real :: densi_cgs,mui select case (ieos) case(10,20) ! calculate just gas + radiation thermal energy - hi = xyzh(4) - densi_cgs = rhoh(hi,particlemass)*unit_density + densi_cgs = rhoh(xyzh(4),particlemass)*unit_density mui = densi_cgs * Rg * tempi / (presi*unit_pressure - radconst * tempi**4 / 3.) ! Get mu from pres and temp call get_idealplusrad_enfromtemp(densi_cgs,tempi,mui,ethi) ethi = particlemass * ethi / unit_ergg case default ! assuming internal energy = thermal energy ethi = particlemass * vxyzu(4) - if (do_radiation) ethi = ethi + particlemass*radprop(iradxi) + if (do_radiation) ethi = ethi + particlemass*rad(iradxi) end select end subroutine calc_thermal_energy @@ -420,9 +419,9 @@ subroutine ionisation_fraction(dens,temp,X,Y,xh0,xh1,xhe0,xhe1,xhe2) xhe2g = xhe2g + dx(3) enddo - xh1 = xh1g * n / nh - xhe1 = xhe1g * n / nhe - xhe2 = xhe2g * n / nhe + xh1 = max(xh1g * n / nh,1.e-99) + xhe1 = max(xhe1g * n / nhe,1.e-99) + xhe2 = max(xhe2g * n / nhe,1.e-99) xh0 = ((nh/n) - xh1g) * n / nh xhe0 = ((nhe/n) - xhe1g - xhe2g) * n / nhe diff --git a/src/main/mpi_memory.F90 b/src/main/mpi_memory.f90 similarity index 100% rename from src/main/mpi_memory.F90 rename to src/main/mpi_memory.f90 diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index a93458977..680aa6fca 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -23,8 +23,8 @@ module radiation_utils public :: get_rad_R public :: radiation_equation_of_state public :: T_from_Etot - public :: radE_from_Trad - public :: Trad_from_radE + public :: radxi_from_Trad + public :: Trad_from_radxi public :: ugas_from_Tgas public :: Tgas_from_ugas public :: get_opacity @@ -136,29 +136,29 @@ end function T_from_Etot !--------------------------------------------------------- !+ -! get the radiation energy from the radiation temperature +! get specific radiation energy from radiation temperature !+ !--------------------------------------------------------- -real function radE_from_Trad(Trad) result(radE) +real function radxi_from_Trad(rho,Trad) result(radxi) use units, only:get_radconst_code - real, intent(in) :: Trad + real, intent(in) :: rho,Trad - radE = Trad**4*get_radconst_code() + radxi = Trad**4*get_radconst_code()/rho -end function radE_from_Trad +end function radxi_from_Trad !--------------------------------------------------------- !+ -! get the radiation temperature from the radiation energy per unit volume +! get radiation temperature from the specific radiation energy !+ !--------------------------------------------------------- -real function Trad_from_radE(radE) result(Trad) +real function Trad_from_radxi(rho,radxi) result(Trad) use units, only:get_radconst_code - real, intent(in) :: radE + real, intent(in) :: rho,radxi - Trad = (radE/get_radconst_code())**0.25 + Trad = (rho*radxi/get_radconst_code())**0.25 -end function Trad_from_radE +end function Trad_from_radxi !--------------------------------------------------------- !+ diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index 3f8091e34..b29226757 100644 --- a/src/main/readwrite_dumps_fortran.f90 +++ b/src/main/readwrite_dumps_fortran.f90 @@ -71,7 +71,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use timestep, only:dtmax,idtmax_n,idtmax_frac use part, only:ibin,krome_nmols,T_gas_cool use metric_tools, only:imetric, imet_et - use eos_stamatellos, only:ttherm_store,teqi_store,opac_store + use eos_stamatellos, only:ttherm_store,ueqi_store,opac_store real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -250,7 +250,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) endif ! write stamatellos cooling values if (icooling == 9) then - call write_array(1,teqi_store,'teqi',npart,k,ipass,idump,nums,nerr) + call write_array(1,ueqi_store,'ueqi',npart,k,ipass,idump,nums,nerr) call write_array(1,ttherm_store,'ttherm',npart,k,ipass,idump,nums,nerr) call write_array(1,opac_store,'opacity',npart,k,ipass,idump,nums,nerr) endif diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 1bfcd95ce..86676275b 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -118,6 +118,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use cons2prim, only:cons2primall use extern_gr, only:get_grforce_all use cooling, only:ufloor,cooling_in_step,Tfloor + use cooling_radapprox,only:radcool_evolve_ui use timing, only:increment_timer,get_timings,itimer_substep use growth, only:check_dustprop use options, only:use_porosity,icooling @@ -158,7 +159,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ibin_dts(ittwas,i) = (int(time_now*ibin_dts(itdt1,i),kind=8) + 0.5)*ibin_dts(itdt,i) enddo endif - !-------------------------------------- ! velocity predictor step, using dtsph !-------------------------------------- @@ -172,14 +172,15 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(npart,xyzh,vxyzu,fxyzu,iphase,hdtsph,store_itype) & !$omp shared(rad,drad,pxyzu) & !$omp shared(Bevol,dBevol,dustevol,ddustevol,use_dustfrac) & - !$omp shared(dustprop,ddustprop,dustproppred,ufloor,icooling) & + !$omp shared(dustprop,ddustprop,dustproppred,ufloor,icooling,Tfloor) & !$omp shared(mprev,filfacprev,filfac,use_porosity) & !$omp shared(ibin,ibin_old,twas,timei) & !$omp firstprivate(itype) & !$omp private(i,hdti) & !$omp reduction(+:nvfloorp) predictor: do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then + ! print *, "predictor, i=", i + if (.not.isdead_or_accreted(xyzh(4,i))) then if (ind_timesteps) then if (iactive(iphase(i))) ibin_old(i) = ibin(i) ! only required for ibin_neigh in force.F90 ! @@ -199,13 +200,14 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else if (icooling == 9) then vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + call radcool_evolve_ui(vxyzu(4,i),hdti,i,Tfloor,xyzh(4,i)) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif endif !--floor the thermal energy if requested and required - if (ufloor > 0.) then + if (ufloor > 0. .and. icooling /= 9) then if (vxyzu(4,i) < ufloor) then vxyzu(4,i) = ufloor nvfloorp = nvfloorp + 1 @@ -251,7 +253,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif else if (nptmass > 0 .or. iexternalforce > 0 .or. h2chemistry .or. cooling_in_step .or. idamp > 0) then - call substep(npart,ntypes,nptmass,dtsph,dtextforce,t,xyzh,vxyzu,& fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,& dptmass,linklist_ptmass,fsink_old,nbinmax,ibin_wake,gtgrad, & @@ -280,7 +281,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(dustevol,ddustprop,dustprop,dustproppred,dustfrac,ddustevol,dustpred,use_dustfrac) & !$omp shared(filfac,filfacpred,use_porosity) & !$omp shared(alphaind,ieos,alphamax,ialphaloc) & -!$omp shared(eos_vars,ufloor,icooling) & +!$omp shared(eos_vars,ufloor,icooling,Tfloor) & !$omp shared(twas,timei) & !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & @@ -329,7 +330,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then ppred(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + if (icooling == 9) then + vpred(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + call radcool_evolve_ui(vxyzu(4,i),hdti,i,Tfloor,xyzh(4,i),vpred(4,i)) + else + vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + endif endif !--floor the thermal energy if requested and required @@ -393,16 +399,13 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (npart > 0) then if (gr) vpred = vxyzu ! Need primitive utherm as a guess in cons2prim - if (icooling == 9) vpred(4,:) = vxyzu(4,:) dt_too_small = .false. call derivs(1,npart,nactive,xyzh,vpred,fxyzu,fext,divcurlv,& divcurlB,Bpred,dBevol,radpred,drad,radprop,dustproppred,ddustprop,& dustpred,ddustevol,filfacpred,dustfrac,eos_vars,timei,dtsph,dtnew,& ppred,dens,metrics,apr_level) - if (do_radiation .and. implicit_radiation) then rad = radpred - vxyzu(4,1:npart) = vpred(4,1:npart) endif if (gr) vxyzu = vpred ! May need primitive variables elsewhere? @@ -492,6 +495,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else if (icooling == 9) then vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) + call radcool_evolve_ui(vxyzu(4,i),dti,i,Tfloor,xyzh(4,i)) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif @@ -518,6 +522,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else if (icooling == 9) then vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + call radcool_evolve_ui(vxyzu(4,i),hdti,i,Tfloor,xyzh(4,i)) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif @@ -525,7 +530,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !--floor the thermal energy if requested and required if (ufloor > 0.) then - if (vxyzu(4,i) < ufloor) then + if (vxyzu(4,i) < ufloor .and. icooling /= 9) then vxyzu(4,i) = ufloor nvfloorc = nvfloorc + 1 endif @@ -578,7 +583,13 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxi = vxyzu(1,i) + hdtsph*fxyzu(1,i) vyi = vxyzu(2,i) + hdtsph*fxyzu(2,i) vzi = vxyzu(3,i) + hdtsph*fxyzu(3,i) - if (maxvxyzu >= 4) eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) + if (maxvxyzu >= 4) then + if (icooling == 9) then + call radcool_evolve_ui(vxyzu(4,i),hdtsph,i,Tfloor,xyzh(4,i),eni) + else + eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) + endif + endif erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 errmax = max(errmax,erri) @@ -631,7 +642,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(Bevol,dBevol,Bpred,pxyzu,ppred) & !$omp shared(dustprop,ddustprop,dustproppred,use_dustfrac,dustevol,dustpred,ddustevol) & !$omp shared(filfac,filfacpred,use_porosity) & -!$omp shared(rad,drad,radpred,icooling) & +!$omp shared(rad,drad,radpred,icooling,Tfloor,xyzh) & !$omp firstprivate(itype) & !$omp schedule(static) until_converged: do i=1,npart @@ -668,7 +679,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) else - vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) + if (icooling == 9) then + call radcool_evolve_ui(vxyzu(4,i),-hdtsph,i,Tfloor,xyzh(4,i)) + vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) + else + vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) + endif endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then @@ -701,9 +717,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif - if (icooling == 9) then - print *, "after 2nd derivs:vpred", maxval(vpred(4,:)), minval(vpred(4,:)) - endif endif if (icooling == 9 .and. iverbose >=2) then print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index 1f68e9ec5..a0f9a3a75 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -335,7 +335,10 @@ subroutine substep_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,metric elseif (use_apr) then pmassi = aprmassoftype(igas,apr_level(i)) endif - + + if (vxyzu(4,i) < 0d0) then + print *, "u is NEGATIVE in SUBSTEPPING!", vxyzu(4,i),i,dens(i) + endif call equationofstate(ieos,pondensi,spsoundi,dens(i),xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) pri = pondensi*dens(i) call get_grforce(xyzh(:,i),metrics(:,:,:,i),metricderivs(:,:,:,i),vxyzu(1:3,i),dens(i),vxyzu(4,i),pri,fext(1:3,i),dtf) @@ -1205,7 +1208,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl ! ! COOLING ! - if (icooling > 0 .and. cooling_in_step) then + if (icooling > 0 .and. cooling_in_step .and. icooling/=9) then if (h2chemistry) then ! ! Call cooling routine, requiring total density, some distance measure and @@ -1224,8 +1227,8 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl else call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,dust_temp(i)) endif - elseif (icooling == 9) then - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,ipart=i) +! elseif (icooling == 9) then +! call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,ipart=i) else ! cooling without stored dust temperature call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool) @@ -1233,7 +1236,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl endif #endif ! update internal energy - if (isionisedi) dudtcool = 0. + if (isionisedi .or. icooling == 9) dudtcool = 0. if (cooling_in_step .or. use_krome) vxyzu(4,i) = vxyzu(4,i) + dt * dudtcool diff --git a/src/setup/set_star_utils.f90 b/src/setup/set_star_utils.f90 index a82a1be51..a841ec0c8 100644 --- a/src/setup/set_star_utils.f90 +++ b/src/setup/set_star_utils.f90 @@ -439,7 +439,7 @@ subroutine set_star_thermalenergy(ieos,den,pres,r,npts,npart,xyzh,vxyzu,rad,eos_ relaxed,use_var_comp,initialtemp,npin) use part, only:do_radiation,rhoh,massoftype,igas,itemp,igasP,iX,iZ,imu,iradxi use eos, only:equationofstate,calc_temp_and_ene,gamma,gmw - use radiation_utils, only:ugas_from_Tgas,radE_from_Trad + use radiation_utils, only:ugas_from_Tgas,radxi_from_Trad use table_utils, only:yinterp use units, only:unit_density,unit_ergg,unit_pressure integer, intent(in) :: ieos,npart,npts @@ -497,7 +497,7 @@ subroutine set_star_thermalenergy(ieos,den,pres,r,npts,npart,xyzh,vxyzu,rad,eos_ endif if (do_radiation) then vxyzu(4,i) = ugas_from_Tgas(tempi,gamma,gmw) - rad(iradxi,i) = radE_from_Trad(tempi)/densi + rad(iradxi,i) = radxi_from_Trad(densi,tempi) else vxyzu(4,i) = eni / unit_ergg endif @@ -514,7 +514,7 @@ end subroutine set_star_thermalenergy !----------------------------------------------------------------------- subroutine solve_uT_profiles(eos_type,r,den,pres,Xfrac,Yfrac,regrid_core,temp,en,mu) use eos, only:get_mean_molecular_weight,calc_temp_and_ene - use physcon, only:radconst,kb_on_mh + use physcon, only:radconst,Rg integer, intent(in) :: eos_type real, intent(in) :: r(:),den(:),pres(:),Xfrac(:),Yfrac(:) logical, intent(in) :: regrid_core @@ -531,7 +531,7 @@ subroutine solve_uT_profiles(eos_type,r,den,pres,Xfrac,Yfrac,regrid_core,temp,en mu(i) = get_mean_molecular_weight(Xfrac(i),1.-Xfrac(i)-Yfrac(i)) ! only used in u, T calculation if ieos==2,12 if (i==1) then guessene = 1.5*pres(i)/den(i) ! initial guess - tempi = min((3.*pres(i)/radconst)**0.25, pres(i)*mu(i)/(den(i)*kb_on_mh)) ! guess for temperature + tempi = min((3.*pres(i)/radconst)**0.25, pres(i)*mu(i)/(den(i)*Rg)) ! guess for temperature else guessene = en(i-1) tempi = temp(i-1) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 590f8a2b4..403e99694 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -185,6 +185,7 @@ module setup real :: R_in(maxdiscs),R_out(maxdiscs),R_ref(maxdiscs),R_c(maxdiscs) real :: pindex(maxdiscs),disc_m(maxdiscs),sig_ref(maxdiscs),sig_norm(maxdiscs) + real :: T_bg,L_star(maxdiscs) real :: qindex(maxdiscs),H_R(maxdiscs) real :: posangl(maxdiscs),incl(maxdiscs) real :: annulus_m(maxdiscs),R_inann(maxdiscs),R_outann(maxdiscs) @@ -211,7 +212,7 @@ module setup (/'1','2','3','4','5','6','7','8','9' /) logical :: istratify - integer :: nplanets,discstrat + integer :: nplanets,discstrat,lumdisc real :: mplanet(maxplanets),rplanet(maxplanets) real :: accrplanet(maxplanets),inclplan(maxplanets) real :: J2planet(maxplanets),spin_period(maxplanets),obliquity(maxplanets) @@ -325,7 +326,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, rad(iradxi,1:npart)=0.!call set_radiation_and_gas_temperature_equal(npart,xyzh,vxyzu,massoftype,rad) radprop(ikappa,1:npart) = iradkappa endif - + !--remind user to check for warnings and errors write(*,20) 20 format(/, & @@ -442,6 +443,9 @@ subroutine set_default_options()!id) annulus_m = 0.05 R_inann = 1. R_outann = 150. + lumdisc = 0 + L_star(:) = 1. + T_bg = 5. !--dust disc R_indust = 1. @@ -616,6 +620,8 @@ subroutine equation_of_state(gamma) use eos, only:isink,qfacdisc,qfacdisc2,polyk2,beta_z,z0 use options, only:ieos,icooling use options, only:nfulldump,alphau,ipdv_heating,ishock_heating + use eos_stamatellos, only:init_S07cool + use physcon, only:rpiontwo real, intent(out) :: gamma real :: H_R_atm, cs @@ -705,11 +711,27 @@ subroutine equation_of_state(gamma) endif else - - !--adiabatic - ieos = 2 - gamma = 5./3. - icooling = 3 + !-- adiabatic + if (lumdisc > 0) then + !--for radapprox cooling + print "(/,a)", ' setting ieos=23 and icooling=9 for radiative cooling approximation' + ieos = 23 + icooling = 9 + gamma = 5./3. ! in case it's needed + call init_S07cool() + if (ndiscs > 1) then + print *, "We can't set up multiple radapprox discs yet :,(" + stop + else + cs = get_cs_from_lum(L_star(1),R_ref(1)) / rpiontwo + H_R(1) = cs * R_ref(1)**0.5 / sqrt(m1) ! single central star, G=1 + endif + else + !--adiabatic + ieos = 2 + gamma = 5./3. + icooling = 3 + endif if (use_mcfost) then icooling = 0 @@ -2243,8 +2265,20 @@ subroutine setup_interactive(id) ! to be changed also in the the setpart function. !-------------------------------------------------------------------------- if (.not. use_global_iso) then - call prompt('Enter q_index',qindex(1)) - qindex=qindex(1) + if (maxvxyzu > 3) then + call prompt("Do you want to set the disc temperatures from the stellar"// & + "luminosity? (0=no 1=yes",lumdisc) + endif + if (lumdisc > 0) then + !get luminosity ... + call prompt("Enter the luminosity of star",L_star(i)) + call prompt("Enter the background temperature e.g. 10 (K)", T_bg) + qindex(1) = 0.25 + qindex = 0.25 + else + call prompt('Enter q_index',qindex(1)) + qindex=qindex(1) + endif if (nsinks<5) then if (iuse_disc(1)) then call prompt('Enter H/R of circumbinary at R_ref',H_R(1)) @@ -2697,7 +2731,7 @@ subroutine write_setupfile(filename) endif call write_inopt(isetgas(i),'isetgas'//trim(disclabel),'how to set gas density profile' // & ' (0=total disc mass,1=mass within annulus,2=surface density normalisation,' // & - '3=surface density at reference radius,4=minimum Toomre Q)',iunit) + '3=surface density at reference radius,4=minimum Toomre Q,5=minimum Toomre Q and Lstar)',iunit) call write_inopt(itapergas(i),'itapergas'//trim(disclabel), & 'exponentially taper the outer disc profile',iunit) if (itapergas(i)) call write_inopt(itapersetgas(i),'itapersetgas'//trim(disclabel), & @@ -2735,12 +2769,22 @@ subroutine write_setupfile(filename) call write_inopt(sig_ref(i),'sig_ref'//trim(disclabel),'sigma at reference radius',iunit) case (4) call write_inopt(Q_min(i),'Q_min'//trim(disclabel),'minimum Toomre Q',iunit) + end select + call write_inopt(lumdisc,'lumdisc', 'Set qindex from stellar luminosity (ieos=23) (0=no 1=yes)',iunit) + if (lumdisc > 0) then + call write_inopt(L_star(i),'L_star'//trim(disclabel),'Stellar luminosity (Lsun)',iunit) + call write_inopt(T_bg,'T_bg'//trim(disclabel),'background Temperature (K)',iunit) + endif call write_inopt(pindex(i),'pindex'//trim(disclabel),'power law index of surface density sig=sig0*r^-p',iunit) - call write_inopt(qindex(i),'qindex'//trim(disclabel),'power law index of sound speed cs=cs0*r^-q',iunit) + if (lumdisc == 0) then + call write_inopt(qindex(i),'qindex'//trim(disclabel),'power law index of sound speed cs=cs0*r^-q',iunit) + endif call write_inopt(posangl(i),'posangl'//trim(disclabel),'position angle (deg)',iunit) call write_inopt(incl(i),'incl'//trim(disclabel),'inclination (deg)',iunit) - if (discstrat == 0) call write_inopt(H_R(i),'H_R'//trim(disclabel),'H/R at R=R_ref',iunit) + if (discstrat == 0 .and. lumdisc == 0) then + call write_inopt(H_R(i),'H_R'//trim(disclabel),'H/R at R=R_ref',iunit) + endif if (iwarp(i)) then call write_inopt(R_warp(i),'R_warp'//trim(disclabel),'warp radius',iunit) call write_inopt(H_warp(i),'H_warp'//trim(disclabel),'warp smoothing length',iunit) @@ -3025,6 +3069,8 @@ subroutine read_setupfile(filename,ierr) end select call read_inopt(discstrat,'discstrat',db,errcount=nerr) + call read_inopt(lumdisc,'lumdisc',db,errcount=nerr) + if (discstrat==1) then call read_inopt(istrat,'istrat',db,errcount=nerr) call read_inopt(z0_ref,'z0',db,errcount=nerr) @@ -3136,10 +3182,12 @@ subroutine read_setupfile(filename,ierr) call read_inopt(Q_min(i),'Q_min'//trim(disclabel),db,min=0.,errcount=nerr) end select call read_inopt(pindex(i),'pindex'//trim(disclabel),db,errcount=nerr) - call read_inopt(qindex(i),'qindex'//trim(disclabel),db,errcount=nerr) + if (lumdisc == 0) call read_inopt(qindex(i),'qindex'//trim(disclabel),db,errcount=nerr) call read_inopt(posangl(i),'posangl'//trim(disclabel),db,min=0.,max=360.,errcount=nerr) call read_inopt(incl(i),'incl'//trim(disclabel),db,min=0.,max=180.,errcount=nerr) - if (discstrat == 0) call read_inopt(H_R(i),'H_R'//trim(disclabel),db,min=0.,errcount=nerr) + if (discstrat == 0 .and. lumdisc == 0) then + call read_inopt(H_R(i),'H_R'//trim(disclabel),db,min=0.,errcount=nerr) + endif call read_inopt(iwarp(i),'iwarp'//trim(disclabel),db,errcount=nerr) if (iwarp(i)) then call read_inopt(R_warp(i),'R_warp'//trim(disclabel),db,min=0.,errcount=nerr) @@ -3214,6 +3262,11 @@ subroutine read_setupfile(filename,ierr) if (do_radiation) call read_inopt(iradkappa,'radkappa',db,err=ierr) + if (lumdisc > 0) then + call read_inopt(L_star(1),'L_star',db,min=0.,errcount=nerr) + call read_inopt(T_bg,'T_bg',db,min=0.,errcount=nerr) + endif + call close_db(db) ierr = nerr if (nerr > 0) then @@ -3492,5 +3545,16 @@ subroutine get_hier_disc_label(i, disclabel) end subroutine get_hier_disc_label +real function get_cs_from_lum(L_star,r) + use physcon, only:kb_on_mh,steboltz,solarl,fourpi + use units, only:udist,unit_velocity + real,intent(in) :: L_star,r + real :: mu + + mu = 2.3 !mean molecular mass + get_cs_from_lum = sqrt(kb_on_mh/mu) * ( (L_star*solarl/(fourpi*steboltz))**0.125 / & + (r*udist)**0.25 + sqrt(T_bg) ) + get_cs_from_lum = get_cs_from_lum/unit_velocity +end function end module setup diff --git a/src/setup/setup_star.f90 b/src/setup/setup_star.f90 index 26c310081..e0cfee23f 100644 --- a/src/setup/setup_star.f90 +++ b/src/setup/setup_star.f90 @@ -33,7 +33,7 @@ module setup ! use io, only:fatal,error,warning,master use part, only:gravity,gr - use physcon, only:solarm,solarr,km,pi,c,kb_on_mh,radconst + use physcon, only:solarm,solarr,km,pi,c,radconst use options, only:nfulldump,iexternalforce,calc_erot,use_var_comp use timestep, only:tmax,dtmax use eos, only:ieos diff --git a/src/setup/setup_windtunnel.f90 b/src/setup/setup_windtunnel.f90 index f4df9bffb..0bbc21f56 100644 --- a/src/setup/setup_windtunnel.f90 +++ b/src/setup/setup_windtunnel.f90 @@ -33,12 +33,13 @@ module setup use io, only:master,fatal use inject, only:init_inject,nstar,Rstar,lattice_type,handled_layers,& wind_radius,wind_injection_x,wind_length,& - rho_inf,pres_inf,v_inf + rho_inf,pres_inf,v_inf,windonly implicit none public :: setpart real :: Mstar + integer :: nstar_in ! guess for no. of star prticles private @@ -54,6 +55,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use eos, only:ieos,gmw use setstar_utils,only:set_star_density use rho_profile, only:rho_polytrope + use relaxstar, only:relax_star use extern_densprofile, only:nrhotab use physcon, only:solarm,solarr use units, only:udist,umass,utime,set_units,unit_velocity,unit_density,unit_pressure @@ -71,9 +73,9 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, real, intent(inout) :: time character(len=20), intent(in) :: fileprefix real :: rhocentre,rmin,pmass,densi,presi,ri - real, allocatable :: r(:),den(:),pres(:) - integer :: ierr,npts,np,i - logical :: use_exactN,setexists + real, allocatable :: r(:),den(:),pres(:),Xfrac(:),Yfrac(:),mu(:) + integer :: ierr,ierr_relax,npts,np,i + logical :: use_exactN,setexists,use_var_comp character(len=30) :: lattice character(len=120) :: setupfile @@ -100,7 +102,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ! Star parameters Rstar = 0.1 Mstar = 1.e-3 - nstar = 1000 + nstar_in = 1000 lattice = 'closepacked' use_exactN = .true. @@ -131,7 +133,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, stop 'please check and edit .setup file and rerun phantomsetup' endif - pmass = Mstar / real(nstar) + pmass = Mstar / real(nstar_in) massoftype(igas) = pmass call check_setup(pmass,ierr) if (ierr /= 0) call fatal('windtunnel','errors in setup parameters') @@ -146,23 +148,29 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, vxyzu(:,:) = 0. ! Set polytropic star - allocate(r(nrhotab),den(nrhotab),pres(nrhotab)) - call rho_polytrope(gamma,polyk,Mstar,r,den,npts,rhocentre,set_polyk=.true.,Rstar=Rstar) - pres = polyk*den**gamma - rmin = r(1) - call set_star_density(lattice,id,master,rmin,Rstar,Mstar,hfact,& + if (.not. windonly) then + allocate(r(nrhotab),den(nrhotab),pres(nrhotab)) + call rho_polytrope(gamma,polyk,Mstar,r,den,npts,rhocentre,set_polyk=.true.,Rstar=Rstar) + pres = polyk*den**gamma + rmin = r(1) + call set_star_density(lattice,id,master,rmin,Rstar,Mstar,hfact,& npts,den,r,npart,npartoftype,massoftype,xyzh,& use_exactN,np,rhozero,npart_total,i_belong) ! Note: mass_is_set = .true., so np is not used - ! Set thermal energy - do i = 1,npart - ri = sqrt(dot_product(xyzh(1:3,i),xyzh(1:3,i))) - densi = yinterp(den(1:npts),r(1:npts),ri) - presi = yinterp(pres(1:npts),r(1:npts),ri) - vxyzu(4,i) = presi / ( (gamma-1.) * densi) - enddo - - deallocate(r,den,pres) - + nstar = npart + use_var_comp = .false. + call relax_star(npts,den,pres,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr_relax) + + ! Set thermal energy + do i = 1,npart + ri = sqrt(dot_product(xyzh(1:3,i),xyzh(1:3,i))) + densi = yinterp(den(1:npts),r(1:npts),ri) + presi = yinterp(pres(1:npts),r(1:npts),ri) + vxyzu(4,i) = presi / ( (gamma-1.) * densi) + enddo + + deallocate(r,den,pres) + endif + print*, "udist = ", udist, "; umass = ", umass, "; utime = ", utime end subroutine setpart @@ -191,7 +199,7 @@ subroutine write_setupfile(filename) call write_options_units(iunit) write(iunit,"(/,a)") '# sphere settings' - call write_inopt(nstar,'nstar','number of particles resolving gas sphere',iunit) + call write_inopt(nstar_in,'nstar','number of particles resolving gas sphere',iunit) ! note: this is an estimate, actual no. of particles is npart outputted from set_sphere call write_inopt(Mstar,'Mstar','sphere mass in code units',iunit) call write_inopt(Rstar,'Rstar','sphere radius in code units',iunit) @@ -237,7 +245,7 @@ subroutine read_setupfile(filename,ierr) call read_options_and_set_units(db,nerr) - call read_inopt(nstar,'nstar',db,errcount=nerr) + call read_inopt(nstar_in,'nstar',db,errcount=nerr) call read_inopt(Mstar,'Mstar',db,errcount=nerr) call read_inopt(Rstar,'Rstar',db,errcount=nerr) diff --git a/src/tests/test_gr.f90 b/src/tests/test_gr.f90 index 905a15a0d..bdc1ad0fa 100644 --- a/src/tests/test_gr.f90 +++ b/src/tests/test_gr.f90 @@ -468,7 +468,7 @@ subroutine test_cons2prim_i(x,v,dens,u,p,ncheck,nfail,errmax,tol) use part, only:ien_entropy,ien_etotal,ien_entropy_s use metric_tools, only:pack_metric,unpack_metric use eos, only:ieos,equationofstate,calc_temp_and_ene - use physcon, only:radconst,kb_on_mh + use physcon, only:radconst real, intent(in) :: x(1:3),v(1:3),dens,p,tol real, intent(inout) :: u diff --git a/src/tests/test_sedov.F90 b/src/tests/test_sedov.F90 index d12efb34a..9e96630d7 100644 --- a/src/tests/test_sedov.F90 +++ b/src/tests/test_sedov.F90 @@ -54,7 +54,7 @@ subroutine test_sedov(ntests,npass) use mpidomain, only:i_belong use checkconserved, only:etot_in,angtot_in,totmom_in,mdust_in use radiation_utils, only:set_radiation_and_gas_temperature_equal,& - T_from_Etot,Tgas_from_ugas,ugas_from_Tgas,radE_from_Trad,Trad_from_radE + T_from_Etot,Tgas_from_ugas,ugas_from_Tgas use readwrite_dumps, only:write_fulldump use step_lf_global, only:init_step integer, intent(inout) :: ntests,npass diff --git a/src/utils/analysis_common_envelope.f90 b/src/utils/analysis_common_envelope.f90 index a527f4b41..7843a5bb2 100644 --- a/src/utils/analysis_common_envelope.f90 +++ b/src/utils/analysis_common_envelope.f90 @@ -22,7 +22,7 @@ module analysis use part, only:xyzmh_ptmass,vxyz_ptmass,nptmass,poten,ihsoft,ihacc,& rhoh,nsinkproperties,maxvxyzu,maxptmass,isdead_or_accreted,& - radprop + rad,radprop use dim, only:do_radiation use units, only:print_units,umass,utime,udist,unit_ergg,unit_density,& unit_pressure,unit_velocity,unit_Bfield,unit_energ @@ -71,7 +71,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ' 5) Roche-lobe utils', & ' 6) Star stabilisation suite', & ' 7) Simulation units and particle properties', & - ' 8) Output .divv', & + ' 8) Output extra quantities', & ' 9) EoS testing', & '10) Profile of newly unbound particles', & '11) Sink properties', & @@ -106,7 +106,6 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) call prompt('Choose analysis type ',analysis_to_perform,1,38) endif - call reset_centreofmass(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass) call adjust_corotating_velocities(npart,particlemass,xyzh,vxyzu,& xyzmh_ptmass,vxyz_ptmass,omega_corotate,dump_number) @@ -129,8 +128,8 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) call star_stabilisation_suite(time,npart,particlemass,xyzh,vxyzu) case(7) !Units call print_simulation_parameters(npart,particlemass) - case(8) !Output .divv - call output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) + case(8) ! output extra quantities + call output_extra_quantities(time,dumpfile,npart,particlemass,xyzh,vxyzu) case(9) !EoS testing call eos_surfaces case(10) !New unbound particle profiles in time @@ -154,7 +153,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) case(19) ! Optical depth profile call tau_profile(time,num,npart,particlemass,xyzh) case(20) ! Particle tracker - call track_particle(time,particlemass,xyzh,vxyzu) + call track_particle(time,npart,particlemass,xyzh,vxyzu) case(21) ! Unbound ion fractions call unbound_ionfrac(time,npart,particlemass,xyzh,vxyzu) case(22) ! Optical depth at recombination @@ -338,7 +337,7 @@ subroutine planet_rvm(time,particlemass,xyzh,vxyzu) real, intent(in) :: time,xyzh(:,:),vxyzu(:,:),particlemass character(len=17), allocatable :: columns(:) real, dimension(3) :: planet_com,planet_vel,sep,vel - real :: rhoi,rhoprev,sepi,si,smin,presi,Rthreshold + real :: rhoi,rhoprev,sepi,si,smin,presi,Rthreshold,xyz_origin(3),vxyz_origin(3) real, allocatable :: data_cols(:),mass(:),vthreshold(:) integer :: i,j,ncols,maxrho_ID,ientropy,Nmasks integer, save :: nplanet @@ -368,6 +367,14 @@ subroutine planet_rvm(time,particlemass,xyzh,vxyzu) if (dump_number == 0) call get_planetIDs(nplanet,planetIDs) isfulldump = (vxyzu(4,1) > 0.) + if (nptmass > 0) then + xyz_origin = xyzmh_ptmass(1:3,1) + vxyz_origin = vxyz_ptmass(1:3,1) + else + xyz_origin = (/0.,0.,0./) + vxyz_origin = (/0.,0.,0./) + endif + ! Find highest density and lowest entropy in planet rhoprev = 0. maxrho_ID = 1 @@ -390,11 +397,11 @@ subroutine planet_rvm(time,particlemass,xyzh,vxyzu) enddo planet_com = xyzh(1:3,maxrho_ID) - sep = planet_com - xyzmh_ptmass(1:3,1) + sep = planet_com - xyz_origin(1:3) if (isfulldump) then planet_vel = vxyzu(1:3,maxrho_ID) - vel = planet_vel - vxyz_ptmass(1:3,1) + vel = planet_vel - vxyz_origin(1:3) else vel = 0. smin = 0. @@ -521,13 +528,13 @@ end subroutine m_vs_t !+ !---------------------------------------------------------------- subroutine bound_mass(time,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp,radprop + use part, only:eos_vars,itemp use ptmass, only:get_accel_sink_gas use vectorutils, only:cross_product3D integer, intent(in) :: npart real, intent(in) :: time,particlemass real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - real :: etoti,ekini,epoti,phii,einti,ethi + real :: etoti,ekini,epoti,phii,ereci,egasi,eradi,ethi real :: E_H2,E_HI,E_HeI,E_HeII real, save :: Xfrac,Yfrac,Zfrac real :: rhopart,ponrhoi,spsoundi,tempi,dum1,dum2,dum3 @@ -593,20 +600,20 @@ subroutine bound_mass(time,npart,particlemass,xyzh,vxyzu) do i = 1,npart if (.not. isdead_or_accreted(xyzh(4,i))) then - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,epoti,ekini,& + egasi,eradi,ereci,etoti) call get_accel_sink_gas(nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass,dum1,dum2,dum3,phii) rhopart = rhoh(xyzh(4,i), particlemass) tempi = eos_vars(itemp,i) call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) call cross_product3D(xyzh(1:3,i), particlemass * vxyzu(1:3,i), rcrossmv) ! Angular momentum w.r.t. CoM - call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,tempi,ethi,radprop(:,i)) + call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,tempi,ethi,rad(:,i)) etoti = ekini + epoti + ethi ! Overwrite etoti outputted by calc_gas_energies to use ethi instead of einti else ! Output 0 for quantities pertaining to accreted particles etoti = 0. epoti = 0. ekini = 0. - einti = 0. ethi = 0. phii = 0. ponrhoi = 0. @@ -686,7 +693,7 @@ subroutine calculate_energies(time,npart,particlemass,xyzh,vxyzu) integer, intent(in) :: npart real, intent(in) :: time,particlemass real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - real :: etoti,ekini,einti,epoti,phii,phii1,jz,fxi,fyi,fzi + real :: etoti,ekini,egasi,eradi,ereci,epoti,phii,phii1,jz,fxi,fyi,fzi real :: rhopart,ponrhoi,spsoundi,tempi,r_ij,radvel real, dimension(3) :: rcrossmv character(len=17), allocatable :: columns(:) @@ -755,7 +762,8 @@ subroutine calculate_energies(time,npart,particlemass,xyzh,vxyzu) jz = rcrossmv(3) encomp(ijz_tot) = encomp(ijz_tot) + jz - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,etoti) encomp(ipot_ps) = encomp(ipot_ps) + particlemass * phii @@ -927,7 +935,7 @@ subroutine roche_lobe_values(time,npart,particlemass,xyzh,vxyzu) integer, parameter :: iFBV = 20 integer, parameter :: iFBJz = 21 real, dimension(iFBJz) :: MRL - real :: etoti, ekini, einti, epoti, phii, jz + real :: etoti, ekini, ereci, egasi, eradi, epoti, phii, jz logical, dimension(:), allocatable, save:: transferred real, save :: m1, m2 real :: sep, sep1, sep2 @@ -1001,7 +1009,8 @@ subroutine roche_lobe_values(time,npart,particlemass,xyzh,vxyzu) call orbit_com(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,com_xyz,com_vxyz) do i=1,npart - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,etoti) sep1 = separation(xyzmh_ptmass(1:3,1),xyzh(1:3,i)) sep2 = separation(xyzmh_ptmass(1:3,2),xyzh(1:3,i)) @@ -1132,7 +1141,8 @@ subroutine star_stabilisation_suite(time,npart,particlemass,xyzh,vxyzu) integer, allocatable :: iorder(:),iorder_a(:) real, allocatable :: star_stability(:) real :: total_mass,rhovol,totvol,rhopart,virialpart,virialfluid - real :: phii,ponrhoi,spsoundi,tempi,epoti,ekini,einti,etoti,totekin,totepot,virialintegral,gamma + real :: phii,ponrhoi,spsoundi,tempi,epoti,ekini,egasi,eradi,ereci,etoti + real :: totekin,totepot,virialintegral,gamma integer, parameter :: ivoleqrad = 1 integer, parameter :: idensrad = 2 integer, parameter :: imassout = 3 @@ -1177,7 +1187,8 @@ subroutine star_stabilisation_suite(time,npart,particlemass,xyzh,vxyzu) rhopart = rhoh(xyzh(4,i), particlemass) totvol = totvol + particlemass / rhopart ! Sum "volume" of all particles virialpart = virialpart + particlemass * ( dot_product(fxyzu(1:3,i),xyzh(1:3,i)) + dot_product(vxyzu(1:3,i),vxyzu(1:3,i)) ) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,etoti) totekin = totekin + ekini totepot = totepot + 0.5*epoti ! Factor of 1/2 to correct for double counting if (rhopart > rho_surface) then @@ -1270,110 +1281,183 @@ end subroutine print_simulation_parameters !---------------------------------------------------------------- !+ -! Write quantities (up to four) to divv file +! Write extra quantities to .extras files +! These files can be read via splash --extracols=[label1],[label2],... !+ !---------------------------------------------------------------- -subroutine output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) +subroutine output_extra_quantities(time,dumpfile,npart,particlemass,xyzh,vxyzu) use part, only:eos_vars,itemp,nucleation,idK0,idK1,idK2,idK3,idJstar,idmu,idgamma use eos, only:entropy use eos_mesa, only:get_eos_kappa_mesa use mesa_microphysics, only:getvalue_mesa use sortutils, only:set_r2func_origin,r2func_origin,indexxfunc use ionization_mod, only:ionisation_fraction - use dust_formation, only:psat_C,eps,set_abundances,mass_per_H, chemical_equilibrium_light, calc_nucleation!, Scrit - !use dim, only:nElements + use dust_formation, only:psat_C,eps,set_abundances,mass_per_H,chemical_equilibrium_light,calc_nucleation integer, intent(in) :: npart character(len=*), intent(in) :: dumpfile real, intent(in) :: time,particlemass real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer :: i,k,Nquantities,ierr,iu - integer, save :: quantities_to_calculate(4) - integer, allocatable :: iorder(:) - real :: ekini,einti,epoti,ethi,phii,rho_cgs,ponrhoi,spsoundi,tempi,& - omega_orb,kappai,kappat,kappar,pgas,mu,entropyi,rhopart,& + character(len=30) :: msg + character(len=17), allocatable:: labels(:) + integer :: i,k,Noptions,ierr + integer, save :: Nquant + integer, save, allocatable :: quants(:) + integer, allocatable :: iorder(:),iu(:) + real :: ekini,epoti,egasi,eradi,ereci,ethi,phii,rho_cgs,ponrhoi,spsoundi,tempi,& + omega_orb,kappai,kappat,kappar,pgas,mu,entropyi,rhopart,v_esci,& dum1,dum2,dum3,dum4,dum5 + real :: pC,pC2,pC2H,pC2H2,nH_tot,epsC,S,taustar,taugr,JstarS real, allocatable, save :: init_entropy(:) - real, allocatable :: quant(:,:) - real, dimension(3) :: com_xyz,com_vxyz,xyz_a,vxyz_a - real :: pC, pC2, pC2H, pC2H2, nH_tot, epsC, S - real :: taustar, taugr, JstarS - real :: v_esci + real, allocatable :: arr(:,:) + real, dimension(3) :: com_xyz,com_vxyz,xyz_a,vxyz_a,sinkcom_xyz,sinkcom_vxyz real, parameter :: Scrit = 2. ! Critical saturation ratio - logical :: verbose = .false. + logical :: req_eos_call,req_gas_energy,req_thermal_energy,verbose=.false. + + Noptions = 13 + allocate(labels(Noptions)) + labels = (/ 'e_kpt ',& + 'e_kp ',& + 'erec ',& + 'mach ',& + 'kappa ',& + 'omega_sinkCM',& + 'omega_core ',& + 'delta_omega ',& + 'entropy_mesa',& + 'entropy_gain',& + 'm ',& + 'vesc ',& + 'JstarS '& + /) - allocate(quant(4,npart)) - Nquantities = 14 if (dump_number == 0) then - print "(14(a,/))",& + call prompt('Enter number of extra quantities to write out: ',Nquant,0) + allocate(quants(Nquant)) + + print "(13(a,/))",& '1) Total energy (kin + pot + therm)', & - '2) Mach number', & - '3) Opacity from MESA tables', & - '4) Gas omega w.r.t. effective CoM', & - '5) Fractional difference between gas and orbital omega', & - '6) MESA EoS specific entropy', & - '7) Fractional entropy gain', & - '8) Specific recombination energy', & - '9) Total energy (kin + pot)', & - '10) Mass coordinate', & - '11) Gas omega w.r.t. CoM', & - '12) Gas omega w.r.t. sink 1',& - '13) JstarS', & - '14) Escape velocity' - - quantities_to_calculate = (/1,2,4,5/) - call prompt('Choose first quantity to compute ',quantities_to_calculate(1),0,Nquantities) - call prompt('Choose second quantity to compute ',quantities_to_calculate(2),0,Nquantities) - call prompt('Choose third quantity to compute ',quantities_to_calculate(3),0,Nquantities) - call prompt('Choose fourth quantity to compute ',quantities_to_calculate(4),0,Nquantities) + '2) Total energy (kin + pot)', & + '3) Specific recombination energy', & + '4) Mach number', & + '5) Opacity from MESA tables', & + '6) Gas omega w.r.t. sink CoM', & + '7) Gas omega w.r.t. sink 1',& + '8) Fractional difference between gas and orbital omega w.r.t. sink CoM', & + '9) MESA EoS specific entropy', & + '10) Fractional entropy gain', & + '11) Mass coordinate', & + '12) Escape velocity', & + '13) JstarS' + + do i=1,Nquant + write(msg, '(a,i2,a)') 'Enter quantity ',i,':' + call prompt(msg,quants(i),0,Noptions) + enddo endif + allocate(arr(Nquant,npart),iu(Nquant)) + arr = 0. + ! Calculations performed outside loop over particles call compute_energies(time) omega_orb = 0. com_xyz = 0. com_vxyz = 0. - do k=1,4 - select case (quantities_to_calculate(k)) - case(0,1,2,3,6,8,9,13,14) ! Nothing to do - case(4,5,11,12) ! Fractional difference between gas and orbital omega - if (quantities_to_calculate(k) == 4 .or. quantities_to_calculate(k) == 5) then - com_xyz = (xyzmh_ptmass(1:3,1)*xyzmh_ptmass(4,1) + xyzmh_ptmass(1:3,2)*xyzmh_ptmass(4,2)) & - / (xyzmh_ptmass(4,1) + xyzmh_ptmass(4,2)) - com_vxyz = (vxyz_ptmass(1:3,1)*xyzmh_ptmass(4,1) + vxyz_ptmass(1:3,2)*xyzmh_ptmass(4,2)) & - / (xyzmh_ptmass(4,1) + xyzmh_ptmass(4,2)) - elseif (quantities_to_calculate(k) == 11 .or. quantities_to_calculate(k) == 12) then - com_xyz = xyzmh_ptmass(1:3,1) - com_vxyz = vxyz_ptmass(1:3,1) - endif - do i=1,nptmass - xyz_a(1:3) = xyzmh_ptmass(1:3,i) - com_xyz(1:3) - vxyz_a(1:3) = vxyz_ptmass(1:3,i) - com_vxyz(1:3) - omega_orb = omega_orb + 0.5 * (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) - enddo - case(7) - if (dump_number==0) allocate(init_entropy(npart)) - case(10) - call set_r2func_origin(0.,0.,0.) - allocate(iorder(npart)) - call indexxfunc(npart,r2func_origin,xyzh,iorder) - deallocate(iorder) - case default - print*,"Error: Requested quantity is invalid." - stop - end select - enddo + epoti = 0. + ekini = 0. + + req_eos_call = any(quants==1 .or. quants==2 .or. quants==4 .or. quants==6 .or. quants==7 & + .or. quants==9 .or. quants==10 .or. quants==13) + req_gas_energy = any(quants==1 .or. quants==2 .or. quants==3) + req_thermal_energy = any(quants==1 .or. quants==3) + + if (any(quants==6 .or. quants==8)) then + sinkcom_xyz = (xyzmh_ptmass(1:3,1)*xyzmh_ptmass(4,1) + xyzmh_ptmass(1:3,2)*xyzmh_ptmass(4,2)) & + / (xyzmh_ptmass(4,1) + xyzmh_ptmass(4,2)) + sinkcom_vxyz = (vxyz_ptmass(1:3,1)*xyzmh_ptmass(4,1) + vxyz_ptmass(1:3,2)*xyzmh_ptmass(4,2)) & + / (xyzmh_ptmass(4,1) + xyzmh_ptmass(4,2)) + endif + + if (any(quants==11)) then + call set_r2func_origin(0.,0.,0.) + allocate(iorder(npart)) + call indexxfunc(npart,r2func_origin,xyzh,iorder) + endif + + if (any(quants==10) .and. dump_number==0) allocate(init_entropy(npart)) + + if (any(quants==13)) call set_abundances ! set initial abundances to get mass_per_H + - !set initial abundances to get mass_per_H - call set_abundances - ! Calculations performed in loop over particles do i=1,npart - do k=1,4 - select case (quantities_to_calculate(k)) + rhopart = rhoh(xyzh(4,i),particlemass) + rho_cgs = rhopart*unit_density + if (req_eos_call) then + call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) + endif + + if (req_gas_energy) then + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,dum1) + endif + + if (req_thermal_energy) then + call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) + endif + + do k=1,Nquant + select case (quants(k)) + case(1) ! Total energy (kin + pot + therm) + arr(k,i) = (ekini + epoti + ethi) / particlemass + case(2) ! Total energy (kin + pot) + arr(k,i) = (ekini + epoti) / particlemass + case(3) ! Specific recombination energy + arr(k,i) = vxyzu(4,i) - ethi / particlemass + case(4) ! Mach number + arr(k,i) = distance(vxyzu(1:3,i)) / spsoundi + case(5) ! Opacity from MESA tables + call ionisation_fraction(rho_cgs,eos_vars(itemp,i),X_in,1.-X_in-Z_in,dum1,dum2,dum3,dum4,dum5) + if (ieos == 10) then + call get_eos_kappa_mesa(rho_cgs,eos_vars(itemp,i),kappai,kappat,kappar) + arr(k,i) = kappai + else + arr(k,i) = 0. + endif + case(6) ! Gas omega w.r.t. sink CoM + xyz_a = xyzh(1:3,i) - sinkcom_xyz(1:3) + vxyz_a = vxyzu(1:3,i) - sinkcom_vxyz(1:3) + arr(k,i) = (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) + case(7) ! Gas omega w.r.t. sink 1 + xyz_a = xyzh(1:3,i) - xyzmh_ptmass(1:3,1) + vxyz_a = vxyzu(1:3,i) - vxyz_ptmass(1:3,1) + arr(k,i) = (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) + case(8) ! Fractional difference between gas and orbital omega + xyz_a = xyzh(1:3,i) - sinkcom_xyz(1:3) + vxyz_a = vxyzu(1:3,i) - sinkcom_vxyz(1:3) + omega_orb = omega_orb + 0.5 * (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) + arr(k,i) = (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) + arr(k,i) = arr(k,i)/omega_orb - 1. + case(9,10) ! Calculate MESA EoS entropy + entropyi = 0. + if (ieos==10) then + call getvalue_mesa(rho_cgs,vxyzu(4,i)*unit_ergg,3,pgas,ierr) ! Get gas pressure + mu = rho_cgs * Rg * eos_vars(itemp,i) / pgas + entropyi = entropy(rho_cgs,ponrhoi*rhopart*unit_pressure,mu,3,vxyzu(4,i)*unit_ergg,ierr) + elseif (ieos==2) then + entropyi = entropy(rho_cgs,ponrhoi*rhopart*unit_pressure,gmw,1) + endif + if (quants(k) == 10) then + if (dump_number == 0) init_entropy(i) = entropyi ! Store initial entropy on each particle + arr(k,i) = entropyi/init_entropy(i) - 1. + elseif (quants(k) == 9) then + arr(k,i) = entropyi + endif + case(11) ! Mass coordinate + arr(k,iorder(i)) = real(i,kind=kind(time)) * particlemass + case(12) ! Escape_velocity + call calc_escape_velocities(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),xyzmh_ptmass,phii,epoti,v_esci) + arr(k,i) = v_esci case(13) !to calculate JstarS - rhopart = rhoh(xyzh(4,i), particlemass) - rho_cgs = rhopart*unit_density - !call equationofstate to obtain temperature and store it in tempi - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) JstarS = 0. !nH_tot is needed to normalize JstarS nH_tot = rho_cgs/mass_per_H @@ -1401,104 +1485,26 @@ subroutine output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) print *,'epsC = ',epsC print *,'tempi = ',tempi print *,'S = ',S - print *,'pC =',pC - print *,'psat_C(tempi) = ',psat_C(tempi) - print *,'nucleation(idmu,i) = ',nucleation(idmu,i) - print *,'nucleation(idgamma,i) = ',nucleation(idgamma,i) print *,'taustar = ',taustar print *,'eps = ',eps print *,'JstarS = ',JstarS endif - quant(k,i) = JstarS - - case(0) ! Skip - quant(k,i) = 0. - - case(1,9) ! Total energy (kin + pot + therm) - rhopart = rhoh(xyzh(4,i), particlemass) - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum1) - if (quantities_to_calculate(k)==1) then - call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) - quant(k,i) = (ekini + epoti + ethi) / particlemass ! Specific energy - elseif (quantities_to_calculate(k)==9) then - quant(k,i) = (ekini + epoti) / particlemass ! Specific energy - endif - - case(2) ! Mach number - rhopart = rhoh(xyzh(4,i), particlemass) - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - quant(k,i) = distance(vxyzu(1:3,i)) / spsoundi - - case(3) ! Opacity from MESA tables - rhopart = rhoh(xyzh(4,i), particlemass) - call ionisation_fraction(rhopart*unit_density,eos_vars(itemp,i),X_in,1.-X_in-Z_in,dum1,dum2,dum3,dum4,dum5) - if (ieos == 10) then - call get_eos_kappa_mesa(rhopart*unit_density,eos_vars(itemp,i),kappai,kappat,kappar) - quant(k,i) = kappai - else - quant(k,i) = 0. - endif - - case(4,11,12) ! Gas omega w.r.t. effective CoM - xyz_a = xyzh(1:3,i) - com_xyz(1:3) - vxyz_a = vxyzu(1:3,i) - com_vxyz(1:3) - quant(k,i) = (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) - - case(5) ! Fractional difference between gas and orbital omega - xyz_a = xyzh(1:3,i) - com_xyz(1:3) - vxyz_a = vxyzu(1:3,i) - com_vxyz(1:3) - quant(k,i) = (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) - quant(k,i) = (quant(k,i) - omega_orb) / omega_orb - - case(6,7) ! Calculate MESA EoS entropy - entropyi = 0. - rhopart = rhoh(xyzh(4,i), particlemass) - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - if (ieos==10) then - call getvalue_mesa(rhopart*unit_density,vxyzu(4,i)*unit_ergg,3,pgas,ierr) ! Get gas pressure - mu = rhopart*unit_density * Rg * eos_vars(itemp,i) / pgas - entropyi = entropy(rhopart*unit_density,ponrhoi*rhopart*unit_pressure,mu,3,vxyzu(4,i)*unit_ergg,ierr) - elseif (ieos==2) then - entropyi = entropy(rhopart*unit_density,ponrhoi*rhopart*unit_pressure,gmw,1) - endif - - if (quantities_to_calculate(k) == 7) then - if (dump_number == 0) then - init_entropy(i) = entropyi ! Store initial entropy on each particle - endif - quant(k,i) = entropyi/init_entropy(i) - 1. - elseif (quantities_to_calculate(k) == 6) then - quant(k,i) = entropyi - endif - - case(8) ! Specific recombination energy - rhopart = rhoh(xyzh(4,i), particlemass) - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) - quant(k,i) = vxyzu(4,i) - ethi / particlemass ! Specific energy - - case(10) ! Mass coordinate - quant(k,iorder(i)) = real(i,kind=kind(time)) * particlemass - - case(14) ! Escape_velocity - call calc_escape_velocities(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),xyzmh_ptmass,phii,epoti,v_esci) - quant(k,i) = v_esci + arr(k,i) = JstarS case default - print*,"Error: Requested quantity is invalid." - stop + call fatal('analysis_common_envelope','Requested quantity is invalid.') end select enddo enddo - open(newunit=iu,file=trim(dumpfile)//".divv",status='replace',form='unformatted') - do k=1,4 - write(iu) (quant(k,i),i=1,npart) + ! Open files + do k=1,Nquant + open(newunit=iu(k),file=trim(dumpfile)//"."//trim(labels(quants(k)))//".extras",status='replace',form='unformatted') + write(iu(k)) (arr(k,i),i=1,npart) + close(iu(k)) enddo - close(iu) - deallocate(quant) + deallocate(arr) -end subroutine output_divv_files +end subroutine output_extra_quantities @@ -1561,32 +1567,41 @@ end subroutine eos_surfaces ! Particle tracker: Paint the life of a particle !+ !---------------------------------------------------------------- -subroutine track_particle(time,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use eos, only:entropy +subroutine track_particle(time,npart,particlemass,xyzh,vxyzu) + use part, only:itemp,iradxi,ilambda + use eos, only:entropy + use radiation_utils, only:Trad_from_radxi use mesa_microphysics, only:getvalue_mesa - use ionization_mod, only:ionisation_fraction + use ionization_mod, only:ionisation_fraction real, intent(in) :: time,particlemass + integer, intent(in) :: npart real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer, parameter :: nparttotrack=10,ncols=17 + integer, parameter :: nparttotrack=6,ncols=20 real :: r,v,rhopart,ponrhoi,Si,spsoundi,tempi,machi,xh0,xh1,xhe0,xhe1,xhe2,& - ekini,einti,epoti,ethi,etoti,dum,phii,pgas,mu + ekini,egasi,eradi,epoti,ereci,etoti,phii,pgas,mu,rho_cgs,Tradi,lambdai real, dimension(ncols) :: datatable character(len=17) :: filenames(nparttotrack),columns(ncols) integer :: i,k,partID(nparttotrack),ientropy,ierr - partID = (/ 1,2,3,4,5,6,7,8,9,10 /) + ! pid_orig is a map from current particle ID to original particle ID, if particles have been removed +! call initial_to_current_IDs(npart,pid_orig) + +! partID = (/ 1,2,3,4,5,6,7,8,9,10 /) + partID = (/ 193332, 966126, 1303771, 1466288, 142011, 36840 /) columns = (/ ' r',& ' v',& ' rho',& ' temp',& + ' Trad',& + ' lambda',& 'entropy',& 'spsound',& ' mach',& ' ekin',& ' epot',& - ' eth',& - ' eint',& + ' egas',& + ' erad',& + ' erec',& ' etot',& ' xHI',& ' xHII',& @@ -1605,36 +1620,43 @@ subroutine track_particle(time,particlemass,xyzh,vxyzu) r = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) v = separation(vxyzu(1:3,i),vxyz_ptmass(1:3,1)) rhopart = rhoh(xyzh(4,i), particlemass) + rho_cgs = rhopart*unit_density call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) machi = v / spsoundi select case(ieos) case(2) - ientropy = 1 + if (do_radiation) then + ientropy = 2 + else + ientropy = 1 + endif case(10,12) ientropy = 2 case default ientropy = -1 end select - if (ieos==10) then - call getvalue_mesa(rhopart*unit_density,vxyzu(4,i)*unit_ergg,3,pgas,ierr) ! Get gas pressure - mu = rhopart*unit_density * Rg * eos_vars(itemp,i) / pgas + if (ieos==10) then ! get mu + call getvalue_mesa(rho_cgs,vxyzu(4,i)*unit_ergg,3,pgas,ierr) ! Get gas pressure + mu = rho_cgs * Rg * tempi / pgas else mu = gmw endif - ! MESA ENTROPY - Si = 0. - if (ieos==10) then - Si = entropy(rhopart*unit_density,ponrhoi*rhopart*unit_pressure,mu,3,vxyzu(4,i)*unit_ergg,ierr) + Tradi = 0. + lambdai = 0. + if (do_radiation) then + lambdai = radprop(ilambda,i) + Tradi = Trad_from_radxi(rhopart,rad(iradxi,i)) + Si = entropy(rho_cgs,ponrhoi*rhopart*unit_pressure,mu,ientropy,vxyzu(4,i)*unit_ergg,ierr,Trad_in=Tradi) + else + Si = entropy(rho_cgs,ponrhoi*rhopart*unit_pressure,mu,ientropy,vxyzu(4,i)*unit_ergg,ierr) endif - ! MESA ENTROPY - ! Si = entropy(rhopart*unit_density,ponrhoi*rhopart*unit_pressure,mu,ientropy,vxyzu(4,i)*unit_ergg,ierr) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) - call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) - etoti = ekini + epoti + ethi - call ionisation_fraction(rhopart*unit_density,eos_vars(itemp,i),X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,etoti) + call ionisation_fraction(rho_cgs,tempi,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) ! Write file - datatable = (/ r,v,rhopart,eos_vars(itemp,i),Si,spsoundi,machi,ekini,epoti,ethi,einti,etoti,xh0,xh1,xhe0,xhe1,xhe2 /) + datatable = (/ r,v,rhopart,tempi,Tradi,lambdai,Si,spsoundi,machi,ekini,epoti,egasi,eradi,ereci,etoti,& + xh0,xh1,xhe0,xhe1,xhe2 /) call write_time_file(trim(adjustl(filenames(k))),columns,time,datatable,ncols,dump_number) enddo @@ -1801,7 +1823,7 @@ subroutine recombination_tau(time,npart,particlemass,xyzh,vxyzu) real, allocatable :: kappa_hist(:),rho_hist(:),tau_r(:),sepbins(:),sepbins_cm(:) logical, allocatable, save :: prev_recombined(:) real :: maxloga,minloga,kappa,kappat,kappar,xh0,xh1,xhe0,xhe1,xhe2,& - ponrhoi,spsoundi,tempi,etoti,ekini,einti,epoti,ethi,phii,dum + ponrhoi,spsoundi,tempi,etoti,ekini,ereci,egasi,eradi,epoti,ethi,phii,dum real, parameter :: recomb_th=0.9 integer :: i,j,nrecombined,bin_ind @@ -1828,7 +1850,8 @@ subroutine recombination_tau(time,npart,particlemass,xyzh,vxyzu) call get_eos_kappa_mesa(rho_part(i)*unit_density,eos_vars(itemp,i),kappa,kappat,kappar) kappa_part(i) = kappa ! In cgs units call ionisation_fraction(rho_part(i)*unit_density,eos_vars(itemp,i),X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) ! Calculate total energy + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,dum) call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rho_part(i),eos_vars(itemp,i),ethi) etoti = ekini + epoti + ethi if ((xh0 > recomb_th) .and. (.not. prev_recombined(i)) .and. (etoti < 0.)) then ! Recombination event and particle is still bound @@ -1888,7 +1911,7 @@ subroutine energy_hist(time,npart,particlemass,xyzh,vxyzu) character(len=40) :: data_formatter integer :: nbins,nhists,i,unitnum real, allocatable :: hist(:),coord(:,:),Emin(:),Emax(:) - real :: rhopart,ponrhoi,spsoundi,tempi,phii,epoti,ekini,einti,ethi,dum + real :: rhopart,ponrhoi,spsoundi,tempi,phii,epoti,ekini,ereci,egasi,eradi,ethi,dum real, allocatable :: quant(:) logical :: ilogbins @@ -1907,11 +1930,12 @@ subroutine energy_hist(time,npart,particlemass,xyzh,vxyzu) do i=1,npart rhopart = rhoh(xyzh(4,i), particlemass) call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,dum) if (ieos==10 .or. ieos==20) then call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) else - ethi = einti + ethi = ethi+ereci endif coord(i,1) = (ekini + epoti)/particlemass coord(i,2) = vxyzu(4,i) - ethi/particlemass @@ -1952,7 +1976,7 @@ subroutine energy_profile(time,npart,particlemass,xyzh,vxyzu) integer :: nbins real, allocatable :: coord(:) real, allocatable :: hist(:),quant(:,:) - real :: ekini,einti,epoti,ethi,phii,pgas,mu,dum,rhopart,ponrhoi,spsoundi,tempi,& + real :: ekini,ereci,egasi,eradi,epoti,ethi,phii,pgas,mu,dum,rhopart,ponrhoi,spsoundi,tempi,& maxcoord,mincoord,xh0,xh1,xhe0,xhe1,xhe2 character(len=17), allocatable :: filename(:),headerline(:) character(len=40) :: data_formatter @@ -2054,7 +2078,8 @@ subroutine energy_profile(time,npart,particlemass,xyzh,vxyzu) call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) select case (iquantity) case(1) ! Energy - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,dum) call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) quant(i,1) = ekini + epoti + ethi case(2) ! Entropy @@ -2070,7 +2095,8 @@ subroutine energy_profile(time,npart,particlemass,xyzh,vxyzu) quant(i,1) = entropy(rhopart*unit_density,ponrhoi*rhopart*unit_pressure,mu,ientropy,ierr=ierr) endif case(3) ! Bernoulli energy (per unit mass) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,dum) quant(i,1) = 0.5*dot_product(vxyzu(1:3,i),vxyzu(1:3,i)) + ponrhoi + vxyzu(4,i) + epoti/particlemass ! 1/2 v^2 + P/rho + phi case(4) ! Ion fraction call ionisation_fraction(rhopart*unit_density,eos_vars(itemp,i),X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) @@ -2195,14 +2221,15 @@ subroutine velocity_histogram(time,num,npart,particlemass,xyzh,vxyzu) character(len=40) :: data_formatter character(len=40) :: file_name1,file_name2 integer :: i,iu1,iu2,ncols - real :: ponrhoi,rhopart,spsoundi,phii,epoti,ekini,einti,tempi,ethi,dum + real :: ponrhoi,rhopart,spsoundi,phii,epoti,ekini,ereci,egasi,eradi,tempi,ethi,dum real, allocatable :: vbound(:),vunbound(:),vr(:) allocate(vbound(npart),vunbound(npart),vr(npart)) do i = 1,npart rhopart = rhoh(xyzh(4,i), particlemass) call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,dum) call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) vr(i) = dot_product(xyzh(1:3,i),vxyzu(1:3,i)) / sqrt(dot_product(xyzh(1:3,i),xyzh(1:3,i))) @@ -2471,111 +2498,73 @@ end subroutine planet_profile !+ !---------------------------------------------------------------- subroutine unbound_profiles(time,num,npart,particlemass,xyzh,vxyzu) - integer, intent(in) :: npart,num - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer, dimension(4) :: npart_hist - real, dimension(5,npart) :: dist_part,rad_part - real, dimension(:), allocatable :: hist_var - real :: etoti,ekini,einti,epoti,ethi,phii,dum,rhopart,ponrhoi,spsoundi,tempi - real :: maxloga,minloga - character(len=18), dimension(4) :: grid_file - character(len=40) :: data_formatter - logical, allocatable, save :: prev_unbound(:,:),prev_bound(:,:) - integer :: i,unitnum,nbins + integer, intent(in) :: npart,num + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + integer, dimension(2) :: nunbound + real, dimension(2,npart) :: dist_part,rad_part + real, dimension(:), allocatable :: hist_var + real :: e_kp,e_kpt,etoti,ekini,ereci,egasi,eradi,epoti,phii,sep,maxloga,minloga + character(len=18), dimension(2) :: grid_file + character(len=40) :: data_formatter + logical, allocatable, save :: prev_bound(:,:) + integer :: i,j,unitnum,nbins,maxj call compute_energies(time) - npart_hist = 0 ! Stores number of particles fulfilling each of the four bound/unbound criterion + nunbound = 0 ! Stores number of particles that have become newly unbound in this dump according to e_kp or e_kpt criterion nbins = 500 - rad_part = 0. ! (4,npart_hist)-array storing separations of particles - dist_part = 0. + rad_part = 0. ! (2,npart_hist)-array storing separations of newly unbound particles + dist_part = 0. ! Array of ones with size of 2? minloga = 0.5 maxloga = 4.3 allocate(hist_var(nbins)) - grid_file = (/ 'grid_unbound_th.ev', & - 'grid_unbound_kp.ev', & - ' grid_bound_kpt.ev', & - ' grid_bound_kp.ev' /) + grid_file = (/ 'grid_unbound_th.ev', 'grid_unbound_kp.ev' /) if (dump_number == 0) then allocate(prev_bound(2,npart)) - allocate(prev_unbound(2,npart)) - prev_bound = .false. - prev_unbound = .false. + prev_bound = .true. ! all particles bound to begin with endif - do i=1,npart - if (.not. isdead_or_accreted(xyzh(4,i))) then - rhopart = rhoh(xyzh(4,i), particlemass) - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) - call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,tempi,ethi) - etoti = ekini + epoti + ethi - - ! Ekin + Epot + Eth > 0 - if ((etoti > 0.) .and. (.not. prev_unbound(1,i))) then - npart_hist(1) = npart_hist(1) + 1 ! Keeps track of number of particles that have become newly unbound in this dump - rad_part(1,npart_hist(1)) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - dist_part(1,npart_hist(1)) = 1. ! Array of ones with size of npart_hist(1)? - prev_unbound(1,i) = .true. - elseif (etoti < 0.) then - prev_unbound(1,i) = .false. - endif - - ! Ekin + Epot > 0 - if ((ekini + epoti > 0.) .and. (.not. prev_unbound(2,i))) then - npart_hist(2) = npart_hist(2) + 1 - rad_part(2,npart_hist(2)) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - dist_part(2,npart_hist(2)) = 1. - prev_unbound(2,i) = .true. - elseif (ekini + epoti < 0.) then - prev_unbound(2,i) = .false. - endif - - ! Ekin + Epot + Eth < 0 - if ((etoti < 0.) .and. (.not. prev_bound(1,i))) then - npart_hist(3) = npart_hist(3) + 1 - rad_part(3,npart_hist(3)) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - dist_part(3,npart_hist(3)) = 1. - prev_bound(1,i) = .true. - elseif (etoti > 0.) then - prev_bound(1,i) = .false. - endif - - ! Ekin + Epot < 0 - if ((ekini + epoti < 0.) .and. (.not. prev_bound(2,i))) then - npart_hist(4) = npart_hist(4) + 1 - rad_part(4,npart_hist(4)) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - dist_part(4,npart_hist(4)) = 1. - prev_bound(2,i) = .true. - elseif (ekini + epoti > 0.) then - prev_bound(2,i) = .false. - endif + if (isdead_or_accreted(xyzh(4,i))) cycle + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,etoti) + e_kp = ekini + epoti + e_kpt = e_kp + egasi + eradi + + if (e_kp > 0. .and. prev_bound(2,i)) then ! newly bound by e_kp criterion + maxj = 2 + sep = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) + elseif (e_kpt > 0. .and. prev_bound(1,i)) then ! newly bound by e_kpt but not e_kp criterion + maxj = 1 + sep = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) + else ! particle state has not changed + cycle endif + + do j = 1,maxj + nunbound(j) = nunbound(j) + 1 + rad_part(j,nunbound(j)) = sep + dist_part(j,nunbound(j)) = 1. + prev_bound(j,i) = .false. + enddo enddo - do i=1,4 - call histogram_setup(rad_part(i,1:npart_hist(i)),dist_part(i,1:npart_hist(i)),hist_var,npart_hist(i),maxloga,minloga,nbins,& + do i=1,2 + call histogram_setup(rad_part(i,1:nunbound(i)),dist_part(i,1:nunbound(i)),hist_var,nunbound(i),maxloga,minloga,nbins,& .false.,.true.) - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" ! Time column plus nbins columns if (num == 0) then ! Write header line - unitnum = 1000 - open(unit=unitnum,file=trim(adjustl(grid_file(i))),status='replace') + open(newunit=unitnum,file=trim(adjustl(grid_file(i))),status='replace') write(unitnum, "(a)") '# Newly bound/unbound particles' close(unit=unitnum) endif - unitnum=1001+i - - open(unit=unitnum,file=trim(adjustl(grid_file(i))), position='append') - + open(newunit=unitnum,file=trim(adjustl(grid_file(i))), position='append') write(unitnum,"()") write(unitnum,data_formatter) time,hist_var(:) - close(unit=unitnum) enddo deallocate(hist_var) @@ -2595,7 +2584,7 @@ subroutine unbound_ionfrac(time,npart,particlemass,xyzh,vxyzu) real, intent(inout) :: xyzh(:,:),vxyzu(:,:) character(len=17) :: columns(5) integer :: i - real :: etoti,ekini,einti,epoti,ethi,phii,dum,rhopart,xion(1:4),& + real :: etoti,ekini,egasi,eradi,ereci,epoti,ethi,phii,dum,rhopart,xion(1:4),& ponrhoi,spsoundi,tempi,xh0,xh1,xhe0,xhe1,xhe2 logical, allocatable, save :: prev_unbound(:),prev_bound(:) real, allocatable, save :: ionfrac(:,:) @@ -2618,7 +2607,7 @@ subroutine unbound_ionfrac(time,npart,particlemass,xyzh,vxyzu) do i=1,npart rhopart = rhoh(xyzh(4,i), particlemass) call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,epoti,ekini,egasi,eradi,ereci,dum) call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,tempi,ethi) etoti = ekini + epoti + ethi @@ -2671,7 +2660,7 @@ subroutine unbound_temp(time,npart,particlemass,xyzh,vxyzu) real, intent(inout) :: xyzh(:,:),vxyzu(:,:) character(len=17) :: columns(1) integer :: i,final_count(7) - real :: etoti,ekini,einti,epoti,ethi,phii,dum,rhopart,& + real :: etoti,ekini,ereci,egasi,eradi,epoti,ethi,phii,dum,rhopart,& ponrhoi,spsoundi,temp_bins(7) logical, allocatable, save :: prev_unbound(:),prev_bound(:) real, allocatable, save :: temp_unbound(:) @@ -2688,7 +2677,7 @@ subroutine unbound_temp(time,npart,particlemass,xyzh,vxyzu) do i=1,npart rhopart = rhoh(xyzh(4,i), particlemass) call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),eos_vars(itemp,i),vxyzu(4,i)) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,epoti,ekini,egasi,eradi,ereci,dum) call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) etoti = ekini + epoti + ethi @@ -2743,11 +2732,10 @@ subroutine recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) integer, intent(in) :: npart,num real, intent(in) :: time,particlemass real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - real :: etoti,ekini,einti,epoti,ethi,phii,dum,rhopart,& - ponrhoi,spsoundi,tempi,pressure,temperature,xh0,xh1,xhe0,xhe1,xhe2 + real :: etoti,ekini,egasi,eradi,ereci,epoti,ethi,phii,dum,rhopart,& + ponrhoi,spsoundi,tempi,xh0,xh1,xhe0,xhe1,xhe2 character(len=40) :: data_formatter,logical_format - logical, allocatable :: isbound(:) - integer, allocatable :: H_state(:),He_state(:) + integer, allocatable :: H_state(:),He_state(:),isbound(:) integer :: i real, parameter :: recomb_th=0.05 @@ -2758,18 +2746,17 @@ subroutine recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) ! Calculate total energy rhopart = rhoh(xyzh(4,i), particlemass) call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,dum) - call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) - etoti = ekini + epoti + ethi + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,epoti,ekini,egasi,eradi,ereci,dum) + call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi,rad(:,i)) + etoti = ekini + epoti! + ethi - call get_eos_pressure_temp_mesa(rhopart*unit_density,vxyzu(4,i)*unit_ergg,pressure,temperature) ! This should depend on ieos - call ionisation_fraction(rhopart*unit_density,temperature,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) + call ionisation_fraction(rhopart*unit_density,tempi,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) ! Is unbound? if (etoti > 0.) then - isbound(i) = .false. + isbound(i) = 0 else - isbound(i) = .true. + isbound(i) = 1 endif ! H ionisation state @@ -2793,8 +2780,8 @@ subroutine recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) endif enddo - write(data_formatter, "(a,I5,a)") "(es18.10e3,", npart, "(1x,i1))" ! Time column plus npart columns - write(logical_format, "(a,I5,a)") "(es18.10e3,", npart, "(1x,L))" ! Time column plus npart columns + write(data_formatter, "(a,I7,a)") "(es18.10e3,", npart, "(1x,i1))" ! Time column plus npart columns + write(logical_format, "(a,I7,a)") "(es18.10e3,", npart, "(1x,i1))" ! Time column plus npart columns if (num == 0) then ! Write header line open(unit=1000,file="H_state.ev",status='replace') @@ -2812,13 +2799,13 @@ subroutine recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) write(1000,data_formatter) time,H_state(:) close(unit=1000) - open(unit=1000,file="He_state.ev", position='append') - write(1000,data_formatter) time,He_state(:) - close(unit=1000) + open(unit=1001,file="He_state.ev", position='append') + write(1001,data_formatter) time,He_state(:) + close(unit=1001) - open(unit=1000,file="isbound.ev", position='append') - write(1000,logical_format) time,isbound(:) - close(unit=1000) + open(unit=1002,file="isbound.ev", position='append') + write(1002,logical_format) time,isbound(:) + close(unit=1002) deallocate(isbound,H_state,He_state) @@ -2981,7 +2968,7 @@ subroutine bound_unbound_thermo(time,npart,particlemass,xyzh,vxyzu) character(len=17), allocatable :: columns(:) integer :: i, ncols real, dimension(8) :: entropy_array - real :: etoti, ekini, einti, epoti, phii, rhopart + real :: etoti, ekini, epoti, phii, rhopart,egasi,eradi,ereci real :: pres_1, proint_1, peint_1, temp_1 real :: troint_1, teint_1, entrop_1, abad_1, gamma1_1, gam_1 integer, parameter :: ient_b = 1 @@ -3004,7 +2991,8 @@ subroutine bound_unbound_thermo(time,npart,particlemass,xyzh,vxyzu) call compute_energies(time) do i=1,npart - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,phii,& + epoti,ekini,egasi,eradi,ereci,etoti) rhopart = rhoh(xyzh(4,i), particlemass) @@ -3016,7 +3004,7 @@ subroutine bound_unbound_thermo(time,npart,particlemass,xyzh,vxyzu) !sums entropy and other quantities for bound particles and unbound particles if (.not. switch(1)) then - etoti = etoti - einti + etoti = etoti - egasi - eradi - ereci endif if (etoti < 0.0) then !bound @@ -3334,7 +3322,7 @@ subroutine J_E_plane(num,npart,particlemass,xyzh,vxyzu) real, intent(in) :: particlemass,xyzh(:,:),vxyzu(:,:) character(len=17), allocatable :: columns(:) integer :: ncols,i - real :: com_xyz(3),com_vxyz(3),dum1,dum2,dum3,dum4,etoti,angmom_com(3),angmom_core(3) + real :: com_xyz(3),com_vxyz(3),dum1,dum2,dum3,dum4,dum5,dum6,etoti,angmom_com(3),angmom_core(3) real, allocatable :: data(:,:) ncols = 7 @@ -3350,7 +3338,7 @@ subroutine J_E_plane(num,npart,particlemass,xyzh,vxyzu) call get_centreofmass(com_xyz,com_vxyz,npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass) do i=1,npart - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),xyzmh_ptmass,dum1,dum2,dum3,dum4,etoti) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),xyzmh_ptmass,dum1,dum2,dum3,dum4,dum5,dum6,etoti) data(1,i) = etoti call cross_product3D(xyzh(1:3,i)-xyzmh_ptmass(1:3,1), vxyzu(1:3,i)-vxyz_ptmass(1:3,1), angmom_core) data(5:7,i) = angmom_core @@ -3751,30 +3739,59 @@ end subroutine get_gas_omega !---------------------------------------------------------------- !+ ! Calculate kinetic, gravitational potential (gas-gas and sink-gas), -! and internal energy of a gas particle. +! and other energies of a gas particle. !+ !---------------------------------------------------------------- -subroutine calc_gas_energies(particlemass,poten,xyzh,vxyzu,radprop,xyzmh_ptmass,phii,epoti,ekini,einti,etoti) +subroutine calc_gas_energies(particlemass,poten,xyzh,vxyzu,rad,xyzmh_ptmass,phii,epoti,ekini,egasi,eradi,ereci,etoti) ! Warning: Do not sum epoti or etoti as it is to obtain a total energy; this would not give the correct ! total energy due to complications related to double-counting. - use ptmass, only:get_accel_sink_gas - use part, only:nptmass,iradxi + use ptmass, only:get_accel_sink_gas + use part, only:nptmass,iradxi,itemp + use eos_idealplusrad, only:get_idealplusrad_temp,egas_from_rhoT,erad_from_rhoT real, intent(in) :: particlemass real(4), intent(in) :: poten - real, intent(in) :: xyzh(:),vxyzu(:),radprop(:) + real, intent(in) :: xyzh(:),vxyzu(:),rad(:) real, dimension(5,nptmass), intent(in) :: xyzmh_ptmass - real, intent(out) :: phii,epoti,ekini,einti,etoti - real :: fxi,fyi,fzi - - phii = 0.0 + real, intent(out) :: phii,epoti,ekini,egasi,eradi,ereci,etoti + real :: fxi,fyi,fzi,rhoi,rho_cgs,spsoundi,ponrhoi,presi,tempi,egasradi + integer :: ierr + rhoi = rhoh(xyzh(4),particlemass) + rho_cgs = rhoi*unit_density + phii = 0. call get_accel_sink_gas(nptmass,xyzh(1),xyzh(2),xyzh(3),xyzh(4),xyzmh_ptmass,fxi,fyi,fzi,phii) - epoti = 2.*poten + particlemass * phii ! For individual particles, need to multiply 2 to poten to get \sum_j G*mi*mj/r ekini = particlemass * 0.5 * dot_product(vxyzu(1:3),vxyzu(1:3)) - einti = particlemass * vxyzu(4) - if (do_radiation) einti = einti + particlemass * radprop(iradxi) - etoti = epoti + ekini + einti + egasradi = 0. + egasi = 0. + ereci = 0. + if (do_radiation) then + eradi = rad(iradxi)*particlemass + else + eradi = 0. + endif + + select case (ieos) + case(2) + egasi = vxyzu(4)*particlemass + egasradi = egasi + eradi + case(10) ! not tested + eradi = 0. ! not implemented + egasi = 0. ! not implemented + call equationofstate(ieos,ponrhoi,spsoundi,rhoi,xyzh(1),xyzh(2),xyzh(3),tempi,vxyzu(4)) + presi = ponrhoi*rhoi + call calc_thermal_energy(particlemass,10,xyzh,vxyzu,presi,tempi,egasradi,rad) + ereci = vxyzu(4)*particlemass - egasradi + case(12) + call get_idealplusrad_temp(rho_cgs,vxyzu(4)*unit_ergg,gmw,tempi,ierr) + egasi = egas_from_rhoT(tempi,gmw)/unit_ergg*particlemass + eradi = erad_from_rhoT(rho_cgs,tempi,gmw)/unit_ergg*particlemass + egasradi = egasi + eradi + case default + call fatal('calc_gas_energies',"EOS type not supported (currently, only supporting ieos=2,10,12)") + end select + + etoti = epoti + ekini + ereci + egasradi end subroutine calc_gas_energies @@ -3848,7 +3865,7 @@ subroutine stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,simp real :: proj(3),orth(3),proj_mag,orth_dist,orth_ratio real :: rhopart,ponrhoi,spsoundi,tempi real :: temp,kappa,kappat,kappar,pres - real :: ekini,epoti,einti,etoti,phii + real :: ekini,epoti,egasi,eradi,ereci,etoti,phii real :: xh0, xh1, xhe0, xhe1, xhe2 real :: temp_profile(ncols,npart) logical :: criteria @@ -3900,8 +3917,8 @@ subroutine stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,simp kappa = 1. endif - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),& - xyzmh_ptmass,phii,epoti,ekini,einti,etoti) + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),rad(:,i),& + xyzmh_ptmass,phii,epoti,ekini,egasi,eradi,ereci,etoti) call ionisation_fraction(rhopart*unit_density,temp,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) @@ -4445,10 +4462,8 @@ subroutine set_eos_options(analysis_to_perform) case(2,12) gamma = 5./3. call prompt('Enter gamma:',gamma,0.) - if (ieos==12) then - gmw = 0.618212823 - call prompt('Enter mean molecular weight for gas+rad EoS:',gmw,0.) - endif + gmw = 0.618212823 + call prompt('Enter mean molecular weight:',gmw,0.) case(10,20) gamma = 5./3. X_in = 0.69843 diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index ea1f79c52..8fe638193 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -47,6 +47,8 @@ module analysis subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) use io, only:fatal use part, only:gravity,mhd,eos_vars + use eos, only:ieos + use eos_stamatellos, only:eos_file,read_optab character(len=*), intent(in) :: dumpfile real, intent(in) :: xyzh(:,:),vxyzu(:,:) @@ -54,6 +56,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) integer, intent(in) :: npart,iunit,numfile character(len=9) :: output + integer :: ierr ! Code calculates the following alphas: @@ -71,6 +74,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) ! Read analysis options call read_analysis_options + if (ieos==23) call read_optab(eos_file,ierr) if (mhd) print*, 'This is an MHD dump: will calculate Maxwell Stress' @@ -365,7 +369,7 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass,eos_vars) real,intent(in) :: pmass real,intent(in) :: xyzh(:,:),vxyzu(:,:),eos_vars(:,:) - integer :: ibin,ipart,nbinned,iallocerr + integer :: ibin,ipart,nbinned,iallocerr,ierr real :: area,csi print '(a,I4)', 'Carrying out radial binning, number of bins: ',nbins @@ -465,7 +469,6 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) use units, only: print_units, umass,udist,utime,unit_velocity,unit_density,unit_Bfield use dim, only: gravity use part, only: mhd,rhoh,alphaind,imu,itemp - use eos, only: ieos implicit none @@ -499,9 +502,9 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) call print_units sigma(:) = sigma(:)*umass/(udist*udist) - if (ieos /= 21) then +! if (ieos /= 23) then csbin(:) = csbin(:)*unit_velocity - endif + !endif omega(:) = omega(:)/utime Keplog = 1.5 @@ -659,7 +662,7 @@ end subroutine calculate_H !+ !------------------------------------------------------- subroutine deallocate_arrays - + use eos_stamatellos, only:optable implicit none deallocate(gravxyz) @@ -670,6 +673,7 @@ subroutine deallocate_arrays deallocate(sigma,csbin,H,toomre_q,omega,epicyc) deallocate(alpha_reyn,alpha_grav,alpha_mag,alpha_art) deallocate(part_scaleheight) + if (allocated(optable)) deallocate(optable) end subroutine deallocate_arrays !-------------------------------------------------------