From c5bc2538508ab7cfbb53ba577c5462050da63b4b Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 18 Jan 2023 11:55:03 +0000 Subject: [PATCH 001/182] added interp_optab.F90 to read opacity table for Stamatellos+ 2007 cooling --- src/main/interp_optab.F90 | 193 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/main/interp_optab.F90 diff --git a/src/main/interp_optab.F90 b/src/main/interp_optab.F90 new file mode 100644 index 000000000..9d04ffe4f --- /dev/null +++ b/src/main/interp_optab.F90 @@ -0,0 +1,193 @@ +!-------------------------------------------------------------------------- +! Scrript to interpolate the opacity table myeos.dat +!-------------------------------------------------------------------------- + +module interp_optab +implicit none +contains +subroutine read_optab(OPTABLE) + use datafiles, only:find_phantom_datafile + + real, intent(out) :: OPTABLE(260,1001,6) + integer i,j,nx,ny + character(len=120) :: filepath + !haracter(len=*), parameter :: tab_eos_file='myeos.dat' + !COMMON /optable/ OPTABLE + + ! read in data file for interpolation + filepath=find_phantom_datafile('myeos.dat','cooling') + print *,"FILEPATH:",filepath + open(10, file=filepath, form="formatted", status="old") + read(10, *) nx, ny + do i = 1,nx + do j = 1,ny + read(10,*) OPTABLE(i,j,1),OPTABLE(i,j,2),OPTABLE(i,j,3),& + OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) + enddo + enddo + +end subroutine read_optab + +subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai,OPTABLE) + real, intent(in) :: ui,rhoi + real, intent(out) :: kappaBar,kappaPart,Ti,gmwi,gammai + real, intent(in) :: OPTABLE(260,1001,6) + + !real OPTABLE(260,1001,6) + integer i,j,k,nx,ny + real m,c + real kbar1,kbar2 + real kappa1,kappa2 + real Tpart1,Tpart2 + real gmw1,gmw2 + real cv + real ui_, rhoi_ + + ! interpolate through OPTABLE to find corresponding kappaBar, kappaPart and T + + if (rhoi.lt.1.0e-24) then + rhoi_ = 1.0e-24 + else + rhoi_ = rhoi + endif + + i = 1 + do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) + i = i + 1 + enddo + + if (ui.lt.0.5302E8) then + ui_ = 0.5302E8 + else + ui_ = ui + endif + + j = 1 + do while ((OPTABLE(i-1,j,3).le.ui_).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i-1,j-1,5) - OPTABLE(i-1,j,5))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,5) - m*OPTABLE(i-1,j,3) + + kbar1 = m*ui_ + c + + m = (OPTABLE(i-1,j-1,6) - OPTABLE(i-1,j,6))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,6) - m*OPTABLE(i-1,j,3) + + kappa1 = m*ui_ + c + + m = (OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,2) - m*OPTABLE(i-1,j,3) + + Tpart1 = m*ui_ + c + + m = (OPTABLE(i-1,j-1,4) - OPTABLE(i-1,j,4))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,4) - m*OPTABLE(i-1,j,3) + + gmw1 = m*ui_ + c + + j = 1 + do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i,j-1,5) - OPTABLE(i,j,5))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,5) - m*OPTABLE(i,j,3) + + kbar2 = m*ui_ + c + + m = (OPTABLE(i,j-1,6) - OPTABLE(i,j,6))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,6) - m*OPTABLE(i,j,3) + + kappa2 = m*ui_ + c + + m = (OPTABLE(i,j-1,2) - OPTABLE(i,j,2))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,2) - m*OPTABLE(i,j,3) + + Tpart2 = m*ui_ + c + + m = (OPTABLE(i,j-1,4) - OPTABLE(i,j,4))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,4) - m*OPTABLE(i,j,3) + + gmw2 = m*ui_ + c + + m = (kappa2 - kappa1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = kappa2 - m*OPTABLE(i,1,1) + + kappaPart = m*rhoi_ + c + !kappaPart = kappaPart*kappa_corr + + m = (kbar2 - kbar1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = kbar2 - m*OPTABLE(i,1,1) + + kappaBar = m*rhoi_ + c + !kappaBar = kappaBar*kappa_corr + + m = (Tpart2 - Tpart1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = Tpart2 - m*OPTABLE(i,1,1) + + Ti = m*rhoi_ + c + + m = (gmw2 - gmw1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = gmw2 - m*OPTABLE(i,1,1) + + gmwi = m*rhoi_ + c + + cv = ui_/Ti + gammai = 1.0d0 + 1.38d-16/1.67d-24/gmwi/cv +end subroutine getopac_opdep + +subroutine getintenerg_opdep(Teqi, rhoi, ueqi, OPTABLE) + real, intent(out) :: ueqi + real, intent(in) :: Teqi,rhoi + !real, intent(inout) :: OPTABLE(260,1001,6) + + real u1, u2 + real m, c + integer i, j, nx, ny + real rhoi_ + real, intent(in) :: OPTABLE(260,1001,6) + + ! interpolate through OPTABLE to obtain equilibrium internal energy + + if (rhoi.lt.1.0e-24) then + rhoi_ = 1.0e-24 + else + rhoi_ = rhoi + endif + + i = 1 + do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) + i = i + 1 + enddo + + j = 1 + do while ((OPTABLE(i-1,j,2).le.Teqi).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3))/(OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2)) + c = OPTABLE(i-1,j,3) - m*OPTABLE(i-1,j,2) + + u1 = m*Teqi + c + + j = 1 + do while ((OPTABLE(i,j,2).le.Teqi).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i,j-1,3) - OPTABLE(i,j,3))/(OPTABLE(i,j-1,2) - OPTABLE(i,j,2)) + c = OPTABLE(i,j,3) - m*OPTABLE(i,j,2) + + u2 = m*Teqi + c + + m = (u2 - u1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = u2 - m*OPTABLE(i,1,1) + + ueqi = m*rhoi_ + c +end subroutine getintenerg_opdep + +end module interp_optab + + From 79282cb433416de1b2bb4a1bb3678de052b58819 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 25 Jan 2023 14:59:17 +0000 Subject: [PATCH 002/182] Stamatellos+2007 cooling implemented. Compiles but not tested. --- build/Makefile | 1 + src/main/cooling.F90 | 12 ++- src/main/cooling_stamatellos.f90 | 81 +++++++++++++++++++ src/main/force.F90 | 11 ++- src/main/interp_optab.F90 | 10 +-- src/main/part.F90 | 16 +++- src/main/step_leapfrog.F90 | 128 ++++++++++++++++++++++++++++--- 7 files changed, 237 insertions(+), 22 deletions(-) create mode 100644 src/main/cooling_stamatellos.f90 diff --git a/build/Makefile b/build/Makefile index 61f685ea5..88a6d5f9c 100644 --- a/build/Makefile +++ b/build/Makefile @@ -507,6 +507,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ cooling_molecular.f90 \ cooling_functions.f90 \ cooling_solver.f90 \ + interp_optab.F90 cooling_stamatellos.f90 \ h2chem.f90 cooling.F90 # # equations of state diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index b6dce2532..b5105d0ba 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -14,7 +14,8 @@ module cooling ! 3 = Gammie cooling [explicit] ! 5 = Koyama & Inutuska (2002) [explicit] ! 6 = Koyama & Inutuska (2002) [implicit] -! +! 7 = Stamatellos et al. (2007) [semi-implicit] +! ! :References: ! Gail & Sedlmayr textbook Physics and chemistry of Circumstellar dust shells ! @@ -67,7 +68,8 @@ subroutine init_cooling(id,master,iprint,ierr) use cooling_molecular, only:init_cooling_molec use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver - + use cooling_stamatellos, only:init_cooling_S07 + integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr @@ -79,6 +81,8 @@ subroutine init_cooling(id,master,iprint,ierr) call init_cooling_ism() else select case(icooling) + case(7) + call init_cooling_S07(ierr) case(6) call init_cooling_KI02(ierr) case(5) @@ -103,6 +107,8 @@ subroutine init_cooling(id,master,iprint,ierr) ufloor = 3.0*kboltz*Tfloor/(2.0*gmw*mass_proton_cgs)/unit_ergg endif if (maxvxyzu < 4) ierr = 1 + elseif (icooling == 7) then + ufloor = 0. ! because we use the umin(:) array else ufloor = 0. endif @@ -179,7 +185,7 @@ subroutine write_options_cooling(iunit) if (icooling > 0) call write_options_cooling_ism(iunit) else call write_inopt(icooling,'icooling','cooling function (0=off, 1=cooling library (step), 2=cooling library (force),'// & - '3=Gammie, 5,6=KI02)',iunit) + '3=Gammie, 5,6=KI02,7=stamatellos)',iunit) select case(icooling) case(0,4,5,6) ! do nothing diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 new file mode 100644 index 000000000..cd8a18781 --- /dev/null +++ b/src/main/cooling_stamatellos.f90 @@ -0,0 +1,81 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! +module cooling_stamatellos +! +! Cooling method of Stamatellos et al. 2007 +! +! :References: Stamatellos et al. 2007 +! +! :Owner: Alison Young +! +! :Runtime parameters: None +! +! :Dependencies: +! + + implicit none + public :: init_cooling_S07, cooling_S07 + real, public :: optable(260,1001,6) + + contains + + subroutine init_cooling_S07(ierr) + use interp_optab, only:read_optab + integer, intent(out) :: ierr + + call read_optab(optable,ierr) + end subroutine init_cooling_S07 + +! +! Do cooling calculation +! + subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) + use physcon, only:steboltz,pi,solarl + use units, only:umass,udist,unit_density,unit_ergg,utime + use interp_optab, only:getopac_opdep,getintenerg_opdep + real,intent(in) :: rhoi,poti,ui,dudti,xi,yi,zi,Tfloor + real,intent(out) :: tthermi,ueqi,umini + real :: coldensi,kappaBari,kappaParti,Lstar,ri2 + real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi + real :: tcool + +! Tfloor is from input parameters and is background heating +! Add to stellar heating. Just assuming one star at (0,0,0) for now + Lstar = 0.1 !in Lsun + ri2 = xi*xi + yi*yi + zi*zi + ri2 = ri2 *udist*udist + Tirri = (Lstar*solarl/(4d0*pi*steboltz)/ri2)**0.25 + Tmini = Tfloor + Tirri + + coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) + coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 + coldensi = coldensi*umass/udist/udist + +! get opacities & Ti for ui + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + Ti,gmwi,gammai,optable) + tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) + dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg! code units +! calculate Teqi + Teqi = dudti*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + Teqi = Teqi/4.d0/steboltz + Teqi = Teqi + Tmini**4.d0 + Teqi = Teqi**0.25d0 + if (Teqi < Tmini) then + Teqi = Tmini + endif + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi,optable) + ueqi = ueqi/unit_ergg + call getintenerg_opdep(Tmini,rhoi*unit_density,umini,optable) + umini = umini/unit_ergg +! calculate thermalization timescale + tthermi = (ueqi - ui)/(dudti + dudt_rad) +! internal energy ui updated later in step + + end subroutine cooling_S07 + + end module cooling_stamatellos diff --git a/src/main/force.F90 b/src/main/force.F90 index 3533dc0f8..00ffbb6f9 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2355,7 +2355,7 @@ subroutine compute_cell(cell,listneigh,nneigh,Bevol,xyzh,vxyzu,fxyzu, & realviscosity = (irealvisc > 0) useresistiveheat = (iresistive_heating > 0) - + over_parts: do ip = 1,cell%npcell if (maxphase==maxp) then @@ -2440,8 +2440,9 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use_dustfrac,damp,icooling use part, only:h2chemistry,rhoanddhdrho,iboundary,igas,maxphase,maxvxyzu,nptmass,xyzmh_ptmass, & massoftype,get_partinfo,tstop,strain_from_dvdx,ithick,iradP,sinks_have_heating, & - nucleation,idK2,idmu,idkappa,idgamma,dust_temp - use cooling, only:energ_cooling,cooling_in_step + nucleation,idK2,idmu,idkappa,idgamma,dust_temp,ttherm,umin,uequil + use cooling, only:energ_cooling,cooling_in_step,Tfloor + use cooling_stamatellos, only:cooling_S07 use ptmass_heating, only:energ_sinkheat #ifdef IND_TIMESTEPS use part, only:ibin @@ -2810,7 +2811,9 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv endif !--add conductivity and resistive heating fxyz4 = fxyz4 + fac*fsum(idendtdissi) - if (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then + if (icooling == 7) then + call cooling_S07(rhoi,poti,vxyzu(4,i),fxyz4,xi,yi,zi,ttherm(i),uequil(i),umin(i),Tfloor) + elseif (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then if (store_dust_temperature) then if (do_nucleation) then call energ_cooling(xi,yi,zi,vxyzu(4,i),dudtcool,rhoi,dt,dust_temp(i),& diff --git a/src/main/interp_optab.F90 b/src/main/interp_optab.F90 index 9d04ffe4f..87c189a84 100644 --- a/src/main/interp_optab.F90 +++ b/src/main/interp_optab.F90 @@ -1,23 +1,23 @@ !-------------------------------------------------------------------------- -! Scrript to interpolate the opacity table myeos.dat +! Script to interpolate the opacity table myeos.dat !-------------------------------------------------------------------------- module interp_optab implicit none contains -subroutine read_optab(OPTABLE) +subroutine read_optab(OPTABLE,ierr) use datafiles, only:find_phantom_datafile real, intent(out) :: OPTABLE(260,1001,6) + integer, intent(out) :: ierr integer i,j,nx,ny character(len=120) :: filepath - !haracter(len=*), parameter :: tab_eos_file='myeos.dat' - !COMMON /optable/ OPTABLE ! read in data file for interpolation filepath=find_phantom_datafile('myeos.dat','cooling') print *,"FILEPATH:",filepath - open(10, file=filepath, form="formatted", status="old") + open(10, file=filepath, form="formatted", status="old",iostat=ierr) + if (ierr > 0) return read(10, *) nx, ny do i = 1,nx do j = 1,ny diff --git a/src/main/part.F90 b/src/main/part.F90 index c94d4a687..eefa1be45 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -57,6 +57,14 @@ module part character(len=*), parameter :: vxyzu_label(4) = (/'vx','vy','vz','u '/) character(len=*), parameter :: Bxyz_label(3) = (/'Bx','By','Bz'/) character(len=*), parameter :: Bevol_label(4) = (/'Bx/rho','By/rho','Bz/rho','psi '/) + +! +!--Stamatellos cooling +! + real,allocatable :: ttherm(:) ! Thermalisation time + real,allocatable :: uequil(:) ! Equilibrium energy + real,allocatable :: umin(:) ! Minimum energy set by Tmin + ! !--tracking particle IDs ! @@ -512,7 +520,9 @@ subroutine allocate_part call allocate_array('mu_chem', mu_chem, maxp_krome) call allocate_array('T_gas_cool', T_gas_cool, maxp_krome) call allocate_array('dudt_chem', dudt_chem, maxp_krome) - + call allocate_array('ttherm', ttherm, maxp) + call allocate_array('uequil', uequil, maxp) + call allocate_array('umin', umin, maxp) end subroutine allocate_part @@ -582,7 +592,11 @@ subroutine deallocate_part if (allocated(ibelong)) deallocate(ibelong) if (allocated(istsactive)) deallocate(istsactive) if (allocated(ibin_sts)) deallocate(ibin_sts) + if (allocated(ttherm)) deallocate(ttherm) + if (allocated(uequil)) deallocate(uequil) + if (allocated(umin)) deallocate(umin) + end subroutine deallocate_part !---------------------------------------------------------------- diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index a4a24220b..bc4d67a9e 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -103,9 +103,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iphase,iamtype,massoftype,maxphase,igas,idust,mhd,& iamboundary,get_ntypes,npartoftypetot,& dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& - dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,ics + dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,& + ics,ttherm,uequil,umin use cooling, only:cooling_in_step,ufloor - use options, only:avdecayconst,alpha,ieos,alphamax + use options, only:avdecayconst,alpha,ieos,alphamax,icooling use deriv, only:derivs use timestep, only:dterr,bignumber,tolv use mpiutils, only:reduceall_mpi @@ -154,6 +155,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif integer, parameter :: maxits = 30 logical :: converged,store_itype + real :: stama_ustep ! ! set initial quantities ! @@ -186,11 +188,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(rad,drad,pxyzu)& !$omp shared(Bevol,dBevol,dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred,ufloor) & + !$omp shared(ttherm,uequil,umin,icooling) & #ifdef IND_TIMESTEPS !$omp shared(ibin,ibin_old,twas,timei) & #endif !$omp firstprivate(itype) & - !$omp private(i,hdti) & + !$omp private(i,hdti,stama_ustep) & !$omp reduction(+:nvfloorp) predictor: do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -210,10 +213,28 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) + if (stama_ustep < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step:cooling stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vxyzu(4,i) = stama_ustep + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then @@ -273,6 +294,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none) schedule(guided,1) & !$omp shared(maxp,maxphase,maxalpha) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,divcurlv,npart,store_itype) & +!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,Bpred,dtsph,massoftype,iphase) & !$omp shared(dustevol,ddustprop,dustprop,dustproppred,dustfrac,ddustevol,dustpred,use_dustfrac) & @@ -283,7 +305,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & -!$omp private(i,spsoundi,alphaloci,divvdti) & +!$omp private(i,spsoundi,alphaloci,divvdti,stama_ustep) & !$omp firstprivate(pmassi,itype,avdecayconst,alpha) & !$omp reduction(+:nvfloorps) predict_sph: do i=1,npart @@ -323,10 +345,27 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then ppred(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 7) then + vpred(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) + if (stama_ustep < 0.) then + vpred(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step predictor: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vpred(4,i) = stama_ustep + endif + else + vpred(4,i) = uequil(i) + endif + endif + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vpred(4,i) < ufloor) then @@ -430,6 +469,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) store_itype = (maxphase==maxp .and. ntypes > 1) !$omp parallel default(none) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,npart,hdtsph,store_itype) & +!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,iphase,its) & !$omp shared(dustevol,ddustevol,use_dustfrac) & @@ -442,7 +482,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp private(dti,hdti) & #endif !$omp shared(rad,radpred,drad)& -!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi) & +!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi,stama_ustep) & !$omp private(pxi,pyi,pzi,p2i) & !$omp private(erri,v2i,eni) & !$omp reduction(max:errmax) & @@ -473,10 +513,27 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-dti/ttherm(i)) + uequil(i)*(1.d0-exp(dti/ttherm(i))) + if (stama_ustep < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step corrector:stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vxyzu(4,i) = stama_ustep + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + dti*dBevol(:,i) @@ -495,10 +552,28 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) + if (stama_ustep < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step synchronise: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vxyzu(4,i) = stama_ustep + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + endif + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then @@ -554,8 +629,25 @@ 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 == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdtsph/ttherm(i)) + uequil(i)*(1.d0-exp(hdtsph/ttherm(i))) + if (stama_ustep < 0.) then + eni = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step eni: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + eni = stama_ustep + endif + else + eni = uequil(i) + endif + 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 !if (erri > errmax) print*,id,' errmax = ',erri,' part ',i,vxi,vxoldi,vyi,vyoldi,vzi,vzoldi errmax = max(errmax,erri) @@ -584,7 +676,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif #endif - endif enddo corrector !$omp enddo !$omp end parallel @@ -638,9 +729,28 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif + + if (icooling == 7) then + if (ttherm(i) > 0.) then +! What should this be? + vxyzu(4,i) = (vxyzu(4,i) + uequil(i)*(1.d0-exp(-ABS(hdtsph)/ttherm(i))))/& + exp(-ABS(hdtsph)/ttherm(i)) + if (vxyzu(4,i) < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(vxyzu(4,i)) then + call warning("In step last: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + + if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) - hdtsph*dBevol(:,i) @@ -1339,7 +1449,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif else ! cooling without stored dust temperature - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt) + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt,poti) endif endif #endif From bceda49ed4dfa1727acf15290b91a295fc2f5894 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 27 Jan 2023 15:42:07 +0000 Subject: [PATCH 003/182] Changed so that cooling is called from step in the form dudt_cool, like the other cooling methods --- src/main/cooling.F90 | 9 ++- src/main/cooling_stamatellos.f90 | 44 ++++++++--- src/main/force.F90 | 9 +-- src/main/part.F90 | 15 ---- src/main/step_leapfrog.F90 | 122 ++----------------------------- 5 files changed, 50 insertions(+), 149 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index b5105d0ba..379a81835 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -120,7 +120,7 @@ end subroutine init_cooling ! this routine returns the effective cooling rate du/dt ! !----------------------------------------------------------------------- -subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in) +subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,dudti_sph,part_id) use io, only:fatal use eos, only:gmw,gamma use physcon, only:Rg @@ -129,9 +129,12 @@ subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,k use cooling_solver, only:energ_cooling_solver use cooling_koyamainutsuka, only:cooling_KoyamaInutsuka_explicit,& cooling_KoyamaInutsuka_implicit - + use cooling_stamatellos, only:cooling_S07 + 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 :: dudti_sph ! in code units + integer, intent(in),optional :: part_id real, intent(out) :: dudt ! in code units real :: mu,polyIndex,T_on_u,Tgas,Tdust,K2,kappa @@ -150,6 +153,8 @@ subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,k if (present(kappa_in)) kappa = kappa_in select case (icooling) + case (7) + call cooling_S07(rho,ui,dudt,xi,yi,zi,Tfloor,dudti_sph,dt,part_id) case (6) call cooling_KoyamaInutsuka_implicit(ui,rho,dt,dudt) case (5) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index cd8a18781..68e0ddaa4 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -33,16 +33,20 @@ end subroutine init_cooling_S07 ! ! Do cooling calculation ! - subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) + subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) + use io, only:warning use physcon, only:steboltz,pi,solarl use units, only:umass,udist,unit_density,unit_ergg,utime use interp_optab, only:getopac_opdep,getintenerg_opdep - real,intent(in) :: rhoi,poti,ui,dudti,xi,yi,zi,Tfloor - real,intent(out) :: tthermi,ueqi,umini + use part, only:poten + real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt + integer,intent(in) :: i + real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,Lstar,ri2 real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi - real :: tcool - + real :: tcool,ueqi,umini,tthermi,poti + + poti = poten(i) ! Tfloor is from input parameters and is background heating ! Add to stellar heating. Just assuming one star at (0,0,0) for now Lstar = 0.1 !in Lsun @@ -53,15 +57,15 @@ subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 - coldensi = coldensi*umass/udist/udist + coldensi = coldensi*umass/udist/udist ! physical units ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi,gammai,optable) - tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) - dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg! code units + tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units + dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg*utime! code units ! calculate Teqi - Teqi = dudti*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini**4.d0 Teqi = Teqi**0.25d0 @@ -73,9 +77,25 @@ subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) call getintenerg_opdep(Tmini,rhoi*unit_density,umini,optable) umini = umini/unit_ergg ! calculate thermalization timescale - tthermi = (ueqi - ui)/(dudti + dudt_rad) -! internal energy ui updated later in step - + if ((dudti_sph + dudt_rad) == 0.d0) then + tthermi = 0d0 + else + tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) + endif + +! internal energy update -> put in form where it'll work as dudtcool + if (tthermi == 0d0) then + dudti_cool = 0.d0 ! condition if denominator above is zero + else + dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + endif + if (isnan(dudti_cool)) then + print *, "poti=",poti, "rhoi=",rhoi + print *, "tcool=",tcool,"coldensi=",coldensi + print *, "Teqi=",Teqi, "dt=",dt,"tthermi=", tthermi,"ueqi=", ueqi + call warning("In Stamatellos cooling","dudticool=NaN",val=ui) + endif + end subroutine cooling_S07 end module cooling_stamatellos diff --git a/src/main/force.F90 b/src/main/force.F90 index 00ffbb6f9..2eef7f64d 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2440,9 +2440,8 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use_dustfrac,damp,icooling use part, only:h2chemistry,rhoanddhdrho,iboundary,igas,maxphase,maxvxyzu,nptmass,xyzmh_ptmass, & massoftype,get_partinfo,tstop,strain_from_dvdx,ithick,iradP,sinks_have_heating, & - nucleation,idK2,idmu,idkappa,idgamma,dust_temp,ttherm,umin,uequil - use cooling, only:energ_cooling,cooling_in_step,Tfloor - use cooling_stamatellos, only:cooling_S07 + nucleation,idK2,idmu,idkappa,idgamma,dust_temp + use cooling, only:energ_cooling,cooling_in_step use ptmass_heating, only:energ_sinkheat #ifdef IND_TIMESTEPS use part, only:ibin @@ -2811,9 +2810,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv endif !--add conductivity and resistive heating fxyz4 = fxyz4 + fac*fsum(idendtdissi) - if (icooling == 7) then - call cooling_S07(rhoi,poti,vxyzu(4,i),fxyz4,xi,yi,zi,ttherm(i),uequil(i),umin(i),Tfloor) - elseif (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then + if (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then if (store_dust_temperature) then if (do_nucleation) then call energ_cooling(xi,yi,zi,vxyzu(4,i),dudtcool,rhoi,dt,dust_temp(i),& diff --git a/src/main/part.F90 b/src/main/part.F90 index eefa1be45..d4cd51b6b 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -57,13 +57,6 @@ module part character(len=*), parameter :: vxyzu_label(4) = (/'vx','vy','vz','u '/) character(len=*), parameter :: Bxyz_label(3) = (/'Bx','By','Bz'/) character(len=*), parameter :: Bevol_label(4) = (/'Bx/rho','By/rho','Bz/rho','psi '/) - -! -!--Stamatellos cooling -! - real,allocatable :: ttherm(:) ! Thermalisation time - real,allocatable :: uequil(:) ! Equilibrium energy - real,allocatable :: umin(:) ! Minimum energy set by Tmin ! !--tracking particle IDs @@ -520,10 +513,6 @@ subroutine allocate_part call allocate_array('mu_chem', mu_chem, maxp_krome) call allocate_array('T_gas_cool', T_gas_cool, maxp_krome) call allocate_array('dudt_chem', dudt_chem, maxp_krome) - call allocate_array('ttherm', ttherm, maxp) - call allocate_array('uequil', uequil, maxp) - call allocate_array('umin', umin, maxp) - end subroutine allocate_part subroutine deallocate_part @@ -592,10 +581,6 @@ subroutine deallocate_part if (allocated(ibelong)) deallocate(ibelong) if (allocated(istsactive)) deallocate(istsactive) if (allocated(ibin_sts)) deallocate(ibin_sts) - if (allocated(ttherm)) deallocate(ttherm) - if (allocated(uequil)) deallocate(uequil) - if (allocated(umin)) deallocate(umin) - end subroutine deallocate_part diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index bc4d67a9e..c951ba2bb 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -104,9 +104,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iamboundary,get_ntypes,npartoftypetot,& dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,& - ics,ttherm,uequil,umin + ics use cooling, only:cooling_in_step,ufloor - use options, only:avdecayconst,alpha,ieos,alphamax,icooling + use options, only:avdecayconst,alpha,ieos,alphamax use deriv, only:derivs use timestep, only:dterr,bignumber,tolv use mpiutils, only:reduceall_mpi @@ -155,7 +155,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif integer, parameter :: maxits = 30 logical :: converged,store_itype - real :: stama_ustep ! ! set initial quantities ! @@ -188,12 +187,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(rad,drad,pxyzu)& !$omp shared(Bevol,dBevol,dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred,ufloor) & - !$omp shared(ttherm,uequil,umin,icooling) & #ifdef IND_TIMESTEPS !$omp shared(ibin,ibin_old,twas,timei) & #endif !$omp firstprivate(itype) & - !$omp private(i,hdti,stama_ustep) & + !$omp private(i,hdti) & !$omp reduction(+:nvfloorp) predictor: do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -213,27 +211,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) - if (stama_ustep < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step:cooling stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vxyzu(4,i) = stama_ustep - endif - else - vxyzu(4,i) = uequil(i) - endif - endif - !--floor the thermal energy if requested and required if (ufloor > 0.) then @@ -294,7 +274,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none) schedule(guided,1) & !$omp shared(maxp,maxphase,maxalpha) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,divcurlv,npart,store_itype) & -!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,Bpred,dtsph,massoftype,iphase) & !$omp shared(dustevol,ddustprop,dustprop,dustproppred,dustfrac,ddustevol,dustpred,use_dustfrac) & @@ -305,7 +284,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & -!$omp private(i,spsoundi,alphaloci,divvdti,stama_ustep) & +!$omp private(i,spsoundi,alphaloci,divvdti) & !$omp firstprivate(pmassi,itype,avdecayconst,alpha) & !$omp reduction(+:nvfloorps) predict_sph: do i=1,npart @@ -345,27 +324,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then ppred(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 7) then - vpred(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) - if (stama_ustep < 0.) then - vpred(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step predictor: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vpred(4,i) = stama_ustep - endif - else - vpred(4,i) = uequil(i) - endif - endif - !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vpred(4,i) < ufloor) then @@ -469,7 +431,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) store_itype = (maxphase==maxp .and. ntypes > 1) !$omp parallel default(none) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,npart,hdtsph,store_itype) & -!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,iphase,its) & !$omp shared(dustevol,ddustevol,use_dustfrac) & @@ -482,7 +443,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp private(dti,hdti) & #endif !$omp shared(rad,radpred,drad)& -!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi,stama_ustep) & +!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi) & !$omp private(pxi,pyi,pzi,p2i) & !$omp private(erri,v2i,eni) & !$omp reduction(max:errmax) & @@ -513,27 +474,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-dti/ttherm(i)) + uequil(i)*(1.d0-exp(dti/ttherm(i))) - if (stama_ustep < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step corrector:stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vxyzu(4,i) = stama_ustep - endif - else - vxyzu(4,i) = uequil(i) - endif - endif - if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + dti*dBevol(:,i) @@ -552,28 +496,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) - if (stama_ustep < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step synchronise: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vxyzu(4,i) = stama_ustep - endif - else - vxyzu(4,i) = uequil(i) - endif - endif endif - !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then @@ -630,22 +557,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vyi = vxyzu(2,i) + hdtsph*fxyzu(2,i) vzi = vxyzu(3,i) + hdtsph*fxyzu(3,i) if (maxvxyzu >= 4) then - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdtsph/ttherm(i)) + uequil(i)*(1.d0-exp(hdtsph/ttherm(i))) - if (stama_ustep < 0.) then - eni = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step eni: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - eni = stama_ustep - endif - else - eni = uequil(i) - endif - else - eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) - endif + eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) endif erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 @@ -729,27 +641,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif - - if (icooling == 7) then - if (ttherm(i) > 0.) then -! What should this be? - vxyzu(4,i) = (vxyzu(4,i) + uequil(i)*(1.d0-exp(-ABS(hdtsph)/ttherm(i))))/& - exp(-ABS(hdtsph)/ttherm(i)) - if (vxyzu(4,i) < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(vxyzu(4,i)) then - call warning("In step last: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - endif - else - vxyzu(4,i) = uequil(i) - endif - endif - if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then @@ -1309,7 +1203,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, fonrmax = 0. !$omp parallel default(none) & !$omp shared(maxp,maxphase) & - !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype) & + !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype,fxyzu) & !$omp shared(eos_vars,dust_temp,store_dust_temperature) & !$omp shared(dt,hdt,timei,iexternalforce,extf_is_velocity_dependent,cooling_in_step,icooling) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,idamp,damp_fac) & @@ -1449,7 +1343,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif else ! cooling without stored dust temperature - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt,poti) + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt,dudti_sph=fxyzu(4,i),part_id=i) endif endif #endif From a50fc565126eb7f9789e23c047c445a0ca937acd Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 18 Jan 2023 11:55:03 +0000 Subject: [PATCH 004/182] added interp_optab.F90 to read opacity table for Stamatellos+ 2007 cooling --- src/main/interp_optab.F90 | 193 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/main/interp_optab.F90 diff --git a/src/main/interp_optab.F90 b/src/main/interp_optab.F90 new file mode 100644 index 000000000..9d04ffe4f --- /dev/null +++ b/src/main/interp_optab.F90 @@ -0,0 +1,193 @@ +!-------------------------------------------------------------------------- +! Scrript to interpolate the opacity table myeos.dat +!-------------------------------------------------------------------------- + +module interp_optab +implicit none +contains +subroutine read_optab(OPTABLE) + use datafiles, only:find_phantom_datafile + + real, intent(out) :: OPTABLE(260,1001,6) + integer i,j,nx,ny + character(len=120) :: filepath + !haracter(len=*), parameter :: tab_eos_file='myeos.dat' + !COMMON /optable/ OPTABLE + + ! read in data file for interpolation + filepath=find_phantom_datafile('myeos.dat','cooling') + print *,"FILEPATH:",filepath + open(10, file=filepath, form="formatted", status="old") + read(10, *) nx, ny + do i = 1,nx + do j = 1,ny + read(10,*) OPTABLE(i,j,1),OPTABLE(i,j,2),OPTABLE(i,j,3),& + OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) + enddo + enddo + +end subroutine read_optab + +subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai,OPTABLE) + real, intent(in) :: ui,rhoi + real, intent(out) :: kappaBar,kappaPart,Ti,gmwi,gammai + real, intent(in) :: OPTABLE(260,1001,6) + + !real OPTABLE(260,1001,6) + integer i,j,k,nx,ny + real m,c + real kbar1,kbar2 + real kappa1,kappa2 + real Tpart1,Tpart2 + real gmw1,gmw2 + real cv + real ui_, rhoi_ + + ! interpolate through OPTABLE to find corresponding kappaBar, kappaPart and T + + if (rhoi.lt.1.0e-24) then + rhoi_ = 1.0e-24 + else + rhoi_ = rhoi + endif + + i = 1 + do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) + i = i + 1 + enddo + + if (ui.lt.0.5302E8) then + ui_ = 0.5302E8 + else + ui_ = ui + endif + + j = 1 + do while ((OPTABLE(i-1,j,3).le.ui_).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i-1,j-1,5) - OPTABLE(i-1,j,5))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,5) - m*OPTABLE(i-1,j,3) + + kbar1 = m*ui_ + c + + m = (OPTABLE(i-1,j-1,6) - OPTABLE(i-1,j,6))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,6) - m*OPTABLE(i-1,j,3) + + kappa1 = m*ui_ + c + + m = (OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,2) - m*OPTABLE(i-1,j,3) + + Tpart1 = m*ui_ + c + + m = (OPTABLE(i-1,j-1,4) - OPTABLE(i-1,j,4))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) + c = OPTABLE(i-1,j,4) - m*OPTABLE(i-1,j,3) + + gmw1 = m*ui_ + c + + j = 1 + do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i,j-1,5) - OPTABLE(i,j,5))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,5) - m*OPTABLE(i,j,3) + + kbar2 = m*ui_ + c + + m = (OPTABLE(i,j-1,6) - OPTABLE(i,j,6))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,6) - m*OPTABLE(i,j,3) + + kappa2 = m*ui_ + c + + m = (OPTABLE(i,j-1,2) - OPTABLE(i,j,2))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,2) - m*OPTABLE(i,j,3) + + Tpart2 = m*ui_ + c + + m = (OPTABLE(i,j-1,4) - OPTABLE(i,j,4))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) + c = OPTABLE(i,j,4) - m*OPTABLE(i,j,3) + + gmw2 = m*ui_ + c + + m = (kappa2 - kappa1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = kappa2 - m*OPTABLE(i,1,1) + + kappaPart = m*rhoi_ + c + !kappaPart = kappaPart*kappa_corr + + m = (kbar2 - kbar1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = kbar2 - m*OPTABLE(i,1,1) + + kappaBar = m*rhoi_ + c + !kappaBar = kappaBar*kappa_corr + + m = (Tpart2 - Tpart1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = Tpart2 - m*OPTABLE(i,1,1) + + Ti = m*rhoi_ + c + + m = (gmw2 - gmw1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = gmw2 - m*OPTABLE(i,1,1) + + gmwi = m*rhoi_ + c + + cv = ui_/Ti + gammai = 1.0d0 + 1.38d-16/1.67d-24/gmwi/cv +end subroutine getopac_opdep + +subroutine getintenerg_opdep(Teqi, rhoi, ueqi, OPTABLE) + real, intent(out) :: ueqi + real, intent(in) :: Teqi,rhoi + !real, intent(inout) :: OPTABLE(260,1001,6) + + real u1, u2 + real m, c + integer i, j, nx, ny + real rhoi_ + real, intent(in) :: OPTABLE(260,1001,6) + + ! interpolate through OPTABLE to obtain equilibrium internal energy + + if (rhoi.lt.1.0e-24) then + rhoi_ = 1.0e-24 + else + rhoi_ = rhoi + endif + + i = 1 + do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) + i = i + 1 + enddo + + j = 1 + do while ((OPTABLE(i-1,j,2).le.Teqi).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3))/(OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2)) + c = OPTABLE(i-1,j,3) - m*OPTABLE(i-1,j,2) + + u1 = m*Teqi + c + + j = 1 + do while ((OPTABLE(i,j,2).le.Teqi).and.(j.lt.1000)) + j = j + 1 + enddo + + m = (OPTABLE(i,j-1,3) - OPTABLE(i,j,3))/(OPTABLE(i,j-1,2) - OPTABLE(i,j,2)) + c = OPTABLE(i,j,3) - m*OPTABLE(i,j,2) + + u2 = m*Teqi + c + + m = (u2 - u1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) + c = u2 - m*OPTABLE(i,1,1) + + ueqi = m*rhoi_ + c +end subroutine getintenerg_opdep + +end module interp_optab + + From e1f9a72e94b1a27f8f81dbafdcbf8919f27e3e15 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 25 Jan 2023 14:59:17 +0000 Subject: [PATCH 005/182] Stamatellos+2007 cooling implemented. --- build/Makefile | 1 + src/main/cooling.F90 | 12 ++- src/main/cooling_stamatellos.f90 | 81 +++++++++++++++++++ src/main/force.F90 | 11 ++- src/main/interp_optab.F90 | 10 +-- src/main/part.F90 | 16 +++- src/main/step_leapfrog.F90 | 128 ++++++++++++++++++++++++++++--- 7 files changed, 237 insertions(+), 22 deletions(-) create mode 100644 src/main/cooling_stamatellos.f90 diff --git a/build/Makefile b/build/Makefile index 4096ff5be..0c39e430f 100644 --- a/build/Makefile +++ b/build/Makefile @@ -507,6 +507,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ cooling_molecular.f90 \ cooling_functions.f90 \ cooling_solver.f90 \ + interp_optab.F90 cooling_stamatellos.f90 \ h2chem.f90 cooling.F90 # # equations of state diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index b6dce2532..b5105d0ba 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -14,7 +14,8 @@ module cooling ! 3 = Gammie cooling [explicit] ! 5 = Koyama & Inutuska (2002) [explicit] ! 6 = Koyama & Inutuska (2002) [implicit] -! +! 7 = Stamatellos et al. (2007) [semi-implicit] +! ! :References: ! Gail & Sedlmayr textbook Physics and chemistry of Circumstellar dust shells ! @@ -67,7 +68,8 @@ subroutine init_cooling(id,master,iprint,ierr) use cooling_molecular, only:init_cooling_molec use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver - + use cooling_stamatellos, only:init_cooling_S07 + integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr @@ -79,6 +81,8 @@ subroutine init_cooling(id,master,iprint,ierr) call init_cooling_ism() else select case(icooling) + case(7) + call init_cooling_S07(ierr) case(6) call init_cooling_KI02(ierr) case(5) @@ -103,6 +107,8 @@ subroutine init_cooling(id,master,iprint,ierr) ufloor = 3.0*kboltz*Tfloor/(2.0*gmw*mass_proton_cgs)/unit_ergg endif if (maxvxyzu < 4) ierr = 1 + elseif (icooling == 7) then + ufloor = 0. ! because we use the umin(:) array else ufloor = 0. endif @@ -179,7 +185,7 @@ subroutine write_options_cooling(iunit) if (icooling > 0) call write_options_cooling_ism(iunit) else call write_inopt(icooling,'icooling','cooling function (0=off, 1=cooling library (step), 2=cooling library (force),'// & - '3=Gammie, 5,6=KI02)',iunit) + '3=Gammie, 5,6=KI02,7=stamatellos)',iunit) select case(icooling) case(0,4,5,6) ! do nothing diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 new file mode 100644 index 000000000..cd8a18781 --- /dev/null +++ b/src/main/cooling_stamatellos.f90 @@ -0,0 +1,81 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! +module cooling_stamatellos +! +! Cooling method of Stamatellos et al. 2007 +! +! :References: Stamatellos et al. 2007 +! +! :Owner: Alison Young +! +! :Runtime parameters: None +! +! :Dependencies: +! + + implicit none + public :: init_cooling_S07, cooling_S07 + real, public :: optable(260,1001,6) + + contains + + subroutine init_cooling_S07(ierr) + use interp_optab, only:read_optab + integer, intent(out) :: ierr + + call read_optab(optable,ierr) + end subroutine init_cooling_S07 + +! +! Do cooling calculation +! + subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) + use physcon, only:steboltz,pi,solarl + use units, only:umass,udist,unit_density,unit_ergg,utime + use interp_optab, only:getopac_opdep,getintenerg_opdep + real,intent(in) :: rhoi,poti,ui,dudti,xi,yi,zi,Tfloor + real,intent(out) :: tthermi,ueqi,umini + real :: coldensi,kappaBari,kappaParti,Lstar,ri2 + real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi + real :: tcool + +! Tfloor is from input parameters and is background heating +! Add to stellar heating. Just assuming one star at (0,0,0) for now + Lstar = 0.1 !in Lsun + ri2 = xi*xi + yi*yi + zi*zi + ri2 = ri2 *udist*udist + Tirri = (Lstar*solarl/(4d0*pi*steboltz)/ri2)**0.25 + Tmini = Tfloor + Tirri + + coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) + coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 + coldensi = coldensi*umass/udist/udist + +! get opacities & Ti for ui + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + Ti,gmwi,gammai,optable) + tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) + dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg! code units +! calculate Teqi + Teqi = dudti*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + Teqi = Teqi/4.d0/steboltz + Teqi = Teqi + Tmini**4.d0 + Teqi = Teqi**0.25d0 + if (Teqi < Tmini) then + Teqi = Tmini + endif + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi,optable) + ueqi = ueqi/unit_ergg + call getintenerg_opdep(Tmini,rhoi*unit_density,umini,optable) + umini = umini/unit_ergg +! calculate thermalization timescale + tthermi = (ueqi - ui)/(dudti + dudt_rad) +! internal energy ui updated later in step + + end subroutine cooling_S07 + + end module cooling_stamatellos diff --git a/src/main/force.F90 b/src/main/force.F90 index 8d76023b7..1ff10e2b3 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2352,7 +2352,7 @@ subroutine compute_cell(cell,listneigh,nneigh,Bevol,xyzh,vxyzu,fxyzu, & realviscosity = (irealvisc > 0) useresistiveheat = (iresistive_heating > 0) - + over_parts: do ip = 1,cell%npcell if (maxphase==maxp) then @@ -2437,8 +2437,9 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use_dustfrac,damp,icooling,implicit_radiation use part, only:h2chemistry,rhoanddhdrho,iboundary,igas,maxphase,maxvxyzu,nptmass,xyzmh_ptmass, & massoftype,get_partinfo,tstop,strain_from_dvdx,ithick,iradP,sinks_have_heating,luminosity, & - nucleation,idK2,idmu,idkappa,idgamma,dust_temp - use cooling, only:energ_cooling,cooling_in_step + nucleation,idK2,idmu,idkappa,idgamma,dust_temp,ttherm,umin,uequil + use cooling, only:energ_cooling,cooling_in_step,Tfloor + use cooling_stamatellos, only:cooling_S07 use ptmass_heating, only:energ_sinkheat #ifdef IND_TIMESTEPS use part, only:ibin @@ -2804,7 +2805,9 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv endif !--add conductivity and resistive heating fxyz4 = fxyz4 + fac*fsum(idendtdissi) - if (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then + if (icooling == 7) then + call cooling_S07(rhoi,poti,vxyzu(4,i),fxyz4,xi,yi,zi,ttherm(i),uequil(i),umin(i),Tfloor) + elseif (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then if (store_dust_temperature) then if (do_nucleation) then call energ_cooling(xi,yi,zi,vxyzu(4,i),dudtcool,rhoi,dt,dust_temp(i),& diff --git a/src/main/interp_optab.F90 b/src/main/interp_optab.F90 index 9d04ffe4f..87c189a84 100644 --- a/src/main/interp_optab.F90 +++ b/src/main/interp_optab.F90 @@ -1,23 +1,23 @@ !-------------------------------------------------------------------------- -! Scrript to interpolate the opacity table myeos.dat +! Script to interpolate the opacity table myeos.dat !-------------------------------------------------------------------------- module interp_optab implicit none contains -subroutine read_optab(OPTABLE) +subroutine read_optab(OPTABLE,ierr) use datafiles, only:find_phantom_datafile real, intent(out) :: OPTABLE(260,1001,6) + integer, intent(out) :: ierr integer i,j,nx,ny character(len=120) :: filepath - !haracter(len=*), parameter :: tab_eos_file='myeos.dat' - !COMMON /optable/ OPTABLE ! read in data file for interpolation filepath=find_phantom_datafile('myeos.dat','cooling') print *,"FILEPATH:",filepath - open(10, file=filepath, form="formatted", status="old") + open(10, file=filepath, form="formatted", status="old",iostat=ierr) + if (ierr > 0) return read(10, *) nx, ny do i = 1,nx do j = 1,ny diff --git a/src/main/part.F90 b/src/main/part.F90 index a996fb1f4..d706ad920 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -57,6 +57,14 @@ module part character(len=*), parameter :: vxyzu_label(4) = (/'vx','vy','vz','u '/) character(len=*), parameter :: Bxyz_label(3) = (/'Bx','By','Bz'/) character(len=*), parameter :: Bevol_label(4) = (/'Bx/rho','By/rho','Bz/rho','psi '/) + +! +!--Stamatellos cooling +! + real,allocatable :: ttherm(:) ! Thermalisation time + real,allocatable :: uequil(:) ! Equilibrium energy + real,allocatable :: umin(:) ! Minimum energy set by Tmin + ! !--tracking particle IDs ! @@ -515,7 +523,9 @@ subroutine allocate_part call allocate_array('mu_chem', mu_chem, maxp_krome) call allocate_array('T_gas_cool', T_gas_cool, maxp_krome) call allocate_array('dudt_chem', dudt_chem, maxp_krome) - + call allocate_array('ttherm', ttherm, maxp) + call allocate_array('uequil', uequil, maxp) + call allocate_array('umin', umin, maxp) end subroutine allocate_part @@ -585,7 +595,11 @@ subroutine deallocate_part if (allocated(ibelong)) deallocate(ibelong) if (allocated(istsactive)) deallocate(istsactive) if (allocated(ibin_sts)) deallocate(ibin_sts) + if (allocated(ttherm)) deallocate(ttherm) + if (allocated(uequil)) deallocate(uequil) + if (allocated(umin)) deallocate(umin) + end subroutine deallocate_part !---------------------------------------------------------------- diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index c72d280a1..e0043575f 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -103,9 +103,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iphase,iamtype,massoftype,maxphase,igas,idust,mhd,& iamboundary,get_ntypes,npartoftypetot,& dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& - dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,ics + dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,& + ics,ttherm,uequil,umin use cooling, only:cooling_in_step,ufloor - use options, only:avdecayconst,alpha,ieos,alphamax + use options, only:avdecayconst,alpha,ieos,alphamax,icooling use deriv, only:derivs use timestep, only:dterr,bignumber,tolv use mpiutils, only:reduceall_mpi @@ -155,6 +156,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif integer, parameter :: maxits = 30 logical :: converged,store_itype + real :: stama_ustep ! ! set initial quantities ! @@ -187,11 +189,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(rad,drad,pxyzu)& !$omp shared(Bevol,dBevol,dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred,ufloor) & + !$omp shared(ttherm,uequil,umin,icooling) & #ifdef IND_TIMESTEPS !$omp shared(ibin,ibin_old,twas,timei) & #endif !$omp firstprivate(itype) & - !$omp private(i,hdti) & + !$omp private(i,hdti,stama_ustep) & !$omp reduction(+:nvfloorp) predictor: do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -211,10 +214,28 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) + if (stama_ustep < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step:cooling stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vxyzu(4,i) = stama_ustep + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then @@ -274,6 +295,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none) schedule(guided,1) & !$omp shared(maxp,maxphase,maxalpha) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,divcurlv,npart,store_itype) & +!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,Bpred,dtsph,massoftype,iphase) & !$omp shared(dustevol,ddustprop,dustprop,dustproppred,dustfrac,ddustevol,dustpred,use_dustfrac) & @@ -284,7 +306,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & -!$omp private(i,spsoundi,alphaloci,divvdti) & +!$omp private(i,spsoundi,alphaloci,divvdti,stama_ustep) & !$omp firstprivate(pmassi,itype,avdecayconst,alpha) & !$omp reduction(+:nvfloorps) predict_sph: do i=1,npart @@ -324,10 +346,27 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then ppred(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 7) then + vpred(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) + if (stama_ustep < 0.) then + vpred(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step predictor: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vpred(4,i) = stama_ustep + endif + else + vpred(4,i) = uequil(i) + endif + endif + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vpred(4,i) < ufloor) then @@ -435,6 +474,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) store_itype = (maxphase==maxp .and. ntypes > 1) !$omp parallel default(none) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,npart,hdtsph,store_itype) & +!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,iphase,its) & !$omp shared(dustevol,ddustevol,use_dustfrac) & @@ -447,7 +487,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp private(dti,hdti) & #endif !$omp shared(rad,radpred,drad)& -!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi) & +!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi,stama_ustep) & !$omp private(pxi,pyi,pzi,p2i) & !$omp private(erri,v2i,eni) & !$omp reduction(max:errmax) & @@ -478,10 +518,27 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-dti/ttherm(i)) + uequil(i)*(1.d0-exp(dti/ttherm(i))) + if (stama_ustep < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step corrector:stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vxyzu(4,i) = stama_ustep + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + dti*dBevol(:,i) @@ -500,10 +557,28 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + if (icooling == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) + if (stama_ustep < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step synchronise: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + vxyzu(4,i) = stama_ustep + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + endif + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then @@ -559,8 +634,25 @@ 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 == 7) then + if (ttherm(i) > 0.) then + stama_ustep = vxyzu(4,i)*exp(-hdtsph/ttherm(i)) + uequil(i)*(1.d0-exp(hdtsph/ttherm(i))) + if (stama_ustep < 0.) then + eni = umin(i) + elseif (isnan(stama_ustep)) then + call warning("In step eni: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + else + eni = stama_ustep + endif + else + eni = uequil(i) + endif + 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 !if (erri > errmax) print*,id,' errmax = ',erri,' part ',i,vxi,vxoldi,vyi,vyoldi,vzi,vzoldi errmax = max(errmax,erri) @@ -589,7 +681,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif #endif - endif enddo corrector !$omp enddo !$omp end parallel @@ -643,9 +734,28 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) + elseif (icooling == 7) then + vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif + + if (icooling == 7) then + if (ttherm(i) > 0.) then +! What should this be? + vxyzu(4,i) = (vxyzu(4,i) + uequil(i)*(1.d0-exp(-ABS(hdtsph)/ttherm(i))))/& + exp(-ABS(hdtsph)/ttherm(i)) + if (vxyzu(4,i) < 0.) then + vxyzu(4,i) = umin(i) + elseif (isnan(vxyzu(4,i)) then + call warning("In step last: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) + endif + else + vxyzu(4,i) = uequil(i) + endif + endif + + if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) - hdtsph*dBevol(:,i) @@ -1348,7 +1458,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif else ! cooling without stored dust temperature - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt) + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt,poti) endif endif #endif From fd462b0eaffe4d253b4f5faed3fdf8243b01a83a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 15 Feb 2023 11:29:58 +0000 Subject: [PATCH 006/182] Resolve conflict --- src/main/cooling.F90 | 9 ++- src/main/cooling_stamatellos.f90 | 44 ++++++++--- src/main/force.F90 | 4 +- src/main/part.F90 | 15 ---- src/main/step_leapfrog.F90 | 122 ++----------------------------- 5 files changed, 48 insertions(+), 146 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index b5105d0ba..379a81835 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -120,7 +120,7 @@ end subroutine init_cooling ! this routine returns the effective cooling rate du/dt ! !----------------------------------------------------------------------- -subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in) +subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,dudti_sph,part_id) use io, only:fatal use eos, only:gmw,gamma use physcon, only:Rg @@ -129,9 +129,12 @@ subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,k use cooling_solver, only:energ_cooling_solver use cooling_koyamainutsuka, only:cooling_KoyamaInutsuka_explicit,& cooling_KoyamaInutsuka_implicit - + use cooling_stamatellos, only:cooling_S07 + 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 :: dudti_sph ! in code units + integer, intent(in),optional :: part_id real, intent(out) :: dudt ! in code units real :: mu,polyIndex,T_on_u,Tgas,Tdust,K2,kappa @@ -150,6 +153,8 @@ subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,k if (present(kappa_in)) kappa = kappa_in select case (icooling) + case (7) + call cooling_S07(rho,ui,dudt,xi,yi,zi,Tfloor,dudti_sph,dt,part_id) case (6) call cooling_KoyamaInutsuka_implicit(ui,rho,dt,dudt) case (5) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index cd8a18781..68e0ddaa4 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -33,16 +33,20 @@ end subroutine init_cooling_S07 ! ! Do cooling calculation ! - subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) + subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) + use io, only:warning use physcon, only:steboltz,pi,solarl use units, only:umass,udist,unit_density,unit_ergg,utime use interp_optab, only:getopac_opdep,getintenerg_opdep - real,intent(in) :: rhoi,poti,ui,dudti,xi,yi,zi,Tfloor - real,intent(out) :: tthermi,ueqi,umini + use part, only:poten + real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt + integer,intent(in) :: i + real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,Lstar,ri2 real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi - real :: tcool - + real :: tcool,ueqi,umini,tthermi,poti + + poti = poten(i) ! Tfloor is from input parameters and is background heating ! Add to stellar heating. Just assuming one star at (0,0,0) for now Lstar = 0.1 !in Lsun @@ -53,15 +57,15 @@ subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 - coldensi = coldensi*umass/udist/udist + coldensi = coldensi*umass/udist/udist ! physical units ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi,gammai,optable) - tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) - dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg! code units + tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units + dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg*utime! code units ! calculate Teqi - Teqi = dudti*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini**4.d0 Teqi = Teqi**0.25d0 @@ -73,9 +77,25 @@ subroutine cooling_S07(rhoi,poti,ui,dudti,xi,yi,zi,tthermi,ueqi,umini,Tfloor) call getintenerg_opdep(Tmini,rhoi*unit_density,umini,optable) umini = umini/unit_ergg ! calculate thermalization timescale - tthermi = (ueqi - ui)/(dudti + dudt_rad) -! internal energy ui updated later in step - + if ((dudti_sph + dudt_rad) == 0.d0) then + tthermi = 0d0 + else + tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) + endif + +! internal energy update -> put in form where it'll work as dudtcool + if (tthermi == 0d0) then + dudti_cool = 0.d0 ! condition if denominator above is zero + else + dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + endif + if (isnan(dudti_cool)) then + print *, "poti=",poti, "rhoi=",rhoi + print *, "tcool=",tcool,"coldensi=",coldensi + print *, "Teqi=",Teqi, "dt=",dt,"tthermi=", tthermi,"ueqi=", ueqi + call warning("In Stamatellos cooling","dudticool=NaN",val=ui) + endif + end subroutine cooling_S07 end module cooling_stamatellos diff --git a/src/main/force.F90 b/src/main/force.F90 index 1ff10e2b3..f62b9c67c 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2805,9 +2805,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv endif !--add conductivity and resistive heating fxyz4 = fxyz4 + fac*fsum(idendtdissi) - if (icooling == 7) then - call cooling_S07(rhoi,poti,vxyzu(4,i),fxyz4,xi,yi,zi,ttherm(i),uequil(i),umin(i),Tfloor) - elseif (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then + if (icooling > 0 .and. dt > 0. .and. .not. cooling_in_step) then if (store_dust_temperature) then if (do_nucleation) then call energ_cooling(xi,yi,zi,vxyzu(4,i),dudtcool,rhoi,dt,dust_temp(i),& diff --git a/src/main/part.F90 b/src/main/part.F90 index d706ad920..072535444 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -57,13 +57,6 @@ module part character(len=*), parameter :: vxyzu_label(4) = (/'vx','vy','vz','u '/) character(len=*), parameter :: Bxyz_label(3) = (/'Bx','By','Bz'/) character(len=*), parameter :: Bevol_label(4) = (/'Bx/rho','By/rho','Bz/rho','psi '/) - -! -!--Stamatellos cooling -! - real,allocatable :: ttherm(:) ! Thermalisation time - real,allocatable :: uequil(:) ! Equilibrium energy - real,allocatable :: umin(:) ! Minimum energy set by Tmin ! !--tracking particle IDs @@ -523,10 +516,6 @@ subroutine allocate_part call allocate_array('mu_chem', mu_chem, maxp_krome) call allocate_array('T_gas_cool', T_gas_cool, maxp_krome) call allocate_array('dudt_chem', dudt_chem, maxp_krome) - call allocate_array('ttherm', ttherm, maxp) - call allocate_array('uequil', uequil, maxp) - call allocate_array('umin', umin, maxp) - end subroutine allocate_part subroutine deallocate_part @@ -595,10 +584,6 @@ subroutine deallocate_part if (allocated(ibelong)) deallocate(ibelong) if (allocated(istsactive)) deallocate(istsactive) if (allocated(ibin_sts)) deallocate(ibin_sts) - if (allocated(ttherm)) deallocate(ttherm) - if (allocated(uequil)) deallocate(uequil) - if (allocated(umin)) deallocate(umin) - end subroutine deallocate_part diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index e0043575f..79757cfbe 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -104,9 +104,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iamboundary,get_ntypes,npartoftypetot,& dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,& - ics,ttherm,uequil,umin + ics use cooling, only:cooling_in_step,ufloor - use options, only:avdecayconst,alpha,ieos,alphamax,icooling + use options, only:avdecayconst,alpha,ieos,alphamax use deriv, only:derivs use timestep, only:dterr,bignumber,tolv use mpiutils, only:reduceall_mpi @@ -156,7 +156,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif integer, parameter :: maxits = 30 logical :: converged,store_itype - real :: stama_ustep ! ! set initial quantities ! @@ -189,12 +188,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(rad,drad,pxyzu)& !$omp shared(Bevol,dBevol,dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred,ufloor) & - !$omp shared(ttherm,uequil,umin,icooling) & #ifdef IND_TIMESTEPS !$omp shared(ibin,ibin_old,twas,timei) & #endif !$omp firstprivate(itype) & - !$omp private(i,hdti,stama_ustep) & + !$omp private(i,hdti) & !$omp reduction(+:nvfloorp) predictor: do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -214,27 +212,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) - if (stama_ustep < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step:cooling stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vxyzu(4,i) = stama_ustep - endif - else - vxyzu(4,i) = uequil(i) - endif - endif - !--floor the thermal energy if requested and required if (ufloor > 0.) then @@ -295,7 +275,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none) schedule(guided,1) & !$omp shared(maxp,maxphase,maxalpha) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,divcurlv,npart,store_itype) & -!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,Bpred,dtsph,massoftype,iphase) & !$omp shared(dustevol,ddustprop,dustprop,dustproppred,dustfrac,ddustevol,dustpred,use_dustfrac) & @@ -306,7 +285,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) #endif !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & -!$omp private(i,spsoundi,alphaloci,divvdti,stama_ustep) & +!$omp private(i,spsoundi,alphaloci,divvdti) & !$omp firstprivate(pmassi,itype,avdecayconst,alpha) & !$omp reduction(+:nvfloorps) predict_sph: do i=1,npart @@ -346,27 +325,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then ppred(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 7) then - vpred(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) - if (stama_ustep < 0.) then - vpred(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step predictor: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vpred(4,i) = stama_ustep - endif - else - vpred(4,i) = uequil(i) - endif - endif - !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vpred(4,i) < ufloor) then @@ -474,7 +436,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) store_itype = (maxphase==maxp .and. ntypes > 1) !$omp parallel default(none) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,npart,hdtsph,store_itype) & -!$omp shared(ttherm,uequil,umin,icooling) & !$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,iphase,its) & !$omp shared(dustevol,ddustevol,use_dustfrac) & @@ -487,7 +448,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp private(dti,hdti) & #endif !$omp shared(rad,radpred,drad)& -!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi,stama_ustep) & +!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi) & !$omp private(pxi,pyi,pzi,p2i) & !$omp private(erri,v2i,eni) & !$omp reduction(max:errmax) & @@ -518,27 +479,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-dti/ttherm(i)) + uequil(i)*(1.d0-exp(dti/ttherm(i))) - if (stama_ustep < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step corrector:stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vxyzu(4,i) = stama_ustep - endif - else - vxyzu(4,i) = uequil(i) - endif - endif - if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + dti*dBevol(:,i) @@ -557,28 +501,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdti/ttherm(i)) + uequil(i)*(1.d0-exp(hdti/ttherm(i))) - if (stama_ustep < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step synchronise: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - vxyzu(4,i) = stama_ustep - endif - else - vxyzu(4,i) = uequil(i) - endif - endif endif - !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then @@ -635,22 +562,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vyi = vxyzu(2,i) + hdtsph*fxyzu(2,i) vzi = vxyzu(3,i) + hdtsph*fxyzu(3,i) if (maxvxyzu >= 4) then - if (icooling == 7) then - if (ttherm(i) > 0.) then - stama_ustep = vxyzu(4,i)*exp(-hdtsph/ttherm(i)) + uequil(i)*(1.d0-exp(hdtsph/ttherm(i))) - if (stama_ustep < 0.) then - eni = umin(i) - elseif (isnan(stama_ustep)) then - call warning("In step eni: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - else - eni = stama_ustep - endif - else - eni = uequil(i) - endif - else - eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) - endif + eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) endif erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 @@ -734,27 +646,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) - elseif (icooling == 7) then - vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif - - if (icooling == 7) then - if (ttherm(i) > 0.) then -! What should this be? - vxyzu(4,i) = (vxyzu(4,i) + uequil(i)*(1.d0-exp(-ABS(hdtsph)/ttherm(i))))/& - exp(-ABS(hdtsph)/ttherm(i)) - if (vxyzu(4,i) < 0.) then - vxyzu(4,i) = umin(i) - elseif (isnan(vxyzu(4,i)) then - call warning("In step last: stama step","stama_ustep = NaN",i=i,val=vxyzu(4,i)) - endif - else - vxyzu(4,i) = uequil(i) - endif - endif - if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then @@ -1318,7 +1212,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, fonrmax = 0. !$omp parallel default(none) & !$omp shared(maxp,maxphase) & - !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype) & + !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype,fxyzu) & !$omp shared(eos_vars,dust_temp,store_dust_temperature) & !$omp shared(dt,hdt,timei,iexternalforce,extf_is_velocity_dependent,cooling_in_step,icooling) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,idamp,damp_fac) & @@ -1458,7 +1352,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif else ! cooling without stored dust temperature - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt,poti) + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt,dudti_sph=fxyzu(4,i),part_id=i) endif endif #endif From 5bc6863940d3adf84fd2148ec24c279220769bc7 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 7 Feb 2023 15:27:18 +0000 Subject: [PATCH 007/182] Renamed module for eos_stamatellos --- src/main/cooling_stamatellos.f90 | 13 +++++++------ src/main/{interp_optab.F90 => eos_stamatellos.f90} | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) rename src/main/{interp_optab.F90 => eos_stamatellos.f90} (98%) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 68e0ddaa4..d041057dd 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -24,7 +24,7 @@ module cooling_stamatellos contains subroutine init_cooling_S07(ierr) - use interp_optab, only:read_optab + use eos_stamatellos, only:read_optab integer, intent(out) :: ierr call read_optab(optable,ierr) @@ -37,7 +37,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning use physcon, only:steboltz,pi,solarl use units, only:umass,udist,unit_density,unit_ergg,utime - use interp_optab, only:getopac_opdep,getintenerg_opdep + use eos_stamatellos, only:getopac_opdep,getintenerg_opdep use part, only:poten real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i @@ -49,7 +49,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) poti = poten(i) ! Tfloor is from input parameters and is background heating ! Add to stellar heating. Just assuming one star at (0,0,0) for now - Lstar = 0.1 !in Lsun + Lstar = 0.0 !in Lsun ri2 = xi*xi + yi*yi + zi*zi ri2 = ri2 *udist*udist Tirri = (Lstar*solarl/(4d0*pi*steboltz)/ri2)**0.25 @@ -90,10 +90,11 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif if (isnan(dudti_cool)) then - print *, "poti=",poti, "rhoi=",rhoi - print *, "tcool=",tcool,"coldensi=",coldensi + print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti + print *, "poti=",poti, "rhoi=",rhoi, "Ti=", Ti + print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph print *, "Teqi=",Teqi, "dt=",dt,"tthermi=", tthermi,"ueqi=", ueqi - call warning("In Stamatellos cooling","dudticool=NaN",val=ui) + call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) endif end subroutine cooling_S07 diff --git a/src/main/interp_optab.F90 b/src/main/eos_stamatellos.f90 similarity index 98% rename from src/main/interp_optab.F90 rename to src/main/eos_stamatellos.f90 index 87c189a84..a51aa44f6 100644 --- a/src/main/interp_optab.F90 +++ b/src/main/eos_stamatellos.f90 @@ -2,7 +2,7 @@ ! Script to interpolate the opacity table myeos.dat !-------------------------------------------------------------------------- -module interp_optab +module eos_stamatellos implicit none contains subroutine read_optab(OPTABLE,ierr) @@ -188,6 +188,6 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi, OPTABLE) ueqi = m*rhoi_ + c end subroutine getintenerg_opdep -end module interp_optab +end module eos_stamatellos From 929d1d33422c02db9f67e730c4da2c6e291fdc2f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 15 Feb 2023 11:05:17 +0000 Subject: [PATCH 008/182] Implementing Stamatellos+ 2007 EOS rather than adiabatic with polytropic cooling. --- src/main/cooling.F90 | 10 +++++----- src/main/cooling_stamatellos.f90 | 19 ++++++------------ src/main/eos.F90 | 33 ++++++++++++++++++++++++++++---- src/main/eos_stamatellos.f90 | 16 ++++++++-------- src/main/readwrite_infile.F90 | 6 +++--- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 379a81835..0e38a9690 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -34,7 +34,7 @@ module cooling use options, only:icooling use timestep, only:C_cool use cooling_solver, only:T0_value ! expose to other routines - + implicit none character(len=*), parameter :: label = 'cooling' @@ -61,14 +61,13 @@ subroutine init_cooling(id,master,iprint,ierr) use dim, only:maxvxyzu,h2chemistry use units, only:unit_ergg use physcon, only:mass_proton_cgs,kboltz - use io, only:error - use eos, only:gamma,gmw + use io, only:error,fatal + use eos, only:gamma,gmw,ieos use cooling_ism, only:init_cooling_ism use chem, only:init_chem use cooling_molecular, only:init_cooling_molec use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver - use cooling_stamatellos, only:init_cooling_S07 integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr @@ -82,7 +81,8 @@ subroutine init_cooling(id,master,iprint,ierr) else select case(icooling) case(7) - call init_cooling_S07(ierr) + if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=7 requires ieos=21',var='ieos',ival=ieos) + ! nothing to do. Initialised in eos.F90 case(6) call init_cooling_KI02(ierr) case(5) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index d041057dd..83a72f258 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -18,18 +18,10 @@ module cooling_stamatellos ! implicit none - public :: init_cooling_S07, cooling_S07 - real, public :: optable(260,1001,6) + public :: cooling_S07 contains - subroutine init_cooling_S07(ierr) - use eos_stamatellos, only:read_optab - integer, intent(out) :: ierr - - call read_optab(optable,ierr) - end subroutine init_cooling_S07 - ! ! Do cooling calculation ! @@ -37,7 +29,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning use physcon, only:steboltz,pi,solarl use units, only:umass,udist,unit_density,unit_ergg,utime - use eos_stamatellos, only:getopac_opdep,getintenerg_opdep + use eos_stamatellos use part, only:poten real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i @@ -61,16 +53,17 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& - Ti,gmwi,gammai,optable) + Ti,gmwi,gammai) tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg*utime! code units ! calculate Teqi Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini**4.d0 - Teqi = Teqi**0.25d0 - if (Teqi < Tmini) then + if (Teqi < Tmini**4.d0) then Teqi = Tmini + else + Teqi = Teqi**0.25d0 endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi,optable) ueqi = ueqi/unit_ergg diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 168b3e63a..4cce65c2e 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -23,7 +23,8 @@ module eos ! 14 = locally isothermal prescription from Farris et al. (2014) for binary system ! 15 = Helmholtz free energy eos ! 16 = Shen eos -! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) + ! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) +! 21 = read tabulated eos of Stametellos et al. (2007) ! ! :References: ! Lodato & Pringle (2007) @@ -41,12 +42,12 @@ module eos ! :Dependencies: dim, dump_utils, eos_barotropic, eos_gasradrec, ! eos_helmholtz, eos_idealplusrad, eos_mesa, eos_piecewise, eos_shen, ! eos_stratified, infile_utils, io, mesa_microphysics, part, physcon, -! units +! units, eos_stamatellos ! use part, only:ien_etotal,ien_entropy,ien_type use dim, only:gr implicit none - integer, parameter, public :: maxeos = 20 + integer, parameter, public :: maxeos = 21 real, public :: polyk, polyk2, gamma real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 logical, public :: extract_eos_from_hdr = .false. @@ -117,6 +118,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam use eos_stratified, only:get_eos_stratified use eos_barotropic, only:get_eos_barotropic use eos_piecewise, only:get_eos_piecewise + use eos_stamatellos integer, intent(in) :: eos_type real, intent(in) :: rhoi,xi,yi,zi real, intent(out) :: ponrhoi,spsoundi @@ -128,7 +130,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam real :: r1,r2 real :: gammai,temperaturei,mui,imui,X_i,Z_i real :: cgsrhoi,cgseni,cgspresi,presi,gam1,cgsspsoundi - real :: uthermconst + real :: uthermconst,kappaBar,kappaPart,gmwi #ifdef GR real :: enthi,pondensi ! Check to see if adiabatic equation of state is being used. @@ -395,6 +397,25 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam tempi = temperaturei if (present(mu_local)) mu_local = 1./imui + case(21) +! +!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=7 +! + if (eni < 0.) then + call fatal('eos','utherm < 0',var='u',val=eni) + endif + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,gmwi,gammai) + + if (gammai > 1.0001) then + ponrhoi = (gammai-1.)*eni ! use this if en is thermal energy + else + ponrhoi = 2./3.*eni ! en is thermal energy and gamma = 1 + endif + + spsoundi = sqrt(gammai*ponrhoi) + case default spsoundi = 0. ! avoids compiler warnings ponrhoi = 0. @@ -419,6 +440,7 @@ subroutine init_eos(eos_type,ierr) use eos_barotropic, only:init_eos_barotropic use eos_shen, only:init_eos_shen_NL3 use eos_gasradrec, only:init_eos_gasradrec + use eos_stamatellos,only:optable,read_optab use dim, only:maxvxyzu,do_radiation integer, intent(in) :: eos_type integer, intent(out) :: ierr @@ -494,7 +516,10 @@ subroutine init_eos(eos_type,ierr) call error('eos','ieos=20, cannot use eos with radiation, will double count radiation pressure') ierr = ierr_option_conflict endif + case(21) + call read_optab(ierr) + end select done_init_eos = .true. diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index a51aa44f6..c5cc1e390 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -3,12 +3,14 @@ !-------------------------------------------------------------------------- module eos_stamatellos -implicit none + implicit none + real, public :: optable(260,1001,6) + public :: read_optab,getopac_opdep contains -subroutine read_optab(OPTABLE,ierr) + +subroutine read_optab(ierr) use datafiles, only:find_phantom_datafile - real, intent(out) :: OPTABLE(260,1001,6) integer, intent(out) :: ierr integer i,j,nx,ny character(len=120) :: filepath @@ -28,13 +30,11 @@ subroutine read_optab(OPTABLE,ierr) end subroutine read_optab -subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai,OPTABLE) +subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) real, intent(in) :: ui,rhoi real, intent(out) :: kappaBar,kappaPart,Ti,gmwi,gammai - real, intent(in) :: OPTABLE(260,1001,6) - !real OPTABLE(260,1001,6) - integer i,j,k,nx,ny + integer i,j,nx,ny real m,c real kbar1,kbar2 real kappa1,kappa2 @@ -145,7 +145,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi, OPTABLE) real u1, u2 real m, c - integer i, j, nx, ny + integer i, j real rhoi_ real, intent(in) :: OPTABLE(260,1001,6) diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index c6502b640..f77c4ee78 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -223,7 +223,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) ! thermodynamics ! call write_options_eos(iwritein) - if (maxvxyzu >= 4 .and. (ieos==2 .or. ieos==10 .or. ieos==15 .or. ieos==12 .or. ieos==16) ) then + if (maxvxyzu >= 4 .and. (ieos==2 .or. ieos==10 .or. ieos==15 .or. ieos==12 .or. ieos==16 .or. ieos==21) ) then call write_inopt(ipdv_heating,'ipdv_heating','heating from PdV work (0=off, 1=on)',iwritein) call write_inopt(ishock_heating,'ishock_heating','shock heating (0=off, 1=on)',iwritein) if (mhd) then @@ -700,14 +700,14 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (beta > 4.) call warn(label,'very high beta viscosity set') #ifndef MCFOST if (maxvxyzu >= 4 .and. (ieos /= 2 .and. ieos /= 4 .and. ieos /= 10 .and. ieos /=11 .and. & - ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 20)) & + ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 20 .and. ieos/=21)) & call fatal(label,'only ieos=2 makes sense if storing thermal energy') #endif if (irealvisc < 0 .or. irealvisc > 12) call fatal(label,'invalid setting for physical viscosity') if (shearparam < 0.) call fatal(label,'stupid value for shear parameter (< 0)') if (irealvisc==2 .and. shearparam > 1) call error(label,'alpha > 1 for shakura-sunyaev viscosity') if (iverbose > 99 .or. iverbose < -9) call fatal(label,'invalid verboseness setting (two digits only)') - if (icooling > 0 .and. ieos /= 2) call fatal(label,'cooling requires adiabatic eos (ieos=2)') + if (icooling > 0 .and. ieos /= 2 .and. ieos/=21) call fatal(label,'cooling requires adiabatic eos (ieos=2)') if (icooling > 0 .and. (ipdv_heating <= 0 .or. ishock_heating <= 0)) & call fatal(label,'cooling requires shock and work contributions') if (((isink_radiation == 1 .or. isink_radiation == 3 ) .and. idust_opacity == 0 ) & From 145972d5dce2963d2807e8abf2a4e473fc33c0ae Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 17 Feb 2023 09:58:23 +0000 Subject: [PATCH 009/182] Changes to eos_stamatellos implementation --- build/Makefile | 4 ++-- src/main/force.F90 | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/build/Makefile b/build/Makefile index 0c39e430f..53a5074ed 100644 --- a/build/Makefile +++ b/build/Makefile @@ -507,13 +507,13 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ cooling_molecular.f90 \ cooling_functions.f90 \ cooling_solver.f90 \ - interp_optab.F90 cooling_stamatellos.f90 \ + cooling_stamatellos.f90 \ h2chem.f90 cooling.F90 # # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos.F90 +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.F90 eos.F90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.F90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 diff --git a/src/main/force.F90 b/src/main/force.F90 index f62b9c67c..168eaf1df 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2437,9 +2437,8 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use_dustfrac,damp,icooling,implicit_radiation use part, only:h2chemistry,rhoanddhdrho,iboundary,igas,maxphase,maxvxyzu,nptmass,xyzmh_ptmass, & massoftype,get_partinfo,tstop,strain_from_dvdx,ithick,iradP,sinks_have_heating,luminosity, & - nucleation,idK2,idmu,idkappa,idgamma,dust_temp,ttherm,umin,uequil - use cooling, only:energ_cooling,cooling_in_step,Tfloor - use cooling_stamatellos, only:cooling_S07 + nucleation,idK2,idmu,idkappa,idgamma,dust_temp + use cooling, only:energ_cooling,cooling_in_step use ptmass_heating, only:energ_sinkheat #ifdef IND_TIMESTEPS use part, only:ibin From e91de33db40159ee6bb48b6f620208fa3a4421bf Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 28 Feb 2023 09:30:15 +0000 Subject: [PATCH 010/182] Fixes for Stamatellos eos & cooling --- build/Makefile | 3 ++- build/Makefile_setups | 10 ++++++++++ src/main/cooling.F90 | 2 ++ src/main/cooling_stamatellos.f90 | 4 ++++ src/main/eos.F90 | 2 +- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/build/Makefile b/build/Makefile index 53a5074ed..faf7fb35e 100644 --- a/build/Makefile +++ b/build/Makefile @@ -513,6 +513,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 + SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.F90 eos.F90 ifeq ($(HDF5), yes) @@ -535,7 +536,7 @@ SOURCES= physcon.f90 ${CONFIG} ${SRCKERNEL} io.F90 units.f90 boundary.f90 \ utils_sort.f90 utils_supertimestep.F90 utils_tables.f90 utils_gravwave.f90 \ utils_sphNG.f90 utils_vectors.f90 utils_datafiles.f90 datafiles.f90 \ gitinfo.f90 ${SRCFASTMATH} random.f90 ${SRCEOS} cullendehnen.f90 ${SRCNIMHD} ${SRCGR} \ - checkoptions.F90 viscosity.f90 damping.f90 options.f90 cons2primsolver.f90 radiation_utils.f90 cons2prim.f90 \ + checkoptions.F90 viscosity.f90 damping.f90 options.f90 cons2primsolver.f90 radiation_utils.f90 cons2prim.f90 \ centreofmass.f90 ${SRCPOT} checkconserved.f90 \ utils_filenames.f90 utils_summary.F90 ${SRCCHEM} ${SRCDUST} \ partinject.F90 utils_inject.f90 dust_formation.F90 ptmass_radiation.F90 ptmass_heating.F90 \ diff --git a/build/Makefile_setups b/build/Makefile_setups index 50428ba0e..2688ac702 100644 --- a/build/Makefile_setups +++ b/build/Makefile_setups @@ -403,6 +403,16 @@ ifeq ($(SETUP), sphereinbox) KNOWN_SETUP=yes endif +ifeq ($(SETUP), sphere) +# sphere setup + ISOTHERMAL=no + PERIODIC=no + IND_TIMESTEPS=yes + GRAVITY=yes + SETUPFILE= velfield_fromcubes.f90 setup_sphere.f90 +KNOWN_SETUP=yes +endif + ifeq ($(SETUP), shock) # shock tube tests PERIODIC=yes diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 0e38a9690..4191ab656 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -68,6 +68,7 @@ subroutine init_cooling(id,master,iprint,ierr) use cooling_molecular, only:init_cooling_molec use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver + use eos_stamatellos, only:read_optab integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr @@ -83,6 +84,7 @@ subroutine init_cooling(id,master,iprint,ierr) case(7) if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=7 requires ieos=21',var='ieos',ival=ieos) ! nothing to do. Initialised in eos.F90 + if (ieos ==2) call read_optab(ierr) case(6) call init_cooling_KI02(ierr) case(5) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 83a72f258..945ee57ba 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -82,12 +82,16 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) else dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif + if (isnan(dudti_cool)) then print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti print *, "poti=",poti, "rhoi=",rhoi, "Ti=", Ti print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph print *, "Teqi=",Teqi, "dt=",dt,"tthermi=", tthermi,"ueqi=", ueqi call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) + stop + else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + dudti_cool = (umini - ui)/dt endif end subroutine cooling_S07 diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 4cce65c2e..0437fa8ea 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -402,7 +402,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam !--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=7 ! if (eni < 0.) then - call fatal('eos','utherm < 0',var='u',val=eni) + call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) endif cgsrhoi = rhoi * unit_density cgseni = eni * unit_ergg From 81459e116478058c203ed28205468a3908f261f1 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 1 Mar 2023 13:21:31 +0000 Subject: [PATCH 011/182] src/setup/setup_sphere.f90 --- src/setup/setup_sphere.f90 | 964 +++++++++++++++++++++++++++++++++++++ 1 file changed, 964 insertions(+) create mode 100644 src/setup/setup_sphere.f90 diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 new file mode 100644 index 000000000..fc314237d --- /dev/null +++ b/src/setup/setup_sphere.f90 @@ -0,0 +1,964 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! +module setup +! +! This module sets up a sphere-in-a-box: a cold, dense sphere placed in +! a warm medium; the two media are in pressure-equilibrium. +! This currently works for gas-only and two-fluid dust. +! +! :References: None +! +! :Owner: James Wurster +! +! :Runtime parameters: +! - BEfac : *over-density factor of the BE sphere [code units]* +! - BEmass : *mass radius of the BE sphere [code units]* +! - BErad_norm : *normalised radius of the BE sphere* +! - BErad_phys : *physical radius of the BE sphere [code units]* +! - BErho_cen : *central density of the BE sphere [code units]* +! - Bzero : *Magnetic field strength in Gauss* +! - ang_Bomega : *Angle (degrees) between B and rotation axis* +! - angvel : *angular velocity in rad/s* +! - beta_r : *rotational-to-gravitational energy ratio* +! - cs_sphere_cgs : *sound speed in sphere in cm/s* +! - density_contrast : *density contrast in code units* +! - dist_unit : *distance unit (e.g. au)* +! - dust_to_gas_ratio : *dust-to-gas ratio* +! - form_binary : *the intent is to form a central binary* +! - graindenscgs : *grain density [g/cm^3]* +! - grainsizecgs : *grain size in [cm]* +! - h_acc : *accretion radius (code units)* +! - h_soft_sinksink : *sink-sink softening radius (code units)* +! - iBE_options : *The set of parameters to define the BE sphere* +! - icreate_sinks : *1: create sinks. 0: do not create sinks* +! - lattice : *particle lattice (random,cubic,closepacked,hcp,hexagonal)* +! - lbox : *length of a box side in terms of spherical radii* +! - mass_unit : *mass unit (e.g. solarm)* +! - masstoflux : *mass-to-magnetic flux ratio in units of critical value* +! - ndusttypes : *number of grain sizes* +! - np : *requested number of particles in sphere* +! - r_crit : *critical radius (code units)* +! - r_sphere : *radius of sphere in code units* +! - rho_final : *final maximum density (<=0 to ignore) (cgs units)* +! - rho_pert_amp : *amplitude of density perturbation* +! - rms_mach : *turbulent rms mach number* +! - shuffle_parts : *relax particles by shuffling* +! - sindex : *power-law index, e.g. MRN* +! - smaxcgs : *maximum grain size [cm]* +! - smincgs : *minimum grain size [cm]* +! - totmass_sphere : *mass of sphere in code units* +! - use_BE_sphere : *centrally condense as a BE sphere* +! +! :Dependencies: boundary, centreofmass, datafiles, dim, dust, eos, +! eos_barotropic, infile_utils, io, kernel, mpidomain, options, part, +! physcon, prompting, ptmass, rho_profile, set_dust, set_dust_options, +! setup_params, spherical, timestep, unifdis, units, +! utils_shuffleparticles, velfield +! + use part, only:mhd,graindens,grainsize,ndusttypes,ndustsmall + use dim, only:use_dust,maxvxyzu,periodic,maxdustsmall + use options, only:calc_erot + use dust, only:grainsizecgs,graindenscgs + use set_dust_options, only:grainsizeinp,graindensinp,igrainsize,igraindens,& + smincgs,smaxcgs,sindex,dustbinfrac + implicit none + + public :: setpart + + private + !--private module variables + real :: xmini(3), xmaxi(3) + real :: density_contrast,totmass_sphere,r_sphere,cs_sphere,cs_sphere_cgs + real :: angvel,beta_r,Bzero_G,masstoflux,dtg,ang_Bomega,rms_mach + real :: rho_pert_amp,lbox + real :: BErho_cen,BErad_phys,BErad_norm,BEmass,BEfac + real :: r_crit_setup,h_acc_setup,h_soft_sinksink_setup,rhofinal_setup + real(kind=8) :: udist,umass + integer :: np,iBEparam,icreate_sinks_setup + logical :: BEsphere,binary,mu_not_B,cs_in_code,angvel_not_betar,shuffle_parts + logical :: is_cube = .true. ! if false, then can set a rectangle if BEsphere=false; for backwards compatibility + character(len=20) :: dist_unit,mass_unit,lattice + character(len= 1), parameter :: labelx(3) = (/'x','y','z'/) + +contains + +!---------------------------------------------------------------- +!+ +! setup for a sphere-in-a-box +!+ +!---------------------------------------------------------------- +subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_out,time,fileprefix) + use physcon, only:pi,solarm,hours,years,au + use dim, only:maxdusttypes,use_dustgrowth,maxdustlarge + use setup_params, only:rhozero,npart_total,rmax,ihavesetupB + use io, only:master,fatal,iprint + use unifdis, only:set_unifdis + use spherical, only:set_sphere + use rho_profile, only:rho_bonnorebert,prompt_BEparameters + use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound + use prompting, only:prompt + use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity + use eos, only:polyk2,ieos,gmw + use eos_barotropic, only:rhocrit0cgs,drhocrit0 + use part, only:Bxyz,Bextx,Bexty,Bextz,igas,idust,set_particle_type,hfact,dustfrac + use set_dust_options, only:dustbinfrac,set_dust_default_options,set_dust_interactively,dust_method + use dust, only:ilimitdustflux + use timestep, only:dtmax,tmax,dtmax_dratio,dtmax_min + use centreofmass, only:reset_centreofmass + use options, only:nfulldump,rhofinal_cgs,hdivbbmax_max,use_dustfrac + use kernel, only:hfact_default + use mpidomain, only:i_belong + use ptmass, only:icreate_sinks,r_crit,h_acc,h_soft_sinksink + use velfield, only:set_velfield_from_cubes + use datafiles, only:find_phantom_datafile + use set_dust, only:set_dustfrac,set_dustbinfrac + use utils_shuffleparticles, only:shuffleparticles + integer, intent(in) :: id + integer, intent(inout) :: npart + integer, intent(out) :: npartoftype(:) + real, intent(out) :: xyzh(:,:) + real, intent(out) :: vxyzu(:,:) + real, intent(out) :: massoftype(:) + real, intent(out) :: polyk,gamma,hfact_out + real, intent(inout) :: time + character(len=20), intent(in) :: fileprefix + character(len=20), parameter :: filevx = 'cube_v1.dat' + character(len=20), parameter :: filevy = 'cube_v2.dat' + character(len=20), parameter :: filevz = 'cube_v3.dat' + real(kind=8) :: h_acc_in + integer :: i,np_in,npartsphere,npmax,iBElast,ierr + integer :: iBE,ilattice + real :: totmass,vol_box,psep,psep_box,pmass_dusttogas + real :: vol_sphere,dens_sphere,dens_medium,cs_medium,angvel_code,przero + real :: totmass_box,t_ff,r2,area,Bzero,rmasstoflux_crit + real :: rxy2,rxyz2,phi,dphi,central_density,edge_density,rmsmach,v2i,turbfac,rhocritTcgs,ui + real, allocatable :: rtab(:),rhotab(:) + logical :: iexist + logical :: make_sinks = .true. ! the default prompt is to ask to make sinks + character(len=120) :: filex,filey,filez + character(len=100) :: filename,cwd + character(len=40) :: fmt + character(len=10) :: h_acc_char + logical :: usebox = .false. + !--Initialise dust distribution, if using dust + if (use_dust) call set_dust_default_options() + + filename = trim(fileprefix)//'.setup' + print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)",& + ' Sphere-in-box setup: Almost Archimedes'' greatest achievement.' + + inquire(file=filename,exist=iexist) + if (iexist) then + call read_setupfile(filename,ierr) + np_in = np + if (ierr /= 0) then + if (id==master) call write_setupfile(filename) + stop + endif + elseif (id==master) then + print "(a,/)",trim(filename)//' not found: using interactive setup' + dist_unit = '1.0d16cm' + mass_unit = 'solarm' + ierr = 1 + do while (ierr /= 0) + call prompt('Enter mass unit (e.g. solarm,jupiterm,earthm)',mass_unit) + call select_unit(mass_unit,umass,ierr) + if (ierr /= 0) print "(a)",' ERROR: mass unit not recognised' + enddo + ierr = 1 + do while (ierr /= 0) + call prompt('Enter distance unit (e.g. au,pc,kpc,0.1pc)',dist_unit) + call select_unit(dist_unit,udist,ierr) + if (ierr /= 0) print "(a)",' ERROR: length unit not recognised' + enddo + ! + ! units + ! + call set_units(dist=udist,mass=umass,G=1.d0) + ! + ! prompt user for settings + ! + npmax = int(2.0/3.0*size(xyzh(1,:))) ! approx max number allowed in sphere given size(xyzh(1,:)) + if (npmax < 300000) then + np = npmax + elseif (npmax < 1000000) then + np = 300000 + else + np = 1000000 + endif + call prompt('Enter the approximate number of particles in the sphere',np,0,npmax) + np_in = np + + lattice = 'closepacked' + ilattice = 3 + call prompt('Enter the type of particle lattice (1=random,2=cubic,3=closepacked,4=hexagonal)',ilattice,0,4) + if (ilattice==1) then + lattice = 'random' + shuffle_parts = .false. + elseif (ilattice==2) then + lattice = 'cubic' + elseif (ilattice==4) then + lattice = 'hexagonal' + endif + + shuffle_parts = .false. + if (ilattice==1) shuffle_parts = .true. + call prompt('Relax particles by shuffling?',shuffle_parts) + + BEsphere = .false. + call prompt('Centrally condense the sphere as a BE sphere?',BEsphere) + + if (.not. BEsphere) then + r_sphere = 4. + call prompt('Enter radius of sphere in units of '//dist_unit,r_sphere,0.) + lbox = 4. + call prompt('Enter the box size in units of spherical radii: ',lbox,1.) + if (.not. is_cube) then + do i=1,3 + xmini(i) = -0.5*(lbox*r_sphere) + xmaxi(i) = -xmini(i) + enddo + endif + + totmass_sphere = 1.0 + call prompt('Enter total mass in sphere in units of '//mass_unit,totmass_sphere,0.) + else + call prompt_BEparameters(iBEparam,BErho_cen,BErad_phys,BErad_norm,BEmass,BEfac,umass,udist,au,solarm) + lbox = 4. + call prompt('Enter the box size in units of spherical radii: ',lbox,1.) + endif + + density_contrast = 30.0 + call prompt('Enter density contrast between sphere and box ',density_contrast,1.) + + binary = .false. + call prompt('Do you intend to form a binary system (i.e. add an m=2 perturbation)?',binary) + + if (binary) then + cs_sphere_cgs = 18696.96 ! cm/s ~ 5K assuming mu = 2.31 & gamma = 5/3 + else + cs_sphere_cgs = 21888.0 ! cm/s ~ 8K assuming mu = 2.31 & gamma = 5/3 + endif + call prompt('Enter sound speed in sphere in units of cm/s',cs_sphere_cgs,0.) + + if (binary) then + angvel = 1.006d-12 + else + angvel = 1.77d-13 + endif + angvel_not_betar = .true. + beta_r = 0.02 + call prompt('Input angular velocity (true); else input ratio of rotational-to-potential energy ',angvel_not_betar) + if (angvel_not_betar) then + call prompt('Enter angular rotation speed in rad/s ',angvel,0.) + else + call prompt('Enter ratio of rotational-to-potential energy ',beta_r,0.) + endif + + rms_mach = 0. + call prompt('Enter the Mach number of the cloud turbulence',rms_mach,0.) + + if (mhd) then + Bzero_G = 1.0d-4 ! G + masstoflux = 5.0 + ang_Bomega = 180.0 + mu_not_B = .true. + call prompt('Input the mass-to-flux ratio (true); else input the magnetic field strength ',mu_not_B) + if (mu_not_B) then + call prompt('Enter mass-to-flux ratio in units of critical value ',masstoflux,0.) + else + call prompt('Enter magnetic field strength in Gauss ',Bzero_G,0.) + endif + call prompt('Enter the angle (degrees) between B and the rotation axis? ',ang_Bomega) + endif + + if (use_dust) then + !--currently assume one fluid dust + dtg = 0.01 + grainsize = 0. + graindens = 0. + grainsizecgs = 0.1 + graindenscgs = 3. + ndustsmall = 1 + smincgs = 1.e-5 + smaxcgs = 1. + sindex = 3.5 + call prompt('Enter total dust to gas ratio',dtg,0.) + call prompt('How many grain sizes do you want?',ndustsmall,1,maxdustsmall) + ndusttypes = ndustsmall + if (ndusttypes > 1) then + !--grainsizes + call prompt('Enter minimum grain size in cm',smincgs,0.) + call prompt('Enter maximum grain size in cm',smaxcgs,0.) + !--mass distribution + call prompt('Enter power-law index, e.g. MRN',sindex) + !--grain density + call prompt('Enter grain density in g/cm^3',graindenscgs,0.) + else + call prompt('Enter grain size in cm',grainsizecgs,0.) + call prompt('Enter grain density in g/cm^3',graindenscgs,0.) + endif + endif + + if (binary) then + rho_pert_amp = 0.1 + call prompt('Enter the amplitute of the density perturbation ',rho_pert_amp,0.0,0.4) + endif + + ! ask about sink particle details; these will not be saved to the .setup file since they exist in the .in file + ! + call prompt('Do you wish to dynamically create sink particles? ',make_sinks) + if (make_sinks) then + if (binary) then + h_acc_char = '3.35au' + else + h_acc_char = '1.0d-2' + endif + call prompt('Enter the accretion radius of the sink (with units; e.g. au,pc,kpc,0.1pc) ',h_acc_char) + call select_unit(h_acc_char,h_acc_in,ierr) + h_acc_setup = h_acc_in + if (ierr==0 ) h_acc_setup = h_acc_setup/udist + r_crit_setup = 5.0*h_acc_setup + icreate_sinks_setup = 1 + if (binary) h_soft_sinksink_setup = 0.4*h_acc_setup + else + icreate_sinks_setup = 0 + rhofinal_setup = 0.15 + call prompt('Enter final maximum density in g/cm^3 (ignored for <= 0) ',rhofinal_setup) + endif + if (id==master) call write_setupfile(filename) + stop 'please edit .setup file and rerun phantomsetup' + else + stop ! MPI, stop on other threads, interactive on master + endif + ! + ! units + ! + call set_units(dist=udist,mass=umass,G=1.d0) + ! + ! set dust properties + ! + if (use_dust) then + use_dustfrac = .true. + ndustsmall = ndusttypes + if (ndusttypes > 1) then + call set_dustbinfrac(smincgs,smaxcgs,sindex,dustbinfrac(1:ndusttypes),grainsize(1:ndusttypes)) + grainsize(1:ndusttypes) = grainsize(1:ndusttypes)/udist + graindens(1:ndusttypes) = graindenscgs/umass*udist**3 + else + grainsize(1) = grainsizecgs/udist + graindens(1) = graindenscgs/umass*udist**3 + endif + endif + ! + ! convert units of sound speed + ! + if (cs_in_code) then + cs_sphere_cgs = cs_sphere*unit_velocity + else + cs_sphere = cs_sphere_cgs/unit_velocity + endif + ! + ! Bonnor-Ebert profile (if requested) + ! + if (BEsphere) then + iBE = 8192 + allocate(rtab(iBE),rhotab(iBE)) + call rho_bonnorebert(iBEparam,BErho_cen,edge_density,BErad_phys,BErad_norm,BEmass,BEfac,cs_sphere, & + gmw,iBE,iBElast,rtab,rhotab,ierr) + central_density = BErho_cen + r_sphere = BErad_phys + totmass_sphere = BEmass + if (ierr > 0) call fatal('setup_sphereinbox','Error in calculating Bonnor-Ebert profile') + endif + do i = 1,3 + xmini(i) = -0.5*(lbox*r_sphere) + xmaxi(i) = -xmini(i) + enddo + ! + ! boundaries + ! + call set_boundary(xmini(1),xmaxi(1),xmini(2),xmaxi(2),xmini(3),xmaxi(3)) + ! + ! general parameters + ! + time = 0. + if (use_dust) dust_method = 1 + hfact = hfact_default + hfact_out = hfact_default + if (maxvxyzu >=4 ) then + gamma = 5./3. + else + gamma = 1. + endif + rmax = r_sphere + if (angvel_not_betar) then + angvel_code = angvel*utime + else + angvel_code = sqrt(3.0*totmass_sphere*beta_r/r_sphere**3) + angvel = angvel_code/utime + endif + vol_box = dxbound*dybound*dzbound + vol_sphere = 4./3.*pi*r_sphere**3 + rhozero = totmass_sphere / vol_sphere + dens_sphere = rhozero + if (BEsphere) then + dens_medium = edge_density/density_contrast + cs_medium = cs_sphere*sqrt(edge_density/dens_medium) + else + dens_medium = dens_sphere/density_contrast + cs_medium = cs_sphere*sqrt(density_contrast) + endif + rhocrit0cgs = dens_medium*unit_density * density_contrast/7.5 ! end of transition region for ieos=8;for density_contrast=30, this yields a coefficient of 4 + rhocritTcgs = rhocrit0cgs*(1.0-drhocrit0) ! start of transition region for ieos=8 + totmass_box = (vol_box - vol_sphere)*dens_medium + totmass = totmass_box + totmass_sphere + t_ff = sqrt(3.*pi/(32.*dens_sphere)) + if (totmass_sphere > 0.9*totmass) then + print*, 'resetting boundaries to increase the number of background particles' + dxbound = (0.1*totmass_sphere/dens_medium)**(1./3.) + do i = 1,3 + xmini(i) = -0.5*dxbound + xmaxi(i) = -xmini(i) + enddo + call set_boundary(xmini(1),xmaxi(1),xmini(2),xmaxi(2),xmini(3),xmaxi(3)) + vol_box = dxbound*dybound*dzbound + totmass_box = (vol_box - vol_sphere)*dens_medium + totmass = totmass_box + totmass_sphere + endif + if (dens_medium*unit_density > rhocritTcgs) then + print*, 'Medium density = ',dens_medium*unit_density,'g/cm^3' + print*, 'Sphere density = ',dens_sphere*unit_density,'g/cm^3' + print*, 'Density at start of EOS transition = ',rhocritTcgs,'g/cm^3' + print*, 'Density at end of EOS transition = ',rhocrit0cgs,'g/cm^3' + call fatal('setup_sphereinbox','Error setting sound-speed transition region in EOS') + endif + ! + ! magnetic field + ! + rmasstoflux_crit = 2./3.*0.53*sqrt(5./pi) ! code units *see derivation at the end of the file* + if (mhd) then + area = pi*r_sphere**2 + if (mu_not_B) then + if (masstoflux > tiny(masstoflux)) then + Bzero = totmass_sphere/(area*masstoflux*rmasstoflux_crit) + else + Bzero = 0. + endif + else + Bzero = Bzero_G/unit_Bfield + masstoflux = totmass_sphere/(area*Bzero*rmasstoflux_crit) + endif + ihavesetupB = .true. + else + Bzero = 0. + endif + Bextx = 0. + Bexty = 0. + Bextz = Bzero + przero = cs_sphere**2*dens_sphere + ! + ! setup particles in the sphere; use this routine to get N_sphere as close to np as possible + ! + if (BEsphere) then + call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh, & + rhotab=rhotab(1:iBElast),rtab=rtab(1:iBElast),nptot=npart_total,& + exactN=.true.,np_requested=np,mask=i_belong) + else + call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& + exactN=.true.,np_requested=np,mask=i_belong) + if (trim(lattice)/='random') print "(a,es10.3)",' Particle separation in sphere = ',psep + endif + print "(a)",' Initialised sphere' + + if (usebox) then + npartsphere = npart + if (np_in /= npartsphere) np = npartsphere + massoftype(igas) = totmass_sphere/npartsphere ! note: before 5 Oct 2021, this was based upon total mass & total number, not sphere numbers + ! + ! setup surrounding low density medium + ! + if (BEsphere .or. trim(lattice)=='random') then + psep_box = dxbound/(vol_box*dens_medium/massoftype(igas))**(1./3.) + else + psep_box = psep*(density_contrast)**(1./3.) + endif + + call set_unifdis(trim(lattice),id,master,xmin,xmax,ymin,ymax,zmin,zmax,psep_box, & + hfact,npart,xyzh,periodic,rmin=r_sphere,nptot=npart_total,mask=i_belong,err=ierr) + print "(a,es10.3)",' Particle separation in low density medium = ',psep_box + print "(a,i10,a)",' added ',npart-npartsphere,' particles in low-density medium' + print*, "" + endif + ! + ! set particle properties + ! + npartoftype(:) = 0 + npartoftype(igas) = npart + dustfrac = 0. + if (massoftype(igas) < epsilon(massoftype(igas))) massoftype(igas) = totmass/npart_total + do i = 1,npartoftype(igas) + call set_particle_type(i,igas) + if (use_dust .and. dust_method==1) then + if (ndusttypes > 1) then + dustfrac(1:ndusttypes,i) = dustbinfrac(1:ndusttypes)*dtg + else + dustfrac(1,i) = dtg/(1.+dtg) ! call set_dustfrac(dtg,dustfrac(:,i)) + endif + endif + enddo + ! + ! Set two-fluid dust + ! (currently deactivated; will need to re-test before use to ensure it is fully compatible with the current dust algorithms) + ! + if (use_dust .and. dust_method==2) then + ! particle separation in dust sphere & sdjust for close-packed lattice + pmass_dusttogas = 10.*dtg*massoftype(igas) + psep = (vol_sphere/pmass_dusttogas/real(np))**(1./3.) + psep = psep*sqrt(2.)**(1./3.) + call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& + exactN=.true.,np_requested=np/10,mask=i_belong) + npartoftype(idust) = int(npart_total) - npartoftype(igas) + massoftype(idust) = totmass_sphere*dtg/npartoftype(idust) + + do i = npartoftype(igas)+1,npart + call set_particle_type(i,idust) + enddo + + print "(a,4(i10,1x))", ' particle numbers: (gas_total, gas_sphere, dust, total): ' & + , npartoftype(igas),npartsphere,npartoftype(idust),npart + print "(a,2es10.3)" , ' particle masses: (gas,dust): ',massoftype(igas),massoftype(idust) + else + print "(a,3(i10,1x))", ' particle numbers: (sphere, low-density medium, total): ' & + , npartsphere, npart-npartsphere,npart + print "(a,es10.3)",' particle mass = ',massoftype(igas) + endif + ! + ! shuffle particles + ! + if (shuffle_parts) then + print*, "lets shuffle!" + if (BEsphere) then + call shuffleparticles(iprint,npart,xyzh,massoftype(igas),dmedium=dens_medium,ntab=iBElast, & + rtab=rtab,dtab=rhotab,dcontrast=density_contrast,is_setup=.true.,prefix=trim(fileprefix)) + else + call shuffleparticles(iprint,npart,xyzh,massoftype(igas), & + rsphere=rmax,dsphere=dens_sphere,dmedium=dens_medium,is_setup=.true.,prefix=trim(fileprefix)) + endif + endif + if (BEsphere) deallocate(rtab,rhotab) + ! + ! reset to centre of mass + ! (if random or shuffling, recentering may shift particles outside of the defined range) + ! + if (trim(lattice)/='random' .and. .not.shuffle_parts) call reset_centreofmass(npart,xyzh,vxyzu) + ! + ! temperature set to give a pressure equilibrium + ! + polyk = cs_sphere**2 + polyk2 = cs_medium**2 + ! + !--Stretching the spatial distribution to perturb the density profile, if requested + ! + if (binary) then + do i = 1,npart + rxy2 = xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) + rxyz2 = rxy2 + xyzh(3,i)*xyzh(3,i) + if (rxyz2 <= r_sphere**2) then + phi = atan(xyzh(2,i)/xyzh(1,i)) + if (xyzh(1,i) < 0.0) phi = phi + pi + dphi = 0.5*rho_pert_amp*sin(2.0*phi) + phi = phi - dphi + xyzh(1,i) = sqrt(rxy2)*cos(phi) + xyzh(2,i) = sqrt(rxy2)*sin(phi) + endif + enddo + endif + ! + ! Velocity: Turbulent velocity field + ! + vxyzu = 0. + if (rms_mach > 0.) then + call getcwd(cwd) + ! personal hack for J. Wurster since different computer clusters required different velocity fields + if (index(cwd,'gpfs1/scratch/astro/jhw5') > 0 .or. index(cwd,'data/dp187/dc-wurs1') > 0 ) then + ! Kennedy or Dial + filex = find_phantom_datafile(filevx,'velfield_sphng') + filey = find_phantom_datafile(filevy,'velfield_sphng') + filez = find_phantom_datafile(filevz,'velfield_sphng') + else + filex = find_phantom_datafile(filevx,'velfield') + filey = find_phantom_datafile(filevy,'velfield') + filez = find_phantom_datafile(filevz,'velfield') + endif + + call set_velfield_from_cubes(xyzh(:,1:npartsphere),vxyzu(:,:npartsphere),npartsphere, & + filex,filey,filez,1.,r_sphere,.false.,ierr) + if (ierr /= 0) call fatal('setup','error setting up velocity field on clouds') + + rmsmach = 0.0 + print*, 'Turbulence being set by user' + do i = 1,npartsphere + v2i = dot_product(vxyzu(1:3,i),vxyzu(1:3,i)) + rmsmach = rmsmach + v2i/cs_sphere**2 + enddo + rmsmach = sqrt(rmsmach/npartsphere) + if (rmsmach > 0.) then + turbfac = rms_mach/rmsmach ! normalise the energy to the desired mach number + else + turbfac = 0. + endif + do i = 1,npartsphere + vxyzu(1:3,i) = turbfac*vxyzu(1:3,i) + enddo + endif + ! + ! Velocity: uniform rotation (thermal energy & magnetic field too) + ! + do i=1,npart + r2 = dot_product(xyzh(1:3,i),xyzh(1:3,i)) + if (r2 < r_sphere**2) then + vxyzu(1,i) = vxyzu(1,i) - angvel_code*xyzh(2,i) + vxyzu(2,i) = vxyzu(2,i) + angvel_code*xyzh(1,i) + ui = cs_sphere**2 * 0.9 + if (maxvxyzu >= 4) vxyzu(4,i) = ui + else + if (maxvxyzu >= 4) vxyzu(4,i) = 1.5*polyk2 + endif + if (mhd) then + Bxyz(:,i) = 0. + Bxyz(1,i) = Bzero*sin(ang_Bomega*pi/180.0) + Bxyz(3,i) = Bzero*cos(ang_Bomega*pi/180.0) + endif + enddo + ! + ! set default runtime parameters if .in file does not exist + ! + filename=trim(fileprefix)//'.in' + inquire(file=filename,exist=iexist) + dtmax = t_ff/100. ! Since this variable can change, always reset it if running phantomsetup + if (.not. iexist) then + if (binary) then + tmax = 1.50*t_ff ! = 13.33 for default settings (Wurster, Price & Bate 2017) + else + tmax = 1.21*t_ff ! = 10.75 for default settings (Wurster, Price & Bate 2016) + endif + ieos = 8 + nfulldump = 1 + calc_erot = .true. + dtmax_dratio = 1.258 + icreate_sinks = icreate_sinks_setup + r_crit = r_crit_setup + h_acc = h_acc_setup + if (binary) h_soft_sinksink = h_soft_sinksink_setup + hdivbbmax_max = 1.0 ! 512. + if (icreate_sinks==1) then + dtmax_min = dtmax/8.0 + else + dtmax_min = 0.0 + rhofinal_cgs = rhofinal_setup + endif + ilimitdustflux = .true. + endif + ! + !--Summarise the sphere + ! + print "(a,i10)",' Input npart_sphere = ',np + print "(1x,50('-'))" + print "(a)",' Quantity (code units) (physical units)' + print "(1x,50('-'))" + fmt = "((a,1pg10.3,3x,1pg10.3),a)" + print fmt,' Total mass : ',totmass,totmass*umass,' g' + print fmt,' Mass in sphere : ',totmass_sphere,totmass_sphere*umass,' g' + print fmt,' Radius of sphere : ',r_sphere,r_sphere*udist,' cm' + if (BEsphere) then + print fmt,' Mean rho sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' + print fmt,' central density : ',central_density,central_density*unit_density,' g/cm^3' + print fmt,' edge density : ',edge_density,edge_density*unit_density,' g/cm^3' + print fmt,' Mean rho medium : ',dens_medium,dens_medium*unit_density,' g/cm^3' + else + print fmt,' Density sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' + print fmt,' Density medium : ',dens_medium,dens_medium*unit_density,' g/cm^3' + endif + print fmt,' cs in sphere : ',cs_sphere,cs_sphere_cgs,' cm/s' + print fmt,' cs in medium : ',cs_medium,cs_medium*unit_velocity,' cm/s' + print fmt,' Free fall time : ',t_ff,t_ff*utime/years,' yrs' + print fmt,' Angular velocity : ',angvel_code,angvel,' rad/s' + print fmt,' Turbulent Mach no: ',rms_mach + print fmt,' Omega*t_ff : ',angvel_code*t_ff + if (mhd) then + print fmt,' B field (z) : ',Bzero,Bzero*unit_Bfield*1.d6,' micro-G' + print fmt,' Alfven speed : ',Bzero/sqrt(dens_sphere),Bzero/sqrt(dens_sphere)*udist/utime,' cm/s' + if (Bzero > 0.) then + print fmt,' plasma beta : ',przero/(0.5*Bzero*Bzero) + print fmt,' mass-to-flux : ',totmass_sphere/(area*Bzero)/rmasstoflux_crit + endif + endif + if (use_dust) then + print fmt,' dust-to-gas ratio: ',dtg,dtg,' ' + endif + print "(1x,50('-'))" + +end subroutine setpart + +!---------------------------------------------------------------- +!+ +! write parameters to setup file +!+ +!---------------------------------------------------------------- +subroutine write_setupfile(filename) + use infile_utils, only: write_inopt + character(len=*), intent(in) :: filename + integer, parameter :: iunit = 20 + integer :: i + + print "(a)",' writing setup options file '//trim(filename) + open(unit=iunit,file=filename,status='replace',form='formatted') + write(iunit,"(a)") '# input file for sphere-in-box setup routines' + write(iunit,"(/,a)") '# units' + call write_inopt(dist_unit,'dist_unit','distance unit (e.g. au)',iunit) + call write_inopt(mass_unit,'mass_unit','mass unit (e.g. solarm)',iunit) + + write(iunit,"(/,a)") '# particle resolution & placement' + call write_inopt(np,'np','requested number of particles in sphere',iunit) + call write_inopt(lattice,'lattice','particle lattice (random,cubic,closepacked,hcp,hexagonal)',iunit) + call write_inopt(shuffle_parts,'shuffle_parts','relax particles by shuffling',iunit) + + write(iunit,"(/,a)") '# options for box' + if (.not.BEsphere .and. .not.is_cube) then + ! left here for backwards compatibility and for simplicity if the user requires a rectangle in the future + do i=1,3 + call write_inopt(xmini(i),labelx(i)//'min',labelx(i)//' min',iunit) + call write_inopt(xmaxi(i),labelx(i)//'max',labelx(i)//' max',iunit) + enddo + else + call write_inopt(lbox,'lbox','length of a box side in terms of spherical radii',iunit) + endif + + write(iunit,"(/,a)") '# intended result' + call write_inopt(binary,'form_binary','the intent is to form a central binary',iunit) + + write(iunit,"(/,a)") '# options for sphere' + call write_inopt(BEsphere,'use_BE_sphere','centrally condense as a BE sphere',iunit) + if (.not. BEsphere) then + call write_inopt(r_sphere,'r_sphere','radius of sphere in code units',iunit) + call write_inopt(totmass_sphere,'totmass_sphere','mass of sphere in code units',iunit) + else + call write_inopt(iBEparam,'iBE_options','The set of parameters to define the BE sphere',iunit) + if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) & + call write_inopt(BErho_cen,'BErho_cen','central density of the BE sphere [code units]',iunit) + if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) & + call write_inopt(BErad_phys,'BErad_phys','physical radius of the BE sphere [code units]',iunit) + if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) & + call write_inopt(BErad_norm,'BErad_norm','normalised radius of the BE sphere',iunit) + if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) & + call write_inopt(BEmass,'BEmass','mass radius of the BE sphere [code units]',iunit) + if (iBEparam==4 .or. iBEparam==5) & + call write_inopt(BEfac,'BEfac','over-density factor of the BE sphere [code units]',iunit) + endif + call write_inopt(density_contrast,'density_contrast','density contrast in code units',iunit) + call write_inopt(cs_sphere_cgs,'cs_sphere_cgs','sound speed in sphere in cm/s',iunit) + if (angvel_not_betar) then + call write_inopt(angvel,'angvel','angular velocity in rad/s',iunit) + else + call write_inopt(beta_r,'beta_r','rotational-to-gravitational energy ratio',iunit) + endif + call write_inopt(rms_mach,'rms_mach','turbulent rms mach number',iunit) + if (mhd) then + if (mu_not_B) then + call write_inopt(masstoflux,'masstoflux','mass-to-magnetic flux ratio in units of critical value',iunit) + else + call write_inopt(Bzero_G,'Bzero','Magnetic field strength in Gauss',iunit) + endif + call write_inopt(ang_Bomega,'ang_Bomega','Angle (degrees) between B and rotation axis',iunit) + endif + if (use_dust) then + write(iunit,"(/,a)") '# Dust properties' + call write_inopt(dtg,'dust_to_gas_ratio','dust-to-gas ratio',iunit) + call write_inopt(ndusttypes,'ndusttypes','number of grain sizes',iunit) + if (ndusttypes > 1) then + call write_inopt(smincgs,'smincgs','minimum grain size [cm]',iunit) + call write_inopt(smaxcgs,'smaxcgs','maximum grain size [cm]',iunit) + call write_inopt(sindex, 'sindex', 'power-law index, e.g. MRN',iunit) + call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) + else + call write_inopt(grainsizecgs,'grainsizecgs','grain size in [cm]',iunit) + call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) + endif + endif + if (binary) then + call write_inopt(rho_pert_amp,'rho_pert_amp','amplitude of density perturbation',iunit) + endif + write(iunit,"(/,a)") '# Sink properties (values in .in file, if present, will take precedence)' + call write_inopt(icreate_sinks_setup,'icreate_sinks','1: create sinks. 0: do not create sinks',iunit) + if (icreate_sinks_setup==1) then + call write_inopt(h_acc_setup,'h_acc','accretion radius (code units)',iunit) + call write_inopt(r_crit_setup,'r_crit','critical radius (code units)',iunit) + if (binary) then + call write_inopt(h_soft_sinksink_setup,'h_soft_sinksink','sink-sink softening radius (code units)',iunit) + endif + else + call write_inopt(rhofinal_setup,'rho_final','final maximum density (<=0 to ignore) (cgs units)',iunit) + endif + close(iunit) + +end subroutine write_setupfile + +!---------------------------------------------------------------- +!+ +! Read parameters from setup file +!+ +!---------------------------------------------------------------- +subroutine read_setupfile(filename,ierr) + use infile_utils, only: open_db_from_file,inopts,read_inopt,close_db + use unifdis, only: is_valid_lattice + use io, only: error + use units, only: select_unit + character(len=*), intent(in) :: filename + integer, intent(out) :: ierr + integer, parameter :: iunit = 21 + integer :: i,nerr,jerr,kerr + type(inopts), allocatable :: db(:) + + !--Read values + print "(a)",' reading setup options from '//trim(filename) + call open_db_from_file(db,filename,iunit,ierr) + call read_inopt(mass_unit,'mass_unit',db,ierr) + call read_inopt(dist_unit,'dist_unit',db,ierr) + call read_inopt(BEsphere,'use_BE_sphere',db,ierr) + call read_inopt(binary,'form_binary',db,ierr) + call read_inopt(np,'np',db,ierr) + call read_inopt(lattice,'lattice',db,ierr) + if (ierr/=0 .or. .not. is_valid_lattice(trim(lattice))) then + print*, ' invalid lattice. Setting to closepacked' + lattice = 'closepacked' + endif + call read_inopt(shuffle_parts,'shuffle_parts',db,ierr) + + call read_inopt(lbox,'lbox',db,jerr) ! for backwards compatibility + if (jerr /= 0) then + do i=1,3 + call read_inopt(xmini(i),labelx(i)//'min',db,ierr) + call read_inopt(xmaxi(i),labelx(i)//'max',db,ierr) + enddo + lbox = -2.0*xmini(1)/r_sphere + endif + + if (.not. BEsphere) then + call read_inopt(r_sphere,'r_sphere',db,ierr) + call read_inopt(totmass_sphere,'totmass_sphere',db,ierr) + else + call read_inopt(iBEparam,'iBE_options',db,ierr) + if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) call read_inopt(BErho_cen,'BErho_cen',db,ierr) + if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) call read_inopt(BErad_phys,'BErad_phys',db,ierr) + if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) call read_inopt(BErad_norm,'BErad_norm',db,ierr) + if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) call read_inopt(BEmass,'BEmass',db,ierr) + if (iBEparam==4 .or. iBEparam==5) call read_inopt(BEfac,'BEfac',db,ierr) + endif + + call read_inopt(density_contrast,'density_contrast',db,ierr) + call read_inopt(cs_sphere,'cs_sphere',db,jerr) + call read_inopt(cs_sphere_cgs,'cs_sphere_cgs',db,kerr) + cs_in_code = .false. ! for backwards compatibility + if (jerr /= 0 .and. kerr == 0) then + cs_in_code = .false. + elseif (jerr == 0 .and. kerr /= 0) then + cs_in_code = .true. + else + ierr = ierr + 1 + endif + call read_inopt(angvel,'angvel',db,jerr) + call read_inopt(beta_r,'beta_r',db,kerr) + angvel_not_betar = .true. + if (jerr /= 0 .and. kerr == 0) then + angvel_not_betar = .false. + elseif (jerr == 0 .and. kerr /= 0) then + angvel_not_betar = .true. + else + ierr = ierr + 1 + endif + call read_inopt(rms_mach,'rms_mach',db,ierr) + mu_not_B = .true. + if (mhd) then + call read_inopt(masstoflux,'masstoflux',db,jerr) + call read_inopt(Bzero_G, 'Bzero', db,kerr) + call read_inopt(ang_Bomega,'ang_Bomega',db,ierr) + if (jerr /= 0 .and. kerr == 0) then + mu_not_B = .false. + elseif (jerr == 0 .and. kerr /= 0) then + mu_not_B = .true. + else + ierr = ierr + 1 + endif + endif + if (use_dust) then + call read_inopt(dtg,'dust_to_gas_ratio',db,ierr) + call read_inopt(ndusttypes,'ndusttypes',db,ierr) + if (ndusttypes > 1) then + call read_inopt(smincgs,'smincgs',db,ierr) + call read_inopt(smaxcgs,'smaxcgs',db,ierr) + call read_inopt(sindex,'cs_sphere',db,ierr) + call read_inopt(graindenscgs,'graindenscgs',db,ierr) + else + call read_inopt(grainsizecgs,'grainsizecgs',db,ierr) + call read_inopt(graindenscgs,'graindenscgs',db,ierr) + endif + endif + if (binary) then + call read_inopt(rho_pert_amp,'rho_pert_amp',db,ierr) + endif + call read_inopt(icreate_sinks_setup,'icreate_sinks',db,ierr) + if (icreate_sinks_setup==1) then + call read_inopt(h_acc_setup,'h_acc',db,ierr) + call read_inopt(r_crit_setup,'r_crit',db,ierr) + if (binary) then + call read_inopt(h_soft_sinksink_setup,'h_soft_sinksink',db,ierr) + endif + else + call read_inopt(rhofinal_setup,'rho_final',db,ierr) + endif + call close_db(db) + ! + ! parse units + ! + call select_unit(mass_unit,umass,nerr) + if (nerr /= 0) then + call error('setup_sphereinbox','mass unit not recognised') + ierr = ierr + 1 + endif + call select_unit(dist_unit,udist,nerr) + if (nerr /= 0) then + call error('setup_sphereinbox','length unit not recognised') + ierr = ierr + 1 + endif + + if (ierr > 0) then + print "(1x,a,i2,a)",'Setup_sphereinbox: ',nerr,' error(s) during read of setup file. Re-writing.' + endif + +end subroutine read_setupfile +!---------------------------------------------------------------- + !--Magnetic flux justification + ! This shows how the critical mass-to-flux values translates from CGS to code units. + ! + ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) ! cgs units of g G^-1 cm^-2 + ! convert base units from cgs to code: + ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *unit_Bfield*udist**2/umass + ! where + ! unit_Bfield = umass/(utime*sqrt(umass*udist/4*pi)) = sqrt(4.*pi*umass)/(utime*sqrt(udist)) + ! therefore + ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *sqrt(4.*pi*umass)*udist**2/(utime*sqrt(udist)*umass) + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*sqrt(umass)*udist**2/(utime*sqrt(udist)*umass) + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*udist**1.5/ (sqrt(umass)*utime) + ! where + ! G [cgs] = 1 * udist**3/(umass*utime**2) + ! therefore + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) *udist**1.5/ (sqrt(umass)*utime) / sqrt(udist**3/(umass*utime**2)) + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) ! code units + +!---------------------------------------------------------------- +end module setup From 9bed0dab9289f5f2de7d9801038286c4ecd1493f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 8 Mar 2023 11:55:52 +0000 Subject: [PATCH 012/182] Move OPTABLE to eos_stamatellos --- build/Makefile_setups | 4 +++- src/main/cooling_stamatellos.f90 | 4 ++-- src/main/eos_stamatellos.f90 | 4 +--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/Makefile_setups b/build/Makefile_setups index 2688ac702..ece2f5228 100644 --- a/build/Makefile_setups +++ b/build/Makefile_setups @@ -399,6 +399,8 @@ endif ifeq ($(SETUP), sphereinbox) # sphere-in-box setup PERIODIC=yes + IND_TIMESTEPS=yes + GRAVITY=yes SETUPFILE= velfield_fromcubes.f90 setup_sphereinbox.f90 KNOWN_SETUP=yes endif @@ -410,7 +412,7 @@ ifeq ($(SETUP), sphere) IND_TIMESTEPS=yes GRAVITY=yes SETUPFILE= velfield_fromcubes.f90 setup_sphere.f90 -KNOWN_SETUP=yes + KNOWN_SETUP=yes endif ifeq ($(SETUP), shock) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 945ee57ba..eb1f19b82 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -65,9 +65,9 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) else Teqi = Teqi**0.25d0 endif - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi,optable) + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg - call getintenerg_opdep(Tmini,rhoi*unit_density,umini,optable) + call getintenerg_opdep(Tmini,rhoi*unit_density,umini) umini = umini/unit_ergg ! calculate thermalization timescale if ((dudti_sph + dudt_rad) == 0.d0) then diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index c5cc1e390..ee1a7ac56 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -138,16 +138,14 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) gammai = 1.0d0 + 1.38d-16/1.67d-24/gmwi/cv end subroutine getopac_opdep -subroutine getintenerg_opdep(Teqi, rhoi, ueqi, OPTABLE) +subroutine getintenerg_opdep(Teqi, rhoi, ueqi) real, intent(out) :: ueqi real, intent(in) :: Teqi,rhoi - !real, intent(inout) :: OPTABLE(260,1001,6) real u1, u2 real m, c integer i, j real rhoi_ - real, intent(in) :: OPTABLE(260,1001,6) ! interpolate through OPTABLE to obtain equilibrium internal energy From e4c4b43a1399faf9b97f5db2bd56934580b9121c Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 8 Mar 2023 14:29:17 +0000 Subject: [PATCH 013/182] Adding variable (de)allocation for cooling --- src/main/eos.F90 | 11 ++++++++--- src/main/eos_stamatellos.f90 | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 0437fa8ea..404a58e22 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -440,7 +440,7 @@ subroutine init_eos(eos_type,ierr) use eos_barotropic, only:init_eos_barotropic use eos_shen, only:init_eos_shen_NL3 use eos_gasradrec, only:init_eos_gasradrec - use eos_stamatellos,only:optable,read_optab + use eos_stamatellos,only:read_optab,init_S07cool use dim, only:maxvxyzu,do_radiation integer, intent(in) :: eos_type integer, intent(out) :: ierr @@ -517,8 +517,8 @@ subroutine init_eos(eos_type,ierr) ierr = ierr_option_conflict endif case(21) - call read_optab(ierr) + call init_S07cool end select done_init_eos = .true. @@ -533,7 +533,8 @@ end subroutine init_eos !+ !----------------------------------------------------------------------- subroutine finish_eos(eos_type,ierr) - use eos_mesa, only: finish_eos_mesa + use eos_mesa, only: finish_eos_mesa + use eos_stamatellos, only: finish_S07cool integer, intent(in) :: eos_type integer, intent(out) :: ierr @@ -546,6 +547,10 @@ subroutine finish_eos(eos_type,ierr) !--MESA EoS deallocation ! call finish_eos_mesa + + case(21) + ! Stamatellos deallocation + call finish_S07cool end select done_init_eos=.false. diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index ee1a7ac56..4ba6ac218 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -5,9 +5,23 @@ module eos_stamatellos implicit none real, public :: optable(260,1001,6) - public :: read_optab,getopac_opdep + real,allocatable,public :: gradP_cool(:),Gpot_cool(:) + public :: read_optab,getopac_opdep,init_S07cool contains + subroutine init_S07cool() + use part, only:npart + + print *, "Allocating S07 arrays" + allocate(gradP_cool(npart)) + allocate(Gpot_cool(npart)) + end subroutine init_S07cool + + subroutine finish_S07cool() + if (allocated(gradP_cool)) deallocate(gradP_cool) + if (allocated(Gpot_cool)) deallocate(Gpot_cool) +end subroutine finish_S07cool + subroutine read_optab(ierr) use datafiles, only:find_phantom_datafile From 1473e6d23006d28cf64947730aef30f2e0005f0b Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 10 Mar 2023 16:24:26 +0000 Subject: [PATCH 014/182] Correcting potential used in Stamatellos cooling --- src/main/cooling_stamatellos.f90 | 29 +++++++++++++++++++---------- src/main/eos_stamatellos.f90 | 7 +++++-- src/main/force.F90 | 11 +++++++++-- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index eb1f19b82..74acde5b3 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -29,16 +29,18 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning use physcon, only:steboltz,pi,solarl use units, only:umass,udist,unit_density,unit_ergg,utime - use eos_stamatellos - use part, only:poten + use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool, & + iunitst + use part, only:eos_vars,igasP real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,Lstar,ri2 real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi - real :: tcool,ueqi,umini,tthermi,poti - - poti = poten(i) + real :: tcool,ueqi,umini,tthermi,poti,presi,coldens2i + + poti = Gpot_cool(i) + presi = eos_vars(igasP,i) ! Tfloor is from input parameters and is background heating ! Add to stellar heating. Just assuming one star at (0,0,0) for now Lstar = 0.0 !in Lsun @@ -46,14 +48,21 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ri2 = ri2 *udist*udist Tirri = (Lstar*solarl/(4d0*pi*steboltz)/ri2)**0.25 Tmini = Tfloor + Tirri + +! get opacities & Ti for ui + + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + Ti,gmwi,gammai) coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 coldensi = coldensi*umass/udist/udist ! physical units - -! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& - Ti,gmwi,gammai) + +! testing Lombardi+ method of estimating the mean column density + coldens2i = 1.014d0 * presi / abs(-gradP_cool(i) /rhoi ) ! Lombardi+ 2015 + coldens2i = coldens2i *umass/udist/udist ! physical units +! write(iunitst,'(5E12.5)') coldensi,coldens2i,presi,gradP_cool(i) + tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg*utime! code units ! calculate Teqi @@ -90,7 +99,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) print *, "Teqi=",Teqi, "dt=",dt,"tthermi=", tthermi,"ueqi=", ueqi call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop - else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then dudti_cool = (umini - ui)/dt endif diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 4ba6ac218..f2602a9dc 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -6,7 +6,8 @@ module eos_stamatellos implicit none real, public :: optable(260,1001,6) real,allocatable,public :: gradP_cool(:),Gpot_cool(:) - public :: read_optab,getopac_opdep,init_S07cool + integer,public :: iunitst=19 + public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains subroutine init_S07cool() @@ -14,12 +15,14 @@ subroutine init_S07cool() print *, "Allocating S07 arrays" allocate(gradP_cool(npart)) - allocate(Gpot_cool(npart)) + allocate(Gpot_cool(npart)) + open (unit=iunitst,file='EOSinfo.dat',status='replace') end subroutine init_S07cool subroutine finish_S07cool() if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) + close(iunitst) end subroutine finish_S07cool subroutine read_optab(ierr) diff --git a/src/main/force.F90 b/src/main/force.F90 index 168eaf1df..57d561010 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -849,6 +849,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt use eos, only:ieos,eos_is_non_ideal,gamma,utherm + use eos_stamatellos, only:gradP_cool,Gpot_cool #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -870,7 +871,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use part, only:ibin_old,iamboundary #endif use timestep, only:bignumber - use options, only:overcleanfac,use_dustfrac,ireconav + use options, only:overcleanfac,use_dustfrac,ireconav,icooling use units, only:get_c_code #ifdef GR use metric_tools,only:imet_minkowski,imetric @@ -1138,7 +1139,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravxi = 0. fgravyi = 0. fgravzi = 0. - + if (icooling == 7) gradP_cool(i) = 0d0 + loop_over_neighbours2: do n = 1,nneigh j = abs(listneigh(n)) @@ -1639,6 +1641,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g projsx = projsxi + projsxj projsy = projsyi + projsyj projsz = projszi + projszj + if (icooling == 7) gradP_cool(i) = gradP_cool(i) + gradp fsum(ifxi) = fsum(ifxi) - runix*(gradp + fgrav) - projsx fsum(ifyi) = fsum(ifyi) - runiy*(gradp + fgrav) - projsy @@ -1884,6 +1887,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g enddo loop_over_neighbours2 + if (icooling == 7) then + Gpot_cool(i) = fsum(ipot) + endif + if (gr .and. gravity .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fgravxi + vyi*fgravyi + vzi*fgravzi endif From 11ee26d9519a830a9c3c1f2b075b79e98b44b269 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 13 Mar 2023 09:37:13 +0000 Subject: [PATCH 015/182] Changing Stamatellos cooling to icooling = 8 --- src/main/cooling.F90 | 2 +- src/main/eos.F90 | 2 +- src/main/force.F90 | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 2bef54d5a..205447c01 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -83,7 +83,7 @@ subroutine init_cooling(id,master,iprint,ierr) else select case(icooling) case(8) - if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=7 requires ieos=21',var='ieos',ival=ieos) + if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=8 requires ieos=21',var='ieos',ival=ieos) ! nothing to do. Initialised in eos.F90 if (ieos ==2) call read_optab(ierr) case(6) diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 404a58e22..a25d7ec8c 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -399,7 +399,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam case(21) ! -!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=7 +!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=8 ! if (eni < 0.) then call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) diff --git a/src/main/force.F90 b/src/main/force.F90 index f44630608..b33451f44 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1159,7 +1159,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravxi = 0. fgravyi = 0. fgravzi = 0. - if (icooling == 7) gradP_cool(i) = 0d0 + if (icooling == 8) gradP_cool(i) = 0d0 loop_over_neighbours2: do n = 1,nneigh @@ -1661,7 +1661,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g projsx = projsxi + projsxj projsy = projsyi + projsyj projsz = projszi + projszj - if (icooling == 7) gradP_cool(i) = gradP_cool(i) + gradp + if (icooling == 8) gradP_cool(i) = gradP_cool(i) + gradp fsum(ifxi) = fsum(ifxi) - runix*(gradp + fgrav) - projsx fsum(ifyi) = fsum(ifyi) - runiy*(gradp + fgrav) - projsy @@ -1901,7 +1901,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g enddo loop_over_neighbours2 - if (icooling == 7) then + if (icooling == 8) then Gpot_cool(i) = fsum(ipot) endif From be29a808b3f51ad5e887b05db8348a7a2a8072e3 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 13 Mar 2023 09:44:58 +0000 Subject: [PATCH 016/182] Fix typo --- src/main/cooling.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 205447c01..a8e39393f 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -113,7 +113,7 @@ subroutine init_cooling(id,master,iprint,ierr) ufloor = 3.0*kboltz*Tfloor/(2.0*gmw*mass_proton_cgs)/unit_ergg endif if (maxvxyzu < 4) ierr = 1 - elseif (icooling == ) then + elseif (icooling == 8) then ufloor = 0. ! because we use the umin(:) array else ufloor = 0. From 458f034f5430cf2d59a6aa6f75041394931958c3 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 13 Mar 2023 10:59:20 +0000 Subject: [PATCH 017/182] Error handling for failure to read EOS table --- src/main/cooling.F90 | 5 +++-- src/main/eos.F90 | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index a8e39393f..9e7b7a0a1 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -1,4 +1,4 @@ -!--------------------------------------------------------------------------! +--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! @@ -85,7 +85,8 @@ subroutine init_cooling(id,master,iprint,ierr) case(8) if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=8 requires ieos=21',var='ieos',ival=ieos) ! nothing to do. Initialised in eos.F90 - if (ieos ==2) call read_optab(ierr) + if (ieos == 2) call read_optab(ierr) + if (ierr > 0) call fatal('cooling','Failed to read myeos.dat',var='ierr',ival=ierr) case(6) call init_cooling_KI02(ierr) case(5) diff --git a/src/main/eos.F90 b/src/main/eos.F90 index a25d7ec8c..74dfd5b13 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -518,6 +518,7 @@ subroutine init_eos(eos_type,ierr) endif case(21) call read_optab(ierr) + if (ierr > 0) call fatal('init_eos','Failed to read myeos.dat',var='ierr',ival=ierr) call init_S07cool end select From 0b22f73d40cd5146a75b0f01d18ace349d728932 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 13 Mar 2023 11:55:58 +0000 Subject: [PATCH 018/182] Read/write options for Stamatellos cooling --- src/main/cooling.F90 | 11 ++++++-- src/main/cooling_stamatellos.f90 | 44 +++++++++++++++++++++++++++++--- src/main/eos.F90 | 2 +- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 9e7b7a0a1..7b8814e0c 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -1,4 +1,4 @@ ---------------------------------------------------------------------------! +!--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! @@ -192,6 +192,7 @@ subroutine write_options_cooling(iunit) use cooling_gammie_PL, only:write_options_cooling_gammie_PL use cooling_molecular, only:write_options_molecularcooling use cooling_solver, only:write_options_cooling_solver + use cooling_stamatellos, only:write_options_cooling_stamatellos integer, intent(in) :: iunit write(iunit,"(/,a)") '# options controlling cooling' @@ -209,6 +210,8 @@ subroutine write_options_cooling(iunit) call write_options_cooling_gammie(iunit) case(7) call write_options_cooling_gammie_PL(iunit) + case(8) + call write_options_cooling_stamatellos(iunit) case default call write_options_cooling_solver(iunit) end select @@ -230,11 +233,12 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) use cooling_ism, only:read_options_cooling_ism use cooling_molecular, only:read_options_molecular_cooling use cooling_solver, only:read_options_cooling_solver + use cooling_stamatellos, only:read_options_cooling_stamatellos character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr integer, save :: ngot = 0 - logical :: igotallism,igotallmol,igotallgammie,igotallgammiePL,igotallfunc + logical :: igotallism,igotallmol,igotallgammie,igotallgammiePL,igotallfunc,igotallstam imatch = .true. igotall = .false. ! cooling options are compulsory @@ -242,6 +246,7 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) igotallmol = .true. igotallgammie = .true. igotallfunc = .true. + igotallstam = .true. select case(trim(name)) case('icooling') @@ -265,6 +270,8 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) call read_options_cooling_gammie(name,valstring,imatch,igotallgammie,ierr) case(7) call read_options_cooling_gammie_PL(name,valstring,imatch,igotallgammiePL,ierr) + case(8) + call read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) case default call read_options_cooling_solver(name,valstring,imatch,igotallfunc,ierr) end select diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 74acde5b3..1b858b188 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -18,7 +18,8 @@ module cooling_stamatellos ! implicit none - public :: cooling_S07 + real, public :: Lstar ! in units of L_sun + public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos contains @@ -59,10 +60,13 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) coldensi = coldensi*umass/udist/udist ! physical units ! testing Lombardi+ method of estimating the mean column density - coldens2i = 1.014d0 * presi / abs(-gradP_cool(i) /rhoi ) ! Lombardi+ 2015 + coldens2i = 1.014d0 * presi / abs(-gradP_cool(i))! /rhoi ) ! Lombardi+ 2015 coldens2i = coldens2i *umass/udist/udist ! physical units ! write(iunitst,'(5E12.5)') coldensi,coldens2i,presi,gradP_cool(i) - +! ! USE LOMBARDI METHOD !! + coldensi = coldens2i + !!! + tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg*utime! code units ! calculate Teqi @@ -104,5 +108,37 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) endif end subroutine cooling_S07 - + + + subroutine write_options_cooling_stamatellos(iunit) + use infile_utils, only:write_inopt + integer, intent(in) :: iunit + + !Tfloor handled in cooling.F90 + call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) + +end subroutine write_options_cooling_stamatellos + + subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) +! use io, only:fatal + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotallstam + integer, intent(out) :: ierr + integer, save :: ngot = 0 + + + imatch = .true. + igotallstam = .false. ! cooling options are compulsory + select case(trim(name)) + case('Lstar') + read(valstring,*,iostat=ierr) Lstar + ngot = ngot + 1 + case default + imatch = .false. + end select + if (ngot >= 1) igotallstam = .true. + +end subroutine read_options_cooling_stamatellos + + end module cooling_stamatellos diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 74dfd5b13..baea4f571 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -433,7 +433,7 @@ end subroutine equationofstate subroutine init_eos(eos_type,ierr) use units, only:unit_velocity use physcon, only:mass_proton_cgs,kboltz - use io, only:error,warning + use io, only:error,warning,fatal use eos_mesa, only:init_eos_mesa use eos_helmholtz, only:eos_helmholtz_init use eos_piecewise, only:init_eos_piecewise From f05cbd926d99b952d700c9bd65c111da02d9f226 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 13 Mar 2023 13:33:45 +0000 Subject: [PATCH 019/182] Contribution from stellar heating to Stamatellos cooling --- src/main/cooling.F90 | 5 +++-- src/main/cooling_stamatellos.f90 | 38 +++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 7b8814e0c..1dedc2436 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -70,6 +70,7 @@ subroutine init_cooling(id,master,iprint,ierr) use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver use eos_stamatellos, only:read_optab + use cooling_stamatellos, only: init_star integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr @@ -84,9 +85,9 @@ subroutine init_cooling(id,master,iprint,ierr) select case(icooling) case(8) if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=8 requires ieos=21',var='ieos',ival=ieos) - ! nothing to do. Initialised in eos.F90 if (ieos == 2) call read_optab(ierr) if (ierr > 0) call fatal('cooling','Failed to read myeos.dat',var='ierr',ival=ierr) + call init_star() case(6) call init_cooling_KI02(ierr) case(5) @@ -280,7 +281,7 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) ierr = 0 if (h2chemistry .and. igotallism .and. ngot >= 2) then igotall = .true. - elseif (icooling >= 0 .and. ngot >= 2 .and. igotallgammie .and. igotallfunc) then + elseif (icooling >= 0 .and. ngot >= 2 .and. igotallgammie .and. igotallfunc .and. igotallstam) then igotall = .true. else igotall = .false. diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 1b858b188..b497f4c81 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -19,10 +19,36 @@ module cooling_stamatellos implicit none real, public :: Lstar ! in units of L_sun + integer :: isink_star ! index of sink to use as illuminating star public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos + public :: init_star contains +subroutine init_star() + use part, only:nptmass,xyzmh_ptmass + integer :: i,imin + real :: rsink2,rsink2min + + rsink2min = 0d0 + if (nptmass == 0) then + isink_star = 0 ! no star present + print *, "No illuminating star." + elseif (nptmass == 1) then + isink_star = 1 + else + do i=1,nptmass + rsink2 = xyzmh_ptmass(1,i)**2 + xyzmh_ptmass(2,i)**2 + xyzmh_ptmass(3,i)**2 + if (i==1 .or. (rsink2 < rsink2min) ) then + rsink2min = rsink2 + imin = i + endif + enddo + isink_star = imin + endif + if (nptmass > 0) print *, "Using sink no. ", isink_star, "as illuminating star." +end subroutine init_star + ! ! Do cooling calculation ! @@ -32,23 +58,23 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use units, only:umass,udist,unit_density,unit_ergg,utime use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool, & iunitst - use part, only:eos_vars,igasP + use part, only:eos_vars,igasP,xyzmh_ptmass real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i real,intent(out) :: dudti_cool - real :: coldensi,kappaBari,kappaParti,Lstar,ri2 + real :: coldensi,kappaBari,kappaParti,ri2 real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi real :: tcool,ueqi,umini,tthermi,poti,presi,coldens2i poti = Gpot_cool(i) presi = eos_vars(igasP,i) ! Tfloor is from input parameters and is background heating -! Add to stellar heating. Just assuming one star at (0,0,0) for now - Lstar = 0.0 !in Lsun - ri2 = xi*xi + yi*yi + zi*zi +! Stellar heating + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2 + (yi-xyzmh_ptmass(2,isink_star))**2 & + + (zi-xyzmh_ptmass(3,isink_star))**2 ri2 = ri2 *udist*udist Tirri = (Lstar*solarl/(4d0*pi*steboltz)/ri2)**0.25 - Tmini = Tfloor + Tirri + Tmini = Tfloor + Tirri ! Tfloor + stellar heating ! get opacities & Ti for ui From e38b52dabf188d7e5c8928a6348a0867886751d3 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 15 Mar 2023 11:56:12 +0000 Subject: [PATCH 020/182] Add option to choose method for estimating the optical depth in Stamatellos cooling --- src/main/cooling_stamatellos.f90 | 42 +++++++++++++++++++------------- src/main/eos_stamatellos.f90 | 2 +- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index b497f4c81..3c0f85f79 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -20,6 +20,7 @@ module cooling_stamatellos implicit none real, public :: Lstar ! in units of L_sun integer :: isink_star ! index of sink to use as illuminating star + integer :: od_method public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star @@ -29,7 +30,7 @@ subroutine init_star() use part, only:nptmass,xyzmh_ptmass integer :: i,imin real :: rsink2,rsink2min - + rsink2min = 0d0 if (nptmass == 0) then isink_star = 0 ! no star present @@ -64,7 +65,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi - real :: tcool,ueqi,umini,tthermi,poti,presi,coldens2i + real :: tcool,ueqi,umini,tthermi,poti,presi poti = Gpot_cool(i) presi = eos_vars(igasP,i) @@ -80,18 +81,17 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi,gammai) - - coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) - coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 - coldensi = coldensi*umass/udist/udist ! physical units - + select case (od_method) + case (1) + coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) + coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 + coldensi = coldensi*umass/udist/udist ! physical units + case(2) ! testing Lombardi+ method of estimating the mean column density - coldens2i = 1.014d0 * presi / abs(-gradP_cool(i))! /rhoi ) ! Lombardi+ 2015 - coldens2i = coldens2i *umass/udist/udist ! physical units -! write(iunitst,'(5E12.5)') coldensi,coldens2i,presi,gradP_cool(i) -! ! USE LOMBARDI METHOD !! - coldensi = coldens2i - !!! + coldensi = 1.014d0 * presi / abs(-gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 + coldensi = coldensi *umass/udist/udist ! physical units + end select +! write(iunitst,'(5E12.5)') coldensi,presi,gradP_cool(i) tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg*utime! code units @@ -130,7 +130,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt + dudti_cool = (umini - ui)/dt endif end subroutine cooling_S07 @@ -140,13 +140,14 @@ subroutine write_options_cooling_stamatellos(iunit) use infile_utils, only:write_inopt integer, intent(in) :: iunit - !Tfloor handled in cooling.F90 + !N.B. Tfloor handled in cooling.F90 + call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) end subroutine write_options_cooling_stamatellos subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) -! use io, only:fatal + use io, only:warning character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallstam integer, intent(out) :: ierr @@ -159,10 +160,17 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie case('Lstar') read(valstring,*,iostat=ierr) Lstar ngot = ngot + 1 + case('OD method') + read(valstring,*,iostat=ierr) od_method + ngot = ngot + 1 case default imatch = .false. end select - if (ngot >= 1) igotallstam = .true. + if (od_method .ne. 1 .and. od_method .ne. 2) then + call warning('cooling_stamatellos','optical depth method unknown') + endif + + if (ngot >= 2) igotallstam = .true. end subroutine read_options_cooling_stamatellos diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index f2602a9dc..0f58868b7 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -5,7 +5,7 @@ module eos_stamatellos implicit none real, public :: optable(260,1001,6) - real,allocatable,public :: gradP_cool(:),Gpot_cool(:) + real,allocatable,public :: Gpot_cool(:), gradP_cool(:) !==gradP/rho integer,public :: iunitst=19 public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains From 1270dafac51f9927dc3ad752a20dca5a74e94350 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 16 Mar 2023 12:06:32 +0000 Subject: [PATCH 021/182] Stellar heating edits in cooling_stamatellos.f90 --- src/main/cooling_stamatellos.f90 | 44 +++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 3c0f85f79..01efea6a3 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -32,9 +32,9 @@ subroutine init_star() real :: rsink2,rsink2min rsink2min = 0d0 - if (nptmass == 0) then - isink_star = 0 ! no star present - print *, "No illuminating star." + if (nptmass == 0 .or. Lstar == 0.0) then + isink_star = 0 ! no stellar heating + print *, "No stellar heating." elseif (nptmass == 1) then isink_star = 1 else @@ -47,7 +47,7 @@ subroutine init_star() enddo isink_star = imin endif - if (nptmass > 0) print *, "Using sink no. ", isink_star, "as illuminating star." + if (isink_star > 0) print *, "Using sink no. ", isink_star, "as illuminating star." end subroutine init_star ! @@ -64,21 +64,25 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) integer,intent(in) :: i real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 - real :: Tirri,gammai,gmwi,Tmini,Ti,dudt_rad,Teqi + real :: gammai,gmwi,Tmini4,Ti,dudt_rad,Teqi real :: tcool,ueqi,umini,tthermi,poti,presi poti = Gpot_cool(i) presi = eos_vars(igasP,i) ! Tfloor is from input parameters and is background heating ! Stellar heating - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2 + (yi-xyzmh_ptmass(2,isink_star))**2 & - + (zi-xyzmh_ptmass(3,isink_star))**2 - ri2 = ri2 *udist*udist - Tirri = (Lstar*solarl/(4d0*pi*steboltz)/ri2)**0.25 - Tmini = Tfloor + Tirri ! Tfloor + stellar heating + if (isink_star > 0 .and. Lstar > 0) then + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + + (zi-xyzmh_ptmass(3,isink_star))**2d0 + ri2 = ri2 *udist*udist +! Tfloor + stellar heating + Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2)) + else + Tmini4 = Tfloor**4d0 + endif ! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi,gammai) select case (od_method) @@ -94,23 +98,24 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! write(iunitst,'(5E12.5)') coldensi,presi,gradP_cool(i) tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units - dudt_rad = 4.d0*steboltz*(Tmini**4.d0 - Ti**4.d0)/tcool/unit_ergg*utime! code units + dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units ! calculate Teqi Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime Teqi = Teqi/4.d0/steboltz - Teqi = Teqi + Tmini**4.d0 - if (Teqi < Tmini**4.d0) then - Teqi = Tmini + Teqi = Teqi + Tmini4 + if (Teqi < Tmini4) then + Teqi = Tmini4**(1.0/4.0) else - Teqi = Teqi**0.25d0 + Teqi = Teqi**(1.0/4.0) endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg - call getintenerg_opdep(Tmini,rhoi*unit_density,umini) + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg ! calculate thermalization timescale if ((dudti_sph + dudt_rad) == 0.d0) then tthermi = 0d0 + write(iunitst,'(A)') "ttherm=0" else tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) endif @@ -147,7 +152,7 @@ subroutine write_options_cooling_stamatellos(iunit) end subroutine write_options_cooling_stamatellos subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) - use io, only:warning + use io, only:warning,fatal character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallstam integer, intent(out) :: ierr @@ -162,6 +167,9 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie ngot = ngot + 1 case('OD method') read(valstring,*,iostat=ierr) od_method + if (od_method < 1 .or. od_method > 2) then + call fatal('cooling options','od_method must be 1 or 2',var='od_method',ival=od_method) + endif ngot = ngot + 1 case default imatch = .false. From 3a625f52ccf7ba8ec69228391cea527504315545 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 16 Mar 2023 12:20:41 +0000 Subject: [PATCH 022/182] remove redundant file --- src/main/interp_optab.F90 | 193 -------------------------------------- 1 file changed, 193 deletions(-) delete mode 100644 src/main/interp_optab.F90 diff --git a/src/main/interp_optab.F90 b/src/main/interp_optab.F90 deleted file mode 100644 index 87c189a84..000000000 --- a/src/main/interp_optab.F90 +++ /dev/null @@ -1,193 +0,0 @@ -!-------------------------------------------------------------------------- -! Script to interpolate the opacity table myeos.dat -!-------------------------------------------------------------------------- - -module interp_optab -implicit none -contains -subroutine read_optab(OPTABLE,ierr) - use datafiles, only:find_phantom_datafile - - real, intent(out) :: OPTABLE(260,1001,6) - integer, intent(out) :: ierr - integer i,j,nx,ny - character(len=120) :: filepath - - ! read in data file for interpolation - filepath=find_phantom_datafile('myeos.dat','cooling') - print *,"FILEPATH:",filepath - open(10, file=filepath, form="formatted", status="old",iostat=ierr) - if (ierr > 0) return - read(10, *) nx, ny - do i = 1,nx - do j = 1,ny - read(10,*) OPTABLE(i,j,1),OPTABLE(i,j,2),OPTABLE(i,j,3),& - OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) - enddo - enddo - -end subroutine read_optab - -subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai,OPTABLE) - real, intent(in) :: ui,rhoi - real, intent(out) :: kappaBar,kappaPart,Ti,gmwi,gammai - real, intent(in) :: OPTABLE(260,1001,6) - - !real OPTABLE(260,1001,6) - integer i,j,k,nx,ny - real m,c - real kbar1,kbar2 - real kappa1,kappa2 - real Tpart1,Tpart2 - real gmw1,gmw2 - real cv - real ui_, rhoi_ - - ! interpolate through OPTABLE to find corresponding kappaBar, kappaPart and T - - if (rhoi.lt.1.0e-24) then - rhoi_ = 1.0e-24 - else - rhoi_ = rhoi - endif - - i = 1 - do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) - i = i + 1 - enddo - - if (ui.lt.0.5302E8) then - ui_ = 0.5302E8 - else - ui_ = ui - endif - - j = 1 - do while ((OPTABLE(i-1,j,3).le.ui_).and.(j.lt.1000)) - j = j + 1 - enddo - - m = (OPTABLE(i-1,j-1,5) - OPTABLE(i-1,j,5))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) - c = OPTABLE(i-1,j,5) - m*OPTABLE(i-1,j,3) - - kbar1 = m*ui_ + c - - m = (OPTABLE(i-1,j-1,6) - OPTABLE(i-1,j,6))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) - c = OPTABLE(i-1,j,6) - m*OPTABLE(i-1,j,3) - - kappa1 = m*ui_ + c - - m = (OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) - c = OPTABLE(i-1,j,2) - m*OPTABLE(i-1,j,3) - - Tpart1 = m*ui_ + c - - m = (OPTABLE(i-1,j-1,4) - OPTABLE(i-1,j,4))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) - c = OPTABLE(i-1,j,4) - m*OPTABLE(i-1,j,3) - - gmw1 = m*ui_ + c - - j = 1 - do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.1000)) - j = j + 1 - enddo - - m = (OPTABLE(i,j-1,5) - OPTABLE(i,j,5))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) - c = OPTABLE(i,j,5) - m*OPTABLE(i,j,3) - - kbar2 = m*ui_ + c - - m = (OPTABLE(i,j-1,6) - OPTABLE(i,j,6))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) - c = OPTABLE(i,j,6) - m*OPTABLE(i,j,3) - - kappa2 = m*ui_ + c - - m = (OPTABLE(i,j-1,2) - OPTABLE(i,j,2))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) - c = OPTABLE(i,j,2) - m*OPTABLE(i,j,3) - - Tpart2 = m*ui_ + c - - m = (OPTABLE(i,j-1,4) - OPTABLE(i,j,4))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) - c = OPTABLE(i,j,4) - m*OPTABLE(i,j,3) - - gmw2 = m*ui_ + c - - m = (kappa2 - kappa1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) - c = kappa2 - m*OPTABLE(i,1,1) - - kappaPart = m*rhoi_ + c - !kappaPart = kappaPart*kappa_corr - - m = (kbar2 - kbar1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) - c = kbar2 - m*OPTABLE(i,1,1) - - kappaBar = m*rhoi_ + c - !kappaBar = kappaBar*kappa_corr - - m = (Tpart2 - Tpart1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) - c = Tpart2 - m*OPTABLE(i,1,1) - - Ti = m*rhoi_ + c - - m = (gmw2 - gmw1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) - c = gmw2 - m*OPTABLE(i,1,1) - - gmwi = m*rhoi_ + c - - cv = ui_/Ti - gammai = 1.0d0 + 1.38d-16/1.67d-24/gmwi/cv -end subroutine getopac_opdep - -subroutine getintenerg_opdep(Teqi, rhoi, ueqi, OPTABLE) - real, intent(out) :: ueqi - real, intent(in) :: Teqi,rhoi - !real, intent(inout) :: OPTABLE(260,1001,6) - - real u1, u2 - real m, c - integer i, j, nx, ny - real rhoi_ - real, intent(in) :: OPTABLE(260,1001,6) - - ! interpolate through OPTABLE to obtain equilibrium internal energy - - if (rhoi.lt.1.0e-24) then - rhoi_ = 1.0e-24 - else - rhoi_ = rhoi - endif - - i = 1 - do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) - i = i + 1 - enddo - - j = 1 - do while ((OPTABLE(i-1,j,2).le.Teqi).and.(j.lt.1000)) - j = j + 1 - enddo - - m = (OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3))/(OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2)) - c = OPTABLE(i-1,j,3) - m*OPTABLE(i-1,j,2) - - u1 = m*Teqi + c - - j = 1 - do while ((OPTABLE(i,j,2).le.Teqi).and.(j.lt.1000)) - j = j + 1 - enddo - - m = (OPTABLE(i,j-1,3) - OPTABLE(i,j,3))/(OPTABLE(i,j-1,2) - OPTABLE(i,j,2)) - c = OPTABLE(i,j,3) - m*OPTABLE(i,j,2) - - u2 = m*Teqi + c - - m = (u2 - u1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) - c = u2 - m*OPTABLE(i,1,1) - - ueqi = m*rhoi_ + c -end subroutine getintenerg_opdep - -end module interp_optab - - From e7fc37e55b84338c3b9f57d89a752e18617ff1a1 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 27 Mar 2023 14:14:25 +0100 Subject: [PATCH 023/182] Implements reading of named tabulated EOS file for Stamatellos/Lombardi EOS/cooling --- src/main/cooling.F90 | 11 +++++++---- src/main/cooling_stamatellos.f90 | 10 ++++++++-- src/main/eos.F90 | 8 ++++---- src/main/eos_stamatellos.f90 | 24 +++++++++++++++++------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 1011031ba..d64344363 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -69,11 +69,12 @@ subroutine init_cooling(id,master,iprint,ierr) use cooling_molecular, only:init_cooling_molec use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver - use eos_stamatellos, only:read_optab + use eos_stamatellos, only:read_optab, eos_file use cooling_stamatellos, only: init_star integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr + logical :: ex cooling_in_step = .true. ierr = 0 @@ -85,8 +86,10 @@ subroutine init_cooling(id,master,iprint,ierr) select case(icooling) case(8) if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=8 requires ieos=21',var='ieos',ival=ieos) - if (ieos == 2) call read_optab(ierr) - if (ierr > 0) call fatal('cooling','Failed to read myeos.dat',var='ierr',ival=ierr) + 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) @@ -116,7 +119,7 @@ subroutine init_cooling(id,master,iprint,ierr) endif if (maxvxyzu < 4) ierr = 1 elseif (icooling == 8) then - ufloor = 0. ! because we use the umin(:) array + ufloor = 0. ! because we calculate & use umin separately else ufloor = 0. endif diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index abf43e3f1..46190084e 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -14,7 +14,7 @@ module cooling_stamatellos ! ! :Runtime parameters: None ! -! :Dependencies: +! :Dependencies: eos_stamatellos, physcon,io,units,part ! implicit none @@ -143,9 +143,11 @@ end subroutine cooling_S07 subroutine write_options_cooling_stamatellos(iunit) use infile_utils, only:write_inopt + use eos_stamatellos, only: eos_file integer, intent(in) :: iunit !N.B. Tfloor handled in cooling.F90 + call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) @@ -153,6 +155,7 @@ end subroutine write_options_cooling_stamatellos subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) use io, only:warning,fatal +use eos_stamatellos, only: eos_file character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallstam integer, intent(out) :: ierr @@ -171,6 +174,9 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie call fatal('cooling options','od_method must be 1 or 2',var='od_method',ival=od_method) endif ngot = ngot + 1 + case('EOS_file') + read(valstring,*,iostat=ierr) eos_file + ngot = ngot + 1 case default imatch = .false. end select @@ -178,7 +184,7 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie call warning('cooling_stamatellos','optical depth method unknown') endif - if (ngot >= 2) igotallstam = .true. + if (ngot >= 3) igotallstam = .true. end subroutine read_options_cooling_stamatellos diff --git a/src/main/eos.F90 b/src/main/eos.F90 index b8abfa757..9ad4fcb12 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -24,7 +24,7 @@ module eos ! 15 = Helmholtz free energy eos ! 16 = Shen eos ! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) -! 21 = read tabulated eos of Stametellos et al. (2007) +! 21 = read tabulated eos (for use with icooling == 8) ! ! :References: ! Lodato & Pringle (2007) @@ -440,7 +440,7 @@ subroutine init_eos(eos_type,ierr) use eos_barotropic, only:init_eos_barotropic use eos_shen, only:init_eos_shen_NL3 use eos_gasradrec, only:init_eos_gasradrec - use eos_stamatellos,only:read_optab,init_S07cool + use eos_stamatellos,only:read_optab,init_S07cool,eos_file use dim, only:maxvxyzu,do_radiation integer, intent(in) :: eos_type integer, intent(out) :: ierr @@ -517,8 +517,8 @@ subroutine init_eos(eos_type,ierr) ierr = ierr_option_conflict endif case(21) - call read_optab(ierr) - if (ierr > 0) call fatal('init_eos','Failed to read myeos.dat',var='ierr',ival=ierr) + call read_optab(eos_file,ierr) + if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) call init_S07cool end select diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 0f58868b7..69aea898f 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -1,11 +1,12 @@ !-------------------------------------------------------------------------- -! Script to interpolate the opacity table myeos.dat +! Script to interpolate the opacity table eos_file !-------------------------------------------------------------------------- module eos_stamatellos implicit none real, public :: optable(260,1001,6) real,allocatable,public :: Gpot_cool(:), gradP_cool(:) !==gradP/rho + character(len=25), public :: eos_file !file name of tabulated EOS file integer,public :: iunitst=19 public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains @@ -17,6 +18,8 @@ subroutine init_S07cool() allocate(gradP_cool(npart)) allocate(Gpot_cool(npart)) open (unit=iunitst,file='EOSinfo.dat',status='replace') + + end subroutine init_S07cool subroutine finish_S07cool() @@ -25,19 +28,26 @@ subroutine finish_S07cool() close(iunitst) end subroutine finish_S07cool -subroutine read_optab(ierr) +subroutine read_optab(eos_file,ierr) use datafiles, only:find_phantom_datafile - + character(len=*),intent(in) :: eos_file integer, intent(out) :: ierr - integer i,j,nx,ny - character(len=120) :: filepath + integer i,j,nx,ny,errread + character(len=120) :: filepath,junk ! read in data file for interpolation - filepath=find_phantom_datafile('myeos.dat','cooling') + filepath=find_phantom_datafile(eos_file,'cooling') print *,"FILEPATH:",filepath open(10, file=filepath, form="formatted", status="old",iostat=ierr) if (ierr > 0) return - read(10, *) nx, ny + do + read(10,'(A120)') junk + if (index(adjustl(junk),'::') .eq. 0) then !ignore comment lines + junk = adjustl(junk) + read(junk, *,iostat=errread) nx, ny + exit + endif + enddo do i = 1,nx do j = 1,ny read(10,*) OPTABLE(i,j,1),OPTABLE(i,j,2),OPTABLE(i,j,3),& From 4070d6627e024f4194dc857ebd6a6de725605a07 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 27 Mar 2023 15:35:48 +0100 Subject: [PATCH 024/182] Bug fixes --- src/main/eos_stamatellos.f90 | 2 +- src/main/step_leapfrog.F90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 69aea898f..16ae0a91d 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -6,7 +6,7 @@ module eos_stamatellos implicit none real, public :: optable(260,1001,6) real,allocatable,public :: Gpot_cool(:), gradP_cool(:) !==gradP/rho - character(len=25), public :: eos_file !file name of tabulated EOS file + character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file integer,public :: iunitst=19 public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 55dd29e17..bcdc7639c 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -99,7 +99,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) rad,drad,radprop,isdead_or_accreted,rhoh,dhdrho,& iphase,iamtype,massoftype,maxphase,igas,idust,mhd,& iamboundary,get_ntypes,npartoftypetot,& - dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass, + dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,ics use options, only:avdecayconst,alpha,ieos,alphamax use deriv, only:derivs From e1ff32e3176728d9e1e8afe446445ca1ef6daf36 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 27 Mar 2023 16:18:48 +0100 Subject: [PATCH 025/182] Add default opacity method --- src/main/cooling_stamatellos.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 46190084e..671646d9d 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -20,7 +20,7 @@ module cooling_stamatellos implicit none real, public :: Lstar ! in units of L_sun integer :: isink_star ! index of sink to use as illuminating star - integer :: od_method + integer :: od_method = 1 ! default = Stamatellos+ 2007 method public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star From 4972d852b70ca5fa4fb4e040279fe346e82559c0 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 28 Mar 2023 15:11:08 +0100 Subject: [PATCH 026/182] Edits to equations for Lombardi+ 2015 cooling --- src/main/cooling_stamatellos.f90 | 46 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 671646d9d..1313b4e0c 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -90,8 +90,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) coldensi = 0.368d0*coldensi ! n=2 in polytrope formalism Forgan+ 2009 coldensi = coldensi*umass/udist/udist ! physical units - case(2) -! testing Lombardi+ method of estimating the mean column density + case (2) +! Lombardi+ method of estimating the mean column density coldensi = 1.014d0 * presi / abs(-gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 coldensi = coldensi *umass/udist/udist ! physical units end select @@ -99,39 +99,51 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units + + ! calculate Teqi - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg + if (od_method == 1) then + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + 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 + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg + endif + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg -! calculate thermalization timescale + +! calculate thermalization timescale and +! internal energy update -> put in form where it'll work as dudtcool + select case (od_method) + case (1) if ((dudti_sph + dudt_rad) == 0.d0) then tthermi = 0d0 write(iunitst,'(A)') "ttherm=0" else tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) endif - -! internal energy update -> put in form where it'll work as dudtcool if (tthermi == 0d0) then dudti_cool = 0.d0 ! condition if denominator above is zero else dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif + case (2) + tthermi = (umini - ui) / dudt_rad + dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph + end select + if (isnan(dudti_cool)) then print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "poti=",poti, "rhoi=",rhoi, "Ti=", Ti + print *, "rhoi=",rhoi, "Ti=", Ti print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph - print *, "Teqi=",Teqi, "dt=",dt,"tthermi=", tthermi,"ueqi=", ueqi + print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then From 4a88d6029626155bafc87e9919b70887bab2b4e7 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 31 Mar 2023 16:06:32 +0100 Subject: [PATCH 027/182] correction to gradP_cool --- src/main/force.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index a473a5af3..2a8e32f59 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1555,7 +1555,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g !--add av term to pressure gradpi = pmassj*(pro2i + qrho2i)*grkerni if (usej) gradpj = pmassj*(pro2j + qrho2j)*grkernj - + !-- calculate grad P from gas pressure alone for cooling + if (icooling == 8) gradP_cool(i) = gradP_cool(i) + & + pmassj*pro2i*grkerni + pmassj*pro2j*grkernj !--artificial thermal conductivity (need j term) if (maxvxyzu >= 4) then #ifdef GR @@ -1662,7 +1664,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g projsx = projsxi + projsxj projsy = projsyi + projsyj projsz = projszi + projszj - if (icooling == 8) gradP_cool(i) = gradP_cool(i) + gradp + fsum(ifxi) = fsum(ifxi) - runix*(gradp + fgrav) - projsx fsum(ifyi) = fsum(ifyi) - runiy*(gradp + fgrav) - projsy From c2ddedbdc3dd689fb435d0d23d4f0ecfa24351a9 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 3 Apr 2023 14:05:58 +0100 Subject: [PATCH 028/182] Changes to generalise opacity table read. --- src/main/cooling.F90 | 12 ++++++++---- src/main/eos_stamatellos.f90 | 26 +++++++++++++++----------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index d64344363..c47f208ce 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -62,15 +62,16 @@ subroutine init_cooling(id,master,iprint,ierr) use dim, only:maxvxyzu,h2chemistry use units, only:unit_ergg use physcon, only:mass_proton_cgs,kboltz - use io, only:error,fatal + use io, only:error,fatal,warning use eos, only:gamma,gmw,ieos use cooling_ism, only:init_cooling_ism use chem, only:init_chem use cooling_molecular, only:init_cooling_molec use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver - use eos_stamatellos, only:read_optab, eos_file - use cooling_stamatellos, only: init_star + use eos_stamatellos, only:read_optab,eos_file + use cooling_stamatellos, only: init_star,od_method + use viscosity, only:irealvisc integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr @@ -85,7 +86,10 @@ subroutine init_cooling(id,master,iprint,ierr) else select case(icooling) case(8) - if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=8 requires ieos=21',var='ieos',ival=ieos) + if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=8 requires ieos=21',& + var='ieos',ival=ieos) + if (irealvisc > 0 .and. od_method == 2) 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) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 16ae0a91d..c85d5dab2 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -4,10 +4,11 @@ module eos_stamatellos implicit none - real, public :: optable(260,1001,6) + real,allocatable,public :: optable(:,:,:) real,allocatable,public :: Gpot_cool(:), gradP_cool(:) !==gradP/rho character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file integer,public :: iunitst=19 + integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains @@ -23,6 +24,7 @@ subroutine init_S07cool() end subroutine init_S07cool subroutine finish_S07cool() + deallocate(optable) if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) close(iunitst) @@ -32,7 +34,7 @@ subroutine read_optab(eos_file,ierr) use datafiles, only:find_phantom_datafile character(len=*),intent(in) :: eos_file integer, intent(out) :: ierr - integer i,j,nx,ny,errread + integer i,j,errread character(len=120) :: filepath,junk ! read in data file for interpolation @@ -47,21 +49,23 @@ subroutine read_optab(eos_file,ierr) read(junk, *,iostat=errread) nx, ny exit endif - enddo +enddo +! allocate array for storing opacity tables + allocate(optable(nx,ny,6)) do i = 1,nx do j = 1,ny read(10,*) OPTABLE(i,j,1),OPTABLE(i,j,2),OPTABLE(i,j,3),& OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) enddo enddo - + print *, 'nx,ny=', nx, ny end subroutine read_optab subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) real, intent(in) :: ui,rhoi real, intent(out) :: kappaBar,kappaPart,Ti,gmwi,gammai - integer i,j,nx,ny + integer i,j real m,c real kbar1,kbar2 real kappa1,kappa2 @@ -79,7 +83,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) endif i = 1 - do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) + do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.nx)) i = i + 1 enddo @@ -90,7 +94,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) endif j = 1 - do while ((OPTABLE(i-1,j,3).le.ui_).and.(j.lt.1000)) + do while ((OPTABLE(i-1,j,3).le.ui_).and.(j.lt.ny)) j = j + 1 enddo @@ -115,7 +119,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) gmw1 = m*ui_ + c j = 1 - do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.1000)) + do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.ny)) j = j + 1 enddo @@ -183,12 +187,12 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) endif i = 1 - do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.260)) + do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.nx)) i = i + 1 enddo j = 1 - do while ((OPTABLE(i-1,j,2).le.Teqi).and.(j.lt.1000)) + do while ((OPTABLE(i-1,j,2).le.Teqi).and.(j.lt.ny)) j = j + 1 enddo @@ -198,7 +202,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) u1 = m*Teqi + c j = 1 - do while ((OPTABLE(i,j,2).le.Teqi).and.(j.lt.1000)) + do while ((OPTABLE(i,j,2).le.Teqi).and.(j.lt.ny)) j = j + 1 enddo From c468ad2050fb399d1cfc39424a2f48bc8f4b417a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 3 Apr 2023 15:49:17 +0100 Subject: [PATCH 029/182] Cooling gradP_cool: make usej consistent --- src/main/force.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 2a8e32f59..86818d062 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1556,8 +1556,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g gradpi = pmassj*(pro2i + qrho2i)*grkerni if (usej) gradpj = pmassj*(pro2j + qrho2j)*grkernj !-- calculate grad P from gas pressure alone for cooling - if (icooling == 8) gradP_cool(i) = gradP_cool(i) + & - pmassj*pro2i*grkerni + pmassj*pro2j*grkernj + if (icooling == 8) then + gradP_cool(i) = gradP_cool(i) + pmassj*pro2i*grkerni + if (usej) gradP_cool(i) = gradP_cool(i) + pmassj*pro2j*grkernj + endif !--artificial thermal conductivity (need j term) if (maxvxyzu >= 4) then #ifdef GR From dfcd9512aad0c1eeb2a5befbac9f4be4d4f843be Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 28 Apr 2023 16:12:38 +0100 Subject: [PATCH 030/182] FLD additions for hybrid cooling: --- src/main/cons2prim.f90 | 6 +- src/main/cooling.F90 | 7 +- src/main/cooling_stamatellos.f90 | 28 ++-- src/main/deriv.F90 | 13 +- src/main/eos_stamatellos.f90 | 12 +- src/main/force.F90 | 4 +- src/main/options.f90 | 1 + src/main/radiation_implicit.f90 | 266 ++++++++++++++++++++++++++++++- src/main/radiation_utils.f90 | 14 +- 9 files changed, 329 insertions(+), 22 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index d3c78c51a..fd73250c9 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -291,7 +291,11 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& ! ! Get the opacity from the density and temperature if required ! - if (iopacity_type > 0) call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i)) + if (iopacity_type == 3) then + call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i),ui=vxyzu(4,i)) + elseif (iopacity_type > 0) then + call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i)) + endif endif ! ! Get radiation pressure from the radiation energy, i.e. P = 1/3 E if optically thick diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index d64344363..e1b0905f1 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -59,10 +59,10 @@ module cooling !+ !----------------------------------------------------------------------- subroutine init_cooling(id,master,iprint,ierr) - use dim, only:maxvxyzu,h2chemistry + use dim, only:maxvxyzu,h2chemistry,do_radiation use units, only:unit_ergg use physcon, only:mass_proton_cgs,kboltz - use io, only:error,fatal + use io, only:error,fatal,warning use eos, only:gamma,gmw,ieos use cooling_ism, only:init_cooling_ism use chem, only:init_chem @@ -90,6 +90,9 @@ subroutine init_cooling(id,master,iprint,ierr) 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) + if (do_radiation) then + call fatal('cooling','Do radiation was switched on!') + endif call init_star() case(6) call init_cooling_KI02(ierr) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 1313b4e0c..78865802b 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -58,17 +58,19 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use physcon, only:steboltz,pi,solarl use units, only:umass,udist,unit_density,unit_ergg,utime use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool, & - iunitst - use part, only:eos_vars,igasP,xyzmh_ptmass + iunitst,du_FLD,FLD + use dim, only:do_radiation + use part, only:eos_vars,igasP,xyzmh_ptmass real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 - real :: gammai,gmwi,Tmini4,Ti,dudt_rad,Teqi - real :: tcool,ueqi,umini,tthermi,poti,presi + real :: gammai,gmwi,Tmini4,Ti,dudt_rad,Teqi,du_tot + real :: tcool,ueqi,umini,tthermi,poti,presi,du_FLDi poti = Gpot_cool(i) presi = eos_vars(igasP,i) + du_FLDi = du_FLD(i) ! Tfloor is from input parameters and is background heating ! Stellar heating if (isink_star > 0 .and. Lstar > 0) then @@ -103,7 +105,14 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! calculate Teqi if (od_method == 1) then - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + if (FLD) then + ! include term from FLD + Teqi = du_FLDi*dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + du_FLDi + else + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + endif Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini4 if (Teqi < Tmini4) then @@ -115,18 +124,18 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ueqi = ueqi/unit_ergg endif - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg ! calculate thermalization timescale and ! internal energy update -> put in form where it'll work as dudtcool select case (od_method) case (1) - if ((dudti_sph + dudt_rad) == 0.d0) then + if ((du_tot) == 0.d0) then tthermi = 0d0 write(iunitst,'(A)') "ttherm=0" else - tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) + tthermi = abs((ueqi - ui)/(du_tot)) endif if (tthermi == 0d0) then dudti_cool = 0.d0 ! condition if denominator above is zero @@ -200,4 +209,5 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie end subroutine read_options_cooling_stamatellos + end module cooling_stamatellos diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 34762a023..242e7776f 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -72,8 +72,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use derivutils, only:do_timing use cons2prim, only:cons2primall,cons2prim_everything,prim2consall use metric_tools, only:init_metric - use radiation_implicit, only:do_radiation_implicit - use options, only:implicit_radiation,implicit_radiation_store_drad + use radiation_implicit, only:do_radiation_implicit,get_diffusion_term_only + use options, only:implicit_radiation,implicit_radiation_store_drad,icooling + use eos_stamatellos, only:FLD,du_FLD,radprop_FLD integer, intent(in) :: icall integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -175,7 +176,13 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& call do_radiation_implicit(dt,npart,rad,xyzh,vxyzu,radprop,drad,ierr) if (ierr /= 0) call fatal('radiation','Failed to converge') endif - + + ! compute diffusion term for hybrid RT & polytropic cooling method + if (icooling == 8 .and. dt > 0. .and. FLD) then + !print *, "calling diff term from deriv" + call get_diffusion_term_only(npart,xyzh,vxyzu,radprop_FLD,du_FLD) + endif + ! ! compute forces ! diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 16ae0a91d..2d6b70bb6 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -5,26 +5,34 @@ module eos_stamatellos implicit none real, public :: optable(260,1001,6) - real,allocatable,public :: Gpot_cool(:), gradP_cool(:) !==gradP/rho + real,allocatable,public :: Gpot_cool(:), du_FLD(:),gradP_cool(:),radprop_FLD(:,:) !gradP_cool=gradP/rho character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file + real, parameter,public :: arad=7.5657d-15 + logical,parameter,public :: FLD = .true. integer,public :: iunitst=19 public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains subroutine init_S07cool() - use part, only:npart + use part, only:npart,maxradprop print *, "Allocating S07 arrays" allocate(gradP_cool(npart)) allocate(Gpot_cool(npart)) + allocate(du_FLD(npart)) + allocate(radprop_FLD(maxradprop,npart)) + open (unit=iunitst,file='EOSinfo.dat',status='replace') end subroutine init_S07cool subroutine finish_S07cool() + use part, only: radprop if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) + if (allocated(du_FLD)) deallocate(du_FLD) + if (allocated(radprop_FLD)) deallocate(radprop_FLD) close(iunitst) end subroutine finish_S07cool diff --git a/src/main/force.F90 b/src/main/force.F90 index a473a5af3..962728dcc 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1159,7 +1159,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravxi = 0. fgravyi = 0. fgravzi = 0. - if (icooling == 8) gradP_cool(i) = 0d0 + if (icooling == 8) then + gradP_cool(i) = 0d0 + endif loop_over_neighbours2: do n = 1,nneigh diff --git a/src/main/options.f90 b/src/main/options.f90 index 38efe745d..4d742c15a 100644 --- a/src/main/options.f90 +++ b/src/main/options.f90 @@ -167,6 +167,7 @@ subroutine set_default_options endif implicit_radiation_store_drad = .false. + ! variable composition use_var_comp = .false. diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index 92d0bf65b..94531cb87 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -46,7 +46,7 @@ module radiation_implicit character(len=*), parameter :: label = 'radiation_implicit' private - public :: do_radiation_implicit + public :: do_radiation_implicit,get_diffusion_term_only contains @@ -1512,4 +1512,268 @@ subroutine solve_quartic(u1term,u0term,uold,soln,moresweep,ierr) end subroutine solve_quartic +!--------------------------------------------------------- +!+ +! Calculate the diffusion term for implementing hybrid +! radiative transfer method of Forgan et al. (2009). +! Used in cooling_stamatellos.f90 +!+ +!--------------------------------------------------------- +subroutine get_diffusion_term_only(npart,xyzh,vxyzu,radprop_FLD,du_FLD) + use io, only:fatal,warning + use eos_stamatellos, only:getopac_opdep + use kernel, only:radkern,grkern,cnormk + use part, only:hfact,ilambda,gradh,rhoh + use physcon, only:steboltz,pi + use units, only:unit_density,unit_energ,unit_opacity,udist,utime,unit_ergg + use timestep, only:dtmax + real, intent(in) :: xyzh(:,:),vxyzu(:,:) + real, intent(inout) :: radprop_FLD(:,:) + real, intent(out) :: du_FLD(:) + integer,allocatable :: ivar(:,:),ijvar(:) + real,allocatable :: utherm(:),rho_all(:) + integer :: npart,nneigh_average,icompactmax,ncompact,ncompactlocal,i,j,k + integer :: icompact,ierr,n + real :: dudiffi,err,steboltz_code,dx,dy,dz,runix,runiy,runiz,rij,rij2,rij1 + real :: diffusion_numerator,diffusion_denominator,dWi,hi,hi1,hi21,q,q2 + real :: kappaBari,kappaParti,Ti,gmwi,gammai,kappaBarj,kappaPartj,Tj,gmwj + real :: rdotdW,rhoi,rhoj,gammaj,ki,kj,pmassj,tdiff + + steboltz_code = steboltz/unit_energ*udist*udist*utime + !print *, 'set steboltz_code' + npart = size(xyzh(1,:)) + nneigh_average = int(4./3.*pi*(radkern*hfact)**3) + 1 + icompactmax = int(1.2*nneigh_average*npart) + allocate(ivar(3,npart),stat=ierr) + if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for ivar') + allocate(ijvar(icompactmax),stat=ierr) + if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for ijvar') + allocate(utherm(npart),stat=ierr) + if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for utherm') + allocate(rho_all(npart),stat=ierr) + if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for rho_all') + !dtimax = dt/imaxstep ?what's this? + + call get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) + ! check for errors + if (ncompact <= 0 .or. ncompactlocal <= 0) then + call fatal('radiation_implicit','empty neighbour list - need to call set_linklist first?') + endif + + utherm(:) = vxyzu(4,:) + du_FLD(:) = 0. + +!$omp parallel do default(none)& +!$omp shared(npart,rho_all,vxyzu,ivar,massoftype,utherm)& +!$omp private(n,i) + do i = 1, npart + rho_all(i) = rhoh(vxyzu(4,i),massoftype(igas)) + if (utherm(i) > 1e-4) print *, "i=", i , utherm(i) + enddo +!$omp end parallel do + + if (any(utherm > 1e-4,1)) print *, "utherm dodgy before got lambda" + radprop_FLD(:,:) = 0. + call get_lambda_hybrid(ivar,ijvar,ncompact,npart,icompactmax,utherm,radprop_FLD,xyzh,rho_all) + + if (any(utherm> 1e-4)) print *, "utherm dodgy after got lambda" + + pmassj = massoftype(igas) + !$omp parallel do default(none)& + !$omp shared(ivar,ijvar,radprop_FLD,rho_all,unit_energ,unit_density,steboltz_code)& + !$omp shared(xyzh,du_FLD,gradh,unit_ergg,utherm,unit_opacity,dtmax)& + !$omp private(i,j,n,ki,kj,rhoi,rhoj,diffusion_numerator,diffusion_denominator)& + !$omp private(icompact,kappaBari,kappaParti,Ti,gmwi,gammai)& + !$omp private(dudiffi,pmassj,rdotdW,rij,rij2,rij1,hi,hi1,hi21,q,q2,dx,dy,dz)& + !$omp private(runix,runiy,runiz,dWi,kappaBarj,kappaPartj,Tj,gmwj,gammaj,tdiff) + do n = 1,ncompact + i = ivar(3,n) + hi = xyzh(4,i) + hi21 = 1./(hi*hi) + hi1 = 1./hi + rhoi = rho_all(i) + if (utherm(i) > 1e-4) print *, i, "utherm dodgy" + call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi,gammai) + if (kappaParti <= 0.) then + print *, "fail", rhoi*unit_density,kappaParti,Ti, utherm(i) + call fatal('get_diffusion_term_only - i','Negative or zero opacity') + endif + ki = 16d0*steboltz_code*radprop_FLD(ilambda,i)*Ti**3.d0!thermal conductivity + ki = ki/rhoi/kappaParti/unit_opacity + + ! + !--NOTE: Needs to do this loop even for boundaryparticles because active + ! boundary particles will need to contribute to the varinew() + ! quantities (i.e. diffusion terms) of particle j due to the way that + ! particle j only finds neighbours inside h_j or non-active particles + ! inside h_i. The varinew() quantities of a boundaryparticle are + ! not used, but its contributions to j are. + + diffusion_numerator = 0. + diffusion_denominator = 0. + dudiffi = 0. + ! + !--All the neighbours loop + ! + do k = 1,ivar(1,n) + icompact = ivar(2,n) + k + j = ijvar(icompact) + rhoj = rho_all(j) + dx = xyzh(1,i) - xyzh(1,j) + dy = xyzh(2,i) - xyzh(2,j) + dz = xyzh(3,i) - xyzh(3,j) + call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj,gammaj) + if (kappaPartj <= 0.) then + print *, "fail", rhoj*unit_density,kappaPartj,Tj, utherm(j)*unit_energ + call fatal('get_diffusion_term_only - j','Negative or zero opacity') + endif + + kj = 16d0*steboltz_code*radprop_FLD(ilambda,j)*Tj**3.d0!thermal conductivity + kj = kj/rhoj/kappaPartj/unit_opacity + rij2 = dx*dx + dy*dy + dz*dz + tiny(0.) + rij = sqrt(rij2) + rij1 = 1./rij + + q = rij/hi + q2 = rij2*hi21 + ! unit vector components + runix = dx*rij1 + runiy = dy*rij1 + runiz = dz*rij1 + + dWi = grkern(q2,q)*cnormk*hi21*hi21*gradh(1,i) + ! r.grad(W) along the separation vector + rdotdW = cnormk*dWi*(runix*dx + runiy*dy + runiz*dz) !Why the cnormk? + diffusion_numerator = 4d0*pmassj*ki*kj*(Ti-Tj)*rdotdW + diffusion_denominator = rhoi*rhoj*(ki+kj)*rij2 + dudiffi = dudiffi + diffusion_numerator/diffusion_denominator + ! Timestep switch: define diffusion timescale between this particle pair: if this is too small, diffusion + ! is so efficient that it is essentially cooling, so diff term is set to zero. + if (dudiffi.ne.0.0d0) then + tdiff = ABS((utherm(i) + utherm(j))/(2.0d0*dudiffi)) + if (tdiff.lt.dtmax) then + dudiffi = 0.0d0 + endif + endif + + enddo + du_FLD(i) = dudiffi + enddo + !$omp end parallel do + + !check energy conserved - what's the tolerance? tiny(err) is machine precision... + err = sum(du_FLD)/minval(du_FLD,MASK= abs(du_FLD) > 0) + err = abs(err) + if (err > 1e-7) then + print *, 'err sum=', sum(du_FLD), "max:", maxval(du_FLD,MASK= abs(du_FLD) > 0),"min:", minval(du_FLD,MASK= abs(du_FLD) > 0) + call fatal('get_diffusion_term_only','energy not conserved',var='err',val=err) + endif + !print *, "about to deallocate" + deallocate(ivar,ijvar,utherm,rho_all) + + end subroutine get_diffusion_term_only + +!--------------------------------------------------------- +!+ +! Calculate the radiation energy density and flux from +! temperature for hybrid cooling +!+ +!--------------------------------------------------------- + subroutine get_lambda_hybrid(ivar,ijvar,ncompact,npart,icompactmax,& + utherm,radprop_FLD,xyzh,rho_all) + use eos_stamatellos, only:getopac_opdep,arad + use kernel, only:get_kernel,cnormk + use units, only:unit_density,unit_ergg,unit_opacity,udist + use part, only:massoftype,igas,gradh + + integer, intent(in) :: ivar(:,:),ijvar(:),ncompact,npart,icompactmax + real, intent(in) :: xyzh(:,:),utherm(:),rho_all(:) + real, intent(inout) :: radprop_FLD(:,:) + integer :: i,j,k,n,icompact + real :: rhoi,rhoj + real :: uradi,dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj,gammaj,wkerni,grkerni + real :: kappaBari,kappaParti,gmwi,gammai,dx,dy,dz,rij2,rij,rij1,Wi,dWi + real :: dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4 + real :: pmassj,hi,hi21,hi1,q,q2 + + pmassj = massoftype(igas) + !$omp parallel do default(none)& + !$omp shared(ivar,ijvar,ncompact,radprop_FLD,unit_opacity,gradh,xyzh,unit_density,unit_ergg)& + !$omp shared(rho_all,utherm,pmassj,udist)& + !$omp private(i,j,k,n,rhoi,rhoj,icompact,uradi,dradi,Ti,Tj,wkerni,grkerni,dT4)& + !$omp private(kappaBarj,kappaPartj,gmwj,gammaj,dx,dy,dz,rij,rij2,rij1,Wi,dWi)& + !$omp private(dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,hi,hi21,hi1,q,q2)& + !$omp private(kappaBari,kappaParti,gmwi,gammai) + do n = 1,ncompact ! over compact particle list + i = ivar(3,n) + ! print *, n,ncompact,utherm(i) + uradi = 0. + dradi = 0. + dradxi = 0. + dradyi = 0. + dradzi = 0. + rhoi = rho_all(i) + + call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi,gammai) + + do k = 1,ivar(1,n) !loop over n neighbours + icompact = ivar(2,n) + k + ! print *, 'icompact',icompact + j = ijvar(icompact) + ! print *,'j',j + rhoj = rho_all(j) + ! print *, 'rhoj',rhoj + ! print *, 'xyzh(1,i)', xyzh(1,i) + ! print *, ' xyzh(1,j)', xyzh(1,j) + dx = xyzh(1,i) - xyzh(1,j) + ! print *, 'dx', dx + dy = xyzh(2,i) - xyzh(2,j) + dz = xyzh(3,i) - xyzh(3,j) + + rij2 = dx*dx + dy*dy + dz*dz + tiny(0.) + rij = sqrt(rij2) + rij1 = 1./rij + hi = xyzh(4,i) + hi21 = 1./(hi*hi) + hi1 = 1./hi + q = rij/hi + q2 = rij2*hi21 + + call get_kernel(q2,q,wkerni,grkerni) + !print *, 'got kernel' + Wi = wkerni*cnormk*hi21*hi1 + dWi = grkerni*cnormk*hi21*hi21*gradh(1,i) + + ! unit vector components + runix = dx/rij + runiy = dy/rij + runiz = dz/rij + + call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj,gammaj) + uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj*udist**3) + ! print *, 'got opdep j' + + dT4 = Ti**4d0 - Tj**4d0 + dradxi = dradxi + pmassj*arad*dT4*dWi*runix/rhoj + dradyi = dradyi + pmassj*arad*dT4*dWi*runiy/rhoj + dradzi = dradzi + pmassj*arad*dT4*dWi*runiz/rhoj + + enddo ! loop over n neighbours + ! print *, 'done neighbour loop for ', i,n + + uradi = uradi + arad*Ti**4d0 ! add self contribution + dradi = sqrt(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! magnitude + if ( (uradi == 0d0) .or. (dradi ==0d0) ) then + R_rad = 0d0 + else + R_rad = dradi / (uradi*rhoi*kappaParti/unit_opacity) !code units + endif + + radprop_FLD(ilambda,i) = (2d0 + R_rad) / (6d0 + 3d0*R_rad + R_rad*R_rad) + !print *, 'radprop_FLD', radprop_FLD(ilambda,i) + radprop_FLD(ikappa,i) = kappaParti / unit_opacity + enddo ! over particles + !$omp end parallel do + + end subroutine get_lambda_hybrid end module radiation_implicit diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 0ad8d3370..0619b345a 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -406,13 +406,15 @@ end function get_kappa ! calculate opacities !+ !-------------------------------------------------------------------- -subroutine get_opacity(opacity_type,density,temperature,kappa) +subroutine get_opacity(opacity_type,density,temperature,kappa,ui) + use eos_stamatellos, only:getopac_opdep use mesa_microphysics, only:get_kappa_mesa - use units, only:unit_density,unit_opacity + use units, only:unit_density,unit_opacity,unit_ergg real, intent(in) :: density, temperature + real, intent(in), optional :: ui real, intent(out) :: kappa integer, intent(in) :: opacity_type - real :: kapt,kapr,rho_cgs + real :: kapt,kapr,rho_cgs,Ti,gmwi,gammai,kapBar,kappaPart select case(opacity_type) case(1) @@ -429,6 +431,12 @@ subroutine get_opacity(opacity_type,density,temperature,kappa) ! kappa = kappa_cgs/unit_opacity + case(3) + ! + ! opacity for Stamatellos/Lombardi EOS + ! + call getopac_opdep(ui*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi,gammai) + kappa = kappaPart/unit_opacity case default ! ! infinite opacity From fa0b21ca214184faebd344ef1a35d1288805b411 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 15 May 2023 17:12:51 +0100 Subject: [PATCH 031/182] Use code values of kboltz and amu --- src/main/eos_stamatellos.f90 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index c85d5dab2..abd946b80 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -61,7 +61,11 @@ subroutine read_optab(eos_file,ierr) print *, 'nx,ny=', nx, ny end subroutine read_optab +! +! Main subroutine for interpolating tables to get EOS values +! subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) + use physcon, only: kboltz,atomic_mass_unit real, intent(in) :: ui,rhoi real, intent(out) :: kappaBar,kappaPart,Ti,gmwi,gammai @@ -166,7 +170,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) gmwi = m*rhoi_ + c cv = ui_/Ti - gammai = 1.0d0 + 1.38d-16/1.67d-24/gmwi/cv + gammai = 1.0d0 + kboltz/atomic_mass_unit/gmwi/cv end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) From 14eeae2df52a99a2238039c7fd11fe9da60ffaf8 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 25 May 2023 16:11:39 +0100 Subject: [PATCH 032/182] small changes to Stamatellos cooling --- src/main/cons2prim.f90 | 2 +- src/main/cooling_stamatellos.f90 | 5 +++-- src/main/eos.F90 | 16 +++++++--------- src/main/force.F90 | 4 ++-- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 340f78ac1..7443ab70b 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -280,7 +280,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& eos_vars(igasP,i) = p_on_rhogas*rhogas eos_vars(ics,i) = spsound eos_vars(itemp,i) = temperaturei - if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation) eos_vars(imu,i) = mui + if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. (ieos.eq.21)) eos_vars(imu,i) = mui if (do_radiation) then if (temperaturei > tiny(0.)) then diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 1313b4e0c..b1e526f40 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -55,7 +55,7 @@ end subroutine init_star ! subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning - use physcon, only:steboltz,pi,solarl + use physcon, only:steboltz,pi,solarl,Rg use units, only:umass,udist,unit_density,unit_ergg,utime use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool, & iunitst @@ -68,7 +68,6 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real :: tcool,ueqi,umini,tthermi,poti,presi poti = Gpot_cool(i) - presi = eos_vars(igasP,i) ! Tfloor is from input parameters and is background heating ! Stellar heating if (isink_star > 0 .and. Lstar > 0) then @@ -85,6 +84,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi,gammai) + presi = eos_vars(igasP,i) + ! presi = Rg*Ti*rhoi select case (od_method) case (1) coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) diff --git a/src/main/eos.F90 b/src/main/eos.F90 index fda740c56..548458fdd 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -24,7 +24,7 @@ module eos ! 14 = locally isothermal prescription from Farris et al. (2014) for binary system ! 15 = Helmholtz free energy eos ! 16 = Shen eos - ! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) +! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) ! 21 = read tabulated eos (for use with icooling == 8) ! ! :References: @@ -429,14 +429,9 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam endif cgsrhoi = rhoi * unit_density cgseni = eni * unit_ergg - call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,gmwi,gammai) - - if (gammai > 1.0001) then - ponrhoi = (gammai-1.)*eni ! use this if en is thermal energy - else - ponrhoi = 2./3.*eni ! en is thermal energy and gamma = 1 - endif - + call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui,gammai) + ! gammai is derived from the tables + ponrhoi = (gammai - 1.) * eni spsoundi = sqrt(gammai*ponrhoi) case default @@ -1262,6 +1257,7 @@ subroutine eosinfo(eos_type,iprint) use eos_barotropic, only:eos_info_barotropic use eos_piecewise, only:eos_info_piecewise use eos_gasradrec, only:eos_info_gasradrec + use eos_stamatellos, only:eos_file integer, intent(in) :: eos_type,iprint if (id/=master) return @@ -1303,6 +1299,8 @@ subroutine eosinfo(eos_type,iprint) else write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in endif + case(21) + write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file end select write(iprint,*) diff --git a/src/main/force.F90 b/src/main/force.F90 index 72db69f09..eacd22803 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1565,8 +1565,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (usej) gradpj = pmassj*(pro2j + qrho2j)*grkernj !-- calculate grad P from gas pressure alone for cooling if (icooling == 8) then - gradP_cool(i) = gradP_cool(i) + pmassj*pro2i*grkerni - if (usej) gradP_cool(i) = gradP_cool(i) + pmassj*pro2j*grkernj + gradP_cool(i) = gradP_cool(i) + pmassj*pri*rho1i*rho1i*grkerni + if (usej) gradP_cool(i) = gradP_cool(i) + pmassj*prj*rho1j*rho1j*grkernj endif !--artificial thermal conductivity (need j term) if (maxvxyzu >= 4) then From a9dbbebc48ef7507fc2b9c9247aedf33e9fe64ee Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 26 May 2023 15:22:13 +0100 Subject: [PATCH 033/182] Small edits for EOS=21 --- src/main/cons2prim.f90 | 3 ++- src/main/eos.F90 | 7 ++++++- src/main/eos_stamatellos.f90 | 12 +++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 7443ab70b..b5b523466 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -175,7 +175,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& Bevol,Bxyz,dustevol,dustfrac,alphaind) use part, only:isdead_or_accreted,massoftype,igas,rhoh,igasP,iradP,iradxi,ics,imu,iX,iZ,& iohm,ihall,nden_nimhd,eta_nimhd,iambi,get_partinfo,iphase,this_is_a_test,& - ndustsmall,itemp,ikappa,idmu,idgamma,icv + ndustsmall,itemp,ikappa,idmu,idgamma,icv,igamma use part, only:nucleation,gamma_chem use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,gamma,& utherm @@ -280,6 +280,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& eos_vars(igasP,i) = p_on_rhogas*rhogas eos_vars(ics,i) = spsound eos_vars(itemp,i) = temperaturei + if (ieos.eq.21) eos_vars(igamma,i) = gammai if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. (ieos.eq.21)) eos_vars(imu,i) = mui if (do_radiation) then diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 548458fdd..99f4f8bd6 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -431,6 +431,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam cgseni = eni * unit_ergg call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui,gammai) ! gammai is derived from the tables + ! print *, 'EOS gamma=', gammai ponrhoi = (gammai - 1.) * eni spsoundi = sqrt(gammai*ponrhoi) @@ -1222,6 +1223,8 @@ logical function eos_outputs_mu(ieos) select case(ieos) case(20) eos_outputs_mu = .true. + case(21) + eos_outputs_mu = .true. case default eos_outputs_mu = .false. end select @@ -1300,7 +1303,7 @@ subroutine eosinfo(eos_type,iprint) write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in endif case(21) - write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file + write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file, 'and calculated gamma.' end select write(iprint,*) @@ -1355,6 +1358,8 @@ subroutine read_headeropts_eos(ieos,hdr,ierr) if (maxvxyzu >= 4) then if (use_krome) then write(iprint,*) 'KROME eos: initial gamma = 1.666667' + elseif (ieos==21) then + write(iprint,*) 'Tabulated eos with derived gamma' else write(iprint,*) 'adiabatic eos: gamma = ',gamma endif diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index abd946b80..25ff5295c 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -76,12 +76,14 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) real Tpart1,Tpart2 real gmw1,gmw2 real cv - real ui_, rhoi_ + real ui_, rhoi_,rhomin,umin + rhomin = OPTABLE(1,1,1) + umin = OPTABLE(1,1,3) ! interpolate through OPTABLE to find corresponding kappaBar, kappaPart and T - if (rhoi.lt.1.0e-24) then - rhoi_ = 1.0e-24 + if (rhoi.lt. rhomin) then + rhoi_ = rhomin else rhoi_ = rhoi endif @@ -91,8 +93,8 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) i = i + 1 enddo - if (ui.lt.0.5302E8) then - ui_ = 0.5302E8 + if (ui.lt.umin) then + ui_ = umin else ui_ = ui endif From e36f50812a727d79cbb948bb1864b9301e4f113e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 1 Jun 2023 10:51:53 +0100 Subject: [PATCH 034/182] Edit to cooling_stamatellos.f90 for pressure method --- src/main/cooling_stamatellos.f90 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index b1e526f40..d5d288d23 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -135,8 +135,12 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif case (2) - tthermi = (umini - ui) / dudt_rad - dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph + if (dudt_rad > 0.d0) then + tthermi = (umini - ui) / dudt_rad + dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph + else ! ie Tmini == Ti + dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS + end if end select @@ -145,6 +149,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) print *, "rhoi=",rhoi, "Ti=", Ti print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini + print *, "dudt_rad=", dudt_rad call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then From a847bfbe8db5bfaecbe363c11a60889fe6fca902 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 1 Jun 2023 17:29:26 +0100 Subject: [PATCH 035/182] attempted fixes to Stamatellos cooling --- src/main/cooling_stamatellos.f90 | 7 +- src/main/eos_stamatellos.f90 | 5 +- src/main/force.F90 | 14 +- src/main/readwrite_dumps_fortran.F90 | 12 +- src/setup/setup_sphere.f90 | 205 ++++++--------------------- 5 files changed, 68 insertions(+), 175 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index d5d288d23..086438e9e 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -67,7 +67,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real :: gammai,gmwi,Tmini4,Ti,dudt_rad,Teqi real :: tcool,ueqi,umini,tthermi,poti,presi - poti = Gpot_cool(i) + poti = Gpot_cool(i) ! Tfloor is from input parameters and is background heating ! Stellar heating if (isink_star > 0 .and. Lstar > 0) then @@ -88,7 +88,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! presi = Rg*Ti*rhoi select case (od_method) case (1) - coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) + 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) @@ -96,7 +96,6 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) coldensi = 1.014d0 * presi / abs(-gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 coldensi = coldensi *umass/udist/udist ! physical units end select -! write(iunitst,'(5E12.5)') coldensi,presi,gradP_cool(i) tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units @@ -135,7 +134,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif case (2) - if (dudt_rad > 0.d0) then + if (abs(dudt_rad) > 0.d0) then tthermi = (umini - ui) / dudt_rad dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph else ! ie Tmini == Ti diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 25ff5295c..a1f913cb8 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -17,9 +17,7 @@ subroutine init_S07cool() print *, "Allocating S07 arrays" allocate(gradP_cool(npart)) - allocate(Gpot_cool(npart)) - open (unit=iunitst,file='EOSinfo.dat',status='replace') - + allocate(Gpot_cool(npart)) end subroutine init_S07cool @@ -27,7 +25,6 @@ subroutine finish_S07cool() deallocate(optable) if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) - close(iunitst) end subroutine finish_S07cool subroutine read_optab(eos_file,ierr) diff --git a/src/main/force.F90 b/src/main/force.F90 index eacd22803..2a6717cc6 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1167,8 +1167,11 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravxi = 0. fgravyi = 0. fgravzi = 0. - if (icooling == 8) gradP_cool(i) = 0d0 - + if (icooling == 8) then + gradP_cool(i) = 0d0 + Gpot_cool(i) = 0d0 + endif + loop_over_neighbours2: do n = 1,nneigh j = abs(listneigh(n)) @@ -1680,6 +1683,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifyi) = fsum(ifyi) - runiy*(gradp + fgrav) - projsy fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) + + if (ieos == 8) Gpot_cool(i) = Gpot_cool(i) + 0.5*pmassj*phii !--calculate divv for use in du, h prediction, av switch etc. fsum(idrhodti) = fsum(idrhodti) + projv*grkerni @@ -1918,9 +1923,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g enddo loop_over_neighbours2 - if (icooling == 8) then - Gpot_cool(i) = fsum(ipot) - endif if (gr .and. gravity .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fgravxi + vyi*fgravyi + vzi*fgravzi @@ -2509,6 +2511,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv #ifdef GR use part, only:pxyzu #endif + use eos_stamatellos, only:Gpot_cool integer, intent(in) :: icall type(cellforce), intent(inout) :: cell @@ -2713,6 +2716,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi + if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + 0.5*(dx*fxi + dy*fyi + dz*fzi) ! add contribution from distant nodes if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index c43c8ff6b..718004db4 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -244,6 +244,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use krome_user, only:krome_nmols use part, only:gamma_chem,mu_chem,T_gas_cool #endif + use eos_stamatellos, only: Gpot_cool, gradP_cool, iunitst real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -251,7 +252,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) integer(kind=8), intent(in), optional :: ntotal integer, parameter :: isteps_sphNG = 0, iphase0 = 0 - integer(kind=8) :: ilen(4) + integer(kind=8) :: ilen(4),i integer :: nums(ndatatypes,4) integer :: ipass,k,l,ioffset integer :: ierr,ierrs(30) @@ -262,6 +263,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) character(len=120) :: blankarray type(dump_h) :: hdr real, allocatable :: temparr(:) + real :: r ! !--collect global information from MPI threads ! @@ -306,6 +308,14 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--open dumpfile ! masterthread: if (id==master) then + ! write Gpot to file + open (unit=iunitst,file=trim(dumpfile)//'_info.dat',status='replace') + write(iunitst,'(4A15)') 'R', 'Gpot_cool', 'gradP_cool', 'P' + do i=1, nparttot + r = sqrt(xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) + xyzh(3,i)*xyzh(3,i) ) + write(iunitst,'(4E15.5)') r,Gpot_cool(i),gradP_cool(i),eos_vars(igasP,i) + enddo + close(iunitst) if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 index fc314237d..7db1cc646 100644 --- a/src/setup/setup_sphere.f90 +++ b/src/setup/setup_sphere.f90 @@ -72,7 +72,7 @@ module setup private !--private module variables real :: xmini(3), xmaxi(3) - real :: density_contrast,totmass_sphere,r_sphere,cs_sphere,cs_sphere_cgs + real :: density_contrast,totmass_sphere,r_sphere,T_sphere,cs_sphere real :: angvel,beta_r,Bzero_G,masstoflux,dtg,ang_Bomega,rms_mach real :: rho_pert_amp,lbox real :: BErho_cen,BErad_phys,BErad_norm,BEmass,BEfac @@ -92,18 +92,17 @@ module setup !+ !---------------------------------------------------------------- subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_out,time,fileprefix) - use physcon, only:pi,solarm,hours,years,au + use physcon, only:pi,solarm,hours,years,au,kboltz,atomic_mass_unit use dim, only:maxdusttypes,use_dustgrowth,maxdustlarge use setup_params, only:rhozero,npart_total,rmax,ihavesetupB use io, only:master,fatal,iprint use unifdis, only:set_unifdis use spherical, only:set_sphere - use rho_profile, only:rho_bonnorebert,prompt_BEparameters use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound use prompting, only:prompt - use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity + use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity,unit_ergg use eos, only:polyk2,ieos,gmw - use eos_barotropic, only:rhocrit0cgs,drhocrit0 + use eos_stamatellos, only:read_optab,getopac_opdep,optable,getintenerg_opdep,eos_file use part, only:Bxyz,Bextx,Bexty,Bextz,igas,idust,set_particle_type,hfact,dustfrac use set_dust_options, only:dustbinfrac,set_dust_default_options,set_dust_interactively,dust_method use dust, only:ilimitdustflux @@ -134,7 +133,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ integer :: iBE,ilattice real :: totmass,vol_box,psep,psep_box,pmass_dusttogas real :: vol_sphere,dens_sphere,dens_medium,cs_medium,angvel_code,przero - real :: totmass_box,t_ff,r2,area,Bzero,rmasstoflux_crit + real :: u_sphere,kappaBar,kappaPart,gmwi,gammai,cs_sphere_cgs + real :: t_ff,r2,area,Bzero,rmasstoflux_crit real :: rxy2,rxyz2,phi,dphi,central_density,edge_density,rmsmach,v2i,turbfac,rhocritTcgs,ui real, allocatable :: rtab(:),rhotab(:) logical :: iexist @@ -149,7 +149,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ filename = trim(fileprefix)//'.setup' print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)",& - ' Sphere-in-box setup: Almost Archimedes'' greatest achievement.' + ' Sphere setup' inquire(file=filename,exist=iexist) if (iexist) then @@ -227,24 +227,13 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ totmass_sphere = 1.0 call prompt('Enter total mass in sphere in units of '//mass_unit,totmass_sphere,0.) else - call prompt_BEparameters(iBEparam,BErho_cen,BErad_phys,BErad_norm,BEmass,BEfac,umass,udist,au,solarm) - lbox = 4. - call prompt('Enter the box size in units of spherical radii: ',lbox,1.) - endif - - density_contrast = 30.0 - call prompt('Enter density contrast between sphere and box ',density_contrast,1.) - - binary = .false. - call prompt('Do you intend to form a binary system (i.e. add an m=2 perturbation)?',binary) - - if (binary) then - cs_sphere_cgs = 18696.96 ! cm/s ~ 5K assuming mu = 2.31 & gamma = 5/3 - else - cs_sphere_cgs = 21888.0 ! cm/s ~ 8K assuming mu = 2.31 & gamma = 5/3 + print *, 'deleted' endif - call prompt('Enter sound speed in sphere in units of cm/s',cs_sphere_cgs,0.) + call prompt('Enter temperature in sphere',T_sphere,1.,100.) + + call prompt('Enter EOS filename',eos_file) + if (binary) then angvel = 1.006d-12 else @@ -354,47 +343,30 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ graindens(1) = graindenscgs/umass*udist**3 endif endif - ! - ! convert units of sound speed - ! - if (cs_in_code) then - cs_sphere_cgs = cs_sphere*unit_velocity - else - cs_sphere = cs_sphere_cgs/unit_velocity - endif - ! - ! Bonnor-Ebert profile (if requested) - ! - if (BEsphere) then - iBE = 8192 - allocate(rtab(iBE),rhotab(iBE)) - call rho_bonnorebert(iBEparam,BErho_cen,edge_density,BErad_phys,BErad_norm,BEmass,BEfac,cs_sphere, & - gmw,iBE,iBElast,rtab,rhotab,ierr) - central_density = BErho_cen - r_sphere = BErad_phys - totmass_sphere = BEmass - if (ierr > 0) call fatal('setup_sphereinbox','Error in calculating Bonnor-Ebert profile') - endif - do i = 1,3 - xmini(i) = -0.5*(lbox*r_sphere) - xmaxi(i) = -xmini(i) - enddo - ! - ! boundaries - ! - call set_boundary(xmini(1),xmaxi(1),xmini(2),xmaxi(2),xmini(3),xmaxi(3)) - ! + + + ! general parameters ! + + vol_sphere = 4./3.*pi*r_sphere**3 + rhozero = totmass_sphere / vol_sphere + dens_sphere = rhozero + + ! call EOS + ieos = 21 + ierr = 0 + call read_optab(eos_file,ierr) + call getintenerg_opdep(T_sphere, dens_sphere*unit_density, u_sphere) + call getopac_opdep(u_sphere,dens_sphere*unit_density,kappaBar,kappaPart,T_sphere,gmwi,gammai) + u_sphere = u_sphere/unit_ergg + gamma = gammai time = 0. if (use_dust) dust_method = 1 hfact = hfact_default hfact_out = hfact_default - if (maxvxyzu >=4 ) then - gamma = 5./3. - else - gamma = 1. - endif + print *, 'gamma =', gamma, 'u_sphere = ',u_sphere,T_sphere + rmax = r_sphere if (angvel_not_betar) then angvel_code = angvel*utime @@ -402,65 +374,14 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ angvel_code = sqrt(3.0*totmass_sphere*beta_r/r_sphere**3) angvel = angvel_code/utime endif - vol_box = dxbound*dybound*dzbound - vol_sphere = 4./3.*pi*r_sphere**3 - rhozero = totmass_sphere / vol_sphere - dens_sphere = rhozero - if (BEsphere) then - dens_medium = edge_density/density_contrast - cs_medium = cs_sphere*sqrt(edge_density/dens_medium) - else - dens_medium = dens_sphere/density_contrast - cs_medium = cs_sphere*sqrt(density_contrast) - endif - rhocrit0cgs = dens_medium*unit_density * density_contrast/7.5 ! end of transition region for ieos=8;for density_contrast=30, this yields a coefficient of 4 - rhocritTcgs = rhocrit0cgs*(1.0-drhocrit0) ! start of transition region for ieos=8 - totmass_box = (vol_box - vol_sphere)*dens_medium - totmass = totmass_box + totmass_sphere + + + totmass = totmass_sphere t_ff = sqrt(3.*pi/(32.*dens_sphere)) - if (totmass_sphere > 0.9*totmass) then - print*, 'resetting boundaries to increase the number of background particles' - dxbound = (0.1*totmass_sphere/dens_medium)**(1./3.) - do i = 1,3 - xmini(i) = -0.5*dxbound - xmaxi(i) = -xmini(i) - enddo - call set_boundary(xmini(1),xmaxi(1),xmini(2),xmaxi(2),xmini(3),xmaxi(3)) - vol_box = dxbound*dybound*dzbound - totmass_box = (vol_box - vol_sphere)*dens_medium - totmass = totmass_box + totmass_sphere - endif - if (dens_medium*unit_density > rhocritTcgs) then - print*, 'Medium density = ',dens_medium*unit_density,'g/cm^3' - print*, 'Sphere density = ',dens_sphere*unit_density,'g/cm^3' - print*, 'Density at start of EOS transition = ',rhocritTcgs,'g/cm^3' - print*, 'Density at end of EOS transition = ',rhocrit0cgs,'g/cm^3' - call fatal('setup_sphereinbox','Error setting sound-speed transition region in EOS') - endif - ! - ! magnetic field - ! - rmasstoflux_crit = 2./3.*0.53*sqrt(5./pi) ! code units *see derivation at the end of the file* - if (mhd) then - area = pi*r_sphere**2 - if (mu_not_B) then - if (masstoflux > tiny(masstoflux)) then - Bzero = totmass_sphere/(area*masstoflux*rmasstoflux_crit) - else - Bzero = 0. - endif - else - Bzero = Bzero_G/unit_Bfield - masstoflux = totmass_sphere/(area*Bzero*rmasstoflux_crit) - endif - ihavesetupB = .true. - else - Bzero = 0. - endif - Bextx = 0. - Bexty = 0. - Bextz = Bzero - przero = cs_sphere**2*dens_sphere + + przero = dens_sphere * kboltz * T_sphere/gmwi/atomic_mass_unit ! code units + cs_sphere = sqrt(gammai * przero/dens_sphere) + cs_sphere_cgs = cs_sphere * unit_velocity ! ! setup particles in the sphere; use this routine to get N_sphere as close to np as possible ! @@ -475,25 +396,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ endif print "(a)",' Initialised sphere' - if (usebox) then - npartsphere = npart - if (np_in /= npartsphere) np = npartsphere - massoftype(igas) = totmass_sphere/npartsphere ! note: before 5 Oct 2021, this was based upon total mass & total number, not sphere numbers - ! - ! setup surrounding low density medium - ! - if (BEsphere .or. trim(lattice)=='random') then - psep_box = dxbound/(vol_box*dens_medium/massoftype(igas))**(1./3.) - else - psep_box = psep*(density_contrast)**(1./3.) - endif - - call set_unifdis(trim(lattice),id,master,xmin,xmax,ymin,ymax,zmin,zmax,psep_box, & - hfact,npart,xyzh,periodic,rmin=r_sphere,nptot=npart_total,mask=i_belong,err=ierr) - print "(a,es10.3)",' Particle separation in low density medium = ',psep_box - print "(a,i10,a)",' added ',npart-npartsphere,' particles in low-density medium' - print*, "" - endif + ! ! set particle properties ! @@ -556,11 +459,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ ! (if random or shuffling, recentering may shift particles outside of the defined range) ! if (trim(lattice)/='random' .and. .not.shuffle_parts) call reset_centreofmass(npart,xyzh,vxyzu) - ! - ! temperature set to give a pressure equilibrium - ! - polyk = cs_sphere**2 - polyk2 = cs_medium**2 + ! !--Stretching the spatial distribution to perturb the density profile, if requested ! @@ -624,16 +523,11 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ if (r2 < r_sphere**2) then vxyzu(1,i) = vxyzu(1,i) - angvel_code*xyzh(2,i) vxyzu(2,i) = vxyzu(2,i) + angvel_code*xyzh(1,i) - ui = cs_sphere**2 * 0.9 + ui = u_sphere if (maxvxyzu >= 4) vxyzu(4,i) = ui else if (maxvxyzu >= 4) vxyzu(4,i) = 1.5*polyk2 endif - if (mhd) then - Bxyz(:,i) = 0. - Bxyz(1,i) = Bzero*sin(ang_Bomega*pi/180.0) - Bxyz(3,i) = Bzero*cos(ang_Bomega*pi/180.0) - endif enddo ! ! set default runtime parameters if .in file does not exist @@ -647,7 +541,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ else tmax = 1.21*t_ff ! = 10.75 for default settings (Wurster, Price & Bate 2016) endif - ieos = 8 + ieos = 21 nfulldump = 1 calc_erot = .true. dtmax_dratio = 1.258 @@ -682,22 +576,13 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ print fmt,' Mean rho medium : ',dens_medium,dens_medium*unit_density,' g/cm^3' else print fmt,' Density sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' - print fmt,' Density medium : ',dens_medium,dens_medium*unit_density,' g/cm^3' endif print fmt,' cs in sphere : ',cs_sphere,cs_sphere_cgs,' cm/s' - print fmt,' cs in medium : ',cs_medium,cs_medium*unit_velocity,' cm/s' print fmt,' Free fall time : ',t_ff,t_ff*utime/years,' yrs' print fmt,' Angular velocity : ',angvel_code,angvel,' rad/s' print fmt,' Turbulent Mach no: ',rms_mach print fmt,' Omega*t_ff : ',angvel_code*t_ff - if (mhd) then - print fmt,' B field (z) : ',Bzero,Bzero*unit_Bfield*1.d6,' micro-G' - print fmt,' Alfven speed : ',Bzero/sqrt(dens_sphere),Bzero/sqrt(dens_sphere)*udist/utime,' cm/s' - if (Bzero > 0.) then - print fmt,' plasma beta : ',przero/(0.5*Bzero*Bzero) - print fmt,' mass-to-flux : ',totmass_sphere/(area*Bzero)/rmasstoflux_crit - endif - endif + if (use_dust) then print fmt,' dust-to-gas ratio: ',dtg,dtg,' ' endif @@ -761,7 +646,7 @@ subroutine write_setupfile(filename) call write_inopt(BEfac,'BEfac','over-density factor of the BE sphere [code units]',iunit) endif call write_inopt(density_contrast,'density_contrast','density contrast in code units',iunit) - call write_inopt(cs_sphere_cgs,'cs_sphere_cgs','sound speed in sphere in cm/s',iunit) + call write_inopt(T_sphere,'T_sphere','temperature in sphere',iunit) if (angvel_not_betar) then call write_inopt(angvel,'angvel','angular velocity in rad/s',iunit) else @@ -860,9 +745,7 @@ subroutine read_setupfile(filename,ierr) if (iBEparam==4 .or. iBEparam==5) call read_inopt(BEfac,'BEfac',db,ierr) endif - call read_inopt(density_contrast,'density_contrast',db,ierr) - call read_inopt(cs_sphere,'cs_sphere',db,jerr) - call read_inopt(cs_sphere_cgs,'cs_sphere_cgs',db,kerr) + call read_inopt(T_sphere,'T_sphere',db,jerr) cs_in_code = .false. ! for backwards compatibility if (jerr /= 0 .and. kerr == 0) then cs_in_code = .false. From 5a974566651a60234303a46b553a61adbb17ea73 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 2 Jun 2023 15:16:56 +0100 Subject: [PATCH 036/182] edits to force.F90 for Stamatellos cooling --- src/main/force.F90 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 2a6717cc6..dc591181b 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1684,7 +1684,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) - if (ieos == 8) Gpot_cool(i) = Gpot_cool(i) + 0.5*pmassj*phii + if (ieos == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii !--calculate divv for use in du, h prediction, av switch etc. fsum(idrhodti) = fsum(idrhodti) + projv*grkerni @@ -1853,10 +1853,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (q2i < q2j) then winter = wkern(q2i,qi)*hi21*hi1*cnormk else - winter = wkern(q2j,qj)*hj21*hj1*cnormk endif !--following quantities are weighted by mass rather than mass/density fsum(idensgasi) = fsum(idensgasi) + pmassj*winter + winter = wkern(q2j,qj)*hj21*hj1*cnormk fsum(idvix) = fsum(idvix) + pmassj*dvx*winter fsum(idviy) = fsum(idviy) + pmassj*dvy*winter fsum(idviz) = fsum(idviz) + pmassj*dvz*winter @@ -1911,6 +1911,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifyi) = fsum(ifyi) - dy*fgravj fsum(ifzi) = fsum(ifzi) - dz*fgravj fsum(ipot) = fsum(ipot) + pmassj*phii + + !-- add contribution of 'distant neighbour' (outside r_kernel) gas particle to potential + if (iamtypej == igas .and. ieos == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii !--self gravity contribution to total energy equation if (gr .and. gravity .and. ien_type == ien_etotal) then @@ -2707,6 +2710,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv !--add self-contribution call kernel_softening(0.,0.,potensoft0,dum) epoti = 0.5*pmassi*(fsum(ipot) + pmassi*potensoft0*hi1) + if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + 0.5*pmassi*potensoft0*hi1 ! !--add contribution from distant nodes, expand these in Taylor series about node centre ! use xcen directly, -1 is placeholder @@ -2716,7 +2720,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi - if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + 0.5*(dx*fxi + dy*fyi + dz*fzi) ! add contribution from distant nodes + if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) - (dx*fxi + dy*fyi + dz*fzi) ! add contribution from distant nodes if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif From 6e4b0955bf43594c6eee6c5ae0221ccdb284ab2d Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 2 Jun 2023 16:32:43 +0100 Subject: [PATCH 037/182] Correction for icooling=8 --- src/main/force.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index dc591181b..96456e22a 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1684,7 +1684,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) - if (ieos == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii + if (icooling == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii !--calculate divv for use in du, h prediction, av switch etc. fsum(idrhodti) = fsum(idrhodti) + projv*grkerni @@ -1913,7 +1913,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ipot) = fsum(ipot) + pmassj*phii !-- add contribution of 'distant neighbour' (outside r_kernel) gas particle to potential - if (iamtypej == igas .and. ieos == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii + if (iamtypej == igas .and. icooling == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii !--self gravity contribution to total energy equation if (gr .and. gravity .and. ien_type == ien_etotal) then From ab5878500667dd9600e0ba8203e367ed20402e38 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 5 Jun 2023 09:38:08 +0100 Subject: [PATCH 038/182] comment out write Gpot_cool to file --- src/main/readwrite_dumps_fortran.F90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 718004db4..271cadcbf 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -309,13 +309,13 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ! masterthread: if (id==master) then ! write Gpot to file - open (unit=iunitst,file=trim(dumpfile)//'_info.dat',status='replace') - write(iunitst,'(4A15)') 'R', 'Gpot_cool', 'gradP_cool', 'P' - do i=1, nparttot - r = sqrt(xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) + xyzh(3,i)*xyzh(3,i) ) - write(iunitst,'(4E15.5)') r,Gpot_cool(i),gradP_cool(i),eos_vars(igasP,i) - enddo - close(iunitst) +! open (unit=iunitst,file=trim(dumpfile)//'_info.dat',status='replace') +! write(iunitst,'(4A15)') 'R', 'Gpot_cool', 'gradP_cool', 'P' +! do i=1, nparttot + ! r = sqrt(xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) + xyzh(3,i)*xyzh(3,i) ) + ! write(iunitst,'(4E15.5)') r,Gpot_cool(i),gradP_cool(i),eos_vars(igasP,i) + ! enddo +! close(iunitst) if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) From ebd56e52c2459eb908868b642f24c4f601edf28f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 7 Jun 2023 11:28:09 +0100 Subject: [PATCH 039/182] Edits to gamma calc in eos_stamatellos.f90 --- src/main/eos_stamatellos.f90 | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index a1f913cb8..ca0959b5f 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -72,7 +72,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) real kappa1,kappa2 real Tpart1,Tpart2 real gmw1,gmw2 - real cv + real cv,cv1,cv2 real ui_, rhoi_,rhomin,umin rhomin = OPTABLE(1,1,1) @@ -120,6 +120,9 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) c = OPTABLE(i-1,j,4) - m*OPTABLE(i-1,j,3) gmw1 = m*ui_ + c + +! cv=dU/dT + cv1 = (OPTABLE(i-1,j,3)-OPTABLE(i-1,j-1,3))/(OPTABLE(i-1,j,2)-OPTABLE(i-1,j-1,2)) j = 1 do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.ny)) @@ -167,8 +170,10 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) c = gmw2 - m*OPTABLE(i,1,1) gmwi = m*rhoi_ + c - - cv = ui_/Ti +! cv=dU/dT + cv2 = (OPTABLE(i,j,3)-OPTABLE(i,j-1,3))/(OPTABLE(i,j,2)-OPTABLE(i,j-1,2)) + ! cv = ui_/Ti + cv = 0.5 *(cv1+cv2) gammai = 1.0d0 + kboltz/atomic_mass_unit/gmwi/cv end subroutine getopac_opdep From 099459b4cfb4c49d2d958a0108fc766f490abcfe Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 7 Jun 2023 14:50:21 +0100 Subject: [PATCH 040/182] remove debug file write --- src/main/cooling_stamatellos.f90 | 4 +--- src/main/eos_stamatellos.f90 | 9 ++++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index d5d288d23..cc6bd0538 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -57,8 +57,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning use physcon, only:steboltz,pi,solarl,Rg use units, only:umass,udist,unit_density,unit_ergg,utime - use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool, & - iunitst + use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool use part, only:eos_vars,igasP,xyzmh_ptmass real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i @@ -125,7 +124,6 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) case (1) if ((dudti_sph + dudt_rad) == 0.d0) then tthermi = 0d0 - write(iunitst,'(A)') "ttherm=0" else tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) endif diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 25ff5295c..cf03af174 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -7,7 +7,7 @@ module eos_stamatellos real,allocatable,public :: optable(:,:,:) real,allocatable,public :: Gpot_cool(:), gradP_cool(:) !==gradP/rho character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file - integer,public :: iunitst=19 +!integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains @@ -18,16 +18,15 @@ subroutine init_S07cool() print *, "Allocating S07 arrays" allocate(gradP_cool(npart)) allocate(Gpot_cool(npart)) - open (unit=iunitst,file='EOSinfo.dat',status='replace') - - + ! open (unit=iunitst,file='EOSinfo.dat',status='replace') + end subroutine init_S07cool subroutine finish_S07cool() deallocate(optable) if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) - close(iunitst) + !close(iunitst) end subroutine finish_S07cool subroutine read_optab(eos_file,ierr) From 4db2a04d646f5d2fa5812b47603c3a057d538d64 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 7 Jun 2023 15:02:22 +0100 Subject: [PATCH 041/182] delete comment --- src/main/eos_stamatellos.f90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index ca0959b5f..eb3d4a663 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -172,7 +172,6 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) gmwi = m*rhoi_ + c ! cv=dU/dT cv2 = (OPTABLE(i,j,3)-OPTABLE(i,j-1,3))/(OPTABLE(i,j,2)-OPTABLE(i,j-1,2)) - ! cv = ui_/Ti cv = 0.5 *(cv1+cv2) gammai = 1.0d0 + kboltz/atomic_mass_unit/gmwi/cv end subroutine getopac_opdep From 00e43e6809b0784b95f7e2d63e3f401bffb1451a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 7 Jun 2023 15:10:59 +0100 Subject: [PATCH 042/182] remove debug write --- src/main/readwrite_dumps_fortran.F90 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 271cadcbf..a5ed5e84e 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -244,7 +244,6 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use krome_user, only:krome_nmols use part, only:gamma_chem,mu_chem,T_gas_cool #endif - use eos_stamatellos, only: Gpot_cool, gradP_cool, iunitst real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -308,15 +307,6 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--open dumpfile ! masterthread: if (id==master) then - ! write Gpot to file -! open (unit=iunitst,file=trim(dumpfile)//'_info.dat',status='replace') -! write(iunitst,'(4A15)') 'R', 'Gpot_cool', 'gradP_cool', 'P' -! do i=1, nparttot - ! r = sqrt(xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) + xyzh(3,i)*xyzh(3,i) ) - ! write(iunitst,'(4E15.5)') r,Gpot_cool(i),gradP_cool(i),eos_vars(igasP,i) - ! enddo -! close(iunitst) - if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) else From 6f58ede077b91ae5d66fe40dfca57312eb5a3332 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 8 Jun 2023 14:00:03 +0100 Subject: [PATCH 043/182] Changes to potential Gpot_cool --- src/main/force.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 96456e22a..506757fff 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2720,7 +2720,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi - if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) - (dx*fxi + dy*fyi + dz*fzi) ! add contribution from distant nodes + if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif From 08141b8895a8daf7ac81259559417b047ea6c524 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 8 Jun 2023 17:12:37 +0100 Subject: [PATCH 044/182] gamma checks --- src/main/cons2prim.f90 | 1 - src/main/cooling_stamatellos.f90 | 3 ++- src/main/eos.F90 | 3 +-- src/main/eos_stamatellos.f90 | 3 ++- src/main/readwrite_dumps_fortran.F90 | 8 ++++++++ 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index b5b523466..84cb27bb4 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -280,7 +280,6 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& eos_vars(igasP,i) = p_on_rhogas*rhogas eos_vars(ics,i) = spsound eos_vars(itemp,i) = temperaturei - if (ieos.eq.21) eos_vars(igamma,i) = gammai if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. (ieos.eq.21)) eos_vars(imu,i) = mui if (do_radiation) then diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 25b434fcd..86cae8a1e 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -58,7 +58,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use physcon, only:steboltz,pi,solarl,Rg use units, only:umass,udist,unit_density,unit_ergg,utime use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool - use part, only:eos_vars,igasP,xyzmh_ptmass + use part, only:eos_vars,igasP,xyzmh_ptmass,igamma real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i real,intent(out) :: dudti_cool @@ -83,6 +83,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi,gammai) + eos_vars(igamma,i) = gammai presi = eos_vars(igasP,i) ! presi = Rg*Ti*rhoi select case (od_method) diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 99f4f8bd6..99cf43666 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -431,10 +431,9 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam cgseni = eni * unit_ergg call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui,gammai) ! gammai is derived from the tables - ! print *, 'EOS gamma=', gammai ponrhoi = (gammai - 1.) * eni spsoundi = sqrt(gammai*ponrhoi) - + case default spsoundi = 0. ! avoids compiler warnings ponrhoi = 0. diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 0b67fbe84..3d378ee0c 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -174,7 +174,8 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) ! cv=dU/dT cv2 = (OPTABLE(i,j,3)-OPTABLE(i,j-1,3))/(OPTABLE(i,j,2)-OPTABLE(i,j-1,2)) cv = 0.5 *(cv1+cv2) - gammai = 1.0d0 + kboltz/atomic_mass_unit/gmwi/cv + gammai = 1.0d0 + (kboltz/atomic_mass_unit/gmwi/cv) +! print *, 'gammai in eos_Stam:', gammai end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index a5ed5e84e..34d065047 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -244,6 +244,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use krome_user, only:krome_nmols use part, only:gamma_chem,mu_chem,T_gas_cool #endif + use eos_stamatellos, only:gradP_cool,Gpot_cool real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -307,6 +308,13 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--open dumpfile ! masterthread: if (id==master) then + open(unit=10,file=trim(dumpfile)//'info.dat') + write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' + do i=1,nparttot + write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& + gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) + enddo + close(10) if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) else From 3372386154b00ff0402c7812bc0192b8326adcc7 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 8 Jun 2023 17:16:26 +0100 Subject: [PATCH 045/182] Correction to Gpot_cool sum --- src/main/force.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 96456e22a..4273f9f1b 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2710,7 +2710,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv !--add self-contribution call kernel_softening(0.,0.,potensoft0,dum) epoti = 0.5*pmassi*(fsum(ipot) + pmassi*potensoft0*hi1) - if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + 0.5*pmassi*potensoft0*hi1 + if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + pmassi*potensoft0*hi1 ! !--add contribution from distant nodes, expand these in Taylor series about node centre ! use xcen directly, -1 is placeholder @@ -2720,7 +2720,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi - if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) - (dx*fxi + dy*fyi + dz*fzi) ! add contribution from distant nodes + if (icooling == 8 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif From 8587c4d9db17050c550ea8bb2d74de5c55625ee9 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 14 Jun 2023 11:22:37 +0100 Subject: [PATCH 046/182] fix typos --- src/main/eos_stamatellos.f90 | 4 ++-- src/main/radiation_utils.f90 | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 4b84fd42d..0cf968caa 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -9,7 +9,7 @@ module eos_stamatellos real, parameter,public :: arad=7.5657d-15 character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file logical,parameter,public :: FLD = .true. - !integer,public :: iunitst=19 + integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains @@ -28,7 +28,7 @@ end subroutine init_S07cool subroutine finish_S07cool() use part, only: radprop - deallopcate(optable) + deallocate(optable) if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) if (allocated(du_FLD)) deallocate(du_FLD) diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index c644e71c5..367101e7d 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -411,12 +411,12 @@ end function get_kappa ! calculate opacities !+ !-------------------------------------------------------------------- -subroutine get_opacity(opacity_type,density,temperature,kappa,ui) +subroutine get_opacity(opacity_type,density,temperature,kappa,u) use eos_stamatellos, only:getopac_opdep use mesa_microphysics, only:get_kappa_mesa use units, only:unit_density,unit_opacity,unit_ergg real, intent(in) :: density, temperature - real, intent(in), optional :: ui + real, intent(in), optional :: u real, intent(out) :: kappa integer, intent(in) :: opacity_type real :: kapt,kapr,rho_cgs,Ti,gmwi,gammai,kapBar,kappaPart @@ -440,7 +440,7 @@ subroutine get_opacity(opacity_type,density,temperature,kappa,ui) ! ! opacity for Stamatellos/Lombardi EOS ! - call getopac_opdep(ui*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi,gammai) + call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi,gammai) kappa = kappaPart/unit_opacity case default ! From a696cd660545f4aa2fcb49bd4d9b3c59a484f090 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 14 Jun 2023 15:02:03 +0100 Subject: [PATCH 047/182] change to ieos 21 --- src/main/cons2prim.f90 | 2 +- src/main/cooling_stamatellos.f90 | 4 ++-- src/main/eos.F90 | 14 +++++++++----- src/main/eos_stamatellos.f90 | 14 +++----------- src/setup/setup_sphere.f90 | 10 ++++++---- 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index b5b523466..42d4d191d 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -280,7 +280,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& eos_vars(igasP,i) = p_on_rhogas*rhogas eos_vars(ics,i) = spsound eos_vars(itemp,i) = temperaturei - if (ieos.eq.21) eos_vars(igamma,i) = gammai + ! if (ieos.eq.21) eos_vars(igamma,i) = gammai if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. (ieos.eq.21)) eos_vars(imu,i) = mui if (do_radiation) then diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 25b434fcd..6b2205e55 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -63,7 +63,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) integer,intent(in) :: i real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 - real :: gammai,gmwi,Tmini4,Ti,dudt_rad,Teqi + real :: gmwi,Tmini4,Ti,dudt_rad,Teqi real :: tcool,ueqi,umini,tthermi,poti,presi poti = Gpot_cool(i) @@ -82,7 +82,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& - Ti,gmwi,gammai) + Ti,gmwi) presi = eos_vars(igasP,i) ! presi = Rg*Ti*rhoi select case (od_method) diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 99f4f8bd6..fb0f9ec02 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -106,7 +106,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam use io, only:fatal,error,warning use part, only:xyzmh_ptmass, nptmass use units, only:unit_density,unit_pressure,unit_ergg,unit_velocity - use physcon, only:kb_on_mh,radconst + use physcon, only:kb_on_mh,radconst,Rg use eos_mesa, only:get_eos_pressure_temp_gamma1_mesa use eos_helmholtz, only:eos_helmholtz_pres_sound use eos_shen, only:eos_shen_NL3 @@ -429,10 +429,14 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam endif cgsrhoi = rhoi * unit_density cgseni = eni * unit_ergg - call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui,gammai) - ! gammai is derived from the tables - ! print *, 'EOS gamma=', gammai - ponrhoi = (gammai - 1.) * eni + call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) + cgspresi = Rg*cgsrhoi*tempi/mui + ponrhoi = (cgspresi/unit_pressure)/rhoi + + gammai = 1.d0 + presi/(eni*rhoi) + ! if (gammai < 1.d0 .or. gammai > 2.d0) then + ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi + ! endif spsoundi = sqrt(gammai*ponrhoi) case default diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 0b67fbe84..0c6f48175 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -62,10 +62,9 @@ end subroutine read_optab ! ! Main subroutine for interpolating tables to get EOS values ! -subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) - use physcon, only: kboltz,atomic_mass_unit +subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) real, intent(in) :: ui,rhoi - real, intent(out) :: kappaBar,kappaPart,Ti,gmwi,gammai + real, intent(out) :: kappaBar,kappaPart,Ti,gmwi integer i,j real m,c @@ -73,7 +72,6 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) real kappa1,kappa2 real Tpart1,Tpart2 real gmw1,gmw2 - real cv,cv1,cv2 real ui_, rhoi_,rhomin,umin rhomin = OPTABLE(1,1,1) @@ -121,9 +119,6 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) c = OPTABLE(i-1,j,4) - m*OPTABLE(i-1,j,3) gmw1 = m*ui_ + c - -! cv=dU/dT - cv1 = (OPTABLE(i-1,j,3)-OPTABLE(i-1,j-1,3))/(OPTABLE(i-1,j,2)-OPTABLE(i-1,j-1,2)) j = 1 do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.ny)) @@ -171,10 +166,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi,gammai) c = gmw2 - m*OPTABLE(i,1,1) gmwi = m*rhoi_ + c -! cv=dU/dT - cv2 = (OPTABLE(i,j,3)-OPTABLE(i,j-1,3))/(OPTABLE(i,j,2)-OPTABLE(i,j-1,2)) - cv = 0.5 *(cv1+cv2) - gammai = 1.0d0 + kboltz/atomic_mass_unit/gmwi/cv + end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 index 7db1cc646..1c40d58d0 100644 --- a/src/setup/setup_sphere.f90 +++ b/src/setup/setup_sphere.f90 @@ -92,7 +92,7 @@ module setup !+ !---------------------------------------------------------------- subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_out,time,fileprefix) - use physcon, only:pi,solarm,hours,years,au,kboltz,atomic_mass_unit + use physcon, only:pi,solarm,hours,years,au,kboltz,kb_on_mh use dim, only:maxdusttypes,use_dustgrowth,maxdustlarge use setup_params, only:rhozero,npart_total,rmax,ihavesetupB use io, only:master,fatal,iprint @@ -358,9 +358,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ ierr = 0 call read_optab(eos_file,ierr) call getintenerg_opdep(T_sphere, dens_sphere*unit_density, u_sphere) - call getopac_opdep(u_sphere,dens_sphere*unit_density,kappaBar,kappaPart,T_sphere,gmwi,gammai) + call getopac_opdep(u_sphere,dens_sphere,kappaBar,kappaPart,T_sphere,gmwi) u_sphere = u_sphere/unit_ergg - gamma = gammai time = 0. if (use_dust) dust_method = 1 hfact = hfact_default @@ -379,9 +378,12 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ totmass = totmass_sphere t_ff = sqrt(3.*pi/(32.*dens_sphere)) - przero = dens_sphere * kboltz * T_sphere/gmwi/atomic_mass_unit ! code units + przero = dens_sphere * kb_on_mh * T_sphere/gmwi ! code units + gammai = 1.d0 + (przero/u_sphere/dens_sphere) cs_sphere = sqrt(gammai * przero/dens_sphere) cs_sphere_cgs = cs_sphere * unit_velocity + polyk = cs_sphere**2 + gamma = 5./3. ! not used but set to keep Phantom happy. ! ! setup particles in the sphere; use this routine to get N_sphere as close to np as possible ! From a6e46bb80afcac2d95644dd6d916a30361844540 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 14 Jun 2023 17:15:33 +0100 Subject: [PATCH 048/182] fix error in eos 21 --- src/main/eos.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 21908907f..c65e80d40 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -431,7 +431,8 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam cgseni = eni * unit_ergg call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) cgspresi = Rg*cgsrhoi*tempi/mui - ponrhoi = (cgspresi/unit_pressure)/rhoi + presi = cgspresi/unit_pressure + ponrhoi = presi/rhoi gammai = 1.d0 + presi/(eni*rhoi) ! if (gammai < 1.d0 .or. gammai > 2.d0) then ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi From a3c78086649d3f5fbf8e458b58ce10fedc013139 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 15 Jun 2023 14:14:43 +0100 Subject: [PATCH 049/182] comment out write debug info file --- src/main/readwrite_dumps_fortran.F90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 34d065047..e793bfc07 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -308,13 +308,13 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--open dumpfile ! masterthread: if (id==master) then - open(unit=10,file=trim(dumpfile)//'info.dat') - write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' - do i=1,nparttot - write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& - gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) - enddo - close(10) + !open(unit=10,file=trim(dumpfile)//'info.dat') +! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' + ! do i=1,nparttot + ! write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& + ! gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) + !enddo + !close(10) if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) else From 620e357675b07ceb79176c88f42050484d0c2b85 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 16 Jun 2023 11:56:26 +0100 Subject: [PATCH 050/182] changes for ieos=21 --- src/main/cooling_stamatellos.f90 | 11 +++++------ src/main/eos.F90 | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 8ef93f684..489b748c5 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -81,22 +81,21 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) endif ! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) - presi = eos_vars(igasP,i) - ! presi = Rg*Ti*rhoi - select case (od_method) + presi = eos_vars(igasP,i) + select case (od_method) case (1) 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+ method of estimating the mean column density - coldensi = 1.014d0 * presi / abs(-gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 + coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 coldensi = coldensi *umass/udist/udist ! physical units end select - tcool = (coldensi**2d0)*kappaBari +(1.d0/kappaParti) ! physical units + tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units diff --git a/src/main/eos.F90 b/src/main/eos.F90 index c65e80d40..f397a7d95 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -430,7 +430,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam cgsrhoi = rhoi * unit_density cgseni = eni * unit_ergg call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) - cgspresi = Rg*cgsrhoi*tempi/mui + cgspresi = kb_on_mh*cgsrhoi*tempi/mui presi = cgspresi/unit_pressure ponrhoi = presi/rhoi gammai = 1.d0 + presi/(eni*rhoi) From 646491e9ca8619a4f35f7a3efa69bf8ac8051c02 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 16 Jun 2023 15:01:44 +0100 Subject: [PATCH 051/182] small changes to ieos=21 and icooling=8 --- src/main/cooling_stamatellos.f90 | 24 ++++++++++++------------ src/main/eos.F90 | 6 +++--- src/main/readwrite_dumps_fortran.F90 | 14 +++++++------- src/setup/setup_sphere.f90 | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 8ef93f684..5b7d22672 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -84,7 +84,6 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) presi = eos_vars(igasP,i) - ! presi = Rg*Ti*rhoi select case (od_method) case (1) coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) ! G cancels out as G=1 in code @@ -101,26 +100,26 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! calculate Teqi - if (od_method == 1) then - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + if (od_method == 1) then + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime Teqi = Teqi/4.d0/steboltz - Teqi = Teqi + Tmini4 - if (Teqi < Tmini4) then + Teqi = Teqi + Tmini4 + if (Teqi < Tmini4) then Teqi = Tmini4**(1.0/4.0) - else + else Teqi = Teqi**(1.0/4.0) - endif - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + endif + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg - endif + endif call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg ! calculate thermalization timescale and ! internal energy update -> put in form where it'll work as dudtcool - select case (od_method) - case (1) + select case (od_method) + case (1) if ((dudti_sph + dudt_rad) == 0.d0) then tthermi = 0d0 else @@ -133,7 +132,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) endif case (2) if (abs(dudt_rad) > 0.d0) then - tthermi = (umini - ui) / dudt_rad + tthermi = (umini - ui) / (dudt_rad)! + tiny(dudt_rad)) dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph else ! ie Tmini == Ti dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS @@ -151,6 +150,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then dudti_cool = (umini - ui)/dt + ! print *, "dudti_cool negative and big" endif end subroutine cooling_S07 diff --git a/src/main/eos.F90 b/src/main/eos.F90 index c65e80d40..325eb54b2 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -430,13 +430,13 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam cgsrhoi = rhoi * unit_density cgseni = eni * unit_ergg call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) - cgspresi = Rg*cgsrhoi*tempi/mui + cgspresi = kb_on_mh*cgsrhoi*tempi/mui presi = cgspresi/unit_pressure ponrhoi = presi/rhoi gammai = 1.d0 + presi/(eni*rhoi) - ! if (gammai < 1.d0 .or. gammai > 2.d0) then + !if (gammai < 1.d0 .or. gammai > 2.d0) then ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi - ! endif + !endif spsoundi = sqrt(gammai*ponrhoi) case default diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index e793bfc07..51e73662e 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -308,13 +308,13 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--open dumpfile ! masterthread: if (id==master) then - !open(unit=10,file=trim(dumpfile)//'info.dat') -! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' - ! do i=1,nparttot - ! write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& - ! gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) - !enddo - !close(10) + open(unit=10,file=trim(dumpfile)//'info.dat') + write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' + do i=1,nparttot + write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& + gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) + enddo + close(10) if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) else diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 index 1c40d58d0..7935ce308 100644 --- a/src/setup/setup_sphere.f90 +++ b/src/setup/setup_sphere.f90 @@ -397,7 +397,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ if (trim(lattice)/='random') print "(a,es10.3)",' Particle separation in sphere = ',psep endif print "(a)",' Initialised sphere' - + npartsphere = npart_total ! ! set particle properties @@ -708,7 +708,7 @@ subroutine read_setupfile(filename,ierr) character(len=*), intent(in) :: filename integer, intent(out) :: ierr integer, parameter :: iunit = 21 - integer :: i,nerr,jerr,kerr + integer :: i,nerr,kerr,jerr type(inopts), allocatable :: db(:) !--Read values From ca1c01c4dde1a825b4d9917bc626fac234f6e545 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 16 Jun 2023 15:26:34 +0100 Subject: [PATCH 052/182] Comment out debug file write --- src/main/readwrite_dumps_fortran.F90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 51e73662e..d62ed3e7e 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -308,13 +308,13 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--open dumpfile ! masterthread: if (id==master) then - open(unit=10,file=trim(dumpfile)//'info.dat') - write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' - do i=1,nparttot - write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& - gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) - enddo - close(10) +! open(unit=10,file=trim(dumpfile)//'info.dat') + ! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' + ! do i=1,nparttot + ! write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& + ! gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) + ! enddo + ! close(10) if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) else From d4a7abea3b5a5e1e1f7d0f397992e5a61189343f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 14:22:11 +0100 Subject: [PATCH 053/182] Fix to energy updates in step when using icooling=8 --- src/main/step_leapfrog.F90 | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index d815dbadb..e57407761 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -101,7 +101,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iamboundary,get_ntypes,npartoftypetot,& dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,ics - use options, only:avdecayconst,alpha,ieos,alphamax + use options, only:avdecayconst,alpha,ieos,alphamax,icooling use deriv, only:derivs use timestep, only:dterr,bignumber,tolv use mpiutils, only:reduceall_mpi @@ -177,7 +177,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(rad,drad,pxyzu) & !$omp shared(Bevol,dBevol,dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred,ufloor) & - !$omp shared(ibin,ibin_old,twas,timei) & + !$omp shared(ibin,ibin_old,twas,timei,icooling) & !$omp firstprivate(itype) & !$omp private(i,hdti) & !$omp reduction(+:nvfloorp) @@ -200,7 +200,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + if (icooling .ne. 8) then + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + else + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + endif endif !--floor the thermal energy if requested and required @@ -262,7 +266,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none) schedule(guided,1) & !$omp shared(maxp,maxphase,maxalpha) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,divcurlv,npart,store_itype) & -!$omp shared(pxyzu,ppred) & +!$omp shared(pxyzu,ppred,icooling) & !$omp shared(Bevol,dBevol,Bpred,dtsph,massoftype,iphase) & !$omp shared(dustevol,ddustprop,dustprop,dustproppred,dustfrac,ddustevol,dustpred,use_dustfrac) & !$omp shared(alphaind,ieos,alphamax,ndustsmall,ialphaloc) & @@ -426,7 +430,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass,massoftype) & -!$omp shared(dtsph,ieos,ufloor) & +!$omp shared(dtsph,ieos,ufloor,icooling) & !$omp shared(ibin,ibin_old,ibin_sts,twas,timei,use_sts,dtsph_next,ibin_wake,sts_it_n) & !$omp shared(ibin_dts,nbinmax,ibinnow) & !$omp private(dti,hdti) & @@ -463,7 +467,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) else - vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) + if (icooling .ne. 8) then + vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) + else + vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) + endif endif if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) @@ -484,8 +492,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - else + elseif (icooling .ne. 8) then vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + else + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + endif !--floor the thermal energy if requested and required @@ -558,7 +569,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase) & !$omp shared(Bevol,dBevol,Bpred,pxyzu,ppred) & !$omp shared(dustprop,ddustprop,dustproppred,use_dustfrac,dustevol,dustpred,ddustevol) & -!$omp shared(rad,drad,radpred) & +!$omp shared(rad,drad,radpred,icooling) & !$omp firstprivate(itype) & !$omp schedule(static) until_converged: do i=1,npart @@ -594,7 +605,11 @@ 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 .ne. 8) then + vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) + else + vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) + endif endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then From 54bcbea715aec022688a04a8a478258bb66f83ef Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 15:09:42 +0100 Subject: [PATCH 054/182] [tab-bot] tabs removed --- src/main/cooling_stamatellos.f90 | 32 ++++++++++++++++---------------- src/main/eos.F90 | 6 +++--- src/main/eos_stamatellos.f90 | 12 ++++++------ src/main/force.F90 | 6 +++--- src/setup/setup_sphere.f90 | 4 ++-- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 42619d732..487e4b996 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -69,7 +69,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) poti = Gpot_cool(i) ! Tfloor is from input parameters and is background heating ! Stellar heating - if (isink_star > 0 .and. Lstar > 0) then + if (isink_star > 0 .and. Lstar > 0.d0) then ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + (zi-xyzmh_ptmass(3,isink_star))**2d0 @@ -103,15 +103,15 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! calculate Teqi if (od_method == 1) then Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - Teqi = Teqi/4.d0/steboltz + 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg + Teqi = Tmini4**(1.0/4.0) + else + Teqi = Teqi**(1.0/4.0) + endif + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg endif call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) @@ -132,12 +132,12 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif case (2) - if (abs(dudt_rad) > 0.d0) then - tthermi = (umini - ui) / (dudt_rad)! + tiny(dudt_rad)) - dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph - else ! ie Tmini == Ti - dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS - end if + if (abs(dudt_rad) > 0.d0) then + tthermi = (umini - ui) / (dudt_rad)! + tiny(dudt_rad)) + dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph + else ! ie Tmini == Ti + dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS + end if end select @@ -191,8 +191,8 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie endif ngot = ngot + 1 case('EOS_file') - read(valstring,*,iostat=ierr) eos_file - ngot = ngot + 1 + read(valstring,*,iostat=ierr) eos_file + ngot = ngot + 1 case default imatch = .false. end select diff --git a/src/main/eos.F90 b/src/main/eos.F90 index b60292845..b8ed67451 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -435,7 +435,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam ponrhoi = presi/rhoi gammai = 1.d0 + presi/(eni*rhoi) !if (gammai < 1.d0 .or. gammai > 2.d0) then - ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi + ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi !endif spsoundi = sqrt(gammai*ponrhoi) @@ -1228,7 +1228,7 @@ logical function eos_outputs_mu(ieos) case(20) eos_outputs_mu = .true. case(21) - eos_outputs_mu = .true. + eos_outputs_mu = .true. case default eos_outputs_mu = .false. end select @@ -1363,7 +1363,7 @@ subroutine read_headeropts_eos(ieos,hdr,ierr) if (use_krome) then write(iprint,*) 'KROME eos: initial gamma = 1.666667' elseif (ieos==21) then - write(iprint,*) 'Tabulated eos with derived gamma' + write(iprint,*) 'Tabulated eos with derived gamma' else write(iprint,*) 'adiabatic eos: gamma = ',gamma endif diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 0c6f48175..e09c388c0 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -41,12 +41,12 @@ subroutine read_optab(eos_file,ierr) open(10, file=filepath, form="formatted", status="old",iostat=ierr) if (ierr > 0) return do - read(10,'(A120)') junk - if (index(adjustl(junk),'::') .eq. 0) then !ignore comment lines - junk = adjustl(junk) - read(junk, *,iostat=errread) nx, ny - exit - endif + read(10,'(A120)') junk + if (index(adjustl(junk),'::') .eq. 0) then !ignore comment lines + junk = adjustl(junk) + read(junk, *,iostat=errread) nx, ny + exit + endif enddo ! allocate array for storing opacity tables allocate(optable(nx,ny,6)) diff --git a/src/main/force.F90 b/src/main/force.F90 index 41e53ff73..8fcdf6a0a 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1201,10 +1201,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravyi = 0. fgravzi = 0. if (icooling == 8) then - gradP_cool(i) = 0d0 - Gpot_cool(i) = 0d0 + gradP_cool(i) = 0d0 + Gpot_cool(i) = 0d0 endif - + loop_over_neighbours2: do n = 1,nneigh j = abs(listneigh(n)) diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 index 7935ce308..f3ce9f9ed 100644 --- a/src/setup/setup_sphere.f90 +++ b/src/setup/setup_sphere.f90 @@ -227,13 +227,13 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ totmass_sphere = 1.0 call prompt('Enter total mass in sphere in units of '//mass_unit,totmass_sphere,0.) else - print *, 'deleted' + print *, 'deleted' endif call prompt('Enter temperature in sphere',T_sphere,1.,100.) call prompt('Enter EOS filename',eos_file) - + if (binary) then angvel = 1.006d-12 else From 766f882026ba628b69c317e77a66b2f2a3707c6a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 15:09:50 +0100 Subject: [PATCH 055/182] [format-bot] obsolete .gt. .lt. .ge. .le. .eq. .ne. replaced --- src/main/cons2prim.f90 | 2 +- src/main/cooling_stamatellos.f90 | 2 +- src/main/eos_stamatellos.f90 | 20 ++++++++++---------- src/main/step_leapfrog.F90 | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 3fed4bc57..128aa6d18 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -281,7 +281,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& eos_vars(ics,i) = spsound eos_vars(itemp,i) = temperaturei - if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. (ieos.eq.21)) eos_vars(imu,i) = mui + if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. (ieos==21)) eos_vars(imu,i) = mui if (do_radiation) then if (temperaturei > tiny(0.)) then diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 487e4b996..8dcc804bb 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -196,7 +196,7 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie case default imatch = .false. end select - if (od_method .ne. 1 .and. od_method .ne. 2) then + if (od_method /= 1 .and. od_method /= 2) then call warning('cooling_stamatellos','optical depth method unknown') endif diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index e09c388c0..9562f4a7d 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -42,7 +42,7 @@ subroutine read_optab(eos_file,ierr) if (ierr > 0) return do read(10,'(A120)') junk - if (index(adjustl(junk),'::') .eq. 0) then !ignore comment lines + if (index(adjustl(junk),'::') == 0) then !ignore comment lines junk = adjustl(junk) read(junk, *,iostat=errread) nx, ny exit @@ -78,25 +78,25 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) umin = OPTABLE(1,1,3) ! interpolate through OPTABLE to find corresponding kappaBar, kappaPart and T - if (rhoi.lt. rhomin) then + if (rhoi < rhomin) then rhoi_ = rhomin else rhoi_ = rhoi endif i = 1 - do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.nx)) + do while((OPTABLE(i,1,1) <= rhoi_).and.(i < nx)) i = i + 1 enddo - if (ui.lt.umin) then + if (ui < umin) then ui_ = umin else ui_ = ui endif j = 1 - do while ((OPTABLE(i-1,j,3).le.ui_).and.(j.lt.ny)) + do while ((OPTABLE(i-1,j,3) <= ui_).and.(j < ny)) j = j + 1 enddo @@ -121,7 +121,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) gmw1 = m*ui_ + c j = 1 - do while ((OPTABLE(i,j,3).le.ui).and.(j.lt.ny)) + do while ((OPTABLE(i,j,3) <= ui).and.(j < ny)) j = j + 1 enddo @@ -180,19 +180,19 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) ! interpolate through OPTABLE to obtain equilibrium internal energy - if (rhoi.lt.1.0e-24) then + if (rhoi < 1.0e-24) then rhoi_ = 1.0e-24 else rhoi_ = rhoi endif i = 1 - do while((OPTABLE(i,1,1).le.rhoi_).and.(i.lt.nx)) + do while((OPTABLE(i,1,1) <= rhoi_).and.(i < nx)) i = i + 1 enddo j = 1 - do while ((OPTABLE(i-1,j,2).le.Teqi).and.(j.lt.ny)) + do while ((OPTABLE(i-1,j,2) <= Teqi).and.(j < ny)) j = j + 1 enddo @@ -202,7 +202,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) u1 = m*Teqi + c j = 1 - do while ((OPTABLE(i,j,2).le.Teqi).and.(j.lt.ny)) + do while ((OPTABLE(i,j,2) <= Teqi).and.(j < ny)) j = j + 1 enddo diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index e57407761..7b76d0487 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -200,7 +200,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - if (icooling .ne. 8) then + if (icooling /= 8) then vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) else vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) @@ -467,7 +467,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) else - if (icooling .ne. 8) then + if (icooling /= 8) then vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) else vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) @@ -492,7 +492,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling .ne. 8) then + elseif (icooling /= 8) then vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) else vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) @@ -605,7 +605,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) else - if (icooling .ne. 8) then + if (icooling /= 8) then vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) else vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) From 2165d0d0165e56f76a4d50fe32bd3f73cc05a384 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 15:10:33 +0100 Subject: [PATCH 056/182] [header-bot] updated file headers --- src/main/cooling.F90 | 5 +++-- src/main/cooling_stamatellos.f90 | 6 ++++-- src/main/eos.F90 | 4 ++-- src/main/eos_stamatellos.f90 | 22 ++++++++++++++++++---- src/main/extern_binary.f90 | 12 ++++++------ src/main/force.F90 | 11 ++++++----- src/main/readwrite_dumps_fortran.F90 | 4 ++-- src/setup/setup_planetdisc.f90 | 2 +- src/setup/setup_sphere.f90 | 11 +++++------ 9 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index c47f208ce..40cccc275 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -28,8 +28,9 @@ module cooling ! - icooling : *cooling function (0=off, 1=cooling library (step), 2=cooling library (force),* ! ! :Dependencies: chem, cooling_gammie, cooling_gammie_PL, cooling_ism, -! cooling_koyamainutsuka, cooling_molecular, cooling_solver, dim, eos, -! infile_utils, io, options, part, physcon, timestep, units +! cooling_koyamainutsuka, cooling_molecular, cooling_solver, +! cooling_stamatellos, dim, eos, eos_stamatellos, infile_utils, io, +! options, part, physcon, timestep, units, viscosity ! use options, only:icooling diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 8dcc804bb..439b098d3 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -12,9 +12,11 @@ module cooling_stamatellos ! ! :Owner: Alison Young ! -! :Runtime parameters: None +! :Runtime parameters: +! - EOS_file : *File containing tabulated EOS values* +! - Lstar : *Luminosity of host star for calculating Tmin (Lsun)* ! -! :Dependencies: eos_stamatellos, physcon,io,units,part +! :Dependencies: eos_stamatellos, infile_utils, io, part, physcon, units ! implicit none diff --git a/src/main/eos.F90 b/src/main/eos.F90 index b8ed67451..ed4be69c7 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -42,8 +42,8 @@ module eos ! ! :Dependencies: dim, dump_utils, eos_barotropic, eos_gasradrec, ! eos_helmholtz, eos_idealplusrad, eos_mesa, eos_piecewise, eos_shen, -! eos_stratified, infile_utils, io, mesa_microphysics, part, physcon, -! units, eos_stamatellos +! eos_stamatellos, eos_stratified, infile_utils, io, mesa_microphysics, +! part, physcon, units ! use part, only:ien_etotal,ien_entropy,ien_type use dim, only:gr diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 9562f4a7d..41c6bb8b1 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -1,8 +1,22 @@ -!-------------------------------------------------------------------------- -! Script to interpolate the opacity table eos_file -!-------------------------------------------------------------------------- - +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! module eos_stamatellos +! +! eos_stamatellos +! +! :References: None +! +! :Owner: Alison Young +! +! :Runtime parameters: None +! +! :Dependencies: datafiles, part +! + implicit none real,allocatable,public :: optable(:,:,:) real,allocatable,public :: Gpot_cool(:), gradP_cool(:) !==gradP/rho diff --git a/src/main/extern_binary.f90 b/src/main/extern_binary.f90 index fc5835313..4a708c607 100644 --- a/src/main/extern_binary.f90 +++ b/src/main/extern_binary.f90 @@ -15,12 +15,12 @@ module extern_binary ! :Owner: Daniel Price ! ! :Runtime parameters: -! - accradius1 : *accretion radius of primary* -! - accradius2 : *accretion radius of secondary (if iexternalforce=binary)* -! - binarymassr : *m1/(m1+m2) of central binary system (if iexternalforce=binary)* -! - eps_soft1 : *Plummer softening of primary* -! - eps_soft2 : *Plummer softening of secondary* -! - ramp : *ramp up mass of secondary over first 5 orbits?* +! - accradius1 : *accretion radius of primary* +! - accradius2 : *accretion radius of secondary (if iexternalforce=binary)* +! - eps_soft1 : *Plummer softening of primary* +! - eps_soft2 : *Plummer softening of secondary* +! - mass2 : *m2 of central binary system (if iexternalforce=binary)* +! - ramp : *ramp up mass of secondary over first 5 orbits?* ! ! :Dependencies: dump_utils, infile_utils, io, physcon ! diff --git a/src/main/force.F90 b/src/main/force.F90 index 8fcdf6a0a..cd4a693de 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -39,11 +39,12 @@ module forces ! ! :Runtime parameters: None ! -! :Dependencies: boundary, cooling, dim, dust, eos, eos_shen, fastmath, io, -! io_summary, kdtree, kernel, linklist, metric_tools, mpiderivs, -! mpiforce, mpimemory, mpiutils, nicil, omputils, options, part, physcon, -! ptmass, ptmass_heating, radiation_utils, timestep, timestep_ind, -! timestep_sts, timing, units, utils_gr, viscosity +! :Dependencies: boundary, cooling, dim, dust, eos, eos_shen, +! eos_stamatellos, fastmath, io, io_summary, kdtree, kernel, linklist, +! metric_tools, mpiderivs, mpiforce, mpimemory, mpiutils, nicil, +! omputils, options, part, physcon, ptmass, ptmass_heating, +! radiation_utils, timestep, timestep_ind, timestep_sts, timing, units, +! utils_gr, viscosity ! use dim, only:maxfsum,maxxpartveciforce,maxp,ndivcurlB,ndivcurlv,& maxdusttypes,maxdustsmall,do_radiation diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index d62ed3e7e..00375b31a 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -19,8 +19,8 @@ module readwrite_dumps_fortran ! :Runtime parameters: None ! ! :Dependencies: boundary, boundary_dyn, checkconserved, dim, dump_utils, -! dust, dust_formation, eos, externalforces, fileutils, io, krome_user, -! lumin_nsdisc, memory, mpi, mpiutils, options, part, +! dust, dust_formation, eos, eos_stamatellos, externalforces, fileutils, +! io, krome_user, lumin_nsdisc, memory, mpi, mpiutils, options, part, ! readwrite_dumps_common, setup_params, sphNGutils, timestep, units ! use dump_utils, only:lenid,ndatatypes,i_int,i_int1,i_int2,i_int4,i_int8,& diff --git a/src/setup/setup_planetdisc.f90 b/src/setup/setup_planetdisc.f90 index 609f73adc..cf66192bb 100644 --- a/src/setup/setup_planetdisc.f90 +++ b/src/setup/setup_planetdisc.f90 @@ -21,7 +21,7 @@ module setup ! - accradius1 : *primary accretion radius* ! - accradius2 : *secondary accretion radius* ! - alphaSS : *desired alpha_SS* -! - mplanet : *m1/(m1+m2)* +! - m2 : *m2* ! - norbits : *number of orbits* ! - np : *number of particles* ! - p_index : *surface density profile* diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 index f3ce9f9ed..6eefe6857 100644 --- a/src/setup/setup_sphere.f90 +++ b/src/setup/setup_sphere.f90 @@ -12,7 +12,7 @@ module setup ! ! :References: None ! -! :Owner: James Wurster +! :Owner: Alison Young ! ! :Runtime parameters: ! - BEfac : *over-density factor of the BE sphere [code units]* @@ -21,10 +21,10 @@ module setup ! - BErad_phys : *physical radius of the BE sphere [code units]* ! - BErho_cen : *central density of the BE sphere [code units]* ! - Bzero : *Magnetic field strength in Gauss* +! - T_sphere : *temperature in sphere* ! - ang_Bomega : *Angle (degrees) between B and rotation axis* ! - angvel : *angular velocity in rad/s* ! - beta_r : *rotational-to-gravitational energy ratio* -! - cs_sphere_cgs : *sound speed in sphere in cm/s* ! - density_contrast : *density contrast in code units* ! - dist_unit : *distance unit (e.g. au)* ! - dust_to_gas_ratio : *dust-to-gas ratio* @@ -54,10 +54,9 @@ module setup ! - use_BE_sphere : *centrally condense as a BE sphere* ! ! :Dependencies: boundary, centreofmass, datafiles, dim, dust, eos, -! eos_barotropic, infile_utils, io, kernel, mpidomain, options, part, -! physcon, prompting, ptmass, rho_profile, set_dust, set_dust_options, -! setup_params, spherical, timestep, unifdis, units, -! utils_shuffleparticles, velfield +! eos_stamatellos, infile_utils, io, kernel, mpidomain, options, part, +! physcon, prompting, ptmass, set_dust, set_dust_options, setup_params, +! spherical, timestep, unifdis, units, utils_shuffleparticles, velfield ! use part, only:mhd,graindens,grainsize,ndusttypes,ndustsmall use dim, only:use_dust,maxvxyzu,periodic,maxdustsmall From cc7027ca7356bdea98990e2b2f5cb646e8c9827e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 15:10:41 +0100 Subject: [PATCH 057/182] [space-bot] whitespace at end of lines removed --- src/main/cooling.F90 | 8 ++++---- src/main/cooling_stamatellos.f90 | 30 +++++++++++++++--------------- src/main/eos.F90 | 4 ++-- src/main/eos_stamatellos.f90 | 24 ++++++++++++------------ src/main/force.F90 | 14 +++++++------- src/main/part.F90 | 4 ++-- src/main/step_leapfrog.F90 | 4 ++-- src/setup/setup_disc.f90 | 8 ++++---- src/setup/setup_sphere.f90 | 12 ++++++------ 9 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 40cccc275..5e4bf835c 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -13,7 +13,7 @@ module cooling ! 2 = cooling library [explicit] ! 3 = Gammie cooling [explicit] ! 5 = Koyama & Inutuska (2002) [explicit] -! 6 = Koyama & Inutuska (2002) [implicit] +! 6 = Koyama & Inutuska (2002) [implicit] ! 7 = Gammie cooling power law [explicit] ! 8 = Stamatellos et al. (2007) [implicit] ! @@ -36,7 +36,7 @@ module cooling use options, only:icooling use timestep, only:C_cool use cooling_solver, only:T0_value ! expose to other routines - + implicit none character(len=*), parameter :: label = 'cooling' @@ -73,7 +73,7 @@ subroutine init_cooling(id,master,iprint,ierr) use eos_stamatellos, only:read_optab,eos_file use cooling_stamatellos, only: init_star,od_method use viscosity, only:irealvisc - + integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr logical :: ex @@ -147,7 +147,7 @@ subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,k use cooling_koyamainutsuka, only:cooling_KoyamaInutsuka_explicit,& cooling_KoyamaInutsuka_implicit use cooling_stamatellos, only:cooling_S07 - + 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 :: dudti_sph ! in code units diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 439b098d3..8dae922c1 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -18,21 +18,21 @@ module cooling_stamatellos ! ! :Dependencies: eos_stamatellos, infile_utils, io, part, physcon, units ! - + implicit none real, public :: Lstar ! in units of L_sun integer :: isink_star ! index of sink to use as illuminating star integer :: od_method = 1 ! default = Stamatellos+ 2007 method public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star - + contains subroutine init_star() use part, only:nptmass,xyzmh_ptmass integer :: i,imin real :: rsink2,rsink2min - + rsink2min = 0d0 if (nptmass == 0 .or. Lstar == 0.0) then isink_star = 0 ! no stellar heating @@ -51,7 +51,7 @@ subroutine init_star() endif if (isink_star > 0) print *, "Using sink no. ", isink_star, "as illuminating star." end subroutine init_star - + ! ! Do cooling calculation ! @@ -67,8 +67,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudt_rad,Teqi real :: tcool,ueqi,umini,tthermi,poti,presi - - poti = Gpot_cool(i) + + poti = Gpot_cool(i) ! Tfloor is from input parameters and is background heating ! Stellar heating if (isink_star > 0 .and. Lstar > 0.d0) then @@ -97,11 +97,11 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 coldensi = coldensi *umass/udist/udist ! physical units end select - + tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units - - + + ! calculate Teqi if (od_method == 1) then Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime @@ -115,10 +115,10 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg endif - + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg - + ! calculate thermalization timescale and ! internal energy update -> put in form where it'll work as dudtcool select case (od_method) @@ -141,21 +141,21 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS end if end select - - + + if (isnan(dudti_cool)) then print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti print *, "rhoi=",rhoi, "Ti=", Ti print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad + print *, "dudt_rad=", dudt_rad call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then dudti_cool = (umini - ui)/dt ! print *, "dudti_cool negative and big" endif - + end subroutine cooling_S07 diff --git a/src/main/eos.F90 b/src/main/eos.F90 index ed4be69c7..90d46b6a2 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -424,7 +424,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam ! !--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=8 ! - if (eni < 0.) then + if (eni < 0.) then call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) endif cgsrhoi = rhoi * unit_density @@ -543,7 +543,7 @@ subroutine init_eos(eos_type,ierr) call read_optab(eos_file,ierr) if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) call init_S07cool - + end select done_init_eos = .true. diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 41c6bb8b1..f328d7f24 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -28,7 +28,7 @@ module eos_stamatellos subroutine init_S07cool() use part, only:npart - + print *, "Allocating S07 arrays" allocate(gradP_cool(npart)) allocate(Gpot_cool(npart)) @@ -41,7 +41,7 @@ subroutine finish_S07cool() if (allocated(Gpot_cool)) deallocate(Gpot_cool) !close(iunitst) end subroutine finish_S07cool - + subroutine read_optab(eos_file,ierr) use datafiles, only:find_phantom_datafile character(len=*),intent(in) :: eos_file @@ -51,7 +51,7 @@ subroutine read_optab(eos_file,ierr) ! read in data file for interpolation filepath=find_phantom_datafile(eos_file,'cooling') - print *,"FILEPATH:",filepath + print *,"FILEPATH:",filepath open(10, file=filepath, form="formatted", status="old",iostat=ierr) if (ierr > 0) return do @@ -70,7 +70,7 @@ subroutine read_optab(eos_file,ierr) OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) enddo enddo - print *, 'nx,ny=', nx, ny + print *, 'nx,ny=', nx, ny end subroutine read_optab ! @@ -96,7 +96,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) rhoi_ = rhomin else rhoi_ = rhoi - endif + endif i = 1 do while((OPTABLE(i,1,1) <= rhoi_).and.(i < nx)) @@ -104,7 +104,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) enddo if (ui < umin) then - ui_ = umin + ui_ = umin else ui_ = ui endif @@ -133,7 +133,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) c = OPTABLE(i-1,j,4) - m*OPTABLE(i-1,j,3) gmw1 = m*ui_ + c - + j = 1 do while ((OPTABLE(i,j,3) <= ui).and.(j < ny)) j = j + 1 @@ -151,8 +151,8 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) m = (OPTABLE(i,j-1,2) - OPTABLE(i,j,2))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) c = OPTABLE(i,j,2) - m*OPTABLE(i,j,3) - - Tpart2 = m*ui_ + c + + Tpart2 = m*ui_ + c m = (OPTABLE(i,j-1,4) - OPTABLE(i,j,4))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) c = OPTABLE(i,j,4) - m*OPTABLE(i,j,3) @@ -173,7 +173,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) m = (Tpart2 - Tpart1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) c = Tpart2 - m*OPTABLE(i,1,1) - + Ti = m*rhoi_ + c m = (gmw2 - gmw1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) @@ -187,7 +187,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) real, intent(out) :: ueqi real, intent(in) :: Teqi,rhoi - real u1, u2 + real u1, u2 real m, c integer i, j real rhoi_ @@ -195,7 +195,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) ! interpolate through OPTABLE to obtain equilibrium internal energy if (rhoi < 1.0e-24) then - rhoi_ = 1.0e-24 + rhoi_ = 1.0e-24 else rhoi_ = rhoi endif diff --git a/src/main/force.F90 b/src/main/force.F90 index cd4a693de..ebdc47ca3 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1201,11 +1201,11 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravxi = 0. fgravyi = 0. fgravzi = 0. - if (icooling == 8) then + if (icooling == 8) then gradP_cool(i) = 0d0 Gpot_cool(i) = 0d0 endif - + loop_over_neighbours2: do n = 1,nneigh j = abs(listneigh(n)) @@ -1723,7 +1723,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifyi) = fsum(ifyi) - runiy*(gradp + fgrav) - projsy fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) - + if (icooling == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii !--calculate divv for use in du, h prediction, av switch etc. @@ -1980,9 +1980,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifyi) = fsum(ifyi) - dy*fgravj fsum(ifzi) = fsum(ifzi) - dz*fgravj fsum(ipot) = fsum(ipot) + pmassj*phii - + !-- add contribution of 'distant neighbour' (outside r_kernel) gas particle to potential - if (iamtypej == igas .and. icooling == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii + if (iamtypej == igas .and. icooling == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii !--self gravity contribution to total energy equation if (gr .and. gravity .and. ien_type == ien_etotal) then @@ -1995,7 +1995,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g enddo loop_over_neighbours2 - + if (gr .and. gravity .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fgravxi + vyi*fgravyi + vzi*fgravzi endif @@ -2471,7 +2471,7 @@ subroutine compute_cell(cell,listneigh,nneigh,Bevol,xyzh,vxyzu,fxyzu, & realviscosity = (irealvisc > 0) useresistiveheat = (iresistive_heating > 0) - + over_parts: do ip = 1,cell%npcell if (maxphase==maxp) then diff --git a/src/main/part.F90 b/src/main/part.F90 index 959589f45..4ede9eb48 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -57,7 +57,7 @@ module part character(len=*), parameter :: vxyzu_label(4) = (/'vx','vy','vz','u '/) character(len=*), parameter :: Bxyz_label(3) = (/'Bx','By','Bz'/) character(len=*), parameter :: Bevol_label(4) = (/'Bx/rho','By/rho','Bz/rho','psi '/) - + ! !--tracking particle IDs ! @@ -587,7 +587,7 @@ subroutine deallocate_part if (allocated(ibelong)) deallocate(ibelong) if (allocated(istsactive)) deallocate(istsactive) if (allocated(ibin_sts)) deallocate(ibin_sts) - + end subroutine deallocate_part !---------------------------------------------------------------- diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 7b76d0487..8679970a7 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -206,7 +206,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) endif endif - + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then @@ -608,7 +608,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (icooling /= 8) then vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) else - vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) + vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) endif endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 7edb8793a..122c47b4a 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -1022,7 +1022,7 @@ subroutine calculate_disc_mass() rgrid_min = R_in(i) rgrid_max = R_out(i) if (isetgas(i)==1) then - rgrid_min = min(rgrid_min,R_inann(i)) + rgrid_min = min(rgrid_min,R_inann(i)) rgrid_max = max(rgrid_max,R_outann(i)) endif if (use_dust) then @@ -1082,7 +1082,7 @@ subroutine calculate_disc_mass() end select totmass_gas = totmass_gas + disc_m(i) - enc_mass(:,i) = enc_m + star_m(i) + enc_mass(:,i) = enc_m + star_m(i) !--dust discs print*,'dust' @@ -1096,7 +1096,7 @@ subroutine calculate_disc_mass() R_indust_swap(i,j),R_outdust_swap(i,j),R_ref(i),R_c_dust(i,j),H_R_dust(i,j)) fac = disc_mdust(i,j) / disc_mtmp sig_normdust(i,j) = sig_normdust(i,j) * fac - enc_mass(:,i) = enc_mass(:,i) + enc_m(:)*fac + enc_mass(:,i) = enc_mass(:,i) + enc_m(:)*fac enddo endif endif @@ -1995,7 +1995,7 @@ subroutine setup_interactive(id) end select case (5:) - + call print_chess_logo()!id) ibinary = 0 diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 index 6eefe6857..6b9ae2acc 100644 --- a/src/setup/setup_sphere.f90 +++ b/src/setup/setup_sphere.f90 @@ -230,9 +230,9 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ endif call prompt('Enter temperature in sphere',T_sphere,1.,100.) - + call prompt('Enter EOS filename',eos_file) - + if (binary) then angvel = 1.006d-12 else @@ -344,14 +344,14 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ endif - + ! general parameters ! - + vol_sphere = 4./3.*pi*r_sphere**3 rhozero = totmass_sphere / vol_sphere dens_sphere = rhozero - + ! call EOS ieos = 21 ierr = 0 @@ -397,7 +397,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ endif print "(a)",' Initialised sphere' npartsphere = npart_total - + ! ! set particle properties ! From 16ed142df8c834eedec0c8d75bf612ba37b00e31 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 15:10:41 +0100 Subject: [PATCH 058/182] [author-bot] updated AUTHORS file --- AUTHORS | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/AUTHORS b/AUTHORS index b37f4f44b..7a8461e8c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -20,55 +20,56 @@ Rebecca Nealon Ward Homan Christophe Pinte Elisabeth Borchert -Megha Sharma +Alison Young Fangyi (Fitz) Hu +Megha Sharma Terrence Tricco Mats Esseldeurs +Stephane Michoulier Simone Ceppi MatsEsseldeurs Caitlyn Hardiman Enrico Ragusa Sergei Biriukov -Giovanni Dipierro Cristiano Longarini +Giovanni Dipierro Roberto Iaconi fhu Hauke Worpel Simone Ceppi -Alison Young -Stephane Michoulier Amena Faruqi Stephen Neilson <36410751+s-neilson@users.noreply.github.com> Martina Toscani Benedetta Veronesi Sahl Rowther -Thomas Reichardt Simon Glover +Thomas Reichardt Jean-François Gonzalez Christopher Russell Alessia Franchini +Alex Pettitt Jolien Malfait Phantom benchmark bot -Alex Pettitt -Nicole Rodrigues Kieran Hirsh +Nicole Rodrigues Amena Faruqi David Trevascus -Megha Sharma Chris Nixon +Megha Sharma Nicolas Cuello -Orsola De Marco -Megha Sharma -Maxime Lombart -Joe Fisher -Giulia Ballabio Benoit Commercon +Giulia Ballabio +Joe Fisher +Maxime Lombart +Megha Sharma +Orsola De Marco Zachary Pellow s-neilson <36410751+s-neilson@users.noreply.github.com> -mats esseldeurs +Alison Young Cox, Samuel Jorge Cuadra -Alison Young +Nicolás Cuello Steven Rieder Stéven Toupin Terrence Tricco +mats esseldeurs From bbf6cb52ad15a7c0b2f73ea1f3a36eba0e491cff Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 15:10:49 +0100 Subject: [PATCH 059/182] [format-bot] end if -> endif; end do -> enddo; if( -> if ( --- src/main/cooling_stamatellos.f90 | 4 ++-- src/setup/set_hierarchical.f90 | 2 +- src/tests/test_dust.F90 | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 8dae922c1..ef6039d3a 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -139,7 +139,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph else ! ie Tmini == Ti dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS - end if + endif end select @@ -151,7 +151,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) print *, "dudt_rad=", dudt_rad call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop - else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + elseif (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then dudti_cool = (umini - ui)/dt ! print *, "dudti_cool negative and big" endif diff --git a/src/setup/set_hierarchical.f90 b/src/setup/set_hierarchical.f90 index bf5455be0..1fa2f973c 100644 --- a/src/setup/set_hierarchical.f90 +++ b/src/setup/set_hierarchical.f90 @@ -733,7 +733,7 @@ subroutine generate_hierarchy_string(nsinks) hierarchy = trim(hierarchy(:pos-1))//','//trim(label)//'1,'//trim(label)//'2' !print*,label - end do + enddo end subroutine generate_hierarchy_string diff --git a/src/tests/test_dust.F90 b/src/tests/test_dust.F90 index 4974ee11d..85eb088c7 100644 --- a/src/tests/test_dust.F90 +++ b/src/tests/test_dust.F90 @@ -595,7 +595,7 @@ subroutine test_drag(ntests,npass) fext = 0. fxyzu = 0. call get_derivs_global(dt=1.) - !if(drag_implicit) call get_derivs_global(dt=1.) + !if (drag_implicit) call get_derivs_global(dt=1.) ! ! check that momentum and energy are conserved From af0aa757d831d8ce695776b1976ba596bc681003 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 5 Jul 2023 15:10:58 +0100 Subject: [PATCH 060/182] [indent-bot] standardised indentation --- src/main/cooling_stamatellos.f90 | 230 +++++++++++++-------------- src/main/dust.F90 | 4 +- src/main/eos.F90 | 12 +- src/main/eos_stamatellos.f90 | 72 ++++----- src/main/force.F90 | 14 +- src/main/part.F90 | 6 +- src/main/readwrite_dumps_fortran.F90 | 10 +- src/setup/set_hierarchical.f90 | 90 +++++------ src/setup/setup_disc.f90 | 2 +- src/setup/setup_sphere.f90 | 4 +- src/utils/utils_mpc.f90 | 4 +- 11 files changed, 224 insertions(+), 224 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index ef6039d3a..282c50beb 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -26,140 +26,140 @@ module cooling_stamatellos public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star - contains +contains subroutine init_star() - use part, only:nptmass,xyzmh_ptmass - integer :: i,imin - real :: rsink2,rsink2min - - rsink2min = 0d0 - if (nptmass == 0 .or. Lstar == 0.0) then - isink_star = 0 ! no stellar heating - print *, "No stellar heating." - elseif (nptmass == 1) then - isink_star = 1 - else - do i=1,nptmass - rsink2 = xyzmh_ptmass(1,i)**2 + xyzmh_ptmass(2,i)**2 + xyzmh_ptmass(3,i)**2 - if (i==1 .or. (rsink2 < rsink2min) ) then - rsink2min = rsink2 - imin = i - endif - enddo - isink_star = imin - endif - if (isink_star > 0) print *, "Using sink no. ", isink_star, "as illuminating star." + use part, only:nptmass,xyzmh_ptmass + integer :: i,imin + real :: rsink2,rsink2min + + rsink2min = 0d0 + if (nptmass == 0 .or. Lstar == 0.0) then + isink_star = 0 ! no stellar heating + print *, "No stellar heating." + elseif (nptmass == 1) then + isink_star = 1 + else + do i=1,nptmass + rsink2 = xyzmh_ptmass(1,i)**2 + xyzmh_ptmass(2,i)**2 + xyzmh_ptmass(3,i)**2 + if (i==1 .or. (rsink2 < rsink2min) ) then + rsink2min = rsink2 + imin = i + endif + enddo + isink_star = imin + endif + if (isink_star > 0) print *, "Using sink no. ", isink_star, "as illuminating star." end subroutine init_star ! ! Do cooling calculation ! - subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) - use io, only:warning - use physcon, only:steboltz,pi,solarl,Rg - use units, only:umass,udist,unit_density,unit_ergg,utime - use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool - use part, only:eos_vars,igasP,xyzmh_ptmass,igamma - real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt - integer,intent(in) :: i - real,intent(out) :: dudti_cool - real :: coldensi,kappaBari,kappaParti,ri2 - real :: gmwi,Tmini4,Ti,dudt_rad,Teqi - real :: tcool,ueqi,umini,tthermi,poti,presi - - poti = Gpot_cool(i) +subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) + use io, only:warning + use physcon, only:steboltz,pi,solarl,Rg + use units, only:umass,udist,unit_density,unit_ergg,utime + use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool + use part, only:eos_vars,igasP,xyzmh_ptmass,igamma + real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt + integer,intent(in) :: i + real,intent(out) :: dudti_cool + real :: coldensi,kappaBari,kappaParti,ri2 + real :: gmwi,Tmini4,Ti,dudt_rad,Teqi + real :: tcool,ueqi,umini,tthermi,poti,presi + + poti = Gpot_cool(i) ! Tfloor is from input parameters and is background heating ! Stellar heating - if (isink_star > 0 .and. Lstar > 0.d0) then - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + if (isink_star > 0 .and. Lstar > 0.d0) then + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + (zi-xyzmh_ptmass(3,isink_star))**2d0 - ri2 = ri2 *udist*udist + ri2 = ri2 *udist*udist ! Tfloor + stellar heating - Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2)) - else - Tmini4 = Tfloor**4d0 - endif + Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2)) + else + Tmini4 = Tfloor**4d0 + endif ! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) - presi = eos_vars(igasP,i) - - select case (od_method) - case (1) - 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) + presi = eos_vars(igasP,i) + + select case (od_method) + case (1) + 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+ method of estimating the mean column density - coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 - coldensi = coldensi *umass/udist/udist ! physical units - end select + coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 + coldensi = coldensi *umass/udist/udist ! physical units + end select - tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units - dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units + tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units + dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units ! calculate Teqi - if (od_method == 1) then - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg - endif + if (od_method == 1) then + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + 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 + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg + endif - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg ! calculate thermalization timescale and ! internal energy update -> put in form where it'll work as dudtcool - select case (od_method) - case (1) - if ((dudti_sph + dudt_rad) == 0.d0) then - tthermi = 0d0 - else - tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) - endif - if (tthermi == 0d0) then - dudti_cool = 0.d0 ! condition if denominator above is zero - else - dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units - endif - case (2) - if (abs(dudt_rad) > 0.d0) then - tthermi = (umini - ui) / (dudt_rad)! + tiny(dudt_rad)) - dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph - else ! ie Tmini == Ti - dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS - endif - end select - - - if (isnan(dudti_cool)) then - print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "rhoi=",rhoi, "Ti=", Ti - print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph - print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad - call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) - stop - elseif (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt - ! print *, "dudti_cool negative and big" - endif - - end subroutine cooling_S07 - - - subroutine write_options_cooling_stamatellos(iunit) + select case (od_method) + case (1) + if ((dudti_sph + dudt_rad) == 0.d0) then + tthermi = 0d0 + else + tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) + endif + if (tthermi == 0d0) then + dudti_cool = 0.d0 ! condition if denominator above is zero + else + dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + endif + case (2) + if (abs(dudt_rad) > 0.d0) then + tthermi = (umini - ui) / (dudt_rad)! + tiny(dudt_rad)) + dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph + else ! ie Tmini == Ti + dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS + endif + end select + + + if (isnan(dudti_cool)) then + print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti + print *, "rhoi=",rhoi, "Ti=", Ti + print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph + print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini + print *, "dudt_rad=", dudt_rad + call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) + stop + elseif (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + dudti_cool = (umini - ui)/dt + ! print *, "dudti_cool negative and big" + endif + +end subroutine cooling_S07 + + +subroutine write_options_cooling_stamatellos(iunit) use infile_utils, only:write_inopt use eos_stamatellos, only: eos_file integer, intent(in) :: iunit @@ -171,9 +171,9 @@ subroutine write_options_cooling_stamatellos(iunit) end subroutine write_options_cooling_stamatellos - subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) +subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) use io, only:warning,fatal -use eos_stamatellos, only: eos_file + use eos_stamatellos, only: eos_file character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallstam integer, intent(out) :: ierr @@ -193,8 +193,8 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie endif ngot = ngot + 1 case('EOS_file') - read(valstring,*,iostat=ierr) eos_file - ngot = ngot + 1 + read(valstring,*,iostat=ierr) eos_file + ngot = ngot + 1 case default imatch = .false. end select @@ -206,4 +206,4 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie end subroutine read_options_cooling_stamatellos - end module cooling_stamatellos +end module cooling_stamatellos diff --git a/src/main/dust.F90 b/src/main/dust.F90 index b8f97474d..b79e140f3 100644 --- a/src/main/dust.F90 +++ b/src/main/dust.F90 @@ -377,8 +377,8 @@ subroutine read_options_dust(name,valstring,imatch,igotall,ierr) !--no longer a compulsory parameter case('irecon') read(valstring,*,iostat=ierr) irecon - !case('drag_implicit') - ! read(valstring,*,iostat=ierr) drag_implicit + !case('drag_implicit') + ! read(valstring,*,iostat=ierr) drag_implicit case default imatch = .false. end select diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 90d46b6a2..e74bf5e26 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -435,7 +435,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam ponrhoi = presi/rhoi gammai = 1.d0 + presi/(eni*rhoi) !if (gammai < 1.d0 .or. gammai > 2.d0) then - ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi + ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi !endif spsoundi = sqrt(gammai*ponrhoi) @@ -557,8 +557,8 @@ end subroutine init_eos !+ !----------------------------------------------------------------------- subroutine finish_eos(eos_type,ierr) - use eos_mesa, only: finish_eos_mesa - use eos_stamatellos, only: finish_S07cool + use eos_mesa, only: finish_eos_mesa + use eos_stamatellos, only: finish_S07cool integer, intent(in) :: eos_type integer, intent(out) :: ierr @@ -1228,7 +1228,7 @@ logical function eos_outputs_mu(ieos) case(20) eos_outputs_mu = .true. case(21) - eos_outputs_mu = .true. + eos_outputs_mu = .true. case default eos_outputs_mu = .false. end select @@ -1307,7 +1307,7 @@ subroutine eosinfo(eos_type,iprint) write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in endif case(21) - write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file, 'and calculated gamma.' + write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file, 'and calculated gamma.' end select write(iprint,*) @@ -1363,7 +1363,7 @@ subroutine read_headeropts_eos(ieos,hdr,ierr) if (use_krome) then write(iprint,*) 'KROME eos: initial gamma = 1.666667' elseif (ieos==21) then - write(iprint,*) 'Tabulated eos with derived gamma' + write(iprint,*) 'Tabulated eos with derived gamma' else write(iprint,*) 'adiabatic eos: gamma = ',gamma endif diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index f328d7f24..dcf4ca520 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -26,20 +26,20 @@ module eos_stamatellos public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains - subroutine init_S07cool() - use part, only:npart - - print *, "Allocating S07 arrays" - allocate(gradP_cool(npart)) - allocate(Gpot_cool(npart)) - ! open (unit=iunitst,file='EOSinfo.dat',status='replace') - end subroutine init_S07cool - - subroutine finish_S07cool() - deallocate(optable) - if (allocated(gradP_cool)) deallocate(gradP_cool) - if (allocated(Gpot_cool)) deallocate(Gpot_cool) - !close(iunitst) +subroutine init_S07cool() + use part, only:npart + + print *, "Allocating S07 arrays" + allocate(gradP_cool(npart)) + allocate(Gpot_cool(npart)) + ! open (unit=iunitst,file='EOSinfo.dat',status='replace') +end subroutine init_S07cool + +subroutine finish_S07cool() + deallocate(optable) + if (allocated(gradP_cool)) deallocate(gradP_cool) + if (allocated(Gpot_cool)) deallocate(Gpot_cool) + !close(iunitst) end subroutine finish_S07cool subroutine read_optab(eos_file,ierr) @@ -55,20 +55,20 @@ subroutine read_optab(eos_file,ierr) open(10, file=filepath, form="formatted", status="old",iostat=ierr) if (ierr > 0) return do - read(10,'(A120)') junk - if (index(adjustl(junk),'::') == 0) then !ignore comment lines - junk = adjustl(junk) - read(junk, *,iostat=errread) nx, ny - exit - endif -enddo + read(10,'(A120)') junk + if (index(adjustl(junk),'::') == 0) then !ignore comment lines + junk = adjustl(junk) + read(junk, *,iostat=errread) nx, ny + exit + endif + enddo ! allocate array for storing opacity tables allocate(optable(nx,ny,6)) do i = 1,nx - do j = 1,ny - read(10,*) OPTABLE(i,j,1),OPTABLE(i,j,2),OPTABLE(i,j,3),& + do j = 1,ny + read(10,*) OPTABLE(i,j,1),OPTABLE(i,j,2),OPTABLE(i,j,3),& OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) - enddo + enddo enddo print *, 'nx,ny=', nx, ny end subroutine read_optab @@ -93,25 +93,25 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) ! interpolate through OPTABLE to find corresponding kappaBar, kappaPart and T if (rhoi < rhomin) then - rhoi_ = rhomin + rhoi_ = rhomin else - rhoi_ = rhoi + rhoi_ = rhoi endif i = 1 do while((OPTABLE(i,1,1) <= rhoi_).and.(i < nx)) - i = i + 1 + i = i + 1 enddo if (ui < umin) then - ui_ = umin + ui_ = umin else - ui_ = ui + ui_ = ui endif j = 1 do while ((OPTABLE(i-1,j,3) <= ui_).and.(j < ny)) - j = j + 1 + j = j + 1 enddo m = (OPTABLE(i-1,j-1,5) - OPTABLE(i-1,j,5))/(OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3)) @@ -136,7 +136,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) j = 1 do while ((OPTABLE(i,j,3) <= ui).and.(j < ny)) - j = j + 1 + j = j + 1 enddo m = (OPTABLE(i,j-1,5) - OPTABLE(i,j,5))/(OPTABLE(i,j-1,3) - OPTABLE(i,j,3)) @@ -195,19 +195,19 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) ! interpolate through OPTABLE to obtain equilibrium internal energy if (rhoi < 1.0e-24) then - rhoi_ = 1.0e-24 + rhoi_ = 1.0e-24 else - rhoi_ = rhoi + rhoi_ = rhoi endif i = 1 do while((OPTABLE(i,1,1) <= rhoi_).and.(i < nx)) - i = i + 1 + i = i + 1 enddo j = 1 do while ((OPTABLE(i-1,j,2) <= Teqi).and.(j < ny)) - j = j + 1 + j = j + 1 enddo m = (OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3))/(OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2)) @@ -217,7 +217,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) j = 1 do while ((OPTABLE(i,j,2) <= Teqi).and.(j < ny)) - j = j + 1 + j = j + 1 enddo m = (OPTABLE(i,j-1,3) - OPTABLE(i,j,3))/(OPTABLE(i,j-1,2) - OPTABLE(i,j,2)) diff --git a/src/main/force.F90 b/src/main/force.F90 index ebdc47ca3..a9cdcd3f4 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -367,9 +367,9 @@ subroutine force(icall,npart,xyzh,vxyzu,fxyzu,divcurlv,divcurlB,Bevol,dBevol,& if (use_dust .and. drag_implicit) then !$omp parallel do default(none) shared(fext,npart,fxyz_drag,fxyz_dragold) private(i) do i=1,npart - fxyz_dragold(1,i) = fxyz_drag(1,i) - fxyz_dragold(2,i) = fxyz_drag(2,i) - fxyz_dragold(3,i) = fxyz_drag(3,i) + fxyz_dragold(1,i) = fxyz_drag(1,i) + fxyz_dragold(2,i) = fxyz_drag(2,i) + fxyz_dragold(3,i) = fxyz_drag(3,i) enddo !$omp end parallel do endif @@ -1202,8 +1202,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravyi = 0. fgravzi = 0. if (icooling == 8) then - gradP_cool(i) = 0d0 - Gpot_cool(i) = 0d0 + gradP_cool(i) = 0d0 + Gpot_cool(i) = 0d0 endif loop_over_neighbours2: do n = 1,nneigh @@ -1333,7 +1333,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g #ifdef DUST if (drag_implicit) then dti = min(dti,get_dt(dt,ibin_old(j))) - endif + endif #endif #endif endif @@ -1912,7 +1912,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif !--following quantities are weighted by mass rather than mass/density fsum(idensgasi) = fsum(idensgasi) + pmassj*winter - winter = wkern(q2j,qj)*hj21*hj1*cnormk + winter = wkern(q2j,qj)*hj21*hj1*cnormk fsum(idvix) = fsum(idvix) + pmassj*dvx*winter fsum(idviy) = fsum(idviy) + pmassj*dvy*winter fsum(idviz) = fsum(idviz) + pmassj*dvz*winter diff --git a/src/main/part.F90 b/src/main/part.F90 index 4ede9eb48..1a396517d 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -347,7 +347,7 @@ module part +1 & ! iphase #endif #ifdef DUST - +3 & ! fxyz_drag + +3 & ! fxyz_drag +3 & ! fxyz_dragold +maxdusttypes & ! dustfrac +maxdustsmall & ! dustevol @@ -1510,8 +1510,8 @@ subroutine fill_sendbuf(i,xtemp) call fill_buffer(xtemp, dustproppred(:,i),nbuf) call fill_buffer(xtemp, dustgasprop(:,i),nbuf) endif - call fill_buffer(xtemp,fxyz_drag(:,i),nbuf) - call fill_buffer(xtemp,fxyz_dragold(:,i),nbuf) + call fill_buffer(xtemp,fxyz_drag(:,i),nbuf) + call fill_buffer(xtemp,fxyz_dragold(:,i),nbuf) endif if (maxp_h2==maxp .or. maxp_krome==maxp) then call fill_buffer(xtemp, abundance(:,i),nbuf) diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 00375b31a..2e53ae392 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -309,12 +309,12 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ! masterthread: if (id==master) then ! open(unit=10,file=trim(dumpfile)//'info.dat') - ! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' - ! do i=1,nparttot - ! write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& + ! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' + ! do i=1,nparttot + ! write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& ! gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) - ! enddo - ! close(10) + ! enddo + ! close(10) if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) else diff --git a/src/setup/set_hierarchical.f90 b/src/setup/set_hierarchical.f90 index 1fa2f973c..90abcf607 100644 --- a/src/setup/set_hierarchical.f90 +++ b/src/setup/set_hierarchical.f90 @@ -718,22 +718,22 @@ subroutine set_multiple(m1,m2,semimajoraxis,eccentricity, & end subroutine set_multiple subroutine generate_hierarchy_string(nsinks) - integer, intent(in) :: nsinks + integer, intent(in) :: nsinks - integer :: i, pos - character(len=10) :: label + integer :: i, pos + character(len=10) :: label - hierarchy = '11,12' + hierarchy = '11,12' - do i=1,nsinks-2 - pos = scan(hierarchy, ',', .true.) + do i=1,nsinks-2 + pos = scan(hierarchy, ',', .true.) - label = trim(hierarchy(pos+1:)) + label = trim(hierarchy(pos+1:)) - hierarchy = trim(hierarchy(:pos-1))//','//trim(label)//'1,'//trim(label)//'2' + hierarchy = trim(hierarchy(:pos-1))//','//trim(label)//'1,'//trim(label)//'2' - !print*,label - enddo + !print*,label + enddo end subroutine generate_hierarchy_string @@ -743,44 +743,44 @@ subroutine print_chess_logo()!id) !integer, intent(in) :: id ! if (id==master) then - print*," " - print*," _:_ " - print*," '-.-' " - print*," () __.'.__ " - print*," .-:--:-. |_______| " - print*," () \____/ \=====/ " - print*," /\ {====} )___( " - print*," (\=, //\\ )__( /_____\ " - print*," __ |'-'-'| // .\ ( ) /____\ | | " - print*," / \ |_____| (( \_ \ )__( | | | | " - print*," \__/ |===| )) `\_) /____\ | | | | " - print*," /____\ | | (/ \ | | | | | | " - print*," | | | | | _.-'| | | | | | | " - print*," |__| )___( )___( /____\ /____\ /_____\ " - print*," (====) (=====) (=====) (======) (======) (=======) " - print*," }===={ }====={ }====={ }======{ }======{ }======={ " - print*," (______)(_______)(_______)(________)(________)(_________) " - print*," " - print*," _ _ _ _ _ _ " - print*," /\ \ / /\ / /\ /\ \ / /\ / /\ " - print*," / \ \ / / / / / // \ \ / / \ / / \ " - print*," / /\ \ \ / /_/ / / // /\ \ \ / / /\ \__ / / /\ \__ " - print*," / / /\ \ \ / /\ \__/ / // / /\ \_\ / / /\ \___\/ / /\ \___\ " - print*," / / / \ \_\ / /\ \___\/ // /_/_ \/_/ \ \ \ \/___/\ \ \ \/___/ " - print*," / / / \/_/ / / /\/___/ // /____/\ \ \ \ \ \ \ " - print*," / / / / / / / / // /\____\/ _ \ \ \ _ \ \ \ " - print*," / / /________ / / / / / // / /______ /_/\__/ / / /_/\__/ / / " - print*,"/ / /_________\/ / / / / // / /_______\\ \/___/ / \ \/___/ / " - print*,"\/____________/\/_/ \/_/ \/__________/ \_____\/ \_____\/ " - print*," " - - print "(/,65('-'),1(/,a),/,65('-'),/)",& + print*," " + print*," _:_ " + print*," '-.-' " + print*," () __.'.__ " + print*," .-:--:-. |_______| " + print*," () \____/ \=====/ " + print*," /\ {====} )___( " + print*," (\=, //\\ )__( /_____\ " + print*," __ |'-'-'| // .\ ( ) /____\ | | " + print*," / \ |_____| (( \_ \ )__( | | | | " + print*," \__/ |===| )) `\_) /____\ | | | | " + print*," /____\ | | (/ \ | | | | | | " + print*," | | | | | _.-'| | | | | | | " + print*," |__| )___( )___( /____\ /____\ /_____\ " + print*," (====) (=====) (=====) (======) (======) (=======) " + print*," }===={ }====={ }====={ }======{ }======{ }======={ " + print*," (______)(_______)(_______)(________)(________)(_________) " + print*," " + print*," _ _ _ _ _ _ " + print*," /\ \ / /\ / /\ /\ \ / /\ / /\ " + print*," / \ \ / / / / / // \ \ / / \ / / \ " + print*," / /\ \ \ / /_/ / / // /\ \ \ / / /\ \__ / / /\ \__ " + print*," / / /\ \ \ / /\ \__/ / // / /\ \_\ / / /\ \___\/ / /\ \___\ " + print*," / / / \ \_\ / /\ \___\/ // /_/_ \/_/ \ \ \ \/___/\ \ \ \/___/ " + print*," / / / \/_/ / / /\/___/ // /____/\ \ \ \ \ \ \ " + print*," / / / / / / / / // /\____\/ _ \ \ \ _ \ \ \ " + print*," / / /________ / / / / / // / /______ /_/\__/ / / /_/\__/ / / " + print*,"/ / /_________\/ / / / / // / /_______\\ \/___/ / \ \/___/ / " + print*,"\/____________/\/_/ \/_/ \/__________/ \_____\/ \_____\/ " + print*," " + + print "(/,65('-'),1(/,a),/,65('-'),/)",& ' Welcome to CHESS (Complete Hierarchical Endless System Setup)' - ! print "(/,65('-'),1(/,a),/,1(a),/,65('-'),/)",& - ! ' Welcome to CHESS (Complete Hierarchical Endless System Setup)', & - ! ' simulate the universe as a hierarchical system' + ! print "(/,65('-'),1(/,a),/,1(a),/,65('-'),/)",& + ! ' Welcome to CHESS (Complete Hierarchical Endless System Setup)', & + ! ' simulate the universe as a hierarchical system' ! endif end subroutine print_chess_logo diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 122c47b4a..c1c9f2a68 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -339,7 +339,7 @@ end subroutine setpart ! !-------------------------------------------------------------------------- subroutine set_default_options()!id) - use sethierarchical, only:set_hierarchical_default_options + use sethierarchical, only:set_hierarchical_default_options ! integer, intent(in) :: id integer :: i diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 index 6b9ae2acc..c297a13b5 100644 --- a/src/setup/setup_sphere.f90 +++ b/src/setup/setup_sphere.f90 @@ -226,7 +226,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ totmass_sphere = 1.0 call prompt('Enter total mass in sphere in units of '//mass_unit,totmass_sphere,0.) else - print *, 'deleted' + print *, 'deleted' endif call prompt('Enter temperature in sphere',T_sphere,1.,100.) @@ -348,7 +348,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ ! general parameters ! - vol_sphere = 4./3.*pi*r_sphere**3 + vol_sphere = 4./3.*pi*r_sphere**3 rhozero = totmass_sphere / vol_sphere dens_sphere = rhozero diff --git a/src/utils/utils_mpc.f90 b/src/utils/utils_mpc.f90 index 269a5c296..ed982fe77 100644 --- a/src/utils/utils_mpc.f90 +++ b/src/utils/utils_mpc.f90 @@ -62,7 +62,7 @@ module mpc !character(len=4) :: flags !character(len=27) :: designation !integer(kind=8) :: last_obs - end type + end type mpc_entry type mpc_comet character(len=4) :: comet_num ! periodic coment number @@ -87,7 +87,7 @@ module mpc integer :: nperturbing ! number of perturbing planets character(len=30) :: name - end type + end type mpc_comet private From 6014ac9691046e9b958777b9dd1f153d2bcb6d3f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 6 Jul 2023 11:01:51 +0100 Subject: [PATCH 061/182] fix errors --- src/main/cons2prim.f90 | 2 +- src/main/cooling_stamatellos.f90 | 15 --------------- src/main/radiation_implicit.f90 | 8 ++++---- src/main/radiation_utils.f90 | 2 +- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index e14abab3e..6a8f87caf 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -294,7 +294,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& ! Get the opacity from the density and temperature if required ! if (iopacity_type == 3) then - call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i),ui=vxyzu(4,i)) + call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i),u=vxyzu(4,i)) elseif (iopacity_type > 0) then call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i)) endif diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index db8df84d5..ac17e8c95 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -164,21 +164,6 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then dudti_cool = (umini - ui)/dt endif - - end subroutine cooling_S07 - - if (isnan(dudti_cool)) then - print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "rhoi=",rhoi, "Ti=", Ti - print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph - print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad - call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) - stop - elseif (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt - ! print *, "dudti_cool negative and big" - endif end subroutine cooling_S07 diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index f3423b6a9..0b3b43f56 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -1593,7 +1593,7 @@ subroutine get_diffusion_term_only(npart,xyzh,vxyzu,radprop_FLD,du_FLD) hi1 = 1./hi rhoi = rho_all(i) if (utherm(i) > 1e-4) print *, i, "utherm dodgy" - call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi,gammai) + call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi) if (kappaParti <= 0.) then print *, "fail", rhoi*unit_density,kappaParti,Ti, utherm(i) call fatal('get_diffusion_term_only - i','Negative or zero opacity') @@ -1622,7 +1622,7 @@ subroutine get_diffusion_term_only(npart,xyzh,vxyzu,radprop_FLD,du_FLD) dx = xyzh(1,i) - xyzh(1,j) dy = xyzh(2,i) - xyzh(2,j) dz = xyzh(3,i) - xyzh(3,j) - call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj,gammaj) + call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj) if (kappaPartj <= 0.) then print *, "fail", rhoj*unit_density,kappaPartj,Tj, utherm(j)*unit_energ call fatal('get_diffusion_term_only - j','Negative or zero opacity') @@ -1714,7 +1714,7 @@ subroutine get_lambda_hybrid(ivar,ijvar,ncompact,npart,icompactmax,& dradzi = 0. rhoi = rho_all(i) - call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi,gammai) + call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi) do k = 1,ivar(1,n) !loop over n neighbours icompact = ivar(2,n) + k @@ -1749,7 +1749,7 @@ subroutine get_lambda_hybrid(ivar,ijvar,ncompact,npart,icompactmax,& runiy = dy/rij runiz = dz/rij - call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj,gammaj) + call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj) uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj*udist**3) ! print *, 'got opdep j' diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 367101e7d..94cf3cb5a 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -440,7 +440,7 @@ subroutine get_opacity(opacity_type,density,temperature,kappa,u) ! ! opacity for Stamatellos/Lombardi EOS ! - call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi,gammai) + call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi) kappa = kappaPart/unit_opacity case default ! From 5f69f22382ad7576f96ab2dca65fcd424cd1a975 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 7 Jul 2023 17:35:41 +0100 Subject: [PATCH 062/182] Start of fixes for FLD for hybrid cooling --- src/main/cooling_stamatellos.f90 | 43 +++--- src/main/deriv.F90 | 10 +- src/main/eos_stamatellos.f90 | 28 ++-- src/main/force.F90 | 15 +- src/main/radiation_implicit.f90 | 254 +++++++------------------------ 5 files changed, 111 insertions(+), 239 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index ac17e8c95..b88c60faa 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -60,7 +60,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use physcon, only:steboltz,pi,solarl,Rg use units, only:umass,udist,unit_density,unit_ergg,utime use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool,& - iunitst,du_FLD,FLD + iunitst,duFLD,doFLD use part, only:eos_vars,igasP,xyzmh_ptmass,igamma real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i @@ -70,7 +70,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real :: tcool,ueqi,umini,tthermi,poti,presi,du_FLDi poti = Gpot_cool(i) - du_FLDi = du_FLD(i) +! du_FLDi = duFLD(i) + du_FLDi = 0d0 ! Tfloor is from input parameters and is background heating ! Stellar heating @@ -106,25 +107,25 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! calculate Teqi - if (od_method == 1) then - if (FLD) then - ! include term from FLD - Teqi = du_FLDi*dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - du_tot = dudti_sph + dudt_rad + du_FLDi - else - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - du_tot = dudti_sph + dudt_rad - endif - 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg - endif + if (od_method == 1) then + if (doFLD) then + ! include term from FLD + Teqi = (du_FLDi+dudti_sph)*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + du_FLDi + else + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + endif + 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 + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg + endif call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 9cfe331a4..2b4f6ab10 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -69,9 +69,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use derivutils, only:do_timing use cons2prim, only:cons2primall,cons2prim_everything,prim2consall use metric_tools, only:init_metric - use radiation_implicit, only:do_radiation_implicit,get_diffusion_term_only,ierr_failed_to_converge + use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge,calc_lambda_hybrid use options, only:implicit_radiation,implicit_radiation_store_drad,icooling - use eos_stamatellos, only:FLD,du_FLD,radprop_FLD + use eos_stamatellos, only:doFLD integer, intent(in) :: icall integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -175,9 +175,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& endif ! compute diffusion term for hybrid RT & polytropic cooling method - if (icooling == 8 .and. dt > 0. .and. FLD) then - !print *, "calling diff term from deriv" - call get_diffusion_term_only(npart,xyzh,vxyzu,radprop_FLD,du_FLD) + if (icooling == 8 .and. dt > 0. .and. doFLD) then + !print *, "calling lambda_hybrud from deriv" + call calc_lambda_hybrid(xyzh,vxyzu(4,:),dens) endif ! diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 9655f4d03..ad00bfd42 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -19,32 +19,33 @@ module eos_stamatellos implicit none real,allocatable,public :: optable(:,:,:) - real,allocatable,public :: Gpot_cool(:), du_FLD(:),gradP_cool(:),radprop_FLD(:,:) !gradP_cool=gradP/rho + real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_fld(:),radprop_FLD(:,:) !gradP_cool=gradP/rho real, parameter,public :: arad=7.5657d-15 character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file - logical,parameter,public :: FLD = .true. + logical,parameter,public :: doFLD = .true. integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in - public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep + public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep!,calc_FLD contains subroutine init_S07cool() - use part, only:npart,maxradprop + use part, only:npart,maxradprop print *, "Allocating S07 arrays" allocate(gradP_cool(npart)) allocate(Gpot_cool(npart)) - allocate(du_FLD(npart)) - allocate(radprop_FLD(maxradprop,npart)) + allocate(duFLD(npart)) + allocate(lambda_fld(npart)) +! allocate(radprop_FLD(maxradprop,npart)) open (unit=iunitst,file='EOSinfo.dat',status='replace') end subroutine init_S07cool subroutine finish_S07cool() - use part, only: radprop deallocate(optable) if (allocated(gradP_cool)) deallocate(gradP_cool) if (allocated(Gpot_cool)) deallocate(Gpot_cool) - if (allocated(du_FLD)) deallocate(du_FLD) - if (allocated(radprop_FLD)) deallocate(radprop_FLD) + if (allocated(duFLD)) deallocate(duFLD) + if (allocated(lambda_fld)) deallocate(lambda_fld) +! if (allocated(radprop_FLD)) deallocate(radprop_FLD) close(iunitst) end subroutine finish_S07cool @@ -237,6 +238,15 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) ueqi = m*rhoi_ + c end subroutine getintenerg_opdep +!subroutine calc_FLD(xyzhi,duFLDi,pmassj,tempi,tempj,rhoi,rhoj,j,grkerni) + !real,intent(inout) :: duFLDi +! integer,intent(in) :: j +! real,intent(in) :: xyzh(4),pmassj,tempi,tempj,rhoi,rhoj,grkerni +! duFLDi = pmassj*arad*tempj**4d0*wkernj/rhoj + + !duFLDi = duFLDi +!end subroutine calc_FLD + end module eos_stamatellos diff --git a/src/main/force.F90 b/src/main/force.F90 index a9cdcd3f4..d1f0a95a9 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -896,14 +896,14 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g #ifdef FINVSQRT use fastmath, only:finvsqrt #endif - use kernel, only:grkern,cnormk,radkern2 + use kernel, only:grkern,cnormk,radkern2,wkern use part, only:igas,idust,iohm,ihall,iambi,maxphase,iactive,& iamtype,iamdust,get_partinfo,mhd,maxvxyzu,maxdvdx,igasP,ics,iradP,itemp use dim, only:maxalpha,maxp,mhd_nonideal,gravity,gr use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt use eos, only:ieos,eos_is_non_ideal,gamma,utherm - use eos_stamatellos, only:gradP_cool,Gpot_cool + use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,arad #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -1032,7 +1032,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi + real :: radPj,fgravxi,fgravyi,fgravzi,wkernj,wkerni ! unpack xi = xpartveci(ixi) @@ -1204,6 +1204,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (icooling == 8) then gradP_cool(i) = 0d0 Gpot_cool(i) = 0d0 + duFLD(i) = 0d0 endif loop_over_neighbours2: do n = 1,nneigh @@ -1724,8 +1725,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) - if (icooling == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii - !--calculate divv for use in du, h prediction, av switch etc. fsum(idrhodti) = fsum(idrhodti) + projv*grkerni @@ -1734,6 +1733,12 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idudtdissi) = fsum(idudtdissi) + dudtdissi + dudtresist !--energy dissipation due to conductivity fsum(idendtdissi) = fsum(idendtdissi) + dendissterm + if (icooling == 8) then + Gpot_cool(i) = Gpot_cool(i) + pmassj*phii +! if (doFLD) then + ! call calc_FLD(duFLD(i),i,j,q2j,qj,hi121,hi1,pmassj,eos_vars(itemp,j),eos_vars(itemp,j),rhoj) + ! endif + endif endif !--add contribution to particle i's force diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index 0b3b43f56..f87c13157 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -46,7 +46,7 @@ module radiation_implicit character(len=*), parameter :: label = 'radiation_implicit' private - public :: do_radiation_implicit,get_diffusion_term_only,ierr_failed_to_converge + public :: do_radiation_implicit,ierr_failed_to_converge,calc_lambda_hybrid contains @@ -1511,36 +1511,32 @@ subroutine solve_quartic(u1term,u0term,uold,soln,moresweep,ierr) call quarticsolve(a,uold,soln,moresweep,ierr) end subroutine solve_quartic - + !--------------------------------------------------------- !+ -! Calculate the diffusion term for implementing hybrid -! radiative transfer method of Forgan et al. (2009). -! Used in cooling_stamatellos.f90 +! Calculate the radiation energy density and flux from +! temperature for hybrid cooling !+ !--------------------------------------------------------- -subroutine get_diffusion_term_only(npart,xyzh,vxyzu,radprop_FLD,du_FLD) - use io, only:fatal,warning - use eos_stamatellos, only:getopac_opdep - use kernel, only:radkern,grkern,cnormk - use part, only:hfact,ilambda,gradh,rhoh - use physcon, only:steboltz,pi - use units, only:unit_density,unit_energ,unit_opacity,udist,utime,unit_ergg - use timestep, only:dtmax - real, intent(in) :: xyzh(:,:),vxyzu(:,:) - real, intent(inout) :: radprop_FLD(:,:) - real, intent(out) :: du_FLD(:) - integer,allocatable :: ivar(:,:),ijvar(:) - real,allocatable :: utherm(:),rho_all(:) - integer :: npart,nneigh_average,icompactmax,ncompact,ncompactlocal,i,j,k - integer :: icompact,ierr,n - real :: dudiffi,err,steboltz_code,dx,dy,dz,runix,runiy,runiz,rij,rij2,rij1 - real :: diffusion_numerator,diffusion_denominator,dWi,hi,hi1,hi21,q,q2 - real :: kappaBari,kappaParti,Ti,gmwi,gammai,kappaBarj,kappaPartj,Tj,gmwj - real :: rdotdW,rhoi,rhoj,gammaj,ki,kj,pmassj,tdiff - - steboltz_code = steboltz/unit_energ*udist*udist*utime - !print *, 'set steboltz_code' + subroutine calc_lambda_hybrid(xyzh,utherm,rho) + use io, only:fatal + use eos_stamatellos, only:getopac_opdep,arad,lambda_fld + use kernel, only:get_kernel,cnormk,radkern + use units, only:unit_density,unit_ergg,unit_opacity,udist + use part, only:massoftype,igas,gradh,hfact + use physcon, only:pi + + real, intent(in) :: xyzh(:,:),utherm(:),rho(:) + integer,allocatable :: ivar(:,:),ijvar(:) + integer :: ncompact,npart,icompactmax,ierr,ncompactlocal + integer :: i,j,k,n,icompact,nneigh_average + real :: rhoi,rhoj + real :: uradi,dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj,gammaj,wkerni,grkerni + real :: kappaBari,kappaParti,gmwi,dx,dy,dz,rij2,rij,rij1,Wi,dWi + real :: dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4 + real :: pmassj,hi,hi21,hi1,q,q2 + logical :: added_self + npart = size(xyzh(1,:)) nneigh_average = int(4./3.*pi*(radkern*hfact)**3) + 1 icompactmax = int(1.2*nneigh_average*npart) @@ -1548,180 +1544,38 @@ subroutine get_diffusion_term_only(npart,xyzh,vxyzu,radprop_FLD,du_FLD) if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for ivar') allocate(ijvar(icompactmax),stat=ierr) if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for ijvar') - allocate(utherm(npart),stat=ierr) - if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for utherm') - allocate(rho_all(npart),stat=ierr) - if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for rho_all') - !dtimax = dt/imaxstep ?what's this? call get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) ! check for errors if (ncompact <= 0 .or. ncompactlocal <= 0) then call fatal('radiation_implicit','empty neighbour list - need to call set_linklist first?') endif - - utherm(:) = vxyzu(4,:) - du_FLD(:) = 0. - -!$omp parallel do default(none)& -!$omp shared(npart,rho_all,vxyzu,ivar,massoftype,utherm)& -!$omp private(n,i) - do i = 1, npart - rho_all(i) = rhoh(vxyzu(4,i),massoftype(igas)) - if (utherm(i) > 1e-4) print *, "i=", i , utherm(i) - enddo -!$omp end parallel do - - if (any(utherm > 1e-4,1)) print *, "utherm dodgy before got lambda" - radprop_FLD(:,:) = 0. - call get_lambda_hybrid(ivar,ijvar,ncompact,npart,icompactmax,utherm,radprop_FLD,xyzh,rho_all) - - if (any(utherm> 1e-4)) print *, "utherm dodgy after got lambda" - - pmassj = massoftype(igas) - !$omp parallel do default(none)& - !$omp shared(ivar,ijvar,radprop_FLD,rho_all,unit_energ,unit_density,steboltz_code)& - !$omp shared(xyzh,du_FLD,gradh,unit_ergg,utherm,unit_opacity,dtmax)& - !$omp private(i,j,n,ki,kj,rhoi,rhoj,diffusion_numerator,diffusion_denominator)& - !$omp private(icompact,kappaBari,kappaParti,Ti,gmwi,gammai)& - !$omp private(dudiffi,pmassj,rdotdW,rij,rij2,rij1,hi,hi1,hi21,q,q2,dx,dy,dz)& - !$omp private(runix,runiy,runiz,dWi,kappaBarj,kappaPartj,Tj,gmwj,gammaj,tdiff) - do n = 1,ncompact - i = ivar(3,n) - hi = xyzh(4,i) - hi21 = 1./(hi*hi) - hi1 = 1./hi - rhoi = rho_all(i) - if (utherm(i) > 1e-4) print *, i, "utherm dodgy" - call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi) - if (kappaParti <= 0.) then - print *, "fail", rhoi*unit_density,kappaParti,Ti, utherm(i) - call fatal('get_diffusion_term_only - i','Negative or zero opacity') - endif - ki = 16d0*steboltz_code*radprop_FLD(ilambda,i)*Ti**3.d0!thermal conductivity - ki = ki/rhoi/kappaParti/unit_opacity - - ! - !--NOTE: Needs to do this loop even for boundaryparticles because active - ! boundary particles will need to contribute to the varinew() - ! quantities (i.e. diffusion terms) of particle j due to the way that - ! particle j only finds neighbours inside h_j or non-active particles - ! inside h_i. The varinew() quantities of a boundaryparticle are - ! not used, but its contributions to j are. - - diffusion_numerator = 0. - diffusion_denominator = 0. - dudiffi = 0. - ! - !--All the neighbours loop - ! - do k = 1,ivar(1,n) - icompact = ivar(2,n) + k - j = ijvar(icompact) - rhoj = rho_all(j) - dx = xyzh(1,i) - xyzh(1,j) - dy = xyzh(2,i) - xyzh(2,j) - dz = xyzh(3,i) - xyzh(3,j) - call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj) - if (kappaPartj <= 0.) then - print *, "fail", rhoj*unit_density,kappaPartj,Tj, utherm(j)*unit_energ - call fatal('get_diffusion_term_only - j','Negative or zero opacity') - endif - - kj = 16d0*steboltz_code*radprop_FLD(ilambda,j)*Tj**3.d0!thermal conductivity - kj = kj/rhoj/kappaPartj/unit_opacity - rij2 = dx*dx + dy*dy + dz*dz + tiny(0.) - rij = sqrt(rij2) - rij1 = 1./rij - - q = rij/hi - q2 = rij2*hi21 - ! unit vector components - runix = dx*rij1 - runiy = dy*rij1 - runiz = dz*rij1 - - dWi = grkern(q2,q)*cnormk*hi21*hi21*gradh(1,i) - ! r.grad(W) along the separation vector - rdotdW = cnormk*dWi*(runix*dx + runiy*dy + runiz*dz) !Why the cnormk? - diffusion_numerator = 4d0*pmassj*ki*kj*(Ti-Tj)*rdotdW - diffusion_denominator = rhoi*rhoj*(ki+kj)*rij2 - dudiffi = dudiffi + diffusion_numerator/diffusion_denominator - ! Timestep switch: define diffusion timescale between this particle pair: if this is too small, diffusion - ! is so efficient that it is essentially cooling, so diff term is set to zero. - if (dudiffi.ne.0.0d0) then - tdiff = ABS((utherm(i) + utherm(j))/(2.0d0*dudiffi)) - if (tdiff.lt.dtmax) then - dudiffi = 0.0d0 - endif - endif - - enddo - du_FLD(i) = dudiffi - enddo - !$omp end parallel do - - !check energy conserved - what's the tolerance? tiny(err) is machine precision... - err = sum(du_FLD)/minval(du_FLD,MASK= abs(du_FLD) > 0) - err = abs(err) - if (err > 1e-7) then - print *, 'err sum=', sum(du_FLD), "max:", maxval(du_FLD,MASK= abs(du_FLD) > 0),"min:", minval(du_FLD,MASK= abs(du_FLD) > 0) - call fatal('get_diffusion_term_only','energy not conserved',var='err',val=err) - endif - !print *, "about to deallocate" - deallocate(ivar,ijvar,utherm,rho_all) - - end subroutine get_diffusion_term_only - -!--------------------------------------------------------- -!+ -! Calculate the radiation energy density and flux from -! temperature for hybrid cooling -!+ -!--------------------------------------------------------- - subroutine get_lambda_hybrid(ivar,ijvar,ncompact,npart,icompactmax,& - utherm,radprop_FLD,xyzh,rho_all) - use eos_stamatellos, only:getopac_opdep,arad - use kernel, only:get_kernel,cnormk - use units, only:unit_density,unit_ergg,unit_opacity,udist - use part, only:massoftype,igas,gradh - - integer, intent(in) :: ivar(:,:),ijvar(:),ncompact,npart,icompactmax - real, intent(in) :: xyzh(:,:),utherm(:),rho_all(:) - real, intent(inout) :: radprop_FLD(:,:) - integer :: i,j,k,n,icompact - real :: rhoi,rhoj - real :: uradi,dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj,gammaj,wkerni,grkerni - real :: kappaBari,kappaParti,gmwi,gammai,dx,dy,dz,rij2,rij,rij1,Wi,dWi - real :: dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4 - real :: pmassj,hi,hi21,hi1,q,q2 pmassj = massoftype(igas) !$omp parallel do default(none)& - !$omp shared(ivar,ijvar,ncompact,radprop_FLD,unit_opacity,gradh,xyzh,unit_density,unit_ergg)& - !$omp shared(rho_all,utherm,pmassj,udist)& + !$omp shared(ivar,ijvar,ncompact,unit_opacity,gradh,xyzh,unit_density,unit_ergg)& + !$omp shared(rho,utherm,pmassj,udist,lambda_fld)& !$omp private(i,j,k,n,rhoi,rhoj,icompact,uradi,dradi,Ti,Tj,wkerni,grkerni,dT4)& !$omp private(kappaBarj,kappaPartj,gmwj,gammaj,dx,dy,dz,rij,rij2,rij1,Wi,dWi)& !$omp private(dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,hi,hi21,hi1,q,q2)& - !$omp private(kappaBari,kappaParti,gmwi,gammai) - do n = 1,ncompact ! over compact particle list + !$omp private(kappaBari,kappaParti,gmwi,added_self) + loop_over_compact_list: do n = 1,ncompact i = ivar(3,n) ! print *, n,ncompact,utherm(i) - uradi = 0. - dradi = 0. - dradxi = 0. - dradyi = 0. - dradzi = 0. - rhoi = rho_all(i) + uradi = 0. + dradi = 0. + rhoi = rho(i) + added_self = .false. - call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi) + call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi) - do k = 1,ivar(1,n) !loop over n neighbours + loop_over_neighbours: do k = 1,ivar(1,n) icompact = ivar(2,n) + k ! print *, 'icompact',icompact j = ijvar(icompact) + if (i == j) added_self = .true. ! print *,'j',j - rhoj = rho_all(j) + rhoj = rho(j) ! print *, 'rhoj',rhoj ! print *, 'xyzh(1,i)', xyzh(1,i) ! print *, ' xyzh(1,j)', xyzh(1,j) @@ -1750,30 +1604,32 @@ subroutine get_lambda_hybrid(ivar,ijvar,ncompact,npart,icompactmax,& runiz = dz/rij call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj) - uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj*udist**3) + uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj)!*udist**3) ! why udist here? kern has h^-3 ! print *, 'got opdep j' dT4 = Ti**4d0 - Tj**4d0 - dradxi = dradxi + pmassj*arad*dT4*dWi*runix/rhoj - dradyi = dradyi + pmassj*arad*dT4*dWi*runiy/rhoj - dradzi = dradzi + pmassj*arad*dT4*dWi*runiz/rhoj + dradxi = dradxi + pmassj*arad*dT4*dWi*runix/rhoj + dradyi = dradyi + pmassj*arad*dT4*dWi*runiy/rhoj + dradzi = dradzi + pmassj*arad*dT4*dWi*runiz/rhoj + enddo loop_over_neighbours - enddo ! loop over n neighbours ! print *, 'done neighbour loop for ', i,n + if (.not. added_self) then +! print *, "Has not added self in lambda hybrid" + uradi = uradi + pmassj*arad*Ti**4d0/rhoi ! add self contribution + endif - uradi = uradi + arad*Ti**4d0 ! add self contribution - dradi = sqrt(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! magnitude - if ( (uradi == 0d0) .or. (dradi ==0d0) ) then - R_rad = 0d0 - else - R_rad = dradi / (uradi*rhoi*kappaParti/unit_opacity) !code units - endif - - radprop_FLD(ilambda,i) = (2d0 + R_rad) / (6d0 + 3d0*R_rad + R_rad*R_rad) - !print *, 'radprop_FLD', radprop_FLD(ilambda,i) - radprop_FLD(ikappa,i) = kappaParti / unit_opacity - enddo ! over particles + dradi = sqrt(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! magnitude + if ( (uradi == 0d0) .or. (dradi == 0d0) ) then + R_rad = 0d0 + else + R_rad = dradi / (uradi*rhoi*kappaParti/unit_opacity) !code units + endif + + lambda_fld(i) = (2d0 + R_rad) / (6d0 + 3d0*R_rad + R_rad*R_rad) + enddo loop_over_compact_list !$omp end parallel do - end subroutine get_lambda_hybrid + end subroutine calc_lambda_hybrid + end module radiation_implicit From 034fc78ac85237a2c1ad53280420bee2ad5bdf88 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 10 Jul 2023 14:30:13 +0100 Subject: [PATCH 063/182] Added self contribution to lambda FLD (hybrid cooling) --- src/main/radiation_implicit.f90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index f87c13157..fd54cbe7f 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -1566,7 +1566,10 @@ subroutine calc_lambda_hybrid(xyzh,utherm,rho) dradi = 0. rhoi = rho(i) added_self = .false. - + hi = xyzh(4,i) + hi21 = 1./(hi*hi) + hi1 = 1./hi + call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi) loop_over_neighbours: do k = 1,ivar(1,n) @@ -1587,9 +1590,6 @@ subroutine calc_lambda_hybrid(xyzh,utherm,rho) rij2 = dx*dx + dy*dy + dz*dz + tiny(0.) rij = sqrt(rij2) rij1 = 1./rij - hi = xyzh(4,i) - hi21 = 1./(hi*hi) - hi1 = 1./hi q = rij/hi q2 = rij2*hi21 @@ -1616,7 +1616,7 @@ subroutine calc_lambda_hybrid(xyzh,utherm,rho) ! print *, 'done neighbour loop for ', i,n if (.not. added_self) then ! print *, "Has not added self in lambda hybrid" - uradi = uradi + pmassj*arad*Ti**4d0/rhoi ! add self contribution + uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution endif dradi = sqrt(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! magnitude From b067995e930a89005ac6b26f5c9ce045c8b34eb7 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 13 Jul 2023 11:57:54 +0100 Subject: [PATCH 064/182] Fix bug in moddump_sphNG2phantom_disc.f90 --- src/utils/moddump_sphNG2phantom_disc.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/moddump_sphNG2phantom_disc.f90 b/src/utils/moddump_sphNG2phantom_disc.f90 index 318bac487..4f72577f1 100644 --- a/src/utils/moddump_sphNG2phantom_disc.f90 +++ b/src/utils/moddump_sphNG2phantom_disc.f90 @@ -32,7 +32,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) use prompting, only:prompt use physcon, only:au,gg use readwrite_dumps_fortran, only:dt_read_in_fortran - use timestep, only:time,dt,dtmax_max,dtmax_min,dtmax0 + use timestep, only:time,dt,dtmax_max,dtmax_min use centreofmass, only: reset_centreofmass integer, intent(inout) :: npart integer, intent(inout) :: npartoftype(:) @@ -97,7 +97,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) enddo close(iunit) - print *, 'dtmax0, dtmax_max,dtmax_min',dtmax0,dtmax_max,dtmax_min + print *, 'dtmax_max,dtmax_min',dtmax_max,dtmax_min newutime = sqrt(au**3/(gg*umass)) print *, "newutime/old", newutime/utime time = time * utime / newutime @@ -171,13 +171,13 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) endif enddo - print *,'Found GAS:', gascount, 'sinks:', sinkcount, & + print *,'Found GAS:', gascount, 'sinks:', sinkcount+nptmass, & 'Other:', othercount, 'Total=', gascount+sinkcount+othercount print *, 'maxtypes:', maxtypes, 'npartoftype:', npartoftype,& 'nptmass:', nptmass print *, 'gamma=', gamma print *, 'Timestep info:' - print *, 'dtmax0, dtmax_max,dtmax_min', dtmax0,dtmax_max,dtmax_min + print *, 'dtmax_max,dtmax_min',dtmax_max,dtmax_min print *, 'utime=', utime return From b2b7e17d790517f12c11a1e1a025ad299f28b57a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 18 Jul 2023 15:43:04 +0100 Subject: [PATCH 065/182] Minor change to if statement format: --- src/main/step_leapfrog.F90 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index e57407761..a74428fb0 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -492,11 +492,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling .ne. 8) then - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) else - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) - + if (icooling .ne. 8) then + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + else + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + endif endif !--floor the thermal energy if requested and required From c3db75b54ddd0a4d9f3c8eee58da265d4772a63f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 19 Jul 2023 11:53:21 +0100 Subject: [PATCH 066/182] Fix bugs from merge --- build/Makefile | 2 +- src/main/force.F90 | 2 +- src/main/step_leapfrog.F90 | 95 +++++++++++++++++++------------------- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/build/Makefile b/build/Makefile index a020932cb..3bde38ab0 100644 --- a/build/Makefile +++ b/build/Makefile @@ -512,7 +512,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos.f90 +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.F90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 diff --git a/src/main/force.F90 b/src/main/force.F90 index 2ec0469b8..3fc066cc9 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -899,7 +899,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use dim, only:maxalpha,maxp,mhd_nonideal,gravity,gr use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt - use eos, only:ieos,eos_is_non_ideal,gamma,utherm + use eos, only:ieos,eos_is_non_ideal,gamma use eos_stamatellos, only:gradP_cool,Gpot_cool #ifdef GRAVITY use kernel, only:kernel_softening diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 56de8b2a0..9b6c8b6a1 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -527,54 +527,53 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif - if (gr) then - pxi = pxyzu(1,i) + hdtsph*fxyzu(1,i) - pyi = pxyzu(2,i) + hdtsph*fxyzu(2,i) - pzi = pxyzu(3,i) + hdtsph*fxyzu(3,i) - eni = pxyzu(4,i) + hdtsph*fxyzu(4,i) - - erri = (pxi - ppred(1,i))**2 + (pyi - ppred(2,i))**2 + (pzi - ppred(3,i))**2 - errmax = max(errmax,erri) - - p2i = pxi*pxi + pyi*pyi + pzi*pzi - p2mean = p2mean + p2i - np = np + 1 - - pxyzu(1,i) = pxi - pxyzu(2,i) = pyi - pxyzu(3,i) = pzi - pxyzu(4,i) = eni - else - 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) - - erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 - errmax = max(errmax,erri) - - v2i = vxi*vxi + vyi*vyi + vzi*vzi - v2mean = v2mean + v2i - np = np + 1 - - vxyzu(1,i) = vxi - vxyzu(2,i) = vyi - vxyzu(3,i) = vzi - !--this is the energy equation if non-isothermal - if (maxvxyzu >= 4) vxyzu(4,i) = eni - endif - - if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) - if (itype==igas) then - ! - ! corrector step for magnetic field and dust - ! - if (mhd) Bevol(:,i) = Bevol(:,i) + hdtsph*dBevol(:,i) - if (do_radiation) rad(:,i) = rad(:,i) + hdtsph*drad(:,i) - if (use_dustfrac) then - dustevol(:,i) = dustevol(:,i) + hdtsph*ddustevol(:,i) - if (use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) - endif + if (gr) then + pxi = pxyzu(1,i) + hdtsph*fxyzu(1,i) + pyi = pxyzu(2,i) + hdtsph*fxyzu(2,i) + pzi = pxyzu(3,i) + hdtsph*fxyzu(3,i) + eni = pxyzu(4,i) + hdtsph*fxyzu(4,i) + + erri = (pxi - ppred(1,i))**2 + (pyi - ppred(2,i))**2 + (pzi - ppred(3,i))**2 + errmax = max(errmax,erri) + + p2i = pxi*pxi + pyi*pyi + pzi*pzi + p2mean = p2mean + p2i + np = np + 1 + + pxyzu(1,i) = pxi + pxyzu(2,i) = pyi + pxyzu(3,i) = pzi + pxyzu(4,i) = eni + else + 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) + + erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 + errmax = max(errmax,erri) + + v2i = vxi*vxi + vyi*vyi + vzi*vzi + v2mean = v2mean + v2i + np = np + 1 + + vxyzu(1,i) = vxi + vxyzu(2,i) = vyi + vxyzu(3,i) = vzi + !--this is the energy equation if non-isothermal + if (maxvxyzu >= 4) vxyzu(4,i) = eni + endif + + if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) + if (itype==igas) then + ! + ! corrector step for magnetic field and dust + ! + if (mhd) Bevol(:,i) = Bevol(:,i) + hdtsph*dBevol(:,i) + if (do_radiation) rad(:,i) = rad(:,i) + hdtsph*drad(:,i) + if (use_dustfrac) then + dustevol(:,i) = dustevol(:,i) + hdtsph*ddustevol(:,i) + if (use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) endif endif endif From cba088230ba26562e57528a0703e2ce836644fa0 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 25 Jul 2023 14:26:28 +0100 Subject: [PATCH 067/182] fix for gradPcool --- src/main/force.F90 | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index a9cdcd3f4..019547701 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1032,7 +1032,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi + real :: radPj,fgravxi,fgravyi,fgravzi,gradpx,gradpy,gradpz ! unpack xi = xpartveci(ixi) @@ -1204,6 +1204,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (icooling == 8) then gradP_cool(i) = 0d0 Gpot_cool(i) = 0d0 + gradpx = 0d0 + gradpy = 0d0 + gradpz = 0d0 endif loop_over_neighbours2: do n = 1,nneigh @@ -1608,8 +1611,14 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (usej) gradpj = pmassj*(pro2j + qrho2j)*grkernj !-- calculate grad P from gas pressure alone for cooling if (icooling == 8) then - gradP_cool(i) = gradP_cool(i) + pmassj*pri*rho1i*rho1i*grkerni - if (usej) gradP_cool(i) = gradP_cool(i) + pmassj*prj*rho1j*rho1j*grkernj + gradpx = gradpx + runix*pmassj*pri*rho1i*rho1i*grkerni + gradpy = gradpy + runiy*pmassj*pri*rho1i*rho1i*grkerni + gradpz = gradpz + runiz*pmassj*pri*rho1i*rho1i*grkerni + if (usej) then + gradpx = gradpx + runix*pmassj*prj*rho1j*rho1j*grkernj + gradpy = gradpy + runiy*pmassj*prj*rho1j*rho1j*grkernj + gradpz = gradpz + runiz*pmassj*prj*rho1j*rho1j*grkernj + endif endif !--artificial thermal conductivity (need j term) if (maxvxyzu >= 4) then @@ -1994,6 +2003,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif is_sph_neighbour enddo loop_over_neighbours2 + + if (icooling == 8) gradP_cool(i) = cnormk*sqrt(gradpx*gradpx + gradpy*gradpy + gradpz*gradpz) if (gr .and. gravity .and. ien_type == ien_etotal) then From 2a765ae8b462f54615ee898c04f2c4b3cacd93e1 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 26 Jul 2023 17:10:41 +0100 Subject: [PATCH 068/182] Fixes for Lombardi cooling approximation --- src/main/force.F90 | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 019547701..9f36e992c 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1032,7 +1032,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi,gradpx,gradpy,gradpz + real :: radPj,fgravxi,fgravyi,fgravzi,gradpx,gradpy,gradpz,gradP_cooli,gradP_coolj ! unpack xi = xpartveci(ixi) @@ -1611,13 +1611,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (usej) gradpj = pmassj*(pro2j + qrho2j)*grkernj !-- calculate grad P from gas pressure alone for cooling if (icooling == 8) then - gradpx = gradpx + runix*pmassj*pri*rho1i*rho1i*grkerni - gradpy = gradpy + runiy*pmassj*pri*rho1i*rho1i*grkerni - gradpz = gradpz + runiz*pmassj*pri*rho1i*rho1i*grkerni + gradP_cooli = pmassj*pri*rho1i*rho1i*grkerni + gradP_coolj = 0d0 if (usej) then - gradpx = gradpx + runix*pmassj*prj*rho1j*rho1j*grkernj - gradpy = gradpy + runiy*pmassj*prj*rho1j*rho1j*grkernj - gradpz = gradpz + runiz*pmassj*prj*rho1j*rho1j*grkernj + gradp_coolj = pmassj*prj*rho1j*rho1j*grkernj endif endif !--artificial thermal conductivity (need j term) @@ -1733,7 +1730,12 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) - if (icooling == 8) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii + if (icooling == 8) then + Gpot_cool(i) = Gpot_cool(i) + pmassj*phii + gradpx = gradpx + runix*(gradP_cooli + gradP_coolj) + gradpy = gradpy + runiy*(gradP_cooli + gradP_coolj) + gradpz = gradpz + runiz*(gradP_cooli + gradP_coolj) + endif !--calculate divv for use in du, h prediction, av switch etc. fsum(idrhodti) = fsum(idrhodti) + projv*grkerni @@ -2004,7 +2006,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g enddo loop_over_neighbours2 - if (icooling == 8) gradP_cool(i) = cnormk*sqrt(gradpx*gradpx + gradpy*gradpy + gradpz*gradpz) + if (icooling == 8) gradP_cool(i) = sqrt(gradpx*gradpx + gradpy*gradpy + gradpz*gradpz) if (gr .and. gravity .and. ien_type == ien_etotal) then From 577e6e7bcb8a9d2073fd55426c86bde5e838316d Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 27 Jul 2023 12:02:56 +0100 Subject: [PATCH 069/182] Revert "Fix bugs from merge" This reverts commit c3db75b54ddd0a4d9f3c8eee58da265d4772a63f. --- build/Makefile | 2 +- src/main/force.F90 | 2 +- src/main/step_leapfrog.F90 | 95 +++++++++++++++++++------------------- 3 files changed, 50 insertions(+), 49 deletions(-) diff --git a/build/Makefile b/build/Makefile index 3bde38ab0..a020932cb 100644 --- a/build/Makefile +++ b/build/Makefile @@ -512,7 +512,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos.f90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.F90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 diff --git a/src/main/force.F90 b/src/main/force.F90 index 71cf6cb0b..f3ab5b8cd 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -900,7 +900,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use dim, only:maxalpha,maxp,mhd_nonideal,gravity,gr use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt - use eos, only:ieos,eos_is_non_ideal,gamma + use eos, only:ieos,eos_is_non_ideal,gamma,utherm use eos_stamatellos, only:gradP_cool,Gpot_cool #ifdef GRAVITY use kernel, only:kernel_softening diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index be021ef42..56f56ccb7 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -527,53 +527,54 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif - if (gr) then - pxi = pxyzu(1,i) + hdtsph*fxyzu(1,i) - pyi = pxyzu(2,i) + hdtsph*fxyzu(2,i) - pzi = pxyzu(3,i) + hdtsph*fxyzu(3,i) - eni = pxyzu(4,i) + hdtsph*fxyzu(4,i) - - erri = (pxi - ppred(1,i))**2 + (pyi - ppred(2,i))**2 + (pzi - ppred(3,i))**2 - errmax = max(errmax,erri) - - p2i = pxi*pxi + pyi*pyi + pzi*pzi - p2mean = p2mean + p2i - np = np + 1 - - pxyzu(1,i) = pxi - pxyzu(2,i) = pyi - pxyzu(3,i) = pzi - pxyzu(4,i) = eni - else - 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) - - erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 - errmax = max(errmax,erri) - - v2i = vxi*vxi + vyi*vyi + vzi*vzi - v2mean = v2mean + v2i - np = np + 1 - - vxyzu(1,i) = vxi - vxyzu(2,i) = vyi - vxyzu(3,i) = vzi - !--this is the energy equation if non-isothermal - if (maxvxyzu >= 4) vxyzu(4,i) = eni - endif - - if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) - if (itype==igas) then - ! - ! corrector step for magnetic field and dust - ! - if (mhd) Bevol(:,i) = Bevol(:,i) + hdtsph*dBevol(:,i) - if (do_radiation) rad(:,i) = rad(:,i) + hdtsph*drad(:,i) - if (use_dustfrac) then - dustevol(:,i) = dustevol(:,i) + hdtsph*ddustevol(:,i) - if (use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) + if (gr) then + pxi = pxyzu(1,i) + hdtsph*fxyzu(1,i) + pyi = pxyzu(2,i) + hdtsph*fxyzu(2,i) + pzi = pxyzu(3,i) + hdtsph*fxyzu(3,i) + eni = pxyzu(4,i) + hdtsph*fxyzu(4,i) + + erri = (pxi - ppred(1,i))**2 + (pyi - ppred(2,i))**2 + (pzi - ppred(3,i))**2 + errmax = max(errmax,erri) + + p2i = pxi*pxi + pyi*pyi + pzi*pzi + p2mean = p2mean + p2i + np = np + 1 + + pxyzu(1,i) = pxi + pxyzu(2,i) = pyi + pxyzu(3,i) = pzi + pxyzu(4,i) = eni + else + 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) + + erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 + errmax = max(errmax,erri) + + v2i = vxi*vxi + vyi*vyi + vzi*vzi + v2mean = v2mean + v2i + np = np + 1 + + vxyzu(1,i) = vxi + vxyzu(2,i) = vyi + vxyzu(3,i) = vzi + !--this is the energy equation if non-isothermal + if (maxvxyzu >= 4) vxyzu(4,i) = eni + endif + + if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) + if (itype==igas) then + ! + ! corrector step for magnetic field and dust + ! + if (mhd) Bevol(:,i) = Bevol(:,i) + hdtsph*dBevol(:,i) + if (do_radiation) rad(:,i) = rad(:,i) + hdtsph*drad(:,i) + if (use_dustfrac) then + dustevol(:,i) = dustevol(:,i) + hdtsph*ddustevol(:,i) + if (use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) + endif endif endif endif From b13ecd4e300f1b9ac864dbf913644c5ed43ef665 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 27 Jul 2023 12:08:36 +0100 Subject: [PATCH 070/182] change .ne. to /= in icooling = 8 --- src/main/step_leapfrog.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 56f56ccb7..65d45af16 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -491,7 +491,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - if (icooling .ne. 8) then + if (icooling /= 8) then vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) else vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) From 38834b90000657f6451f41bb7c797660367e6120 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 27 Jul 2023 12:36:13 +0100 Subject: [PATCH 071/182] bug fixes --- build/Makefile | 2 +- src/main/eos_stamatellos.f90 | 1 + src/main/force.F90 | 2 +- src/main/step_leapfrog.F90 | 5 ++--- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/Makefile b/build/Makefile index a020932cb..3bde38ab0 100644 --- a/build/Makefile +++ b/build/Makefile @@ -512,7 +512,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos.f90 +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.F90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index dcf4ca520..7ed51195b 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -24,6 +24,7 @@ module eos_stamatellos !integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep + public :: finish_S07cool contains subroutine init_S07cool() diff --git a/src/main/force.F90 b/src/main/force.F90 index f3ab5b8cd..71cf6cb0b 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -900,7 +900,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use dim, only:maxalpha,maxp,mhd_nonideal,gravity,gr use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt - use eos, only:ieos,eos_is_non_ideal,gamma,utherm + use eos, only:ieos,eos_is_non_ideal,gamma use eos_stamatellos, only:gradP_cool,Gpot_cool #ifdef GRAVITY use kernel, only:kernel_softening diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 65d45af16..79819a2e7 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -505,7 +505,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) nvfloorc = nvfloorc + 1 endif endif - + if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + hdti*dBevol(:,i) @@ -577,8 +577,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif endif - endif - enddo corrector + enddo corrector !$omp enddo !$omp end parallel if (use_dustgrowth) call check_dustprop(npart,dustprop(1,:)) From 68acaabd658d3acc6a8c84a715a00300c9229f10 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 27 Jul 2023 12:39:55 +0100 Subject: [PATCH 072/182] bugfixes --- build/Makefile | 2 +- src/main/eos_stamatellos.f90 | 2 +- src/main/force.F90 | 2 +- src/main/step_leapfrog.F90 | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/build/Makefile b/build/Makefile index a020932cb..3bde38ab0 100644 --- a/build/Makefile +++ b/build/Makefile @@ -512,7 +512,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos.f90 +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.F90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index dcf4ca520..b78bff0e4 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -23,7 +23,7 @@ module eos_stamatellos character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file !integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in - public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep + public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep,finish_S07cool contains subroutine init_S07cool() diff --git a/src/main/force.F90 b/src/main/force.F90 index f3ab5b8cd..71cf6cb0b 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -900,7 +900,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use dim, only:maxalpha,maxp,mhd_nonideal,gravity,gr use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt - use eos, only:ieos,eos_is_non_ideal,gamma,utherm + use eos, only:ieos,eos_is_non_ideal,gamma use eos_stamatellos, only:gradP_cool,Gpot_cool #ifdef GRAVITY use kernel, only:kernel_softening diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 65d45af16..7a85e05f7 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -577,7 +577,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif endif - endif enddo corrector !$omp enddo !$omp end parallel From 5461e3539ba7d413f60037cb88dd4a9f2f9b578d Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 27 Jul 2023 12:41:07 +0100 Subject: [PATCH 073/182] minor edit --- src/main/eos_stamatellos.f90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 7ed51195b..b78bff0e4 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -23,8 +23,7 @@ module eos_stamatellos character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file !integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in - public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep - public :: finish_S07cool + public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep,finish_S07cool contains subroutine init_S07cool() From 30b6e2506d13623380cf9728691cc75d2698bd8b Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 27 Jul 2023 13:47:14 +0100 Subject: [PATCH 074/182] minor edit --- src/main/step_leapfrog.F90 | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 1fbc85379..81d7e2085 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -94,7 +94,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use dim, only:maxp,ndivcurlv,maxvxyzu,maxptmass,maxalpha,nalpha,h2chemistry,& use_dustgrowth,use_krome,gr,do_radiation use io, only:iprint,fatal,iverbose,id,master,warning - use options, only:iexternalforce,use_dustfrac,implicit_radiation + use options, only:iexternalforce,use_dustfrac,implicit_radiation,icooling use part, only:xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,Bevol,dBevol, & rad,drad,radprop,isdead_or_accreted,rhoh,dhdrho,& iphase,iamtype,massoftype,maxphase,igas,idust,mhd,& @@ -172,7 +172,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none) & !$omp shared(npart,xyzh,vxyzu,fxyzu,iphase,hdtsph,store_itype) & - !$omp shared(rad,drad,pxyzu)& + !$omp shared(rad,drad,pxyzu,icooling) & !$omp shared(Bevol,dBevol,dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred,ufloor) & !$omp shared(ibin,ibin_old,twas,timei) & @@ -197,6 +197,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 8) then + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif @@ -308,6 +310,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then ppred(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling == 8) then + vpred(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif @@ -420,7 +424,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel default(none) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,npart,hdtsph,store_itype) & !$omp shared(pxyzu,ppred) & -!$omp shared(Bevol,dBevol,iphase,its) & +!$omp shared(Bevol,dBevol,iphase,its,icooling) & !$omp shared(dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass,massoftype) & @@ -460,6 +464,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) + elseif (icooling == 8) then + vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif @@ -483,7 +489,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else +<<<<<<< Updated upstream vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) +======= + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) +>>>>>>> Stashed changes endif !--floor the thermal energy if requested and required @@ -552,7 +562,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (.not.converged .and. npart > 0) then !$omp parallel do default(none)& !$omp private(i) & -!$omp shared(npart,hdtsph)& +!$omp shared(npart,hdtsph,icooling)& !$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase) & !$omp shared(Bevol,dBevol,Bpred,pxyzu,ppred) & !$omp shared(dustprop,ddustprop,dustproppred,use_dustfrac,dustevol,dustpred,ddustevol) & From 826f8f0916a5c445b3ac7500d6cd316d47bb7187 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 31 Aug 2023 17:02:05 +0100 Subject: [PATCH 075/182] Revert to 2a765ae --- AUTHORS | 26 +- README.md | 38 +- build/Makefile | 105 +++-- build/Makefile_defaults_aocc | 1 - build/Makefile_fastmath | 4 +- build/Makefile_setups | 111 +++-- build/Makefile_systems | 2 +- data/forcing/README | 10 - docs/CE.rst | 12 +- docs/bots.rst | 74 --- docs/developer-guide.rst | 3 +- docs/gitinfo.rst | 39 +- docs/hdf5.rst | 32 +- docs/setups-best.rst | 2 +- docs/setups-list.rst | 14 +- docs/staging.rst | 21 +- docs/testing.rst | 122 ++--- scripts/HEADER-module | 2 +- scripts/HEADER-program | 2 +- scripts/buildbot.sh | 47 +- src/lib/NICIL/src/nicil.F90 | 20 +- src/main/bondiexact.f90 | 2 +- src/main/bondiexact_gr.f90 | 2 +- src/main/boundary.f90 | 2 +- src/main/boundary_dynamic.f90 | 4 +- src/main/centreofmass.f90 | 2 +- src/main/checkconserved.f90 | 6 +- src/main/checkoptions.F90 | 21 +- src/main/checksetup.F90 | 122 +++-- src/main/config.F90 | 8 +- src/main/cons2prim.f90 | 11 +- src/main/cons2primsolver.f90 | 10 +- src/main/{cooling.f90 => cooling.F90} | 2 +- src/main/cooling_functions.f90 | 2 +- src/main/cooling_gammie.f90 | 2 +- src/main/cooling_gammie_PL.f90 | 2 +- src/main/cooling_ism.f90 | 2 +- src/main/cooling_koyamainutsuka.f90 | 2 +- src/main/cooling_molecular.f90 | 2 +- src/main/cooling_solver.f90 | 2 +- src/main/cullendehnen.f90 | 11 +- src/main/damping.f90 | 2 +- src/main/datafiles.f90 | 2 +- src/main/dens.F90 | 7 +- src/main/deriv.F90 | 41 +- src/main/dtype_kdtree.F90 | 2 +- src/main/{dust.f90 => dust.F90} | 4 +- ...{dust_formation.f90 => dust_formation.F90} | 12 +- src/main/energies.F90 | 210 +++++---- src/main/{eos.f90 => eos.F90} | 70 ++- src/main/eos_barotropic.f90 | 2 +- src/main/eos_gasradrec.f90 | 2 +- src/main/eos_helmholtz.f90 | 2 +- src/main/eos_idealplusrad.f90 | 2 +- src/main/eos_mesa.f90 | 2 +- src/main/eos_mesa_microphysics.f90 | 2 +- src/main/eos_piecewise.f90 | 2 +- src/main/eos_shen.f90 | 2 +- src/main/eos_stamatellos.f90 | 2 +- src/main/eos_stratified.f90 | 2 +- src/main/evolve.F90 | 21 +- src/main/{evwrite.f90 => evwrite.F90} | 35 +- src/main/extern_Bfield.f90 | 2 +- src/main/extern_binary.f90 | 2 +- src/main/extern_binary_gw.f90 | 2 +- src/main/extern_corotate.f90 | 2 +- src/main/extern_densprofile.f90 | 2 +- ...{extern_gnewton.f90 => extern_gnewton.F90} | 2 +- src/main/extern_gr.F90 | 2 +- src/main/extern_gwinspiral.f90 | 2 +- src/main/extern_lensethirring.f90 | 2 +- .../{extern_prdrag.f90 => extern_prdrag.F90} | 2 +- src/main/extern_spiral.f90 | 2 +- src/main/extern_staticsine.f90 | 2 +- ...{externalforces.f90 => externalforces.F90} | 6 +- ...nalforces_gr.f90 => externalforces_gr.F90} | 4 +- src/main/fastmath.f90 | 2 +- src/main/force.F90 | 127 +++-- src/main/forcing.F90 | 30 +- src/main/fs_data.f90 | 2 +- src/main/geometry.f90 | 2 +- src/main/gitinfo.f90 | 2 +- src/main/growth.F90 | 37 +- src/main/growth_smol.f90 | 2 +- src/main/h2chem.f90 | 4 +- src/main/initial.F90 | 87 ++-- src/main/inject_BHL.f90 | 17 +- src/main/inject_asteroidwind.f90 | 10 +- src/main/inject_bondi.f90 | 10 +- src/main/inject_firehose.f90 | 9 +- src/main/inject_galcen_winds.f90 | 10 +- src/main/inject_keplerianshear.f90 | 29 +- src/main/inject_rochelobe.f90 | 10 +- src/main/inject_sne.f90 | 10 +- src/main/inject_steadydisc.f90 | 39 +- src/main/inject_unifwind.f90 | 10 +- src/main/{inject_wind.f90 => inject_wind.F90} | 112 ++--- src/main/inverse4x4.f90 | 2 +- src/main/io.F90 | 2 +- src/main/ionization.f90 | 2 +- src/main/kdtree.F90 | 2 +- src/main/kernel_WendlandC2.f90 | 2 +- src/main/kernel_WendlandC4.f90 | 2 +- src/main/kernel_WendlandC6.f90 | 2 +- src/main/kernel_cubic.f90 | 2 +- src/main/kernel_quartic.f90 | 2 +- src/main/kernel_quintic.f90 | 2 +- src/main/krome.f90 | 2 +- src/main/linklist_kdtree.F90 | 4 +- src/main/lumin_nsdisc.F90 | 12 +- src/main/memory.F90 | 16 +- src/main/metric_kerr-schild.f90 | 2 +- src/main/metric_kerr.f90 | 2 +- src/main/metric_minkowski.f90 | 2 +- src/main/metric_schwarzschild.f90 | 2 +- src/main/metric_tools.F90 | 2 +- src/main/mf_write.f90 | 2 +- src/main/mol_data.f90 | 2 +- src/main/mpi_balance.F90 | 36 +- src/main/mpi_dens.F90 | 2 +- src/main/mpi_derivs.F90 | 2 +- src/main/mpi_domain.F90 | 4 +- src/main/mpi_force.F90 | 2 +- src/main/{mpi_memory.f90 => mpi_memory.F90} | 2 +- src/main/mpi_tree.F90 | 2 +- src/main/mpi_utils.F90 | 2 +- ...il_supplement.f90 => nicil_supplement.F90} | 6 +- src/main/options.f90 | 2 +- src/main/part.F90 | 124 +++-- src/main/partinject.F90 | 83 ++-- src/main/{phantom.f90 => phantom.F90} | 2 +- src/main/photoevap.f90 | 432 ++++++++++++++++++ src/main/physcon.f90 | 2 +- src/main/ptmass.F90 | 42 +- ...{ptmass_heating.f90 => ptmass_heating.F90} | 13 +- ...ass_radiation.f90 => ptmass_radiation.F90} | 2 +- src/main/quitdump.f90 | 2 +- src/main/radiation_implicit.f90 | 244 ++++------ src/main/radiation_utils.f90 | 2 +- src/main/random.f90 | 2 +- src/main/readwrite_dumps.F90 | 7 +- src/main/readwrite_dumps_common.F90 | 105 ++--- src/main/readwrite_dumps_fortran.F90 | 206 ++++++--- src/main/readwrite_dumps_hdf5.F90 | 4 +- src/main/readwrite_infile.F90 | 58 ++- ...{sort_particles.f90 => sort_particles.F90} | 2 +- src/main/step_leapfrog.F90 | 125 ++--- src/main/step_supertimestep.F90 | 2 +- src/main/{timestep.f90 => timestep.F90} | 2 +- src/main/units.f90 | 16 +- src/main/utils_allocate.f90 | 2 +- src/main/utils_binary.f90 | 32 +- src/main/utils_cpuinfo.f90 | 2 +- src/main/utils_datafiles.f90 | 10 +- src/main/utils_deriv.f90 | 50 +- src/main/utils_dumpfiles.f90 | 95 ++-- src/main/utils_dumpfiles_hdf5.f90 | 2 +- src/main/utils_filenames.f90 | 131 +----- src/main/utils_gr.F90 | 2 +- src/main/utils_hdf5.f90 | 2 +- src/main/utils_healpix.f90 | 2 +- src/main/utils_indtimesteps.F90 | 4 +- src/main/utils_infiles.f90 | 2 +- src/main/utils_inject.f90 | 2 +- src/main/utils_mathfunc.f90 | 2 +- src/main/utils_omp.F90 | 2 +- src/main/utils_raytracer.f90 | 2 +- src/main/utils_shuffleparticles.F90 | 2 +- src/main/utils_sort.f90 | 2 +- src/main/utils_sphNG.f90 | 2 +- src/main/utils_spline.f90 | 2 +- src/main/utils_summary.F90 | 2 +- src/main/utils_supertimestep.F90 | 2 +- src/main/utils_system.f90 | 2 +- src/main/utils_tables.f90 | 2 +- src/main/utils_timing.f90 | 39 +- src/main/utils_vectors.f90 | 2 +- src/main/viscosity.f90 | 2 +- src/main/wind.F90 | 24 +- src/main/wind_equations.f90 | 10 +- src/main/writeheader.F90 | 2 +- src/setup/density_profiles.f90 | 2 +- src/setup/libsetup.f90 | 2 +- src/setup/phantomsetup.F90 | 26 +- src/setup/readwrite_kepler.f90 | 2 +- src/setup/readwrite_mesa.f90 | 181 ++++---- src/setup/relax_star.f90 | 32 +- src/setup/set_Bfield.f90 | 2 +- src/setup/set_binary.f90 | 173 +++---- src/setup/set_cubic_core.f90 | 2 +- src/setup/set_disc.F90 | 6 +- src/setup/set_dust.f90 | 2 +- src/setup/set_dust_options.f90 | 2 +- src/setup/set_fixedentropycore.f90 | 2 +- src/setup/set_flyby.f90 | 4 +- src/setup/set_hierarchical.f90 | 34 +- src/setup/set_hierarchical_utils.f90 | 2 +- src/setup/set_planets.f90 | 2 +- src/setup/set_shock.f90 | 2 +- src/setup/set_slab.f90 | 2 +- src/setup/set_softened_core.f90 | 2 +- src/setup/set_sphere.f90 | 2 +- src/setup/set_star.f90 | 48 +- src/setup/set_star_utils.f90 | 15 +- src/setup/set_unifdis.f90 | 2 +- src/setup/set_units.f90 | 2 +- src/setup/set_vfield.f90 | 2 +- src/setup/setup_BHL.f90 | 2 +- src/setup/setup_alfvenwave.f90 | 2 +- src/setup/setup_asteroidwind.f90 | 2 +- src/setup/setup_binary.f90 | 38 +- src/setup/setup_blob.f90 | 2 +- .../{setup_bondi.f90 => setup_bondi.F90} | 2 +- src/setup/setup_bondiinject.f90 | 2 +- src/setup/setup_chinchen.f90 | 2 +- src/setup/setup_cluster.f90 | 2 +- src/setup/setup_collidingclouds.f90 | 50 +- src/setup/setup_common.f90 | 2 +- src/setup/setup_disc.f90 | 6 +- src/setup/setup_dustsettle.f90 | 2 +- src/setup/setup_dustybox.f90 | 2 +- src/setup/setup_dustysedov.f90 | 2 +- src/setup/setup_empty.f90 | 2 +- src/setup/setup_firehose.f90 | 2 +- src/setup/setup_galaxies.f90 | 2 +- src/setup/setup_galcen_stars.f90 | 2 +- src/setup/setup_galdisc.f90 | 12 +- src/setup/setup_grdisc.F90 | 2 +- src/setup/setup_grtde.f90 | 2 +- src/setup/setup_gwdisc.f90 | 2 +- src/setup/setup_hierarchical.f90 | 2 +- src/setup/setup_jadvect.f90 | 2 +- src/setup/setup_kh.f90 | 2 +- src/setup/setup_mhdblast.f90 | 2 +- src/setup/setup_mhdrotor.f90 | 2 +- src/setup/setup_mhdsine.f90 | 2 +- src/setup/setup_mhdvortex.f90 | 2 +- src/setup/setup_mhdwave.f90 | 2 +- src/setup/setup_nsdisc.f90 | 4 +- src/setup/setup_orstang.f90 | 2 +- src/setup/setup_params.f90 | 2 +- src/setup/setup_photoevap.f90 | 97 ++++ src/setup/setup_planetdisc.f90 | 2 +- src/setup/setup_prtest.f90 | 28 +- src/setup/setup_quebec.f90 | 2 +- src/setup/setup_radiativebox.f90 | 2 +- src/setup/setup_sedov.f90 | 2 +- src/setup/setup_shock.F90 | 88 ++-- src/setup/setup_solarsystem.f90 | 2 +- src/setup/setup_sphereinbox.f90 | 4 +- src/setup/setup_srblast.f90 | 2 +- src/setup/setup_srpolytrope.f90 | 2 +- src/setup/setup_star.f90 | 2 +- src/setup/setup_taylorgreen.f90 | 2 +- src/setup/setup_testparticles.F90 | 24 +- src/setup/setup_tokamak.f90 | 2 +- src/setup/setup_torus.f90 | 2 +- src/setup/setup_turb.f90 | 2 +- src/setup/setup_unifdis.f90 | 35 +- src/setup/setup_wave.f90 | 11 +- src/setup/setup_wavedamp.f90 | 48 +- src/setup/setup_wddisc.f90 | 2 +- src/setup/{setup_wind.f90 => setup_wind.F90} | 91 ++-- src/setup/stretchmap.f90 | 2 +- src/setup/velfield_fromcubes.f90 | 2 +- src/tests/directsum.f90 | 2 +- src/tests/phantomtest.f90 | 2 +- src/tests/test_cooling.f90 | 2 +- src/tests/test_corotate.f90 | 2 +- src/tests/test_damping.f90 | 2 +- src/tests/test_derivs.F90 | 2 +- src/tests/test_dust.F90 | 2 +- src/tests/test_eos.f90 | 2 +- src/tests/test_eos_stratified.f90 | 2 +- src/tests/test_externf.f90 | 2 +- src/tests/test_externf_gr.f90 | 2 +- .../{test_fastmath.f90 => test_fastmath.F90} | 2 +- src/tests/test_geometry.f90 | 2 +- src/tests/test_gnewton.f90 | 2 +- src/tests/{test_gr.f90 => test_gr.F90} | 2 +- .../{test_gravity.f90 => test_gravity.F90} | 2 +- .../{test_growth.f90 => test_growth.F90} | 66 +-- src/tests/test_hierarchical.f90 | 2 +- src/tests/test_indtstep.F90 | 2 +- src/tests/test_kdtree.F90 | 2 +- src/tests/test_kernel.f90 | 2 +- src/tests/test_link.F90 | 2 +- src/tests/test_luminosity.F90 | 2 +- src/tests/{test_mpi.f90 => test_mpi.F90} | 2 +- src/tests/test_nonidealmhd.F90 | 2 +- src/tests/test_part.f90 | 2 +- src/tests/test_poly.f90 | 2 +- src/tests/test_ptmass.f90 | 2 +- src/tests/test_radiation.f90 | 5 +- src/tests/test_rwdump.F90 | 2 +- src/tests/test_sedov.F90 | 4 +- src/tests/test_setdisc.f90 | 2 +- src/tests/test_smol.F90 | 2 +- src/tests/test_step.F90 | 2 +- src/tests/test_wind.f90 | 178 -------- src/tests/testsuite.F90 | 20 +- src/tests/utils_testsuite.f90 | 2 +- src/utils/acc2ang.f90 | 2 +- src/utils/adaptivemesh.f90 | 2 +- src/utils/analysis_1particle.f90 | 2 +- src/utils/analysis_BRhoOrientation.F90 | 2 +- src/utils/analysis_CoM.f90 | 2 +- src/utils/analysis_GalMerger.f90 | 2 +- src/utils/analysis_MWpdf.f90 | 2 +- src/utils/analysis_NSmerger.f90 | 2 +- src/utils/analysis_alpha.f90 | 2 +- src/utils/analysis_angmom.f90 | 2 +- src/utils/analysis_angmomvec.f90 | 2 +- src/utils/analysis_average_orb_en.f90 | 2 +- src/utils/analysis_binarydisc.f90 | 7 +- src/utils/analysis_bzrms.f90 | 2 +- src/utils/analysis_clumpfind.F90 | 2 +- src/utils/analysis_clumpfindWB23.F90 | 2 +- .../analysis_collidingcloudevolution.f90 | 2 +- .../analysis_collidingcloudhistograms.f90 | 2 +- ...elope.f90 => analysis_common_envelope.F90} | 218 ++------- src/utils/analysis_cooling.f90 | 2 +- src/utils/analysis_disc.f90 | 2 +- src/utils/analysis_disc_MFlow.f90 | 2 +- src/utils/analysis_disc_eccentric.f90 | 2 +- src/utils/analysis_disc_mag.f90 | 2 +- src/utils/analysis_disc_planet.f90 | 2 +- src/utils/analysis_disc_stresses.f90 | 2 +- src/utils/analysis_dtheader.f90 | 2 +- src/utils/analysis_dustmass.f90 | 2 +- src/utils/analysis_dustydisc.f90 | 2 +- ...s_dustywind.f90 => analysis_dustywind.F90} | 6 +- src/utils/analysis_etotgr.f90 | 2 +- src/utils/analysis_getneighbours.f90 | 2 +- src/utils/analysis_gws.f90 | 2 +- src/utils/analysis_jet.f90 | 2 +- src/utils/analysis_kdtree.F90 | 2 +- src/utils/analysis_kepler.f90 | 2 +- src/utils/analysis_macctrace.f90 | 2 +- src/utils/analysis_mapping_mass.f90 | 2 +- src/utils/analysis_mcfost.f90 | 2 +- src/utils/analysis_mcfostcmdline.f90 | 2 +- src/utils/analysis_pairing.f90 | 2 +- src/utils/analysis_particle.f90 | 2 +- src/utils/analysis_pdfs.f90 | 2 +- src/utils/analysis_phantom_dump.f90 | 2 +- src/utils/analysis_polytropes.f90 | 2 +- src/utils/analysis_prdrag.f90 | 2 +- src/utils/analysis_protostar_environ.F90 | 2 +- src/utils/analysis_ptmass.f90 | 2 +- src/utils/analysis_raytracer.f90 | 2 +- src/utils/analysis_sinkmass.f90 | 2 +- src/utils/analysis_sphere.f90 | 2 +- src/utils/analysis_structurefn.f90 | 2 +- src/utils/analysis_tde.f90 | 2 +- src/utils/analysis_torus.f90 | 2 +- src/utils/analysis_trackbox.f90 | 2 +- src/utils/analysis_tracks.f90 | 2 +- .../analysis_velocitydispersion_vs_scale.f90 | 2 +- src/utils/analysis_velocityshear.f90 | 2 +- src/utils/analysis_write_kdtree.F90 | 2 +- src/utils/combinedustdumps.f90 | 2 +- src/utils/cubicsolve.f90 | 2 +- src/utils/diffdumps.f90 | 2 +- src/utils/dustywaves.f90 | 2 +- src/utils/ev2kdot.f90 | 2 +- src/utils/ev2mdot.f90 | 2 +- src/utils/evol_dustywaves.f90 | 2 +- src/utils/get_struct_slope.f90 | 2 +- src/utils/getmathflags.f90 | 2 +- src/utils/grid2pdf.f90 | 2 +- src/utils/hdf5utils.f90 | 2 +- src/utils/icosahedron.f90 | 2 +- src/utils/interpolate3D_amr.F90 | 2 +- src/utils/io_grid.f90 | 2 +- src/utils/io_structurefn.f90 | 2 +- src/utils/leastsquares.f90 | 2 +- src/utils/libphantom-splash.f90 | 2 +- src/utils/lombperiod.f90 | 2 +- src/utils/mflow.f90 | 2 +- src/utils/moddump_CoM.f90 | 2 +- src/utils/moddump_addflyby.f90 | 2 +- src/utils/moddump_addplanets.f90 | 2 +- src/utils/moddump_binary.f90 | 2 +- src/utils/moddump_binarystar.f90 | 2 +- src/utils/moddump_changemass.f90 | 2 +- src/utils/moddump_default.f90 | 2 +- src/utils/moddump_disc.f90 | 2 +- src/utils/moddump_dustadd.f90 | 2 +- src/utils/moddump_extenddisc.f90 | 2 +- src/utils/moddump_growthtomultigrain.f90 | 2 +- src/utils/moddump_mergepart.f90 | 2 +- src/utils/moddump_messupSPH.f90 | 2 +- src/utils/moddump_perturbgas.f90 | 2 +- src/utils/moddump_polytrope.f90 | 2 +- src/utils/moddump_rad_to_LTE.f90 | 4 +- src/utils/moddump_recalcuT.f90 | 2 +- .../moddump_removeparticles_cylinder.f90 | 2 +- src/utils/moddump_removeparticles_radius.f90 | 2 +- src/utils/moddump_rotate.f90 | 2 +- src/utils/moddump_sink.f90 | 4 +- src/utils/moddump_sinkbinary.f90 | 2 +- src/utils/moddump_sphNG2phantom.f90 | 2 +- src/utils/moddump_sphNG2phantom_addBfield.f90 | 2 +- src/utils/moddump_sphNG2phantom_disc.f90 | 10 +- src/utils/moddump_splitpart.f90 | 2 +- src/utils/moddump_taylorgreen.f90 | 2 +- src/utils/moddump_tidal.f90 | 2 +- src/utils/moddump_torus.f90 | 2 +- src/utils/multirun.f90 | 2 +- src/utils/multirun_mach.f90 | 2 +- src/utils/pdfs.f90 | 2 +- src/utils/phantom2divb.f90 | 2 +- src/utils/phantom2divv.f90 | 2 +- src/utils/phantom2gadget.f90 | 2 +- src/utils/phantom2hdf5.f90 | 2 +- src/utils/phantom2sphNG.f90 | 2 +- src/utils/phantom_moddump.f90 | 2 +- src/utils/phantomanalysis.f90 | 5 +- src/utils/phantomevcompare.f90 | 2 +- src/utils/phantomextractsinks.f90 | 2 +- src/utils/plot_kernel.f90 | 2 +- src/utils/powerspectrums.f90 | 2 +- src/utils/prompting.f90 | 2 +- src/utils/quartic.f90 | 2 +- src/utils/rhomach.f90 | 2 +- src/utils/showarrays.f90 | 2 +- src/utils/showheader.f90 | 6 +- src/utils/solvelinearsystem.f90 | 2 +- src/utils/splitpart.f90 | 2 +- src/utils/struct2struct.f90 | 2 +- .../{struct_part.f90 => struct_part.F90} | 10 +- src/utils/test_binary.f90 | 2 +- src/utils/testbinary.f90 | 2 +- src/utils/utils_disc.f90 | 2 +- src/utils/utils_ephemeris.f90 | 2 +- src/utils/utils_evfiles.f90 | 2 +- src/utils/utils_getneighbours.F90 | 2 +- src/utils/utils_gravwave.f90 | 2 +- src/utils/utils_linalg.f90 | 2 +- src/utils/utils_mpc.f90 | 2 +- src/utils/utils_orbits.f90 | 2 +- ...tracer_all.f90 => utils_raytracer_all.F90} | 2 +- src/utils/utils_splitmerge.f90 | 2 +- src/utils/velfield.f90 | 2 +- 445 files changed, 2900 insertions(+), 3121 deletions(-) delete mode 100644 data/forcing/README delete mode 100644 docs/bots.rst rename src/main/{cooling.f90 => cooling.F90} (99%) rename src/main/{dust.f90 => dust.F90} (99%) rename src/main/{dust_formation.f90 => dust_formation.F90} (98%) rename src/main/{eos.f90 => eos.F90} (96%) rename src/main/{evwrite.f90 => evwrite.F90} (96%) rename src/main/{extern_gnewton.f90 => extern_gnewton.F90} (98%) rename src/main/{extern_prdrag.f90 => extern_prdrag.F90} (99%) rename src/main/{externalforces.f90 => externalforces.F90} (99%) rename src/main/{externalforces_gr.f90 => externalforces_gr.F90} (98%) rename src/main/{inject_wind.f90 => inject_wind.F90} (92%) rename src/main/{mpi_memory.f90 => mpi_memory.F90} (99%) rename src/main/{nicil_supplement.f90 => nicil_supplement.F90} (97%) rename src/main/{phantom.f90 => phantom.F90} (97%) create mode 100644 src/main/photoevap.f90 rename src/main/{ptmass_heating.f90 => ptmass_heating.F90} (82%) rename src/main/{ptmass_radiation.f90 => ptmass_radiation.F90} (99%) rename src/main/{sort_particles.f90 => sort_particles.F90} (98%) rename src/main/{timestep.f90 => timestep.F90} (99%) rename src/setup/{setup_bondi.f90 => setup_bondi.F90} (99%) create mode 100644 src/setup/setup_photoevap.f90 rename src/setup/{setup_wind.f90 => setup_wind.F90} (93%) rename src/tests/{test_fastmath.f90 => test_fastmath.F90} (98%) rename src/tests/{test_gr.f90 => test_gr.F90} (99%) rename src/tests/{test_gravity.f90 => test_gravity.F90} (99%) rename src/tests/{test_growth.f90 => test_growth.F90} (91%) rename src/tests/{test_mpi.f90 => test_mpi.F90} (98%) delete mode 100644 src/tests/test_wind.f90 rename src/utils/{analysis_common_envelope.f90 => analysis_common_envelope.F90} (95%) rename src/utils/{analysis_dustywind.f90 => analysis_dustywind.F90} (98%) rename src/utils/{struct_part.f90 => struct_part.F90} (97%) rename src/utils/{utils_raytracer_all.f90 => utils_raytracer_all.F90} (99%) diff --git a/AUTHORS b/AUTHORS index 8725b3380..7a8461e8c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -20,6 +20,7 @@ Rebecca Nealon Ward Homan Christophe Pinte Elisabeth Borchert +Alison Young Fangyi (Fitz) Hu Megha Sharma Terrence Tricco @@ -27,22 +28,21 @@ Mats Esseldeurs Stephane Michoulier Simone Ceppi MatsEsseldeurs -Enrico Ragusa Caitlyn Hardiman -fhu +Enrico Ragusa Sergei Biriukov Cristiano Longarini Giovanni Dipierro Roberto Iaconi +fhu Hauke Worpel -Alison Young Simone Ceppi -Stephen Neilson <36410751+s-neilson@users.noreply.github.com> Amena Faruqi +Stephen Neilson <36410751+s-neilson@users.noreply.github.com> Martina Toscani Benedetta Veronesi -Simon Glover Sahl Rowther +Simon Glover Thomas Reichardt Jean-François Gonzalez Christopher Russell @@ -52,16 +52,11 @@ Jolien Malfait Phantom benchmark bot Kieran Hirsh Nicole Rodrigues -David Trevascus Amena Faruqi +David Trevascus +Chris Nixon Megha Sharma Nicolas Cuello -Chris Nixon -Orsola De Marco -Joe Fisher -Giulia Ballabio -s-neilson <36410751+s-neilson@users.noreply.github.com> -Megha Sharma Benoit Commercon Giulia Ballabio Joe Fisher @@ -69,13 +64,10 @@ Maxime Lombart Megha Sharma Orsola De Marco Zachary Pellow +s-neilson <36410751+s-neilson@users.noreply.github.com> +Alison Young Cox, Samuel -mats esseldeurs -Nicolás Cuello Jorge Cuadra -Steven Rieder -Stéven Toupin -Alison Young Nicolás Cuello Steven Rieder Stéven Toupin diff --git a/README.md b/README.md index bcb9f6dc1..600d757b6 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,21 @@ Phantom is a 3D Smoothed Particle Hydrodynamics and Magnetohydrodynamics code fo Status ------ - -[![build](https://github.com/danieljprice/phantom/actions/workflows/build.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/build.yml) -[![test](https://github.com/danieljprice/phantom/actions/workflows/test.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/test.yml) -[![mpi](https://github.com/danieljprice/phantom/actions/workflows/mpi.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/mpi.yml) -[![mcfost](https://github.com/danieljprice/phantom/actions/workflows/mcfost.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/mcfost.yml) +![testkd](https://github.com/danieljprice/phantom/workflows/testkd/badge.svg) +![test2](https://github.com/danieljprice/phantom/workflows/test2/badge.svg) +![testcyl](https://github.com/danieljprice/phantom/workflows/testcyl/badge.svg) +![mpi](https://github.com/danieljprice/phantom/workflows/mpi/badge.svg) +![GR](https://github.com/danieljprice/phantom/workflows/GR/badge.svg) +![dust](https://github.com/danieljprice/phantom/workflows/dust/badge.svg) +![dust growth](https://github.com/danieljprice/phantom/workflows/growth/badge.svg) +![non-ideal mhd](https://github.com/danieljprice/phantom/workflows/nimhd/badge.svg) +![utils](https://github.com/danieljprice/phantom/workflows/utils/badge.svg) [![Documentation](https://readthedocs.org/projects/phantomsph/badge/?version=latest)](https://phantomsph.readthedocs.io/en/latest/?badge=latest) Links ----- -- Project homepage: http://phantomsph.github.io/ +- Project homepage: http://phantomsph.bitbucket.io/ - Code repository: https://github.com/danieljprice/phantom/ - Documentation: https://phantomsph.readthedocs.org/ - Code paper: http://adsabs.harvard.edu/abs/2018PASA...35...31P @@ -44,12 +48,7 @@ Getting help If you need help, please try the following, in order: 1. Check the [documentation](https://phantomsph.readthedocs.org/). -2. If you encounter a bug, [file an issue](https://github.com/danieljprice/phantom/issues/new) -3. If you want to request a feature, [file an issue](https://github.com/danieljprice/phantom/issues/new), using the issue tracker. -4. If you need help on how to use phantom, [file an issue](https://github.com/danieljprice/phantom/issues/new) - -We welcome general discussion about Phantom, Smoothed Particle Hydrodynamics, -and astrophysics at the [Phantom Slack](https://phantomsph.slack.com/). However, please use the github issues for support requests. +2. File an issue, as a [bug report](https://github.com/danieljprice/phantom/issues/new) or [feature request](https://github.com/danieljprice/phantom/issues/new), using the issue tracker. Contributing ------------ @@ -59,16 +58,25 @@ We welcome contributions, including (but not limited to): 2. Documentation, also by [pull request](https://github.com/danieljprice/phantom/pulls). Docs can be edited in the docs/ directory of the main code. 3. Suggestions for features or bug reports, via the [issue tracker](https://github.com/danieljprice/phantom/issues/new). Please file bugs via github rather than by email. +Slack +----- + +We welcome general discussion about Phantom, Smoothed Particle Hydrodynamics, +and astrophysics at the [Phantom Slack](https://phantomsph.slack.com/). + Citation -------- Please cite [Price et al. (2018)](http://adsabs.harvard.edu/abs/2018PASA...35...31P) when using Phantom. Wherever possible, please try to also cite original references for the algorithms you are using. A partial list can be found in `docs/phantom.bib` file, or by reading the relevant sections of the paper. -Other things -------------- +Licence +------- -For CHANGES see the release notes: https://phantomsph.readthedocs.io/en/latest/releasenotes.html. See LICENCE file for usage and distribution conditions. Copyright (c) 2007-2023 Daniel Price and contributors (see AUTHORS file). +Release notes +------------- + +For CHANGES see the release notes: https://phantomsph.readthedocs.io/en/latest/releasenotes.html. diff --git a/build/Makefile b/build/Makefile index 3bde38ab0..bf65504a9 100644 --- a/build/Makefile +++ b/build/Makefile @@ -69,6 +69,7 @@ CCFLAGS = -O5 LIBCXX = -lstdc++ #FPPFLAGS= LDFLAGS= +SRCPHOTO= LIBTOOL=ar rcs #---------------------------------------------------------------- @@ -85,6 +86,7 @@ LIBTOOL=ar rcs # -DDRIVING ! use turbulence driving # -DMHD ! magnetic fields # -DNONIDEALMHD ! non-ideal magnetic fields including ionisation; uses NICIL +# -DPHOTO ! turn on the photoevaporation # -DLIGHTCURVE ! lightcurve estimation include Makefile_setups @@ -94,25 +96,17 @@ ifndef SETUPFILE endif ifndef SRCNIMHD - SRCNIMHD = nicil.F90 nicil_supplement.f90 + SRCNIMHD = nicil.F90 nicil_supplement.F90 endif ifndef SRCDUST - SRCDUST = dust.f90 growth.F90 + SRCDUST = dust.F90 growth.F90 endif ifdef SMOL SRCDUST+= growth_smol.f90 endif -ifdef SRCINJECT - INJECT_PARTICLES=yes -else - # compile with default wind injection modules but INJECT_PARTICLES=yes or no - # is still optional in the setup block - SRCINJECT=utils_binary.f90 set_binary.f90 inject_wind.f90 -endif - #ifndef SRCGROWTH # SRCGROWTH = growth.F90 #endif @@ -129,8 +123,8 @@ ifeq ($(MCFOST), yes) MCFOST_LIBS = $(PREFIX)/lib MCFOST_LIB = $(PREFIX)/lib MCFOST_INCLUDE = $(PREFIX)/include - ifeq ("X$(HDF5_DIR)","X") - HDF5_DIR=$(PREFIX) + ifeq ("X$(HDF5ROOT)","X") + HDF5ROOT=$(PREFIX) endif else #--otherwise assume the source code is lying around somewhere @@ -149,8 +143,8 @@ ifeq ($(MCFOST), yes) FPPFLAGS+= -DMCFOST LDFLAGS+= -I$(MCFOST_INCLUDE) -I$(MCFOST_INCLUDE)/voro++ -I$(MCFOST_INCLUDE)/hdf5 -I$(MCFOST_INCLUDE)/$(FC) \ -L$(MCFOST_LIB) -lmcfost -L$(MCFOST_LIBS) $(LIBCXX) -lcfitsio -lvoro++ -lsprng \ - -L$(HDF5_DIR) -lhdf5_fortran -lhdf5 -lz #$(LXGBOOST) - #-L$(HDF5_DIR)/lib/Intel -lhdf5_fortran + -L$(HDF5ROOT) -lhdf5_fortran -lhdf5 -lz #$(LXGBOOST) + #-L$(HDF5ROOT)/lib/Intel -lhdf5_fortran endif include Makefile_systems @@ -276,18 +270,22 @@ ifeq ($(STS_TIMESTEPS), yes) FPPFLAGS += -DSTS_TIMESTEPS endif -ifeq ($(RADIATION), yes) - FPPFLAGS += -DRADIATION +ifeq ($(DEBUG), yes) + FFLAGS += -DDEBUG endif -ifeq ($(SINK_RADIATION), yes) - FPPFLAGS += -DSINK_RADIATION +ifeq ($(RADIATION), yes) + FPPFLAGS += -DRADIATION endif ifeq ($(DUST_NUCLEATION), yes) FPPFLAGS += -DDUST_NUCLEATION endif +ifeq ($(SINK_RADIATION), yes) + FPPFLAGS += -DSINK_RADIATION +endif + ifdef SRCTURB FPPFLAGS += -DDRIVING endif @@ -301,9 +299,6 @@ else endif endif -ifeq ($(AOCC), yes) - FPPFLAGS += -DAOCC -endif # # kernel choice # @@ -322,9 +317,13 @@ endif # on command line. Otherwise on # if injection module selected # -ifeq ($(INJECT_PARTICLES), yes) +ifeq ($(INJECT_PARTICLES), no) + SRCINJECT= +else +ifdef SRCINJECT FPPFLAGS += -DINJECT_PARTICLES endif +endif ifdef LIGHTCURVE FPPFLAGS += -DLIGHTCURVE @@ -415,21 +414,21 @@ endif # - lib for the shared library .so files # # Often both directories are under one root, -# e.g. HDF5_DIR= /usr/local/opt/hdf5 -# In this case just set HDF5_DIR for your machine. +# e.g. HDF5ROOT= /usr/local/opt/hdf5 +# In this case just set HDF5ROOT for your machine. # # However, sometimes these directories are separate, # then you must set both HDF5INCLUDE and HDF5LIB. # ifeq ($(HDF5), yes) -ifeq (X$(HDF5_DIR), X) - HDF5_DIR= /usr/local/opt/hdf5 +ifeq (X$(HDF5ROOT), X) + HDF5ROOT= /usr/local/opt/hdf5 endif ifeq (X$(HDF5INCLUDE), X) - HDF5INCLUDE= $(HDF5_DIR)/include + HDF5INCLUDE= $(HDF5ROOT)/include endif ifeq (X$(HDF5LIB), X) - HDF5LIB= $(HDF5_DIR)/lib + HDF5LIB= $(HDF5ROOT)/lib endif FFLAGS+= -I$(HDF5INCLUDE) CCFLAGS+= -I$(HDF5INCLUDE) @@ -472,13 +471,13 @@ SRCPOTS= extern_corotate.f90 \ extern_binary.f90 \ extern_spiral.f90 \ extern_lensethirring.f90 \ - extern_gnewton.f90 \ - lumin_nsdisc.F90 extern_prdrag.f90 \ + extern_gnewton.F90 \ + lumin_nsdisc.F90 extern_prdrag.F90 \ extern_Bfield.f90 \ extern_densprofile.f90 \ extern_staticsine.f90 \ extern_gwinspiral.f90 \ - externalforces.f90 + externalforces.F90 endif ifeq (X$(SRCPOT), X) SRCPOT=${SRCPOTS} @@ -487,7 +486,7 @@ endif # metrics for GR # ifeq ($(GR),yes) - SRCPOT=extern_gr.F90 $(SRCPOTS:externalforces.f90=externalforces_gr.f90) + SRCPOT=extern_gr.F90 $(SRCPOTS:externalforces.F90=externalforces_gr.F90) endif ifdef METRIC SRCMETRIC= metric_${METRIC}.f90 @@ -512,7 +511,8 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 + +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.F90 eos.F90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.F90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 @@ -537,14 +537,14 @@ SOURCES= physcon.f90 ${CONFIG} ${SRCKERNEL} io.F90 units.f90 \ checkoptions.F90 viscosity.f90 damping.f90 options.f90 cons2primsolver.f90 radiation_utils.f90 cons2prim.f90 \ centreofmass.f90 ${SRCPOT} checkconserved.f90 \ utils_filenames.f90 utils_summary.F90 ${SRCCHEM} ${SRCDUST} \ - mpi_memory.f90 mpi_derivs.F90 mpi_tree.F90 kdtree.F90 linklist_kdtree.F90 utils_healpix.f90 utils_raytracer.f90 \ - partinject.F90 utils_inject.f90 dust_formation.f90 ptmass_radiation.f90 ptmass_heating.f90 \ - utils_deriv.f90 radiation_implicit.f90 ${SRCTURB} \ - ${SRCINJECT_DEPS} wind_equations.f90 wind.F90 ${SRCINJECT} \ + mpi_memory.F90 mpi_derivs.F90 mpi_tree.F90 kdtree.F90 linklist_kdtree.F90 utils_healpix.f90 utils_raytracer.f90 \ + partinject.F90 utils_inject.f90 dust_formation.F90 ptmass_radiation.F90 ptmass_heating.F90 \ + radiation_implicit.f90 ${SRCTURB} \ + ${SRCPHOTO} ${SRCINJECT_DEPS} ${SRCINJECT} \ ${SRCKROME} memory.F90 ${SRCREADWRITE_DUMPS} \ quitdump.f90 ptmass.F90 \ - readwrite_infile.F90 dens.F90 force.F90 deriv.F90 energies.F90 sort_particles.f90 \ - utils_shuffleparticles.F90 evwrite.f90 step_leapfrog.F90 writeheader.F90 ${SRCAN} step_supertimestep.F90 \ + readwrite_infile.F90 dens.F90 force.F90 utils_deriv.f90 deriv.F90 energies.F90 sort_particles.F90 \ + utils_shuffleparticles.F90 evwrite.F90 step_leapfrog.F90 writeheader.F90 ${SRCAN} step_supertimestep.F90 \ mf_write.f90 evolve.F90 utils_orbits.f90 utils_linalg.f90 \ checksetup.F90 initial.F90 @@ -611,16 +611,15 @@ edit: checksetup #---------------------------------------------------- # these are the sources for anything which uses the readwrite_dumps module # -SRCDUMP= physcon.f90 ${CONFIG} ${SRCKERNEL} utils_omp.F90 io.F90 units.f90 \ - boundary.f90 boundary_dynamic.f90 mpi_utils.F90 \ - utils_timing.f90 utils_infiles.f90 dtype_kdtree.f90 utils_allocate.f90 part.F90 \ - ${DOMAIN} mpi_dens.F90 mpi_force.F90 \ - mpi_balance.F90 mpi_memory.f90 mpi_derivs.F90 mpi_tree.F90 kdtree.F90 linklist_kdtree.F90 \ +SRCDUMP= physcon.f90 ${CONFIG} ${SRCKERNEL} utils_omp.F90 io.F90 units.f90 boundary.f90 boundary_dynamic.f90 mpi_utils.F90 \ + utils_timing.f90 utils_infiles.f90 dtype_kdtree.f90 utils_allocate.f90 part.F90 ${DOMAIN} \ + mpi_dens.F90 mpi_force.F90 \ + mpi_balance.F90 mpi_memory.F90 mpi_derivs.F90 mpi_tree.F90 kdtree.F90 linklist_kdtree.F90 \ utils_dumpfiles.f90 utils_vectors.f90 utils_mathfunc.f90 \ utils_datafiles.f90 utils_filenames.f90 utils_system.f90 utils_tables.f90 datafiles.f90 gitinfo.f90 \ centreofmass.f90 \ timestep.f90 ${SRCEOS} cullendehnen.f90 dust_formation.F90 \ - ${SRCGR} ${SRCPOT} \ + ${SRCGR} ${SRCPOT} ${SRCPHOTO} \ memory.F90 \ utils_sphNG.f90 \ setup_params.f90 ${SRCFASTMATH} checkoptions.F90 \ @@ -680,18 +679,18 @@ cleansetup: # phantom test suite # ifeq ($(MPI),yes) - SRCTESTMPI = test_mpi.f90 + SRCTESTMPI = test_mpi.F90 else SRCTESTMPI = endif SRCTESTS=utils_testsuite.f90 ${TEST_FASTMATH} test_kernel.f90 \ - test_dust.F90 test_growth.f90 test_smol.F90 \ - test_nonidealmhd.F90 directsum.f90 test_gravity.f90 \ + test_dust.F90 test_growth.F90 test_smol.F90 \ + test_nonidealmhd.F90 directsum.f90 test_gravity.F90 \ test_derivs.F90 test_cooling.f90 test_eos_stratified.f90 \ test_eos.f90 test_externf.f90 test_rwdump.f90 \ test_step.F90 test_indtstep.F90 set_disc.F90 test_setdisc.F90 \ - test_hierarchical.f90 test_damping.f90 test_wind.f90 \ + test_hierarchical.f90 test_damping.f90 \ test_link.F90 test_kdtree.F90 test_part.f90 test_ptmass.f90 test_luminosity.F90\ test_gnewton.f90 test_corotate.f90 test_geometry.f90 \ ${SRCTESTMPI} test_sedov.F90 test_poly.f90 test_radiation.F90 \ @@ -767,7 +766,7 @@ OBJG2PDF= io.o utils_filenames.o asciiutils.o write_griddata.o \ .PHONY: grid2pdf grid2pdf: checksys checkparams checkhdf5 $(OBJG2PDF) @echo "objects are $(OBJG2PDF)" - $(FC) $(FFLAGS) -o $(BINDIR)/grid2pdf $(OBJG2PDF) $(LDFLAGS) -L$(HDF5_DIR)/lib -lhdf5 + $(FC) $(FFLAGS) -o $(BINDIR)/grid2pdf $(OBJG2PDF) $(LDFLAGS) -L$(HDF5ROOT)/lib -lhdf5 @echo "" @echo "Grid2pdf: we are Possibly Dangerously Fanatical" @echo "" @@ -1101,10 +1100,10 @@ cleantestbinary: # check for anything that depends on HDF5 # checkhdf5: - ifeq (X${HDF5_DIR}, X) - @echo; echo "ERROR: HDF5_DIR should be set before compiling with HDF5 utilities"; echo; ${MAKE} err; + ifeq (X${HDF5ROOT}, X) + @echo; echo "ERROR: HDF5ROOT should be set before compiling with HDF5 utilities"; echo; ${MAKE} err; else - @if [ -d $$HDF5_DIR ]; then echo; echo "HDF5_DIR=$$HDF5_DIR"; echo; else echo; echo "ERROR: Directory given by HDF5_DIR=$$HDF5_DIR does not exist"; echo; ${MAKE} err; fi; + @if [ -d $$HDF5ROOT ]; then echo; echo "HDF5ROOT=$$HDF5ROOT"; echo; else echo; echo "ERROR: Directory given by HDF5ROOT=$$HDF5ROOT does not exist"; echo; ${MAKE} err; fi; endif #---------------------------------------------------- diff --git a/build/Makefile_defaults_aocc b/build/Makefile_defaults_aocc index 17c20121e..452ef08bd 100644 --- a/build/Makefile_defaults_aocc +++ b/build/Makefile_defaults_aocc @@ -12,4 +12,3 @@ KNOWN_SYSTEM=yes OMPFLAGS= -fopenmp -AOCC = yes diff --git a/build/Makefile_fastmath b/build/Makefile_fastmath index a148a96c0..0e05134d1 100644 --- a/build/Makefile_fastmath +++ b/build/Makefile_fastmath @@ -29,7 +29,7 @@ endif ifeq ($(FASTMATH), yes) SRCFASTMATH=fastmath.o - TEST_FASTMATH=test_fastmath.f90 + TEST_FASTMATH=test_fastmath.F90 FPPFLAGS+=-DFINVSQRT else SRCFASTMATH= @@ -38,7 +38,7 @@ endif fastmath.o: fastmath.f90 $(FC) $(FFLAGS) -o $@ -c $< || ${MAKE} fastmathlinkerr -test_fastmath.o: test_fastmath.f90 +test_fastmath.o: test_fastmath.F90 $(FC) $(FFLAGS) -o $@ -c $< || ${MAKE} fastmathlinkerr getmathflags.o: getmathflags.f90 $(FC) $(FFLAGS) -o $@ -c $< || ${MAKE} fastmathlinkerr diff --git a/build/Makefile_setups b/build/Makefile_setups index 951275952..3ba061da4 100644 --- a/build/Makefile_setups +++ b/build/Makefile_setups @@ -19,12 +19,6 @@ ifeq ($(SETUP), mcfost) # [buildbot skip] override SETUP=disc MCFOST=yes endif -ifeq ($(SETUP), dustymcfost) # [buildbot skip] - OBSOLETE_SETUP=yes - OLDSETUP=dustymcfost - override SETUP=dustydisc - MCFOST=yes -endif ifeq ($(SETUP), planets) # [buildbot skip] OBSOLETE_SETUP=yes OLDSETUP= planets @@ -154,6 +148,17 @@ ifeq ($(SETUP), wd) ANALYSIS = analysis_gws.f90 endif +ifeq ($(SETUP), photoevap) +# Mark Hutchison photoevaporating disc + DISC_VISCOSITY=yes + FPPFLAGS= -DPHOTO + SETUPFILE= setup_photoevap.f90 + ANALYSIS= analysis_disc.f90 + KNOWN_SETUP=yes + IND_TIMESTEPS=yes + SRCPHOTO=photoevap.f90 +endif + ifeq ($(SETUP), disc) # locally isothermal gas disc DISC_VISCOSITY=yes @@ -266,9 +271,8 @@ ifeq ($(SETUP), nshwdisc) endif ifeq ($(SETUP), prtest) -# simple test of Poynting-Robertson drag +# simple test of prdrag SETUPFILE= setup_prtest.f90 - ISOTHERMAL=yes KNOWN_SETUP=yes endif @@ -740,7 +744,7 @@ ifeq ($(SETUP), star) # import stellar model from 1D stellar evolution code SETUPFILE= setup_star.f90 MODFILE= utils_binary.f90 set_binary.f90 moddump_binary.f90 - ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 + ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.F90 KNOWN_SETUP=yes MAXP=10000000 GRAVITY=yes @@ -753,85 +757,64 @@ ifeq ($(SETUP), grstar) IND_TIMESTEPS=yes SETUPFILE= setup_star.f90 MODFILE= moddump_tidal.f90 - ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 + ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.F90 KNOWN_SETUP=yes MAXP=100000000 GRAVITY=yes endif -ifeq ($(SETUP), radstar) -# setup a star as in the star setup but with radiation +ifeq ($(SETUP), dustystar) +# import stellar model from 1D stellar evolution code w/dust + FPPFLAGS= -DDUST_NUCLEATION -DSINK_RADIATION -DSTAR SETUPFILE= setup_star.f90 MODFILE= utils_binary.f90 set_binary.f90 moddump_binary.f90 - ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 + ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.F90 dust_formation.F90 KNOWN_SETUP=yes MAXP=10000000 GRAVITY=yes - RADIATION=yes endif -ifeq ($(SETUP), dustystar) -# import stellar model from 1D stellar evolution code w/dust - FPPFLAGS= -DDUST_NUCLEATION -DSTAR +ifeq ($(SETUP), radstar) +# setup a star as in the star setup but with radiation SETUPFILE= setup_star.f90 MODFILE= utils_binary.f90 set_binary.f90 moddump_binary.f90 - ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 dust_formation.F90 + ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.F90 KNOWN_SETUP=yes MAXP=10000000 GRAVITY=yes - SINK_RADIATION=yes + RADIATION=yes endif ifeq ($(SETUP), isowind) # isothermal spherical wind - SETUPFILE= setup_wind.f90 + FPPFLAGS= -DWIND -DSINK_RADIATION -DDUST_NUCLEATION ISOTHERMAL=yes - INJECT_PARTICLES=yes - KNOWN_SETUP=yes + WIND=yes endif - ifeq ($(SETUP), wind) # wind setup with dust nucleation - SETUPFILE= setup_wind.f90 + FPPFLAGS= -DWIND -DSINK_RADIATION -DDUST_NUCLEATION ANALYSIS= analysis_cooling.F90 - SINK_RADIATION=yes - DUST_NUCLEATION=yes - INJECT_PARTICLES=yes - KNOWN_SETUP=yes + WIND=yes endif - ifeq ($(SETUP), ismwind) # wind setup with dust nucleation and ISM cooling - SETUPFILE= setup_wind.f90 + FPPFLAGS= -DWIND -DSINK_RADIATION -DDUST_NUCLEATION ANALYSIS= analysis_cooling.F90 H2CHEM=yes - SINK_RADIATION=yes - DUST_NUCLEATION=yes - INJECT_PARTICLES=yes - KNOWN_SETUP=yes + WIND=yes endif - ifeq ($(SETUP), radwind) # wind setup with dust nucleation - SETUPFILE= setup_wind.f90 - ANALYSIS= utils_getneighbours.f90 utils_raytracer_all.f90 analysis_raytracer.f90 - SINK_RADIATION=yes - DUST_NUCLEATION=yes - INJECT_PARTICLES=yes - KNOWN_SETUP=yes + FPPFLAGS= -DWIND -DSINK_RADIATION -DDUST_NUCLEATION + ANALYSIS= utils_getneighbours.f90 utils_raytracer_all.F90 analysis_raytracer.f90 + WIND=yes endif -ifeq ($(SETUP), test) -# default setup for tests - PERIODIC=yes - CONST_ARTRES=yes - CURLV=yes - MHD=yes - DUST=yes - RADIATION=yes - SINK_RADIATION=yes - DUST_NUCLEATION=yes - KERNEL=cubic +ifeq ($(WIND), yes) +# wind particle injection setup + SETUPFILE= setup_wind.F90 + SRCINJECT= utils_binary.f90 set_binary.f90 wind_equations.F90 wind.F90 inject_wind.f90 KNOWN_SETUP=yes endif @@ -920,11 +903,11 @@ ifeq ($(SETUP), isosgdisc) # isothermal self-gravitating disc SETUPFILE= setup_disc.f90 GRAVITY=yes + KNOWN_SETUP=yes IND_TIMESTEPS=yes ANALYSIS=analysis_dustydisc.f90 ISOTHERMAL=yes DISC_VISCOSITY=yes - KNOWN_SETUP=yes endif ifeq ($(SETUP), dustyisosgdisc) @@ -932,11 +915,11 @@ ifeq ($(SETUP), dustyisosgdisc) SETUPFILE= setup_disc.f90 GRAVITY=yes DUST=yes + KNOWN_SETUP=yes IND_TIMESTEPS=yes ANALYSIS=analysis_dustydisc.f90 ISOTHERMAL=yes DISC_VISCOSITY=yes - KNOWN_SETUP=yes endif ifeq ($(SETUP), dustsettle) @@ -949,6 +932,18 @@ ifeq ($(SETUP), dustsettle) KNOWN_SETUP=yes endif +ifeq ($(SETUP), test) +# default setup for tests + PERIODIC=yes + KNOWN_SETUP=yes + CONST_ARTRES=yes + CURLV=yes + MHD=yes + DUST=yes + RADIATION=yes + KERNEL=cubic +endif + ifeq ($(SETUP), test2) # default setup for tests DISC_VISCOSITY=yes @@ -958,31 +953,29 @@ endif ifeq ($(SETUP), testcyl) # default setup for tests DISC_VISCOSITY=yes + KNOWN_SETUP=yes IND_TIMESTEPS=yes CONST_ARTRES=yes CURLV=yes - KNOWN_SETUP=yes endif ifeq ($(SETUP), testkd) # default setup for tests PERIODIC=yes + KNOWN_SETUP=yes IND_TIMESTEPS=yes CONST_ARTRES=yes CURLV=yes MHD=yes RADIATION=yes - SINK_RADIATION=yes - DUST_NUCLEATION=yes - KNOWN_SETUP=yes endif ifeq ($(SETUP), testgrav) # self-gravity unit tests GRAVITY=yes + KNOWN_SETUP=yes CONST_ARTRES=yes CURLV=yes - KNOWN_SETUP=yes endif ifeq ($(SETUP), testdust) diff --git a/build/Makefile_systems b/build/Makefile_systems index c603407eb..bb9ff39ec 100644 --- a/build/Makefile_systems +++ b/build/Makefile_systems @@ -101,7 +101,7 @@ ifeq ($(SYSTEM), ozstar) WALLTIME='168:00:00' endif -ifeq ($(SYSTEM), nt) +ifeq ($(SYSTEM), ozstar2) # ozstar milan cluster include Makefile_defaults_aocc OMPFLAGS=-fopenmp diff --git a/data/forcing/README b/data/forcing/README deleted file mode 100644 index 99065dec1..000000000 --- a/data/forcing/README +++ /dev/null @@ -1,10 +0,0 @@ -The forcing data file is too large to be stored in the Phantom git repository -It will be downloaded automatically when you run the code - -or can be retrieved manually using wget from the phantom website, e.g.: - -wget http://users.monash.edu.au/~dprice/phantom/data/forcing.dat - -The files are: - -forcing.dat diff --git a/docs/CE.rst b/docs/CE.rst index 382a7b017..a3be7f23d 100644 --- a/docs/CE.rst +++ b/docs/CE.rst @@ -73,7 +73,7 @@ Use SETUP=star or SETUP=dustystar and if not specified, the default options. 2.2 make setup 2.3 ./phantomsetup star (option 5 MESA star, input profile = Jan_Star_Phantom_Profile.data, desired EOS = 10, use constant entropy profile, Relax star automatically = yes). The core radius is the softening radius (2-3Ro) - the core mass is the same as the one you have measured from MESA (0.46Mo in Jan_Star_Phantom_Profile.data). + the core mass is the same as the one you have measured from MESA (0.46Mo in Jan_Star_Phantom_Profile). This produces a file called star.setup - this file has all the options so you can edit it. 2.4 vim star.setup, (write_rho_to_file = T) Relaxation @@ -124,13 +124,3 @@ if you come from 2.10, then use as initial model (hereafter initial_nnnnn) one o softening length for the primary core = 1., softening length for companion = 0.1) 2.16 vim binary.in (optional, tmax=200.00, dtmax=0.100) 2.17 ./phantom binary.in - - -**D. Setup sink properties (luminosity)** - -:: - - 2.18 ./phantommoddump binary_00000.tmp dusty_binary_00000.tmp 0.0 - option 9, 12 lum - 2.19 vim dusty_binary.in (adapt isink_radiation, idust_opacity) - 2.20 ./phantom dusty_binary.in diff --git a/docs/bots.rst b/docs/bots.rst deleted file mode 100644 index 880e4f4ad..000000000 --- a/docs/bots.rst +++ /dev/null @@ -1,74 +0,0 @@ -running the bots on a pull request -================================== - -Wondering how to "run the bots" as requested in the pull request template? -Look no further... - -what are the bots and why should I run them? --------------------------------------------- - -The bots perform some automated maintenance tasks in phantom, like -updating the file headers, fixing indentation errors and updating the -AUTHORS list. Running the bots yourself allows you to keep ownership over -the lines of code you wrote, e.g. when typing "git blame" on a subroutine -or when looking at who wrote particular lines in VSCode. Otherwise a small -adjustment in indentation means the lines will be attributed to someone else... - -performing a dry run -~~~~~~~~~~~~~~~~~~~~~ - -By default the bots perform a dry run, making no changes but showing you -what will be changed when you apply the changes. - -You can run the bots yourself as follows:: - - cd phantom/scripts - ./bots.sh - -doing it for real -~~~~~~~~~~~~~~~~~~~~~ - -If you are happy with the dry run, and you have a clean repository (i.e. everything -is committed onto the current branch you are working on), proceed to ACTUALLY -run the bots as follows:: - - cd phantom/scripts - ./bots.sh --commit - -Please note this will PULL, COMMIT and PUSH to whatever git repository your current -branch is tracking. If it is tracking the main branch of the main repo -of phantom your push will be disallowed. Instead you should push the changes -to your fork and issue a pull request. - -apply but do not commit -~~~~~~~~~~~~~~~~~~~~~~~~ - -In some circumstances you want to apply the changes to the files but leave them -as "modified" in the current directory, which means that the can be reversed -with "git restore" and/or committed manually:: - - cd phantom/scripts - ./bots.sh --apply - -running only specific bots -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can run specific bots using the --only flag, e.g.:: - - cd phantom/scripts - ./bots.sh --only authors - -or, to run multiple (or all):: - - cd phantom/scripts - ./bots.sh --apply --only "tabs gt shout header whitespace authors endif" - -fixing merge conflicts in the AUTHORS file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -you can easily recreate/update the AUTHORS file using the authors bot:: - - cd phantom/scripts - ./bots.sh --apply --only authors - cd .. - git add AUTHORS diff --git a/docs/developer-guide.rst b/docs/developer-guide.rst index 02d783985..ef4934464 100644 --- a/docs/developer-guide.rst +++ b/docs/developer-guide.rst @@ -6,13 +6,12 @@ Here is the Phantom developer guide. .. toctree:: :maxdepth: 1 - fork fortran philosophy styleguide setup testing - bots datafiles staging + fork sort diff --git a/docs/gitinfo.rst b/docs/gitinfo.rst index 38edd26e4..b5fb91643 100644 --- a/docs/gitinfo.rst +++ b/docs/gitinfo.rst @@ -8,7 +8,9 @@ Getting your first copy Once you have a GitHub account, you must create your own :doc:`fork `. This is done using the “fork” button (the big button on top right of the -repo page). You can then clone your fork to your computer:: +repo page). You can then clone your fork to your computer: + +:: git clone https://github.com/USERNAME/phantom.git @@ -19,7 +21,9 @@ Setting your username and email address --------------------------------------- Before you can push changes, you must ensure that your name and email -address are set, as follows:: +address are set, as follows: + +:: cd phantom git config --global user.name "Joe Bloggs" @@ -31,7 +35,9 @@ in the commit logs (and in the AUTHORS file) Receiving updates from your fork -------------------------------- -Procedure is: stash your changes, pull the updates, reapply your changes:: +Procedure is: stash your changes, pull the updates, reapply your changes + +:: git stash git pull @@ -41,14 +47,18 @@ Receiving updates from the master branch ---------------------------------------- Before you can receive updates from the master branch, you must first link -your fork to the master branch:: +your fork to the master branch: + +:: git remote add upstream https://github.com/danieljprice/phantom.git This only needs to be done once. To update, the procedure is: stash your changes, pull the updates, -reapply your changes:: +reapply your changes + +:: git stash git fetch upstream @@ -62,17 +72,23 @@ Committing changes to your fork Submit changes to Phantom carefully! The first thing is to pull any upstream changes as described above. Once you have done this, first -check what you will commit:: +check what you will commit: + +:: git diff then go through each subset of changes you have made and commit the -file(s) with a message:: +file(s) with a message: + +:: git commit -m 'changed units in dim file for problem x' src/main/dim_myprob.f90 and so on, for all the files that you want to commit. Then, when you’re -ready to push the changeset back to your fork use:: +ready to push the changeset back to your fork use + +:: git push @@ -80,9 +96,10 @@ Note that you will only be allowed to push changes if you have already updated your copy to the latest version. If you have just updated your code from the master repo, simply update -your fork via:: +your fork via - git commit -m 'merge' +:: + git commit git push This will push all the remote changes to your forked version of Phantom. @@ -91,7 +108,7 @@ Committing changes to the master branch --------------------------------------- This is done through a “pull request”. To do this, -you can click the “contribute” button on the GitHub page to request +you can click the big “pull request” button on the GitHub page to request that your changes be pulled into the master copy of Phantom. Please do this frequently. Many small pull requests are much better than one giant pull request! diff --git a/docs/hdf5.rst b/docs/hdf5.rst index bbccd0a60..c08aca9ad 100644 --- a/docs/hdf5.rst +++ b/docs/hdf5.rst @@ -38,7 +38,7 @@ On macOS you can install HDF5 with Homebrew. brew install hdf5 The shared object library and include files are at -``/usr/local/opt/hdf5``. Use this directory as ``HDF5_DIR`` (see below). +``/usr/local/opt/hdf5``. Use this directory as ``HDF5ROOT`` (see below). On Ubuntu 18.04, for example, you can install HDF5 with apt. @@ -48,7 +48,7 @@ On Ubuntu 18.04, for example, you can install HDF5 with apt. The location of the library is then ``/usr/lib/x86_64-linux-gnu/hdf5/serial``. Use this directory as -``HDF5_DIR`` (see below). +``HDF5ROOT`` (see below). Compiling ~~~~~~~~~ @@ -93,19 +93,25 @@ Compiling Phantom Writing HDF5 output is a compile time option and requires access to the Fortran HDF5 library. To compile for HDF5 output set ``HDF5_DIR``, for -example if HDF5 was installed with Homebrew on macOS:: +example if HDF5 was installed with Homebrew on macOS + +:: HDF5_DIR=/usr/local/opt/hdf5 -or if it was installed with APT on Ubuntu:: +or if it was installed with APT on Ubuntu + +:: HDF5_DIR=/usr/lib/x86_64-linux-gnu/hdf5/serial -Then compile with:: +Then compile with + +:: - make HDF5=yes + make HDF5=yes HDF5ROOT=$HDF5_DIR -The variable ``HDF5_DIR`` specifies the location of the HDF5 library. +The variable ``HDF5ROOT`` specifies the location of the HDF5 library. .. note:: @@ -121,15 +127,19 @@ Ozstar On Ozstar you need to make sure that the OpenMPI and HDF5 modules are loaded. The variable ``HDF5_DIR`` gives the location of the HDF5 library -once the HDF5 module is loaded:: +once the HDF5 module is loaded. + +:: module load iccifort/2018.1.163-gcc-6.4.0 module load openmpi/3.0.0 module load hdf5/1.10.1 -Then when you compile Phantom ensure ``HDF5_DIR`` is set correctly:: +Then when you compile Phantom use ``HDF5_DIR`` for ``HDF5ROOT``: + +:: - make SYSTEM=ozstar HDF5=yes phantom setup + make SYSTEM=ozstar HDF5=yes HDF5ROOT=$HDF5_DIR phantom setup Note that you must have the HDF5 module loaded when running phantom, phantomsetup, etc. So make sure to put ``module load hdf5/1.10.1`` in @@ -153,7 +163,7 @@ then you would compile ``phantom2hdf5`` as follows :: - make SETUP=dustydisc MAXP=10000000 HDF5=yes phantom2hdf5 + make SETUP=dustydisc MAXP=10000000 HDF5=yes HDF5ROOT=$HDF5_DIR phantom2hdf5 Recall that you will need to set ``HDF5_DIR`` appropriately for your system. diff --git a/docs/setups-best.rst b/docs/setups-best.rst index b0c156665..baea8090f 100644 --- a/docs/setups-best.rst +++ b/docs/setups-best.rst @@ -13,7 +13,7 @@ +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | binary | binary stars | self-gravity | `setup_binary.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| wind | wind setup with dust nucleation | | `setup_wind.f90 `__ | +| wind | wind setup with dust nucleation | | `setup_wind.F90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | jet | Jet simulation from Price, Tricco & Bate (2012) | MHD, self-gravity, isothermal, periodic | `setup_sphereinbox.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ diff --git a/docs/setups-list.rst b/docs/setups-list.rst index 18f054c35..d4c24f099 100644 --- a/docs/setups-list.rst +++ b/docs/setups-list.rst @@ -89,11 +89,11 @@ +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | hierarchical | hierarchical system setup | | `setup_hierarchical.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| ismwind | wind setup with dust nucleation and ISM cooling | H2 Chemistry | `setup_wind.f90 `__ | +| ismwind | wind setup with dust nucleation and ISM cooling | H2 Chemistry | `setup_wind.F90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | isosgdisc | isothermal self-gravitating disc | self-gravity, disc viscosity, isothermal | `setup_disc.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| isowind | isothermal spherical wind | isothermal | `setup_wind.f90 `__ | +| isowind | isothermal spherical wind | isothermal | `setup_wind.F90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | jadvect | MHD current loop advection problem | MHD, periodic | `setup_jadvect.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ @@ -129,13 +129,15 @@ +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | orstang | Orszag-Tang vortex | MHD, periodic | `setup_orstang.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +| photoevap | Mark Hutchison photoevaporating disc | disc viscosity | `setup_photoevap.f90 `__ | ++------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | planetatm | disc interaction with fixed planet orbit + atmosphere | isothermal | `setup_disc.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | planetdisc | planet disc interaction with fixed planet orbit | isothermal | `setup_planetdisc.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | polytrope | single or binary polytrope test | self-gravity, isothermal | `setup_star.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| prtest | simple test of Poynting-Robertson drag | isothermal | `setup_prtest.f90 `__ | +| prtest | simple test of prdrag | | `setup_prtest.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | quebec | Terry Tricco | self-gravity | `setup_quebec.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ @@ -147,7 +149,7 @@ +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | radstar | setup a star as in the star setup but with radiation | self-gravity, radiation | `setup_star.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| radwind | wind setup with dust nucleation | | `setup_wind.f90 `__ | +| radwind | wind setup with dust nucleation | | `setup_wind.F90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | sedov | Sedov blast wave test | periodic | `setup_sedov.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ @@ -155,8 +157,6 @@ +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | shock | shock tube tests | periodic | `setup_shock.F90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| solarsystem | orbits of minor planets | dust, isothermal | `setup_solarsystem.f90 `__ | -+------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | sphereinbox | sphere-in-box setup | periodic | `setup_sphereinbox.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | srblast | special relativistic blast wave test (spherical) | GR, minkowski, periodic | `setup_srblast.f90 `__ | @@ -209,6 +209,6 @@ +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ | wddisc | disc around a white dwarf | dust, isothermal | `setup_wddisc.f90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| wind | wind setup with dust nucleation | | `setup_wind.f90 `__ | +| wind | wind setup with dust nucleation | | `setup_wind.F90 `__ | +------------------+---------------------------------------------------------------+----------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ diff --git a/docs/staging.rst b/docs/staging.rst index d88828121..bbc11c099 100644 --- a/docs/staging.rst +++ b/docs/staging.rst @@ -3,14 +3,13 @@ Creating a stable release of the code Procedure is: -- set the version number in phantom/build/Makefile -- set the version number in phantom/docs/conf.py -- update the :doc:`release notes ` -- use git to tag the code version for the release:: -``` -git tag 'v2055.0.1' -``` -- push the tag and let the github actions do the rest:: -``` -git push -v tags -``` +- set the version number in phantom/build/Makefile +- update the :doc:`release notes ` +- select a gitsha that passes the nightly tests +- merge this to the ‘staging’ branch +- create pull request for merge to ‘stable’ + +The merge to stable can be approved only by developers with special +permission. Nobody has direct write permission to the stable branch, you +*must* issue a pull request from staging. The merge will only be allowed +if the pipeline test is passing diff --git a/docs/testing.rst b/docs/testing.rst index 68659c4e6..9e4d3f0e0 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -1,40 +1,31 @@ -Getting your code to pass the github actions -============================================ +Making sure your changes are safe to commit +=========================================== -On every pull request a sequence of continuous integration tests -are performed to check that code is safe to merge into master. -The scripts in the .github/workflows directory are as follows: +There are two automated checking procedures that you can use to make +sure that changes you are about to commit do not break the code. These +are both run nightly anyway (and will email you the results), but here +is how to make sure that your changes do not break the code for others. -- |build|_: checks that phantom, phantomsetup, phantomanalysis and phantommoddump compile with every possible SETUP= flag -- |test|_: runs the test suite [see below] -- |mpi|_: runs the test suite with MPI [see below] -- |mcfost|_: compiles and links phantom+mcfost +Running the test suite +~~~~~~~~~~~~~~~~~~~~~~ -.. |build| image:: https://github.com/danieljprice/phantom/actions/workflows/build.yml/badge.svg -.. _build: https://github.com/danieljprice/phantom/actions/workflows/build.yml +You can run the whole test suite using: -.. |test| image:: https://github.com/danieljprice/phantom/actions/workflows/test.yml/badge.svg -.. _test: https://github.com/danieljprice/phantom/actions/workflows/test.yml - -.. |mpi| image:: https://github.com/danieljprice/phantom/actions/workflows/mpi.yml/badge.svg -.. _mpi: https://github.com/danieljprice/phantom/actions/workflows/mpi.yml - -.. |mcfost| image:: https://github.com/danieljprice/phantom/actions/workflows/mcfost.yml/badge.svg -.. _mcfost: https://github.com/danieljprice/phantom/actions/workflows/mcfost.yml - -Running the test suite on your own machine -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can run the test suite using:: +:: make test -This is just a shortcut for the following sequence of commands:: +This is just a shortcut for the following sequence of commands: + +:: make SETUP=test phantomtest ./bin/phantomtest -You can run the complete testsuite yourself using the testbot wrapper script:: +The test suite is also run nightly to check for regressions. You can run +the complete nightly test yourself using the testbot wrapper script: + +:: cd phantom/scripts ./testbot.sh @@ -43,7 +34,9 @@ Running selected parts of the test suite ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can run just part of the test suite by giving an additional argument -as follows:: +as follows: + +:: make SETUP=test phantomtest && ./bin/phantomtest derivs @@ -105,76 +98,23 @@ A non-exhaustive list of possible arguments are as follows: The buildbot ~~~~~~~~~~~~ -The buildbot also runs in an action and checks that the code compiles in all of +The buildbot runs nightly and checks that the code compiles in all of the possible SETUP configurations in the Makefile. You can run this -offline as follows:: - - cd phantom/scripts - ./buildbot.sh - -If you want to check only those SETUPS that were failing in the actions, -edit the buildbot.sh script and override the allsetups= line, e.g:: - - allsetups='disc star' - -Common reasons for failure -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We enforce the following policies in merging to the master branch: - -1. Code must compile and run with and without DEBUG=yes -2. Code must compile with ability to change the precision of reals to real*4 (this is enforced in SETUP=blob) -3. Code must compile with no warnings when compiled with gfortran (enforced with NOWARN=yes which adds the -Werror flag) -4. Testsuite must work with and without MPI, i.e. compile with MPI=yes - -How to reproduce the github build environment offline -====================================================== -Just occasionally it is hard to reproduce a failure in the actions. It *is* -possible to recreate the github actions environment offline, using a Docker container. -I suggest to do this *only* as a last resort. The recommended steps are as follows: - -Running the actions locally -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1. Install `Docker `_ -2. Install `act `_ -3. run the pull_request workflow +yourself as follows: :: - act pull_request - -Checking the phantom build that is failing manually -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If you just want to check things manually but in the same environment -as used in the actions, try the following:: - -1. Install [Docker](https://docs.docker.com/desktop/install/mac-install/) -2. Install Docker command line tools - -:: - - brew install docker + cd phantom/scripts + ./buildbot.sh -3. Install the ubuntu-latest image in Docker, e.g. by typing in a terminal [around 6.5Gb download] +Because some of the setups are compiled with large static arrays which +may exceed the memory limits of your local machine, you can optionally +check only those setups that have idim less than some value, e.g.: :: - docker pull nektos/act-environments-ubuntu:18.04 - -4. Run the image, and proceed to run phantom build checks manually - -:: + cd phantom/scripts + ./buildbot.sh 1000000 - git clone https://github.com/danieljprice/phantom - mkdir -p runs/mydisc - cd runs/mydisc - ~/phantom/scripts/writemake.sh disc > Makefile - export DEBUG=yes - export PHANTOM_DIR=~/phantom - make - make setup - make analysis - make moddump - ./phantomsetup disc - ./phantomsetup disc - ./phantomsetup disc - ./phantom disc +which checks only SETUPs with idim set to 1 million particles or less in +the dim file. diff --git a/scripts/HEADER-module b/scripts/HEADER-module index e6f5a8618..5f72a072c 100644 --- a/scripts/HEADER-module +++ b/scripts/HEADER-module @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-THISYEAR The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! ! :MODULE: [generated automatically] ! diff --git a/scripts/HEADER-program b/scripts/HEADER-program index 59d916bd4..fef7841e9 100644 --- a/scripts/HEADER-program +++ b/scripts/HEADER-program @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-THISYEAR The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! ! PROGRAM: [generated automatically] ! diff --git a/scripts/buildbot.sh b/scripts/buildbot.sh index 74ce14c8a..beb1bd68c 100755 --- a/scripts/buildbot.sh +++ b/scripts/buildbot.sh @@ -167,7 +167,7 @@ check_phantomsetup () myfail=0; setup=$1; if [ -e ./bin/phantomsetup ]; then - print_result "phantomsetup exists" $pass; + print_result "exists" $pass; else print_result "FAIL: phantomsetup does not exist" $fail; myfail=$(( myfail + 1 )); @@ -178,9 +178,6 @@ check_phantomsetup () mkdir $dirname; cd /tmp/$dirname; cp $phantomdir/bin/phantomsetup .; - # - # run ./phantomsetup prefix, answering any questions with "Enter" - # myinput="\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; prefix="myrun"; echo -e "$myinput" > myinput.txt; @@ -192,9 +189,6 @@ check_phantomsetup () print_result "FAIL: requires input other than 'Enter'" $fail; myfail=$(( myfail + 1 )); fi - # - # run phantomsetup up to 3 times to successfully create/rewrite the .setup file - # ./phantomsetup $prefix < myinput.txt > /dev/null; ./phantomsetup $prefix < myinput.txt > /dev/null; if [ -e "$prefix.setup" ]; then @@ -202,42 +196,8 @@ check_phantomsetup () else print_result "no .setup file" $warn; fi - infile="${prefix}.in" - if [ -e "$infile" ]; then + if [ -e "$prefix.in" ]; then print_result "creates .in file" $pass; - # - # if creating the .in file succeeds, try to run phantom - # on the .in file with nmax=0 - # - if [ -e $phantomdir/bin/phantom ]; then - print_result "phantom exists" $pass; - cp $phantomdir/bin/phantom .; - # - # set nmax=0 in the .in file - # - sed 's/nmax = .*/nmax = 0/g' ${infile} > ${infile}.bak - mv ${infile}.bak ${infile} - # - # run phantom on the .in file - # - ./phantom $infile > /dev/null; err=$?; - if [ $err -eq 0 ]; then - print_result "./phantom $infile runs ok" $pass; - dumpfile="${prefix}_00000" - if [ -s $dumpfile ]; then - print_result "${dumpfile} successfully created" $pass; - else - print_result "FAIL: did not create ${dumpfile}" $fail; - myfail=$(( myfail + 1 )); - fi - else - print_result "FAIL: ./phantom $infile fails with error" $fail; - myfail=$(( myfail + 1 )); - fi - else - print_result "FAIL: phantom does not exist" $fail; - myfail=$(( myfail + 1 )); - fi else print_result "FAILED to create .in file after 3 attempts" $fail; myfail=$(( myfail + 1 )); @@ -440,9 +400,6 @@ for setup in $listofsetups; do echo "$htext" >> $htmlfile; fi if [ "X$target" == "Xsetup" ] && [ "X$component" == "Xsetup" ]; then - # also build phantom main binary - echo "compiling phantom with SETUP=$setup" - make SETUP=$setup $nolibs $mynowarn $maxp $mydebug 1>> $makeout 2>> $errorlog; err=$?; check_phantomsetup $setup; elif [ "X$target" == "Xanalysis" ] && [ "X$component" == "Xanalysis" ]; then check_phantomanalysis $setup; diff --git a/src/lib/NICIL/src/nicil.F90 b/src/lib/NICIL/src/nicil.F90 index cefc345ff..ccb4e706d 100644 --- a/src/lib/NICIL/src/nicil.F90 +++ b/src/lib/NICIL/src/nicil.F90 @@ -1239,7 +1239,6 @@ pure subroutine nicil_update_nimhd(icall,eta_ohm,eta_hall,eta_ambi,Bfield,rho,T, else nden_electronR = nicil_ionR_get_ne(nden_save(1:iire)) ! in this case, need to calculate electron density from ions n_g_tot = 0. ! to prevent compiler warnings - zeta = 0. ! prevent compiler warnings endif !--Sum the ion populations from thermal and cosmic ray ionisation @@ -1295,7 +1294,6 @@ pure subroutine nicil_update_nimhd(icall,eta_ohm,eta_hall,eta_ambi,Bfield,rho,T, else !--Return constant coefficient version and exit call nicil_nimhd_get_eta_cnst(eta_ohm,eta_hall,eta_ambi,Bfield,rho) - if (present(data_out)) data_out = 0. endif if (present(itry)) itry = itry_n0 @@ -2290,14 +2288,9 @@ end subroutine nicil_get_dt_nimhd pure subroutine nicil_get_halldrift(eta_hall,Bx,By,Bz,jcurrent,vdrift) real, intent(in) :: eta_hall,Bx,By,Bz,jcurrent(3) real, intent(out) :: vdrift(3) - real :: B1,B2 + real :: B1 - B2 = Bx*Bx + By*By + Bz*Bz - if (B2 > 0.) then - B1 = 1.0/sqrt(B2) - else - B1 = 0. - endif + B1 = 1.0/sqrt(Bx*Bx + By*By + Bz*Bz) vdrift = -eta_hall*jcurrent*B1 end subroutine nicil_get_halldrift @@ -2309,14 +2302,9 @@ end subroutine nicil_get_halldrift pure subroutine nicil_get_ambidrift(eta_ambi,Bx,By,Bz,jcurrent,vdrift) real, intent(in) :: eta_ambi,Bx,By,Bz,jcurrent(3) real, intent(out) :: vdrift(3) - real :: B2,B21 + real :: B21 - B2 = Bx*Bx + By*By + Bz*Bz - if (B2 > 0.) then - B21 = 1.0/B2 - else - B21 = 0. - endif + B21 = 1.0/(Bx*Bx + By*By + Bz*Bz) vdrift(1) = eta_ambi*( jcurrent(2)*Bz - jcurrent(3)*By )*B21 vdrift(2) = eta_ambi*( jcurrent(3)*Bx - jcurrent(1)*Bz )*B21 vdrift(3) = eta_ambi*( jcurrent(1)*By - jcurrent(2)*Bx )*B21 diff --git a/src/main/bondiexact.f90 b/src/main/bondiexact.f90 index 992ff21a7..7254d93d5 100644 --- a/src/main/bondiexact.f90 +++ b/src/main/bondiexact.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module bondiexact ! diff --git a/src/main/bondiexact_gr.f90 b/src/main/bondiexact_gr.f90 index ddc693e3c..f2ed8b459 100644 --- a/src/main/bondiexact_gr.f90 +++ b/src/main/bondiexact_gr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module bondiexact ! diff --git a/src/main/boundary.f90 b/src/main/boundary.f90 index 4ecb9fcaa..349cec742 100644 --- a/src/main/boundary.f90 +++ b/src/main/boundary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module boundary ! diff --git a/src/main/boundary_dynamic.f90 b/src/main/boundary_dynamic.f90 index 22e0303d8..7bf1b7a27 100644 --- a/src/main/boundary_dynamic.f90 +++ b/src/main/boundary_dynamic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module boundary_dyn ! @@ -360,7 +360,7 @@ subroutine find_dynamic_boundaries(npart,nptmass,dtmax,xyz_n_all,xyz_x_all,ierr) ! add uninteresting particles to the averages if (.not.bdy_is_interesting) then n_bkg = n_bkg + 1 - v_bkg = v_bkg + vxyzu(1:3,i) + v_bkg = v_bkg + vxyzu(:,i) if (mhd) B_bkg = B_bkg + Bevol(:,i)*rhoi endif endif diff --git a/src/main/centreofmass.f90 b/src/main/centreofmass.f90 index a638095de..2b224bab3 100644 --- a/src/main/centreofmass.f90 +++ b/src/main/centreofmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module centreofmass ! diff --git a/src/main/checkconserved.f90 b/src/main/checkconserved.f90 index c42381bbe..5591532bb 100644 --- a/src/main/checkconserved.f90 +++ b/src/main/checkconserved.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module checkconserved ! @@ -39,7 +39,7 @@ subroutine init_conservation_checks(should_conserve_energy,should_conserve_momen should_conserve_angmom,should_conserve_dustmass) use options, only:icooling,ieos,ipdv_heating,ishock_heating,& iresistive_heating,use_dustfrac,iexternalforce - use dim, only:mhd,maxvxyzu,periodic,inject_parts + use dim, only:mhd,maxvxyzu,periodic,particles_are_injected use part, only:iboundary,npartoftype use boundary_dyn,only:dynamic_bdy logical, intent(out) :: should_conserve_energy,should_conserve_momentum @@ -73,7 +73,7 @@ subroutine init_conservation_checks(should_conserve_energy,should_conserve_momen ! ! Each injection routine will need to bookeep conserved quantities, but until then... ! - if (inject_parts .or. dynamic_bdy) then + if (particles_are_injected .or. dynamic_bdy) then should_conserve_energy = .false. should_conserve_momentum = .false. should_conserve_angmom = .false. diff --git a/src/main/checkoptions.F90 b/src/main/checkoptions.F90 index 18073c2b3..be131470c 100644 --- a/src/main/checkoptions.F90 +++ b/src/main/checkoptions.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module checkoptions ! @@ -14,7 +14,7 @@ module checkoptions ! ! :Runtime parameters: None ! -! :Dependencies: dim, io, metric_tools, mpiutils, part +! :Dependencies: dim, io, metric_tools, part ! implicit none public :: check_compile_time_settings @@ -30,10 +30,9 @@ module checkoptions ! !------------------------------------------------------------------- subroutine check_compile_time_settings(ierr) - use part, only:mhd,gravity,ngradh,h2chemistry,maxvxyzu,use_dust,gr - use dim, only:use_dustgrowth,maxtypes,mpi,inject_parts - use io, only:error,id,master,fatal,warning - use mpiutils, only:barrier_mpi + use part, only:mhd,gravity,ngradh,h2chemistry,maxvxyzu,use_dust,gr + use dim, only:use_dustgrowth,maxtypes + use io, only:error,id,master,fatal,warning #ifdef GR use metric_tools, only:icoordinate,icoord_cartesian use dim, only:maxsts @@ -143,16 +142,10 @@ subroutine check_compile_time_settings(ierr) #endif #ifdef DUSTGROWTH - if (.not. use_dustgrowth) then - call error(string,'-DDUSTGROWTH but use_dustgrowth = .false.') - ierr = 16 - endif + if (.not. use_dustgrowth) call error(string,'-DDUSTGROWTH but use_dustgrowth = .false.') #endif - if (mpi .and. inject_parts) call error(string,'MPI currently not compatible with particle injection') - - call barrier_mpi - + return end subroutine check_compile_time_settings end module checkoptions diff --git a/src/main/checksetup.F90 b/src/main/checksetup.F90 index 6251c415b..fb8b187a7 100644 --- a/src/main/checksetup.F90 +++ b/src/main/checksetup.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module checksetup ! @@ -16,7 +16,7 @@ module checksetup ! ! :Dependencies: boundary, boundary_dyn, centreofmass, dim, dust, eos, ! externalforces, io, metric_tools, nicil, options, part, physcon, -! ptmass_radiation, sortutils, timestep, units, utils_gr +! sortutils, timestep, units, utils_gr ! implicit none public :: check_setup @@ -38,7 +38,7 @@ module checksetup !------------------------------------------------------------------ subroutine check_setup(nerror,nwarn,restart) use dim, only:maxp,maxvxyzu,periodic,use_dust,ndim,mhd,use_dustgrowth, & - do_radiation,n_nden_phantom,mhd_nonideal,do_nucleation,use_krome + do_radiation,n_nden_phantom,mhd_nonideal,do_nucleation use part, only:xyzh,massoftype,hfact,vxyzu,npart,npartoftype,nptmass,gravity, & iphase,maxphase,isetphase,labeltype,igas,h2chemistry,maxtypes,& idust,xyzmh_ptmass,vxyz_ptmass,iboundary,isdeadh,ll,ideadhead,& @@ -90,6 +90,12 @@ subroutine check_setup(nerror,nwarn,restart) print*,'ERROR: sum of npartoftype /= npart: np=',npart,' but sum=',sum(npartoftype) nerror = nerror + 1 endif +#ifndef KROME + if (gamma <= 0.) then + print*,'WARNING! gamma not set (should be set > 0 even if not used)' + nwarn = nwarn + 1 + endif +#endif if (hfact < 1. .or. isnan(hfact)) then print*,'ERROR: hfact = ',hfact,', should be >= 1' nerror = nerror + 1 @@ -98,21 +104,17 @@ subroutine check_setup(nerror,nwarn,restart) print*,'ERROR: polyk = ',polyk,', should be >= 0' nerror = nerror + 1 endif - if (use_krome) then - if (ieos /= 19) then - print*, 'KROME setup. Only eos=19 makes sense.' - nerror = nerror + 1 - endif - else - if (polyk < tiny(0.) .and. ieos /= 2) then - print*,'WARNING! polyk = ',polyk,' in setup, speed of sound will be zero in equation of state' - nwarn = nwarn + 1 - endif - if (gamma <= 0.) then - print*,'WARNING! gamma not set (should be set > 0 even if not used)' - nwarn = nwarn + 1 - endif +#ifdef KROME + if (ieos /= 19) then + print*, 'KROME setup. Only eos=19 makes sense.' + nerror = nerror + 1 + endif +#else + if (polyk < tiny(0.) .and. ieos /= 2) then + print*,'WARNING! polyk = ',polyk,' in setup, speed of sound will be zero in equation of state' + nwarn = nwarn + 1 endif +#endif if (npart < 0) then print*,'ERROR: npart = ',npart,', should be >= 0' nerror = nerror + 1 @@ -293,8 +295,7 @@ subroutine check_setup(nerror,nwarn,restart) ! warn about external force settings ! if (iexternalforce==iext_star .and. nptmass==0) then - if (id==master) print "(a,/,a)",'WARNING: iexternalforce=1 does not conserve momentum:',& - ' use a sink particle at r=0 if you care about this' + print*,'WARNING: iexternalforce=1 does not conserve momentum - use a sink particle at r=0 if you care about this' nwarn = nwarn + 1 endif ! @@ -332,15 +333,15 @@ subroutine check_setup(nerror,nwarn,restart) if (gravity .or. nptmass > 0) then if (.not.G_is_unity()) then if (gravity) then - if (id==master) print*,'ERROR: self-gravity ON but G /= 1 in code units, got G=',get_G_code() + print*,'ERROR: self-gravity ON but G /= 1 in code units, got G=',get_G_code() elseif (nptmass > 0) then - if (id==master) print*,'ERROR: sink particles used but G /= 1 in code units, got G=',get_G_code() + print*,'ERROR: sink particles used but G /= 1 in code units, got G=',get_G_code() endif nerror = nerror + 1 endif endif if (.not. gr .and. (gravity .or. mhd) .and. ien_type == ien_etotal) then - if (id==master) print*,'Cannot use total energy with self gravity or mhd' + print*,'Cannot use total energy with self gravity or mhd' nerror = nerror + 1 endif ! @@ -348,12 +349,12 @@ subroutine check_setup(nerror,nwarn,restart) ! if (mhd) then if (all(abs(Bxyz(:,1:npart)) < tiny(0.))) then - if (id==master) print*,'WARNING: MHD is ON but magnetic field is zero everywhere' + print*,'WARNING: MHD is ON but magnetic field is zero everywhere' nwarn = nwarn + 1 endif if (mhd_nonideal) then if (n_nden /= n_nden_phantom) then - if (id==master) print*,'ERROR: n_nden in nicil.f90 needs to match n_nden_phantom in config.F90; n_nden = ',n_nden + print*,'ERROR: n_nden in nicil.f90 needs to match n_nden_phantom in config.F90; n_nden = ',n_nden nerror = nerror + 1 endif endif @@ -404,7 +405,7 @@ subroutine check_setup(nerror,nwarn,restart) ! !--check radiation setup ! - if (do_radiation) call check_setup_radiation(npart,nerror,nwarn,radprop,rad) + if (do_radiation) call check_setup_radiation(npart,nerror,radprop,rad) ! !--check dust growth arrays ! @@ -511,8 +512,7 @@ end function in_range !------------------------------------------------------------------ subroutine check_setup_ptmass(nerror,nwarn,hmin) use dim, only:maxptmass - use part, only:nptmass,xyzmh_ptmass,ihacc,ihsoft,gr,iTeff,sinks_have_luminosity,ilum - use ptmass_radiation, only:isink_radiation + use part, only:nptmass,xyzmh_ptmass,ihacc,ihsoft,gr,iTeff,sinks_have_luminosity integer, intent(inout) :: nerror,nwarn real, intent(in) :: hmin integer :: i,j,n @@ -589,11 +589,6 @@ subroutine check_setup_ptmass(nerror,nwarn,hmin) ! ! check that radiation properties are sensible ! - if (isink_radiation > 1 .and. xyzmh_ptmass(ilum,1) < 1e-10) then - nerror = nerror + 1 - print*,'ERROR: isink_radiation > 1 and sink particle has no luminosity' - return - endif if (sinks_have_luminosity(nptmass,xyzmh_ptmass)) then if (any(xyzmh_ptmass(iTeff,1:nptmass) < 100.)) then print*,'WARNING: sink particle temperature less than 100K' @@ -609,7 +604,7 @@ end subroutine check_setup_ptmass !+ !------------------------------------------------------------------ subroutine check_setup_growth(npart,nerror) - use part, only:dustprop,dustprop_label,iamdust,iphase,maxphase,maxp + use part, only:dustprop,dustprop_label integer, intent(in) :: npart integer, intent(inout) :: nerror integer :: i,j,nbad(4) @@ -618,16 +613,12 @@ subroutine check_setup_growth(npart,nerror) !-- Check that all the parameters are > 0 when needed do i=1,npart do j=1,2 - if (maxphase==maxp) then - if (iamdust(iphase(i)) .and. dustprop(j,i) <= 0.) nbad(j) = nbad(j) + 1 - elseif (dustprop(j,i) < 0.) then - nbad(j) = nbad(j) + 1 - endif + if (dustprop(j,i) < 0.) nbad(j) = nbad(j) + 1 enddo enddo do j=1,2 if (nbad(j) > 0) then - print*,'ERROR: dustgrowth: ',nbad(j),' of ',npart,' particles with '//trim(dustprop_label(j))//' <= 0' + print*,'ERROR: ',nbad(j),' of ',npart,' particles with '//trim(dustprop_label(j))//' < 0' nerror = nerror + 1 endif enddo @@ -715,13 +706,13 @@ subroutine check_setup_dustgrid(nerror,nwarn) nerror = nerror + 1 endif enddo - do i=1,ndusttypes - if (grainsize(i) > 10.*km/udist) then - print*,'WARNING: grainsize is HUGE (>10km) in dust bin ',i,': s = ',grainsize(i)*udist/km,' km' - nwarn = nwarn + 1 - endif - enddo endif + do i=1,ndusttypes + if (grainsize(i) > 10.*km/udist) then + print*,'WARNING: grainsize is HUGE (>10km) in dust bin ',i,': s = ',grainsize(i)*udist/km,' km' + nwarn = nwarn + 1 + endif + enddo end subroutine check_setup_dustgrid @@ -907,57 +898,46 @@ end subroutine check_for_identical_positions !------------------------------------------------------------------ !+ -! 1) check for optically thin particles when mcfost is disabled, -! as the particles will then be overlooked if they are flagged as thin -! 2) check that radiation energy is never negative to begin with -! 3) check for NaNs +! 1) check for optically thin particles when mcfost is disabled, +! as the particles will then be overlooked if they are flagged as thin +! 2) check that radiation energy is never negative to begin with +! 3) check for NaNs !+ !------------------------------------------------------------------ -subroutine check_setup_radiation(npart,nerror,nwarn,radprop,rad) +subroutine check_setup_radiation(npart, nerror, radprop, rad) use part, only:ithick, iradxi, ikappa integer, intent(in) :: npart - integer, intent(inout) :: nerror,nwarn + integer, intent(inout) :: nerror real, intent(in) :: rad(:,:), radprop(:,:) - integer :: i,nthin,nradEn,nkappa,nwarn_en + integer :: i, nthin, nradEn, nkappa nthin = 0 nradEn = 0 nkappa = 0 - nwarn_en = 0 - do i=1,npart - if (radprop(ithick, i) < 0.5) nthin = nthin + 1 - if (rad(iradxi, i) < 0.) nradEn = nradEn + 1 - if (radprop(ikappa, i) <= 0.0 .or. isnan(radprop(ikappa,i))) nkappa = nkappa + 1 - if (rad(iradxi, i) <= 0.) nwarn_en = nwarn_en + 1 + do i=1, npart + if (radprop(ithick, i) < 0.5) nthin=nthin + 1 + if (rad(iradxi, i) < 0.) nradEn=nradEn + 1 + if (radprop(ikappa, i) <= 0.0 .or. isnan(radprop(ikappa,i))) nkappa=nkappa + 1 enddo if (nthin > 0) then - print "(/,a,i10,a,i10,a,/)",' ERROR in setup: ',nthin,' of ',npart,& + print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nthin,' of ',npart,& ' particles are being treated as optically thin without MCFOST being compiled' nerror = nerror + 1 endif if (nradEn > 0) then - print "(/,a,i10,a,i10,a,/)",' ERROR in setup: ',nradEn,' of ',npart,& - ' particles have negative radiation energy' + print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nradEn,' of ',npart,& + ' particles have negative radiation Energy' nerror = nerror + 1 endif - if (nwarn_en > 0) then - print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nwarn_en,' of ',npart,& - ' particles have radiation energy equal to zero' - nwarn = nwarn + 1 - endif - if (nkappa > 0) then - print "(/,a,i10,a,i10,a,/)",' ERROR in setup: ',nkappa,' of ',npart,& + print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nkappa,' of ',npart,& ' particles have opacity <= 0.0 or NaN' nerror = nerror + 1 endif - call check_NaN(npart,rad,'radiation_energy',nerror) - call check_NaN(npart,radprop,'radiation properties',nerror) - end subroutine check_setup_radiation end module checksetup diff --git a/src/main/config.F90 b/src/main/config.F90 index bb548a994..4c3e731e3 100644 --- a/src/main/config.F90 +++ b/src/main/config.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module dim ! @@ -22,6 +22,8 @@ module dim integer, parameter, public :: phantom_version_minor = PHANTOM_VERSION_MINOR integer, parameter, public :: phantom_version_micro = PHANTOM_VERSION_MICRO character(len=*), parameter, public :: phantom_version_string = PHANTOM_VERSION_STRING + character(len=80), parameter :: & ! module version + modid="$Id$" public @@ -314,9 +316,9 @@ module dim ! logical for bookkeeping !-------------------- #ifdef INJECT_PARTICLES - logical, parameter :: inject_parts = .true. + logical, parameter :: particles_are_injected = .true. #else - logical, parameter :: inject_parts = .false. + logical, parameter :: particles_are_injected = .false. #endif !-------------------- diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index fdfe891f3..128aa6d18 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cons2prim ! @@ -177,7 +177,8 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& iohm,ihall,nden_nimhd,eta_nimhd,iambi,get_partinfo,iphase,this_is_a_test,& ndustsmall,itemp,ikappa,idmu,idgamma,icv,igamma use part, only:nucleation,gamma_chem - use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,gamma + use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,gamma,& + utherm use radiation_utils, only:radiation_equation_of_state,get_opacity use dim, only:mhd,maxvxyzu,maxphase,maxp,use_dustgrowth,& do_radiation,nalpha,mhd_nonideal,do_nucleation,use_krome @@ -267,7 +268,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& endif if (use_krome) gammai = gamma_chem(i) if (maxvxyzu >= 4) then - uui = vxyzu(4,i) + uui = utherm(vxyzu(:,i),rhogas,gammai) if (uui < 0.) call warning('cons2prim','Internal energy < 0',i,'u',uui) call equationofstate(ieos,p_on_rhogas,spsound,rhogas,xi,yi,zi,temperaturei,eni=uui,& gamma_local=gammai,mu_local=mui,Xlocal=X_i,Zlocal=Z_i) @@ -323,10 +324,6 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& ! if (mhd_nonideal) then Bi = sqrt(Bxi*Bxi + Byi*Byi + Bzi*Bzi) - ! sanity check the temperature - if (temperaturei < 1.) call warning('cons2prim',& - 'T < 1K in non-ideal MHD library',i,'T',temperaturei) - call nicil_update_nimhd(0,eta_nimhd(iohm,i),eta_nimhd(ihall,i),eta_nimhd(iambi,i), & Bi,rhoi,temperaturei,nden_nimhd(:,i),ierrlist) endif diff --git a/src/main/cons2primsolver.f90 b/src/main/cons2primsolver.f90 index 6d29e0727..b7e5232a1 100644 --- a/src/main/cons2primsolver.f90 +++ b/src/main/cons2primsolver.f90 @@ -2,17 +2,13 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cons2primsolver ! -! Internal routines containing the GR conservative to -! primitive variable solver, as described in section 7 -! of Liptai & Price (2019) +! None ! -! :References: -! Liptai & Price (2019), MNRAS 485, 819 -! Tejeda (2012), PhD thesis, IAS Trieste +! :References: None ! ! :Owner: David Liptai ! diff --git a/src/main/cooling.f90 b/src/main/cooling.F90 similarity index 99% rename from src/main/cooling.f90 rename to src/main/cooling.F90 index 5b21e84ad..5e4bf835c 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling ! diff --git a/src/main/cooling_functions.f90 b/src/main/cooling_functions.f90 index 04ff47305..8f6523b37 100644 --- a/src/main/cooling_functions.f90 +++ b/src/main/cooling_functions.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_functions ! diff --git a/src/main/cooling_gammie.f90 b/src/main/cooling_gammie.f90 index 6b44a079e..aec346728 100644 --- a/src/main/cooling_gammie.f90 +++ b/src/main/cooling_gammie.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_gammie ! diff --git a/src/main/cooling_gammie_PL.f90 b/src/main/cooling_gammie_PL.f90 index 0262a0787..1846c678b 100644 --- a/src/main/cooling_gammie_PL.f90 +++ b/src/main/cooling_gammie_PL.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_gammie_PL ! diff --git a/src/main/cooling_ism.f90 b/src/main/cooling_ism.f90 index 3b1b2313b..fec966326 100644 --- a/src/main/cooling_ism.f90 +++ b/src/main/cooling_ism.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_ism ! diff --git a/src/main/cooling_koyamainutsuka.f90 b/src/main/cooling_koyamainutsuka.f90 index 71fb2196e..e344455a2 100644 --- a/src/main/cooling_koyamainutsuka.f90 +++ b/src/main/cooling_koyamainutsuka.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_koyamainutsuka ! diff --git a/src/main/cooling_molecular.f90 b/src/main/cooling_molecular.f90 index 798408f18..6ff20bfb6 100644 --- a/src/main/cooling_molecular.f90 +++ b/src/main/cooling_molecular.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_molecular ! diff --git a/src/main/cooling_solver.f90 b/src/main/cooling_solver.f90 index c578d474a..d97aae90b 100644 --- a/src/main/cooling_solver.f90 +++ b/src/main/cooling_solver.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_solver ! diff --git a/src/main/cullendehnen.f90 b/src/main/cullendehnen.f90 index 37dbbeac7..f1161e670 100644 --- a/src/main/cullendehnen.f90 +++ b/src/main/cullendehnen.f90 @@ -2,15 +2,13 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cullendehnen ! -! Utility routines for the Cullen & Dehnen shock detection switch +! cullendehnen ! -! :References: -! Cullen & Dehnen (2010), MNRAS 408, 669 -! Price et al. (2018), PASA 35, e031 +! :References: None ! ! :Owner: Elisabeth Borchert ! @@ -28,6 +26,7 @@ module cullendehnen !+ !------------------------------------------------------------------------------- pure real function get_alphaloc(divvdti,spsoundi,hi,xi_limiter,alphamin,alphamax) + !use kernel, only:radkern real, intent(in) :: divvdti,spsoundi,hi,xi_limiter,alphamin,alphamax real :: source real :: temp @@ -63,7 +62,7 @@ pure real function xi_limiter(dvdx) fac = max(-divv,0.)**2 traceS = curlvx**2 + curlvy**2 + curlvz**2 - if (fac + traceS > epsilon(0.)) then + if (fac + traceS > 0.) then xi_limiter = fac/(fac + traceS) else xi_limiter = 1. diff --git a/src/main/damping.f90 b/src/main/damping.f90 index 055a367a0..2064ef262 100644 --- a/src/main/damping.f90 +++ b/src/main/damping.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module damping ! diff --git a/src/main/datafiles.f90 b/src/main/datafiles.f90 index 3fedf3827..171fefd41 100644 --- a/src/main/datafiles.f90 +++ b/src/main/datafiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module datafiles ! diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 6ef38a06f..71f4ba968 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module densityforce ! @@ -27,6 +27,8 @@ module densityforce use timing, only:getused,printused,print_time implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" public :: densityiterate,get_neighbour_stats @@ -889,6 +891,7 @@ pure subroutine calculate_rmatrix_from_sums(rhosum,denom,rmatrix,idone) rmatrix(6) = rxxi*ryyi - rxyi*rxyi ! zz idone = .true. + return end subroutine calculate_rmatrix_from_sums !---------------------------------------------------------------- @@ -923,7 +926,7 @@ pure subroutine calculate_divcurlv_from_sums(rhosum,termnorm,divcurlvi,ndivcurlv !--time derivative of div v, needed for Cullen-Dehnen switch if (nalpha >= 2) then !--Divvdt For switch - if (use_exact_linear .and. abs(denom) > tiny(denom)) then + if (use_exact_linear) then ddenom = 1./denom call exactlinear(gradaxdx,gradaxdy,gradaxdz,rhosum(idaxdxi),rhosum(idaxdyi),rhosum(idaxdzi),rmatrix,ddenom) call exactlinear(gradaydx,gradaydy,gradaydz,rhosum(idaydxi),rhosum(idaydyi),rhosum(idaydzi),rmatrix,ddenom) diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 7fcd13155..269ad7220 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module deriv ! @@ -16,10 +16,12 @@ module deriv ! ! :Dependencies: cons2prim, densityforce, derivutils, dim, externalforces, ! forces, forcing, growth, io, linklist, metric_tools, options, part, -! ptmass, ptmass_radiation, radiation_implicit, timestep, timestep_ind, -! timing +! photoevap, ptmass, ptmass_radiation, radiation_implicit, timestep, +! timestep_ind, timing ! implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" public :: derivs, get_derivs_global real, private :: stressmax @@ -38,7 +40,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& Bevol,dBevol,rad,drad,radprop,dustprop,ddustprop,& dustevol,ddustevol,dustfrac,eos_vars,time,dt,dtnew,pxyzu,dens,metrics) use dim, only:maxvxyzu,mhd,fast_divcurlB,gr,periodic,do_radiation,& - sink_radiation,use_dustgrowth,ind_timesteps + sink_radiation,use_dustgrowth use io, only:iprint,fatal,error use linklist, only:set_linklist use densityforce, only:densityiterate @@ -46,10 +48,18 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use externalforces, only:externalforce use part, only:dustgasprop,dvdx,Bxyz,set_boundaries_to_active,& nptmass,xyzmh_ptmass,sinks_have_heating,dust_temp,VrelVf,fxyz_drag +#ifdef IND_TIMESTEPS use timestep_ind, only:nbinmax - use timestep, only:dtmax,dtcourant,dtforce,dtrad +#else + use timestep, only:dtcourant,dtforce,dtrad +#endif + use timestep, only:dtmax #ifdef DRIVING use forcing, only:forceit +#endif +#ifdef PHOTO + use photoevap, only:find_ionfront,photo_ionize + use part, only:massoftype #endif use growth, only:get_growth_rate use ptmass_radiation, only:get_dust_temperature @@ -121,6 +131,16 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& call do_timing('link',tlast,tcpulast,start=.true.) +#ifdef PHOTO + ! + ! update location of particles on grid and calculate the location of the ionization front + ! + call find_ionfront(time,npart,xyzh,massoftype(igas)) + ! + ! update the temperatures of the particles depending on whether ionized or not + ! + call photo_ionize(vxyzu,npart) +#endif ! ! calculate density by direct summation ! @@ -151,7 +171,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& if (do_radiation .and. implicit_radiation .and. dt > 0.) then call do_radiation_implicit(dt,npart,rad,xyzh,vxyzu,radprop,drad,ierr) if (ierr /= 0 .and. ierr /= ierr_failed_to_converge) call fatal('radiation','Failed in radiation') - call do_timing('radiation',tlast,tcpulast) endif ! @@ -191,11 +210,11 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! ! set new timestep from Courant/forces condition ! - if (ind_timesteps) then - dtnew = dtmax/2.**nbinmax ! minimum timestep over all particles - else - dtnew = min(dtforce,dtcourant,dtrad,dtmax) - endif +#ifdef IND_TIMESTEPS + dtnew = dtmax/2**nbinmax ! minimum timestep over all particles +#else + dtnew = min(dtforce,dtcourant,dtrad,dtmax) +#endif call do_timing('total',t1,tcpu1,lunit=iprint) diff --git a/src/main/dtype_kdtree.F90 b/src/main/dtype_kdtree.F90 index 88b1303d6..f97d5ac95 100644 --- a/src/main/dtype_kdtree.F90 +++ b/src/main/dtype_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module dtypekdtree ! diff --git a/src/main/dust.f90 b/src/main/dust.F90 similarity index 99% rename from src/main/dust.f90 rename to src/main/dust.F90 index 4c61da088..b79e140f3 100644 --- a/src/main/dust.f90 +++ b/src/main/dust.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module dust ! @@ -409,7 +409,7 @@ subroutine read_options_dust(name,valstring,imatch,igotall,ierr) end select !--Check that we have just the *necessary* parameters - if (all(igot >= ineed)) igotall = .true. + if (all(ineed == igot)) igotall = .true. end subroutine read_options_dust diff --git a/src/main/dust_formation.f90 b/src/main/dust_formation.F90 similarity index 98% rename from src/main/dust_formation.f90 rename to src/main/dust_formation.F90 index 25fc703fc..cb55a2d4c 100644 --- a/src/main/dust_formation.f90 +++ b/src/main/dust_formation.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module dust_formation ! @@ -32,7 +32,7 @@ module dust_formation integer, public :: idust_opacity = 0 public :: set_abundances,evolve_dust,evolve_chem,calc_kappa_dust,& - calc_kappa_bowen,chemical_equilibrium_light,psat_C,calc_nucleation,& + calc_kappa_bowen,chemical_equilibrium_light,& read_options_dust_formation,write_options_dust_formation,& calc_Eddington_factor,calc_muGamma,init_muGamma,init_nucleation,& write_headeropts_dust_formation,read_headeropts_dust_formation @@ -41,7 +41,6 @@ module dust_formation ! real, public :: kappa_gas = 2.d-4 - real, public, parameter :: Scrit = 2. ! Critical saturation ratio private @@ -83,6 +82,7 @@ module dust_formation -4.38897d+05, -1.58111d+05, 2.49224d+01, 1.08714d-03, -5.62504d-08, & !TiO -3.32351d+05, -3.04694d+05, 5.86984d+01, 1.17096d-03, -5.06729d-08, & !TiO2 2.26786d+05, -1.43775d+05, 2.92429d+01, 1.69434d-04, -1.79867d-08], shape(coefs)) !C2 + real, parameter :: Scrit = 2. ! Critical saturation ratio real, parameter :: vfactor = sqrt(kboltz/(2.*pi*atomic_mass_unit*12.01)) !real, parameter :: vfactor = sqrt(kboltz/(8.*pi*atomic_mass_unit*12.01)) @@ -179,7 +179,7 @@ subroutine evolve_chem(dt, T, rho_cgs, JKmuS) S = pC/psat_C(T) if (S > Scrit) then !call nucleation(T, pC, pC2, 0., pC2H, pC2H2, S, JstarS, taustar, taugr) - call calc_nucleation(T, pC, 0., 0., 0., pC2H2, S, JstarS, taustar, taugr) + call nucleation(T, pC, 0., 0., 0., pC2H2, S, JstarS, taustar, taugr) JstarS = JstarS/ nH_tot call evol_K(JKmuS(idJstar), JKmuS(idK0:idK3), JstarS, taustar, taugr, dt, Jstar_new, K_new) else @@ -272,7 +272,7 @@ end function calc_Eddington_factor ! Compute nucleation rate ! !---------------------------- -subroutine calc_nucleation(T, pC, pC2, pC3, pC2H, pC2H2, S, JstarS, taustar, taugr) +subroutine nucleation(T, pC, pC2, pC3, pC2H, pC2H2, S, JstarS, taustar, taugr) ! all quantities are in cgs real, intent(in) :: T, pC, pC2, pC3, pC2H, pC2H2, S real, intent(out) :: JstarS, taustar, taugr @@ -320,7 +320,7 @@ subroutine calc_nucleation(T, pC, pC2, pC3, pC2H, pC2H2, S, JstarS, taustar, tau taustar = 1.d-30 endif taugr = kboltz*T/(A0*v1*(alpha1*pC*(1.-1./S) + 2.*alpha2/sqrt(2.)*(pC2+pC2H+pC2H2)*(1.-1./S**2))) -end subroutine calc_nucleation +end subroutine nucleation !------------------------------------ ! diff --git a/src/main/energies.F90 b/src/main/energies.F90 index aa83c46f0..558f8adba 100644 --- a/src/main/energies.F90 +++ b/src/main/energies.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module energies ! @@ -17,9 +17,9 @@ module energies ! :Runtime parameters: None ! ! :Dependencies: boundary_dyn, centreofmass, dim, dust, eos, eos_piecewise, -! externalforces, gravwaveutils, io, kernel, metric_tools, mpiutils, -! nicil, options, part, ptmass, timestep, units, utils_gr, vectorutils, -! viscosity +! externalforces, fastmath, gravwaveutils, io, kernel, metric_tools, +! mpiutils, nicil, options, part, ptmass, timestep, units, utils_gr, +! vectorutils, viscosity ! use dim, only:maxdusttypes,maxdustsmall use units, only:utime @@ -62,7 +62,7 @@ module energies !---------------------------------------------------------------- subroutine compute_energies(t) use dim, only:maxp,maxvxyzu,maxalpha,maxtypes,mhd_nonideal,maxp_hard,& - lightcurve,use_dust,maxdusttypes,do_radiation,gr,use_krome + lightcurve,use_dust,maxdusttypes,do_radiation,gr use part, only:rhoh,xyzh,vxyzu,massoftype,npart,maxphase,iphase,& alphaind,Bevol,divcurlB,iamtype,& igas,idust,iboundary,istar,idarkmatter,ibulge,& @@ -70,11 +70,11 @@ subroutine compute_energies(t) isdead_or_accreted,epot_sinksink,imacc,ispinx,ispiny,& ispinz,mhd,gravity,poten,dustfrac,eos_vars,itemp,igasP,ics,& nden_nimhd,eta_nimhd,iion,ndustsmall,graindens,grainsize,& - iamdust,ndusttypes,rad,iradxi,gamma_chem + iamdust,ndusttypes,rad,iradxi use part, only:pxyzu,fxyzu,fext use gravwaveutils, only:calculate_strain,calc_gravitwaves use centreofmass, only:get_centreofmass_accel - use eos, only:polyk,gamma,eos_is_non_ideal,eos_outputs_gasP + use eos, only:polyk,utherm,gamma,eos_is_non_ideal,eos_outputs_gasP use eos_piecewise, only:gamma_pwp use io, only:id,fatal,master use externalforces, only:externalforce,externalforce_vdependent,was_accreted,accradius1 @@ -83,14 +83,19 @@ subroutine compute_energies(t) use ptmass, only:get_accel_sink_gas use viscosity, only:irealvisc,shearfunc use nicil, only:nicil_update_nimhd,nicil_get_halldrift,nicil_get_ambidrift, & - use_ohm,use_hall,use_ambi,n_data_out,n_warn,eta_constant + use_ohm,use_hall,use_ambi,n_data_out,n_warn use boundary_dyn, only:dynamic_bdy,find_dynamic_boundaries use kernel, only:radkern use timestep, only:dtmax +#ifdef GR use part, only:metrics use metric_tools, only:unpack_metric use utils_gr, only:dot_product_gr,get_geodesic_accel use vectorutils, only:cross_product3D +#ifdef FINVSQRT + use fastmath, only:finvsqrt +#endif +#endif use part, only:luminosity use dust, only:get_ts,idrag real, intent(in) :: t @@ -108,8 +113,10 @@ subroutine compute_energies(t) real :: curlBi(3),vhalli(3),vioni(3),data_out(n_data_out) real :: erotxi,erotyi,erotzi,fdum(3),x0(3),v0(3),a0(3),xyz_x_all(3),xyz_n_all(3) real :: ethermi +#ifdef GR real :: pdotv,bigvi(1:3),alpha_gr,beta_gr_UP(1:3),lorentzi,pxi,pyi,pzi real :: gammaijdown(1:3,1:3),angi(1:3),fourvel_space(3) +#endif integer :: i,j,itype,iu integer :: ierrlist(n_warn) integer(kind=8) :: np,npgas,nptot,np_rho(maxtypes),np_rho_thread(maxtypes) @@ -167,14 +174,14 @@ subroutine compute_energies(t) !$omp shared(alphaind,massoftype,irealvisc,iu) & !$omp shared(ieos,gamma,nptmass,xyzmh_ptmass,vxyz_ptmass,xyzcom) & !$omp shared(Bevol,divcurlB,iphase,poten,dustfrac,use_dustfrac) & -!$omp shared(use_ohm,use_hall,use_ambi,nden_nimhd,eta_nimhd,eta_constant) & +!$omp shared(use_ohm,use_hall,use_ambi,nden_nimhd,eta_nimhd) & !$omp shared(ev_data,np_rho,erot_com,calc_erot,gas_only,track_mass) & -!$omp shared(calc_gravitwaves,gamma_chem) & +!$omp shared(calc_gravitwaves) & !$omp shared(iev_erad,iev_rho,iev_dt,iev_entrop,iev_rhop,iev_alpha) & !$omp shared(iev_B,iev_divB,iev_hdivB,iev_beta,iev_temp,iev_etao,iev_etah) & !$omp shared(iev_etaa,iev_vel,iev_vhall,iev_vion,iev_n) & !$omp shared(iev_dtg,iev_ts,iev_macc,iev_totlum,iev_erot,iev_viscrat) & -!$omp shared(eos_vars,grainsize,graindens,ndustsmall,metrics) & +!$omp shared(eos_vars,grainsize,graindens,ndustsmall) & !$omp private(i,j,xi,yi,zi,hi,rhoi,vxi,vyi,vzi,Bxi,Byi,Bzi,Bi,B2i,epoti,vsigi,v2i,vi1) & !$omp private(ponrhoi,spsoundi,spsound2i,va2cs2,rho1cs2,ethermi,dumx,dumy,dumz,valfven2i,divBi,hdivBonBi,curlBi) & !$omp private(rho1i,shearparam_art,shearparam_phys,ratio_phys_to_av,betai) & @@ -183,7 +190,10 @@ subroutine compute_energies(t) !$omp private(erotxi,erotyi,erotzi,fdum) & !$omp private(ev_data_thread,np_rho_thread) & !$omp firstprivate(alphai,itype,pmassi) & +#ifdef GR +!$omp shared(metrics) & !$omp private(pxi,pyi,pzi,gammaijdown,alpha_gr,beta_gr_UP,bigvi,lorentzi,pdotv,angi,fourvel_space) & +#endif !$omp shared(idrag) & !$omp private(tsi,iregime,idusttype) & !$omp shared(luminosity,track_lum) & @@ -237,53 +247,57 @@ subroutine compute_energies(t) vyi = vxyzu(2,i) vzi = vxyzu(3,i) - if (gr) then - pxi = pxyzu(1,i) - pyi = pxyzu(2,i) - pzi = pxyzu(3,i) - - ! linear momentum - xmom = xmom + pmassi*pxi - ymom = ymom + pmassi*pyi - zmom = zmom + pmassi*pzi - - call unpack_metric(metrics(:,:,:,i),betaUP=beta_gr_UP,alpha=alpha_gr,gammaijdown=gammaijdown) - bigvi = (vxyzu(1:3,i)+beta_gr_UP)/alpha_gr - v2i = dot_product_gr(bigvi,bigvi,gammaijdown) - lorentzi = 1./sqrt(1.-v2i) - pdotv = pxi*vxi + pyi*vyi + pzi*vzi - - ! angular momentum - fourvel_space = (lorentzi/alpha_gr)*vxyzu(1:3,i) - call cross_product3D(xyzh(1:3,i),fourvel_space,angi) ! position cross with four-velocity - angx = angx + pmassi*angi(1) - angy = angy + pmassi*angi(2) - angz = angz + pmassi*angi(3) - - ! kinetic energy - ekin = ekin + pmassi*(pdotv + alpha_gr/lorentzi - 1.) ! The 'kinetic term' in total specific energy, minus rest mass - mtot = mtot + pmassi - else - ! centre of mass - xcom = xcom + pmassi*xi - ycom = ycom + pmassi*yi - zcom = zcom + pmassi*zi - mtot = mtot + pmassi - - ! linear momentum - xmom = xmom + pmassi*vxi - ymom = ymom + pmassi*vyi - zmom = zmom + pmassi*vzi - - ! angular momentum - angx = angx + pmassi*(yi*vzi - zi*vyi) - angy = angy + pmassi*(zi*vxi - xi*vzi) - angz = angz + pmassi*(xi*vyi - yi*vxi) - - ! kinetic energy & rms velocity - v2i = vxi*vxi + vyi*vyi + vzi*vzi - ekin = ekin + pmassi*v2i - endif +#ifdef GR + pxi = pxyzu(1,i) + pyi = pxyzu(2,i) + pzi = pxyzu(3,i) + + ! linear momentum + xmom = xmom + pmassi*pxi + ymom = ymom + pmassi*pyi + zmom = zmom + pmassi*pzi + + call unpack_metric(metrics(:,:,:,i),betaUP=beta_gr_UP,alpha=alpha_gr,gammaijdown=gammaijdown) + bigvi = (vxyzu(1:3,i)+beta_gr_UP)/alpha_gr + v2i = dot_product_gr(bigvi,bigvi,gammaijdown) +#ifdef FINVSQRT + lorentzi = finvsqrt(1.-v2i) +#else + lorentzi = 1./sqrt(1.-v2i) +#endif + pdotv = pxi*vxi + pyi*vyi + pzi*vzi + + ! angular momentum + fourvel_space = (lorentzi/alpha_gr)*vxyzu(1:3,i) + call cross_product3D(xyzh(1:3,i),fourvel_space,angi) ! position cross with four-velocity + angx = angx + pmassi*angi(1) + angy = angy + pmassi*angi(2) + angz = angz + pmassi*angi(3) + + ! kinetic energy + ekin = ekin + pmassi*(pdotv + alpha_gr/lorentzi - 1.) ! The 'kinetic term' in total specific energy, minus rest mass + mtot = mtot + pmassi +#else + ! centre of mass + xcom = xcom + pmassi*xi + ycom = ycom + pmassi*yi + zcom = zcom + pmassi*zi + mtot = mtot + pmassi + + ! linear momentum + xmom = xmom + pmassi*vxi + ymom = ymom + pmassi*vyi + zmom = zmom + pmassi*vzi + + ! angular momentum + angx = angx + pmassi*(yi*vzi - zi*vyi) + angy = angy + pmassi*(zi*vxi - xi*vzi) + angz = angz + pmassi*(xi*vyi - yi*vxi) + + ! kinetic energy & rms velocity + v2i = vxi*vxi + vyi*vyi + vzi*vzi + ekin = ekin + pmassi*v2i +#endif vrms = vrms + v2i @@ -354,9 +368,10 @@ subroutine compute_energies(t) ponrhoi = eos_vars(igasP,i)/rhoi spsoundi = eos_vars(ics,i) if (maxvxyzu >= 4) then - ethermi = pmassi*vxyzu(4,i)*gasfrac - if (gr) ethermi = (alpha_gr/lorentzi)*ethermi - + ethermi = pmassi*utherm(vxyzu(:,i),rhoi,gamma)*gasfrac +#ifdef GR + ethermi = (alpha_gr/lorentzi)*ethermi +#endif etherm = etherm + ethermi if (vxyzu(iu,i) < tiny(vxyzu(iu,i))) np_e_eq_0 = np_e_eq_0 + 1 @@ -374,11 +389,11 @@ subroutine compute_energies(t) vsigi = spsoundi ! entropy - if (use_krome) then - call ev_data_update(ev_data_thread,iev_entrop,pmassi*ponrhoi*rhoi**(1.-gamma_chem(i))) - else - call ev_data_update(ev_data_thread,iev_entrop,pmassi*ponrhoi*rhoi**(1.-gamma)) - endif +#ifdef KROME + call ev_data_update(ev_data_thread,iev_entrop,pmassi*ponrhoi*rhoi**(1.-gamma_chem(i))) +#else + call ev_data_update(ev_data_thread,iev_entrop,pmassi*ponrhoi*rhoi**(1.-gamma)) +#endif ! gas temperature if (eos_is_non_ideal(ieos) .or. eos_outputs_gasP(ieos)) then @@ -463,26 +478,24 @@ subroutine compute_energies(t) call ev_data_update(ev_data_thread,iev_vel, sqrt(v2i) ) call ev_data_update(ev_data_thread,iev_vion, vion ) endif - if (.not.eta_constant) then - n_ion = 0 - do j = 9,21 - n_ion = n_ion + data_out(j) - enddo - n_total = data_out(5) - if (n_total > 0.) then - n_total1 = 1.0/n_total - else - n_total1 = 0.0 ! only possible if eta_constant = .true. - endif - eta_nimhd(iion,i) = n_ion*n_total1 ! Save ionisation fraction for the dump file - call ev_data_update(ev_data_thread,iev_n(1),n_ion*n_total1) - call ev_data_update(ev_data_thread,iev_n(2),data_out( 8)*n_total1) - call ev_data_update(ev_data_thread,iev_n(3),data_out( 8)) - call ev_data_update(ev_data_thread,iev_n(4),n_total-n_ion) - call ev_data_update(ev_data_thread,iev_n(5),data_out(24)) - call ev_data_update(ev_data_thread,iev_n(6),data_out(23)) - call ev_data_update(ev_data_thread,iev_n(7),data_out(22)) + n_ion = 0 + do j = 9,21 + n_ion = n_ion + data_out(j) + enddo + n_total = data_out(5) + if (n_total > 0.) then + n_total1 = 1.0/n_total + else + n_total1 = 0.0 ! only possible if eta_constant = .true. endif + eta_nimhd(iion,i) = n_ion*n_total1 ! Save ionisation fraction for the dump file + call ev_data_update(ev_data_thread,iev_n(1),n_ion*n_total1) + call ev_data_update(ev_data_thread,iev_n(2),data_out( 8)*n_total1) + call ev_data_update(ev_data_thread,iev_n(3),data_out( 8)) + call ev_data_update(ev_data_thread,iev_n(4),n_total-n_ion) + call ev_data_update(ev_data_thread,iev_n(5),data_out(24)) + call ev_data_update(ev_data_thread,iev_n(6),data_out(23)) + call ev_data_update(ev_data_thread,iev_n(7),data_out(22)) endif endif endif isgas @@ -707,20 +720,20 @@ subroutine compute_energies(t) if (calc_gravitwaves) then pmassi = massoftype(igas) x0 = 0.; v0 = 0.; a0 = 0. ! use the origin by default - if (gr) then - !call get_geodesic_accel(axyz,npart,vxyzu(1:3,:),metrics,metricderivs) - !call calculate_strain(hx,hp,pmassi,x0,v0,a0,npart,xyzh,vxyzu,axyz) - call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& - fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) - else - if (iexternalforce==0) then ! if no external forces, use centre of mass of particles - x0 = (/xcom,ycom,zcom/) - v0 = (/xmom,ymom,zmom/) - call get_centreofmass_accel(a0,npart,xyzh,fxyzu,fext,nptmass,xyzmh_ptmass,fxyz_ptmass) - endif - call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& - fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) +#ifdef GR + !call get_geodesic_accel(axyz,npart,vxyzu(1:3,:),metrics,metricderivs) + !call calculate_strain(hx,hp,pmassi,x0,v0,a0,npart,xyzh,vxyzu,axyz) + call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& + fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) +#else + if (iexternalforce==0) then ! if no external forces, use centre of mass of particles + x0 = (/xcom,ycom,zcom/) + v0 = (/xmom,ymom,zmom/) + call get_centreofmass_accel(a0,npart,xyzh,fxyzu,fext,nptmass,xyzmh_ptmass,fxyz_ptmass) endif + call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& + fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) +#endif ev_data(iev_sum,iev_gws(1)) = hx(1) ev_data(iev_sum,iev_gws(2)) = hp(1) ev_data(iev_sum,iev_gws(3)) = hx(2) @@ -751,6 +764,7 @@ subroutine compute_energies(t) if (ierr==1) call fatal('energies','there is no high density gas for the dynamic boundaries') endif + return end subroutine compute_energies !---------------------------------------------------------------- !+ diff --git a/src/main/eos.f90 b/src/main/eos.F90 similarity index 96% rename from src/main/eos.f90 rename to src/main/eos.F90 index 3f03ef488..e74bf5e26 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos ! @@ -54,7 +54,7 @@ module eos logical, public :: extract_eos_from_hdr = .false. integer, public :: isink = 0. - public :: equationofstate,setpolyk,eosinfo,get_mean_molecular_weight + public :: equationofstate,setpolyk,eosinfo,utherm,en_from_utherm,get_mean_molecular_weight public :: get_TempPresCs,get_spsound,get_temperature,get_pressure,get_cv public :: eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP public :: get_local_u_internal @@ -752,6 +752,63 @@ real function get_u_from_rhoT(rho,temp,eos_type,uguess) result(u) end function get_u_from_rhoT + +!----------------------------------------------------------------------- +!+ +! the following two functions transparently handle evolution +! of the entropy instead of the thermal energy +!+ +!----------------------------------------------------------------------- +real function utherm(vxyzui,rho,gammai) + real, intent(in) :: vxyzui(4),rho,gammai + real :: gamm1,en + + en = vxyzui(4) + if (gr) then + utherm = en + elseif (ien_type == ien_entropy) then + gamm1 = (gammai - 1.) + if (gamm1 > tiny(gamm1)) then + utherm = (en/gamm1)*rho**gamm1 + else + stop 'gamma=1 using entropy evolution' + endif + elseif (ien_type == ien_etotal) then + utherm = en - 0.5*dot_product(vxyzui(1:3),vxyzui(1:3)) + else + utherm = en + endif + +end function utherm + +!----------------------------------------------------------------------- +!+ +! function to transparently handle evolution of the entropy +! instead of the thermal energy +!+ +!----------------------------------------------------------------------- +real function en_from_utherm(vxyzui,rho,gammai) + real, intent(in) :: vxyzui(4),rho,gammai + real :: gamm1,utherm + + utherm = vxyzui(4) + if (gr) then + en_from_utherm = utherm + elseif (ien_type == ien_entropy) then + gamm1 = gammai - 1. + if (gamm1 > tiny(gamm1)) then + en_from_utherm = gamm1*utherm*rho**(1.-gamma) + else + stop 'gamma=1 using entropy evolution' + endif + elseif (ien_type == ien_etotal) then + en_from_utherm = utherm + 0.5*dot_product(vxyzui(1:3),vxyzui(1:3)) + else + en_from_utherm = utherm + endif + +end function en_from_utherm + !----------------------------------------------------------------------- !+ ! Get recombination energy (per unit mass) assumming complete @@ -1355,7 +1412,6 @@ end subroutine read_headeropts_eos !+ !----------------------------------------------------------------------- subroutine write_options_eos(iunit) - use dim, only:use_krome use infile_utils, only:write_inopt use eos_helmholtz, only:eos_helmholtz_write_inopt use eos_barotropic, only:write_options_eos_barotropic @@ -1365,11 +1421,9 @@ subroutine write_options_eos(iunit) write(iunit,"(/,a)") '# options controlling equation of state' call write_inopt(ieos,'ieos','eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)',iunit) - - if (.not.use_krome .or. .not.eos_outputs_mu(ieos)) then - call write_inopt(gmw,'mu','mean molecular weight',iunit) - endif - +#ifndef KROME + if (.not. eos_outputs_mu(ieos)) call write_inopt(gmw,'mu','mean molecular weight',iunit) +#endif select case(ieos) case(8) call write_options_eos_barotropic(iunit) diff --git a/src/main/eos_barotropic.f90 b/src/main/eos_barotropic.f90 index d42385e38..549150e9b 100644 --- a/src/main/eos_barotropic.f90 +++ b/src/main/eos_barotropic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_barotropic ! diff --git a/src/main/eos_gasradrec.f90 b/src/main/eos_gasradrec.f90 index 09e743e0f..6487e492a 100644 --- a/src/main/eos_gasradrec.f90 +++ b/src/main/eos_gasradrec.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_gasradrec ! diff --git a/src/main/eos_helmholtz.f90 b/src/main/eos_helmholtz.f90 index de34545bf..2b6c57ae9 100644 --- a/src/main/eos_helmholtz.f90 +++ b/src/main/eos_helmholtz.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_helmholtz ! diff --git a/src/main/eos_idealplusrad.f90 b/src/main/eos_idealplusrad.f90 index 5fbe0b0ff..35d48c973 100644 --- a/src/main/eos_idealplusrad.f90 +++ b/src/main/eos_idealplusrad.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_idealplusrad ! diff --git a/src/main/eos_mesa.f90 b/src/main/eos_mesa.f90 index 54fc7c700..43ddb121c 100644 --- a/src/main/eos_mesa.f90 +++ b/src/main/eos_mesa.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_mesa ! diff --git a/src/main/eos_mesa_microphysics.f90 b/src/main/eos_mesa_microphysics.f90 index 958e4158a..db9c016d0 100644 --- a/src/main/eos_mesa_microphysics.f90 +++ b/src/main/eos_mesa_microphysics.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mesa_microphysics ! diff --git a/src/main/eos_piecewise.f90 b/src/main/eos_piecewise.f90 index 78c087b04..ddc4a57c1 100644 --- a/src/main/eos_piecewise.f90 +++ b/src/main/eos_piecewise.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_piecewise ! diff --git a/src/main/eos_shen.f90 b/src/main/eos_shen.f90 index 8212addb1..17e8976ed 100644 --- a/src/main/eos_shen.f90 +++ b/src/main/eos_shen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_shen ! diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index b78bff0e4..dcf4ca520 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -23,7 +23,7 @@ module eos_stamatellos character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file !integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in - public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep,finish_S07cool + public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep contains subroutine init_S07cool() diff --git a/src/main/eos_stratified.f90 b/src/main/eos_stratified.f90 index 5c106e750..2e3d5faee 100644 --- a/src/main/eos_stratified.f90 +++ b/src/main/eos_stratified.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module eos_stratified ! diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index bf6e6b5e7..5ab58bf4b 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module evolve ! @@ -30,7 +30,7 @@ module evolve contains -subroutine evol(infile,logfile,evfile,dumpfile,flag) +subroutine evol(infile,logfile,evfile,dumpfile) use io, only:iprint,iwritein,id,master,iverbose,& flush_warnings,nprocs,fatal,warning use timestep, only:time,tmax,dt,dtmax,nmax,nout,nsteps,dtextforce,rhomaxnow,& @@ -62,8 +62,8 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) #else use timestep, only:dtforce,dtcourant,dterr,print_dtlog #endif - use timestep_sts, only:use_sts - use supertimestep, only:step_sts + use timestep_sts, only: use_sts + use supertimestep, only: step_sts #ifdef DRIVING use forcing, only:write_forcingdump #endif @@ -105,7 +105,6 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use mf_write, only:binpos_write #endif - integer, optional, intent(in) :: flag character(len=*), intent(in) :: infile character(len=*), intent(inout) :: logfile,evfile,dumpfile integer :: i,noutput,noutput_dtmax,nsteplast,ncount_fulldumps @@ -166,7 +165,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use_global_dt = .false. istepfrac = 0 tlast = tzero - dt = dtmax/2.**nbinmax ! use 2.0 here to allow for step too small + dt = dtmax/2**nbinmax nmovedtot = 0 tall = 0. tcheck = time @@ -218,19 +217,15 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) ! ! injection of new particles into simulation ! - if (.not. present(flag)) then - npart_old=npart - call inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,npart,npartoftype,dtinject) - call update_injected_particles(npart_old,npart,istepfrac,nbinmax,time,dtmax,dt,dtinject) - endif + npart_old=npart + call inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,npart,npartoftype,dtinject) + call update_injected_particles(npart_old,npart,istepfrac,nbinmax,time,dtmax,dt,dtinject) #endif dtmaxold = dtmax #ifdef IND_TIMESTEPS istepfrac = istepfrac + 1 nbinmaxprev = nbinmax - if (nbinmax > maxbins) call fatal('evolve','timestep too small: try decreasing dtmax?') - !--determine if dt needs to be decreased; if so, then this will be done ! in step the next time it is called; ! for global timestepping, this is called in the block where at_dump_time==.true. diff --git a/src/main/evwrite.f90 b/src/main/evwrite.F90 similarity index 96% rename from src/main/evwrite.f90 rename to src/main/evwrite.F90 index 61ff46cb1..e5420c4e8 100644 --- a/src/main/evwrite.f90 +++ b/src/main/evwrite.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module evwrite ! @@ -37,7 +37,7 @@ module evwrite ! ! :Runtime parameters: None ! -! :Dependencies: boundary, boundary_dyn, dim, energies, eos, +! :Dependencies: boundary, boundary_dyn, dim, energies, eos, extern_binary, ! externalforces, fileutils, gravwaveutils, io, mpiutils, nicil, options, ! part, ptmass, timestep, units, viscosity ! @@ -247,7 +247,7 @@ subroutine init_evfile(iunit,evfile,open_file) endif end subroutine init_evfile - +! !---------------------------------------------------------------- !+ ! creates up to three lables per input value, and fills the required @@ -300,7 +300,7 @@ subroutine fill_ev_tag(ev_fmt,itag,label,cmd,i,j) endif enddo enddo - + ! end subroutine fill_ev_tag !---------------------------------------------------------------- !+ @@ -350,9 +350,11 @@ end subroutine fill_ev_header subroutine write_evfile(t,dt) use energies, only:compute_energies,ev_data_update use io, only:id,master,ievfile +#ifndef GR use timestep, only:dtmax_user use options, only:iexternalforce - use externalforces,only:accretedmass1,accretedmass2 + use extern_binary, only:accretedmass1,accretedmass2 +#endif real, intent(in) :: t,dt integer :: i,j real :: ev_data_out(ielements) @@ -362,12 +364,14 @@ subroutine write_evfile(t,dt) if (id==master) then !--fill in additional details that are not calculated in energies.f +#ifndef GR ev_data(iev_sum,iev_dt) = dt ev_data(iev_sum,iev_dtx) = dtmax_user if (iexternalforce==iext_binary) then ev_data(iev_sum,iev_maccsink(1)) = accretedmass1 ev_data(iev_sum,iev_maccsink(2)) = accretedmass2 endif +#endif ! Fill in the data_out array j = 1 do i = 1,iquantities @@ -401,6 +405,7 @@ subroutine write_evfile(t,dt) call flush(ievfile) endif + return end subroutine write_evfile !---------------------------------------------------------------- !+ @@ -411,7 +416,7 @@ end subroutine write_evfile !---------------------------------------------------------------- subroutine write_evlog(iprint) use dim, only:maxp,maxalpha,mhd,maxvxyzu,periodic,mhd_nonideal,& - use_dust,maxdusttypes,do_radiation,inject_parts + use_dust,maxdusttypes,do_radiation,particles_are_injected use energies, only:ekin,etherm,emag,epot,etot,rmsmach,vrms,accretedmass,mdust,mgas,xyzcom use energies, only:erad use part, only:nptmass,ndusttypes @@ -425,7 +430,7 @@ subroutine write_evlog(iprint) character(len=120) :: string,Mdust_label(maxdusttypes) integer :: i - if (ndead > 0 .or. nptmass > 0 .or. icreate_sinks > 0 .or. inject_parts .or. iverbose > 0) then + if (ndead > 0 .or. nptmass > 0 .or. icreate_sinks > 0 .or. particles_are_injected .or. iverbose > 0) then write(iprint,"(1x,4(a,I10))") 'npart=',npartall,', n_alive=',npartall-ndead, & ', n_dead_or_accreted=',ndead,', nptmass=',nptmass endif @@ -445,10 +450,8 @@ subroutine write_evlog(iprint) endif write(iprint,"(1x,3(a,es10.3))") "Centre of Mass = ",xyzcom(1),", ",xyzcom(2),", ",xyzcom(3) - if (ev_data(iev_max,iev_rho) > 0.) then ! avoid floating point exception if no gas particles - write(iprint,"(1x,a,'(max)=',es10.3,' (mean)=',es10.3,' (max)=',es10.3,a)") & + write(iprint,"(1x,a,'(max)=',es10.3,' (mean)=',es10.3,' (max)=',es10.3,a)") & 'density ',ev_data(iev_max,iev_rho),ev_data(iev_ave,iev_rho),ev_data(iev_max,iev_rho)*unit_density,' g/cm^3' - endif if (use_dustfrac) then write(iprint,"(1x,a,'(max)=',es10.3,1x,'(mean)=',es10.3,1x,'(min)=',es10.3)") & @@ -468,11 +471,11 @@ subroutine write_evlog(iprint) string = '' if (maxalpha==maxp) then - if (ev_data(iev_max,iev_alpha) > 0.) write(string,"(a,'(max)=',es10.3)") ' alpha',ev_data(iev_max,iev_alpha) + write(string,"(a,'(max)=',es10.3)") ' alpha',ev_data(iev_max,iev_alpha) endif if (len_trim(string) > 0) write(iprint,"(a)") trim(string) - if (irealvisc /= 0 .and. npartall > 0) then + if (irealvisc /= 0) then if (periodic) then if (irealvisc==1) then write(iprint,"(1x,1(a,'=',es10.3,', '),(a,'=',es10.3))") & @@ -481,8 +484,9 @@ subroutine write_evlog(iprint) endif write(iprint,"(1x,1(a,'(max)=',es10.3,', '),('(mean)=',es10.3),(' (min)=',es10.3))") & 'Ratio of physical-to-art. visc',ev_data(iev_max,iev_viscrat),ev_data(iev_min,iev_viscrat) - elseif (npartall > 0) then - write(iprint,"(1x,1(a,'=',es10.3))") 'RMS Mach #',rmsmach + else + write(iprint,"(1x,1(a,'=',es10.3))") & + 'RMS Mach #',rmsmach endif if (mhd) then @@ -495,6 +499,7 @@ subroutine write_evlog(iprint) endif write(iprint,"(/)") + return end subroutine write_evlog - +!---------------------------------------------------------------- end module evwrite diff --git a/src/main/extern_Bfield.f90 b/src/main/extern_Bfield.f90 index 8ced5e325..12e354518 100644 --- a/src/main/extern_Bfield.f90 +++ b/src/main/extern_Bfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_Bfield ! diff --git a/src/main/extern_binary.f90 b/src/main/extern_binary.f90 index e26cbf168..4a708c607 100644 --- a/src/main/extern_binary.f90 +++ b/src/main/extern_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_binary ! diff --git a/src/main/extern_binary_gw.f90 b/src/main/extern_binary_gw.f90 index 93b6e1c07..764a31b6f 100644 --- a/src/main/extern_binary_gw.f90 +++ b/src/main/extern_binary_gw.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_binary ! diff --git a/src/main/extern_corotate.f90 b/src/main/extern_corotate.f90 index a96802926..a56b207ff 100644 --- a/src/main/extern_corotate.f90 +++ b/src/main/extern_corotate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_corotate ! diff --git a/src/main/extern_densprofile.f90 b/src/main/extern_densprofile.f90 index 9dd4cde27..8473714da 100644 --- a/src/main/extern_densprofile.f90 +++ b/src/main/extern_densprofile.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_densprofile ! diff --git a/src/main/extern_gnewton.f90 b/src/main/extern_gnewton.F90 similarity index 98% rename from src/main/extern_gnewton.f90 rename to src/main/extern_gnewton.F90 index af89ff741..c7bd46db4 100644 --- a/src/main/extern_gnewton.f90 +++ b/src/main/extern_gnewton.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_gnewton ! diff --git a/src/main/extern_gr.F90 b/src/main/extern_gr.F90 index a3b0ae350..048706ed4 100644 --- a/src/main/extern_gr.F90 +++ b/src/main/extern_gr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_gr ! diff --git a/src/main/extern_gwinspiral.f90 b/src/main/extern_gwinspiral.f90 index 6ef4a6012..94dfa3b16 100644 --- a/src/main/extern_gwinspiral.f90 +++ b/src/main/extern_gwinspiral.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_gwinspiral ! diff --git a/src/main/extern_lensethirring.f90 b/src/main/extern_lensethirring.f90 index c05bf54d0..372a08c8a 100644 --- a/src/main/extern_lensethirring.f90 +++ b/src/main/extern_lensethirring.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_lensethirring ! diff --git a/src/main/extern_prdrag.f90 b/src/main/extern_prdrag.F90 similarity index 99% rename from src/main/extern_prdrag.f90 rename to src/main/extern_prdrag.F90 index cccb8d924..9e067f170 100644 --- a/src/main/extern_prdrag.f90 +++ b/src/main/extern_prdrag.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_prdrag ! diff --git a/src/main/extern_spiral.f90 b/src/main/extern_spiral.f90 index cba734676..c26d9b78f 100644 --- a/src/main/extern_spiral.f90 +++ b/src/main/extern_spiral.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_spiral ! diff --git a/src/main/extern_staticsine.f90 b/src/main/extern_staticsine.f90 index e469b8fbb..92d267ab7 100644 --- a/src/main/extern_staticsine.f90 +++ b/src/main/extern_staticsine.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module extern_staticsine ! diff --git a/src/main/externalforces.f90 b/src/main/externalforces.F90 similarity index 99% rename from src/main/externalforces.f90 rename to src/main/externalforces.F90 index c05b30b64..04e023bfa 100644 --- a/src/main/externalforces.f90 +++ b/src/main/externalforces.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module externalforces ! @@ -23,14 +23,14 @@ module externalforces ! extern_lensethirring, extern_prdrag, extern_spiral, extern_staticsine, ! infile_utils, io, lumin_nsdisc, part, units ! - use extern_binary, only:accradius1,mass1,accretedmass1,accretedmass2 + use extern_binary, only:accradius1,mass1 use extern_corotate, only:omega_corotate ! so public from this module implicit none private public :: externalforce,externalforce_vdependent public :: accrete_particles,was_accreted - public :: accradius1,omega_corotate,accretedmass1,accretedmass2 + public :: accradius1,omega_corotate public :: write_options_externalforces,read_options_externalforces public :: initialise_externalforces,is_velocity_dependent public :: update_vdependent_extforce_leapfrog diff --git a/src/main/externalforces_gr.f90 b/src/main/externalforces_gr.F90 similarity index 98% rename from src/main/externalforces_gr.f90 rename to src/main/externalforces_gr.F90 index 1334ff2af..0a3e1b79a 100644 --- a/src/main/externalforces_gr.f90 +++ b/src/main/externalforces_gr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module externalforces ! @@ -39,8 +39,6 @@ module externalforces public :: mass1 ! exported from metric module real, public :: accradius1 = 0. real, public :: accradius1_hard = 0. - real, public :: accretedmass1 = 0. - real, public :: accretedmass2 = 0. logical, public :: extract_iextern_from_hdr = .false. diff --git a/src/main/fastmath.f90 b/src/main/fastmath.f90 index fec93b016..33520c4ec 100644 --- a/src/main/fastmath.f90 +++ b/src/main/fastmath.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module fastmath ! diff --git a/src/main/force.F90 b/src/main/force.F90 index 71cf6cb0b..9f36e992c 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module forces ! @@ -54,6 +54,8 @@ module forces use part, only:iradxi,ifluxx,ifluxy,ifluxz,ikappa,ien_type,ien_entropy,ien_etotal,ien_entropy_s implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" integer, parameter :: maxcellcache = 1000 @@ -900,7 +902,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use dim, only:maxalpha,maxp,mhd_nonideal,gravity,gr use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt - use eos, only:ieos,eos_is_non_ideal,gamma + use eos, only:ieos,eos_is_non_ideal,gamma,utherm use eos_stamatellos, only:gradP_cool,Gpot_cool #ifdef GRAVITY use kernel, only:kernel_softening @@ -910,10 +912,14 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use boundary, only:dxbound,dybound,dzbound #endif use dim, only:use_dust,use_dustgrowth,ind_timesteps +#ifdef DUST use dust, only:get_ts,idrag,icut_backreaction,ilimitdustflux,irecon,drag_implicit - use kernel, only:wkern_drag,cnormk_drag,wkern,cnormk + use kernel, only:wkern_drag,cnormk_drag use part, only:ndustsmall,grainsize,graindens +#ifdef DUSTGROWTH use kernel, only:wkern,cnormk +#endif +#endif #ifdef IND_TIMESTEPS use part, only:ibin_old,iamboundary use timestep_ind,only:get_dt @@ -921,7 +927,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use timestep, only:bignumber use options, only:overcleanfac,use_dustfrac,ireconav,icooling,limit_radiation_flux use units, only:get_c_code +#ifdef GR use metric_tools,only:imet_minkowski,imetric +#endif use utils_gr, only:get_bigv use radiation_utils, only:get_rad_R integer, intent(in) :: i @@ -984,11 +992,16 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g #ifdef KROME real :: gammaj #endif +#ifdef DUST integer :: iregime,idusttype,l real :: dragterm,dragheating,wdrag,dv2,tsijtmp real :: grkernav,tsj(maxdusttypes),dustfracterms(maxdusttypes),term real :: projvstar,projf_drag,epstsj,sdrag1,sdrag2!,rhogas1i + !real :: Dav(maxdusttypes),vsigeps,depsdissterm(maxdusttypes) +#ifdef DUSTGROWTH real :: winter +#endif +#endif real :: dBevolx,dBevoly,dBevolz,divBsymmterm,divBdiffterm real :: rho21i,rho21j,Bxi,Byi,Bzi,psii,pmjrho21grkerni,pmjrho21grkernj real :: auterm,avBterm,mrhoi5,vsigB @@ -1123,7 +1136,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g Bzi = 0.0 psii = 0.0 endif - if (use_dust .and. use_dustfrac) then + if (use_dustfrac) then +#ifdef DUST dustfraci(:) = xpartveci(idustfraci:idustfraciend) dustfracisum = sum(dustfraci(:)) if (ilimitdustflux) then @@ -1132,8 +1146,17 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g tsi(:) = xpartveci(itstop:itstopend) endif epstsi = sum(dustfraci(:)*tsi(:)) +!------------------------------------------------ +!--sqrt(rho*epsilon) method +! sqrtrhodustfraci(:) = sqrt(rhoi*dustfraci(:)) +!------------------------------------------------ !--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) sqrtrhodustfraci(:) = sqrt(dustfraci(:)/(1.-dustfraci(:))) +!------------------------------------------------ +!--asin(sqrt(epsilon)) method +! sqrtrhodustfraci(:) = asin(sqrt(dustfraci(:))) +!------------------------------------------------ +#endif else dustfraci(:) = 0. dustfracisum = 0. @@ -1310,9 +1333,11 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g ibin_wake(j) = max(ibinnow_m1,ibin_wake(j)) ibin_neighi = max(ibin_neighi,ibin_old(j)) endif - if (use_dust .and. drag_implicit) then +#ifdef DUST + if (drag_implicit) then dti = min(dti,get_dt(dt,ibin_old(j))) endif +#endif #endif endif pmassj = massoftype(iamtypej) @@ -1341,8 +1366,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g projv = dvx*runix + dvy*runiy + dvz*runiz if (iamgasj .and. maxvxyzu >= 4) then - enj = vxyzu(4,j) - if (eos_is_non_ideal(ieos)) then ! only do this if eos requires temperature in physical units + enj = utherm(vxyzu(:,j),rhoj,gamma) + if (eos_is_non_ideal(ieos)) then ! Is this condition required, or should this be always true? tempj = eos_vars(itemp,j) denij = 0.5*(eni/tempi + enj/tempj)*(tempi - tempj) ! dU = c_V * dT else @@ -1350,7 +1375,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif else denij = 0. - enj = 0. endif if (gr) then @@ -1428,8 +1452,16 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g dustfracj(:) = dustfrac(:,j) dustfracjsum = sum(dustfracj(:)) rhogasj = rhoj*(1. - dustfracjsum) - !--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) +!------------------------------------------------ +!--sqrt(rho*epsilon) method +! sqrtrhodustfracj(:) = sqrt(rhoj*dustfracj(:)) +!------------------------------------------------ +!--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) sqrtrhodustfracj(:) = sqrt(dustfracj(:)/(1.-dustfracj(:))) +!------------------------------------------------ +!--asin(sqrt(epsilon)) method +! sqrtrhodustfracj(:) = asin(sqrt(dustfracj(:))) +!------------------------------------------------ else dustfracj(:) = 0. dustfracjsum = 0. @@ -1439,6 +1471,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (maxalpha==maxp) alphaj = alphaind(1,j) + if (gr) densj = dens(j) prj = eos_vars(igasP,j) spsoundj = eos_vars(ics,j) radPj = 0. @@ -1475,6 +1508,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g !rhoj = 0. rho1j = 0. rho21j = 0. + densj = 0. mrhoj5 = 0. autermj = 0. @@ -1506,7 +1540,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g qrho2i = 0. qrho2j = 0. if (gr) then - densj = dens(j) enthi = 1.+eni+pri/densi enthj = 1.+enj+prj/densj endif @@ -1586,20 +1619,22 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif !--artificial thermal conductivity (need j term) if (maxvxyzu >= 4) then - if (gr) then - denij = alphagri*eni/lorentzi - alphagrj*enj/lorentzj - if (imetric==imet_minkowski) then ! Eq 60 in LP19 - rhoav1 = 2./(enthi*densi + enthj*densj) - vsigu = min(1.,sqrt(abs(pri-prj)*rhoav1)) - else - vsigu = abs(vij) ! Eq 61 in LP19 - endif - elseif (gravity) then +#ifdef GR + denij = alphagri*eni/lorentzi - alphagrj*enj/lorentzj + if (imetric==imet_minkowski) then ! Eq 60 in LP19 + rhoav1 = 2./(enthi*densi + enthj*densj) + vsigu = min(1.,sqrt(abs(pri-prj)*rhoav1)) + else + vsigu = abs(vij) ! Eq 61 in LP19 + endif +#else + if (gravity) then vsigu = abs(projv) else rhoav1 = 2./(rhoi + rhoj) vsigu = sqrt(abs(pri - prj)*rhoav1) endif +#endif dendissterm = vsigu*denij*(auterm*grkerni + autermj*grkernj) endif @@ -1749,7 +1784,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g radDi = c_code*radlambdai/radkappai/rhoi - ! TWO FIRST DERIVATIVES ! + ! TWO FIRST DERIVATES ! radDFWi = pmassj*radDi*grkerni*rho21i*& (radFi(1)*runix + radFi(2)*runiy + radFi(3)*runiz) @@ -1760,7 +1795,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g ! (rhoi*radeni-rhoj*radenj)*grkerni*rij1 endif - if (use_dust .and. use_dustfrac) then +#ifdef DUST + if (use_dustfrac) then tsj = 0. do l=1,ndustsmall ! get stopping time - for one fluid dust we do not know deltav, but it is small by definition @@ -1784,18 +1820,20 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g do l=1,ndustsmall if (dustfraci(l) > 0. .or. dustfracj(l) > 0.) then - ! define average of kernels + ! define averages of diffusion coefficient and kernels + !Dav(l) = dustfraci(l)*tsi(l) + dustfracj(l)*tsj(l) grkernav = 0.5*(grkerni + grkernj) - !--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) +!------------------------------------------------ +!--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) dustfracterms(l) = pmassj*sqrtrhodustfracj(l)*rho1j & *((tsi(l)-epstsi)*(1.-dustfraci(l))/(1.-dustfracisum) & +(tsj(l)-epstsj)*(1.-dustfracj(l))/(1.-dustfracjsum)) & *(pri - prj)*grkernav*rij1 fsum(iddustevoli+(l-1)) = fsum(iddustevoli+(l-1)) - dustfracterms(l) - - !--sqrt(rho*epsilon) method and sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) +!------------------------------------------------ +!--sqrt(rho*epsilon) method and sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) if (maxvxyzu >= 4) fsum(idudtdusti+(l-1)) = fsum(idudtdusti+(l-1)) - sqrtrhodustfraci(l)*dustfracterms(l)*denij endif ! Equation 270 in Phantom paper @@ -1807,6 +1845,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif enddo endif +#endif else !ifgas ! @@ -1816,11 +1855,11 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifyi) = fsum(ifyi) - fgrav*runiy fsum(ifzi) = fsum(ifzi) - fgrav*runiz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) - +#ifdef DUST ! ! gas-dust: compute drag terms ! - if (use_dust .and. idrag>0) then + if (idrag>0) then if (iamgasi .and. iamdustj .and. icut_backreaction==0) then projvstar = projv if (irecon >= 0) call reconstruct_dv(projv,dx,dy,dz,runix,runiy,runiz,dvdxi,dvdxj,projvstar,irecon) @@ -1877,6 +1916,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif if (use_dustgrowth) then call get_ts(idrag,1,grainsizei,graindensi,rhoj,rhoi,spsoundj,dv2,tsijtmp,iregime) +#ifdef DUSTGROWTH if (q2i < q2j) then winter = wkern(q2i,qi)*hi21*hi1*cnormk else @@ -1888,6 +1928,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idviy) = fsum(idviy) + pmassj*dvy*winter fsum(idviz) = fsum(idviz) + pmassj*dvz*winter fsum(icsi) = fsum(icsi) + pmassj*spsoundj*winter +#endif else !--the following works for large grains only (not hybrid large and small grains) idusttype = iamtypei - idust + 1 @@ -1916,6 +1957,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifdragzi) = fsum(ifdragzi) - dragterm*runiz endif endif +#endif endif ifgas !--self gravity contribution to total energy equation @@ -1971,6 +2013,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idudtdissi) = fsum(idudtdissi) + vxi*fgravxi + vyi*fgravyi + vzi*fgravzi endif + return end subroutine compute_forces !---------------------------------------------------------------- @@ -2075,6 +2118,7 @@ subroutine get_stress(pri,spsoundi,rhoi,rho1i,xi,yi,zi, & vwavei = spsoundi endif + return end subroutine get_stress !---------------------------------------------------------------- @@ -2092,10 +2136,11 @@ subroutine start_cell(cell,iphase,xyzh,vxyzu,gradh,divcurlv,divcurlB,dvdx,Bevol, use viscosity, only:irealvisc,bulkvisc use dust, only:get_ts,idrag use part, only:grainsize,graindens - use part, only:ibin_old + use part, only:ibin_old use timestep_ind, only:get_dt - use nicil, only:nimhd_get_jcbcb + use nicil, only:nimhd_get_jcbcb use radiation_utils, only:get_rad_R + use eos, only:utherm type(cellforce), intent(inout) :: cell integer(kind=1), intent(in) :: iphase(:) real, intent(in) :: xyzh(:,:) @@ -2174,9 +2219,10 @@ subroutine start_cell(cell,iphase,xyzh,vxyzu,gradh,divcurlv,divcurlB,dvdx,Bevol, if (iamgasi) then if (ndivcurlv >= 1) divcurlvi(:) = real(divcurlv(:,i),kind=kind(divcurlvi)) if (maxvxyzu >= 4) then - eni = vxyzu(4,i) + !eni = utherm(vxyzu(:,i),rhoi,gamma) + eni = vxyzu(4,i) else - eni = 0.0 + eni = 0.0 endif ! @@ -2513,6 +2559,9 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv rad,drad,radprop,dtrad) use io, only:fatal,warning +#ifdef FINVSQRT + use fastmath, only:finvsqrt +#endif use dim, only:mhd,mhd_nonideal,lightcurve,use_dust,maxdvdx,use_dustgrowth,gr,use_krome,& store_dust_temperature,do_nucleation use eos, only:gamma,ieos,iopacity_type @@ -2544,14 +2593,17 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use metric_tools, only:unpack_metric use utils_gr, only:get_u0 use io, only:error +#ifdef DUSTGROWTH use dust, only:idrag,get_ts use part, only:Omega_k +#endif use io, only:warning use physcon, only:c,kboltz #ifdef GR use part, only:pxyzu #endif use eos_stamatellos, only:Gpot_cool + integer, intent(in) :: icall type(cellforce), intent(inout) :: cell real, intent(inout) :: fxyzu(:,:) @@ -2585,8 +2637,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv integer, intent(inout) :: ndustres real, intent(inout) :: dustresfacmean,dustresfacmax real, intent(in) :: rad(:,:),radprop(:,:) - real, intent(out) :: drad(:,:) - real, intent(inout) :: dtrad + real, intent(out) :: drad(:,:),dtrad real :: c_code,dtradi,radlambdai,radkappai real :: xpartveci(maxxpartveciforce),fsum(maxfsum) real :: rhoi,rho1i,rhogasi,hi,hi1,pmassi,tempi @@ -2613,8 +2664,10 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv logical :: allow_decrease,dtcheck character(len=16) :: dtchar #endif +#ifdef DUSTGROWTH real :: tstopint,gsizei,gdensi integer :: ireg +#endif integer :: ip,i real :: densi, vxi,vyi,vzi,u0i,dudtcool,dudtheat real :: posi(3),veli(3),gcov(0:3,0:3),metrici(0:3,0:3,2) @@ -3021,7 +3074,8 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv endif else ! not gas - if (use_dustgrowth .and. iamdusti) then +#ifdef DUSTGROWTH + if (iamdusti) then !- return interpolations to their respective arrays dustgasprop(2,i) = fsum(idensgasi) !- rhogas !- interpolations are mass weigthed, divide result by rhog,i @@ -3036,6 +3090,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv dustgasprop(4,i)**2,tstopint,ireg) dustgasprop(3,i) = tstopint * Omega_k(i) !- Stokes number endif +#endif if (maxvxyzu > 4) fxyzu(4,i) = 0. ! timestep based on Courant condition for non-gas particles @@ -3051,7 +3106,11 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv ! timestep based on force condition if (abs(f2i) > epsilon(f2i)) then +#ifdef FINVSQRT + dtf = C_force*sqrt(hi*finvsqrt(f2i)) +#else dtf = C_force*sqrt(hi/sqrt(f2i)) +#endif endif ! one fluid dust timestep diff --git a/src/main/forcing.F90 b/src/main/forcing.F90 index 7b3a10e24..f9c3d98e8 100644 --- a/src/main/forcing.F90 +++ b/src/main/forcing.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module forcing ! @@ -963,7 +963,9 @@ subroutine forceit(t,npart,xyzh,vxyzu,fxyzu) real, intent(out) :: fxyzu(:,:) logical :: update_accel = .true. -! real :: tinfile +#ifdef STIR_FROM_FILE + real :: tinfile +#endif logical, parameter :: Debug = .false. !!=================================================================== @@ -975,25 +977,25 @@ subroutine forceit(t,npart,xyzh,vxyzu,fxyzu) if (t > (tprev + st_dtfreq)) then tprev = st_dtfreq*int(t/st_dtfreq) ! round to last full dtfreq update_accel = .true. - if (stir_from_file) then - call read_stirring_data_from_file(forcingfile,t,tinfile) - !if (id==master .and. iverbose >= 2) print*,' got new accel, tinfile = ',tinfile - endif +#ifdef STIR_FROM_FILE + call read_stirring_data_from_file(forcingfile,t,tinfile) + !if (id==master .and. iverbose >= 2) print*,' got new accel, tinfile = ',tinfile +#endif endif if (Debug) print *, 'stir: stirring start' call st_calcAccel(npart,xyzh,fxyzu) - if (.not. stir_from_file) then - if (update_accel) then - if (Debug) print*,'updating accelerations...' - call st_ounoiseupdate(6*st_nmodes, st_OUphases, st_OUvar, st_dtfreq, st_decay) - call st_calcPhases() - !! Store random seed in memory for later checkpoint. - call random_seed (get = st_randseed) - endif +#ifndef STIR_FROM_FILE + if (update_accel) then + if (Debug) print*,'updating accelerations...' + call st_ounoiseupdate(6*st_nmodes, st_OUphases, st_OUvar, st_dtfreq, st_decay) + call st_calcPhases() + !! Store random seed in memory for later checkpoint. + call random_seed (get = st_randseed) endif +#endif if (Debug) print *, 'stir: stirring end' diff --git a/src/main/fs_data.f90 b/src/main/fs_data.f90 index 12206a3c7..3e0bb4cf4 100644 --- a/src/main/fs_data.f90 +++ b/src/main/fs_data.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module fs_data ! diff --git a/src/main/geometry.f90 b/src/main/geometry.f90 index b78d805a8..b370d005b 100644 --- a/src/main/geometry.f90 +++ b/src/main/geometry.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module geometry ! diff --git a/src/main/gitinfo.f90 b/src/main/gitinfo.f90 index 19a62cf92..f860700f5 100644 --- a/src/main/gitinfo.f90 +++ b/src/main/gitinfo.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module gitinfo ! diff --git a/src/main/growth.F90 b/src/main/growth.F90 index bc12547e3..8f6500070 100644 --- a/src/main/growth.F90 +++ b/src/main/growth.F90 @@ -2,16 +2,16 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module growth ! ! Contains routine for dust growth and fragmentation ! ! :References: -! Stepinski & Valageas (1997), A&A 319, 1007 -! Kobayashi & Tanaka (2010), Icarus 206, 735 -! Rozner, Grishin & Perets (2020), MNRAS 496, 4827 +! Stepinski & Valageas (1997) +! Kobayashi & Tanaka (2009) +! Rozner & Grishin (2020) ! ! :Owner: Arnaud Vericel ! @@ -38,7 +38,6 @@ module growth use units, only:udist,umass,utime,unit_density,unit_velocity use physcon, only:au,Ro use part, only:xyzmh_ptmass,nptmass,this_is_a_flyby - use options, only:use_mcfost implicit none !--Default values for the growth and fragmentation of dust in the input file @@ -63,9 +62,11 @@ module growth real, public :: cohacc real, public :: dsize +#ifdef MCFOST logical, public :: f_smax = .false. real, public :: size_max = 0.2 !- cm integer, public :: b_per_dex = 5 +#endif public :: get_growth_rate,get_vrelonvfrag,check_dustprop public :: write_options_growth,read_options_growth,print_growthinfo,init_growth @@ -349,7 +350,7 @@ end subroutine comp_snow_line !+ !----------------------------------------------------------------------- subroutine write_options_growth(iunit) - use infile_utils, only:write_inopt + use infile_utils, only:write_inopt integer, intent(in) :: iunit write(iunit,"(/,a)") '# options controlling growth' @@ -372,11 +373,11 @@ subroutine write_options_growth(iunit) call write_inopt(dsizecgs,'dsize','size of ejected grain during erosion in cm',iunit) endif - if (use_mcfost) then - call write_inopt(f_smax,'force_smax','(mcfost) set manually maximum size for binning',iunit) - call write_inopt(size_max,'size_max_user','(mcfost) maximum size for binning in cm',iunit) - call write_inopt(b_per_dex,'bin_per_dex','(mcfost) number of bins of sizes per dex',iunit) - endif +#ifdef MCFOST + call write_inopt(f_smax,'force_smax','(mcfost) set manually maximum size for binning',iunit) + call write_inopt(size_max,'size_max_user','(mcfost) maximum size for binning in cm',iunit) + call write_inopt(b_per_dex,'bin_per_dex','(mcfost) number of bins of sizes per dex',iunit) +#endif end subroutine write_options_growth @@ -436,6 +437,7 @@ subroutine read_options_growth(name,valstring,imatch,igotall,ierr) read(valstring,*,iostat=ierr) this_is_a_flyby ngot = ngot + 1 if (nptmass < 2) tmp = .true. +#ifdef MCFOST case('force_smax') read(valstring,*,iostat=ierr) f_smax ngot = ngot + 1 @@ -445,11 +447,14 @@ subroutine read_options_growth(name,valstring,imatch,igotall,ierr) case('bin_per_dex') read(valstring,*,iostat=ierr) b_per_dex ngot = ngot + 1 +#endif case default imatch = .false. end select - if (use_mcfost) imcf = 3 +#ifdef MCFOST + imcf = 3 +#endif if (ieros == 1) goteros = 3 @@ -813,7 +818,6 @@ subroutine merge_bins(npart,grid,npartmin) ndustlarge = ndusttypes end subroutine merge_bins - !----------------------------------------------------------------------- !+ ! Convert a one-fluid dustgrowth sim into a two-fluid one (used by moddump_dustadd) @@ -885,12 +889,7 @@ subroutine convert_to_twofluid(npart,xyzh,vxyzu,massoftype,npartoftype,np_ratio, use_dustfrac = .false. end subroutine convert_to_twofluid - -!----------------------------------------------------------------------- -!+ -! Compute the relative velocity following Stepinski & Valageas (1997) -!+ -!----------------------------------------------------------------------- +!--Compute the relative velocity following Stepinski & Valageas (1997) real function vrelative(dustgasprop,Vt) use physcon, only:roottwo real, intent(in) :: dustgasprop(:),Vt diff --git a/src/main/growth_smol.f90 b/src/main/growth_smol.f90 index c89207c4b..2eea408f3 100644 --- a/src/main/growth_smol.f90 +++ b/src/main/growth_smol.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module growth_smol ! diff --git a/src/main/h2chem.f90 b/src/main/h2chem.f90 index 4e9b11f9e..798efa3ca 100644 --- a/src/main/h2chem.f90 +++ b/src/main/h2chem.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module chem ! @@ -261,7 +261,7 @@ subroutine evolve_abundances(ui,rhoi,chemarrays,nchem,dphot,dt) nstep2=1 tstep2=tstep elseif (abco <= 0.d0) then - nstep2=int(rhoi*1000.d0)+1 + nstep2=int(rhoi*1000.d0) tstep2=tstep/nstep2 else ! tsteptest=-abco/(k0*abcp*beta*np1*np1 - gamma_co*abco*np1) diff --git a/src/main/initial.F90 b/src/main/initial.F90 index a63657cb8..4855f77ab 100644 --- a/src/main/initial.F90 +++ b/src/main/initial.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module initial ! @@ -21,8 +21,8 @@ module initial ! growth, inject, io, io_summary, krome_interface, linklist, ! metric_tools, mf_write, mpibalance, mpidomain, mpimemory, mpitree, ! mpiutils, nicil, nicil_sup, omputils, options, part, partinject, -! ptmass, radiation_utils, readwrite_dumps, readwrite_infile, timestep, -! timestep_ind, timestep_sts, timing, units, writeheader +! photoevap, ptmass, radiation_utils, readwrite_dumps, readwrite_infile, +! timestep, timestep_ind, timestep_sts, timing, units, writeheader ! implicit none @@ -111,13 +111,13 @@ end subroutine initialise subroutine startrun(infile,logfile,evfile,dumpfile,noread) use mpiutils, only:reduceall_mpi,barrier_mpi,reduce_in_place_mpi use dim, only:maxp,maxalpha,maxvxyzu,maxptmass,maxdusttypes,itau_alloc,itauL_alloc,& - nalpha,mhd,mhd_nonideal,do_radiation,gravity,use_dust,mpi,do_nucleation,& + nalpha,mhd,do_radiation,gravity,use_dust,mpi,do_nucleation,& use_dustgrowth,ind_timesteps,idumpfile use deriv, only:derivs use evwrite, only:init_evfile,write_evfile,write_evlog use energies, only:compute_energies use io, only:idisk1,iprint,ievfile,error,iwritein,flush_warnings,& - die,fatal,id,master,nprocs,real4,warning,iverbose + die,fatal,id,master,nprocs,real4,warning use externalforces, only:externalforce,initialise_externalforces,update_externalforce,& externalforce_vdependent use options, only:iexternalforce,icooling,use_dustfrac,rhofinal1,rhofinal_cgs @@ -141,10 +141,15 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) use extern_gr, only:get_grforce_all use metric_tools, only:init_metric,imet_minkowski,imetric #endif +#ifdef PHOTO + use photoevap, only:set_photoevap_grid +#endif +#ifdef NONIDEALMHD use units, only:utime,umass,unit_Bfield use eos, only:gmw use nicil, only:nicil_initialise use nicil_sup, only:use_consistent_gmw +#endif use ptmass, only:init_ptmass,get_accel_sink_gas,get_accel_sink_sink, & h_acc,r_crit,r_crit2,rho_crit,rho_crit_cgs,icreate_sinks, & r_merge_uncond,r_merge_cond,r_merge_uncond2,r_merge_cond2,r_merge2 @@ -214,7 +219,9 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) real :: dtsinkgas,dtsinksink,fonrmax,dtphi2,dtnew_first,dtinject real :: stressmax,xmin,ymin,zmin,xmax,ymax,zmax,dx,dy,dz,tolu,toll real :: dummy(3) +#ifdef NONIDEALMHD real :: gmw_nicil +#endif #ifndef GR real :: dtf,fextv(3) #endif @@ -284,14 +291,12 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) ! !--initialise values for non-ideal MHD ! - if (mhd_nonideal) then - call nicil_initialise(real(utime),real(udist),real(umass),real(unit_Bfield),ierr,iprint,iprint) - if (ierr/=0) call fatal('initial','error initialising nicil (the non-ideal MHD library)') - - call use_consistent_gmw(ierr,gmw,gmw_nicil) - if (ierr/=0) write(iprint,'(2(a,Es18.7))') & - ' initial: Modifying mean molecular weight from ',gmw,' to ',gmw_nicil - endif +#ifdef NONIDEALMHD + call nicil_initialise(utime,udist,umass,unit_Bfield,ierr,iprint,iprint) + if (ierr/=0) call fatal('initial','error initialising nicil (the non-ideal MHD library)') + call use_consistent_gmw(ierr,gmw,gmw_nicil) + if (ierr/=0) write(iprint,'(2(a,Es18.7))')' initial: Modifying mean molecular mass from ',gmw,' to ',gmw_nicil +#endif nden_nimhd = 0.0 ! !--Initialise and verify parameters for super-timestepping @@ -397,6 +402,12 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) call balancedomains(npart) endif +! +!--set up photoevaporation grid, define relevant constants, etc. +! +#ifdef PHOTO + call set_photoevap_grid +#endif ! !--get timestep for external forces ! @@ -576,15 +587,7 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) if (maxalpha==maxp .and. nalpha >= 0) nderivinit = 2 if (do_radiation) nderivinit = 1 - !$omp parallel do default(none) & - !$omp shared(npart,eos_vars,fxyzu) & - !$omp private(i) - do i=1,npart - eos_vars(3,i) = -1.0 ! initial guess for temperature overridden in eos - fxyzu(:,i) = 0. ! so that div_a is 0 in first call to viscosity switch - enddo - !$omp end parallel do - + eos_vars(3,:) = -1.0 ! initial guess for temperature overridden in eos do j=1,nderivinit if (ntot > 0) call derivs(1,npart,npart,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,Bevol,dBevol,& rad,drad,radprop,dustprop,ddustprop,dustevol,ddustevol,dustfrac,& @@ -650,12 +653,12 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) #endif ! !--Determine the maximum separation of particles - xmax = -0.5*huge(xmax) - ymax = -0.5*huge(ymax) - zmax = -0.5*huge(zmax) - xmin = -xmax - ymin = -ymax - zmin = -zmax + xmax = -huge(xmax) + ymax = -huge(ymax) + zmax = -huge(zmax) + xmin = huge(xmin) + ymin = huge(ymin) + zmin = huge(zmin) !$omp parallel do default(none) & !$omp shared(npart,xyzh) & !$omp private(i) & @@ -686,7 +689,7 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) ! !--Print box sizes and masses ! - if (id==master .and. iverbose >= 1) then + if (id==master) then if (get_conserv > 0.0) then write(iprint,'(1x,a)') 'Initial mass and extent of particle distribution (in code units):' else @@ -707,27 +710,23 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) angtot_in = angtot totmom_in = totmom mdust_in = mdust - if (id==master .and. iverbose >= 1) then - write(iprint,'(1x,a)') 'Setting initial values to verify conservation laws:' - endif + if (id==master) write(iprint,'(1x,a)') 'Setting initial values (in code units) to verify conservation laws:' else - if (id==master .and. iverbose >= 1) then - write(iprint,'(1x,a)') 'Reading initial values to verify conservation laws from previous run:' + if (id==master) then + write(iprint,'(1x,a)') 'Reading initial values (in code units) to verify conservation laws from previous run:' endif endif if (id==master) then - if (iverbose >= 1) then - write(iprint,'(1x,a,es18.6)') 'Initial total energy: ', etot_in - write(iprint,'(1x,a,es18.6)') 'Initial angular momentum: ', angtot_in - write(iprint,'(1x,a,es18.6)') 'Initial linear momentum: ', totmom_in - endif + write(iprint,'(2x,a,es18.6)') 'Initial total energy: ', etot_in + write(iprint,'(2x,a,es18.6)') 'Initial angular momentum: ', angtot_in + write(iprint,'(2x,a,es18.6)') 'Initial linear momentum: ', totmom_in if (use_dust) then dust_label = 'dust' call make_tags_unique(ndusttypes,dust_label) do i=1,ndusttypes - if (mdust_in(i) > 0.) write(iprint,'(1x,a,es18.6)') 'Initial '//trim(dust_label(i))//' mass: ',mdust_in(i) + if (mdust_in(i) > 0.) write(iprint,'(2x,a,es18.6)') 'Initial '//trim(dust_label(i))//' mass: ',mdust_in(i) enddo - write(iprint,'(1x,a,es18.6)') 'Initial total dust mass:', sum(mdust_in(:)) + write(iprint,'(2x,a,es18.6)') 'Initial total dust mass: ', sum(mdust_in(:)) endif endif ! @@ -738,10 +737,8 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) if (get_conserv > 0.0) then get_conserv = -1. if (id==master) then - if (abs(etot_in) > tolu ) call warning('initial',& - 'consider changing units to reduce abs(total energy)',var='etot',val=etot_in) - if (mtot > tolu .or. mtot < toll) call warning('initial',& - 'consider changing units so total mass is closer to unity',var='mtot',val=mtot) + if (abs(etot_in) > tolu ) call warning('initial','consider changing code-units to reduce abs(total energy)') + if (mtot > tolu .or. mtot < toll) call warning('initial','consider changing code-units to have total mass closer to unity') ! if (dx > tolu .or. dx < toll .or. dy > tolu .or. dy < toll .or. dz > tolu .or. dz < toll) & !call warning('initial','consider changing code-units to have box length closer to unity') endif diff --git a/src/main/inject_BHL.f90 b/src/main/inject_BHL.f90 index 31fc559d6..af5769fa0 100644 --- a/src/main/inject_BHL.f90 +++ b/src/main/inject_BHL.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -29,8 +29,7 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'BHL' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject ! !--runtime settings for this module ! @@ -101,11 +100,7 @@ subroutine init_inject(ierr) size_y = ceiling(3.*wind_cylinder_radius/psep) size_z = ceiling(3.*wind_cylinder_radius/(sqrt(3.)*psep/2.)) do pass=1,2 - if (pass == 2) then - if (allocated(layer_even)) deallocate(layer_even) - if (allocated(layer_odd)) deallocate(layer_odd) - allocate(layer_even(2,neven), layer_odd(2,nodd)) - endif + if (pass == 2) allocate(layer_even(2,neven), layer_odd(2,nodd)) neven = 0 nodd = 0 do i=1,size_y @@ -258,7 +253,6 @@ subroutine inject_or_update_particles(ifirst, n, position, velocity, h, u, bound call add_or_update_particle(itype,position_u,velocity_u,h(i)/udist,u(i)/(udist**2/utime**2),& ifirst+i-1,npart,npartoftype,xyzh,vxyzu) enddo - end subroutine inject_or_update_particles !----------------------------------------------------------------------- @@ -335,9 +329,4 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) igotall = (ngot >= 8) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_asteroidwind.f90 b/src/main/inject_asteroidwind.f90 index dd2d6c25e..f7edca39a 100644 --- a/src/main/inject_asteroidwind.f90 +++ b/src/main/inject_asteroidwind.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -28,8 +28,7 @@ module inject character(len=*), parameter, public :: inject_type = 'asteroidwind' real, public :: mdot = 5.e8 ! mass injection rate in grams/second - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject private @@ -224,9 +223,4 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_bondi.f90 b/src/main/inject_bondi.f90 index 2272daf80..460e6af0f 100644 --- a/src/main/inject_bondi.f90 +++ b/src/main/inject_bondi.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -30,8 +30,7 @@ module inject public :: init_inject, & inject_particles, & write_options_inject, & - read_options_inject, & - set_default_options_inject + read_options_inject !-- Runtime variables read from input file real, public :: rin = 18.1 @@ -316,9 +315,4 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_firehose.f90 b/src/main/inject_firehose.f90 index c1246d526..3e2408b23 100644 --- a/src/main/inject_firehose.f90 +++ b/src/main/inject_firehose.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -26,7 +26,7 @@ module inject character(len=*), parameter, public :: inject_type = 'firehose' public :: inject_particles, write_options_inject, read_options_inject - public :: init_inject, set_default_options_inject + public :: init_inject real, private :: Mdot = 0. real, private :: Mdotcode = 0. @@ -273,9 +273,4 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_galcen_winds.f90 b/src/main/inject_galcen_winds.f90 index ea366c5cf..8f337f774 100644 --- a/src/main/inject_galcen_winds.f90 +++ b/src/main/inject_galcen_winds.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -25,8 +25,7 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'galcen_winds' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject real :: outer_boundary = 20. character(len=120) :: datafile = 'winddata.txt' @@ -304,9 +303,4 @@ subroutine read_wind_data(filename,nstars) end subroutine read_wind_data -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_keplerianshear.f90 b/src/main/inject_keplerianshear.f90 index 43c728e2c..6e2eef224 100644 --- a/src/main/inject_keplerianshear.f90 +++ b/src/main/inject_keplerianshear.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -49,8 +49,7 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'keplerianshear' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject public :: set_injection_parameters type injectparams @@ -207,7 +206,6 @@ subroutine write_options_inject(iunit) call write_inopt(injp%HoverR, 'HoverR', 'disc aspect ratio at inner sector radius', iunit) call write_inopt(injp%disc_mass,'disc_mass', 'total disc mass', iunit) call write_inopt(injp%object_mass,'object_mass', 'mass of the central object', iunit) - end subroutine write_options_inject !----------------------------------------------------------------------- @@ -276,11 +274,6 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - subroutine set_injection_parameters(R_in, R_out, Rsect_in,Rsect_out,dr_bound,& phimax,phi_inject,p_index,q_index,HoverR,disc_mass,object_mass) @@ -382,11 +375,14 @@ subroutine determine_particle_status(nqueue, nkill, nboundary, ndomain, nexit) enddo + return end subroutine determine_particle_status + !---- ! Subroutine fills the injection zones with boundary particles !--- + subroutine replenish_injection_zone(ninject,time,dtlast,injected) use eos, only:polyk,gamma use io, only:id,master @@ -505,12 +501,15 @@ subroutine replenish_injection_zone(ninject,time,dtlast,injected) enddo + return end subroutine replenish_injection_zone !---------------------------------- ! Rotates a particle in the z axis !---------------------------------- + subroutine rotate_particle_z(xyz,vxyz,phi) + real, intent(inout) :: phi, xyz(3), vxyz(3) real :: x,y,vx,vy @@ -526,11 +525,12 @@ subroutine rotate_particle_z(xyz,vxyz,phi) vxyz(1) = vx*cos(phi) - vy*sin(phi) vxyz(2) = vx*sin(phi) + vy*cos(phi) + return end subroutine rotate_particle_z !---------------------------------- !+ -! Rotates a single vector in the z axis +! Rotates a single vector in the z axis !+ !----------------------------------- @@ -541,13 +541,15 @@ subroutine rotate_vector_z(oldvec,newvec,phi) newvec(1) = oldvec(1)*cos(phi) - oldvec(2)*sin(phi) newvec(2) = oldvec(1)*sin(phi) + oldvec(2)*cos(phi) + return end subroutine rotate_vector_z -!----------------------------------------------------------------------- +! !+ ! Helper function to calculate polar co-ordinates from x,y !+ -!----------------------------------------------------------------------- +! + subroutine calc_polar_coordinates(r,phi,x,y) real, intent(in) :: x,y @@ -556,14 +558,17 @@ subroutine calc_polar_coordinates(r,phi,x,y) r = sqrt(x*x + y*y) phi = atan2(y,x) + return end subroutine calc_polar_coordinates + !----------------------------------------------------------------------- !+ ! Simple function to calculate the disc's surface density normalisation ! for a disc mass, inner and outer radii and the powerlaw index !+ !----------------------------------------------------------------------- + real function sigma0(Mdisc, Rinner, Router, p_index) real, intent(in) :: Mdisc,Rinner, Router, p_index diff --git a/src/main/inject_rochelobe.f90 b/src/main/inject_rochelobe.f90 index 55079d0bc..a13785b09 100644 --- a/src/main/inject_rochelobe.f90 +++ b/src/main/inject_rochelobe.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -24,8 +24,7 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'rochelobe' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject real, private :: Mdot = 1.0e-9 real, private :: Mdotcode = 0. @@ -338,9 +337,4 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_sne.f90 b/src/main/inject_sne.f90 index e0f95d8fb..a7c4e0720 100644 --- a/src/main/inject_sne.f90 +++ b/src/main/inject_sne.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -19,8 +19,7 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'supernovae' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject integer, parameter :: maxsn = 30 real, parameter :: xyz_sn(3,maxsn) = & @@ -175,9 +174,4 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_steadydisc.f90 b/src/main/inject_steadydisc.f90 index 254e3b57a..aa29630b8 100644 --- a/src/main/inject_steadydisc.f90 +++ b/src/main/inject_steadydisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -25,8 +25,7 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'steadydisc' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject real, private :: R_ref,sig_ref real, private :: p_index,q_index,HoverR,M_star @@ -57,9 +56,8 @@ subroutine init_inject(ierr) allocate(listinner(maxinj),listouter(maxinj)) if (idamp /= 3) then - call error('init_inject','these boundary conditions require idamp=3: switching it on') - idamp = 3 - ierr = 0 + call error('init_inject','these boundary conditions require idamp=3') + ierr = 1 endif end subroutine init_inject @@ -71,7 +69,7 @@ end subroutine init_inject !----------------------------------------------------------------------- subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& npart,npartoftype,dtinject) - use io, only:id,master,fatal + use io, only:id,master use damping, only:r1in,r2in,r1out,r2out real, intent(in) :: time, dtlast real, intent(inout) :: xyzh(:,:), vxyzu(:,:), xyzmh_ptmass(:,:), vxyz_ptmass(:,:) @@ -91,15 +89,9 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& ! injected = 0 if (ninner > inject_threshold) then - if (ninner > size(listinner)) then - call fatal('inject','too many particles outside inner boundary ',var='r',val=r1in) - endif call inject_particles_in_annulus(r1in,r2in,ninner,injected,listinner) endif if (nouter > inject_threshold) then - if (nouter > size(listouter)) then - call fatal('inject','too many particles outside outer boundary ',var='r',val=r2out) - endif call inject_particles_in_annulus(r1out,r2out,nouter,injected,listouter) endif @@ -223,8 +215,7 @@ end subroutine write_options_inject !----------------------------------------------------------------------- subroutine read_options_inject(name,valstring,imatch,igotall,ierr) use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db - use io, only:error,fatal,iunit=>imflow,lenprefix,fileprefix - use damping, only:r1in,r2out,r2in,r1out + use io, only:error,iunit=>imflow,lenprefix,fileprefix character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr @@ -249,30 +240,18 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) if (.not.read_discparams) then filename = trim(fileprefix)//'.discparams' call open_db_from_file(db,filename,iunit,ierr) - if (ierr /= 0) then - call error('inject','could not open .discparams file') - return - endif - call read_inopt(r1in,'R_in',db,errcount=nerr) - r2in = 1.19*r1in - call read_inopt(r2out,'R_out',db,errcount=nerr) - r1out = 0.84*r2out + if (ierr /= 0) call error('inject','could not open .discparams file') call read_inopt(R_ref,'R_ref',db,errcount=nerr) call read_inopt(HoverR,'H/R_ref',db,errcount=nerr) - call read_inopt(sig_ref,'sig_ref',db,errcount=nerr,min=tiny(0.)) + call read_inopt(sig_ref,'sig_ref',db,errcount=nerr) call read_inopt(M_star,'M_star',db,errcount=nerr) call read_inopt(p_index,'p_index',db,errcount=nerr) call read_inopt(q_index,'q_index',db,errcount=nerr) - if (nerr /= 0) call fatal('inject','error with parameters in .discparams file',var='errors',ival=nerr) + if (nerr /= 0) call error('inject','missing parameters in .discparams file',var='errors',ival=nerr) call close_db(db) if (ierr==0 .and. nerr==0) read_discparams = .true. endif end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_unifwind.f90 b/src/main/inject_unifwind.f90 index 275fb3b75..1c7b5f7b9 100644 --- a/src/main/inject_unifwind.f90 +++ b/src/main/inject_unifwind.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -22,8 +22,7 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'unifwind' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject real, public :: wind_density = 7.2d-16 real, public :: wind_velocity = 29. @@ -181,9 +180,4 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) igotall = (ngot >= 4) end subroutine read_options_inject -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag -end subroutine set_default_options_inject - end module inject diff --git a/src/main/inject_wind.f90 b/src/main/inject_wind.F90 similarity index 92% rename from src/main/inject_wind.f90 rename to src/main/inject_wind.F90 index 4e40ad475..5fbad9ed1 100644 --- a/src/main/inject_wind.f90 +++ b/src/main/inject_wind.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -28,32 +28,46 @@ module inject ! infile_utils, injectutils, io, options, part, partinject, physcon, ! ptmass_radiation, setbinary, timestep, units, wind, wind_equations ! - use dim, only:isothermal,nucleation + use physcon, only:solarl + use dim, only:isothermal implicit none character(len=*), parameter, public :: inject_type = 'wind' - public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - wind_injection_radius,set_default_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject,wind_injection_radius private ! !--runtime settings for this module ! ! Read from input file - integer:: sonic_type = -1 - integer:: iboundary_spheres = 5 - integer:: iwind_resolution = 5 - integer:: nfill_domain = 0 - real :: wind_velocity_km_s - real :: wind_mass_rate_Msun_yr - real :: wind_injection_radius_au - real :: wind_temperature +#ifdef DUST_NUCLEATION + integer:: sonic_type = 1 + real:: wind_velocity_km_s = 0. + real:: wind_mass_rate_Msun_yr = 1.d-5 + real:: wind_injection_radius_au = 2.37686663 + real:: wind_temperature = 2500. +#elif ISOTHERMAL + integer:: sonic_type = 1 + real:: wind_velocity_km_s = 0. + real:: wind_mass_rate_Msun_yr = 8.2d-8 + real:: wind_injection_radius_au = 0. + real:: wind_temperature +#else + integer:: sonic_type = 0 + real:: wind_velocity_km_s = 30. + real:: wind_mass_rate_Msun_yr = 1.d-8 + real:: wind_injection_radius_au = 1.1 + real:: wind_temperature = 3000. +#endif + integer :: iboundary_spheres = 5 + integer :: iwind_resolution = 10 + integer :: nfill_domain = 10 real :: outer_boundary_au = 30. real :: wind_shell_spacing = 1. real :: pulsation_period real :: pulsation_period_days = 0. real :: piston_velocity_km_s = 0. - real :: dtpulsation = huge(0.) + real :: dtpulsation = 1.d99 ! global variables integer, parameter :: wind_emitting_sink = 1 @@ -242,8 +256,8 @@ subroutine init_inject(ierr) if ( .not. pulsating_wind .or. nfill_domain > 0) then tboundary = (iboundary_spheres+nfill_domain)*time_between_spheres tend = max(tmax,tboundary)*utime - call save_windprofile(real(Rinject*udist),real(wind_injection_speed*unit_velocity),& - wind_temperature,real(outer_boundary_au*au), tend, tcross, 'wind_profile1D.dat') + call save_windprofile(Rinject*udist,wind_injection_speed*unit_velocity,& + wind_temperature, outer_boundary_au*au, tend, tcross, 'wind_profile1D.dat') if (tboundary > tmax) then print *,'simulation time < time to reach the last boundary shell' endif @@ -324,7 +338,7 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& use io, only:fatal,iverbose use wind, only:interp_wind_profile !,wind_profile use part, only:igas,iTeff,iReff,iboundary,nptmass,delete_particles_outside_sphere,& - delete_dead_particles_inside_radius,dust_temp,n_nucleation + delete_dead_particles_inside_radius,dust_temp,n_nucleation use partinject, only:add_or_update_particle use injectutils, only:inject_geodesic_sphere use units, only:udist, utime @@ -366,7 +380,7 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& ! i = npart inner_radius = wind_injection_radius + deltaR_osc*sin(omega_osc*time) - if (outer_boundary_au > Rinject) call delete_particles_outside_sphere(x0,real(outer_boundary_au*au/udist),npart) + if (outer_boundary_au > Rinject) call delete_particles_outside_sphere(x0,outer_boundary_au*au/udist,npart) call delete_dead_particles_inside_radius(x0,inner_radius,npart) if (npart /= i .and. iverbose > 0) print *,'deleted ',i-npart,'particles, remaining',npart @@ -374,7 +388,7 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& time_period = 0. if (do_molecular_cooling) then r_compOrb = sqrt(sum((xyzmh_ptmass(1:3,2)-xyzmh_ptmass(1:3,1))**2)) - call fit_spherical_wind(xyzh,vxyzu,r_compOrb,real(outer_boundary_au*au/udist),npart,fit_rho_inner_new,& + call fit_spherical_wind(xyzh,vxyzu,r_compOrb,outer_boundary_au*au/udist,npart,fit_rho_inner_new,& fit_rho_power_new,fit_vel_new) ! catch poor fit values and revert to previous value if (fit_rho_inner_new > 0. .and. fit_rho_inner_new < 1) fit_rho_inner = fit_rho_inner_new @@ -478,7 +492,6 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& !dr = neighbour_distance*wind_injection_radius !dtinject = 0.25*dr/sqrt(cs2max) dtinject = min(0.2*time_between_spheres,dtpulsation) - if (time <= 0.) dtinject = 0.01*dtinject end subroutine inject_particles @@ -547,19 +560,19 @@ subroutine fit_spherical_wind(xyzh,vxyzu,r_sep, r_outer, n_part, n0, m, v_inf) use part, only: rhoh ! Data dictionary: Arguments - real,intent(in) :: xyzh(:,:), vxyzu(:,:) - integer, intent(in) :: n_part - real, intent(out) :: n0, m, v_inf - real, intent(in) :: r_sep, r_outer + real,intent(in) :: xyzh(:,:), vxyzu(:,:) + integer, intent(in) :: n_part + double precision, intent(out) :: n0, m, v_inf + double precision, intent(in) :: r_sep, r_outer ! Data dictionary: Additional parameters for calculations - real, dimension(:), allocatable :: allR, allRho, allV - real, dimension(:), allocatable :: density_fit_compZone, velocity_cutoff - real, dimension(:), allocatable :: density_log_noCompZone, density_fit_noCompZone - real, dimension(:), allocatable :: radius_log_noCompZone, radius_fit_noCompZone - real, parameter :: radius_cutoffFactor2 = 9d-1 - integer :: n_velocity, n_density_noCompZone, n_density_compZone,i - real :: radius_cutoff1, radius_cutoff2 + double precision, dimension(:), allocatable :: allR, allRho, allV + double precision, dimension(:), allocatable :: density_fit_compZone, velocity_cutoff + double precision, dimension(:), allocatable :: density_log_noCompZone, density_fit_noCompZone + double precision, dimension(:), allocatable :: radius_log_noCompZone, radius_fit_noCompZone + double precision, parameter :: radius_cutoffFactor2 = 9d-1 + integer :: n_velocity, n_density_noCompZone, n_density_compZone,i + double precision :: radius_cutoff1, radius_cutoff2 allocate(allR(n_part)) allocate(allRho(n_part)) @@ -617,43 +630,6 @@ subroutine fit_spherical_wind(xyzh,vxyzu,r_sep, r_outer, n_part, n0, m, v_inf) end subroutine fit_spherical_wind - -subroutine set_default_options_inject(flag) - - integer, optional, intent(in) :: flag - integer :: icase - - if (present(flag)) then - icase = flag - else - icase = 0 - endif - - if (isothermal) then - sonic_type = 1 - wind_velocity_km_s = 0. - wind_mass_rate_Msun_yr = 8.2d-8 - wind_injection_radius_au = 0. - else - !trans-sonic wind - if (icase == 1) then - sonic_type = 1 - wind_velocity_km_s = 0. - wind_mass_rate_Msun_yr = 1.d-5 - wind_injection_radius_au = 2. - wind_temperature = 50000. - !super sonic-wind - else - sonic_type = 0 - wind_velocity_km_s = 20. - wind_mass_rate_Msun_yr = 1.d-5 - wind_injection_radius_au = 2. - wind_temperature = 2500. - endif - endif - -end subroutine set_default_options_inject - !----------------------------------------------------------------------- !+ ! Writes input options to the input file @@ -664,7 +640,7 @@ subroutine write_options_inject(iunit) use infile_utils, only: write_inopt integer, intent(in) :: iunit - if (sonic_type < 0) call set_default_options_inject + write(iunit,"(/,a)") '# options controlling particle injection' call write_inopt(sonic_type,'sonic_type','find transonic solution (1=yes,0=no)',iunit) call write_inopt(wind_velocity_km_s,'wind_velocity','injection wind velocity (km/s, if sonic_type = 0)',iunit) !call write_inopt(pulsation_period_days,'pulsation_period','stellar pulsation period (days)',iunit) diff --git a/src/main/inverse4x4.f90 b/src/main/inverse4x4.f90 index 2450eaf08..413980946 100644 --- a/src/main/inverse4x4.f90 +++ b/src/main/inverse4x4.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module inverse4x4 ! diff --git a/src/main/io.F90 b/src/main/io.F90 index 1c48207ac..a5a9d7776 100644 --- a/src/main/io.F90 +++ b/src/main/io.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module io ! diff --git a/src/main/ionization.f90 b/src/main/ionization.f90 index ebc536639..8c0d20446 100644 --- a/src/main/ionization.f90 +++ b/src/main/ionization.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module ionization_mod ! diff --git a/src/main/kdtree.F90 b/src/main/kdtree.F90 index 0452a5772..af63ca7ac 100644 --- a/src/main/kdtree.F90 +++ b/src/main/kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module kdtree ! diff --git a/src/main/kernel_WendlandC2.f90 b/src/main/kernel_WendlandC2.f90 index 546ea1be4..e32c5a387 100644 --- a/src/main/kernel_WendlandC2.f90 +++ b/src/main/kernel_WendlandC2.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_WendlandC4.f90 b/src/main/kernel_WendlandC4.f90 index 596233360..07bf0dd22 100644 --- a/src/main/kernel_WendlandC4.f90 +++ b/src/main/kernel_WendlandC4.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_WendlandC6.f90 b/src/main/kernel_WendlandC6.f90 index 20f819c1b..20de39192 100644 --- a/src/main/kernel_WendlandC6.f90 +++ b/src/main/kernel_WendlandC6.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_cubic.f90 b/src/main/kernel_cubic.f90 index 075292bfc..a4c26b0a2 100644 --- a/src/main/kernel_cubic.f90 +++ b/src/main/kernel_cubic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_quartic.f90 b/src/main/kernel_quartic.f90 index 4e32bb18b..2d2ababea 100644 --- a/src/main/kernel_quartic.f90 +++ b/src/main/kernel_quartic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_quintic.f90 b/src/main/kernel_quintic.f90 index 15358b5ed..fc41db6b0 100644 --- a/src/main/kernel_quintic.f90 +++ b/src/main/kernel_quintic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/krome.f90 b/src/main/krome.f90 index ce638b4f2..329be0746 100644 --- a/src/main/krome.f90 +++ b/src/main/krome.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module krome_interface ! diff --git a/src/main/linklist_kdtree.F90 b/src/main/linklist_kdtree.F90 index b644c7d75..9d7dbf2c4 100644 --- a/src/main/linklist_kdtree.F90 +++ b/src/main/linklist_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module linklist ! @@ -25,6 +25,8 @@ module linklist use part, only:ll use dtypekdtree, only:kdnode implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" integer, allocatable :: cellatid(:) integer, public, allocatable :: ifirstincell(:) diff --git a/src/main/lumin_nsdisc.F90 b/src/main/lumin_nsdisc.F90 index 139ed68a5..6ffd0090b 100644 --- a/src/main/lumin_nsdisc.F90 +++ b/src/main/lumin_nsdisc.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module lumin_nsdisc ! @@ -17,7 +17,7 @@ module lumin_nsdisc ! ! :Runtime parameters: None ! -! :Dependencies: eos, infile_utils, io, physcon, units +! :Dependencies: eos, fastmath, infile_utils, io, physcon, units ! use physcon, only: pi @@ -120,11 +120,17 @@ end subroutine make_grid_points subroutine get_grid_bins( r, zt, rbin, ztbin, phi, phibin ) use physcon, only:pi, twopi use io, only : fatal +#ifdef FINVSQRT + use fastmath, only:finvsqrt +#endif real, intent(in) :: r, phi, zt integer, intent(out) :: rbin, ztbin, phibin real :: B, C, ztnew - +#ifdef FINVSQRT + rbin = int( nr*finvsqrt( (rmax-rmin)/((r-rmin)))) !optimized for speed not readability +#else rbin = int( nr*sqrt( (r-rmin)/(rmax-rmin))) +#endif B = 2.*(thetamin-thetamax)/(nth) C = 2.*(zmin-zmax)/nz diff --git a/src/main/memory.F90 b/src/main/memory.F90 index 500b414a7..0052ef85b 100644 --- a/src/main/memory.F90 +++ b/src/main/memory.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module memory ! @@ -15,7 +15,7 @@ module memory ! :Runtime parameters: None ! ! :Dependencies: allocutils, dim, io, linklist, mpibalance, mpiderivs, -! mpimemory, mpitree, part +! mpimemory, mpitree, part, photoevap ! implicit none @@ -34,6 +34,9 @@ subroutine allocate_memory(ntot, part_only) use mpibalance, only:allocate_balance_arrays use mpiderivs, only:allocate_cell_comms_arrays use mpitree, only:allocate_tree_comms_arrays +#ifdef PHOTO + use photoevap, only:allocate_photoevap +#endif integer(kind=8), intent(in) :: ntot logical, optional, intent(in) :: part_only @@ -83,6 +86,9 @@ subroutine allocate_memory(ntot, part_only) call allocate_part if (.not. part_only_) then call allocate_linklist +#ifdef PHOTO + call allocate_photoevap +#endif if (mpi) then call allocate_mpi_memory(npart=n) call allocate_balance_arrays @@ -107,6 +113,9 @@ subroutine deallocate_memory(part_only) use dim, only:update_max_sizes,mpi use part, only:deallocate_part use linklist, only:deallocate_linklist +#ifdef PHOTO + use photoevap, only:deallocate_photoevap +#endif use mpimemory, only:deallocate_mpi_memory use mpibalance, only:deallocate_balance_arrays use mpiderivs, only:deallocate_cell_comms_arrays @@ -125,6 +134,9 @@ subroutine deallocate_memory(part_only) call deallocate_part if (.not. part_only_) then call deallocate_linklist +#ifdef PHOTO + call deallocate_photoevap +#endif endif if (mpi) then diff --git a/src/main/metric_kerr-schild.f90 b/src/main/metric_kerr-schild.f90 index 6557462be..e9364f2be 100644 --- a/src/main/metric_kerr-schild.f90 +++ b/src/main/metric_kerr-schild.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_kerr.f90 b/src/main/metric_kerr.f90 index 329efe265..a9db18e60 100644 --- a/src/main/metric_kerr.f90 +++ b/src/main/metric_kerr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_minkowski.f90 b/src/main/metric_minkowski.f90 index 94295f28e..a65e0ecff 100644 --- a/src/main/metric_minkowski.f90 +++ b/src/main/metric_minkowski.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_schwarzschild.f90 b/src/main/metric_schwarzschild.f90 index 73d3451e8..3d325c8bb 100644 --- a/src/main/metric_schwarzschild.f90 +++ b/src/main/metric_schwarzschild.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_tools.F90 b/src/main/metric_tools.F90 index 17cd33f10..a4475ac68 100644 --- a/src/main/metric_tools.F90 +++ b/src/main/metric_tools.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module metric_tools ! diff --git a/src/main/mf_write.f90 b/src/main/mf_write.f90 index 66249b76a..3325435e9 100644 --- a/src/main/mf_write.f90 +++ b/src/main/mf_write.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mf_write ! diff --git a/src/main/mol_data.f90 b/src/main/mol_data.f90 index a71d18ebc..8b54756e2 100644 --- a/src/main/mol_data.f90 +++ b/src/main/mol_data.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mol_data ! diff --git a/src/main/mpi_balance.F90 b/src/main/mpi_balance.F90 index 91e604027..06202e648 100644 --- a/src/main/mpi_balance.F90 +++ b/src/main/mpi_balance.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpibalance ! @@ -44,33 +44,19 @@ module mpibalance contains -!---------------------------------------------------------------- -!+ -! allocate memory -!+ -!---------------------------------------------------------------- -subroutine allocate_balance_arrays() +subroutine allocate_balance_arrays use allocutils, only:allocate_array - call allocate_array('nsent', nsent, nprocs) call allocate_array('nexpect', nexpect, nprocs) call allocate_array('nrecv', nrecv, nprocs) call allocate_array('countrequest',countrequest,nprocs) - end subroutine allocate_balance_arrays -!---------------------------------------------------------------- -!+ -! deallocate memory -!+ -!---------------------------------------------------------------- -subroutine deallocate_balance_arrays() - +subroutine deallocate_balance_arrays if (allocated(nsent )) deallocate(nsent ) if (allocated(nexpect )) deallocate(nexpect ) if (allocated(nrecv )) deallocate(nrecv ) if (allocated(countrequest)) deallocate(countrequest) - end subroutine deallocate_balance_arrays !---------------------------------------------------------------- @@ -178,18 +164,14 @@ end subroutine balancedomains !+ !---------------------------------------------------------------- subroutine balance_init(npart) - use part, only:fill_sendbuf integer, intent(in) :: npart - integer :: i,nbuf - - ! use a dummy call to fill_sendbuf to find out the buffer size - call fill_sendbuf(1,xbuffer,nbuf) ! just fill for particle #1 + integer :: i !--use persistent communication type for receives ! cannot do same for sends as there are different destination, ! unless we make a request for each processor ! - call MPI_RECV_INIT(xbuffer,nbuf,MPI_DEFAULT_REAL,MPI_ANY_SOURCE, & + call MPI_RECV_INIT(xbuffer,size(xbuffer),MPI_DEFAULT_REAL,MPI_ANY_SOURCE, & MPI_ANY_TAG,comm_balance,irequestrecv(1),mpierr) ! !--post a non-blocking receive so that we can receive particles @@ -216,6 +198,7 @@ subroutine balance_init(npart) ! ncomplete = 0 + return end subroutine balance_init !----------------------------------------------------------------------- @@ -293,7 +276,6 @@ subroutine send_part(i,newproc,replace) integer, intent(in) :: i,newproc logical, intent(in), optional :: replace logical :: idone,doreplace - integer :: nbuf if (present(replace)) then doreplace = replace @@ -305,9 +287,9 @@ subroutine send_part(i,newproc,replace) if (newproc < 0 .or. newproc > nprocs-1) then call fatal('balance','error in ibelong',ival=newproc,var='ibelong') else - call fill_sendbuf(i,xsendbuf,nbuf) + call fill_sendbuf(i,xsendbuf) ! tag cannot be i, because some MPI implementations do not support large values for the tag - call MPI_ISEND(xsendbuf,nbuf,MPI_DEFAULT_REAL,newproc,0,comm_balance,irequestsend(1),mpierr) + call MPI_ISEND(xsendbuf,size(xsendbuf),MPI_DEFAULT_REAL,newproc,0,comm_balance,irequestsend(1),mpierr) !--wait for send to complete, receive whilst doing so idone = .false. @@ -320,7 +302,7 @@ subroutine send_part(i,newproc,replace) call kill_particle(i) nsent(newproc+1) = nsent(newproc+1) + 1 - + return end subroutine send_part !---------------------------------------------------------------- diff --git a/src/main/mpi_dens.F90 b/src/main/mpi_dens.F90 index 5a512ea63..e2beadda5 100644 --- a/src/main/mpi_dens.F90 +++ b/src/main/mpi_dens.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpidens ! diff --git a/src/main/mpi_derivs.F90 b/src/main/mpi_derivs.F90 index 0eadd0034..2f8eba0d4 100644 --- a/src/main/mpi_derivs.F90 +++ b/src/main/mpi_derivs.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpiderivs ! diff --git a/src/main/mpi_domain.F90 b/src/main/mpi_domain.F90 index 7a89c32cd..e9e5a8eca 100644 --- a/src/main/mpi_domain.F90 +++ b/src/main/mpi_domain.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpidomain ! @@ -22,6 +22,8 @@ module mpidomain use io, only:nprocs use part, only:ibelong implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" integer, parameter :: ndim = 3 diff --git a/src/main/mpi_force.F90 b/src/main/mpi_force.F90 index 96ccacad9..c8132147c 100644 --- a/src/main/mpi_force.F90 +++ b/src/main/mpi_force.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpiforce ! diff --git a/src/main/mpi_memory.f90 b/src/main/mpi_memory.F90 similarity index 99% rename from src/main/mpi_memory.f90 rename to src/main/mpi_memory.F90 index ad8ad64d6..efd94d97e 100644 --- a/src/main/mpi_memory.f90 +++ b/src/main/mpi_memory.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpimemory ! diff --git a/src/main/mpi_tree.F90 b/src/main/mpi_tree.F90 index 8183b03b5..66cf2ea81 100644 --- a/src/main/mpi_tree.F90 +++ b/src/main/mpi_tree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpitree ! diff --git a/src/main/mpi_utils.F90 b/src/main/mpi_utils.F90 index bc2cc34ad..4c9615f45 100644 --- a/src/main/mpi_utils.F90 +++ b/src/main/mpi_utils.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpiutils ! diff --git a/src/main/nicil_supplement.f90 b/src/main/nicil_supplement.F90 similarity index 97% rename from src/main/nicil_supplement.f90 rename to src/main/nicil_supplement.F90 index 45717c48b..9728fa41b 100644 --- a/src/main/nicil_supplement.f90 +++ b/src/main/nicil_supplement.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module nicil_sup ! @@ -23,7 +23,7 @@ module nicil_sup ! - alpha_AD : *power law exponent for ambipolar diffusion* ! - an_grain : *minimum grain radius (cm)* ! - ax_grain : *maximum grain radius (cm)* -! - eta_const_type : *Coefficient type: (1) phys.cnst+B+rho (2) C_NI+B+rho (3) constant* +! - eta_const_type : *Coefficient type: phys.cnst+B+rho (1), C_NI+B+rho (2), C_NI (3)* ! - eta_constant : *Use constant coefficients for all non-ideal MHD terms* ! - fdg : *dust-to-gas mass ratio* ! - gamma_AD : *ion-neutral coupling coefficient for ambipolar diffusion* @@ -85,7 +85,7 @@ subroutine write_options_nicil(iunit) call write_inopt(use_ambi, 'use_ambi' ,'Calculate the coefficient for ambipolar diffusion',iunit) call write_inopt(eta_constant,'eta_constant','Use constant coefficients for all non-ideal MHD terms',iunit) if ( eta_constant ) then - call write_inopt(eta_const_type,'eta_const_type','Coefficient type: (1) phys.cnst+B+rho (2) C_NI+B+rho (3) constant',iunit) + call write_inopt(eta_const_type,'eta_const_type','Coefficient type: phys.cnst+B+rho (1), C_NI+B+rho (2), C_NI (3)',iunit) if ( eta_const_type==1 ) then if ( use_ohm .or. use_hall ) then call write_inopt(n_e_cnst,'n_e_cnst' ,'constant electron number density',iunit) diff --git a/src/main/options.f90 b/src/main/options.f90 index 6ac0f8927..f2239cc1f 100644 --- a/src/main/options.f90 +++ b/src/main/options.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module options ! diff --git a/src/main/part.F90 b/src/main/part.F90 index 0ec095e8e..1a396517d 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module part ! @@ -39,6 +39,8 @@ module part use krome_user, only: krome_nmols #endif implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" ! !--basic storage needed for read/write of particle data ! @@ -55,7 +57,6 @@ module part character(len=*), parameter :: vxyzu_label(4) = (/'vx','vy','vz','u '/) character(len=*), parameter :: Bxyz_label(3) = (/'Bx','By','Bz'/) character(len=*), parameter :: Bevol_label(4) = (/'Bx/rho','By/rho','Bz/rho','psi '/) - character(len=*), parameter :: alphaind_label(3) = (/'alpha ','alphaloc','div_a '/) ! !--tracking particle IDs @@ -120,13 +121,6 @@ module part character(len=*), parameter :: abundance_label(5) = & (/'h2ratio','abHIq ','abhpq ','abeq ','abco '/) #endif -! -!--make a public krome_nmols variable to avoid ifdefs elsewhere -! -#ifndef KROME - integer, parameter :: krome_nmols = 0 -#endif - ! !--eos_variables ! @@ -207,7 +201,9 @@ module part integer, parameter :: ihall = 2 ! eta_hall integer, parameter :: iambi = 3 ! eta_ambi integer, parameter :: iion = 4 ! ionisation fraction +#ifdef NONIDEALMHD character(len=*), parameter :: eta_nimhd_label(4) = (/'eta_{OR}','eta_{HE}','eta_{AD}','ne/n '/) +#endif ! !-- Ray tracing : optical depth ! @@ -323,7 +319,82 @@ module part ! information between MPI threads ! integer, parameter, private :: usedivcurlv = min(ndivcurlv,1) - integer, parameter :: ipartbufsize = 128 + integer, parameter :: ipartbufsize = 4 & ! xyzh + +maxvxyzu & ! vxyzu + +maxvxyzu & ! vpred +#ifdef GR + +maxvxyzu & ! pxyzu + +maxvxyzu & ! ppred + +1 & ! dens +#endif + +maxvxyzu & ! fxyzu + +3 & ! fext + +usedivcurlv & ! divcurlv +#if !defined(CONST_AV) && !defined(DISC_VISCOSITY) + +nalpha & ! alphaind +#endif +#ifndef ANALYSIS + +ngradh & ! gradh +#endif +#ifdef MHD + +maxBevol & ! Bevol + +maxBevol & ! Bpred +#endif +#ifdef RADIATION + +3*maxirad + maxradprop & ! rad,radpred,drad,radprop +#endif +#ifndef ANALYSIS + +1 & ! iphase +#endif +#ifdef DUST + +3 & ! fxyz_drag + +3 & ! fxyz_dragold + +maxdusttypes & ! dustfrac + +maxdustsmall & ! dustevol + +maxdustsmall & ! dustpred +#ifdef DUSTGROWTH + +2 & ! dustprop + +2 & ! dustproppred + +4 & ! dustgasprop +#endif +#endif +#ifdef H2CHEM + +nabundances & ! abundance +#endif +#ifdef DUST_NUCLEATION + +1 & ! nucleation rate + +4 & ! normalized moments \hat{K}_i = K_i/n + +1 & ! mean molecular weight + +1 & ! gamma + +1 & ! super saturation ratio + +1 & ! kappa dust + +1 & ! alpha +#endif +#ifdef KROME + +krome_nmols & ! abundance + +1 & ! variable gamma + +1 & ! variable mu + +1 & ! temperature + +1 & ! cooling rate +#endif + +maxeosvars & ! eos_vars +#ifdef SINK_RADIATION + +1 & ! dust temperature + +1 & ! optical depth +#endif +#ifdef GRAVITY + +1 & ! poten +#endif +#ifdef IND_TIMESTEPS + +1 & ! ibin + +1 & ! ibin_old + +1 & ! ibin_wake + +1 & ! dt_in + +1 & ! twas +#endif + +1 & ! iorig + +0 + real :: hfact,Bextx,Bexty,Bextz integer :: npart integer(kind=8) :: ntot @@ -370,7 +441,6 @@ module part private :: hrho4,hrho8,hrho4_pmass,hrho8_pmass,hrhomixed_pmass private :: get_ntypes_i4,get_ntypes_i8 - contains subroutine allocate_part @@ -439,11 +509,11 @@ subroutine allocate_part call allocate_array('nucleation', nucleation, n_nucleation, maxp_nucleation*inucleation) call allocate_array('tau', tau, maxp*itau_alloc) call allocate_array('tau_lucy', tau_lucy, maxp*itauL_alloc) - if (use_krome) then - call allocate_array('abundance', abundance, krome_nmols, maxp_krome) - else - call allocate_array('abundance', abundance, nabundances, maxp_h2) - endif +#ifdef KROME + call allocate_array('abundance', abundance, krome_nmols, maxp_krome) +#else + call allocate_array('abundance', abundance, nabundances, maxp_h2) +#endif call allocate_array('gamma_chem', gamma_chem, maxp_krome) call allocate_array('mu_chem', mu_chem, maxp_krome) call allocate_array('T_gas_cool', T_gas_cool, maxp_krome) @@ -575,11 +645,11 @@ subroutine init_part endif if (store_dust_temperature) dust_temp = -1. !-- Initialise dust properties to zero - if (use_dustgrowth) then - dustprop(:,:) = 0. - dustgasprop(:,:) = 0. - VrelVf(:) = 0. - endif +#ifdef DUSTGROWTH + dustprop(:,:) = 0. + dustgasprop(:,:) = 0. + VrelVf(:) = 0. +#endif if (ind_timesteps) then ibin(:) = 0 ibin_old(:) = 0 @@ -1269,7 +1339,7 @@ subroutine reorder_particles(iorder,np) integer, intent(in) :: iorder(:) integer, intent(in) :: np - integer :: isrc,nbuf + integer :: isrc real :: xtemp(ipartbufsize) do i=1,np @@ -1281,7 +1351,7 @@ subroutine reorder_particles(iorder,np) enddo ! Swap particles around - call fill_sendbuf(i,xtemp,nbuf) + call fill_sendbuf(i,xtemp) call copy_particle_all(isrc,i,.false.) call unfill_buffer(isrc,xtemp) @@ -1387,12 +1457,12 @@ end subroutine change_status_pos ! to send to another processor !+ !---------------------------------------------------------------- -subroutine fill_sendbuf(i,xtemp,nbuf) +subroutine fill_sendbuf(i,xtemp) use io, only:fatal use mpiutils, only:fill_buffer integer, intent(in) :: i real, intent(out) :: xtemp(ipartbufsize) - integer, intent(out) :: nbuf + integer :: nbuf ! !--package particle information into one simple wrapper ! @@ -1468,8 +1538,9 @@ subroutine fill_sendbuf(i,xtemp,nbuf) endif call fill_buffer(xtemp,iorig(i),nbuf) endif - if (nbuf > ipartbufsize) call fatal('fill_sendbuf','error: send buffer size overflow',var='nbuf',ival=nbuf) + if (nbuf /= ipartbufsize) call fatal('fill_sendbuf','error in send buffer size') + return end subroutine fill_sendbuf !---------------------------------------------------------------- @@ -1558,6 +1629,7 @@ subroutine unfill_buffer(ipart,xbuf) divBsymm(ipart) = 0. endif + return end subroutine unfill_buffer !---------------------------------------------------------------- diff --git a/src/main/partinject.F90 b/src/main/partinject.F90 index 8e3b7e0d8..f9ec0ec26 100644 --- a/src/main/partinject.F90 +++ b/src/main/partinject.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module partinject ! @@ -17,20 +17,18 @@ module partinject ! ! :Runtime parameters: None ! -! :Dependencies: cons2prim, dim, extern_gr, io, metric_tools, options, -! part, timestep_ind +! :Dependencies: cons2prim, extern_gr, io, metric_tools, options, part, +! timestep_ind ! implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" public :: add_or_update_particle, add_or_update_sink public :: update_injected_particles - - ! ! Use this flag if particles are updated rather than injected (e.g. inject_sne) ! see inject_sne for use; currently only valid for gas particles - ! logical, public :: updated_particle = .false. - private contains @@ -44,10 +42,12 @@ subroutine add_or_update_particle(itype,position,velocity,h,u,particle_number,np use part, only:maxp,iamtype,iphase,maxvxyzu,iboundary,nucleation use part, only:maxalpha,alphaind,maxgradh,gradh,fxyzu,fext,set_particle_type use part, only:mhd,Bevol,dBevol,Bxyz,divBsymm!,dust_temp - use part, only:divcurlv,divcurlB,ndivcurlv,ndivcurlB,ntot,ibin + use part, only:divcurlv,divcurlB,ndivcurlv,ndivcurlB,ntot use io, only:fatal - use dim, only:ind_timesteps +#ifdef IND_TIMESTEPS + use part, only:ibin use timestep_ind, only:nbinmax +#endif integer, intent(in) :: itype real, intent(in) :: position(3), velocity(3), h, u real, intent(in), optional :: JKmuS(:) @@ -75,37 +75,32 @@ subroutine add_or_update_particle(itype,position,velocity,h,u,particle_number,np npartoftype(itype_old) = npartoftype(itype_old) - 1 npartoftype(itype) = npartoftype(itype)+1 endif - call set_particle_type(particle_number,itype) - ! Update particle type, position, size, velocity and energy xyzh(1,particle_number) = position(1) xyzh(2,particle_number) = position(2) xyzh(3,particle_number) = position(3) if (itype /= iboundary .or. new_particle) xyzh(4,particle_number) = h - vxyzu(1,particle_number) = velocity(1) vxyzu(2,particle_number) = velocity(2) vxyzu(3,particle_number) = velocity(3) if (maxvxyzu>=4) vxyzu(4,particle_number) = u - fxyzu(:,particle_number) = 0. fext(:,particle_number) = 0. - if (mhd) then Bevol(:,particle_number) = 0. dBevol(:,particle_number) = 0. Bxyz(:,particle_number) = 0. divBsymm(particle_number) = 0. endif - if (ndivcurlv > 0) divcurlv(:,particle_number) = 0. if (ndivcurlB > 0) divcurlB(:,particle_number) = 0. if (maxalpha==maxp) alphaind(:,particle_number) = 0. if (maxgradh==maxp) gradh(:,particle_number) = 0. !if (store_dust_temperature) dust_temp(:,particle_number) = 0. - - if (ind_timesteps) ibin(particle_number) = nbinmax +#ifdef IND_TIMESTEPS + ibin(particle_number) = nbinmax +#endif if (present(jKmuS)) nucleation(:,particle_number) = JKmuS(:) end subroutine add_or_update_particle @@ -130,7 +125,6 @@ subroutine add_or_update_sink(position,velocity,radius,mass,sink_number) elseif (sink_number > nptmass+1) then call fatal('Add sink', 'Incorrect sink number (> maxptmass + 1).') endif - ! Update sink position, size, velocity and mass xyzmh_ptmass(1,sink_number) = position(1) xyzmh_ptmass(2,sink_number) = position(2) @@ -140,7 +134,6 @@ subroutine add_or_update_sink(position,velocity,radius,mass,sink_number) vxyz_ptmass(1,sink_number) = velocity(1) vxyz_ptmass(2,sink_number) = velocity(2) vxyz_ptmass(3,sink_number) = velocity(3) - end subroutine add_or_update_sink !----------------------------------------------------------------------- @@ -151,9 +144,11 @@ end subroutine add_or_update_sink !+ !----------------------------------------------------------------------- subroutine update_injected_particles(npartold,npart,istepfrac,nbinmax,time,dtmax,dt,dtinject) - use dim, only:ind_timesteps +#ifdef IND_TIMESTEPS use timestep_ind, only:get_newbin,change_nbinmax,get_dt - use part, only:twas,ibin,ibin_old,norig,iorig,iphase,igas,iunknown + use part, only:twas,ibin,ibin_old +#endif + use part, only:norig,iorig,iphase,igas,iunknown #ifdef GR use part, only:xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext use cons2prim, only:prim2consall @@ -167,7 +162,9 @@ subroutine update_injected_particles(npartold,npart,istepfrac,nbinmax,time,dtmax real, intent(inout) :: dt real, intent(in) :: time,dtmax,dtinject integer :: i +#ifdef IND_TIMESTEPS integer(kind=1) :: nbinmaxprev +#endif #ifdef GR real :: dtext_dum #endif @@ -187,24 +184,24 @@ subroutine update_injected_particles(npartold,npart,istepfrac,nbinmax,time,dtmax endif #endif - if (ind_timesteps) then - ! find timestep bin associated with dtinject - nbinmaxprev = nbinmax - call get_newbin(dtinject,dtmax,nbinmax,allow_decrease=.false.) - if (nbinmax > nbinmaxprev) then ! update number of bins if needed - call change_nbinmax(nbinmax,nbinmaxprev,istepfrac,dtmax,dt) - endif - ! put all injected particles on shortest bin - do i=npartold+1,npart - ibin(i) = nbinmax - ibin_old(i) = nbinmax ! for particle waking to ensure that neighbouring particles are promptly woken - twas(i) = time + 0.5*get_dt(dtmax,ibin(i)) - enddo - else - ! For global timestepping, reset the timestep, since this is otherwise - ! not updated until after the call to step. - dt = min(dt,dtinject) +#ifdef IND_TIMESTEPS + ! find timestep bin associated with dtinject + nbinmaxprev = nbinmax + call get_newbin(dtinject,dtmax,nbinmax,allow_decrease=.false.) + if (nbinmax > nbinmaxprev) then ! update number of bins if needed + call change_nbinmax(nbinmax,nbinmaxprev,istepfrac,dtmax,dt) endif + ! put all injected particles on shortest bin + do i=npartold+1,npart + ibin(i) = nbinmax + ibin_old(i) = nbinmax ! for particle waking to ensure that neighbouring particles are promptly woken + twas(i) = time + 0.5*get_dt(dtmax,ibin(i)) + enddo +#else + ! For global timestepping, reset the timestep, since this is otherwise + ! not updated until after the call to step. + dt = min(dt,dtinject) +#endif ! add particle ID do i=npartold+1,npart @@ -217,11 +214,11 @@ subroutine update_injected_particles(npartold,npart,istepfrac,nbinmax,time,dtmax do i=1,npart if (iphase(i) == iunknown) then iphase(i) = igas - if (ind_timesteps) then - ibin(i) = nbinmax - ibin_old(i) = nbinmax - twas(i) = time + 0.5*get_dt(dtmax,ibin(i)) - endif +#ifdef IND_TIMESTEPS + ibin(i) = nbinmax + ibin_old(i) = nbinmax + twas(i) = time + 0.5*get_dt(dtmax,ibin(i)) +#endif endif enddo endif diff --git a/src/main/phantom.f90 b/src/main/phantom.F90 similarity index 97% rename from src/main/phantom.f90 rename to src/main/phantom.F90 index 8d26dafd8..462586c35 100644 --- a/src/main/phantom.f90 +++ b/src/main/phantom.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantom ! diff --git a/src/main/photoevap.f90 b/src/main/photoevap.f90 new file mode 100644 index 000000000..a985bf61b --- /dev/null +++ b/src/main/photoevap.f90 @@ -0,0 +1,432 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! +module photoevap +! +! This module contains all the subroutines necessary for the +! photoevaporation switch +! +! :References: Alexander, Clarke & Pringle (2006), MNRAS 369, 216-228 +! +! :Owner: Daniel Price +! +! :Runtime parameters: +! - ionflux_cgs : *Stellar EUV flux rate* +! - mu_cgs : *Mean molecular weight* +! - recombrate_cgs : *Recombination rate (alpha)* +! +! :Dependencies: allocutils, dim, eos, externalforces, infile_utils, io, +! physcon, units +! + + implicit none + + !--# of grid nodes for photoevaporation grid + integer, parameter :: Nr = 400 + integer, parameter :: Nphi = 400 + integer, parameter :: Ntheta = 400 + + !--Index to identify which cell particles belong + integer, allocatable :: Rnum(:) + integer, allocatable :: Thetanum(:) + integer, allocatable :: Phinum(:) + + !--# of particles per cell and ray. + integer :: Cellpartnum(Nr-1,Ntheta-1,Nphi-1) + integer :: Raypartnum(Ntheta-1,Nphi-1) + + !--Location of ionization front and # of ionized particles in ray + integer :: Ionfront(Ntheta-1,Nphi-1) + integer :: Nion(Ntheta-1,Nphi-1) + + !--Reciprical of cell volume + real :: rCellvol(Nr-1,Nphi-1) + + !--Fraction of ions to neutrals in boundary cell + real :: Ionfrac(Ntheta-1,Nphi-1) + + !--Change in # of ions per unit time due to stellar flux (constant in time) + real :: dN_ion(Ntheta-1) + + !--Photoevaporation grid minimums and increment values + real :: Rgrid_min, Thetagrid_min, Phigrid_min + real :: dr_grid, dphi_grid, dtheta_grid + + !--Recombination rate, ionization flux, mean Mol. weight, temperature of ions + real :: recombrate + real :: recombrate_cgs = 2.6d-13 + real :: ionflux + real :: ionflux_cgs = 1.d41 + real :: mu + real :: mu_cgs = 1.26 + real :: mH + real :: temp_ion + real :: energy_to_temperature_ratio + + real :: prev_time + + public :: allocate_photoevap + public :: deallocate_photoevap + public :: write_options_photoevap + public :: read_options_photoevap + public :: photo_ionize + public :: find_ionfront + public :: set_photoevap_grid + + private + +contains + +!*************************************************************************************** +!*************************************************************************************** + +subroutine allocate_photoevap + use dim, only:maxp + use allocutils, only:allocate_array + + call allocate_array('Rnum', Rnum, maxp) + call allocate_array('Thetanum', Thetanum, maxp) + call allocate_array('Phinum', Phinum, maxp) + +end subroutine allocate_photoevap + +subroutine deallocate_photoevap + + deallocate(Rnum) + deallocate(Thetanum) + deallocate(Phinum) + +end subroutine deallocate_photoevap + +!---------------------------------------------------------------- +!+ +! This subroutine makes a spherical grid for photoevaporation +! Note: this routine is ment to be called only once at the +! beginning of the simulation to get the grid spacing. +!+ +!---------------------------------------------------------------- +subroutine set_photoevap_grid + use units, only:udist,umass,utime + use physcon, only:pi,atomic_mass_unit,mass_proton_cgs,kboltz,Rg + use externalforces, only:accradius1 + use eos, only:gamma + + integer :: i,j + + !--Inner and outer radius of grid + real :: R_in + real :: R_out + + !--Photoevaporation grid min and max in each direction + real :: Rgrid_max + real :: Thetagrid_max + real :: Phigrid_max + + !--photoevaporation grid in r,theta directions + real :: r_grid(Nr) + real :: theta_grid(Ntheta) + + !--TODO: try to read these in from setup_photoevap + R_in = accradius1 + R_out = 10.0 + + !--Set the temperature of ions to 10,000 K + temp_ion = 1.d4 + + !--Constant that converts specific energy density (u) to temperature in K. + ! Note: the (udist/utime)**2 comes from adding physical units back onto u. + !energy_to_temperature_ratio = Rg/(mu*(gamma-1.))/(udist/utime)**2 + energy_to_temperature_ratio = kboltz/((gamma-1.)*mu*atomic_mass_unit)*(utime/udist)**2 + + !--Mass of hydrogen gas molecule in code units + mH = mu*mass_proton_cgs/umass + + !--Time at previous time step (Initialized to zero here) + prev_time = 0. + + !--photoevaporation grid's inner/outer radius and other dimensions + Rgrid_min = R_in + Rgrid_max = 1.3*R_out + Thetagrid_min = 0. + Thetagrid_max = pi + Phigrid_min = -pi + Phigrid_max = pi + + !--photoevaporation grid spacing in each direction (with Nr x Nphi x Ntheta nodes) + dr_grid = (Rgrid_max - Rgrid_min )/(Nr-1) + dtheta_grid = (Thetagrid_max - Thetagrid_min)/(Ntheta-1) + dphi_grid = (Phigrid_max - Phigrid_min )/(Nphi-1) + + !--photoevaporation grid in r,theta directions + r_grid = (/( Rgrid_min + dr_grid*i , i = 0, Nr-1 )/) + theta_grid = (/( Thetagrid_min + dtheta_grid*i, i = 0, Ntheta-1 )/) + + do i = 1,Ntheta-1 + do j = 1,Nr-1 + !--Calculate the volume of each grid cell (symmetrical in phi so only need two dimensional array) + rCellvol(j,i) = (0.5*(r_grid(j)+r_grid(j+1)))**2*sin(0.5*(theta_grid(i)+theta_grid(i+1)))*dr_grid*dtheta_grid*dphi_grid + enddo + + !--Calculate the ionization rate in each ray (symmetrical in phi so only need one dimensional array) + dN_ion(i) = (0.25/pi*sin(0.5*(theta_grid(j)+theta_grid(j+1)))*dtheta_grid*dphi_grid)*ionflux + enddo + + !--Because the reciprical of Cellvol is only ever used: rCellvol = 1/Cellvol + rCellvol = 1./rCellvol + +end subroutine set_photoevap_grid + +!----------------------------------------------------------------------- +!+ +! Subroutine to identify in which grid cell particles reside, solve the +! ionization/recombination balance for each ray, and finally find the +! location for the ionization front. +!+ +!----------------------------------------------------------------------- +subroutine find_ionfront(timei,npart,xyzh,pmassi) + use io, only:fatal + integer, intent(in) :: npart + real, intent(in) :: timei + real, intent(in) :: pmassi + real, intent(in) :: xyzh(:,:) + + integer :: i,j,k + + !--Cumulative sum of particles along ray just below current cell + integer :: curr_ray_count + + !--Change in # of ions per unit time due to recombination rate + real :: dN_recomb + + !--Position of particle in spherical coordinates + real :: r_pos,theta_pos,phi_pos + + real :: pmass_on_mH + real :: dt + + !--Find how much time has elapsed since the last call + dt = timei - prev_time + + if ( dt == 0. ) then + print*,'WARNING! find_ionfront was called needlessly!' + else + + !--Gives the number of hydrogen gas molecules per SPH particle + pmass_on_mH = pmassi/mH + +!$omp parallel do private(i,r_pos,theta_pos,phi_pos) schedule(static) + do i = 1,npart + r_pos = sqrt(sum(xyzh(1:3,i)**2)) + theta_pos = acos(xyzh(3,i)/r_pos) + phi_pos = atan2(xyzh(2,i),xyzh(1,i)) + + ! Find the (*INTEGER*) grid node just below the particle in each direction + Rnum(i) = int((r_pos-Rgrid_min)/dr_grid)+1 + Thetanum(i) = int((theta_pos-Thetagrid_min)/dtheta_grid)+1 + Phinum(i) = int((phi_pos-Phigrid_min)/dphi_grid)+1 + enddo +!$omp end parallel do + + !--Re-initialize/re-calculate Cellpartnum every time step + Cellpartnum = 0 +!$omp parallel do private(i) schedule(static) + do i = 1,npart + Cellpartnum(Rnum(i),Thetanum(i),Phinum(i)) = Cellpartnum(Rnum(i),Thetanum(i),Phinum(i)) + 1 + enddo +!$omp end parallel do + + !--Find the total number of particles along each ray (used to speed up loop below if ray is empty) + Raypartnum(:,:) = sum(Cellpartnum,1) + + ! + !--Solve for ionization/recombination balance and update Nion, ionization + ! front, and fraction of ionized particles at the front + ! +!$omp parallel do default(none) & +!$omp private(i,j,k,dN_recomb,curr_ray_count) & +!$omp shared(Ionfrac,Ionfront,Raypartnum,Cellpartnum,rCellvol,recombrate,dN_ion,Nion,dt,pmass_on_mH) & +!$omp schedule(dynamic) + do i = 1,Nphi-1 + do j = 1,Ntheta-1 + !--Save radial location of ionfront for current ray in k + k = Ionfront(j,i) + + !--Find the change in Nion due to recombination + if ( k == 1 ) then + dN_recomb = Ionfrac(j,i)*Cellpartnum(k,j,i)**2*rCellvol(k,j) + else + dN_recomb = sum(Cellpartnum(1:k-1,j,i)**2*rCellvol(1:k-1,j)) + Ionfrac(j,i)*Cellpartnum(k,j,i)**2*rCellvol(k,j) + endif + dN_recomb = recombrate*dN_recomb*pmass_on_mH + + !--Update the # of ionized particles in each radial column + if ( Raypartnum(j,i) > 0 ) then + Nion(j,i) = Nion(j,i) + nint(dt*(dN_ion(j)/pmass_on_mH-dN_recomb)) + + !--Make sure that flux doesn't "build-up" in the fully ionized columns + ! (i.e. the excess light escapes the system) + if ( Nion(j,i) > Raypartnum(j,i) ) then + Nion(j,i) = Raypartnum(j,i) + endif + +!!!!!! +! print*,dN_ion(j)/pmass_on_mH,dN_recomb,Nion(j,i) +!!!!!! + + if ( Nion(j,i) < 0 ) then + print*,'Warning! Negative ion number!',Nion(j,i),j,i + Nion(j,i) = 0 + endif + else + Nion(j,i) = 0 !--If no particles, then Nion must be reset + endif + + !--Now that we have the # of ions in each column, integrate from the star + ! out to Nion to find where the ionization front is located + k = 1 + curr_ray_count = Cellpartnum(k,j,i) + do while ( curr_ray_count < Nion(j,i) ) + if ( k < Nr-1 ) then + k = k+1 + else + exit + endif + curr_ray_count = curr_ray_count + Cellpartnum(k,j,i) + enddo + + !--Save the new ionization front radial cell # for the next iteration + Ionfront(j,i) = k + + !--Find the fraction of ions to neutrals in the ionization front + ! This only needs to be done for cells with more particles than Nion + if ( Raypartnum(j,i) <= Nion(j,i) ) then + Ionfrac(j,i) = 1. + else + if ( Cellpartnum(k,j,i) == 0 ) then + Ionfrac(j,i) = 1. + else + Ionfrac(j,i) = (Nion(j,i)-(curr_ray_count-Cellpartnum(k,j,i)))/real(Cellpartnum(k,j,i)) + endif + endif + + if ( Ionfrac(j,i) < 0 ) then + call fatal('find_ionfront','Ionfrac is less than zero!') + elseif ( Ionfrac(j,i) > 1 ) then + call fatal('find_ionfront','Ionfrac is greater than 1!') + endif + + enddo + enddo +!$omp end parallel do + + prev_time = timei + endif + +end subroutine find_ionfront + +!----------------------------------------------------------------------- +!+ +! Update the temperatures of the particles (Ionized,Boundary,Neutral) +!+ +!----------------------------------------------------------------------- +subroutine photo_ionize(vxyzu,npart) + use io, only:fatal + integer, intent(in) :: npart + real, intent(inout) :: vxyzu(:,:) + + integer :: ipart + + !--Temperature of the particle in Kelvin + real :: temperature,tempi + + if ( size(vxyzu,1) /= 4 ) then + call fatal('photoevap','no u in vxyzu variable: compile with ISOTHERMAL=no') + endif + +!$omp parallel do default(none) & +!$omp private(ipart,tempi,temperature) & +!$omp shared(npart,vxyzu,energy_to_temperature_ratio,Rnum,Thetanum,Phinum,Ionfrac,Ionfront,temp_ion) + do ipart = 1,npart + tempi = vxyzu(4,ipart)/energy_to_temperature_ratio + + if ( Rnum(ipart) < Ionfront(Thetanum(ipart),Phinum(ipart)).or. & + Rnum(ipart) >= Nr ) then + ! Above ionization front (ionized particles) + temperature = temp_ion + + elseif ( Rnum(ipart) == Ionfront(Thetanum(ipart),Phinum(ipart)) ) then + ! Ionization front (fractionally ionized) + temperature = Ionfrac(Thetanum(ipart),Phinum(ipart))*temp_ion + & + (1.-Ionfrac(Thetanum(ipart),Phinum(ipart)))*tempi + + else + ! Below ionization front (neutral particles) + temperature = tempi + + endif + + vxyzu(4,ipart) = temperature*energy_to_temperature_ratio + + enddo +!$omp end parallel do + +end subroutine photo_ionize + +!----------------------------------------------------------------------- +!+ +! writes input options to the input file +!+ +!----------------------------------------------------------------------- +subroutine write_options_photoevap(iunit) + use infile_utils, only:write_inopt + + integer, intent(in) :: iunit + + write(iunit,"(/,a)") '# options controlling photoevaporation' + call write_inopt(mu_cgs,'mu_cgs','Mean molecular weight',iunit) + call write_inopt(recombrate_cgs,'recombrate_cgs','Recombination rate (alpha)',iunit) + call write_inopt(ionflux_cgs,'ionflux_cgs','Stellar EUV flux rate',iunit) + +end subroutine write_options_photoevap + +!----------------------------------------------------------------------- +!+ +! reads input options from the input file +!+ +!----------------------------------------------------------------------- +subroutine read_options_photoevap(name,valstring,imatch,igotall,ierr) + use units, only:udist,utime + + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotall + integer, intent(out) :: ierr + integer, save :: ngot = 0 + + imatch = .false. + igotall = .true. + ierr = 0 + + select case(trim(name)) + case('mu_cgs') + read(valstring,*,iostat=ierr) mu_cgs + mu = mu_cgs + ngot = ngot + 1 + case('recombrate_cgs') + read(valstring,*,iostat=ierr) recombrate_cgs + recombrate = recombrate_cgs*utime/udist**3 + ngot = ngot + 1 + case('ionflux_cgs') + read(valstring,*,iostat=ierr) ionflux_cgs + ionflux = ionflux_cgs*utime + ngot = ngot + 1 + case default + imatch = .false. + end select + igotall = ( ngot >= 3 ) + +end subroutine read_options_photoevap + +end module photoevap diff --git a/src/main/physcon.f90 b/src/main/physcon.f90 index c931aa688..4c5a01af9 100644 --- a/src/main/physcon.f90 +++ b/src/main/physcon.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module physcon ! diff --git a/src/main/ptmass.F90 b/src/main/ptmass.F90 index d4fabe75d..2e9ef1788 100644 --- a/src/main/ptmass.F90 +++ b/src/main/ptmass.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module ptmass ! @@ -40,7 +40,8 @@ module ptmass use part, only:nsinkproperties,gravity,is_accretable use io, only:iscfile,iskfile,id,master implicit none - + character(len=80), parameter, public :: & ! module version + modid="$Id$" public :: init_ptmass, finish_ptmass public :: pt_write_sinkev, pt_close_sinkev public :: get_accel_sink_gas, get_accel_sink_sink @@ -850,16 +851,18 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,time) use part, only:ihacc,ihsoft,igas,iamtype,get_partinfo,iphase,iactive,maxphase,rhoh, & ispinx,ispiny,ispinz,fxyz_ptmass_sinksink,eos_vars,igasP - use dim, only:maxp,maxneigh,maxvxyzu,maxptmass,ind_timesteps + use dim, only:maxp,maxneigh,maxvxyzu,maxptmass use kdtree, only:getneigh use kernel, only:kernel_softening,radkern use io, only:id,iprint,fatal,iverbose,nprocs #ifdef PERIODIC use boundary, only:dxbound,dybound,dzbound #endif +#ifdef IND_TIMESTEPS use part, only:ibin,ibin_wake +#endif use linklist, only:getneigh_pos,ifirstincell,listneigh=>listneigh_global - use eos, only:gamma + use eos, only:gamma,utherm use eos_barotropic,only:gamma_barotropic use eos_piecewise, only:gamma_pwp use options, only:ieos @@ -876,10 +879,13 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote real, intent(inout) :: xyzmh_ptmass(:,:) real, intent(inout) :: vxyz_ptmass(:,:),fxyz_ptmass(:,:) real, intent(in) :: time - integer(kind=1) :: iphasei,ibin_wakei,ibin_itest + integer(kind=1) :: iphasei,ibin_wakei integer :: nneigh integer, parameter :: maxcache = 12000 integer, parameter :: nneigh_thresh = 1024 ! approximate epot if neigh>neigh_thresh; (-ve for off) +#ifdef IND_TIMESTEPS + integer(kind=1) :: ibin_itest +#endif real, save :: xyzcache(maxcache,3) real :: dptmass(ndptmass,nptmass+1) real :: xi,yi,zi,hi,hi1,hi21,xj,yj,zj,hj1,hj21,xk,yk,zk,hk1 @@ -931,7 +937,9 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote vzi = vxyzu(3,itest) iphasei = iphase(itest) divvi = divcurlv(1,itest) - if (ind_timesteps) ibin_itest = ibin(itest) +#ifdef IND_TIMESTEPS + ibin_itest = ibin(itest) +#endif if (gravity) poteni = poten(itest) endif ! @@ -946,8 +954,10 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote call bcast_mpi(vzi,id_rhomax) call bcast_mpi(iphasei,id_rhomax) call bcast_mpi(divvi,id_rhomax) - if (ind_timesteps) call bcast_mpi(ibin_itest,id_rhomax) - if (gravity) call bcast_mpi(poteni,id_rhomax) +#ifdef IND_TIMESTEPS + call bcast_mpi(ibin_itest,id_rhomax) +#endif + call bcast_mpi(poteni,id_rhomax) ! ! determine radius in which to check the criteria ! @@ -1027,7 +1037,9 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote #ifdef PERIODIC !$omp shared(dxbound,dybound,dzbound) & #endif +#ifdef IND_TIMESTEPS !$omp shared(ibin_wake,ibin_itest) & +#endif !$omp private(n,j,xj,yj,zj,hj1,hj21,psoftj,rij2,nk,k,xk,yk,zk,hk1,psoftk,rjk2,psofti,rik2) & !$omp private(dx,dy,dz,dvx,dvy,dvz,dv2,isgasj,isdustj) & !$omp private(rhoj,q2i,qi,fsoft,rcrossvx,rcrossvy,rcrossvz,radxy2,radyz2,radxz2) & @@ -1065,13 +1077,13 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote rij2 = dx*dx + dy*dy + dz*dz if (rij2 < hcheck2) then - if (ind_timesteps) then - ibin_wake(j) = max(ibin_wake(j),ibin_itest) - if (.not.iactivej .or. ifail==inosink_active) then - ifail = inosink_active - cycle over_neigh - endif +#ifdef IND_TIMESTEPS + ibin_wake(j) = max(ibin_wake(j),ibin_itest) + if (.not.iactivej .or. ifail==inosink_active) then + ifail = inosink_active + cycle over_neigh endif +#endif nneigh_act = nneigh_act + 1 @@ -1103,7 +1115,7 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote if (itypej==igas) then rhoj = rhoh(xyzh(4,j),pmassj) if (maxvxyzu >= 4) then - etherm = etherm + pmassj*vxyzu(4,j) + etherm = etherm + pmassj*utherm(vxyzu(:,j),rhoj,gamma) else if (ieos==2 .and. gamma > 1.001) then etherm = etherm + pmassj*(eos_vars(igasP,j)/rhoj)/(gamma - 1.) diff --git a/src/main/ptmass_heating.f90 b/src/main/ptmass_heating.F90 similarity index 82% rename from src/main/ptmass_heating.f90 rename to src/main/ptmass_heating.F90 index 370c6103c..dd265338b 100644 --- a/src/main/ptmass_heating.f90 +++ b/src/main/ptmass_heating.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module ptmass_heating ! @@ -48,4 +48,15 @@ subroutine energ_sinkheat(nptmass,xyzmh_ptmass,xi,yi,zi,dudtheati) end subroutine energ_sinkheat +!----------------------------------------------------------------------- +!+ +! Heating from nuclear burning +!+ +!----------------------------------------------------------------------- +! subroutine nuc_heating() + + +! end subroutine nuc_heating + + end module ptmass_heating diff --git a/src/main/ptmass_radiation.f90 b/src/main/ptmass_radiation.F90 similarity index 99% rename from src/main/ptmass_radiation.f90 rename to src/main/ptmass_radiation.F90 index f2cb966d2..21d075dc4 100644 --- a/src/main/ptmass_radiation.f90 +++ b/src/main/ptmass_radiation.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module ptmass_radiation ! diff --git a/src/main/quitdump.f90 b/src/main/quitdump.f90 index f06e2bb2f..1e93a9595 100644 --- a/src/main/quitdump.f90 +++ b/src/main/quitdump.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module quitdump ! diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index 5f354fa34..3cabc2937 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module radiation_implicit ! @@ -56,9 +56,7 @@ module radiation_implicit !+ !--------------------------------------------------------- subroutine do_radiation_implicit(dt,npart,rad,xyzh,vxyzu,radprop,drad,ierr) - use io, only:fatal,warning - use timing, only:get_timings - use derivutils, only:do_timing + use io, only:fatal,warning integer, intent(in) :: npart real, intent(in) :: dt,xyzh(:,:) real, intent(inout) :: radprop(:,:),rad(:,:),vxyzu(:,:),drad(:,:) @@ -66,7 +64,6 @@ subroutine do_radiation_implicit(dt,npart,rad,xyzh,vxyzu,radprop,drad,ierr) integer :: nsubsteps,i,nit logical :: failed,moresweep real :: dtsub,errorE,errorU - real(kind=4) :: tlast,tcpulast real, allocatable :: origEU(:,:),EU0(:,:) ierr = 0 @@ -74,9 +71,7 @@ subroutine do_radiation_implicit(dt,npart,rad,xyzh,vxyzu,radprop,drad,ierr) allocate(origEU(2,npart),EU0(2,npart),stat=ierr) if (ierr/=0) call fatal('radiation_implicit','could not allocate memory to origEU and EU0') - call get_timings(tlast,tcpulast) call save_radiation_energies(npart,rad,xyzh,vxyzu,radprop,drad,origEU,.false.) - call do_timing('radsave',tlast,tcpulast,start=.true.) nsubsteps = 1 moresweep = .true. @@ -84,18 +79,14 @@ subroutine do_radiation_implicit(dt,npart,rad,xyzh,vxyzu,radprop,drad,ierr) moresweep = .false. dtsub = dt/nsubsteps over_substeps: do i = 1,nsubsteps - call do_radiation_onestep(dtsub,npart,rad,xyzh,vxyzu,radprop,origEU,EU0,failed,nit,errorE,errorU,moresweep,ierr) + call do_radiation_onestep(dtsub,rad,xyzh,vxyzu,radprop,origEU,EU0,failed,nit,errorE,errorU,moresweep,ierr) if (failed .or. moresweep) then ierr = ierr_failed_to_converge call warning('radiation_implicit','integration failed - using U and E values anyway') moresweep = .false. !exit over_substeps endif - if (i /= nsubsteps) then - call get_timings(tlast,tcpulast) - call save_radiation_energies(npart,rad,xyzh,vxyzu,radprop,drad,origEU,.true.) - call do_timing('radsave',tlast,tcpulast) - endif + if (i /= nsubsteps) call save_radiation_energies(npart,rad,xyzh,vxyzu,radprop,drad,origEU,.true.) enddo over_substeps !if (moresweep) then @@ -145,131 +136,74 @@ end subroutine save_radiation_energies ! perform single iteration !+ !--------------------------------------------------------- -subroutine do_radiation_onestep(dt,npart,rad,xyzh,vxyzu,radprop,origEU,EU0,failed,nit,errorE,errorU,moresweep,ierr) +subroutine do_radiation_onestep(dt,rad,xyzh,vxyzu,radprop,origEU,EU0,failed,nit,errorE,errorU,moresweep,ierr) use io, only:fatal,error,iverbose,warning use part, only:hfact - use part, only:pdvvisc=>luminosity,dvdx,nucleation,dust_temp,eos_vars,drad,iradxi,fxyzu use physcon, only:pi use kernel, only:radkern - use timing, only:get_timings - use derivutils, only:do_timing - use options, only:implicit_radiation_store_drad real, intent(in) :: dt,xyzh(:,:),origEU(:,:) - integer, intent(in) :: npart real, intent(inout) :: radprop(:,:),rad(:,:),vxyzu(:,:) logical, intent(out) :: failed,moresweep integer, intent(out) :: nit,ierr - real, intent(out) :: errorE,errorU,EU0(2,npart) + real, intent(out) :: errorE,errorU,EU0(:,:) integer, allocatable :: ivar(:,:),ijvar(:) - integer :: ncompact,ncompactlocal,icompactmax,nneigh_average,its_global,its + integer :: ncompact,ncompactlocal,npart,icompactmax,nneigh_average,its real, allocatable :: vari(:,:),varij(:,:),varij2(:,:),varinew(:,:) - real :: maxerrE2,maxerrU2,maxerrE2last,maxerrU2last - real(kind=4) :: tlast,tcpulast,t1,tcpu1 + real :: maxerrE2,maxerrU2,maxerrE2last,maxerrU2last logical :: converged - call get_timings(tlast,tcpulast) - failed = .false. errorE = 0. errorU = 0. ierr = 0 + npart = size(xyzh(1,:)) nneigh_average = int(4./3.*pi*(radkern*hfact)**3) + 1 - icompactmax = int(1.2*10.*nneigh_average*npart) + icompactmax = int(1.2*nneigh_average*npart) allocate(ivar(3,npart),stat=ierr) if (ierr/=0) call fatal('radiation_implicit','cannot allocate memory for ivar') allocate(ijvar(icompactmax),stat=ierr) if (ierr/=0) call fatal('radiation_implicit','cannot allocate memory for ijvar') - allocate(vari(2,npart),varij(2,icompactmax),varij2(4,icompactmax),varinew(3,npart),stat=ierr) + allocate(vari(2,npart),varij(4,icompactmax),varij2(3,icompactmax),varinew(3,npart),stat=ierr) if (ierr/=0) call fatal('radiation_implicit','cannot allocate memory for vari, varij, varij2, varinew') !dtimax = dt/imaxstep call get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) - ! check for errors if (ncompact <= 0 .or. ncompactlocal <= 0) then call error('radiation_implicit','empty neighbour list - need to call set_linklist first?') ierr = ierr_neighbourlist_empty return endif - - call do_timing('radneighlist',tlast,tcpulast,start=.true.) - - !$omp parallel default(none) & - !$omp shared(tlast,tcpulast,ncompact,ncompactlocal,npart,icompactmax,dt,its_global) & - !$omp shared(xyzh,vxyzu,ivar,ijvar,varinew,radprop,rad,vari,varij,varij2,origEU,EU0) & - !$omp shared(pdvvisc,dvdx,nucleation,dust_temp,eos_vars,drad,fxyzu,implicit_radiation_store_drad) & - !$omp shared(converged,maxerrE2,maxerrU2,maxerrE2last,maxerrU2last,itsmax_rad,moresweep,tol_rad,iverbose,ierr) & - !$omp private(t1,tcpu1,its) call fill_arrays(ncompact,ncompactlocal,npart,icompactmax,dt,& xyzh,vxyzu,ivar,ijvar,radprop,rad,vari,varij,varij2,EU0) - !$omp master - call do_timing('radarrays',tlast,tcpulast) - !$omp end master - - !$omp single maxerrE2last = huge(0.) maxerrU2last = huge(0.) - !$omp end single iterations: do its=1,itsmax_rad - - !$omp master - call get_timings(t1,tcpu1) - !$omp end master - call compute_flux(ivar,ijvar,ncompact,npart,icompactmax,varij2,vari,EU0,varinew,radprop) - !$omp master - call do_timing('radflux',t1,tcpu1) - !$omp end master + call compute_flux(ivar,ijvar,ncompact,npart,icompactmax,varij,varij2,vari,EU0,varinew,radprop) call calc_lambda_and_eddington(ivar,ncompactlocal,npart,vari,EU0,radprop,ierr) - !$omp master - call do_timing('radlambda',t1,tcpu1) - !$omp end master call calc_diffusion_term(ivar,ijvar,varij,ncompact,npart,icompactmax,radprop,vari,EU0,varinew,ierr) - !$omp master - call do_timing('raddiff',t1,tcpu1) - !$omp end master - - call update_gas_radiation_energy(ivar,vari,ncompact,npart,ncompactlocal,& - radprop,rad,origEU,varinew,EU0,& - pdvvisc,dvdx,nucleation,dust_temp,eos_vars,drad,fxyzu,& - implicit_radiation_store_drad,moresweep,maxerrE2,maxerrU2) - - !$omp master - call do_timing('radupdate',t1,tcpu1) - !$omp end master - - !$omp single - if (iverbose >= 2) then - print*,'iteration: ',its,' error = ',maxerrE2,maxerrU2 - endif - converged = (maxerrE2 <= tol_rad .and. maxerrU2 <= tol_rad) - maxerrU2last = maxerrU2 - !$omp end single + call update_gas_radiation_energy(ivar,ijvar,vari,ncompact,npart,ncompactlocal,& + vxyzu,radprop,rad,origEU,varinew,EU0,moresweep,maxerrE2,maxerrU2) + if (iverbose >= 2) print*,'iteration: ',its,' error = ',maxerrE2,maxerrU2 + converged = (maxerrE2 <= tol_rad .and. maxerrU2 <= tol_rad) if (converged) exit iterations + maxerrU2last = maxerrU2 enddo iterations - !$omp single - its_global = its ! save the iteration count, should be same on all threads - !$omp end single - - !$omp end parallel - if (converged) then if (iverbose >= 0) print "(1x,a,i4,a,es10.3,a,es10.3)", & - trim(label)//': succeeded with ',its_global,' iterations: xi err:',maxerrE2,' u err:',maxerrU2 + trim(label)//': succeeded with ',its,' iterations: xi err:',maxerrE2,' u err:',maxerrU2 else call warning('radiation_implicit','maximum iterations reached') moresweep = .true. endif - nit = its - call do_timing('radits',tlast,tcpulast) call store_radiation_results(ncompactlocal,npart,ivar,EU0,rad,vxyzu) - call do_timing('radstore',tlast,tcpulast) end subroutine do_radiation_onestep @@ -294,14 +228,15 @@ subroutine get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) integer :: icompact_private,icompact,icompactmax,iamtypei,nneigh_trial integer, parameter :: maxcellcache = 10000 integer, save, allocatable :: neighlist(:) - real :: dx,dy,dz,hi21,hj1,rij2,q2i,q2j + real :: dx,dy,dz,hi21,rij2,q2i real, save, allocatable :: xyzcache(:,:) + !real, save :: xyzcache(maxcellcache,3) !$omp threadprivate(xyzcache,neighlist) logical :: iactivei,iamdusti,iamgasi if (.not. allocated(neighlist)) then !$omp parallel - allocate(neighlist(size(xyzh(1,:))),xyzcache(maxcellcache,4)) + allocate(neighlist(size(xyzh(1,:))),xyzcache(maxcellcache,3)) !$omp end parallel endif @@ -309,11 +244,11 @@ subroutine get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) ncompactlocal = 0 icompact = 0 icompactmax = size(ijvar) - !$omp parallel do default(none) schedule(runtime)& + !$omp parallel do schedule(runtime)& !$omp shared(ncells,xyzh,inodeparts,inoderange,iphase,dxbound,dybound,dzbound,ifirstincell)& - !$omp shared(ivar,ijvar,ncompact,icompact,icompactmax,maxphase,maxp)& - !$omp private(icell,i,j,k,n,ip,iactivei,iamgasi,iamdusti,iamtypei,dx,dy,dz,rij2,q2i,q2j)& - !$omp private(hi21,hj1,ncompact_private,icompact_private,nneigh_trial,nneigh) + !$omp shared(ncompact,icompact,icompactmax)& + !$omp private(icell,i,j,k,n,ip,iactivei,iamgasi,iamdusti,iamtypei,dx,dy,dz,rij2,q2i)& + !$omp private(hi21,ncompact_private,icompact_private,nneigh_trial,nneigh) over_cells: do icell=1,int(ncells) i = ifirstincell(icell) @@ -324,7 +259,7 @@ subroutine get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) ! !--get the neighbour list and fill the cell cache ! - call get_neighbour_list(icell,listneigh,nneigh_trial,xyzh,xyzcache,maxcellcache,getj=.true.) + call get_neighbour_list(icell,listneigh,nneigh_trial,xyzh,xyzcache,maxcellcache) over_parts: do ip = inoderange(1,icell),inoderange(2,icell) i = inodeparts(ip) @@ -355,12 +290,10 @@ subroutine get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) dx = xyzh(1,i) - xyzcache(n,1) dy = xyzh(2,i) - xyzcache(n,2) dz = xyzh(3,i) - xyzcache(n,3) - hj1 = xyzcache(n,4) else dx = xyzh(1,i) - xyzh(1,j) dy = xyzh(2,i) - xyzh(2,j) dz = xyzh(3,i) - xyzh(3,j) - hj1 = 1./xyzh(4,j) endif if (periodic) then if (abs(dx) > 0.5*dxbound) dx = dx - dxbound*SIGN(1.0,dx) @@ -369,11 +302,10 @@ subroutine get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) endif rij2 = dx*dx + dy*dy + dz*dz q2i = rij2*hi21 - q2j = rij2*hj1*hj1 ! !--do interaction if r/h < compact support size ! - is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then + is_sph_neighbour: if (q2i < radkern2) then ! .or. q2j < radkern2) then nneigh = nneigh + 1 neighlist(nneigh) = j endif is_sph_neighbour @@ -423,26 +355,29 @@ subroutine fill_arrays(ncompact,ncompactlocal,npart,icompactmax,dt,xyzh,vxyzu,iv integer, intent(in) :: ivar(:,:),ijvar(:) real, intent(in) :: dt,xyzh(:,:),vxyzu(:,:),rad(:,:) real, intent(inout) :: radprop(:,:) - real, intent(out) :: vari(:,:),EU0(2,npart),varij(2,icompactmax),varij2(4,icompactmax) + real, intent(out) :: vari(:,:),EU0(2,npart),varij(4,icompactmax),varij2(3,icompactmax) integer :: n,i,j,k,icompact real :: cv_effective,pmi,hi,hi21,hi41,rhoi,dx,dy,dz,rij2,rij,rij1,dr,dti,& dvxdxi,dvxdyi,dvxdzi,dvydxi,dvydyi,dvydzi,dvzdxi,dvzdyi,dvzdzi,& pmj,rhoj,hj,hj21,hj41,v2i,vi,v2j,vj,dWi,dWj,dvx,dvy,dvz,rhomean,& dvdotdr,dv,vmu,dvdWimj,dvdWimi,dvdWjmj,c_code,& - dWidrlightrhorhom,dWjdrlightrhorhom,& + dWidrlightrhorhom,dWiidrlightrhorhom,dWjdrlightrhorhom,& pmjdWrijrhoi,pmjdWrunix,pmjdWruniy,pmjdWruniz,& dust_kappai,dust_cooling,heatingISRi,dust_gas c_code = get_c_code() - !$omp do & - !$omp private(n,i,j,k,rhoi,icompact,pmi,dvxdxi,dvxdyi,dvxdzi,dvydxi,dvydyi,dvydzi,dti) & + dti = dt + !$omp parallel do default(none) & + !$omp shared(EU0,radprop,rad,xyzh,vxyzu,c_code,vari,ivar,ijvar,varij,varij2,dvdx,dxbound,dybound,dzbound) & + !$omp shared(dust_temp,ncompactlocal,ncompact,massoftype,iopacity_type,nucleation,dt,gradh,cv_type) & + !$omp firstprivate(dti) & + !$omp private(n,i,j,k,rhoi,icompact,pmi,dvxdxi,dvxdyi,dvxdzi,dvydxi,dvydyi,dvydzi) & !$omp private(dvzdxi,dvzdyi,dvzdzi,dx,dy,dz,rij2,rij,rij1,dr,pmj,rhoj,hi,hj,hi21,hj21,hi41,hj41) & !$omp private(v2i,vi,v2j,vj,dWi,dWj,dvx,dvy,dvz,rhomean,dvdotdr,dv,vmu,dvdWimj,dvdWimi,dvdWjmj) & - !$omp private(dWidrlightrhorhom,pmjdWrijrhoi,dWjdrlightrhorhom,cv_effective) & + !$omp private(dWidrlightrhorhom,pmjdWrijrhoi,dWjdrlightrhorhom,dWiidrlightrhorhom,cv_effective) & !$omp private(pmjdWrunix,pmjdWruniy,pmjdWruniz,dust_kappai,dust_cooling,heatingISRi,dust_gas) do n = 1,ncompact - dti = dt i = ivar(3,n) ! if (iphase(i) == 0) then EU0(1,i) = rad(iradxi,i) @@ -526,6 +461,8 @@ subroutine fill_arrays(ncompact,ncompactlocal,npart,icompactmax,dt,xyzh,vxyzu,iv dvy = vxyzu(2,i) - vxyzu(2,j) dvz = vxyzu(3,i) - vxyzu(3,j) + rhomean = 0.5*(rhoi+rhoj) + dvdotdr = dvx*dx + dvy*dy + dvz*dz dv = dvdotdr/dr @@ -542,6 +479,7 @@ subroutine fill_arrays(ncompact,ncompactlocal,npart,icompactmax,dt,xyzh,vxyzu,iv ! Coefficients for p(div(v))/rho term in gas energy equation (e.g. eq 26, Whitehouse & Bate 2004) dWidrlightrhorhom = c_code*dWi/dr*pmj/(rhoi*rhoj) + dWiidrlightrhorhom = c_code*dWi/dr*pmi/(rhoi*rhoj) dWjdrlightrhorhom = c_code*dWj/dr*pmj/(rhoi*rhoj) pmjdWrijrhoi = pmj*dWi*rij1/rhoi @@ -562,12 +500,13 @@ subroutine fill_arrays(ncompact,ncompactlocal,npart,icompactmax,dt,xyzh,vxyzu,iv dvzdzi = dvzdzi - dvz*pmjdWruniz varij(1,icompact) = rhoj - varij(2,icompact) = 0.5*(dWidrlightrhorhom+dWjdrlightrhorhom) + varij(2,icompact) = dWiidrlightrhorhom + varij(3,icompact) = dWidrlightrhorhom + varij(4,icompact) = dWjdrlightrhorhom varij2(1,icompact) = pmjdWrunix varij2(2,icompact) = pmjdWruniy varij2(3,icompact) = pmjdWruniz - varij2(4,icompact) = rhoj enddo dvdx(1,i) = real(dvxdxi,kind=kind(dvdx)) ! convert to real*4 explicitly to avoid warnings dvdx(2,i) = real(dvxdyi,kind=kind(dvdx)) @@ -583,7 +522,7 @@ subroutine fill_arrays(ncompact,ncompactlocal,npart,icompactmax,dt,xyzh,vxyzu,iv vari(2,n) = rhoi ! endif enddo - !$omp enddo + !$omp end parallel do end subroutine fill_arrays @@ -593,15 +532,16 @@ end subroutine fill_arrays ! compute radiative flux !+ !--------------------------------------------------------- -subroutine compute_flux(ivar,ijvar,ncompact,npart,icompactmax,varij2,vari,EU0,varinew,radprop) +subroutine compute_flux(ivar,ijvar,ncompact,npart,icompactmax,varij,varij2,vari,EU0,varinew,radprop) integer, intent(in) :: ivar(:,:),ijvar(:),ncompact,npart,icompactmax - real, intent(in) :: varij2(4,icompactmax),vari(2,npart),EU0(2,npart) + real, intent(in) :: varij(4,icompactmax),varij2(3,icompactmax),vari(2,npart),EU0(2,npart) real, intent(inout) :: radprop(:,:) real, intent(out) :: varinew(3,npart) ! we use this parallel loop to set varinew to zero integer :: i,j,k,n,icompact - real :: rhoi,rhoj,pmjdWrunix,pmjdWruniy,pmjdWruniz,dedxi,dedyi,dedzi,dradenij,rhoiEU0 + real :: rhoi,rhoj,pmjdWrunix,pmjdWruniy,pmjdWruniz,dedxi,dedyi,dedzi,dradenij - !$omp do schedule(runtime)& + !$omp parallel do default(none)& + !$omp shared(vari,ivar,EU0,varij2,ijvar,varij,ncompact,radprop,varinew)& !$omp private(i,j,k,n,dedxi,dedyi,dedzi,rhoi,rhoj,icompact)& !$omp private(pmjdWrunix,pmjdWruniy,pmjdWruniz,dradenij) @@ -616,18 +556,17 @@ subroutine compute_flux(ivar,ijvar,ncompact,npart,icompactmax,varij2,vari,EU0,va dedzi = 0. rhoi = vari(2,n) - rhoiEU0 = rhoi*EU0(1,i) do k = 1,ivar(1,n) icompact = ivar(2,n) + k j = ijvar(icompact) + rhoj = varij(1,icompact) pmjdWrunix = varij2(1,icompact) pmjdWruniy = varij2(2,icompact) pmjdWruniz = varij2(3,icompact) - rhoj = varij2(4,icompact) ! Calculates the gradient of E (where E=rho*e, and e is xi) - dradenij = rhoj*EU0(1,j) - rhoiEU0 + dradenij = rhoj*EU0(1,j) - rhoi*EU0(1,i) dedxi = dedxi + dradenij*pmjdWrunix dedyi = dedyi + dradenij*pmjdWruniy dedzi = dedzi + dradenij*pmjdWruniz @@ -637,7 +576,7 @@ subroutine compute_flux(ivar,ijvar,ncompact,npart,icompactmax,varij2,vari,EU0,va radprop(ifluxy,i) = dedyi radprop(ifluxz,i) = dedzi enddo - !$omp enddo + !$omp end parallel do end subroutine compute_flux @@ -655,13 +594,13 @@ subroutine calc_lambda_and_eddington(ivar,ncompactlocal,npart,vari,EU0,radprop,i integer, intent(in) :: ivar(:,:),ncompactlocal,npart real, intent(in) :: vari(:,:),EU0(2,npart) real, intent(inout) :: radprop(:,:) - integer, intent(out) :: ierr - integer :: n,i + integer :: n,i,ierr real :: rhoi,gradE1i,opacity,radRi ierr = 0 - !$omp do schedule(runtime)& - !$omp private(i,n,rhoi,gradE1i,opacity,radRi) & + !$omp parallel do default(none)& + !$omp shared(vari,ivar,radprop,ncompactlocal,EU0,dust_temp,nucleation,limit_radiation_flux) & + !$omp private(i,n,rhoi,gradE1i,opacity,radRi)& !$omp reduction(max:ierr) do n = 1,ncompactlocal i = ivar(3,n) @@ -688,7 +627,7 @@ subroutine calc_lambda_and_eddington(ivar,ncompactlocal,npart,vari,EU0,radprop,i radprop(ilambda,i) = (2. + radRi ) / (6. + 3.*radRi + radRi**2) ! Levermore & Pomraning's flux limiter (e.g. eq 12, Whitehouse & Bate 2004) radprop(iedd,i) = radprop(ilambda,i) + radprop(ilambda,i)**2 * radRi**2 ! e.g., eq 11, Whitehouse & Bate (2004) enddo - !$omp enddo + !$omp end parallel do end subroutine calc_lambda_and_eddington @@ -703,24 +642,24 @@ subroutine calc_diffusion_term(ivar,ijvar,varij,ncompact,npart,icompactmax, & use io, only:error use part, only:dust_temp,nucleation integer, intent(in) :: ivar(:,:),ijvar(:),ncompact,npart,icompactmax - real, intent(in) :: vari(:,:),varij(2,icompactmax),EU0(2,npart),radprop(:,:) + real, intent(in) :: vari(:,:),varij(4,icompactmax),EU0(2,npart),radprop(:,:) integer, intent(out) :: ierr real, intent(inout) :: varinew(3,npart) integer :: n,i,j,k,icompact - real :: rhoi,rhoj,opacityi,opacityj,bi,bj,b1,dWdrlightrhorhom + real :: rhoi,rhoj,opacityi,opacityj,bi,bj,b1 + real :: dWiidrlightrhorhom,dWidrlightrhorhom,dWjdrlightrhorhom real :: diffusion_numerator,diffusion_denominator,tempval1,tempval2 ierr = 0 - !$omp do schedule(runtime)& + !$omp parallel do default(none)& + !$omp shared(vari,varij,ivar,ijvar,radprop,ncompact,EU0,varinew,dust_temp,nucleation)& !$omp private(i,j,k,n,rhoi,rhoj,opacityi,opacityj,bi,bj,b1,diffusion_numerator,diffusion_denominator)& - !$omp private(dWdrlightrhorhom,tempval1,tempval2,icompact)& + !$omp private(dWiidrlightrhorhom,dWidrlightrhorhom,dWjdrlightrhorhom,tempval1,tempval2,icompact)& !$omp reduction(max:ierr) do n = 1,ncompact i = ivar(3,n) ! if (iphase(i) == 0) then rhoi = vari(2,n) - opacityi = radprop(ikappa,i) - bi = radprop(ilambda,i)/(opacityi*rhoi) ! !--NOTE: Needs to do this loop even for boundaryparticles because active ! boundary particles will need to contribute to the varinew() @@ -740,10 +679,13 @@ subroutine calc_diffusion_term(ivar,ijvar,varij,ncompact,npart,icompactmax, & icompact = ivar(2,n) + k j = ijvar(icompact) rhoj = varij(1,icompact) - dWdrlightrhorhom = varij(2,icompact) + dWiidrlightrhorhom = varij(2,icompact) + dWidrlightrhorhom = varij(3,icompact) + dWjdrlightrhorhom = varij(4,icompact) ! !--Set c*lambda/kappa*rho term (radiative diffusion coefficient) for current quantities ! + opacityi = radprop(ikappa,i) opacityj = radprop(ikappa,j) if (dustRT) then if (dust_temp(i) < Tdust_threshold) opacityi = nucleation(idkappa,i) @@ -753,6 +695,7 @@ subroutine calc_diffusion_term(ivar,ijvar,varij,ncompact,npart,icompactmax, & ierr = max(ierr,ierr_negative_opacity) call error(label,'Negative or zero opacity',val=min(opacityi,opacityj)) endif + bi = radprop(ilambda,i)/(opacityi*rhoi) bj = radprop(ilambda,j)/(opacityj*rhoj) ! !--Choose the 'average' diffusion value. The (bi+bj) quantity biased in @@ -762,13 +705,31 @@ subroutine calc_diffusion_term(ivar,ijvar,varij,ncompact,npart,icompactmax, & ! !--Diffusion numerator and denominator ! - diffusion_numerator = diffusion_numerator - dWdrlightrhorhom*b1*EU0(1,j)*rhoj - diffusion_denominator = diffusion_denominator + dWdrlightrhorhom*b1*rhoi + diffusion_numerator = diffusion_numerator - 0.5*dWidrlightrhorhom*b1*EU0(1,j)*rhoj + diffusion_denominator = diffusion_denominator + 0.5*dWidrlightrhorhom*b1*rhoi + ! + !--If particle j is active, need to add contribution due to i for hj + ! + ! if (iactive(iphase(j))) then ! + tempval1 = 0.5*dWiidrlightrhorhom*b1 + tempval2 = tempval1*rhoj + tempval1 = tempval1*EU0(1,i)*rhoi + !$omp atomic + varinew(1,j) = varinew(1,j) - tempval1 + !$omp atomic + varinew(2,j) = varinew(2,j) + tempval2 + ! else + ! diffusion_numerator = diffusion_numerator - 0.5*dWjdrlightrhorhom*b1*EU0(1,J)*rhoj + ! diffusion_denominator = diffusion_denominator + 0.5*dWjdrlightrhorhom*b1*rhoi + ! endif + ! ENDIF !--iphase(j)==0 enddo + !$omp atomic varinew(1,i) = varinew(1,i) + diffusion_numerator + !$omp atomic varinew(2,i) = varinew(2,i) + diffusion_denominator enddo - !$omp enddo + !$omp end parallel do end subroutine calc_diffusion_term @@ -777,22 +738,18 @@ end subroutine calc_diffusion_term ! update gas and radiation energy !+ !--------------------------------------------------------- -subroutine update_gas_radiation_energy(ivar,vari,ncompact,npart,ncompactlocal,& - radprop,rad,origEU,varinew,EU0,& - pdvvisc,dvdx,nucleation,dust_temp,eos_vars,drad,fxyzu, & - store_drad,moresweep,maxerrE2,maxerrU2) +subroutine update_gas_radiation_energy(ivar,ijvar,vari,ncompact,npart,ncompactlocal,& + vxyzu,radprop,rad,origEU,varinew,EU0,moresweep,maxerrE2,maxerrU2) use io, only:fatal,error + use part, only:pdvvisc=>luminosity,dvdx,nucleation,dust_temp,eos_vars,drad,iradxi,fxyzu use units, only:get_radconst_code,get_c_code,unit_density use physcon, only:mass_proton_cgs use eos, only:metallicity=>Z_in - integer, intent(in) :: ivar(:,:),ncompact,npart,ncompactlocal - real, intent(in) :: vari(:,:),varinew(3,npart),rad(:,:),origEU(:,:) - real(kind=4), intent(in) :: pdvvisc(:),dvdx(:,:) - real, intent(in) :: eos_vars(:,:) - real, intent(inout) :: drad(:,:),fxyzu(:,:),nucleation(:,:),dust_temp(:) + use options, only:implicit_radiation_store_drad + integer, intent(in) :: ivar(:,:),ijvar(:),ncompact,npart,ncompactlocal + real, intent(in) :: vari(:,:),varinew(3,npart),rad(:,:),origEU(:,:),vxyzu(:,:) real, intent(inout) :: radprop(:,:),EU0(2,npart) real, intent(out) :: maxerrE2,maxerrU2 - logical, intent(in) :: store_drad logical, intent(out):: moresweep integer :: i,j,n,ieqtype,ierr logical :: moresweep2,skip_quartic @@ -807,12 +764,13 @@ subroutine update_gas_radiation_energy(ivar,vari,ncompact,npart,ncompactlocal,& a_code = get_radconst_code() c_code = get_c_code() moresweep = .false. - !$omp single maxerrE2 = 0. maxerrU2 = 0. - !$omp end single - !$omp do schedule(runtime)& + !$omp parallel do default(none)& + !$omp shared(vari,ivar,ijvar,radprop,rad,ncompact,ncompactlocal,EU0,varinew) & + !$omp shared(dvdx,origEU,nucleation,dust_temp,eos_vars,implicit_radiation_store_drad,cv_type) & + !$omp shared(moresweep,pdvvisc,metallicity,vxyzu,iopacity_type,a_code,c_code,massoftype,drad,fxyzu) & !$omp private(i,j,n,rhoi,dti,diffusion_numerator,diffusion_denominator,U1i,skip_quartic,Tgas,E1i,dUcomb,dEcomb) & !$omp private(gradEi2,gradvPi,rpdiag,rpall,radpresdenom,stellarradiation,dust_tempi,dust_kappai,xnH2) & !$omp private(dust_cooling,heatingISRi,dust_gas,gas_dust_val,dustgammaval,gas_dust_cooling,cosmic_ray) & @@ -1047,10 +1005,10 @@ subroutine update_gas_radiation_energy(ivar,vari,ncompact,npart,ncompactlocal,& ! EU0(1,i) = E1i EU0(2,i) = U1i - radprop(icv,i) = get_cv(rhoi,EU0(2,i),cv_type) + radprop(icv,i) = get_cv(rhoi,EU0(2,i),cv_type) ! should this be EU0(2,i)?? radprop(ikappa,i) = get_kappa(iopacity_type,EU0(2,i),radprop(icv,i),rhoi) - if (store_drad) then ! use this for testing + if (implicit_radiation_store_drad) then ! use this for testing drad(iradxi,i) = (E1i - origEU(1,i))/dti ! dxi/dt fxyzu(4,i) = (U1i - origEU(2,i))/dti ! du/dt endif @@ -1062,7 +1020,7 @@ subroutine update_gas_radiation_energy(ivar,vari,ncompact,npart,ncompactlocal,& endif enddo main_loop -!$omp enddo +!$omp end parallel do end subroutine update_gas_radiation_energy diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 153928690..1465081a5 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module radiation_utils ! diff --git a/src/main/random.f90 b/src/main/random.f90 index 58d875b78..ec2d71988 100644 --- a/src/main/random.f90 +++ b/src/main/random.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module random ! diff --git a/src/main/readwrite_dumps.F90 b/src/main/readwrite_dumps.F90 index f2d82edc1..c437eb95f 100644 --- a/src/main/readwrite_dumps.F90 +++ b/src/main/readwrite_dumps.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module readwrite_dumps ! @@ -27,13 +27,8 @@ module readwrite_dumps public :: write_smalldump,write_fulldump,read_smalldump,read_dump,write_gadgetdump -#ifdef AOCC - logical, pointer, public :: opened_full_dump - logical, pointer, public :: dt_read_in -#else logical, pointer, public :: opened_full_dump => opened_full_dump_fortran ! for use in analysis files if user wishes to skip small dumps logical, pointer, public :: dt_read_in => dt_read_in_fortran ! to determine if dt has been read in so that ibin & ibinold can be set on restarts -#endif integer, parameter, public :: is_small_dump = 1978 integer, parameter, public :: is_not_mhd = 1979 diff --git a/src/main/readwrite_dumps_common.F90 b/src/main/readwrite_dumps_common.F90 index c68246def..63bed518e 100644 --- a/src/main/readwrite_dumps_common.F90 +++ b/src/main/readwrite_dumps_common.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module readwrite_dumps_common ! @@ -118,28 +118,27 @@ end subroutine get_options_from_fileid !--------------------------------------------------------------- subroutine check_arrays(i1,i2,noffset,npartoftype,npartread,nptmass,nsinkproperties,massoftype,& alphafile,tfile,phantomdump,got_iphase,got_xyzh,got_vxyzu,got_alpha, & - got_krome_mols,got_krome_gamma,got_krome_mu,got_krome_T, & + got_krome_mols,got_krome_gamma,got_krome_mu,got_krome_T,got_x,got_z,got_mu, & got_abund,got_dustfrac,got_sink_data,got_sink_vels,got_Bxyz,got_psi,got_dustprop,got_pxyzu,got_VrelVf, & - got_dustgasprop,got_rad,got_radprop,got_Tdust,got_eosvars,got_nucleation,got_iorig,iphase,& + got_dustgasprop,got_temp,got_raden,got_kappa,got_Tdust,got_nucleation,got_iorig,iphase,& xyzh,vxyzu,pxyzu,alphaind,xyzmh_ptmass,Bevol,iorig,iprint,ierr) use dim, only:maxp,maxvxyzu,maxalpha,maxBevol,mhd,h2chemistry,use_dustgrowth,gr,& - do_radiation,store_dust_temperature,do_nucleation,use_krome + do_radiation,store_dust_temperature,do_nucleation use eos, only:ieos,polyk,gamma,eos_is_non_ideal - use part, only:maxphase,isetphase,set_particle_type,igas,ihacc,ihsoft,imacc,ilum,ikappa,& - xyzmh_ptmass_label,vxyz_ptmass_label,get_pmass,rhoh,dustfrac,ndusttypes,norig,& - itemp,iX,iZ,imu + use part, only:maxphase,isetphase,set_particle_type,igas,ihacc,ihsoft,imacc,& + xyzmh_ptmass_label,vxyz_ptmass_label,get_pmass,rhoh,dustfrac,ndusttypes,norig use io, only:warning,id,master use options, only:alpha,use_dustfrac,use_var_comp use sphNGutils, only:itype_from_sphNG_iphase,isphNG_accreted use dust_formation, only:init_nucleation integer, intent(in) :: i1,i2,noffset,npartoftype(:),npartread,nptmass,nsinkproperties real, intent(in) :: massoftype(:),alphafile,tfile - logical, intent(in) :: phantomdump,got_iphase,got_xyzh(:),got_vxyzu(:),got_alpha(:),got_dustprop(:) - logical, intent(in) :: got_VrelVf,got_dustgasprop(:) + logical, intent(in) :: phantomdump,got_iphase,got_xyzh(:),got_vxyzu(:),got_alpha,got_dustprop(:) + logical, intent(in) :: got_VrelVf,got_dustgasprop(:),got_x,got_z,got_mu logical, intent(in) :: got_abund(:),got_dustfrac(:),got_sink_data(:),got_sink_vels(:),got_Bxyz(:) logical, intent(in) :: got_krome_mols(:),got_krome_gamma,got_krome_mu,got_krome_T - logical, intent(in) :: got_psi,got_Tdust,got_eosvars(:),got_nucleation(:),got_pxyzu(:),got_rad(:) - logical, intent(in) :: got_radprop(:),got_iorig + logical, intent(in) :: got_psi,got_temp,got_Tdust,got_nucleation(:),got_pxyzu(:),got_raden(:) + logical, intent(in) :: got_kappa,got_iorig integer(kind=1), intent(inout) :: iphase(:) integer(kind=8), intent(inout) :: iorig(:) real, intent(inout) :: vxyzu(:,:),Bevol(:,:),pxyzu(:,:) @@ -226,37 +225,37 @@ subroutine check_arrays(i1,i2,noffset,npartoftype,npartread,nptmass,nsinkpropert ierr = 9 return endif - if (use_krome) then - if (.not.all(got_krome_mols).and. npartread > 0) then - if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but abundances not found in dump file' - ! ierr = 9 - return - endif - if (.not.got_krome_gamma .and. npartread > 0) then - if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but gamma not found in dump file' - ! ierr = 9 - return - endif - if (.not.got_krome_mu .and. npartread > 0) then - if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but mu not found in dump file' - ! ierr = 9 - return - endif - if (.not.got_krome_T .and. npartread > 0) then - if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but temperature not found in dump file' - ! ierr = 9 - return - endif +#ifdef KROME + if (.not.all(got_krome_mols).and. npartread > 0) then + if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but abundances not found in dump file' +! ierr = 9 + return + endif + if (.not.got_krome_gamma .and. npartread > 0) then + if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but gamma not found in dump file' +! ierr = 9 + return endif - if (eos_is_non_ideal(ieos) .and. .not.got_eosvars(itemp)) then + if (.not.got_krome_mu .and. npartread > 0) then + if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but mu not found in dump file' +! ierr = 9 + return + endif + if (.not.got_krome_T .and. npartread > 0) then + if (id==master) write(*,*) 'error in rdump: using KROME chemistry, but temperature not found in dump file' +! ierr = 9 + return + endif +#endif + if (eos_is_non_ideal(ieos) .and. .not.got_temp) then if (id==master .and. i1==1) write(*,"(/,a,/)") 'WARNING: missing temperature information from file' endif - use_var_comp = (got_eosvars(iX) .and. got_eosvars(iZ) .and. got_eosvars(imu)) + use_var_comp = (got_x .and. got_z .and. got_mu) if (store_dust_temperature .and. .not.got_Tdust) then if (id==master .and. i1==1) write(*,"(/,a,/)") 'WARNING: missing dust temperature information from file' endif if (maxalpha==maxp) then - if (got_alpha(1)) then + if (got_alpha) then if (alphafile < 0.99 .and. tfile > 0.) then if (any(alphaind(1,i1:i2) > 1.0 .or. alphaind(1,i1:i2) < 0.)) then if (id==master) write(iprint,*) 'ERROR! AV alpha < 0 or alpha > 1 in dump file: using alpha' @@ -280,25 +279,27 @@ subroutine check_arrays(i1,i2,noffset,npartoftype,npartread,nptmass,nsinkpropert enddo endif if (use_dustfrac .and. .not. all(got_dustfrac(1:ndusttypes))) then - if (id==master .and. i1==1) write(*,*) 'WARNING! using one-fluid dust, but no dust fraction found in dump file' + if (id==master .and. i1==1) write(*,*) 'ERROR! using one-fluid dust, but no dust fraction found in dump file' if (id==master .and. i1==1) write(*,*) ' Setting dustfrac = 0' dustfrac = 0. + !ierr = 13 + return endif if (use_dustgrowth .and. .not.got_dustprop(1)) then - if (id==master) write(*,*) 'ERROR! using dustgrowth, but no grain size found in dump file' - ierr = ierr + 1 + write(*,*) 'ERROR! using dustgrowth, but no grain size found in dump file' + return endif - if (use_dustgrowth .and. .not.got_dustprop(2)) then - if (id==master) write(*,*) 'ERROR! using dustgrowth, but no grain density found in dump file' - ierr = ierr + 1 + if (use_dustgrowth .and. .not.got_dustprop(1)) then + write(*,*) 'ERROR! using dustgrowth, but no grain density found in dump file' + return endif if (use_dustgrowth .and. .not.got_VrelVf) then - if (id==master) write(*,*) 'ERROR! using dustgrowth, but no Vrel/Vfrag found in dump file' - ierr = ierr + 1 + write(*,*) 'ERROR! using dustgrowth, but no Vrel/Vfrag found in dump file' + return endif if (use_dustgrowth .and. .not.got_dustgasprop(3)) then - if (id==master) write(*,*) 'ERROR! using dustgrowth, but no St found in dump file' - ierr = ierr + 1 + write(*,*) 'ERROR! using dustgrowth, but no St found in dump file' + return endif ! ! sink particle arrays @@ -321,24 +322,24 @@ subroutine check_arrays(i1,i2,noffset,npartoftype,npartread,nptmass,nsinkpropert endif if (id==master .and. i1==1) then print "(2(a,i4),a)",' got ',nsinkproperties,' sink properties from ',nptmass,' sink particles' - if (nptmass > 0) print "(1x,58('-'),/,1x,a,'|',5(a9,1x,'|'),/,1x,58('-'))",& - 'ID',' Mass ',' Racc ',' Macc ',' hsoft ',' Lsink ' + if (nptmass > 0) print "(1x,47('-'),/,1x,a,'|',4(a9,1x,'|'),/,1x,47('-'))",& + 'ID',' Mass ',' Racc ',' Macc ',' hsoft ' do i=1,min(nptmass,999) - if (xyzmh_ptmass(4,i) > 0.) print "(i3,'|',5(1pg9.2,1x,'|'))",i,xyzmh_ptmass(4,i),xyzmh_ptmass(ihacc,i),& - xyzmh_ptmass(imacc,i),xyzmh_ptmass(ihsoft,i),xyzmh_ptmass(ilum,i) + if (xyzmh_ptmass(4,i) > 0.) print "(i3,'|',4(1pg9.2,1x,'|'))",i,xyzmh_ptmass(4,i), & + xyzmh_ptmass(ihacc,i),xyzmh_ptmass(imacc,i),xyzmh_ptmass(ihsoft,i) enddo - if (nptmass > 0) print "(1x,58('-'))" + if (nptmass > 0) print "(1x,47('-'))" endif endif ! ! radiation arrays ! if (do_radiation) then - if (.not.all(got_rad)) then + if (.not.all(got_raden)) then if (id==master .and. i1==1) write(*,*) 'ERROR: RADIATION=yes but radiation arrays not found in Phantom dump file' ierr = ierr + 1 endif - if (.not.got_radprop(ikappa)) then + if (.not.got_kappa) then if (id==master .and. i1==1) write(*,"(/,a,/)") 'WARNING: RADIATION=yes but opacity not found in Phantom dump file' endif endif diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index cc679d26c..2e53ae392 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module readwrite_dumps_fortran ! @@ -20,13 +20,15 @@ module readwrite_dumps_fortran ! ! :Dependencies: boundary, boundary_dyn, checkconserved, dim, dump_utils, ! dust, dust_formation, eos, eos_stamatellos, externalforces, fileutils, -! io, lumin_nsdisc, memory, mpi, mpiutils, options, part, +! io, krome_user, lumin_nsdisc, memory, mpi, mpiutils, options, part, ! readwrite_dumps_common, setup_params, sphNGutils, timestep, units ! use dump_utils, only:lenid,ndatatypes,i_int,i_int1,i_int2,i_int4,i_int8,& i_real,i_real4,i_real8,int1,int2,int1o,int2o,dump_h,lentag use readwrite_dumps_common, only:check_arrays,fileident,get_options_from_fileid implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" public :: write_smalldump_fortran,write_fulldump_fortran,read_smalldump_fortran,read_dump_fortran @@ -148,6 +150,7 @@ subroutine start_threadwrite(id,iunit,filename) endif endif + return end subroutine start_threadwrite !-------------------------------------------------------------------- @@ -176,6 +179,7 @@ subroutine end_threadwrite(id) endif #endif + return end subroutine end_threadwrite !-------------------------------------------------------------------- @@ -195,6 +199,7 @@ subroutine get_dump_size(fileid,smalldump) end subroutine get_dump_size + !-------------------------------------------------------------------- !+ ! subroutine to write output to full dump file @@ -203,8 +208,7 @@ end subroutine get_dump_size !------------------------------------------------------------------- subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use dim, only:maxp,maxvxyzu,maxalpha,ndivcurlv,ndivcurlB,maxgrav,gravity,use_dust,& - lightcurve,use_dustgrowth,store_dust_temperature,gr,do_nucleation,& - ind_timesteps,mhd_nonideal,use_krome + lightcurve,use_dustgrowth,store_dust_temperature,gr,do_nucleation use eos, only:ieos,eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP use io, only:idump,iprint,real4,id,master,error,warning,nprocs use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,Bevol,Bevol_label,Bxyz,Bxyz_label,npart,maxtypes, & @@ -216,16 +220,29 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) dustfrac_label,tstop_label,dustprop,dustprop_label,eos_vars,eos_vars_label,ndusttypes,ndustsmall,VrelVf,& VrelVf_label,dustgasprop,dustgasprop_label,dust_temp,pxyzu,pxyzu_label,dens,& !,dvdx,dvdx_label rad,rad_label,radprop,radprop_label,do_radiation,maxirad,maxradprop,itemp,igasP,igamma,& - iorig,iX,iZ,imu,nucleation,nucleation_label,n_nucleation,tau,itau_alloc,tau_lucy,itauL_alloc,& - luminosity,eta_nimhd,eta_nimhd_label + iorig,iX,iZ,imu,nucleation,nucleation_label,n_nucleation,tau,itau_alloc,tau_lucy,itauL_alloc use options, only:use_dustfrac,use_var_comp,icooling use dump_utils, only:tag,open_dumpfile_w,allocate_header,& free_header,write_header,write_array,write_block_header use mpiutils, only:reduce_mpi,reduceall_mpi - use timestep, only:dtmax,idtmax_n,idtmax_frac - use part, only:ibin,krome_nmols,gamma_chem,mu_chem,T_gas_cool + use timestep, only:idtmax_n,idtmax_frac +#ifdef IND_TIMESTEPS + use timestep, only:dtmax + use part, only:ibin +#endif #ifdef PRDRAG use lumin_nsdisc, only:beta +#endif +#ifdef LIGHTCURVE + use part, only:luminosity +#endif +#ifdef NONIDEALMHD + use dim, only:mhd_nonideal + use part, only:eta_nimhd,eta_nimhd_label +#endif +#ifdef KROME + use krome_user, only:krome_nmols + use part, only:gamma_chem,mu_chem,T_gas_cool #endif use eos_stamatellos, only:gradP_cool,Gpot_cool real, intent(in) :: t @@ -403,11 +420,11 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) if (gravity .and. maxgrav==maxp) then call write_array(1,poten,'poten',npart,k,ipass,idump,nums,ierrs(17)) endif - if (ind_timesteps) then - if (.not.allocated(temparr)) allocate(temparr(npart)) - temparr(1:npart) = dtmax/2.**ibin(1:npart) - call write_array(1,temparr,'dt',npart,k,ipass,idump,nums,ierrs(18),use_kind=4) - endif +#ifdef IND_TIMESTEPS + if (.not.allocated(temparr)) allocate(temparr(npart)) + temparr(1:npart) = dtmax/2**ibin(1:npart) + call write_array(1,temparr,'dt',npart,k,ipass,idump,nums,ierrs(18),use_kind=4) +#endif call write_array(1,iorig,'iorig',npart,k,ipass,idump,nums,ierrs(29)) #ifdef PRDRAG @@ -419,16 +436,17 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(1,temparr,'beta_pr',npart,k,ipass,idump,nums,ierrs(19)) endif #endif +#ifdef LIGHTCURVE if (lightcurve) then call write_array(1,luminosity,'luminosity',npart,k,ipass,idump,nums,ierrs(20)) endif - - if (use_krome) then - call write_array(1,abundance,abundance_label,krome_nmols,npart,k,ipass,idump,nums,ierrs(21)) - call write_array(1,gamma_chem,'gamma',npart,k,ipass,idump,nums,ierrs(22)) - call write_array(1,mu_chem,'mu',npart,k,ipass,idump,nums,ierrs(23)) - call write_array(1,T_gas_cool,'temp',npart,k,ipass,idump,nums,ierrs(24)) - endif +#endif +#ifdef KROME + call write_array(1,abundance,abundance_label,krome_nmols,npart,k,ipass,idump,nums,ierrs(21)) + call write_array(1,gamma_chem,'gamma',npart,k,ipass,idump,nums,ierrs(22)) + call write_array(1,mu_chem,'mu',npart,k,ipass,idump,nums,ierrs(23)) + call write_array(1,T_gas_cool,'temp',npart,k,ipass,idump,nums,ierrs(24)) +#endif if (do_nucleation) then call write_array(1,nucleation,nucleation_label,n_nucleation,npart,k,ipass,idump,nums,ierrs(25)) endif @@ -474,10 +492,12 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(4,divBsymm,'divBsymm',npart,k,ipass,idump,nums,ierrs(2)) endif if (any(ierrs(1:2) /= 0)) call error('write_dump','error writing MHD arrays') +#ifdef NONIDEALMHD if (mhd_nonideal) then call write_array(4,eta_nimhd,eta_nimhd_label,4,npart,k,ipass,idump,nums,ierrs(1)) if (ierrs(1) /= 0) call error('write_dump','error writing non-ideal MHD arrays') endif +#endif endif enddo if (ipass==1) call write_block_header(narraylengths,ilen,nums,idump,ierr) @@ -510,10 +530,13 @@ subroutine write_smalldump_fortran(t,dumpfile) nptmass,nsinkproperties,xyzmh_ptmass,xyzmh_ptmass_label,& abundance,abundance_label,mhd,dustfrac,iamtype_int11,& dustprop,dustprop_label,dustfrac_label,ndusttypes,& - rad,rad_label,do_radiation,maxirad,luminosity + rad,rad_label,do_radiation,maxirad use dump_utils, only:open_dumpfile_w,dump_h,allocate_header,free_header,& write_header,write_array,write_block_header use mpiutils, only:reduceall_mpi +#ifdef LIGHTCURVE + use part, only:luminosity +#endif real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer(kind=8) :: ilen(4) @@ -588,8 +611,9 @@ subroutine write_smalldump_fortran(t,dumpfile) if (use_dust) & call write_array(1,dustfrac,dustfrac_label,ndusttypes,npart,k,ipass,idump,nums,ierr,singleprec=.true.) call write_array(1,xyzh,xyzh_label,4,npart,k,ipass,idump,nums,ierr,index=4,use_kind=4) - +#ifdef LIGHTCURVE if (lightcurve) call write_array(1,luminosity,'luminosity',npart,k,ipass,idump,nums,ierr,singleprec=.true.) +#endif if (do_radiation) call write_array(1,rad,rad_label,maxirad,npart,k,ipass,idump,nums,ierr,singleprec=.true.) enddo ! @@ -615,6 +639,7 @@ subroutine write_smalldump_fortran(t,dumpfile) close(unit=idump) call end_threadwrite(id) + return end subroutine write_smalldump_fortran @@ -628,7 +653,7 @@ end subroutine write_smalldump_fortran subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ierr,headeronly,dustydisc) use memory, only:allocate_memory - use dim, only:maxp,maxvxyzu,gravity,lightcurve,mhd,maxp_hard,inject_parts,mpi + use dim, only:maxp,maxvxyzu,gravity,lightcurve,mhd,maxp_hard use io, only:real4,master,iverbose,error,warning ! do not allow calls to fatal in this routine use part, only:xyzh,vxyzu,massoftype,npart,npartoftype,maxtypes,iphase, & maxphase,isetphase,nptmass,nsinkproperties,maxptmass,get_pmass, & @@ -699,7 +724,7 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie ! ! read header from the dump file ! - call read_header(idisk1,hdr,ierr,tagged=tagged) + call read_header(idisk1,hdr,tagged,ierr) if (ierr /= 0) then call error('read_dump','error reading header from file') return @@ -766,18 +791,19 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie if (present(headeronly)) then if (headeronly) return endif + + if (iblock==1) then ! -!--allocate main arrays +!--Allocate main arrays ! - if (iblock==1) then - if (dynamic_bdy .or. inject_parts) then - if (mpi) then - call allocate_memory(max(nparttot,int(maxp_hard/nprocs,kind=8))) - else - call allocate_memory(max(nparttot,int(maxp_hard,kind=8))) - endif + if (dynamic_bdy) then + call allocate_memory(int(maxp_hard,kind=8)) else +#ifdef INJECT_PARTICLES + call allocate_memory(max(nparttot,int(maxp_hard,kind=8))) +#else call allocate_memory(nparttot) +#endif endif endif ! @@ -792,6 +818,7 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie npart = npart + npartread if (npartread <= 0 .and. nptmass <= 0) then + print*,' SKIPPING BLOCK npartread = ',npartread call skipblock(idisk1,nums(:,1),nums(:,2),nums(:,3),nums(:,4),tagged,ierr) if (ierr /= 0) then print*,' error skipping block' @@ -865,14 +892,10 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie call check_npartoftype(npartoftype,npart) write(iprint,"(a,/)") ' <<< ERROR! end of file reached in data read' ierr = 666 + return end subroutine read_dump_fortran -!-------------------------------------------------------------------- -!+ -! sanity check on npartoftype -!+ -!------------------------------------------------------------------- subroutine check_npartoftype(npartoftype,npart) integer, intent(inout) :: npartoftype(:) integer, intent(in) :: npart @@ -883,16 +906,16 @@ subroutine check_npartoftype(npartoftype,npart) endif end subroutine check_npartoftype - !-------------------------------------------------------------------- !+ ! subroutine to read a small dump from file, as written ! in write_smalldump !+ !------------------------------------------------------------------- + subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ierr,headeronly,dustydisc) use memory, only:allocate_memory - use dim, only:maxvxyzu,mhd,maxphase,maxp + use dim, only:maxvxyzu,mhd,maxphase,maxp,maxp_hard use io, only:real4,master,iverbose,error,warning ! do not allow calls to fatal in this routine use part, only:npart,npartoftype,maxtypes,nptmass,nsinkproperties,maxptmass, & massoftype @@ -900,6 +923,7 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro ierr_realsize,read_header,extract,free_header,read_block_header use mpiutils, only:reduce_mpi,reduceall_mpi use options, only:use_dustfrac + use boundary_dyn, only:dynamic_bdy character(len=*), intent(in) :: dumpfile real, intent(out) :: tfile,hfactfile integer, intent(in) :: idisk1,iprint,id,nprocs @@ -953,7 +977,7 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro ! !--single values ! - call read_header(idisk1,hdr,ierr,singleprec=.true.,tagged=tagged) + call read_header(idisk1,hdr,tagged,ierr,singleprec=.true.) if (ierr /= 0) then call error('read_smalldump','error reading header from file') return @@ -975,10 +999,17 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro call free_header(hdr,ierr) ! - !--Allocate main arrays (no need for extra space here re: particle injection - ! as small dumps are only read for visualisation/analysis purposes) + !--Allocate main arrays ! - call allocate_memory(nparttot) + if (dynamic_bdy) then + call allocate_memory(int(maxp_hard,kind=8)) + else +#ifdef INJECT_PARTICLES + call allocate_memory(int(maxp_hard,kind=8)) +#else + call allocate_memory(nparttot) +#endif + endif ! !--arrays ! @@ -1112,32 +1143,42 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto massoftype,nptmass,nsinkproperties,phantomdump,tagged,singleprec,& tfile,alphafile,idisk1,iprint,ierr) use dump_utils, only:read_array,match_tag - use dim, only:use_dust,h2chemistry,maxalpha,maxp,gravity,maxgrav,maxvxyzu,do_nucleation, & - use_dustgrowth,maxdusttypes,ndivcurlv,maxphase,gr,store_dust_temperature,& - ind_timesteps,use_krome - use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,dustfrac,dustfrac_label,abundance,abundance_label, & + use dim, only:use_dust,h2chemistry,maxalpha,maxp,gravity,maxgrav,maxvxyzu, do_nucleation, & + use_dustgrowth,maxdusttypes,ndivcurlv,maxphase,gr,store_dust_temperature + use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,dustfrac,abundance,abundance_label, & alphaind,poten,xyzmh_ptmass,xyzmh_ptmass_label,vxyz_ptmass,vxyz_ptmass_label, & - Bevol,Bxyz,Bxyz_label,nabundances,iphase,idust, & - eos_vars,eos_vars_label,maxeosvars,dustprop,dustprop_label,divcurlv,divcurlv_label,iX,iZ,imu, & + Bevol,Bxyz,Bxyz_label,nabundances,iphase,idust,dustfrac_label, & + eos_vars,eos_vars_label,dustprop,dustprop_label,divcurlv,divcurlv_label,iX,iZ,imu, & VrelVf,VrelVf_label,dustgasprop,dustgasprop_label,pxyzu,pxyzu_label,dust_temp, & rad,rad_label,radprop,radprop_label,do_radiation,maxirad,maxradprop,ifluxx,ifluxy,ifluxz, & nucleation,nucleation_label,n_nucleation,ikappa,tau,itau_alloc,tau_lucy,itauL_alloc,& - ithick,ilambda,iorig,dt_in,krome_nmols,gamma_chem,mu_chem,T_gas_cool + ithick,itemp,igasP,ilambda,iorig use sphNGutils, only:mass_sphng,got_mass,set_gas_particle_mass + use eos, only:ieos,eos_is_non_ideal,eos_outputs_gasP +#ifdef IND_TIMESTEPS + use part, only:dt_in +#endif +#ifdef KROME + use krome_user, only: krome_nmols + use part, only: gamma_chem,mu_chem,T_gas_cool +#endif +#ifndef KROME + integer, parameter :: krome_nmols = 0 +#endif integer, intent(in) :: i1,i2,noffset,narraylengths,nums(:,:),npartread,npartoftype(:),idisk1,iprint real, intent(in) :: massoftype(:) integer, intent(in) :: nptmass,nsinkproperties logical, intent(in) :: phantomdump,singleprec,tagged real, intent(in) :: tfile,alphafile integer, intent(out) :: ierr - logical :: match logical :: got_dustfrac(maxdusttypes) - logical :: got_iphase,got_xyzh(4),got_vxyzu(4),got_abund(nabundances),got_alpha(1),got_poten + logical :: match + logical :: got_iphase,got_xyzh(4),got_vxyzu(4),got_abund(nabundances),got_alpha,got_poten logical :: got_sink_data(nsinkproperties),got_sink_vels(3),got_Bxyz(3) - logical :: got_krome_mols(krome_nmols),got_krome_T,got_krome_gamma,got_krome_mu - logical :: got_eosvars(maxeosvars),got_nucleation(n_nucleation),got_ray_tracer - logical :: got_psi,got_Tdust,got_dustprop(2),got_VrelVf,got_dustgasprop(4) - logical :: got_divcurlv(4),got_rad(maxirad),got_radprop(maxradprop),got_pxyzu(4),got_iorig + logical :: got_krome_mols(krome_nmols),got_krome_T,got_krome_gamma,got_krome_mu,got_x,got_z,got_mu + logical :: got_nucleation(n_nucleation),got_ray_tracer + logical :: got_psi,got_gasP,got_temp,got_Tdust,got_dustprop(2),got_VrelVf,got_dustgasprop(4), & + got_divcurlv(4),got_raden(maxirad),got_kappa,got_pxyzu(4),got_iorig character(len=lentag) :: tag,tagarr(64) integer :: k,i,iarr,ik,ndustfraci @@ -1155,7 +1196,8 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto got_sink_vels = .false. got_Bxyz = .false. got_psi = .false. - got_eosvars = .false. + got_gasP = .false. + got_temp = .false. got_dustprop = .false. got_VrelVf = .false. got_dustgasprop = .false. @@ -1165,10 +1207,13 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto got_krome_gamma = .false. got_krome_mu = .false. got_krome_T = .false. + got_x = .false. + got_z = .false. + got_mu = .false. got_nucleation = .false. got_ray_tracer = .false. - got_rad = .false. - got_radprop = .false. + got_raden = .false. + got_kappa = .false. got_pxyzu = .false. got_iorig = .false. @@ -1212,12 +1257,12 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto if (h2chemistry) then call read_array(abundance,abundance_label,got_abund,ik,i1,i2,noffset,idisk1,tag,match,ierr) endif - if (use_krome) then - call read_array(abundance,abundance_label,got_krome_mols,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(gamma_chem,'gamma',got_krome_gamma,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(mu_chem,'mu',got_krome_mu,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(T_gas_cool,'temp',got_krome_T,ik,i1,i2,noffset,idisk1,tag,match,ierr) - endif +#ifdef KROME + call read_array(abundance,abundance_label,got_krome_mols,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(gamma_chem,'gamma',got_krome_gamma,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(mu_chem,'mu',got_krome_mu,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(T_gas_cool,'temp',got_krome_T,ik,i1,i2,noffset,idisk1,tag,match,ierr) +#endif if (do_nucleation) then call read_array(nucleation,nucleation_label,got_nucleation,ik,i1,i2,noffset,idisk1,tag,match,ierr) endif @@ -1230,9 +1275,16 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto if (store_dust_temperature) then call read_array(dust_temp,'Tdust',got_Tdust,ik,i1,i2,noffset,idisk1,tag,match,ierr) endif - call read_array(eos_vars,eos_vars_label,got_eosvars,ik,i1,i2,noffset,idisk1,tag,match,ierr) - - if (maxalpha==maxp) call read_array(alphaind,(/'alpha'/),got_alpha,ik,i1,i2,noffset,idisk1,tag,match,ierr) + if (eos_outputs_gasP(ieos) .or. eos_is_non_ideal(ieos)) then + call read_array(eos_vars(igasP,:),eos_vars_label(igasP),got_gasP,ik,i1,i2,noffset,idisk1,tag,match,ierr) + endif + if (eos_is_non_ideal(ieos)) then + call read_array(eos_vars(itemp,:),eos_vars_label(itemp),got_temp,ik,i1,i2,noffset,idisk1,tag,match,ierr) + endif + call read_array(eos_vars(iX,:),eos_vars_label(iX),got_x,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(eos_vars(iZ,:),eos_vars_label(iZ),got_z,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(eos_vars(imu,:),eos_vars_label(imu),got_mu,ik,i1,i2,noffset,idisk1,tag,match,ierr) + if (maxalpha==maxp) call read_array(alphaind(1,:),'alpha',got_alpha,ik,i1,i2,noffset,idisk1,tag,match,ierr) ! ! read divcurlv if it is in the file ! @@ -1241,17 +1293,23 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto ! read gravitational potential if it is in the file ! if (gravity .and. maxgrav==maxp) call read_array(poten,'poten',got_poten,ik,i1,i2,noffset,idisk1,tag,match,ierr) +#ifdef IND_TIMESTEPS ! ! read dt if it is in the file ! - if (ind_timesteps) call read_array(dt_in,'dt',dt_read_in_fortran,ik,i1,i2,noffset,idisk1,tag,match,ierr) - + call read_array(dt_in,'dt',dt_read_in_fortran,ik,i1,i2,noffset,idisk1,tag,match,ierr) +#endif ! read particle ID's call read_array(iorig,'iorig',got_iorig,ik,i1,i2,noffset,idisk1,tag,match,ierr) if (do_radiation) then - call read_array(rad,rad_label,got_rad,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(radprop,radprop_label,got_radprop,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(rad,rad_label,got_raden,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(radprop(ikappa,:),radprop_label(ikappa),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(radprop(ithick,:),radprop_label(ithick),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(radprop(ilambda,:),radprop_label(ilambda),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(radprop(ifluxx,:),radprop_label(ifluxx),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(radprop(ifluxy,:),radprop_label(ifluxy),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(radprop(ifluxz,:),radprop_label(ifluxz),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) endif case(2) call read_array(xyzmh_ptmass,xyzmh_ptmass_label,got_sink_data,ik,1,nptmass,0,idisk1,tag,match,ierr) @@ -1273,9 +1331,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto ! call check_arrays(i1,i2,noffset,npartoftype,npartread,nptmass,nsinkproperties,massoftype,& alphafile,tfile,phantomdump,got_iphase,got_xyzh,got_vxyzu,got_alpha, & - got_krome_mols,got_krome_gamma,got_krome_mu,got_krome_T, & + got_krome_mols,got_krome_gamma,got_krome_mu,got_krome_T,got_x,got_z,got_mu, & got_abund,got_dustfrac,got_sink_data,got_sink_vels,got_Bxyz,got_psi,got_dustprop,got_pxyzu,got_VrelVf, & - got_dustgasprop,got_rad,got_radprop,got_Tdust,got_eosvars,got_nucleation,got_iorig,iphase,& + got_dustgasprop,got_temp,got_raden,got_kappa,got_Tdust,got_nucleation,got_iorig,iphase,& xyzh,vxyzu,pxyzu,alphaind,xyzmh_ptmass,Bevol,iorig,iprint,ierr) if (.not. phantomdump) then print *, "Calling set_gas_particle_mass" diff --git a/src/main/readwrite_dumps_hdf5.F90 b/src/main/readwrite_dumps_hdf5.F90 index cc8e496c4..0b6f6df7b 100644 --- a/src/main/readwrite_dumps_hdf5.F90 +++ b/src/main/readwrite_dumps_hdf5.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module readwrite_dumps_hdf5 ! @@ -35,6 +35,8 @@ module readwrite_dumps_hdf5 externalforce_hdf5 implicit none + character(len=80), parameter, public :: & ! module version + modid="$Id$" public :: read_dump_hdf5,read_smalldump_hdf5 public :: write_smalldump_hdf5,write_fulldump_hdf5,write_dump_hdf5 diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index a1fc1f71d..f5823228e 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module readwrite_infile ! @@ -66,9 +66,9 @@ module readwrite_infile ! ! :Dependencies: boundary_dyn, cooling, damping, dim, dust, dust_formation, ! eos, externalforces, forcing, gravwaveutils, growth, infile_utils, -! inject, io, linklist, metric, nicil_sup, options, part, ptmass, -! ptmass_radiation, radiation_implicit, radiation_utils, timestep, -! viscosity +! inject, io, linklist, metric, nicil_sup, options, part, photoevap, +! ptmass, ptmass_radiation, radiation_implicit, radiation_utils, +! timestep, viscosity ! use timestep, only:dtmax_dratio,dtmax_max,dtmax_min use options, only:nfulldump,nmaxdumps,twallmax,iexternalforce,tolh, & @@ -82,7 +82,7 @@ module readwrite_infile use viscosity, only:irealvisc,shearparam,bulkvisc use part, only:hfact,ien_type use io, only:iverbose - use dim, only:do_radiation,nucleation,use_dust,use_dustgrowth,mhd_nonideal + use dim, only:do_radiation,nucleation,use_dust,use_dustgrowth implicit none logical :: incl_runtime2 = .false. @@ -105,12 +105,19 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) use linklist, only:write_inopts_link use dust, only:write_options_dust use growth, only:write_options_growth +#ifdef PHOTO + use photoevap, only:write_options_photoevap +#endif #ifdef INJECT_PARTICLES use inject, only:write_options_inject #endif use dust_formation, only:write_options_dust_formation +#ifdef NONIDEALMHD use nicil_sup, only:write_options_nicil +#endif +#ifdef GR use metric, only:write_options_metric +#endif use eos, only:write_options_eos,ieos use ptmass, only:write_options_ptmass use ptmass_radiation,only:write_options_ptmass_radiation @@ -262,20 +269,24 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) if (use_dust) call write_options_dust(iwritein) if (use_dustgrowth) call write_options_growth(iwritein) +#ifdef PHOTO + call write_options_photoevap(iwritein) +#endif + write(iwritein,"(/,a)") '# options for injecting/removing particles' #ifdef INJECT_PARTICLES call write_options_inject(iwritein) #endif - call write_inopt(rkill,'rkill','deactivate particles outside this radius (<0 is off)',iwritein) - if (nucleation) call write_options_dust_formation(iwritein) + call write_inopt(rkill,'rkill','deactivate particles outside this radius (<0 is off)',iwritein) if (sink_radiation) then write(iwritein,"(/,a)") '# options controling radiation pressure from sink particles' call write_options_ptmass_radiation(iwritein) endif - - if (mhd_nonideal) call write_options_nicil(iwritein) +#ifdef NONIDEALMHD + call write_options_nicil(iwritein) +#endif if (do_radiation) then write(iwritein,"(/,a)") '# options for radiation' @@ -290,13 +301,16 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) call write_inopt(cv_type,'cv_type','how to get cv and mean mol weight (0=constant,1=mesa)',iwritein) endif endif - if (gr) call write_options_metric(iwritein) +#ifdef GR + call write_options_metric(iwritein) +#endif call write_options_gravitationalwaves(iwritein) call write_options_boundary(iwritein) if (iwritein /= iprint) close(unit=iwritein) if (iwritein /= iprint) write(iprint,"(/,a)") ' input file '//trim(infile)//' written successfully.' + return end subroutine write_infile !----------------------------------------------------------------- @@ -318,12 +332,19 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) use linklist, only:read_inopts_link use dust, only:read_options_dust use growth, only:read_options_growth +#ifdef GR use metric, only:read_options_metric +#endif +#ifdef PHOTO + use photoevap, only:read_options_photoevap +#endif #ifdef INJECT_PARTICLES use inject, only:read_options_inject #endif use dust_formation, only:read_options_dust_formation,idust_opacity +#ifdef NONIDEALMHD use nicil_sup, only:read_options_nicil +#endif use part, only:mhd,nptmass use cooling, only:read_options_cooling use ptmass, only:read_options_ptmass @@ -345,7 +366,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) real :: ratio logical :: imatch,igotallrequired,igotallturb,igotalllink,igotloops logical :: igotallbowen,igotallcooling,igotalldust,igotallextern,igotallinject,igotallgrowth - logical :: igotallionise,igotallnonideal,igotalleos,igotallptmass,igotalldamping + logical :: igotallionise,igotallnonideal,igotalleos,igotallptmass,igotallphoto,igotalldamping logical :: igotallprad,igotalldustform,igotallgw,igotallgr,igotallbdy integer, parameter :: nrequired = 1 @@ -361,6 +382,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) igotallturb = .true. igotalldust = .true. igotallgrowth = .true. + igotallphoto = .true. igotalllink = .true. igotallextern = .true. igotallinject = .true. @@ -535,7 +557,12 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) !--Extract if one-fluid dust is used from the fileid if (.not.imatch .and. use_dust) call read_options_dust(name,valstring,imatch,igotalldust,ierr) if (.not.imatch .and. use_dustgrowth) call read_options_growth(name,valstring,imatch,igotallgrowth,ierr) - if (.not.imatch .and. gr) call read_options_metric(name,valstring,imatch,igotallgr,ierr) +#ifdef GR + if (.not.imatch) call read_options_metric(name,valstring,imatch,igotallgr,ierr) +#endif +#ifdef PHOTO + if (.not.imatch) call read_options_photoevap(name,valstring,imatch,igotallphoto,ierr) +#endif #ifdef INJECT_PARTICLES if (.not.imatch) call read_options_inject(name,valstring,imatch,igotallinject,ierr) #endif @@ -543,7 +570,9 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (.not.imatch .and. sink_radiation) then call read_options_ptmass_radiation(name,valstring,imatch,igotallprad,ierr) endif - if (.not.imatch .and. mhd_nonideal) call read_options_nicil(name,valstring,imatch,igotallnonideal,ierr) +#ifdef NONIDEALMHD + if (.not.imatch) call read_options_nicil(name,valstring,imatch,igotallnonideal,ierr) +#endif if (.not.imatch) call read_options_eos(name,valstring,imatch,igotalleos,ierr) if (.not.imatch .and. maxvxyzu >= 4) call read_options_cooling(name,valstring,imatch,igotallcooling,ierr) if (.not.imatch) call read_options_damping(name,valstring,imatch,igotalldamping,ierr) @@ -570,7 +599,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) igotallrequired = (ngot >= nrequired) .and. igotalllink .and. igotallbowen .and. igotalldust & .and. igotalleos .and. igotallcooling .and. igotallextern .and. igotallturb & .and. igotallptmass .and. igotallinject .and. igotallionise .and. igotallnonideal & - .and. igotallgrowth .and. igotalldamping .and. igotallprad & + .and. igotallphoto .and. igotallgrowth .and. igotalldamping .and. igotallprad & .and. igotalldustform .and. igotallgw .and. igotallgr .and. igotallbdy if (ierr /= 0 .or. ireaderr > 0 .or. .not.igotallrequired) then @@ -590,6 +619,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (.not.igotalldust) write(*,*) 'missing dust options' if (.not.igotallgr) write(*,*) 'missing metric parameters (eg, spin, mass)' if (.not.igotallgrowth) write(*,*) 'missing growth options' + if (.not.igotallphoto) write(*,*) 'missing photoevaporation options' if (.not.igotallextern) then if (gr) then write(*,*) 'missing GR quantities (eg: accretion radius)' diff --git a/src/main/sort_particles.f90 b/src/main/sort_particles.F90 similarity index 98% rename from src/main/sort_particles.f90 rename to src/main/sort_particles.F90 index 6239caf4c..b08d8856a 100644 --- a/src/main/sort_particles.f90 +++ b/src/main/sort_particles.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module sort_particles ! diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 79819a2e7..8679970a7 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module step_lf_global ! @@ -33,7 +33,9 @@ module step_lf_global use part, only:radpred use timestep_ind, only:maxbins,itdt,ithdt,itdt1,ittwas implicit none - real :: ibin_dts(4,0:maxbins) + character(len=80), parameter, public :: & ! module version + modid="$Id$" + real :: ibin_dts(4,0:maxbins) contains @@ -98,7 +100,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iphase,iamtype,massoftype,maxphase,igas,idust,mhd,& iamboundary,get_ntypes,npartoftypetot,& dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& - dustprop,ddustprop,dustproppred,pxyzu,dens,metrics,ics + dustprop,ddustprop,dustproppred,ndustsmall,pxyzu,dens,metrics,ics use options, only:avdecayconst,alpha,ieos,alphamax,icooling use deriv, only:derivs use timestep, only:dterr,bignumber,tolv @@ -112,7 +114,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use part, only:gamma_chem #endif use timestep, only:dtmax,dtmax_ifactor,dtdiff - use timestep_ind, only:get_dt,nbinmax,decrease_dtmax,dt_too_small + use timestep_ind, only:get_dt,nbinmax,decrease_dtmax,ibinnow,dt_too_small use timestep_sts, only:sts_get_dtau_next,use_sts,ibin_sts,sts_it_n use part, only:ibin,ibin_old,twas,iactive,ibin_wake #ifdef GR @@ -136,8 +138,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) real, intent(out) :: dtnew integer :: i,its,np,ntypes,itype,nwake,nvfloorp,nvfloorps,nvfloorc,ialphaloc real :: timei,erri,errmax,v2i,errmaxmean - real :: vxi,vyi,vzi,eni,hdtsph,pmassi - real :: alphaloci,source,tdecay1,hi,rhoi,ddenom,spsoundi + real :: vxi,vyi,vzi,eni,vxoldi,vyoldi,vzoldi,hdtsph,pmassi + real :: alphaloci,divvdti,source,tdecay1,hi,rhoi,ddenom,spsoundi real :: v2mean,hdti real(kind=4) :: t1,t2,tcpu1,tcpu2 real :: pxi,pyi,pzi,p2i,p2mean @@ -267,12 +269,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(pxyzu,ppred,icooling) & !$omp shared(Bevol,dBevol,Bpred,dtsph,massoftype,iphase) & !$omp shared(dustevol,ddustprop,dustprop,dustproppred,dustfrac,ddustevol,dustpred,use_dustfrac) & -!$omp shared(alphaind,ieos,alphamax,ialphaloc) & +!$omp shared(alphaind,ieos,alphamax,ndustsmall,ialphaloc) & !$omp shared(eos_vars,ufloor) & !$omp shared(twas,timei) & !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & -!$omp private(i,spsoundi,alphaloci) & +!$omp private(i,spsoundi,alphaloci,divvdti) & !$omp firstprivate(pmassi,itype,avdecayconst,alpha) & !$omp reduction(+:nvfloorps) predict_sph: do i=1,npart @@ -430,10 +432,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass,massoftype) & !$omp shared(dtsph,ieos,ufloor,icooling) & !$omp shared(ibin,ibin_old,ibin_sts,twas,timei,use_sts,dtsph_next,ibin_wake,sts_it_n) & -!$omp shared(ibin_dts,nbinmax) & +!$omp shared(ibin_dts,nbinmax,ibinnow) & !$omp private(dti,hdti) & !$omp shared(rad,radpred,drad)& -!$omp private(i,vxi,vyi,vzi) & +!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi) & !$omp private(pxi,pyi,pzi,p2i) & !$omp private(erri,v2i,eni) & !$omp reduction(max:errmax) & @@ -490,12 +492,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) + elseif (icooling /= 8) then + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) else - if (icooling /= 8) then - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) - else - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) - endif + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + endif !--floor the thermal energy if requested and required @@ -505,7 +506,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) nvfloorc = nvfloorc + 1 endif endif - + if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + hdti*dBevol(:,i) @@ -527,41 +528,13 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif - if (gr) then - pxi = pxyzu(1,i) + hdtsph*fxyzu(1,i) - pyi = pxyzu(2,i) + hdtsph*fxyzu(2,i) - pzi = pxyzu(3,i) + hdtsph*fxyzu(3,i) - eni = pxyzu(4,i) + hdtsph*fxyzu(4,i) - - erri = (pxi - ppred(1,i))**2 + (pyi - ppred(2,i))**2 + (pzi - ppred(3,i))**2 - errmax = max(errmax,erri) - - p2i = pxi*pxi + pyi*pyi + pzi*pzi - p2mean = p2mean + p2i - np = np + 1 - - pxyzu(1,i) = pxi - pxyzu(2,i) = pyi - pxyzu(3,i) = pzi - pxyzu(4,i) = eni - else - 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) - - erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 - errmax = max(errmax,erri) - - v2i = vxi*vxi + vyi*vyi + vzi*vzi - v2mean = v2mean + v2i - np = np + 1 - - vxyzu(1,i) = vxi - vxyzu(2,i) = vyi - vxyzu(3,i) = vzi - !--this is the energy equation if non-isothermal - if (maxvxyzu >= 4) vxyzu(4,i) = eni + if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdti*ddustprop(:,i) + if (itype==igas) then + if (mhd) Bevol(:,i) = Bevol(:,i) + hdti*dBevol(:,i) + if (do_radiation) rad(:,i) = rad(:,i) + hdti*drad(:,i) + if (use_dustfrac) then + dustevol(:,i) = dustevol(:,i) + hdti*ddustevol(:,i) + if (use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdti*ddustprop(:,i) endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) @@ -577,7 +550,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif endif - enddo corrector + endif + enddo corrector !$omp enddo !$omp end parallel if (use_dustgrowth) call check_dustprop(npart,dustprop(1,:)) @@ -761,7 +735,7 @@ end subroutine step_extern_sph_gr subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,time) use dim, only:maxptmass,maxp,maxvxyzu - use io, only:iverbose,id,master,iprint,warning,fatal + use io, only:iverbose,id,master,iprint,warning use externalforces, only:externalforce,accrete_particles,update_externalforce use options, only:iexternalforce use part, only:maxphase,isdead_or_accreted,iamboundary,igas,iphase,iamtype,& @@ -777,7 +751,7 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me real, intent(in) :: dtsph,time real, intent(inout) :: dtextforce real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:),pxyzu(:,:),dens(:),metrics(:,:,:,:),metricderivs(:,:,:,:) - integer :: i,itype,nsubsteps,naccreted,its,ierr,nlive + integer :: i,itype,nsubsteps,naccreted,its,ierr real :: timei,t_end_step,hdt,pmassi real :: dt,dtf,dtextforcenew,dtextforce_min real :: pri,spsoundi,pondensi,tempi,gammai @@ -874,8 +848,7 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me tempi = eos_vars(itemp,i) rhoi = rhoh(hi,massoftype(igas)) - ! Note: grforce needs derivatives of the metric, - ! which do not change between pmom iterations +! Note: grforce needs derivatives of the metric, which do not change between pmom iterations pmom_iterations: do while (its <= itsmax .and. .not. converged) its = its + 1 pprev = pxyz @@ -888,8 +861,7 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me if (pmom_err < ptol) converged = .true. fexti = fstar enddo pmom_iterations - if (its > itsmax ) call warning('step_extern_gr',& - 'max # of pmom iterations',var='pmom_err',val=pmom_err) + if (its > itsmax ) call warning('step_extern_gr','Reached max number of pmom iterations. pmom_err ',val=pmom_err) pitsmax = max(its,pitsmax) perrmax = max(pmom_err,perrmax) @@ -902,11 +874,9 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me its = 0 converged = .false. vxyz_star = vxyz - ! Note: since particle positions change between iterations - ! the metric and its derivatives need to be updated. - ! cons2prim does not require derivatives of the metric, - ! so those can updated once the iterations are complete - ! in order to reduce the number of computations. +! Note: since particle positions change between iterations the metric and its derivatives need to be updated. +! cons2prim does not require derivatives of the metric, so those can updated once the iterations +! are complete, in order to reduce the number of computations. xyz_iterations: do while (its <= itsmax .and. .not. converged) its = its+1 xyz_prev = xyz @@ -954,7 +924,6 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me ! accretedmass = 0. naccreted = 0 - nlive = 0 dtextforce_min = bignumber !$omp parallel default(none) & @@ -965,7 +934,7 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me !$omp private(pri,pondensi,spsoundi,tempi,dtf) & !$omp firstprivate(itype,pmassi) & !$omp reduction(min:dtextforce_min) & - !$omp reduction(+:accretedmass,naccreted,nlive) & + !$omp reduction(+:accretedmass,naccreted) & !$omp shared(idamp,damp_fac) !$omp do accreteloop: do i=1,npart @@ -999,16 +968,11 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me naccreted = naccreted + 1 endif endif - nlive = nlive + 1 endif enddo accreteloop !$omp enddo !$omp end parallel - if (npart > 2 .and. nlive < 2) then - call fatal('step','all particles accreted',var='nlive',ival=nlive) - endif - if (iverbose >= 2 .and. id==master .and. naccreted /= 0) write(iprint,"(a,es10.3,a,i4,a)") & 'Step: at time ',timei,', ',naccreted,' particles were accreted. Mass accreted = ',accretedmass @@ -1046,7 +1010,7 @@ end subroutine step_extern_gr !+ !---------------------------------------------------------------- subroutine step_extern_sph(dt,npart,xyzh,vxyzu) - use part, only:isdead_or_accreted + use part, only:isdead_or_accreted,iboundary,iphase,iamtype real, intent(in) :: dt integer, intent(in) :: npart real, intent(inout) :: xyzh(:,:) @@ -1054,7 +1018,7 @@ subroutine step_extern_sph(dt,npart,xyzh,vxyzu) integer :: i !$omp parallel do default(none) & - !$omp shared(npart,xyzh,vxyzu,dt) & + !$omp shared(npart,xyzh,vxyzu,dt,iphase) & !$omp private(i) do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -1114,11 +1078,11 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:) integer(kind=1), intent(in) :: nbinmax integer(kind=1), intent(inout) :: ibin_wake(:) - integer :: i,itype,nsubsteps,naccreted,nfail,nfaili,merge_n,nlive + integer :: i,itype,nsubsteps,ichem,naccreted,nfail,nfaili,merge_n integer :: merge_ij(nptmass) integer(kind=1) :: ibin_wakei real :: timei,hdt,fextx,fexty,fextz,fextxi,fextyi,fextzi,phii,pmassi - real :: dtphi2,dtphi2i,vxhalfi,vyhalfi,vzhalfi,fxi,fyi,fzi + real :: dtphi2,dtphi2i,vxhalfi,vyhalfi,vzhalfi,fxi,fyi,fzi,deni real :: dudtcool,fextv(3),poti,ui,rhoi real :: dt,dtextforcenew,dtsinkgas,fonrmax,fonrmaxi real :: dtf,accretedmass,t_end_step,dtextforce_min @@ -1221,8 +1185,8 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, #endif !$omp private(dphot,abundi,gmwvar) & !$omp private(ui,rhoi) & - !$omp private(i,dudtcool,fxi,fyi,fzi,phii) & - !$omp private(fextx,fexty,fextz,fextxi,fextyi,fextzi,poti,fextv,accreted) & + !$omp private(i,ichem,dudtcool,fxi,fyi,fzi,phii) & + !$omp private(fextx,fexty,fextz,fextxi,fextyi,fextzi,poti,deni,fextv,accreted) & !$omp private(fonrmaxi,dtphi2i,dtf) & !$omp private(vxhalfi,vyhalfi,vzhalfi) & !$omp firstprivate(pmassi,itype) & @@ -1393,7 +1357,6 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, accretedmass = 0. nfail = 0 naccreted = 0 - nlive = 0 ibin_wakei = 0 dptmass(:,:) = 0. @@ -1406,7 +1369,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, !$omp reduction(+:dptmass) & !$omp private(i,accreted,nfaili,fxi,fyi,fzi) & !$omp firstprivate(itype,pmassi,ibin_wakei) & - !$omp reduction(+:accretedmass,nfail,naccreted,nlive) + !$omp reduction(+:accretedmass,nfail,naccreted) !$omp do accreteloop: do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -1449,16 +1412,12 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif if (nfaili > 1) nfail = nfail + 1 endif - nlive = nlive + 1 endif + enddo accreteloop !$omp enddo !$omp end parallel - if (npart > 2 .and. nlive < 2) then - call fatal('step','all particles accreted',var='nlive',ival=nlive) - endif - ! ! reduction of sink particle changes across MPI ! diff --git a/src/main/step_supertimestep.F90 b/src/main/step_supertimestep.F90 index 9dd9d932c..e770751d7 100644 --- a/src/main/step_supertimestep.F90 +++ b/src/main/step_supertimestep.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module supertimestep ! diff --git a/src/main/timestep.f90 b/src/main/timestep.F90 similarity index 99% rename from src/main/timestep.f90 rename to src/main/timestep.F90 index 2a6a857fc..a349c43b3 100644 --- a/src/main/timestep.f90 +++ b/src/main/timestep.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module timestep ! diff --git a/src/main/units.f90 b/src/main/units.f90 index 71dfd54b0..14a8cd605 100644 --- a/src/main/units.f90 +++ b/src/main/units.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module units ! @@ -35,7 +35,7 @@ module units public :: get_G_code, get_c_code, get_radconst_code, get_kbmh_code public :: c_is_unity, G_is_unity, in_geometric_units public :: is_time_unit, is_length_unit - public :: in_solarr, in_solarm, in_solarl + public :: in_solarr, in_solarm contains @@ -464,17 +464,5 @@ real(kind=8) function in_solarr(val) result(rval) rval = val*(udist/solarr) end function in_solarr -!--------------------------------------------------------------------------- -!+ -! function to convert a luminosity value from code units to solar luminosity -!+ -!--------------------------------------------------------------------------- -real(kind=8) function in_solarl(val) result(rval) - use physcon, only:solarl - real, intent(in) :: val - - rval = val*(unit_luminosity/solarl) - -end function in_solarl end module units diff --git a/src/main/utils_allocate.f90 b/src/main/utils_allocate.f90 index bdc5f9407..9c5476e85 100644 --- a/src/main/utils_allocate.f90 +++ b/src/main/utils_allocate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module allocutils ! diff --git a/src/main/utils_binary.f90 b/src/main/utils_binary.f90 index ed96493c8..f7bfcfa38 100644 --- a/src/main/utils_binary.f90 +++ b/src/main/utils_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module binaryutils ! @@ -62,13 +62,7 @@ real function get_E_from_mean_anomaly(M_ref,ecc) result(E) M_guess = M_ref - 2.*tol do while (abs(M_ref - M_guess) > tol) - if (ecc < 1.) then ! eccentric - M_guess = E_guess - ecc*sin(E_guess) - elseif (ecc > 1.) then ! hyperbolic - M_guess = ecc*sinh(E_guess) - E_guess - else ! parabolic - M_guess = E_guess + 1./3.*E_guess**3 - endif + M_guess = E_guess - ecc*sin(E_guess) if (M_guess > M_ref) then E_right = E_guess else @@ -81,33 +75,13 @@ real function get_E_from_mean_anomaly(M_ref,ecc) result(E) end function get_E_from_mean_anomaly -!--------------------------------------------------------------- -!+ -! Get eccentric (or parabolic/hyperbolic) anomaly from true anomaly -! https://space.stackexchange.com/questions/23128/design-of-an-elliptical-transfer-orbit/23130#23130 -!+ -!--------------------------------------------------------------- -real function get_E_from_true_anomaly(theta,ecc) result(E) - real, intent(in) :: theta ! true anomaly in radians - real, intent(in) :: ecc ! eccentricity - - if (ecc < 1.) then - E = atan2(sqrt(1. - ecc**2)*sin(theta),(ecc + cos(theta))) - elseif (ecc > 1.) then ! hyperbolic - !E = atanh(sqrt(ecc**2 - 1.)*sin(theta)/(ecc + cos(theta))) - E = 2.*atanh(sqrt((ecc - 1.)/(ecc + 1.))*tan(0.5*theta)) - else ! parabolic - E = tan(0.5*theta) - endif - -end function get_E_from_true_anomaly - !----------------------------------------------------------------------- !+ ! Calculate semi-major axis, ecc, ra and rp from radius(3), velocity(3) ! mass of central object and iexternalforce (for LT corrections) !+ !----------------------------------------------------------------------- + subroutine get_orbit_bits(vel,rad,m1,iexternalforce,semia,ecc,ra,rp) real, intent(in) :: m1, vel(3), rad(3) integer, intent(in) :: iexternalforce diff --git a/src/main/utils_cpuinfo.f90 b/src/main/utils_cpuinfo.f90 index 4fa898b6a..88e92e909 100644 --- a/src/main/utils_cpuinfo.f90 +++ b/src/main/utils_cpuinfo.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cpuinfo ! diff --git a/src/main/utils_datafiles.f90 b/src/main/utils_datafiles.f90 index ad8965012..94cb3c3f6 100644 --- a/src/main/utils_datafiles.f90 +++ b/src/main/utils_datafiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module datautils ! @@ -209,10 +209,10 @@ logical function has_write_permission(dir) has_write_permission = .true. open(newunit=iunit,file=trim(dir)//'data.tmp.abcd',action='write',iostat=ierr) - if (ierr /= 0) has_write_permission = .false. - - close(iunit,status='delete',iostat=ierr) - if (ierr /= 0) has_write_permission = .false. + if (ierr /= 0) then + has_write_permission = .false. + endif + close(iunit,status='delete') end function has_write_permission diff --git a/src/main/utils_deriv.f90 b/src/main/utils_deriv.f90 index c83bbb762..d73e33338 100644 --- a/src/main/utils_deriv.f90 +++ b/src/main/utils_deriv.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module derivutils ! @@ -16,9 +16,7 @@ module derivutils ! ! :Dependencies: io, mpiutils, timing ! - use timing, only: timers,itimer_dens,itimer_force,itimer_link,itimer_extf,itimer_balance,itimer_cons2prim,& - itimer_radiation,itimer_rad_save,itimer_rad_neighlist,itimer_rad_arrays,itimer_rad_its,& - itimer_rad_flux,itimer_rad_lambda,itimer_rad_diff,itimer_rad_update,itimer_rad_store + use timing, only: timers,itimer_dens,itimer_force,itimer_link,itimer_extf,itimer_balance,itimer_cons2prim implicit none @@ -41,47 +39,21 @@ subroutine do_timing(label,tlast,tcpulast,start,lunit) real(kind=4), intent(inout) :: tlast,tcpulast logical, intent(in), optional :: start integer, intent(in), optional :: lunit - integer :: itimer real(kind=4) :: t2,tcpu2,tcpu,twall call get_timings(t2,tcpu2) twall = reduce_mpi('+',t2-tlast) tcpu = reduce_mpi('+',tcpu2-tcpulast) - select case (label) - case ('dens') - itimer = itimer_dens - case ('force') - itimer = itimer_force - case ('link') - itimer = itimer_link - case ('cons2prim') - itimer = itimer_cons2prim - case ('radiation') - itimer = itimer_radiation - case ('radsave') - itimer = itimer_rad_save - case ('radneighlist') - itimer = itimer_rad_neighlist - case ('radarrays') - itimer = itimer_rad_arrays - case ('radits') - itimer = itimer_rad_its - case ('radflux') - itimer = itimer_rad_flux - case ('radlambda') - itimer = itimer_rad_lambda - case ('raddiff') - itimer = itimer_rad_diff - case ('radupdate') - itimer = itimer_rad_update - case ('radstore') - itimer = itimer_rad_store - case default - itimer = 1 - end select - - call increment_timer(itimer,t2-tlast,tcpu2-tcpulast) + if (label=='dens') then + call increment_timer(itimer_dens,t2-tlast,tcpu2-tcpulast) + elseif (label=='force') then + call increment_timer(itimer_force,t2-tlast,tcpu2-tcpulast) + elseif (label=='link') then + call increment_timer(itimer_link,t2-tlast,tcpu2-tcpulast) + elseif (label=='cons2prim') then + call increment_timer(itimer_cons2prim,t2-tlast,tcpu2-tcpulast) + endif if (iverbose >= 2 .and. id==master) then if (present(start)) then diff --git a/src/main/utils_dumpfiles.f90 b/src/main/utils_dumpfiles.f90 index 7e443fdbe..0e3e3335c 100644 --- a/src/main/utils_dumpfiles.f90 +++ b/src/main/utils_dumpfiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module dump_utils ! @@ -1121,13 +1121,12 @@ end subroutine open_dumpfile_w ! open a dump file and read the file id ! and generic header information !----------------------------------------- -subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags,tagged) +subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags) integer, intent(in) :: iunit character(len=*), intent(in) :: filename character(len=lenid), intent(out) :: fileid integer, intent(out) :: ierr - logical, intent(in), optional :: singleprec,requiretags - logical, intent(out), optional :: tagged + logical, intent(in), optional :: singleprec,requiretags integer(kind=4) :: int1i,int2i,int3i integer :: iversion_file,ierr1 logical :: r4,must_have_tags @@ -1194,11 +1193,6 @@ subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags,tag endif endif - ! return whether or not file is in tagged format - if (present(tagged)) then - tagged = (fileid(2:2) == 'T' .or. fileid(2:2) == 't') - endif - end subroutine open_dumpfile_r !------------------------------------------------------- @@ -1236,22 +1230,19 @@ end function get_error_text ! read the file header into the dump_header structure !+ !------------------------------------------------------- -subroutine read_header(iunit,hdr,ierr,singleprec,tagged) +subroutine read_header(iunit,hdr,tagged,ierr,singleprec) integer, intent(in) :: iunit type(dump_h), intent(out) :: hdr + logical, intent(in) :: tagged integer, intent(out) :: ierr logical, intent(in), optional :: singleprec - logical, intent(in), optional :: tagged - logical :: convert_prec,tags + logical :: convert_prec integer :: i,n real(kind=4), allocatable :: dumr4(:) convert_prec = .false. if (present(singleprec)) convert_prec = singleprec - tags = .true. - if (present(tagged)) tags = tagged - do i=1,ndatatypes read (iunit, iostat=ierr) n if (n < 0) n = 0 @@ -1259,66 +1250,66 @@ subroutine read_header(iunit,hdr,ierr,singleprec,tagged) select case(i) case(i_int) allocate(hdr%inttags(n),hdr%intvals(n),stat=ierr) + hdr%inttags(:) = '' if (n > 0) then - hdr%inttags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%inttags - read(iunit, iostat=ierr) hdr%intvals + if (tagged) read(iunit, iostat=ierr) hdr%inttags(1:n) + read(iunit, iostat=ierr) hdr%intvals(1:n) endif case(i_int1) allocate(hdr%int1tags(n),hdr%int1vals(n),stat=ierr) + hdr%int1tags(:) = '' if (n > 0) then - hdr%int1tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int1tags - read(iunit, iostat=ierr) hdr%int1vals + if (tagged) read(iunit, iostat=ierr) hdr%int1tags(1:n) + read(iunit, iostat=ierr) hdr%int1vals(1:n) endif case(i_int2) allocate(hdr%int2tags(n),hdr%int2vals(n),stat=ierr) + hdr%int2tags(:) = '' if (n > 0) then - hdr%int2tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int2tags - read(iunit, iostat=ierr) hdr%int2vals + if (tagged) read(iunit, iostat=ierr) hdr%int2tags(1:n) + read(iunit, iostat=ierr) hdr%int2vals(1:n) endif case(i_int4) allocate(hdr%int4tags(n),hdr%int4vals(n),stat=ierr) + hdr%int4tags(:) = '' if (n > 0) then - hdr%int4tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int4tags - read(iunit, iostat=ierr) hdr%int4vals + if (tagged) read(iunit, iostat=ierr) hdr%int4tags(1:n) + read(iunit, iostat=ierr) hdr%int4vals(1:n) endif case(i_int8) allocate(hdr%int8tags(n),hdr%int8vals(n),stat=ierr) + hdr%int8tags(:) = '' if (n > 0) then - hdr%int8tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int8tags - read(iunit, iostat=ierr) hdr%int8vals + if (tagged) read(iunit, iostat=ierr) hdr%int8tags(1:n) + read(iunit, iostat=ierr) hdr%int8vals(1:n) endif case(i_real) allocate(hdr%realtags(n),hdr%realvals(n),stat=ierr) + hdr%realtags(:) = '' if (n > 0) then - hdr%realtags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%realtags + if (tagged) read(iunit, iostat=ierr) hdr%realtags(1:n) if (convert_prec .and. kind(0.) /= 4) then allocate(dumr4(n),stat=ierr) - read(iunit, iostat=ierr) dumr4 + read(iunit, iostat=ierr) dumr4(1:n) hdr%realvals(1:n) = real(dumr4(1:n)) deallocate(dumr4) else - read(iunit, iostat=ierr) hdr%realvals + read(iunit, iostat=ierr) hdr%realvals(1:n) endif endif case(i_real4) allocate(hdr%real4tags(n),hdr%real4vals(n),stat=ierr) + hdr%real4tags(:) = '' if (n > 0) then - hdr%real4tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%real4tags - read(iunit, iostat=ierr) hdr%real4vals + if (tagged) read(iunit, iostat=ierr) hdr%real4tags(1:n) + read(iunit, iostat=ierr) hdr%real4vals(1:n) endif case(i_real8) allocate(hdr%real8tags(n),hdr%real8vals(n),stat=ierr) + hdr%real8tags(:) = '' if (n > 0) then - hdr%real8tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%real8tags - read(iunit, iostat=ierr) hdr%real8vals + if (tagged) read(iunit, iostat=ierr) hdr%real8tags(1:n) + read(iunit, iostat=ierr) hdr%real8vals(1:n) endif end select enddo @@ -2063,10 +2054,6 @@ subroutine read_array_real4(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag,ma matched = .true. if (match_datatype) then got_arr = .true. - if (i2 > size(arr)) then - print*,'ERROR: array size too small reading array: need ',i2,' got ',size(arr) - read(iunit,iostat=ierr) - endif read(iunit,iostat=ierr) (dum,i=1,noffset),arr(i1:i2) else print*,'ERROR: wrong datatype for '//trim(tag)//' (is not real4)' @@ -2084,22 +2071,21 @@ end subroutine read_array_real4 !-------------------------------------------------------------------- subroutine read_array_real4arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag,matched,ierr) real(kind=4), intent(inout) :: arr(:,:) - character(len=*), intent(in) :: arr_tag(:),tag - logical, intent(inout) :: got_arr(:) + character(len=*), intent(in) :: arr_tag(size(arr(1,:))),tag + logical, intent(inout) :: got_arr(size(arr(1,:))) integer, intent(in) :: ikind,i1,i2,noffset,iunit logical, intent(inout) :: matched integer, intent(out) :: ierr integer :: i,j,nread real(kind=4) :: dum real(kind=8) :: dumr8 - real(kind=4), allocatable :: dummy(:) real(kind=8), allocatable :: dummyr8(:) logical :: match_datatype if (matched .or. ikind < i_real) return match_datatype = (ikind==i_real4 .or. (kind(0.)==4 .and. ikind==i_real)) - do j=1,min(size(arr(:,1)),size(arr_tag)) + do j=1,size(arr(:,1)) if (match_tag(tag,arr_tag(j)) .and. .not.matched) then matched = .true. if (match_datatype) then @@ -2109,12 +2095,7 @@ subroutine read_array_real4arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag ierr = ierr_arraysize return endif - nread = i2-i1+1 - allocate(dummy(nread)) - read(iunit,iostat=ierr) (dum,i=1,noffset),dummy(1:nread) - arr(j,i1:i2) = dummy - deallocate(dummy) - !read(iunit,iostat=ierr) (dum,i=1,noffset),arr(j,i1:i2) + read(iunit,iostat=ierr) (dum,i=1,noffset),arr(j,i1:i2) elseif (ikind==i_real4) then got_arr(j) = .true. !print*,'WARNING: converting '//trim(tag)//' from real*8->real*4' @@ -2192,8 +2173,8 @@ end subroutine read_array_real8 !-------------------------------------------------------------------- subroutine read_array_real8arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag,matched,ierr) real(kind=8), intent(inout) :: arr(:,:) - character(len=*), intent(in) :: arr_tag(:),tag - logical, intent(inout) :: got_arr(:) + character(len=*), intent(in) :: arr_tag(size(arr(1,:))),tag + logical, intent(inout) :: got_arr(size(arr(1,:))) integer, intent(in) :: ikind,i1,i2,noffset,iunit logical, intent(inout) :: matched integer, intent(out) :: ierr @@ -2207,7 +2188,7 @@ subroutine read_array_real8arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag if (matched .or. ikind < i_real) return match_datatype = (ikind==i_real8 .or. (kind(0.)==8 .and. ikind==i_real)) - do j=1,min(size(arr(:,1)),size(arr_tag)) + do j=1,size(arr(:,1)) if (match_tag(tag,arr_tag(j)) .and. .not.matched) then matched = .true. if (match_datatype) then diff --git a/src/main/utils_dumpfiles_hdf5.f90 b/src/main/utils_dumpfiles_hdf5.f90 index 32ab218c2..dade21905 100644 --- a/src/main/utils_dumpfiles_hdf5.f90 +++ b/src/main/utils_dumpfiles_hdf5.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module utils_dumpfiles_hdf5 ! diff --git a/src/main/utils_filenames.f90 b/src/main/utils_filenames.f90 index bdc05883c..c2a6308eb 100644 --- a/src/main/utils_filenames.f90 +++ b/src/main/utils_filenames.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module fileutils ! @@ -19,11 +19,9 @@ module fileutils ! implicit none - public :: getnextfilename,numfromfile,basename,get_ncolumns,skip_header - public :: read_column_labels,get_column_labels,split + public :: getnextfilename,numfromfile,basename,get_ncolumns,skip_header,get_column_labels,split public :: strip_extension,is_digit,files_are_sequential public :: ucase,lcase,make_tags_unique,get_nlines,string_delete,string_replace,nospaces - integer, parameter :: max_line_length = 10000 ! for finding number of columns private @@ -533,47 +531,22 @@ pure subroutine split(string,delim,stringarr,nsplit) end subroutine split -!----------------------------------------------------------------- -! -! utility to count number of times a character appears in a string -! -!----------------------------------------------------------------- -integer function count_char(string,mychar) - character(len=*), intent(in) :: string - character(len=1), intent(in) :: mychar - integer :: i - - count_char = 0 - do i=1,len(string) - if (string(i:i)==mychar) count_char = count_char + 1 - enddo - -end function count_char - !--------------------------------------------------------------------------- ! ! extract a list of labels from the header line of a file ! !--------------------------------------------------------------------------- -subroutine get_column_labels(line,nlabels,labels,method,ndesired,csv) +subroutine get_column_labels(line,nlabels,labels,method) character(len=*), intent(in) :: line integer, intent(out) :: nlabels character(len=*), dimension(:), intent(out) :: labels integer, intent(out), optional :: method - integer, intent(in), optional :: ndesired - logical, intent(in), optional :: csv - integer :: i1,i2,i,nlabelstmp,nlabels_prev,istyle,ntarget + integer :: i1,i2,i,nlabelstmp,istyle character(len=1) :: leadingchar - character(len=4), parameter :: spaces = ' ' - logical :: is_csv nlabels = 0 i1 = 1 istyle = 0 - ntarget = -1 - is_csv = .false. - if (present(csv)) is_csv = csv - if (present(ndesired)) ntarget = ndesired ! ! strip leading comment character ('#') ! @@ -585,50 +558,25 @@ subroutine get_column_labels(line,nlabels,labels,method,ndesired,csv) i1 = max(i1,index(line,'=')+1) i2 = i1 - if (index(nospaces(line),'][') > 0 .and. .not.is_csv) then + if (index(nospaces(line),'][') > 0) then ! ! format style 1: # [ mylabel1 ] [ mylabel2 ] [ mylabel3 ] ! istyle = 1 - i1 = max(index(line,'[')+1,i1) ! strip leading square bracket - ! try with different number of spaces between brackets (if labels not found) - over_spaces1: do i=4,0,-1 - call split(line(i1:),']'//spaces(1:i)//'[',labels,nlabels) - if (nlabels > 1) exit over_spaces1 - enddo over_spaces1 - elseif (index(line,',') > 1 .or. is_csv) then + call split(line(i1:),']',labels,nlabels) + elseif (index(line,',') > 1) then ! ! format style 2: mylabel1,mylabel2,mylabel3 ! istyle = 2 call split(line(i1:),',',labels,nlabelstmp) - if (is_csv) then - nlabels = nlabelstmp ! allow blank/arbitrary labels in csv format - else - nlabels = count_sensible_labels(nlabelstmp,labels) - endif + nlabels = count_sensible_labels(nlabelstmp,labels) else ! ! format style 3: # mylabel1 mylabel2 mylabel3 ! istyle = 3 - ! try splitting with 4, then 3, then 2 spaces until the number of labels decreases - nlabels_prev = 0 - over_spaces: do i=4,2,-1 - call split(line(i1:),spaces(1:i),labels,nlabelstmp) - ! quit if we already have the target number of labels - if (nlabelstmp == ntarget) exit over_spaces - - ! if the number of labels is > 1 but has decreased, quit, unless nlabels - ! still exceeds the number of labels we are hoping for (ntarget) - if ((nlabelstmp < nlabels_prev .or. nlabelstmp >= max(nlabels_prev,2) & - .and. i < 4 .and. .not. (ntarget > 0 .and. nlabelstmp > ntarget))) then - ! take the answer with the previous number of spaces - call split(line(i1:),spaces(1:i+1),labels,nlabelstmp) - exit over_spaces - endif - nlabels_prev = nlabelstmp - enddo over_spaces + call split(line(i1:),' ',labels,nlabelstmp) ! ! this style is dangerous, so perform sanity checks ! on the labels to ensure they are sensible @@ -652,6 +600,10 @@ subroutine get_column_labels(line,nlabels,labels,method,ndesired,csv) ! delete brackets if (nlabels <= size(labels)) then call string_delete(labels(i),',') + if (istyle==1) then + call string_delete(labels(i),'[') + call string_delete(labels(i),']') + endif if (istyle==1 .or. istyle==2) then labels(i) = trim(adjustl(labels(i))) ! delete leading numbers @@ -664,66 +616,9 @@ subroutine get_column_labels(line,nlabels,labels,method,ndesired,csv) labels(i) = trim(adjustl(labels(i))) endif enddo - ! delete loose trailing square bracket but only if not matching - if (istyle==1) then - if (index(labels(nlabels),']') > 0) then - i1 = count_char(labels(nlabels),'[') ! number of open brackets - i2 = count_char(labels(nlabels),']') ! number of closed brackets - if (i2 > i1) then ! if brackets do not match - ! find last trailing bracket - i2 = index(labels(nlabels),']',back=.true.) - ! delete it, but only if followed by spaces - if (i2==len_trim(labels(nlabels))) then - labels(nlabels) = labels(nlabels)(1:i2-1) - endif - endif - endif - endif end subroutine get_column_labels -!--------------------------------------------------------------------------- -! -! interface to the above routine that also searches for the line -! containing the column labels in the list of header lines -! -!--------------------------------------------------------------------------- -subroutine read_column_labels(iunit,nheaderlines,ncols,nlabels,labels,csv,debug) - integer, intent(in) :: iunit,nheaderlines,ncols - integer, intent(out) :: nlabels - character(len=*), dimension(:), intent(out) :: labels - logical, intent(in), optional :: csv,debug - character(len=len(labels(1))), dimension(size(labels)) :: tmplabel - character(len=max_line_length) :: line - logical :: is_csv,verbose,got_labels - integer :: i,imethod,ierr,nwanted - - is_csv = .false. - verbose = .false. - if (present(csv)) is_csv = csv - if (present(debug)) verbose = debug - got_labels = .false. - nlabels = 0 - nwanted = min(ncols,size(labels)) ! can either retrieve all labels or completely fill the labels array - labels = '' - rewind(iunit) - do i=1,nheaderlines - read(iunit,"(a)",iostat=ierr) line - !--try to match column labels from this header line, if not already matched (or dubious match) - call get_column_labels(trim(line),nlabels,tmplabel,method=imethod,ndesired=nwanted,csv=csv) - !--if we get nlabels > ncolumns, use them, but keep trying for a better match - if ((got_labels .and. nlabels == nwanted) .or. & - (.not.got_labels .and. nlabels >= nwanted & ! only allow single-spaced labels if == ncols - .and. (.not.(imethod>=4) .or. nlabels==nwanted))) then - labels(1:nwanted) = tmplabel(1:nwanted) - got_labels = .true. - endif - if (verbose) print "(5(1x,a,i0))",'DEBUG: line ',i,'nlabels = ',nlabels,& - 'want ',ncols,'method=',imethod,'len_trim(line)=',len_trim(line) !,' LABELS= '//tmplabel(1:ncols) - enddo - -end subroutine read_column_labels - !--------------------------------------------------------------------------- ! ! indicate if a character is a digit (number) or not diff --git a/src/main/utils_gr.F90 b/src/main/utils_gr.F90 index 59e128afd..dc4bdc818 100644 --- a/src/main/utils_gr.F90 +++ b/src/main/utils_gr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module utils_gr ! diff --git a/src/main/utils_hdf5.f90 b/src/main/utils_hdf5.f90 index 824c303fe..1abb6d55a 100644 --- a/src/main/utils_hdf5.f90 +++ b/src/main/utils_hdf5.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module utils_hdf5 ! diff --git a/src/main/utils_healpix.f90 b/src/main/utils_healpix.f90 index 922b7c034..51d0638a7 100644 --- a/src/main/utils_healpix.f90 +++ b/src/main/utils_healpix.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module healpix ! diff --git a/src/main/utils_indtimesteps.F90 b/src/main/utils_indtimesteps.F90 index 00a3415f8..22cffdf29 100644 --- a/src/main/utils_indtimesteps.F90 +++ b/src/main/utils_indtimesteps.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module timestep_ind ! @@ -43,7 +43,7 @@ pure real function get_dt(dtmax,ibini) real, intent(in) :: dtmax integer(kind=1), intent(in) :: ibini - get_dt = dtmax/2.**ibini + get_dt = dtmax/2**ibini end function get_dt diff --git a/src/main/utils_infiles.f90 b/src/main/utils_infiles.f90 index ec49fd6f4..8c7fe046e 100644 --- a/src/main/utils_infiles.f90 +++ b/src/main/utils_infiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module infile_utils ! diff --git a/src/main/utils_inject.f90 b/src/main/utils_inject.f90 index e28f69f75..3d5645f50 100644 --- a/src/main/utils_inject.f90 +++ b/src/main/utils_inject.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module injectutils ! diff --git a/src/main/utils_mathfunc.f90 b/src/main/utils_mathfunc.f90 index f07f519f5..27ea6a179 100644 --- a/src/main/utils_mathfunc.f90 +++ b/src/main/utils_mathfunc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mathfunc ! diff --git a/src/main/utils_omp.F90 b/src/main/utils_omp.F90 index 32ee09250..4e16060bd 100644 --- a/src/main/utils_omp.F90 +++ b/src/main/utils_omp.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module omputils ! diff --git a/src/main/utils_raytracer.f90 b/src/main/utils_raytracer.f90 index ee414f1ca..26fc66a15 100644 --- a/src/main/utils_raytracer.f90 +++ b/src/main/utils_raytracer.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module raytracer ! diff --git a/src/main/utils_shuffleparticles.F90 b/src/main/utils_shuffleparticles.F90 index 7a8665a1a..f44bd8c81 100644 --- a/src/main/utils_shuffleparticles.F90 +++ b/src/main/utils_shuffleparticles.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module utils_shuffleparticles ! diff --git a/src/main/utils_sort.f90 b/src/main/utils_sort.f90 index eae395000..cedd629cf 100644 --- a/src/main/utils_sort.f90 +++ b/src/main/utils_sort.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module sortutils ! diff --git a/src/main/utils_sphNG.f90 b/src/main/utils_sphNG.f90 index 065101387..cacdd585a 100644 --- a/src/main/utils_sphNG.f90 +++ b/src/main/utils_sphNG.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module sphNGutils ! diff --git a/src/main/utils_spline.f90 b/src/main/utils_spline.f90 index bb40adb31..e532c079f 100644 --- a/src/main/utils_spline.f90 +++ b/src/main/utils_spline.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module splineutils ! diff --git a/src/main/utils_summary.F90 b/src/main/utils_summary.F90 index 14b618a63..9a93f2824 100644 --- a/src/main/utils_summary.F90 +++ b/src/main/utils_summary.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module io_summary ! diff --git a/src/main/utils_supertimestep.F90 b/src/main/utils_supertimestep.F90 index 45cf8082e..35b688886 100644 --- a/src/main/utils_supertimestep.F90 +++ b/src/main/utils_supertimestep.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module timestep_sts ! diff --git a/src/main/utils_system.f90 b/src/main/utils_system.f90 index 7f43d764e..d3f20ca3d 100644 --- a/src/main/utils_system.f90 +++ b/src/main/utils_system.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module systemutils ! diff --git a/src/main/utils_tables.f90 b/src/main/utils_tables.f90 index 292abac6f..a575406c5 100644 --- a/src/main/utils_tables.f90 +++ b/src/main/utils_tables.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module table_utils ! diff --git a/src/main/utils_timing.f90 b/src/main/utils_timing.f90 index 935b90e3d..c04be142c 100644 --- a/src/main/utils_timing.f90 +++ b/src/main/utils_timing.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module timing ! @@ -50,21 +50,11 @@ module timing itimer_force = 9, & itimer_force_local = 10, & itimer_force_remote = 11, & - itimer_radiation = 12, & - itimer_rad_save = 13, & - itimer_rad_neighlist = 14, & - itimer_rad_arrays = 15, & - itimer_rad_its = 16, & - itimer_rad_flux = 17, & - itimer_rad_lambda = 18, & - itimer_rad_diff = 19, & - itimer_rad_update = 20, & - itimer_rad_store = 21, & - itimer_cons2prim = 22, & - itimer_extf = 23, & - itimer_ev = 24, & - itimer_io = 25 - integer, public, parameter :: ntimers = 25 ! should be equal to the largest itimer index + itimer_cons2prim = 12, & + itimer_extf = 13, & + itimer_ev = 14, & + itimer_io = 15 + integer, public, parameter :: ntimers = 15 ! should be equal to the largest itimer index type(timer), public :: timers(ntimers) private @@ -91,16 +81,6 @@ subroutine setup_timers call init_timer(itimer_force , 'force', itimer_step ) call init_timer(itimer_force_local , 'local', itimer_force ) call init_timer(itimer_force_remote, 'remote', itimer_force ) - call init_timer(itimer_radiation , 'radiation', itimer_step ) - call init_timer(itimer_rad_save , 'save', itimer_radiation ) - call init_timer(itimer_rad_neighlist,'neighlist', itimer_radiation ) - call init_timer(itimer_rad_arrays , 'arrays', itimer_radiation ) - call init_timer(itimer_rad_its , 'its', itimer_radiation ) - call init_timer(itimer_rad_flux , 'flux', itimer_rad_its ) - call init_timer(itimer_rad_lambda , 'lambda', itimer_rad_its ) - call init_timer(itimer_rad_diff , 'diff', itimer_rad_its ) - call init_timer(itimer_rad_update , 'update', itimer_rad_its ) - call init_timer(itimer_rad_store , 'store', itimer_radiation ) call init_timer(itimer_cons2prim , 'cons2prim', itimer_step ) call init_timer(itimer_extf , 'extf', itimer_step ) call init_timer(itimer_ev , 'write_ev', 0 ) @@ -313,10 +293,11 @@ subroutine print_timer(lu,itimer,time_total) integer, intent(in) :: itimer real(kind=4), intent(in) :: time_total + ! Print label and tree structure + write(lu, "(1x,a)", advance="no") trim(timers(itimer)%treelabel) + ! Print timings if (timers(itimer)%wall > epsilon(0._4)) then - ! Print label and tree structure - write(lu, "(1x,a)", advance="no") trim(timers(itimer)%treelabel) if (time_total > 7200.0) then write(lu,"(' ',f7.2,'h ',f8.2,'h ',f6.2,' ',f6.2,'%',' ',f6.2,'%')") & timers(itimer)%wall/3600.,& @@ -339,6 +320,8 @@ subroutine print_timer(lu,itimer,time_total) timers(itimer)%loadbal*100.,& timers(itimer)%wall/time_total*100. endif + else + write(lu, "()") endif end subroutine print_timer diff --git a/src/main/utils_vectors.f90 b/src/main/utils_vectors.f90 index eb268abd2..bb49251e0 100644 --- a/src/main/utils_vectors.f90 +++ b/src/main/utils_vectors.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module vectorutils ! diff --git a/src/main/viscosity.f90 b/src/main/viscosity.f90 index 604dbe593..674815fd4 100644 --- a/src/main/viscosity.f90 +++ b/src/main/viscosity.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module viscosity ! diff --git a/src/main/wind.F90 b/src/main/wind.F90 index c2ac72734..5f974107f 100644 --- a/src/main/wind.F90 +++ b/src/main/wind.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module wind ! @@ -29,8 +29,8 @@ module wind private ! Shared variables - real, parameter :: Tdust_stop = 0.01 ! Temperature at outer boundary of wind simulation - real, parameter :: dtmin = 1.d-3 ! Minimum allowed timsestep (for 1D integration) + real, parameter :: Tdust_stop = 1.d-2 ! Temperature at outer boundary of wind simulation + real, parameter :: dtmin = 1.d-3 ! Minimum allowed timsestep (for 1D integration) integer, parameter :: wind_emitting_sink = 1 character(len=*), parameter :: label = 'wind' @@ -67,7 +67,7 @@ subroutine setup_wind(Mstar_cg, Mdot_code, u_to_T, r0, T0, v0, rsonic, tsonic, s Mstar_cgs = Mstar_cg wind_gamma = gamma - Mdot_cgs = real(Mdot_code * umass/utime) + Mdot_cgs = Mdot_code * umass/utime u_to_temperature_ratio = u_to_T if (idust_opacity == 2) then @@ -120,14 +120,14 @@ subroutine init_wind(r0, v0, T0, time_end, state, tau_lucy_init) Mstar_cgs = xyzmh_ptmass(4,wind_emitting_sink)*umass state%dt = 1000. - if (time_end > 0.) then + if (time_end > 0.d0) then ! integration stops when time = time_end state%find_sonic_solution = .false. state%time_end = time_end else ! integration stops once the sonic point is reached state%find_sonic_solution = .true. - state%time_end = -1. + state%time_end = -1.d0 endif state%time = 0. state%r_old = 0. @@ -312,7 +312,7 @@ subroutine wind_step(state) call calc_cooling_rate(Q_code,dlnQ_dlnT,state%rho/unit_density,state%Tg,state%Tdust,& state%mu,state%gamma,state%K2,state%kappa) state%Q = Q_code*unit_ergg - state%dQ_dr = (state%Q-Q_old)/(1.e-10+state%r-state%r_old) + state%dQ_dr = (state%Q-Q_old)/(1.d-10+state%r-state%r_old) endif state%time = state%time + state%dt @@ -441,10 +441,10 @@ subroutine wind_step(state) !apply cooling if (icooling > 0) then Q_old = state%Q - call calc_cooling_rate(Q_code,dlnQ_dlnT,real(state%rho/unit_density),state%Tg,state%Tdust,& + call calc_cooling_rate(Q_code,dlnQ_dlnT,state%rho/unit_density,state%Tg,state%Tdust,& state%mu,state%gamma,state%K2,state%kappa) state%Q = Q_code*unit_ergg - state%dQ_dr = (state%Q-Q_old)/(1.e-10+state%r-state%r_old) + state%dQ_dr = (state%Q-Q_old)/(1.d-10+state%r-state%r_old) endif if (state%time_end > 0. .and. state%time + state%dt > state%time_end) then @@ -910,7 +910,7 @@ subroutine interp_wind_profile(time, local_time, r, v, u, rho, e, GM, fdone, JKm e = .5*v**2 - GM/r + gammai*u if (local_time == 0.) then - fdone = 1. + fdone = 1.d0 else fdone = ltime/(local_time*utime) endif @@ -929,7 +929,7 @@ subroutine save_windprofile(r0, v0, T0, rout, tend, tcross, filename) real, intent(in) :: r0, v0, T0, tend, rout real, intent(out) :: tcross !time to cross the entire integration domain character(*), intent(in) :: filename - real, parameter :: Tdust_stop = 1. ! Temperature at outer boundary of wind simulation + real, parameter :: Tdust_stop = 1.d0 ! Temperature at outer boundary of wind simulation integer, parameter :: nlmax = 8192 ! maxium number of steps store in the 1D profile real :: time_end, tau_lucy_init real :: r_incr,v_incr,T_incr,mu_incr,gamma_incr,r_base,v_base,T_base,mu_base,gamma_base,eps @@ -958,7 +958,7 @@ subroutine save_windprofile(r0, v0, T0, rout, tend, tcross, filename) eps = 0.01 iter = 0 itermax = int(huge(itermax)/10.) !this number is huge but may be needed for RK6 solver - tcross = huge(0.) + tcross = 1.d99 writeline = 0 r_base = state%r diff --git a/src/main/wind_equations.f90 b/src/main/wind_equations.f90 index f6fec0ec5..a04454303 100644 --- a/src/main/wind_equations.f90 +++ b/src/main/wind_equations.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module wind_equations ! @@ -109,10 +109,10 @@ subroutine evolve_hydro(dt, rvT, Rstar_cgs, Mdot_cgs, mu, gamma, alpha, dalpha_d rvT = new_rvT !constrain timestep so the changes in r,v & T do not exceed dt_tol - dt_next = min(dt_next,1e-2*real(au/new_rvt(2)),& - dt_tol*dt*abs(rvt(1)/(1e-10+(new_rvt(1)-rvt(1)))),& - dt_tol*dt*abs(rvt(2)/(1e-10+(new_rvt(2)-rvt(2)))),& - dt_tol*dt*abs(rvt(3)/(1e-10+(new_rvt(3)-rvt(3))))) + dt_next = min(dt_next,1.d-2*au/new_rvt(2),& + dt_tol*dt*abs(rvt(1)/(1.d-10+(new_rvt(1)-rvt(1)))),& + dt_tol*dt*abs(rvt(2)/(1.d-10+(new_rvt(2)-rvt(2)))),& + dt_tol*dt*abs(rvt(3)/(1.d-10+(new_rvt(3)-rvt(3))))) spcode = 0 if (numerator < -num_tol .and. denominator > -denom_tol) spcode = 1 !no solution for stationary wind diff --git a/src/main/writeheader.F90 b/src/main/writeheader.F90 index b634f2a10..e7a6a891d 100644 --- a/src/main/writeheader.F90 +++ b/src/main/writeheader.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module writeheader ! diff --git a/src/setup/density_profiles.f90 b/src/setup/density_profiles.f90 index d71a5a5e6..792263102 100644 --- a/src/setup/density_profiles.f90 +++ b/src/setup/density_profiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module rho_profile ! diff --git a/src/setup/libsetup.f90 b/src/setup/libsetup.f90 index 990b40f9d..6280a072e 100644 --- a/src/setup/libsetup.f90 +++ b/src/setup/libsetup.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module libsetup ! diff --git a/src/setup/phantomsetup.F90 b/src/setup/phantomsetup.F90 index 5d0a13cb9..7026c3c90 100644 --- a/src/setup/phantomsetup.F90 +++ b/src/setup/phantomsetup.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantomsetup ! @@ -20,13 +20,13 @@ program phantomsetup ! setup_params, systemutils, timestep, units ! use memory, only:allocate_memory,deallocate_memory - use dim, only:tagline,maxvxyzu,mpi,& + use dim, only:tagline,maxp,maxvxyzu,mpi,& ndivcurlv,ndivcurlB,maxp_hard use part, only:xyzh,massoftype,hfact,vxyzu,npart,npartoftype, & - Bxyz,Bextx,Bexty,Bextz,rhoh,& + Bxyz,Bextx,Bexty,Bextz,rhoh,iphase,maxphase,& isetphase,igas,iamtype,labeltype,mhd,init_part use setBfield, only:set_Bfield - use eos, only:polyk,gamma + use eos, only:polyk,gamma,en_from_utherm use io, only:set_io_unit_numbers,id,master,nprocs,iwritein,fatal,warning use readwrite_dumps, only:init_readwrite_dumps,write_fulldump use readwrite_infile,only:write_infile,read_infile @@ -47,11 +47,12 @@ program phantomsetup use krome_interface, only:write_KromeSetupFile #endif implicit none - integer :: nargs,nprocsfake,nerr,nwarn,myid,myid1 + integer :: nargs,i,nprocsfake,nerr,nwarn,myid,myid1 integer(kind=8) :: ntotal,n_alloc integer, parameter :: lenprefix = 120 character(len=lenprefix) :: fileprefix character(len=lenprefix+10) :: dumpfile,infile,evfile,logfile + real :: pmassi logical :: iexist nprocs = 1 ! for MPI, this is not initialised until init_mpi, but an initialised value is required for init_part @@ -135,9 +136,20 @@ program phantomsetup !--perform sanity checks on the output of setpart routine ! call check_setup(nerr,nwarn) - if (nwarn > 0) call warning('initial','warnings during particle setup',var='warnings',ival=nwarn) if (nerr > 0) call fatal('initial','errors in particle setup',var='errors',ival=nerr) +! +!--setup defines thermal energy: if we are using the entropy then +! we need to convert this into the entropy variable before writing the dump file +! (the dump file write converts back to utherm) +! + if (maxvxyzu==4) then + pmassi = massoftype(igas) + do i=1,npart + if (maxphase==maxp) pmassi = massoftype(iamtype(iphase(i))) + vxyzu(maxvxyzu,i) = en_from_utherm(vxyzu(:,i),rhoh(xyzh(4,i),pmassi),gamma) + enddo + endif if (nprocsfake > 1) then ntotal = npart_total @@ -148,7 +160,7 @@ program phantomsetup ! if code is run in relativistic units (c=1) if (c_is_unity()) calc_gravitwaves = .true. - if (id==master .and. nerr==0 .and. nwarn==0) call print_units() + if (id==master) call print_units() ! !--dumpfile name should end in .tmp unless density has been calculated ! (never true using phantomsetup) diff --git a/src/setup/readwrite_kepler.f90 b/src/setup/readwrite_kepler.f90 index 2ab20d606..372d41061 100644 --- a/src/setup/readwrite_kepler.f90 +++ b/src/setup/readwrite_kepler.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module readwrite_kepler ! diff --git a/src/setup/readwrite_mesa.f90 b/src/setup/readwrite_mesa.f90 index bb8312f36..e268d1c02 100644 --- a/src/setup/readwrite_mesa.f90 +++ b/src/setup/readwrite_mesa.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module readwrite_mesa ! @@ -31,22 +31,23 @@ module readwrite_mesa !----------------------------------------------------------------------- subroutine read_mesa(filepath,rho,r,pres,m,ene,temp,X_in,Z_in,Xfrac,Yfrac,Mstar,ierr,cgsunits) use physcon, only:solarm,solarr - use fileutils, only:get_nlines,get_ncolumns,string_delete,lcase,read_column_labels + use fileutils, only:get_nlines,get_ncolumns,string_delete,lcase use datafiles, only:find_phantom_datafile use units, only:udist,umass,unit_density,unit_pressure,unit_ergg + integer :: lines,rows,i,ncols,nheaderlines,iu character(len=*), intent(in) :: filepath - integer, intent(out) :: ierr - real, intent(in) :: X_in,Z_in - real, allocatable,dimension(:),intent(out) :: rho,r,pres,m,ene,temp,Xfrac,Yfrac - real, intent(out) :: Mstar logical, intent(in), optional :: cgsunits - integer :: lines,i,ncols,nheaderlines,nlabels - integer :: idir,iu + integer, intent(out) :: ierr + character(len=10000) :: dumc character(len=120) :: fullfilepath - character(len=24),allocatable :: header(:) + character(len=24),allocatable :: header(:),dum(:) logical :: iexist,usecgs,ismesafile,got_column real,allocatable,dimension(:,:) :: dat + real, intent(in) :: X_in,Z_in + real,allocatable,dimension(:),intent(out) :: rho,r,pres,m,ene,temp,Xfrac,Yfrac + real, intent(out) :: Mstar + rows = 0 usecgs = .false. if (present(cgsunits)) usecgs = cgsunits ! @@ -62,119 +63,93 @@ subroutine read_mesa(filepath,rho,r,pres,m,ene,temp,X_in,Z_in,Xfrac,Yfrac,Mstar, lines = get_nlines(fullfilepath) ! total number of lines in file print "(1x,a)",trim(fullfilepath) - open(newunit=iu,file=fullfilepath,status='old',iostat=ierr) - if (ierr /= 0) then - print "(a,/)",' ERROR opening file '//trim(fullfilepath) - return - endif - + open(newunit=iu,file=fullfilepath,status='old') call get_ncolumns(iu,ncols,nheaderlines) if (nheaderlines == 6) then ! Assume file is a MESA profile, and so it has 6 header lines, and (row=3, col=2) = number of zones - read(iu,'()',iostat=ierr) - read(iu,'()',iostat=ierr) - read(iu,*,iostat=ierr) lines,lines - read(iu,'()',iostat=ierr) - read(iu,'()',iostat=ierr) - if (ierr /= 0) then - print "(a,/)",' ERROR reading MESA file header' - return - endif + read(iu,'()') + read(iu,'()') + read(iu,*) lines,lines + read(iu,'()') + read(iu,'()') ismesafile = .true. else ismesafile = .false. lines = lines - nheaderlines do i = 1,nheaderlines-1 - read(iu,'()',iostat=ierr) + read(iu,'()') enddo - if (ierr /= 0) then - print "(a,/)",' ERROR reading file header [not MESA format]' - return - endif endif if (lines <= 0) then ! file not found ierr = 1 return endif - ! extract column labels from the file header - allocate(header(ncols),dat(lines,ncols)) - call read_column_labels(iu,nheaderlines,ncols,nlabels,header) - if (nlabels /= ncols) print*,' WARNING: different number of labels compared to columns' + read(iu,'(a)') dumc! counting rows + call string_delete(dumc,'[') + call string_delete(dumc,']') + allocate(dum(500)) ; dum = 'aaa' + read(dumc,*,end=101) dum +101 continue + do i = 1,500 + if (dum(i)=='aaa') then + rows = i-1 + exit + endif + enddo + allocate(header(rows),dat(lines,rows)) + header(1:rows) = dum(1:rows) + deallocate(dum) + do i = 1,lines + read(iu,*) dat(lines-i+1,1:rows) + enddo allocate(m(lines),r(lines),pres(lines),rho(lines),ene(lines), & - temp(lines),Xfrac(lines),Yfrac(lines)) + temp(lines),Xfrac(lines),Yfrac(lines)) - over_directions: do idir=1,2 ! try backwards, then forwards - if (idir==1) then - ! read MESA file backwards, from surface to centre - do i = 1,lines - read(iu,*,iostat=ierr) dat(lines-i+1,1:ncols) - enddo - else - ! read file forwards, from centre to surface - do i = 1,lines - read(iu,*,iostat=ierr) dat(i,1:ncols) - enddo - endif - if (ierr /= 0) then - print "(a,/)",' ERROR reading data from file: reached end of file?' + close(iu) + ! Set mass fractions to fixed inputs if not in file + Xfrac = X_in + Yfrac = 1. - X_in - Z_in + do i = 1,rows + if (header(i)(1:1) == '#' .and. .not. trim(lcase(header(i)))=='#mass') then + print '("Detected wrong header entry : ",A," in file ",A)',trim(lcase(header(i))),trim(fullfilepath) + ierr = 2 return endif - - ! Set mass fractions to fixed inputs if not in file - Xfrac = X_in - Yfrac = 1. - X_in - Z_in - do i = 1,ncols - if (header(i)(1:1) == '#' .and. .not. trim(lcase(header(i)))=='#mass') then - print '("Detected wrong header entry : ",a," in file ",a)',trim(lcase(header(i))),trim(fullfilepath) - ierr = 2 - return - endif - got_column = .true. - select case(trim(lcase(header(i)))) - case('mass_grams') - m = dat(1:lines,i) - case('mass','#mass','m') - m = dat(1:lines,i) - if (ismesafile .or. maxval(m) < 1.e-10*solarm) m = m * solarm ! If reading MESA profile, 'mass' is in units of Msun - case('rho','density') - rho = dat(1:lines,i) - case('logrho') - rho = 10**(dat(1:lines,i)) - case('energy','e_int','e_internal') - ene = dat(1:lines,i) - case('radius_cm') - r = dat(1:lines,i) - case('radius','r') - r = dat(1:lines,i) - if (ismesafile .or. maxval(r) < 1e-10*solarr) r = r * solarr - case('logr') - r = (10**dat(1:lines,i)) * solarr - case('pressure','p') - pres = dat(1:lines,i) - case('temperature','t') - temp = dat(1:lines,i) - case('x_mass_fraction_h','xfrac') - Xfrac = dat(1:lines,i) - case('y_mass_fraction_he','yfrac') - Yfrac = dat(1:lines,i) - case default - got_column = .false. - end select - if (got_column .and. idir==1) print "(1x,i0,': ',a)",i,trim(header(i)) - enddo - if (idir==1) print "(a)" - - ! quit the loop over directions if the radius increases - if (idir==1 .and. r(2) > r(1)) exit over_directions - - ! otherwise rewind and re-skip header - rewind(iu) - do i=1,nheaderlines - read(iu,*,iostat=ierr) - enddo - enddo over_directions - close(iu) + got_column = .true. + select case(trim(lcase(header(i)))) + case('mass_grams') + m = dat(1:lines,i) + case('mass','#mass') + m = dat(1:lines,i) + if (ismesafile) m = m * solarm ! If reading MESA profile, 'mass' is in units of Msun + case('rho','density') + rho = dat(1:lines,i) + case('logrho') + rho = 10**(dat(1:lines,i)) + case('energy','e_int','e_internal') + ene = dat(1:lines,i) + case('radius_cm') + r = dat(1:lines,i) + case('radius') + r = dat(1:lines,i) + if (ismesafile) r = r * solarr + case('logr') + r = (10**dat(1:lines,i)) * solarr + case('pressure') + pres = dat(1:lines,i) + case('temperature') + temp = dat(1:lines,i) + case('x_mass_fraction_h','xfrac') + Xfrac = dat(1:lines,i) + case('y_mass_fraction_he','yfrac') + Yfrac = dat(1:lines,i) + case default + got_column = .false. + end select + if (got_column) print "(1x,i0,': ',a)",i,trim(header(i)) + enddo + print "(a)" if (.not. usecgs) then m = m / umass diff --git a/src/setup/relax_star.f90 b/src/setup/relax_star.f90 index 10ebeba56..65db5de98 100644 --- a/src/setup/relax_star.f90 +++ b/src/setup/relax_star.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module relaxstar ! @@ -15,6 +15,7 @@ module relaxstar ! ! :Runtime parameters: ! - maxits : *maximum number of relaxation iterations* +! - tol_dens : *% error in density to stop relaxation* ! - tol_ekin : *tolerance on ekin/epot to stop relaxation* ! ! :Dependencies: checksetup, damping, deriv, dim, dump_utils, energies, @@ -26,6 +27,7 @@ module relaxstar public :: relax_star,write_options_relax,read_options_relax real, private :: tol_ekin = 1.e-7 ! criteria for being converged + real, private :: tol_dens = 1. ! allow 1% RMS error in density integer, private :: maxits = 1000 real, private :: gammaprev,hfactprev,mass1prev @@ -175,9 +177,9 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np ierr = ierr_unbound return endif - if (id==master) print "(/,3(a,1pg11.3),/,a,1pg11.3,a,i4)",& + if (id==master) print "(/,3(a,1pg11.3),/,a,0pf6.2,a,es11.3,a,i4)",& ' RELAX-A-STAR-O-MATIC: Etherm:',etherm,' Epot:',Epot, ' R*:',maxval(r), & - ' WILL stop when Ekin/Epot < ',tol_ekin,' OR Iter=',maxits + ' WILL stop WHEN: dens error < ',tol_dens,'% AND Ekin/Epot < ',tol_ekin,' OR Iter=',maxits if (write_files) then if (.not.restart) call write_fulldump(t,filename) @@ -213,22 +215,18 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np ! compute energies and check for convergence ! call compute_energies(t) - converged = (ekin > 0. .and. ekin/abs(epot) < tol_ekin) !.and. rmserr < 0.01*tol_dens) + converged = (ekin > 0. .and. ekin/abs(epot) < tol_ekin .and. rmserr < 0.01*tol_dens) ! ! print information to screen ! if (use_step) then - if (id==master .and. mod(nits,10)==0 .or. nits==1) then - print "(a,es10.3,a,2pf6.2,2(a,1pg11.3))",& - ' Relaxing star: t/dyn:',t/tdyn,', dens error:',rmserr,'%, R*:',rmax, & - ' Ekin/Epot:',ekin/abs(epot) - endif + if (id==master) print "(a,es10.3,a,2pf6.2,2(a,1pg11.3))",& + ' Relaxing star: t/dyn:',t/tdyn,', dens error:',rmserr,'%, R*:',rmax, & + ' Ekin/Epot:',ekin/abs(epot) else - if (id==master .and. mod(nits,10)==0 .or. nits==1) then - print "(a,i4,a,i4,a,2pf6.2,2(a,1pg11.3))",& - ' Relaxing star: Iter',nits,'/',maxits, & - ', dens error:',rmserr,'%, R*:',rmax,' Ekin/Epot:',ekin/abs(epot) - endif + if (id==master) print "(a,i4,a,i4,a,2pf6.2,2(a,1pg11.3))",& + ' Relaxing star: Iter',nits,'/',maxits, & + ', dens error:',rmserr,'%, R*:',rmax,' Ekin/Epot:',ekin/abs(epot) endif ! ! additional diagnostic output, mainly for debugging/checking @@ -441,7 +439,7 @@ subroutine check_for_existing_file(filename,npart,mgas,xyzh,vxyzu,restart,ierr) real, intent(inout) :: xyzh(:,:),vxyzu(:,:) logical, intent(out) :: restart integer, intent(out) :: ierr - logical :: iexist + logical :: iexist,tagged character(len=len(filename)) :: restart_file,filetmp character(len=lenid) :: fileid type(dump_h) :: hdr @@ -466,7 +464,7 @@ subroutine check_for_existing_file(filename,npart,mgas,xyzh,vxyzu,restart,ierr) print "(/,1x,a)",'>> RESTARTING relaxation from '//trim(restart_file) call open_dumpfile_r(idump,restart_file,fileid,ierr) - call read_header(idump,hdr,ierr) + call read_header(idump,hdr,tagged,ierr) close(idump) if (ierr /= 0) then print "(a)",' ERROR: could not read file header' @@ -547,6 +545,7 @@ subroutine write_options_relax(iunit) integer, intent(in) :: iunit call write_inopt(tol_ekin,'tol_ekin','tolerance on ekin/epot to stop relaxation',iunit) + call write_inopt(tol_dens,'tol_dens','% error in density to stop relaxation',iunit) call write_inopt(maxits,'maxits','maximum number of relaxation iterations',iunit) end subroutine write_options_relax @@ -562,6 +561,7 @@ subroutine read_options_relax(db,nerr) integer, intent(inout) :: nerr call read_inopt(tol_ekin,'tol_ekin',db,errcount=nerr) + call read_inopt(tol_dens,'tol_dens',db,errcount=nerr) call read_inopt(maxits,'maxits',db,errcount=nerr) end subroutine read_options_relax diff --git a/src/setup/set_Bfield.f90 b/src/setup/set_Bfield.f90 index 2a1a2dfe5..1c1f9afc6 100644 --- a/src/setup/set_Bfield.f90 +++ b/src/setup/set_Bfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setBfield ! diff --git a/src/setup/set_binary.f90 b/src/setup/set_binary.f90 index 270f6f927..90c75396e 100644 --- a/src/setup/set_binary.f90 +++ b/src/setup/set_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setbinary ! @@ -47,31 +47,16 @@ module setbinary contains -!------------------------------------------------------------------------------ +!---------------------------------------------------------------- !+ -! setup for a binary orbit -! -! INPUT: -! m1 - mass of object 1 -! m2 - mass of object 2 -! semimajoraxis - semimajor axis (e/=1) or pericentre distance (e=1) -! eccentricity - eccentricity -! accretion_radius1 - accretion radius for point mass 1 -! accretion_radius2 - accretion radius for point mass 2 -! [optional] posang_ascnode - position angle of the ascending node (Omega, deg) -! [optional] arg_peri - argument of periapsis (w, deg) -! [optional] incl - orbital inclination (i, deg) -! [optional] f - true anomaly (nu, deg) -! [optional] mean_anomaly - mean anomaly (M, deg; replaces true anomaly) -! -! OUTPUT: cartesian positions and velocities for both objects +! setup for a binary !+ -!------------------------------------------------------------------------------ +!---------------------------------------------------------------- subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & accretion_radius1,accretion_radius2, & xyzmh_ptmass,vxyz_ptmass,nptmass,ierr,omega_corotate,& posang_ascnode,arg_peri,incl,f,mean_anomaly,verbose) - use binaryutils, only:get_E,get_E_from_mean_anomaly,get_E_from_true_anomaly + use binaryutils, only:get_E,get_E_from_mean_anomaly real, intent(in) :: m1,m2 real, intent(in) :: semimajoraxis,eccentricity real, intent(in) :: accretion_radius1,accretion_radius2 @@ -82,12 +67,10 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & real, intent(out), optional :: omega_corotate logical, intent(in), optional :: verbose integer :: i1,i2,i - real :: mtot,dx(3),dv(3),Rochelobe1,Rochelobe2,period,bigM,rperi,rapo + real :: mtot,dx(3),dv(3),Rochelobe1,Rochelobe2,period,bigM real :: x1(3),x2(3),v1(3),v2(3),omega0,cosi,sini,xangle,reducedmass,angmbin - real :: a,E,E_dot,P(3),Q(3),omega,big_omega,inc,ecc,tperi - real :: term1,term2,term3,term4,theta,theta_max,energy + real :: a,E,E_dot,P(3),Q(3),omega,big_omega,inc,ecc,tperi,term1,term2,theta logical :: do_verbose - character(len=12) :: orbit_type ierr = 0 do_verbose = .true. @@ -99,67 +82,12 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & ! masses mtot = m1 + m2 - reducedmass = m1*m2/mtot - - ! check for stupid parameter choices - if (m1 <= 0.) then - print "(1x,a)",'ERROR: set_binary: primary mass <= 0' - ierr = ierr_m1 - endif - if (m2 < 0.) then - print "(1x,a)",'ERROR: set_binary: secondary mass < 0' - ierr = ierr_m2 - endif - if (abs(semimajoraxis) <= tiny(0.)) then - print "(1x,a)",'ERROR: set_binary: semi-major axis = 0' - ierr = ierr_semi - endif - if (semimajoraxis < 0. .and. eccentricity <= 1.) then - print "(1x,a)",'ERROR: set_binary: using a < 0 requires e > 1' - ierr = ierr_semi - endif - if (eccentricity < 0.) then - print "(1x,a)",'ERROR: set_binary: eccentricity must be positive' - ierr = ierr_ecc - endif - if (eccentricity > 1. .and. present(f)) then - theta = f*pi/180. - theta_max = acos(-1./eccentricity) - if (abs(theta) > theta_max) then - print "(1x,2(a,f8.2))",'ERROR: max true anomaly for e = ',eccentricity, & - ' is |nu| < ',theta_max*180./pi - ierr = ierr_ecc - endif - endif - ! exit routine if cannot continue - if (ierr /= 0) return - ! set parameters that depend on the orbit type - if (eccentricity < 1.) then - a = abs(semimajoraxis) - rperi = a*(1. - eccentricity) - rapo = semimajoraxis*(1. + eccentricity) - period = sqrt(4.*pi**2*a**3/mtot) - angmbin = reducedmass*sqrt(mtot*a*(1. - eccentricity**2)) - energy = -mtot/(2.*a) - elseif (eccentricity > 1.) then - a = -abs(semimajoraxis) - rperi = a*(1. - eccentricity) - rapo = huge(rapo) - period = huge(period) - angmbin = reducedmass*sqrt(mtot*a*(1. - eccentricity**2)) - energy = -mtot/(2.*a) - else - a = huge(a) - rperi = abs(semimajoraxis) ! for parabolic orbit we must give the pericentre distance - rapo = huge(rapo) - period = huge(period) - angmbin = reducedmass*sqrt(2.*mtot*rperi) - energy = 0. - endif - - Rochelobe1 = Rochelobe_estimate(m2,m1,rperi) - Rochelobe2 = Rochelobe_estimate(m1,m2,rperi) + Rochelobe1 = Rochelobe_estimate(m2,m1,semimajoraxis) + Rochelobe2 = Rochelobe_estimate(m1,m2,semimajoraxis) + period = sqrt(4.*pi**2*semimajoraxis**3/mtot) + reducedmass = m1*m2/mtot + angmbin = reducedmass*sqrt(mtot*semimajoraxis*(1. - eccentricity**2)) if (do_verbose) then print "(/,2x,a)",'---------- binary parameters ----------- ' @@ -168,23 +96,45 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & 'secondary mass :',m2, & 'mass ratio m2/m1 :',m2/m1, & 'reduced mass :',reducedmass, & - 'semi-major axis :',a, & + 'semi-major axis :',semimajoraxis, & 'period :',period, & 'eccentricity :',eccentricity, & - 'pericentre :',rperi, & - 'apocentre :',rapo + 'pericentre :',semimajoraxis*(1. - eccentricity), & + 'apocentre :',semimajoraxis*(1. + eccentricity) endif if (accretion_radius1 > Rochelobe1) then - print "(1x,a)",'WARNING: set_binary: accretion radius of primary > Roche lobe at periastron' + print "(1x,a)",'WARNING: set_binary: accretion radius of primary > Roche lobe' endif if (accretion_radius2 > Rochelobe2) then - print "(1x,a)",'WARNING: set_binary: accretion radius of secondary > Roche lobe at periastron' + print "(1x,a)",'WARNING: set_binary: accretion radius of secondary > Roche lobe' + endif +! +!--check for stupid parameter choices +! + if (m1 <= 0.) then + print "(1x,a)",'ERROR: set_binary: primary mass <= 0' + ierr = ierr_m1 endif + if (m2 < 0.) then + print "(1x,a)",'ERROR: set_binary: secondary mass <= 0' + ierr = ierr_m2 + endif + if (semimajoraxis <= 0.) then + print "(1x,a)",'ERROR: set_binary: semi-major axis <= 0' + ierr = ierr_semi + endif + if (eccentricity > 1. .or. eccentricity < 0.) then + print "(1x,a)",'ERROR: set_binary: eccentricity must be between 0 and 1' + ierr = ierr_ecc + endif + ! exit routine if cannot continue + if (ierr /= 0) return dx = 0. dv = 0. if (present(posang_ascnode) .and. present(arg_peri) .and. present(incl)) then ! Campbell elements + a = semimajoraxis ecc = eccentricity omega = arg_peri*pi/180. ! our conventions here are Omega is measured East of North @@ -192,10 +142,10 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & inc = incl*pi/180. if (present(f)) then - ! get eccentric, parabolic or hyperbolic anomaly from true anomaly + ! get eccentric anomaly from true anomaly ! (https://en.wikipedia.org/wiki/Eccentric_anomaly#From_the_true_anomaly) theta = f*pi/180. - E = get_E_from_true_anomaly(theta,ecc) + E = atan2(sqrt(1. - ecc**2)*sin(theta),(ecc + cos(theta))) elseif (present(mean_anomaly)) then ! get eccentric anomaly from mean anomaly by solving Kepler equation bigM = mean_anomaly*pi/180. @@ -216,36 +166,17 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & Q(2) = -sin(omega)*sin(big_omega) + cos(omega)*cos(inc)*cos(big_omega) Q(3) = sin(inc)*cos(omega) - if (eccentricity < 1.) then ! eccentric - orbit_type = 'Eccentric' - term1 = a*(cos(E)-ecc) - term2 = a*(sqrt(1. - ecc*ecc)*sin(E)) - E_dot = sqrt((m1 + m2)/(a**3))/(1.-ecc*cos(E)) - term3 = a*(-sin(E)*E_dot) - term4 = a*(sqrt(1.- ecc*ecc)*cos(E)*E_dot) - elseif (eccentricity > 1.) then ! hyperbolic - orbit_type = 'Hyperbolic' - term1 = a*(cosh(E)-ecc) - term2 = -a*(sqrt(ecc*ecc - 1.)*sinh(E)) - E_dot = sqrt((m1 + m2)/(abs(a)**3))/(ecc*cosh(E)-1.) - term3 = a*(sinh(E)*E_dot) - term4 = -a*(sqrt(ecc*ecc - 1.)*cosh(E)*E_dot) - else ! parabolic - orbit_type = 'Parabolic' - term1 = rperi*(1. - E*E) - term2 = rperi*(2.*E) - E_dot = sqrt(2.*(m1 + m2)/(rperi**3))/(1. + E*E) - term3 = -E*(rperi*E_dot) - term4 = rperi*E_dot - endif + term1 = cos(E)-eccentricity + term2 = sqrt(1.-(eccentricity*eccentricity))*sin(E) + E_dot = sqrt((m1 + m2)/(a**3))/(1.-eccentricity*cos(E)) if (do_verbose) then print "(4(2x,a,1pg14.6,/),2x,a,1pg14.6)", & - trim(orbit_type)//' anomaly:',E, & + 'Eccentric anomaly:',E, & 'E_dot :',E_dot, & 'inclination (i, deg):',incl, & 'angle asc. node (O, deg):',posang_ascnode, & - 'arg. periapsis (w, deg):',arg_peri + 'arg. pericentre (w, deg):',arg_peri if (present(f)) print "(2x,a,1pg14.6)", & 'true anomaly (f, deg):',f if (present(mean_anomaly)) print "(2x,a,1pg14.6)", & @@ -254,10 +185,10 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & ! Rotating everything ! Set the positions for the primary and the central secondary - dx(:) = term1*P(:) + term2*Q(:) + dx(:) = a*(term1*P(:) + term2*Q(:)) ! + xyzmh_ptmass(1,1) ! Set the velocities - dv(:) = term3*P(:) + term4*Q(:) + dv(:) = -a*sin(E)*E_dot*P(:) + a*sqrt(1.-(ecc*ecc))*cos(E)*E_dot*Q(:) else ! set binary at apastron @@ -270,16 +201,14 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & x2 = dx*m1/mtot ! velocities - v1 = -dv*m2/mtot - v2 = dv*m1/mtot + v1 = -dv*m2/mtot !(/0.,-m2/mtot*vmag,0./) + v2 = dv*m1/mtot !(/0.,m1/mtot*vmag,0./) omega0 = v1(2)/x1(1) ! print info about positions and velocities if (do_verbose) then - print "(9(2x,a,1pg14.6,/),2x,a,1pg14.6)", & - 'energy (mtot/2a) :',energy,& - 'energy (KE+PE) :',-mtot/sqrt(dot_product(dx,dx)) + 0.5*dot_product(dv,dv),& + print "(7(2x,a,1pg14.6,/),2x,a,1pg14.6)", & 'angular momentum :',angmbin, & 'mean ang. speed :',omega0, & 'Omega_0 (prim) :',v1(2)/x1(1), & diff --git a/src/setup/set_cubic_core.f90 b/src/setup/set_cubic_core.f90 index ce3fa9427..a12a2ee42 100644 --- a/src/setup/set_cubic_core.f90 +++ b/src/setup/set_cubic_core.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setcubiccore ! diff --git a/src/setup/set_disc.F90 b/src/setup/set_disc.F90 index 6d37bf634..59296fe1e 100644 --- a/src/setup/set_disc.F90 +++ b/src/setup/set_disc.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setdisc ! @@ -74,8 +74,8 @@ subroutine set_disc(id,master,mixture,nparttot,npart,npart_start,rmin,rmax, & particle_type,particle_mass,hfact,xyzh,vxyzu,polyk, & position_angle,inclination,ismooth,alpha,rwarp,warp_smoothl, & bh_spin,bh_spin_angle,rref,enc_mass,r_grid,writefile,ierr,prefix,verbose) - use io, only:stdout - use part, only:maxp,idust,maxtypes + use io, only:stdout + use part, only:maxp,idust,maxtypes use centreofmass, only:get_total_angular_momentum integer, intent(in) :: id,master integer, optional, intent(in) :: nparttot diff --git a/src/setup/set_dust.f90 b/src/setup/set_dust.f90 index 632877194..1846b537d 100644 --- a/src/setup/set_dust.f90 +++ b/src/setup/set_dust.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module set_dust ! diff --git a/src/setup/set_dust_options.f90 b/src/setup/set_dust_options.f90 index fee9fd98a..e30e659e0 100644 --- a/src/setup/set_dust_options.f90 +++ b/src/setup/set_dust_options.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module set_dust_options ! diff --git a/src/setup/set_fixedentropycore.f90 b/src/setup/set_fixedentropycore.f90 index 6bf31ec59..4d6f22234 100644 --- a/src/setup/set_fixedentropycore.f90 +++ b/src/setup/set_fixedentropycore.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setfixedentropycore ! diff --git a/src/setup/set_flyby.f90 b/src/setup/set_flyby.f90 index b7668f9e6..4c7a95aff 100644 --- a/src/setup/set_flyby.f90 +++ b/src/setup/set_flyby.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setflyby ! @@ -194,7 +194,7 @@ function get_T_flyby(m1,m2,dma,n0) result(T) xi = -2*sqrt(n0-1.0)*dma yi = dma*(1.0-(xi/p)**2) - !--gravitational parameter + !--graviational parameter G = 1.0 ! we assume code units where G=1 mu = G*(m1+m2) diff --git a/src/setup/set_hierarchical.f90 b/src/setup/set_hierarchical.f90 index 5eeca00d0..90abcf607 100644 --- a/src/setup/set_hierarchical.f90 +++ b/src/setup/set_hierarchical.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module sethierarchical ! @@ -19,8 +19,7 @@ module sethierarchical ! ! :Owner: Simone Ceppi ! -! :Runtime parameters: -! - hierarchy : *string definining the hierarchy (e.g. 111,112,121,1221,1222)* +! :Runtime parameters: None ! ! :Dependencies: infile_utils, setbinary, sethier_utils ! @@ -111,35 +110,24 @@ subroutine write_hierarchical_setupfile(iunit) integer :: i write(iunit,"(/,a)") '# options for hierarchical system' - call write_inopt(hierarchy, 'hierarchy','string definining the hierarchy (e.g. 111,112,121,1221,1222)', iunit) + call write_inopt(hierarchy, 'hierarchy','', iunit) hs%labels = process_hierarchy(hierarchy) write(iunit,"(/,a)") '# sink properties' do i=1,hs%labels%sink_num - call write_inopt(hs%sinks(i)%mass, trim(hs%labels%sink(i))//'_mass',& - 'mass of object '//trim(hs%labels%sink(i)), iunit) - enddo - do i=1,hs%labels%sink_num - call write_inopt(hs%sinks(i)%accr, trim(hs%labels%sink(i))//'_accr',& - 'accretion radius for object '//trim(hs%labels%sink(i)), iunit) + call write_inopt(hs%sinks(i)%mass, trim(hs%labels%sink(i))//'_mass','', iunit) + call write_inopt(hs%sinks(i)%accr, trim(hs%labels%sink(i))//'_accr','', iunit) enddo write(iunit,"(/,a)") '# orbit properties' do i=1,hs%labels%hl_num - write(iunit,"(a)") '# binary '//trim(hs%labels%hl(i)) - call write_inopt(hs%levels(i)%a, trim(hs%labels%hl(i))//'_a',& - 'semi-major axis for binary '//trim(hs%labels%hl(i)),iunit) - call write_inopt(hs%levels(i)%e, trim(hs%labels%hl(i))//'_e',& - 'eccentricity for binary '//trim(hs%labels%hl(i)),iunit) - call write_inopt(hs%levels(i)%inc, trim(hs%labels%hl(i))//'_i',& - 'i [deg] inclination for binary '//trim(hs%labels%hl(i)),iunit) - call write_inopt(hs%levels(i)%O, trim(hs%labels%hl(i))//'_O',& - 'Omega [deg] PA of ascending node for binary '//trim(hs%labels%hl(i)),iunit) - call write_inopt(hs%levels(i)%w, trim(hs%labels%hl(i))//'_w',& - 'w [deg] argument of periapsis for binary '//trim(hs%labels%hl(i)),iunit) - call write_inopt(hs%levels(i)%f, trim(hs%labels%hl(i))//'_f',& - 'f [deg] true anomaly for binary '//trim(hs%labels%hl(i)),iunit) + call write_inopt(hs%levels(i)%a, trim(hs%labels%hl(i))//'_a','',iunit) + call write_inopt(hs%levels(i)%e, trim(hs%labels%hl(i))//'_e','',iunit) + call write_inopt(hs%levels(i)%inc, trim(hs%labels%hl(i))//'_i','',iunit) + call write_inopt(hs%levels(i)%O, trim(hs%labels%hl(i))//'_O','',iunit) + call write_inopt(hs%levels(i)%w, trim(hs%labels%hl(i))//'_w','',iunit) + call write_inopt(hs%levels(i)%f, trim(hs%labels%hl(i))//'_f','',iunit) enddo end subroutine write_hierarchical_setupfile diff --git a/src/setup/set_hierarchical_utils.f90 b/src/setup/set_hierarchical_utils.f90 index 8a1b4205c..16f4d8f00 100644 --- a/src/setup/set_hierarchical_utils.f90 +++ b/src/setup/set_hierarchical_utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module sethier_utils ! diff --git a/src/setup/set_planets.f90 b/src/setup/set_planets.f90 index 5a0ee55ed..49e9bba1e 100644 --- a/src/setup/set_planets.f90 +++ b/src/setup/set_planets.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setplanets ! diff --git a/src/setup/set_shock.f90 b/src/setup/set_shock.f90 index 65fd65484..f84b887c7 100644 --- a/src/setup/set_shock.f90 +++ b/src/setup/set_shock.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setshock ! diff --git a/src/setup/set_slab.f90 b/src/setup/set_slab.f90 index d8851f693..5626e9367 100644 --- a/src/setup/set_slab.f90 +++ b/src/setup/set_slab.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module slab ! diff --git a/src/setup/set_softened_core.f90 b/src/setup/set_softened_core.f90 index dd3648941..4a5b721d6 100644 --- a/src/setup/set_softened_core.f90 +++ b/src/setup/set_softened_core.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setsoftenedcore ! diff --git a/src/setup/set_sphere.f90 b/src/setup/set_sphere.f90 index 7aec455b2..3fe9463da 100644 --- a/src/setup/set_sphere.f90 +++ b/src/setup/set_sphere.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module spherical ! diff --git a/src/setup/set_star.f90 b/src/setup/set_star.f90 index 24071d154..7a617d3c3 100644 --- a/src/setup/set_star.f90 +++ b/src/setup/set_star.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setstar ! @@ -41,7 +41,6 @@ module setstar real :: initialtemp real :: rcore real :: mcore - real :: lcore real :: hsoft real :: hacc ! accretion radius if star is a sink particle character(len=120) :: input_profile,dens_profile @@ -81,7 +80,6 @@ subroutine set_defaults_star(star) star%hacc = 1. star%rcore = 0. star%mcore = 0. - star%lcore = 0. star%isofteningopt = 1 ! By default, specify rcore star%np = 1000 star%input_profile = 'P12_Phantom_Profile.data' @@ -110,7 +108,7 @@ subroutine set_star(id,master,star,xyzh,vxyzu,eos_vars,rad,& write_kepler_comp use radiation_utils, only:set_radiation_and_gas_temperature_equal use relaxstar, only:relax_star - use part, only:ihsoft,igas,imu,set_particle_type,ilum + use part, only:ihsoft,igas,imu,set_particle_type use extern_densprofile, only:write_rhotab use unifdis, only:mask_prototype use physcon, only:pi @@ -174,11 +172,6 @@ subroutine set_star(id,master,star,xyzh,vxyzu,eos_vars,rad,& ierr = 2 return endif - if (star%mstar < 0.) then - call fatal('set_star','cannot set up a star with negative mass!') - ierr = 2 - return - endif call set_star_density(lattice,id,master,rmin,star%rstar,star%mstar,hfact,& npts,den,r,npart,npartoftype,massoftype,xyzh,use_exactN,& star%np,rhozero,npart_total,mask) @@ -192,11 +185,10 @@ subroutine set_star(id,master,star,xyzh,vxyzu,eos_vars,rad,& ! ! add sink particle stellar core ! - if (star%isinkcore) call set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,ihsoft,& - star%mcore,star%hsoft,ilum,star%lcore,ierr) + if (star%isinkcore) call set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,& + ihsoft,star%mcore,star%hsoft,ierr) if (ierr==1) call fatal('set_stellar_core','mcore <= 0') if (ierr==2) call fatal('set_stellar_core','hsoft <= 0') - if (ierr==3) call fatal('set_stellar_core','lcore < 0') ! ! Write the desired profile to file (do this before relaxation) ! @@ -448,8 +440,8 @@ end subroutine set_defaults_given_profile subroutine set_star_interactive(id,master,star,need_iso,use_var_comp,ieos,polyk) use prompting, only:prompt use setstar_utils, only:nprofile_opts,profile_opt,need_inputprofile,need_rstar - use units, only:in_solarm,in_solarr,in_solarl,udist,umass,unit_luminosity - use physcon, only:solarr,solarm,solarl + use units, only:in_solarm,in_solarr,udist,umass + use physcon, only:solarr,solarm type(star_t), intent(out) :: star integer, intent(in) :: id,master logical, intent(out) :: use_var_comp @@ -457,14 +449,13 @@ subroutine set_star_interactive(id,master,star,need_iso,use_var_comp,ieos,polyk) integer, intent(inout) :: ieos real, intent(inout) :: polyk integer :: i - real :: mstar_msun,rstar_rsun,rcore_rsun,mcore_msun,lcore_lsun,hsoft_rsun + real :: mstar_msun,rstar_rsun,rcore_rsun,mcore_msun,hsoft_rsun ! set defaults call set_defaults_star(star) mstar_msun = real(in_solarm(star%mstar)) rstar_rsun = real(in_solarr(star%rstar)) mcore_msun = real(in_solarm(star%mcore)) - lcore_lsun = real(in_solarl(star%lcore)) rcore_rsun = real(in_solarr(star%rcore)) hsoft_rsun = real(in_solarr(star%hsoft)) @@ -515,10 +506,8 @@ subroutine set_star_interactive(id,master,star,need_iso,use_var_comp,ieos,polyk) if (star%isinkcore) then call prompt('Enter mass of the created sink particle core [Msun]',mcore_msun,0.) call prompt('Enter softening length of the sink particle core [Rsun]',hsoft_rsun,0.) - call prompt('Enter sink particle luminosity [Lsun]',lcore_lsun,0.) star%mcore = mcore_msun*real(solarm/umass) star%hsoft = hsoft_rsun*real(solarr/udist) - star%lcore = lcore_lsun*real(solarl/unit_luminosity) endif case(1) star%isinkcore = .true. ! Create sink particle core automatically @@ -543,20 +532,19 @@ subroutine set_star_interactive(id,master,star,need_iso,use_var_comp,ieos,polyk) star%mcore = mcore_msun*real(solarm/umass) star%rcore = rcore_rsun*real(solarr/udist) end select - call prompt('Enter sink particle luminosity [Lsun]',lcore_lsun,0.) - star%lcore = lcore_lsun*real(solarl/unit_luminosity) + + call prompt('Enter output file name of cored stellar profile:',star%outputfilename) case(2) star%isinkcore = .true. ! Create sink particle core automatically print*,'Specify core radius and initial guess for mass of sink particle core' call prompt('Enter core radius in Rsun : ',rcore_rsun,0.) call prompt('Enter guess for core mass in Msun : ',mcore_msun,0.) - call prompt('Enter sink particle luminosity [Lsun]',lcore_lsun,0.) call prompt('Enter output file name of cored stellar profile:',star%outputfilename) star%mcore = mcore_msun*real(solarm/umass) star%rcore = rcore_rsun*real(solarr/udist) - star%lcore = lcore_lsun*real(solarl/unit_luminosity) end select + case(ievrard) call prompt('Enter the specific internal energy (units of GM/R) ',star%ui_coef,0.) case(:0) @@ -573,7 +561,7 @@ end subroutine set_star_interactive subroutine write_options_star(star,iunit,label) use infile_utils, only:write_inopt,get_optstring use setstar_utils, only:nprofile_opts,profile_opt,need_inputprofile,need_rstar - use units, only:in_solarm,in_solarr,in_solarl + use units, only:in_solarm,in_solarr type(star_t), intent(in) :: star integer, intent(in) :: iunit character(len=*), intent(in), optional :: label @@ -626,8 +614,6 @@ subroutine write_options_star(star,iunit,label) call write_inopt(in_solarm(star%mcore),'mcore'//trim(c),& 'Initial guess for mass of sink particle stellar core [Msun]',iunit) endif - call write_inopt(in_solarl(star%lcore),'lcore'//trim(c),& - 'Luminosity of point mass stellar core [Lsun]',iunit) else call write_inopt(star%isinkcore,'isinkcore'//trim(c),& 'Add a sink particle stellar core',iunit) @@ -637,8 +623,6 @@ subroutine write_options_star(star,iunit,label) call write_inopt(in_solarr(star%hsoft),'hsoft'//trim(c),& 'Softening length of sink particle stellar core [Rsun]',iunit) endif - call write_inopt(in_solarl(star%lcore),'lcore'//trim(c),& - 'Luminosity of sink core particle [Lsun]',iunit) endif case (ievrard) call write_inopt(star%ui_coef,'ui_coef'//trim(c),& @@ -662,8 +646,8 @@ end subroutine write_options_star subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) use infile_utils, only:inopts,read_inopt use setstar_utils, only:need_inputprofile,need_rstar,nprofile_opts - use units, only:umass,udist,unit_luminosity - use physcon, only:solarm,solarr,solarl + use units, only:umass,udist + use physcon, only:solarm,solarr type(star_t), intent(out) :: star type(inopts), allocatable, intent(inout) :: db(:) integer, intent(out) :: need_iso @@ -672,7 +656,7 @@ subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) integer, intent(inout) :: nerr character(len=*), intent(in), optional :: label character(len=10) :: c - real :: mcore_msun,rcore_rsun,lcore_lsun,mstar_msun,rstar_rsun,hsoft_rsun + real :: mcore_msun,rcore_rsun,mstar_msun,rstar_rsun,hsoft_rsun ! set defaults call set_defaults_star(star) @@ -713,7 +697,7 @@ subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) else star%isinkcore = .true. call read_inopt(star%input_profile,'input_profile'//trim(c),db,errcount=nerr) - call read_inopt(star%outputfilename,'outputfilename'//trim(c),db,errcount=nerr) + call read_inopt(star%outputfilename,'outputfilename//trim(c)',db,errcount=nerr) if (star%isoftcore==1) call read_inopt(star%isofteningopt,'isofteningopt'//trim(c),& db,errcount=nerr,min=0) if ((star%isofteningopt==1) .or. (star%isofteningopt==3)) then @@ -725,8 +709,6 @@ subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) call read_inopt(mcore_msun,'mcore'//trim(c),db,errcount=nerr,min=0.) star%mcore = mcore_msun*real(solarm/umass) endif - call read_inopt(lcore_lsun,'lcore'//trim(c),db,errcount=nerr,min=0.) - star%lcore = lcore_lsun*real(solarl/unit_luminosity) endif case(ievrard) call read_inopt(star%ui_coef,'ui_coef'//trim(c),db,errcount=nerr,min=0.) diff --git a/src/setup/set_star_utils.f90 b/src/setup/set_star_utils.f90 index 5bcfbfef2..a07d903c0 100644 --- a/src/setup/set_star_utils.f90 +++ b/src/setup/set_star_utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setstar_utils ! @@ -310,13 +310,11 @@ end subroutine set_star_density ! Add a sink particle as a stellar core !+ !----------------------------------------------------------------------- -subroutine set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,ihsoft,mcore,& - hsoft,ilum,lcore,ierr) +subroutine set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,ihsoft,mcore,hsoft,ierr) integer, intent(out) :: nptmass,ierr real, intent(out) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) - real, intent(in) :: mcore,hsoft,lcore - integer, intent(in) :: ihsoft,ilum - integer :: n + real, intent(in) :: mcore,hsoft + integer :: n,ihsoft ierr = 0 ! Check for sensible values @@ -328,17 +326,12 @@ subroutine set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,ihsoft,mcore,& ierr = 2 return endif - if (lcore < 0.) then - ierr = 3 - return - endif nptmass = 1 n = nptmass xyzmh_ptmass(:,n) = 0. ! zero all quantities by default xyzmh_ptmass(4,n) = mcore xyzmh_ptmass(ihsoft,n) = hsoft - xyzmh_ptmass(ilum,n) = lcore vxyz_ptmass(:,n) = 0. end subroutine set_stellar_core diff --git a/src/setup/set_unifdis.f90 b/src/setup/set_unifdis.f90 index 64ccd8bc5..d327b6865 100644 --- a/src/setup/set_unifdis.f90 +++ b/src/setup/set_unifdis.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module unifdis ! diff --git a/src/setup/set_units.f90 b/src/setup/set_units.f90 index 6754f4884..e3a950bd6 100644 --- a/src/setup/set_units.f90 +++ b/src/setup/set_units.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setunits ! diff --git a/src/setup/set_vfield.f90 b/src/setup/set_vfield.f90 index 3b5bdf238..d0826809d 100644 --- a/src/setup/set_vfield.f90 +++ b/src/setup/set_vfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setvfield ! diff --git a/src/setup/setup_BHL.f90 b/src/setup/setup_BHL.f90 index 08a7497c2..ad8969346 100644 --- a/src/setup/setup_BHL.f90 +++ b/src/setup/setup_BHL.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_alfvenwave.f90 b/src/setup/setup_alfvenwave.f90 index 6564fad26..2c54c12c8 100644 --- a/src/setup/setup_alfvenwave.f90 +++ b/src/setup/setup_alfvenwave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_asteroidwind.f90 b/src/setup/setup_asteroidwind.f90 index 0b2215f9d..eddfaea3f 100644 --- a/src/setup/setup_asteroidwind.f90 +++ b/src/setup/setup_asteroidwind.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_binary.f90 b/src/setup/setup_binary.f90 index 533de808c..d089c8b18 100644 --- a/src/setup/setup_binary.f90 +++ b/src/setup/setup_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -13,14 +13,10 @@ module setup ! :Owner: Daniel Price ! ! :Runtime parameters: -! - O : *position angle of ascending node (deg)* -! - a : *semi-major axis (e.g. 1 au), period (e.g. 10*days) or rp if e=1* +! - a : *semi-major axis (e.g. 1 au) or period (e.g. 10*days)* ! - corotate : *set stars in corotation* ! - eccentricity : *eccentricity* -! - f : *initial true anomaly (180=apoastron)* -! - inc : *inclination (deg)* ! - relax : *relax stars into equilibrium* -! - w : *argument of periapsis (deg)* ! ! :Dependencies: centreofmass, dim, eos, externalforces, infile_utils, io, ! mpidomain, options, part, physcon, relaxstar, setbinary, setstar, @@ -31,7 +27,7 @@ module setup implicit none public :: setpart - real :: a,ecc,inc,O,w,f + real :: a,ecc logical :: relax,corotate type(star_t) :: star(2) character(len=20) :: semi_major_axis @@ -54,7 +50,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& use physcon, only:solarm,au,pi,solarr,days use options, only:iexternalforce use externalforces, only:iext_corotate,omega_corotate - use io, only:master,fatal + use io, only:master use setstar, only:set_star,set_defaults_star,shift_star use eos, only:X_in,Z_in,ieos use setup_params, only:rhozero,npart_total @@ -102,10 +98,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& semi_major_axis = '10.' a = 10. ecc = 0. - inc = 0. - O = 0. - w = 270. - f = 180. ieos = 2 if (id==master) print "(/,65('-'),1(/,a),/,65('-'),/)",& @@ -154,16 +146,13 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& nptmass_in = 0 if (iexternalforce==iext_corotate) then call set_binary(star(1)%mstar,star(2)%mstar,a,ecc,star(1)%hacc,star(2)%hacc,& - xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,ierr,omega_corotate,& - posang_ascnode=O,arg_peri=w,incl=inc,f=f,verbose=(id==master)) + xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,ierr,omega_corotate) add_spin = .false. ! already in corotating frame else call set_binary(star(1)%mstar,star(2)%mstar,a,ecc,star(1)%hacc,star(2)%hacc,& - xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,ierr,& - posang_ascnode=O,arg_peri=w,incl=inc,f=f,verbose=(id==master)) + xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,ierr) add_spin = corotate endif - if (ierr /= 0) call fatal ('setup_binary','error in call to set_binary') ! !--place stars into orbit, or add real sink particles if iprofile=0 ! @@ -197,10 +186,10 @@ subroutine write_setupfile(filename) use relaxstar, only:write_options_relax use setunits, only:write_options_units character(len=*), intent(in) :: filename - integer :: iunit + integer, parameter :: iunit = 20 print "(a)",' writing setup options file '//trim(filename) - open(newunit=iunit,file=filename,status='replace',form='formatted') + open(unit=iunit,file=filename,status='replace',form='formatted') write(iunit,"(a)") '# input file for binary setup routines' call write_options_units(iunit,gr) @@ -208,12 +197,8 @@ subroutine write_setupfile(filename) call write_options_star(star(2),iunit,label='2') write(iunit,"(/,a)") '# orbit settings' - call write_inopt(semi_major_axis,'a','semi-major axis (e.g. 1 au), period (e.g. 10*days) or rp if e=1',iunit) + call write_inopt(semi_major_axis,'a','semi-major axis (e.g. 1 au) or period (e.g. 10*days)',iunit) call write_inopt(ecc,'ecc','eccentricity',iunit) - call write_inopt(inc,'inc','inclination (deg)',iunit) - call write_inopt(O,'O','position angle of ascending node (deg)',iunit) - call write_inopt(w,'w','argument of periapsis (deg)',iunit) - call write_inopt(f,'f','initial true anomaly (180=apoastron)',iunit) call write_inopt(corotate,'corotate','set stars in corotation',iunit) if (any(star(:)%iprofile > 0)) then @@ -254,11 +239,6 @@ subroutine read_setupfile(filename,ieos,polyk,ierr) call read_inopt(semi_major_axis,'a',db,errcount=nerr) call read_inopt(ecc,'ecc',db,min=0.,errcount=nerr) - call read_inopt(inc,'inc',db,errcount=nerr) - call read_inopt(O,'O',db,errcount=nerr) - call read_inopt(w,'w',db,errcount=nerr) - call read_inopt(f,'f',db,errcount=nerr) - call read_inopt(corotate,'corotate',db,errcount=nerr) if (any(star(:)%iprofile > 0)) then diff --git a/src/setup/setup_blob.f90 b/src/setup/setup_blob.f90 index ec8ec343d..89c4b2a5a 100644 --- a/src/setup/setup_blob.f90 +++ b/src/setup/setup_blob.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_bondi.f90 b/src/setup/setup_bondi.F90 similarity index 99% rename from src/setup/setup_bondi.f90 rename to src/setup/setup_bondi.F90 index 0edc1ce43..78389239f 100644 --- a/src/setup/setup_bondi.f90 +++ b/src/setup/setup_bondi.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_bondiinject.f90 b/src/setup/setup_bondiinject.f90 index 057a0839e..a6b724ab0 100644 --- a/src/setup/setup_bondiinject.f90 +++ b/src/setup/setup_bondiinject.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_chinchen.f90 b/src/setup/setup_chinchen.f90 index ef0ecfa73..687284395 100644 --- a/src/setup/setup_chinchen.f90 +++ b/src/setup/setup_chinchen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_cluster.f90 b/src/setup/setup_cluster.f90 index 2a63e6ad5..9e3b4386a 100644 --- a/src/setup/setup_cluster.f90 +++ b/src/setup/setup_cluster.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_collidingclouds.f90 b/src/setup/setup_collidingclouds.f90 index 5ebfdaa10..34884af92 100644 --- a/src/setup/setup_collidingclouds.f90 +++ b/src/setup/setup_collidingclouds.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -50,6 +50,7 @@ module setup real :: cs_cloud(Ncloud_max) real :: rms_mach(Ncloud_max),density_contrast,T_bkg,plasmaB,Bzero,angB(3) real :: r_crit_setup,h_acc_setup,h_soft_sinksink_setup,rho_crit_cgs_setup + real(kind=8) :: udist,umass logical :: input_plasmaB character(len= 1), parameter :: labelx(4) = (/'x','y','z','r'/) @@ -69,7 +70,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound use boundary_dyn, only:width_bkg,rho_thresh_bdy,rho_bkg_ini,dxyz,vbdyx,vbdyy,vbdyz,in_domain,irho_bkg_ini use prompting, only:prompt - use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity,umass,udist + use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity use eos, only:polyk2,gmw use part, only:Bxyz,Bextx,Bexty,Bextz,igas,idust,set_particle_type,periodic use timestep, only:dtmax,tmax @@ -80,7 +81,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use mpidomain, only:i_belong use ptmass, only:icreate_sinks,r_crit,h_acc,h_soft_sinksink,rho_crit_cgs use cooling, only:Tfloor - use setunits, only:dist_unit,mass_unit,set_units_interactive + use setunits, only:dist_unit,mass_unit integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -108,7 +109,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, logical :: iexist,in_cloud,make_sinks logical :: moving_bkg = .true. ! For each component, will set the background velocity to that of the clouds, if the clouds are the same character(len=120) :: filex,filey,filez - character(len=100) :: filename + character(len=100) :: filename,cwd character(len= 40) :: fmt,lattice character(len= 10) :: h_acc_char ! @@ -128,12 +129,19 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, input_plasmaB = .false. make_sinks = .true. dynamic_bdy = .true. - dist_unit = 'pc' - mass_unit = 'solarm' - filex = find_phantom_datafile(filevx,'velfield') - filey = find_phantom_datafile(filevy,'velfield') - filez = find_phantom_datafile(filevz,'velfield') + call getcwd(cwd) + print*, index(cwd,'gpfs1/scratch/astro/jhw5') + if (index(cwd,'gpfs1/scratch/astro/jhw5') > 0 .or. index(cwd,'data/dp187/dc-wurs1') > 0 ) then + ! Kennedy or Dial + filex = find_phantom_datafile(filevx,'velfield_sphng') + filey = find_phantom_datafile(filevy,'velfield_sphng') + filez = find_phantom_datafile(filevz,'velfield_sphng') + else + filex = find_phantom_datafile(filevx,'velfield') + filey = find_phantom_datafile(filevy,'velfield') + filez = find_phantom_datafile(filevz,'velfield') + endif ! !--Read setup file, else prep prompt user for inputs ! @@ -148,19 +156,36 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, if (id==master) call write_setupfile(filename) stop endif + do i = 1,Ncloud + v2max = max(v2max,v_cloud(1,i)**2 + v_cloud(2,i)**2 +v_cloud(3,i)**2) + enddo elseif (id==master) then print "(a,/)",trim(filename)//' not found: using interactive setup' + dist_unit = 'pc' + mass_unit = 'solarm' + ierr = 1 + do while (ierr /= 0) + call prompt('Enter mass unit (e.g. solarm,jupiterm,earthm)',mass_unit) + call select_unit(mass_unit,umass,ierr) + if (ierr /= 0) print "(a)",' ERROR: mass unit not recognised' + enddo + ierr = 1 + do while (ierr /= 0) + call prompt('Enter distance unit (e.g. au,pc,kpc,0.1pc)',dist_unit) + call select_unit(dist_unit,udist,ierr) + if (ierr /= 0) print "(a)",' ERROR: length unit not recognised' + enddo ! ! units ! - call set_units_interactive() + call set_units(dist=udist,mass=umass,G=1.d0) ! ! prompt user for settings ! Ncloud = 2 npmax = int(2.0/3.0*size(xyzh(1,:)))/(2*Ncloud) ! approx max number allowed in sphere given size(xyzh(1,:)) np = npmax - np = 10000 + np = 30000 v_cloud = 0.0 ! velocity in km/s r_cloud(1,:) = 50.0 ! semi-major-axis (x) in pc r_cloud(2,:) = 12.5 ! semi-minor-axis (y) in pc @@ -318,9 +343,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ! !--general parameters of the cloud ! - do i = 1,Ncloud - v2max = max(v2max,v_cloud(1,i)**2 + v_cloud(2,i)**2 +v_cloud(3,i)**2) - enddo v_cloud = v_cloud/(unit_velocity*1.d-5) ! from km/s -> code units v2max = v2max /(unit_velocity*1.d-5)**2 ! from km/s -> code units vol_cloud = 4./3.*pi*r_cloud(1,:)*r_cloud(2,:)*r_cloud(3,:) diff --git a/src/setup/setup_common.f90 b/src/setup/setup_common.f90 index 706b18ef9..9eefb6f81 100644 --- a/src/setup/setup_common.f90 +++ b/src/setup/setup_common.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index c8263f479..c1c9f2a68 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -407,7 +407,7 @@ subroutine set_default_options()!id) !--gas disc R_in = 1. R_out = 150. - R_ref = 10. + R_ref = 1. R_c = 150. R_warp = 0. H_warp = 0. @@ -2150,7 +2150,7 @@ subroutine setup_interactive(id) !--gas disc R_in = accr1 - R_ref = min(10.*R_in,R_out) + R_ref = R_in R_c = R_out disc_mfac = 1. if (ndiscs > 1) qindex = 0. diff --git a/src/setup/setup_dustsettle.f90 b/src/setup/setup_dustsettle.f90 index 83c64886b..0263b5408 100644 --- a/src/setup/setup_dustsettle.f90 +++ b/src/setup/setup_dustsettle.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_dustybox.f90 b/src/setup/setup_dustybox.f90 index fd8b7f0fe..3ad1547f3 100644 --- a/src/setup/setup_dustybox.f90 +++ b/src/setup/setup_dustybox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_dustysedov.f90 b/src/setup/setup_dustysedov.f90 index bf6fe0c8d..784c84269 100644 --- a/src/setup/setup_dustysedov.f90 +++ b/src/setup/setup_dustysedov.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_empty.f90 b/src/setup/setup_empty.f90 index 16ab99ccf..255a69687 100644 --- a/src/setup/setup_empty.f90 +++ b/src/setup/setup_empty.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_firehose.f90 b/src/setup/setup_firehose.f90 index 03ee60f0f..6fbf9a61f 100644 --- a/src/setup/setup_firehose.f90 +++ b/src/setup/setup_firehose.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_galaxies.f90 b/src/setup/setup_galaxies.f90 index ecac91afb..b27838052 100644 --- a/src/setup/setup_galaxies.f90 +++ b/src/setup/setup_galaxies.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_galcen_stars.f90 b/src/setup/setup_galcen_stars.f90 index 0c3778c94..208147d63 100644 --- a/src/setup/setup_galcen_stars.f90 +++ b/src/setup/setup_galcen_stars.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_galdisc.f90 b/src/setup/setup_galdisc.f90 index b03fc2541..3e6de1214 100644 --- a/src/setup/setup_galdisc.f90 +++ b/src/setup/setup_galdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -14,7 +14,7 @@ module setup ! ! :Runtime parameters: None ! -! :Dependencies: datafiles, dim, extern_spiral, externalforces, io, kernel, +! :Dependencies: datafiles, dim, extern_spiral, externalforces, io, ! mpiutils, options, part, physcon, prompting, random, set_dust, ! setup_params, units ! @@ -62,7 +62,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use io, only:fatal use prompting, only:prompt use set_dust, only:set_dustfrac - use kernel, only:hfact_default integer, intent(in) :: id integer, intent(out) :: npart integer, intent(out) :: npartoftype(:) @@ -101,7 +100,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--initialising units and flags ! ! set code units - call set_units(dist=100.*pc,mass=1.d5*solarm,G=1.d0) + call set_units(dist=100.*pc,mass=1.d05*solarm,G=1.) ! !--set input file options !--maxvxyzu(3-4) and therefore ieos(1-2) are set in dim_galdisc @@ -109,7 +108,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, icooling = 0 !1=cooling on, 0=off nfulldump = 1 - hfact = hfact_default + hfact = 1.2 ! !-------------------------Setting-energies------------------------- @@ -404,7 +403,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, print "(a,i10)",' random seed = ',iseed print "(3(a,f10.3),a)",' galactic disc setup... rmin = ',rcylin,' rmax = ',rcyl,' in units of ',udist/kpc,' kpc' xi = ran2(iseed) - npart = min(maxp,500000) + npart = maxp call prompt('Enter number of particles ',npart,1,maxp) call bcast_mpi(npart) if (npart > maxp) call fatal('setup','npart > maxp; use ./phantomsetup --maxp=10000000') @@ -577,6 +576,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, enddo endif + return end subroutine setpart !/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ diff --git a/src/setup/setup_grdisc.F90 b/src/setup/setup_grdisc.F90 index 640f8cf9b..f9015d35b 100644 --- a/src/setup/setup_grdisc.F90 +++ b/src/setup/setup_grdisc.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_grtde.f90 b/src/setup/setup_grtde.f90 index bcaf0e30c..818f81f19 100644 --- a/src/setup/setup_grtde.f90 +++ b/src/setup/setup_grtde.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_gwdisc.f90 b/src/setup/setup_gwdisc.f90 index 701e3c456..ced4b97ab 100644 --- a/src/setup/setup_gwdisc.f90 +++ b/src/setup/setup_gwdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_hierarchical.f90 b/src/setup/setup_hierarchical.f90 index eda66d600..33ee98955 100644 --- a/src/setup/setup_hierarchical.f90 +++ b/src/setup/setup_hierarchical.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_jadvect.f90 b/src/setup/setup_jadvect.f90 index 2f9e1c06a..ccd05cffa 100644 --- a/src/setup/setup_jadvect.f90 +++ b/src/setup/setup_jadvect.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_kh.f90 b/src/setup/setup_kh.f90 index c83f7c0fa..66d0172d3 100644 --- a/src/setup/setup_kh.f90 +++ b/src/setup/setup_kh.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdblast.f90 b/src/setup/setup_mhdblast.f90 index 19ade125d..721e84ece 100644 --- a/src/setup/setup_mhdblast.f90 +++ b/src/setup/setup_mhdblast.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdrotor.f90 b/src/setup/setup_mhdrotor.f90 index 9a9c2a234..d33fb7148 100644 --- a/src/setup/setup_mhdrotor.f90 +++ b/src/setup/setup_mhdrotor.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdsine.f90 b/src/setup/setup_mhdsine.f90 index 371c5852d..1b82b39de 100644 --- a/src/setup/setup_mhdsine.f90 +++ b/src/setup/setup_mhdsine.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdvortex.f90 b/src/setup/setup_mhdvortex.f90 index b7138b364..4d7c8e994 100644 --- a/src/setup/setup_mhdvortex.f90 +++ b/src/setup/setup_mhdvortex.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdwave.f90 b/src/setup/setup_mhdwave.f90 index fe25a364a..495b8f668 100644 --- a/src/setup/setup_mhdwave.f90 +++ b/src/setup/setup_mhdwave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_nsdisc.f90 b/src/setup/setup_nsdisc.f90 index da14cf4c6..bda3ffeb3 100644 --- a/src/setup/setup_nsdisc.f90 +++ b/src/setup/setup_nsdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -52,7 +52,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, udist_km = 1.e5/udist ! code units are cm gamma = 1.0 - npart = 1e5 + npart = size(xyzh(1,:)) npartoftype(1) = npart hfact = 1.2 time = 0. diff --git a/src/setup/setup_orstang.f90 b/src/setup/setup_orstang.f90 index 137c9854d..30dfb4f14 100644 --- a/src/setup/setup_orstang.f90 +++ b/src/setup/setup_orstang.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_params.f90 b/src/setup/setup_params.f90 index f8c3301a5..3c541304b 100644 --- a/src/setup/setup_params.f90 +++ b/src/setup/setup_params.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup_params ! diff --git a/src/setup/setup_photoevap.f90 b/src/setup/setup_photoevap.f90 new file mode 100644 index 000000000..984f28f01 --- /dev/null +++ b/src/setup/setup_photoevap.f90 @@ -0,0 +1,97 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! +module setup +! +! this module sets up photoevaporation problem +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: externalforces, io, options, physcon, setdisc, units +! + implicit none + public :: setpart + + private + +contains + +!---------------------------------------------------------------- +! +! This subroutine is a utility for setting up discs +! +!---------------------------------------------------------------- +subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) + use units, only:umass,set_units + use setdisc, only:set_disc + use physcon, only:pi,au,solarm + use io, only:master + use externalforces, only:accradius1,iext_star + use options, only:iexternalforce + integer, intent(in) :: id + integer, intent(out) :: npart + integer, intent(out) :: npartoftype(:) + real, intent(out) :: xyzh(:,:) + real, intent(out) :: polyk,gamma,hfact + real, intent(out) :: vxyzu(:,:) + real, intent(out) :: massoftype(:) + real, intent(inout) :: time + character (len=20) , intent (in) :: fileprefix + real :: R_in,R_out + real :: xinc + real :: discmass + + ! + ! Set problem parameters + ! + + !--disc inner and outer radius + R_in = 2. + R_out = 10. + + npart = size(xyzh(1,:)) + + call set_units(dist=au,mass=solarm,G=1.) + + npartoftype(:) = 0 + npartoftype(1) = npart + gamma = 5./3. + time = 0. + xinc = 0.0*(pi/180.0) ! Must be in radians + discmass = 5.d22/umass + + call set_disc(id,master = master, & + npart = npartoftype(1), & + rmin = R_in, & + rmax = R_out, & + p_index = 1.5, & + q_index = 0.75, & + HoverR = 0.05, & + disc_mass = discmass, & + star_mass = 1.0, & + gamma = gamma, & + particle_mass = massoftype(1), & + hfact = hfact, & + xyzh = xyzh, & + vxyzu = vxyzu, & + polyk = polyk, & + inclination = xinc, & + prefix = fileprefix) + + ! + !--set default options for the input file + ! + iexternalforce = iext_star + accradius1 = R_in + + return +end subroutine setpart + +end module setup diff --git a/src/setup/setup_planetdisc.f90 b/src/setup/setup_planetdisc.f90 index 250b6288c..cf66192bb 100644 --- a/src/setup/setup_planetdisc.f90 +++ b/src/setup/setup_planetdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_prtest.f90 b/src/setup/setup_prtest.f90 index 08fd76dfc..7afd4233c 100644 --- a/src/setup/setup_prtest.f90 +++ b/src/setup/setup_prtest.f90 @@ -2,20 +2,20 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! -! test of Poynting-Robertson drag, as per Figure 18 of Price et al. (2018) +! this module does setup ! -! :References: Price et al. (2018), PASA 35, e031 +! :References: None ! ! :Owner: Daniel Price ! ! :Runtime parameters: None ! -! :Dependencies: externalforces, io, kernel, options, physcon, -! setup_params, spherical, units +! :Dependencies: externalforces, io, options, physcon, setup_params, +! spherical, units ! implicit none public :: setpart @@ -36,8 +36,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use externalforces,only:mass1,iext_prdrag use spherical, only:set_sphere use units, only:set_units - use physcon, only:km,pi - use kernel, only:hfact_default + use physcon, only:km + real, parameter :: pi = 3.1415926536 integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -48,22 +48,23 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, character(len=20), intent(in) :: fileprefix real, intent(out) :: vxyzu(:,:) real :: totmass,totvol,psep,rmax,rmin,xyz_orig(3) - real :: r,vphi,phi + real :: r, vphi, phi integer :: i,np,nx,maxvxyzu - call set_units(dist=10.*km,c=1.d0) + call set_units(dist=10.*km,c=1.) ! !--general parameters ! time = 0. - hfact = hfact_default + hfact = 1.2 gamma = 1. rmin = 0. rmax = 0.05 + ! !--setup particles ! - np = 100 + np = 100 !size(xyzh(1,:)) maxvxyzu = size(vxyzu(:,1)) totvol = 4./3.*pi*rmax**3 nx = int(np**(1./3.)) @@ -75,7 +76,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, npart = 0 npart_total = 0 - xyz_orig(:) = (/0.,200.,0./) + xyz_orig(:) = (/0.,100.,0./) call set_sphere('closepacked',id,master,rmin,rmax,psep,hfact,npart,xyzh, & nptot=npart_total,xyz_origin=xyz_orig) @@ -107,6 +108,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call warning('setup_prtest','maxvxyzu should not be 4, so set temp=0 for you') endif enddo + ! ! --- set input defaults for nonviscous particles in prdrag ! @@ -115,6 +117,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, alpha=0. beta=0. + end subroutine setpart end module setup + diff --git a/src/setup/setup_quebec.f90 b/src/setup/setup_quebec.f90 index 795f3813c..128b4c41c 100644 --- a/src/setup/setup_quebec.f90 +++ b/src/setup/setup_quebec.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_radiativebox.f90 b/src/setup/setup_radiativebox.f90 index 23fa719e8..0850a5624 100644 --- a/src/setup/setup_radiativebox.f90 +++ b/src/setup/setup_radiativebox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_sedov.f90 b/src/setup/setup_sedov.f90 index 5c2626949..cb28cbdb8 100644 --- a/src/setup/setup_sedov.f90 +++ b/src/setup/setup_sedov.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_shock.F90 b/src/setup/setup_shock.F90 index 943e3ef2c..84d0ccdb8 100644 --- a/src/setup/setup_shock.F90 +++ b/src/setup/setup_shock.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -40,12 +40,15 @@ module setup ! prompting, radiation_utils, set_dust, setshock, setup_params, timestep, ! unifdis, units ! - use dim, only:maxvxyzu,use_dust,do_radiation,mhd_nonideal + use dim, only:maxvxyzu,use_dust,do_radiation use options, only:use_dustfrac use timestep, only:dtmax,tmax use dust, only:K_code use eos, only:ieos,gmw +#ifdef NONIDEALMHD use nicil, only:use_ohm,use_hall,use_ambi,C_OR,C_HE,C_AD,rho_i_cnst +#endif + implicit none integer :: nx, icase, dust_method @@ -103,7 +106,9 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use eos_idealplusrad,only:get_idealgasplusrad_tempfrompres,get_idealplusrad_enfromtemp use eos, only:temperature_coef,init_eos use cooling, only:T0_value +#ifdef NONIDEALMHD use nicil, only:eta_constant,eta_const_type,icnstsemi +#endif integer, intent(in) :: id integer, intent(out) :: npartoftype(:) integer, intent(inout) :: npart @@ -121,9 +126,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, logical :: iexist,jexist,use_closepacked if (gr) call set_units(G=1.,c=1.,mass=10.*solarm) - if (do_radiation .or. icooling > 0 .or. mhd_nonideal) then - call set_units(dist=au,mass=solarm,G=1.d0) - endif + if (do_radiation .or. icooling > 0) call set_units(dist=au,mass=solarm,G=1.d0) ! ! quit if not periodic ! @@ -323,11 +326,11 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ! set remaining .in file properties ! if (.not. iexist) then - if (mhd_nonideal) then - eta_constant = .true. - eta_const_type = icnstsemi - rho_i_cnst = rho_i_cnst * rhozero ! Modify ion density from fraction to physical (for ambipolar diffusion) - endif +#ifdef NONIDEALMHD + eta_constant = .true. + eta_const_type = icnstsemi + rho_i_cnst = rho_i_cnst * rhozero ! Modify ion density from fraction to physical (for ambipolar diffusion) +#endif endif ! ! set cooling function information from initial conditions @@ -412,7 +415,9 @@ subroutine choose_shock (gamma,polyk,dtg,iexist) integer, parameter :: nshocks = 11 character(len=30) :: shocks(nshocks) integer :: i,choice +#ifdef NONIDEALMHD real :: gamma_AD +#endif real :: const,uu,dens,pres,Tgas integer :: relativistic_choice real :: uthermconst,densleft,densright,pondens,spsound,soundspeed @@ -422,11 +427,11 @@ subroutine choose_shock (gamma,polyk,dtg,iexist) if (.not. iexist) then tmax = 0.20 dtmax = 0.01 - if (mhd_nonideal) then - use_ohm = .false. - use_hall = .false. - use_ambi = .false. - endif +#ifdef NONIDEALMHD + use_ohm = .false. + use_hall = .false. + use_ambi = .false. +#endif endif nx = 256 xleft = -0.500 @@ -524,12 +529,12 @@ subroutine choose_shock (gamma,polyk,dtg,iexist) if (.not. iexist) then tmax = 4.0e6 dtmax = 1.0e4 - if (mhd_nonideal) then - use_ambi = .true. - gamma_AD = 1.0 - rho_i_cnst = 1.0d-5 - C_AD = 1.0/(gamma_AD*rho_i_cnst) - endif +#ifdef NONIDEALMHD + use_ambi = .true. + gamma_AD = 1.0 + rho_i_cnst = 1.0d-5 + C_AD = 1.0/(gamma_AD*rho_i_cnst) +#endif endif gamma = 1.0 polyk = 0.01 @@ -539,7 +544,8 @@ subroutine choose_shock (gamma,polyk,dtg,iexist) xleft = -4.00d6 case(8) !--Steady shock (Falle 2003) - if (mhd_nonideal .and. .not. iexist) then +#ifdef NONIDEALMHD + if (.not. iexist) then use_ohm = .true. use_hall = .true. use_ambi = .true. @@ -547,6 +553,7 @@ subroutine choose_shock (gamma,polyk,dtg,iexist) C_HE = -3.53d-2 C_AD = 7.83d-3 endif +#endif if (.not. iexist) then tmax = 1.0 endif @@ -635,6 +642,7 @@ subroutine choose_shock (gamma,polyk,dtg,iexist) call prompt('Enter kappa (total radiation opacity)',kappa,0.,1e6) endif + return end subroutine choose_shock !------------------------------------------ @@ -733,15 +741,15 @@ subroutine write_setupfile(filename,iprint,numstates,gamma,polyk,dtg) call write_inopt(ieos,'ieos','equation of state option',lu,ierr1) call write_inopt(gmw,'gmw','mean molecular weight',lu,ierr1) !if (do_radiation) call write_inopt(gmw,'gmw','mean molecular weight',lu,ierr1) - if (mhd_nonideal) then - call write_inopt(use_ohm,'use_ohm','include Ohmic resistivity',lu,ierr1) - call write_inopt(use_hall,'use_hall','include the Hall effect',lu,ierr1) - call write_inopt(use_ambi,'use_ambi','include ambipolar diffusion',lu,ierr1) - call write_inopt(rho_i_cnst,'rho_i_cnst','constant ion density',lu,ierr1) - call write_inopt(C_OR,'C_OR','Ohmic resistivity coefficient',lu,ierr1) - call write_inopt(C_HE,'C_HE','Hall effect coefficient',lu,ierr1) - call write_inopt(C_AD,'C_AD','Ambipolar diffusion coefficient',lu,ierr1) - endif +#ifdef NONIDEALMHD + call write_inopt(use_ohm,'use_ohm','include Ohmic resistivity',lu,ierr1) + call write_inopt(use_hall,'use_hall','include the Hall effect',lu,ierr1) + call write_inopt(use_ambi,'use_ambi','include ambipolar diffusion',lu,ierr1) + call write_inopt(rho_i_cnst,'rho_i_cnst','constant ion density',lu,ierr1) + call write_inopt(C_OR,'C_OR','Ohmic resistivity coefficient',lu,ierr1) + call write_inopt(C_HE,'C_HE','Hall effect coefficient',lu,ierr1) + call write_inopt(C_AD,'C_AD','Ambipolar diffusion coefficient',lu,ierr1) +#endif close(unit=lu) @@ -794,15 +802,15 @@ subroutine read_setupfile(filename,iprint,numstates,gamma,polyk,dtg,ierr) call read_inopt(ieos,'ieos',db,errcount=nerr) call read_inopt(gmw,'gmw',db,errcount=nerr) !if (do_radiation) call read_inopt(gmw,'gmw',db,errcount=nerr) - if (mhd_nonideal) then - call read_inopt(use_ohm,'use_ohm',db,errcount=nerr) - call read_inopt(use_hall,'use_hall',db,errcount=nerr) - call read_inopt(use_ambi,'use_ambi',db,errcount=nerr) - call read_inopt(rho_i_cnst,'rho_i_cnst',db,errcount=nerr) - call read_inopt(C_OR,'C_OR',db,errcount=nerr) - call read_inopt(C_HE,'C_HE',db,errcount=nerr) - call read_inopt(C_AD,'C_AD',db,errcount=nerr) - endif +#ifdef NONIDEALMHD + call read_inopt(use_ohm,'use_ohm',db,errcount=nerr) + call read_inopt(use_hall,'use_hall',db,errcount=nerr) + call read_inopt(use_ambi,'use_ambi',db,errcount=nerr) + call read_inopt(rho_i_cnst,'rho_i_cnst',db,errcount=nerr) + call read_inopt(C_OR,'C_OR',db,errcount=nerr) + call read_inopt(C_HE,'C_HE',db,errcount=nerr) + call read_inopt(C_AD,'C_AD',db,errcount=nerr) +#endif if (nerr > 0) then print "(1x,a,i2,a)",'Setup_shock: ',nerr,' error(s) during read of setup file' diff --git a/src/setup/setup_solarsystem.f90 b/src/setup/setup_solarsystem.f90 index 5ccca23ff..333519a44 100644 --- a/src/setup/setup_solarsystem.f90 +++ b/src/setup/setup_solarsystem.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_sphereinbox.f90 b/src/setup/setup_sphereinbox.f90 index 2b079ecba..d063ecbc6 100644 --- a/src/setup/setup_sphereinbox.f90 +++ b/src/setup/setup_sphereinbox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -658,7 +658,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ if (.not. iexist) then ! default values tmax = 1.21*t_ff ! = 10.75 for default settings (Wurster, Price & Bate 2016) - if (maxvxyzu < 4) ieos = 8 + ieos = 8 nfulldump = 1 calc_erot = .true. icreate_sinks = icreate_sinks_setup diff --git a/src/setup/setup_srblast.f90 b/src/setup/setup_srblast.f90 index 8e45ece8d..f2c51e692 100644 --- a/src/setup/setup_srblast.f90 +++ b/src/setup/setup_srblast.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_srpolytrope.f90 b/src/setup/setup_srpolytrope.f90 index 4fb8ac843..12c738f3d 100644 --- a/src/setup/setup_srpolytrope.f90 +++ b/src/setup/setup_srpolytrope.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_star.f90 b/src/setup/setup_star.f90 index 8107fceca..3eb33b4e5 100644 --- a/src/setup/setup_star.f90 +++ b/src/setup/setup_star.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_taylorgreen.f90 b/src/setup/setup_taylorgreen.f90 index 27a207eae..734395340 100644 --- a/src/setup/setup_taylorgreen.f90 +++ b/src/setup/setup_taylorgreen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_testparticles.F90 b/src/setup/setup_testparticles.F90 index 29fe851c0..c498e3407 100644 --- a/src/setup/setup_testparticles.F90 +++ b/src/setup/setup_testparticles.F90 @@ -2,11 +2,11 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! -! setup for test particles +! None ! ! :References: None ! @@ -41,8 +41,12 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use options, only:iexternalforce,alpha,alphamax,alphau,beta,nfulldump use units, only:set_units use physcon, only:solarm - use externalforces, only:iext_star +#ifdef GR + use externalforces, only:iext_gr use metric, only:a +#else + use externalforces, only:iext_star +#endif use eos, only:ieos use physcon, only:pi use prompting, only:prompt @@ -66,11 +70,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ! general parameters ! time = 0. - if (gr) then - gamma = 5./3. ! GR cannot have gamma=1 - else - gamma = 1. - endif + gamma = 1. polyk = 0. npart = 10 ieos = 11 @@ -192,8 +192,12 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, vxyzu(1:3,i) = rtan*vcirc enddo - a = spin - if (.not.gr) iexternalforce = iext_star +#ifdef GR + iexternalforce = iext_gr + a = spin +#else + iexternalforce = iext_star +#endif end subroutine setpart diff --git a/src/setup/setup_tokamak.f90 b/src/setup/setup_tokamak.f90 index 25a2c3af7..ce127623b 100644 --- a/src/setup/setup_tokamak.f90 +++ b/src/setup/setup_tokamak.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_torus.f90 b/src/setup/setup_torus.f90 index 0a7570b0b..ee410b98e 100644 --- a/src/setup/setup_torus.f90 +++ b/src/setup/setup_torus.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_turb.f90 b/src/setup/setup_turb.f90 index 5b0b4881e..bbc8626da 100644 --- a/src/setup/setup_turb.f90 +++ b/src/setup/setup_turb.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_unifdis.f90 b/src/setup/setup_unifdis.f90 index ae8e7b409..c93b9e641 100644 --- a/src/setup/setup_unifdis.f90 +++ b/src/setup/setup_unifdis.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -27,8 +27,8 @@ module setup ! - zmin : *zmin boundary* ! ! :Dependencies: boundary, cooling, cooling_ism, dim, eos, infile_utils, -! io, mpidomain, options, part, physcon, prompting, radiation_utils, -! set_dust, setunits, setup_params, timestep, unifdis, units +! io, mpidomain, options, part, physcon, prompting, set_dust, setunits, +! setup_params, timestep, unifdis, units ! use dim, only:use_dust,mhd,gr use options, only:use_dustfrac @@ -55,13 +55,12 @@ module setup !+ !---------------------------------------------------------------- subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) - use dim, only:maxvxyzu,h2chemistry,use_dustgrowth,do_radiation + use dim, only:maxvxyzu,h2chemistry use setup_params, only:npart_total,ihavesetupB use io, only:master use unifdis, only:set_unifdis,latticetype,get_xyzmin_xyzmax_exact use boundary, only:xmin,ymin,zmin,xmax,ymax,zmax,dxbound,dybound,dzbound,set_boundary - use part, only:Bxyz,periodic,abundance,igas,iHI,dustfrac,ndustsmall,& - ndusttypes,grainsize,graindens,dustprop,rad + use part, only:Bxyz,periodic,abundance,igas,iHI,dustfrac,ndustsmall,ndusttypes,grainsize,graindens use physcon, only:pi,mass_proton_cgs,kboltz,years,pc,solarm,micron use set_dust, only:set_dustfrac use setunits, only:dist_unit,mass_unit @@ -72,7 +71,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use timestep, only:dtmax,tmax,C_cour,C_force,C_cool,tolv use cooling, only:Tfloor use cooling_ism, only:abundc,abundo,abundsi,abunde,dust_to_gas_ratio,iphoto - use radiation_utils, only:set_radiation_and_gas_temperature_equal integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -228,13 +226,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, enddo endif - if (use_dustgrowth) then - do i=1,npart - dustprop(1,i) = grainsize(1) - dustprop(2,i) = graindens(1) - enddo - endif - if (h2chemistry) then do i=1,npart abundance(:,i) = 0. @@ -250,10 +241,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ihavesetupB = .true. endif - if (do_radiation) then - call set_radiation_and_gas_temperature_equal(npart,xyzh,vxyzu,massoftype,rad) - endif - end subroutine setpart !------------------------------------------------------------------------ @@ -305,9 +292,9 @@ subroutine setup_interactive() end subroutine setup_interactive !------------------------------------------------------------------------ -!+ -! write setup file -!+ +! +! write setup file +! !------------------------------------------------------------------------ subroutine write_setupfile(filename) use infile_utils, only:write_inopt @@ -349,9 +336,9 @@ subroutine write_setupfile(filename) end subroutine write_setupfile !------------------------------------------------------------------------ -!+ -! read setup file -!+ +! +! read setup file +! !------------------------------------------------------------------------ subroutine read_setupfile(filename,ierr) use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db diff --git a/src/setup/setup_wave.f90 b/src/setup/setup_wave.f90 index e60ff7b5c..ad86dcb0b 100644 --- a/src/setup/setup_wave.f90 +++ b/src/setup/setup_wave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -35,7 +35,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use unifdis, only:set_unifdis,rho_func use boundary, only:set_boundary,xmin,ymin,zmin,xmax,ymax,zmax,dxbound,dybound,dzbound use mpiutils, only:bcast_mpi - use part, only:labeltype,set_particle_type,igas,idust,dustfrac,periodic,ndustsmall,ndustlarge,ndusttypes + use part, only:labeltype,set_particle_type,igas,idust,dustfrac,periodic use physcon, only:pi use kernel, only:radkern use dim, only:maxvxyzu,use_dust,maxp @@ -73,8 +73,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, cs = 1. ampl = 1.d-4 use_dustfrac = .false. - ndustsmall = 0 - ndustlarge = 0 if (id==master) then itype = 1 print "(/,a,/)",' >>> Setting up particles for linear wave test <<<' @@ -94,16 +92,11 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call prompt('Enter constant drag coefficient',K_code(1),0.) if (use_dustfrac) then massfac = 1. + dtg - ndustsmall = 1 else ntypes = 2 - ndustlarge = 1 endif endif endif - call bcast_mpi(ndustsmall) - call bcast_mpi(ndustlarge) - ndusttypes = ndustsmall + ndustlarge call bcast_mpi(npartx) ! ! boundaries diff --git a/src/setup/setup_wavedamp.f90 b/src/setup/setup_wavedamp.f90 index d1ad6ee52..8464bb638 100644 --- a/src/setup/setup_wavedamp.f90 +++ b/src/setup/setup_wavedamp.f90 @@ -2,16 +2,14 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! ! This module initialises the wave damping test, as per ! Choi et al. 2009 (has been generalised for additional studies) ! -! :References: -! Wurster, Price & Ayliffe (2014), MNRAS 444, 1104 (Section 4.1) -! Wurster, Price & Bate (2016), MNRAS 457, 1037 +! :References: None ! ! :Owner: Daniel Price ! @@ -27,7 +25,7 @@ module setup ! - nx : *Particles in the x-direction* ! - ohmtest : *Testing Ohmic resistivity* ! - polyk : *Initial polyk* -! - realvals : *Using physical units (F: arbitrary units)* +! - realvals : *Using physical values (F: arbitrary values)* ! - rect : *Using rectangular cp grid (F: cubic cp grid)* ! - rhoin : *Initial density* ! - viscoff : *Using no viscosity (F: using viscosity* @@ -37,20 +35,21 @@ module setup ! nicil, options, part, physcon, prompting, setup_params, timestep, ! unifdis, units ! - use part, only:mhd - use nicil, only:use_ohm,use_hall,use_ambi - use nicil, only:eta_constant,eta_const_type,C_OR,C_HE,C_AD,icnstphys,icnstsemi,icnst - use nicil, only:n_e_cnst,rho_i_cnst,rho_n_cnst,gamma_AD,alpha_AD,hall_lt_zero + use part, only:mhd + use nicil, only:use_ohm,use_hall,use_ambi + use nicil, only:eta_constant,eta_const_type,C_OR,C_HE,C_AD,icnstphys,icnstsemi,icnst + use nicil, only:n_e_cnst,rho_i_cnst,rho_n_cnst,gamma_AD,alpha_AD,hall_lt_zero + ! implicit none integer, private :: nx real, private :: kwave,amplitude,polykin,rhoin0,Bxin0 logical, private :: realvals,geo_cp,rect logical, private :: isowave,kx_kxy,vx_vz,viscoff,ambitest,halltest,ohmtest - + ! public :: setpart - + ! private - + ! contains !---------------------------------------------------------------- !+ @@ -115,10 +114,9 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--Prompt the user for relevant input to create .setup if file does not already exist ! setupname=trim(fileprefix)//'.setup' - print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)", ' Wave damping test.' + print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)", ' Wave-damping test.' inquire(file=setupname,exist=jexist) if (jexist) call read_setupfile(setupname,ierr) - if ( (ierr /= 0 .or. .not.iexist .or. .not.jexist) .and. id==master) then ! Set defaults realvals = .false. @@ -362,12 +360,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, write(*,*) "setup: total volume = ",dxbound*dybound*dzbound end subroutine setpart - -!------------------------------------------------------------------------ -!+ -! write options to .setup file -!+ -!------------------------------------------------------------------------ +!----------------------------------------------------------------------- subroutine write_setupfile(filename) use infile_utils, only: write_inopt character(len=*), intent(in) :: filename @@ -375,15 +368,13 @@ subroutine write_setupfile(filename) print "(a)",' writing setup options file '//trim(filename) open(unit=iunit,file=filename,status='replace',form='formatted') - write(iunit,"(a)") '# input file for wave damping setup routines' - + write(iunit,"(a)") '# input file for wave-dampening setup routines' write(iunit,"(/,a)") '# units and orientation' - call write_inopt(realvals,'realvals','Using physical units (F: arbitrary units)',iunit) + call write_inopt(realvals,'realvals','Using physical values (F: arbitrary values)',iunit) if (mhd) call write_inopt(isowave,'isowave','Modelling a sound wave (F: Alfven wave)',iunit) call write_inopt(kx_kxy,'kx_kxy','Using wavenumber in x only (F: initialise in x,y)',iunit) call write_inopt(vx_vz,'vx_vz','Using velocity in x (F: initialise in z)',iunit) call write_inopt(viscoff,'viscoff','Using no viscosity (F: using viscosity',iunit) - write(iunit,"(/,a)") '# Grid setup' call write_inopt(geo_cp,'geo_cp','Using close-packed grid (F: cubic).',iunit) if (geo_cp) call write_inopt(rect,'rect','Using rectangular cp grid (F: cubic cp grid)',iunit) @@ -393,7 +384,6 @@ subroutine write_setupfile(filename) if (mhd .and. .not. isowave) call write_inopt(Bxin0,'Bxin','Initial x-magnetic field',iunit) call write_inopt(amplitude,'amplitude','Initial wave amplitude',iunit) call write_inopt(kwave,'kwave','Wavenumber (k/pi)',iunit) - write(iunit,"(/,a)") '# Test problem and values' if (mhd) then call write_inopt(ambitest,'ambitest','Testing ambipolar diffusion',iunit) @@ -403,12 +393,7 @@ subroutine write_setupfile(filename) close(iunit) end subroutine write_setupfile - -!------------------------------------------------------------------------ -!+ -! read options from .setup file -!+ -!------------------------------------------------------------------------ +!----------------------------------------------------------------------- subroutine read_setupfile(filename,ierr) use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db character(len=*), intent(in) :: filename @@ -439,6 +424,7 @@ subroutine read_setupfile(filename,ierr) call read_inopt(ohmtest, 'ohmtest', db,ierr) if (ohmtest) use_ohm = .true. endif + call close_db(db) end subroutine read_setupfile diff --git a/src/setup/setup_wddisc.f90 b/src/setup/setup_wddisc.f90 index 82d5a0cac..d6056ec6d 100644 --- a/src/setup/setup_wddisc.f90 +++ b/src/setup/setup_wddisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_wind.f90 b/src/setup/setup_wind.F90 similarity index 93% rename from src/setup/setup_wind.f90 rename to src/setup/setup_wind.F90 index 7c86957ce..d349f0794 100644 --- a/src/setup/setup_wind.f90 +++ b/src/setup/setup_wind.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -46,7 +46,7 @@ module setup ! - wind_gamma : *adiabatic index (initial if Krome chemistry used)* ! ! :Dependencies: dim, eos, infile_utils, inject, io, part, physcon, -! prompting, setbinary, sethierarchical, spherical, timestep, units +! prompting, setbinary, sethierarchical, spherical, units ! use dim, only:isothermal implicit none @@ -82,7 +82,7 @@ subroutine set_default_parameters_wind() wind_gamma = 5./3. if (isothermal) then - T_wind = 30000. + T_wind = 30000. temp_exponent = 0.5 ! primary_racc_au = 0.465 ! primary_mass_msun = 1.5 @@ -132,13 +132,12 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use part, only: xyzmh_ptmass, vxyz_ptmass, nptmass, igas, iTeff, iLum, iReff use physcon, only: au, solarm, mass_proton_cgs, kboltz, solarl use units, only: umass,set_units,unit_velocity,utime,unit_energ,udist - use inject, only: init_inject,set_default_options_inject + use inject, only: init_inject use setbinary, only: set_binary use sethierarchical, only: set_multiple use io, only: master use eos, only: gmw,ieos,isink,qfacdisc use spherical, only: set_sphere - use timestep, only: tmax,dtmax integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -154,7 +153,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call set_units(dist=au,mass=solarm,G=1.) call set_default_parameters_wind() - +! !--general parameters ! time = 0. @@ -168,7 +167,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, endif endif - call set_default_options_inject() ! !--space available for injected gas particles ! @@ -285,17 +283,10 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ieos = 1 endif else - T_wind = 0. gamma = wind_gamma endif polyk = kboltz*T_wind/(mass_proton_cgs * gmw * unit_velocity**2) - ! - ! avoid failures in the setup by ensuring that tmax and dtmax are large enough - ! - tmax = max(tmax,100.) - dtmax = max(tmax/10.,dtmax) - end subroutine setpart !---------------------------------------------------------------- @@ -321,7 +312,7 @@ subroutine setup_interactive() if (iwind == 3) T_wind = primary_Teff endif - icompanion_star = 0 + icompanion_star = 1 call prompt('Add binary?',icompanion_star,0,2) !Hierarchical triple system @@ -507,18 +498,11 @@ subroutine setup_interactive() print "(a)",'Stellar parameters' endif ichoice = 2 - print "(a)",' 3: Mass = 1.2 Msun, accretion radius = 1. au (trans-sonic)',& - ' 2: Mass = 1.2 Msun, accretion radius = 0.2568 au',& - ' 1: Mass = 1.0 Msun, accretion radius = 1.2568 au', & + print "(a)",' 2: Mass = 1.2 Msun, accretion radius = 0.2568 au',& + ' 1: Mass = 1.0 Msun, accretion radius = 1.2568 au', & ' 0: custom' - call prompt('select mass and radius of primary',ichoice,0,3) + call prompt('select mass and radius of primary',ichoice,0,2) select case(ichoice) - case(3) - primary_lum_lsun = 2.d4 - primary_Teff = 5.d4 - primary_mass_msun = 1.2 - primary_racc_au = 1. - wind_gamma = 1.4 case(2) primary_mass_msun = 1.2 primary_racc_au = 0.2568 @@ -572,31 +556,6 @@ subroutine setup_interactive() end subroutine setup_interactive -!---------------------------------------------------------------- -!+ -! get luminosity and effective radius in code units -! from various combinations of L, Teff and Reff in physical inuts -!+ -!---------------------------------------------------------------- -subroutine get_lum_and_Reff(lum_lsun,reff_au,Teff,lum,Reff) - use physcon, only:au,steboltz,solarl,pi - use units, only:udist,unit_luminosity - real, intent(inout) :: lum_lsun,reff_au,Teff - real, intent(out) :: lum,Reff - - if (Teff <= tiny(0.) .and. lum_lsun > 0. .and. Reff_au > 0.) then - primary_Teff = (lum_lsun*solarl/(4.*pi*steboltz*(Reff_au*au)**2))**0.25 - elseif (Reff_au <= 0. .and. lum_lsun > 0. .and. Teff > 0.) then - Reff_au = sqrt(lum_lsun*solarl/(4.*pi*steboltz*Teff**4))/au - elseif (Reff_au > 0. .and. lum_lsun <= 0. .and. Teff > 0.) then - lum_lsun = 4.*pi*steboltz*Teff**4*(primary_Reff_au*au)**2/solarl - endif - - lum = lum_lsun*(solarl/unit_luminosity) - Reff = Reff_au*(au/udist) - -end subroutine get_lum_and_Reff - !---------------------------------------------------------------- !+ ! write parameters to setup file @@ -604,18 +563,33 @@ end subroutine get_lum_and_Reff !---------------------------------------------------------------- subroutine write_setupfile(filename) use infile_utils, only:write_inopt + use physcon, only:au,steboltz,solarl,solarm,pi + use units, only:utime,unit_energ,udist character(len=*), intent(in) :: filename integer, parameter :: iunit = 20 print "(a)",' writing setup options file '//trim(filename) open(unit=iunit,file=filename,status='replace',form='formatted') write(iunit,"(a)") '# input file for wind setup routine' - - call get_lum_and_Reff(primary_lum_lsun,primary_Reff_au,primary_Teff,primary_lum,primary_Reff) + if (primary_Teff == 0. .and. primary_lum_lsun > 0. .and. primary_Reff_au > 0.) & + primary_Teff = (primary_lum_lsun*solarl/(4.*pi*steboltz*(primary_Reff_au*au)**2))**0.25 + if (primary_Reff_au == 0. .and. primary_lum_lsun > 0. .and. primary_Teff > 0.) & + primary_Reff_au = sqrt(primary_lum_lsun*solarl/(4.*pi*steboltz*primary_Teff**4))/au + if (primary_Reff_au > 0. .and. primary_lum_lsun == 0. .and. primary_Teff > 0.) & + primary_lum_lsun = 4.*pi*steboltz*primary_Teff**4*(primary_Reff_au*au)**2/solarl + primary_lum = primary_lum_lsun * (solarl * utime / unit_energ) + primary_Reff = primary_Reff_au*(au / udist) if (icompanion_star == 2) then - call get_lum_and_Reff(secondary_lum_lsun,secondary_Reff_au,secondary_Teff,secondary_lum,secondary_Reff) - + if (secondary_Teff == 0. .and. secondary_lum_lsun > 0. .and. secondary_Reff_au > 0.) & + secondary_Teff = (secondary_lum_lsun*solarl/(4.*pi*steboltz*(secondary_Reff_au*au)**2))**0.25 + if (secondary_Reff_au == 0. .and. secondary_lum_lsun > 0. .and. secondary_Teff > 0.) & + secondary_Reff_au = sqrt(secondary_lum_lsun*solarl/(4.*pi*steboltz*secondary_Teff**4))/au + if (secondary_Reff_au > 0. .and. secondary_lum_lsun == 0. .and. secondary_Teff > 0.) & + secondary_lum_lsun = 4.*pi*steboltz*secondary_Teff**4*(secondary_Reff_au*au)**2/solarl + + secondary_Reff = secondary_Reff_au*(au / udist) + secondary_lum = secondary_lum_lsun * (solarl * utime / unit_energ) call write_inopt(icompanion_star,'icompanion_star','set to 1 for a binary system, 2 for a triple system',iunit) !-- hierarchical triple write(iunit,"(/,a)") '# options for hierarchical triple' @@ -679,8 +653,13 @@ subroutine write_setupfile(filename) call write_inopt(primary_Reff_au,'primary_Reff','primary star effective radius (au)',iunit) call write_inopt(icompanion_star,'icompanion_star','set to 1 for a binary system, 2 for a triple system',iunit) if (icompanion_star == 1) then - call get_lum_and_Reff(secondary_lum_lsun,secondary_Reff_au,secondary_Teff,secondary_lum,secondary_Reff) - + if (secondary_Teff == 0. .and. secondary_lum_lsun > 0. .and. secondary_Reff_au > 0.) & + secondary_Teff = (secondary_lum_lsun*solarl/(4.*pi*steboltz*(secondary_Reff_au*au)**2))**0.25 + if (secondary_Reff_au == 0. .and. secondary_lum_lsun > 0. .and. secondary_Teff > 0.) & + secondary_Reff_au = sqrt(secondary_lum_lsun*solarl/(4.*pi*steboltz*secondary_Teff**4))/au + if (secondary_Reff_au > 0. .and. secondary_lum_lsun == 0. .and. secondary_Teff > 0.) & + secondary_lum_lsun = 4.*pi*steboltz*secondary_Teff**4*(secondary_Reff_au*au)**2/solarl + secondary_lum = secondary_lum_lsun * (solarl * utime / unit_energ) call write_inopt(secondary_mass_msun,'secondary_mass','secondary star mass (Msun)',iunit) call write_inopt(secondary_racc_au,'secondary_racc','secondary star accretion radius (au)',iunit) call write_inopt(secondary_lum_lsun,'secondary_lum','secondary star luminosity (Lsun)',iunit) diff --git a/src/setup/stretchmap.f90 b/src/setup/stretchmap.f90 index 94aac53c6..fb7c3b51f 100644 --- a/src/setup/stretchmap.f90 +++ b/src/setup/stretchmap.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module stretchmap ! diff --git a/src/setup/velfield_fromcubes.f90 b/src/setup/velfield_fromcubes.f90 index 8388cbb7a..cc7703044 100644 --- a/src/setup/velfield_fromcubes.f90 +++ b/src/setup/velfield_fromcubes.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module velfield ! diff --git a/src/tests/directsum.f90 b/src/tests/directsum.f90 index fe53e38fa..ef5e49130 100644 --- a/src/tests/directsum.f90 +++ b/src/tests/directsum.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module directsum ! diff --git a/src/tests/phantomtest.f90 b/src/tests/phantomtest.f90 index b1090e72c..1be31e58f 100644 --- a/src/tests/phantomtest.f90 +++ b/src/tests/phantomtest.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantomtest ! diff --git a/src/tests/test_cooling.f90 b/src/tests/test_cooling.f90 index 75733587f..8784a2fa7 100644 --- a/src/tests/test_cooling.f90 +++ b/src/tests/test_cooling.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testcooling ! diff --git a/src/tests/test_corotate.f90 b/src/tests/test_corotate.f90 index 9cdaedb2c..4b8c90562 100644 --- a/src/tests/test_corotate.f90 +++ b/src/tests/test_corotate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testcorotate ! diff --git a/src/tests/test_damping.f90 b/src/tests/test_damping.f90 index 358a0860c..252ec958b 100644 --- a/src/tests/test_damping.f90 +++ b/src/tests/test_damping.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testdamping ! diff --git a/src/tests/test_derivs.F90 b/src/tests/test_derivs.F90 index 22d97edb0..00cee763b 100644 --- a/src/tests/test_derivs.F90 +++ b/src/tests/test_derivs.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testderivs ! diff --git a/src/tests/test_dust.F90 b/src/tests/test_dust.F90 index 6b5da7c77..85eb088c7 100644 --- a/src/tests/test_dust.F90 +++ b/src/tests/test_dust.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testdust ! diff --git a/src/tests/test_eos.f90 b/src/tests/test_eos.f90 index 9152e1b2a..de34253a5 100644 --- a/src/tests/test_eos.f90 +++ b/src/tests/test_eos.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testeos ! diff --git a/src/tests/test_eos_stratified.f90 b/src/tests/test_eos_stratified.f90 index 065ffef27..5f56b6a13 100644 --- a/src/tests/test_eos_stratified.f90 +++ b/src/tests/test_eos_stratified.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testeos_stratified ! diff --git a/src/tests/test_externf.f90 b/src/tests/test_externf.f90 index f3777f756..d457c73f3 100644 --- a/src/tests/test_externf.f90 +++ b/src/tests/test_externf.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testexternf ! diff --git a/src/tests/test_externf_gr.f90 b/src/tests/test_externf_gr.f90 index 57f621b26..0d6f044b2 100644 --- a/src/tests/test_externf_gr.f90 +++ b/src/tests/test_externf_gr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testexternf ! diff --git a/src/tests/test_fastmath.f90 b/src/tests/test_fastmath.F90 similarity index 98% rename from src/tests/test_fastmath.f90 rename to src/tests/test_fastmath.F90 index b04bbd1b3..2214b92df 100644 --- a/src/tests/test_fastmath.f90 +++ b/src/tests/test_fastmath.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testmath ! diff --git a/src/tests/test_geometry.f90 b/src/tests/test_geometry.f90 index 2abfd79bc..06016eaf3 100644 --- a/src/tests/test_geometry.f90 +++ b/src/tests/test_geometry.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testgeometry ! diff --git a/src/tests/test_gnewton.f90 b/src/tests/test_gnewton.f90 index 3757597b4..9790e5b58 100644 --- a/src/tests/test_gnewton.f90 +++ b/src/tests/test_gnewton.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testgnewton ! diff --git a/src/tests/test_gr.f90 b/src/tests/test_gr.F90 similarity index 99% rename from src/tests/test_gr.f90 rename to src/tests/test_gr.F90 index 77e2de2d7..ea5398427 100644 --- a/src/tests/test_gr.f90 +++ b/src/tests/test_gr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testgr ! diff --git a/src/tests/test_gravity.f90 b/src/tests/test_gravity.F90 similarity index 99% rename from src/tests/test_gravity.f90 rename to src/tests/test_gravity.F90 index ec23df777..fea70f982 100644 --- a/src/tests/test_gravity.f90 +++ b/src/tests/test_gravity.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testgravity ! diff --git a/src/tests/test_growth.f90 b/src/tests/test_growth.F90 similarity index 91% rename from src/tests/test_growth.f90 rename to src/tests/test_growth.F90 index c30aa7442..439b7250a 100644 --- a/src/tests/test_growth.f90 +++ b/src/tests/test_growth.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testgrowth ! @@ -21,7 +21,11 @@ module testgrowth ! use testutils, only:checkval,update_test_scores use io, only:id,master +#ifdef DUST +#ifdef DUSTGROWTH use testdust, only:test_dustybox +#endif +#endif implicit none public :: test_growth @@ -34,22 +38,23 @@ module testgrowth !+ !----------------------------------------------------------------------- subroutine test_growth(ntests,npass) - use dim, only:use_dust,use_dustgrowth - use growth, only:init_growth,ifrag,isnow - use physcon, only:solarm,au - use units, only:set_units - use mpiutils, only:barrier_mpi +#ifdef DUST +#ifdef DUSTGROWTH + use growth, only:init_growth,ifrag,isnow + use physcon, only:solarm,au + use units, only:set_units + use mpiutils, only:barrier_mpi +#endif +#endif integer, intent(inout) :: ntests,npass + +#ifdef DUST +#ifdef DUSTGROWTH integer :: nfailed(5),ierr !don't forget the dimension of nfailed logical, dimension(2) :: logic = (/.false., .true./) integer :: i,j - if (use_dust .and. use_dustgrowth) then - if (id==master) write(*,"(/,a)") '--> TESTING DUSTGROWTH MODULE' - else - if (id==master) write(*,"(/,a)") '--> SKIPPING DUSTGROWTH TEST (REQUIRES -DDUST -DDUSTGROWTH)' - return - endif + if (id==master) write(*,"(/,a)") '--> TESTING DUSTGROWTH MODULE' call set_units(mass=solarm,dist=au,G=1.d0) @@ -81,9 +86,16 @@ subroutine test_growth(ntests,npass) enddo if (id==master) write(*,"(/,a)") '<-- DUSTGROWTH TEST COMPLETE' +#else + if (id==master) write(*,"(/,a)") '--> SKIPPING DUSTGROWTH TEST (REQUIRES -DDUST -DDUSTGROWTH)' +#endif +#endif end subroutine test_growth +#ifdef DUST +#ifdef DUSTGROWTH + !------------------- !------------------- !------------------- @@ -91,8 +103,7 @@ end subroutine test_growth subroutine test_farmingbox(ntests,npass,frag,onefluid) use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound use kernel, only:hfact_default - use part, only:init_part,igas,idust,npart,xyzh,vxyzu,npartoftype,& - massoftype,set_particle_type,& + use part, only:init_part,igas,idust,npart,xyzh,vxyzu,npartoftype,massoftype,set_particle_type,& fxyzu,fext,Bevol,dBevol,dustprop,ddustprop,& dustfrac,dustevol,ddustevol,iphase,maxtypes,& VrelVf,dustgasprop,Omega_k,alphaind,iamtype,& @@ -125,13 +136,12 @@ subroutine test_farmingbox(ntests,npass,frag,onefluid) integer :: ncheck(4),nerr(4) real :: errmax(4) integer :: ierr,iam - integer, parameter :: ngrid = 20000 logical :: do_output = .false. real :: deltax,dz,hfact,totmass,rhozero - real :: Stcomp(ngrid),Stini(ngrid) - real :: cscomp(ngrid),tau(ngrid) - real :: s(ngrid),time,timelim(ngrid) + real :: Stcomp(20000),Stini(20000) + real :: cscomp(20000),tau(20000) + real :: s(20000),time,timelim(20000) real :: sinit,dens,t,tmax,dt,dtext,dtnew,guillaume,dtgratio,rhog,rhod real, parameter :: tolst = 5.e-4 @@ -170,8 +180,9 @@ subroutine test_farmingbox(ntests,npass,frag,onefluid) endif dens = 1./unit_density - write(*,"(/,a)") '--> testing FARMINGBOX using: '//trim(stringfrag)//& - ' and '//trim(stringmethod)//' dust method' + write(*,*)'--> testing FARMINGBOX using: ',trim(stringfrag),' and ',trim(stringmethod), ' dust method' + write(*,*)'------------------------------------------------------------------------' + ! ! initialise ! @@ -180,7 +191,7 @@ subroutine test_farmingbox(ntests,npass,frag,onefluid) ! ! setup for dustybox problem ! - nx = 16 + nx = 32 deltax = 1./nx dz = 2.*sqrt(6.)/nx call set_boundary(-0.5,0.5,-0.25,0.25,-dz,dz) @@ -328,8 +339,7 @@ subroutine test_farmingbox(ntests,npass,frag,onefluid) call step(npart,npart,t,dt,dtext,dtnew) t = t + dt if (do_output .and. mod(i,modu)==0) then - call write_file_err(i,t,xyzh,dustprop(1,:)*udist,s*udist,& - dustgasprop(3,:),Stcomp,npart,"farmingbox_") + call write_file_err(i,t,xyzh,dustprop(1,:)*udist,s*udist,dustgasprop(3,:),Stcomp,npart,"farmingbox_") endif do j=1,npart iam = iamtype(iphase(j)) @@ -368,12 +378,11 @@ subroutine test_farmingbox(ntests,npass,frag,onefluid) end subroutine test_farmingbox -subroutine write_file_err(step,t,xyzh,gsize,gsize_exact,St,St_exact,npart,prefix) +subroutine write_file_err(step,t,xyzh,size,size_exact,St,St_exact,npart,prefix) use part, only:iamdust,iphase,iamgas real, intent(in) :: t real, intent(in) :: xyzh(:,:) - real, intent(in) :: St(:),St_exact(:) - real(kind=8), intent(in) :: gsize(:),gsize_exact(:) + real, intent(in) :: St(:),St_exact(:),size(:),size_exact(:) character(len=*), intent(in) :: prefix integer, intent(in) :: npart,step character(len=30) :: filename,str @@ -384,11 +393,14 @@ subroutine write_file_err(step,t,xyzh,gsize,gsize_exact,St,St_exact,npart,prefix open(newunit=lu,file=filename,status='replace') write(lu,*) t do i=1,npart - if (iamdust(iphase(i))) write(lu,*) xyzh(1,i),xyzh(2,i),xyzh(3,i),gsize(i),gsize_exact(i),& + if (iamdust(iphase(i))) write(lu,*) xyzh(1,i),xyzh(2,i),xyzh(3,i),size(i),size_exact(i),& St(i),St_exact(i) enddo close(lu) end subroutine write_file_err +#endif +#endif + end module testgrowth diff --git a/src/tests/test_hierarchical.f90 b/src/tests/test_hierarchical.f90 index a84b3d66b..0b303975c 100644 --- a/src/tests/test_hierarchical.f90 +++ b/src/tests/test_hierarchical.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testsethier ! diff --git a/src/tests/test_indtstep.F90 b/src/tests/test_indtstep.F90 index d136ec9f6..550d5273a 100644 --- a/src/tests/test_indtstep.F90 +++ b/src/tests/test_indtstep.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testindtstep ! diff --git a/src/tests/test_kdtree.F90 b/src/tests/test_kdtree.F90 index 4308c9867..55c569d49 100644 --- a/src/tests/test_kdtree.F90 +++ b/src/tests/test_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testkdtree ! diff --git a/src/tests/test_kernel.f90 b/src/tests/test_kernel.f90 index b89c628af..2e14ec3cd 100644 --- a/src/tests/test_kernel.f90 +++ b/src/tests/test_kernel.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testkernel ! diff --git a/src/tests/test_link.F90 b/src/tests/test_link.F90 index dc3b5566f..fb9a473a7 100644 --- a/src/tests/test_link.F90 +++ b/src/tests/test_link.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testlink ! diff --git a/src/tests/test_luminosity.F90 b/src/tests/test_luminosity.F90 index 04e14d591..576cfa708 100644 --- a/src/tests/test_luminosity.F90 +++ b/src/tests/test_luminosity.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testlum ! diff --git a/src/tests/test_mpi.f90 b/src/tests/test_mpi.F90 similarity index 98% rename from src/tests/test_mpi.f90 rename to src/tests/test_mpi.F90 index 307bd6851..03a30a907 100644 --- a/src/tests/test_mpi.f90 +++ b/src/tests/test_mpi.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testmpi ! diff --git a/src/tests/test_nonidealmhd.F90 b/src/tests/test_nonidealmhd.F90 index a69b01169..cfd2d6547 100644 --- a/src/tests/test_nonidealmhd.F90 +++ b/src/tests/test_nonidealmhd.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testnimhd ! diff --git a/src/tests/test_part.f90 b/src/tests/test_part.f90 index e0ccb61ed..206aaa173 100644 --- a/src/tests/test_part.f90 +++ b/src/tests/test_part.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testpart ! diff --git a/src/tests/test_poly.f90 b/src/tests/test_poly.f90 index 427d2b5ad..fe8490db9 100644 --- a/src/tests/test_poly.f90 +++ b/src/tests/test_poly.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testpoly ! diff --git a/src/tests/test_ptmass.f90 b/src/tests/test_ptmass.f90 index a2563889c..e4eac3af6 100644 --- a/src/tests/test_ptmass.f90 +++ b/src/tests/test_ptmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testptmass ! diff --git a/src/tests/test_radiation.f90 b/src/tests/test_radiation.f90 index dc7501c9f..585df2771 100644 --- a/src/tests/test_radiation.f90 +++ b/src/tests/test_radiation.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testradiation ! @@ -425,7 +425,6 @@ subroutine test_radiation_diffusion(ntests,npass) ! reset various things call init_part() limit_radiation_flux = .true. - drad = 0. end subroutine test_radiation_diffusion @@ -466,7 +465,7 @@ subroutine setup_radiation_diffusion_problem_sinusoid(kappa_code,c_code,xi0,rho0 rho0 = 2.5e-24 massoftype(igas) = rho0*dxbound*dybound*dzbound/nptot !*1e-25 pmassi = massoftype(igas) - if (maxphase==maxp) iphase(1:npart) = isetphase(igas,iactive=.true.) + if (maxphase==maxp) iphase(:) = isetphase(igas,iactive=.true.) npartoftype(:) = 0 npartoftype(igas) = npart nactive = npart diff --git a/src/tests/test_rwdump.F90 b/src/tests/test_rwdump.F90 index ba8d425b8..bdf54c8bf 100644 --- a/src/tests/test_rwdump.F90 +++ b/src/tests/test_rwdump.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testrwdump ! diff --git a/src/tests/test_sedov.F90 b/src/tests/test_sedov.F90 index 268ad74e3..c55ea24ee 100644 --- a/src/tests/test_sedov.F90 +++ b/src/tests/test_sedov.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testsedov ! @@ -171,7 +171,7 @@ subroutine test_sedov(ntests,npass) angtot_in = angtot totmom_in = totmom mdust_in = mdust - call evol('test.in',logfile,evfile,dumpfile,1) + call evol('test.in',logfile,evfile,dumpfile) call write_evfile(time,dt) etotend = etot momtotend = totmom diff --git a/src/tests/test_setdisc.f90 b/src/tests/test_setdisc.f90 index 39c910361..130bdaea3 100644 --- a/src/tests/test_setdisc.f90 +++ b/src/tests/test_setdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testsetdisc ! diff --git a/src/tests/test_smol.F90 b/src/tests/test_smol.F90 index 1f483dd93..dc0908e4c 100644 --- a/src/tests/test_smol.F90 +++ b/src/tests/test_smol.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testsmol ! diff --git a/src/tests/test_step.F90 b/src/tests/test_step.F90 index 2fd468fa7..375333319 100644 --- a/src/tests/test_step.F90 +++ b/src/tests/test_step.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module teststep ! diff --git a/src/tests/test_wind.f90 b/src/tests/test_wind.f90 deleted file mode 100644 index 164b79c77..000000000 --- a/src/tests/test_wind.f90 +++ /dev/null @@ -1,178 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module testwind -! -! Unit tests of the wind injection module -! -! :References: None -! -! :Owner: Lionel Siess -! -! :Runtime parameters: None -! -! :Dependencies: boundary, checksetup, dim, eos, inject, io, options, part, -! partinject, physcon, step_lf_global, testutils, timestep, timestep_ind, -! units, wind -! - implicit none - public :: test_wind - - private - -contains -!---------------------------------------------------------- -!+ -! Unit tests of timestepping and boundary crossing -!+ -!---------------------------------------------------------- -subroutine test_wind(ntests,npass) - use io, only:iprint,id,master,iverbose!,iwritein - use boundary, only:set_boundary - use options, only:ieos!,icooling - use physcon, only:au,solarm,solarl - use units, only:umass,set_units,utime,unit_energ,udist - use inject, only:init_inject,inject_particles,set_default_options_inject,inject_type - use eos, only:gmw,ieos,init_eos,gamma,polyk - use part, only:npart,init_part,nptmass,xyzmh_ptmass,vxyz_ptmass,xyzh,vxyzu,& - nptmass,npartoftype,igas,iTeff,iLum,iReff,massoftype,ntot - use timestep, only:time,tmax,dt,dtmax,nsteps,dtrad,dtforce,dtcourant,dterr,print_dtlog - use step_lf_global, only:step,init_step - use testutils, only:checkval,update_test_scores - use dim, only:isothermal,inject_parts,mpi - use partinject, only:update_injected_particles - use timestep_ind, only:nbinmax - use wind, only:trvurho_1D - use checksetup, only:check_setup - !use readwrite_infile, only:read_infile,write_infile - - integer, intent(inout) :: ntests,npass - - integer :: i,ierr,nerror,istepfrac,npart_old,nfailed(9),nwarn - real :: dtinject,dtlast,t,default_particle_mass,dtext,dtnew,dtprint,dtmaxold,tprint - - if (mpi) then - if (id==master) write(*,"(/,a,/)") '--> SKIPPING WIND TEST (currently not working with MPI)' - return - elseif (inject_type /= 'wind') then - if (id==master) write(*,"(/,a,/)") '--> SKIPPING WIND TEST (need to compile with wind injection module)' - return - else - if (id==master) write(*,"(/,a,/)") '--> TESTING WIND MODULE' - endif - - call set_units(dist=au,mass=solarm,G=1.d0) - call set_boundary(-50.,50.,-50.,50.,-50.,50.) - - call init_part() - - ! set properties of mass-losing sink particle - nptmass = 1 - xyzmh_ptmass(4,1) = 1.2*solarm/umass - xyzmh_ptmass(5,1) = au/udist - xyzmh_ptmass(iTeff,1) = 50000. - xyzmh_ptmass(iReff,1) = au/udist - xyzmh_ptmass(iLum,1) = 2e4 *solarl * utime / unit_energ - - ! - ! for binary wind simulations the particle mass is IRRELEVANT - ! since it will be over-written on the first call to init_inject - ! - default_particle_mass = 1.e-11 - massoftype(igas) = default_particle_mass * (solarm / umass) - - gmw = 2.381 - if (isothermal) then - gamma = 1. - ieos = 1 - else - gamma = 1.4 - ieos = 2 - endif - polyk = 0. - - call init_eos(ieos,ierr) - - iverbose = 0 - !icooling = 0 - dtmax = 1. - tmax = 8. - tprint = tmax - dt = 0. - dtinject = huge(dtinject) - dtrad = huge(dtrad) - t = 0. - dtnew = 0. - - ! trans-sonic wind - call set_default_options_inject(1) - call check_setup(nerror,nwarn) - - istepfrac = 0 - nfailed(:) = 0 - call init_inject(nerror) - - !debug if (id==master) call write_infile('w.in','w.log','w.ev','w_00000',iwritein,iprint) - - ! check particle's mass - call checkval(massoftype(igas),1.490822861042279E-09,epsilon(0.),& - nfailed(1),'no errors in setting particle mass') - npart_old = npart - call inject_particles(t,0.,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& - npart,npartoftype,dtinject) - call update_injected_particles(npart_old,npart,istepfrac,nbinmax,t,dtmax,dt,dtinject) - - ! check 1D wind profile - i = size(trvurho_1D(1,:)) - !print '((5(1x,es22.15)))',trvurho_1D(:,i),massoftype(igas) - call checkval(trvurho_1D(2,i),7.058624412798283E+13,epsilon(0.),nfailed(2),'outer wind radius') - call checkval(trvurho_1D(3,i),1.112160584479353E+06,epsilon(0.),nfailed(3),'outer wind velocity') - call checkval(trvurho_1D(4,i),2.031820842001706E+12,epsilon(0.),nfailed(4),'outer wind internal energy') - call checkval(trvurho_1D(5,i),8.878887149408118E-15,epsilon(0.),nfailed(5),'outer wind density') - - dt = dtinject - dtlast = 0. - time = 0. - - call init_step(npart_old,time,dtmax) - - do while (t < tmax) - - dtext = dt - ! - ! injection of new particles into simulation - ! - npart_old=npart - call inject_particles(t,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,npart,npartoftype,dtinject) - call update_injected_particles(npart_old,npart,istepfrac,nbinmax,t,dtmax,dt,dtinject) - dtmaxold = dtmax - nsteps = nsteps+1 - - call step(npart,npart,t,dt,dtext,dtnew) - - t = t + dt - time = t - - dtlast = dt - dtprint = min(tprint,tmax) - t + epsilon(dtmax) - if (dtprint <= epsilon(dtmax) .or. dtprint >= (1.0-1e-8)*dtmax ) dtprint = dtmax + epsilon(dtmax) - dt = min(dtforce,dtcourant,dterr,dtmax+epsilon(dtmax),dtprint,dtinject,dtrad) - if (id==master) call print_dtlog(iprint,time,dt,dtforce,dtcourant,dterr,dtmax,dtrad,dtprint,dtinject,ntot) - - enddo - - !print '((3(1x,es22.15),i8))',xyzmh_ptmass(4,1),xyzmh_ptmass(7,1),xyzmh_ptmass(15,1),npart - call checkval(xyzmh_ptmass(4,1),1.199987894518367E+00,epsilon(0.),nfailed(6),'sink particle mass') - call checkval(xyzmh_ptmass(7,1),0.,epsilon(0.),nfailed(7),'mass accreted') - call checkval(npart,12180,0,nfailed(8),'number of ejected particles') - call checkval(xyzmh_ptmass(15,1),1.591640703559762E-06,epsilon(0.),nfailed(9),'wind mass loss rate') - call update_test_scores(ntests,nfailed,npass) - - if (id==master) write(*,"(/,a)") '<-- WIND TEST COMPLETE' - -end subroutine test_wind - -end module testwind diff --git a/src/tests/testsuite.F90 b/src/tests/testsuite.F90 index 87841d2a7..0b665fc17 100644 --- a/src/tests/testsuite.F90 +++ b/src/tests/testsuite.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module test ! @@ -20,8 +20,7 @@ module test ! testgeometry, testgnewton, testgr, testgravity, testgrowth, ! testindtstep, testkdtree, testkernel, testlink, testmath, testmpi, ! testnimhd, testpart, testpoly, testptmass, testradiation, testrwdump, -! testsedov, testsetdisc, testsethier, testsmol, teststep, testwind, -! timing +! testsedov, testsetdisc, testsethier, testsmol, teststep, timing ! implicit none public :: testsuite @@ -63,7 +62,6 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) use testeos, only:test_eos use testcooling, only:test_cooling use testgeometry, only:test_geometry - use testwind, only:test_wind use testpoly, only:test_poly use testdamping, only:test_damping use testradiation,only:test_radiation @@ -79,7 +77,7 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) logical :: testall,dolink,dokdtree,doderivs,dokernel,dostep,dorwdump,dosmol logical :: doptmass,dognewton,dosedov,doexternf,doindtstep,dogravity,dogeom logical :: dosetdisc,doeos,docooling,dodust,donimhd,docorotate,doany,dogrowth - logical :: dogr,doradiation,dopart,dopoly,dompi,dohier,dodamp,dowind + logical :: dogr,doradiation,dopart,dopoly,dompi,dohier,dodamp #ifdef FINVSQRT logical :: usefsqrt,usefinvsqrt #endif @@ -131,7 +129,6 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) dompi = .false. dohier = .false. dodamp = .false. - dowind = .false. if (index(string,'deriv') /= 0) doderivs = .true. if (index(string,'grav') /= 0) dogravity = .true. @@ -152,11 +149,10 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) if (index(string,'mpi') /= 0) dompi = .true. if (index(string,'hier') /= 0) dohier = .true. if (index(string,'damp') /= 0) dodamp = .true. - if (index(string,'wind') /= 0) dowind = .true. doany = any((/doderivs,dogravity,dodust,dogrowth,donimhd,dorwdump,& doptmass,docooling,dogeom,dogr,dosmol,doradiation,& - dopart,dopoly,dohier,dodamp,dowind/)) + dopart,dopoly,dohier,dodamp/)) select case(trim(string)) case('kernel','kern') @@ -195,8 +191,6 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) dogrowth = .true. case('nimhd') donimhd = .true. - case('wind') - dowind = .true. case('mpi') dompi = .true. case default @@ -396,12 +390,6 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) call test_radiation(ntests,npass) call set_default_options_testsuite(iverbose) ! restore defaults endif -!--test of wind module -! - if (dowind.or.testall) then - call test_wind(ntests,npass) - call set_default_options_testsuite(iverbose) ! restore defaults - endif ! !--now do a "real" calculation, putting it all together (Sedov blast wave) ! diff --git a/src/tests/utils_testsuite.f90 b/src/tests/utils_testsuite.f90 index 189cb855f..12396e048 100644 --- a/src/tests/utils_testsuite.f90 +++ b/src/tests/utils_testsuite.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testutils ! diff --git a/src/utils/acc2ang.f90 b/src/utils/acc2ang.f90 index dc0b2048e..6954a24bf 100644 --- a/src/utils/acc2ang.f90 +++ b/src/utils/acc2ang.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program get_ang ! diff --git a/src/utils/adaptivemesh.f90 b/src/utils/adaptivemesh.f90 index c2b347fb8..584d039c7 100644 --- a/src/utils/adaptivemesh.f90 +++ b/src/utils/adaptivemesh.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module adaptivemesh ! diff --git a/src/utils/analysis_1particle.f90 b/src/utils/analysis_1particle.f90 index 6c9a48513..3e6115eb7 100644 --- a/src/utils/analysis_1particle.f90 +++ b/src/utils/analysis_1particle.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_BRhoOrientation.F90 b/src/utils/analysis_BRhoOrientation.F90 index 9abb5ca50..85de0a47c 100644 --- a/src/utils/analysis_BRhoOrientation.F90 +++ b/src/utils/analysis_BRhoOrientation.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_CoM.f90 b/src/utils/analysis_CoM.f90 index 890797894..299bec5e4 100644 --- a/src/utils/analysis_CoM.f90 +++ b/src/utils/analysis_CoM.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_GalMerger.f90 b/src/utils/analysis_GalMerger.f90 index 5239c1f23..bd0811e91 100644 --- a/src/utils/analysis_GalMerger.f90 +++ b/src/utils/analysis_GalMerger.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_MWpdf.f90 b/src/utils/analysis_MWpdf.f90 index eab4a122c..f852384f4 100644 --- a/src/utils/analysis_MWpdf.f90 +++ b/src/utils/analysis_MWpdf.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_NSmerger.f90 b/src/utils/analysis_NSmerger.f90 index 957f35983..fcf68b473 100644 --- a/src/utils/analysis_NSmerger.f90 +++ b/src/utils/analysis_NSmerger.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_alpha.f90 b/src/utils/analysis_alpha.f90 index e2036f989..0c97f93ac 100644 --- a/src/utils/analysis_alpha.f90 +++ b/src/utils/analysis_alpha.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_angmom.f90 b/src/utils/analysis_angmom.f90 index bdeecc687..c68f4aefc 100644 --- a/src/utils/analysis_angmom.f90 +++ b/src/utils/analysis_angmom.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_angmomvec.f90 b/src/utils/analysis_angmomvec.f90 index 2a0d76b7f..f743db53e 100644 --- a/src/utils/analysis_angmomvec.f90 +++ b/src/utils/analysis_angmomvec.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_average_orb_en.f90 b/src/utils/analysis_average_orb_en.f90 index 56a9ca69f..5d87bf4b5 100644 --- a/src/utils/analysis_average_orb_en.f90 +++ b/src/utils/analysis_average_orb_en.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_binarydisc.f90 b/src/utils/analysis_binarydisc.f90 index c4a66dc94..2b58788cb 100644 --- a/src/utils/analysis_binarydisc.f90 +++ b/src/utils/analysis_binarydisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! @@ -482,7 +482,7 @@ end subroutine read_dotin !----------------------------------------------------------------------- subroutine get_binary_params(ipri,isec,xyzmh_ptmass,vxyz_ptmass,time,a,ecc,G) !----------------------------------------------------------------------- - use io, only:fatal,warning + use io, only:fatal implicit none @@ -516,7 +516,7 @@ subroutine get_binary_params(ipri,isec,xyzmh_ptmass,vxyz_ptmass,time,a,ecc,G) Lmag = sqrt(dot_product(L,L)) E = 0.5*dot_product(dv,dv) - G*(mpri+msec)/rbin - if (abs(E) < tiny(E)) call warning(analysistype, 'E=0 for binary') + if (abs(E) < tiny(E)) stop 'binary energy problem' call get_ae(Lmag,E,mpri,msec,a,ecc) if (time <= tiny(time)) then @@ -548,6 +548,7 @@ subroutine get_ae(Lmag,E,m1,m2,a,ecc) real,intent(in) :: Lmag,E,m1,m2 if (Lmag < tiny(Lmag)) stop 'Lmag is zero in get_ae' + if (abs(E) < tiny(E)) stop 'E is zero in get_ae' ! Hence obtain the binary eccentricity ecc = sqrt(1.0 + (2.0*E*Lmag**2)/((m1+m2)**2)) diff --git a/src/utils/analysis_bzrms.f90 b/src/utils/analysis_bzrms.f90 index 81f38be88..5b568f2dc 100644 --- a/src/utils/analysis_bzrms.f90 +++ b/src/utils/analysis_bzrms.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_clumpfind.F90 b/src/utils/analysis_clumpfind.F90 index f75bea93b..3058b7d5f 100644 --- a/src/utils/analysis_clumpfind.F90 +++ b/src/utils/analysis_clumpfind.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_clumpfindWB23.F90 b/src/utils/analysis_clumpfindWB23.F90 index f6a5cd3d6..947b5d3c9 100644 --- a/src/utils/analysis_clumpfindWB23.F90 +++ b/src/utils/analysis_clumpfindWB23.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_collidingcloudevolution.f90 b/src/utils/analysis_collidingcloudevolution.f90 index 49db64b2e..9e51df350 100644 --- a/src/utils/analysis_collidingcloudevolution.f90 +++ b/src/utils/analysis_collidingcloudevolution.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_collidingcloudhistograms.f90 b/src/utils/analysis_collidingcloudhistograms.f90 index 4bf17b21d..bf6fb79b8 100644 --- a/src/utils/analysis_collidingcloudhistograms.f90 +++ b/src/utils/analysis_collidingcloudhistograms.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_common_envelope.f90 b/src/utils/analysis_common_envelope.F90 similarity index 95% rename from src/utils/analysis_common_envelope.f90 rename to src/utils/analysis_common_envelope.F90 index 3c70d694f..89f6fd72c 100644 --- a/src/utils/analysis_common_envelope.f90 +++ b/src/utils/analysis_common_envelope.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! @@ -83,7 +83,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) !chose analysis type if (dump_number==0) then - print "(41(a,/))", & + print "(40(a,/))", & ' 1) Sink separation', & ' 2) Bound and unbound quantities', & ' 3) Energies', & @@ -122,10 +122,9 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) '37) Planet profile',& '38) Velocity profile',& '39) Angular momentum profile',& - '40) Keplerian velocity profile',& - '41) Total dust mass' + '40) Keplerian velocity profile' analysis_to_perform = 1 - call prompt('Choose analysis type ',analysis_to_perform,1,41) + call prompt('Choose analysis type ',analysis_to_perform,1,40) endif call reset_centreofmass(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass) @@ -133,7 +132,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) xyzmh_ptmass,vxyz_ptmass,omega_corotate,dump_number) ! List of analysis options that require specifying EOS options - requires_eos_opts = any((/2,3,4,6,8,9,11,13,14,15,20,21,22,23,24,25,26,29,30,31,32,33,35,41/) == analysis_to_perform) + requires_eos_opts = any((/2,3,4,6,8,9,11,13,14,15,20,21,22,23,24,25,26,29,30,31,32,33,35/) == analysis_to_perform) if (dump_number == 0 .and. requires_eos_opts) call set_eos_options(analysis_to_perform) select case(analysis_to_perform) @@ -201,8 +200,6 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) call angular_momentum_profile(time,num,npart,particlemass,xyzh,vxyzu) case(40) ! Keplerian velocity profile call vkep_profile(time,num,npart,particlemass,xyzh,vxyzu) - case(41) !Total dust mass - call total_dust_mass(time,npart,particlemass,xyzh) case(12) !sink properties call sink_properties(time,npart,particlemass,xyzh,vxyzu) case(13) !MESA EoS compute total entropy and other average thermodynamical quantities @@ -305,97 +302,38 @@ end subroutine do_analysis subroutine total_dust_mass(time,npart,particlemass,xyzh) - use part, only:nucleation,idK3,idK0,idK1, idJstar + use part, only:nucleation,idK3 use dust_formation, only:set_abundances, mass_per_H use physcon, only:atomic_mass_unit real, intent(in) :: time,particlemass,xyzh(:,:) integer, intent(in) :: npart - integer :: i,ncols,j - real, dimension(2) :: dust_mass + integer :: i,ncols + real, dimension(1) :: dust_mass character(len=17), allocatable :: columns(:) - real, allocatable :: temp(:) !npart - real :: median,mass_factor,grain_size - real, parameter :: a0 = 1.28e-4 !radius of a carbon atom in micron - call set_abundances !initialize mass_per_H - dust_mass = 0. - ncols = 2 + call set_abundances !without the calling, the parameter mass_per_H is zero + dust_mass(1) = 0 + ncols = 1 print *,'size(nucleation,1) = ',size(nucleation,1) print *,'size(nucleation,2) = ',size(nucleation,2) - allocate(columns(ncols),temp(npart)) - columns = (/'Dust mass [Msun]', & - 'median size [um]'/) - j=0 - mass_factor = 12.*atomic_mass_unit*particlemass/mass_per_H + allocate(columns(ncols)) + columns = (/'total dust mass'/) do i = 1,npart if (.not. isdead_or_accreted(xyzh(4,i))) then - dust_mass(1) = dust_mass(1) + nucleation(idK3,i) *mass_factor - grain_size = a0*nucleation(idK1,i)/(nucleation(idK0,i)+1.0E-99) !in micron - if (grain_size > a0) then - j = j+1 - temp(j) = grain_size - endif + dust_mass(1) = dust_mass(1) + nucleation(idK3,i) & + * 12*atomic_mass_unit*particlemass*2.0E+33/mass_per_H + !the factor 2.0E+33 convert particlemass from solar units to cgs + !12*atomic_mass_unit is the mass of a Carbon atom endif enddo - call sort(temp,j) - if (mod(j,2)==0) then !npart - median = (temp(j/2)+temp(j/2+1))/2.0 !(temp(npart/2)+temp(npart/2+1))/2.0 - else - median = (temp(j/2)+temp(j/2+1))/2.0 !temp(npart/2+1) - endif - - dust_mass(2) = median - call write_time_file('total_dust_mass_vs_time', columns, time, dust_mass, ncols, dump_number) !after execution of the analysis routine, a file named "total_dust_mass_vs_time.ev" appears - deallocate(columns,temp) + deallocate(columns) end subroutine total_dust_mass -! -------------------------------------------------------------------- -! integer function FindMinimum(): -! This function returns the location of the minimum in the section -! between Start and End. -! -------------------------------------------------------------------- - -integer function FindMinimum(x, Start, Fin) - implicit none - integer, intent(in) :: start, fin - real, dimension(Fin), intent(in) :: x - real :: minimum - integer :: location - integer :: i - - minimum = x(start) ! assume the first is the min - location = start ! record its position - do i = start+1, fin ! start with next elements - if (x(i) < minimum) then ! if x(i) less than the min? - minimum = x(i) ! yes, a new minimum found - location = i ! record its position - endif - enddo - findminimum = location ! return the position -end function FindMinimum - -! -------------------------------------------------------------------- -! subroutine Sort(): -! This subroutine receives an array x() and sorts it into ascending -! order. -! -------------------------------------------------------------------- - -subroutine Sort(x, longitud) - implicit none - integer, intent(in) :: longitud - real, dimension(longitud), intent(inout) :: x - integer :: i - integer :: location - - do i = 1, longitud-1 ! except for the last - location = findminimum(x, i, longitud) ! find min from this to last - call swap(x(i), x(location)) ! swap this and the minimum - enddo -end subroutine Sort + !---------------------------------------------------------------- @@ -527,7 +465,7 @@ subroutine planet_rvm(time,particlemass,xyzh,vxyzu) mass(1), mass(2), mass(3), mass(4), mass(5), rhoprev, smin /) call write_time_file('planet_rvm', columns, time, data_cols, ncols, dump_number) - deallocate(data_cols,columns,mass,vthreshold) + deallocate(data_cols,columns,vthreshold,mass) end subroutine planet_rvm @@ -996,7 +934,8 @@ subroutine create_profile(time, num, npart, particlemass, xyzh, vxyzu) call write_file(name_in, 'profile', columns, profile, size(profile(1,:)), ncols, num) - deallocate(profile,columns) + deallocate(profile) + deallocate(columns) end subroutine create_profile @@ -1204,7 +1143,7 @@ subroutine roche_lobe_values(time,npart,particlemass,xyzh,vxyzu) ' Fallback Jz'/) call write_time_file('roche_lobes', columns, time, MRL, ncols, dump_number) - deallocate(columns,iorder) + deallocate(columns) end subroutine roche_lobe_values @@ -1327,7 +1266,7 @@ subroutine star_stabilisation_suite(time,npart,particlemass,xyzh,vxyzu) star_stability(imassfracout) = star_stability(imassout) / total_mass call write_time_file('star_stability', columns, time, star_stability, ncols, dump_number) - deallocate(columns,star_stability,iorder,iorder_a) + deallocate(columns) end subroutine star_stabilisation_suite @@ -1366,14 +1305,12 @@ end subroutine print_simulation_parameters !+ !---------------------------------------------------------------- subroutine output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp,nucleation,idK0,idK1,idK2,idK3,idJstar,idmu,idgamma + use part, only:eos_vars,itemp 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:calc_thermal_energy,ionisation_fraction - use dust_formation, only:psat_C,eps,set_abundances,mass_per_H, chemical_equilibrium_light, calc_nucleation!, Scrit - !use dim, only:nElements integer, intent(in) :: npart character(len=*), intent(in) :: dumpfile real, intent(in) :: time,particlemass @@ -1381,21 +1318,17 @@ subroutine output_divv_files(time,dumpfile,npart,particlemass,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,& + real :: ekini,einti,epoti,ethi,phii,rhopart,ponrhoi,spsoundi,tempi,& + omega_orb,kappai,kappat,kappar,pgas,mu,entropyi,& dum1,dum2,dum3,dum4,dum5 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, parameter :: Scrit = 2. ! Critical saturation ratio - logical :: verbose = .false. allocate(quant(4,npart)) - Nquantities = 13 + Nquantities = 12 if (dump_number == 0) then - print "(13(a,/))",& + print "(12(a,/))",& '1) Total energy (kin + pot + therm)', & '2) Mach number', & '3) Opacity from MESA tables', & @@ -1407,8 +1340,7 @@ subroutine output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) '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' !option to calculate JstarS + '12) Gas omega w.r.t. sink 1' quantities_to_calculate = (/1,2,4,5/) call prompt('Choose first quantity to compute ',quantities_to_calculate(1),1,Nquantities) @@ -1424,13 +1356,13 @@ subroutine output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) com_vxyz = 0. do k=1,4 select case (quantities_to_calculate(k)) - case(1,2,3,6,8,9,13) ! Nothing to do + case(1,2,3,6,8,9) ! 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)) + / (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)) + / (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) @@ -1446,61 +1378,16 @@ subroutine output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) 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 - !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)) - 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 - epsC = eps(3) - nucleation(idK3,i) - if (epsC < 0.) then - print *,'eps(C) =',eps(3),', K3=',nucleation(idK3,i),', epsC=',epsC,', T=',tempi,' rho=',rho_cgs - print *,'JKmuS=',nucleation(:,i) - stop '[S-dust_formation] epsC < 0!' - endif - if (tempi > 450.) then - !call chemical_equilibrium_light to obtain pC, and pC2H2 - call chemical_equilibrium_light(rho_cgs, tempi, epsC, pC, pC2, pC2H, pC2H2, nucleation(idmu,i), nucleation(idgamma,i)) - S = pC/psat_C(tempi) - if (S > Scrit) then - !call nucleation_function to obtain JstarS - call calc_nucleation(tempi, pC, 0., 0., 0., pC2H2, S, JstarS, taustar, taugr) - JstarS = JstarS/ nH_tot - endif - endif - !Check if the variables have meaningful values close to condensation temperatures - if (tempi >= 1400. .and. tempi <= 1500. .and. verbose ) then - print *,'size(nucleation,1) = ',size(nucleation,1) - print *,'size(nucleation,2) = ',size(nucleation,2) - print *,'nucleation(idK3,i) = ',nucleation(idK3,i) - 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(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)) @@ -1580,7 +1467,6 @@ subroutine output_divv_files(time,dumpfile,npart,particlemass,xyzh,vxyzu) write(iu) (quant(k,i),i=1,npart) enddo close(iu) - deallocate(quant) end subroutine output_divv_files @@ -1790,8 +1676,6 @@ subroutine tau_profile(time,num,npart,particlemass,xyzh) open(unit=unitnum, file=trim(adjustl(filename)), position='append') write(unitnum,data_formatter) time,tau_r close(unit=unitnum) - deallocate(rad_part,kappa_part,rho_part) - deallocate(rho_hist,kappa_hist,sepbins,tau_r) end subroutine tau_profile @@ -1953,7 +1837,6 @@ subroutine recombination_tau(time,npart,particlemass,xyzh,vxyzu) call write_time_file("recombination_tau",(/' tau'/),-1.,tau_recombined(i),1,i-1) ! Set num = i-1 so that header will be written for particle 1 and particle 1 only enddo endif - deallocate(recombined_pid,rad_part,kappa_part,rho_part) end subroutine recombination_tau @@ -2016,7 +1899,6 @@ subroutine energy_hist(time,npart,particlemass,xyzh,vxyzu) write(unitnum,data_formatter) time,hist close(unit=unitnum) enddo - deallocate(filename,coord,hist,Emin,Emax,quant) end subroutine energy_hist @@ -2179,8 +2061,6 @@ subroutine energy_profile(time,npart,particlemass,xyzh,vxyzu) write(unitnum,data_formatter) time,hist close(unit=unitnum) enddo - deallocate(iorder,coord,headerline,filename,quant,hist) - end subroutine energy_profile @@ -2256,7 +2136,6 @@ subroutine rotation_profile(time,num,npart,xyzh,vxyzu) write(unitnum,data_formatter) time,hist_var(:) close(unit=unitnum) enddo - deallocate(hist_var,grid_file,dist_part,rad_part) end subroutine rotation_profile @@ -2375,7 +2254,6 @@ subroutine velocity_profile(time,num,npart,particlemass,xyzh,vxyzu) open(newunit=iu, file=trim(adjustl(file_name)), position='append') write(iu,data_formatter) time,hist close(unit=iu) - deallocate(hist,dist_part,rad_part) end subroutine velocity_profile @@ -2485,7 +2363,6 @@ subroutine vkep_profile(time,num,npart,particlemass,xyzh,vxyzu) open(newunit=iu, file=trim(adjustl(file_name)), position='append') write(iu,data_formatter) time,hist close(unit=iu) - deallocate(hist,dist_part,rad_part) end subroutine vkep_profile @@ -2539,7 +2416,6 @@ subroutine planet_profile(num,dumpfile,particlemass,xyzh,vxyzu) enddo close(unit=iu) - deallocate(R,z,rho) end subroutine planet_profile @@ -2658,8 +2534,6 @@ subroutine unbound_profiles(time,num,npart,particlemass,xyzh,vxyzu) close(unit=unitnum) enddo - deallocate(hist_var) - end subroutine unbound_profiles @@ -3402,7 +3276,7 @@ subroutine gravitational_drag(time,npart,particlemass,xyzh,vxyzu) write (filename, "(A16,I0)") "sink_drag_", i call write_time_file(trim(adjustl(filename)), columns, time, drag_force(:,i), ncols, dump_number) enddo - deallocate(columns,drag_force,force_cut_vec,Rcut) + deallocate(columns) end subroutine gravitational_drag @@ -3440,7 +3314,7 @@ subroutine J_E_plane(num,npart,particlemass,xyzh,vxyzu) data(1,:) = data(1,:) / particlemass ! specific energy call write_file('JEplane','JEplane',columns,data,size(data(1,:)),ncols,num) - deallocate(columns,data) + deallocate(columns) end subroutine J_E_plane @@ -3458,7 +3332,7 @@ subroutine planet_destruction(time,npart,particlemass,xyzh,vxyzu) character(len=18) :: filename real, allocatable :: planetDestruction(:) integer :: ncols,i,j - real, save :: time_old + real, allocatable, save :: time_old real, allocatable, save :: particleRho(:) character(len=50) :: planetRadiusPromptString real, allocatable, save :: planetRadii(:) !In units of Rsun @@ -3470,7 +3344,8 @@ subroutine planet_destruction(time,npart,particlemass,xyzh,vxyzu) real, allocatable, save :: currentKhAblatedMass(:) ncols=5 - allocate(columns(ncols),planetDestruction(ncols)) + allocate(columns(ncols)) + allocate(planetDestruction(ncols)) columns=(/" rhoGas", & " kh_rhoCrit", & " kh_lmax", & @@ -3497,6 +3372,7 @@ subroutine planet_destruction(time,npart,particlemass,xyzh,vxyzu) call prompt(planetRadiusPromptString,planetRadii(i),0.0,1.0) enddo + allocate(time_old) allocate(particleRho(npart)) allocate(currentKhAblatedMass(nptmass)) @@ -3533,8 +3409,6 @@ subroutine planet_destruction(time,npart,particlemass,xyzh,vxyzu) enddo time_old=time - - deallocate(columns,planetDestruction) end subroutine planet_destruction !----------------------------------------------------------------------------------------- @@ -3587,9 +3461,8 @@ subroutine create_bindingEnergy_profile(time,num,npart,particlemass,xyzh,vxyzu) profile(3,i)=previousBindingEnergyU+currentParticleGPE-(vxyzu(4,j)*particlemass) enddo - call write_file('bEnergyProfile','bEnergyProfiles',columns,profile,npart,ncols,num) - deallocate(columns,iorder,profile) + call write_file('bEnergyProfile','bEnergyProfiles',columns,profile,npart,ncols,num) end subroutine create_bindingEnergy_profile @@ -4007,7 +3880,6 @@ subroutine stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,simp if (i > 1) profile(2,i) = profile(2,i-1) + particlemass enddo - deallocate(profile) print*, "Profile completed" end subroutine stellar_profile @@ -4051,7 +3923,6 @@ subroutine get_interior_mass(xyzh,vxyzu,donor_xyzm,companion_xyzm,particlemass,n interior_mass = npart_int * particlemass call get_centreofmass(com_xyz,com_vxyz,npart_int,xyz_int,vxyz_int,nptmass,xyzmh_ptmass,vxyz_ptmass) - deallocate(iorder) end subroutine get_interior_mass @@ -4103,7 +3974,6 @@ subroutine orbit_com(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,com_xyz,c enddo npart_a = k - 1 call get_centreofmass(com_xyz,com_vxyz,npart_a,xyz_a,vxyz_a,nptmass,xyzmh_ptmass,vxyz_ptmass) - deallocate(iorder,xyz_a,vxyz_a) end subroutine orbit_com @@ -4412,9 +4282,9 @@ function sphInterpolation(npart,particlemass,particleRho,particleXyzh,interpolat integer :: i,j integer, allocatable :: iorder(:) - real :: currentR,currentQ,currentQ2 - real :: nearestSphH - real :: currentParticleRho,currentSphSummandFactor + real :: currentR,currentQ,currentQ2 + real :: nearestSphH + real :: currentParticleRho,currentSphSummandFactor interpolatedData=0.0 allocate(iorder(npart)) @@ -4439,8 +4309,6 @@ function sphInterpolation(npart,particlemass,particleRho,particleXyzh,interpolat currentSphSummandFactor=(particlemass/currentParticleRho)*((1.0/((nearestSphH**3.0)*pi))*wkern(currentQ2,currentQ)) interpolatedData=interpolatedData+(currentSphSummandFactor*toInterpolate(:,j)) enddo - deallocate(iorder) - end function sphInterpolation !Sorting routines diff --git a/src/utils/analysis_cooling.f90 b/src/utils/analysis_cooling.f90 index f2c83cd2f..76f57db48 100644 --- a/src/utils/analysis_cooling.f90 +++ b/src/utils/analysis_cooling.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc.f90 b/src/utils/analysis_disc.f90 index e284dc8cf..3dfe270e8 100644 --- a/src/utils/analysis_disc.f90 +++ b/src/utils/analysis_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_MFlow.f90 b/src/utils/analysis_disc_MFlow.f90 index 341a1b4d1..099d5ba97 100644 --- a/src/utils/analysis_disc_MFlow.f90 +++ b/src/utils/analysis_disc_MFlow.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_eccentric.f90 b/src/utils/analysis_disc_eccentric.f90 index 6c242ed30..327310a10 100644 --- a/src/utils/analysis_disc_eccentric.f90 +++ b/src/utils/analysis_disc_eccentric.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_mag.f90 b/src/utils/analysis_disc_mag.f90 index 79e87352e..188033327 100644 --- a/src/utils/analysis_disc_mag.f90 +++ b/src/utils/analysis_disc_mag.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_planet.f90 b/src/utils/analysis_disc_planet.f90 index b582ac50b..16452b9f8 100644 --- a/src/utils/analysis_disc_planet.f90 +++ b/src/utils/analysis_disc_planet.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index e0acf7e43..ffb966aab 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_dtheader.f90 b/src/utils/analysis_dtheader.f90 index 3d2fe285a..bd2d8d9fd 100644 --- a/src/utils/analysis_dtheader.f90 +++ b/src/utils/analysis_dtheader.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_dustmass.f90 b/src/utils/analysis_dustmass.f90 index eedb3cbf9..a1ef10cd5 100644 --- a/src/utils/analysis_dustmass.f90 +++ b/src/utils/analysis_dustmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_dustydisc.f90 b/src/utils/analysis_dustydisc.f90 index e4fbf91b4..4022c9f30 100644 --- a/src/utils/analysis_dustydisc.f90 +++ b/src/utils/analysis_dustydisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_dustywind.f90 b/src/utils/analysis_dustywind.F90 similarity index 98% rename from src/utils/analysis_dustywind.f90 rename to src/utils/analysis_dustywind.F90 index 2b4b675e3..7f2ff8e50 100644 --- a/src/utils/analysis_dustywind.f90 +++ b/src/utils/analysis_dustywind.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! @@ -24,8 +24,8 @@ module analysis private integer, parameter :: N = 1024 !32 - real, parameter :: theta = 0., phi = 0. - real, parameter :: u(3) = (/ sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta) /) + double precision, parameter :: theta = 0., phi = 0. + double precision, parameter :: u(3) = (/ sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta) /) contains diff --git a/src/utils/analysis_etotgr.f90 b/src/utils/analysis_etotgr.f90 index f0c2f50a3..bcd93f6ff 100644 --- a/src/utils/analysis_etotgr.f90 +++ b/src/utils/analysis_etotgr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_getneighbours.f90 b/src/utils/analysis_getneighbours.f90 index b8a617ef5..c9ccc8898 100644 --- a/src/utils/analysis_getneighbours.f90 +++ b/src/utils/analysis_getneighbours.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_gws.f90 b/src/utils/analysis_gws.f90 index 0a4dc055d..a472ed830 100644 --- a/src/utils/analysis_gws.f90 +++ b/src/utils/analysis_gws.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_jet.f90 b/src/utils/analysis_jet.f90 index 6dd31f949..7fdc0ea23 100644 --- a/src/utils/analysis_jet.f90 +++ b/src/utils/analysis_jet.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_kdtree.F90 b/src/utils/analysis_kdtree.F90 index cdf614797..2d48b1047 100644 --- a/src/utils/analysis_kdtree.F90 +++ b/src/utils/analysis_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_kepler.f90 b/src/utils/analysis_kepler.f90 index 756a28bfa..b22b1e9b0 100644 --- a/src/utils/analysis_kepler.f90 +++ b/src/utils/analysis_kepler.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_macctrace.f90 b/src/utils/analysis_macctrace.f90 index 4c012b6e0..818a672be 100644 --- a/src/utils/analysis_macctrace.f90 +++ b/src/utils/analysis_macctrace.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_mapping_mass.f90 b/src/utils/analysis_mapping_mass.f90 index 0a440b13d..006bb5b01 100644 --- a/src/utils/analysis_mapping_mass.f90 +++ b/src/utils/analysis_mapping_mass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_mcfost.f90 b/src/utils/analysis_mcfost.f90 index 29b0e71f0..79f2f2a7e 100644 --- a/src/utils/analysis_mcfost.f90 +++ b/src/utils/analysis_mcfost.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_mcfostcmdline.f90 b/src/utils/analysis_mcfostcmdline.f90 index 495828ced..480319606 100644 --- a/src/utils/analysis_mcfostcmdline.f90 +++ b/src/utils/analysis_mcfostcmdline.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_pairing.f90 b/src/utils/analysis_pairing.f90 index a2d8a01b0..b53cf849e 100644 --- a/src/utils/analysis_pairing.f90 +++ b/src/utils/analysis_pairing.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_particle.f90 b/src/utils/analysis_particle.f90 index fa3a06feb..d83175ce2 100644 --- a/src/utils/analysis_particle.f90 +++ b/src/utils/analysis_particle.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_pdfs.f90 b/src/utils/analysis_pdfs.f90 index 3bc97092e..74e22a2c8 100644 --- a/src/utils/analysis_pdfs.f90 +++ b/src/utils/analysis_pdfs.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_phantom_dump.f90 b/src/utils/analysis_phantom_dump.f90 index ddc26a7a6..0b92ed414 100644 --- a/src/utils/analysis_phantom_dump.f90 +++ b/src/utils/analysis_phantom_dump.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_polytropes.f90 b/src/utils/analysis_polytropes.f90 index 9054cbb44..0dcb5c3c2 100644 --- a/src/utils/analysis_polytropes.f90 +++ b/src/utils/analysis_polytropes.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_prdrag.f90 b/src/utils/analysis_prdrag.f90 index 05e8d9fa0..ca5e2f5b0 100644 --- a/src/utils/analysis_prdrag.f90 +++ b/src/utils/analysis_prdrag.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_protostar_environ.F90 b/src/utils/analysis_protostar_environ.F90 index e23faa0dd..8025366ef 100644 --- a/src/utils/analysis_protostar_environ.F90 +++ b/src/utils/analysis_protostar_environ.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_ptmass.f90 b/src/utils/analysis_ptmass.f90 index 431ba7445..5fe14576a 100644 --- a/src/utils/analysis_ptmass.f90 +++ b/src/utils/analysis_ptmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_raytracer.f90 b/src/utils/analysis_raytracer.f90 index 81205233c..6ef3f236b 100644 --- a/src/utils/analysis_raytracer.f90 +++ b/src/utils/analysis_raytracer.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_sinkmass.f90 b/src/utils/analysis_sinkmass.f90 index 03e4a60cf..5d1021502 100644 --- a/src/utils/analysis_sinkmass.f90 +++ b/src/utils/analysis_sinkmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_sphere.f90 b/src/utils/analysis_sphere.f90 index 2ea8d5320..3233a3645 100644 --- a/src/utils/analysis_sphere.f90 +++ b/src/utils/analysis_sphere.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_structurefn.f90 b/src/utils/analysis_structurefn.f90 index 73a2d7ffe..025142b61 100644 --- a/src/utils/analysis_structurefn.f90 +++ b/src/utils/analysis_structurefn.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_tde.f90 b/src/utils/analysis_tde.f90 index 746661e92..3f2a45588 100644 --- a/src/utils/analysis_tde.f90 +++ b/src/utils/analysis_tde.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_torus.f90 b/src/utils/analysis_torus.f90 index 82e33695e..8982b739c 100644 --- a/src/utils/analysis_torus.f90 +++ b/src/utils/analysis_torus.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_trackbox.f90 b/src/utils/analysis_trackbox.f90 index ab3d23ba8..5cf2ad845 100644 --- a/src/utils/analysis_trackbox.f90 +++ b/src/utils/analysis_trackbox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_tracks.f90 b/src/utils/analysis_tracks.f90 index 5efa306a7..93bdaf19c 100644 --- a/src/utils/analysis_tracks.f90 +++ b/src/utils/analysis_tracks.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_velocitydispersion_vs_scale.f90 b/src/utils/analysis_velocitydispersion_vs_scale.f90 index 7c7ff311c..e2afdff7f 100644 --- a/src/utils/analysis_velocitydispersion_vs_scale.f90 +++ b/src/utils/analysis_velocitydispersion_vs_scale.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_velocityshear.f90 b/src/utils/analysis_velocityshear.f90 index 8fdd9059b..088f9b1b8 100644 --- a/src/utils/analysis_velocityshear.f90 +++ b/src/utils/analysis_velocityshear.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_write_kdtree.F90 b/src/utils/analysis_write_kdtree.F90 index f0f161286..86bf11c7a 100644 --- a/src/utils/analysis_write_kdtree.F90 +++ b/src/utils/analysis_write_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/combinedustdumps.f90 b/src/utils/combinedustdumps.f90 index f7b1c8d9a..0ffb046df 100644 --- a/src/utils/combinedustdumps.f90 +++ b/src/utils/combinedustdumps.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program combinedustdumps ! diff --git a/src/utils/cubicsolve.f90 b/src/utils/cubicsolve.f90 index feb34185f..e3be48d23 100644 --- a/src/utils/cubicsolve.f90 +++ b/src/utils/cubicsolve.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cubic ! diff --git a/src/utils/diffdumps.f90 b/src/utils/diffdumps.f90 index 43f984310..67455c2c5 100644 --- a/src/utils/diffdumps.f90 +++ b/src/utils/diffdumps.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program diffdumps ! diff --git a/src/utils/dustywaves.f90 b/src/utils/dustywaves.f90 index 77aa7b1c4..d224918c1 100644 --- a/src/utils/dustywaves.f90 +++ b/src/utils/dustywaves.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module dustywaves ! diff --git a/src/utils/ev2kdot.f90 b/src/utils/ev2kdot.f90 index 1b3231c77..3a08e2f6a 100644 --- a/src/utils/ev2kdot.f90 +++ b/src/utils/ev2kdot.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program get_kdot ! diff --git a/src/utils/ev2mdot.f90 b/src/utils/ev2mdot.f90 index 7376ef84d..6e608090f 100644 --- a/src/utils/ev2mdot.f90 +++ b/src/utils/ev2mdot.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program get_mdot ! diff --git a/src/utils/evol_dustywaves.f90 b/src/utils/evol_dustywaves.f90 index 324bb0199..b89dce091 100644 --- a/src/utils/evol_dustywaves.f90 +++ b/src/utils/evol_dustywaves.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program ekin ! diff --git a/src/utils/get_struct_slope.f90 b/src/utils/get_struct_slope.f90 index 8768ff985..8b7f25cf6 100644 --- a/src/utils/get_struct_slope.f90 +++ b/src/utils/get_struct_slope.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program get_struct_slope ! diff --git a/src/utils/getmathflags.f90 b/src/utils/getmathflags.f90 index 463208c2c..7c0933ffe 100644 --- a/src/utils/getmathflags.f90 +++ b/src/utils/getmathflags.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program getmathflags ! diff --git a/src/utils/grid2pdf.f90 b/src/utils/grid2pdf.f90 index 61da9786a..c218cc93e 100644 --- a/src/utils/grid2pdf.f90 +++ b/src/utils/grid2pdf.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program grid2pdf ! diff --git a/src/utils/hdf5utils.f90 b/src/utils/hdf5utils.f90 index e11c6a574..db5967bae 100644 --- a/src/utils/hdf5utils.f90 +++ b/src/utils/hdf5utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module hdf5utils ! diff --git a/src/utils/icosahedron.f90 b/src/utils/icosahedron.f90 index 08b27b32d..8e7af7f6a 100644 --- a/src/utils/icosahedron.f90 +++ b/src/utils/icosahedron.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module icosahedron ! diff --git a/src/utils/interpolate3D_amr.F90 b/src/utils/interpolate3D_amr.F90 index ec65a2395..c1b1fd229 100644 --- a/src/utils/interpolate3D_amr.F90 +++ b/src/utils/interpolate3D_amr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module interpolations3D_amr ! diff --git a/src/utils/io_grid.f90 b/src/utils/io_grid.f90 index 157e3d32c..19b318101 100644 --- a/src/utils/io_grid.f90 +++ b/src/utils/io_grid.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module io_grid ! diff --git a/src/utils/io_structurefn.f90 b/src/utils/io_structurefn.f90 index c4f58d898..ea875825a 100644 --- a/src/utils/io_structurefn.f90 +++ b/src/utils/io_structurefn.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module io_structurefn ! diff --git a/src/utils/leastsquares.f90 b/src/utils/leastsquares.f90 index 4f7228b94..9de22876c 100644 --- a/src/utils/leastsquares.f90 +++ b/src/utils/leastsquares.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module leastsquares ! diff --git a/src/utils/libphantom-splash.f90 b/src/utils/libphantom-splash.f90 index 3a470b943..ab7b57d47 100644 --- a/src/utils/libphantom-splash.f90 +++ b/src/utils/libphantom-splash.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module libphantomsplash ! diff --git a/src/utils/lombperiod.f90 b/src/utils/lombperiod.f90 index f51c4108a..801424ecc 100644 --- a/src/utils/lombperiod.f90 +++ b/src/utils/lombperiod.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program lombperiod ! diff --git a/src/utils/mflow.f90 b/src/utils/mflow.f90 index 830f82c9d..18fbfcbd3 100644 --- a/src/utils/mflow.f90 +++ b/src/utils/mflow.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program mflow ! diff --git a/src/utils/moddump_CoM.f90 b/src/utils/moddump_CoM.f90 index 0b2840d85..08a001dbf 100644 --- a/src/utils/moddump_CoM.f90 +++ b/src/utils/moddump_CoM.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_addflyby.f90 b/src/utils/moddump_addflyby.f90 index f131ada10..431c220a7 100644 --- a/src/utils/moddump_addflyby.f90 +++ b/src/utils/moddump_addflyby.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_addplanets.f90 b/src/utils/moddump_addplanets.f90 index 17b34a18f..1b7d9b60d 100644 --- a/src/utils/moddump_addplanets.f90 +++ b/src/utils/moddump_addplanets.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_binary.f90 b/src/utils/moddump_binary.f90 index f7b376871..76396c9d1 100644 --- a/src/utils/moddump_binary.f90 +++ b/src/utils/moddump_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_binarystar.f90 b/src/utils/moddump_binarystar.f90 index 4d7d9e49b..b8cfca8f8 100644 --- a/src/utils/moddump_binarystar.f90 +++ b/src/utils/moddump_binarystar.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_changemass.f90 b/src/utils/moddump_changemass.f90 index 0c2fc022e..86d45d298 100644 --- a/src/utils/moddump_changemass.f90 +++ b/src/utils/moddump_changemass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_default.f90 b/src/utils/moddump_default.f90 index 44ea7de38..68e9a207d 100644 --- a/src/utils/moddump_default.f90 +++ b/src/utils/moddump_default.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_disc.f90 b/src/utils/moddump_disc.f90 index df393c926..7ff0e65cc 100644 --- a/src/utils/moddump_disc.f90 +++ b/src/utils/moddump_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_dustadd.f90 b/src/utils/moddump_dustadd.f90 index f145b5e68..712e8071f 100644 --- a/src/utils/moddump_dustadd.f90 +++ b/src/utils/moddump_dustadd.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_extenddisc.f90 b/src/utils/moddump_extenddisc.f90 index 73759d3ef..25b5e685e 100644 --- a/src/utils/moddump_extenddisc.f90 +++ b/src/utils/moddump_extenddisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_growthtomultigrain.f90 b/src/utils/moddump_growthtomultigrain.f90 index 0eb70bbda..3f1390c26 100644 --- a/src/utils/moddump_growthtomultigrain.f90 +++ b/src/utils/moddump_growthtomultigrain.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_mergepart.f90 b/src/utils/moddump_mergepart.f90 index 0a3513e63..bf2e2fc12 100644 --- a/src/utils/moddump_mergepart.f90 +++ b/src/utils/moddump_mergepart.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_messupSPH.f90 b/src/utils/moddump_messupSPH.f90 index f89ebb1e2..16b512c77 100644 --- a/src/utils/moddump_messupSPH.f90 +++ b/src/utils/moddump_messupSPH.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_perturbgas.f90 b/src/utils/moddump_perturbgas.f90 index dd5ab7326..8d23233d2 100644 --- a/src/utils/moddump_perturbgas.f90 +++ b/src/utils/moddump_perturbgas.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_polytrope.f90 b/src/utils/moddump_polytrope.f90 index 7a7195788..147f1fd62 100644 --- a/src/utils/moddump_polytrope.f90 +++ b/src/utils/moddump_polytrope.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_rad_to_LTE.f90 b/src/utils/moddump_rad_to_LTE.f90 index 1c93efd4d..c3c309830 100644 --- a/src/utils/moddump_rad_to_LTE.f90 +++ b/src/utils/moddump_rad_to_LTE.f90 @@ -2,11 +2,11 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! -! Convert radiation dump to LTE dump (ieos=12) +! moddump ! ! :References: None ! diff --git a/src/utils/moddump_recalcuT.f90 b/src/utils/moddump_recalcuT.f90 index fe673eb37..e33629c0a 100644 --- a/src/utils/moddump_recalcuT.f90 +++ b/src/utils/moddump_recalcuT.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_removeparticles_cylinder.f90 b/src/utils/moddump_removeparticles_cylinder.f90 index 6f2de9da1..7e53a63db 100644 --- a/src/utils/moddump_removeparticles_cylinder.f90 +++ b/src/utils/moddump_removeparticles_cylinder.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_removeparticles_radius.f90 b/src/utils/moddump_removeparticles_radius.f90 index dd9ada106..040634afa 100644 --- a/src/utils/moddump_removeparticles_radius.f90 +++ b/src/utils/moddump_removeparticles_radius.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_rotate.f90 b/src/utils/moddump_rotate.f90 index 25689954c..a19351ed7 100644 --- a/src/utils/moddump_rotate.f90 +++ b/src/utils/moddump_rotate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sink.f90 b/src/utils/moddump_sink.f90 index faceeda4d..880f51081 100644 --- a/src/utils/moddump_sink.f90 +++ b/src/utils/moddump_sink.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! @@ -77,7 +77,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) xyzmh_ptmass(1,isinkpart) = newx print*,'x-coordinate changed to ',xyzmh_ptmass(1,isinkpart) - Lnuc = xyzmh_ptmass(ilum,isinkpart) + Lnuc = xyzmh_ptmass(1,ilum) Lnuc_cgs = Lnuc * unit_energ / utime call prompt('Enter new sink heating luminosity in erg/s:',Lnuc_cgs,0.) xyzmh_ptmass(ilum,isinkpart) = Lnuc_cgs / unit_energ * utime diff --git a/src/utils/moddump_sinkbinary.f90 b/src/utils/moddump_sinkbinary.f90 index 52283052a..6e55a8177 100644 --- a/src/utils/moddump_sinkbinary.f90 +++ b/src/utils/moddump_sinkbinary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sphNG2phantom.f90 b/src/utils/moddump_sphNG2phantom.f90 index c344d0840..9d53bfe82 100644 --- a/src/utils/moddump_sphNG2phantom.f90 +++ b/src/utils/moddump_sphNG2phantom.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sphNG2phantom_addBfield.f90 b/src/utils/moddump_sphNG2phantom_addBfield.f90 index bb34829d8..23acdfa5c 100644 --- a/src/utils/moddump_sphNG2phantom_addBfield.f90 +++ b/src/utils/moddump_sphNG2phantom_addBfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sphNG2phantom_disc.f90 b/src/utils/moddump_sphNG2phantom_disc.f90 index 8aaff0730..318bac487 100644 --- a/src/utils/moddump_sphNG2phantom_disc.f90 +++ b/src/utils/moddump_sphNG2phantom_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! @@ -32,7 +32,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) use prompting, only:prompt use physcon, only:au,gg use readwrite_dumps_fortran, only:dt_read_in_fortran - use timestep, only:time,dt,dtmax_max,dtmax_min + use timestep, only:time,dt,dtmax_max,dtmax_min,dtmax0 use centreofmass, only: reset_centreofmass integer, intent(inout) :: npart integer, intent(inout) :: npartoftype(:) @@ -97,7 +97,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) enddo close(iunit) - print *, 'dtmax_max,dtmax_min',dtmax_max,dtmax_min + print *, 'dtmax0, dtmax_max,dtmax_min',dtmax0,dtmax_max,dtmax_min newutime = sqrt(au**3/(gg*umass)) print *, "newutime/old", newutime/utime time = time * utime / newutime @@ -171,13 +171,13 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) endif enddo - print *,'Found GAS:', gascount, 'sinks:', sinkcount+nptmass, & + print *,'Found GAS:', gascount, 'sinks:', sinkcount, & 'Other:', othercount, 'Total=', gascount+sinkcount+othercount print *, 'maxtypes:', maxtypes, 'npartoftype:', npartoftype,& 'nptmass:', nptmass print *, 'gamma=', gamma print *, 'Timestep info:' - print *, 'dtmax_max,dtmax_min',dtmax_max,dtmax_min + print *, 'dtmax0, dtmax_max,dtmax_min', dtmax0,dtmax_max,dtmax_min print *, 'utime=', utime return diff --git a/src/utils/moddump_splitpart.f90 b/src/utils/moddump_splitpart.f90 index c55368973..bc47ec60a 100644 --- a/src/utils/moddump_splitpart.f90 +++ b/src/utils/moddump_splitpart.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_taylorgreen.f90 b/src/utils/moddump_taylorgreen.f90 index fd1613dcd..282d53f78 100644 --- a/src/utils/moddump_taylorgreen.f90 +++ b/src/utils/moddump_taylorgreen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_tidal.f90 b/src/utils/moddump_tidal.f90 index 4eacbe666..4f2cb2896 100644 --- a/src/utils/moddump_tidal.f90 +++ b/src/utils/moddump_tidal.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_torus.f90 b/src/utils/moddump_torus.f90 index 7cc782ebc..f30096374 100644 --- a/src/utils/moddump_torus.f90 +++ b/src/utils/moddump_torus.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/multirun.f90 b/src/utils/multirun.f90 index 6085a8a50..59d4d4704 100644 --- a/src/utils/multirun.f90 +++ b/src/utils/multirun.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program multirun ! diff --git a/src/utils/multirun_mach.f90 b/src/utils/multirun_mach.f90 index 5b189a9e0..9f0e3bf01 100644 --- a/src/utils/multirun_mach.f90 +++ b/src/utils/multirun_mach.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program multirun ! diff --git a/src/utils/pdfs.f90 b/src/utils/pdfs.f90 index 0ae12f9e7..77aeac124 100644 --- a/src/utils/pdfs.f90 +++ b/src/utils/pdfs.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module pdfs ! diff --git a/src/utils/phantom2divb.f90 b/src/utils/phantom2divb.f90 index 9386bb51d..90bd053a8 100644 --- a/src/utils/phantom2divb.f90 +++ b/src/utils/phantom2divb.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantom2divb ! diff --git a/src/utils/phantom2divv.f90 b/src/utils/phantom2divv.f90 index ee90b8be5..3f6d6f9f4 100644 --- a/src/utils/phantom2divv.f90 +++ b/src/utils/phantom2divv.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantom2divv ! diff --git a/src/utils/phantom2gadget.f90 b/src/utils/phantom2gadget.f90 index c499197b8..eeddb5695 100644 --- a/src/utils/phantom2gadget.f90 +++ b/src/utils/phantom2gadget.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantom2gadget ! diff --git a/src/utils/phantom2hdf5.f90 b/src/utils/phantom2hdf5.f90 index b332ce44c..a2d0ee5c3 100644 --- a/src/utils/phantom2hdf5.f90 +++ b/src/utils/phantom2hdf5.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantom2hdf5 ! diff --git a/src/utils/phantom2sphNG.f90 b/src/utils/phantom2sphNG.f90 index ac6079b09..f3f826abc 100644 --- a/src/utils/phantom2sphNG.f90 +++ b/src/utils/phantom2sphNG.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantom2sphNG ! diff --git a/src/utils/phantom_moddump.f90 b/src/utils/phantom_moddump.f90 index fccf96931..502069cd3 100644 --- a/src/utils/phantom_moddump.f90 +++ b/src/utils/phantom_moddump.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantommoddump ! diff --git a/src/utils/phantomanalysis.f90 b/src/utils/phantomanalysis.f90 index 1e444dbf1..b9ac76e5e 100644 --- a/src/utils/phantomanalysis.f90 +++ b/src/utils/phantomanalysis.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantomanalysis ! @@ -58,8 +58,7 @@ program phantomanalysis ! if (iarg==1) then - !iloc = index(dumpfile,'_0') - iloc = index(dumpfile,'_',.true.) !to load dump > 9999 + iloc = index(dumpfile,'_0') if (iloc > 1) then fileprefix = trim(dumpfile(1:iloc-1)) diff --git a/src/utils/phantomevcompare.f90 b/src/utils/phantomevcompare.f90 index 42a9c32b1..4c9d98e21 100644 --- a/src/utils/phantomevcompare.f90 +++ b/src/utils/phantomevcompare.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantomevcompare ! diff --git a/src/utils/phantomextractsinks.f90 b/src/utils/phantomextractsinks.f90 index 04b83cce5..20ea944d1 100644 --- a/src/utils/phantomextractsinks.f90 +++ b/src/utils/phantomextractsinks.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program phantomextractsinks ! diff --git a/src/utils/plot_kernel.f90 b/src/utils/plot_kernel.f90 index 4973d3d5b..61d6ea9eb 100644 --- a/src/utils/plot_kernel.f90 +++ b/src/utils/plot_kernel.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program plot_kernel ! diff --git a/src/utils/powerspectrums.f90 b/src/utils/powerspectrums.f90 index 1e65bc262..6897aab80 100644 --- a/src/utils/powerspectrums.f90 +++ b/src/utils/powerspectrums.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module powerspectrums ! diff --git a/src/utils/prompting.f90 b/src/utils/prompting.f90 index 1462eb885..c32c6c73d 100644 --- a/src/utils/prompting.f90 +++ b/src/utils/prompting.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module prompting ! diff --git a/src/utils/quartic.f90 b/src/utils/quartic.f90 index 83afe6690..ff7a71af7 100644 --- a/src/utils/quartic.f90 +++ b/src/utils/quartic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module quartic ! diff --git a/src/utils/rhomach.f90 b/src/utils/rhomach.f90 index 956d246b5..ed9ee6dbc 100644 --- a/src/utils/rhomach.f90 +++ b/src/utils/rhomach.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module rhomach ! diff --git a/src/utils/showarrays.f90 b/src/utils/showarrays.f90 index 252c3c05d..354f79649 100644 --- a/src/utils/showarrays.f90 +++ b/src/utils/showarrays.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program showarrays ! diff --git a/src/utils/showheader.f90 b/src/utils/showheader.f90 index bb355bc9b..9ffb166b3 100644 --- a/src/utils/showheader.f90 +++ b/src/utils/showheader.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program showheader ! @@ -43,7 +43,7 @@ program showheader ! try to open it as a small dump close(iu) call open_dumpfile_r(iu,dumpfile,fileid,ierr,singleprec=.true.) - if (ierr == 0) call read_header(iu,hdr,ierr,singleprec=.true.) + if (ierr == 0) call read_header(iu,hdr,.true.,ierr,singleprec=.true.) else print "(a)",' ERROR opening '//trim(dumpfile) endif @@ -51,7 +51,7 @@ program showheader ! ! read and print the file header ! - call read_header(iu,hdr,ierr) + call read_header(iu,hdr,.true.,ierr) endif if (ierr == 0) then if (nargs > 1) print "(/,':: ',a,' ::',/)",trim(dumpfile) diff --git a/src/utils/solvelinearsystem.f90 b/src/utils/solvelinearsystem.f90 index ed2c26f5b..68a2150ba 100644 --- a/src/utils/solvelinearsystem.f90 +++ b/src/utils/solvelinearsystem.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module solvelinearsystem ! diff --git a/src/utils/splitpart.f90 b/src/utils/splitpart.f90 index a63a5a928..d1c4502f0 100644 --- a/src/utils/splitpart.f90 +++ b/src/utils/splitpart.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module splitpart ! diff --git a/src/utils/struct2struct.f90 b/src/utils/struct2struct.f90 index 2ba0b54c2..7b13c9346 100644 --- a/src/utils/struct2struct.f90 +++ b/src/utils/struct2struct.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program struct2struct ! diff --git a/src/utils/struct_part.f90 b/src/utils/struct_part.F90 similarity index 97% rename from src/utils/struct_part.f90 rename to src/utils/struct_part.F90 index 63da27b42..bfad358d9 100644 --- a/src/utils/struct_part.f90 +++ b/src/utils/struct_part.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module structurefn_part ! @@ -140,20 +140,20 @@ subroutine get_structure_fn(sf,nbins,norder,distmin,distmax,xbins,ncount,npart,x call get_timings(t1,tcpu1) !$omp parallel do schedule(runtime) default(none) & - !$omp shared(npts,xyz,vel,list,npart,tcpu1) & + !$omp shared(npts,xyz,vel,list,npart) & !$omp firstprivate(distmin2,dxbox,dybox,dzbox,ddxbin,norder,minusdistminddxbin) & !$omp private(ipt,xpt,velpt,dx,dy,dz,rij2,rij1,rij,dvdotr) & - !$omp private(i,dvx,dvy,dvz,tcpu2) & + !$omp private(i,dvx,dvy,dvz) & !$omp private(dvterm,dvtrans,dvdotrterm,dvtransterm,ibin) & !$omp reduction(+:ncount) & !$omp reduction(+:sf) do ipt=1,npts -!$ if (.false.) then +#ifndef _OPENMP if (mod(ipt,100)==0) then call cpu_time(tcpu2) print*,' ipt = ',ipt,tcpu2-tcpu1 endif -!$ endif +#endif i = list(ipt) xpt(1) = xyz(1,i) xpt(2) = xyz(2,i) diff --git a/src/utils/test_binary.f90 b/src/utils/test_binary.f90 index 1f08f57e0..6ab272583 100644 --- a/src/utils/test_binary.f90 +++ b/src/utils/test_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module testbinary ! diff --git a/src/utils/testbinary.f90 b/src/utils/testbinary.f90 index d31988c25..244afd815 100644 --- a/src/utils/testbinary.f90 +++ b/src/utils/testbinary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! program testbin ! diff --git a/src/utils/utils_disc.f90 b/src/utils/utils_disc.f90 index 02f994a27..d3628ccf4 100644 --- a/src/utils/utils_disc.f90 +++ b/src/utils/utils_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module discanalysisutils ! diff --git a/src/utils/utils_ephemeris.f90 b/src/utils/utils_ephemeris.f90 index fb3a72322..66664e39c 100644 --- a/src/utils/utils_ephemeris.f90 +++ b/src/utils/utils_ephemeris.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module ephemeris ! diff --git a/src/utils/utils_evfiles.f90 b/src/utils/utils_evfiles.f90 index ece09037e..9b41d1a35 100644 --- a/src/utils/utils_evfiles.f90 +++ b/src/utils/utils_evfiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module evutils ! diff --git a/src/utils/utils_getneighbours.F90 b/src/utils/utils_getneighbours.F90 index 2c1dd26f2..0e6861216 100644 --- a/src/utils/utils_getneighbours.F90 +++ b/src/utils/utils_getneighbours.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module getneighbours ! diff --git a/src/utils/utils_gravwave.f90 b/src/utils/utils_gravwave.f90 index ed0c0ddcb..65765b8b7 100644 --- a/src/utils/utils_gravwave.f90 +++ b/src/utils/utils_gravwave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module gravwaveutils ! diff --git a/src/utils/utils_linalg.f90 b/src/utils/utils_linalg.f90 index e1b2e5bac..ede6a00fe 100644 --- a/src/utils/utils_linalg.f90 +++ b/src/utils/utils_linalg.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module linalg ! diff --git a/src/utils/utils_mpc.f90 b/src/utils/utils_mpc.f90 index 7b6489ddc..ed982fe77 100644 --- a/src/utils/utils_mpc.f90 +++ b/src/utils/utils_mpc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module mpc ! diff --git a/src/utils/utils_orbits.f90 b/src/utils/utils_orbits.f90 index 00ba9ea53..fe2d70e50 100644 --- a/src/utils/utils_orbits.f90 +++ b/src/utils/utils_orbits.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module orbits_data ! diff --git a/src/utils/utils_raytracer_all.f90 b/src/utils/utils_raytracer_all.F90 similarity index 99% rename from src/utils/utils_raytracer_all.f90 rename to src/utils/utils_raytracer_all.F90 index 19faadab3..26855bb9c 100644 --- a/src/utils/utils_raytracer_all.f90 +++ b/src/utils/utils_raytracer_all.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module raytracer_all ! diff --git a/src/utils/utils_splitmerge.f90 b/src/utils/utils_splitmerge.f90 index 4f740734f..73e3b8558 100644 --- a/src/utils/utils_splitmerge.f90 +++ b/src/utils/utils_splitmerge.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module splitmergeutils ! diff --git a/src/utils/velfield.f90 b/src/utils/velfield.f90 index 564c8badb..2ea560734 100644 --- a/src/utils/velfield.f90 +++ b/src/utils/velfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module velfield ! From 38f58409412a51995beb834e3f3fa14ee992576b Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 1 Sep 2023 09:38:30 +0100 Subject: [PATCH 076/182] made subroutine public in eos_stamatellos.f90 --- src/main/eos_stamatellos.f90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index dcf4ca520..7ed51195b 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -24,6 +24,7 @@ module eos_stamatellos !integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep + public :: finish_S07cool contains subroutine init_S07cool() From 328cbff5eaad7371869ea66ef26f028b716926f1 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 29 Sep 2023 11:14:27 +0100 Subject: [PATCH 077/182] Added extra file handling tests for reading opacity table --- src/main/eos_stamatellos.f90 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 7ed51195b..92f84fb49 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -57,7 +57,8 @@ subroutine read_optab(eos_file,ierr) if (ierr > 0) return do read(10,'(A120)') junk - if (index(adjustl(junk),'::') == 0) then !ignore comment lines + 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) read(junk, *,iostat=errread) nx, ny exit @@ -72,6 +73,8 @@ subroutine read_optab(eos_file,ierr) enddo enddo print *, 'nx,ny=', nx, ny + print *, "Optable first row:" + print *, (OPTABLE(1,1,i),i=1, 6) end subroutine read_optab ! From 848ccfff3026d77155d3d9c3d6c7e7f8395f8e84 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 29 Sep 2023 16:58:47 +0100 Subject: [PATCH 078/182] fix merge conflicts --- src/main/cooling_stamatellos.f90 | 8 ++++++++ src/main/force.F90 | 2 +- src/main/step_leapfrog.F90 | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 282c50beb..e1ea435cc 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -87,6 +87,14 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) Ti,gmwi) presi = eos_vars(igasP,i) + +if (isnan(kappaBari)) then + print *, "kappaBari is NaN\n", " ui(erg) = ", ui*unit_ergg, "rhoi=", rhoi*unit_density, "Ti=", Ti, & + "i=", i + stop +endif + + select case (od_method) case (1) coldensi = sqrt(abs(poti*rhoi)/4.d0/pi) ! G cancels out as G=1 in code diff --git a/src/main/force.F90 b/src/main/force.F90 index 1ad98cd5a..a3257e649 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1366,7 +1366,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g projv = dvx*runix + dvy*runiy + dvz*runiz if (iamgasj .and. maxvxyzu >= 4) then - enj = utherm(vxyzu(:,j),rhoj,gamma) + enj = vxyzu(4,j) if (eos_is_non_ideal(ieos)) then ! Is this condition required, or should this be always true? tempj = eos_vars(itemp,j) denij = 0.5*(eni/tempi + enj/tempj)*(tempi - tempj) ! dU = c_V * dT diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index e38de93f6..8679970a7 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -550,6 +550,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif endif + endif enddo corrector !$omp enddo !$omp end parallel From 8b8338b576ab0e413ad28ffd279f6245d1e33a78 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 11 Oct 2023 14:18:10 +0100 Subject: [PATCH 079/182] Fix merge bugs --- src/main/force.F90 | 2 +- src/main/step_leapfrog.F90 | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 4a1576b06..8365b85f9 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1367,7 +1367,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g projv = dvx*runix + dvy*runiy + dvz*runiz if (iamgasj .and. maxvxyzu >= 4) then - enj = utherm(vxyzu(:,j),rhoj,gamma) + enj = vxyzu(4,j) if (eos_is_non_ideal(ieos)) then ! Is this condition required, or should this be always true? tempj = eos_vars(itemp,j) denij = 0.5*(eni/tempi + enj/tempj)*(tempi - tempj) ! dU = c_V * dT diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index e38de93f6..8b98f287e 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -1,4 +1,4 @@ -!--------------------------------------------------------------------------! + !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! @@ -550,6 +550,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif endif endif + endif enddo corrector !$omp enddo !$omp end parallel From 277adce4406abbe0414d6ad9499f7179284ff215 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 16 Nov 2023 13:54:27 +0000 Subject: [PATCH 080/182] Added FLD for hybrid cooling after Forgan+ 2009 --- src/main/cooling_stamatellos.F90 | 220 +++++++++++++++++++++++++++++++ src/main/deriv.F90 | 180 ++++++++++++++++++++++++- src/main/eos_stamatellos.f90 | 17 +-- 3 files changed, 405 insertions(+), 12 deletions(-) create mode 100644 src/main/cooling_stamatellos.F90 diff --git a/src/main/cooling_stamatellos.F90 b/src/main/cooling_stamatellos.F90 new file mode 100644 index 000000000..09adfd7f3 --- /dev/null +++ b/src/main/cooling_stamatellos.F90 @@ -0,0 +1,220 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! +module cooling_stamatellos +! +! Cooling method of Stamatellos et al. 2007 +! +! :References: Stamatellos et al. 2007 +! +! :Owner: Alison Young +! +! :Runtime parameters: +! - EOS_file : *File containing tabulated EOS values* +! - Lstar : *Luminosity of host star for calculating Tmin (Lsun)* +! +! :Dependencies: eos_stamatellos, infile_utils, io, part, physcon, units +! + + implicit none + real, public :: Lstar ! in units of L_sun + integer :: isink_star ! index of sink to use as illuminating star + integer :: od_method = 1 ! default = Stamatellos+ 2007 method + public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos + public :: init_star + +contains + +subroutine init_star() + use part, only:nptmass,xyzmh_ptmass + integer :: i,imin + real :: rsink2,rsink2min + + rsink2min = 0d0 + if (nptmass == 0 .or. Lstar == 0.0) then + isink_star = 0 ! no stellar heating + print *, "No stellar heating." + elseif (nptmass == 1) then + isink_star = 1 + else + do i=1,nptmass + rsink2 = xyzmh_ptmass(1,i)**2 + xyzmh_ptmass(2,i)**2 + xyzmh_ptmass(3,i)**2 + if (i==1 .or. (rsink2 < rsink2min) ) then + rsink2min = rsink2 + imin = i + endif + enddo + isink_star = imin + endif + if (isink_star > 0) print *, "Using sink no. ", isink_star, "as illuminating star." +end subroutine init_star + +! +! Do cooling calculation +! +subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) + use io, only:warning + use physcon, only:steboltz,pi,solarl,Rg + use units, only:umass,udist,unit_density,unit_ergg,utime + use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool,& + iunitst,duFLD,doFLD + use part, only:eos_vars,igasP,xyzmh_ptmass,igamma + real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt + integer,intent(in) :: i + real,intent(out) :: dudti_cool + real :: coldensi,kappaBari,kappaParti,ri2 + real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,du_tot + real :: tcool,ueqi,umini,tthermi,poti,presi,du_FLDi + + poti = Gpot_cool(i) + du_FLDi = duFLD(i) +! du_FLDi = 0d0 + +! Tfloor is from input parameters and is background heating +! Stellar heating + if (isink_star > 0 .and. Lstar > 0.d0) then + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + + (zi-xyzmh_ptmass(3,isink_star))**2d0 + ri2 = ri2 *udist*udist +! Tfloor + stellar heating + Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2)) + else + Tmini4 = Tfloor**4d0 + endif + +! get opacities & Ti for ui + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + Ti,gmwi) + presi = eos_vars(igasP,i) + + select case (od_method) + case (1) + 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+ method of estimating the mean column density + coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 + coldensi = coldensi *umass/udist/udist ! physical units + end select + + tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units + dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units + + +! calculate Teqi + if (od_method == 1) then + if (doFLD) then + ! include term from FLD + Teqi = (du_FLDi+dudti_sph)*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + du_FLDi + else + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + endif + 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 + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg + endif + + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg + +! calculate thermalization timescale and +! internal energy update -> put in form where it'll work as dudtcool + select case (od_method) + case (1) + if ((du_tot) == 0.d0) then + tthermi = 0d0 + else + tthermi = abs((ueqi - ui)/(du_tot)) + endif + if (tthermi == 0d0) then + dudti_cool = 0.d0 ! condition if denominator above is zero + else + dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + endif + case (2) + if (abs(dudt_rad) > 0.d0) then + tthermi = (umini - ui) / dudt_rad ! + tiny(dudt_rad)) + dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph + else ! ie Tmini == Ti + dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS + end if + end select + + + if (isnan(dudti_cool)) then + print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti + print *, "rhoi=",rhoi, "Ti=", Ti + print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph + print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini + print *, "dudt_rad=", dudt_rad + call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) + stop + else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + dudti_cool = (umini - ui)/dt + endif + +end subroutine cooling_S07 + + +subroutine write_options_cooling_stamatellos(iunit) + use infile_utils, only:write_inopt + use eos_stamatellos, only: eos_file + integer, intent(in) :: iunit + + !N.B. Tfloor handled in cooling.F90 + call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) + call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure',iunit) + call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) + +end subroutine write_options_cooling_stamatellos + +subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) + use io, only:warning,fatal + use eos_stamatellos, only: eos_file + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotallstam + integer, intent(out) :: ierr + integer, save :: ngot = 0 + + + imatch = .true. + igotallstam = .false. ! cooling options are compulsory + select case(trim(name)) + case('Lstar') + read(valstring,*,iostat=ierr) Lstar + ngot = ngot + 1 + case('OD method') + read(valstring,*,iostat=ierr) od_method + if (od_method < 1 .or. od_method > 2) then + call fatal('cooling options','od_method must be 1 or 2',var='od_method',ival=od_method) + endif + ngot = ngot + 1 + case('EOS_file') + read(valstring,*,iostat=ierr) eos_file + ngot = ngot + 1 + case default + imatch = .false. + end select + if (od_method /= 1 .and. od_method /= 2) then + call warning('cooling_stamatellos','optical depth method unknown') + endif + + if (ngot >= 3) igotallstam = .true. + +end subroutine read_options_cooling_stamatellos + +end module cooling_stamatellos + diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 2b4f6ab10..9cbecb923 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -69,9 +69,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use derivutils, only:do_timing use cons2prim, only:cons2primall,cons2prim_everything,prim2consall use metric_tools, only:init_metric - use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge,calc_lambda_hybrid + use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge use options, only:implicit_radiation,implicit_radiation_store_drad,icooling - use eos_stamatellos, only:doFLD + use eos_stamatellos, only:doFLD,lambda_FLD integer, intent(in) :: icall integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -176,8 +176,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! compute diffusion term for hybrid RT & polytropic cooling method if (icooling == 8 .and. dt > 0. .and. doFLD) then - !print *, "calling lambda_hybrud from deriv" - call calc_lambda_hybrid(xyzh,vxyzu(4,:),dens) + !print *, "calling lambda_hybrid from deriv" + call set_linklist(npart,nactive,xyzh,vxyzu) + call calc_lambda(npart,xyzh,vxyzu,dens,lambda_FLD) endif ! @@ -265,4 +266,175 @@ subroutine get_derivs_global(tused,dt_new,dt) end subroutine get_derivs_global +subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) + use io, only:error + use dim, only:maxneigh + use part, only:get_partinfo,iamgas,iboundary,igas,maxphase,massoftype,iphase,gradh +#ifdef PERIODIC + use boundary, only:dxbound,dybound,dzbound +#endif + use kernel, only:radkern2,wkern,grkern,cnormk,get_kernel + use linklist, only:get_neighbour_list + use units, only:unit_density,unit_ergg + use eos_stamatellos, only:getopac_opdep,arad + + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:) + real, intent(in) :: vxyzu(:,:) + real, intent(in) :: rho(:) + real, intent(inout) :: lambda(:) + + integer, parameter :: maxcellcache = 10000 + logical :: iactivei,iamdusti,iamgasi,iactivej,iamgasj,iamdustj + integer :: iamtypei,i,j,n,iamtypej,mylistneigh(maxneigh),nneigh + integer(kind=1) :: iphasei + real :: rhoi,rhoj,uradi,xi,yi,zi + real :: dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj,gammaj,wkerni,grkerni + real :: kappaBari,kappaParti,gmwi,dx,dy,dz,rij2,rij,rij1,Wi,dWi + real :: dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4 + real :: pmassi,pmassj,hi,hi21,hi1,q,q2,q2i,xj,yj,zj,qi,q2j + real :: hj21,hi4i,hj,hj1,hi41,hi31,gradhi + real :: xyzcache(maxcellcache,4) + logical :: added_self,ignoreself + ignoreself = .true. + +! loop over parts +!$omp parallel do schedule(runtime) default(none) & +!$omp shared(npart,xyzh,iphase,ignoreself) & +!$omp shared(rho,lambda,massoftype,vxyzu,unit_density,unit_ergg,gradh) & +!$omp private(i,j,n,mylistneigh,nneigh,xyzcache,iphasei,iactivei) & +!$omp private(iamdusti,iamgasi,iactivej,iamgasj,iamdustj,iamtypei,iamtypej) & +!$omp private(rhoi,rhoj,uradi,xi,yi,zi,dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj) & +!$omp private(gammaj,wkerni,grkerni,kappaBari,kappaParti,gmwi,dx,dy,dz,rij2) & +!$omp private(rij,rij1,Wi,dWi,dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4) & +!$omp private(pmassi,pmassj,hi,hi21,hi1,q,q2,q2i,xj,yj,zj,qi,q2j,hj21,hi4i,hj,hj1) & +!$omp private(hi41,hi31,gradhi,added_self) + + over_parts: do i = 1,npart + ! + !---loop of neighbours to calculate radiation energy density + ! + !check active and gas particle + call get_neighbour_list(i,mylistneigh,nneigh,xyzh,xyzcache,maxcellcache, & + getj=.true.) + iphasei = iphase(i) + call get_partinfo(iphasei,iactivei,iamgasi,iamdusti,iamtypei) + if (.not. iactivei) cycle over_parts + if (iamtypei == iboundary) cycle over_parts + if (.not. iamgasi) cycle over_parts + + uradi = 0. + dradi = 0. + pmassi = massoftype(iamtypei) + rhoi = rho(i) + added_self = .false. + + call getopac_opdep(vxyzu(4,i)*unit_ergg,rhoi*unit_density,kappabari, & + kappaparti,ti,gmwi) + hi = xyzh(4,i) + hi1 = 1./hi + hi21 = hi1*hi1 + hi31 = hi1*hi21 + hi41 = hi21*hi21 + xi = xyzh(1,i) + yi = xyzh(2,i) + zi = xyzh(3,i) + ! + !--compute density and related quantities from the smoothing length + ! + pmassi = massoftype(iamtypei) + dradxi = 0.0 + dradyi = 0.0 + dradzi = 0.0 + + loop_over_neighbours: do n = 1,nneigh + j = mylistneigh(n) + if (j < 0) cycle loop_over_neighbours + if ((ignoreself) .and. (i==j)) cycle loop_over_neighbours + + if (n <= maxcellcache) then + ! positions from cache are already mod boundary + xj = xyzcache(n,1) + yj = xyzcache(n,2) + zj = xyzcache(n,3) + else + xj = xyzh(1,j) + yj = xyzh(2,j) + zj = xyzh(3,j) + endif + + dx = xi - xj + dy = yi - yj + dz = zi - zj +#ifdef PERIODIC + if (abs(dx) > 0.5*dxbound) dx = dx - dxbound*SIGN(1.0,dx) + if (abs(dy) > 0.5*dybound) dy = dy - dybound*SIGN(1.0,dy) + if (abs(dz) > 0.5*dzbound) dz = dz - dzbound*SIGN(1.0,dz) +#endif + rij2 = dx*dx + dy*dy + dz*dz + TINY(0.) + rij = SQRT(rij2) + q2i = rij2*hi21 + qi = SQRT(q2i) + + !--hj is in the cell cache but not in the neighbour cache + ! as not accessed during the density summation + hj1 = 1./xyzh(4,j) + hj = 1./hj1 + hj21 = hj1*hj1 + q2j = rij2*hj21 + is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then + call get_partinfo(iphase(j),iactivej,iamgasj,iamdustj,iamtypej) + + if (.not.iamgasj) cycle loop_over_neighbours + !Get kernel quantities + if (gradh(1,i) > 0.) then + gradhi = gradh(1,i) + else + !call error('force','stored gradh is zero, resetting to 1') + gradhi = 1. + endif + + call get_kernel(q2,q,wkerni,grkerni) + Wi = wkerni*cnormk*hi21*hi1 + dWi = grkerni*cnormk*hi21*hi21*gradh(1,i) + pmassj = massoftype(iamtypej) + rhoj = rho(j) + + call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,kappaBarj, & + kappaPartj,Tj,gmwj) + uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj) + ! unit vector components + runix = dx/rij + runiy = dy/rij + runiz = dz/rij + + dT4 = Ti**4d0 - Tj**4d0 + dradxi = dradxi + arad*pmassj*dT4*dWi*runix/rhoj + dradyi = dradyi + arad*pmassj*dT4*dWi*runiy/rhoj + dradzi = dradzi + arad*pmassj*dT4*dWi*runiz/rhoj + endif is_sph_neighbour + + enddo loop_over_neighbours + + if (.not. added_self) then + ! print *, "Has not added self in lambda hybrid + uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution + endif + ! urad = cnormk*uradi + arad*Ti**4.0d0 + dradi = cnormk*SQRT(dradxi**2.0d0 + dradyi**2.0d0 + dradzi**2.0d0) + !Now calculate flux limiter coefficients + !Calculate in cgs (converted to code units in forcei) + + if ((dradi.eq.0.0d0).or.(uradi.eq.0.0d0)) then + R_rad = 0.0d0 + else + R_rad = dradi/(uradi*rhoi*kappaParti) + endif + + lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) + + enddo over_parts +!$omp end parallel do +end subroutine calc_lambda + end module deriv diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index d5d920f63..a5e86a78f 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -22,7 +22,7 @@ module eos_stamatellos real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_fld(:),radprop_FLD(:,:) !gradP_cool=gradP/rho real, parameter,public :: arad=7.5657d-15 character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file - logical,parameter,public :: doFLD = .true. + logical,parameter,public :: doFLD = .True. integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in @@ -31,13 +31,14 @@ module eos_stamatellos subroutine init_S07cool() use part, only:npart,maxradprop - print *, "Allocating S07 arrays" + print *, "Allocating cooling arrays" allocate(gradP_cool(npart)) allocate(Gpot_cool(npart)) allocate(duFLD(npart)) allocate(lambda_fld(npart)) ! allocate(radprop_FLD(maxradprop,npart)) open (unit=iunitst,file='EOSinfo.dat',status='replace') + if (doFLD) print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" end subroutine init_S07cool subroutine finish_S07cool() @@ -59,7 +60,7 @@ subroutine read_optab(eos_file,ierr) ! read in data file for interpolation filepath=find_phantom_datafile(eos_file,'cooling') - print *,"FILEPATH:",filepath + print *,"EOS file: FILEPATH:",filepath open(10, file=filepath, form="formatted", status="old",iostat=ierr) if (ierr > 0) return do @@ -79,9 +80,9 @@ subroutine read_optab(eos_file,ierr) OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) enddo enddo - print *, 'nx,ny=', nx, ny - print *, "Optable first row:" - print *, (OPTABLE(1,1,i),i=1, 6) +! print *, 'nx,ny=', nx, ny +! print *, "Optable first row:" +! print *, (OPTABLE(1,1,i),i=1, 6) end subroutine read_optab ! @@ -109,7 +110,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) rhoi_ = rhoi endif - i = 1 + i = 2 do while((OPTABLE(i,1,1) <= rhoi_).and.(i < nx)) i = i + 1 enddo @@ -120,7 +121,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) ui_ = ui endif - j = 1 + j = 2 do while ((OPTABLE(i-1,j,3) <= ui_).and.(j < ny)) j = j + 1 enddo From 0ea6382f053cb0e1a632f255036aff017b78f92c Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 21 Nov 2023 12:01:40 +0000 Subject: [PATCH 081/182] FLD edits --- src/main/cooling_stamatellos.F90 | 62 ++++++++++++++++---------------- src/main/deriv.F90 | 16 +++++---- src/main/eos_stamatellos.f90 | 27 +++++++++++--- src/main/force.F90 | 31 +++++++++++++--- src/main/radiation_implicit.f90 | 3 ++ 5 files changed, 94 insertions(+), 45 deletions(-) diff --git a/src/main/cooling_stamatellos.F90 b/src/main/cooling_stamatellos.F90 index 09adfd7f3..3004bf952 100644 --- a/src/main/cooling_stamatellos.F90 +++ b/src/main/cooling_stamatellos.F90 @@ -58,7 +58,7 @@ end subroutine init_star subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning use physcon, only:steboltz,pi,solarl,Rg - use units, only:umass,udist,unit_density,unit_ergg,utime + use units, only:umass,udist,unit_density,unit_ergg,utime,unit_opacity use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool,& iunitst,duFLD,doFLD use part, only:eos_vars,igasP,xyzmh_ptmass,igamma @@ -98,22 +98,22 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) coldensi = coldensi*umass/udist/udist ! physical units case (2) ! Lombardi+ method of estimating the mean column density - coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 + coldensi = 1.014d0 * presi /abs(gradP_cool(i))! 1.014d0*P/(-gradP/rho) Lombardi+2015 coldensi = coldensi *umass/udist/udist ! physical units end select tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units - - + ! calculate Teqi - if (od_method == 1) then + if (od_method == 1 .or. od_method == 2) then if (doFLD) then ! include term from FLD - Teqi = (du_FLDi+dudti_sph)*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + Teqi = (du_FLDi+dudti_sph)*(coldensi**2.d0*kappaBari/unit_opacity + (1.d0/(kappaParti/unit_opacity))) & + *unit_ergg/utime du_tot = dudti_sph + dudt_rad + du_FLDi else - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + Teqi = dudti_sph*(coldensi**2.d0*kappaBari/unit_opacity + (1.d0/(kappaParti/unit_opacity)))*unit_ergg/utime du_tot = dudti_sph + dudt_rad endif Teqi = Teqi/4.d0/steboltz @@ -127,13 +127,13 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ueqi = ueqi/unit_ergg endif - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg ! calculate thermalization timescale and ! internal energy update -> put in form where it'll work as dudtcool - select case (od_method) - case (1) + ! select case (od_method) + !case (1) if ((du_tot) == 0.d0) then tthermi = 0d0 else @@ -144,27 +144,29 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) else dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif - case (2) - if (abs(dudt_rad) > 0.d0) then - tthermi = (umini - ui) / dudt_rad ! + tiny(dudt_rad)) - dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph - else ! ie Tmini == Ti - dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS - end if - end select +! case (2) +! if (abs(dudt_rad) > 0.d0) then +! tthermi = (umini - ui) / dudt_rad ! + tiny(dudt_rad)) +! dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt & +! + dudti_sph +! else ! ie Tmini == Ti +! dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS +! end if +! end select - if (isnan(dudti_cool)) then - print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "rhoi=",rhoi, "Ti=", Ti - print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph - print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad - call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) - stop - else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt - endif + if (isnan(dudti_cool)) then +! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti + print *, "sph, rad, fld", dudti_sph,dudt_rad,du_FLDi + print *, "rhoi=",rhoi, "Ti=", Ti +! print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph +! print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini +! print *, "dudt_rad=", dudt_rad, "ueqi", ueqi +! call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) + stop + else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + dudti_cool = (umini - ui)/dt + endif end subroutine cooling_S07 diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 9cbecb923..a3576dd99 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -275,7 +275,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) #endif use kernel, only:radkern2,wkern,grkern,cnormk,get_kernel use linklist, only:get_neighbour_list - use units, only:unit_density,unit_ergg + use units, only:unit_density,unit_ergg,unit_opacity use eos_stamatellos, only:getopac_opdep,arad integer, intent(in) :: npart @@ -300,7 +300,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) ! loop over parts !$omp parallel do schedule(runtime) default(none) & -!$omp shared(npart,xyzh,iphase,ignoreself) & +!$omp shared(npart,xyzh,iphase,ignoreself,unit_opacity) & !$omp shared(rho,lambda,massoftype,vxyzu,unit_density,unit_ergg,gradh) & !$omp private(i,j,n,mylistneigh,nneigh,xyzcache,iphasei,iactivei) & !$omp private(iamdusti,iamgasi,iactivej,iamgasj,iamdustj,iamtypei,iamtypej) & @@ -322,7 +322,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) if (.not. iactivei) cycle over_parts if (iamtypei == iboundary) cycle over_parts if (.not. iamgasi) cycle over_parts - + if (rho(i) < tiny(rhoi)) cycle over_parts uradi = 0. dradi = 0. pmassi = massoftype(iamtypei) @@ -350,6 +350,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) loop_over_neighbours: do n = 1,nneigh j = mylistneigh(n) if (j < 0) cycle loop_over_neighbours + if (rho(j) < tiny(rhoi)) cycle loop_over_neighbours if ((ignoreself) .and. (i==j)) cycle loop_over_neighbours if (n <= maxcellcache) then @@ -399,7 +400,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) dWi = grkerni*cnormk*hi21*hi21*gradh(1,i) pmassj = massoftype(iamtypej) rhoj = rho(j) - + if (rhoj < tiny(rhoj)) cycle loop_over_neighbours call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,kappaBarj, & kappaPartj,Tj,gmwj) uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj) @@ -428,11 +429,14 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) if ((dradi.eq.0.0d0).or.(uradi.eq.0.0d0)) then R_rad = 0.0d0 else - R_rad = dradi/(uradi*rhoi*kappaParti) + R_rad = dradi/(uradi*rhoi*kappaParti/unit_opacity) endif lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) - + if (isnan(lambda(i))) then + print *, "lambda isnan. i, R_Rad, uradi,dradi,rhoi,kappaParti", & + i,R_Rad,uradi,dradi,rhoi,kappaParti + endif enddo over_parts !$omp end parallel do end subroutine calc_lambda diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index a5e86a78f..f6b323eb8 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -19,7 +19,7 @@ module eos_stamatellos implicit none real,allocatable,public :: optable(:,:,:) - real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_fld(:),radprop_FLD(:,:) !gradP_cool=gradP/rho + real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_FLD(:),radprop_FLD(:,:) !gradP_cool=gradP/rho real, parameter,public :: arad=7.5657d-15 character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file logical,parameter,public :: doFLD = .True. @@ -27,6 +27,7 @@ module eos_stamatellos integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep,finish_S07cool + public :: get_k_fld contains subroutine init_S07cool() @@ -146,7 +147,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) gmw1 = m*ui_ + c - j = 1 + j = 2 do while ((OPTABLE(i,j,3) <= ui).and.(j < ny)) j = j + 1 enddo @@ -212,12 +213,12 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) rhoi_ = rhoi endif - i = 1 + i = 2 do while((OPTABLE(i,1,1) <= rhoi_).and.(i < nx)) i = i + 1 enddo - j = 1 + j = 2 do while ((OPTABLE(i-1,j,2) <= Teqi).and.(j < ny)) j = j + 1 enddo @@ -227,7 +228,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) u1 = m*Teqi + c - j = 1 + j = 2 do while ((OPTABLE(i,j,2) <= Teqi).and.(j < ny)) j = j + 1 enddo @@ -243,6 +244,22 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) ueqi = m*rhoi_ + c end subroutine getintenerg_opdep +subroutine get_k_fld(rhoi,eni,i,ki,Ti) + use physcon, only:steboltz + use units, only:unit_density,unit_ergg,unit_opacity + real,intent(in) :: rhoi,eni + integer,intent(in) :: i + real :: kappaBar,gmwi,kappaPart + real,intent(out) :: ki,Ti + + call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) + ki = 16d0 * steboltz * lambda_FLD(i) * Ti**3 /rhoi/kappaPart/unit_opacity + if (isnan(ki)) then + print *, "WARNING k isnan, lambda_FLDi,Ti,rhoi,kappaPart", & + lambda_FLD(i), Ti, rhoi,kappaPart + endif +end subroutine get_k_fld + !subroutine calc_FLD(xyzhi,duFLDi,pmassj,tempi,tempj,rhoi,rhoj,j,grkerni) !real,intent(inout) :: duFLDi ! integer,intent(in) :: j diff --git a/src/main/force.F90 b/src/main/force.F90 index 8365b85f9..56b08dd72 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -903,7 +903,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt use eos, only:ieos,eos_is_non_ideal,gamma - use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,arad + use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,arad,getopac_opdep,get_k_fld #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -1032,7 +1032,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi,wkernj,wkerni,gradpx,gradpy,gradpz,gradP_cooli,gradP_coolj + real :: radPj,fgravxi,fgravyi,fgravzi,wkernj,wkerni,gradpx,gradpy,gradpz + real :: gradP_cooli,gradP_coolj,kfldi,kfldj,Ti,Tj,diffterm ! unpack xi = xpartveci(ixi) @@ -1208,6 +1209,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g gradpx = 0d0 gradpy = 0d0 gradpz = 0d0 + diffterm = 0d0 + call get_k_fld(rhoi,eni,i,kfldi,Ti) +! print *, "rhoi,eni,i,kfldi,Ti", rhoi,eni,i,kfldi,Ti endif loop_over_neighbours2: do n = 1,nneigh @@ -1748,9 +1752,28 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idendtdissi) = fsum(idendtdissi) + dendissterm if (icooling == 8) then Gpot_cool(i) = Gpot_cool(i) + pmassj*phii -! if (doFLD) then + if (doFLD) then +! print *, rhoj, "calling k_fld for j" + call get_k_fld(rhoj,enj,j,kfldj,Tj) + if ((kfldj + kfldi) == 0.) then + diffterm = 0d0 + elseif (rhoj == 0.) then + diffterm = 0d0 + else + diffterm = 4d0*pmassj/rhoi/rhoj + diffterm = diffterm * kfldi * kfldj / (kfldi+kfldj) + diffterm = diffterm * (Ti - Tj) / rij2 + diffterm = diffterm*cnormk*grkerni*(runix*dx + runiy*dy + runiz*dz) + endif + duFLD(i) = duFLD(i) + diffterm + if (isnan(duFLD(i))) then + print *, "FLD is nan for particle i=, j = ", i,j + print *, "rhoi,rhoj,rij2,diffterm",rhoi,rhoj,rij2,diffterm + print *, "kfldi, kfldj, Ti,Tj", kfldi,kfldj, Ti,Tj + stop + endif ! call calc_FLD(duFLD(i),i,j,q2j,qj,hi121,hi1,pmassj,eos_vars(itemp,j),eos_vars(itemp,j),rhoj) - ! endif + endif endif endif diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index fd54cbe7f..d8982d504 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -1564,6 +1564,9 @@ subroutine calc_lambda_hybrid(xyzh,utherm,rho) ! print *, n,ncompact,utherm(i) uradi = 0. dradi = 0. + dradxi = 0. + dradyi = 0. + dradzi = 0. rhoi = rho(i) added_self = .false. hi = xyzh(4,i) From e933a36cddf8bd07bdb217064db914e7303524dc Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 30 Nov 2023 14:13:28 +0000 Subject: [PATCH 082/182] Added combined Stamatellos/Lombardi cooling method --- src/main/cooling_stamatellos.f90 | 92 ++++++++++++++------------------ 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index e1ea435cc..5a32f774b 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -57,16 +57,16 @@ end subroutine init_star ! subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning - use physcon, only:steboltz,pi,solarl,Rg - use units, only:umass,udist,unit_density,unit_ergg,utime + use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh + use units, only:umass,udist,unit_density,unit_ergg,utime,unit_pressure use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool use part, only:eos_vars,igasP,xyzmh_ptmass,igamma real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 - real :: gmwi,Tmini4,Ti,dudt_rad,Teqi - real :: tcool,ueqi,umini,tthermi,poti,presi + real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,Hstam,HLom + real :: tcool,ueqi,tthermi,poti,presi,Hcomb poti = Gpot_cool(i) ! Tfloor is from input parameters and is background heating @@ -85,8 +85,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) - presi = eos_vars(igasP,i) - + presi = kb_on_mh*rhoi*unit_density*Ti/gmwi + presi = presi/unit_pressure if (isnan(kappaBari)) then print *, "kappaBari is NaN\n", " ui(erg) = ", ui*unit_ergg, "rhoi=", rhoi*unit_density, "Ti=", Ti, & @@ -94,68 +94,58 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) stop endif - 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+ method of estimating the mean column density - coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 +! 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) + HStam = sqrt(abs(poti*rhoi)/4.0d0/pi)*0.368d0/rhoi + HLom = 1.014d0*presi/abs(gradP_cool(i))/rhoi + Hcomb = 1.0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/HStam)**2.0d0) + coldensi = Hcomb*rhoi + coldensi = coldensi*umass/udist/udist end select tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units - ! calculate Teqi - if (od_method == 1) then - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg + Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime + 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 - - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg ! calculate thermalization timescale and -! internal energy update -> put in form where it'll work as dudtcool - select case (od_method) - case (1) - if ((dudti_sph + dudt_rad) == 0.d0) then - tthermi = 0d0 - else - tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) - endif - if (tthermi == 0d0) then - dudti_cool = 0.d0 ! condition if denominator above is zero - else - dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units - endif - case (2) - if (abs(dudt_rad) > 0.d0) then - tthermi = (umini - ui) / (dudt_rad)! + tiny(dudt_rad)) - dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph - else ! ie Tmini == Ti - dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS - endif - end select - +! internal energy update -> this is in a form where it'll work as dudtcool + if ((dudti_sph + dudt_rad) == 0.d0) then + tthermi = 0d0 + else + tthermi = abs((ueqi - ui)/(dudti_sph + dudt_rad)) + endif + if (tthermi == 0d0) then + dudti_cool = 0.d0 ! condition if denominator above is zero + else + dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + endif + if (isnan(dudti_cool)) then print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti print *, "rhoi=",rhoi, "Ti=", Ti print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph - print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini + print *, "dt=",dt,"tthermi=", tthermi print *, "dudt_rad=", dudt_rad call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop @@ -174,7 +164,7 @@ subroutine write_options_cooling_stamatellos(iunit) !N.B. Tfloor handled in cooling.F90 call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) - call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure',iunit) + call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure (3) combined',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) end subroutine write_options_cooling_stamatellos @@ -196,8 +186,8 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie ngot = ngot + 1 case('OD method') read(valstring,*,iostat=ierr) od_method - if (od_method < 1 .or. od_method > 2) then - call fatal('cooling options','od_method must be 1 or 2',var='od_method',ival=od_method) + if (od_method < 1 .or. od_method > 3) then + call fatal('cooling options','od_method must be 1, 2 or 3',var='od_method',ival=od_method) endif ngot = ngot + 1 case('EOS_file') @@ -206,7 +196,7 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie case default imatch = .false. end select - if (od_method /= 1 .and. od_method /= 2) then + if (od_method /= 1 .and. od_method /= 2 .and. od_method /= 3) then call warning('cooling_stamatellos','optical depth method unknown') endif From f746def2a443982ea13776cc412b102c040a976e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 30 Nov 2023 14:26:50 +0000 Subject: [PATCH 083/182] Bug fix in cooling_stamatellos.f90 --- src/main/cooling_stamatellos.f90 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 5a32f774b..a5550f598 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -66,7 +66,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,Hstam,HLom - real :: tcool,ueqi,tthermi,poti,presi,Hcomb + real :: tcool,ueqi,umini,tthermi,poti,presi,Hcomb poti = Gpot_cool(i) ! Tfloor is from input parameters and is background heating @@ -127,6 +127,9 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg + ! calculate thermalization timescale and ! internal energy update -> this is in a form where it'll work as dudtcool if ((dudti_sph + dudt_rad) == 0.d0) then From af4566adb7286ff04a36b07020a0c0037e34c7c3 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 8 Jan 2024 17:37:59 +0000 Subject: [PATCH 084/182] FLD implemented in dens module --- src/main/cooling_stamatellos.f90 | 115 ++++++++--------- src/main/dens.F90 | 182 ++++++++++++++++++++++++++- src/main/deriv.F90 | 71 +++++++---- src/main/eos_stamatellos.f90 | 33 ++--- src/main/force.F90 | 14 ++- src/main/radiation_implicit.f90 | 12 +- src/main/readwrite_dumps_fortran.F90 | 6 +- 7 files changed, 317 insertions(+), 116 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index b88c60faa..d18a0187a 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -57,11 +57,11 @@ end subroutine init_star ! subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning - use physcon, only:steboltz,pi,solarl,Rg - use units, only:umass,udist,unit_density,unit_ergg,utime + use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh + use units, only:umass,udist,unit_density,unit_ergg,utime,unit_pressure use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool,& - iunitst,duFLD,doFLD - use part, only:eos_vars,igasP,xyzmh_ptmass,igamma + duFLD,doFLD + use part, only:xyzmh_ptmass real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i real,intent(out) :: dudti_cool @@ -70,8 +70,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real :: tcool,ueqi,umini,tthermi,poti,presi,du_FLDi poti = Gpot_cool(i) -! du_FLDi = duFLD(i) - du_FLDi = 0d0 + du_FLDi = duFLD(i) +! du_FLDi = 0d0 ! Tfloor is from input parameters and is background heating ! Stellar heating @@ -89,7 +89,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) - presi = eos_vars(igasP,i) + presi = kb_on_mh*rhoi*unit_density*Ti/gmwi + presi = presi/unit_pressure select case (od_method) case (1) @@ -105,66 +106,58 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units - ! calculate Teqi - if (od_method == 1) then - if (doFLD) then - ! include term from FLD - Teqi = (du_FLDi+dudti_sph)*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - du_tot = dudti_sph + dudt_rad + du_FLDi - else - Teqi = dudti_sph*(coldensi**2.d0*kappaBari + (1.d0/kappaParti))*unit_ergg/utime - du_tot = dudti_sph + dudt_rad - endif - 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg - endif - - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg + + if (doFLD) then + ! include term from FLD + Teqi = (du_FLDi+dudti_sph) *tcool*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + du_FLDi + else + Teqi = dudti_sph*tcool*unit_ergg/utime + du_tot = dudti_sph + dudt_rad + endif + 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 + + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg + + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg + + !if (Ti > 6d0) print *, "eq temps:", Teqi,Ti + ! calculate thermalization timescale and ! internal energy update -> put in form where it'll work as dudtcool - select case (od_method) - case (1) - if ((du_tot) == 0.d0) then - tthermi = 0d0 - else - tthermi = abs((ueqi - ui)/(du_tot)) - endif - if (tthermi == 0d0) then - dudti_cool = 0.d0 ! condition if denominator above is zero - else - dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units - endif - case (2) - if (abs(dudt_rad) > 0.d0) then - tthermi = (umini - ui) / dudt_rad ! + tiny(dudt_rad)) - dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt + dudti_sph - else ! ie Tmini == Ti - dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS - end if - end select + if ((du_tot) == 0.d0) then + tthermi = 0d0 + else + tthermi = abs((ueqi - ui)/(du_tot)) + endif + if (tthermi == 0d0) then + dudti_cool = 0.d0 ! condition if denominator above is zero + else + dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + endif - if (isnan(dudti_cool)) then - print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "rhoi=",rhoi, "Ti=", Ti - print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph - print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad - call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) - stop - else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt - endif + if (isnan(dudti_cool)) then + print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti + print *, "rhoi=",rhoi, "Ti=", Ti + print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph + print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini + print *, "dudt_rad=", dudt_rad + call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) + stop + else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + dudti_cool = (umini - ui)/dt + endif end subroutine cooling_S07 diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 71f4ba968..a6b891254 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -139,6 +139,8 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol use io_summary,only:summary_variable,iosumhup,iosumhdn use timing, only:increment_timer,get_timings,itimer_dens_local,itimer_dens_remote use omputils, only:omp_thread_num,omp_num_threads + use eos_stamatellos, only:doFLD,lambda_FLD,urad_FLD + use options, only:icooling integer, intent(in) :: icall,npart,nactive real, intent(inout) :: xyzh(:,:) real, intent(in) :: vxyzu(:,:),fxyzu(:,:),fext(:,:) @@ -265,6 +267,8 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol !$omp shared(cell_counters) & !$omp shared(thread_complete) & !$omp shared(ncomplete_mpi) & +!$omp shared(icooling) & +!$omp shared(lambda_FLD,urad_FLD) & !$omp reduction(+:nlocal) & !$omp private(do_export) & !$omp private(j) & @@ -344,7 +348,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - + if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) if (do_export) then call write_cell(stack_waiting,cell) else @@ -377,7 +381,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - + if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) if (do_export) then call write_cell(stack_waiting,cell) exit local_its @@ -447,7 +451,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol cell_xpos=cell%xpos,cell_xsizei=cell%xsizei,cell_rcuti=cell%rcuti) call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - + if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) remote_export = .false. remote_export(cell%owner+1) = .true. ! use remote_export array to send back to the owner @@ -508,6 +512,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol 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) + if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) call write_cell(stack_redo,cell) else @@ -1650,4 +1655,175 @@ subroutine store_results(icall,cell,getdv,getdb,realviscosity,stressmax,xyzh,& end subroutine store_results +! calc_lambda is called for each cell +subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda,urad_FLD) + use io, only:error + use dim, only:maxp + use kernel,only:get_kernel,wab0 + use part, only:get_partinfo,iamgas,igas,maxphase,massoftype + use part, only:rhoanddhdrho + use physcon, only:radconst + use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code + use eos_stamatellos, only:getopac_opdep +#ifdef PERIODIC + use boundary, only:dxbound,dybound,dzbound +#endif + + type(celldens), intent(in) :: cell + 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(:,:) + real, intent(inout) :: lambda(:),urad_FLD(:) + + integer :: icell,i,iamtypei,iamtypej,j,n + logical :: iactivei,iamgasi,iamdusti,ignoreself + logical :: iactivej,iamgasj,iamdustj + real(kind=8) :: hi,hi1,hi21,hi31,hi41 + real :: rhoi,rho1i,dhdrhoi,pmassi,kappabari,kappaparti,Ti,gmwi + real :: xj,yj,zj,dx,dy,dz + real :: rij2,rij,q2i,qi,hj1,hj,hj21,q2j + real :: wabi,grkerni,gradhi,wkerni,dwkerni + real :: pmassj,rhoj,rho1j,dhdrhoj,kappabarj,kappaPartj,Tj,gmwj + real :: uradi,dradi,dradxi,dradyi,dradzi,runix,runiy,runiz + real :: dT4,R_rad + integer :: ngradh_err + real :: uradself + + ngradh_err = 0 + over_parts: do icell = 1,cell%npcell + i = inodeparts(cell%arr_index(icell)) + ! note: only active particles have been sent here + if (maxphase==maxp) then + call get_partinfo(cell%iphase(icell),iactivei,iamgasi,iamdusti,iamtypei) + else + iactivei = .true. + iamtypei = igas + iamgasi = .true. + endif + + hi = cell%h(icell) + hi1 = 1./hi + hi21 = hi1*hi1 + hi31 = hi1*hi21 + hi41 = hi21*hi21 + + ignoreself = (cell%owner == i) + uradi = 0d0 + dradi = 0d0 + dradxi = 0.0 + dradyi = 0.0 + dradzi = 0.0 + + pmassi = massoftype(iamtypei) + !calculate rhoi + call rhoanddhdrho(hi,hi1,rhoi,rho1i,dhdrhoi,pmassi) + ! get Ti from tabulated eos + call getopac_opdep(vxyzu(4,i)*unit_ergg,rhoi*unit_density,kappabari, & + kappaparti,Ti,gmwi) + + loop_over_neighbours: do n=1,nneigh + j = abs(listneigh(n)) + if (i==j) cycle loop_over_neighbours + xj = xyzh(1,j) + yj = xyzh(2,j) + zj = xyzh(3,j) + + dx = cell%xpartvec(ixi,icell) - xj + dy = cell%xpartvec(iyi,icell) - yj + dz = cell%xpartvec(izi,icell) - zj + +#ifdef PERIODIC + if (abs(dx) > 0.5*dxbound) dx = dx - dxbound*SIGN(1.0,dx) + if (abs(dy) > 0.5*dybound) dy = dy - dybound*SIGN(1.0,dy) + if (abs(dz) > 0.5*dzbound) dz = dz - dzbound*SIGN(1.0,dz) +#endif + + rij2 = dx*dx + dy*dy + dz*dz + TINY(0.) + rij = SQRT(rij2) + q2i = rij2*hi21 + qi = SQRT(q2i) + + hj1 = 1./xyzh(4,j) + hj = 1./hj1 + hj21 = hj1*hj1 + q2j = rij2*hj21 + + is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then + if (maxphase==maxp) then + call get_partinfo(iphase(j),iactivej,iamgasj,iamdustj,iamtypej) + else + iactivej = .true. + iamtypej = igas + iamgasj = .true. + endif + if (.not. iamgasj) cycle loop_over_neighbours + if (.not. iactivej) cycle loop_over_neighbours + ! get kernel quantities + if (gradh(1,i) > 0.) then + gradhi = gradh(1,i) + !elseif (ngradh_err < 20) then + ! call error('force','stored gradh is zero, resetting to 1') + ! gradhi = 1. + ! ngradh_err = ngradh_err + 1 + else + gradhi = 1. + ngradh_err = ngradh_err + 1 + endif + call get_kernel(q2i,qi,wabi,grkerni) + wkerni = wabi*cnormk*hi21*hi1 + dwkerni = grkerni*cnormk*hi21*hi21*gradh(1,i) + pmassj = massoftype(iamtypej) + call rhoanddhdrho(hj,hj1,rhoj,rho1j,dhdrhoj,pmassj) + call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,& + kappaBarj,kappaPartj,Tj,gmwj) + uradi = uradi + get_radconst_code()*(Tj**4.0d0)*wkerni*pmassj/rhoj + + ! calculate components of gradient + runix = dx/rij + runiy = dy/rij + runiz = dz/rij + + dT4 = Ti**4d0 - Tj**4d0 + dradxi = dradxi + get_radconst_code()*pmassj*dT4*dwkerni*runix/rhoj + dradyi = dradyi + get_radconst_code()*pmassj*dT4*dwkerni*runiy/rhoj + dradzi = dradzi + get_radconst_code()*pmassj*dT4*dwkerni*runiz/rhoj + + endif is_sph_neighbour + + enddo loop_over_neighbours + + ! add self contribution + + uradi = uradi + cnormk*hi31*get_radconst_code()*(Ti**4d0) & + *wab0*pmassi/rhoi + if (uradi > 1.d0) print *, "cnormk,hi31,radconst,Ti,wab0,pmassi,rhoi",& + cnormk,hi31,get_radconst_code(),Ti,wab0,pmassi,rhoi,"wabi,wkerni,pmassj,rhoj", & + wabi,wkerni,pmassj,rhoj +!$omp critical + if (iamgasi .and. uradi > 0d0) urad_FLD(i) = uradi +!$omp end critical + !Now calculate flux limiter coefficients + !Calculate in code units (converted to code units in forcei) + dradi = SQRT(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! should this be normalised somehow? + if ((dradi.eq.0.0d0).or.(uradi.eq.0.0d0)) then + R_rad = 0.0d0 + else + R_rad = dradi/(uradi*rhoi*kappaParti/unit_opacity) + endif +!$omp critical + lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) +!$omp end critical + if (isnan(lambda(i))) then + print *, "lambda isnan when calculated. i, R_Rad, uradi,dradi,rhoi,",& + "kappaParti, Ti",i,R_Rad,uradi,dradi,rhoi,kappaParti,Ti + endif + + enddo over_parts + if (ngradh_err > 0) print *, "ngradh_errors = ", ngradh_err +end subroutine calc_lambda_cell + end module densityforce diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index a3576dd99..b5d68e3ba 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -71,7 +71,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use metric_tools, only:init_metric use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge use options, only:implicit_radiation,implicit_radiation_store_drad,icooling - use eos_stamatellos, only:doFLD,lambda_FLD + integer, intent(in) :: icall integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -158,7 +158,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& set_boundaries_to_active = .false. ! boundary particles are no longer treated as active call do_timing('dens',tlast,tcpulast) endif - + if (gr) then call cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) else @@ -174,13 +174,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& if (ierr /= 0 .and. ierr /= ierr_failed_to_converge) call fatal('radiation','Failed in radiation') endif - ! compute diffusion term for hybrid RT & polytropic cooling method - if (icooling == 8 .and. dt > 0. .and. doFLD) then - !print *, "calling lambda_hybrid from deriv" - call set_linklist(npart,nactive,xyzh,vxyzu) - call calc_lambda(npart,xyzh,vxyzu,dens,lambda_FLD) - endif - ! ! compute forces ! @@ -276,7 +269,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) use kernel, only:radkern2,wkern,grkern,cnormk,get_kernel use linklist, only:get_neighbour_list use units, only:unit_density,unit_ergg,unit_opacity - use eos_stamatellos, only:getopac_opdep,arad + use eos_stamatellos, only:getopac_opdep integer, intent(in) :: npart real, intent(in) :: xyzh(:,:) @@ -287,7 +280,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) integer, parameter :: maxcellcache = 10000 logical :: iactivei,iamdusti,iamgasi,iactivej,iamgasj,iamdustj integer :: iamtypei,i,j,n,iamtypej,mylistneigh(maxneigh),nneigh - integer(kind=1) :: iphasei + integer(kind=1) :: iphasei,iphasej real :: rhoi,rhoj,uradi,xi,yi,zi real :: dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj,gammaj,wkerni,grkerni real :: kappaBari,kappaParti,gmwi,dx,dy,dz,rij2,rij,rij1,Wi,dWi @@ -296,8 +289,11 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) real :: hj21,hi4i,hj,hj1,hi41,hi31,gradhi real :: xyzcache(maxcellcache,4) logical :: added_self,ignoreself + integer :: success_count ignoreself = .true. - + + print *, "calculating lambda in deriv" + success_count = 0 ! loop over parts !$omp parallel do schedule(runtime) default(none) & !$omp shared(npart,xyzh,iphase,ignoreself,unit_opacity) & @@ -308,7 +304,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) !$omp private(gammaj,wkerni,grkerni,kappaBari,kappaParti,gmwi,dx,dy,dz,rij2) & !$omp private(rij,rij1,Wi,dWi,dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4) & !$omp private(pmassi,pmassj,hi,hi21,hi1,q,q2,q2i,xj,yj,zj,qi,q2j,hj21,hi4i,hj,hj1) & -!$omp private(hi41,hi31,gradhi,added_self) +!$omp private(hi41,hi31,gradhi,added_self,success_count,iphasej) over_parts: do i = 1,npart ! @@ -319,10 +315,11 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) getj=.true.) iphasei = iphase(i) call get_partinfo(iphasei,iactivei,iamgasi,iamdusti,iamtypei) + print *, i, iactivei,iamgasi,rho(i),"nneigh:",nneigh if (.not. iactivei) cycle over_parts if (iamtypei == iboundary) cycle over_parts if (.not. iamgasi) cycle over_parts - if (rho(i) < tiny(rhoi)) cycle over_parts + uradi = 0. dradi = 0. pmassi = massoftype(iamtypei) @@ -350,9 +347,14 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) loop_over_neighbours: do n = 1,nneigh j = mylistneigh(n) if (j < 0) cycle loop_over_neighbours - if (rho(j) < tiny(rhoi)) cycle loop_over_neighbours + iphasej = iphase(j) + call get_partinfo(iphasej,iactivej,iamgasj,iamdustj,iamtypej) + if (.not. iactivej) cycle loop_over_neighbours + if (iamtypej == iboundary) cycle loop_over_neighbours + if (.not. iamgasj) cycle loop_over_neighbours if ((ignoreself) .and. (i==j)) cycle loop_over_neighbours - + if (xyzh(4,j) < 0d0) cycle loop_over_neighbours + print *, "n=", n if (n <= maxcellcache) then ! positions from cache are already mod boundary xj = xyzcache(n,1) @@ -385,8 +387,8 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) q2j = rij2*hj21 is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then call get_partinfo(iphase(j),iactivej,iamgasj,iamdustj,iamtypej) - if (.not.iamgasj) cycle loop_over_neighbours + if (.not.iactivej) cycle loop_over_neighbours !Get kernel quantities if (gradh(1,i) > 0.) then gradhi = gradh(1,i) @@ -394,7 +396,7 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) !call error('force','stored gradh is zero, resetting to 1') gradhi = 1. endif - + !print *, "q2i,q2j", q2i,q2j call get_kernel(q2,q,wkerni,grkerni) Wi = wkerni*cnormk*hi21*hi1 dWi = grkerni*cnormk*hi21*hi21*gradh(1,i) @@ -403,23 +405,29 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) if (rhoj < tiny(rhoj)) cycle loop_over_neighbours call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,kappaBarj, & kappaPartj,Tj,gmwj) - uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj) +! uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj) + if (uradi > 1e40) then + print *, "Urad huge- i,j,pmassj,Tj,Wi,hi,rhoj:", i,j,pmassj,Tj,Wi,1/hi1,rhoj,xj,yj,zj + print *, "wkerni,cnormk,hi21,hi1", wkerni,cnormk,hi21,hi1,tiny(rhoj) + print *, "max min rho", maxval(rho), minval(rho) + stop + endif ! unit vector components runix = dx/rij runiy = dy/rij runiz = dz/rij dT4 = Ti**4d0 - Tj**4d0 - dradxi = dradxi + arad*pmassj*dT4*dWi*runix/rhoj - dradyi = dradyi + arad*pmassj*dT4*dWi*runiy/rhoj - dradzi = dradzi + arad*pmassj*dT4*dWi*runiz/rhoj +! dradxi = dradxi + arad*pmassj*dT4*dWi*runix/rhoj +! dradyi = dradyi + arad*pmassj*dT4*dWi*runiy/rhoj +! dradzi = dradzi + arad*pmassj*dT4*dWi*runiz/rhoj endif is_sph_neighbour enddo loop_over_neighbours if (.not. added_self) then ! print *, "Has not added self in lambda hybrid - uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution +! uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution endif ! urad = cnormk*uradi + arad*Ti**4.0d0 dradi = cnormk*SQRT(dradxi**2.0d0 + dradyi**2.0d0 + dradzi**2.0d0) @@ -434,11 +442,24 @@ subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) if (isnan(lambda(i))) then - print *, "lambda isnan. i, R_Rad, uradi,dradi,rhoi,kappaParti", & - i,R_Rad,uradi,dradi,rhoi,kappaParti + print *, "lambda isnan when calculated. i, R_Rad, uradi,dradi,rhoi,kappaParti, Ti", & + i,R_Rad,uradi,dradi,rhoi,kappaParti,Ti + elseif (lambda(i) < tiny(lambda(i))) then + print *, "lambda is 0,i, rhoi, uradi", i, rhoi, uradi + stop + else +!$omp critical + success_count = success_count + 1 +!$omp end critical endif enddo over_parts !$omp end parallel do + print *, "success =", success_count + do i=1,npart + if (lambda(i) < tiny(lambda(i))) then + print *, "lambda is 0,i, rhoi, uradi", i, rhoi, uradi,kappaParti + endif + enddo end subroutine calc_lambda end module deriv diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index f6b323eb8..5455fcaa5 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -19,8 +19,7 @@ module eos_stamatellos implicit none real,allocatable,public :: optable(:,:,:) - real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_FLD(:),radprop_FLD(:,:) !gradP_cool=gradP/rho - real, parameter,public :: arad=7.5657d-15 + real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_FLD(:),urad_FLD(:) !gradP_cool=gradP/rho character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file logical,parameter,public :: doFLD = .True. integer,public :: iunitst=19 @@ -37,7 +36,8 @@ subroutine init_S07cool() allocate(Gpot_cool(npart)) allocate(duFLD(npart)) allocate(lambda_fld(npart)) -! allocate(radprop_FLD(maxradprop,npart)) + allocate(urad_FLD(npart)) + urad_FLD(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') if (doFLD) print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" end subroutine init_S07cool @@ -48,7 +48,7 @@ subroutine finish_S07cool() if (allocated(Gpot_cool)) deallocate(Gpot_cool) if (allocated(duFLD)) deallocate(duFLD) if (allocated(lambda_fld)) deallocate(lambda_fld) -! if (allocated(radprop_FLD)) deallocate(radprop_FLD) + if (allocated(urad_FLD)) deallocate(urad_FLD) close(iunitst) end subroutine finish_S07cool @@ -176,13 +176,11 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) c = kappa2 - m*OPTABLE(i,1,1) kappaPart = m*rhoi_ + c - !kappaPart = kappaPart*kappa_corr m = (kbar2 - kbar1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) c = kbar2 - m*OPTABLE(i,1,1) kappaBar = m*rhoi_ + c - !kappaBar = kappaBar*kappa_corr m = (Tpart2 - Tpart1)/(OPTABLE(i,1,1)-OPTABLE(i-1,1,1)) c = Tpart2 - m*OPTABLE(i,1,1) @@ -193,7 +191,6 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) c = gmw2 - m*OPTABLE(i,1,1) gmwi = m*rhoi_ + c - end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) @@ -245,18 +242,26 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) end subroutine getintenerg_opdep subroutine get_k_fld(rhoi,eni,i,ki,Ti) - use physcon, only:steboltz - use units, only:unit_density,unit_ergg,unit_opacity + use physcon, only:c,fourpi + use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code real,intent(in) :: rhoi,eni integer,intent(in) :: i real :: kappaBar,gmwi,kappaPart real,intent(out) :: ki,Ti - call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) - ki = 16d0 * steboltz * lambda_FLD(i) * Ti**3 /rhoi/kappaPart/unit_opacity - if (isnan(ki)) then - print *, "WARNING k isnan, lambda_FLDi,Ti,rhoi,kappaPart", & - lambda_FLD(i), Ti, rhoi,kappaPart + if (lambda_FLD(i) == 0d0) then + !print *, i, "lambda_FLD=0" + !stop + ki = 0. + else + call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) + kappaPart = kappaPart/unit_opacity + ! steboltz = 4pi/c * arad + ki = 16d0*(fourpi/c)*get_radconst_code()*lambda_FLD(i)*Ti**3 /rhoi/kappaPart + if (isnan(ki)) then + print *, "WARNING k isnan, lambda_FLDi,Ti,rhoi,kappaPart", & + lambda_FLD(i), Ti, rhoi,kappaPart + endif endif end subroutine get_k_fld diff --git a/src/main/force.F90 b/src/main/force.F90 index 56b08dd72..34b528379 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -903,7 +903,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt use eos, only:ieos,eos_is_non_ideal,gamma - use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,arad,getopac_opdep,get_k_fld + use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,getopac_opdep,get_k_fld #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -1033,7 +1033,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj real :: radPj,fgravxi,fgravyi,fgravzi,wkernj,wkerni,gradpx,gradpy,gradpz - real :: gradP_cooli,gradP_coolj,kfldi,kfldj,Ti,Tj,diffterm + real :: gradP_cooli,gradP_coolj,kfldi,kfldj,Ti,Tj,diffterm,gmwi ! unpack xi = xpartveci(ixi) @@ -1210,8 +1210,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g gradpy = 0d0 gradpz = 0d0 diffterm = 0d0 - call get_k_fld(rhoi,eni,i,kfldi,Ti) -! print *, "rhoi,eni,i,kfldi,Ti", rhoi,eni,i,kfldi,Ti + if (dt > 0d0) then + ! print *, "rhoi,eni,i,kfldi,Ti", rhoi,eni,i + call get_k_fld(rhoi,eni,i,kfldi,Ti) + endif endif loop_over_neighbours2: do n = 1,nneigh @@ -1752,8 +1754,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idendtdissi) = fsum(idendtdissi) + dendissterm if (icooling == 8) then Gpot_cool(i) = Gpot_cool(i) + pmassj*phii - if (doFLD) then -! print *, rhoj, "calling k_fld for j" + if (doFLD .and. dt > 0.) then + !print *, rhoj, "calling k_fld for j", j, enj call get_k_fld(rhoj,enj,j,kfldj,Tj) if ((kfldj + kfldi) == 0.) then diffterm = 0d0 diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index d8982d504..51dd0415b 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -1520,7 +1520,7 @@ end subroutine solve_quartic !--------------------------------------------------------- subroutine calc_lambda_hybrid(xyzh,utherm,rho) use io, only:fatal - use eos_stamatellos, only:getopac_opdep,arad,lambda_fld + use eos_stamatellos, only:getopac_opdep,lambda_fld use kernel, only:get_kernel,cnormk,radkern use units, only:unit_density,unit_ergg,unit_opacity,udist use part, only:massoftype,igas,gradh,hfact @@ -1607,19 +1607,19 @@ subroutine calc_lambda_hybrid(xyzh,utherm,rho) runiz = dz/rij call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj) - uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj)!*udist**3) ! why udist here? kern has h^-3 +! uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj)!*udist**3) ! why udist here? kern has h^-3 ! print *, 'got opdep j' dT4 = Ti**4d0 - Tj**4d0 - dradxi = dradxi + pmassj*arad*dT4*dWi*runix/rhoj - dradyi = dradyi + pmassj*arad*dT4*dWi*runiy/rhoj - dradzi = dradzi + pmassj*arad*dT4*dWi*runiz/rhoj + ! dradxi = dradxi + pmassj*arad*dT4*dWi*runix/rhoj + ! dradyi = dradyi + pmassj*arad*dT4*dWi*runiy/rhoj + ! dradzi = dradzi + pmassj*arad*dT4*dWi*runiz/rhoj enddo loop_over_neighbours ! print *, 'done neighbour loop for ', i,n if (.not. added_self) then ! print *, "Has not added self in lambda hybrid" - uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution +! uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution endif dradi = sqrt(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! magnitude diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 2e53ae392..d30f2f004 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -244,7 +244,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use krome_user, only:krome_nmols use part, only:gamma_chem,mu_chem,T_gas_cool #endif - use eos_stamatellos, only:gradP_cool,Gpot_cool + use eos_stamatellos, only:gradP_cool,Gpot_cool,doFLD,urad_FLD real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -408,6 +408,10 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,ierrs(13),index=iZ) endif endif + ! write urad to file (stamatellos + FLD) + if (icooling == 8 .and. doFLD) then + call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) + endif ! smoothing length written as real*4 to save disk space call write_array(1,xyzh,xyzh_label,1,npart,k,ipass,idump,nums,ierrs(14),use_kind=4,index=4) From 864b48d272567bfbfd8e164b1c6244c26dc0cc5f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 9 Jan 2024 10:21:07 +0000 Subject: [PATCH 085/182] Tidying code --- src/main/cooling_stamatellos.f90 | 16 ++++++++-------- src/main/dens.F90 | 1 - src/main/deriv.F90 | 2 +- src/main/eos_stamatellos.f90 | 13 +------------ 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index d18a0187a..75b0b2412 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -13,8 +13,8 @@ module cooling_stamatellos ! :Owner: Alison Young ! ! :Runtime parameters: -! - EOS_file : *File containing tabulated EOS values* -! - Lstar : *Luminosity of host star for calculating Tmin (Lsun)* +! - EOS_file : File containing tabulated EOS values +! - Lstar : Luminosity of host star for calculating Tmin (Lsun) ! ! :Dependencies: eos_stamatellos, infile_utils, io, part, physcon, units ! @@ -49,7 +49,8 @@ subroutine init_star() enddo isink_star = imin endif - if (isink_star > 0) print *, "Using sink no. ", isink_star, "as illuminating star." + if (isink_star > 0) print *, "Using sink no. ", isink_star,& + "at (xyz)",xyzmh_ptmass(1:3,isink_star),"as illuminating star." end subroutine init_star ! @@ -71,7 +72,6 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) poti = Gpot_cool(i) du_FLDi = duFLD(i) -! du_FLDi = 0d0 ! Tfloor is from input parameters and is background heating ! Stellar heating @@ -89,8 +89,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) - presi = kb_on_mh*rhoi*unit_density*Ti/gmwi - presi = presi/unit_pressure + presi = kb_on_mh*rhoi*unit_density*Ti/gmwi ! cgs + presi = presi/unit_pressure !code units select case (od_method) case (1) @@ -100,7 +100,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) case (2) ! Lombardi+ method of estimating the mean column density coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 - coldensi = coldensi *umass/udist/udist ! physical units + coldensi = coldensi * umass/udist/udist ! physical units end select tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units @@ -110,7 +110,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) if (doFLD) then ! include term from FLD - Teqi = (du_FLDi+dudti_sph) *tcool*unit_ergg/utime + Teqi = (du_FLDi + dudti_sph) *tcool*unit_ergg/utime ! physical units du_tot = dudti_sph + dudt_rad + du_FLDi else Teqi = dudti_sph*tcool*unit_ergg/utime diff --git a/src/main/dens.F90 b/src/main/dens.F90 index a6b891254..d0e39b353 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -1655,7 +1655,6 @@ subroutine store_results(icall,cell,getdv,getdb,realviscosity,stressmax,xyzh,& end subroutine store_results -! calc_lambda is called for each cell subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda,urad_FLD) use io, only:error use dim, only:maxp diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index b5d68e3ba..d630841c8 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -70,7 +70,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use cons2prim, only:cons2primall,cons2prim_everything,prim2consall use metric_tools, only:init_metric use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge - use options, only:implicit_radiation,implicit_radiation_store_drad,icooling + use options, only:implicit_radiation,implicit_radiation_store_drad integer, intent(in) :: icall integer, intent(inout) :: npart diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 5455fcaa5..f59c6d386 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -250,13 +250,11 @@ subroutine get_k_fld(rhoi,eni,i,ki,Ti) real,intent(out) :: ki,Ti if (lambda_FLD(i) == 0d0) then - !print *, i, "lambda_FLD=0" - !stop ki = 0. else call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) kappaPart = kappaPart/unit_opacity - ! steboltz = 4pi/c * arad + ! steboltz constant = 4pi/c * arad ki = 16d0*(fourpi/c)*get_radconst_code()*lambda_FLD(i)*Ti**3 /rhoi/kappaPart if (isnan(ki)) then print *, "WARNING k isnan, lambda_FLDi,Ti,rhoi,kappaPart", & @@ -265,15 +263,6 @@ subroutine get_k_fld(rhoi,eni,i,ki,Ti) endif end subroutine get_k_fld -!subroutine calc_FLD(xyzhi,duFLDi,pmassj,tempi,tempj,rhoi,rhoj,j,grkerni) - !real,intent(inout) :: duFLDi -! integer,intent(in) :: j -! real,intent(in) :: xyzh(4),pmassj,tempi,tempj,rhoi,rhoj,grkerni -! duFLDi = pmassj*arad*tempj**4d0*wkernj/rhoj - - !duFLDi = duFLDi -!end subroutine calc_FLD - end module eos_stamatellos From d70220f1b924698c563fd10b39d3e4c400bb2af7 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 10 Jan 2024 15:59:38 +0000 Subject: [PATCH 086/182] delete old file --- src/main/cooling_stamatellos.F90 | 222 ------------------------------- 1 file changed, 222 deletions(-) delete mode 100644 src/main/cooling_stamatellos.F90 diff --git a/src/main/cooling_stamatellos.F90 b/src/main/cooling_stamatellos.F90 deleted file mode 100644 index 3004bf952..000000000 --- a/src/main/cooling_stamatellos.F90 +++ /dev/null @@ -1,222 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module cooling_stamatellos -! -! Cooling method of Stamatellos et al. 2007 -! -! :References: Stamatellos et al. 2007 -! -! :Owner: Alison Young -! -! :Runtime parameters: -! - EOS_file : *File containing tabulated EOS values* -! - Lstar : *Luminosity of host star for calculating Tmin (Lsun)* -! -! :Dependencies: eos_stamatellos, infile_utils, io, part, physcon, units -! - - implicit none - real, public :: Lstar ! in units of L_sun - integer :: isink_star ! index of sink to use as illuminating star - integer :: od_method = 1 ! default = Stamatellos+ 2007 method - public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos - public :: init_star - -contains - -subroutine init_star() - use part, only:nptmass,xyzmh_ptmass - integer :: i,imin - real :: rsink2,rsink2min - - rsink2min = 0d0 - if (nptmass == 0 .or. Lstar == 0.0) then - isink_star = 0 ! no stellar heating - print *, "No stellar heating." - elseif (nptmass == 1) then - isink_star = 1 - else - do i=1,nptmass - rsink2 = xyzmh_ptmass(1,i)**2 + xyzmh_ptmass(2,i)**2 + xyzmh_ptmass(3,i)**2 - if (i==1 .or. (rsink2 < rsink2min) ) then - rsink2min = rsink2 - imin = i - endif - enddo - isink_star = imin - endif - if (isink_star > 0) print *, "Using sink no. ", isink_star, "as illuminating star." -end subroutine init_star - -! -! Do cooling calculation -! -subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) - use io, only:warning - use physcon, only:steboltz,pi,solarl,Rg - use units, only:umass,udist,unit_density,unit_ergg,utime,unit_opacity - use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,Gpot_cool,& - iunitst,duFLD,doFLD - use part, only:eos_vars,igasP,xyzmh_ptmass,igamma - real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt - integer,intent(in) :: i - real,intent(out) :: dudti_cool - real :: coldensi,kappaBari,kappaParti,ri2 - real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,du_tot - real :: tcool,ueqi,umini,tthermi,poti,presi,du_FLDi - - poti = Gpot_cool(i) - du_FLDi = duFLD(i) -! du_FLDi = 0d0 - -! Tfloor is from input parameters and is background heating -! Stellar heating - if (isink_star > 0 .and. Lstar > 0.d0) then - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & - + (yi-xyzmh_ptmass(2,isink_star))**2d0 & - + (zi-xyzmh_ptmass(3,isink_star))**2d0 - ri2 = ri2 *udist*udist -! Tfloor + stellar heating - Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2)) - else - Tmini4 = Tfloor**4d0 - endif - -! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& - Ti,gmwi) - presi = eos_vars(igasP,i) - - select case (od_method) - case (1) - 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+ method of estimating the mean column density - coldensi = 1.014d0 * presi /abs(gradP_cool(i))! 1.014d0*P/(-gradP/rho) Lombardi+2015 - coldensi = coldensi *umass/udist/udist ! physical units - end select - - tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units - dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units - -! calculate Teqi - if (od_method == 1 .or. od_method == 2) then - if (doFLD) then - ! include term from FLD - Teqi = (du_FLDi+dudti_sph)*(coldensi**2.d0*kappaBari/unit_opacity + (1.d0/(kappaParti/unit_opacity))) & - *unit_ergg/utime - du_tot = dudti_sph + dudt_rad + du_FLDi - else - Teqi = dudti_sph*(coldensi**2.d0*kappaBari/unit_opacity + (1.d0/(kappaParti/unit_opacity)))*unit_ergg/utime - du_tot = dudti_sph + dudt_rad - endif - 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg - endif - - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg - -! calculate thermalization timescale and -! internal energy update -> put in form where it'll work as dudtcool - ! select case (od_method) - !case (1) - if ((du_tot) == 0.d0) then - tthermi = 0d0 - else - tthermi = abs((ueqi - ui)/(du_tot)) - endif - if (tthermi == 0d0) then - dudti_cool = 0.d0 ! condition if denominator above is zero - else - dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units - endif -! case (2) -! if (abs(dudt_rad) > 0.d0) then -! tthermi = (umini - ui) / dudt_rad ! + tiny(dudt_rad)) -! dudti_cool = (ui*exp(-dt/tthermi) + umini*(1.d0-exp(-dt/tthermi)) -ui)/dt & -! + dudti_sph -! else ! ie Tmini == Ti -! dudti_cool = (umini - ui)/dt + dudti_sph ! ? CHECK THIS -! end if -! end select - - - if (isnan(dudti_cool)) then -! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "sph, rad, fld", dudti_sph,dudt_rad,du_FLDi - print *, "rhoi=",rhoi, "Ti=", Ti -! print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph -! print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini -! print *, "dudt_rad=", dudt_rad, "ueqi", ueqi -! call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) - stop - else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt - endif - -end subroutine cooling_S07 - - -subroutine write_options_cooling_stamatellos(iunit) - use infile_utils, only:write_inopt - use eos_stamatellos, only: eos_file - integer, intent(in) :: iunit - - !N.B. Tfloor handled in cooling.F90 - call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) - call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure',iunit) - call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) - -end subroutine write_options_cooling_stamatellos - -subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) - use io, only:warning,fatal - use eos_stamatellos, only: eos_file - character(len=*), intent(in) :: name,valstring - logical, intent(out) :: imatch,igotallstam - integer, intent(out) :: ierr - integer, save :: ngot = 0 - - - imatch = .true. - igotallstam = .false. ! cooling options are compulsory - select case(trim(name)) - case('Lstar') - read(valstring,*,iostat=ierr) Lstar - ngot = ngot + 1 - case('OD method') - read(valstring,*,iostat=ierr) od_method - if (od_method < 1 .or. od_method > 2) then - call fatal('cooling options','od_method must be 1 or 2',var='od_method',ival=od_method) - endif - ngot = ngot + 1 - case('EOS_file') - read(valstring,*,iostat=ierr) eos_file - ngot = ngot + 1 - case default - imatch = .false. - end select - if (od_method /= 1 .and. od_method /= 2) then - call warning('cooling_stamatellos','optical depth method unknown') - endif - - if (ngot >= 3) igotallstam = .true. - -end subroutine read_options_cooling_stamatellos - -end module cooling_stamatellos - From 725b2abbb0ecabaebbe8d8f038884c8963b7a288 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 10 Jan 2024 16:25:10 +0000 Subject: [PATCH 087/182] Tidying code --- src/main/dens.F90 | 18 +++- src/main/deriv.F90 | 203 ----------------------------------- src/main/eos_stamatellos.f90 | 2 - 3 files changed, 13 insertions(+), 210 deletions(-) diff --git a/src/main/dens.F90 b/src/main/dens.F90 index d0e39b353..dc7f30f99 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -348,7 +348,9 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + if (icooling==8 .and. doFLD) then + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + endif if (do_export) then call write_cell(stack_waiting,cell) else @@ -381,7 +383,9 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + if (icooling==8 .and. doFLD) then + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + endif if (do_export) then call write_cell(stack_waiting,cell) exit local_its @@ -451,7 +455,9 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol cell_xpos=cell%xpos,cell_xsizei=cell%xsizei,cell_rcuti=cell%rcuti) call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + if (icooling==8 .and. doFLD) then + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + endif remote_export = .false. remote_export(cell%owner+1) = .true. ! use remote_export array to send back to the owner @@ -512,7 +518,9 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol 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) - if (icooling==8 .and. doFLD) call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + if (icooling==8 .and. doFLD) then + call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) + endif call write_cell(stack_redo,cell) else @@ -1822,7 +1830,7 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra endif enddo over_parts - if (ngradh_err > 0) print *, "ngradh_errors = ", ngradh_err +! if (ngradh_err > 0) print *, "ngradh_errors = ", ngradh_err end subroutine calc_lambda_cell end module densityforce diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index d630841c8..f71fa5192 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -259,207 +259,4 @@ subroutine get_derivs_global(tused,dt_new,dt) end subroutine get_derivs_global -subroutine calc_lambda(npart,xyzh,vxyzu,rho,lambda) - use io, only:error - use dim, only:maxneigh - use part, only:get_partinfo,iamgas,iboundary,igas,maxphase,massoftype,iphase,gradh -#ifdef PERIODIC - use boundary, only:dxbound,dybound,dzbound -#endif - use kernel, only:radkern2,wkern,grkern,cnormk,get_kernel - use linklist, only:get_neighbour_list - use units, only:unit_density,unit_ergg,unit_opacity - use eos_stamatellos, only:getopac_opdep - - integer, intent(in) :: npart - real, intent(in) :: xyzh(:,:) - real, intent(in) :: vxyzu(:,:) - real, intent(in) :: rho(:) - real, intent(inout) :: lambda(:) - - integer, parameter :: maxcellcache = 10000 - logical :: iactivei,iamdusti,iamgasi,iactivej,iamgasj,iamdustj - integer :: iamtypei,i,j,n,iamtypej,mylistneigh(maxneigh),nneigh - integer(kind=1) :: iphasei,iphasej - real :: rhoi,rhoj,uradi,xi,yi,zi - real :: dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj,gammaj,wkerni,grkerni - real :: kappaBari,kappaParti,gmwi,dx,dy,dz,rij2,rij,rij1,Wi,dWi - real :: dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4 - real :: pmassi,pmassj,hi,hi21,hi1,q,q2,q2i,xj,yj,zj,qi,q2j - real :: hj21,hi4i,hj,hj1,hi41,hi31,gradhi - real :: xyzcache(maxcellcache,4) - logical :: added_self,ignoreself - integer :: success_count - ignoreself = .true. - - print *, "calculating lambda in deriv" - success_count = 0 -! loop over parts -!$omp parallel do schedule(runtime) default(none) & -!$omp shared(npart,xyzh,iphase,ignoreself,unit_opacity) & -!$omp shared(rho,lambda,massoftype,vxyzu,unit_density,unit_ergg,gradh) & -!$omp private(i,j,n,mylistneigh,nneigh,xyzcache,iphasei,iactivei) & -!$omp private(iamdusti,iamgasi,iactivej,iamgasj,iamdustj,iamtypei,iamtypej) & -!$omp private(rhoi,rhoj,uradi,xi,yi,zi,dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj) & -!$omp private(gammaj,wkerni,grkerni,kappaBari,kappaParti,gmwi,dx,dy,dz,rij2) & -!$omp private(rij,rij1,Wi,dWi,dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4) & -!$omp private(pmassi,pmassj,hi,hi21,hi1,q,q2,q2i,xj,yj,zj,qi,q2j,hj21,hi4i,hj,hj1) & -!$omp private(hi41,hi31,gradhi,added_self,success_count,iphasej) - - over_parts: do i = 1,npart - ! - !---loop of neighbours to calculate radiation energy density - ! - !check active and gas particle - call get_neighbour_list(i,mylistneigh,nneigh,xyzh,xyzcache,maxcellcache, & - getj=.true.) - iphasei = iphase(i) - call get_partinfo(iphasei,iactivei,iamgasi,iamdusti,iamtypei) - print *, i, iactivei,iamgasi,rho(i),"nneigh:",nneigh - if (.not. iactivei) cycle over_parts - if (iamtypei == iboundary) cycle over_parts - if (.not. iamgasi) cycle over_parts - - uradi = 0. - dradi = 0. - pmassi = massoftype(iamtypei) - rhoi = rho(i) - added_self = .false. - - call getopac_opdep(vxyzu(4,i)*unit_ergg,rhoi*unit_density,kappabari, & - kappaparti,ti,gmwi) - hi = xyzh(4,i) - hi1 = 1./hi - hi21 = hi1*hi1 - hi31 = hi1*hi21 - hi41 = hi21*hi21 - xi = xyzh(1,i) - yi = xyzh(2,i) - zi = xyzh(3,i) - ! - !--compute density and related quantities from the smoothing length - ! - pmassi = massoftype(iamtypei) - dradxi = 0.0 - dradyi = 0.0 - dradzi = 0.0 - - loop_over_neighbours: do n = 1,nneigh - j = mylistneigh(n) - if (j < 0) cycle loop_over_neighbours - iphasej = iphase(j) - call get_partinfo(iphasej,iactivej,iamgasj,iamdustj,iamtypej) - if (.not. iactivej) cycle loop_over_neighbours - if (iamtypej == iboundary) cycle loop_over_neighbours - if (.not. iamgasj) cycle loop_over_neighbours - if ((ignoreself) .and. (i==j)) cycle loop_over_neighbours - if (xyzh(4,j) < 0d0) cycle loop_over_neighbours - print *, "n=", n - if (n <= maxcellcache) then - ! positions from cache are already mod boundary - xj = xyzcache(n,1) - yj = xyzcache(n,2) - zj = xyzcache(n,3) - else - xj = xyzh(1,j) - yj = xyzh(2,j) - zj = xyzh(3,j) - endif - - dx = xi - xj - dy = yi - yj - dz = zi - zj -#ifdef PERIODIC - if (abs(dx) > 0.5*dxbound) dx = dx - dxbound*SIGN(1.0,dx) - if (abs(dy) > 0.5*dybound) dy = dy - dybound*SIGN(1.0,dy) - if (abs(dz) > 0.5*dzbound) dz = dz - dzbound*SIGN(1.0,dz) -#endif - rij2 = dx*dx + dy*dy + dz*dz + TINY(0.) - rij = SQRT(rij2) - q2i = rij2*hi21 - qi = SQRT(q2i) - - !--hj is in the cell cache but not in the neighbour cache - ! as not accessed during the density summation - hj1 = 1./xyzh(4,j) - hj = 1./hj1 - hj21 = hj1*hj1 - q2j = rij2*hj21 - is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then - call get_partinfo(iphase(j),iactivej,iamgasj,iamdustj,iamtypej) - if (.not.iamgasj) cycle loop_over_neighbours - if (.not.iactivej) cycle loop_over_neighbours - !Get kernel quantities - if (gradh(1,i) > 0.) then - gradhi = gradh(1,i) - else - !call error('force','stored gradh is zero, resetting to 1') - gradhi = 1. - endif - !print *, "q2i,q2j", q2i,q2j - call get_kernel(q2,q,wkerni,grkerni) - Wi = wkerni*cnormk*hi21*hi1 - dWi = grkerni*cnormk*hi21*hi21*gradh(1,i) - pmassj = massoftype(iamtypej) - rhoj = rho(j) - if (rhoj < tiny(rhoj)) cycle loop_over_neighbours - call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,kappaBarj, & - kappaPartj,Tj,gmwj) -! uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj) - if (uradi > 1e40) then - print *, "Urad huge- i,j,pmassj,Tj,Wi,hi,rhoj:", i,j,pmassj,Tj,Wi,1/hi1,rhoj,xj,yj,zj - print *, "wkerni,cnormk,hi21,hi1", wkerni,cnormk,hi21,hi1,tiny(rhoj) - print *, "max min rho", maxval(rho), minval(rho) - stop - endif - ! unit vector components - runix = dx/rij - runiy = dy/rij - runiz = dz/rij - - dT4 = Ti**4d0 - Tj**4d0 -! dradxi = dradxi + arad*pmassj*dT4*dWi*runix/rhoj -! dradyi = dradyi + arad*pmassj*dT4*dWi*runiy/rhoj -! dradzi = dradzi + arad*pmassj*dT4*dWi*runiz/rhoj - endif is_sph_neighbour - - enddo loop_over_neighbours - - if (.not. added_self) then - ! print *, "Has not added self in lambda hybrid -! uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution - endif - ! urad = cnormk*uradi + arad*Ti**4.0d0 - dradi = cnormk*SQRT(dradxi**2.0d0 + dradyi**2.0d0 + dradzi**2.0d0) - !Now calculate flux limiter coefficients - !Calculate in cgs (converted to code units in forcei) - - if ((dradi.eq.0.0d0).or.(uradi.eq.0.0d0)) then - R_rad = 0.0d0 - else - R_rad = dradi/(uradi*rhoi*kappaParti/unit_opacity) - endif - - lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) - if (isnan(lambda(i))) then - print *, "lambda isnan when calculated. i, R_Rad, uradi,dradi,rhoi,kappaParti, Ti", & - i,R_Rad,uradi,dradi,rhoi,kappaParti,Ti - elseif (lambda(i) < tiny(lambda(i))) then - print *, "lambda is 0,i, rhoi, uradi", i, rhoi, uradi - stop - else -!$omp critical - success_count = success_count + 1 -!$omp end critical - endif - enddo over_parts -!$omp end parallel do - print *, "success =", success_count - do i=1,npart - if (lambda(i) < tiny(lambda(i))) then - print *, "lambda is 0,i, rhoi, uradi", i, rhoi, uradi,kappaParti - endif - enddo -end subroutine calc_lambda - end module deriv diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index f59c6d386..a5586f7be 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -82,8 +82,6 @@ subroutine read_optab(eos_file,ierr) enddo enddo ! print *, 'nx,ny=', nx, ny -! print *, "Optable first row:" -! print *, (OPTABLE(1,1,i),i=1, 6) end subroutine read_optab ! From d8045dbe604f470059c5e2a6096af452dad259d9 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 10 Jan 2024 16:29:23 +0000 Subject: [PATCH 088/182] adding Stamatellos/Lombardi opacity --- src/main/radiation_utils.f90 | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 1465081a5..100c387d8 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -411,13 +411,15 @@ end function get_kappa ! calculate opacities !+ !-------------------------------------------------------------------- -subroutine get_opacity(opacity_type,density,temperature,kappa) +subroutine get_opacity(opacity_type,density,temperature,kappa,u) + use eos_stamatellos, only:getopac_opdep use mesa_microphysics, only:get_kappa_mesa - use units, only:unit_density,unit_opacity + use units, only:unit_density,unit_opacity,unit_ergg real, intent(in) :: density, temperature real, intent(out) :: kappa integer, intent(in) :: opacity_type - real :: kapt,kapr,rho_cgs + real, intent(in), optional :: u + real :: kapt,kapr,rho_cgs,Ti,gmwi,gammai,kapBar,kappaPart select case(opacity_type) case(1) @@ -433,6 +435,12 @@ subroutine get_opacity(opacity_type,density,temperature,kappa) ! constant opacity ! kappa = kappa_cgs/unit_opacity + case(3) + ! + ! opacity for Stamatellos/Lombardi EOS + ! + call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi) + kappa = kappaPart/unit_opacity case default ! From a5c16dcb714ca03df47254c051c76456a4740837 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 11 Jan 2024 11:36:39 +0000 Subject: [PATCH 089/182] fixes after merge --- src/main/cons2prim.f90 | 6 +----- src/main/cooling.F90 | 4 +--- src/main/force.F90 | 4 +--- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 6a8f87caf..128aa6d18 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -293,11 +293,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& ! ! Get the opacity from the density and temperature if required ! - if (iopacity_type == 3) then - call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i),u=vxyzu(4,i)) - elseif (iopacity_type > 0) then - call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i)) - endif + if (iopacity_type > 0) call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i)) endif ! ! Get radiation pressure from the radiation energy, i.e. P = 1/3 E if optically thick diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 7fe5f8542..8684182cb 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -95,9 +95,7 @@ subroutine init_cooling(id,master,iprint,ierr) 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) - if (do_radiation) then - call fatal('cooling','Do radiation was switched on!') - endif + if (do_radiation) then call fatal('cooling','Do radiation was switched on!') call init_star() case(6) call init_cooling_KI02(ierr) diff --git a/src/main/force.F90 b/src/main/force.F90 index 34b528379..0591bb11c 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1769,12 +1769,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif duFLD(i) = duFLD(i) + diffterm if (isnan(duFLD(i))) then - print *, "FLD is nan for particle i=, j = ", i,j print *, "rhoi,rhoj,rij2,diffterm",rhoi,rhoj,rij2,diffterm print *, "kfldi, kfldj, Ti,Tj", kfldi,kfldj, Ti,Tj - stop + call fatal('force','duFLD is nan',i,var='duFLD',val=duFLD(i)) endif - ! call calc_FLD(duFLD(i),i,j,q2j,qj,hi121,hi1,pmassj,eos_vars(itemp,j),eos_vars(itemp,j),rhoj) endif endif endif From 28bc64f8d8674545adc41665bccad366a2405dd5 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 11 Jan 2024 11:40:41 +0000 Subject: [PATCH 090/182] bug fix --- src/main/cooling.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 8684182cb..c9ffd8a27 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -95,7 +95,7 @@ subroutine init_cooling(id,master,iprint,ierr) 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) - if (do_radiation) then call fatal('cooling','Do radiation was switched on!') + if (do_radiation) call fatal('cooling','Do radiation was switched on!') call init_star() case(6) call init_cooling_KI02(ierr) From 856101516845b5e2654970266fddf9bead837a2c Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 12 Jan 2024 14:41:59 +0000 Subject: [PATCH 091/182] bug fix --- src/main/force.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 0591bb11c..d5284b8b9 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -932,6 +932,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g #endif use utils_gr, only:get_bigv use radiation_utils, only:get_rad_R + use io, only:fatal integer, intent(in) :: i logical, intent(in) :: iamgasi,iamdusti real, intent(in) :: xpartveci(:) @@ -1771,7 +1772,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (isnan(duFLD(i))) then print *, "rhoi,rhoj,rij2,diffterm",rhoi,rhoj,rij2,diffterm print *, "kfldi, kfldj, Ti,Tj", kfldi,kfldj, Ti,Tj - call fatal('force','duFLD is nan',i,var='duFLD',val=duFLD(i)) + call fatal('force','duFLD is nan',i=i,var='duFLD',val=duFLD(i)) endif endif endif From f72bbbf14ddff68551e78ff8095d5378df8bf52f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 12 Jan 2024 15:29:38 +0000 Subject: [PATCH 092/182] Tidying after merge --- build/Makefile | 3 - src/main/force.F90 | 4 +- src/main/radiation_implicit.f90 | 125 +-------------------------- src/main/radiation_utils.f90 | 2 +- src/main/readwrite_dumps_fortran.F90 | 10 +-- src/main/step_leapfrog.F90 | 2 +- 6 files changed, 9 insertions(+), 137 deletions(-) diff --git a/build/Makefile b/build/Makefile index 2191eeff7..ecc33ca33 100644 --- a/build/Makefile +++ b/build/Makefile @@ -514,9 +514,6 @@ SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.F90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 - - ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.F90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 else diff --git a/src/main/force.F90 b/src/main/force.F90 index d5284b8b9..dd73c722d 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1212,7 +1212,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g gradpz = 0d0 diffterm = 0d0 if (dt > 0d0) then - ! print *, "rhoi,eni,i,kfldi,Ti", rhoi,eni,i call get_k_fld(rhoi,eni,i,kfldi,Ti) endif endif @@ -1756,7 +1755,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (icooling == 8) then Gpot_cool(i) = Gpot_cool(i) + pmassj*phii if (doFLD .and. dt > 0.) then - !print *, rhoj, "calling k_fld for j", j, enj call get_k_fld(rhoj,enj,j,kfldj,Tj) if ((kfldj + kfldi) == 0.) then diffterm = 0d0 @@ -1772,7 +1770,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (isnan(duFLD(i))) then print *, "rhoi,rhoj,rij2,diffterm",rhoi,rhoj,rij2,diffterm print *, "kfldi, kfldj, Ti,Tj", kfldi,kfldj, Ti,Tj - call fatal('force','duFLD is nan',i=i,var='duFLD',val=duFLD(i)) + call fatal('force','duFLD is nan',i=i,var='duFLD',val=duFLD(i)) endif endif endif diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index 51dd0415b..3cabc2937 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -46,7 +46,7 @@ module radiation_implicit character(len=*), parameter :: label = 'radiation_implicit' private - public :: do_radiation_implicit,ierr_failed_to_converge,calc_lambda_hybrid + public :: do_radiation_implicit,ierr_failed_to_converge contains @@ -1511,128 +1511,5 @@ subroutine solve_quartic(u1term,u0term,uold,soln,moresweep,ierr) call quarticsolve(a,uold,soln,moresweep,ierr) end subroutine solve_quartic - -!--------------------------------------------------------- -!+ -! Calculate the radiation energy density and flux from -! temperature for hybrid cooling -!+ -!--------------------------------------------------------- - subroutine calc_lambda_hybrid(xyzh,utherm,rho) - use io, only:fatal - use eos_stamatellos, only:getopac_opdep,lambda_fld - use kernel, only:get_kernel,cnormk,radkern - use units, only:unit_density,unit_ergg,unit_opacity,udist - use part, only:massoftype,igas,gradh,hfact - use physcon, only:pi - - real, intent(in) :: xyzh(:,:),utherm(:),rho(:) - integer,allocatable :: ivar(:,:),ijvar(:) - integer :: ncompact,npart,icompactmax,ierr,ncompactlocal - integer :: i,j,k,n,icompact,nneigh_average - real :: rhoi,rhoj - real :: uradi,dradi,Ti,Tj,kappaBarj,kappaPartj,gmwj,gammaj,wkerni,grkerni - real :: kappaBari,kappaParti,gmwi,dx,dy,dz,rij2,rij,rij1,Wi,dWi - real :: dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,dT4 - real :: pmassj,hi,hi21,hi1,q,q2 - logical :: added_self - - npart = size(xyzh(1,:)) - nneigh_average = int(4./3.*pi*(radkern*hfact)**3) + 1 - icompactmax = int(1.2*nneigh_average*npart) - allocate(ivar(3,npart),stat=ierr) - if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for ivar') - allocate(ijvar(icompactmax),stat=ierr) - if (ierr/=0) call fatal('get_diffusion_term_only','cannot allocate memory for ijvar') - - call get_compacted_neighbour_list(xyzh,ivar,ijvar,ncompact,ncompactlocal) - ! check for errors - if (ncompact <= 0 .or. ncompactlocal <= 0) then - call fatal('radiation_implicit','empty neighbour list - need to call set_linklist first?') - endif - - pmassj = massoftype(igas) - !$omp parallel do default(none)& - !$omp shared(ivar,ijvar,ncompact,unit_opacity,gradh,xyzh,unit_density,unit_ergg)& - !$omp shared(rho,utherm,pmassj,udist,lambda_fld)& - !$omp private(i,j,k,n,rhoi,rhoj,icompact,uradi,dradi,Ti,Tj,wkerni,grkerni,dT4)& - !$omp private(kappaBarj,kappaPartj,gmwj,gammaj,dx,dy,dz,rij,rij2,rij1,Wi,dWi)& - !$omp private(dradxi,dradyi,dradzi,runix,runiy,runiz,R_rad,hi,hi21,hi1,q,q2)& - !$omp private(kappaBari,kappaParti,gmwi,added_self) - loop_over_compact_list: do n = 1,ncompact - i = ivar(3,n) - ! print *, n,ncompact,utherm(i) - uradi = 0. - dradi = 0. - dradxi = 0. - dradyi = 0. - dradzi = 0. - rhoi = rho(i) - added_self = .false. - hi = xyzh(4,i) - hi21 = 1./(hi*hi) - hi1 = 1./hi - - call getopac_opdep(utherm(i)*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,Ti,gmwi) - - loop_over_neighbours: do k = 1,ivar(1,n) - icompact = ivar(2,n) + k - ! print *, 'icompact',icompact - j = ijvar(icompact) - if (i == j) added_self = .true. - ! print *,'j',j - rhoj = rho(j) - ! print *, 'rhoj',rhoj - ! print *, 'xyzh(1,i)', xyzh(1,i) - ! print *, ' xyzh(1,j)', xyzh(1,j) - dx = xyzh(1,i) - xyzh(1,j) - ! print *, 'dx', dx - dy = xyzh(2,i) - xyzh(2,j) - dz = xyzh(3,i) - xyzh(3,j) - - rij2 = dx*dx + dy*dy + dz*dz + tiny(0.) - rij = sqrt(rij2) - rij1 = 1./rij - q = rij/hi - q2 = rij2*hi21 - - call get_kernel(q2,q,wkerni,grkerni) - !print *, 'got kernel' - Wi = wkerni*cnormk*hi21*hi1 - dWi = grkerni*cnormk*hi21*hi21*gradh(1,i) - - ! unit vector components - runix = dx/rij - runiy = dy/rij - runiz = dz/rij - - call getopac_opdep(utherm(j)*unit_ergg,rhoj*unit_density,kappaBarj,kappaPartj,Tj,gmwj) -! uradi = uradi + arad*pmassj*Tj**4.0d0*Wi/(rhoj)!*udist**3) ! why udist here? kern has h^-3 - ! print *, 'got opdep j' - - dT4 = Ti**4d0 - Tj**4d0 - ! dradxi = dradxi + pmassj*arad*dT4*dWi*runix/rhoj - ! dradyi = dradyi + pmassj*arad*dT4*dWi*runiy/rhoj - ! dradzi = dradzi + pmassj*arad*dT4*dWi*runiz/rhoj - enddo loop_over_neighbours - - ! print *, 'done neighbour loop for ', i,n - if (.not. added_self) then -! print *, "Has not added self in lambda hybrid" -! uradi = uradi + cnormk*hi1*hi21*pmassj*arad*Ti**4d0/rhoi ! add self contribution - endif - - dradi = sqrt(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! magnitude - if ( (uradi == 0d0) .or. (dradi == 0d0) ) then - R_rad = 0d0 - else - R_rad = dradi / (uradi*rhoi*kappaParti/unit_opacity) !code units - endif - - lambda_fld(i) = (2d0 + R_rad) / (6d0 + 3d0*R_rad + R_rad*R_rad) - enddo loop_over_compact_list - !$omp end parallel do - - end subroutine calc_lambda_hybrid end module radiation_implicit diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 0aa06a6fe..dd701c892 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -417,7 +417,7 @@ subroutine get_opacity(opacity_type,density,temperature,kappa) real, intent(in) :: density, temperature real, intent(out) :: kappa integer, intent(in) :: opacity_type - real :: kapt,kapr,rho_cgs,Ti,gmwi,gammai,kapBar,kappaPart + real :: kapt,kapr,rho_cgs select case(opacity_type) case(1) diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index d30f2f004..28362db81 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -309,10 +309,10 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ! masterthread: if (id==master) then ! open(unit=10,file=trim(dumpfile)//'info.dat') - ! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' + ! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool' ! do i=1,nparttot ! write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& - ! gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) + ! gradP_cool(i) ! enddo ! close(10) if (idtmax_frac==0) then @@ -409,9 +409,9 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) endif endif ! write urad to file (stamatellos + FLD) - if (icooling == 8 .and. doFLD) then - call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) - endif +! if (icooling == 8 .and. doFLD) then +! call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) +! endif ! smoothing length written as real*4 to save disk space call write_array(1,xyzh,xyzh_label,1,npart,k,ipass,idump,nums,ierrs(14),use_kind=4,index=4) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 8b98f287e..8679970a7 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -1,4 +1,4 @@ - !--------------------------------------------------------------------------! +!--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! From 494983bedc703f082f022526448078e441364260 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 23 Jan 2024 10:33:07 +0000 Subject: [PATCH 093/182] Added Modified Lombardi cooling method --- src/main/cooling_stamatellos.f90 | 40 ++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 8033904e9..eb84fc4a8 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -30,13 +30,16 @@ module cooling_stamatellos subroutine init_star() use part, only:nptmass,xyzmh_ptmass + use io, only:fatal integer :: i,imin real :: rsink2,rsink2min rsink2min = 0d0 - if (nptmass == 0 .or. Lstar == 0.0) then + if (nptmass == 0 .or. ( Lstar == 0.0 .and. od_method /=4)) then isink_star = 0 ! no stellar heating print *, "No stellar heating." + elseif (od_method ==4 .and. nptmass == 0) then + call fatal('init star','od_method = 4 but there is no sink!',var='nptmass',ival=nptmass) elseif (nptmass == 1) then isink_star = 1 else @@ -58,7 +61,7 @@ end subroutine init_star ! subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning - use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh + 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 @@ -69,20 +72,21 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,Hstam,HLom,du_tot + real :: cs2,Om2,Q3D,Hmod2 real :: tcool,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi poti = Gpot_cool(i) du_FLDi = duFLD(i) + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + + (zi-xyzmh_ptmass(3,isink_star))**2d0 + ! Tfloor is from input parameters and is background heating ! Stellar heating if (isink_star > 0 .and. Lstar > 0.d0) then - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & - + (yi-xyzmh_ptmass(2,isink_star))**2d0 & - + (zi-xyzmh_ptmass(3,isink_star))**2d0 - ri2 = ri2 *udist*udist ! Tfloor + stellar heating - Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2)) + Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) else Tmini4 = Tfloor**4d0 endif @@ -113,9 +117,18 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) ! Combined method HStam = sqrt(abs(poti*rhoi)/4.0d0/pi)*0.368d0/rhoi HLom = 1.014d0*presi/abs(gradP_cool(i))/rhoi - Hcomb = 1.0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/HStam)**2.0d0) + Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/HStam)**2.0d0) coldensi = Hcomb*rhoi - coldensi = coldensi*umass/udist/udist + coldensi = coldensi*umass/udist/udist ! physical units +case (4) +! Modified Lombardi method + HLom = presi/abs(gradP_cool(i))/rhoi + cs2 = presi/rhoi + Om2 = xyzmh_ptmass(4,isink_star)/(ri2**(1.5)) !NB we are using spherical radius here + Q3D = Om2/(4.d0*pi*rhoi) + Hmod2 = (cs2/Om2) * piontwo /(1d0 + (1d0/(rpiontwo*Q3D))) + Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/Hmod2)) + coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units end select tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units @@ -180,7 +193,7 @@ subroutine write_options_cooling_stamatellos(iunit) !N.B. Tfloor handled in cooling.F90 call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) - call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure (3) combined',iunit) + call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) Stamatellos(2) Lombardi (3) combined (4) modified Lombardi',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) end subroutine write_options_cooling_stamatellos @@ -202,8 +215,8 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie ngot = ngot + 1 case('OD method') read(valstring,*,iostat=ierr) od_method - if (od_method < 1 .or. od_method > 3) then - call fatal('cooling options','od_method must be 1, 2 or 3',var='od_method',ival=od_method) + if (od_method < 1 .or. od_method > 4) then + call fatal('cooling options','od_method must be 1, 2, 3 or 4',var='od_method',ival=od_method) endif ngot = ngot + 1 case('EOS_file') @@ -212,9 +225,6 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie case default imatch = .false. end select - if (od_method /= 1 .and. od_method /= 2 .and. od_method /= 3) then - call warning('cooling_stamatellos','optical depth method unknown') - endif if (ngot >= 3) igotallstam = .true. From 6a5ccc527dbe4a5a4b0d7d6e0f4fdf00f4e186e2 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 29 Jan 2024 16:50:24 +0000 Subject: [PATCH 094/182] Added FLD as a runtime option for icooling=8 --- src/main/cooling.F90 | 2 +- src/main/cooling_stamatellos.f90 | 19 +++++++++++++++---- src/main/dens.F90 | 2 +- src/main/eos_stamatellos.f90 | 8 ++++++-- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index c9ffd8a27..6a77b5dd1 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -212,7 +212,7 @@ subroutine write_options_cooling(iunit) if (icooling > 0) call write_options_cooling_ism(iunit) else call write_inopt(icooling,'icooling','cooling function (0=off, 1=cooling library (step), 2=cooling library (force),'// & - '3=Gammie, 5,6=KI02, 7=powerlaw, 8=stamatellos)',iunit) + '3=Gammie, 5,6=KI02, 7=powerlaw, 8=polytropic approx)',iunit) select case(icooling) case(0,4,5,6) ! do nothing diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index eb84fc4a8..2422e363e 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -23,6 +23,7 @@ module cooling_stamatellos real, public :: Lstar ! in units of L_sun integer :: isink_star ! index of sink to use as illuminating star integer :: od_method = 1 ! default = Stamatellos+ 2007 method + integer :: fld_opt = 1 ! by default FLD is switched on public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star @@ -193,25 +194,26 @@ subroutine write_options_cooling_stamatellos(iunit) !N.B. Tfloor handled in cooling.F90 call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) - call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) Stamatellos(2) Lombardi (3) combined (4) modified Lombardi',iunit) + call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) Stamatellos (2) Lombardi (3) combined (4) modified Lombardi',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) + call write_inopt(FLD_opt,'do FLD','Do FLD? (1) yes (0) no',iunit) end subroutine write_options_cooling_stamatellos subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) use io, only:warning,fatal - use eos_stamatellos, only: eos_file + use eos_stamatellos, only: eos_file,doFLD character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallstam integer, intent(out) :: ierr integer, save :: ngot = 0 - imatch = .true. igotallstam = .false. ! cooling options are compulsory select case(trim(name)) case('Lstar') read(valstring,*,iostat=ierr) Lstar + if (Lstar < 0.) call fatal('Lstar','Luminosity cannot be negative') ngot = ngot + 1 case('OD method') read(valstring,*,iostat=ierr) od_method @@ -222,11 +224,20 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie case('EOS_file') read(valstring,*,iostat=ierr) eos_file ngot = ngot + 1 + case('do FLD') + read(valstring,*,iostat=ierr) FLD_opt + if (FLD_opt < 0) call fatal('FLD_opt','FLD option out of range') + if (FLD_opt == 0) then + doFLD = .false. + elseif (FLD_opt == 1) then + doFLD = .true. + endif + ngot = ngot + 1 case default imatch = .false. end select - if (ngot >= 3) igotallstam = .true. + if (ngot >= 4) igotallstam = .true. end subroutine read_options_cooling_stamatellos diff --git a/src/main/dens.F90 b/src/main/dens.F90 index dc7f30f99..43a4995a0 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -268,7 +268,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol !$omp shared(thread_complete) & !$omp shared(ncomplete_mpi) & !$omp shared(icooling) & -!$omp shared(lambda_FLD,urad_FLD) & +!$omp shared(lambda_FLD,urad_FLD,doFLD) & !$omp reduction(+:nlocal) & !$omp private(do_export) & !$omp private(j) & diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 63d8afd90..a9bcefde0 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -21,7 +21,7 @@ module eos_stamatellos real,allocatable,public :: optable(:,:,:) real,allocatable,public :: Gpot_cool(:),duFLD(:),gradP_cool(:),lambda_FLD(:),urad_FLD(:) !gradP_cool=gradP/rho character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file - logical,parameter,public :: doFLD = .True. + logical,public :: doFLD = .True. integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in @@ -40,7 +40,11 @@ subroutine init_S07cool() allocate(urad_FLD(npart)) urad_FLD(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') - if (doFLD) print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" + if (doFLD) then + print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" + else + print *, "NOT using FLD. Using cooling only" + endif end subroutine init_S07cool subroutine finish_S07cool() From cc0567e6cd2f12ab012327364fbc34ed5b4840df Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 30 Jan 2024 15:37:53 +0000 Subject: [PATCH 095/182] Rearranged Modified Lombardi equation --- src/main/cooling_stamatellos.f90 | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 2422e363e..428b3b0b9 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -39,8 +39,8 @@ subroutine init_star() if (nptmass == 0 .or. ( Lstar == 0.0 .and. od_method /=4)) then isink_star = 0 ! no stellar heating print *, "No stellar heating." - elseif (od_method ==4 .and. nptmass == 0) then - call fatal('init star','od_method = 4 but there is no sink!',var='nptmass',ival=nptmass) + elseif (od_method == 4 .and. nptmass == 0) then + print *, "NO central star." elseif (nptmass == 1) then isink_star = 1 else @@ -79,9 +79,11 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) poti = Gpot_cool(i) du_FLDi = duFLD(i) - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & - + (yi-xyzmh_ptmass(2,isink_star))**2d0 & - + (zi-xyzmh_ptmass(3,isink_star))**2d0 + if (isink_star > 0) then + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + + (zi-xyzmh_ptmass(3,isink_star))**2d0 + endif ! Tfloor is from input parameters and is background heating ! Stellar heating @@ -121,13 +123,18 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) 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) + case (4) ! Modified Lombardi method HLom = presi/abs(gradP_cool(i))/rhoi cs2 = presi/rhoi - Om2 = xyzmh_ptmass(4,isink_star)/(ri2**(1.5)) !NB we are using spherical radius here - Q3D = Om2/(4.d0*pi*rhoi) - Hmod2 = (cs2/Om2) * piontwo /(1d0 + (1d0/(rpiontwo*Q3D))) + 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) + !Q3D = Om2/(4.d0*pi*rhoi) + !Hmod2 = (cs2/Om2) * piontwo /(1d0 + (1d0/(rpiontwo*Q3D))) Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/Hmod2)) coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units end select From 1e9a9f9c0ee11a69cfc6760d7dc816294c792525 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 2 Feb 2024 12:21:55 +0000 Subject: [PATCH 096/182] Bug fix for Modified Lombardi cooling --- src/main/cooling_stamatellos.f90 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 428b3b0b9..ec7d6bf14 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -36,11 +36,12 @@ subroutine init_star() real :: rsink2,rsink2min rsink2min = 0d0 - if (nptmass == 0 .or. ( Lstar == 0.0 .and. od_method /=4)) then - isink_star = 0 ! no stellar heating + + isink_star = 0 + if (od_method == 4 .and. nptmass == 0) then + print *, "NO central star and using od_method = 4" + elseif (nptmass == 0) then print *, "No stellar heating." - elseif (od_method == 4 .and. nptmass == 0) then - print *, "NO central star." elseif (nptmass == 1) then isink_star = 1 else @@ -54,7 +55,7 @@ subroutine init_star() isink_star = imin endif if (isink_star > 0) print *, "Using sink no. ", isink_star,& - "at (xyz)",xyzmh_ptmass(1:3,isink_star),"as illuminating star." + "at (xyz)",xyzmh_ptmass(1:3,isink_star)!"as illuminating star." end subroutine init_star ! From 4f9047525d2c6e2c4e34028c0bb57072c40d8c3e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 21 Feb 2024 04:02:40 +0000 Subject: [PATCH 097/182] Adjust stellar heating estimate in cooling_stamatellos.f90 and write extra quantities to dump files --- src/main/cooling_stamatellos.f90 | 36 +++++++++++++----------- src/main/readwrite_dumps_fortran.F90 | 8 ++++-- src/utils/moddump_sphNG2phantom_disc.f90 | 6 ++-- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index ec7d6bf14..a9aaedf31 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -22,7 +22,7 @@ module cooling_stamatellos implicit none real, public :: Lstar ! in units of L_sun integer :: isink_star ! index of sink to use as illuminating star - integer :: od_method = 1 ! default = Stamatellos+ 2007 method + integer :: od_method = 4 ! default = Stamatellos+ 2007 method integer :: fld_opt = 1 ! by default FLD is switched on public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star @@ -66,7 +66,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) 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 + duFLD,doFLD,ttherm_store,teqi_store,floor_energy use part, only:xyzmh_ptmass real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt @@ -74,7 +74,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,Hstam,HLom,du_tot - real :: cs2,Om2,Q3D,Hmod2 + real :: cs2,Om2,Hmod2 real :: tcool,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi poti = Gpot_cool(i) @@ -86,15 +86,6 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) + (zi-xyzmh_ptmass(3,isink_star))**2d0 endif -! Tfloor is from input parameters and is background heating -! Stellar heating - if (isink_star > 0 .and. Lstar > 0.d0) then -! Tfloor + stellar heating - Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) - else - Tmini4 = Tfloor**4d0 - endif - ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) @@ -140,6 +131,15 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units end select +! Tfloor is from input parameters and is background heating +! Stellar heating + if (isink_star > 0 .and. Lstar > 0.d0) then +! Tfloor + stellar heating + Tmini4 = Tfloor**4d0 + exp(-coldensi*kappaBari)*(Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) + else + Tmini4 = Tfloor**4d0 + endif + tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units @@ -154,12 +154,12 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini4 - if (Teqi < Tmini4) then - Teqi = Tmini4**(1.0/4.0) - else +! if (Teqi < Tmini4) then +! Teqi = Tmini4**(1.0/4.0) +! else Teqi = Teqi**(1.0/4.0) - endif - +! endif + teqi_store(i) = Teqi call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg @@ -174,6 +174,8 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) tthermi = abs((ueqi - ui)/(du_tot)) endif + ttherm_store(i) = tthermi + if (tthermi == 0d0) then dudti_cool = 0.d0 ! condition if denominator above is zero else diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 28362db81..b8f1bff67 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -244,7 +244,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use krome_user, only:krome_nmols use part, only:gamma_chem,mu_chem,T_gas_cool #endif - use eos_stamatellos, only:gradP_cool,Gpot_cool,doFLD,urad_FLD + use eos_stamatellos, only:gradP_cool,doFLD,urad_FLD,ttherm_store,teqi_store real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -409,9 +409,11 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) endif endif ! write urad to file (stamatellos + FLD) -! if (icooling == 8 .and. doFLD) then + if (icooling == 8) then ! .and. doFLD) then ! call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) -! endif + call write_array(1,teqi_store,'teqi',npart,k,ipass,idump,nums,ierrs(13)) + call write_array(1,ttherm_store,'ttherm',npart,k,ipass,idump,nums,ierrs(13)) + endif ! smoothing length written as real*4 to save disk space call write_array(1,xyzh,xyzh_label,1,npart,k,ipass,idump,nums,ierrs(14),use_kind=4,index=4) diff --git a/src/utils/moddump_sphNG2phantom_disc.f90 b/src/utils/moddump_sphNG2phantom_disc.f90 index 318bac487..b2db777da 100644 --- a/src/utils/moddump_sphNG2phantom_disc.f90 +++ b/src/utils/moddump_sphNG2phantom_disc.f90 @@ -32,7 +32,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) use prompting, only:prompt use physcon, only:au,gg use readwrite_dumps_fortran, only:dt_read_in_fortran - use timestep, only:time,dt,dtmax_max,dtmax_min,dtmax0 + use timestep, only:time,dt,dtmax_max,dtmax_min use centreofmass, only: reset_centreofmass integer, intent(inout) :: npart integer, intent(inout) :: npartoftype(:) @@ -97,7 +97,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) enddo close(iunit) - print *, 'dtmax0, dtmax_max,dtmax_min',dtmax0,dtmax_max,dtmax_min + print *, 'dtmax_max,dtmax_min',dtmax_max,dtmax_min newutime = sqrt(au**3/(gg*umass)) print *, "newutime/old", newutime/utime time = time * utime / newutime @@ -177,7 +177,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) 'nptmass:', nptmass print *, 'gamma=', gamma print *, 'Timestep info:' - print *, 'dtmax0, dtmax_max,dtmax_min', dtmax0,dtmax_max,dtmax_min + print *, 'dtmax_max,dtmax_min', dtmax_max,dtmax_min print *, 'utime=', utime return From 1313236641eddf72955fdb25537bc259c9388793 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 21 Feb 2024 04:05:26 +0000 Subject: [PATCH 098/182] Corrected sink read in moddump_sphNG2phantom_disc.f90 --- src/utils/moddump_sphNG2phantom_disc.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/moddump_sphNG2phantom_disc.f90 b/src/utils/moddump_sphNG2phantom_disc.f90 index b2db777da..8e06851a5 100644 --- a/src/utils/moddump_sphNG2phantom_disc.f90 +++ b/src/utils/moddump_sphNG2phantom_disc.f90 @@ -82,9 +82,9 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) nptmass = nptmass + npt do i=1,npt read (iunit,*) junk - read (iunit,'(10E15.6)') (xyzmh_ptmass(j,nptmass),j=1,10) + read (iunit,'(10E15.6)') (xyzmh_ptmass(j,i),j=1,10) read (iunit,*) junk - read (iunit,'(3E15.6)') (vxyz_ptmass(j,nptmass),j=1,3) + read (iunit,'(3E15.6)') (vxyz_ptmass(j,i),j=1,3) enddo close(iunit) endif From 3971f1b9ef4d7d4dfd3f0599a460595bcb55360b Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 21 Feb 2024 06:38:41 +0000 Subject: [PATCH 099/182] Fixes for icooling=8 --- src/main/eos_stamatellos.f90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index a9bcefde0..f20f99075 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -20,8 +20,9 @@ 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(:) character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file - logical,public :: doFLD = .True. + logical,public :: doFLD = .True., floor_energy = .False. integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in @@ -38,6 +39,8 @@ subroutine init_S07cool() allocate(duFLD(npart)) allocate(lambda_fld(npart)) allocate(urad_FLD(npart)) + allocate(ttherm_store(npart)) + allocate(teqi_store(npart)) urad_FLD(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') if (doFLD) then @@ -54,6 +57,8 @@ subroutine finish_S07cool() 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) close(iunitst) end subroutine finish_S07cool From 1d0327b458644494a3a8fc7e0f4921ab7dd7ad41 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 28 Feb 2024 15:32:54 +0000 Subject: [PATCH 100/182] Changes to write opacity to dump (icooling=8) --- src/main/cooling_stamatellos.f90 | 29 ++++++++++++++-------------- src/main/eos_stamatellos.f90 | 4 +++- src/main/readwrite_dumps_fortran.F90 | 2 ++ 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index a9aaedf31..beedaf568 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -66,7 +66,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) 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,floor_energy + duFLD,doFLD,ttherm_store,teqi_store,opac_store use part, only:xyzmh_ptmass real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt @@ -75,7 +75,7 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,Hstam,HLom,du_tot real :: cs2,Om2,Hmod2 - real :: tcool,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi + real :: opac,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi poti = Gpot_cool(i) du_FLDi = duFLD(i) @@ -140,25 +140,26 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) Tmini4 = Tfloor**4d0 endif - tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units - dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units + opac = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units + opac_store(i) = opac + dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opac/unit_ergg*utime! code units if (doFLD) then ! include term from FLD - Teqi = (du_FLDi + dudti_sph) *tcool*unit_ergg/utime ! physical units + Teqi = (du_FLDi + dudti_sph) *opac*unit_ergg/utime ! physical units du_tot = dudti_sph + dudt_rad + du_FLDi else - Teqi = dudti_sph*tcool*unit_ergg/utime + Teqi = dudti_sph*opac*unit_ergg/utime du_tot = dudti_sph + dudt_rad endif - + Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini4 -! if (Teqi < Tmini4) then -! Teqi = Tmini4**(1.0/4.0) -! else + if (Teqi < Tmini4) then + Teqi = Tmini4**(1.0/4.0) + else Teqi = Teqi**(1.0/4.0) -! endif + endif teqi_store(i) = Teqi call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg @@ -183,11 +184,11 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) endif if (isnan(dudti_cool)) then - print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti +! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti print *, "rhoi=",rhoi, "Ti=", Ti - print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph + print *, "opac=",opac,"coldensi=",coldensi,"dudti_sph",dudti_sph print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad + print *, "dudt_rad=", dudt_rad ,"dudt_dlf=",du_fldi,"ueqi=",ueqi,"ui=",ui call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index f20f99075..203570437 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(:) + real,allocatable,public :: ttherm_store(:),teqi_store(:),opac_store(:) character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file logical,public :: doFLD = .True., floor_energy = .False. integer,public :: iunitst=19 @@ -41,6 +41,7 @@ subroutine init_S07cool() allocate(urad_FLD(npart)) allocate(ttherm_store(npart)) allocate(teqi_store(npart)) + allocate(opac_store(npart)) urad_FLD(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') if (doFLD) then @@ -59,6 +60,7 @@ subroutine finish_S07cool() if (allocated(urad_FLD)) deallocate(urad_FLD) if (allocated(ttherm_store)) deallocate(ttherm_store) if (allocated(teqi_store)) deallocate(teqi_store) + if (allocated(opac_store)) deallocate(opac_store) close(iunitst) end subroutine finish_S07cool diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index b8f1bff67..5628665b1 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -245,6 +245,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use part, only:gamma_chem,mu_chem,T_gas_cool #endif use eos_stamatellos, only:gradP_cool,doFLD,urad_FLD,ttherm_store,teqi_store + use eos_stamatellos, only:opac_store real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -413,6 +414,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ! call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) call write_array(1,teqi_store,'teqi',npart,k,ipass,idump,nums,ierrs(13)) call write_array(1,ttherm_store,'ttherm',npart,k,ipass,idump,nums,ierrs(13)) + call write_array(1,opac_store,'opacity',npart,k,ipass,idump,nums,ierrs(13)) endif ! smoothing length written as real*4 to save disk space From e5fda5acc412490c9da339b49ead45236f974678 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 10 Apr 2024 16:34:33 +0100 Subject: [PATCH 101/182] restoring upstream changes part 1 --- AUTHORS | 31 ------ README.md | 38 +++----- build/Makefile_defaults_aocc | 1 + build/Makefile_fastmath | 4 +- data/forcing/README | 10 ++ docs/developer-guide/index.rst | 3 +- docs/examples/CE.rst | 12 ++- docs/getting-started/gitinfo.rst | 39 +++----- docs/user-guide/hdf5.rst | 32 +++---- scripts/HEADER-module | 2 +- scripts/HEADER-program | 2 +- src/lib/NICIL/src/nicil.F90 | 20 +++- src/main/bondiexact.f90 | 2 +- src/main/bondiexact_gr.f90 | 2 +- src/main/boundary.f90 | 2 +- src/main/boundary_dynamic.f90 | 4 +- src/main/centreofmass.f90 | 2 +- src/main/checkconserved.f90 | 6 +- src/main/checkoptions.F90 | 14 ++- src/main/checksetup.f90 | 95 ++++++++++--------- src/main/config.F90 | 8 +- src/main/cons2prim.f90 | 19 ++-- src/main/cons2primsolver.f90 | 10 +- src/main/cooling.F90 | 18 ++-- src/main/cooling_functions.f90 | 2 +- src/main/cooling_gammie.f90 | 2 +- src/main/cooling_gammie_PL.f90 | 2 +- src/main/cooling_ism.f90 | 2 +- src/main/cooling_koyamainutsuka.f90 | 2 +- src/main/cooling_molecular.f90 | 2 +- src/main/cooling_solver.f90 | 2 +- src/main/cullendehnen.f90 | 11 ++- src/main/datafiles.f90 | 2 +- src/main/eos.F90 | 3 +- src/main/utils_indtimesteps.F90 | 4 +- src/main/utils_inject.f90 | 2 +- src/main/utils_mathfunc.f90 | 2 +- src/main/utils_omp.F90 | 2 +- src/main/utils_raytracer.f90 | 2 +- src/main/utils_shuffleparticles.F90 | 2 +- src/main/utils_sort.f90 | 2 +- src/main/utils_sphNG.f90 | 2 +- src/main/utils_spline.f90 | 2 +- src/main/utils_summary.F90 | 2 +- src/main/utils_supertimestep.F90 | 2 +- src/main/utils_system.f90 | 2 +- src/main/utils_tables.f90 | 2 +- src/main/utils_vectors.f90 | 2 +- src/main/viscosity.f90 | 2 +- src/main/wind.F90 | 24 ++--- src/main/wind_equations.f90 | 10 +- src/main/writeheader.F90 | 2 +- src/utils/acc2ang.f90 | 2 +- src/utils/adaptivemesh.f90 | 2 +- src/utils/analysis_1particle.f90 | 2 +- src/utils/analysis_CoM.f90 | 2 +- src/utils/analysis_GalMerger.f90 | 2 +- src/utils/analysis_MWpdf.f90 | 2 +- src/utils/analysis_NSmerger.f90 | 2 +- src/utils/analysis_alpha.f90 | 2 +- src/utils/analysis_angmom.f90 | 2 +- src/utils/analysis_angmomvec.f90 | 2 +- src/utils/analysis_average_orb_en.f90 | 2 +- src/utils/analysis_binarydisc.f90 | 7 +- src/utils/analysis_bzrms.f90 | 2 +- .../analysis_collidingcloudevolution.f90 | 2 +- .../analysis_collidingcloudhistograms.f90 | 2 +- src/utils/analysis_cooling.f90 | 2 +- src/utils/analysis_disc.f90 | 2 +- src/utils/analysis_disc_MFlow.f90 | 2 +- src/utils/analysis_disc_eccentric.f90 | 2 +- src/utils/analysis_disc_mag.f90 | 2 +- src/utils/analysis_disc_planet.f90 | 2 +- src/utils/analysis_disc_stresses.f90 | 2 +- src/utils/analysis_dtheader.f90 | 2 +- src/utils/analysis_dustmass.f90 | 2 +- src/utils/analysis_dustydisc.f90 | 2 +- src/utils/analysis_etotgr.f90 | 2 +- src/utils/analysis_getneighbours.f90 | 2 +- src/utils/analysis_gws.f90 | 2 +- src/utils/analysis_jet.f90 | 2 +- src/utils/analysis_kepler.f90 | 2 +- src/utils/analysis_macctrace.f90 | 2 +- src/utils/analysis_mapping_mass.f90 | 2 +- src/utils/analysis_mcfost.f90 | 2 +- src/utils/analysis_mcfostcmdline.f90 | 2 +- src/utils/analysis_pairing.f90 | 2 +- src/utils/analysis_particle.f90 | 2 +- src/utils/analysis_pdfs.f90 | 2 +- src/utils/analysis_phantom_dump.f90 | 2 +- src/utils/analysis_polytropes.f90 | 2 +- src/utils/analysis_prdrag.f90 | 2 +- src/utils/analysis_ptmass.f90 | 2 +- src/utils/analysis_raytracer.f90 | 2 +- src/utils/analysis_sinkmass.f90 | 2 +- src/utils/analysis_sphere.f90 | 2 +- src/utils/analysis_structurefn.f90 | 2 +- src/utils/analysis_tde.f90 | 2 +- src/utils/analysis_torus.f90 | 2 +- src/utils/analysis_trackbox.f90 | 2 +- src/utils/analysis_tracks.f90 | 2 +- .../analysis_velocitydispersion_vs_scale.f90 | 2 +- src/utils/analysis_velocityshear.f90 | 2 +- src/utils/combinedustdumps.f90 | 2 +- src/utils/cubicsolve.f90 | 2 +- src/utils/diffdumps.f90 | 2 +- src/utils/dustywaves.f90 | 2 +- src/utils/ev2kdot.f90 | 2 +- src/utils/ev2mdot.f90 | 2 +- src/utils/evol_dustywaves.f90 | 2 +- src/utils/get_struct_slope.f90 | 2 +- src/utils/getmathflags.f90 | 2 +- src/utils/grid2pdf.f90 | 2 +- src/utils/hdf5utils.f90 | 2 +- src/utils/icosahedron.f90 | 2 +- src/utils/io_grid.f90 | 2 +- src/utils/io_structurefn.f90 | 2 +- src/utils/leastsquares.f90 | 2 +- src/utils/libphantom-splash.f90 | 2 +- src/utils/lombperiod.f90 | 2 +- src/utils/mflow.f90 | 2 +- src/utils/moddump_CoM.f90 | 2 +- src/utils/moddump_addflyby.f90 | 2 +- src/utils/moddump_addplanets.f90 | 2 +- src/utils/moddump_binary.f90 | 2 +- src/utils/moddump_binarystar.f90 | 2 +- src/utils/moddump_changemass.f90 | 2 +- src/utils/moddump_default.f90 | 2 +- src/utils/moddump_disc.f90 | 2 +- src/utils/moddump_dustadd.f90 | 2 +- src/utils/moddump_extenddisc.f90 | 2 +- src/utils/moddump_growthtomultigrain.f90 | 2 +- src/utils/moddump_mergepart.f90 | 2 +- src/utils/moddump_messupSPH.f90 | 2 +- src/utils/moddump_perturbgas.f90 | 2 +- src/utils/moddump_polytrope.f90 | 2 +- src/utils/moddump_rad_to_LTE.f90 | 4 +- src/utils/moddump_recalcuT.f90 | 2 +- .../moddump_removeparticles_cylinder.f90 | 2 +- src/utils/moddump_removeparticles_radius.f90 | 2 +- src/utils/moddump_rotate.f90 | 2 +- src/utils/moddump_sink.f90 | 4 +- src/utils/moddump_sinkbinary.f90 | 2 +- src/utils/moddump_sphNG2phantom.f90 | 2 +- src/utils/moddump_sphNG2phantom_addBfield.f90 | 2 +- src/utils/moddump_sphNG2phantom_disc.f90 | 2 +- src/utils/moddump_splitpart.f90 | 2 +- src/utils/moddump_taylorgreen.f90 | 2 +- src/utils/moddump_tidal.f90 | 2 +- src/utils/moddump_torus.f90 | 2 +- src/utils/multirun.f90 | 2 +- src/utils/multirun_mach.f90 | 2 +- src/utils/pdfs.f90 | 2 +- src/utils/phantom2divb.f90 | 2 +- src/utils/phantom2divv.f90 | 2 +- src/utils/phantom2gadget.f90 | 2 +- src/utils/phantom2hdf5.f90 | 2 +- src/utils/phantom2sphNG.f90 | 2 +- src/utils/phantom_moddump.f90 | 2 +- src/utils/phantomanalysis.f90 | 5 +- src/utils/phantomevcompare.f90 | 2 +- src/utils/phantomextractsinks.f90 | 2 +- src/utils/plot_kernel.f90 | 2 +- src/utils/powerspectrums.f90 | 2 +- src/utils/prompting.f90 | 2 +- src/utils/quartic.f90 | 2 +- src/utils/rhomach.f90 | 2 +- src/utils/showarrays.f90 | 2 +- src/utils/showheader.f90 | 6 +- src/utils/solvelinearsystem.f90 | 2 +- src/utils/splitpart.f90 | 2 +- src/utils/struct2struct.f90 | 2 +- src/utils/test_binary.f90 | 2 +- src/utils/testbinary.f90 | 2 +- src/utils/utils_disc.f90 | 2 +- src/utils/utils_ephemeris.f90 | 2 +- src/utils/utils_evfiles.f90 | 2 +- src/utils/utils_gravwave.f90 | 2 +- src/utils/utils_linalg.f90 | 2 +- src/utils/utils_mpc.f90 | 2 +- src/utils/utils_orbits.f90 | 2 +- src/utils/utils_splitmerge.f90 | 2 +- src/utils/velfield.f90 | 2 +- 183 files changed, 367 insertions(+), 385 deletions(-) create mode 100644 data/forcing/README diff --git a/AUTHORS b/AUTHORS index 7c163a247..4b972f1d7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -31,15 +31,9 @@ Sergei Biriukov Cristiano Longarini Giovanni Dipierro Roberto Iaconi -fhu Hauke Worpel -<<<<<<< HEAD -Simone Ceppi -Amena Faruqi -======= Amena Faruqi Alison Young ->>>>>>> upstream/master Stephen Neilson <36410751+s-neilson@users.noreply.github.com> Martina Toscani Benedetta Veronesi @@ -54,25 +48,6 @@ Jolien Malfait Phantom benchmark bot Kieran Hirsh Nicole Rodrigues -<<<<<<< HEAD -Amena Faruqi -David Trevascus -Chris Nixon -Megha Sharma -Nicolas Cuello -Benoit Commercon -Giulia Ballabio -Joe Fisher -Maxime Lombart -Megha Sharma -Orsola De Marco -Zachary Pellow -s-neilson <36410751+s-neilson@users.noreply.github.com> -Alison Young -Cox, Samuel -Jorge Cuadra -Nicolás Cuello -======= David Trevascus Nicolás Cuello Farzana Meru @@ -87,16 +62,10 @@ Benoit Commercon Giulia Ballabio s-neilson <36410751+s-neilson@users.noreply.github.com> MICHOULIER Stephane ->>>>>>> upstream/master Steven Rieder Jeremy Smallwood Cox, Samuel Jorge Cuadra Stéven Toupin -<<<<<<< HEAD -Terrence Tricco -mats esseldeurs -======= Taj Jankovič Chunliang Mu ->>>>>>> upstream/master diff --git a/README.md b/README.md index 600d757b6..bcb9f6dc1 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,17 @@ Phantom is a 3D Smoothed Particle Hydrodynamics and Magnetohydrodynamics code fo Status ------ -![testkd](https://github.com/danieljprice/phantom/workflows/testkd/badge.svg) -![test2](https://github.com/danieljprice/phantom/workflows/test2/badge.svg) -![testcyl](https://github.com/danieljprice/phantom/workflows/testcyl/badge.svg) -![mpi](https://github.com/danieljprice/phantom/workflows/mpi/badge.svg) -![GR](https://github.com/danieljprice/phantom/workflows/GR/badge.svg) -![dust](https://github.com/danieljprice/phantom/workflows/dust/badge.svg) -![dust growth](https://github.com/danieljprice/phantom/workflows/growth/badge.svg) -![non-ideal mhd](https://github.com/danieljprice/phantom/workflows/nimhd/badge.svg) -![utils](https://github.com/danieljprice/phantom/workflows/utils/badge.svg) + +[![build](https://github.com/danieljprice/phantom/actions/workflows/build.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/build.yml) +[![test](https://github.com/danieljprice/phantom/actions/workflows/test.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/test.yml) +[![mpi](https://github.com/danieljprice/phantom/actions/workflows/mpi.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/mpi.yml) +[![mcfost](https://github.com/danieljprice/phantom/actions/workflows/mcfost.yml/badge.svg)](https://github.com/danieljprice/phantom/actions/workflows/mcfost.yml) [![Documentation](https://readthedocs.org/projects/phantomsph/badge/?version=latest)](https://phantomsph.readthedocs.io/en/latest/?badge=latest) Links ----- -- Project homepage: http://phantomsph.bitbucket.io/ +- Project homepage: http://phantomsph.github.io/ - Code repository: https://github.com/danieljprice/phantom/ - Documentation: https://phantomsph.readthedocs.org/ - Code paper: http://adsabs.harvard.edu/abs/2018PASA...35...31P @@ -48,7 +44,12 @@ Getting help If you need help, please try the following, in order: 1. Check the [documentation](https://phantomsph.readthedocs.org/). -2. File an issue, as a [bug report](https://github.com/danieljprice/phantom/issues/new) or [feature request](https://github.com/danieljprice/phantom/issues/new), using the issue tracker. +2. If you encounter a bug, [file an issue](https://github.com/danieljprice/phantom/issues/new) +3. If you want to request a feature, [file an issue](https://github.com/danieljprice/phantom/issues/new), using the issue tracker. +4. If you need help on how to use phantom, [file an issue](https://github.com/danieljprice/phantom/issues/new) + +We welcome general discussion about Phantom, Smoothed Particle Hydrodynamics, +and astrophysics at the [Phantom Slack](https://phantomsph.slack.com/). However, please use the github issues for support requests. Contributing ------------ @@ -58,25 +59,16 @@ We welcome contributions, including (but not limited to): 2. Documentation, also by [pull request](https://github.com/danieljprice/phantom/pulls). Docs can be edited in the docs/ directory of the main code. 3. Suggestions for features or bug reports, via the [issue tracker](https://github.com/danieljprice/phantom/issues/new). Please file bugs via github rather than by email. -Slack ------ - -We welcome general discussion about Phantom, Smoothed Particle Hydrodynamics, -and astrophysics at the [Phantom Slack](https://phantomsph.slack.com/). - Citation -------- Please cite [Price et al. (2018)](http://adsabs.harvard.edu/abs/2018PASA...35...31P) when using Phantom. Wherever possible, please try to also cite original references for the algorithms you are using. A partial list can be found in `docs/phantom.bib` file, or by reading the relevant sections of the paper. -Licence -------- +Other things +------------- +For CHANGES see the release notes: https://phantomsph.readthedocs.io/en/latest/releasenotes.html. See LICENCE file for usage and distribution conditions. Copyright (c) 2007-2023 Daniel Price and contributors (see AUTHORS file). -Release notes -------------- - -For CHANGES see the release notes: https://phantomsph.readthedocs.io/en/latest/releasenotes.html. diff --git a/build/Makefile_defaults_aocc b/build/Makefile_defaults_aocc index 452ef08bd..17c20121e 100644 --- a/build/Makefile_defaults_aocc +++ b/build/Makefile_defaults_aocc @@ -12,3 +12,4 @@ KNOWN_SYSTEM=yes OMPFLAGS= -fopenmp +AOCC = yes diff --git a/build/Makefile_fastmath b/build/Makefile_fastmath index 0e05134d1..a148a96c0 100644 --- a/build/Makefile_fastmath +++ b/build/Makefile_fastmath @@ -29,7 +29,7 @@ endif ifeq ($(FASTMATH), yes) SRCFASTMATH=fastmath.o - TEST_FASTMATH=test_fastmath.F90 + TEST_FASTMATH=test_fastmath.f90 FPPFLAGS+=-DFINVSQRT else SRCFASTMATH= @@ -38,7 +38,7 @@ endif fastmath.o: fastmath.f90 $(FC) $(FFLAGS) -o $@ -c $< || ${MAKE} fastmathlinkerr -test_fastmath.o: test_fastmath.F90 +test_fastmath.o: test_fastmath.f90 $(FC) $(FFLAGS) -o $@ -c $< || ${MAKE} fastmathlinkerr getmathflags.o: getmathflags.f90 $(FC) $(FFLAGS) -o $@ -c $< || ${MAKE} fastmathlinkerr diff --git a/data/forcing/README b/data/forcing/README new file mode 100644 index 000000000..99065dec1 --- /dev/null +++ b/data/forcing/README @@ -0,0 +1,10 @@ +The forcing data file is too large to be stored in the Phantom git repository +It will be downloaded automatically when you run the code + +or can be retrieved manually using wget from the phantom website, e.g.: + +wget http://users.monash.edu.au/~dprice/phantom/data/forcing.dat + +The files are: + +forcing.dat diff --git a/docs/developer-guide/index.rst b/docs/developer-guide/index.rst index 1c29a8046..b9d169785 100644 --- a/docs/developer-guide/index.rst +++ b/docs/developer-guide/index.rst @@ -6,13 +6,14 @@ Here is the Phantom developer guide. .. toctree:: :maxdepth: 1 + fork fortran vscode philosophy styleguide setup testing + bots datafiles staging - fork sort diff --git a/docs/examples/CE.rst b/docs/examples/CE.rst index 12e80f8a0..2c38b5f86 100644 --- a/docs/examples/CE.rst +++ b/docs/examples/CE.rst @@ -73,7 +73,7 @@ Use SETUP=star or SETUP=dustystar and if not specified, the default options. 2.2 make setup 2.3 ./phantomsetup star (option 5 MESA star, input profile = Jan_Star_Phantom_Profile.data, desired EOS = 10, use constant entropy profile, Relax star automatically = yes). The core radius is the softening radius (2-3Ro) - the core mass is the same as the one you have measured from MESA (0.46Mo in Jan_Star_Phantom_Profile). + the core mass is the same as the one you have measured from MESA (0.46Mo in Jan_Star_Phantom_Profile.data). This produces a file called star.setup - this file has all the options so you can edit it. 2.4 vim star.setup, (write_rho_to_file = T) @@ -126,3 +126,13 @@ if you come from 2.10, then use as initial model (hereafter initial_nnnnn) one o softening length for the primary core = 1., softening length for companion = 0.1) 2.16 vim binary.in (optional, tmax=200.00, dtmax=0.100) 2.17 ./phantom binary.in + + +**D. Setup sink properties (luminosity)** + +:: + + 2.18 ./phantommoddump binary_00000.tmp dusty_binary_00000.tmp 0.0 + option 9, 12 lum + 2.19 vim dusty_binary.in (adapt isink_radiation, idust_opacity) + 2.20 ./phantom dusty_binary.in diff --git a/docs/getting-started/gitinfo.rst b/docs/getting-started/gitinfo.rst index 46c179d38..de0ab83e4 100644 --- a/docs/getting-started/gitinfo.rst +++ b/docs/getting-started/gitinfo.rst @@ -8,9 +8,7 @@ Getting your first copy Once you have a GitHub account, you must create your own :doc:`fork `. This is done using the “fork” button (the big button on top right of the -repo page). You can then clone your fork to your computer: - -:: +repo page). You can then clone your fork to your computer:: git clone https://github.com/USERNAME/phantom.git @@ -21,9 +19,7 @@ Setting your username and email address --------------------------------------- Before you can push changes, you must ensure that your name and email -address are set, as follows: - -:: +address are set, as follows:: cd phantom git config --global user.name "Joe Bloggs" @@ -35,9 +31,7 @@ in the commit logs (and in the AUTHORS file) Receiving updates from your fork -------------------------------- -Procedure is: stash your changes, pull the updates, reapply your changes - -:: +Procedure is: stash your changes, pull the updates, reapply your changes:: git stash git pull @@ -47,18 +41,14 @@ Receiving updates from the master branch ---------------------------------------- Before you can receive updates from the master branch, you must first link -your fork to the master branch: - -:: +your fork to the master branch:: git remote add upstream https://github.com/danieljprice/phantom.git This only needs to be done once. To update, the procedure is: stash your changes, pull the updates, -reapply your changes - -:: +reapply your changes:: git stash git fetch upstream @@ -72,23 +62,17 @@ Committing changes to your fork Submit changes to Phantom carefully! The first thing is to pull any upstream changes as described above. Once you have done this, first -check what you will commit: - -:: +check what you will commit:: git diff then go through each subset of changes you have made and commit the -file(s) with a message: - -:: +file(s) with a message:: git commit -m 'changed units in dim file for problem x' src/main/dim_myprob.f90 and so on, for all the files that you want to commit. Then, when you’re -ready to push the changeset back to your fork use - -:: +ready to push the changeset back to your fork use:: git push @@ -96,10 +80,9 @@ Note that you will only be allowed to push changes if you have already updated your copy to the latest version. If you have just updated your code from the master repo, simply update -your fork via +your fork via:: -:: - git commit + git commit -m 'merge' git push This will push all the remote changes to your forked version of Phantom. @@ -108,7 +91,7 @@ Committing changes to the master branch --------------------------------------- This is done through a “pull request”. To do this, -you can click the big “pull request” button on the GitHub page to request +you can click the “contribute” button on the GitHub page to request that your changes be pulled into the master copy of Phantom. Please do this frequently. Many small pull requests are much better than one giant pull request! diff --git a/docs/user-guide/hdf5.rst b/docs/user-guide/hdf5.rst index c08aca9ad..bbccd0a60 100644 --- a/docs/user-guide/hdf5.rst +++ b/docs/user-guide/hdf5.rst @@ -38,7 +38,7 @@ On macOS you can install HDF5 with Homebrew. brew install hdf5 The shared object library and include files are at -``/usr/local/opt/hdf5``. Use this directory as ``HDF5ROOT`` (see below). +``/usr/local/opt/hdf5``. Use this directory as ``HDF5_DIR`` (see below). On Ubuntu 18.04, for example, you can install HDF5 with apt. @@ -48,7 +48,7 @@ On Ubuntu 18.04, for example, you can install HDF5 with apt. The location of the library is then ``/usr/lib/x86_64-linux-gnu/hdf5/serial``. Use this directory as -``HDF5ROOT`` (see below). +``HDF5_DIR`` (see below). Compiling ~~~~~~~~~ @@ -93,25 +93,19 @@ Compiling Phantom Writing HDF5 output is a compile time option and requires access to the Fortran HDF5 library. To compile for HDF5 output set ``HDF5_DIR``, for -example if HDF5 was installed with Homebrew on macOS - -:: +example if HDF5 was installed with Homebrew on macOS:: HDF5_DIR=/usr/local/opt/hdf5 -or if it was installed with APT on Ubuntu - -:: +or if it was installed with APT on Ubuntu:: HDF5_DIR=/usr/lib/x86_64-linux-gnu/hdf5/serial -Then compile with - -:: +Then compile with:: - make HDF5=yes HDF5ROOT=$HDF5_DIR + make HDF5=yes -The variable ``HDF5ROOT`` specifies the location of the HDF5 library. +The variable ``HDF5_DIR`` specifies the location of the HDF5 library. .. note:: @@ -127,19 +121,15 @@ Ozstar On Ozstar you need to make sure that the OpenMPI and HDF5 modules are loaded. The variable ``HDF5_DIR`` gives the location of the HDF5 library -once the HDF5 module is loaded. - -:: +once the HDF5 module is loaded:: module load iccifort/2018.1.163-gcc-6.4.0 module load openmpi/3.0.0 module load hdf5/1.10.1 -Then when you compile Phantom use ``HDF5_DIR`` for ``HDF5ROOT``: - -:: +Then when you compile Phantom ensure ``HDF5_DIR`` is set correctly:: - make SYSTEM=ozstar HDF5=yes HDF5ROOT=$HDF5_DIR phantom setup + make SYSTEM=ozstar HDF5=yes phantom setup Note that you must have the HDF5 module loaded when running phantom, phantomsetup, etc. So make sure to put ``module load hdf5/1.10.1`` in @@ -163,7 +153,7 @@ then you would compile ``phantom2hdf5`` as follows :: - make SETUP=dustydisc MAXP=10000000 HDF5=yes HDF5ROOT=$HDF5_DIR phantom2hdf5 + make SETUP=dustydisc MAXP=10000000 HDF5=yes phantom2hdf5 Recall that you will need to set ``HDF5_DIR`` appropriately for your system. diff --git a/scripts/HEADER-module b/scripts/HEADER-module index 5f72a072c..e6f5a8618 100644 --- a/scripts/HEADER-module +++ b/scripts/HEADER-module @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-THISYEAR The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! ! :MODULE: [generated automatically] ! diff --git a/scripts/HEADER-program b/scripts/HEADER-program index fef7841e9..59d916bd4 100644 --- a/scripts/HEADER-program +++ b/scripts/HEADER-program @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-THISYEAR The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! ! PROGRAM: [generated automatically] ! diff --git a/src/lib/NICIL/src/nicil.F90 b/src/lib/NICIL/src/nicil.F90 index ccb4e706d..cefc345ff 100644 --- a/src/lib/NICIL/src/nicil.F90 +++ b/src/lib/NICIL/src/nicil.F90 @@ -1239,6 +1239,7 @@ pure subroutine nicil_update_nimhd(icall,eta_ohm,eta_hall,eta_ambi,Bfield,rho,T, else nden_electronR = nicil_ionR_get_ne(nden_save(1:iire)) ! in this case, need to calculate electron density from ions n_g_tot = 0. ! to prevent compiler warnings + zeta = 0. ! prevent compiler warnings endif !--Sum the ion populations from thermal and cosmic ray ionisation @@ -1294,6 +1295,7 @@ pure subroutine nicil_update_nimhd(icall,eta_ohm,eta_hall,eta_ambi,Bfield,rho,T, else !--Return constant coefficient version and exit call nicil_nimhd_get_eta_cnst(eta_ohm,eta_hall,eta_ambi,Bfield,rho) + if (present(data_out)) data_out = 0. endif if (present(itry)) itry = itry_n0 @@ -2288,9 +2290,14 @@ end subroutine nicil_get_dt_nimhd pure subroutine nicil_get_halldrift(eta_hall,Bx,By,Bz,jcurrent,vdrift) real, intent(in) :: eta_hall,Bx,By,Bz,jcurrent(3) real, intent(out) :: vdrift(3) - real :: B1 + real :: B1,B2 - B1 = 1.0/sqrt(Bx*Bx + By*By + Bz*Bz) + B2 = Bx*Bx + By*By + Bz*Bz + if (B2 > 0.) then + B1 = 1.0/sqrt(B2) + else + B1 = 0. + endif vdrift = -eta_hall*jcurrent*B1 end subroutine nicil_get_halldrift @@ -2302,9 +2309,14 @@ end subroutine nicil_get_halldrift pure subroutine nicil_get_ambidrift(eta_ambi,Bx,By,Bz,jcurrent,vdrift) real, intent(in) :: eta_ambi,Bx,By,Bz,jcurrent(3) real, intent(out) :: vdrift(3) - real :: B21 + real :: B2,B21 - B21 = 1.0/(Bx*Bx + By*By + Bz*Bz) + B2 = Bx*Bx + By*By + Bz*Bz + if (B2 > 0.) then + B21 = 1.0/B2 + else + B21 = 0. + endif vdrift(1) = eta_ambi*( jcurrent(2)*Bz - jcurrent(3)*By )*B21 vdrift(2) = eta_ambi*( jcurrent(3)*Bx - jcurrent(1)*Bz )*B21 vdrift(3) = eta_ambi*( jcurrent(1)*By - jcurrent(2)*Bx )*B21 diff --git a/src/main/bondiexact.f90 b/src/main/bondiexact.f90 index 35abcd9e8..e39ddd970 100644 --- a/src/main/bondiexact.f90 +++ b/src/main/bondiexact.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module bondiexact ! diff --git a/src/main/bondiexact_gr.f90 b/src/main/bondiexact_gr.f90 index ceb08100a..869fc061a 100644 --- a/src/main/bondiexact_gr.f90 +++ b/src/main/bondiexact_gr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module bondiexact ! diff --git a/src/main/boundary.f90 b/src/main/boundary.f90 index ac732f48e..08bb0fd34 100644 --- a/src/main/boundary.f90 +++ b/src/main/boundary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module boundary ! diff --git a/src/main/boundary_dynamic.f90 b/src/main/boundary_dynamic.f90 index 29786f8f7..88642a872 100644 --- a/src/main/boundary_dynamic.f90 +++ b/src/main/boundary_dynamic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module boundary_dyn ! @@ -360,7 +360,7 @@ subroutine find_dynamic_boundaries(npart,nptmass,dtmax,xyz_n_all,xyz_x_all,ierr) ! add uninteresting particles to the averages if (.not.bdy_is_interesting) then n_bkg = n_bkg + 1 - v_bkg = v_bkg + vxyzu(:,i) + v_bkg = v_bkg + vxyzu(1:3,i) if (mhd) B_bkg = B_bkg + Bevol(:,i)*rhoi endif endif diff --git a/src/main/centreofmass.f90 b/src/main/centreofmass.f90 index 29ee1788b..88fb0fb70 100644 --- a/src/main/centreofmass.f90 +++ b/src/main/centreofmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module centreofmass ! diff --git a/src/main/checkconserved.f90 b/src/main/checkconserved.f90 index 32b54f110..e47e96955 100644 --- a/src/main/checkconserved.f90 +++ b/src/main/checkconserved.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module checkconserved ! @@ -39,7 +39,7 @@ subroutine init_conservation_checks(should_conserve_energy,should_conserve_momen should_conserve_angmom,should_conserve_dustmass) use options, only:icooling,ieos,ipdv_heating,ishock_heating,& iresistive_heating,use_dustfrac,iexternalforce - use dim, only:mhd,maxvxyzu,periodic,particles_are_injected + use dim, only:mhd,maxvxyzu,periodic,inject_parts use part, only:iboundary,npartoftype use boundary_dyn,only:dynamic_bdy logical, intent(out) :: should_conserve_energy,should_conserve_momentum @@ -73,7 +73,7 @@ subroutine init_conservation_checks(should_conserve_energy,should_conserve_momen ! ! Each injection routine will need to bookeep conserved quantities, but until then... ! - if (particles_are_injected .or. dynamic_bdy) then + if (inject_parts .or. dynamic_bdy) then should_conserve_energy = .false. should_conserve_momentum = .false. should_conserve_angmom = .false. diff --git a/src/main/checkoptions.F90 b/src/main/checkoptions.F90 index fe21f493c..d230f40bf 100644 --- a/src/main/checkoptions.F90 +++ b/src/main/checkoptions.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module checkoptions ! @@ -14,7 +14,7 @@ module checkoptions ! ! :Runtime parameters: None ! -! :Dependencies: dim, io, metric_tools, part +! :Dependencies: dim, io, metric_tools, mpiutils, part ! implicit none public :: check_compile_time_settings @@ -143,10 +143,16 @@ subroutine check_compile_time_settings(ierr) #endif #ifdef DUSTGROWTH - if (.not. use_dustgrowth) call error(string,'-DDUSTGROWTH but use_dustgrowth = .false.') + if (.not. use_dustgrowth) then + call error(string,'-DDUSTGROWTH but use_dustgrowth = .false.') + ierr = 16 + endif #endif - return + if (mpi .and. inject_parts) call error(string,'MPI currently not compatible with particle injection') + + call barrier_mpi + end subroutine check_compile_time_settings end module checkoptions diff --git a/src/main/checksetup.f90 b/src/main/checksetup.f90 index f35039f6e..e4e0c17cd 100644 --- a/src/main/checksetup.f90 +++ b/src/main/checksetup.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module checksetup ! @@ -16,7 +16,7 @@ module checksetup ! ! :Dependencies: boundary, boundary_dyn, centreofmass, dim, dust, eos, ! externalforces, io, metric_tools, nicil, options, part, physcon, -! sortutils, timestep, units, utils_gr +! ptmass_radiation, sortutils, timestep, units, utils_gr ! implicit none public :: check_setup @@ -91,12 +91,6 @@ subroutine check_setup(nerror,nwarn,restart) print*,'ERROR: sum of npartoftype /= npart: np=',npart,' but sum=',sum(npartoftype) nerror = nerror + 1 endif -#ifndef KROME - if (gamma <= 0.) then - print*,'WARNING! gamma not set (should be set > 0 even if not used)' - nwarn = nwarn + 1 - endif -#endif if (hfact < 1. .or. isnan(hfact)) then print*,'ERROR: hfact = ',hfact,', should be >= 1' nerror = nerror + 1 @@ -105,7 +99,6 @@ subroutine check_setup(nerror,nwarn,restart) print*,'ERROR: polyk = ',polyk,', should be >= 0' nerror = nerror + 1 endif - if (use_krome) then if (ieos /= 19) then print*, 'KROME setup. Only eos=19 makes sense.' @@ -121,12 +114,6 @@ subroutine check_setup(nerror,nwarn,restart) nwarn = nwarn + 1 endif endif -#else - if (polyk < tiny(0.) .and. ieos /= 2) then - print*,'WARNING! polyk = ',polyk,' in setup, speed of sound will be zero in equation of state' - nwarn = nwarn + 1 - endif -#endif if (npart < 0) then print*,'ERROR: npart = ',npart,', should be >= 0' nerror = nerror + 1 @@ -307,7 +294,8 @@ subroutine check_setup(nerror,nwarn,restart) ! warn about external force settings ! if (iexternalforce==iext_star .and. nptmass==0) then - print*,'WARNING: iexternalforce=1 does not conserve momentum - use a sink particle at r=0 if you care about this' + if (id==master) print "(a,/,a)",'WARNING: iexternalforce=1 does not conserve momentum:',& + ' use a sink particle at r=0 if you care about this' nwarn = nwarn + 1 endif ! @@ -345,9 +333,9 @@ subroutine check_setup(nerror,nwarn,restart) if (gravity .or. nptmass > 0) then if (.not.G_is_unity()) then if (gravity) then - print*,'ERROR: self-gravity ON but G /= 1 in code units, got G=',get_G_code() + if (id==master) print*,'ERROR: self-gravity ON but G /= 1 in code units, got G=',get_G_code() elseif (nptmass > 0) then - print*,'ERROR: sink particles used but G /= 1 in code units, got G=',get_G_code() + if (id==master) print*,'ERROR: sink particles used but G /= 1 in code units, got G=',get_G_code() endif fix_units = .true. if (fix_units) then @@ -360,7 +348,7 @@ subroutine check_setup(nerror,nwarn,restart) endif endif if (.not. gr .and. (gravity .or. mhd) .and. ien_type == ien_etotal) then - print*,'Cannot use total energy with self gravity or mhd' + if (id==master) print*,'Cannot use total energy with self gravity or mhd' nerror = nerror + 1 endif ! @@ -368,12 +356,12 @@ subroutine check_setup(nerror,nwarn,restart) ! if (mhd) then if (all(abs(Bxyz(:,1:npart)) < tiny(0.))) then - print*,'WARNING: MHD is ON but magnetic field is zero everywhere' + if (id==master) print*,'WARNING: MHD is ON but magnetic field is zero everywhere' nwarn = nwarn + 1 endif if (mhd_nonideal) then if (n_nden /= n_nden_phantom) then - print*,'ERROR: n_nden in nicil.f90 needs to match n_nden_phantom in config.F90; n_nden = ',n_nden + if (id==master) print*,'ERROR: n_nden in nicil.f90 needs to match n_nden_phantom in config.F90; n_nden = ',n_nden nerror = nerror + 1 endif endif @@ -424,7 +412,7 @@ subroutine check_setup(nerror,nwarn,restart) ! !--check radiation setup ! - if (do_radiation) call check_setup_radiation(npart,nerror,radprop,rad) + if (do_radiation) call check_setup_radiation(npart,nerror,nwarn,radprop,rad) ! !--check dust growth arrays ! @@ -660,7 +648,7 @@ end subroutine check_setup_ptmass !+ !------------------------------------------------------------------ subroutine check_setup_growth(npart,nerror) - use part, only:dustprop,dustprop_label + use part, only:dustprop,dustprop_label,iamdust,iphase,maxphase,maxp integer, intent(in) :: npart integer, intent(inout) :: nerror integer :: i,j,nbad(4) @@ -669,12 +657,16 @@ subroutine check_setup_growth(npart,nerror) !-- Check that all the parameters are > 0 when needed do i=1,npart do j=1,2 - if (dustprop(j,i) < 0.) nbad(j) = nbad(j) + 1 + if (maxphase==maxp) then + if (iamdust(iphase(i)) .and. dustprop(j,i) <= 0.) nbad(j) = nbad(j) + 1 + elseif (dustprop(j,i) < 0.) then + nbad(j) = nbad(j) + 1 + endif enddo enddo do j=1,2 if (nbad(j) > 0) then - print*,'ERROR: ',nbad(j),' of ',npart,' particles with '//trim(dustprop_label(j))//' < 0' + print*,'ERROR: dustgrowth: ',nbad(j),' of ',npart,' particles with '//trim(dustprop_label(j))//' <= 0' nerror = nerror + 1 endif enddo @@ -762,13 +754,13 @@ subroutine check_setup_dustgrid(nerror,nwarn) nerror = nerror + 1 endif enddo + do i=1,ndusttypes + if (grainsize(i) > 10.*km/udist) then + print*,'WARNING: grainsize is HUGE (>10km) in dust bin ',i,': s = ',grainsize(i)*udist/km,' km' + nwarn = nwarn + 1 + endif + enddo endif - do i=1,ndusttypes - if (grainsize(i) > 10.*km/udist) then - print*,'WARNING: grainsize is HUGE (>10km) in dust bin ',i,': s = ',grainsize(i)*udist/km,' km' - nwarn = nwarn + 1 - endif - enddo end subroutine check_setup_dustgrid @@ -954,46 +946,57 @@ end subroutine check_for_identical_positions !------------------------------------------------------------------ !+ -! 1) check for optically thin particles when mcfost is disabled, -! as the particles will then be overlooked if they are flagged as thin -! 2) check that radiation energy is never negative to begin with -! 3) check for NaNs +! 1) check for optically thin particles when mcfost is disabled, +! as the particles will then be overlooked if they are flagged as thin +! 2) check that radiation energy is never negative to begin with +! 3) check for NaNs !+ !------------------------------------------------------------------ -subroutine check_setup_radiation(npart, nerror, radprop, rad) +subroutine check_setup_radiation(npart,nerror,nwarn,radprop,rad) use part, only:ithick, iradxi, ikappa integer, intent(in) :: npart - integer, intent(inout) :: nerror + integer, intent(inout) :: nerror,nwarn real, intent(in) :: rad(:,:), radprop(:,:) - integer :: i, nthin, nradEn, nkappa + integer :: i,nthin,nradEn,nkappa,nwarn_en nthin = 0 nradEn = 0 nkappa = 0 - do i=1, npart - if (radprop(ithick, i) < 0.5) nthin=nthin + 1 - if (rad(iradxi, i) < 0.) nradEn=nradEn + 1 - if (radprop(ikappa, i) <= 0.0 .or. isnan(radprop(ikappa,i))) nkappa=nkappa + 1 + nwarn_en = 0 + do i=1,npart + if (radprop(ithick, i) < 0.5) nthin = nthin + 1 + if (rad(iradxi, i) < 0.) nradEn = nradEn + 1 + if (radprop(ikappa, i) <= 0.0 .or. isnan(radprop(ikappa,i))) nkappa = nkappa + 1 + if (rad(iradxi, i) <= 0.) nwarn_en = nwarn_en + 1 enddo if (nthin > 0) then - print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nthin,' of ',npart,& + print "(/,a,i10,a,i10,a,/)",' ERROR in setup: ',nthin,' of ',npart,& ' particles are being treated as optically thin without MCFOST being compiled' nerror = nerror + 1 endif if (nradEn > 0) then - print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nradEn,' of ',npart,& - ' particles have negative radiation Energy' + print "(/,a,i10,a,i10,a,/)",' ERROR in setup: ',nradEn,' of ',npart,& + ' particles have negative radiation energy' nerror = nerror + 1 endif + if (nwarn_en > 0) then + print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nwarn_en,' of ',npart,& + ' particles have radiation energy equal to zero' + nwarn = nwarn + 1 + endif + if (nkappa > 0) then - print "(/,a,i10,a,i10,a,/)",' WARNING in setup: ',nkappa,' of ',npart,& + print "(/,a,i10,a,i10,a,/)",' ERROR in setup: ',nkappa,' of ',npart,& ' particles have opacity <= 0.0 or NaN' nerror = nerror + 1 endif + call check_NaN(npart,rad,'radiation_energy',nerror) + call check_NaN(npart,radprop,'radiation properties',nerror) + end subroutine check_setup_radiation end module checksetup diff --git a/src/main/config.F90 b/src/main/config.F90 index e75941504..069005dd4 100644 --- a/src/main/config.F90 +++ b/src/main/config.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module dim ! @@ -22,8 +22,6 @@ module dim integer, parameter, public :: phantom_version_minor = PHANTOM_VERSION_MINOR integer, parameter, public :: phantom_version_micro = PHANTOM_VERSION_MICRO character(len=*), parameter, public :: phantom_version_string = PHANTOM_VERSION_STRING - character(len=80), parameter :: & ! module version - modid="$Id$" public @@ -322,9 +320,9 @@ module dim ! logical for bookkeeping !-------------------- #ifdef INJECT_PARTICLES - logical, parameter :: particles_are_injected = .true. + logical, parameter :: inject_parts = .true. #else - logical, parameter :: particles_are_injected = .false. + logical, parameter :: inject_parts = .false. #endif !-------------------- diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 8969d0dee..151dc9337 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cons2prim ! @@ -177,7 +177,8 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& iohm,ihall,nden_nimhd,eta_nimhd,iambi,get_partinfo,iphase,this_is_a_test,& ndustsmall,itemp,ikappa,idmu,idgamma,icv use part, only:nucleation,igamma - use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,gamma + use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,& + gamma use radiation_utils, only:radiation_equation_of_state,get_opacity use dim, only:mhd,maxvxyzu,maxphase,maxp,use_dustgrowth,& do_radiation,nalpha,mhd_nonideal,do_nucleation,use_krome,update_muGamma @@ -271,7 +272,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& endif if (use_krome) gammai = eos_vars(igamma,i) if (maxvxyzu >= 4) then - uui = utherm(vxyzu(:,i),rhogas,gammai) + uui = vxyzu(4,i) if (uui < 0.) call warning('cons2prim','Internal energy < 0',i,'u',uui) call equationofstate(ieos,p_on_rhogas,spsound,rhogas,xi,yi,zi,temperaturei,eni=uui,& gamma_local=gammai,mu_local=mui,Xlocal=X_i,Zlocal=Z_i) @@ -283,7 +284,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& eos_vars(igasP,i) = p_on_rhogas*rhogas eos_vars(ics,i) = spsound eos_vars(itemp,i) = temperaturei - if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. update_muGamma or. (ieos==21)) eos_vars(imu,i) = mui + if (use_var_comp .or. eos_outputs_mu(ieos) .or. do_nucleation .or. update_muGamma) eos_vars(imu,i) = mui if (do_radiation) then if (temperaturei > tiny(0.)) then @@ -295,11 +296,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& ! ! Get the opacity from the density and temperature if required ! - if (iopacity_type == 3) then - call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i),u=vxyzu(4,i)) - elseif (iopacity_type > 0) then - call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i)) - endif + if (iopacity_type > 0) call get_opacity(iopacity_type,rhogas,temperaturei,radprop(ikappa,i)) endif ! ! Get radiation pressure from the radiation energy, i.e. P = 1/3 E if optically thick @@ -330,6 +327,10 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& ! if (mhd_nonideal) then Bi = sqrt(Bxi*Bxi + Byi*Byi + Bzi*Bzi) + ! sanity check the temperature + if (temperaturei < 1.) call warning('cons2prim',& + 'T < 1K in non-ideal MHD library',i,'T',temperaturei) + call nicil_update_nimhd(0,eta_nimhd(iohm,i),eta_nimhd(ihall,i),eta_nimhd(iambi,i), & Bi,rhoi,temperaturei,nden_nimhd(:,i),ierrlist) endif diff --git a/src/main/cons2primsolver.f90 b/src/main/cons2primsolver.f90 index af64a5e59..10e81529d 100644 --- a/src/main/cons2primsolver.f90 +++ b/src/main/cons2primsolver.f90 @@ -2,13 +2,17 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cons2primsolver ! -! None +! Internal routines containing the GR conservative to +! primitive variable solver, as described in section 7 +! of Liptai & Price (2019) ! -! :References: None +! :References: +! Liptai & Price (2019), MNRAS 485, 819 +! Tejeda (2012), PhD thesis, IAS Trieste ! ! :Owner: David Liptai ! diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 3c0817808..582838213 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling ! @@ -15,7 +15,7 @@ module cooling ! 5 = Koyama & Inutuska (2002) [explicit] ! 6 = Koyama & Inutuska (2002) [implicit] ! 7 = Gammie cooling power law [explicit] -! 8 = Stamatellos et al. (2007) [implicit] +! 9 = Stamatellos et al. (2007) [implicit] ! ! :References: ! Gail & Sedlmayr textbook Physics and chemistry of Circumstellar dust shells @@ -89,7 +89,7 @@ subroutine init_cooling(id,master,iprint,ierr) case(9) if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=9 requires ieos=21',& var='ieos',ival=ieos) - if (irealvisc > 0 .and. od_method == 2) call warning('cooling',& + 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) @@ -99,7 +99,6 @@ subroutine init_cooling(id,master,iprint,ierr) call fatal('cooling','Do radiation was switched on!') endif call init_star() - cooling_in_step = .false. case(6) call init_cooling_KI02(ierr) case(5) @@ -111,20 +110,22 @@ subroutine init_cooling(id,master,iprint,ierr) case(7) ! Gammie PL cooling_in_step = .false. + case(8) + cooling_in_step = .false. case default call init_cooling_solver(ierr) end select !--calculate the energy floor in code units - if (Tfloor > 0.) then + if (icooling == 9) then + ufloor = 0. ! because we calculate & use umin separately + elseif (Tfloor > 0.) then if (gamma > 1.) then ufloor = kboltz*Tfloor/((gamma-1.)*gmw*mass_proton_cgs)/unit_ergg else ufloor = 3.0*kboltz*Tfloor/(2.0*gmw*mass_proton_cgs)/unit_ergg endif if (maxvxyzu < 4) ierr = 1 - elseif (icooling == 9) then - ufloor = 0. ! because we calculate & use umin separately else ufloor = 0. endif @@ -136,9 +137,8 @@ end subroutine init_cooling ! this routine returns the effective cooling rate du/dt ! !----------------------------------------------------------------------- -! my version: subroutine energ_cooling(xi,yi,zi,ui,dudt,rho,dt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,dudti_sph,part_id) -subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,abund_in) +subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,abund_in,dudti_sph,part_id) use io, only:fatal use dim, only:nabundances use eos, only:gmw,gamma,ieos,get_temperature_from_u diff --git a/src/main/cooling_functions.f90 b/src/main/cooling_functions.f90 index 407f5d983..229afeaef 100644 --- a/src/main/cooling_functions.f90 +++ b/src/main/cooling_functions.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_functions ! diff --git a/src/main/cooling_gammie.f90 b/src/main/cooling_gammie.f90 index 0b36b09d8..3fffe3565 100644 --- a/src/main/cooling_gammie.f90 +++ b/src/main/cooling_gammie.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_gammie ! diff --git a/src/main/cooling_gammie_PL.f90 b/src/main/cooling_gammie_PL.f90 index 16a685a91..15ae40733 100644 --- a/src/main/cooling_gammie_PL.f90 +++ b/src/main/cooling_gammie_PL.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_gammie_PL ! diff --git a/src/main/cooling_ism.f90 b/src/main/cooling_ism.f90 index 21eaba17b..60d574c75 100644 --- a/src/main/cooling_ism.f90 +++ b/src/main/cooling_ism.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_ism ! diff --git a/src/main/cooling_koyamainutsuka.f90 b/src/main/cooling_koyamainutsuka.f90 index 1d1485153..eee002b73 100644 --- a/src/main/cooling_koyamainutsuka.f90 +++ b/src/main/cooling_koyamainutsuka.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_koyamainutsuka ! diff --git a/src/main/cooling_molecular.f90 b/src/main/cooling_molecular.f90 index 507c0eb55..48055b2c9 100644 --- a/src/main/cooling_molecular.f90 +++ b/src/main/cooling_molecular.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_molecular ! diff --git a/src/main/cooling_solver.f90 b/src/main/cooling_solver.f90 index 3eb2295fb..8775b5c7f 100644 --- a/src/main/cooling_solver.f90 +++ b/src/main/cooling_solver.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_solver ! diff --git a/src/main/cullendehnen.f90 b/src/main/cullendehnen.f90 index 11566c10c..5ebd2e7c9 100644 --- a/src/main/cullendehnen.f90 +++ b/src/main/cullendehnen.f90 @@ -2,13 +2,15 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cullendehnen ! -! cullendehnen +! Utility routines for the Cullen & Dehnen shock detection switch ! -! :References: None +! :References: +! Cullen & Dehnen (2010), MNRAS 408, 669 +! Price et al. (2018), PASA 35, e031 ! ! :Owner: Elisabeth Borchert ! @@ -26,7 +28,6 @@ module cullendehnen !+ !------------------------------------------------------------------------------- pure real function get_alphaloc(divvdti,spsoundi,hi,xi_limiter,alphamin,alphamax) - !use kernel, only:radkern real, intent(in) :: divvdti,spsoundi,hi,xi_limiter,alphamin,alphamax real :: source real :: temp @@ -62,7 +63,7 @@ pure real function xi_limiter(dvdx) fac = max(-divv,0.)**2 traceS = curlvx**2 + curlvy**2 + curlvz**2 - if (fac + traceS > 0.) then + if (fac + traceS > epsilon(0.)) then xi_limiter = fac/(fac + traceS) else xi_limiter = 1. diff --git a/src/main/datafiles.f90 b/src/main/datafiles.f90 index 4bef68eaa..b5f68a30d 100644 --- a/src/main/datafiles.f90 +++ b/src/main/datafiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module datafiles ! diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 238d68919..9204baaf0 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos ! @@ -1586,6 +1586,7 @@ subroutine read_options_eos(name,valstring,imatch,igotall,ierr) store_dust_temperature = .true. update_muGamma = .true. endif + if (ieos == 21) update_muGamma = .true. case('mu') read(valstring,*,iostat=ierr) gmw ! not compulsory to read in diff --git a/src/main/utils_indtimesteps.F90 b/src/main/utils_indtimesteps.F90 index d3262157f..14ad9f826 100644 --- a/src/main/utils_indtimesteps.F90 +++ b/src/main/utils_indtimesteps.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module timestep_ind ! @@ -43,7 +43,7 @@ pure real function get_dt(dtmax,ibini) real, intent(in) :: dtmax integer(kind=1), intent(in) :: ibini - get_dt = dtmax/2**ibini + get_dt = dtmax/2.**ibini end function get_dt diff --git a/src/main/utils_inject.f90 b/src/main/utils_inject.f90 index f1e7844e1..ca43b16ff 100644 --- a/src/main/utils_inject.f90 +++ b/src/main/utils_inject.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module injectutils ! diff --git a/src/main/utils_mathfunc.f90 b/src/main/utils_mathfunc.f90 index ee2fe826e..e133bdbb7 100644 --- a/src/main/utils_mathfunc.f90 +++ b/src/main/utils_mathfunc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mathfunc ! diff --git a/src/main/utils_omp.F90 b/src/main/utils_omp.F90 index c120e9f88..07b462298 100644 --- a/src/main/utils_omp.F90 +++ b/src/main/utils_omp.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module omputils ! diff --git a/src/main/utils_raytracer.f90 b/src/main/utils_raytracer.f90 index 8899cfa82..fe327480b 100644 --- a/src/main/utils_raytracer.f90 +++ b/src/main/utils_raytracer.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module raytracer ! diff --git a/src/main/utils_shuffleparticles.F90 b/src/main/utils_shuffleparticles.F90 index 7f9f9afe4..4d519b273 100644 --- a/src/main/utils_shuffleparticles.F90 +++ b/src/main/utils_shuffleparticles.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module utils_shuffleparticles ! diff --git a/src/main/utils_sort.f90 b/src/main/utils_sort.f90 index 627a347be..97031f2d2 100644 --- a/src/main/utils_sort.f90 +++ b/src/main/utils_sort.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module sortutils ! diff --git a/src/main/utils_sphNG.f90 b/src/main/utils_sphNG.f90 index 7f8240246..c0fe72c0a 100644 --- a/src/main/utils_sphNG.f90 +++ b/src/main/utils_sphNG.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module sphNGutils ! diff --git a/src/main/utils_spline.f90 b/src/main/utils_spline.f90 index bb6a14158..2d97899f7 100644 --- a/src/main/utils_spline.f90 +++ b/src/main/utils_spline.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module splineutils ! diff --git a/src/main/utils_summary.F90 b/src/main/utils_summary.F90 index 5b0ce0c63..e3c780c39 100644 --- a/src/main/utils_summary.F90 +++ b/src/main/utils_summary.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module io_summary ! diff --git a/src/main/utils_supertimestep.F90 b/src/main/utils_supertimestep.F90 index 7e255dcb0..4f59faa67 100644 --- a/src/main/utils_supertimestep.F90 +++ b/src/main/utils_supertimestep.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module timestep_sts ! diff --git a/src/main/utils_system.f90 b/src/main/utils_system.f90 index 82890cb0b..35c718e1b 100644 --- a/src/main/utils_system.f90 +++ b/src/main/utils_system.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module systemutils ! diff --git a/src/main/utils_tables.f90 b/src/main/utils_tables.f90 index 5e22b2359..47320b69c 100644 --- a/src/main/utils_tables.f90 +++ b/src/main/utils_tables.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module table_utils ! diff --git a/src/main/utils_vectors.f90 b/src/main/utils_vectors.f90 index e11805b38..e529d5f36 100644 --- a/src/main/utils_vectors.f90 +++ b/src/main/utils_vectors.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module vectorutils ! diff --git a/src/main/viscosity.f90 b/src/main/viscosity.f90 index fd8b2d4eb..114165a0e 100644 --- a/src/main/viscosity.f90 +++ b/src/main/viscosity.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module viscosity ! diff --git a/src/main/wind.F90 b/src/main/wind.F90 index 7997d3b9c..259e21e5c 100644 --- a/src/main/wind.F90 +++ b/src/main/wind.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module wind ! @@ -29,8 +29,8 @@ module wind private ! Shared variables - real, parameter :: Tdust_stop = 1.d-2 ! Temperature at outer boundary of wind simulation - real, parameter :: dtmin = 1.d-3 ! Minimum allowed timsestep (for 1D integration) + real, parameter :: Tdust_stop = 0.01 ! Temperature at outer boundary of wind simulation + real, parameter :: dtmin = 1.d-3 ! Minimum allowed timsestep (for 1D integration) integer, parameter :: wind_emitting_sink = 1 character(len=*), parameter :: label = 'wind' @@ -67,7 +67,7 @@ subroutine setup_wind(Mstar_cg, Mdot_code, u_to_T, r0, T0, v0, rsonic, tsonic, s Mstar_cgs = Mstar_cg wind_gamma = gamma - Mdot_cgs = Mdot_code * umass/utime + Mdot_cgs = real(Mdot_code * umass/utime) u_to_temperature_ratio = u_to_T if (idust_opacity == 2) then @@ -121,14 +121,14 @@ subroutine init_wind(r0, v0, T0, time_end, state, tau_lucy_init) Mstar_cgs = xyzmh_ptmass(4,wind_emitting_sink)*umass state%dt = 1000. - if (time_end > 0.d0) then + if (time_end > 0.) then ! integration stops when time = time_end state%find_sonic_solution = .false. state%time_end = time_end else ! integration stops once the sonic point is reached state%find_sonic_solution = .true. - state%time_end = -1.d0 + state%time_end = -1. endif state%time = 0. state%r_old = 0. @@ -315,7 +315,7 @@ subroutine wind_step(state) call calc_cooling_rate(Q_code,dlnQ_dlnT,state%rho/unit_density,state%Tg,state%Tdust,& state%mu,state%gamma,state%K2,state%kappa) state%Q = Q_code*unit_ergg - state%dQ_dr = (state%Q-Q_old)/(1.d-10+state%r-state%r_old) + state%dQ_dr = (state%Q-Q_old)/(1.e-10+state%r-state%r_old) endif state%time = state%time + state%dt @@ -446,10 +446,10 @@ subroutine wind_step(state) !apply cooling if (icooling > 0) then Q_old = state%Q - call calc_cooling_rate(Q_code,dlnQ_dlnT,state%rho/unit_density,state%Tg,state%Tdust,& + call calc_cooling_rate(Q_code,dlnQ_dlnT,real(state%rho/unit_density),state%Tg,state%Tdust,& state%mu,state%gamma,state%K2,state%kappa) state%Q = Q_code*unit_ergg - state%dQ_dr = (state%Q-Q_old)/(1.d-10+state%r-state%r_old) + state%dQ_dr = (state%Q-Q_old)/(1.e-10+state%r-state%r_old) endif if (state%time_end > 0. .and. state%time + state%dt > state%time_end) then @@ -915,7 +915,7 @@ subroutine interp_wind_profile(time, local_time, r, v, u, rho, e, GM, fdone, JKm e = .5*v**2 - GM/r + gammai*u if (local_time == 0.) then - fdone = 1.d0 + fdone = 1. else fdone = ltime/(local_time*utime) endif @@ -934,7 +934,7 @@ subroutine save_windprofile(r0, v0, T0, rout, tend, tcross, filename) real, intent(in) :: r0, v0, T0, tend, rout real, intent(out) :: tcross !time to cross the entire integration domain character(*), intent(in) :: filename - real, parameter :: Tdust_stop = 1.d0 ! Temperature at outer boundary of wind simulation + real, parameter :: Tdust_stop = 1. ! Temperature at outer boundary of wind simulation integer, parameter :: nlmax = 8192 ! maxium number of steps store in the 1D profile real :: time_end, tau_lucy_init real :: r_incr,v_incr,T_incr,mu_incr,gamma_incr,r_base,v_base,T_base,mu_base,gamma_base,eps @@ -963,7 +963,7 @@ subroutine save_windprofile(r0, v0, T0, rout, tend, tcross, filename) eps = 0.01 iter = 0 itermax = int(huge(itermax)/10.) !this number is huge but may be needed for RK6 solver - tcross = 1.d99 + tcross = huge(0.) writeline = 0 r_base = state%r diff --git a/src/main/wind_equations.f90 b/src/main/wind_equations.f90 index a42ae4dbc..ac0a78922 100644 --- a/src/main/wind_equations.f90 +++ b/src/main/wind_equations.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module wind_equations ! @@ -109,10 +109,10 @@ subroutine evolve_hydro(dt, rvT, Rstar_cgs, Mdot_cgs, mu, gamma, alpha, dalpha_d rvT = new_rvT !constrain timestep so the changes in r,v & T do not exceed dt_tol - dt_next = min(dt_next,1.d-2*au/new_rvt(2),& - dt_tol*dt*abs(rvt(1)/(1.d-10+(new_rvt(1)-rvt(1)))),& - dt_tol*dt*abs(rvt(2)/(1.d-10+(new_rvt(2)-rvt(2)))),& - dt_tol*dt*abs(rvt(3)/(1.d-10+(new_rvt(3)-rvt(3))))) + dt_next = min(dt_next,1e-2*real(au/new_rvt(2)),& + dt_tol*dt*abs(rvt(1)/(1e-10+(new_rvt(1)-rvt(1)))),& + dt_tol*dt*abs(rvt(2)/(1e-10+(new_rvt(2)-rvt(2)))),& + dt_tol*dt*abs(rvt(3)/(1e-10+(new_rvt(3)-rvt(3))))) spcode = 0 if (numerator < -num_tol .and. denominator > -denom_tol) spcode = 1 !no solution for stationary wind diff --git a/src/main/writeheader.F90 b/src/main/writeheader.F90 index 1eb9ab6d4..0d32e639b 100644 --- a/src/main/writeheader.F90 +++ b/src/main/writeheader.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module writeheader ! diff --git a/src/utils/acc2ang.f90 b/src/utils/acc2ang.f90 index df76f6491..56058bbb5 100644 --- a/src/utils/acc2ang.f90 +++ b/src/utils/acc2ang.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program get_ang ! diff --git a/src/utils/adaptivemesh.f90 b/src/utils/adaptivemesh.f90 index 21fd65cc4..2072329a5 100644 --- a/src/utils/adaptivemesh.f90 +++ b/src/utils/adaptivemesh.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module adaptivemesh ! diff --git a/src/utils/analysis_1particle.f90 b/src/utils/analysis_1particle.f90 index b2cb53133..eb96fac59 100644 --- a/src/utils/analysis_1particle.f90 +++ b/src/utils/analysis_1particle.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_CoM.f90 b/src/utils/analysis_CoM.f90 index 3410eb43b..199caa247 100644 --- a/src/utils/analysis_CoM.f90 +++ b/src/utils/analysis_CoM.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_GalMerger.f90 b/src/utils/analysis_GalMerger.f90 index 8933337c5..4dc4d3352 100644 --- a/src/utils/analysis_GalMerger.f90 +++ b/src/utils/analysis_GalMerger.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_MWpdf.f90 b/src/utils/analysis_MWpdf.f90 index 2bdc9edf8..84f49013c 100644 --- a/src/utils/analysis_MWpdf.f90 +++ b/src/utils/analysis_MWpdf.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_NSmerger.f90 b/src/utils/analysis_NSmerger.f90 index 1f78050cf..053402dff 100644 --- a/src/utils/analysis_NSmerger.f90 +++ b/src/utils/analysis_NSmerger.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_alpha.f90 b/src/utils/analysis_alpha.f90 index 9bd33f774..d96f6fe49 100644 --- a/src/utils/analysis_alpha.f90 +++ b/src/utils/analysis_alpha.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_angmom.f90 b/src/utils/analysis_angmom.f90 index 960439d11..f27a87c2c 100644 --- a/src/utils/analysis_angmom.f90 +++ b/src/utils/analysis_angmom.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_angmomvec.f90 b/src/utils/analysis_angmomvec.f90 index 7bafc874b..31c6d6c3d 100644 --- a/src/utils/analysis_angmomvec.f90 +++ b/src/utils/analysis_angmomvec.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_average_orb_en.f90 b/src/utils/analysis_average_orb_en.f90 index fa6047ca7..f9c99a3af 100644 --- a/src/utils/analysis_average_orb_en.f90 +++ b/src/utils/analysis_average_orb_en.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_binarydisc.f90 b/src/utils/analysis_binarydisc.f90 index c71d0912a..0894b7133 100644 --- a/src/utils/analysis_binarydisc.f90 +++ b/src/utils/analysis_binarydisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! @@ -482,7 +482,7 @@ end subroutine read_dotin !----------------------------------------------------------------------- subroutine get_binary_params(ipri,isec,xyzmh_ptmass,vxyz_ptmass,time,a,ecc,G) !----------------------------------------------------------------------- - use io, only:fatal + use io, only:fatal,warning implicit none @@ -516,7 +516,7 @@ subroutine get_binary_params(ipri,isec,xyzmh_ptmass,vxyz_ptmass,time,a,ecc,G) Lmag = sqrt(dot_product(L,L)) E = 0.5*dot_product(dv,dv) - G*(mpri+msec)/rbin - if (abs(E) < tiny(E)) stop 'binary energy problem' + if (abs(E) < tiny(E)) call warning(analysistype, 'E=0 for binary') call get_ae(Lmag,E,mpri,msec,a,ecc) if (time <= tiny(time)) then @@ -548,7 +548,6 @@ subroutine get_ae(Lmag,E,m1,m2,a,ecc) real,intent(in) :: Lmag,E,m1,m2 if (Lmag < tiny(Lmag)) stop 'Lmag is zero in get_ae' - if (abs(E) < tiny(E)) stop 'E is zero in get_ae' ! Hence obtain the binary eccentricity ecc = sqrt(1.0 + (2.0*E*Lmag**2)/((m1+m2)**2)) diff --git a/src/utils/analysis_bzrms.f90 b/src/utils/analysis_bzrms.f90 index d314f6807..e5b6443e2 100644 --- a/src/utils/analysis_bzrms.f90 +++ b/src/utils/analysis_bzrms.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_collidingcloudevolution.f90 b/src/utils/analysis_collidingcloudevolution.f90 index da9125d01..52cfdec52 100644 --- a/src/utils/analysis_collidingcloudevolution.f90 +++ b/src/utils/analysis_collidingcloudevolution.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_collidingcloudhistograms.f90 b/src/utils/analysis_collidingcloudhistograms.f90 index bf60b57bf..c17daaddb 100644 --- a/src/utils/analysis_collidingcloudhistograms.f90 +++ b/src/utils/analysis_collidingcloudhistograms.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_cooling.f90 b/src/utils/analysis_cooling.f90 index e97271720..ed70fc07e 100644 --- a/src/utils/analysis_cooling.f90 +++ b/src/utils/analysis_cooling.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc.f90 b/src/utils/analysis_disc.f90 index 053466f37..1f3e9f07f 100644 --- a/src/utils/analysis_disc.f90 +++ b/src/utils/analysis_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_MFlow.f90 b/src/utils/analysis_disc_MFlow.f90 index 170dd1fb5..9cb995cae 100644 --- a/src/utils/analysis_disc_MFlow.f90 +++ b/src/utils/analysis_disc_MFlow.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_eccentric.f90 b/src/utils/analysis_disc_eccentric.f90 index e203204e1..caf029f94 100644 --- a/src/utils/analysis_disc_eccentric.f90 +++ b/src/utils/analysis_disc_eccentric.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_mag.f90 b/src/utils/analysis_disc_mag.f90 index d0ad3a51a..10f91136d 100644 --- a/src/utils/analysis_disc_mag.f90 +++ b/src/utils/analysis_disc_mag.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_planet.f90 b/src/utils/analysis_disc_planet.f90 index bf267ae92..aad84a586 100644 --- a/src/utils/analysis_disc_planet.f90 +++ b/src/utils/analysis_disc_planet.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index 5b375c92d..f6ffe0648 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_dtheader.f90 b/src/utils/analysis_dtheader.f90 index 51e0ab65b..d36b73452 100644 --- a/src/utils/analysis_dtheader.f90 +++ b/src/utils/analysis_dtheader.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_dustmass.f90 b/src/utils/analysis_dustmass.f90 index 07cea5567..a072aedbe 100644 --- a/src/utils/analysis_dustmass.f90 +++ b/src/utils/analysis_dustmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_dustydisc.f90 b/src/utils/analysis_dustydisc.f90 index 7824cfacf..c7f2d879b 100644 --- a/src/utils/analysis_dustydisc.f90 +++ b/src/utils/analysis_dustydisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_etotgr.f90 b/src/utils/analysis_etotgr.f90 index 9acfbed46..be1a500aa 100644 --- a/src/utils/analysis_etotgr.f90 +++ b/src/utils/analysis_etotgr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_getneighbours.f90 b/src/utils/analysis_getneighbours.f90 index 021ddb8e7..fb20606c7 100644 --- a/src/utils/analysis_getneighbours.f90 +++ b/src/utils/analysis_getneighbours.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_gws.f90 b/src/utils/analysis_gws.f90 index 9ca705e63..9be0e4330 100644 --- a/src/utils/analysis_gws.f90 +++ b/src/utils/analysis_gws.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_jet.f90 b/src/utils/analysis_jet.f90 index 8cffd8658..86c86dca8 100644 --- a/src/utils/analysis_jet.f90 +++ b/src/utils/analysis_jet.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_kepler.f90 b/src/utils/analysis_kepler.f90 index 9ed372f14..e6e63d942 100644 --- a/src/utils/analysis_kepler.f90 +++ b/src/utils/analysis_kepler.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_macctrace.f90 b/src/utils/analysis_macctrace.f90 index 9699bdcb5..26b1e224c 100644 --- a/src/utils/analysis_macctrace.f90 +++ b/src/utils/analysis_macctrace.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_mapping_mass.f90 b/src/utils/analysis_mapping_mass.f90 index 5e0c2ea84..892b5fb4c 100644 --- a/src/utils/analysis_mapping_mass.f90 +++ b/src/utils/analysis_mapping_mass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_mcfost.f90 b/src/utils/analysis_mcfost.f90 index 1f323a9e3..05259161b 100644 --- a/src/utils/analysis_mcfost.f90 +++ b/src/utils/analysis_mcfost.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_mcfostcmdline.f90 b/src/utils/analysis_mcfostcmdline.f90 index 23c2c70f4..2e3b10dc9 100644 --- a/src/utils/analysis_mcfostcmdline.f90 +++ b/src/utils/analysis_mcfostcmdline.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_pairing.f90 b/src/utils/analysis_pairing.f90 index 539822289..fbef57fe5 100644 --- a/src/utils/analysis_pairing.f90 +++ b/src/utils/analysis_pairing.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_particle.f90 b/src/utils/analysis_particle.f90 index 88df31857..5691ff0a9 100644 --- a/src/utils/analysis_particle.f90 +++ b/src/utils/analysis_particle.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_pdfs.f90 b/src/utils/analysis_pdfs.f90 index 0846c6264..96c64fc73 100644 --- a/src/utils/analysis_pdfs.f90 +++ b/src/utils/analysis_pdfs.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_phantom_dump.f90 b/src/utils/analysis_phantom_dump.f90 index 64dca841d..0ffc60048 100644 --- a/src/utils/analysis_phantom_dump.f90 +++ b/src/utils/analysis_phantom_dump.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_polytropes.f90 b/src/utils/analysis_polytropes.f90 index fa8df727f..bd0c57df8 100644 --- a/src/utils/analysis_polytropes.f90 +++ b/src/utils/analysis_polytropes.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_prdrag.f90 b/src/utils/analysis_prdrag.f90 index ddd71172b..14160df8a 100644 --- a/src/utils/analysis_prdrag.f90 +++ b/src/utils/analysis_prdrag.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_ptmass.f90 b/src/utils/analysis_ptmass.f90 index 79f013b42..85477e1d4 100644 --- a/src/utils/analysis_ptmass.f90 +++ b/src/utils/analysis_ptmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_raytracer.f90 b/src/utils/analysis_raytracer.f90 index b8197dbfb..2a8305c9e 100644 --- a/src/utils/analysis_raytracer.f90 +++ b/src/utils/analysis_raytracer.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_sinkmass.f90 b/src/utils/analysis_sinkmass.f90 index d5b8bb38a..7993d3664 100644 --- a/src/utils/analysis_sinkmass.f90 +++ b/src/utils/analysis_sinkmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_sphere.f90 b/src/utils/analysis_sphere.f90 index 3a4ee3f7b..837a5257a 100644 --- a/src/utils/analysis_sphere.f90 +++ b/src/utils/analysis_sphere.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_structurefn.f90 b/src/utils/analysis_structurefn.f90 index c93e77b2d..0e91bedde 100644 --- a/src/utils/analysis_structurefn.f90 +++ b/src/utils/analysis_structurefn.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_tde.f90 b/src/utils/analysis_tde.f90 index cacc90c70..e0aa5ae7e 100644 --- a/src/utils/analysis_tde.f90 +++ b/src/utils/analysis_tde.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_torus.f90 b/src/utils/analysis_torus.f90 index 83cadc742..f6a745703 100644 --- a/src/utils/analysis_torus.f90 +++ b/src/utils/analysis_torus.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_trackbox.f90 b/src/utils/analysis_trackbox.f90 index 3bbd3193b..efbe6e251 100644 --- a/src/utils/analysis_trackbox.f90 +++ b/src/utils/analysis_trackbox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_tracks.f90 b/src/utils/analysis_tracks.f90 index 48ef90829..3812cc3b4 100644 --- a/src/utils/analysis_tracks.f90 +++ b/src/utils/analysis_tracks.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_velocitydispersion_vs_scale.f90 b/src/utils/analysis_velocitydispersion_vs_scale.f90 index e96af593f..7bd2daa9d 100644 --- a/src/utils/analysis_velocitydispersion_vs_scale.f90 +++ b/src/utils/analysis_velocitydispersion_vs_scale.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_velocityshear.f90 b/src/utils/analysis_velocityshear.f90 index 3c56397a8..16637d2d6 100644 --- a/src/utils/analysis_velocityshear.f90 +++ b/src/utils/analysis_velocityshear.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/combinedustdumps.f90 b/src/utils/combinedustdumps.f90 index 3a675c463..7dbbdf2d5 100755 --- a/src/utils/combinedustdumps.f90 +++ b/src/utils/combinedustdumps.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program combinedustdumps ! diff --git a/src/utils/cubicsolve.f90 b/src/utils/cubicsolve.f90 index 46db8aad2..3d88f97f5 100644 --- a/src/utils/cubicsolve.f90 +++ b/src/utils/cubicsolve.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cubic ! diff --git a/src/utils/diffdumps.f90 b/src/utils/diffdumps.f90 index c54a093ba..9423c6960 100644 --- a/src/utils/diffdumps.f90 +++ b/src/utils/diffdumps.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program diffdumps ! diff --git a/src/utils/dustywaves.f90 b/src/utils/dustywaves.f90 index af14457ed..2d671513f 100644 --- a/src/utils/dustywaves.f90 +++ b/src/utils/dustywaves.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module dustywaves ! diff --git a/src/utils/ev2kdot.f90 b/src/utils/ev2kdot.f90 index 1e32e39ca..dced7d521 100644 --- a/src/utils/ev2kdot.f90 +++ b/src/utils/ev2kdot.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program get_kdot ! diff --git a/src/utils/ev2mdot.f90 b/src/utils/ev2mdot.f90 index e9f899484..40374442b 100644 --- a/src/utils/ev2mdot.f90 +++ b/src/utils/ev2mdot.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program get_mdot ! diff --git a/src/utils/evol_dustywaves.f90 b/src/utils/evol_dustywaves.f90 index 777c3e67d..e9584604c 100644 --- a/src/utils/evol_dustywaves.f90 +++ b/src/utils/evol_dustywaves.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program ekin ! diff --git a/src/utils/get_struct_slope.f90 b/src/utils/get_struct_slope.f90 index 157d82e18..789e39854 100644 --- a/src/utils/get_struct_slope.f90 +++ b/src/utils/get_struct_slope.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program get_struct_slope ! diff --git a/src/utils/getmathflags.f90 b/src/utils/getmathflags.f90 index f5800c35c..fbe9f872e 100644 --- a/src/utils/getmathflags.f90 +++ b/src/utils/getmathflags.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program getmathflags ! diff --git a/src/utils/grid2pdf.f90 b/src/utils/grid2pdf.f90 index 262f40216..8ae7ad563 100644 --- a/src/utils/grid2pdf.f90 +++ b/src/utils/grid2pdf.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program grid2pdf ! diff --git a/src/utils/hdf5utils.f90 b/src/utils/hdf5utils.f90 index fbbed0413..34031f068 100644 --- a/src/utils/hdf5utils.f90 +++ b/src/utils/hdf5utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module hdf5utils ! diff --git a/src/utils/icosahedron.f90 b/src/utils/icosahedron.f90 index 9ac9dbada..d0b00c594 100644 --- a/src/utils/icosahedron.f90 +++ b/src/utils/icosahedron.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module icosahedron ! diff --git a/src/utils/io_grid.f90 b/src/utils/io_grid.f90 index 9e74dfe43..a54cec7fe 100644 --- a/src/utils/io_grid.f90 +++ b/src/utils/io_grid.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module io_grid ! diff --git a/src/utils/io_structurefn.f90 b/src/utils/io_structurefn.f90 index e91667800..ca736c360 100644 --- a/src/utils/io_structurefn.f90 +++ b/src/utils/io_structurefn.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module io_structurefn ! diff --git a/src/utils/leastsquares.f90 b/src/utils/leastsquares.f90 index 644985262..f71fd3473 100644 --- a/src/utils/leastsquares.f90 +++ b/src/utils/leastsquares.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module leastsquares ! diff --git a/src/utils/libphantom-splash.f90 b/src/utils/libphantom-splash.f90 index 37063007d..2c0fc772a 100644 --- a/src/utils/libphantom-splash.f90 +++ b/src/utils/libphantom-splash.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module libphantomsplash ! diff --git a/src/utils/lombperiod.f90 b/src/utils/lombperiod.f90 index 295dc7147..d9b7a668e 100644 --- a/src/utils/lombperiod.f90 +++ b/src/utils/lombperiod.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program lombperiod ! diff --git a/src/utils/mflow.f90 b/src/utils/mflow.f90 index 163ef7eec..ea284e3fa 100644 --- a/src/utils/mflow.f90 +++ b/src/utils/mflow.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program mflow ! diff --git a/src/utils/moddump_CoM.f90 b/src/utils/moddump_CoM.f90 index 13ea42ec8..72df6ef41 100644 --- a/src/utils/moddump_CoM.f90 +++ b/src/utils/moddump_CoM.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_addflyby.f90 b/src/utils/moddump_addflyby.f90 index 350e2db20..59bb9ca36 100644 --- a/src/utils/moddump_addflyby.f90 +++ b/src/utils/moddump_addflyby.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_addplanets.f90 b/src/utils/moddump_addplanets.f90 index ee71c218d..9f913bb0c 100644 --- a/src/utils/moddump_addplanets.f90 +++ b/src/utils/moddump_addplanets.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_binary.f90 b/src/utils/moddump_binary.f90 index 03e7ec38d..c4c1077c3 100644 --- a/src/utils/moddump_binary.f90 +++ b/src/utils/moddump_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_binarystar.f90 b/src/utils/moddump_binarystar.f90 index 27e9fbc42..4e15def00 100644 --- a/src/utils/moddump_binarystar.f90 +++ b/src/utils/moddump_binarystar.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_changemass.f90 b/src/utils/moddump_changemass.f90 index 7d8acfa6f..a407d17e7 100644 --- a/src/utils/moddump_changemass.f90 +++ b/src/utils/moddump_changemass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_default.f90 b/src/utils/moddump_default.f90 index 076fb2b9b..0ae0f2a97 100644 --- a/src/utils/moddump_default.f90 +++ b/src/utils/moddump_default.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_disc.f90 b/src/utils/moddump_disc.f90 index fb9157e68..13a7bd473 100644 --- a/src/utils/moddump_disc.f90 +++ b/src/utils/moddump_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_dustadd.f90 b/src/utils/moddump_dustadd.f90 index dc9fb58f9..588a74707 100644 --- a/src/utils/moddump_dustadd.f90 +++ b/src/utils/moddump_dustadd.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_extenddisc.f90 b/src/utils/moddump_extenddisc.f90 index 1998cfa5c..1f16281da 100644 --- a/src/utils/moddump_extenddisc.f90 +++ b/src/utils/moddump_extenddisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_growthtomultigrain.f90 b/src/utils/moddump_growthtomultigrain.f90 index 5574e9cc0..0c5e599df 100644 --- a/src/utils/moddump_growthtomultigrain.f90 +++ b/src/utils/moddump_growthtomultigrain.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_mergepart.f90 b/src/utils/moddump_mergepart.f90 index 813d6cf56..17d42b67b 100644 --- a/src/utils/moddump_mergepart.f90 +++ b/src/utils/moddump_mergepart.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_messupSPH.f90 b/src/utils/moddump_messupSPH.f90 index 5cbc89761..1f0b8a257 100644 --- a/src/utils/moddump_messupSPH.f90 +++ b/src/utils/moddump_messupSPH.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_perturbgas.f90 b/src/utils/moddump_perturbgas.f90 index 44562425a..8e895aafa 100644 --- a/src/utils/moddump_perturbgas.f90 +++ b/src/utils/moddump_perturbgas.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_polytrope.f90 b/src/utils/moddump_polytrope.f90 index 7e8b9e5bd..ed9554b90 100644 --- a/src/utils/moddump_polytrope.f90 +++ b/src/utils/moddump_polytrope.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_rad_to_LTE.f90 b/src/utils/moddump_rad_to_LTE.f90 index a2abc1295..7b14b0ee0 100644 --- a/src/utils/moddump_rad_to_LTE.f90 +++ b/src/utils/moddump_rad_to_LTE.f90 @@ -2,11 +2,11 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! -! moddump +! Convert radiation dump to LTE dump (ieos=12) ! ! :References: None ! diff --git a/src/utils/moddump_recalcuT.f90 b/src/utils/moddump_recalcuT.f90 index 5aa1792a7..814c275cf 100644 --- a/src/utils/moddump_recalcuT.f90 +++ b/src/utils/moddump_recalcuT.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_removeparticles_cylinder.f90 b/src/utils/moddump_removeparticles_cylinder.f90 index faca53808..eed6b214f 100644 --- a/src/utils/moddump_removeparticles_cylinder.f90 +++ b/src/utils/moddump_removeparticles_cylinder.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_removeparticles_radius.f90 b/src/utils/moddump_removeparticles_radius.f90 index 53a2e0cd6..d9bbd3e94 100644 --- a/src/utils/moddump_removeparticles_radius.f90 +++ b/src/utils/moddump_removeparticles_radius.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_rotate.f90 b/src/utils/moddump_rotate.f90 index 8cf4cca41..34a6a069f 100644 --- a/src/utils/moddump_rotate.f90 +++ b/src/utils/moddump_rotate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sink.f90 b/src/utils/moddump_sink.f90 index 4cbf7c449..444a45e22 100644 --- a/src/utils/moddump_sink.f90 +++ b/src/utils/moddump_sink.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! @@ -77,7 +77,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) xyzmh_ptmass(1,isinkpart) = newx print*,'x-coordinate changed to ',xyzmh_ptmass(1,isinkpart) - Lnuc = xyzmh_ptmass(1,ilum) + Lnuc = xyzmh_ptmass(ilum,isinkpart) Lnuc_cgs = Lnuc * unit_energ / utime call prompt('Enter new sink heating luminosity in erg/s:',Lnuc_cgs,0.) xyzmh_ptmass(ilum,isinkpart) = Lnuc_cgs / unit_energ * utime diff --git a/src/utils/moddump_sinkbinary.f90 b/src/utils/moddump_sinkbinary.f90 index 94a73f429..46a128db7 100644 --- a/src/utils/moddump_sinkbinary.f90 +++ b/src/utils/moddump_sinkbinary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sphNG2phantom.f90 b/src/utils/moddump_sphNG2phantom.f90 index 682843b10..ad1b1feb7 100644 --- a/src/utils/moddump_sphNG2phantom.f90 +++ b/src/utils/moddump_sphNG2phantom.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sphNG2phantom_addBfield.f90 b/src/utils/moddump_sphNG2phantom_addBfield.f90 index 423925306..e33c1cb92 100644 --- a/src/utils/moddump_sphNG2phantom_addBfield.f90 +++ b/src/utils/moddump_sphNG2phantom_addBfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_sphNG2phantom_disc.f90 b/src/utils/moddump_sphNG2phantom_disc.f90 index d274101eb..833b765cf 100644 --- a/src/utils/moddump_sphNG2phantom_disc.f90 +++ b/src/utils/moddump_sphNG2phantom_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_splitpart.f90 b/src/utils/moddump_splitpart.f90 index a3cb83619..9f932cffc 100644 --- a/src/utils/moddump_splitpart.f90 +++ b/src/utils/moddump_splitpart.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_taylorgreen.f90 b/src/utils/moddump_taylorgreen.f90 index 3d3630111..f165d49b6 100644 --- a/src/utils/moddump_taylorgreen.f90 +++ b/src/utils/moddump_taylorgreen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_tidal.f90 b/src/utils/moddump_tidal.f90 index 35db33aae..a4a1b4b51 100644 --- a/src/utils/moddump_tidal.f90 +++ b/src/utils/moddump_tidal.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/moddump_torus.f90 b/src/utils/moddump_torus.f90 index 241a124af..3de87ae9a 100644 --- a/src/utils/moddump_torus.f90 +++ b/src/utils/moddump_torus.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module moddump ! diff --git a/src/utils/multirun.f90 b/src/utils/multirun.f90 index 8bf04032e..5536cdcf5 100644 --- a/src/utils/multirun.f90 +++ b/src/utils/multirun.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program multirun ! diff --git a/src/utils/multirun_mach.f90 b/src/utils/multirun_mach.f90 index 6e6407880..df2cb5b97 100644 --- a/src/utils/multirun_mach.f90 +++ b/src/utils/multirun_mach.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program multirun ! diff --git a/src/utils/pdfs.f90 b/src/utils/pdfs.f90 index 93bbe84dc..fd306041d 100644 --- a/src/utils/pdfs.f90 +++ b/src/utils/pdfs.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module pdfs ! diff --git a/src/utils/phantom2divb.f90 b/src/utils/phantom2divb.f90 index 88ea4e22f..cac56bccd 100644 --- a/src/utils/phantom2divb.f90 +++ b/src/utils/phantom2divb.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantom2divb ! diff --git a/src/utils/phantom2divv.f90 b/src/utils/phantom2divv.f90 index 613c932cf..0befaad7d 100644 --- a/src/utils/phantom2divv.f90 +++ b/src/utils/phantom2divv.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantom2divv ! diff --git a/src/utils/phantom2gadget.f90 b/src/utils/phantom2gadget.f90 index 77422aaef..1681ff9cc 100644 --- a/src/utils/phantom2gadget.f90 +++ b/src/utils/phantom2gadget.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantom2gadget ! diff --git a/src/utils/phantom2hdf5.f90 b/src/utils/phantom2hdf5.f90 index 6d327dba2..d4d032e0c 100644 --- a/src/utils/phantom2hdf5.f90 +++ b/src/utils/phantom2hdf5.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantom2hdf5 ! diff --git a/src/utils/phantom2sphNG.f90 b/src/utils/phantom2sphNG.f90 index f0717c272..b4532fbef 100644 --- a/src/utils/phantom2sphNG.f90 +++ b/src/utils/phantom2sphNG.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantom2sphNG ! diff --git a/src/utils/phantom_moddump.f90 b/src/utils/phantom_moddump.f90 index 0ec474738..a6ed9bb0d 100644 --- a/src/utils/phantom_moddump.f90 +++ b/src/utils/phantom_moddump.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantommoddump ! diff --git a/src/utils/phantomanalysis.f90 b/src/utils/phantomanalysis.f90 index 60c16c288..a0b88c2d2 100644 --- a/src/utils/phantomanalysis.f90 +++ b/src/utils/phantomanalysis.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantomanalysis ! @@ -58,7 +58,8 @@ program phantomanalysis ! if (iarg==1) then - iloc = index(dumpfile,'_0') + !iloc = index(dumpfile,'_0') + iloc = index(dumpfile,'_',.true.) !to load dump > 9999 if (iloc > 1) then fileprefix = trim(dumpfile(1:iloc-1)) diff --git a/src/utils/phantomevcompare.f90 b/src/utils/phantomevcompare.f90 index 7cc6d7339..8a0d15062 100644 --- a/src/utils/phantomevcompare.f90 +++ b/src/utils/phantomevcompare.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantomevcompare ! diff --git a/src/utils/phantomextractsinks.f90 b/src/utils/phantomextractsinks.f90 index 158f6ecd6..1e4577fde 100644 --- a/src/utils/phantomextractsinks.f90 +++ b/src/utils/phantomextractsinks.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantomextractsinks ! diff --git a/src/utils/plot_kernel.f90 b/src/utils/plot_kernel.f90 index bf6525be9..35b176884 100644 --- a/src/utils/plot_kernel.f90 +++ b/src/utils/plot_kernel.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program plot_kernel ! diff --git a/src/utils/powerspectrums.f90 b/src/utils/powerspectrums.f90 index 446c128cd..0ffd56515 100644 --- a/src/utils/powerspectrums.f90 +++ b/src/utils/powerspectrums.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module powerspectrums ! diff --git a/src/utils/prompting.f90 b/src/utils/prompting.f90 index 7150a9045..c87e5f77c 100644 --- a/src/utils/prompting.f90 +++ b/src/utils/prompting.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module prompting ! diff --git a/src/utils/quartic.f90 b/src/utils/quartic.f90 index 2ac30de9f..4ae9ee375 100644 --- a/src/utils/quartic.f90 +++ b/src/utils/quartic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module quartic ! diff --git a/src/utils/rhomach.f90 b/src/utils/rhomach.f90 index 730f96a85..8164eb3a2 100644 --- a/src/utils/rhomach.f90 +++ b/src/utils/rhomach.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module rhomach ! diff --git a/src/utils/showarrays.f90 b/src/utils/showarrays.f90 index e3cb34833..64762b59c 100644 --- a/src/utils/showarrays.f90 +++ b/src/utils/showarrays.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program showarrays ! diff --git a/src/utils/showheader.f90 b/src/utils/showheader.f90 index 9e6b797b6..b70b1a884 100644 --- a/src/utils/showheader.f90 +++ b/src/utils/showheader.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program showheader ! @@ -43,7 +43,7 @@ program showheader ! try to open it as a small dump close(iu) call open_dumpfile_r(iu,dumpfile,fileid,ierr,singleprec=.true.) - if (ierr == 0) call read_header(iu,hdr,.true.,ierr,singleprec=.true.) + if (ierr == 0) call read_header(iu,hdr,ierr,singleprec=.true.) else print "(a)",' ERROR opening '//trim(dumpfile) endif @@ -51,7 +51,7 @@ program showheader ! ! read and print the file header ! - call read_header(iu,hdr,.true.,ierr) + call read_header(iu,hdr,ierr) endif if (ierr == 0) then if (nargs > 1) print "(/,':: ',a,' ::',/)",trim(dumpfile) diff --git a/src/utils/solvelinearsystem.f90 b/src/utils/solvelinearsystem.f90 index a74d3b407..fefb6c08e 100644 --- a/src/utils/solvelinearsystem.f90 +++ b/src/utils/solvelinearsystem.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module solvelinearsystem ! diff --git a/src/utils/splitpart.f90 b/src/utils/splitpart.f90 index bde83db10..c6847e607 100644 --- a/src/utils/splitpart.f90 +++ b/src/utils/splitpart.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module splitpart ! diff --git a/src/utils/struct2struct.f90 b/src/utils/struct2struct.f90 index bc7470b63..2d22707f3 100644 --- a/src/utils/struct2struct.f90 +++ b/src/utils/struct2struct.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program struct2struct ! diff --git a/src/utils/test_binary.f90 b/src/utils/test_binary.f90 index ca149e2bd..4dd432524 100644 --- a/src/utils/test_binary.f90 +++ b/src/utils/test_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testbinary ! diff --git a/src/utils/testbinary.f90 b/src/utils/testbinary.f90 index a58d51db3..f7da761f8 100644 --- a/src/utils/testbinary.f90 +++ b/src/utils/testbinary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program testbin ! diff --git a/src/utils/utils_disc.f90 b/src/utils/utils_disc.f90 index b38f09bd9..91b783c29 100644 --- a/src/utils/utils_disc.f90 +++ b/src/utils/utils_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module discanalysisutils ! diff --git a/src/utils/utils_ephemeris.f90 b/src/utils/utils_ephemeris.f90 index fe9666b07..c6d0a689c 100644 --- a/src/utils/utils_ephemeris.f90 +++ b/src/utils/utils_ephemeris.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module ephemeris ! diff --git a/src/utils/utils_evfiles.f90 b/src/utils/utils_evfiles.f90 index fef0a7090..515da58e6 100644 --- a/src/utils/utils_evfiles.f90 +++ b/src/utils/utils_evfiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module evutils ! diff --git a/src/utils/utils_gravwave.f90 b/src/utils/utils_gravwave.f90 index db9348a6b..225f091b6 100644 --- a/src/utils/utils_gravwave.f90 +++ b/src/utils/utils_gravwave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module gravwaveutils ! diff --git a/src/utils/utils_linalg.f90 b/src/utils/utils_linalg.f90 index 8c22b1fac..c4c6c22bd 100644 --- a/src/utils/utils_linalg.f90 +++ b/src/utils/utils_linalg.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module linalg ! diff --git a/src/utils/utils_mpc.f90 b/src/utils/utils_mpc.f90 index 5eda889e4..3a90abd94 100644 --- a/src/utils/utils_mpc.f90 +++ b/src/utils/utils_mpc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpc ! diff --git a/src/utils/utils_orbits.f90 b/src/utils/utils_orbits.f90 index 94e97e6f7..a92cd3da9 100644 --- a/src/utils/utils_orbits.f90 +++ b/src/utils/utils_orbits.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module orbits_data ! diff --git a/src/utils/utils_splitmerge.f90 b/src/utils/utils_splitmerge.f90 index c8c91312e..87ec4670c 100644 --- a/src/utils/utils_splitmerge.f90 +++ b/src/utils/utils_splitmerge.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module splitmergeutils ! diff --git a/src/utils/velfield.f90 b/src/utils/velfield.f90 index fbdcb70a9..4792a65f7 100644 --- a/src/utils/velfield.f90 +++ b/src/utils/velfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module velfield ! From c04a21a0c28ba8c928866fadebb362cdff82fdc1 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 10 Apr 2024 17:03:02 +0100 Subject: [PATCH 102/182] restoring upstream changes part 2 --- src/main/damping.f90 | 2 +- src/main/dens.F90 | 4 +- src/main/deriv.F90 | 27 +- src/main/dtype_kdtree.F90 | 2 +- src/main/{dust.F90 => dust.f90} | 4 +- ...{dust_formation.F90 => dust_formation.f90} | 0 src/main/energies.F90 | 196 ++++--- src/main/eos_barotropic.f90 | 2 +- src/main/eos_gasradrec.f90 | 2 +- src/main/eos_helmholtz.f90 | 2 +- src/main/eos_idealplusrad.f90 | 2 +- src/main/eos_mesa.f90 | 2 +- src/main/eos_mesa_microphysics.f90 | 2 +- src/main/eos_piecewise.f90 | 2 +- src/main/eos_shen.f90 | 2 +- src/main/eos_stratified.f90 | 2 +- src/main/evwrite.F90 | 505 ------------------ src/main/extern_Bfield.f90 | 2 +- src/main/extern_binary.f90 | 2 +- src/main/extern_binary_gw.f90 | 2 +- src/main/extern_corotate.f90 | 2 +- src/main/extern_densprofile.f90 | 2 +- ...{extern_gnewton.F90 => extern_gnewton.f90} | 2 +- src/main/extern_gwinspiral.f90 | 2 +- src/main/extern_lensethirring.f90 | 2 +- .../{extern_prdrag.F90 => extern_prdrag.f90} | 2 +- src/main/extern_spiral.f90 | 2 +- src/main/extern_staticsine.f90 | 2 +- src/main/externalforces.F90 | 2 +- src/main/externalforces_gr.F90 | 2 +- src/main/kdtree.F90 | 2 +- src/main/readwrite_dumps_hdf5.F90 | 4 +- ...{sort_particles.F90 => sort_particles.f90} | 2 +- src/main/step_supertimestep.F90 | 2 +- src/main/{timestep.F90 => timestep.f90} | 2 +- src/main/units.f90 | 16 +- src/main/utils_allocate.f90 | 2 +- src/main/utils_binary.f90 | 32 +- src/main/utils_cpuinfo.f90 | 2 +- src/main/utils_datafiles.f90 | 10 +- src/main/utils_dumpfiles.f90 | 95 ++-- src/main/utils_dumpfiles_hdf5.f90 | 2 +- src/main/utils_gr.F90 | 2 +- src/main/utils_hdf5.f90 | 2 +- src/main/utils_healpix.f90 | 2 +- src/main/utils_infiles.f90 | 2 +- 46 files changed, 247 insertions(+), 716 deletions(-) rename src/main/{dust.F90 => dust.f90} (99%) rename src/main/{dust_formation.F90 => dust_formation.f90} (100%) delete mode 100644 src/main/evwrite.F90 rename src/main/{extern_gnewton.F90 => extern_gnewton.f90} (98%) rename src/main/{extern_prdrag.F90 => extern_prdrag.f90} (99%) rename src/main/{sort_particles.F90 => sort_particles.f90} (98%) rename src/main/{timestep.F90 => timestep.f90} (99%) diff --git a/src/main/damping.f90 b/src/main/damping.f90 index 87d3c98ce..d7c83f925 100644 --- a/src/main/damping.f90 +++ b/src/main/damping.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module damping ! diff --git a/src/main/dens.F90 b/src/main/dens.F90 index a596f78dc..daece1767 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module densityforce ! @@ -939,7 +939,7 @@ pure subroutine calculate_divcurlv_from_sums(rhosum,termnorm,divcurlvi,ndivcurlv !--time derivative of div v, needed for Cullen-Dehnen switch if (nalpha >= 2) then !--Divvdt For switch - if (use_exact_linear) then + if (use_exact_linear .and. abs(denom) > tiny(denom)) then ddenom = 1./denom call exactlinear(gradaxdx,gradaxdy,gradaxdz,rhosum(idaxdxi),rhosum(idaxdyi),rhosum(idaxdzi),rmatrix,ddenom) call exactlinear(gradaydx,gradaydy,gradaydz,rhosum(idaydxi),rhosum(idaydyi),rhosum(idaydzi),rmatrix,ddenom) diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index dc2dd9876..fd6b06ceb 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module deriv ! @@ -20,8 +20,6 @@ module deriv ! timestep, timestep_ind, timing ! implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" public :: derivs, get_derivs_global real, private :: stressmax @@ -40,7 +38,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& Bevol,dBevol,rad,drad,radprop,dustprop,ddustprop,& dustevol,ddustevol,filfac,dustfrac,eos_vars,time,dt,dtnew,pxyzu,dens,metrics) use dim, only:maxvxyzu,mhd,fast_divcurlB,gr,periodic,do_radiation,& - sink_radiation,use_dustgrowth + sink_radiation,use_dustgrowth,ind_timesteps use io, only:iprint,fatal,error use linklist, only:set_linklist use densityforce, only:densityiterate @@ -48,12 +46,8 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use externalforces, only:externalforce use part, only:dustgasprop,dvdx,Bxyz,set_boundaries_to_active,& nptmass,xyzmh_ptmass,sinks_have_heating,dust_temp,VrelVf,fxyz_drag -#ifdef IND_TIMESTEPS use timestep_ind, only:nbinmax -#else - use timestep, only:dtcourant,dtforce,dtrad -#endif - use timestep, only:dtmax + use timestep, only:dtmax,dtcourant,dtforce,dtrad #ifdef DRIVING use forcing, only:forceit #endif @@ -149,7 +143,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& set_boundaries_to_active = .false. ! boundary particles are no longer treated as active call do_timing('dens',tlast,tcpulast) endif - + if (gr) then call cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) else @@ -163,8 +157,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& if (do_radiation .and. implicit_radiation .and. dt > 0.) then call do_radiation_implicit(dt,npart,rad,xyzh,vxyzu,radprop,drad,ierr) if (ierr /= 0 .and. ierr /= ierr_failed_to_converge) call fatal('radiation','Failed in radiation') + call do_timing('radiation',tlast,tcpulast) endif - + ! ! compute forces ! @@ -204,11 +199,11 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! ! set new timestep from Courant/forces condition ! -#ifdef IND_TIMESTEPS - dtnew = dtmax/2**nbinmax ! minimum timestep over all particles -#else - dtnew = min(dtforce,dtcourant,dtrad,dtmax) -#endif + if (ind_timesteps) then + dtnew = dtmax/2.**nbinmax ! minimum timestep over all particles + else + dtnew = min(dtforce,dtcourant,dtrad,dtmax) + endif call do_timing('total',t1,tcpu1,lunit=iprint) diff --git a/src/main/dtype_kdtree.F90 b/src/main/dtype_kdtree.F90 index 3cee3685c..6cf50144f 100644 --- a/src/main/dtype_kdtree.F90 +++ b/src/main/dtype_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module dtypekdtree ! diff --git a/src/main/dust.F90 b/src/main/dust.f90 similarity index 99% rename from src/main/dust.F90 rename to src/main/dust.f90 index 44b92240d..8270c5ea9 100644 --- a/src/main/dust.F90 +++ b/src/main/dust.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module dust ! @@ -410,7 +410,7 @@ subroutine read_options_dust(name,valstring,imatch,igotall,ierr) end select !--Check that we have just the *necessary* parameters - if (all(ineed == igot)) igotall = .true. + if (all(igot >= ineed)) igotall = .true. end subroutine read_options_dust diff --git a/src/main/dust_formation.F90 b/src/main/dust_formation.f90 similarity index 100% rename from src/main/dust_formation.F90 rename to src/main/dust_formation.f90 diff --git a/src/main/energies.F90 b/src/main/energies.F90 index 20d229c8c..27684ce97 100644 --- a/src/main/energies.F90 +++ b/src/main/energies.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module energies ! @@ -17,9 +17,9 @@ module energies ! :Runtime parameters: None ! ! :Dependencies: boundary_dyn, centreofmass, dim, dust, eos, eos_piecewise, -! externalforces, fastmath, gravwaveutils, io, kernel, metric_tools, -! mpiutils, nicil, options, part, ptmass, timestep, units, utils_gr, -! vectorutils, viscosity +! externalforces, gravwaveutils, io, kernel, metric_tools, mpiutils, +! nicil, options, part, ptmass, timestep, units, utils_gr, vectorutils, +! viscosity ! use dim, only:maxdusttypes,maxdustsmall use units, only:utime @@ -62,7 +62,7 @@ module energies !---------------------------------------------------------------- subroutine compute_energies(t) use dim, only:maxp,maxvxyzu,maxalpha,maxtypes,mhd_nonideal,maxp_hard,& - lightcurve,use_dust,maxdusttypes,do_radiation,gr + lightcurve,use_dust,maxdusttypes,do_radiation,gr,use_krome use part, only:rhoh,xyzh,vxyzu,massoftype,npart,maxphase,iphase,& alphaind,Bevol,divcurlB,iamtype,igamma,& igas,idust,iboundary,istar,idarkmatter,ibulge,& @@ -74,7 +74,7 @@ subroutine compute_energies(t) use part, only:pxyzu,fxyzu,fext use gravwaveutils, only:calculate_strain,calc_gravitwaves use centreofmass, only:get_centreofmass_accel - use eos, only:polyk,utherm,gamma,eos_is_non_ideal,eos_outputs_gasP + use eos, only:polyk,gamma,eos_is_non_ideal,eos_outputs_gasP use eos_piecewise, only:gamma_pwp use io, only:id,fatal,master use externalforces, only:externalforce,externalforce_vdependent,was_accreted,accradius1 @@ -83,19 +83,14 @@ subroutine compute_energies(t) use ptmass, only:get_accel_sink_gas use viscosity, only:irealvisc,shearfunc use nicil, only:nicil_update_nimhd,nicil_get_halldrift,nicil_get_ambidrift, & - use_ohm,use_hall,use_ambi,n_data_out,n_warn + use_ohm,use_hall,use_ambi,n_data_out,n_warn,eta_constant use boundary_dyn, only:dynamic_bdy,find_dynamic_boundaries use kernel, only:radkern use timestep, only:dtmax -#ifdef GR use part, only:metrics use metric_tools, only:unpack_metric use utils_gr, only:dot_product_gr,get_geodesic_accel use vectorutils, only:cross_product3D -#ifdef FINVSQRT - use fastmath, only:finvsqrt -#endif -#endif use part, only:luminosity use dust, only:get_ts,idrag real, intent(in) :: t @@ -113,10 +108,8 @@ subroutine compute_energies(t) real :: curlBi(3),vhalli(3),vioni(3),data_out(n_data_out) real :: erotxi,erotyi,erotzi,fdum(3),x0(3),v0(3),a0(3),xyz_x_all(3),xyz_n_all(3) real :: ethermi -#ifdef GR real :: pdotv,bigvi(1:3),alpha_gr,beta_gr_UP(1:3),lorentzi,pxi,pyi,pzi real :: gammaijdown(1:3,1:3),angi(1:3),fourvel_space(3) -#endif integer :: i,j,itype,iu integer :: ierrlist(n_warn) integer(kind=8) :: np,npgas,nptot,np_rho(maxtypes),np_rho_thread(maxtypes) @@ -174,14 +167,14 @@ subroutine compute_energies(t) !$omp shared(alphaind,massoftype,irealvisc,iu) & !$omp shared(ieos,gamma,nptmass,xyzmh_ptmass,vxyz_ptmass,xyzcom) & !$omp shared(Bevol,divcurlB,iphase,poten,dustfrac,use_dustfrac) & -!$omp shared(use_ohm,use_hall,use_ambi,nden_nimhd,eta_nimhd) & +!$omp shared(use_ohm,use_hall,use_ambi,nden_nimhd,eta_nimhd,eta_constant) & !$omp shared(ev_data,np_rho,erot_com,calc_erot,gas_only,track_mass) & !$omp shared(calc_gravitwaves) & !$omp shared(iev_erad,iev_rho,iev_dt,iev_entrop,iev_rhop,iev_alpha) & !$omp shared(iev_B,iev_divB,iev_hdivB,iev_beta,iev_temp,iev_etao,iev_etah) & !$omp shared(iev_etaa,iev_vel,iev_vhall,iev_vion,iev_n) & !$omp shared(iev_dtg,iev_ts,iev_macc,iev_totlum,iev_erot,iev_viscrat) & -!$omp shared(eos_vars,grainsize,graindens,ndustsmall) & +!$omp shared(eos_vars,grainsize,graindens,ndustsmall,metrics) & !$omp private(i,j,xi,yi,zi,hi,rhoi,vxi,vyi,vzi,Bxi,Byi,Bzi,Bi,B2i,epoti,vsigi,v2i,vi1) & !$omp private(ponrhoi,spsoundi,gammai,spsound2i,va2cs2,rho1cs2,ethermi,dumx,dumy,dumz,valfven2i,divBi,hdivBonBi,curlBi) & !$omp private(rho1i,shearparam_art,shearparam_phys,ratio_phys_to_av,betai) & @@ -190,10 +183,7 @@ subroutine compute_energies(t) !$omp private(erotxi,erotyi,erotzi,fdum) & !$omp private(ev_data_thread,np_rho_thread) & !$omp firstprivate(alphai,itype,pmassi) & -#ifdef GR -!$omp shared(metrics) & !$omp private(pxi,pyi,pzi,gammaijdown,alpha_gr,beta_gr_UP,bigvi,lorentzi,pdotv,angi,fourvel_space) & -#endif !$omp shared(idrag) & !$omp private(tsi,iregime,idusttype) & !$omp shared(luminosity,track_lum) & @@ -247,57 +237,53 @@ subroutine compute_energies(t) vyi = vxyzu(2,i) vzi = vxyzu(3,i) -#ifdef GR - pxi = pxyzu(1,i) - pyi = pxyzu(2,i) - pzi = pxyzu(3,i) - - ! linear momentum - xmom = xmom + pmassi*pxi - ymom = ymom + pmassi*pyi - zmom = zmom + pmassi*pzi - - call unpack_metric(metrics(:,:,:,i),betaUP=beta_gr_UP,alpha=alpha_gr,gammaijdown=gammaijdown) - bigvi = (vxyzu(1:3,i)+beta_gr_UP)/alpha_gr - v2i = dot_product_gr(bigvi,bigvi,gammaijdown) -#ifdef FINVSQRT - lorentzi = finvsqrt(1.-v2i) -#else - lorentzi = 1./sqrt(1.-v2i) -#endif - pdotv = pxi*vxi + pyi*vyi + pzi*vzi - - ! angular momentum - fourvel_space = (lorentzi/alpha_gr)*vxyzu(1:3,i) - call cross_product3D(xyzh(1:3,i),fourvel_space,angi) ! position cross with four-velocity - angx = angx + pmassi*angi(1) - angy = angy + pmassi*angi(2) - angz = angz + pmassi*angi(3) - - ! kinetic energy - ekin = ekin + pmassi*(pdotv + alpha_gr/lorentzi - 1.) ! The 'kinetic term' in total specific energy, minus rest mass - mtot = mtot + pmassi -#else - ! centre of mass - xcom = xcom + pmassi*xi - ycom = ycom + pmassi*yi - zcom = zcom + pmassi*zi - mtot = mtot + pmassi - - ! linear momentum - xmom = xmom + pmassi*vxi - ymom = ymom + pmassi*vyi - zmom = zmom + pmassi*vzi - - ! angular momentum - angx = angx + pmassi*(yi*vzi - zi*vyi) - angy = angy + pmassi*(zi*vxi - xi*vzi) - angz = angz + pmassi*(xi*vyi - yi*vxi) - - ! kinetic energy & rms velocity - v2i = vxi*vxi + vyi*vyi + vzi*vzi - ekin = ekin + pmassi*v2i -#endif + if (gr) then + pxi = pxyzu(1,i) + pyi = pxyzu(2,i) + pzi = pxyzu(3,i) + + ! linear momentum + xmom = xmom + pmassi*pxi + ymom = ymom + pmassi*pyi + zmom = zmom + pmassi*pzi + + call unpack_metric(metrics(:,:,:,i),betaUP=beta_gr_UP,alpha=alpha_gr,gammaijdown=gammaijdown) + bigvi = (vxyzu(1:3,i)+beta_gr_UP)/alpha_gr + v2i = dot_product_gr(bigvi,bigvi,gammaijdown) + lorentzi = 1./sqrt(1.-v2i) + pdotv = pxi*vxi + pyi*vyi + pzi*vzi + + ! angular momentum + fourvel_space = (lorentzi/alpha_gr)*vxyzu(1:3,i) + call cross_product3D(xyzh(1:3,i),fourvel_space,angi) ! position cross with four-velocity + angx = angx + pmassi*angi(1) + angy = angy + pmassi*angi(2) + angz = angz + pmassi*angi(3) + + ! kinetic energy + ekin = ekin + pmassi*(pdotv + alpha_gr/lorentzi - 1.) ! The 'kinetic term' in total specific energy, minus rest mass + mtot = mtot + pmassi + else + ! centre of mass + xcom = xcom + pmassi*xi + ycom = ycom + pmassi*yi + zcom = zcom + pmassi*zi + mtot = mtot + pmassi + + ! linear momentum + xmom = xmom + pmassi*vxi + ymom = ymom + pmassi*vyi + zmom = zmom + pmassi*vzi + + ! angular momentum + angx = angx + pmassi*(yi*vzi - zi*vyi) + angy = angy + pmassi*(zi*vxi - xi*vzi) + angz = angz + pmassi*(xi*vyi - yi*vxi) + + ! kinetic energy & rms velocity + v2i = vxi*vxi + vyi*vyi + vzi*vzi + ekin = ekin + pmassi*v2i + endif vrms = vrms + v2i @@ -369,10 +355,9 @@ subroutine compute_energies(t) spsoundi = eos_vars(ics,i) gammai = eos_vars(igamma,i) if (maxvxyzu >= 4) then - ethermi = pmassi*utherm(vxyzu(:,i),rhoi,gamma)*gasfrac -#ifdef GR - ethermi = (alpha_gr/lorentzi)*ethermi -#endif + ethermi = pmassi*vxyzu(4,i)*gasfrac + if (gr) ethermi = (alpha_gr/lorentzi)*ethermi + etherm = etherm + ethermi if (vxyzu(iu,i) < tiny(vxyzu(iu,i))) np_e_eq_0 = np_e_eq_0 + 1 @@ -475,24 +460,26 @@ subroutine compute_energies(t) call ev_data_update(ev_data_thread,iev_vel, sqrt(v2i) ) call ev_data_update(ev_data_thread,iev_vion, vion ) endif - n_ion = 0 - do j = 9,21 - n_ion = n_ion + data_out(j) - enddo - n_total = data_out(5) - if (n_total > 0.) then - n_total1 = 1.0/n_total - else - n_total1 = 0.0 ! only possible if eta_constant = .true. + if (.not.eta_constant) then + n_ion = 0 + do j = 9,21 + n_ion = n_ion + data_out(j) + enddo + n_total = data_out(5) + if (n_total > 0.) then + n_total1 = 1.0/n_total + else + n_total1 = 0.0 ! only possible if eta_constant = .true. + endif + eta_nimhd(iion,i) = n_ion*n_total1 ! Save ionisation fraction for the dump file + call ev_data_update(ev_data_thread,iev_n(1),n_ion*n_total1) + call ev_data_update(ev_data_thread,iev_n(2),data_out( 8)*n_total1) + call ev_data_update(ev_data_thread,iev_n(3),data_out( 8)) + call ev_data_update(ev_data_thread,iev_n(4),n_total-n_ion) + call ev_data_update(ev_data_thread,iev_n(5),data_out(24)) + call ev_data_update(ev_data_thread,iev_n(6),data_out(23)) + call ev_data_update(ev_data_thread,iev_n(7),data_out(22)) endif - eta_nimhd(iion,i) = n_ion*n_total1 ! Save ionisation fraction for the dump file - call ev_data_update(ev_data_thread,iev_n(1),n_ion*n_total1) - call ev_data_update(ev_data_thread,iev_n(2),data_out( 8)*n_total1) - call ev_data_update(ev_data_thread,iev_n(3),data_out( 8)) - call ev_data_update(ev_data_thread,iev_n(4),n_total-n_ion) - call ev_data_update(ev_data_thread,iev_n(5),data_out(24)) - call ev_data_update(ev_data_thread,iev_n(6),data_out(23)) - call ev_data_update(ev_data_thread,iev_n(7),data_out(22)) endif endif endif isgas @@ -718,20 +705,20 @@ subroutine compute_energies(t) if (calc_gravitwaves) then pmassi = massoftype(igas) x0 = 0.; v0 = 0.; a0 = 0. ! use the origin by default -#ifdef GR - !call get_geodesic_accel(axyz,npart,vxyzu(1:3,:),metrics,metricderivs) - !call calculate_strain(hx,hp,pmassi,x0,v0,a0,npart,xyzh,vxyzu,axyz) - call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& - fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) -#else - if (iexternalforce==0) then ! if no external forces, use centre of mass of particles - x0 = (/xcom,ycom,zcom/) - v0 = (/xmom,ymom,zmom/) - call get_centreofmass_accel(a0,npart,xyzh,fxyzu,fext,nptmass,xyzmh_ptmass,fxyz_ptmass) + if (gr) then + !call get_geodesic_accel(axyz,npart,vxyzu(1:3,:),metrics,metricderivs) + !call calculate_strain(hx,hp,pmassi,x0,v0,a0,npart,xyzh,vxyzu,axyz) + call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& + fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) + else + if (iexternalforce==0) then ! if no external forces, use centre of mass of particles + x0 = (/xcom,ycom,zcom/) + v0 = (/xmom,ymom,zmom/) + call get_centreofmass_accel(a0,npart,xyzh,fxyzu,fext,nptmass,xyzmh_ptmass,fxyz_ptmass) + endif + call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& + fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) endif - call calculate_strain(hx,hp,pmassi,ddq_xy,x0,v0,a0,npart,xyzh,vxyzu(1:3,:),fxyzu,& - fext,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass) -#endif ev_data(iev_sum,iev_gws(1)) = hx(1) ev_data(iev_sum,iev_gws(2)) = hp(1) ev_data(iev_sum,iev_gws(3)) = hx(2) @@ -762,7 +749,6 @@ subroutine compute_energies(t) if (ierr==1) call fatal('energies','there is no high density gas for the dynamic boundaries') endif - return end subroutine compute_energies !---------------------------------------------------------------- !+ diff --git a/src/main/eos_barotropic.f90 b/src/main/eos_barotropic.f90 index df0ec4b8b..93f32e64c 100644 --- a/src/main/eos_barotropic.f90 +++ b/src/main/eos_barotropic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_barotropic ! diff --git a/src/main/eos_gasradrec.f90 b/src/main/eos_gasradrec.f90 index c478d7290..d8e949aba 100644 --- a/src/main/eos_gasradrec.f90 +++ b/src/main/eos_gasradrec.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_gasradrec ! diff --git a/src/main/eos_helmholtz.f90 b/src/main/eos_helmholtz.f90 index d7a835899..882967eba 100644 --- a/src/main/eos_helmholtz.f90 +++ b/src/main/eos_helmholtz.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_helmholtz ! diff --git a/src/main/eos_idealplusrad.f90 b/src/main/eos_idealplusrad.f90 index ecb29e49c..b48c73974 100644 --- a/src/main/eos_idealplusrad.f90 +++ b/src/main/eos_idealplusrad.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_idealplusrad ! diff --git a/src/main/eos_mesa.f90 b/src/main/eos_mesa.f90 index 7f1a6f25c..216f04deb 100644 --- a/src/main/eos_mesa.f90 +++ b/src/main/eos_mesa.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_mesa ! diff --git a/src/main/eos_mesa_microphysics.f90 b/src/main/eos_mesa_microphysics.f90 index 30fdd716e..aa9268c13 100644 --- a/src/main/eos_mesa_microphysics.f90 +++ b/src/main/eos_mesa_microphysics.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mesa_microphysics ! diff --git a/src/main/eos_piecewise.f90 b/src/main/eos_piecewise.f90 index a3ebb2ed9..8462e4bcf 100644 --- a/src/main/eos_piecewise.f90 +++ b/src/main/eos_piecewise.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_piecewise ! diff --git a/src/main/eos_shen.f90 b/src/main/eos_shen.f90 index 5749b8122..7c2548677 100644 --- a/src/main/eos_shen.f90 +++ b/src/main/eos_shen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_shen ! diff --git a/src/main/eos_stratified.f90 b/src/main/eos_stratified.f90 index 3f3cd8a44..37f9bcd14 100644 --- a/src/main/eos_stratified.f90 +++ b/src/main/eos_stratified.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_stratified ! diff --git a/src/main/evwrite.F90 b/src/main/evwrite.F90 deleted file mode 100644 index 9d063e020..000000000 --- a/src/main/evwrite.F90 +++ /dev/null @@ -1,505 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module evwrite -! -! Calculates conserved quantities etc and writes to .ev file; -! Also writes log output -! To Developer: To add values to the .ev file, follow the following procedure. -! In the init_evfile subroutine in evwrite.F90, add the following command: -! call fill_ev_label(ev_fmt,ev_tag_int,ev_tag_char,action,i,j) -! and in compute_energies subroutine in energies.F90, add the following command: -! call ev_data_update(ev_data_thread,ev_tag_int,value) -! where -! ev_fmt,ev_data_thread,i,j: pre-defined quantities to included verbatim -! ev_tag_char: a string to identify the quantity for use in the header -! (e.g. 'c_s' for sound speed) -! ev_tag_int: an integer to identify the quantity (e.g. 'iev_cs' for sound speed); -! this integer must be included in energies (as a public variable, -! and in the openmp declarations), and passed to evwrite via use energies. -! ev_value: the value of the quantity for particle i (e.g., spsoundi for sound speed) -! action: a string identifying what action(s) you would like performed -! on the quantity. The available options are -! 0: no action taken (e.g. for time) -! s: sum quantity (e.g. for entropy) -! x: print the maximum quantity -! a: print the average (mean) quantity -! n: print the minimum quantity -! where any or all of x,a,n can be used as a single action. Although 0 & s are treated -! the same, they are kept separate for clarity without added computational cost -! -! :References: None -! -! :Owner: James Wurster -! -! :Runtime parameters: None -! -! :Dependencies: boundary, boundary_dyn, dim, energies, eos, extern_binary, -! externalforces, fileutils, gravwaveutils, io, mpiutils, nicil, options, -! part, ptmass, timestep, units, viscosity -! - use io, only:fatal,iverbose - use options, only:iexternalforce - use timestep, only:dtmax_dratio - use externalforces, only:iext_binary,was_accreted - use energies, only:inumev,iquantities,ev_data - use energies, only:ndead,npartall - use energies, only:gas_only,track_mass,track_lum - use energies, only:iev_sum,iev_max,iev_min,iev_ave - use energies, only:iev_time,iev_ekin,iev_etherm,iev_emag,iev_epot,iev_etot,iev_totmom,iev_com,& - iev_angmom,iev_rho,iev_dt,iev_dtx,iev_entrop,iev_rmsmach,iev_vrms,iev_rhop,iev_alpha,& - iev_B,iev_divB,iev_hdivB,iev_beta,iev_temp,iev_etao,iev_etah,& - iev_etaa,iev_vel,iev_vhall,iev_vion,iev_n,& - iev_dtg,iev_ts,iev_dm,iev_momall,iev_angall,iev_angall,iev_maccsink,& - iev_macc,iev_eacc,iev_totlum,iev_erot,iev_viscrat,iev_erad,iev_gws,iev_mass,iev_bdy - - implicit none - public :: init_evfile, write_evfile, write_evlog - private :: fill_ev_tag, fill_ev_header - - integer, private :: ielements - integer, private :: ev_cmd(inumev) ! array of the actions to be taken - character(len=19),private :: ev_label(inumev) ! to make the header for the .ev file - - private - -contains - -!---------------------------------------------------------------- -!+ -! opens the .ev file for output -!+ -!---------------------------------------------------------------- -subroutine init_evfile(iunit,evfile,open_file) - use io, only:id,master,warning - use dim, only:maxtypes,maxalpha,maxp,maxp_hard,mhd,mhd_nonideal,lightcurve - use options, only:calc_erot,ishock_heating,ipdv_heating,use_dustfrac - use units, only:c_is_unity - use part, only:igas,idust,iboundary,istar,idarkmatter,ibulge,npartoftype,ndusttypes,maxtypes - use nicil, only:use_ohm,use_hall,use_ambi - use viscosity, only:irealvisc - use mpiutils, only:reduceall_mpi - use eos, only:ieos,eos_is_non_ideal,eos_outputs_gasP - use gravwaveutils, only:calc_gravitwaves - use boundary_dyn, only:dynamic_bdy - integer, intent(in) :: iunit - character(len= *), intent(in) :: evfile - logical, intent(in) :: open_file - character(len= 27) :: ev_fmt - character(len= 11) :: dustname - integer :: i,j,k - integer(kind=8) :: npartoftypetot(maxtypes) - ! - !--Initialise additional variables - ! - npartoftypetot = reduceall_mpi('+', npartoftype) - gas_only = .true. - do i = 2,maxtypes - if (npartoftypetot(i) > 0) gas_only = .false. - enddo - write(ev_fmt,'(a)') "(1x,'[',i2.2,1x,a11,']',2x)" - ! - !--Define all the variables to be included in the .ev file and their supplementary information - ! - i = 1 - j = 1 - call fill_ev_tag(ev_fmt,iev_time, 'time', '0', i,j) - call fill_ev_tag(ev_fmt,iev_ekin, 'ekin', '0', i,j) - call fill_ev_tag(ev_fmt,iev_etherm, 'etherm', '0', i,j) - call fill_ev_tag(ev_fmt,iev_emag, 'emag', '0', i,j) - call fill_ev_tag(ev_fmt,iev_epot, 'epot', '0', i,j) - call fill_ev_tag(ev_fmt,iev_etot, 'etot', '0', i,j) - call fill_ev_tag(ev_fmt,iev_erad, 'erad', '0', i,j) - call fill_ev_tag(ev_fmt,iev_totmom, 'totmom', '0', i,j) - call fill_ev_tag(ev_fmt,iev_angmom, 'angtot', '0', i,j) - call fill_ev_tag(ev_fmt,iev_rho, 'rho', 'xa',i,j) - call fill_ev_tag(ev_fmt,iev_dt, 'dt', '0', i,j) - if (dtmax_dratio > 0.) then - call fill_ev_tag(ev_fmt,iev_dtx, 'dtmax', '0', i,j) - endif - if (maxp==maxp_hard) then - call fill_ev_tag(ev_fmt,iev_mass,'mass', '0', i,j) - endif - call fill_ev_tag(ev_fmt,iev_entrop, 'totentrop','s', i,j) - call fill_ev_tag(ev_fmt,iev_rmsmach,'rmsmach', '0', i,j) - call fill_ev_tag(ev_fmt,iev_vrms, 'vrms', '0', i,j) - call fill_ev_tag(ev_fmt,iev_com(1), 'xcom', '0', i,j) - call fill_ev_tag(ev_fmt,iev_com(2), 'ycom', '0', i,j) - call fill_ev_tag(ev_fmt,iev_com(3), 'zcom', '0', i,j) - if (.not. gas_only) then - if (npartoftypetot(igas) > 0) call fill_ev_tag(ev_fmt,iev_rhop(1),'rho gas', 'xa',i,j) - if (npartoftypetot(idust) > 0) call fill_ev_tag(ev_fmt,iev_rhop(2),'rho dust','xa',i,j) - if (npartoftypetot(iboundary) > 0) call fill_ev_tag(ev_fmt,iev_rhop(3),'rho bdy', 'xa',i,j) - if (npartoftypetot(istar) > 0) call fill_ev_tag(ev_fmt,iev_rhop(4),'rho star','xa',i,j) - if (npartoftypetot(idarkmatter) > 0) call fill_ev_tag(ev_fmt,iev_rhop(5),'rho dm', 'xa',i,j) - if (npartoftypetot(ibulge) > 0) call fill_ev_tag(ev_fmt,iev_rhop(6),'rho blg', 'xa',i,j) - endif - if (maxalpha==maxp) then - call fill_ev_tag(ev_fmt, iev_alpha, 'alpha', 'x', i,j) - endif - if (eos_is_non_ideal(ieos) .or. eos_outputs_gasP(ieos)) then - call fill_ev_tag(ev_fmt, iev_temp, 'temp', 'xan',i,j) - endif - if ( mhd ) then - call fill_ev_tag(ev_fmt, iev_B, 'B', 'xan',i,j) - call fill_ev_tag(ev_fmt, iev_divB, 'divB', 'xa' ,i,j) - call fill_ev_tag(ev_fmt, iev_hdivB, 'hdivB/B','xa' ,i,j) - call fill_ev_tag(ev_fmt, iev_beta, 'beta_P', 'xan',i,j) - if (mhd_nonideal) then - if (use_ohm) then - call fill_ev_tag(ev_fmt,iev_etao, 'eta_o', 'xan',i,j) - endif - if (use_hall) then - call fill_ev_tag(ev_fmt,iev_etah(1),'eta_h', 'xan',i,j) - call fill_ev_tag(ev_fmt,iev_etah(2),'|eta_h|', 'xan',i,j) - call fill_ev_tag(ev_fmt,iev_vhall, 'v_hall', 'xan',i,j) - endif - if (use_ambi) then - call fill_ev_tag(ev_fmt,iev_etaa, 'eta_a', 'xan',i,j) - call fill_ev_tag(ev_fmt,iev_vel, 'velocity', 'xan',i,j) - call fill_ev_tag(ev_fmt,iev_vion, 'v_ion', 'xan',i,j) - endif - call fill_ev_tag(ev_fmt, iev_n(1), 'ni/n(i+n)','xan',i,j) - call fill_ev_tag(ev_fmt, iev_n(2), 'ne/n(i+n)','xan',i,j) - call fill_ev_tag(ev_fmt, iev_n(3), 'n_e', 'xa', i,j) - call fill_ev_tag(ev_fmt, iev_n(4), 'n_n', 'xa', i,j) - call fill_ev_tag(ev_fmt, iev_n(5), 'n_g(Z=-1)','xa', i,j) - call fill_ev_tag(ev_fmt, iev_n(6), 'n_g(Z= 0)','xa', i,j) - call fill_ev_tag(ev_fmt, iev_n(7), 'n_g(Z=+1)','xa', i,j) - endif - endif - if (use_dustfrac) then - call fill_ev_tag(ev_fmt, iev_dtg,'dust/gas', 'xan',i,j) - call fill_ev_tag(ev_fmt, iev_ts, 't_s', 'xn', i,j) - do k=1,ndusttypes - write(dustname,'(a,I3)') 'DustMass',k - call fill_ev_tag(ev_fmt,iev_dm(k), dustname, '0', i,j) - enddo - endif - if (iexternalforce > 0) then - call fill_ev_tag(ev_fmt, iev_momall,'totmomall', '0',i,j) - call fill_ev_tag(ev_fmt, iev_angall,'angall', '0',i,j) - if (iexternalforce==iext_binary) then - call fill_ev_tag(ev_fmt,iev_maccsink(1),'Macc sink 1', '0',i,j) - call fill_ev_tag(ev_fmt,iev_maccsink(2),'Macc sink 2', '0',i,j) - endif - endif - if (was_accreted(iexternalforce,-1.0)) then - call fill_ev_tag(ev_fmt,iev_macc, 'accretedmas', 's',i,j) - call fill_ev_tag(ev_fmt,iev_eacc, 'eacc', '0',i,j) - track_mass = .true. - else - track_mass = .false. - endif - if (ishock_heating==0 .or. ipdv_heating==0 .or. lightcurve) then - call fill_ev_tag(ev_fmt,iev_totlum,'tot lum', '0',i,j) - track_lum = .true. - else - track_lum = .false. - endif - if (calc_erot) then - call fill_ev_tag(ev_fmt,iev_erot(1),'erot_x', 's',i,j) - call fill_ev_tag(ev_fmt,iev_erot(2),'erot_y', 's',i,j) - call fill_ev_tag(ev_fmt,iev_erot(3),'erot_z', 's',i,j) - call fill_ev_tag(ev_fmt,iev_erot(4),'erot', '0',i,j) - endif - if (irealvisc /= 0) then - call fill_ev_tag(ev_fmt,iev_viscrat,'visc_rat','xan',i,j) - endif - - if (calc_gravitwaves) then - call fill_ev_tag(ev_fmt,iev_gws(1),'hx_0','0',i,j) - call fill_ev_tag(ev_fmt,iev_gws(2),'hp_0','0',i,j) - call fill_ev_tag(ev_fmt,iev_gws(3),'hx_{30}','0',i,j) - call fill_ev_tag(ev_fmt,iev_gws(4),'hp_{30}','0',i,j) - call fill_ev_tag(ev_fmt,iev_gws(5),'hx_{60}','0',i,j) - call fill_ev_tag(ev_fmt,iev_gws(6),'hp_{60}','0',i,j) - call fill_ev_tag(ev_fmt,iev_gws(7),'hx_{90}','0',i,j) - call fill_ev_tag(ev_fmt,iev_gws(8),'hp_{90}','0',i,j) - endif - if (dynamic_bdy) then - call fill_ev_tag(ev_fmt,iev_bdy(1,1),'min_x','0',i,j) - call fill_ev_tag(ev_fmt,iev_bdy(1,2),'max_x','0',i,j) - call fill_ev_tag(ev_fmt,iev_bdy(2,1),'min_y','0',i,j) - call fill_ev_tag(ev_fmt,iev_bdy(2,2),'max_y','0',i,j) - call fill_ev_tag(ev_fmt,iev_bdy(3,1),'min_z','0',i,j) - call fill_ev_tag(ev_fmt,iev_bdy(3,2),'max_z','0',i,j) - endif - iquantities = i - 1 ! The number of different quantities to analyse - ielements = j - 1 ! The number of values to be calculated (i.e. the number of columns in .ve) - ! - !--all threads do above, but only master writes file - ! (the open_file is to prevent an .ev file from being made during the test suite) - ! - if (open_file .and. id == master) then - ! - !--open the file for output - ! - open(unit=iunit,file=evfile,form='formatted',status='replace') - ! - !--write a header line - ! - write(ev_fmt,'(a,I3,a)') '(',ielements+1,'a)' - write(iunit,ev_fmt)'#',ev_label(1:ielements) - endif - -end subroutine init_evfile -! -!---------------------------------------------------------------- -!+ -! creates up to three lables per input value, and fills the required -! tracking arrays; this includes a check to verify the actions are legal -!+ -!---------------------------------------------------------------- -subroutine fill_ev_tag(ev_fmt,itag,label,cmd,i,j) - integer, intent(inout) :: i,j - integer, intent(out) :: itag - character(len=*), intent(in) :: ev_fmt,label,cmd - integer :: ki,kj,iindex,joffset - - ! initialise command - itag = i - joffset = 1 - ev_cmd(i) = 0 - ! - ! make the headers & set ev_cmd - if (index(cmd,'0') > 0) call fill_ev_header(ev_fmt,label,'0',j,joffset) - if (index(cmd,'s') > 0) call fill_ev_header(ev_fmt,label,'s',j,joffset) - if (index(cmd,'x') > 0) then - call fill_ev_header(ev_fmt,label,'x',j,joffset) - ev_cmd(i) = ev_cmd(i) + 1 - joffset = joffset + 1 - endif - if (index(cmd,'a') > 0) then - call fill_ev_header(ev_fmt,label,'a',j,joffset) - ev_cmd(i) = ev_cmd(i) + 2 - joffset = joffset + 1 - endif - if (index(cmd,'n') > 0) then - call fill_ev_header(ev_fmt,label,'n',j,joffset) - ev_cmd(i) = ev_cmd(i) + 5 - endif - i = i + 1 - j = j + len(trim(cmd)) - ! - ! verify action command is legal - if ( (index(cmd,'x') > 0) .or. (index(cmd,'a') > 0) .or. (index(cmd,'n') > 0) ) then - iindex = 1 - else - iindex = 0 - endif - if ( index(cmd,'0') + index(cmd,'s') + iindex > 1) & - call fatal('fill_ev_tag','using an invalid sequence of actions for element', var=cmd) - do ki = 1,len(cmd)-1 - do kj = ki+1,len(cmd) - if ( cmd(ki:ki)==cmd(kj:kj) ) then - call fatal('fill_ev_tag','using duplicate actions for the same quantity', var=cmd) - endif - enddo - enddo - ! -end subroutine fill_ev_tag -!---------------------------------------------------------------- -!+ -! Fill an array to be used for the header of the .ev file -!+ -!---------------------------------------------------------------- -subroutine fill_ev_header(ev_fmt,label,cxmn,j,joffset) - integer, intent(in) :: j,joffset - character(len=* ), intent(in) :: ev_fmt,label - character(len= 1), intent(in) :: cxmn - character(len=11) :: label0 - character(len= 3) :: ext - integer :: j_actual - - if (len(label)>11 .and. (cxmn=='0' .or. cxmn=='s') ) then - label0 = label(1:11) - elseif (len(label)>9 .and. (cxmn=='x' .or. cxmn=='a' .or. cxmn=='n')) then - label0 = label(1:9) - else - label0 = label - endif - ext = "" - if (len(label)<=7) then - if (cxmn=='x') ext = "max" - if (cxmn=='a') ext = "ave" - if (cxmn=='n') ext = "min" - elseif (len(label)<=9) then - if (cxmn=='x') ext = "X" - if (cxmn=='a') ext = "A" - if (cxmn=='n') ext = "N" - endif - if (ext/="") write(label0,'(a,1x,a)')trim(label0),trim(ext); - ! - j_actual = j + joffset - 1 - if (j_actual > 99) then - write(ev_label(j_actual),ev_fmt) 100-j_actual,trim(label0) - else - write(ev_label(j_actual),ev_fmt) j_actual,trim(label0) - endif - -end subroutine fill_ev_header -!---------------------------------------------------------------- -!+ -! calculates total energy, etc, and writes line to .ev file -!+ -!---------------------------------------------------------------- -subroutine write_evfile(t,dt) - use energies, only:compute_energies,ev_data_update - use io, only:id,master,ievfile -#ifndef GR - use timestep, only:dtmax_user - use options, only:iexternalforce - use extern_binary, only:accretedmass1,accretedmass2 -#endif - real, intent(in) :: t,dt - integer :: i,j - real :: ev_data_out(ielements) - character(len=35) :: ev_format - - call compute_energies(t) - - if (id==master) then - !--fill in additional details that are not calculated in energies.f -#ifndef GR - ev_data(iev_sum,iev_dt) = dt - ev_data(iev_sum,iev_dtx) = dtmax_user - if (iexternalforce==iext_binary) then - ev_data(iev_sum,iev_maccsink(1)) = accretedmass1 - ev_data(iev_sum,iev_maccsink(2)) = accretedmass2 - endif -#endif - ! Fill in the data_out array - j = 1 - do i = 1,iquantities - if (ev_cmd(i)==0) then - ! include the total value - ev_data_out(j) = ev_data(iev_sum,i) - j = j + 1 - else - if (ev_cmd(i)==1 .or. ev_cmd(i)==3 .or. ev_cmd(i)==6 .or. ev_cmd(i)==8) then - ! include the maximum value - ev_data_out(j) = ev_data(iev_max,i) - j = j + 1 - endif - if (ev_cmd(i)==2 .or. ev_cmd(i)==3 .or. ev_cmd(i)==7 .or. ev_cmd(i)==8) then - ! include the average value - ev_data_out(j) = ev_data(iev_ave,i) - j = j + 1 - endif - if (ev_cmd(i)==5 .or. ev_cmd(i)==6 .or. ev_cmd(i)==7 .or. ev_cmd(i)==8) then - ! include the minimum value - ev_data_out(j) = ev_data(iev_min,i) - j = j + 1 - endif - endif - enddo - ! - !--write line to .ev file (should correspond to header, below) - ! - write(ev_format,'(a,I3,a)')"(",ielements,"(1pe18.10,1x))" - write(ievfile,ev_format) ev_data_out - call flush(ievfile) - endif - - return -end subroutine write_evfile -!---------------------------------------------------------------- -!+ -! Writes nicely formatted output to the log file/screen -! Must be called *after* a call to compute energies has been -! performed -!+ -!---------------------------------------------------------------- -subroutine write_evlog(iprint) - use dim, only:maxp,maxalpha,mhd,maxvxyzu,periodic,mhd_nonideal,& - use_dust,maxdusttypes,do_radiation,particles_are_injected - use energies, only:ekin,etherm,emag,epot,etot,rmsmach,vrms,accretedmass,mdust,mgas,xyzcom - use energies, only:erad - use part, only:nptmass,ndusttypes - use viscosity, only:irealvisc,shearparam - use boundary, only:dxbound,dybound,dzbound - use units, only:unit_density - use options, only:use_dustfrac - use fileutils, only:make_tags_unique - use ptmass, only:icreate_sinks - integer, intent(in) :: iprint - character(len=120) :: string,Mdust_label(maxdusttypes) - integer :: i - - if (ndead > 0 .or. nptmass > 0 .or. icreate_sinks > 0 .or. particles_are_injected .or. iverbose > 0) then - write(iprint,"(1x,4(a,I10))") 'npart=',npartall,', n_alive=',npartall-ndead, & - ', n_dead_or_accreted=',ndead,', nptmass=',nptmass - endif - - write(iprint,"(1x,3('E',a,'=',es10.3,', '),('E',a,'=',es10.3))") 'tot',etot,'kin',ekin,'therm',etherm,'pot',epot - - if (mhd) write(iprint,"(1x,('E',a,'=',es10.3))") 'mag',emag - if (do_radiation) write(iprint,"(1x,('E',a,'=',es10.3))") 'rad',erad - if (track_mass) write(iprint,"(1x,('E',a,'=',es10.3))") 'acc',ev_data(iev_sum,iev_eacc) - write(iprint,"(1x,1(a,'=',es10.3,', '),(a,'=',es10.3))") & - 'Linm',ev_data(iev_sum,iev_totmom),'Angm',ev_data(iev_sum,iev_angmom) - if (iexternalforce > 0) then - if (abs(ev_data(iev_sum,iev_angall)-ev_data(iev_sum,iev_angmom)) > tiny(0.)) then - write(iprint,"(1x,1(a,'=',es10.3,', '),(a,'=',es10.3),a)") & - 'Linm',ev_data(iev_sum,iev_momall),'Angm',ev_data(iev_sum,iev_angall),' [including accreted particles]' - endif - endif - write(iprint,"(1x,3(a,es10.3))") "Centre of Mass = ",xyzcom(1),", ",xyzcom(2),", ",xyzcom(3) - - write(iprint,"(1x,a,'(max)=',es10.3,' (mean)=',es10.3,' (max)=',es10.3,a)") & - 'density ',ev_data(iev_max,iev_rho),ev_data(iev_ave,iev_rho),ev_data(iev_max,iev_rho)*unit_density,' g/cm^3' - - if (use_dustfrac) then - write(iprint,"(1x,a,'(max)=',es10.3,1x,'(mean)=',es10.3,1x,'(min)=',es10.3)") & - 'dust2gas ',ev_data(iev_max,iev_dtg),ev_data(iev_ave,iev_dtg),ev_data(iev_min,iev_dtg) - write(iprint,"(3x,a,'(mean)=',es10.3,1x,'(min)=',es10.3)") 't_stop ',ev_data(iev_ave,iev_ts),ev_data(iev_min,iev_ts) - endif - if (use_dust) then - write(iprint,"(1x,'Mgas = ',es10.3)") mgas - Mdust_label = 'Mdust' - call make_tags_unique(ndusttypes,Mdust_label) - do i=1,ndusttypes - write(iprint,"(1x,1(a,' = ',es10.3))") trim(Mdust_label(i)),mdust(i) - enddo - endif - - if (track_mass) write(iprint,"(1x,1(a,'=',es10.3))") 'Accreted mass',accretedmass - - string = '' - if (maxalpha==maxp) then - write(string,"(a,'(max)=',es10.3)") ' alpha',ev_data(iev_max,iev_alpha) - endif - if (len_trim(string) > 0) write(iprint,"(a)") trim(string) - - if (irealvisc /= 0) then - if (periodic) then - if (irealvisc==1) then - write(iprint,"(1x,1(a,'=',es10.3,', '),(a,'=',es10.3))") & - 'RMS Mach #',rmsmach,'Reynolds # ',vrms*min(dxbound,dybound,dzbound)/shearparam - endif - endif - write(iprint,"(1x,1(a,'(max)=',es10.3,', '),('(mean)=',es10.3),(' (min)=',es10.3))") & - 'Ratio of physical-to-art. visc',ev_data(iev_max,iev_viscrat),ev_data(iev_min,iev_viscrat) - else - write(iprint,"(1x,1(a,'=',es10.3))") & - 'RMS Mach #',rmsmach - endif - - if (mhd) then - write(iprint,"(1x,1(a,'(max)=',es10.3,', '),(a,'(mean)=',es10.3))") & - 'div B ',ev_data(iev_max,iev_divB),'div B ',ev_data(iev_ave,iev_divB) - write(iprint,"(1x,1(a,'(max)=',es10.3,', '),(a,'(mean)=',es10.3))") & - 'h|div B|/B ',ev_data(iev_max,iev_hdivB),'h|div B|/B ',ev_data(iev_ave,iev_hdivB) - if (ev_data(iev_max,iev_hdivB) > 10.) & - write(iprint,'(a)') 'WARNING! h|div B|/B is growing! Recommend increasing hdivbbmax_max for better stability' - endif - write(iprint,"(/)") - - return -end subroutine write_evlog -!---------------------------------------------------------------- -end module evwrite diff --git a/src/main/extern_Bfield.f90 b/src/main/extern_Bfield.f90 index 908411d22..1b4319e70 100644 --- a/src/main/extern_Bfield.f90 +++ b/src/main/extern_Bfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_Bfield ! diff --git a/src/main/extern_binary.f90 b/src/main/extern_binary.f90 index 88ffde885..d22725666 100644 --- a/src/main/extern_binary.f90 +++ b/src/main/extern_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_binary ! diff --git a/src/main/extern_binary_gw.f90 b/src/main/extern_binary_gw.f90 index 50814ee54..c41bcd59b 100644 --- a/src/main/extern_binary_gw.f90 +++ b/src/main/extern_binary_gw.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_binary ! diff --git a/src/main/extern_corotate.f90 b/src/main/extern_corotate.f90 index 89ddbb143..72eedd4e5 100644 --- a/src/main/extern_corotate.f90 +++ b/src/main/extern_corotate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_corotate ! diff --git a/src/main/extern_densprofile.f90 b/src/main/extern_densprofile.f90 index e2ef14160..e16d09be2 100644 --- a/src/main/extern_densprofile.f90 +++ b/src/main/extern_densprofile.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_densprofile ! diff --git a/src/main/extern_gnewton.F90 b/src/main/extern_gnewton.f90 similarity index 98% rename from src/main/extern_gnewton.F90 rename to src/main/extern_gnewton.f90 index d5508125d..75a8563e9 100644 --- a/src/main/extern_gnewton.F90 +++ b/src/main/extern_gnewton.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_gnewton ! diff --git a/src/main/extern_gwinspiral.f90 b/src/main/extern_gwinspiral.f90 index 224a22287..3d6df7205 100644 --- a/src/main/extern_gwinspiral.f90 +++ b/src/main/extern_gwinspiral.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_gwinspiral ! diff --git a/src/main/extern_lensethirring.f90 b/src/main/extern_lensethirring.f90 index 62ddf2e89..d039422cb 100644 --- a/src/main/extern_lensethirring.f90 +++ b/src/main/extern_lensethirring.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_lensethirring ! diff --git a/src/main/extern_prdrag.F90 b/src/main/extern_prdrag.f90 similarity index 99% rename from src/main/extern_prdrag.F90 rename to src/main/extern_prdrag.f90 index a8356d305..78456bd68 100644 --- a/src/main/extern_prdrag.F90 +++ b/src/main/extern_prdrag.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_prdrag ! diff --git a/src/main/extern_spiral.f90 b/src/main/extern_spiral.f90 index f84598934..b485802f4 100644 --- a/src/main/extern_spiral.f90 +++ b/src/main/extern_spiral.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_spiral ! diff --git a/src/main/extern_staticsine.f90 b/src/main/extern_staticsine.f90 index a3f6385a6..bbb12be75 100644 --- a/src/main/extern_staticsine.f90 +++ b/src/main/extern_staticsine.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_staticsine ! diff --git a/src/main/externalforces.F90 b/src/main/externalforces.F90 index 0d9b707d1..ffd8ba7fc 100644 --- a/src/main/externalforces.F90 +++ b/src/main/externalforces.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module externalforces ! diff --git a/src/main/externalforces_gr.F90 b/src/main/externalforces_gr.F90 index b43123e8b..ae3f37a96 100644 --- a/src/main/externalforces_gr.F90 +++ b/src/main/externalforces_gr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module externalforces ! diff --git a/src/main/kdtree.F90 b/src/main/kdtree.F90 index be9a663aa..9b70a7f1f 100644 --- a/src/main/kdtree.F90 +++ b/src/main/kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module kdtree ! diff --git a/src/main/readwrite_dumps_hdf5.F90 b/src/main/readwrite_dumps_hdf5.F90 index cb0ae30c6..3e929d7b4 100644 --- a/src/main/readwrite_dumps_hdf5.F90 +++ b/src/main/readwrite_dumps_hdf5.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module readwrite_dumps_hdf5 ! @@ -35,8 +35,6 @@ module readwrite_dumps_hdf5 externalforce_hdf5 implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" public :: read_dump_hdf5,read_smalldump_hdf5 public :: write_smalldump_hdf5,write_fulldump_hdf5,write_dump_hdf5 diff --git a/src/main/sort_particles.F90 b/src/main/sort_particles.f90 similarity index 98% rename from src/main/sort_particles.F90 rename to src/main/sort_particles.f90 index a8343c1f9..89cba893a 100644 --- a/src/main/sort_particles.F90 +++ b/src/main/sort_particles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module sort_particles ! diff --git a/src/main/step_supertimestep.F90 b/src/main/step_supertimestep.F90 index 0833435b9..413f0615b 100644 --- a/src/main/step_supertimestep.F90 +++ b/src/main/step_supertimestep.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module supertimestep ! diff --git a/src/main/timestep.F90 b/src/main/timestep.f90 similarity index 99% rename from src/main/timestep.F90 rename to src/main/timestep.f90 index d0ca11800..99bd0e172 100644 --- a/src/main/timestep.F90 +++ b/src/main/timestep.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module timestep ! diff --git a/src/main/units.f90 b/src/main/units.f90 index f133cd4d5..62cae18aa 100644 --- a/src/main/units.f90 +++ b/src/main/units.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module units ! @@ -35,7 +35,7 @@ module units public :: get_G_code, get_c_code, get_radconst_code, get_kbmh_code public :: c_is_unity, G_is_unity, in_geometric_units public :: is_time_unit, is_length_unit - public :: in_solarr, in_solarm + public :: in_solarr, in_solarm, in_solarl contains @@ -464,5 +464,17 @@ real(kind=8) function in_solarr(val) result(rval) rval = val*(udist/solarr) end function in_solarr +!--------------------------------------------------------------------------- +!+ +! function to convert a luminosity value from code units to solar luminosity +!+ +!--------------------------------------------------------------------------- +real(kind=8) function in_solarl(val) result(rval) + use physcon, only:solarl + real, intent(in) :: val + + rval = val*(unit_luminosity/solarl) + +end function in_solarl end module units diff --git a/src/main/utils_allocate.f90 b/src/main/utils_allocate.f90 index 76e2abf2f..d3c704cc1 100644 --- a/src/main/utils_allocate.f90 +++ b/src/main/utils_allocate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module allocutils ! diff --git a/src/main/utils_binary.f90 b/src/main/utils_binary.f90 index dfb78aeee..5f9ca8851 100644 --- a/src/main/utils_binary.f90 +++ b/src/main/utils_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module binaryutils ! @@ -62,7 +62,13 @@ real function get_E_from_mean_anomaly(M_ref,ecc) result(E) M_guess = M_ref - 2.*tol do while (abs(M_ref - M_guess) > tol) - M_guess = E_guess - ecc*sin(E_guess) + if (ecc < 1.) then ! eccentric + M_guess = E_guess - ecc*sin(E_guess) + elseif (ecc > 1.) then ! hyperbolic + M_guess = ecc*sinh(E_guess) - E_guess + else ! parabolic + M_guess = E_guess + 1./3.*E_guess**3 + endif if (M_guess > M_ref) then E_right = E_guess else @@ -75,13 +81,33 @@ real function get_E_from_mean_anomaly(M_ref,ecc) result(E) end function get_E_from_mean_anomaly +!--------------------------------------------------------------- +!+ +! Get eccentric (or parabolic/hyperbolic) anomaly from true anomaly +! https://space.stackexchange.com/questions/23128/design-of-an-elliptical-transfer-orbit/23130#23130 +!+ +!--------------------------------------------------------------- +real function get_E_from_true_anomaly(theta,ecc) result(E) + real, intent(in) :: theta ! true anomaly in radians + real, intent(in) :: ecc ! eccentricity + + if (ecc < 1.) then + E = atan2(sqrt(1. - ecc**2)*sin(theta),(ecc + cos(theta))) + elseif (ecc > 1.) then ! hyperbolic + !E = atanh(sqrt(ecc**2 - 1.)*sin(theta)/(ecc + cos(theta))) + E = 2.*atanh(sqrt((ecc - 1.)/(ecc + 1.))*tan(0.5*theta)) + else ! parabolic + E = tan(0.5*theta) + endif + +end function get_E_from_true_anomaly + !----------------------------------------------------------------------- !+ ! Calculate semi-major axis, ecc, ra and rp from radius(3), velocity(3) ! mass of central object and iexternalforce (for LT corrections) !+ !----------------------------------------------------------------------- - subroutine get_orbit_bits(vel,rad,m1,iexternalforce,semia,ecc,ra,rp) real, intent(in) :: m1, vel(3), rad(3) integer, intent(in) :: iexternalforce diff --git a/src/main/utils_cpuinfo.f90 b/src/main/utils_cpuinfo.f90 index 5c78bb27e..5e50794c9 100644 --- a/src/main/utils_cpuinfo.f90 +++ b/src/main/utils_cpuinfo.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cpuinfo ! diff --git a/src/main/utils_datafiles.f90 b/src/main/utils_datafiles.f90 index 8d5977c51..f3212a0dd 100644 --- a/src/main/utils_datafiles.f90 +++ b/src/main/utils_datafiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module datautils ! @@ -209,10 +209,10 @@ logical function has_write_permission(dir) has_write_permission = .true. open(newunit=iunit,file=trim(dir)//'data.tmp.abcd',action='write',iostat=ierr) - if (ierr /= 0) then - has_write_permission = .false. - endif - close(iunit,status='delete') + if (ierr /= 0) has_write_permission = .false. + + close(iunit,status='delete',iostat=ierr) + if (ierr /= 0) has_write_permission = .false. end function has_write_permission diff --git a/src/main/utils_dumpfiles.f90 b/src/main/utils_dumpfiles.f90 index 99501cdb5..7691ea5c7 100644 --- a/src/main/utils_dumpfiles.f90 +++ b/src/main/utils_dumpfiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module dump_utils ! @@ -1121,12 +1121,13 @@ end subroutine open_dumpfile_w ! open a dump file and read the file id ! and generic header information !----------------------------------------- -subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags) +subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags,tagged) integer, intent(in) :: iunit character(len=*), intent(in) :: filename character(len=lenid), intent(out) :: fileid integer, intent(out) :: ierr - logical, intent(in), optional :: singleprec,requiretags + logical, intent(in), optional :: singleprec,requiretags + logical, intent(out), optional :: tagged integer(kind=4) :: int1i,int2i,int3i integer :: iversion_file,ierr1 logical :: r4,must_have_tags @@ -1193,6 +1194,11 @@ subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags) endif endif + ! return whether or not file is in tagged format + if (present(tagged)) then + tagged = (fileid(2:2) == 'T' .or. fileid(2:2) == 't') + endif + end subroutine open_dumpfile_r !------------------------------------------------------- @@ -1230,19 +1236,22 @@ end function get_error_text ! read the file header into the dump_header structure !+ !------------------------------------------------------- -subroutine read_header(iunit,hdr,tagged,ierr,singleprec) +subroutine read_header(iunit,hdr,ierr,singleprec,tagged) integer, intent(in) :: iunit type(dump_h), intent(out) :: hdr - logical, intent(in) :: tagged integer, intent(out) :: ierr logical, intent(in), optional :: singleprec - logical :: convert_prec + logical, intent(in), optional :: tagged + logical :: convert_prec,tags integer :: i,n real(kind=4), allocatable :: dumr4(:) convert_prec = .false. if (present(singleprec)) convert_prec = singleprec + tags = .true. + if (present(tagged)) tags = tagged + do i=1,ndatatypes read (iunit, iostat=ierr) n if (n < 0) n = 0 @@ -1250,66 +1259,66 @@ subroutine read_header(iunit,hdr,tagged,ierr,singleprec) select case(i) case(i_int) allocate(hdr%inttags(n),hdr%intvals(n),stat=ierr) - hdr%inttags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%inttags(1:n) - read(iunit, iostat=ierr) hdr%intvals(1:n) + hdr%inttags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%inttags + read(iunit, iostat=ierr) hdr%intvals endif case(i_int1) allocate(hdr%int1tags(n),hdr%int1vals(n),stat=ierr) - hdr%int1tags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%int1tags(1:n) - read(iunit, iostat=ierr) hdr%int1vals(1:n) + hdr%int1tags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%int1tags + read(iunit, iostat=ierr) hdr%int1vals endif case(i_int2) allocate(hdr%int2tags(n),hdr%int2vals(n),stat=ierr) - hdr%int2tags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%int2tags(1:n) - read(iunit, iostat=ierr) hdr%int2vals(1:n) + hdr%int2tags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%int2tags + read(iunit, iostat=ierr) hdr%int2vals endif case(i_int4) allocate(hdr%int4tags(n),hdr%int4vals(n),stat=ierr) - hdr%int4tags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%int4tags(1:n) - read(iunit, iostat=ierr) hdr%int4vals(1:n) + hdr%int4tags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%int4tags + read(iunit, iostat=ierr) hdr%int4vals endif case(i_int8) allocate(hdr%int8tags(n),hdr%int8vals(n),stat=ierr) - hdr%int8tags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%int8tags(1:n) - read(iunit, iostat=ierr) hdr%int8vals(1:n) + hdr%int8tags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%int8tags + read(iunit, iostat=ierr) hdr%int8vals endif case(i_real) allocate(hdr%realtags(n),hdr%realvals(n),stat=ierr) - hdr%realtags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%realtags(1:n) + hdr%realtags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%realtags if (convert_prec .and. kind(0.) /= 4) then allocate(dumr4(n),stat=ierr) - read(iunit, iostat=ierr) dumr4(1:n) + read(iunit, iostat=ierr) dumr4 hdr%realvals(1:n) = real(dumr4(1:n)) deallocate(dumr4) else - read(iunit, iostat=ierr) hdr%realvals(1:n) + read(iunit, iostat=ierr) hdr%realvals endif endif case(i_real4) allocate(hdr%real4tags(n),hdr%real4vals(n),stat=ierr) - hdr%real4tags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%real4tags(1:n) - read(iunit, iostat=ierr) hdr%real4vals(1:n) + hdr%real4tags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%real4tags + read(iunit, iostat=ierr) hdr%real4vals endif case(i_real8) allocate(hdr%real8tags(n),hdr%real8vals(n),stat=ierr) - hdr%real8tags(:) = '' if (n > 0) then - if (tagged) read(iunit, iostat=ierr) hdr%real8tags(1:n) - read(iunit, iostat=ierr) hdr%real8vals(1:n) + hdr%real8tags(:) = '' + if (tags) read(iunit, iostat=ierr) hdr%real8tags + read(iunit, iostat=ierr) hdr%real8vals endif end select enddo @@ -2054,6 +2063,10 @@ subroutine read_array_real4(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag,ma matched = .true. if (match_datatype) then got_arr = .true. + if (i2 > size(arr)) then + print*,'ERROR: array size too small reading array: need ',i2,' got ',size(arr) + read(iunit,iostat=ierr) + endif read(iunit,iostat=ierr) (dum,i=1,noffset),arr(i1:i2) else print*,'ERROR: wrong datatype for '//trim(tag)//' (is not real4)' @@ -2071,21 +2084,22 @@ end subroutine read_array_real4 !-------------------------------------------------------------------- subroutine read_array_real4arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag,matched,ierr) real(kind=4), intent(inout) :: arr(:,:) - character(len=*), intent(in) :: arr_tag(size(arr(1,:))),tag - logical, intent(inout) :: got_arr(size(arr(1,:))) + character(len=*), intent(in) :: arr_tag(:),tag + logical, intent(inout) :: got_arr(:) integer, intent(in) :: ikind,i1,i2,noffset,iunit logical, intent(inout) :: matched integer, intent(out) :: ierr integer :: i,j,nread real(kind=4) :: dum real(kind=8) :: dumr8 + real(kind=4), allocatable :: dummy(:) real(kind=8), allocatable :: dummyr8(:) logical :: match_datatype if (matched .or. ikind < i_real) return match_datatype = (ikind==i_real4 .or. (kind(0.)==4 .and. ikind==i_real)) - do j=1,size(arr(:,1)) + do j=1,min(size(arr(:,1)),size(arr_tag)) if (match_tag(tag,arr_tag(j)) .and. .not.matched) then matched = .true. if (match_datatype) then @@ -2095,7 +2109,12 @@ subroutine read_array_real4arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag ierr = ierr_arraysize return endif - read(iunit,iostat=ierr) (dum,i=1,noffset),arr(j,i1:i2) + nread = i2-i1+1 + allocate(dummy(nread)) + read(iunit,iostat=ierr) (dum,i=1,noffset),dummy(1:nread) + arr(j,i1:i2) = dummy + deallocate(dummy) + !read(iunit,iostat=ierr) (dum,i=1,noffset),arr(j,i1:i2) elseif (ikind==i_real4) then got_arr(j) = .true. !print*,'WARNING: converting '//trim(tag)//' from real*8->real*4' @@ -2173,8 +2192,8 @@ end subroutine read_array_real8 !-------------------------------------------------------------------- subroutine read_array_real8arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag,matched,ierr) real(kind=8), intent(inout) :: arr(:,:) - character(len=*), intent(in) :: arr_tag(size(arr(1,:))),tag - logical, intent(inout) :: got_arr(size(arr(1,:))) + character(len=*), intent(in) :: arr_tag(:),tag + logical, intent(inout) :: got_arr(:) integer, intent(in) :: ikind,i1,i2,noffset,iunit logical, intent(inout) :: matched integer, intent(out) :: ierr @@ -2188,7 +2207,7 @@ subroutine read_array_real8arr(arr,arr_tag,got_arr,ikind,i1,i2,noffset,iunit,tag if (matched .or. ikind < i_real) return match_datatype = (ikind==i_real8 .or. (kind(0.)==8 .and. ikind==i_real)) - do j=1,size(arr(:,1)) + do j=1,min(size(arr(:,1)),size(arr_tag)) if (match_tag(tag,arr_tag(j)) .and. .not.matched) then matched = .true. if (match_datatype) then diff --git a/src/main/utils_dumpfiles_hdf5.f90 b/src/main/utils_dumpfiles_hdf5.f90 index 787580de6..581d06cd8 100644 --- a/src/main/utils_dumpfiles_hdf5.f90 +++ b/src/main/utils_dumpfiles_hdf5.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module utils_dumpfiles_hdf5 ! diff --git a/src/main/utils_gr.F90 b/src/main/utils_gr.F90 index a00aa68a0..479476ca6 100644 --- a/src/main/utils_gr.F90 +++ b/src/main/utils_gr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module utils_gr ! diff --git a/src/main/utils_hdf5.f90 b/src/main/utils_hdf5.f90 index 42f2ee222..2afa77842 100644 --- a/src/main/utils_hdf5.f90 +++ b/src/main/utils_hdf5.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module utils_hdf5 ! diff --git a/src/main/utils_healpix.f90 b/src/main/utils_healpix.f90 index 52c246ece..407761514 100644 --- a/src/main/utils_healpix.f90 +++ b/src/main/utils_healpix.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module healpix ! diff --git a/src/main/utils_infiles.f90 b/src/main/utils_infiles.f90 index 30ea78959..c40332b25 100644 --- a/src/main/utils_infiles.f90 +++ b/src/main/utils_infiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module infile_utils ! From 2c802a94a0cc8e48e54403ec9f118b93a6447622 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 11 Apr 2024 12:24:19 +0100 Subject: [PATCH 103/182] restoring upstream changes part 3 --- src/main/checksetup.f90 | 2 +- src/main/eos.F90 | 2 +- src/main/evwrite.f90 | 500 ++ src/main/extern_binary_gw.f90 | 2 +- src/main/extern_densprofile.f90 | 2 +- src/main/extern_gr.f90 | 411 ++ src/main/extern_gwinspiral.f90 | 2 +- src/main/extern_lensethirring.f90 | 2 +- src/main/extern_spiral.f90 | 2 +- src/main/extern_staticsine.f90 | 2 +- ...{externalforces.F90 => externalforces.f90} | 6 +- ...nalforces_gr.F90 => externalforces_gr.f90} | 4 +- src/main/fastmath.f90 | 2 +- src/main/force.F90 | 2 +- src/main/forcing.F90 | 30 +- src/main/fs_data.f90 | 2 +- src/main/geometry.f90 | 2 +- src/main/gitinfo.f90 | 2 +- src/main/growth_smol.f90 | 2 +- src/main/h2chem.f90 | 4 +- src/main/inject_BHL.f90 | 17 +- src/main/inject_bondi.f90 | 10 +- src/main/inject_firehose.f90 | 9 +- src/main/inject_galcen_winds.f90 | 10 +- src/main/inject_keplerianshear.f90 | 29 +- src/main/inject_rochelobe.f90 | 10 +- src/main/inject_sne.f90 | 10 +- src/main/inject_unifwind.f90 | 10 +- src/main/{inject_wind.F90 => inject_wind.f90} | 0 src/main/inverse4x4.f90 | 2 +- src/main/io.F90 | 2 +- src/main/ionization.f90 | 2 +- src/main/kernel_WendlandC2.f90 | 2 +- src/main/kernel_WendlandC4.f90 | 2 +- src/main/kernel_WendlandC6.f90 | 2 +- src/main/kernel_cubic.f90 | 2 +- src/main/kernel_quartic.f90 | 2 +- src/main/kernel_quintic.f90 | 2 +- src/main/krome.f90 | 2 +- src/main/linklist_kdtree.F90 | 4 +- src/main/lumin_nsdisc.f90 | 12 +- src/main/memory.f90 | 16 +- src/main/metric_kerr-schild.f90 | 2 +- src/main/metric_kerr.f90 | 2 +- src/main/metric_minkowski.f90 | 2 +- src/main/metric_schwarzschild.f90 | 2 +- src/main/metric_tools.F90 | 2 +- src/main/mf_write.f90 | 2 +- src/main/mol_data.f90 | 2 +- src/main/mpi_balance.F90 | 36 +- src/main/mpi_dens.F90 | 2 +- src/main/mpi_derivs.F90 | 2 +- src/main/mpi_domain.F90 | 4 +- src/main/mpi_force.F90 | 2 +- src/main/mpi_memory.F90 | 2 +- src/main/mpi_memory.f90 | 317 ++ src/main/mpi_tree.F90 | 2 +- src/main/mpi_utils.F90 | 2 +- src/main/nicil_supplement.F90 | 2 +- src/main/nicil_supplement.f90 | 236 + src/main/options.f90 | 3 +- src/main/part.F90 | 40 +- src/main/phantom.F90 | 2 +- src/main/photoevap.f90 | 432 -- src/main/physcon.f90 | 2 +- ...{ptmass_heating.F90 => ptmass_heating.f90} | 0 ...ass_radiation.F90 => ptmass_radiation.f90} | 2 +- src/main/quitdump.f90 | 2 +- src/main/radiation_utils.f90 | 2 +- src/main/random.f90 | 2 +- src/main/readwrite_dumps.F90 | 7 +- src/main/readwrite_dumps_fortran.F90 | 158 +- src/main/step_leapfrog.F90 | 143 +- src/utils/analysis_BRhoOrientation.F90 | 2 +- src/utils/analysis_clumpfind.F90 | 2 +- src/utils/analysis_clumpfindWB23.F90 | 2 +- src/utils/analysis_common_envelope.F90 | 4594 ----------------- src/utils/analysis_dustywind.F90 | 348 -- src/utils/analysis_kdtree.F90 | 2 +- src/utils/analysis_protostar_environ.F90 | 2 +- src/utils/analysis_write_kdtree.F90 | 2 +- src/utils/interpolate3D_amr.F90 | 2 +- src/utils/struct_part.F90 | 269 - src/utils/utils_getneighbours.F90 | 2 +- src/utils/utils_raytracer_all.F90 | 1199 ----- 85 files changed, 1823 insertions(+), 7159 deletions(-) create mode 100644 src/main/evwrite.f90 create mode 100644 src/main/extern_gr.f90 rename src/main/{externalforces.F90 => externalforces.f90} (99%) rename src/main/{externalforces_gr.F90 => externalforces_gr.f90} (99%) rename src/main/{inject_wind.F90 => inject_wind.f90} (100%) create mode 100644 src/main/mpi_memory.f90 create mode 100644 src/main/nicil_supplement.f90 delete mode 100644 src/main/photoevap.f90 rename src/main/{ptmass_heating.F90 => ptmass_heating.f90} (100%) rename src/main/{ptmass_radiation.F90 => ptmass_radiation.f90} (99%) delete mode 100644 src/utils/analysis_common_envelope.F90 delete mode 100644 src/utils/analysis_dustywind.F90 delete mode 100644 src/utils/struct_part.F90 delete mode 100644 src/utils/utils_raytracer_all.F90 diff --git a/src/main/checksetup.f90 b/src/main/checksetup.f90 index e4e0c17cd..a14201b96 100644 --- a/src/main/checksetup.f90 +++ b/src/main/checksetup.f90 @@ -996,7 +996,7 @@ subroutine check_setup_radiation(npart,nerror,nwarn,radprop,rad) call check_NaN(npart,rad,'radiation_energy',nerror) call check_NaN(npart,radprop,'radiation properties',nerror) - + end subroutine check_setup_radiation end module checksetup diff --git a/src/main/eos.F90 b/src/main/eos.F90 index 9204baaf0..e90d18aeb 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos ! diff --git a/src/main/evwrite.f90 b/src/main/evwrite.f90 new file mode 100644 index 000000000..8c8e5b76f --- /dev/null +++ b/src/main/evwrite.f90 @@ -0,0 +1,500 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module evwrite +! +! Calculates conserved quantities etc and writes to .ev file; +! Also writes log output +! To Developer: To add values to the .ev file, follow the following procedure. +! In the init_evfile subroutine in evwrite.F90, add the following command: +! call fill_ev_label(ev_fmt,ev_tag_int,ev_tag_char,action,i,j) +! and in compute_energies subroutine in energies.F90, add the following command: +! call ev_data_update(ev_data_thread,ev_tag_int,value) +! where +! ev_fmt,ev_data_thread,i,j: pre-defined quantities to included verbatim +! ev_tag_char: a string to identify the quantity for use in the header +! (e.g. 'c_s' for sound speed) +! ev_tag_int: an integer to identify the quantity (e.g. 'iev_cs' for sound speed); +! this integer must be included in energies (as a public variable, +! and in the openmp declarations), and passed to evwrite via use energies. +! ev_value: the value of the quantity for particle i (e.g., spsoundi for sound speed) +! action: a string identifying what action(s) you would like performed +! on the quantity. The available options are +! 0: no action taken (e.g. for time) +! s: sum quantity (e.g. for entropy) +! x: print the maximum quantity +! a: print the average (mean) quantity +! n: print the minimum quantity +! where any or all of x,a,n can be used as a single action. Although 0 & s are treated +! the same, they are kept separate for clarity without added computational cost +! +! :References: None +! +! :Owner: James Wurster +! +! :Runtime parameters: None +! +! :Dependencies: boundary, boundary_dyn, dim, energies, eos, +! externalforces, fileutils, gravwaveutils, io, mpiutils, nicil, options, +! part, ptmass, timestep, units, viscosity +! + use io, only:fatal,iverbose + use options, only:iexternalforce + use timestep, only:dtmax_dratio + use externalforces, only:iext_binary,was_accreted + use energies, only:inumev,iquantities,ev_data + use energies, only:ndead,npartall + use energies, only:gas_only,track_mass,track_lum + use energies, only:iev_sum,iev_max,iev_min,iev_ave + use energies, only:iev_time,iev_ekin,iev_etherm,iev_emag,iev_epot,iev_etot,iev_totmom,iev_com,& + iev_angmom,iev_rho,iev_dt,iev_dtx,iev_entrop,iev_rmsmach,iev_vrms,iev_rhop,iev_alpha,& + iev_B,iev_divB,iev_hdivB,iev_beta,iev_temp,iev_etao,iev_etah,& + iev_etaa,iev_vel,iev_vhall,iev_vion,iev_n,& + iev_dtg,iev_ts,iev_dm,iev_momall,iev_angall,iev_angall,iev_maccsink,& + iev_macc,iev_eacc,iev_totlum,iev_erot,iev_viscrat,iev_erad,iev_gws,iev_mass,iev_bdy + + implicit none + public :: init_evfile, write_evfile, write_evlog + private :: fill_ev_tag, fill_ev_header + + integer, private :: ielements + integer, private :: ev_cmd(inumev) ! array of the actions to be taken + character(len=19),private :: ev_label(inumev) ! to make the header for the .ev file + + private + +contains + +!---------------------------------------------------------------- +!+ +! opens the .ev file for output +!+ +!---------------------------------------------------------------- +subroutine init_evfile(iunit,evfile,open_file) + use io, only:id,master,warning + use dim, only:maxtypes,maxalpha,maxp,maxp_hard,mhd,mhd_nonideal,lightcurve + use options, only:calc_erot,ishock_heating,ipdv_heating,use_dustfrac + use units, only:c_is_unity + use part, only:igas,idust,iboundary,istar,idarkmatter,ibulge,npartoftype,ndusttypes,maxtypes + use nicil, only:use_ohm,use_hall,use_ambi + use viscosity, only:irealvisc + use mpiutils, only:reduceall_mpi + use eos, only:ieos,eos_is_non_ideal,eos_outputs_gasP + use gravwaveutils, only:calc_gravitwaves + use boundary_dyn, only:dynamic_bdy + integer, intent(in) :: iunit + character(len= *), intent(in) :: evfile + logical, intent(in) :: open_file + character(len= 27) :: ev_fmt + character(len= 11) :: dustname + integer :: i,j,k + integer(kind=8) :: npartoftypetot(maxtypes) + ! + !--Initialise additional variables + ! + npartoftypetot = reduceall_mpi('+', npartoftype) + gas_only = .true. + do i = 2,maxtypes + if (npartoftypetot(i) > 0) gas_only = .false. + enddo + write(ev_fmt,'(a)') "(1x,'[',i2.2,1x,a11,']',2x)" + ! + !--Define all the variables to be included in the .ev file and their supplementary information + ! + i = 1 + j = 1 + call fill_ev_tag(ev_fmt,iev_time, 'time', '0', i,j) + call fill_ev_tag(ev_fmt,iev_ekin, 'ekin', '0', i,j) + call fill_ev_tag(ev_fmt,iev_etherm, 'etherm', '0', i,j) + call fill_ev_tag(ev_fmt,iev_emag, 'emag', '0', i,j) + call fill_ev_tag(ev_fmt,iev_epot, 'epot', '0', i,j) + call fill_ev_tag(ev_fmt,iev_etot, 'etot', '0', i,j) + call fill_ev_tag(ev_fmt,iev_erad, 'erad', '0', i,j) + call fill_ev_tag(ev_fmt,iev_totmom, 'totmom', '0', i,j) + call fill_ev_tag(ev_fmt,iev_angmom, 'angtot', '0', i,j) + call fill_ev_tag(ev_fmt,iev_rho, 'rho', 'xa',i,j) + call fill_ev_tag(ev_fmt,iev_dt, 'dt', '0', i,j) + if (dtmax_dratio > 0.) then + call fill_ev_tag(ev_fmt,iev_dtx, 'dtmax', '0', i,j) + endif + if (maxp==maxp_hard) then + call fill_ev_tag(ev_fmt,iev_mass,'mass', '0', i,j) + endif + call fill_ev_tag(ev_fmt,iev_entrop, 'totentrop','s', i,j) + call fill_ev_tag(ev_fmt,iev_rmsmach,'rmsmach', '0', i,j) + call fill_ev_tag(ev_fmt,iev_vrms, 'vrms', '0', i,j) + call fill_ev_tag(ev_fmt,iev_com(1), 'xcom', '0', i,j) + call fill_ev_tag(ev_fmt,iev_com(2), 'ycom', '0', i,j) + call fill_ev_tag(ev_fmt,iev_com(3), 'zcom', '0', i,j) + if (.not. gas_only) then + if (npartoftypetot(igas) > 0) call fill_ev_tag(ev_fmt,iev_rhop(1),'rho gas', 'xa',i,j) + if (npartoftypetot(idust) > 0) call fill_ev_tag(ev_fmt,iev_rhop(2),'rho dust','xa',i,j) + if (npartoftypetot(iboundary) > 0) call fill_ev_tag(ev_fmt,iev_rhop(3),'rho bdy', 'xa',i,j) + if (npartoftypetot(istar) > 0) call fill_ev_tag(ev_fmt,iev_rhop(4),'rho star','xa',i,j) + if (npartoftypetot(idarkmatter) > 0) call fill_ev_tag(ev_fmt,iev_rhop(5),'rho dm', 'xa',i,j) + if (npartoftypetot(ibulge) > 0) call fill_ev_tag(ev_fmt,iev_rhop(6),'rho blg', 'xa',i,j) + endif + if (maxalpha==maxp) then + call fill_ev_tag(ev_fmt, iev_alpha, 'alpha', 'x', i,j) + endif + if (eos_is_non_ideal(ieos) .or. eos_outputs_gasP(ieos)) then + call fill_ev_tag(ev_fmt, iev_temp, 'temp', 'xan',i,j) + endif + if ( mhd ) then + call fill_ev_tag(ev_fmt, iev_B, 'B', 'xan',i,j) + call fill_ev_tag(ev_fmt, iev_divB, 'divB', 'xa' ,i,j) + call fill_ev_tag(ev_fmt, iev_hdivB, 'hdivB/B','xa' ,i,j) + call fill_ev_tag(ev_fmt, iev_beta, 'beta_P', 'xan',i,j) + if (mhd_nonideal) then + if (use_ohm) then + call fill_ev_tag(ev_fmt,iev_etao, 'eta_o', 'xan',i,j) + endif + if (use_hall) then + call fill_ev_tag(ev_fmt,iev_etah(1),'eta_h', 'xan',i,j) + call fill_ev_tag(ev_fmt,iev_etah(2),'|eta_h|', 'xan',i,j) + call fill_ev_tag(ev_fmt,iev_vhall, 'v_hall', 'xan',i,j) + endif + if (use_ambi) then + call fill_ev_tag(ev_fmt,iev_etaa, 'eta_a', 'xan',i,j) + call fill_ev_tag(ev_fmt,iev_vel, 'velocity', 'xan',i,j) + call fill_ev_tag(ev_fmt,iev_vion, 'v_ion', 'xan',i,j) + endif + call fill_ev_tag(ev_fmt, iev_n(1), 'ni/n(i+n)','xan',i,j) + call fill_ev_tag(ev_fmt, iev_n(2), 'ne/n(i+n)','xan',i,j) + call fill_ev_tag(ev_fmt, iev_n(3), 'n_e', 'xa', i,j) + call fill_ev_tag(ev_fmt, iev_n(4), 'n_n', 'xa', i,j) + call fill_ev_tag(ev_fmt, iev_n(5), 'n_g(Z=-1)','xa', i,j) + call fill_ev_tag(ev_fmt, iev_n(6), 'n_g(Z= 0)','xa', i,j) + call fill_ev_tag(ev_fmt, iev_n(7), 'n_g(Z=+1)','xa', i,j) + endif + endif + if (use_dustfrac) then + call fill_ev_tag(ev_fmt, iev_dtg,'dust/gas', 'xan',i,j) + call fill_ev_tag(ev_fmt, iev_ts, 't_s', 'xn', i,j) + do k=1,ndusttypes + write(dustname,'(a,I3)') 'DustMass',k + call fill_ev_tag(ev_fmt,iev_dm(k), dustname, '0', i,j) + enddo + endif + if (iexternalforce > 0) then + call fill_ev_tag(ev_fmt, iev_momall,'totmomall', '0',i,j) + call fill_ev_tag(ev_fmt, iev_angall,'angall', '0',i,j) + if (iexternalforce==iext_binary) then + call fill_ev_tag(ev_fmt,iev_maccsink(1),'Macc sink 1', '0',i,j) + call fill_ev_tag(ev_fmt,iev_maccsink(2),'Macc sink 2', '0',i,j) + endif + endif + if (was_accreted(iexternalforce,-1.0)) then + call fill_ev_tag(ev_fmt,iev_macc, 'accretedmas', 's',i,j) + call fill_ev_tag(ev_fmt,iev_eacc, 'eacc', '0',i,j) + track_mass = .true. + else + track_mass = .false. + endif + if (ishock_heating==0 .or. ipdv_heating==0 .or. lightcurve) then + call fill_ev_tag(ev_fmt,iev_totlum,'tot lum', '0',i,j) + track_lum = .true. + else + track_lum = .false. + endif + if (calc_erot) then + call fill_ev_tag(ev_fmt,iev_erot(1),'erot_x', 's',i,j) + call fill_ev_tag(ev_fmt,iev_erot(2),'erot_y', 's',i,j) + call fill_ev_tag(ev_fmt,iev_erot(3),'erot_z', 's',i,j) + call fill_ev_tag(ev_fmt,iev_erot(4),'erot', '0',i,j) + endif + if (irealvisc /= 0) then + call fill_ev_tag(ev_fmt,iev_viscrat,'visc_rat','xan',i,j) + endif + + if (calc_gravitwaves) then + call fill_ev_tag(ev_fmt,iev_gws(1),'hx_0','0',i,j) + call fill_ev_tag(ev_fmt,iev_gws(2),'hp_0','0',i,j) + call fill_ev_tag(ev_fmt,iev_gws(3),'hx_{30}','0',i,j) + call fill_ev_tag(ev_fmt,iev_gws(4),'hp_{30}','0',i,j) + call fill_ev_tag(ev_fmt,iev_gws(5),'hx_{60}','0',i,j) + call fill_ev_tag(ev_fmt,iev_gws(6),'hp_{60}','0',i,j) + call fill_ev_tag(ev_fmt,iev_gws(7),'hx_{90}','0',i,j) + call fill_ev_tag(ev_fmt,iev_gws(8),'hp_{90}','0',i,j) + endif + if (dynamic_bdy) then + call fill_ev_tag(ev_fmt,iev_bdy(1,1),'min_x','0',i,j) + call fill_ev_tag(ev_fmt,iev_bdy(1,2),'max_x','0',i,j) + call fill_ev_tag(ev_fmt,iev_bdy(2,1),'min_y','0',i,j) + call fill_ev_tag(ev_fmt,iev_bdy(2,2),'max_y','0',i,j) + call fill_ev_tag(ev_fmt,iev_bdy(3,1),'min_z','0',i,j) + call fill_ev_tag(ev_fmt,iev_bdy(3,2),'max_z','0',i,j) + endif + iquantities = i - 1 ! The number of different quantities to analyse + ielements = j - 1 ! The number of values to be calculated (i.e. the number of columns in .ve) + ! + !--all threads do above, but only master writes file + ! (the open_file is to prevent an .ev file from being made during the test suite) + ! + if (open_file .and. id == master) then + ! + !--open the file for output + ! + open(unit=iunit,file=evfile,form='formatted',status='replace') + ! + !--write a header line + ! + write(ev_fmt,'(a,I3,a)') '(',ielements+1,'a)' + write(iunit,ev_fmt)'#',ev_label(1:ielements) + endif + +end subroutine init_evfile + +!---------------------------------------------------------------- +!+ +! creates up to three lables per input value, and fills the required +! tracking arrays; this includes a check to verify the actions are legal +!+ +!---------------------------------------------------------------- +subroutine fill_ev_tag(ev_fmt,itag,label,cmd,i,j) + integer, intent(inout) :: i,j + integer, intent(out) :: itag + character(len=*), intent(in) :: ev_fmt,label,cmd + integer :: ki,kj,iindex,joffset + + ! initialise command + itag = i + joffset = 1 + ev_cmd(i) = 0 + ! + ! make the headers & set ev_cmd + if (index(cmd,'0') > 0) call fill_ev_header(ev_fmt,label,'0',j,joffset) + if (index(cmd,'s') > 0) call fill_ev_header(ev_fmt,label,'s',j,joffset) + if (index(cmd,'x') > 0) then + call fill_ev_header(ev_fmt,label,'x',j,joffset) + ev_cmd(i) = ev_cmd(i) + 1 + joffset = joffset + 1 + endif + if (index(cmd,'a') > 0) then + call fill_ev_header(ev_fmt,label,'a',j,joffset) + ev_cmd(i) = ev_cmd(i) + 2 + joffset = joffset + 1 + endif + if (index(cmd,'n') > 0) then + call fill_ev_header(ev_fmt,label,'n',j,joffset) + ev_cmd(i) = ev_cmd(i) + 5 + endif + i = i + 1 + j = j + len(trim(cmd)) + ! + ! verify action command is legal + if ( (index(cmd,'x') > 0) .or. (index(cmd,'a') > 0) .or. (index(cmd,'n') > 0) ) then + iindex = 1 + else + iindex = 0 + endif + if ( index(cmd,'0') + index(cmd,'s') + iindex > 1) & + call fatal('fill_ev_tag','using an invalid sequence of actions for element', var=cmd) + do ki = 1,len(cmd)-1 + do kj = ki+1,len(cmd) + if ( cmd(ki:ki)==cmd(kj:kj) ) then + call fatal('fill_ev_tag','using duplicate actions for the same quantity', var=cmd) + endif + enddo + enddo + +end subroutine fill_ev_tag +!---------------------------------------------------------------- +!+ +! Fill an array to be used for the header of the .ev file +!+ +!---------------------------------------------------------------- +subroutine fill_ev_header(ev_fmt,label,cxmn,j,joffset) + integer, intent(in) :: j,joffset + character(len=* ), intent(in) :: ev_fmt,label + character(len= 1), intent(in) :: cxmn + character(len=11) :: label0 + character(len= 3) :: ext + integer :: j_actual + + if (len(label)>11 .and. (cxmn=='0' .or. cxmn=='s') ) then + label0 = label(1:11) + elseif (len(label)>9 .and. (cxmn=='x' .or. cxmn=='a' .or. cxmn=='n')) then + label0 = label(1:9) + else + label0 = label + endif + ext = "" + if (len(label)<=7) then + if (cxmn=='x') ext = "max" + if (cxmn=='a') ext = "ave" + if (cxmn=='n') ext = "min" + elseif (len(label)<=9) then + if (cxmn=='x') ext = "X" + if (cxmn=='a') ext = "A" + if (cxmn=='n') ext = "N" + endif + if (ext/="") write(label0,'(a,1x,a)')trim(label0),trim(ext); + ! + j_actual = j + joffset - 1 + if (j_actual > 99) then + write(ev_label(j_actual),ev_fmt) 100-j_actual,trim(label0) + else + write(ev_label(j_actual),ev_fmt) j_actual,trim(label0) + endif + +end subroutine fill_ev_header +!---------------------------------------------------------------- +!+ +! calculates total energy, etc, and writes line to .ev file +!+ +!---------------------------------------------------------------- +subroutine write_evfile(t,dt) + use energies, only:compute_energies,ev_data_update + use io, only:id,master,ievfile + use timestep, only:dtmax_user + use options, only:iexternalforce + use externalforces,only:accretedmass1,accretedmass2 + real, intent(in) :: t,dt + integer :: i,j + real :: ev_data_out(ielements) + character(len=35) :: ev_format + + call compute_energies(t) + + if (id==master) then + !--fill in additional details that are not calculated in energies.f + ev_data(iev_sum,iev_dt) = dt + ev_data(iev_sum,iev_dtx) = dtmax_user + if (iexternalforce==iext_binary) then + ev_data(iev_sum,iev_maccsink(1)) = accretedmass1 + ev_data(iev_sum,iev_maccsink(2)) = accretedmass2 + endif + ! Fill in the data_out array + j = 1 + do i = 1,iquantities + if (ev_cmd(i)==0) then + ! include the total value + ev_data_out(j) = ev_data(iev_sum,i) + j = j + 1 + else + if (ev_cmd(i)==1 .or. ev_cmd(i)==3 .or. ev_cmd(i)==6 .or. ev_cmd(i)==8) then + ! include the maximum value + ev_data_out(j) = ev_data(iev_max,i) + j = j + 1 + endif + if (ev_cmd(i)==2 .or. ev_cmd(i)==3 .or. ev_cmd(i)==7 .or. ev_cmd(i)==8) then + ! include the average value + ev_data_out(j) = ev_data(iev_ave,i) + j = j + 1 + endif + if (ev_cmd(i)==5 .or. ev_cmd(i)==6 .or. ev_cmd(i)==7 .or. ev_cmd(i)==8) then + ! include the minimum value + ev_data_out(j) = ev_data(iev_min,i) + j = j + 1 + endif + endif + enddo + ! + !--write line to .ev file (should correspond to header, below) + ! + write(ev_format,'(a,I3,a)')"(",ielements,"(1pe18.10,1x))" + write(ievfile,ev_format) ev_data_out + call flush(ievfile) + endif + +end subroutine write_evfile +!---------------------------------------------------------------- +!+ +! Writes nicely formatted output to the log file/screen +! Must be called *after* a call to compute energies has been +! performed +!+ +!---------------------------------------------------------------- +subroutine write_evlog(iprint) + use dim, only:maxp,maxalpha,mhd,maxvxyzu,periodic,mhd_nonideal,& + use_dust,maxdusttypes,do_radiation,inject_parts + use energies, only:ekin,etherm,emag,epot,etot,rmsmach,vrms,accretedmass,mdust,mgas,xyzcom + use energies, only:erad + use part, only:nptmass,ndusttypes + use viscosity, only:irealvisc,shearparam + use boundary, only:dxbound,dybound,dzbound + use units, only:unit_density + use options, only:use_dustfrac + use fileutils, only:make_tags_unique + use ptmass, only:icreate_sinks + integer, intent(in) :: iprint + character(len=120) :: string,Mdust_label(maxdusttypes) + integer :: i + + if (ndead > 0 .or. nptmass > 0 .or. icreate_sinks > 0 .or. inject_parts .or. iverbose > 0) then + write(iprint,"(1x,4(a,I10))") 'npart=',npartall,', n_alive=',npartall-ndead, & + ', n_dead_or_accreted=',ndead,', nptmass=',nptmass + endif + + write(iprint,"(1x,3('E',a,'=',es10.3,', '),('E',a,'=',es10.3))") 'tot',etot,'kin',ekin,'therm',etherm,'pot',epot + + if (mhd) write(iprint,"(1x,('E',a,'=',es10.3))") 'mag',emag + if (do_radiation) write(iprint,"(1x,('E',a,'=',es10.3))") 'rad',erad + if (track_mass) write(iprint,"(1x,('E',a,'=',es10.3))") 'acc',ev_data(iev_sum,iev_eacc) + write(iprint,"(1x,1(a,'=',es10.3,', '),(a,'=',es10.3))") & + 'Linm',ev_data(iev_sum,iev_totmom),'Angm',ev_data(iev_sum,iev_angmom) + if (iexternalforce > 0) then + if (abs(ev_data(iev_sum,iev_angall)-ev_data(iev_sum,iev_angmom)) > tiny(0.)) then + write(iprint,"(1x,1(a,'=',es10.3,', '),(a,'=',es10.3),a)") & + 'Linm',ev_data(iev_sum,iev_momall),'Angm',ev_data(iev_sum,iev_angall),' [including accreted particles]' + endif + endif + write(iprint,"(1x,3(a,es10.3))") "Centre of Mass = ",xyzcom(1),", ",xyzcom(2),", ",xyzcom(3) + + if (ev_data(iev_max,iev_rho) > 0.) then ! avoid floating point exception if no gas particles + write(iprint,"(1x,a,'(max)=',es10.3,' (mean)=',es10.3,' (max)=',es10.3,a)") & + 'density ',ev_data(iev_max,iev_rho),ev_data(iev_ave,iev_rho),ev_data(iev_max,iev_rho)*unit_density,' g/cm^3' + endif + + if (use_dustfrac) then + write(iprint,"(1x,a,'(max)=',es10.3,1x,'(mean)=',es10.3,1x,'(min)=',es10.3)") & + 'dust2gas ',ev_data(iev_max,iev_dtg),ev_data(iev_ave,iev_dtg),ev_data(iev_min,iev_dtg) + write(iprint,"(3x,a,'(mean)=',es10.3,1x,'(min)=',es10.3)") 't_stop ',ev_data(iev_ave,iev_ts),ev_data(iev_min,iev_ts) + endif + if (use_dust) then + write(iprint,"(1x,'Mgas = ',es10.3)") mgas + Mdust_label = 'Mdust' + call make_tags_unique(ndusttypes,Mdust_label) + do i=1,ndusttypes + write(iprint,"(1x,1(a,' = ',es10.3))") trim(Mdust_label(i)),mdust(i) + enddo + endif + + if (track_mass) write(iprint,"(1x,1(a,'=',es10.3))") 'Accreted mass',accretedmass + + string = '' + if (maxalpha==maxp) then + if (ev_data(iev_max,iev_alpha) > 0.) write(string,"(a,'(max)=',es10.3)") ' alpha',ev_data(iev_max,iev_alpha) + endif + if (len_trim(string) > 0) write(iprint,"(a)") trim(string) + + if (irealvisc /= 0 .and. npartall > 0) then + if (periodic) then + if (irealvisc==1) then + write(iprint,"(1x,1(a,'=',es10.3,', '),(a,'=',es10.3))") & + 'RMS Mach #',rmsmach,'Reynolds # ',vrms*min(dxbound,dybound,dzbound)/shearparam + endif + endif + write(iprint,"(1x,1(a,'(max)=',es10.3,', '),('(mean)=',es10.3),(' (min)=',es10.3))") & + 'Ratio of physical-to-art. visc',ev_data(iev_max,iev_viscrat),ev_data(iev_min,iev_viscrat) + elseif (npartall > 0) then + write(iprint,"(1x,1(a,'=',es10.3))") 'RMS Mach #',rmsmach + endif + + if (mhd) then + write(iprint,"(1x,1(a,'(max)=',es10.3,', '),(a,'(mean)=',es10.3))") & + 'div B ',ev_data(iev_max,iev_divB),'div B ',ev_data(iev_ave,iev_divB) + write(iprint,"(1x,1(a,'(max)=',es10.3,', '),(a,'(mean)=',es10.3))") & + 'h|div B|/B ',ev_data(iev_max,iev_hdivB),'h|div B|/B ',ev_data(iev_ave,iev_hdivB) + if (ev_data(iev_max,iev_hdivB) > 10.) & + write(iprint,'(a)') 'WARNING! h|div B|/B is growing! Recommend increasing hdivbbmax_max for better stability' + endif + write(iprint,"(/)") + +end subroutine write_evlog + +end module evwrite diff --git a/src/main/extern_binary_gw.f90 b/src/main/extern_binary_gw.f90 index c41bcd59b..db906d239 100644 --- a/src/main/extern_binary_gw.f90 +++ b/src/main/extern_binary_gw.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_binary ! diff --git a/src/main/extern_densprofile.f90 b/src/main/extern_densprofile.f90 index e16d09be2..407e50fae 100644 --- a/src/main/extern_densprofile.f90 +++ b/src/main/extern_densprofile.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_densprofile ! diff --git a/src/main/extern_gr.f90 b/src/main/extern_gr.f90 new file mode 100644 index 000000000..3d3aacdb2 --- /dev/null +++ b/src/main/extern_gr.f90 @@ -0,0 +1,411 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module extern_gr +! +! Compute terms related to derivatives of the metric which appear +! on the right hand side of the momentum equation +! +! :References: +! Liptai & Price (2019), MNRAS 485, 819 +! Magnall, Price, Lasky & Macpherson (2023), Phys. Rev D. 108, 103534 +! +! :Owner: Spencer Magnall +! +! :Runtime parameters: None +! +! :Dependencies: eos, io, metric_tools, part, physcon, timestep, utils_gr +! + implicit none + + public :: get_grforce, get_grforce_all, update_grforce_leapfrog, get_tmunu_all, get_tmunu_all_exact, get_tmunu + + private + +contains + +!--------------------------------------------------------------- +!+ +! Wrapper subroutine for computing the force due to spacetime curvature +! (This may be useful in the future if there is something that indicates +! whether a particle is gas or test particle.) +!+ +!--------------------------------------------------------------- +subroutine get_grforce(xyzhi,metrici,metricderivsi,veli,densi,ui,pi,fexti,dtf) + use io, only:iprint,fatal,error + real, intent(in) :: xyzhi(4),metrici(:,:,:),metricderivsi(0:3,0:3,3),veli(3),densi,ui,pi + real, intent(out) :: fexti(3) + real, intent(out), optional :: dtf + integer :: ierr + + call forcegr(xyzhi(1:3),metrici,metricderivsi,veli,densi,ui,pi,fexti,ierr) + if (ierr > 0) then + write(iprint,*) 'x,y,z = ',xyzhi(1:3) + call error('get_u0 in extern_gr','1/sqrt(-v_mu v^mu) ---> non-negative: v_mu v^mu') + call fatal('get_grforce','could not compute forcegr at r = ',val=sqrt(dot_product(xyzhi(1:3),xyzhi(1:3))) ) + endif + + if (present(dtf)) call dt_grforce(xyzhi,fexti,dtf) + +end subroutine get_grforce + +!--------------------------------------------------------------- +!+ +! Wrapper of the above, computing accelerations due to metric +! gradients on all particles +!+ +!--------------------------------------------------------------- +subroutine get_grforce_all(npart,xyzh,metrics,metricderivs,vxyzu,dens,fext,dtexternal) + use timestep, only:C_force + use eos, only:ieos,get_pressure + use part, only:isdead_or_accreted + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:), metrics(:,:,:,:), metricderivs(:,:,:,:), dens(:) + real, intent(inout) :: vxyzu(:,:) + real, intent(out) :: fext(:,:), dtexternal + integer :: i + real :: dtf,pi + + dtexternal = huge(dtexternal) + + !$omp parallel do default(none) & + !$omp shared(npart,xyzh,metrics,metricderivs,vxyzu,dens,fext,ieos,C_force) & + !$omp private(i,dtf,pi) & + !$omp reduction(min:dtexternal) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + pi = get_pressure(ieos,xyzh(:,i),dens(i),vxyzu(:,i)) + call get_grforce(xyzh(:,i),metrics(:,:,:,i),metricderivs(:,:,:,i),vxyzu(1:3,i),dens(i),vxyzu(4,i),pi,fext(1:3,i),dtf) + dtexternal = min(dtexternal,C_force*dtf) + endif + enddo + !$omp end parallel do + +end subroutine get_grforce_all + +!--------------------------------------------------------------------------- +!+ +! Subroutine to calculate the timestep constraint from the 'external force' +! this is multiplied by the safety factor C_force elsewhere +!+ +!--------------------------------------------------------------------------- +subroutine dt_grforce(xyzh,fext,dtf) + use physcon, only:pi + use metric_tools, only:imetric,imet_schwarzschild,imet_kerr + real, intent(in) :: xyzh(4),fext(3) + real, intent(out) :: dtf + real :: r,r2,dtf1,dtf2,f2i + integer, parameter :: steps_per_orbit = 100 + + f2i = fext(1)*fext(1) + fext(2)*fext(2) + fext(3)*fext(3) + if (f2i > 0.) then + dtf1 = sqrt(xyzh(4)/sqrt(f2i)) ! This is not really accurate since fi is a component of dp/dt, not da/dt + else + dtf1 = huge(dtf1) + endif + + select case (imetric) + case (imet_schwarzschild,imet_kerr) + r2 = xyzh(1)*xyzh(1) + xyzh(2)*xyzh(2) + xyzh(3)*xyzh(3) + r = sqrt(r2) + dtf2 = (2.*pi*sqrt(r*r2))/steps_per_orbit + case default + dtf2 = huge(dtf2) + end select + + dtf = min(dtf1,dtf2) + +end subroutine dt_grforce + +!---------------------------------------------------------------- +!+ +! Compute the source terms required on the right hand side of +! the relativistic momentum equation. These are of the form: +! T^\mu\nu dg_\mu\nu/dx^i +!+ +!---------------------------------------------------------------- +pure subroutine forcegr(x,metrici,metricderivsi,v,dens,u,p,fterm,ierr) + use metric_tools, only:unpack_metric + use utils_gr, only:get_u0 + real, intent(in) :: x(3),metrici(:,:,:),metricderivsi(0:3,0:3,3),v(3),dens,u,p + real, intent(out) :: fterm(3) + integer, intent(out) :: ierr + real :: gcov(0:3,0:3), gcon(0:3,0:3) + real :: v4(0:3), term(0:3,0:3) + real :: enth, uzero + integer :: i + + call unpack_metric(metrici,gcov=gcov,gcon=gcon) + + enth = 1. + u + p/dens + + ! lower-case 4-velocity + v4(0) = 1. + v4(1:3) = v(:) + + ! first component of the upper-case 4-velocity + call get_u0(gcov,v,uzero,ierr) + + ! energy-momentum tensor times sqrtg on 2rho* + do i=0,3 + term(0:3,i) = 0.5*(enth*uzero*v4(0:3)*v4(i) + P*gcon(0:3,i)/(dens*uzero)) + enddo + + ! source term + fterm = 0. + do i=0,3 + fterm(1) = fterm(1) + dot_product(term(:,i),metricderivsi(:,i,1)) + fterm(2) = fterm(2) + dot_product(term(:,i),metricderivsi(:,i,2)) + fterm(3) = fterm(3) + dot_product(term(:,i),metricderivsi(:,i,3)) + enddo + +end subroutine forcegr + +!-------- I don't think this is actually being used at the moment.... +subroutine update_grforce_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,densi,ui,pi) + use io, only:fatal + real, intent(in) :: dt,xi,yi,zi + real, intent(in) :: vhalfx,vhalfy,vhalfz + real, intent(inout) :: fxi,fyi,fzi + real, intent(inout) :: fexti(3) + real, intent(in) :: densi,ui,pi +! real :: fextv(3) +! real :: v1x, v1y, v1z, v1xold, v1yold, v1zold, vhalf2, erri, dton2 +! logical :: converged +! integer :: its, itsmax +! integer, parameter :: maxitsext = 50 ! maximum number of iterations on external force +! real, parameter :: tolv = 1.e-2 +! real, parameter :: tolv2 = tolv*tolv +! real,dimension(3) :: pos,vel +! real :: dtf +! +! itsmax = maxitsext +! its = 0 +! converged = .false. +! dton2 = 0.5*dt +! +! v1x = vhalfx +! v1y = vhalfy +! v1z = vhalfz +! vhalf2 = vhalfx*vhalfx + vhalfy*vhalfy + vhalfz*vhalfz +! fextv = 0. ! to avoid compiler warning +! +! iterations : do while (its < itsmax .and. .not.converged) +! its = its + 1 +! erri = 0. +! v1xold = v1x +! v1yold = v1y +! v1zold = v1z +! pos = (/xi,yi,zi/) +! vel = (/v1x,v1y,v1z/) +! call get_grforce(pos,vel,densi,ui,pi,fextv,dtf) +! ! xi = pos(1) +! ! yi = pos(2) +! ! zi = pos(3) +! v1x = vel(1) +! v1y = vel(2) +! v1z = vel(3) +! +! v1x = vhalfx + dton2*(fxi + fextv(1)) +! v1y = vhalfy + dton2*(fyi + fextv(2)) +! v1z = vhalfz + dton2*(fzi + fextv(3)) +! +! erri = (v1x - v1xold)**2 + (v1y - v1yold)**2 + (v1z - v1zold)**2 +! erri = erri / vhalf2 +! converged = (erri < tolv2) +! +! enddo iterations +! +! if (its >= maxitsext) call fatal('update_grforce_leapfrog','VELOCITY ITERATIONS ON EXTERNAL FORCE NOT CONVERGED!!') +! +! fexti(1) = fextv(1) +! fexti(2) = fextv(2) +! fexti(3) = fextv(3) +! +! fxi = fxi + fexti(1) +! fyi = fyi + fexti(2) +! fzi = fzi + fexti(3) + +end subroutine update_grforce_leapfrog + +!---------------------------------------------------------------- +!+ +! compute stress energy tensor on all particles +!+ +!---------------------------------------------------------------- +subroutine get_tmunu_all(npart,xyzh,metrics,vxyzu,metricderivs,dens,tmunus) + use eos, only:ieos,get_pressure + use part, only:isdead_or_accreted + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:), metrics(:,:,:,:), metricderivs(:,:,:,:), dens(:) + real, intent(inout) :: vxyzu(:,:),tmunus(:,:,:) + real :: pi + integer :: i + + !$omp parallel do default(none) & + !$omp shared(npart,xyzh,metrics,vxyzu,dens,ieos,tmunus) & + !$omp private(i,pi) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + pi = get_pressure(ieos,xyzh(:,i),dens(i),vxyzu(:,i)) + call get_tmunu(xyzh(:,i),metrics(:,:,:,i),vxyzu(1:3,i),& + dens(i),vxyzu(4,i),pi,tmunus(:,:,i)) + endif + enddo + !$omp end parallel do + +end subroutine get_tmunu_all + +!------------------------------------------------------------------------- +!+ +! calculate the covariant form of the stress energy tensor +! for a particle at position x +!+ +!------------------------------------------------------------------------- +subroutine get_tmunu(x,metrici,v,dens,u,p,tmunu) + use metric_tools, only:unpack_metric + use utils_gr, only:get_u0 + real, intent(in) :: x(3),metrici(:,:,:),v(3),dens,u,p + real, intent(out) :: tmunu(0:3,0:3) + real :: w,v4(0:3),uzero,u_upper(0:3),u_lower(0:3) + real :: gcov(0:3,0:3), gcon(0:3,0:3) + real :: gammaijdown(1:3,1:3),betadown(3),alpha + integer :: ierr,mu,nu + + ! Reference for all the variables used in this routine: + ! w - the enthalpy + ! gcov - the covariant form of the metric tensor + ! gcon - the contravariant form of the metric tensor + ! gammaijdown - the covariant form of the spatial metric + ! alpha - the lapse + ! betadown - the covariant component of the shift + ! v4 - the uppercase 4 velocity in covariant form + ! v - the fluid velocity v^x + ! vcov - the covariant form of big V_i + ! bigV - the uppercase contravariant V^i + + ! Calculate the enthalpy + w = 1 + u + p/dens + + ! Get cov and con versions of the metric + spatial metric and lapse and shift + ! Not entirely convinced that the lapse and shift calculations are acccurate for the general case!! + call unpack_metric(metrici,gcov=gcov,gcon=gcon,gammaijdown=gammaijdown,alpha=alpha,betadown=betadown) + + ! We are going to use the same Tmunu calc as force GR + ! And then lower it using the metric + ! i.e calc T^{\mu\nu} and then lower it using the metric + ! tensor + ! lower-case 4-velocity (contravariant) + v4(0) = 1. + v4(1:3) = v(:) + + ! first component of the upper-case 4-velocity (contravariant) + call get_u0(gcov,v,uzero,ierr) + + u_upper = uzero*v4 + do mu=0,3 + u_lower(mu) = gcov(mu,0)*u_upper(0) + gcov(mu,1)*u_upper(1) & + + gcov(mu,2)*u_upper(2) + gcov(mu,3)*u_upper(3) + enddo + + ! Stress energy tensor in contravariant form + do nu=0,3 + do mu=0,3 + tmunu(mu,nu) = w*dens*u_lower(mu)*u_lower(nu) + p*gcov(mu,nu) + enddo + enddo + +end subroutine get_tmunu + +!------------------------------------------------------------------------- +!+ +! the following two routines are for testing purposes +! and could be deleted at some stage (as used in Magnall et al. 2023) +!+ +!------------------------------------------------------------------------- +subroutine get_tmunu_exact(x,metrici,metricderivsi,v,dens,u,p,tmunu) + use metric_tools, only:unpack_metric + use utils_gr, only:get_sqrtg + real, intent(in) :: x(3),metrici(:,:,:),metricderivsi(0:3,0:3,3),v(3),dens,u,p + real, intent(out) :: tmunu(0:3,0:3) + real :: w,v4(0:3),vcov(3),lorentz + real :: gcov(0:3,0:3), gcon(0:3,0:3) + real :: gammaijdown(1:3,1:3),betadown(3),alpha + real :: velshiftterm + real :: rhostar,rhoprim,negsqrtg + integer :: i,j + + ! Calculate the enthalpy + ! enthalpy should be 1 as we have zero pressure + ! or should have zero pressure + w = 1 + ! Calculate the exact value of density from conserved density + + call unpack_metric(metrici,gcov=gcov,gcon=gcon,gammaijdown=gammaijdown,alpha=alpha,betadown=betadown) + ! We need the covariant version of the 3 velocity + ! gamma_ij v^j = v_i where gamma_ij is the spatial metric + do i=1, 3 + vcov(i) = gammaijdown(i,1)*v(1) + gammaijdown(i,2)*v(2) + gammaijdown(i,3)*v(3) + enddo + + ! Calculate the lorentz factor + lorentz = (1. - (vcov(1)*v(1) + vcov(2)*v(2) + vcov(3)*v(3)))**(-0.5) + + ! Calculate the 4-velocity + velshiftterm = vcov(1)*betadown(1) + vcov(2)*betadown(2) + vcov(3)*betadown(3) + v4(0) = lorentz*(-alpha + velshiftterm) + v4(1:3) = lorentz*v(1:3) + + rhostar = 13.294563008157013D0 + call get_sqrtg(gcov,negsqrtg) + + ! Set/Calculate primitive density using rhostar exactly + rhoprim = rhostar/(negsqrtg/alpha) + + ! Stress energy tensor + do j=0,3 + do i=0,3 + tmunu(i,j) = rhoprim*w*v4(i)*v4(j) ! + p*gcov(i,j) neglect the pressure term as we don't care + enddo + enddo + +end subroutine get_tmunu_exact + +!------------------------------------------------------------------------- +!+ +! see above: for testing purposes and could be deleted at some stage +! (as used in Magnall et al. 2023) +!+ +!------------------------------------------------------------------------- +subroutine get_tmunu_all_exact(npart,xyzh,metrics,vxyzu,metricderivs,dens,tmunus) + use eos, only:ieos,get_pressure + use part, only:isdead_or_accreted + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:), metrics(:,:,:,:), metricderivs(:,:,:,:), dens(:) + real, intent(inout) :: vxyzu(:,:),tmunus(:,:,:) + real :: pi + integer :: i + logical :: firstpart + real :: tmunu(4,4) + + tmunu = 0. + firstpart = .true. + ! TODO write openmp parallel code + do i=1, npart + if (.not.isdead_or_accreted(xyzh(4,i)) .and. firstpart) then + pi = get_pressure(ieos,xyzh(:,i),dens(i),vxyzu(:,i)) + call get_tmunu_exact(xyzh(:,i),metrics(:,:,:,i), metricderivs(:,:,:,i), & + vxyzu(1:3,i),dens(i),vxyzu(4,i),pi,tmunus(:,:,i)) + firstpart = .false. + tmunu(:,:) = tmunus(:,:,i) + else + tmunus(:,:,i) = tmunu(:,:) + endif + enddo + +end subroutine get_tmunu_all_exact + +end module extern_gr diff --git a/src/main/extern_gwinspiral.f90 b/src/main/extern_gwinspiral.f90 index 3d6df7205..460cb5c3b 100644 --- a/src/main/extern_gwinspiral.f90 +++ b/src/main/extern_gwinspiral.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_gwinspiral ! diff --git a/src/main/extern_lensethirring.f90 b/src/main/extern_lensethirring.f90 index d039422cb..cfc6b9b03 100644 --- a/src/main/extern_lensethirring.f90 +++ b/src/main/extern_lensethirring.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_lensethirring ! diff --git a/src/main/extern_spiral.f90 b/src/main/extern_spiral.f90 index b485802f4..ddeb68966 100644 --- a/src/main/extern_spiral.f90 +++ b/src/main/extern_spiral.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_spiral ! diff --git a/src/main/extern_staticsine.f90 b/src/main/extern_staticsine.f90 index bbb12be75..8d71b1c14 100644 --- a/src/main/extern_staticsine.f90 +++ b/src/main/extern_staticsine.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module extern_staticsine ! diff --git a/src/main/externalforces.F90 b/src/main/externalforces.f90 similarity index 99% rename from src/main/externalforces.F90 rename to src/main/externalforces.f90 index ffd8ba7fc..51f3ecd3c 100644 --- a/src/main/externalforces.F90 +++ b/src/main/externalforces.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module externalforces ! @@ -23,14 +23,14 @@ module externalforces ! extern_lensethirring, extern_prdrag, extern_spiral, extern_staticsine, ! infile_utils, io, lumin_nsdisc, part, units ! - use extern_binary, only:accradius1,mass1 + use extern_binary, only:accradius1,mass1,accretedmass1,accretedmass2 use extern_corotate, only:omega_corotate ! so public from this module implicit none private public :: externalforce,externalforce_vdependent public :: accrete_particles,was_accreted - public :: accradius1,omega_corotate + public :: accradius1,omega_corotate,accretedmass1,accretedmass2 public :: write_options_externalforces,read_options_externalforces public :: initialise_externalforces,is_velocity_dependent public :: update_vdependent_extforce_leapfrog diff --git a/src/main/externalforces_gr.F90 b/src/main/externalforces_gr.f90 similarity index 99% rename from src/main/externalforces_gr.F90 rename to src/main/externalforces_gr.f90 index ae3f37a96..562660310 100644 --- a/src/main/externalforces_gr.F90 +++ b/src/main/externalforces_gr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module externalforces ! @@ -39,6 +39,8 @@ module externalforces public :: mass1 ! exported from metric module real, public :: accradius1 = 0. real, public :: accradius1_hard = 0. + real, public :: accretedmass1 = 0. + real, public :: accretedmass2 = 0. logical, public :: extract_iextern_from_hdr = .false. diff --git a/src/main/fastmath.f90 b/src/main/fastmath.f90 index 7b22fc762..59bb2a052 100644 --- a/src/main/fastmath.f90 +++ b/src/main/fastmath.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module fastmath ! diff --git a/src/main/force.F90 b/src/main/force.F90 index a7e063d2a..2caa4f23f 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module forces ! diff --git a/src/main/forcing.F90 b/src/main/forcing.F90 index 070d9b534..878e88f86 100644 --- a/src/main/forcing.F90 +++ b/src/main/forcing.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module forcing ! @@ -963,9 +963,7 @@ subroutine forceit(t,npart,xyzh,vxyzu,fxyzu) real, intent(out) :: fxyzu(:,:) logical :: update_accel = .true. -#ifdef STIR_FROM_FILE - real :: tinfile -#endif +! real :: tinfile logical, parameter :: Debug = .false. !!=================================================================== @@ -977,25 +975,25 @@ subroutine forceit(t,npart,xyzh,vxyzu,fxyzu) if (t > (tprev + st_dtfreq)) then tprev = st_dtfreq*int(t/st_dtfreq) ! round to last full dtfreq update_accel = .true. -#ifdef STIR_FROM_FILE - call read_stirring_data_from_file(forcingfile,t,tinfile) - !if (id==master .and. iverbose >= 2) print*,' got new accel, tinfile = ',tinfile -#endif + if (stir_from_file) then + call read_stirring_data_from_file(forcingfile,t,tinfile) + !if (id==master .and. iverbose >= 2) print*,' got new accel, tinfile = ',tinfile + endif endif if (Debug) print *, 'stir: stirring start' call st_calcAccel(npart,xyzh,fxyzu) -#ifndef STIR_FROM_FILE - if (update_accel) then - if (Debug) print*,'updating accelerations...' - call st_ounoiseupdate(6*st_nmodes, st_OUphases, st_OUvar, st_dtfreq, st_decay) - call st_calcPhases() - !! Store random seed in memory for later checkpoint. - call random_seed (get = st_randseed) + if (.not. stir_from_file) then + if (update_accel) then + if (Debug) print*,'updating accelerations...' + call st_ounoiseupdate(6*st_nmodes, st_OUphases, st_OUvar, st_dtfreq, st_decay) + call st_calcPhases() + !! Store random seed in memory for later checkpoint. + call random_seed (get = st_randseed) + endif endif -#endif if (Debug) print *, 'stir: stirring end' diff --git a/src/main/fs_data.f90 b/src/main/fs_data.f90 index ed04c3664..2e5c0718f 100644 --- a/src/main/fs_data.f90 +++ b/src/main/fs_data.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module fs_data ! diff --git a/src/main/geometry.f90 b/src/main/geometry.f90 index db5d816f3..e0fcf88d2 100644 --- a/src/main/geometry.f90 +++ b/src/main/geometry.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module geometry ! diff --git a/src/main/gitinfo.f90 b/src/main/gitinfo.f90 index f1840f72e..8ea06264e 100644 --- a/src/main/gitinfo.f90 +++ b/src/main/gitinfo.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module gitinfo ! diff --git a/src/main/growth_smol.f90 b/src/main/growth_smol.f90 index d5a4e290b..0a818364f 100644 --- a/src/main/growth_smol.f90 +++ b/src/main/growth_smol.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module growth_smol ! diff --git a/src/main/h2chem.f90 b/src/main/h2chem.f90 index 126e5556f..a79faa951 100644 --- a/src/main/h2chem.f90 +++ b/src/main/h2chem.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module chem ! @@ -261,7 +261,7 @@ subroutine evolve_abundances(ui,rhoi,chemarrays,nchem,dphot,dt) nstep2=1 tstep2=tstep elseif (abco <= 0.d0) then - nstep2=int(rhoi*1000.d0) + nstep2=int(rhoi*1000.d0)+1 tstep2=tstep/nstep2 else ! tsteptest=-abco/(k0*abcp*beta*np1*np1 - gamma_co*abco*np1) diff --git a/src/main/inject_BHL.f90 b/src/main/inject_BHL.f90 index e5cc3c3fe..860dcf058 100644 --- a/src/main/inject_BHL.f90 +++ b/src/main/inject_BHL.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -29,7 +29,8 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'BHL' - public :: init_inject,inject_particles,write_options_inject,read_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject,& + set_default_options_inject ! !--runtime settings for this module ! @@ -100,7 +101,11 @@ subroutine init_inject(ierr) size_y = ceiling(3.*wind_cylinder_radius/psep) size_z = ceiling(3.*wind_cylinder_radius/(sqrt(3.)*psep/2.)) do pass=1,2 - if (pass == 2) allocate(layer_even(2,neven), layer_odd(2,nodd)) + if (pass == 2) then + if (allocated(layer_even)) deallocate(layer_even) + if (allocated(layer_odd)) deallocate(layer_odd) + allocate(layer_even(2,neven), layer_odd(2,nodd)) + endif neven = 0 nodd = 0 do i=1,size_y @@ -253,6 +258,7 @@ subroutine inject_or_update_particles(ifirst, n, position, velocity, h, u, bound call add_or_update_particle(itype,position_u,velocity_u,h(i)/udist,u(i)/(udist**2/utime**2),& ifirst+i-1,npart,npartoftype,xyzh,vxyzu) enddo + end subroutine inject_or_update_particles !----------------------------------------------------------------------- @@ -329,4 +335,9 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) igotall = (ngot >= 8) end subroutine read_options_inject +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + end module inject diff --git a/src/main/inject_bondi.f90 b/src/main/inject_bondi.f90 index 1e7ceca6f..8eb40aec7 100644 --- a/src/main/inject_bondi.f90 +++ b/src/main/inject_bondi.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -30,7 +30,8 @@ module inject public :: init_inject, & inject_particles, & write_options_inject, & - read_options_inject + read_options_inject, & + set_default_options_inject !-- Runtime variables read from input file real, public :: rin = 18.1 @@ -316,4 +317,9 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + end module inject diff --git a/src/main/inject_firehose.f90 b/src/main/inject_firehose.f90 index 043a0774f..92bf578c0 100644 --- a/src/main/inject_firehose.f90 +++ b/src/main/inject_firehose.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -26,7 +26,7 @@ module inject character(len=*), parameter, public :: inject_type = 'firehose' public :: inject_particles, write_options_inject, read_options_inject - public :: init_inject + public :: init_inject, set_default_options_inject real, private :: Mdot = 0. real, private :: Mdotcode = 0. @@ -273,4 +273,9 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + end module inject diff --git a/src/main/inject_galcen_winds.f90 b/src/main/inject_galcen_winds.f90 index 29156a92c..231367852 100644 --- a/src/main/inject_galcen_winds.f90 +++ b/src/main/inject_galcen_winds.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -25,7 +25,8 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'galcen_winds' - public :: init_inject,inject_particles,write_options_inject,read_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject,& + set_default_options_inject real :: outer_boundary = 20. character(len=120) :: datafile = 'winddata.txt' @@ -303,4 +304,9 @@ subroutine read_wind_data(filename,nstars) end subroutine read_wind_data +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + end module inject diff --git a/src/main/inject_keplerianshear.f90 b/src/main/inject_keplerianshear.f90 index d2f44be91..ac93e0858 100644 --- a/src/main/inject_keplerianshear.f90 +++ b/src/main/inject_keplerianshear.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -49,7 +49,8 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'keplerianshear' - public :: init_inject,inject_particles,write_options_inject,read_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject,& + set_default_options_inject public :: set_injection_parameters type injectparams @@ -206,6 +207,7 @@ subroutine write_options_inject(iunit) call write_inopt(injp%HoverR, 'HoverR', 'disc aspect ratio at inner sector radius', iunit) call write_inopt(injp%disc_mass,'disc_mass', 'total disc mass', iunit) call write_inopt(injp%object_mass,'object_mass', 'mass of the central object', iunit) + end subroutine write_options_inject !----------------------------------------------------------------------- @@ -274,6 +276,11 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + subroutine set_injection_parameters(R_in, R_out, Rsect_in,Rsect_out,dr_bound,& phimax,phi_inject,p_index,q_index,HoverR,disc_mass,object_mass) @@ -375,14 +382,11 @@ subroutine determine_particle_status(nqueue, nkill, nboundary, ndomain, nexit) enddo - return end subroutine determine_particle_status - !---- ! Subroutine fills the injection zones with boundary particles !--- - subroutine replenish_injection_zone(ninject,time,dtlast,injected) use eos, only:polyk,gamma use io, only:id,master @@ -501,15 +505,12 @@ subroutine replenish_injection_zone(ninject,time,dtlast,injected) enddo - return end subroutine replenish_injection_zone !---------------------------------- ! Rotates a particle in the z axis !---------------------------------- - subroutine rotate_particle_z(xyz,vxyz,phi) - real, intent(inout) :: phi, xyz(3), vxyz(3) real :: x,y,vx,vy @@ -525,12 +526,11 @@ subroutine rotate_particle_z(xyz,vxyz,phi) vxyz(1) = vx*cos(phi) - vy*sin(phi) vxyz(2) = vx*sin(phi) + vy*cos(phi) - return end subroutine rotate_particle_z !---------------------------------- !+ -! Rotates a single vector in the z axis +! Rotates a single vector in the z axis !+ !----------------------------------- @@ -541,15 +541,13 @@ subroutine rotate_vector_z(oldvec,newvec,phi) newvec(1) = oldvec(1)*cos(phi) - oldvec(2)*sin(phi) newvec(2) = oldvec(1)*sin(phi) + oldvec(2)*cos(phi) - return end subroutine rotate_vector_z -! +!----------------------------------------------------------------------- !+ ! Helper function to calculate polar co-ordinates from x,y !+ -! - +!----------------------------------------------------------------------- subroutine calc_polar_coordinates(r,phi,x,y) real, intent(in) :: x,y @@ -558,17 +556,14 @@ subroutine calc_polar_coordinates(r,phi,x,y) r = sqrt(x*x + y*y) phi = atan2(y,x) - return end subroutine calc_polar_coordinates - !----------------------------------------------------------------------- !+ ! Simple function to calculate the disc's surface density normalisation ! for a disc mass, inner and outer radii and the powerlaw index !+ !----------------------------------------------------------------------- - real function sigma0(Mdisc, Rinner, Router, p_index) real, intent(in) :: Mdisc,Rinner, Router, p_index diff --git a/src/main/inject_rochelobe.f90 b/src/main/inject_rochelobe.f90 index 2c9b015a7..ffe84d4dd 100644 --- a/src/main/inject_rochelobe.f90 +++ b/src/main/inject_rochelobe.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -24,7 +24,8 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'rochelobe' - public :: init_inject,inject_particles,write_options_inject,read_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject,& + set_default_options_inject real, private :: Mdot = 1.0e-9 real, private :: Mdotcode = 0. @@ -337,4 +338,9 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + end module inject diff --git a/src/main/inject_sne.f90 b/src/main/inject_sne.f90 index e74e9bc67..24d3bc2ab 100644 --- a/src/main/inject_sne.f90 +++ b/src/main/inject_sne.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -19,7 +19,8 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'supernovae' - public :: init_inject,inject_particles,write_options_inject,read_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject,& + set_default_options_inject integer, parameter :: maxsn = 30 real, parameter :: xyz_sn(3,maxsn) = & @@ -174,4 +175,9 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) end subroutine read_options_inject +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + end module inject diff --git a/src/main/inject_unifwind.f90 b/src/main/inject_unifwind.f90 index b7c2ace45..d1a456ff6 100644 --- a/src/main/inject_unifwind.f90 +++ b/src/main/inject_unifwind.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inject ! @@ -22,7 +22,8 @@ module inject implicit none character(len=*), parameter, public :: inject_type = 'unifwind' - public :: init_inject,inject_particles,write_options_inject,read_options_inject + public :: init_inject,inject_particles,write_options_inject,read_options_inject,& + set_default_options_inject real, public :: wind_density = 7.2d-16 real, public :: wind_velocity = 29. @@ -180,4 +181,9 @@ subroutine read_options_inject(name,valstring,imatch,igotall,ierr) igotall = (ngot >= 4) end subroutine read_options_inject +subroutine set_default_options_inject(flag) + + integer, optional, intent(in) :: flag +end subroutine set_default_options_inject + end module inject diff --git a/src/main/inject_wind.F90 b/src/main/inject_wind.f90 similarity index 100% rename from src/main/inject_wind.F90 rename to src/main/inject_wind.f90 diff --git a/src/main/inverse4x4.f90 b/src/main/inverse4x4.f90 index 341f965ae..2107fae70 100644 --- a/src/main/inverse4x4.f90 +++ b/src/main/inverse4x4.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module inverse4x4 ! diff --git a/src/main/io.F90 b/src/main/io.F90 index 183166ce4..97e2bb204 100644 --- a/src/main/io.F90 +++ b/src/main/io.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module io ! diff --git a/src/main/ionization.f90 b/src/main/ionization.f90 index 65fc3065a..032bc9ad6 100644 --- a/src/main/ionization.f90 +++ b/src/main/ionization.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module ionization_mod ! diff --git a/src/main/kernel_WendlandC2.f90 b/src/main/kernel_WendlandC2.f90 index 52b0c1e5d..882b2d4a4 100644 --- a/src/main/kernel_WendlandC2.f90 +++ b/src/main/kernel_WendlandC2.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_WendlandC4.f90 b/src/main/kernel_WendlandC4.f90 index b5fe7a638..ea1202d65 100644 --- a/src/main/kernel_WendlandC4.f90 +++ b/src/main/kernel_WendlandC4.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_WendlandC6.f90 b/src/main/kernel_WendlandC6.f90 index edf471d83..b7b690789 100644 --- a/src/main/kernel_WendlandC6.f90 +++ b/src/main/kernel_WendlandC6.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_cubic.f90 b/src/main/kernel_cubic.f90 index 8a851253d..bf16cead5 100644 --- a/src/main/kernel_cubic.f90 +++ b/src/main/kernel_cubic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_quartic.f90 b/src/main/kernel_quartic.f90 index 7fdb09ddc..a698e32b6 100644 --- a/src/main/kernel_quartic.f90 +++ b/src/main/kernel_quartic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/kernel_quintic.f90 b/src/main/kernel_quintic.f90 index 79e8fd149..64482f474 100644 --- a/src/main/kernel_quintic.f90 +++ b/src/main/kernel_quintic.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module kernel ! diff --git a/src/main/krome.f90 b/src/main/krome.f90 index d0f632675..4ece40748 100644 --- a/src/main/krome.f90 +++ b/src/main/krome.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module krome_interface ! diff --git a/src/main/linklist_kdtree.F90 b/src/main/linklist_kdtree.F90 index 553365dcc..4913f0925 100644 --- a/src/main/linklist_kdtree.F90 +++ b/src/main/linklist_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module linklist ! @@ -25,8 +25,6 @@ module linklist use part, only:ll use dtypekdtree, only:kdnode implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" integer, allocatable :: cellatid(:) integer, public, allocatable :: ifirstincell(:) diff --git a/src/main/lumin_nsdisc.f90 b/src/main/lumin_nsdisc.f90 index 0c5936a03..90db88923 100644 --- a/src/main/lumin_nsdisc.f90 +++ b/src/main/lumin_nsdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module lumin_nsdisc ! @@ -17,7 +17,7 @@ module lumin_nsdisc ! ! :Runtime parameters: None ! -! :Dependencies: eos, fastmath, infile_utils, io, physcon, units +! :Dependencies: eos, infile_utils, io, physcon, units ! use physcon, only: pi @@ -120,17 +120,11 @@ end subroutine make_grid_points subroutine get_grid_bins( r, zt, rbin, ztbin, phi, phibin ) use physcon, only:pi, twopi use io, only : fatal -#ifdef FINVSQRT - use fastmath, only:finvsqrt -#endif real, intent(in) :: r, phi, zt integer, intent(out) :: rbin, ztbin, phibin real :: B, C, ztnew -#ifdef FINVSQRT - rbin = int( nr*finvsqrt( (rmax-rmin)/((r-rmin)))) !optimized for speed not readability -#else + rbin = int( nr*sqrt( (r-rmin)/(rmax-rmin))) -#endif B = 2.*(thetamin-thetamax)/(nth) C = 2.*(zmin-zmax)/nz diff --git a/src/main/memory.f90 b/src/main/memory.f90 index ccd3f4fb0..b20dae9f4 100644 --- a/src/main/memory.f90 +++ b/src/main/memory.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module memory ! @@ -15,7 +15,7 @@ module memory ! :Runtime parameters: None ! ! :Dependencies: allocutils, dim, io, linklist, mpibalance, mpiderivs, -! mpimemory, mpitree, part, photoevap +! mpimemory, mpitree, part ! implicit none @@ -34,9 +34,6 @@ subroutine allocate_memory(ntot, part_only) use mpibalance, only:allocate_balance_arrays use mpiderivs, only:allocate_cell_comms_arrays use mpitree, only:allocate_tree_comms_arrays -#ifdef PHOTO - use photoevap, only:allocate_photoevap -#endif integer(kind=8), intent(in) :: ntot logical, optional, intent(in) :: part_only @@ -86,9 +83,6 @@ subroutine allocate_memory(ntot, part_only) call allocate_part if (.not. part_only_) then call allocate_linklist -#ifdef PHOTO - call allocate_photoevap -#endif if (mpi) then call allocate_mpi_memory(npart=n) call allocate_balance_arrays @@ -113,9 +107,6 @@ subroutine deallocate_memory(part_only) use dim, only:update_max_sizes,mpi use part, only:deallocate_part use linklist, only:deallocate_linklist -#ifdef PHOTO - use photoevap, only:deallocate_photoevap -#endif use mpimemory, only:deallocate_mpi_memory use mpibalance, only:deallocate_balance_arrays use mpiderivs, only:deallocate_cell_comms_arrays @@ -134,9 +125,6 @@ subroutine deallocate_memory(part_only) call deallocate_part if (.not. part_only_) then call deallocate_linklist -#ifdef PHOTO - call deallocate_photoevap -#endif endif if (mpi) then diff --git a/src/main/metric_kerr-schild.f90 b/src/main/metric_kerr-schild.f90 index 240ba7034..59ada6922 100644 --- a/src/main/metric_kerr-schild.f90 +++ b/src/main/metric_kerr-schild.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_kerr.f90 b/src/main/metric_kerr.f90 index de31643b5..b270e4111 100644 --- a/src/main/metric_kerr.f90 +++ b/src/main/metric_kerr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_minkowski.f90 b/src/main/metric_minkowski.f90 index 1d4e62579..3562abad8 100644 --- a/src/main/metric_minkowski.f90 +++ b/src/main/metric_minkowski.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_schwarzschild.f90 b/src/main/metric_schwarzschild.f90 index 8f496edec..6add9d242 100644 --- a/src/main/metric_schwarzschild.f90 +++ b/src/main/metric_schwarzschild.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module metric ! diff --git a/src/main/metric_tools.F90 b/src/main/metric_tools.F90 index 2cf9f92c0..8fd54fdf0 100644 --- a/src/main/metric_tools.F90 +++ b/src/main/metric_tools.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module metric_tools ! diff --git a/src/main/mf_write.f90 b/src/main/mf_write.f90 index 84745ed05..486ec1bf7 100644 --- a/src/main/mf_write.f90 +++ b/src/main/mf_write.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mf_write ! diff --git a/src/main/mol_data.f90 b/src/main/mol_data.f90 index 1dc804833..fe91bae89 100644 --- a/src/main/mol_data.f90 +++ b/src/main/mol_data.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mol_data ! diff --git a/src/main/mpi_balance.F90 b/src/main/mpi_balance.F90 index 6fcf162f7..1679dda42 100644 --- a/src/main/mpi_balance.F90 +++ b/src/main/mpi_balance.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpibalance ! @@ -44,19 +44,33 @@ module mpibalance contains -subroutine allocate_balance_arrays +!---------------------------------------------------------------- +!+ +! allocate memory +!+ +!---------------------------------------------------------------- +subroutine allocate_balance_arrays() use allocutils, only:allocate_array + call allocate_array('nsent', nsent, nprocs) call allocate_array('nexpect', nexpect, nprocs) call allocate_array('nrecv', nrecv, nprocs) call allocate_array('countrequest',countrequest,nprocs) + end subroutine allocate_balance_arrays -subroutine deallocate_balance_arrays +!---------------------------------------------------------------- +!+ +! deallocate memory +!+ +!---------------------------------------------------------------- +subroutine deallocate_balance_arrays() + if (allocated(nsent )) deallocate(nsent ) if (allocated(nexpect )) deallocate(nexpect ) if (allocated(nrecv )) deallocate(nrecv ) if (allocated(countrequest)) deallocate(countrequest) + end subroutine deallocate_balance_arrays !---------------------------------------------------------------- @@ -164,14 +178,18 @@ end subroutine balancedomains !+ !---------------------------------------------------------------- subroutine balance_init(npart) + use part, only:fill_sendbuf integer, intent(in) :: npart - integer :: i + integer :: i,nbuf + + ! use a dummy call to fill_sendbuf to find out the buffer size + call fill_sendbuf(1,xbuffer,nbuf) ! just fill for particle #1 !--use persistent communication type for receives ! cannot do same for sends as there are different destination, ! unless we make a request for each processor ! - call MPI_RECV_INIT(xbuffer,size(xbuffer),MPI_DEFAULT_REAL,MPI_ANY_SOURCE, & + call MPI_RECV_INIT(xbuffer,nbuf,MPI_DEFAULT_REAL,MPI_ANY_SOURCE, & MPI_ANY_TAG,comm_balance,irequestrecv(1),mpierr) ! !--post a non-blocking receive so that we can receive particles @@ -198,7 +216,6 @@ subroutine balance_init(npart) ! ncomplete = 0 - return end subroutine balance_init !----------------------------------------------------------------------- @@ -276,6 +293,7 @@ subroutine send_part(i,newproc,replace) integer, intent(in) :: i,newproc logical, intent(in), optional :: replace logical :: idone,doreplace + integer :: nbuf if (present(replace)) then doreplace = replace @@ -287,9 +305,9 @@ subroutine send_part(i,newproc,replace) if (newproc < 0 .or. newproc > nprocs-1) then call fatal('balance','error in ibelong',ival=newproc,var='ibelong') else - call fill_sendbuf(i,xsendbuf) + call fill_sendbuf(i,xsendbuf,nbuf) ! tag cannot be i, because some MPI implementations do not support large values for the tag - call MPI_ISEND(xsendbuf,size(xsendbuf),MPI_DEFAULT_REAL,newproc,0,comm_balance,irequestsend(1),mpierr) + call MPI_ISEND(xsendbuf,nbuf,MPI_DEFAULT_REAL,newproc,0,comm_balance,irequestsend(1),mpierr) !--wait for send to complete, receive whilst doing so idone = .false. @@ -302,7 +320,7 @@ subroutine send_part(i,newproc,replace) call kill_particle(i) nsent(newproc+1) = nsent(newproc+1) + 1 - return + end subroutine send_part !---------------------------------------------------------------- diff --git a/src/main/mpi_dens.F90 b/src/main/mpi_dens.F90 index f6f1480f9..d578658e3 100644 --- a/src/main/mpi_dens.F90 +++ b/src/main/mpi_dens.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpidens ! diff --git a/src/main/mpi_derivs.F90 b/src/main/mpi_derivs.F90 index a8deacbd0..a9b2b2641 100644 --- a/src/main/mpi_derivs.F90 +++ b/src/main/mpi_derivs.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpiderivs ! diff --git a/src/main/mpi_domain.F90 b/src/main/mpi_domain.F90 index b8ff8cb95..b58c49fed 100644 --- a/src/main/mpi_domain.F90 +++ b/src/main/mpi_domain.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpidomain ! @@ -22,8 +22,6 @@ module mpidomain use io, only:nprocs use part, only:ibelong implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" integer, parameter :: ndim = 3 diff --git a/src/main/mpi_force.F90 b/src/main/mpi_force.F90 index faeb48e36..3dab68ded 100644 --- a/src/main/mpi_force.F90 +++ b/src/main/mpi_force.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpiforce ! diff --git a/src/main/mpi_memory.F90 b/src/main/mpi_memory.F90 index bb61caeb9..5d635f2d4 100644 --- a/src/main/mpi_memory.F90 +++ b/src/main/mpi_memory.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpimemory ! diff --git a/src/main/mpi_memory.f90 b/src/main/mpi_memory.f90 new file mode 100644 index 000000000..5d635f2d4 --- /dev/null +++ b/src/main/mpi_memory.f90 @@ -0,0 +1,317 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module mpimemory +! +! None +! +! :References: None +! +! :Owner: Conrad Chan +! +! :Runtime parameters: None +! +! :Dependencies: dim, io, mpidens, mpiforce +! + use io, only:fatal,iprint + use mpidens, only:celldens,stackdens + use mpiforce, only:cellforce,stackforce + + implicit none + + interface allocate_stack + module procedure allocate_stack_dens,allocate_stack_force + end interface allocate_stack + + interface swap_stacks ! force doesn't require a stack swap + module procedure swap_stacks_dens + end interface swap_stacks + + interface push_onto_stack + module procedure push_onto_stack_dens,push_onto_stack_force + end interface push_onto_stack + + interface get_cell + module procedure get_cell_dens,get_cell_force + end interface get_cell + + interface write_cell + module procedure write_cell_dens,write_cell_force + end interface write_cell + + interface reserve_stack + module procedure reserve_stack_dens,reserve_stack_force + end interface reserve_stack + + public :: allocate_mpi_memory + public :: deallocate_mpi_memory + public :: allocate_stack + public :: swap_stacks + public :: push_onto_stack + public :: get_cell + public :: write_cell + public :: reserve_stack + public :: reset_stacks + public :: increase_mpi_memory + + ! stacks to be referenced from density and force routines + type(stackdens), public :: dens_stack_1 + type(stackdens), public :: dens_stack_2 + type(stackdens), public :: dens_stack_3 + type(stackforce), public :: force_stack_1 + type(stackforce), public :: force_stack_2 + + integer, public :: stacksize + + private + + ! primary chunk of memory requested using alloc + type(celldens), allocatable, target :: dens_cells(:,:) + type(cellforce), allocatable, target :: force_cells(:,:) + +contains + +subroutine allocate_mpi_memory(npart, stacksize_in) + integer, optional, intent(in) :: npart + integer, optional, intent(in) :: stacksize_in + integer :: allocstat + + allocstat = 0 + + if (present(stacksize_in)) stacksize = stacksize_in + if (present(npart)) call calculate_stacksize(npart) + + if (allocated(dens_cells)) then + if (stacksize /= size(dens_cells,1)) then + call fatal('stack', 'dens_cells already allocated with a different size') + endif + endif + + if (allocated(force_cells)) then + if (stacksize /= size(force_cells,1)) then + call fatal('stack', 'force_cells already allocated with a different size') + endif + endif + + if (.not. allocated(dens_cells)) allocate(dens_cells(stacksize,3), stat=allocstat) + if (allocstat /= 0) call fatal('stack','fortran memory allocation error') + call allocate_stack(dens_stack_1, 1) + call allocate_stack(dens_stack_2, 2) + call allocate_stack(dens_stack_3, 3) + + if (.not. allocated(force_cells)) allocate(force_cells(stacksize,2), stat=allocstat) + if (allocstat /= 0) call fatal('stack','fortran memory allocation error') + call allocate_stack(force_stack_1, 1) + call allocate_stack(force_stack_2, 2) + +end subroutine allocate_mpi_memory + +subroutine increase_mpi_memory + use io, only:id + real, parameter :: factor = 1.5 + integer :: stacksize_new + integer :: allocstat + + ! temporary memory for increasing stack sizes + type(celldens), allocatable, target :: dens_cells_tmp(:,:) + type(cellforce), allocatable, target :: force_cells_tmp(:,:) + + stacksize_new = int(real(stacksize) * factor) + write(iprint, *) 'MPI dens stack exceeded on', id, 'increasing size to', stacksize_new + + ! Expand density + call move_alloc(dens_cells, dens_cells_tmp) + allocate(dens_cells(stacksize_new,3), stat=allocstat) + if (allocstat /= 0) call fatal('stack', 'error increasing dens stack size') + dens_cells(1:stacksize,:) = dens_cells_tmp(:,:) + deallocate(dens_cells_tmp) + + ! Expand force + call move_alloc(force_cells, force_cells_tmp) + allocate(force_cells(stacksize_new,2), stat=allocstat) + if (allocstat /= 0) call fatal('stack', 'error increasing force stack size') + force_cells(1:stacksize,:) = force_cells_tmp(:,:) + deallocate(force_cells_tmp) + + stacksize = stacksize_new + call allocate_stack(force_stack_1, 1) + call allocate_stack(force_stack_2, 2) + call allocate_stack(dens_stack_1, dens_stack_1%number) + call allocate_stack(dens_stack_2, dens_stack_2%number) + call allocate_stack(dens_stack_3, dens_stack_3%number) +end subroutine increase_mpi_memory + +subroutine calculate_stacksize(npart) + use dim, only:mpi,minpart + use io, only:nprocs,id,master + integer, intent(in) :: npart + integer, parameter :: safety = 8 + + ! size of the stack needed for communication, + ! should be at least the maximum number of cells that need + ! to be exported to other tasks. + ! + ! if it is not large enough, it will be automatically expanded + + ! number of particles per cell, divided by number of tasks + if (mpi .and. nprocs > 1) then + ! assume that every cell will be exported, with some safety factor + stacksize = (npart / minpart / nprocs) * safety + + if (id == master) then + write(iprint, *) 'MPI memory stack size = ', stacksize + write(iprint, *) ' (total number of cells that can be exported by a single task)' + endif + else + stacksize = 0 + endif + +end subroutine calculate_stacksize + +subroutine deallocate_mpi_memory + if (allocated(dens_cells )) deallocate(dens_cells ) + if (allocated(force_cells)) deallocate(force_cells) +end subroutine deallocate_mpi_memory + +subroutine allocate_stack_dens(stack, i) + type(stackdens), intent(inout) :: stack + integer, intent(in) :: i + + stack%number = i + stack%cells => dens_cells(1:stacksize,stack%number) + stack%maxlength = stacksize + +end subroutine allocate_stack_dens + +subroutine allocate_stack_force(stack, i) + type(stackforce), intent(inout) :: stack + integer, intent(in) :: i + + stack%number = i + stack%cells => force_cells(1:stacksize,stack%number) + stack%maxlength = stacksize + +end subroutine allocate_stack_force + +subroutine swap_stacks_dens(stack_a, stack_b) + type(stackdens), intent(inout) :: stack_a + type(stackdens), intent(inout) :: stack_b + + integer :: temp_n + integer :: temp_number + + if (stack_a%maxlength /= stack_b%maxlength) call fatal('stack', 'stack swap of unequal size') + + ! counters + temp_n = stack_a%n + stack_a%n = stack_b%n + stack_b%n = temp_n + + ! addresses + temp_number = stack_a%number + stack_a%number = stack_b%number + stack_b%number = temp_number + + ! change pointers + stack_a%cells => dens_cells(1:stacksize,stack_a%number) + stack_b%cells => dens_cells(1:stacksize,stack_b%number) + +end subroutine swap_stacks_dens + +subroutine push_onto_stack_dens(stack,cell) + type(stackdens), intent(inout) :: stack + type(celldens), intent(in) :: cell + + integer :: i + + call reserve_stack(stack,i) + + ! no other thread will write to the same position, so it is threadsafe to write without a critical section + stack%cells(i) = cell +end subroutine push_onto_stack_dens + +subroutine push_onto_stack_force(stack,cell) + type(stackforce), intent(inout) :: stack + type(cellforce), intent(in) :: cell + + integer :: i + + call reserve_stack(stack,i) + + ! no other thread will write to the same position, so it is threadsafe to write without a critical section + stack%cells(i) = cell +end subroutine push_onto_stack_force + +type(celldens) function get_cell_dens(stack,i) + type(stackdens), intent(in) :: stack + integer, intent(in) :: i + + if (stack%n < i) call fatal('dens','attempting to read invalid stack address') + get_cell_dens = stack%cells(i) +end function get_cell_dens + +type(cellforce) function get_cell_force(stack,i) + type(stackforce), intent(in) :: stack + integer, intent(in) :: i + + if (stack%n < i) call fatal('force','attempting to read invalid stack address') + get_cell_force = stack%cells(i) +end function get_cell_force + +subroutine write_cell_dens(stack,cell) + type(stackdens), intent(inout) :: stack + type(celldens), intent(inout) :: cell + + if (cell%waiting_index > stack%maxlength) call fatal('dens','attempting to write to invalid stack address') + stack%cells(cell%waiting_index) = cell + +end subroutine write_cell_dens + +subroutine write_cell_force(stack,cell) + type(stackforce), intent(inout) :: stack + type(cellforce), intent(inout) :: cell + + if (cell%waiting_index > stack%maxlength) call fatal('force','attempting to write to invalid stack address') + stack%cells(cell%waiting_index) = cell + +end subroutine write_cell_force + +subroutine reserve_stack_dens(stack,i) + type(stackdens), intent(inout) :: stack + integer, intent(out) :: i + + !$omp atomic capture + stack%n = stack%n + 1 + i = stack%n + !$omp end atomic + + if (i > stack%maxlength) call fatal('dens','MPI stack exceeded') + +end subroutine reserve_stack_dens + +subroutine reserve_stack_force(stack,i) + type(stackforce), intent(inout) :: stack + integer, intent(out) :: i + + !$omp atomic capture + stack%n = stack%n + 1 + i = stack%n + !$omp end atomic + + if (i > stack%maxlength) call fatal('force','MPI stack exceeded') + +end subroutine reserve_stack_force + +subroutine reset_stacks + dens_stack_1%n=0 + dens_stack_2%n=0 + dens_stack_3%n=0 + + force_stack_1%n=0 + force_stack_2%n=0 +end subroutine reset_stacks + +end module mpimemory diff --git a/src/main/mpi_tree.F90 b/src/main/mpi_tree.F90 index 77f496c19..fe49e3c22 100644 --- a/src/main/mpi_tree.F90 +++ b/src/main/mpi_tree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpitree ! diff --git a/src/main/mpi_utils.F90 b/src/main/mpi_utils.F90 index 5dea33e2b..e725bc020 100644 --- a/src/main/mpi_utils.F90 +++ b/src/main/mpi_utils.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module mpiutils ! diff --git a/src/main/nicil_supplement.F90 b/src/main/nicil_supplement.F90 index 0f53c0ded..33533c07b 100644 --- a/src/main/nicil_supplement.F90 +++ b/src/main/nicil_supplement.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module nicil_sup ! diff --git a/src/main/nicil_supplement.f90 b/src/main/nicil_supplement.f90 new file mode 100644 index 000000000..c0d5fbfd3 --- /dev/null +++ b/src/main/nicil_supplement.f90 @@ -0,0 +1,236 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module nicil_sup +! +! Contains wrapper routines so that NICIL can be used in Phantom +! +! :References: Wurster (2016) +! Wurster (2021) +! +! :Owner: Daniel Price +! +! :Runtime parameters: +! - C_AD : *constant coefficient for ambipolar diffusion* +! - C_HE : *constant coefficient for the Hall effect (incl. sign)* +! - C_OR : *constant coefficient for ohmic resistivity* +! - Cdt_diff : *coefficient to control the Ohmic & ambipolar timesteps* +! - Cdt_hall : *coefficient to control the Hall timestep* +! - a0_grain : *grain radius (cm)* +! - alpha_AD : *power law exponent for ambipolar diffusion* +! - an_grain : *minimum grain radius (cm)* +! - ax_grain : *maximum grain radius (cm)* +! - eta_const_type : *Coefficient type: (1) phys.cnst+B+rho (2) C_NI+B+rho (3) constant* +! - eta_constant : *Use constant coefficients for all non-ideal MHD terms* +! - fdg : *dust-to-gas mass ratio* +! - gamma_AD : *ion-neutral coupling coefficient for ambipolar diffusion* +! - hall_lt_zero : *sign of the hall coefficient (<0 if T)* +! - n_e_cnst : *constant electron number density* +! - rho_bulk : *bulk grain density (g/cm^3)* +! - rho_i_cnst : *ionisation density for ambipolar diffusion* +! - rho_n_cnst : *neutral density for ambipolar diffusion* +! - use_ambi : *Calculate the coefficient for ambipolar diffusion* +! - use_hall : *Calculate the coefficient for the Hall effect* +! - use_ohm : *Calculate the coefficient for Ohmic resistivity* +! - zeta : *cosmic ray ionisation rate (s^-1)* +! +! :Dependencies: infile_utils, nicil, physcon +! + use nicil, only: use_ohm,use_hall,use_ambi,na, & + fdg,rho_bulk,a0_grain,an_grain,ax_grain,zeta_cgs,Cdt_diff,Cdt_hall, & + eta_constant,eta_const_type,icnstphys,icnstsemi,icnst,C_OR,C_HE,C_AD, & + n_e_cnst,hall_lt_zero,rho_i_cnst,rho_n_cnst,alpha_AD,gamma_AD + implicit none + ! + !--Subroutines + public :: use_consistent_gmw,write_options_nicil,read_options_nicil + + private + +contains + +!----------------------------------------------------------------------- +!+ +! Ensures a consistent meanmolecular mass is used +!+ +!----------------------------------------------------------------------- +subroutine use_consistent_gmw(ierr,gmw_eos,gmw_nicil) + use nicil, only:meanmolmass + integer, intent(out) :: ierr + real, intent(out) :: gmw_nicil + real, intent(inout) :: gmw_eos + + gmw_nicil = meanmolmass + if (abs(meanmolmass-gmw_eos) > epsilon(gmw_eos)) then + ierr = 1 + gmw_eos = meanmolmass + endif + +end subroutine use_consistent_gmw +!----------------------------------------------------------------------- +!+ +! writes input options to the input file +!+ +!----------------------------------------------------------------------- +subroutine write_options_nicil(iunit) + use infile_utils, only:write_inopt + integer, intent(in) :: iunit + + write(iunit,"(/,a)") '# options controlling non-ideal MHD' + call write_inopt(use_ohm , 'use_ohm' ,'Calculate the coefficient for Ohmic resistivity',iunit) + call write_inopt(use_hall, 'use_hall' ,'Calculate the coefficient for the Hall effect',iunit) + call write_inopt(use_ambi, 'use_ambi' ,'Calculate the coefficient for ambipolar diffusion',iunit) + call write_inopt(eta_constant,'eta_constant','Use constant coefficients for all non-ideal MHD terms',iunit) + if ( eta_constant ) then + call write_inopt(eta_const_type,'eta_const_type','Coefficient type: (1) phys.cnst+B+rho (2) C_NI+B+rho (3) constant',iunit) + if ( eta_const_type==1 ) then + if ( use_ohm .or. use_hall ) then + call write_inopt(n_e_cnst,'n_e_cnst' ,'constant electron number density',iunit) + if ( use_hall ) call write_inopt(hall_lt_zero, 'hall_lt_zero' ,'sign of the hall coefficient (<0 if T)',iunit) + endif + if ( use_ambi ) then + call write_inopt(gamma_AD, 'gamma_AD', 'ion-neutral coupling coefficient for ambipolar diffusion',iunit) + call write_inopt(rho_i_cnst, 'rho_i_cnst','ionisation density for ambipolar diffusion',iunit) + call write_inopt(rho_n_cnst, 'rho_n_cnst','neutral density for ambipolar diffusion',iunit) + call write_inopt(alpha_AD, 'alpha_AD', 'power law exponent for ambipolar diffusion',iunit) + endif + elseif ( eta_const_type==2 ) then + if ( use_ohm ) call write_inopt(C_OR,'C_OR', 'semi-constant coefficient for ohmic resistivity',iunit) + if ( use_hall ) call write_inopt(C_HE,'C_HE', 'semi-constant coefficient for the Hall effect (incl. sign)',iunit) + if ( use_ambi ) call write_inopt(C_AD,'C_AD', 'semi-constant coefficient for ambipolar diffusion',iunit) + elseif ( eta_const_type==3 ) then + if ( use_ohm ) call write_inopt(C_OR,'C_OR', 'constant coefficient for ohmic resistivity',iunit) + if ( use_hall ) call write_inopt(C_HE,'C_HE', 'constant coefficient for the Hall effect (incl. sign)',iunit) + if ( use_ambi ) call write_inopt(C_AD,'C_AD', 'constant coefficient for ambipolar diffusion',iunit) + endif + endif + call write_inopt(Cdt_diff, 'Cdt_diff', 'coefficient to control the Ohmic & ambipolar timesteps',iunit) + call write_inopt(Cdt_hall, 'Cdt_hall', 'coefficient to control the Hall timestep',iunit) + if ( .not. eta_constant ) then + write(iunit,"(/,a)") '# options controlling ionisation' + call write_inopt(fdg, 'fdg', 'dust-to-gas mass ratio',iunit) + call write_inopt(rho_bulk, 'rho_bulk', 'bulk grain density (g/cm^3)',iunit) + if ( na==1 ) then + call write_inopt(a0_grain, 'a0_grain', 'grain radius (cm)',iunit) + else + call write_inopt(an_grain, 'an_grain', 'minimum grain radius (cm)',iunit) + call write_inopt(ax_grain, 'ax_grain', 'maximum grain radius (cm)',iunit) + endif + call write_inopt(zeta_cgs, 'zeta', 'cosmic ray ionisation rate (s^-1)',iunit) + endif + +end subroutine write_options_nicil +!----------------------------------------------------------------------- +!+ +! reads input options from the input file +!+ +!----------------------------------------------------------------------- +subroutine read_options_nicil(name,valstring,imatch,igotall,ierr) + use physcon, only:fourpi + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotall + integer, intent(out) :: ierr + integer :: ngotmax + integer, save :: ngot = 0 + + !--Initialise parameters + imatch = .true. + igotall = .false. + !--Number of input parameters + ngotmax = 6 + + !--Read input parameters + select case(trim(name)) + case('use_ohm') + read(valstring,*,iostat=ierr) use_ohm + ngot = ngot + 1 + case('use_hall') + read(valstring,*,iostat=ierr) use_hall + ngot = ngot + 1 + case('use_ambi') + read(valstring,*,iostat=ierr) use_ambi + ngot = ngot + 1 + case('eta_constant') + read(valstring,*,iostat=ierr) eta_constant + ngot = ngot + 1 + if (eta_constant) then + ngotmax = ngotmax + 1 + else + ngotmax = ngotmax + 4 + if (na==1) ngotmax = ngotmax + 1 + endif + case('eta_const_type') + read(valstring,*,iostat=ierr) eta_const_type + ngot = ngot + 1 + if (eta_const_type==1) then + if (use_ohm ) ngotmax = ngotmax + 1 + if (use_hall) ngotmax = ngotmax + 2 + if (use_ambi) ngotmax = ngotmax + 4 + elseif (eta_const_type==2 .or. eta_const_type==3) then + if (use_ohm ) ngotmax = ngotmax + 1 + if (use_hall) ngotmax = ngotmax + 1 + if (use_ambi) ngotmax = ngotmax + 1 + endif + case('C_OR') + read(valstring,*,iostat=ierr) C_OR + ngot = ngot + 1 + case('C_HE') + read(valstring,*,iostat=ierr) C_HE + ngot = ngot + 1 + case('C_AD') + read(valstring,*,iostat=ierr) C_AD + ngot = ngot + 1 + case('n_e_cnst') + read(valstring,*,iostat=ierr) n_e_cnst + ngot = ngot + 1 + case('hall_lt_zero') + read(valstring,*,iostat=ierr) hall_lt_zero + ngot = ngot + 1 + case('gamma_AD') + read(valstring,*,iostat=ierr) gamma_AD + ngot = ngot + 1 + case('rho_i_cnst') + read(valstring,*,iostat=ierr) rho_i_cnst + ngot = ngot + 1 + case('rho_n_cnst') + read(valstring,*,iostat=ierr) rho_n_cnst + ngot = ngot + 1 + case('alpha_AD') + read(valstring,*,iostat=ierr) alpha_AD + ngot = ngot + 1 + case('fdg') + read(valstring,*,iostat=ierr) fdg + ngot = ngot + 1 + case('rho_bulk') + read(valstring,*,iostat=ierr) rho_bulk + ngot = ngot + 1 + case('a0_grain') + read(valstring,*,iostat=ierr) a0_grain + ngot = ngot + 1 + case('an_grain') + read(valstring,*,iostat=ierr) an_grain + ngot = ngot + 1 + case('ax_grain') + read(valstring,*,iostat=ierr) ax_grain + ngot = ngot + 1 + case('zeta') + read(valstring,*,iostat=ierr) zeta_cgs + ngot = ngot + 1 + case('Cdt_diff') + read(valstring,*,iostat=ierr) Cdt_diff + ngot = ngot + 1 + case('Cdt_hall') + read(valstring,*,iostat=ierr) Cdt_hall + ngot = ngot + 1 + case default + imatch = .false. + end select + if ( ngot >= ngotmax ) igotall = .true. + +end subroutine read_options_nicil + +!----------------------------------------------------------------------- +end module nicil_sup diff --git a/src/main/options.f90 b/src/main/options.f90 index 403d48be5..36bc7e5eb 100644 --- a/src/main/options.f90 +++ b/src/main/options.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module options ! @@ -167,7 +167,6 @@ subroutine set_default_options endif implicit_radiation_store_drad = .false. - ! variable composition use_var_comp = .false. diff --git a/src/main/part.F90 b/src/main/part.F90 index 383d7f89b..652935668 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module part ! @@ -39,8 +39,6 @@ module part use krome_user, only: krome_nmols #endif implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" ! !--basic storage needed for read/write of particle data ! @@ -57,6 +55,7 @@ module part character(len=*), parameter :: vxyzu_label(4) = (/'vx','vy','vz','u '/) character(len=*), parameter :: Bxyz_label(3) = (/'Bx','By','Bz'/) character(len=*), parameter :: Bevol_label(4) = (/'Bx/rho','By/rho','Bz/rho','psi '/) + character(len=*), parameter :: alphaind_label(3) = (/'alpha ','alphaloc','div_a '/) ! !--tracking particle IDs @@ -139,6 +138,13 @@ module part 'ne/nH: fraction of electrons ',& 'nCO/nH: fraction of Carbon Monoxide '/) +! +!--make a public krome_nmols variable to avoid ifdefs elsewhere +! +#ifndef KROME + integer, parameter :: krome_nmols = 0 +#endif + ! !--eos_variables ! @@ -223,9 +229,7 @@ module part integer, parameter :: ihall = 2 ! eta_hall integer, parameter :: iambi = 3 ! eta_ambi integer, parameter :: iion = 4 ! ionisation fraction -#ifdef NONIDEALMHD character(len=*), parameter :: eta_nimhd_label(4) = (/'eta_{OR}','eta_{HE}','eta_{AD}','ne/n '/) -#endif ! !-- Ray tracing : optical depth ! @@ -340,6 +344,7 @@ module part ! integer, parameter, private :: usedivcurlv = min(ndivcurlv,1) integer, parameter :: ipartbufsize = 129 + real :: hfact,Bextx,Bexty,Bextz integer :: npart integer(kind=8) :: ntot @@ -386,6 +391,7 @@ module part private :: hrho4,hrho8,hrho4_pmass,hrho8_pmass,hrhomixed_pmass private :: get_ntypes_i4,get_ntypes_i8 + contains subroutine allocate_part @@ -464,7 +470,6 @@ subroutine allocate_part call allocate_array('nucleation', nucleation, n_nucleation, maxp_nucleation*inucleation) call allocate_array('tau', tau, maxp*itau_alloc) call allocate_array('tau_lucy', tau_lucy, maxp*itauL_alloc) - if (use_krome) then call allocate_array('abundance', abundance, krome_nmols, maxp_krome) else @@ -472,6 +477,7 @@ subroutine allocate_part endif call allocate_array('T_gas_cool', T_gas_cool, maxp_krome) + end subroutine allocate_part subroutine deallocate_part @@ -607,11 +613,11 @@ subroutine init_part endif if (store_dust_temperature) dust_temp = -1. !-- Initialise dust properties to zero -#ifdef DUSTGROWTH - dustprop(:,:) = 0. - dustgasprop(:,:) = 0. - VrelVf(:) = 0. -#endif + if (use_dustgrowth) then + dustprop(:,:) = 0. + dustgasprop(:,:) = 0. + VrelVf(:) = 0. + endif if (ind_timesteps) then ibin(:) = 0 ibin_old(:) = 0 @@ -1312,7 +1318,7 @@ subroutine reorder_particles(iorder,np) integer, intent(in) :: iorder(:) integer, intent(in) :: np - integer :: isrc + integer :: isrc,nbuf real :: xtemp(ipartbufsize) do i=1,np @@ -1324,7 +1330,7 @@ subroutine reorder_particles(iorder,np) enddo ! Swap particles around - call fill_sendbuf(i,xtemp) + call fill_sendbuf(i,xtemp,nbuf) call copy_particle_all(isrc,i,.false.) call unfill_buffer(isrc,xtemp) @@ -1430,12 +1436,12 @@ end subroutine change_status_pos ! to send to another processor !+ !---------------------------------------------------------------- -subroutine fill_sendbuf(i,xtemp) +subroutine fill_sendbuf(i,xtemp,nbuf) use io, only:fatal use mpiutils, only:fill_buffer integer, intent(in) :: i real, intent(out) :: xtemp(ipartbufsize) - integer :: nbuf + integer, intent(out) :: nbuf ! !--package particle information into one simple wrapper ! @@ -1511,9 +1517,8 @@ subroutine fill_sendbuf(i,xtemp) endif call fill_buffer(xtemp,iorig(i),nbuf) endif - if (nbuf /= ipartbufsize) call fatal('fill_sendbuf','error in send buffer size') + if (nbuf > ipartbufsize) call fatal('fill_sendbuf','error: send buffer size overflow',var='nbuf',ival=nbuf) - return end subroutine fill_sendbuf !---------------------------------------------------------------- @@ -1602,7 +1607,6 @@ subroutine unfill_buffer(ipart,xbuf) divBsymm(ipart) = 0. endif - return end subroutine unfill_buffer !---------------------------------------------------------------- diff --git a/src/main/phantom.F90 b/src/main/phantom.F90 index f8c0becf7..3046d69ba 100644 --- a/src/main/phantom.F90 +++ b/src/main/phantom.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantom ! diff --git a/src/main/photoevap.f90 b/src/main/photoevap.f90 deleted file mode 100644 index a985bf61b..000000000 --- a/src/main/photoevap.f90 +++ /dev/null @@ -1,432 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module photoevap -! -! This module contains all the subroutines necessary for the -! photoevaporation switch -! -! :References: Alexander, Clarke & Pringle (2006), MNRAS 369, 216-228 -! -! :Owner: Daniel Price -! -! :Runtime parameters: -! - ionflux_cgs : *Stellar EUV flux rate* -! - mu_cgs : *Mean molecular weight* -! - recombrate_cgs : *Recombination rate (alpha)* -! -! :Dependencies: allocutils, dim, eos, externalforces, infile_utils, io, -! physcon, units -! - - implicit none - - !--# of grid nodes for photoevaporation grid - integer, parameter :: Nr = 400 - integer, parameter :: Nphi = 400 - integer, parameter :: Ntheta = 400 - - !--Index to identify which cell particles belong - integer, allocatable :: Rnum(:) - integer, allocatable :: Thetanum(:) - integer, allocatable :: Phinum(:) - - !--# of particles per cell and ray. - integer :: Cellpartnum(Nr-1,Ntheta-1,Nphi-1) - integer :: Raypartnum(Ntheta-1,Nphi-1) - - !--Location of ionization front and # of ionized particles in ray - integer :: Ionfront(Ntheta-1,Nphi-1) - integer :: Nion(Ntheta-1,Nphi-1) - - !--Reciprical of cell volume - real :: rCellvol(Nr-1,Nphi-1) - - !--Fraction of ions to neutrals in boundary cell - real :: Ionfrac(Ntheta-1,Nphi-1) - - !--Change in # of ions per unit time due to stellar flux (constant in time) - real :: dN_ion(Ntheta-1) - - !--Photoevaporation grid minimums and increment values - real :: Rgrid_min, Thetagrid_min, Phigrid_min - real :: dr_grid, dphi_grid, dtheta_grid - - !--Recombination rate, ionization flux, mean Mol. weight, temperature of ions - real :: recombrate - real :: recombrate_cgs = 2.6d-13 - real :: ionflux - real :: ionflux_cgs = 1.d41 - real :: mu - real :: mu_cgs = 1.26 - real :: mH - real :: temp_ion - real :: energy_to_temperature_ratio - - real :: prev_time - - public :: allocate_photoevap - public :: deallocate_photoevap - public :: write_options_photoevap - public :: read_options_photoevap - public :: photo_ionize - public :: find_ionfront - public :: set_photoevap_grid - - private - -contains - -!*************************************************************************************** -!*************************************************************************************** - -subroutine allocate_photoevap - use dim, only:maxp - use allocutils, only:allocate_array - - call allocate_array('Rnum', Rnum, maxp) - call allocate_array('Thetanum', Thetanum, maxp) - call allocate_array('Phinum', Phinum, maxp) - -end subroutine allocate_photoevap - -subroutine deallocate_photoevap - - deallocate(Rnum) - deallocate(Thetanum) - deallocate(Phinum) - -end subroutine deallocate_photoevap - -!---------------------------------------------------------------- -!+ -! This subroutine makes a spherical grid for photoevaporation -! Note: this routine is ment to be called only once at the -! beginning of the simulation to get the grid spacing. -!+ -!---------------------------------------------------------------- -subroutine set_photoevap_grid - use units, only:udist,umass,utime - use physcon, only:pi,atomic_mass_unit,mass_proton_cgs,kboltz,Rg - use externalforces, only:accradius1 - use eos, only:gamma - - integer :: i,j - - !--Inner and outer radius of grid - real :: R_in - real :: R_out - - !--Photoevaporation grid min and max in each direction - real :: Rgrid_max - real :: Thetagrid_max - real :: Phigrid_max - - !--photoevaporation grid in r,theta directions - real :: r_grid(Nr) - real :: theta_grid(Ntheta) - - !--TODO: try to read these in from setup_photoevap - R_in = accradius1 - R_out = 10.0 - - !--Set the temperature of ions to 10,000 K - temp_ion = 1.d4 - - !--Constant that converts specific energy density (u) to temperature in K. - ! Note: the (udist/utime)**2 comes from adding physical units back onto u. - !energy_to_temperature_ratio = Rg/(mu*(gamma-1.))/(udist/utime)**2 - energy_to_temperature_ratio = kboltz/((gamma-1.)*mu*atomic_mass_unit)*(utime/udist)**2 - - !--Mass of hydrogen gas molecule in code units - mH = mu*mass_proton_cgs/umass - - !--Time at previous time step (Initialized to zero here) - prev_time = 0. - - !--photoevaporation grid's inner/outer radius and other dimensions - Rgrid_min = R_in - Rgrid_max = 1.3*R_out - Thetagrid_min = 0. - Thetagrid_max = pi - Phigrid_min = -pi - Phigrid_max = pi - - !--photoevaporation grid spacing in each direction (with Nr x Nphi x Ntheta nodes) - dr_grid = (Rgrid_max - Rgrid_min )/(Nr-1) - dtheta_grid = (Thetagrid_max - Thetagrid_min)/(Ntheta-1) - dphi_grid = (Phigrid_max - Phigrid_min )/(Nphi-1) - - !--photoevaporation grid in r,theta directions - r_grid = (/( Rgrid_min + dr_grid*i , i = 0, Nr-1 )/) - theta_grid = (/( Thetagrid_min + dtheta_grid*i, i = 0, Ntheta-1 )/) - - do i = 1,Ntheta-1 - do j = 1,Nr-1 - !--Calculate the volume of each grid cell (symmetrical in phi so only need two dimensional array) - rCellvol(j,i) = (0.5*(r_grid(j)+r_grid(j+1)))**2*sin(0.5*(theta_grid(i)+theta_grid(i+1)))*dr_grid*dtheta_grid*dphi_grid - enddo - - !--Calculate the ionization rate in each ray (symmetrical in phi so only need one dimensional array) - dN_ion(i) = (0.25/pi*sin(0.5*(theta_grid(j)+theta_grid(j+1)))*dtheta_grid*dphi_grid)*ionflux - enddo - - !--Because the reciprical of Cellvol is only ever used: rCellvol = 1/Cellvol - rCellvol = 1./rCellvol - -end subroutine set_photoevap_grid - -!----------------------------------------------------------------------- -!+ -! Subroutine to identify in which grid cell particles reside, solve the -! ionization/recombination balance for each ray, and finally find the -! location for the ionization front. -!+ -!----------------------------------------------------------------------- -subroutine find_ionfront(timei,npart,xyzh,pmassi) - use io, only:fatal - integer, intent(in) :: npart - real, intent(in) :: timei - real, intent(in) :: pmassi - real, intent(in) :: xyzh(:,:) - - integer :: i,j,k - - !--Cumulative sum of particles along ray just below current cell - integer :: curr_ray_count - - !--Change in # of ions per unit time due to recombination rate - real :: dN_recomb - - !--Position of particle in spherical coordinates - real :: r_pos,theta_pos,phi_pos - - real :: pmass_on_mH - real :: dt - - !--Find how much time has elapsed since the last call - dt = timei - prev_time - - if ( dt == 0. ) then - print*,'WARNING! find_ionfront was called needlessly!' - else - - !--Gives the number of hydrogen gas molecules per SPH particle - pmass_on_mH = pmassi/mH - -!$omp parallel do private(i,r_pos,theta_pos,phi_pos) schedule(static) - do i = 1,npart - r_pos = sqrt(sum(xyzh(1:3,i)**2)) - theta_pos = acos(xyzh(3,i)/r_pos) - phi_pos = atan2(xyzh(2,i),xyzh(1,i)) - - ! Find the (*INTEGER*) grid node just below the particle in each direction - Rnum(i) = int((r_pos-Rgrid_min)/dr_grid)+1 - Thetanum(i) = int((theta_pos-Thetagrid_min)/dtheta_grid)+1 - Phinum(i) = int((phi_pos-Phigrid_min)/dphi_grid)+1 - enddo -!$omp end parallel do - - !--Re-initialize/re-calculate Cellpartnum every time step - Cellpartnum = 0 -!$omp parallel do private(i) schedule(static) - do i = 1,npart - Cellpartnum(Rnum(i),Thetanum(i),Phinum(i)) = Cellpartnum(Rnum(i),Thetanum(i),Phinum(i)) + 1 - enddo -!$omp end parallel do - - !--Find the total number of particles along each ray (used to speed up loop below if ray is empty) - Raypartnum(:,:) = sum(Cellpartnum,1) - - ! - !--Solve for ionization/recombination balance and update Nion, ionization - ! front, and fraction of ionized particles at the front - ! -!$omp parallel do default(none) & -!$omp private(i,j,k,dN_recomb,curr_ray_count) & -!$omp shared(Ionfrac,Ionfront,Raypartnum,Cellpartnum,rCellvol,recombrate,dN_ion,Nion,dt,pmass_on_mH) & -!$omp schedule(dynamic) - do i = 1,Nphi-1 - do j = 1,Ntheta-1 - !--Save radial location of ionfront for current ray in k - k = Ionfront(j,i) - - !--Find the change in Nion due to recombination - if ( k == 1 ) then - dN_recomb = Ionfrac(j,i)*Cellpartnum(k,j,i)**2*rCellvol(k,j) - else - dN_recomb = sum(Cellpartnum(1:k-1,j,i)**2*rCellvol(1:k-1,j)) + Ionfrac(j,i)*Cellpartnum(k,j,i)**2*rCellvol(k,j) - endif - dN_recomb = recombrate*dN_recomb*pmass_on_mH - - !--Update the # of ionized particles in each radial column - if ( Raypartnum(j,i) > 0 ) then - Nion(j,i) = Nion(j,i) + nint(dt*(dN_ion(j)/pmass_on_mH-dN_recomb)) - - !--Make sure that flux doesn't "build-up" in the fully ionized columns - ! (i.e. the excess light escapes the system) - if ( Nion(j,i) > Raypartnum(j,i) ) then - Nion(j,i) = Raypartnum(j,i) - endif - -!!!!!! -! print*,dN_ion(j)/pmass_on_mH,dN_recomb,Nion(j,i) -!!!!!! - - if ( Nion(j,i) < 0 ) then - print*,'Warning! Negative ion number!',Nion(j,i),j,i - Nion(j,i) = 0 - endif - else - Nion(j,i) = 0 !--If no particles, then Nion must be reset - endif - - !--Now that we have the # of ions in each column, integrate from the star - ! out to Nion to find where the ionization front is located - k = 1 - curr_ray_count = Cellpartnum(k,j,i) - do while ( curr_ray_count < Nion(j,i) ) - if ( k < Nr-1 ) then - k = k+1 - else - exit - endif - curr_ray_count = curr_ray_count + Cellpartnum(k,j,i) - enddo - - !--Save the new ionization front radial cell # for the next iteration - Ionfront(j,i) = k - - !--Find the fraction of ions to neutrals in the ionization front - ! This only needs to be done for cells with more particles than Nion - if ( Raypartnum(j,i) <= Nion(j,i) ) then - Ionfrac(j,i) = 1. - else - if ( Cellpartnum(k,j,i) == 0 ) then - Ionfrac(j,i) = 1. - else - Ionfrac(j,i) = (Nion(j,i)-(curr_ray_count-Cellpartnum(k,j,i)))/real(Cellpartnum(k,j,i)) - endif - endif - - if ( Ionfrac(j,i) < 0 ) then - call fatal('find_ionfront','Ionfrac is less than zero!') - elseif ( Ionfrac(j,i) > 1 ) then - call fatal('find_ionfront','Ionfrac is greater than 1!') - endif - - enddo - enddo -!$omp end parallel do - - prev_time = timei - endif - -end subroutine find_ionfront - -!----------------------------------------------------------------------- -!+ -! Update the temperatures of the particles (Ionized,Boundary,Neutral) -!+ -!----------------------------------------------------------------------- -subroutine photo_ionize(vxyzu,npart) - use io, only:fatal - integer, intent(in) :: npart - real, intent(inout) :: vxyzu(:,:) - - integer :: ipart - - !--Temperature of the particle in Kelvin - real :: temperature,tempi - - if ( size(vxyzu,1) /= 4 ) then - call fatal('photoevap','no u in vxyzu variable: compile with ISOTHERMAL=no') - endif - -!$omp parallel do default(none) & -!$omp private(ipart,tempi,temperature) & -!$omp shared(npart,vxyzu,energy_to_temperature_ratio,Rnum,Thetanum,Phinum,Ionfrac,Ionfront,temp_ion) - do ipart = 1,npart - tempi = vxyzu(4,ipart)/energy_to_temperature_ratio - - if ( Rnum(ipart) < Ionfront(Thetanum(ipart),Phinum(ipart)).or. & - Rnum(ipart) >= Nr ) then - ! Above ionization front (ionized particles) - temperature = temp_ion - - elseif ( Rnum(ipart) == Ionfront(Thetanum(ipart),Phinum(ipart)) ) then - ! Ionization front (fractionally ionized) - temperature = Ionfrac(Thetanum(ipart),Phinum(ipart))*temp_ion + & - (1.-Ionfrac(Thetanum(ipart),Phinum(ipart)))*tempi - - else - ! Below ionization front (neutral particles) - temperature = tempi - - endif - - vxyzu(4,ipart) = temperature*energy_to_temperature_ratio - - enddo -!$omp end parallel do - -end subroutine photo_ionize - -!----------------------------------------------------------------------- -!+ -! writes input options to the input file -!+ -!----------------------------------------------------------------------- -subroutine write_options_photoevap(iunit) - use infile_utils, only:write_inopt - - integer, intent(in) :: iunit - - write(iunit,"(/,a)") '# options controlling photoevaporation' - call write_inopt(mu_cgs,'mu_cgs','Mean molecular weight',iunit) - call write_inopt(recombrate_cgs,'recombrate_cgs','Recombination rate (alpha)',iunit) - call write_inopt(ionflux_cgs,'ionflux_cgs','Stellar EUV flux rate',iunit) - -end subroutine write_options_photoevap - -!----------------------------------------------------------------------- -!+ -! reads input options from the input file -!+ -!----------------------------------------------------------------------- -subroutine read_options_photoevap(name,valstring,imatch,igotall,ierr) - use units, only:udist,utime - - character(len=*), intent(in) :: name,valstring - logical, intent(out) :: imatch,igotall - integer, intent(out) :: ierr - integer, save :: ngot = 0 - - imatch = .false. - igotall = .true. - ierr = 0 - - select case(trim(name)) - case('mu_cgs') - read(valstring,*,iostat=ierr) mu_cgs - mu = mu_cgs - ngot = ngot + 1 - case('recombrate_cgs') - read(valstring,*,iostat=ierr) recombrate_cgs - recombrate = recombrate_cgs*utime/udist**3 - ngot = ngot + 1 - case('ionflux_cgs') - read(valstring,*,iostat=ierr) ionflux_cgs - ionflux = ionflux_cgs*utime - ngot = ngot + 1 - case default - imatch = .false. - end select - igotall = ( ngot >= 3 ) - -end subroutine read_options_photoevap - -end module photoevap diff --git a/src/main/physcon.f90 b/src/main/physcon.f90 index e395009e3..2577d5fd6 100644 --- a/src/main/physcon.f90 +++ b/src/main/physcon.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module physcon ! diff --git a/src/main/ptmass_heating.F90 b/src/main/ptmass_heating.f90 similarity index 100% rename from src/main/ptmass_heating.F90 rename to src/main/ptmass_heating.f90 diff --git a/src/main/ptmass_radiation.F90 b/src/main/ptmass_radiation.f90 similarity index 99% rename from src/main/ptmass_radiation.F90 rename to src/main/ptmass_radiation.f90 index d8bbb78ff..18954ec84 100644 --- a/src/main/ptmass_radiation.F90 +++ b/src/main/ptmass_radiation.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module ptmass_radiation ! diff --git a/src/main/quitdump.f90 b/src/main/quitdump.f90 index c2761ddbb..5f0159905 100644 --- a/src/main/quitdump.f90 +++ b/src/main/quitdump.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module quitdump ! diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 8c9f3aeb2..468a0be97 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module radiation_utils ! diff --git a/src/main/random.f90 b/src/main/random.f90 index 6a8ea2ce0..e77444401 100644 --- a/src/main/random.f90 +++ b/src/main/random.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module random ! diff --git a/src/main/readwrite_dumps.F90 b/src/main/readwrite_dumps.F90 index 2b33cbcf3..ff82e7935 100644 --- a/src/main/readwrite_dumps.F90 +++ b/src/main/readwrite_dumps.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module readwrite_dumps ! @@ -27,8 +27,13 @@ module readwrite_dumps public :: write_smalldump,write_fulldump,read_smalldump,read_dump,write_gadgetdump +#ifdef AOCC + logical, pointer, public :: opened_full_dump + logical, pointer, public :: dt_read_in +#else logical, pointer, public :: opened_full_dump => opened_full_dump_fortran ! for use in analysis files if user wishes to skip small dumps logical, pointer, public :: dt_read_in => dt_read_in_fortran ! to determine if dt has been read in so that ibin & ibinold can be set on restarts +#endif integer, parameter, public :: is_small_dump = 1978 integer, parameter, public :: is_not_mhd = 1979 diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index fa606f937..389bb7fef 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module readwrite_dumps_fortran ! @@ -19,7 +19,7 @@ module readwrite_dumps_fortran ! :Runtime parameters: None ! ! :Dependencies: boundary, boundary_dyn, checkconserved, dim, dump_utils, -! dust, dust_formation, eos, eos_stamatellos, externalforces, fileutils, io, lumin_nsdisc, +! dust, dust_formation, eos, externalforces, fileutils, io, lumin_nsdisc, ! memory, metric_tools, mpi, mpiutils, options, part, ! readwrite_dumps_common, setup_params, sphNGutils, timestep, units ! @@ -27,8 +27,6 @@ module readwrite_dumps_fortran i_real,i_real4,i_real8,int1,int2,int1o,int2o,dump_h,lentag use readwrite_dumps_common, only:check_arrays,fileident,get_options_from_fileid implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" public :: write_smalldump_fortran,write_fulldump_fortran,read_smalldump_fortran,read_dump_fortran @@ -150,7 +148,6 @@ subroutine start_threadwrite(id,iunit,filename) endif endif - return end subroutine start_threadwrite !-------------------------------------------------------------------- @@ -179,7 +176,6 @@ subroutine end_threadwrite(id) endif #endif - return end subroutine end_threadwrite !-------------------------------------------------------------------- @@ -199,7 +195,6 @@ subroutine get_dump_size(fileid,smalldump) end subroutine get_dump_size - !-------------------------------------------------------------------- !+ ! subroutine to write output to full dump file @@ -234,8 +229,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use lumin_nsdisc, only:beta #endif use metric_tools, only:imetric, imet_et - use eos_stamatellos, only:gradP_cool,Gpot_cool,doFLD,urad_FLD - + use eos_stamatellos, only:gradP_cool,doFLD,urad_FLD,ttherm_store,teqi_store,opac_store real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -243,7 +237,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) integer(kind=8), intent(in), optional :: ntotal integer, parameter :: isteps_sphNG = 0, iphase0 = 0 - integer(kind=8) :: ilen(4),i + integer(kind=8) :: ilen(4) integer :: nums(ndatatypes,4) integer :: ipass,k,l,ioffset integer :: ierr,ierrs(30) @@ -254,7 +248,6 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) character(len=120) :: blankarray type(dump_h) :: hdr real, allocatable :: temparr(:) - real :: r ! !--collect global information from MPI threads ! @@ -299,13 +292,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--open dumpfile ! masterthread: if (id==master) then -! open(unit=10,file=trim(dumpfile)//'info.dat') - ! write(10,'(6A16)') '# R', 'Gpot_cool','poten','gradP_cool', 'eos_vars(gasP)','eos_vars(gamma)' - ! do i=1,nparttot - ! write(10,'(6E16.5)') sqrt(xyzh(1,i)**2+xyzh(2,i)**2+xyzh(3,i)**2),Gpot_cool(i),poten(i),& - ! gradP_cool(i),eos_vars(igasP,i),eos_vars(igamma,i) - ! enddo - ! close(10) + if (idtmax_frac==0) then write(iprint,"(/,/,'--------> TIME = ',g12.4,': full dump written to file ',a,' <--------',/)") t,trim(dumpfile) else @@ -418,11 +405,13 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,ierrs(13),index=iZ) endif endif - ! write urad to file (stamatellos + FLD) - if (icooling == 9 .and. doFLD) then - call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) + ! write stamatellos cooling values + if (icooling == 9) then ! .and. doFLD) then +! call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) + call write_array(1,teqi_store,'teqi',npart,k,ipass,idump,nums,ierrs(13)) + call write_array(1,ttherm_store,'ttherm',npart,k,ipass,idump,nums,ierrs(13)) + call write_array(1,opac_store,'opacity',npart,k,ipass,idump,nums,ierrs(13)) endif - ! smoothing length written as real*4 to save disk space call write_array(1,xyzh,xyzh_label,1,npart,k,ipass,idump,nums,ierrs(14),use_kind=4,index=4) if (maxalpha==maxp) call write_array(1,alphaind,(/'alpha'/),1,npart,k,ipass,idump,nums,ierrs(15)) @@ -434,11 +423,11 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) if (gravity .and. maxgrav==maxp) then call write_array(1,poten,'poten',npart,k,ipass,idump,nums,ierrs(17)) endif -#ifdef IND_TIMESTEPS - if (.not.allocated(temparr)) allocate(temparr(npart)) - temparr(1:npart) = dtmax/2**ibin(1:npart) - call write_array(1,temparr,'dt',npart,k,ipass,idump,nums,ierrs(18),use_kind=4) -#endif + if (ind_timesteps) then + if (.not.allocated(temparr)) allocate(temparr(npart)) + temparr(1:npart) = dtmax/2.**ibin(1:npart) + call write_array(1,temparr,'dt',npart,k,ipass,idump,nums,ierrs(18),use_kind=4) + endif call write_array(1,iorig,'iorig',npart,k,ipass,idump,nums,ierrs(29)) #ifdef PRDRAG @@ -450,10 +439,10 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(1,temparr,'beta_pr',npart,k,ipass,idump,nums,ierrs(19)) endif #endif -#ifdef LIGHTCURVE if (lightcurve) then call write_array(1,luminosity,'luminosity',npart,k,ipass,idump,nums,ierrs(20)) endif + if (use_krome) then call write_array(1,abundance,abundance_label,krome_nmols,npart,k,ipass,idump,nums,ierrs(21)) call write_array(1,T_gas_cool,'temp',npart,k,ipass,idump,nums,ierrs(24)) @@ -462,6 +451,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(1,eos_vars(imu,:),eos_vars_label(imu),npart,k,ipass,idump,nums,ierrs(12)) call write_array(1,eos_vars(igamma,:),eos_vars_label(igamma),npart,k,ipass,idump,nums,ierrs(12)) endif + if (do_nucleation) then call write_array(1,nucleation,nucleation_label,n_nucleation,npart,k,ipass,idump,nums,ierrs(25)) endif @@ -507,12 +497,10 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(4,divBsymm,'divBsymm',npart,k,ipass,idump,nums,ierrs(2)) endif if (any(ierrs(1:2) /= 0)) call error('write_dump','error writing MHD arrays') -#ifdef NONIDEALMHD if (mhd_nonideal) then call write_array(4,eta_nimhd,eta_nimhd_label,4,npart,k,ipass,idump,nums,ierrs(1)) if (ierrs(1) /= 0) call error('write_dump','error writing non-ideal MHD arrays') endif -#endif endif enddo if (ipass==1) call write_block_header(narraylengths,ilen,nums,idump,ierr) @@ -551,9 +539,6 @@ subroutine write_smalldump_fortran(t,dumpfile) use dump_utils, only:open_dumpfile_w,dump_h,allocate_header,free_header,& write_header,write_array,write_block_header use mpiutils, only:reduceall_mpi -#ifdef LIGHTCURVE - use part, only:luminosity -#endif real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer(kind=8) :: ilen(4) @@ -629,9 +614,8 @@ subroutine write_smalldump_fortran(t,dumpfile) if (use_dust) & call write_array(1,dustfrac,dustfrac_label,ndusttypes,npart,k,ipass,idump,nums,ierr,singleprec=.true.) call write_array(1,xyzh,xyzh_label,4,npart,k,ipass,idump,nums,ierr,index=4,use_kind=4) -#ifdef LIGHTCURVE + if (lightcurve) call write_array(1,luminosity,'luminosity',npart,k,ipass,idump,nums,ierr,singleprec=.true.) -#endif if (do_radiation) call write_array(1,rad,rad_label,maxirad,npart,k,ipass,idump,nums,ierr,singleprec=.true.) enddo ! @@ -657,7 +641,6 @@ subroutine write_smalldump_fortran(t,dumpfile) close(unit=idump) call end_threadwrite(id) - return end subroutine write_smalldump_fortran @@ -671,7 +654,7 @@ end subroutine write_smalldump_fortran subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ierr,headeronly,dustydisc) use memory, only:allocate_memory - use dim, only:maxp,maxvxyzu,gravity,lightcurve,mhd,maxp_hard + use dim, only:maxp,maxvxyzu,gravity,lightcurve,mhd,maxp_hard,inject_parts,mpi use io, only:real4,master,iverbose,error,warning ! do not allow calls to fatal in this routine use part, only:xyzh,vxyzu,massoftype,npart,npartoftype,maxtypes,iphase, & maxphase,isetphase,nptmass,nsinkproperties,maxptmass,get_pmass, & @@ -742,7 +725,7 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie ! ! read header from the dump file ! - call read_header(idisk1,hdr,tagged,ierr) + call read_header(idisk1,hdr,ierr,tagged=tagged) if (ierr /= 0) then call error('read_dump','error reading header from file') return @@ -809,19 +792,18 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie if (present(headeronly)) then if (headeronly) return endif - - if (iblock==1) then ! -!--Allocate main arrays +!--allocate main arrays ! - if (dynamic_bdy) then - call allocate_memory(int(maxp_hard,kind=8)) + if (iblock==1) then + if (dynamic_bdy .or. inject_parts) then + if (mpi) then + call allocate_memory(max(nparttot,int(maxp_hard/nprocs,kind=8))) + else + call allocate_memory(max(nparttot,int(maxp_hard,kind=8))) + endif else -#ifdef INJECT_PARTICLES - call allocate_memory(max(nparttot,int(maxp_hard,kind=8))) -#else call allocate_memory(nparttot) -#endif endif endif ! @@ -836,7 +818,6 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie npart = npart + npartread if (npartread <= 0 .and. nptmass <= 0) then - print*,' SKIPPING BLOCK npartread = ',npartread call skipblock(idisk1,nums(:,1),nums(:,2),nums(:,3),nums(:,4),tagged,ierr) if (ierr /= 0) then print*,' error skipping block' @@ -910,10 +891,14 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie call check_npartoftype(npartoftype,npart) write(iprint,"(a,/)") ' <<< ERROR! end of file reached in data read' ierr = 666 - return end subroutine read_dump_fortran +!-------------------------------------------------------------------- +!+ +! sanity check on npartoftype +!+ +!------------------------------------------------------------------- subroutine check_npartoftype(npartoftype,npart) integer, intent(inout) :: npartoftype(:) integer, intent(in) :: npart @@ -924,16 +909,16 @@ subroutine check_npartoftype(npartoftype,npart) endif end subroutine check_npartoftype + !-------------------------------------------------------------------- !+ ! subroutine to read a small dump from file, as written ! in write_smalldump !+ !------------------------------------------------------------------- - subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ierr,headeronly,dustydisc) use memory, only:allocate_memory - use dim, only:maxvxyzu,mhd,maxphase,maxp,maxp_hard + use dim, only:maxvxyzu,mhd,maxphase,maxp use io, only:real4,master,iverbose,error,warning ! do not allow calls to fatal in this routine use part, only:npart,npartoftype,maxtypes,nptmass,nsinkproperties,maxptmass, & massoftype @@ -941,7 +926,6 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro ierr_realsize,read_header,extract,free_header,read_block_header use mpiutils, only:reduce_mpi,reduceall_mpi use options, only:use_dustfrac - use boundary_dyn, only:dynamic_bdy character(len=*), intent(in) :: dumpfile real, intent(out) :: tfile,hfactfile integer, intent(in) :: idisk1,iprint,id,nprocs @@ -995,7 +979,7 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro ! !--single values ! - call read_header(idisk1,hdr,tagged,ierr,singleprec=.true.) + call read_header(idisk1,hdr,ierr,singleprec=.true.,tagged=tagged) if (ierr /= 0) then call error('read_smalldump','error reading header from file') return @@ -1017,17 +1001,10 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro call free_header(hdr,ierr) ! - !--Allocate main arrays + !--Allocate main arrays (no need for extra space here re: particle injection + ! as small dumps are only read for visualisation/analysis purposes) ! - if (dynamic_bdy) then - call allocate_memory(int(maxp_hard,kind=8)) - else -#ifdef INJECT_PARTICLES - call allocate_memory(int(maxp_hard,kind=8)) -#else - call allocate_memory(nparttot) -#endif - endif + call allocate_memory(nparttot) ! !--arrays ! @@ -1161,28 +1138,28 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto massoftype,nptmass,nsinkproperties,phantomdump,tagged,singleprec,& tfile,alphafile,idisk1,iprint,ierr) use dump_utils, only:read_array,match_tag - use dim, only:use_dust,h2chemistry,maxalpha,maxp,gravity,maxgrav,maxvxyzu, do_nucleation, & - use_dustgrowth,maxdusttypes,ndivcurlv,maxphase,gr,store_dust_temperature - use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,dustfrac,abundance,abundance_label, & + use dim, only:use_dust,h2chemistry,maxalpha,maxp,gravity,maxgrav,maxvxyzu,do_nucleation, & + use_dustgrowth,maxdusttypes,ndivcurlv,maxphase,gr,store_dust_temperature,& + ind_timesteps,use_krome + use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,dustfrac,dustfrac_label,abundance,abundance_label, & alphaind,poten,xyzmh_ptmass,xyzmh_ptmass_label,vxyz_ptmass,vxyz_ptmass_label, & Bevol,Bxyz,Bxyz_label,nabundances,iphase,idust, & eos_vars,eos_vars_label,maxeosvars,dustprop,dustprop_label,divcurlv,divcurlv_label,iX,iZ,imu, & VrelVf,VrelVf_label,dustgasprop,dustgasprop_label,filfac,filfac_label,pxyzu,pxyzu_label,dust_temp, & rad,rad_label,radprop,radprop_label,do_radiation,maxirad,maxradprop,ifluxx,ifluxy,ifluxz, & nucleation,nucleation_label,n_nucleation,ikappa,tau,itau_alloc,tau_lucy,itauL_alloc,& - ithick,ilambda,iorig,dt_in,krome_nmols,T_gas_cool,igasP,itemp + ithick,ilambda,iorig,dt_in,krome_nmols,T_gas_cool use sphNGutils, only:mass_sphng,got_mass,set_gas_particle_mass use options, only:use_porosity - use eos, only:ieos,eos_is_non_ideal,eos_outputs_gasP integer, intent(in) :: i1,i2,noffset,narraylengths,nums(:,:),npartread,npartoftype(:),idisk1,iprint real, intent(in) :: massoftype(:) integer, intent(in) :: nptmass,nsinkproperties logical, intent(in) :: phantomdump,singleprec,tagged real, intent(in) :: tfile,alphafile integer, intent(out) :: ierr - logical :: got_dustfrac(maxdusttypes) logical :: match - logical :: got_iphase,got_xyzh(4),got_vxyzu(4),got_abund(nabundances),got_alpha,got_poten + logical :: got_dustfrac(maxdusttypes) + logical :: got_iphase,got_xyzh(4),got_vxyzu(4),got_abund(nabundances),got_alpha(1),got_poten logical :: got_sink_data(nsinkproperties),got_sink_vels(3),got_Bxyz(3) logical :: got_krome_mols(krome_nmols),got_krome_T,got_krome_gamma,got_krome_mu logical :: got_eosvars(maxeosvars),got_nucleation(n_nucleation),got_ray_tracer @@ -1205,8 +1182,7 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto got_sink_vels = .false. got_Bxyz = .false. got_psi = .false. - got_gasP = .false. - got_temp = .false. + got_eosvars = .false. got_dustprop = .false. got_VrelVf = .false. got_filfac = .false. @@ -1217,13 +1193,10 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto got_krome_gamma = .false. got_krome_mu = .false. got_krome_T = .false. - got_x = .false. - got_z = .false. - got_mu = .false. got_nucleation = .false. got_ray_tracer = .false. - got_raden = .false. - got_kappa = .false. + got_rad = .false. + got_radprop = .false. got_pxyzu = .false. got_iorig = .false. @@ -1284,16 +1257,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto if (store_dust_temperature) then call read_array(dust_temp,'Tdust',got_Tdust,ik,i1,i2,noffset,idisk1,tag,match,ierr) endif - if (eos_outputs_gasP(ieos) .or. eos_is_non_ideal(ieos)) then - call read_array(eos_vars(igasP,:),eos_vars_label(igasP),got_gasP,ik,i1,i2,noffset,idisk1,tag,match,ierr) - endif - if (eos_is_non_ideal(ieos)) then - call read_array(eos_vars(itemp,:),eos_vars_label(itemp),got_temp,ik,i1,i2,noffset,idisk1,tag,match,ierr) - endif - call read_array(eos_vars(iX,:),eos_vars_label(iX),got_x,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(eos_vars(iZ,:),eos_vars_label(iZ),got_z,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(eos_vars(imu,:),eos_vars_label(imu),got_mu,ik,i1,i2,noffset,idisk1,tag,match,ierr) - if (maxalpha==maxp) call read_array(alphaind(1,:),'alpha',got_alpha,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(eos_vars,eos_vars_label,got_eosvars,ik,i1,i2,noffset,idisk1,tag,match,ierr) + + if (maxalpha==maxp) call read_array(alphaind,(/'alpha'/),got_alpha,ik,i1,i2,noffset,idisk1,tag,match,ierr) ! ! read divcurlv if it is in the file ! @@ -1302,23 +1268,17 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto ! read gravitational potential if it is in the file ! if (gravity .and. maxgrav==maxp) call read_array(poten,'poten',got_poten,ik,i1,i2,noffset,idisk1,tag,match,ierr) -#ifdef IND_TIMESTEPS ! ! read dt if it is in the file ! - call read_array(dt_in,'dt',dt_read_in_fortran,ik,i1,i2,noffset,idisk1,tag,match,ierr) -#endif + if (ind_timesteps) call read_array(dt_in,'dt',dt_read_in_fortran,ik,i1,i2,noffset,idisk1,tag,match,ierr) + ! read particle ID's call read_array(iorig,'iorig',got_iorig,ik,i1,i2,noffset,idisk1,tag,match,ierr) if (do_radiation) then - call read_array(rad,rad_label,got_raden,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(radprop(ikappa,:),radprop_label(ikappa),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(radprop(ithick,:),radprop_label(ithick),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(radprop(ilambda,:),radprop_label(ilambda),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(radprop(ifluxx,:),radprop_label(ifluxx),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(radprop(ifluxy,:),radprop_label(ifluxy),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) - call read_array(radprop(ifluxz,:),radprop_label(ifluxz),got_kappa,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(rad,rad_label,got_rad,ik,i1,i2,noffset,idisk1,tag,match,ierr) + call read_array(radprop,radprop_label,got_radprop,ik,i1,i2,noffset,idisk1,tag,match,ierr) endif case(2) call read_array(xyzmh_ptmass,xyzmh_ptmass_label,got_sink_data,ik,1,nptmass,0,idisk1,tag,match,ierr) @@ -1342,9 +1302,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto ! call check_arrays(i1,i2,noffset,npartoftype,npartread,nptmass,nsinkproperties,massoftype,& alphafile,tfile,phantomdump,got_iphase,got_xyzh,got_vxyzu,got_alpha, & - got_krome_mols,got_krome_gamma,got_krome_mu,got_krome_T,got_x,got_z,got_mu, & + got_krome_mols,got_krome_gamma,got_krome_mu,got_krome_T, & got_abund,got_dustfrac,got_sink_data,got_sink_vels,got_Bxyz,got_psi,got_dustprop,got_pxyzu,got_VrelVf, & - got_dustgasprop,got_temp,got_raden,got_kappa,got_Tdust,got_nucleation,got_iorig,iphase,& + got_dustgasprop,got_rad,got_radprop,got_Tdust,got_eosvars,got_nucleation,got_iorig,iphase,& xyzh,vxyzu,pxyzu,alphaind,xyzmh_ptmass,Bevol,iorig,iprint,ierr) if (.not. phantomdump) then print *, "Calling set_gas_particle_mass" diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 45a96dd18..9f878498e 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -1,8 +1,8 @@ - !--------------------------------------------------------------------------! +!--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module step_lf_global ! @@ -33,9 +33,7 @@ module step_lf_global use part, only:radpred use timestep_ind, only:maxbins,itdt,ithdt,itdt1,ittwas implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" - real :: ibin_dts(4,0:maxbins) + real :: ibin_dts(4,0:maxbins) contains @@ -94,7 +92,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use dim, only:maxp,ndivcurlv,maxvxyzu,maxptmass,maxalpha,nalpha,h2chemistry,& use_dustgrowth,use_krome,gr,do_radiation use io, only:iprint,fatal,iverbose,id,master,warning - use options, only:iexternalforce,use_dustfrac,implicit_radiation,icooling + use options, only:iexternalforce,use_dustfrac,implicit_radiation use part, only:xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,Bevol,dBevol, & rad,drad,radprop,isdead_or_accreted,rhoh,dhdrho,& iphase,iamtype,massoftype,maxphase,igas,idust,mhd,& @@ -111,7 +109,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iosumflrp,iosumflrps,iosumflrc use boundary_dyn, only:dynamic_bdy,update_xyzminmax use timestep, only:dtmax,dtmax_ifactor,dtdiff - use timestep_ind, only:get_dt,nbinmax,decrease_dtmax,ibinnow,dt_too_small + use timestep_ind, only:get_dt,nbinmax,decrease_dtmax,dt_too_small use timestep_sts, only:sts_get_dtau_next,use_sts,ibin_sts,sts_it_n use part, only:ibin,ibin_old,twas,iactive,ibin_wake use part, only:metricderivs @@ -134,8 +132,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) real, intent(out) :: dtnew integer :: i,its,np,ntypes,itype,nwake,nvfloorp,nvfloorps,nvfloorc,ialphaloc real :: timei,erri,errmax,v2i,errmaxmean - real :: vxi,vyi,vzi,eni,vxoldi,vyoldi,vzoldi,hdtsph,pmassi - real :: alphaloci,divvdti,source,tdecay1,hi,rhoi,ddenom,spsoundi + real :: vxi,vyi,vzi,eni,hdtsph,pmassi + real :: alphaloci,source,tdecay1,hi,rhoi,ddenom,spsoundi real :: v2mean,hdti real(kind=4) :: t1,t2,tcpu1,tcpu2 real :: pxi,pyi,pzi,p2i,p2mean @@ -195,8 +193,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 9) then - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else if (icooling /= 9) then vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) @@ -271,16 +267,16 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none) schedule(guided,1) & !$omp shared(maxp,maxphase,maxalpha) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,divcurlv,npart,store_itype) & -!$omp shared(pxyzu,ppred,icooling) & +!$omp shared(pxyzu,ppred) & !$omp shared(Bevol,dBevol,Bpred,dtsph,massoftype,iphase) & !$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) & +!$omp shared(eos_vars,ufloor,icooling) & !$omp shared(twas,timei) & !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & -!$omp private(i,spsoundi,alphaloci,divvdti) & +!$omp private(i,spsoundi,alphaloci) & !$omp firstprivate(pmassi,itype,avdecayconst,alpha) & !$omp reduction(+:nvfloorps) predict_sph: do i=1,npart @@ -320,8 +316,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then ppred(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling == 9) then - vpred(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif @@ -441,16 +435,16 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel default(none) & !$omp shared(xyzh,vxyzu,vpred,fxyzu,npart,hdtsph,store_itype) & !$omp shared(pxyzu,ppred) & -!$omp shared(Bevol,dBevol,iphase,its,icooling) & +!$omp shared(Bevol,dBevol,iphase,its) & !$omp shared(dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass,massoftype) & !$omp shared(dtsph,ieos,ufloor,icooling) & !$omp shared(ibin,ibin_old,ibin_sts,twas,timei,use_sts,dtsph_next,ibin_wake,sts_it_n) & -!$omp shared(ibin_dts,nbinmax,ibinnow) & +!$omp shared(ibin_dts,nbinmax) & !$omp private(dti,hdti) & !$omp shared(rad,radpred,drad)& -!$omp private(i,vxi,vyi,vzi,vxoldi,vyoldi,vzoldi) & +!$omp private(i,vxi,vyi,vzi) & !$omp private(pxi,pyi,pzi,p2i) & !$omp private(erri,v2i,eni) & !$omp reduction(max:errmax) & @@ -481,8 +475,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) - elseif (icooling == 9) then - vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) else if (icooling /= 9) then vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) @@ -512,7 +504,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) elseif (icooling /= 9) then vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) else - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) endif !--floor the thermal energy if requested and required @@ -542,15 +534,48 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ibin(i) = ibin_wake(i) ibin_wake(i) = 0 ! reset flag endif - endif + else ! not individual timesteps == global timestepping + ! + ! For velocity-dependent forces compare the new v + ! with the predicted v used in the force evaluation. + ! Determine whether or not we need to iterate. + ! - if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdti*ddustprop(:,i) - if (itype==igas) then - if (mhd) Bevol(:,i) = Bevol(:,i) + hdti*dBevol(:,i) - if (do_radiation) rad(:,i) = rad(:,i) + hdti*drad(:,i) - if (use_dustfrac) then - dustevol(:,i) = dustevol(:,i) + hdti*ddustevol(:,i) - if (use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdti*ddustprop(:,i) + if (gr) then + pxi = pxyzu(1,i) + hdtsph*fxyzu(1,i) + pyi = pxyzu(2,i) + hdtsph*fxyzu(2,i) + pzi = pxyzu(3,i) + hdtsph*fxyzu(3,i) + eni = pxyzu(4,i) + hdtsph*fxyzu(4,i) + + erri = (pxi - ppred(1,i))**2 + (pyi - ppred(2,i))**2 + (pzi - ppred(3,i))**2 + errmax = max(errmax,erri) + + p2i = pxi*pxi + pyi*pyi + pzi*pzi + p2mean = p2mean + p2i + np = np + 1 + + pxyzu(1,i) = pxi + pxyzu(2,i) = pyi + pxyzu(3,i) = pzi + pxyzu(4,i) = eni + else + 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) + + erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 + errmax = max(errmax,erri) + + v2i = vxi*vxi + vyi*vyi + vzi*vzi + v2mean = v2mean + v2i + np = np + 1 + + vxyzu(1,i) = vxi + vxyzu(2,i) = vyi + vxyzu(3,i) = vzi + !--this is the energy equation if non-isothermal + if (maxvxyzu >= 4 .and. icooling/=9) vxyzu(4,i) = eni endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) @@ -586,12 +611,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (.not.converged .and. npart > 0) then !$omp parallel do default(none)& !$omp private(i) & -!$omp shared(npart,hdtsph,icooling)& +!$omp shared(npart,hdtsph)& !$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase) & !$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) & !$omp firstprivate(itype) & !$omp schedule(static) until_converged: do i=1,npart @@ -628,12 +653,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) + elseif (icooling /= 9) then + vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) else - if (icooling /= 9) then - vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) - else - vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) - endif + vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then @@ -760,7 +783,7 @@ end subroutine step_extern_sph_gr subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,time) use dim, only:maxptmass,maxp,maxvxyzu - use io, only:iverbose,id,master,iprint,warning + use io, only:iverbose,id,master,iprint,warning,fatal use externalforces, only:externalforce,accrete_particles,update_externalforce use options, only:iexternalforce use part, only:maxphase,isdead_or_accreted,iamboundary,igas,iphase,iamtype,& @@ -776,7 +799,7 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me real, intent(in) :: dtsph,time real, intent(inout) :: dtextforce real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:),pxyzu(:,:),dens(:),metrics(:,:,:,:),metricderivs(:,:,:,:) - integer :: i,itype,nsubsteps,naccreted,its,ierr + integer :: i,itype,nsubsteps,naccreted,its,ierr,nlive real :: timei,t_end_step,hdt,pmassi real :: dt,dtf,dtextforcenew,dtextforce_min real :: pri,spsoundi,pondensi,tempi,gammai @@ -871,7 +894,8 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me tempi = eos_vars(itemp,i) rhoi = rhoh(hi,massoftype(igas)) -! Note: grforce needs derivatives of the metric, which do not change between pmom iterations + ! Note: grforce needs derivatives of the metric, + ! which do not change between pmom iterations pmom_iterations: do while (its <= itsmax .and. .not. converged) its = its + 1 pprev = pxyz @@ -884,7 +908,8 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me if (pmom_err < ptol) converged = .true. fexti = fstar enddo pmom_iterations - if (its > itsmax ) call warning('step_extern_gr','Reached max number of pmom iterations. pmom_err ',val=pmom_err) + if (its > itsmax ) call warning('step_extern_gr',& + 'max # of pmom iterations',var='pmom_err',val=pmom_err) pitsmax = max(its,pitsmax) perrmax = max(pmom_err,perrmax) @@ -897,9 +922,11 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me its = 0 converged = .false. vxyz_star = vxyz -! Note: since particle positions change between iterations the metric and its derivatives need to be updated. -! cons2prim does not require derivatives of the metric, so those can updated once the iterations -! are complete, in order to reduce the number of computations. + ! Note: since particle positions change between iterations + ! the metric and its derivatives need to be updated. + ! cons2prim does not require derivatives of the metric, + ! so those can updated once the iterations are complete + ! in order to reduce the number of computations. xyz_iterations: do while (its <= itsmax .and. .not. converged) its = its+1 xyz_prev = xyz @@ -947,6 +974,7 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me ! accretedmass = 0. naccreted = 0 + nlive = 0 dtextforce_min = bignumber !$omp parallel default(none) & !$omp shared(npart,xyzh,metrics,metricderivs,vxyzu,fext,iphase,ntypes,massoftype,hdt,timei) & @@ -956,7 +984,7 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me !$omp private(pri,pondensi,spsoundi,tempi,dtf) & !$omp firstprivate(itype,pmassi) & !$omp reduction(min:dtextforce_min) & - !$omp reduction(+:accretedmass,naccreted) & + !$omp reduction(+:accretedmass,naccreted,nlive) & !$omp shared(idamp,damp_fac) !$omp do accreteloop: do i=1,npart @@ -990,11 +1018,16 @@ subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,me naccreted = naccreted + 1 endif endif + nlive = nlive + 1 endif enddo accreteloop !$omp enddo !$omp end parallel + if (npart > 2 .and. nlive < 2) then + call fatal('step','all particles accreted',var='nlive',ival=nlive) + endif + if (iverbose >= 2 .and. id==master .and. naccreted /= 0) write(iprint,"(a,es10.3,a,i4,a)") & 'Step: at time ',timei,', ',naccreted,' particles were accreted. Mass accreted = ',accretedmass @@ -1031,7 +1064,7 @@ end subroutine step_extern_gr !+ !---------------------------------------------------------------- subroutine step_extern_sph(dt,npart,xyzh,vxyzu) - use part, only:isdead_or_accreted,iboundary,iphase,iamtype + use part, only:isdead_or_accreted real, intent(in) :: dt integer, intent(in) :: npart real, intent(inout) :: xyzh(:,:) @@ -1039,7 +1072,7 @@ subroutine step_extern_sph(dt,npart,xyzh,vxyzu) integer :: i !$omp parallel do default(none) & - !$omp shared(npart,xyzh,vxyzu,dt,iphase) & + !$omp shared(npart,xyzh,vxyzu,dt) & !$omp private(i) do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -1102,7 +1135,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) integer(kind=1), intent(in) :: nbinmax integer(kind=1), intent(inout) :: ibin_wake(:) - integer :: i,itype,nsubsteps,ichem,naccreted,nfail,nfaili,merge_n + integer :: i,itype,nsubsteps,naccreted,nfail,nfaili,merge_n,nlive integer :: merge_ij(nptmass) integer(kind=1) :: ibin_wakei real :: timei,hdt,fextx,fexty,fextz,fextxi,fextyi,fextzi,phii,pmassi @@ -1201,7 +1234,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, fonrmax = 0. !$omp parallel default(none) & !$omp shared(maxp,maxphase) & - !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype,fxyzu) & + !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype) & !$omp shared(eos_vars,dust_temp,store_dust_temperature) & !$omp shared(dt,hdt,timei,iexternalforce,extf_is_velocity_dependent,cooling_in_step,icooling) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,idamp,damp_fac) & @@ -1348,8 +1381,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif else ! cooling without stored dust temperature - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),dudtcool,rhoi,dt,dudti_sph=fxyzu(4,i),part_id=i) -! upstream version call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool) + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,dudti_sph=fxyzu(4,i),part_id=i) endif endif #endif @@ -1395,6 +1427,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, accretedmass = 0. nfail = 0 naccreted = 0 + nlive = 0 ibin_wakei = 0 dptmass(:,:) = 0. @@ -1407,7 +1440,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, !$omp reduction(+:dptmass) & !$omp private(i,accreted,nfaili,fxi,fyi,fzi) & !$omp firstprivate(itype,pmassi,ibin_wakei) & - !$omp reduction(+:accretedmass,nfail,naccreted) + !$omp reduction(+:accretedmass,nfail,naccreted,nlive) !$omp do accreteloop: do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then @@ -1450,12 +1483,16 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif if (nfaili > 1) nfail = nfail + 1 endif + nlive = nlive + 1 endif - enddo accreteloop !$omp enddo !$omp end parallel + if (npart > 2 .and. nlive < 2) then + call fatal('step','all particles accreted',var='nlive',ival=nlive) + endif + ! ! reduction of sink particle changes across MPI ! diff --git a/src/utils/analysis_BRhoOrientation.F90 b/src/utils/analysis_BRhoOrientation.F90 index 3ba144698..73170e3e6 100644 --- a/src/utils/analysis_BRhoOrientation.F90 +++ b/src/utils/analysis_BRhoOrientation.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_clumpfind.F90 b/src/utils/analysis_clumpfind.F90 index 46bd494a2..697a4e1c1 100644 --- a/src/utils/analysis_clumpfind.F90 +++ b/src/utils/analysis_clumpfind.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_clumpfindWB23.F90 b/src/utils/analysis_clumpfindWB23.F90 index b11b2a975..da430b9ff 100644 --- a/src/utils/analysis_clumpfindWB23.F90 +++ b/src/utils/analysis_clumpfindWB23.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_common_envelope.F90 b/src/utils/analysis_common_envelope.F90 deleted file mode 100644 index 86ee7cb4f..000000000 --- a/src/utils/analysis_common_envelope.F90 +++ /dev/null @@ -1,4594 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module analysis -! -! Analysis routine for common envelope simulations -! -! :References: None -! -! :Owner: Mike Lau -! -! :Runtime parameters: None -! -! :Dependencies: centreofmass, dust_formation, energies, eos, -! eos_gasradrec, eos_mesa, extern_corotate, io, ionization_mod, kernel, -! mesa_microphysics, part, physcon, prompting, ptmass, setbinary, -! sortutils, table_utils, units, vectorutils -! - - use part, only:xyzmh_ptmass,vxyz_ptmass,nptmass,poten,ihsoft,ihacc,& - rhoh,nsinkproperties,maxvxyzu,maxptmass,isdead_or_accreted - use units, only:print_units,umass,utime,udist,unit_ergg,unit_density,& - unit_pressure,unit_velocity,unit_Bfield,unit_energ - use physcon, only:gg,pi,c,Rg - use io, only:fatal - use prompting, only:prompt - use centreofmass, only:get_centreofmass, reset_centreofmass - use energies, only:compute_energies,ekin,etherm,epot,etot - use ptmass, only:get_accel_sink_gas,get_accel_sink_sink - use kernel, only:kernel_softening,radkern,wkern,cnormk - use eos, only:equationofstate,ieos,init_eos,X_in,Z_in,gmw,get_spsound,done_init_eos - use eos_gasradrec,only:irecomb - use eos_mesa, only:get_eos_kappa_mesa,get_eos_pressure_temp_mesa,& - get_eos_various_mesa,get_eos_pressure_temp_gamma1_mesa - use setbinary, only:Rochelobe_estimate,L1_point - use sortutils, only:set_r2func_origin,r2func_origin,indexxfunc - use table_utils, only:logspace - implicit none - character(len=20), parameter, public :: analysistype = 'common_envelope' - integer :: analysis_to_perform - integer :: dump_number = 0 - real :: omega_corotate=0,init_radius,rho_surface,gamma - logical, dimension(5) :: switch = .false. - public :: do_analysis - public :: tconv_profile,get_interior_mass ! public = no unused fn warning - public :: planet_destruction,total_dust_mass ! make public to avoid compiler warning - private - -contains - -subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) - character(len=*), intent(in) :: dumpfile - integer, intent(in) :: num,npart,iunit - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - real, intent(in) :: particlemass,time - integer :: unitnum,i,ncols - logical :: requires_eos_opts - - !case 5 variables - real :: rhopart - - !case 7 variables - character(len=17), allocatable :: columns(:) - - !case 12 variables - real :: etoti, ekini, einti, epoti, phii - - real, dimension(3) :: com_xyz, com_vxyz - real, dimension(3) :: xyz_a, vxyz_a - real, allocatable :: histogram_data(:,:) - real :: ang_vel - - real :: pres_1i, proint_1i, peint_1i, temp_1i - real :: troint_1i, teint_1i, entrop_1i, abad_1i, gamma1_1i, gam_1i - - !case 16 variables - real, allocatable :: thermodynamic_quantities(:,:) - real, allocatable :: radius_1i, dens_1i - - - !chose analysis type - if (dump_number==0) then - print "(41(a,/))", & - ' 1) Sink separation', & - ' 2) Bound and unbound quantities', & - ' 3) Energies', & - ' 4) Profile from centre of mass', & - ' 5) Roche-lobe utils', & - ' 6) Star stabilisation suite', & - ' 7) Simulation units and particle properties', & - ' 8) Output .divv', & - ' 9) EoS testing', & - '11) Profile of newly unbound particles', & - '12) Sink properties', & - '13) MESA EoS compute total entropy and other average td quantities', & - '14) MESA EoS save on file thermodynamical quantities for all particles', & - '15) Gravitational drag on sinks', & - '16) CoM of gas around primary core', & - '17) Miscellaneous', & - '18) J-E plane', & - '19) Rotation profile', & - '20) Energy profile', & - '21) Recombination statistics', & - '22) Optical depth profile', & - '23) Particle tracker', & - '24) Unbound ion fraction', & - '25) Optical depth at recombination', & - '26) Envelope binding energy', & - '27) Print dumps number matching separation', & - '28) Companion mass coordinate vs. time', & - '29) Energy histogram',& - '30) Analyse disk',& - '31) Recombination energy vs time',& - '32) Binding energy profile',& - '33) planet_rvm',& - '34) Velocity histogram',& - '35) Unbound temperature',& - '36) Planet mass distribution',& - '37) Planet profile',& - '38) Velocity profile',& - '39) Angular momentum profile',& - '40) Keplerian velocity profile',& - '41) Total dust mass' - analysis_to_perform = 1 - call prompt('Choose analysis type ',analysis_to_perform,1,41) - 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) - - ! List of analysis options that require specifying EOS options - requires_eos_opts = any((/2,3,4,5,6,8,9,11,13,14,15,20,21,22,23,24,25,26,29,30,31,32,33,35,41/) == analysis_to_perform) - if (dump_number == 0 .and. requires_eos_opts) call set_eos_options(analysis_to_perform) - - select case(analysis_to_perform) - case(1) !sink separation - call separation_vs_time(time) - case(2) !bound and unbound quantities - call bound_mass(time,npart,particlemass,xyzh,vxyzu) - case(3) !Energies and bound mass - call calculate_energies(time,npart,particlemass,xyzh,vxyzu) - case(4) !Profile from COM (can be used for stellar profile) - call create_profile(time, num, npart, particlemass, xyzh, vxyzu) - case(5) !Mass within roche lobes - call roche_lobe_values(time,npart,particlemass,xyzh,vxyzu) - case(6) !Star stabilisation suite - 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(9) !EoS testing - call eos_surfaces - case(11) !New unbound particle profiles in time - call unbound_profiles(time,num,npart,particlemass,xyzh,vxyzu) - case(19) ! Rotation profile - call rotation_profile(time,num,npart,xyzh,vxyzu) - case(20) ! Energy profile - call energy_profile(time,npart,particlemass,xyzh,vxyzu) - case(21) ! Recombination statistics - call recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) - case(22) ! Optical depth profile - call tau_profile(time,num,npart,particlemass,xyzh) - case(23) ! Particle tracker - call track_particle(time,particlemass,xyzh,vxyzu) - case(24) ! Unbound ion fractions - call unbound_ionfrac(time,npart,particlemass,xyzh,vxyzu) - case(25) ! Optical depth at recombination - call recombination_tau(time,npart,particlemass,xyzh,vxyzu) - case(26) ! Calculate binding energy outside core - call env_binding_ene(npart,particlemass,xyzh,vxyzu) - case(27) ! Print dump number corresponding to given set of sink-sink separations - call print_dump_numbers(dumpfile) - case(28) ! Companion mass coordinate (spherical mass shells) vs. time - call m_vs_t(time,npart,particlemass,xyzh) - case(29) ! Energy histogram - call energy_hist(time,npart,particlemass,xyzh,vxyzu) - case(30) ! Analyse disk around companion - call analyse_disk(num,npart,particlemass,xyzh,vxyzu) - case(31) ! Recombination energy vs. time - call erec_vs_t(time,npart,particlemass,xyzh) - case(32) ! Binding energy profile - call create_bindingEnergy_profile(time,num,npart,particlemass,xyzh,vxyzu) - case(33) ! Planet coordinates and mass - call planet_rvm(time,particlemass,xyzh,vxyzu) - case(34) ! Velocity histogram - call velocity_histogram(time,num,npart,particlemass,xyzh,vxyzu) - case(35) ! Unbound temperatures - call unbound_temp(time,npart,particlemass,xyzh,vxyzu) - case(36) ! Planet mass distribution - call planet_mass_distribution(time,num,npart,xyzh) - case(37) ! Calculate planet profile - call planet_profile(num,dumpfile,particlemass,xyzh,vxyzu) - case(38) ! Velocity profile - call velocity_profile(time,num,npart,particlemass,xyzh,vxyzu) - case(39) ! Angular momentum profile - call angular_momentum_profile(time,num,npart,particlemass,xyzh,vxyzu) - case(40) ! Keplerian velocity profile - call vkep_profile(time,num,npart,particlemass,xyzh,vxyzu) - case(41) !Total dust mass - call total_dust_mass(time,npart,particlemass,xyzh) - case(12) !sink properties - call sink_properties(time,npart,particlemass,xyzh,vxyzu) - case(13) !MESA EoS compute total entropy and other average thermodynamical quantities - call bound_unbound_thermo(time,npart,particlemass,xyzh,vxyzu) - case(14) !MESA EoS save on file thermodynamical quantities for all particles - allocate(thermodynamic_quantities(5,npart)) - do i=1,npart - - !particle radius - radius_1i = distance(xyzh(1:3,i)) * udist - - !particles density in code units - rhopart = rhoh(xyzh(4,i), particlemass) - dens_1i = rhopart * unit_density - - !gets entropy for the current particle - call get_eos_various_mesa(rhopart*unit_density,vxyzu(4,i) * unit_ergg, & - pres_1i,proint_1i,peint_1i,temp_1i,troint_1i, & - teint_1i,entrop_1i,abad_1i,gamma1_1i,gam_1i) - - !stores everything in an array - thermodynamic_quantities(1,i) = radius_1i - thermodynamic_quantities(2,i) = dens_1i - thermodynamic_quantities(3,i) = pres_1i - thermodynamic_quantities(4,i) = temp_1i - thermodynamic_quantities(5,i) = entrop_1i - - enddo - ncols = 5 - allocate(columns(ncols)) - columns = (/' radius', & - ' density', & - ' pressure', & - ' temperature', & - ' entropy'/) - call write_file('td_quantities', 'thermodynamics', columns, thermodynamic_quantities, npart, ncols, num) - - unitnum = unitnum + 1 - deallocate(thermodynamic_quantities) - - case(15) !Gravitational drag on sinks - call gravitational_drag(time,npart,particlemass,xyzh,vxyzu) - - case(16) - call get_core_gas_com(time,npart,xyzh,vxyzu) - - case(17) - ncols = 6 - allocate(columns(ncols)) - columns = (/' x', & - ' y', & - ' z', & - ' r', & - 'spec. energy', & - ' omega ratio'/) - - call orbit_com(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,com_xyz,com_vxyz) - - ang_vel = 0. - - do i=1,nptmass - if (xyzmh_ptmass(4,i) > 0.) then - 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) - ang_vel = ang_vel + (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) - endif - enddo - - ang_vel = ang_vel / 2. - - allocate(histogram_data(6,npart)) - - do i=1,npart - xyz_a(1:3) = xyzh(1:3,i) - com_xyz(1:3) - vxyz_a(1:3) = vxyzu(1:3,i) - com_vxyz(1:3) - - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) - histogram_data(1:3,i) = xyzh(1:3,i) - histogram_data(4,i) = distance(xyz_a(1:3)) - histogram_data(5,i) = epoti + ekini - histogram_data(6,i) = (-xyz_a(2) * vxyz_a(1) + xyz_a(1) * vxyz_a(2)) / dot_product(xyz_a(1:2), xyz_a(1:2)) - histogram_data(6,i) = (histogram_data(6,i) - ang_vel) / ang_vel - enddo - - call write_file('specific_energy_particles', 'histogram', columns, histogram_data, size(histogram_data(1,:)), ncols, num) - - deallocate(histogram_data) - - case(18) - call J_E_plane(num,npart,particlemass,xyzh,vxyzu) - end select - !increase dump number counter - dump_number = dump_number + 1 - -end subroutine do_analysis - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!!!!! Analysis routines !!!!! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - -subroutine total_dust_mass(time,npart,particlemass,xyzh) - use part, only:nucleation,idK3,idK0,idK1, idJstar - use dust_formation, only:set_abundances, mass_per_H - use physcon, only:atomic_mass_unit - real, intent(in) :: time,particlemass,xyzh(:,:) - integer, intent(in) :: npart - integer :: i,ncols,j - real, dimension(2) :: dust_mass - character(len=17), allocatable :: columns(:) - real, allocatable :: temp(:) !npart - real :: median,mass_factor,grain_size - real, parameter :: a0 = 1.28e-4 !radius of a carbon atom in micron - - call set_abundances !initialize mass_per_H - dust_mass = 0. - ncols = 2 - print *,'size(nucleation,1) = ',size(nucleation,1) - print *,'size(nucleation,2) = ',size(nucleation,2) - allocate(columns(ncols),temp(npart)) - columns = (/'Dust mass [Msun]', & - 'median size [um]'/) - j=0 - mass_factor = 12.*atomic_mass_unit*particlemass/mass_per_H - do i = 1,npart - if (.not. isdead_or_accreted(xyzh(4,i))) then - dust_mass(1) = dust_mass(1) + nucleation(idK3,i) *mass_factor - grain_size = a0*nucleation(idK1,i)/(nucleation(idK0,i)+1.0E-99) !in micron - if (grain_size > a0) then - j = j+1 - temp(j) = grain_size - endif - endif - enddo - - call sort(temp,j) - if (mod(j,2)==0) then !npart - median = (temp(j/2)+temp(j/2+1))/2.0 !(temp(npart/2)+temp(npart/2+1))/2.0 - else - median = (temp(j/2)+temp(j/2+1))/2.0 !temp(npart/2+1) - endif - - dust_mass(2) = median - - call write_time_file('total_dust_mass_vs_time', columns, time, dust_mass, ncols, dump_number) - !after execution of the analysis routine, a file named "total_dust_mass_vs_time.ev" appears - deallocate(columns,temp) - -end subroutine total_dust_mass - -! -------------------------------------------------------------------- -! integer function FindMinimum(): -! This function returns the location of the minimum in the section -! between Start and End. -! -------------------------------------------------------------------- - -integer function FindMinimum(x, Start, Fin) - implicit none - integer, intent(in) :: start, fin - real, dimension(Fin), intent(in) :: x - real :: minimum - integer :: location - integer :: i - - minimum = x(start) ! assume the first is the min - location = start ! record its position - do i = start+1, fin ! start with next elements - if (x(i) < minimum) then ! if x(i) less than the min? - minimum = x(i) ! yes, a new minimum found - location = i ! record its position - endif - enddo - findminimum = location ! return the position -end function FindMinimum - -! -------------------------------------------------------------------- -! subroutine Sort(): -! This subroutine receives an array x() and sorts it into ascending -! order. -! -------------------------------------------------------------------- - -subroutine Sort(x, longitud) - implicit none - integer, intent(in) :: longitud - real, dimension(longitud), intent(inout) :: x - integer :: i - integer :: location - - do i = 1, longitud-1 ! except for the last - location = findminimum(x, i, longitud) ! find min from this to last - call swap(x(i), x(location)) ! swap this and the minimum - enddo -end subroutine Sort - - -!---------------------------------------------------------------- -!+ -! Separation vs. time -!+ -!---------------------------------------------------------------- -subroutine separation_vs_time(time) - real, intent(in) :: time - character(len=17), allocatable :: columns(:) - real :: sink_separation(4,nptmass-1) - integer :: i,ncols - ncols = 4*(nptmass-1) - allocate(columns(ncols)) - - do i=1,(nptmass-1) - call separation_vector(xyzmh_ptmass(1:3,1),xyzmh_ptmass(1:3,i+1),sink_separation(1:4,i)) - - write(columns((i*4)-3), '(A11,I1)') ' x sep. ', i - write(columns((i*4)-2), '(A11,I1)') ' y sep. ', i - write(columns((i*4)-1), '(A11,I1)') ' z sep. ', i - write(columns((i*4)), '(A11,I1)') ' sep. ', i - enddo - - call write_time_file('separation_vs_time', columns, time, sink_separation, ncols, dump_number) - deallocate(columns) -end subroutine separation_vs_time - - -!---------------------------------------------------------------- -!+ -! Output planet position (x,y,z,r) and velocity (vx,vy,vz,|v|) -! relative to core, instantaneous mass according to different -! criteria (m1,m2,m3,m4,m5), max. density, and min. entropy -! -! For small dumps, only (x,y,z,r) and rhomax may be determined. -! All other quantities will be outputted as zero. -!+ -!---------------------------------------------------------------- -subroutine planet_rvm(time,particlemass,xyzh,vxyzu) - use eos, only:entropy - 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, allocatable :: data_cols(:),mass(:),vthreshold(:) - integer :: i,j,ncols,maxrho_ID,ientropy,Nmasks - integer, save :: nplanet - integer, allocatable, save :: planetIDs(:) - logical :: isfulldump - - if (.not. done_init_eos) call fatal("planet_rvm","EOS has not been initialised.") - - ncols = 15 - allocate(data_cols(ncols),columns(ncols)) - columns = (/' x sep', & - ' y sep', & - ' z sep', & - ' sep', & - ' vx', & - ' vy', & - ' vz', & - ' v', & - ' m1', & - ' m2', & - ' m3', & - ' m4', & - ' m5', & - ' rhomax', & - ' smin'/) - - if (dump_number == 0) call get_planetIDs(nplanet,planetIDs) - isfulldump = (vxyzu(4,1) > 0.) - - ! Find highest density and lowest entropy in planet - rhoprev = 0. - maxrho_ID = 1 - smin = huge(0.) - ientropy = 1 - ieos = 2 - gamma = 5./3. - do i = 1,nplanet - rhoi = rhoh(xyzh(4,planetIDs(i)), particlemass) - if (rhoi > rhoprev) then - maxrho_ID = planetIDs(i) - rhoprev = rhoi - endif - - if (isfulldump) then - presi = (gamma-1.)*vxyzu(4,i) - si = entropy(rhoi*unit_density,presi*unit_pressure,gmw,ientropy) - smin = min(smin,si) - endif - enddo - - planet_com = xyzh(1:3,maxrho_ID) - sep = planet_com - xyzmh_ptmass(1:3,1) - - if (isfulldump) then - planet_vel = vxyzu(1:3,maxrho_ID) - vel = planet_vel - vxyz_ptmass(1:3,1) - else - vel = 0. - smin = 0. - endif - - ! Sum planet mass according to criterion - Nmasks = 5 ! Number of velocity thresholds for calculating planet mass - allocate(mass(Nmasks),vthreshold(Nmasks)) - mass = 0. - if (isfulldump) then - Rthreshold = 0.21 ! Radius criterion to be considered part of planet - vthreshold = (/0.1,0.3,0.5,0.7,0.9/) ! Allowed fractional deviation in particle velocity from velocity of densest planet particle - do i = 1,nplanet - sepi = separation(xyzh(1:3,planetIDs(i)), planet_com) - do j = 1,Nmasks - if ( (sepi < Rthreshold) .and. (abs(1. - dot_product(vxyzu(1:3,planetIDs(i)),planet_vel)/& - dot_product(planet_vel,planet_vel)) < vthreshold(j)) ) then ! vi dot vp / vp^2 > threshold - mass(j:Nmasks) = mass(j:Nmasks) + 1. - exit - endif - enddo - enddo - mass = mass * particlemass - endif - - data_cols = (/ sep(1), sep(2), sep(3), distance(planet_com),& - vel(1), vel(2), vel(3), distance(vel),& - mass(1), mass(2), mass(3), mass(4), mass(5), rhoprev, smin /) - call write_time_file('planet_rvm', columns, time, data_cols, ncols, dump_number) - - deallocate(data_cols,columns,mass,vthreshold) - -end subroutine planet_rvm - - -!---------------------------------------------------------------- -!+ -! Output radial distribution of planetary material -!+ -!---------------------------------------------------------------- -subroutine planet_mass_distribution(time,num,npart,xyzh) - integer, intent(in) :: npart,num - real, intent(in) :: time - real, intent(inout) :: xyzh(:,:) - real, allocatable :: rad_part(:),dist_part(:),hist_var(:) - real :: mina,maxa,xyz_origin(3) - character(len=17) :: filename - character(len=100) :: data_formatter,headerline - integer :: i,iu,nbins - integer, save :: nplanet - integer, allocatable, save :: planetIDs(:) - - if (dump_number == 0) call get_planetIDs(nplanet,planetIDs) - - nbins = 1000 ! Radial bins - mina = 0. - maxa = 4.2 - - allocate(rad_part(nplanet),dist_part(nplanet),hist_var(nbins)) - filename = ' planet_m_dist.ev' - xyz_origin = xyzmh_ptmass(1:3,1) - - dist_part = 0. - rad_part = 0. - do i = 1,nplanet - rad_part(i) = separation(xyzh(1:3,planetIDs(i)),xyz_origin) - dist_part(i) = 1. - enddo - - call histogram_setup(rad_part,dist_part,hist_var,nplanet,maxa,mina,nbins,.false.,.false.) - - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - if (num == 0) then - open(newunit=iu, file=trim(adjustl(filename)), status='replace') - write(headerline, "(a,i5,a,f5.2,a,f5.2)") "# Planet mass distribution, nbins = ", nbins,", min a = ", mina, ", max a = ", maxa - write(iu, "(a)") headerline - close(unit=iu) - endif - open(newunit=iu, file=trim(adjustl(filename)), position='append') - write(iu,data_formatter) time,hist_var(:) - close(unit=iu) - - deallocate(rad_part,dist_part,hist_var) - -end subroutine planet_mass_distribution - - -!---------------------------------------------------------------- -!+ -! Companion mass coordinate (spherical mass shells) vs. time -!+ -!---------------------------------------------------------------- -subroutine m_vs_t(time,npart,particlemass,xyzh) - integer, intent(in) :: npart - real, intent(in) :: time,particlemass,xyzh(:,:) - character(len=17) :: colname - real :: sinksinksep,mass(1) - integer :: i,k - integer, allocatable :: iorder(:) - - allocate(iorder(npart)) - - call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) ! Order particles by distance from core - call indexxfunc(npart,r2func_origin,xyzh,iorder) - - sinksinksep = separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) - do i=1,npart - k = iorder(i) - if (separation(xyzh(1:3,k), xyzmh_ptmass(1:3,1)) > sinksinksep) exit - enddo - - mass = i*particlemass + xyzmh_ptmass(4,1) - write(colname, '(A11)') ' mass coord' - call write_time_file(' m_vs_t',colname,time,mass,1,dump_number) - - deallocate(iorder) - -end subroutine m_vs_t - - -!---------------------------------------------------------------- -!+ -! Bound mass -!+ -!---------------------------------------------------------------- -subroutine bound_mass(time,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use ptmass, only:get_accel_sink_gas - use ionization_mod, only:calc_thermal_energy - 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 :: E_H2,E_HI,E_HeI,E_HeII - real, save :: Xfrac,Yfrac,Zfrac - real :: rhopart,ponrhoi,spsoundi,tempi,dum1,dum2,dum3 - real, dimension(3) :: rcrossmv - real, dimension(28) :: bound - integer :: i,bound_i,ncols - integer, parameter :: ib=1,ibt=9,ibe=17 - character(len=17), allocatable :: columns(:) - - if (.not. done_init_eos) call fatal("bound_mass","EOS has not been initialised.") - - ncols = 28 - bound = 0. - allocate(columns(ncols)) - columns = (/' b num part', & ! Total bound number of particles - ' b mass', & ! Total bound gas mass - ' b ang mom', & ! Total bound gas angular momentum wrt CoM of entire system - ' b tot en', & ! Total bound energy of gas - ' ub num part', & - ' ub mass', & - ' ub ang mom', & - ' ub tot en', & - ' bt num part', & ! As in comments above, but including thermal energy in criterion - ' bt mass', & - ' bt ang mom', & - ' bt tot en', & - 'ubt num part', & - ' ubt mass', & - ' ubt ang mom', & - ' ubt tot en', & - ' be num part', & - ' be mass', & - ' be ang mom', & - ' be tot en', & - 'ube num part', & - ' ube mass', & - ' ube ang mom', & - ' ube tot en', & - ' HeII bm', & ! Bound mass including recombination energy of HeII - ' HeII+HeI bm', & ! Bound mass including recombination energy of HeII, HeI - ' He+HI bm', & ! Bound mass including recombination energy of HeII, HeI, HI - ' He+HI+H2 bm'/) ! Bound mass including recombination energy of HeII, HeI, HI, H2 - - Zfrac = 0. - if (dump_number == 0) then - if (ieos /= 10 .and. ieos /= 20) then ! For MESA EoS, just use X_in and Z_in from eos module - Xfrac = 0.69843 - Zfrac = 0.01426 - call prompt('Enter hydrogen mass fraction to assume for recombination:',Xfrac,0.,1.) - call prompt('Enter metallicity to assume for recombination:',Zfrac,0.,1.) - else - Xfrac = X_in - Zfrac = Z_in - endif - Yfrac = 1. - Xfrac - Zfrac - endif - - ! Ionisation energies per particle (in code units) - E_H2 = 0.5*Xfrac*0.0022866 * particlemass - E_HI = Xfrac*0.0068808 * particlemass - E_HeI = 0.25*Yfrac*0.012442 * particlemass - E_HeII = 0.25*Yfrac*0.027536 * particlemass - - do i = 1,npart - if (.not. isdead_or_accreted(xyzh(4,i))) then - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,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) - 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. - rcrossmv = (/ 0., 0., 0. /) - endif - - ! Bound criterion - if ((epoti + ekini < 0.) .or. isdead_or_accreted(xyzh(4,i))) then - bound_i = ib - else - bound_i = ib + 4 ! Unbound - endif - - bound(bound_i) = bound(bound_i) + 1 - bound(bound_i + 1) = bound(bound_i + 1) + particlemass - bound(bound_i + 2) = bound(bound_i + 2) + distance(rcrossmv) - bound(bound_i + 3) = bound(bound_i + 3) + etoti - - ! Bound criterion INCLUDING thermal energy - if ((epoti + ekini + ethi < 0.) .or. isdead_or_accreted(xyzh(4,i))) then - bound_i = ibt - else - bound_i = ibt + 4 - endif - - bound(bound_i) = bound(bound_i) + 1 - bound(bound_i + 1) = bound(bound_i + 1) + particlemass - bound(bound_i + 2) = bound(bound_i + 2) + distance(rcrossmv) - bound(bound_i + 3) = bound(bound_i + 3) + etoti - - ! Bound criterion using enthalpy - if ((epoti + ekini + ethi + ponrhoi*particlemass < 0.) .or. isdead_or_accreted(xyzh(4,i))) then - bound_i = ibe - else - bound_i = ibe + 4 - endif - - bound(bound_i) = bound(bound_i) + 1 - bound(bound_i + 1) = bound(bound_i + 1) + particlemass - bound(bound_i + 2) = bound(bound_i + 2) + distance(rcrossmv) - bound(bound_i + 3) = bound(bound_i + 3) + etoti - - ! Bound criterion including HeI + HeII ionisation energy - if ((epoti + ekini + ethi + E_HeII < 0.) .or. isdead_or_accreted(xyzh(4,i))) then - bound(25) = bound(25) + particlemass - endif - - ! Bound criterion including HeI + HeII ionisation energy - if ((epoti + ekini + ethi + E_HeII + E_HeI < 0.) .or. isdead_or_accreted(xyzh(4,i))) then - bound(26) = bound(26) + particlemass - endif - - ! Bound criterion including HeI + HeII + HI ionisation energy - if ((epoti + ekini + ethi + E_HeII + E_HeI + E_HI < 0.) .or. isdead_or_accreted(xyzh(4,i))) then - bound(27) = bound(27) + particlemass - endif - - ! Bound criterion including HeI + HeII + HI + H2 ionisation energy - if ((epoti + ekini + ethi + E_HeII + E_HeI + E_HI + E_H2 < 0.) .or. isdead_or_accreted(xyzh(4,i))) then - bound(28) = bound(28) + particlemass - endif - enddo - - call write_time_file('boundunbound_vs_time', columns, time, bound, ncols, dump_number) - deallocate(columns) - -end subroutine bound_mass - - -!---------------------------------------------------------------- -!+ -! Calculate energies -!+ -!---------------------------------------------------------------- -subroutine calculate_energies(time,npart,particlemass,xyzh,vxyzu) - use vectorutils, only:cross_product3D - 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 :: rhopart,ponrhoi,spsoundi,tempi,r_ij,radvel - real, dimension(3) :: rcrossmv - character(len=17), allocatable :: columns(:) - integer :: i, j, ncols - logical :: inearsink - integer, parameter :: ie_tot = 1 - integer, parameter :: ie_pot = ie_tot + 1 - integer, parameter :: ie_kin = ie_pot + 1 - integer, parameter :: ie_therm = ie_kin + 1 - integer, parameter :: ipot_sink = ie_therm + 1 - integer, parameter :: ikin_sink = ipot_sink + 1 - integer, parameter :: iorb_sink = ikin_sink + 1 - integer, parameter :: iorb_comp = iorb_sink + 1 - integer, parameter :: ipot_env = iorb_comp + 1 - integer, parameter :: ie_env = ipot_env + 1 - integer, parameter :: ikin_bound = ie_env + 1 - integer, parameter :: ikin_unbound = ikin_bound + 1 - integer, parameter :: imass_bound = ikin_unbound + 1 - integer, parameter :: imass_unbound = imass_bound + 1 - integer, parameter :: ipot_pp = imass_unbound + 1 - integer, parameter :: ipot_ps = ipot_pp + 1 - integer, parameter :: ijz_tot = ipot_ps + 1 - integer, parameter :: ijz_bound = ijz_tot + 1 - integer, parameter :: ijz_unbound = ijz_bound + 1 - integer, parameter :: ijz_orb = ijz_unbound + 1 - integer, parameter :: ie_gas = ijz_orb + 1 - integer, parameter :: fallbackmass = ie_gas + 1 - integer, parameter :: fallbackmom = fallbackmass + 1 - real, dimension(fallbackmom) :: encomp - - ncols = 23 - allocate(columns(ncols)) - columns = (/'total energy',& - ' pot energy',& - ' kin energy',& - 'therm energy',& - ' sink pot',& - ' sink kin',& - ' sink orb',& - ' comp orb',& - ' env pot',& - ' env energy',& - ' bound kin',& - ' unbound kin',& - ' bound mass',& - 'unbound mass',& - ' p-p pot',& - ' p-s pot',& - ' tot ang mom',& - ' b ang mom',& - ' ub ang mom',& - ' orb ang mom',& - ' gas energy',& - ' fallback',& - 'fallback mom'/) - - encomp(5:) = 0. - call compute_energies(time) - ekin = 0. - - do i=1,npart - encomp(ipot_pp) = encomp(ipot_pp) + poten(i) ! poten already includes factor of 1/2 to correct for double counting - encomp(ipot_env) = encomp(ipot_env) + poten(i) - - call cross_product3D(xyzh(1:3,i), particlemass * vxyzu(1:3,i), rcrossmv) - jz = rcrossmv(3) - encomp(ijz_tot) = encomp(ijz_tot) + jz - - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) - - encomp(ipot_ps) = encomp(ipot_ps) + particlemass * phii - - phii1 = 0. - call get_accel_sink_gas(1,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass,fxi,fyi,fzi,phii1) - encomp(ipot_env) = encomp(ipot_env) + phii1 * particlemass - - do j=1,nptmass - if (xyzmh_ptmass(4,j) > 0.) then - r_ij = separation(xyzmh_ptmass(1:3,j),xyzh(1:3,i)) - if (r_ij < 80.) then - inearsink = .true. - endif - endif - enddo - - 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 (etoti < 0) then - encomp(ikin_bound) = encomp(ikin_bound) + ekini - encomp(imass_bound) = encomp(imass_bound) + particlemass - encomp(ijz_bound) = encomp(ijz_bound) + jz - radvel = dot_product(vxyzu(1:3,i),xyzh(1:3,i)) / distance(xyzh(1:3,i)) - - if (inearsink .eqv. .false.) then - if (radvel < 0.) then - encomp(fallbackmass) = encomp(fallbackmass) + particlemass - encomp(fallbackmom) = encomp(fallbackmom) + particlemass * radvel - endif - endif - - else - encomp(ikin_unbound) = encomp(ikin_unbound) + ekini - encomp(imass_unbound) = encomp(imass_unbound) + particlemass - encomp(ijz_unbound) = encomp(ijz_unbound) + jz - endif - enddo - - do i=1,nptmass - if (xyzmh_ptmass(4,i) > 0.) then - call cross_product3D(xyzmh_ptmass(1:3,i), xyzmh_ptmass(4,i)*vxyz_ptmass(1:3,i), rcrossmv) - jz = rcrossmv(3) - encomp(ijz_tot) = jz + encomp(ijz_tot) - encomp(ijz_orb) = jz + encomp(ijz_orb) - encomp(ikin_sink) = encomp(ikin_sink) + 0.5 * xyzmh_ptmass(4,i) * distance(vxyz_ptmass(1:3,i))**2 - if (i==2) encomp(iorb_comp) = encomp(iorb_comp) + 0.5 * xyzmh_ptmass(4,i) * distance(vxyz_ptmass(1:3,i))**2 - endif - enddo - - do i=1,nptmass-1 - if (xyzmh_ptmass(4,i) > 0.) then - do j=i+1,nptmass - if (xyzmh_ptmass(4,j) > 0.) then - r_ij = separation(xyzmh_ptmass(1:3,i),xyzmh_ptmass(1:3,j)) - encomp(ipot_sink) = encomp(ipot_sink) - xyzmh_ptmass(4,i) * xyzmh_ptmass(4,j) / r_ij - if (i==1 .and. j==2) encomp(iorb_comp) = encomp(iorb_comp) - xyzmh_ptmass(4,i) * xyzmh_ptmass(4,j) / r_ij - endif - enddo - endif - enddo - - ekin = encomp(ikin_bound) + encomp(ikin_unbound) + encomp(ikin_sink) - encomp(iorb_sink) = encomp(ipot_sink) + encomp(ikin_sink) - encomp(ie_env) = encomp(ipot_env) + etherm + encomp(ikin_bound) - epot = encomp(ipot_pp) + encomp(ipot_ps) + encomp(ipot_sink) - etot = epot + ekin + etherm - encomp(ie_gas) = encomp(ikin_bound) + encomp(ikin_unbound) + encomp(ipot_ps) - - encomp(ie_tot) = etot - encomp(ie_pot) = epot - encomp(ie_kin) = ekin - encomp(ie_therm) = etherm - - call write_time_file('energy', columns, time, encomp, ncols, dump_number) - deallocate(columns) - -end subroutine calculate_energies - - -!!!!! Create profile !!!!! -subroutine create_profile(time, num, npart, particlemass, xyzh, vxyzu) - integer, intent(in) :: npart, num - real, intent(in) :: time, particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - real, save :: profile_vector(3) - integer :: ncols - character(len=15) :: name_in - real, allocatable :: profile(:,:) - - if (dump_number == 0) then - profile_vector=(/1.,0.,0./) - call prompt('Would you like simple profiles?', switch(1), .true.) - call prompt('Choose profile vector x-component ',profile_vector(1)) - call prompt('Choose profile vector y-component ',profile_vector(2)) - call prompt('Choose profile vector z-component ',profile_vector(3)) - endif - - if (switch(1)) then - ncols = 8 - else - ncols = 18 - endif - - if (all(profile_vector <= tiny(profile_vector))) then - write(*,*)'Using all particles!' - call stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,switch(1)) - write(name_in, "(a)") 'part_profile' - else - write(*,*)'Profile_vector is:',profile_vector - call stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,switch(1),profile_vector) - write(name_in, "(a,i1,i1,i1)") 'ray_profile_',int(profile_vector(1:3)) - endif - - allocate(columns(18)) - columns = (/' radius',& - ' mass coord',& - ' azimuth',& - ' density',& - ' velocity',& - ' rad. vel.',& - ' vxy tan.',& - ' omega',& !Simple creates up to here - ' int. energy',& - ' pressure',& - ' sound speed',& - ' temp',& - ' kappa',& - ' mfp',& - ' energy',& - ' HII frac',& - ' HeII frac',& - ' HeIII frac'/) - - call write_file(name_in, 'profile', columns, profile, size(profile(1,:)), ncols, num) - - deallocate(profile,columns) -end subroutine create_profile - - -!!!!! Roche lobe values !!!!! -subroutine roche_lobe_values(time,npart,particlemass,xyzh,vxyzu) - use vectorutils, only:cross_product3D - integer, intent(in) :: npart - real, intent(in) :: time, particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - integer :: i, j, nFB, nR1T, ncols - integer, parameter :: iRL1 = 1 - integer, parameter :: iMRL1 = 2 - integer, parameter :: iBMRL1 = 3 - integer, parameter :: ijzRL1 = 4 - integer, parameter :: iRL2 = 5 - integer, parameter :: iMRL2 = 6 - integer, parameter :: iBMRL2 = 7 - integer, parameter :: ijzRL2 = 8 - integer, parameter :: iR1 = 9 - integer, parameter :: iR1T = 10 - integer, parameter :: iRej = 11 - integer, parameter :: iMej = 12 - integer, parameter :: iBMej = 13 - integer, parameter :: ijzej = 14 - integer, parameter :: iBjzej = 15 - integer, parameter :: iMF = 16 - integer, parameter :: ijzMF = 17 - integer, parameter :: iDR = 18 - integer, parameter :: iFB = 19 - integer, parameter :: iFBV = 20 - integer, parameter :: iFBJz = 21 - real, dimension(iFBJz) :: MRL - real :: etoti, ekini, einti, epoti, phii, jz - logical, dimension(:), allocatable, save:: transferred - real, save :: m1, m2 - real :: sep, sep1, sep2 - real :: rhovol, rhomass, rhopart, R1, rad_vel, sepCoO - real :: temp_const, ponrhoi, spsoundi, tempi - real, dimension(3) :: rcrossmv, CoO, com_xyz, com_vxyz - real, allocatable :: xyz_a(:,:) - integer :: npart_a, mean_rad_num - integer, allocatable :: iorder(:) - - allocate(iorder(npart),xyz_a(3,npart)) - - MRL = 0. - rhovol = 0. - rhomass = 0. - nFB = 0 - nR1T = 0 - temp_const = (unit_pressure / unit_density) * 1.34 / Rg - - if (dump_number == 0) then - m1 = npart * particlemass + xyzmh_ptmass(4,1) - m2 = xyzmh_ptmass(4,2) - allocate(transferred(npart)) - transferred(1:npart) = .false. - - rho_surface = rhoh(xyzh(4,1), particlemass) - do i=1,npart - rhopart = rhoh(xyzh(4,i), particlemass) - if (rhopart < rho_surface) then - rho_surface = rhopart - endif - enddo - endif - - mean_rad_num = npart / 200 - npart_a = 0 - - do i=1,npart - rhopart = rhoh(xyzh(4,i), particlemass) - if (rhopart > rho_surface) then - if (separation(xyzh(1:3,i), xyzmh_ptmass(1:3,1)) < & - separation(xyzh(1:3,i), xyzmh_ptmass(1:3,2))) then - rhomass = rhomass + particlemass - rhovol = rhovol + particlemass / rhopart - npart_a = npart_a + 1 - xyz_a(1:3,npart_a) = xyzh(1:3,i) - endif - endif - enddo - - call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) - call indexxfunc(npart_a,r2func_origin,xyz_a,iorder) - - R1 = 0 - do i=npart_a-mean_rad_num,npart_a - j = iorder(i) - R1 = R1 + separation(xyz_a(1:3,j),xyzmh_ptmass(1:3,1)) - enddo - - R1 = R1 / real(mean_rad_num) - - sep = separation(xyzmh_ptmass(1:3,1),xyzmh_ptmass(1:3,2)) - MRL(iRL1) = Rochelobe_estimate(m2,m1,sep) - MRL(iRL2) = Rochelobe_estimate(m1,m2,sep) - - !R1 = (3. * rhovol/(4. * pi))**(1./3.) - CoO(1:3) = (xyzmh_ptmass(1:3,1) + xyzmh_ptmass(1:3,2)) / 2. - MRL(iR1) = R1 - MRL(iRej) = separation(CoO(1:3),xyzmh_ptmass(1:3,1)) + R1 - - 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),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) - - sep1 = separation(xyzmh_ptmass(1:3,1),xyzh(1:3,i)) - sep2 = separation(xyzmh_ptmass(1:3,2),xyzh(1:3,i)) - sepCoO = separation(CoO(1:3),xyzh(1:3,i)) - - call cross_product3D(xyzh(1:3,i)-com_xyz(1:3), particlemass * vxyzu(1:3,i), rcrossmv) - jz = rcrossmv(3) - - if (sep1 < MRL(iRL1)) then - MRL(iMRL1) = MRL(iMRL1) + particlemass - MRL(ijzRL1) = MRL(ijzRL1) + jz - if (etoti < 0) then - MRL(iBMRL1) = MRL(iBMRL1) + particlemass - endif - endif - - if (sep2 < MRL(iRL2)) then - MRL(iMRL2) = MRL(iMRL2) + particlemass - MRL(ijzRL2) = MRL(ijzRL2) + jz - - if (transferred(i) .eqv. .false.) then - MRL(iMF) = MRL(iMF) + particlemass - MRL(ijzMF) = MRL(ijzMF) + jz - transferred(i) = .true. - endif - - if (etoti < 0) then - MRL(iBMRL2) = MRL(iBMRL2) + particlemass - endif - endif - - if ((sep1 - xyzh(4,i) < R1) .and. (sep1 + xyzh(4,i) > R1)) then !!!!FIX THIS - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - MRL(iR1T) = MRL(iR1T) + ponrhoi * temp_const - nR1T = nR1T + 1 - endif - - if (sepCoO > MRL(iRej)) then - rad_vel = dot_product(vxyzu(1:3,i),xyzh(1:3,i)) / distance(xyzh(1:3,i)) - - MRL(iMej) = MRL(iMej) + particlemass - MRL(ijzej) = MRL(ijzej) + jz - - if (etoti < 0) then - MRL(iBMej) = MRL(iBMej) + particlemass - MRL(iBjzej) = MRL(iBjzej) + jz - endif - - if (rad_vel < 0) then - MRL(iFB) = MRL(iFB) + particlemass - MRL(iFBV) = MRL(iFBV) + rad_vel - MRL(iFBJz) = MRL(iFBJz) + jz - nFB = nFB + 1 - endif - endif - enddo - - if (nR1T == 0) then - MRL(iR1T) = 0 - else - MRL(iR1T) = MRL(iR1T) / real(nR1T) - endif - - if (nFB == 0) then - MRL(iFBV) = 0 - else - MRL(iFBV) = MRL(iFBV) / real(nFB) - endif - - - - MRL(iMRL1) = MRL(iMRL1) + xyzmh_ptmass(4,1) - MRL(iMRL2) = MRL(iMRL2) + xyzmh_ptmass(4,2) - - MRL(iDR) = (R1 - MRL(iRL1)) / R1 - - call cross_product3D(xyzmh_ptmass(1:3,1) - com_xyz(1:3),xyzmh_ptmass(4,1) * vxyz_ptmass(1:3,1),rcrossmv) - MRL(ijzRL1) = MRL(ijzRL1) + rcrossmv(3) - - call cross_product3D(xyzmh_ptmass(1:3,2) - com_xyz(1:3),xyzmh_ptmass(4,2) * vxyz_ptmass(1:3,2),rcrossmv) - MRL(ijzRL2) = MRL(ijzRL2) + rcrossmv(3) - - m1 = rhomass + xyzmh_ptmass(4,1) - m2 = MRL(iMRL2) - - ncols = 21 - allocate(columns(ncols)) - columns = (/' RL1',& - ' Mass in RL1',& - ' B Mass RL1',& - ' jz in RL1',& - ' RL2',& - ' Mass in RL2',& - ' B Mass RL2',& - ' jz in RL2',& - ' R1',& - ' R1 temp',& - ' R_ejecta',& - 'Mass ejected',& - 'B Mass eject',& - ' jz ejected',& - ' B jz eject',& - ' Mass flow',& - 'Mass flow jz',& - ' R1-RL1/R1',& - ' Fallback',& - 'Fallback vel',& - ' Fallback Jz'/) - - call write_time_file('roche_lobes', columns, time, MRL, ncols, dump_number) - deallocate(columns,iorder) - -end subroutine roche_lobe_values - -!---------------------------------------------------------------- -!+ -! Star stabilisation -!+ -!---------------------------------------------------------------- -subroutine star_stabilisation_suite(time,npart,particlemass,xyzh,vxyzu) - use part, only:fxyzu - use eos, only:equationofstate - integer, intent(in) :: npart - real, intent(in) :: time, particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - integer :: i,j,k,ncols,mean_rad_num,npart_a - 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 - integer, parameter :: ivoleqrad = 1 - integer, parameter :: idensrad = 2 - integer, parameter :: imassout = 3 - integer, parameter :: imassfracout = 4 - integer, parameter :: ipartrad = 5 - integer, parameter :: ipart2hrad = 6 - integer, parameter :: ipdensrad = 7 - integer, parameter :: ip2hdensrad = 8 - integer, parameter :: ivirialpart = 9 - integer, parameter :: ivirialfluid = 10 - - ncols = 10 - allocate(columns(ncols),star_stability(ncols),iorder(npart),iorder_a(npart)) - columns = (/'vol. eq. rad',& - ' density rad',& - 'mass outside',& - 'frac outside',& - ' part rad',& - ' part 2h rad',& - ' p dens rad',& - 'p2h dens rad',& - 'part. virial',& ! Residual of virial theorem for self-gravitating particles - 'fluid virial'/) ! Residual of virial theorem for fluid - - ! Get order of particles by distance from sink particle core - call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) - call indexxfunc(npart,r2func_origin,xyzh,iorder) - - ! Get density of outermost particle in initial star dump - if (dump_number == 0) then - rho_surface = rhoh(xyzh(4,iorder(npart)), particlemass) - endif - - npart_a = 0 - totvol = 0. - rhovol = 0. - virialpart = 0. - totekin = 0. - totepot = 0. - virialintegral= 0. - do i = 1,npart - 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),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) - totekin = totekin + ekini - totepot = totepot + 0.5*epoti ! Factor of 1/2 to correct for double counting - if (rhopart > rho_surface) then - ! Sum "volume" of particles within "surface" of initial star dump - rhovol = rhovol + particlemass / rhopart - npart_a = npart_a + 1 ! Count number of particles within "surface" of initial star dump - endif - ! Calculate residual of Virial theorem for fluid - if (ieos == 2) then - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,gamma_local=gamma) - else - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - endif - virialintegral = virialintegral + 3. * ponrhoi * particlemass - enddo - virialpart = virialpart / (abs(totepot) + 2.*abs(totekin)) ! Normalisation for the virial - virialfluid = (virialintegral + totepot) / (abs(virialintegral) + abs(totepot)) - - ! Sort particles within "surface" by radius - call indexxfunc(npart_a,r2func_origin,xyzh,iorder_a) - - mean_rad_num = npart / 200 ! 0.5 percent of particles - star_stability = 0. - ! Loop over the outermost npart/200 particles that are within the "surface" - do i = npart_a - mean_rad_num,npart_a - j = iorder(i) - k = iorder_a(i) - star_stability(ipartrad) = star_stability(ipartrad) + separation(xyzh(1:3,j),xyzmh_ptmass(1:3,1)) - star_stability(ipart2hrad) = star_stability(ipart2hrad) + separation(xyzh(1:3,j),xyzmh_ptmass(1:3,1)) + xyzh(4,j) - star_stability(ipdensrad) = star_stability(ipdensrad) + separation(xyzh(1:3,k),xyzmh_ptmass(1:3,1)) - star_stability(ip2hdensrad) = star_stability(ip2hdensrad) + separation(xyzh(1:3,k),xyzmh_ptmass(1:3,1)) + xyzh(4,j) - enddo - - star_stability(ipartrad) = star_stability(ipartrad) / real(mean_rad_num) - star_stability(ipart2hrad) = star_stability(ipart2hrad) / real(mean_rad_num) - star_stability(ipdensrad) = star_stability(ipdensrad) / real(mean_rad_num) - star_stability(ip2hdensrad) = star_stability(ip2hdensrad) / real(mean_rad_num) - star_stability(ivoleqrad) = (3. * totvol/(4. * pi))**(1./3.) - star_stability(idensrad) = (3. * rhovol/(4. * pi))**(1./3.) - star_stability(ivirialpart) = virialpart - star_stability(ivirialfluid)= virialfluid - - if (dump_number == 0) then - init_radius = star_stability(ivoleqrad) - endif - - star_stability(imassout) = 0. - total_mass = xyzmh_ptmass(4,1) - do i = 1,npart - if (separation(xyzmh_ptmass(1:3,1),xyzh(1:3,i)) > init_radius) then - star_stability(imassout) = star_stability(imassout) + particlemass - endif - total_mass = total_mass + particlemass - enddo - - star_stability(imassfracout) = star_stability(imassout) / total_mass - call write_time_file('star_stability', columns, time, star_stability, ncols, dump_number) - deallocate(columns,star_stability,iorder,iorder_a) - -end subroutine star_stabilisation_suite - - -!---------------------------------------------------------------- -!+ -! Print simulation parameters -!+ -!---------------------------------------------------------------- -subroutine print_simulation_parameters(npart,particlemass) - integer, intent(in) :: npart - real, intent(in) :: particlemass - integer :: i - - write(*,"(/,3(a,es10.3,1x),a)") ' Mass: ',umass, 'g Length: ',udist, 'cm Time: ',utime,'s' - write(*,"(3(a,es10.3,1x),a)") ' Density: ',unit_density, 'g/cm^3 Energy: ',unit_energ,'erg En/m: ',unit_ergg,'erg/g' - write(*,"(3(a,es10.3,1x),a)") ' Velocity: ',unit_velocity,'cm/s Bfield: ',unit_Bfield,'G Pressure: ',& - unit_pressure,'g/cm s^2' - write(*,"(2(a,es10.3,1x),/)") ' G: ', gg*umass*utime**2/udist**3,' c: ',c*utime/udist - - do i=1,nptmass - if (xyzmh_ptmass(4,i) > 0.) then - write(*,'(A,I2,A,ES10.3,A,ES10.3)') 'Point mass ',i,': M = ',xyzmh_ptmass(4,i),' and h_soft = ',xyzmh_ptmass(ihsoft,i) - endif - enddo - write(*,"(A,ES10.3)") 'Sink-sink separation: ', separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) - - write(*,'(A,I7,A,ES10.3)') 'Gas particles : ',npart,' particles, each of mass ',particlemass - -end subroutine print_simulation_parameters - - -!---------------------------------------------------------------- -!+ -! Write quantities (up to four) to divv file -!+ -!---------------------------------------------------------------- -subroutine output_divv_files(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:calc_thermal_energy,ionisation_fraction - use dust_formation, only:psat_C,eps,set_abundances,mass_per_H, chemical_equilibrium_light, calc_nucleation!, Scrit - !use dim, only:nElements - 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,& - dum1,dum2,dum3,dum4,dum5 - 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, parameter :: Scrit = 2. ! Critical saturation ratio - logical :: verbose = .false. - - allocate(quant(4,npart)) - Nquantities = 14 - if (dump_number == 0) then - print "(14(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) - endif - - ! 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 - - !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)) - 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 - epsC = eps(3) - nucleation(idK3,i) - if (epsC < 0.) then - print *,'eps(C) =',eps(3),', K3=',nucleation(idK3,i),', epsC=',epsC,', T=',tempi,' rho=',rho_cgs - print *,'JKmuS=',nucleation(:,i) - stop '[S-dust_formation] epsC < 0!' - endif - if (tempi > 450.) then - !call chemical_equilibrium_light to obtain pC, and pC2H2 - call chemical_equilibrium_light(rho_cgs, tempi, epsC, pC, pC2, pC2H, pC2H2, nucleation(idmu,i), nucleation(idgamma,i)) - S = pC/psat_C(tempi) - if (S > Scrit) then - !call nucleation_function to obtain JstarS - call calc_nucleation(tempi, pC, 0., 0., 0., pC2H2, S, JstarS, taustar, taugr) - JstarS = JstarS/ nH_tot - endif - endif - !Check if the variables have meaningful values close to condensation temperatures - if (tempi >= 1400. .and. tempi <= 1500. .and. verbose ) then - print *,'size(nucleation,1) = ',size(nucleation,1) - print *,'size(nucleation,2) = ',size(nucleation,2) - print *,'nucleation(idK3,i) = ',nucleation(idK3,i) - 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),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 - case default - print*,"Error: Requested quantity is invalid." - stop - 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) - enddo - close(iu) - deallocate(quant) - -end subroutine output_divv_files - - - -!!!!! EoS surfaces !!!!! -subroutine eos_surfaces - integer :: i, j, ierr - real :: rho_array(1000) = (/ (10**(i/10000.), i=-180000,-30150,150) /) - real :: eni_array(1000) = (/ (10**(i/10000.), i=120000,149970,30) /) - real :: temp_array(400) = (/ (10**(i/1000.), i=3000,6990,10) /) - real :: kappa_array(1000,400) - real :: gam1_array(1000,1000) - real :: pres_array(1000,1000) - real :: dum(1000,1000) - real :: kappat, kappar - - - do i=1,size(rho_array) - do j=1,size(eni_array) - if (j < size(temp_array) + 1) then - call get_eos_kappa_mesa(rho_array(i),temp_array(j),kappa_array(i,j),kappat,kappar) - endif - call get_eos_pressure_temp_gamma1_mesa(rho_array(i),eni_array(j),pres_array(i,j),dum(i,j),gam1_array(i,j),ierr) - !call get_eos_pressure_temp_mesa(rho_array(i),eni_array(j),pres_array(i,j),temp) - !pres_array(i,j) = eni_array(j)*rho_array(i)*0.66667 / pres_array(i,j) - enddo - enddo - - open(unit=1000, file='mesa_eos_pressure.out', status='replace') - - !Write data to file - do i=1,1000 - write(1000,"(1000(3x,es18.11e2,1x))") pres_array(i,:) - enddo - - close(unit=1000) - - open(unit=1002, file='mesa_eos_gamma.out', status='replace') - - !Write data to file - do i=1,1000 - write(1002,"(1000(3x,es18.11e2,1x))") gam1_array(i,:) - enddo - - close(unit=1002) - - open(unit=1001, file='mesa_eos_kappa.out', status='replace') - - !Write data to file - do i=1,1000 - write(1001,"(400(3x,es18.11e2,1x))") kappa_array(i,:) - enddo - - close(unit=1001) - -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 - use mesa_microphysics, only:getvalue_mesa - use ionization_mod, only:calc_thermal_energy,ionisation_fraction - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer, parameter :: nparttotrack=10,ncols=17 - real :: r,v,rhopart,ponrhoi,Si,spsoundi,tempi,machi,xh0,xh1,xhe0,xhe1,xhe2,& - ekini,einti,epoti,ethi,etoti,dum,phii,pgas,mu - 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 /) - columns = (/ ' r',& - ' v',& - ' rho',& - ' temp',& - 'entropy',& - 'spsound',& - ' mach',& - ' ekin',& - ' epot',& - ' eth',& - ' eint',& - ' etot',& - ' xHI',& - ' xHII',& - ' xHeI',& - ' xHeII',& - ' xHeIII' /) - - call compute_energies(time) - - do i=1,nparttotrack - write (filenames(i),"(a1,i7.7)") "p", partID(i) - enddo - - do k=1,nparttotrack - i = partID(k) - 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) - 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 - 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 - 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) - 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),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) - - ! Write file - datatable = (/ r,v,rhopart,eos_vars(itemp,i),Si,spsoundi,machi,ekini,epoti,ethi,einti,etoti,xh0,xh1,xhe0,xhe1,xhe2 /) - call write_time_file(trim(adjustl(filenames(k))),columns,time,datatable,ncols,dump_number) - enddo - -end subroutine track_particle - - -!---------------------------------------------------------------- -!+ -! Optical depth profile -!+ -!---------------------------------------------------------------- -subroutine tau_profile(time,num,npart,particlemass,xyzh) - use part, only:eos_vars,itemp - integer, intent(in) :: npart,num - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:) - integer :: nbins - real, allocatable :: rad_part(:),kappa_part(:),rho_part(:) - real, allocatable :: kappa_hist(:),rho_hist(:),tau_r(:),sepbins(:) - real :: maxloga,minloga,kappa,kappat,kappar - character(len=17) :: filename - character(len=40) :: data_formatter - integer :: i,unitnum - - call compute_energies(time) - nbins = 500 - - allocate(rad_part(npart),kappa_part(npart),rho_part(npart)) - rad_part = 0. - kappa_part = 0. - rho_part = 0. - minloga = 0.5 - maxloga = 4.3 - - allocate(rho_hist(nbins),kappa_hist(nbins),sepbins(nbins),tau_r(nbins)) - filename = ' grid_tau.ev' - - do i=1,npart - rho_part(i) = rhoh(xyzh(4,i), particlemass) - rad_part(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - call get_eos_kappa_mesa(rho_part(i)*unit_density,eos_vars(itemp,i),kappa,kappat,kappar) - kappa_part(i) = kappa ! In cgs units? - enddo - - call histogram_setup(rad_part(1:npart),kappa_part,kappa_hist,npart,maxloga,minloga,nbins,.true.,.true.) - call histogram_setup(rad_part(1:npart),rho_part,rho_hist,npart,maxloga,minloga,nbins,.true.,.true.) - - - ! Integrate optical depth inwards - sepbins = (/ (10**(minloga + (i-1) * (maxloga-minloga)/real(nbins)), i=1,nbins) /) ! Create log-uniform bins - ! Convert to cgs units (kappa has already been outputted in cgs) - rho_hist = rho_hist * unit_density - sepbins = sepbins * udist ! udist should be Rsun in cm - - tau_r(nbins) = 0. - do i=nbins,2,-1 - tau_r(i-1) = tau_r(i) + kappa_hist(i) * rho_hist(i) * (sepbins(i+1) - sepbins(i)) - enddo - - ! Write data row - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - if (num == 0) then - unitnum = 1000 - open(unit=unitnum, file=trim(adjustl(filename)), status='replace') - write(unitnum, "(a)") '# Optical depth profile' - close(unit=unitnum) - endif - unitnum=1002 - open(unit=unitnum, file=trim(adjustl(filename)), position='append') - write(unitnum,data_formatter) time,tau_r - close(unit=unitnum) - deallocate(rad_part,kappa_part,rho_part) - deallocate(rho_hist,kappa_hist,sepbins,tau_r) - -end subroutine tau_profile - -!---------------------------------------------------------------- -!+ -! Sound crossing time profile -!+ -!---------------------------------------------------------------- -subroutine tconv_profile(time,num,npart,particlemass,xyzh,vxyzu) - use part, only:itemp - use eos, only:get_spsound - use units, only:unit_velocity - integer, intent(in) :: npart,num - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer :: nbins - real, allocatable :: rad_part(:),cs_part(:) - real, allocatable :: cs_hist(:),tconv(:),sepbins(:) - real :: maxloga,minloga,rhoi - character(len=17) :: filename - character(len=40) :: data_formatter - integer :: i,unitnum - - call compute_energies(time) - nbins = 500 - allocate(rad_part(npart),cs_part(npart)) - rad_part = 0. - cs_part = 0. - minloga = 0.5 - maxloga = 4.3 - - allocate(cs_hist(nbins),sepbins(nbins),tconv(nbins)) - filename = ' grid_tconv.ev' - - do i=1,npart - rhoi = rhoh(xyzh(4,i), particlemass) - rad_part(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - cs_part(i) = get_spsound(eos_type=ieos,xyzi=xyzh(:,i),rhoi=rhoi,vxyzui=vxyzu(:,i),gammai=gamma,mui=gmw,Xi=X_in,Zi=Z_in) - enddo - - call histogram_setup(rad_part(1:npart),cs_part,cs_hist,npart,maxloga,minloga,nbins,.true.,.true.) - - ! Integrate sound-crossing time from surface inwards - sepbins = (/ (10**(minloga + (i-1) * (maxloga-minloga)/real(nbins)), i=1,nbins) /) ! Create log-uniform bins - ! Convert to cgs units - cs_hist = cs_hist * unit_velocity - sepbins = sepbins * udist ! udist should be Rsun in cm - - tconv(nbins) = 0. - do i=nbins,2,-1 - if (cs_hist(i) < tiny(1.)) then - tconv(i-1) = tconv(i) - else - tconv(i-1) = tconv(i) + (sepbins(i+1) - sepbins(i)) / cs_hist(i) - endif - enddo - - ! Write data row - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - if (num == 0) then - unitnum = 1000 - open(unit=unitnum, file=trim(adjustl(filename)), status='replace') - write(unitnum, "(a)") '# Sound crossing time profile' - close(unit=unitnum) - endif - unitnum=1002 - open(unit=unitnum, file=trim(adjustl(filename)), position='append') - write(unitnum,data_formatter) time,tconv - close(unit=unitnum) - - deallocate(rad_part,cs_part) - -end subroutine tconv_profile - - -!---------------------------------------------------------------- -!+ -! Histogram of optical depth at hydrogen recombination -!+ -!---------------------------------------------------------------- -subroutine recombination_tau(time,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use ionization_mod, only:calc_thermal_energy,ionisation_fraction - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer :: nbins - integer, allocatable :: recombined_pid(:) - real, allocatable :: rad_part(:),kappa_part(:),rho_part(:) - real, allocatable, save:: tau_recombined(:) - 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 - real, parameter :: recomb_th=0.9 - integer :: i,j,nrecombined,bin_ind - - call compute_energies(time) - allocate(rad_part(npart),kappa_part(npart),rho_part(npart),recombined_pid(npart)) - rad_part = 0. - kappa_part = 0. - rho_part = 0. - nbins = 300 ! Number of radial bins - minloga = 0.5 - maxloga = 4.3 - allocate(rho_hist(nbins),kappa_hist(nbins),sepbins(nbins),sepbins_cm(nbins),tau_r(nbins)) - if (dump_number == 0) then - allocate(tau_recombined(npart),prev_recombined(npart)) - tau_recombined = -1. ! Store tau of newly-recombined particles. -ve data means particle never recombined] - prev_recombined = .false. ! All hydrogen is ionised at the start - endif - - j=0 - do i=1,npart - rho_part(i) = rhoh(xyzh(4,i), particlemass) - rad_part(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - call equationofstate(ieos,ponrhoi,spsoundi,rho_part(i),xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - 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),xyzmh_ptmass,phii,epoti,ekini,einti,dum) ! Calculate total energy - 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 - j=j+1 - recombined_pid(j) = i - prev_recombined(i) = .true. - else - prev_recombined(i) = .false. - endif - enddo - nrecombined = j - - call histogram_setup(rad_part(1:npart),kappa_part,kappa_hist,npart,maxloga,minloga,nbins,.true.,.true.) - call histogram_setup(rad_part(1:npart),rho_part,rho_hist,npart,maxloga,minloga,nbins,.true.,.true.) - - ! Integrate optical depth inwards - sepbins = (/ (10.**(minloga + (i-1) * (maxloga-minloga)/real(nbins)), i=1,nbins) /) ! Create log-uniform bins - - ! Convert to cgs units (kappa has already been outputted in cgs) - rho_hist = rho_hist * unit_density - sepbins_cm = sepbins * udist ! udist should be Rsun in g - - ! Integrate bins in tau(r) - tau_r(nbins) = 0. - do i=nbins,2,-1 - tau_r(i-1) = tau_r(i) + kappa_hist(i) * rho_hist(i) * (sepbins_cm(i+1) - sepbins_cm(i)) - enddo - - ! Integrate optical depth for each newly recombined particle - do j=1,nrecombined - i = recombined_pid(j) - bin_ind = 1 + nint( nbins * ( log10(rad_part(i))-minloga ) / (maxloga-minloga) ) ! Find radial bin of recombined particle - tau_recombined(i) = tau_r(bin_ind) - enddo - ! Trick write_time_file into writing my data table - if (dump_number == 320) then - do i=1,npart - call write_time_file("recombination_tau",(/' tau'/),-1.,tau_recombined(i),1,i-1) ! Set num = i-1 so that header will be written for particle 1 and particle 1 only - enddo - endif - deallocate(recombined_pid,rad_part,kappa_part,rho_part) - -end subroutine recombination_tau - - -!---------------------------------------------------------------- -!+ -! Energy histogram -!+ -!---------------------------------------------------------------- -subroutine energy_hist(time,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use ionization_mod, only:calc_thermal_energy - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: filename(:) - 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, allocatable :: quant(:) - logical :: ilogbins - - nhists = 3 - nbins = 500 - allocate(filename(nhists),coord(npart,nhists),hist(nbins),Emin(nhists),Emax(nhists)) - Emin = (/ -0.0446, 0., 0. /) - Emax = (/ 0.0315, 0.0105, 0.0105 /) - ilogbins = .false. - filename = (/ ' hist_kp.ev', & - ' hist_erec.ev', & - ' hist_eth.ev' /) - - allocate(quant(npart)) - quant = (/ (1., i=1,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),xyzmh_ptmass,phii,epoti,ekini,einti,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 - endif - coord(i,1) = (ekini + epoti)/particlemass - coord(i,2) = vxyzu(4,i) - ethi/particlemass - coord(i,3) = ethi/particlemass - enddo - - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - do i=1,nhists - call histogram_setup(coord(:,i),quant,hist,npart,Emax(i),Emin(i),nbins,.false.,ilogbins) - if (dump_number == 0) then - unitnum = 1000 - open(unit=unitnum, file=trim(adjustl(filename(i))), status='replace') - close(unit=unitnum) - endif - unitnum=1001+i - open(unit=unitnum, file=trim(adjustl(filename(i))), status='old', position='append') - write(unitnum,data_formatter) time,hist - close(unit=unitnum) - enddo - deallocate(filename,coord,hist,Emin,Emax,quant) - -end subroutine energy_hist - - -!---------------------------------------------------------------- -!+ -! Energy profile -!+ -!---------------------------------------------------------------- -subroutine energy_profile(time,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use eos, only:entropy - use mesa_microphysics, only:getvalue_mesa - use ionization_mod, only:calc_thermal_energy,ionisation_fraction - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer :: nbins - real, allocatable :: coord(:) - real, allocatable :: hist(:),quant(:,:) - real :: ekini,einti,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 - integer :: i,k,unitnum,ierr,ientropy,nvars - integer, allocatable :: iorder(:) - integer, save :: iquantity - logical :: ilogbins - logical, save :: use_mass_coord - - if (dump_number==0) then - iquantity = 1 - use_mass_coord = .false. - print "(4(/,a))",'1. Energy',& - '2. Entropy',& - '3. Bernoulli energy',& - '4. Ion fractions' - call prompt("Select quantity to calculate",iquantity,1,4) - call prompt("Bin in mass coordinates instead of radius?",use_mass_coord) - endif - - nbins = 500 - allocate(hist(nbins)) - if (use_mass_coord) then - mincoord = 3.8405 ! Min. mass coordinate - maxcoord = 12.0 ! Max. mass coordinate - ilogbins = .false. - else - mincoord = 0.5 ! Min. log(r) - maxcoord = 4.3 ! Max. log(r) - ilogbins = .true. - endif - - call compute_energies(time) - - ! Allocate arrays for single variable outputs - if ( (iquantity==1) .or. (iquantity==2) .or. (iquantity==3) ) then - nvars = 1 - else - nvars = 5 - endif - allocate(filename(nvars),headerline(nvars),quant(npart,nvars),coord(npart)) - - coord = 0. - quant = 0. - select case (iquantity) - case(1) ! Energy - filename = ' grid_Etot.ev' - headerline = '# Energy profile ' - case(2) ! Entropy - filename = ' grid_entropy.ev' - headerline = '# Entropy profile' - select case(ieos) - case(2) - ientropy = 1 - case(12) - ientropy = 2 - case(10,20) - ientropy = 3 - case default - ientropy = -1 - end select - case(3) ! Bernoulli energy (per unit mass) - filename = 'grid_bernoulli.ev' - headerline = '# Bernoulli prof.' - case(4) ! Ion fraction profiles - filename = (/ ' grid_HI.ev', & - ' grid_HII.ev', & - ' grid_HeI.ev', & - ' grid_HeII.ev', & - ' grid_HeIII.ev' /) - headerline = (/ ' # HI', & - ' # HII', & - ' # HeI', & - ' # HeII', & - ' # HeIII' /) - end select - - allocate(iorder(npart)) - if (use_mass_coord) then - call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) ! Order particles by distance from core - call indexxfunc(npart,r2func_origin,xyzh,iorder) - else - iorder = (/(i, i=1,npart, 1)/) ! Have iorder(k) be same as k - endif - - do k=1,npart - i = iorder(k) ! Loop from innermost to outermost particle - if (use_mass_coord) then - coord(i) = real(k-1) ! Number of particles interior to particle k - else - coord(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) - endif - - 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)) - select case (iquantity) - case(1) ! Energy - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,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) - quant(i,1) = ekini + epoti + ethi - case(2) ! Entropy - if ((ieos==10) .and. (ientropy==2)) 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 - else - mu = gmw - endif - if ((ieos==10) .and. (ientropy==3)) then - quant(i,1) = entropy(rhopart*unit_density,ponrhoi*rhopart*unit_pressure,mu,ientropy,vxyzu(4,i)*unit_ergg,ierr) - else - 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),xyzmh_ptmass,phii,epoti,ekini,einti,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) - quant(i,1) = xh0 - quant(i,2) = xh1 - quant(i,3) = xhe0 - quant(i,4) = xhe1 - quant(i,5) = xhe2 - end select - enddo - - if (use_mass_coord) coord = coord * particlemass + xyzmh_ptmass(4,1) - - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - do i=1,nvars - call histogram_setup(coord,quant(:,i),hist,npart,maxcoord,mincoord,nbins,.true.,ilogbins) - if (dump_number == 0) then - unitnum = 1000 - open(unit=unitnum, file=trim(adjustl(filename(i))), status='replace') - write(unitnum, "(a)") trim(headerline(i)) - close(unit=unitnum) - endif - unitnum=1001+i - open(unit=unitnum, file=trim(adjustl(filename(i))), status='old', position='append') - write(unitnum,data_formatter) time,hist - close(unit=unitnum) - enddo - deallocate(iorder,coord,headerline,filename,quant,hist) - -end subroutine energy_profile - - -!---------------------------------------------------------------- -!+ -! Rotation profiles -!+ -!---------------------------------------------------------------- -subroutine rotation_profile(time,num,npart,xyzh,vxyzu) - use vectorutils, only:cross_product3D - integer, intent(in) :: npart,num - real, intent(in) :: time - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer :: nbins - real, allocatable :: rad_part(:) - real, allocatable :: hist_var(:),dist_part(:,:) - real :: minloga,maxloga,sep_vector(3),vel_vector(3),J_vector(3),xyz_origin(3),vxyz_origin(3),omega,vphi - character(len=17), allocatable :: grid_file(:) - character(len=40) :: data_formatter - integer :: i,unitnum,nfiles,iradius - - nbins = 500 - minloga = 0.5 - maxloga = 4.3 - iradius = 1 ! 1: Bin by cylindrical radius; 2: Bin by spherical radius; 3: Bin by cylindrical radius from CM - - nfiles = 2 - allocate(hist_var(nbins),grid_file(nfiles),dist_part(nfiles,npart),rad_part(npart)) - rad_part = 0. - dist_part = 0. - grid_file = (/ ' grid_omega.ev', & - ' grid_Jz.ev' /) - - select case (iradius) - case(1,2) ! Take donor core as origin - xyz_origin = xyzmh_ptmass(1:3,1) - vxyz_origin = vxyz_ptmass(1:3,1) - case(3) ! Take sink CM as origin - xyz_origin = (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)) - vxyz_origin = (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)) - end select - - do i=1,npart - select case (iradius) - case(1,3) ! Bin by cylindrical radius - rad_part(i) = sqrt( dot_product(xyzh(1:2,i) - xyz_origin(1:2), xyzh(1:2,i) - xyz_origin(1:2)) ) - case(2) ! Bin by spherical radius - rad_part(i) = separation(xyzh(1:3,i),xyz_origin) - end select - - call get_gas_omega(xyz_origin,vxyz_origin,xyzh(1:3,i),vxyzu(1:3,i),vphi,omega) - dist_part(1,i) = vphi - - sep_vector = xyzh(1:3,i) - xyz_origin(1:3) - vel_vector = vxyzu(1:3,i) - vxyz_origin(1:3) - call cross_product3D(vel_vector, sep_vector, J_vector) - dist_part(2,i) = dot_product(J_vector, (/0.,0.,1./)) - enddo - - do i=1,nfiles - call histogram_setup(rad_part(1:npart),dist_part(i,1:npart),hist_var,npart,maxloga,minloga,nbins,.true.,.true.) - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - if (num == 0) then - unitnum = 1000 - open(unit=unitnum, file=trim(adjustl(grid_file(i))), status='replace') - write(unitnum, "(a)") '# z-component of angular velocity' - close(unit=unitnum) - endif - unitnum=1001+i - open(unit=unitnum, file=trim(adjustl(grid_file(i))), position='append') - write(unitnum,data_formatter) time,hist_var(:) - close(unit=unitnum) - enddo - deallocate(hist_var,grid_file,dist_part,rad_part) - -end subroutine rotation_profile - - -!---------------------------------------------------------------- -!+ -! Velocity distribution -!+ -!---------------------------------------------------------------- -subroutine velocity_histogram(time,num,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use ionization_mod, only:calc_thermal_energy - real, intent(in) :: time,particlemass - integer, intent(in) :: npart,num - real, intent(inout) :: 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, 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),xyzmh_ptmass,phii,epoti,ekini,einti,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))) - - if (ekini+epoti > 0.) then - vbound(i) = -1.e15 - vunbound(i) = vr(i) - else - vbound(i) = vr(i) - vunbound(i) = -1.e15 - endif - enddo - - ncols = npart - write(data_formatter, "(a,I6.6,a)") "(", ncols+1, "(2x,es18.11e2))" - file_name1 = "vel_bound.ev" - file_name2 = "vel_unbound.ev" - - if (dump_number == 0) then - open(newunit=iu1, file=file_name1, status='replace') - open(newunit=iu2, file=file_name2, status='replace') - else - open(newunit=iu1, file=file_name1, position='append') - open(newunit=iu2, file=file_name2, position='append') - endif - - write(iu1,data_formatter) time,vbound - write(iu2,data_formatter) time,vunbound - close(unit=iu1) - close(unit=iu2) - - deallocate(vbound,vunbound,vr) - -end subroutine velocity_histogram - - -!---------------------------------------------------------------- -!+ -! Velocity profile -!+ -!---------------------------------------------------------------- -subroutine velocity_profile(time,num,npart,particlemass,xyzh,vxyzu) - real, intent(in) :: time,particlemass - integer, intent(in) :: npart,num - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=40) :: data_formatter - character(len=40) :: file_name - integer :: i,nbins,iu,count - real :: rmin,rmax,xyz_origin(3),vxyz_origin(3),vphi,omega,& - theta1,theta2,tantheta1,tantheta2,tantheta - real, allocatable, dimension(:) :: rad_part,dist_part,hist - - nbins = 500 - rmin = 0. - rmax = 5. - - allocate(hist(nbins),dist_part(npart),rad_part(npart)) - dist_part = 0. - file_name = ' vphi_profile.ev' - - ! Select origin - xyz_origin = xyzmh_ptmass(1:3,1) - vxyz_origin = vxyz_ptmass(1:3,1) - - ! Masking in polar angle - theta1 = 75. ! Polar angle in deg - theta2 = 105. - tantheta1 = tan(theta1*3.14159/180.) - tantheta2 = tan(theta2*3.14159/180.) - - count = 0 - do i = 1,npart - rad_part(i) = sqrt( dot_product(xyzh(1:2,i) - xyz_origin(1:2), xyzh(1:2,i) - xyz_origin(1:2)) ) ! Cylindrical radius - - ! Masking in polar angle - tantheta = rad_part(i)/(xyzh(3,i) - xyzmh_ptmass(3,1)) - if ( (tantheta>0. .and. tanthetatantheta2) ) cycle - - call get_gas_omega(xyz_origin,vxyz_origin,xyzh(1:3,i),vxyzu(1:3,i),vphi,omega) - dist_part(i) = vphi - count = count + 1 - enddo - - call histogram_setup(rad_part,dist_part,hist,count,rmax,rmin,nbins,.true.,.false.) - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - if (num == 0) then - open(newunit=iu, file=trim(adjustl(file_name)), status='replace') - write(iu, "(a)") '# Azimuthal velocity profile' - close(unit=iu) - endif - open(newunit=iu, file=trim(adjustl(file_name)), position='append') - write(iu,data_formatter) time,hist - close(unit=iu) - deallocate(hist,dist_part,rad_part) - -end subroutine velocity_profile - - -!---------------------------------------------------------------- -!+ -! Specific z-angular momentum profile -!+ -!---------------------------------------------------------------- -subroutine angular_momentum_profile(time,num,npart,particlemass,xyzh,vxyzu) - real, intent(in) :: time,particlemass - integer, intent(in) :: npart,num - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=40) :: data_formatter - character(len=40) :: file_name - integer :: i,nbins,iu,count - real :: rmin,rmax,xyz_origin(3),vxyz_origin(3),& - theta1,theta2,tantheta1,tantheta2,tantheta - real, allocatable, dimension(:) :: rad_part,dist_part,hist - - nbins = 500 - rmin = 0. - rmax = 5. - - allocate(hist(nbins),dist_part(npart),rad_part(npart)) - dist_part = 0. - file_name = ' jz_profile.ev' - - ! Select origin - xyz_origin = xyzmh_ptmass(1:3,1) - vxyz_origin = vxyz_ptmass(1:3,1) - - ! Masking in polar angle - theta1 = 75. ! Polar angle in deg - theta2 = 105. - tantheta1 = tan(theta1*3.14159/180.) - tantheta2 = tan(theta2*3.14159/180.) - - count = 0 - do i = 1,npart - rad_part(i) = sqrt( dot_product(xyzh(1:2,i) - xyz_origin(1:2), xyzh(1:2,i) - xyz_origin(1:2)) ) ! Cylindrical radius - - ! Masking in polar angle - tantheta = rad_part(i)/(xyzh(3,i) - xyzmh_ptmass(3,1)) - if ( (tantheta>0. .and. tanthetatantheta2) ) cycle - - dist_part(i) = ( (xyzh(1,i)-xyz_origin(1))*(vxyzu(2,i)-vxyz_origin(2)) - & - (xyzh(2,i)-xyz_origin(2))*(vxyzu(1,i)-vxyz_origin(1)) ) - count = count + 1 - enddo - - call histogram_setup(rad_part,dist_part,hist,count,rmax,rmin,nbins,.true.,.false.) - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - if (num == 0) then - open(newunit=iu, file=trim(adjustl(file_name)), status='replace') - write(iu, "(a)") '# z-angular momentum profile' - close(unit=iu) - endif - open(newunit=iu, file=trim(adjustl(file_name)), position='append') - write(iu,data_formatter) time,hist - close(unit=iu) - -end subroutine angular_momentum_profile - - -!---------------------------------------------------------------- -!+ -! Keplerian velocity profile -!+ -!---------------------------------------------------------------- -subroutine vkep_profile(time,num,npart,particlemass,xyzh,vxyzu) - use sortutils, only:set_r2func_origin,r2func_origin,find_rank - use part, only:iorder=>ll - real, intent(in) :: time,particlemass - integer, intent(in) :: npart,num - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=40) :: data_formatter,file_name - integer :: i,nbins,iu - real :: rmin,rmax,massi,Mtot - real, allocatable :: hist(:),rad_part(:),dist_part(:) - - nbins = 500 - rmin = 0. - rmax = 5. - - allocate(hist(nbins),rad_part(npart),dist_part(npart)) - dist_part = 0. - file_name = ' vkep_profile.ev' - - call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) - call find_rank(npart,r2func_origin,xyzh(1:3,:),iorder) - - Mtot = npart*particlemass - do i = 1,npart - massi = Mtot * real(iorder(i)-1) / real(npart) + xyzmh_ptmass(4,1) - rad_part(i) = separation( xyzh(1:3,i), xyzmh_ptmass(1:3,1) ) - dist_part(i) = sqrt(massi/rad_part(i)) - enddo - - call histogram_setup(rad_part,dist_part,hist,npart,rmax,rmin,nbins,.true.,.false.) - write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" - if (num == 0) then - open(newunit=iu, file=trim(adjustl(file_name)), status='replace') - write(iu, "(a)") '# Keplerian velocity profile' - close(unit=iu) - endif - open(newunit=iu, file=trim(adjustl(file_name)), position='append') - write(iu,data_formatter) time,hist - close(unit=iu) - deallocate(hist,dist_part,rad_part) - -end subroutine vkep_profile - - -!---------------------------------------------------------------- -!+ -! Planet profile -!+ -!---------------------------------------------------------------- -subroutine planet_profile(num,dumpfile,particlemass,xyzh,vxyzu) - character(len=*), intent(in) :: dumpfile - integer, intent(in) :: num - real, intent(in) :: particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=40) :: file_name - integer :: i,maxrho_ID,iu - integer, save :: nplanet - integer, allocatable, save :: planetIDs(:) - real :: rhoprev - real, dimension(3) :: planet_com,planet_vcom,vnorm,ri,Rvec - real, allocatable :: R(:),z(:),rho(:) - - if (dump_number ==0 ) call get_planetIDs(nplanet,planetIDs) - allocate(R(nplanet),z(nplanet),rho(nplanet)) - - ! Find highest density in planet - rhoprev = 0. - maxrho_ID = planetIDs(1) - do i = 1,nplanet - rho(i) = rhoh(xyzh(4,planetIDs(i)), particlemass) - if (rho(i) > rhoprev) then - maxrho_ID = planetIDs(i) - rhoprev = rho(i) - endif - enddo - planet_com = xyzh(1:3,maxrho_ID) - planet_vcom = vxyzu(1:3,maxrho_ID) - vnorm = planet_vcom / sqrt(dot_product(planet_vcom,planet_vcom)) - - ! Write to file - file_name = trim(dumpfile)//".planetpart" - open(newunit=iu, file=file_name, status='replace') - - ! Record R and z cylindrical coordinates w.r.t. planet_com - do i = 1,nplanet - ri = xyzh(1:3,planetIDs(i)) - planet_com ! Particle position w.r.t. planet_com - z(i) = dot_product(ri, vnorm) - Rvec = ri - z(i)*vnorm - R(i) = sqrt(dot_product(Rvec,Rvec)) - ! write(iu,"(es13.6,2x,es13.6,2x,es13.6)") R(i),z(i),rho(i) - write(iu,"(es13.6,2x,es13.6,2x,es13.6,2x,es13.6,2x,es13.6)") xyzh(1,i),xyzh(2,i),xyzh(3,i),rho(i),vxyzu(4,i) - enddo - - close(unit=iu) - deallocate(R,z,rho) - -end subroutine planet_profile - - -!---------------------------------------------------------------- -!+ -! Unbound profiles -!+ -!---------------------------------------------------------------- -subroutine unbound_profiles(time,num,npart,particlemass,xyzh,vxyzu) - use ionization_mod, only:calc_thermal_energy - 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 - - call compute_energies(time) - npart_hist = 0 ! Stores number of particles fulfilling each of the four bound/unbound criterion - nbins = 500 - rad_part = 0. ! (4,npart_hist)-array storing separations of particles - dist_part = 0. - 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' /) - - if (dump_number == 0) then - allocate(prev_bound(2,npart)) - allocate(prev_unbound(2,npart)) - prev_bound = .false. - prev_unbound = .false. - 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),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 - endif - 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,& - .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') - 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') - - write(unitnum,"()") - write(unitnum,data_formatter) time,hist_var(:) - - close(unit=unitnum) - enddo - deallocate(hist_var) - -end subroutine unbound_profiles - - -!---------------------------------------------------------------- -!+ -! Unbound ion fractions: Look at distribution of ion fraction when given particle is unbound -!+ -!---------------------------------------------------------------- -subroutine unbound_ionfrac(time,npart,particlemass,xyzh,vxyzu) - use ionization_mod, only:calc_thermal_energy,get_xion,ionisation_fraction - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17) :: columns(5) - integer :: i - real :: etoti,ekini,einti,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(:,:) - - columns = (/' xion1', & - ' xion2', & - ' xion3', & - ' xion4', & - ' 1-xion3' /) - - if (dump_number == 0) then - allocate(prev_unbound(npart),prev_bound(npart)) - prev_bound = .false. - prev_unbound = .false. - allocate(ionfrac(npart,5)) - ionfrac = -1. ! Initialise ion states to -1 - endif - - call compute_energies(time) - 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),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 - - if ((etoti > 0.) .and. (.not. prev_unbound(i))) then - if (ieos == 10) then ! MESA EoS - call ionisation_fraction(rhopart*unit_density,tempi,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) - elseif (ieos == 20) then ! Gas + radiation + recombination EoS - call get_xion(log10(rhopart*unit_density),tempi,X_in,1.-X_in-Z_in,xion) - xh0 = xion(1) ! H2 ionisation fraction - xh1 = xion(2) ! H ionisation fraction - xhe1 = xion(3) ! He ionisation to He+ fraction - xhe2 = xion(4) ! He+ ionisation to He++ fraction - xhe0 = 1.-xion(3) - else ! Not supported - print*,"Error, not sensible to use unbound_ionfrac when not using MESA EoS (ieos=10) or gas+rad+rec EoS (ieos=20)" - stop - endif - ionfrac(i,1) = xh0 - ionfrac(i,2) = xh1 - ionfrac(i,3) = xhe1 - ionfrac(i,4) = xhe2 - ionfrac(i,5) = xhe0 - prev_unbound(i) = .true. - elseif (etoti < 0.) then - prev_unbound(i) = .false. - endif - enddo - - ! Trick write_time_file into writing my data table - print*,'Dump number is ',dump_number - if (dump_number == 258) then - do i=1,npart - call write_time_file("unbound_ionfrac",columns,-1.,ionfrac(i,1:5),5,i-1) ! Set num = i-1 so that header will be written for particle 1 and particle 1 only - enddo - endif - -end subroutine unbound_ionfrac - - -!---------------------------------------------------------------- -!+ -! Unbound temperature -!+ -!---------------------------------------------------------------- -subroutine unbound_temp(time,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use ionization_mod, only:calc_thermal_energy,get_xion - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17) :: columns(1) - integer :: i,final_count(7) - real :: etoti,ekini,einti,epoti,ethi,phii,dum,rhopart,& - ponrhoi,spsoundi,temp_bins(7) - logical, allocatable, save :: prev_unbound(:),prev_bound(:) - real, allocatable, save :: temp_unbound(:) - - columns = (/' temp'/) - - if (dump_number == 0) then - allocate(prev_unbound(npart),prev_bound(npart),temp_unbound(npart)) - prev_bound = .false. - prev_unbound = .false. - temp_unbound = 0. ! Initialise temperatures to 0. - endif - - 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),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 - - if ((etoti > 0.) .and. (.not. prev_unbound(i))) then - temp_unbound(i) = eos_vars(itemp,i) - prev_unbound(i) = .true. - elseif (etoti < 0.) then - prev_unbound(i) = .false. - endif - enddo - - print*,'dump_number=',dump_number - ! Trick write_time_file into writing my data table - if (dump_number == 167) then - temp_bins = (/ 2.e3, 5.5e3, 8.e3, 1.5e4, 2.e4, 4.e4, 1.e15 /) - final_count = 0 - do i=1,npart - if (temp_unbound(i) > 1.e-15) then - if (temp_unbound(i) < temp_bins(1)) then - final_count(1:7) = final_count(1:7) + 1 - elseif (temp_unbound(i) < temp_bins(2)) then - final_count(2:7) = final_count(2:7) + 1 - elseif (temp_unbound(i) < temp_bins(3)) then - final_count(3:7) = final_count(3:7) + 1 - elseif (temp_unbound(i) < temp_bins(4)) then - final_count(4:7) = final_count(4:7) + 1 - elseif (temp_unbound(i) < temp_bins(5)) then - final_count(5:7) = final_count(5:7) + 1 - elseif (temp_unbound(i) < temp_bins(6)) then - final_count(6:7) = final_count(6:7) + 1 - elseif (temp_unbound(i) < temp_bins(7)) then - final_count(7) = final_count(7) + 1 - endif - endif - call write_time_file("unbound_temp",columns,-1.,temp_unbound(i),1,i-1) ! Set num = i-1 so that header will be written for particle 1 and particle 1 only - enddo - - print*,final_count - endif - -end subroutine unbound_temp - - -!---------------------------------------------------------------- -!+ -! Recombination statistics -!+ -!---------------------------------------------------------------- -subroutine recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use ionization_mod, only:calc_thermal_energy,ionisation_fraction - 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 - character(len=40) :: data_formatter,logical_format - logical, allocatable :: isbound(:) - integer, allocatable :: H_state(:),He_state(:) - integer :: i - real, parameter :: recomb_th=0.05 - - call compute_energies(time) - - allocate(isbound(npart),H_state(npart),He_state(npart)) - do i=1,npart - ! 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),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 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) - - ! Is unbound? - if (etoti > 0.) then - isbound(i) = .false. - else - isbound(i) = .true. - endif - - ! H ionisation state - if (xh0 > recomb_th) then - H_state(i) = 1 - elseif (xh1 > recomb_th) then - H_state(i) = 2 - else - H_state(i) = 0 ! This should not happen - endif - - ! H ionisation state - if (xhe0 > recomb_th) then - He_state(i) = 1 - elseif (xhe1 > recomb_th) then - He_state(i) = 2 - elseif (xhe2 > recomb_th) then - He_state(i) = 3 - else - He_state(i) = 0 ! This should not happen - 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 - - if (num == 0) then ! Write header line - open(unit=1000, file="H_state.ev", status='replace') - write(1000, "(a)") '# Ion fraction statistics' - close(unit=1000) - open(unit=1001, file="He_state.ev", status='replace') - write(1001, "(a)") '# Ion fraction statistics' - close(unit=1001) - open(unit=1002, file="isbound.ev", status='replace') - write(1002, "(a)") '# Ion fraction statistics' - close(unit=1002) - endif - - open(unit=1000, file="H_state.ev", position='append') - 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=1000, file="isbound.ev", position='append') - write(1000,logical_format) time,isbound(:) - close(unit=1000) - - deallocate(isbound,H_state,He_state) - -end subroutine recombination_stats - - -!---------------------------------------------------------------- -!+ -! Sink properties -!+ -!---------------------------------------------------------------- -subroutine sink_properties(time,npart,particlemass,xyzh,vxyzu) - use vectorutils, only:cross_product3D - integer, intent(in) :: npart - real, intent(in) :: time, particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - character(len=17) :: filename - real :: sinkcomp(35) - real :: ang_mom(3) - real :: phitot, dtsinksink, fonrmax - real :: fxi, fyi, fzi, phii - real, dimension(4,maxptmass) :: fssxyz_ptmass - real, dimension(4,maxptmass) :: fxyz_ptmass - real, dimension(3,maxptmass) :: dsdt_ptmass - real, dimension(3) :: com_xyz,com_vxyz - integer :: i,ncols,merge_n,merge_ij(nptmass) - - ncols = 31 - allocate(columns(ncols)) - columns = (/' x', & - ' y', & - ' z', & - ' r', & - ' vx', & - ' vy', & - ' vz', & - ' |v|', & - ' px', & - ' py', & - ' pz', & - ' |p|', & - ' fssx', & - ' fssy', & - ' fssz', & - ' |fss|', & - ' fsx', & - ' fsy', & - ' fsz', & - ' |fs|', & - ' ang mom x', & - ' ang mom y', & - ' ang mom z', & - ' |ang mom|', & - ' kin en', & - ' CoM x ', & - ' CoM y ', & - ' CoM z ', & - ' CoM vx', & - ' CoM vy', & - ' CoM vz' /) - - fxyz_ptmass = 0. - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) - fssxyz_ptmass = fxyz_ptmass - do i=1,npart - call get_accel_sink_gas(nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass,& - fxi,fyi,fzi,phii,particlemass,fxyz_ptmass,dsdt_ptmass,fonrmax) - enddo - - ! Determine position and velocity of the CoM - call orbit_com(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,com_xyz,com_vxyz) - - do i=1,nptmass - sinkcomp = 0. - write (filename, "(A16,I0)") "sink_properties_", i - - ! position xyz - sinkcomp(1:3) = xyzmh_ptmass(1:3,i) - ! position modulus - sinkcomp(4) = distance(xyzmh_ptmass(1:3,i)) - ! velocity xyz - sinkcomp(5:7) = vxyz_ptmass(1:3,i) - ! velocity modulus - sinkcomp(8) = distance(vxyz_ptmass(1:3,i)) - ! momentum xyz - sinkcomp(9:11) = xyzmh_ptmass(4,i)*vxyz_ptmass(1:3,i) - ! momentum modulus - sinkcomp(12) = xyzmh_ptmass(4,i)*sinkcomp(8) - ! force xyz - sinkcomp(13:15) = fssxyz_ptmass(1:3,i) - ! force modulus - sinkcomp(16) = distance(fssxyz_ptmass(1:3,i)) - ! tot force xyz - sinkcomp(17:19) = fxyz_ptmass(1:3,i) - ! tot force modulus - sinkcomp(20) = distance(fxyz_ptmass(1:3,i)) - ! angular momentum xyz - call cross_product3D(xyzmh_ptmass(1:3,i), xyzmh_ptmass(4,i)*vxyz_ptmass(1:3,i), ang_mom) - sinkcomp(21:23) = ang_mom - ! angular momentum modulus - sinkcomp(24) = distance(ang_mom(1:3)) - ! kinetic energy - sinkcomp(25) = 0.5*xyzmh_ptmass(4,i)*sinkcomp(8)**2 - ! CoM position - sinkcomp(26:28) = com_xyz(1:3) - ! CoM velocity - sinkcomp(29:31) = com_vxyz(1:3) - - call write_time_file(filename, columns, time, sinkcomp, ncols, dump_number) - enddo - deallocate(columns) - -end subroutine sink_properties - - - -subroutine env_binding_ene(npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use ionization_mod, only:calc_thermal_energy - integer, intent(in) :: npart - real, intent(in) :: particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - integer :: i - real :: ethi,phii,rhoi,ponrhoi,spsoundi,tempi,dum1,dum2,dum3 - real :: bind_g,bind_th,bind_int,eth_tot,eint_tot - - bind_g = 0. - bind_th = 0. - bind_int = 0. - eint_tot = 0. - eth_tot = 0. - do i=1,npart - ! Gas-gas potential - bind_g = bind_g + poten(i) ! Double counting factor of 1/2 already included in poten - - ! Sink-sink potential - phii = 0. - call get_accel_sink_gas(1,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass(:,1),dum1,dum2,dum3,phii) ! Include only core particle; no companion - bind_g = bind_g + particlemass * phii - - rhoi = rhoh(xyzh(4,i), particlemass) - call equationofstate(ieos,ponrhoi,spsoundi,rhoi,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhoi,eos_vars(itemp,i),ethi) - - eth_tot = eth_tot + ethi - eint_tot = eint_tot + particlemass * vxyzu(4,i) - enddo - bind_th = bind_g + eth_tot - bind_int = bind_g + eint_tot - - print*,bind_g*unit_energ, bind_th*unit_energ, bind_int*unit_energ - -end subroutine env_binding_ene - - -subroutine bound_unbound_thermo(time,npart,particlemass,xyzh,vxyzu) - integer, intent(in) :: npart - real, intent(in) :: time, particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - integer :: i, ncols - real, dimension(8) :: entropy_array - real :: etoti, ekini, einti, epoti, phii, rhopart - 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 - integer, parameter :: ient_ub = 2 - integer, parameter :: itemp_b = 3 - integer, parameter :: itemp_ub = 4 - integer, parameter :: ipres_b = 5 - integer, parameter :: ipres_ub = 6 - integer, parameter :: idens_b = 7 - integer, parameter :: idens_ub = 8 - - !zeroes the entropy variable and others - entropy_array = 0. - - !setup - if (dump_number == 0) then - call prompt('Would you like to use thermal energy in the computation of the bound/unbound status?', switch(1),.false.) - endif - - call compute_energies(time) - - do i=1,npart - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) - - rhopart = rhoh(xyzh(4,i), particlemass) - - !gets entropy for the current particle - call get_eos_various_mesa(rhopart*unit_density,vxyzu(4,i) * unit_ergg, & - pres_1,proint_1,peint_1,temp_1,troint_1, & - teint_1,entrop_1,abad_1,gamma1_1,gam_1) - - !sums entropy and other quantities for bound particles and unbound particles - - if (.not. switch(1)) then - etoti = etoti - einti - endif - - if (etoti < 0.0) then !bound - entropy_array(ient_b) = entropy_array(ient_b) + entrop_1 - entropy_array(itemp_b) = entropy_array(itemp_b) + temp_1 - entropy_array(ipres_b) = entropy_array(ipres_b) + pres_1 - entropy_array(idens_b) = entropy_array(idens_b) + rhopart*unit_density - - else !unbound - entropy_array(ient_ub) = entropy_array(ient_ub) + entrop_1 - entropy_array(itemp_ub) = entropy_array(itemp_ub) + temp_1 - entropy_array(ipres_ub) = entropy_array(ipres_ub) + pres_1 - entropy_array(idens_ub) = entropy_array(idens_ub) + rhopart*unit_density - - endif - - enddo - - !average - entropy_array(itemp_b) = entropy_array(itemp_b) / npart - entropy_array(itemp_ub) = entropy_array(itemp_ub) / npart - entropy_array(ipres_b) = entropy_array(ipres_b) / npart - entropy_array(ipres_ub) = entropy_array(ipres_ub) / npart - entropy_array(idens_b) = entropy_array(idens_b) / npart - entropy_array(idens_ub) = entropy_array(idens_ub) / npart - - !writes on file - ncols = 8 - allocate(columns(ncols)) - columns = (/' b entr',& - ' unb entr',& - ' avg b temp',& - ' avg unb temp',& - ' avg b pres',& - ' avg unb pres',& - ' avg b dens',& - ' avg unb dens'/) - call write_time_file('entropy_vs_time', columns, time, entropy_array, ncols, dump_number) - deallocate(columns) -end subroutine bound_unbound_thermo - - -!---------------------------------------------------------------- -!+ -! Gravitational drag -!+ -!---------------------------------------------------------------- -subroutine gravitational_drag(time,npart,particlemass,xyzh,vxyzu) - use prompting, only:prompt - use vectorutils, only:cross_product3D - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - character(len=17) :: filename - integer :: i,j,k,ncols,sizeRcut,vol_npart,merge_ij(nptmass),merge_n - integer, allocatable :: iorder(:) - real, dimension(:), allocatable, save :: ang_mom_old,time_old - real, dimension(:,:), allocatable :: drag_force - real, dimension(4,maxptmass) :: fxyz_ptmass,fxyz_ptmass_sinksink - real, dimension(3,maxptmass) :: dsdt_ptmass - real, dimension(3) :: avg_vel,avg_vel_par,avg_vel_perp,& - com_xyz,com_vxyz,unit_vel,unit_vel_perp,& - pos_wrt_CM,vel_wrt_CM,ang_mom,com_vec,& - unit_sep,unit_sep_perp,vel_contrast_vec,Fgrav - real :: drag_perp,drag_par,drag_perp_proj,& - vel_contrast,mdot,sep,Jdot,R2,& - rho_avg,cs,racc,fonrmax,fxi,fyi,fzi,& - phii,phitot,dtsinksink,interior_mass,sinksinksep,& - volume,vol_mass,vKep,omega,maxsep,cos_psi,mass_coregas,& - com_sink_sep,Fgrav_mag - real, dimension(:), allocatable :: Rcut - real, dimension(:,:,:), allocatable :: force_cut_vec - logical, save :: iacc,icentreonCM - integer, save :: iavgopt - - ! OPTIONS - if (dump_number == 0) then - print*,'Options for averaging gas properties:' - print "(6(/,a))",'1. Average over sphere centred on the companion (not recommended)',& - '2. Average over sphere centred on opposite side of orbit',& - '3. Average over annulus',& - '4. Average over annulus but excluding sphere centred on the companion',& - '5. Average over sphere twice as far on the opposite side of the orbit',& - '6. Average over sphere half as far on the opposite side of the orbit' - iavgopt = 2 - call prompt('Select option above : ',iavgopt,1,6) - icentreonCM = .false. - select case (iavgopt) - case(2,5,6) - call prompt('Centre averaging sphere on the CM (otherwise, centre on primary core)?: ',icentreonCM) - case(3,4) - call prompt('Centre annulus on the CM (otherwise, centre on primary core)?: ',icentreonCM) - end select - - write(*,"(a,i2)") 'Using ieos = ',ieos - if ( xyzmh_ptmass(ihacc,2) > 0 ) then - write(*,"(a,f13.7,a)") 'Companion has accretion radius = ', xyzmh_ptmass(ihacc,2), '(code units)' - write(*,"(a)") 'Will analyse accretion' - iacc = .true. - else - iacc = .false. - endif - endif - - ncols = 31 - allocate(columns(ncols),iorder(npart),force_cut_vec(4,maxptmass,5)) - allocate(drag_force(ncols,nptmass)) - columns = (/' drag_perp', & ! 1 Component of net force (excluding sink-sink) perpendicular to sink separation (projection on (r2-r1) x z) - ' drag_par', & ! 2 Component of net force (excluding sink-sink) projected along sink separation, -(r2-r1) - 'drag_perp_pr', & ! 3 'drag_perp' projected along the -v direction - ' F_dot_v', & ! 4 Dot product of 'drag_perp_pr' and sink velocity (<0 means energy dissipation) - ' drag_torque', & ! 5 torque / r of sink - ' cos_psi', & ! 6 Cosine of angle between (r2-r1) x z and -v - ' Fgrav', & ! 7 Magnitude of gravitational force from core and gas around it inferred from net force minus drag - 'mass_coregas', & ! 8 Mass of core+gas inferred from net force minus drag - ' drag_BHL', & ! 9 Bondi-Hoyle-Lyttleton drag force - ' mdot_BHL', & ! 10 Bond-Hoyle-Lyttleton mass accretion rate - ' v_con', & ! 11 Magnitude of average background gas velocity minus sink velocity, positive when vsink dot vgas < 0 - ' v_con_par', & ! 12 Projection of velocity contrast on -vsink - ' v_Kep', & ! 13 Keplerian velocity of companion, sqrt(M( 0.) then - rho_avg = vol_mass / volume - avg_vel_par(1:3) = dot_product(avg_vel, unit_vel) * unit_vel - avg_vel_perp(1:3) = avg_vel(1:3) - avg_vel_par(1:3) - vel_contrast_vec = avg_vel - vxyz_ptmass(1:3,i) - vel_contrast = sign( distance(vel_contrast_vec), -dot_product(vxyz_ptmass(1:3,i), avg_vel) ) - racc = 2. * xyzmh_ptmass(4,i) / (vel_contrast**2 + cs**2) ! Accretion radius - mdot = 4.*pi * xyzmh_ptmass(4,i)**2 * rho_avg / (cs**2 + vel_contrast**2)**1.5 ! BHL mass accretion rate - endif - - - ! Sum acceleration (fxyz_ptmass) on companion due to gravity of gas particles - force_cut_vec = 0. - fxyz_ptmass = 0. - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) - - sizeRcut = 5 - if (i == 1) allocate(Rcut(sizeRcut)) - call logspace(Rcut,0.4,2.5) - !Rcut = Rcut * racc ! Bin by fraction of accretion radius - Rcut = Rcut * separation( xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2) ) ! Bin by fraction of sink-sink separation - - do j = 1,npart - if (.not. isdead_or_accreted(xyzh(4,j))) then - ! Get total gravitational force from gas - call get_accel_sink_gas(nptmass,xyzh(1,j),xyzh(2,j),xyzh(3,j),xyzh(4,j),xyzmh_ptmass,& - fxi,fyi,fzi,phii,particlemass,fxyz_ptmass,dsdt_ptmass,fonrmax) - ! Get force from gas within distance cutoff - do k = 1,sizeRcut - if ( separation(xyzh(1:3,j), xyzmh_ptmass(1:4,i)) < Rcut(k) ) then - call get_accel_sink_gas(nptmass,xyzh(1,j),xyzh(2,j),xyzh(3,j),xyzh(4,j),xyzmh_ptmass,& - fxi,fyi,fzi,phii,particlemass,force_cut_vec(1:4,:,k),dsdt_ptmass,fonrmax) - endif - enddo - endif - enddo - - ! Calculate angular momentum of companion wrt orbit CoM - pos_wrt_CM = xyzmh_ptmass(1:3,i) - com_xyz(1:3) - vel_wrt_CM = vxyz_ptmass(1:3,i) - com_vxyz(1:3) - call cross_product3D(pos_wrt_CM, xyzmh_ptmass(4,i) * vel_wrt_CM, ang_mom) - Jdot = (ang_mom(3) - ang_mom_old(i)) / (time - time_old(i)) ! Average change in angular momentum - R2 = distance(xyzmh_ptmass(1:3,i) - com_xyz(1:3)) - ang_mom_old(i) = ang_mom(3) ! Set ang_mom_old for next dump - time_old(i) = time - - ! Calculate mass interior to companion - call set_r2func_origin(xyzmh_ptmass(1,3-i),xyzmh_ptmass(2,3-i),xyzmh_ptmass(3,3-i)) ! Order particles by distance from donor core - call indexxfunc(npart,r2func_origin,xyzh,iorder) - sinksinksep = separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) - interior_mass = xyzmh_ptmass(4,3-i) ! Include mass of donor core - select case(iavgopt) - case(5) ! Calculate mass interior to R/2 - maxsep = 2.*sinksinksep - case(6) ! Calculate mass interior to 2*R - maxsep = 0.5*sinksinksep - case default ! Calculate mass interior to R - maxsep = sinksinksep - end select - do j = 1,npart - k = iorder(j) - sep = separation(xyzmh_ptmass(1:3,3-i), xyzh(1:3,k)) - if (sep > maxsep) exit - interior_mass = interior_mass + particlemass - enddo - vKep = sqrt(interior_mass / sinksinksep) - - ! Calculate perpendicular force projected along -v - cos_psi = cos_vector_angle(-unit_sep_perp, -vxyz_ptmass(1:3,i)) ! Theta is angle between (r2-r1) x z and -v - drag_par = - dot_product(fxyz_ptmass(1:3,i),unit_sep) * xyzmh_ptmass(4,i) ! Total force projected along -(r2-r1) - drag_perp = dot_product(fxyz_ptmass(1:3,i),-unit_sep_perp) * xyzmh_ptmass(4,i) ! Total force projected along -(r2-r1) x z - drag_perp_proj = drag_perp / cos_psi ! Perpendicular force projected along -v - - ! Calculate core + gas mass based on projected gravitational force - Fgrav = fxyz_ptmass(1:3,i) * xyzmh_ptmass(4,i) - drag_perp_proj * (-unit_vel) ! Ftot,gas + Fsinksink = Fdrag + Fgrav - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass_sinksink,phitot,dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) - Fgrav = Fgrav + fxyz_ptmass_sinksink(1:3,i) * xyzmh_ptmass(4,i) - Fgrav_mag = distance(Fgrav) - mass_coregas = Fgrav_mag * sinksinksep**2 / xyzmh_ptmass(4,i) - - ! Calculate CoM inferred from core + gas mass - com_vec = (mass_coregas * xyzmh_ptmass(1:3,3-i) + xyzmh_ptmass(4,i) * xyzmh_ptmass(1:3,i)) / (mass_coregas + xyzmh_ptmass(4,i)) - com_sink_sep = separation(com_vec, xyzmh_ptmass(1:3,i)) - - drag_force(1,i) = drag_perp - drag_force(2,i) = drag_par - drag_force(3,i) = drag_perp_proj - drag_force(4,i) = drag_perp_proj * (-distance(vxyz_ptmass(1:3,i))) - drag_force(5,i) = Jdot / R2 - drag_force(6,i) = cos_psi - drag_force(7,i) = Fgrav_mag - drag_force(8,i) = mass_coregas - drag_force(9,i) = mdot * vel_contrast ! BHL drag force - drag_force(10,i) = mdot - drag_force(11,i) = vel_contrast - drag_force(12,i) = dot_product(vel_contrast_vec, -unit_vel) - drag_force(13,i) = vKep - drag_force(14,i) = interior_mass - drag_force(15,i) = omega - drag_force(16,i) = cs - drag_force(17,i) = rho_avg - drag_force(18,i) = racc - drag_force(19,i) = com_sink_sep - drag_force(20,i) = separation(com_xyz(1:3),xyzmh_ptmass(1:3,i)) - drag_force(21,i) = sinksinksep - drag_force(22,i) = - dot_product(force_cut_vec(1:3,i,1),unit_sep) * xyzmh_ptmass(4,i) - drag_force(23,i) = - dot_product(force_cut_vec(1:3,i,1),unit_sep_perp) * xyzmh_ptmass(4,i) - drag_force(24,i) = - dot_product(force_cut_vec(1:3,i,2),unit_sep) * xyzmh_ptmass(4,i) - drag_force(25,i) = - dot_product(force_cut_vec(1:3,i,2),unit_sep_perp) * xyzmh_ptmass(4,i) - drag_force(26,i) = - dot_product(force_cut_vec(1:3,i,3),unit_sep) * xyzmh_ptmass(4,i) - drag_force(27,i) = - dot_product(force_cut_vec(1:3,i,3),unit_sep_perp) * xyzmh_ptmass(4,i) - drag_force(28,i) = - dot_product(force_cut_vec(1:3,i,4),unit_sep) * xyzmh_ptmass(4,i) - drag_force(29,i) = - dot_product(force_cut_vec(1:3,i,4),unit_sep_perp) * xyzmh_ptmass(4,i) - drag_force(30,i) = - dot_product(force_cut_vec(1:3,i,5),unit_sep) * xyzmh_ptmass(4,i) - drag_force(31,i) = - dot_product(force_cut_vec(1:3,i,5),unit_sep_perp) * xyzmh_ptmass(4,i) - - ! Write to output - write (filename, "(A16,I0)") "sink_drag_", i - call write_time_file(trim(adjustl(filename)), columns, time, drag_force(:,i), ncols, dump_number) - enddo - deallocate(columns,drag_force,force_cut_vec,Rcut) - -end subroutine gravitational_drag - - -subroutine J_E_plane(num,npart,particlemass,xyzh,vxyzu) - use vectorutils, only:cross_product3D - integer, intent(in) :: npart,num - 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, allocatable :: data(:,:) - - ncols = 7 - allocate(columns(ncols),data(ncols,npart)) - columns = (/' E',& - ' Jxcom',& - ' Jycom',& - ' Jzcom',& - ' Jxcore',& - ' Jycore',& - ' Jzcore'/) - - 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),xyzmh_ptmass,dum1,dum2,dum3,dum4,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 - call cross_product3D(xyzh(1:3,i)-com_xyz(1:3), vxyz_ptmass(1:3,i)-com_vxyz(1:3), angmom_com) - data(2:4,i) = angmom_com - enddo - - data(1,:) = data(1,:) / particlemass ! specific energy - - call write_file('JEplane','JEplane',columns,data,size(data(1,:)),ncols,num) - deallocate(columns,data) - -end subroutine J_E_plane - -!------------------------------------------------------------------- -!+ -! Planet destruction -!+ -!------------------------------------------------------------------- -subroutine planet_destruction(time,npart,particlemass,xyzh,vxyzu) - use kernel, only:wkern - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - character(len=18) :: filename - real, allocatable :: planetDestruction(:) - integer :: ncols,i,j - real, save :: time_old - real, allocatable, save :: particleRho(:) - character(len=50) :: planetRadiusPromptString - real, allocatable, save :: planetRadii(:) !In units of Rsun - - real, dimension(3) :: currentGasVel, currentVelContrast - real :: currentRho(1) !Is a one element array because sphInterpolation returns a 1 dimensional array. - real :: currentRhoScaled,currentVelContrastScaled,currentPlanetRhoScaled - real :: currentPlanetMassScaled,currentPlanetRadiusScaled - real, allocatable, save :: currentKhAblatedMass(:) - - ncols=5 - allocate(columns(ncols),planetDestruction(ncols)) - columns=(/" rhoGas", & - " kh_rhoCrit", & - " kh_lmax", & - " kh_mdot", & - " kh_ablatedM" /) - - !Kelvin-Helmholtz instability planet destruction as described in "On the survival of brown dwarfs - !and planets by their giant host star" (https://arxiv.org/abs/1210.0879). Description of columns: - !rhoGas: background gas density at sink. In units of g/cm^3. - !kh_rhoCrit: paper equation 5. In units of g/cm^3. - !kh_lmax: paper equation 6. In units of Jupiter radii. - !kh_mdot: paper equation 7. In units of Jupiter mass/year. - !kh_ablatedM: kh_mdot integrated over time. In units of Jupiter masses. - - currentRho = 0. - do i=1,nptmass - if (i==1) cycle !The first sink is assumed to be the core. - - if ((dump_number==0) .and. (i==2)) then !This is only done once. - allocate(planetRadii(nptmass)) - planetRadii=0.1 - do j=2,nptmass - write(planetRadiusPromptString,"(A13,I0,A32)") "Enter planet ",j-1," radius in units of solar radii" - call prompt(planetRadiusPromptString,planetRadii(i),0.0,1.0) - enddo - - allocate(particleRho(npart)) - allocate(currentKhAblatedMass(nptmass)) - - time_old=0.0 - particleRho=getParticleRho(xyzh(4,:),particlemass) - currentKhAblatedMass=0.0 - endif - - - currentRho=sphInterpolation(npart,particlemass,particleRho,xyzh,xyzmh_ptmass(1:3,i),reshape(particleRho,(/1,npart/))) - currentGasVel=sphInterpolation(npart,particlemass,particleRho,xyzh,xyzmh_ptmass(1:3,i),vxyzu(1:3,:)) - currentVelContrast=vxyz_ptmass(1:3,i)-currentGasVel - - currentPlanetRadiusScaled=planetRadii(i)/0.1 !In units of 0.1 Rsun. - currentPlanetMassScaled=xyzmh_ptmass(4,i)*104.74 !In units of 10 jupiter masses. - currentPlanetRhoScaled=(xyzmh_ptmass(4,i)/((4.0/3.0)*pi*(planetRadii(i)**3.0)))*0.44 !In units of 13.34 g/cm^3 - currentRhoScaled=currentRho(1)*59000.0 !In units of 10^-4 g/cm^3. - currentVelContrastScaled=distance(currentVelContrast)*4.37 !In units of 100 km/s. - - planetDestruction(1)=currentRho(1)*5.9 - planetDestruction(2)=3.82*(currentPlanetRhoScaled**(4.0/3.0))*(currentPlanetMassScaled**(2.0/3.0))& - *(currentVelContrastScaled**(-2.0)) - planetDestruction(3)=0.0000263*(currentVelContrastScaled**2.0)*currentRhoScaled*(currentPlanetRhoScaled**((-5.0)/3.0))& - *(currentPlanetMassScaled**((-1.0)/3.0)) - planetDestruction(4)=11.0*currentVelContrastScaled*currentRhoScaled*(currentPlanetRadiusScaled**2.0)& - *(planetDestruction(3)/(currentPlanetRadiusScaled*0.973)) - - currentKhAblatedMass(i)=currentKhAblatedMass(i)+((time-time_old)*planetDestruction(4)*0.0000505) - planetDestruction(5)=currentKhAblatedMass(i) - - - write(filename, "(A17,I0)") "sink_destruction_",i - call write_time_file(filename, columns, time, planetDestruction, ncols, dump_number) - enddo - - time_old=time - - deallocate(columns,planetDestruction) -end subroutine planet_destruction - -!----------------------------------------------------------------------------------------- -!+ -!Binding energy profile -!+ -!----------------------------------------------------------------------------------------- -subroutine create_bindingEnergy_profile(time,num,npart,particlemass,xyzh,vxyzu) - real, intent(in) :: time,particlemass - integer, intent(in) :: num,npart - real, intent(in) :: xyzh(4,npart),vxyzu(4,npart) - - character(len=17), allocatable :: columns(:) - real, allocatable :: profile(:,:) - integer :: ncols,i,j - integer, allocatable :: iorder(:) - real :: currentInteriorMass,currentParticleGPE,currentCoreParticleSeparation - real :: previousBindingEnergy,previousBindingEnergyU - - ncols=3 - allocate(columns(ncols),iorder(npart)) - allocate(profile(ncols,npart)) - columns=(/" radius",& - " bEnergy",& !Binding energy without internal energy. - " bEnergy (u)"/) !Binding energy with internal energy. - - - call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) - call indexxfunc(npart,r2func_origin,xyzh,iorder) - currentInteriorMass=xyzmh_ptmass(4,1)+(npart*particlemass) !Initally set to the entire mass of the star. - - do i=npart,1,-1 !Loops over all particles from outer to inner. - j=iorder(i) - currentInteriorMass=currentInteriorMass-particlemass - currentCoreParticleSeparation=separation(xyzmh_ptmass(1:3,1),xyzh(1:3,j)) - currentParticleGPE=(currentInteriorMass*particlemass)/currentCoreParticleSeparation - - !The binding energy at a particular radius is the sum of the gravitational potential energies - !(and internal energies in the case of the third column) of all particles beyond that radius. - if (i==npart) then - previousBindingEnergy=0.0 - previousBindingEnergyU=0.0 - else - previousBindingEnergy=profile(2,i+1) - previousBindingEnergyU=profile(3,i+1) - endif - - profile(1,i)=currentCoreParticleSeparation - profile(2,i)=previousBindingEnergy+currentParticleGPE - profile(3,i)=previousBindingEnergyU+currentParticleGPE-(vxyzu(4,j)*particlemass) - enddo - - call write_file('bEnergyProfile','bEnergyProfiles',columns,profile,npart,ncols,num) - deallocate(columns,iorder,profile) - -end subroutine create_bindingEnergy_profile - - -subroutine get_core_gas_com(time,npart,xyzh,vxyzu) - use sortutils, only:set_r2func_origin,r2func_origin,indexxfunc - integer, intent(in) :: npart - real, intent(in) :: time - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - real :: sep,maxsep,core_gas_com(3),core_gas_vcom(3),xyz_gas(4,npart),vxyz_gas(3,npart) - real, allocatable :: mytable(:) - character(len=17), allocatable :: columns(:) - character(len=17) :: filename - integer, save :: ngas - integer, allocatable, save :: iorder(:) - integer :: ncols,j,k - - ncols = 12 - allocate(columns(ncols)) - allocate(mytable(ncols)) - mytable = 0. - columns = (/' gas_com_x', & - ' gas_com_y', & - ' gas_com_z', & - ' gas_com_vx', & - ' gas_com_vy', & - ' gas_com_vz', & - ' core_x', & - ' core_y', & - ' core_z', & - ' core_vx', & - ' core_vy', & - ' core_vz' /) - - - ! Record particles that are closest to primary core - if (dump_number == 0) then - allocate(iorder(npart)) - maxsep = 10. ! 10 Rsun - ngas = 0 - call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) ! Order particles by distance from donor core - call indexxfunc(npart,r2func_origin,xyzh,iorder) - - do j=1,npart - k = iorder(j) - if (j < 10) print*,k - sep = separation(xyzmh_ptmass(1:3,1), xyzh(1:3,k)) - if (sep > maxsep) exit - ngas = ngas + 1 - enddo - endif - - print*,'ngas=',ngas - - do j=1,ngas - k = iorder(j) - xyz_gas(1:4,j) = xyzh(1:4,k) - vxyz_gas(1:3,j) = vxyzu(1:3,k) - enddo - - call get_centreofmass(core_gas_com,core_gas_vcom,ngas,xyz_gas,vxyz_gas) ! Do not include sinks - - mytable(1:3) = core_gas_com(1:3) - mytable(4:6) = core_gas_vcom(1:3) - mytable(7:9) = xyzmh_ptmass(1:3,1) - mytable(10:12) = vxyz_ptmass(1:3,1) - - write (filename, "(A16,I0)") "core_gas_com" - call write_time_file(trim(adjustl(filename)),columns,time,mytable,ncols,dump_number) -end subroutine get_core_gas_com - - -!---------------------------------------------------------------- -!+ -! Print dump numbers corresponding to given sink-sink separations -!+ -!---------------------------------------------------------------- -subroutine print_dump_numbers(dumpfile) - character(len=*), intent(in) :: dumpfile - character(len=50), allocatable, save :: dumpfiles(:) - integer :: nseps - integer, save :: i - real, allocatable :: sinksinksep(:) - real :: sep - - nseps = 2 - allocate(sinksinksep(nseps)) - if (dump_number == 0) then - allocate(dumpfiles(nseps)) - i=1 - endif - sinksinksep = (/ 938., 67. /) - - sep = separation(xyzmh_ptmass(1:3,1),xyzmh_ptmass(1:3,2)) - if ( sep < sinksinksep(i) ) then - dumpfiles(i) = trim(dumpfile) - i=i+1 - endif - if (i==nseps+1) then - print "(5(a,/))",'../',dumpfiles - return - endif - -end subroutine print_dump_numbers - - -!---------------------------------------------------------------- -!+ -! Analyse disk -!+ -!---------------------------------------------------------------- -subroutine analyse_disk(num,npart,particlemass,xyzh,vxyzu) - use part, only:eos_vars,itemp - use extern_corotate, only:get_companion_force - use ionization_mod, only:calc_thermal_energy - use vectorutils, only:cross_product3D - integer, intent(in) :: num,npart - real, intent(in) :: particlemass - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - character(len=17), allocatable :: columns(:) - real, allocatable :: data(:,:) - real :: diskz,diskR2,diskR1,R,omegai,phii,rhopart,ponrhoi,spsoundi,tempi,& - epoti,ekini,ethi,Ji(3),vrel2,fxi,fyi,fzi,vphi - integer :: ncols,i - - ncols = 9 - allocate(columns(ncols),data(ncols,npart)) - data = -1. - columns = (/' R',& ! cylindrical radius w.r.t companion - ' E',& ! specific energy (kin+pot only) w.r.t. companion - ' Omega',& ! angular momentum w.r.t. companion - ' Jx',& ! specific angular momentum components - ' Jy',& - ' Jz',& - ' ekin',& - ' epot',& ! gravitational potential energy due to companion only - ' etherm'/) - - ! Set disk dimensions - diskz = 50. ! disk half-thickness - diskR1 = 5. ! disk inner radius - diskR2 = 150. ! disk outer radius - - do i=1,npart - ! Skip if particle is not within the defined disk - if (abs(xyzh(3,i) - xyzmh_ptmass(3,2)) > diskz) cycle - R = sqrt( (xyzh(1,i) - xyzmh_ptmass(1,2))**2 + (xyzh(2,i) - xyzmh_ptmass(2,2))**2 ) - if ( (R > diskR2) .or. (R < diskR1) ) cycle - - vrel2 = (vxyzu(1,i) - vxyz_ptmass(1,2))**2 + (vxyzu(2,i) - vxyz_ptmass(2,2))**2 + (vxyzu(3,i) - vxyz_ptmass(3,2))**2 - ekini = 0.5*particlemass*vrel2 - - ! Calculate gravitational potential due to companion only - phii = 0. - call get_companion_force(xyzh(1:3,i),fxi,fyi,fzi,phii) - epoti = phii*particlemass - - ! Calculate thermal 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) - - call get_gas_omega(xyzmh_ptmass(1:3,2),vxyz_ptmass(1:3,2),xyzh(1:3,i),vxyzu(1:3,i),vphi,omegai) - call cross_product3D(xyzh(1:3,i)-xyzmh_ptmass(1:3,2), vxyzu(1:3,i)-vxyz_ptmass(1:3,2), Ji) - - data(1,i) = R - data(2,i) = (ekini+epoti) / particlemass - data(3,i) = omegai - data(4:6,i) = Ji - data(7,i) = ekini - data(8,i) = epoti - data(9,i) = ethi - enddo - call write_file('companion_disk','companion_disk',columns,data,npart,ncols,num) - deallocate(columns) - -end subroutine analyse_disk - - -!---------------------------------------------------------------- -!+ -! Recombination energy vs. time -!+ -!---------------------------------------------------------------- -subroutine erec_vs_t(time,npart,particlemass,xyzh) - use ionization_mod, only:get_erec_components - integer, intent(in) :: npart - real, intent(in) :: time,particlemass - real, intent(inout) :: xyzh(:,:) - character(len=17) :: filename,columns(4) - integer :: i - real :: ereci(4),erec(4),tempi,rhoi - - columns = (/' H2', & - ' HI', & - ' HeI', & - ' HeII'/) - - erec = 0. - do i = 1,npart - rhoi = rhoh(xyzh(4,i), particlemass) - call get_erec_components( log10(rhoi*unit_density), tempi, X_in, 1.-X_in-Z_in, ereci) - erec = erec + ereci - enddo - - write (filename, "(A16,I0)") "erec_vs_t" - call write_time_file(trim(adjustl(filename)),columns,time,erec,4,dump_number) - -end subroutine erec_vs_t - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!!!!! Routines used in analysis routines !!!!! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -!---------------------------------------------------------------- -!+ -! Calculate the angular velocity of an envelope gas particle -! relative to a reference point -!+ -!---------------------------------------------------------------- -subroutine get_gas_omega(xyz_centre,vxyz_centre,xyzi,vxyzi,vphi,omega) - use vectorutils, only:cross_product3D - real, intent(in) :: xyz_centre(3),vxyz_centre(3),xyzi(3),vxyzi(3) - real, intent(out) :: vphi,omega - real :: Rmag,R(3),phi_unitvec(3),R_unitvec(3) - - ! xyz_centre: Position vector of reference point - ! vxyz_centre: Velocity vector of reference point - ! R: Cylindrical radius vector - R(1:2) = xyzi(1:2) - xyz_centre(1:2) ! Separation in x-y plane - R(3) = 0. - Rmag = sqrt(dot_product(R,R)) - R_unitvec = R / Rmag - call cross_product3D((/0.,0.,1./), R_unitvec, phi_unitvec) ! phi = z x R - vphi = dot_product(vxyzi - vxyz_centre, phi_unitvec) - omega = vphi / Rmag -end subroutine get_gas_omega - - -!---------------------------------------------------------------- -!+ -! Calculate kinetic, gravitational potential (gas-gas and sink-gas), -! and internal energy of a gas particle. -!+ -!---------------------------------------------------------------- -subroutine calc_gas_energies(particlemass,poten,xyzh,vxyzu,xyzmh_ptmass,phii,epoti,ekini,einti,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 - real, intent(in) :: particlemass - real(4), intent(in) :: poten - real, dimension(4), intent(in) :: xyzh,vxyzu - real, dimension(5,nptmass), intent(in) :: xyzmh_ptmass - real, intent(out) :: phii,epoti,ekini,einti,etoti - real :: fxi,fyi,fzi - - phii = 0.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) - etoti = epoti + ekini + einti - -end subroutine calc_gas_energies - - -subroutine adjust_corotating_velocities(npart,particlemass,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,omega_c,dump_number) - use vectorutils, only:cross_product3D - real, dimension(:,:), intent(in) :: xyzmh_ptmass,xyzh - real, dimension(:,:), intent(inout) :: vxyzu,vxyz_ptmass - real, intent(inout) :: omega_c - real, intent(in) :: particlemass - integer, intent(in) :: npart, dump_number - - logical :: switch - real :: sep, mtot - real, dimension(3) :: omega_vec, omegacrossr - integer :: i - - if (dump_number == 0) then - call prompt('Was this in a corotating frame?',switch,.false.) - - if (switch) then - sep = separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) - mtot = sum(xyzmh_ptmass(4,:)) + npart*particlemass - omega_c = sqrt(mtot / sep**3) - else - omega_c = -1 - endif - endif - - if (omega_c > 0.) then - omega_vec = (/ 0.,0.,omega_c /) - - do i=1,npart - call cross_product3D(omega_vec,xyzh(1:3,i),omegacrossr) - vxyzu(1:3,i) = vxyzu(1:3,i) + omegacrossr(1:3) - enddo - - do i=1,nptmass - call cross_product3D(omega_vec,xyzmh_ptmass(1:3,i),omegacrossr) - vxyz_ptmass(1:3,i) = vxyz_ptmass(1:3,i) + omegacrossr(1:3) - enddo - endif -end subroutine adjust_corotating_velocities - - -! returns a profile from the centre of mass -! profile can either use all particles or can find particles within 2h of a given ray -! if simple flag is set to true, it will only produce a limited subset -subroutine stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,simple,ray) - use eos, only:ieos,equationofstate,X_in, Z_in - use eos_mesa, only:get_eos_kappa_mesa,get_eos_pressure_temp_mesa - use physcon, only:kboltz,mass_proton_cgs - use centreofmass, only:get_centreofmass - use energies, only:compute_energies - use part, only:xyzmh_ptmass,rhoh,ihsoft,poten - use units, only:udist,unit_ergg,unit_density,unit_pressure,unit_velocity,unit_energ - use kernel, only:kernel_softening,radkern - use ptmass, only:get_accel_sink_gas - use ionization_mod, only:ionisation_fraction - - real, intent(in) :: time - integer, intent(in) :: ncols - real, intent(in) :: particlemass - integer, intent(in) :: npart - real, intent(in) :: xyzh(:,:) - real, intent(inout) :: vxyzu(:,:) - real, intent(out), allocatable :: profile(:,:) - logical, intent(in) :: simple - real, intent(in), optional :: ray(3) - integer :: i,iprofile - 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 :: xh0, xh1, xhe0, xhe1, xhe2 - real :: temp_profile(ncols,npart) - logical :: criteria - - call compute_energies(time) - - iprofile = 0 - - do i=1,npart - if (xyzh(4,i) >= 0) then - - if (present(ray)) then - proj_mag = dot_product(xyzh(1:3,i),ray(1:3)) - proj = proj_mag * ray - orth(1:3) = xyzh(1:3,i) - proj(1:3) - orth_dist = separation(orth,(/0.,0.,0./)) - orth_ratio = orth_dist / xyzh(4,i) - if (orth_ratio < radkern .and. proj_mag > 0.) then - criteria = .true. - else - criteria = .false. - endif - else - criteria = .true. - endif - - if (criteria) then - - iprofile = iprofile + 1 - - rhopart = rhoh(xyzh(4,i), particlemass) - - temp_profile(1,iprofile) = distance(xyzh(1:3,i)) * udist - temp_profile(3,iprofile) = atan2(xyzh(2,i),xyzh(1,i)) - temp_profile(4,iprofile) = rhopart * unit_density - temp_profile(5,iprofile) = distance(vxyzu(1:3,i)) * unit_velocity - temp_profile(6,iprofile) = dot_product(vxyzu(1:3,i),xyzh(1:3,i)) / distance(xyzh(1:3,i)) * unit_velocity - temp_profile(7,iprofile) = sqrt(distance(vxyzu(1:2,i))**2 - (dot_product(vxyzu(1:2,i),xyzh(1:2,i)) & - / distance(xyzh(1:2,i)))**2) * unit_velocity - temp_profile(8,iprofile) = temp_profile(7,iprofile) / (distance(xyzh(1:2,i)) * udist) - if (simple .eqv. .false.) then - call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) - - if (ieos == 10) then - call get_eos_pressure_temp_mesa(rhopart*unit_density,vxyzu(4,i) * unit_ergg,pres,temp) - call get_eos_kappa_mesa(rhopart*unit_density,temp,kappa,kappat,kappar) - else - temp = (ponrhoi * (unit_pressure/unit_density) * 2.381 * mass_proton_cgs) / kboltz - kappa = 1. - endif - - call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),xyzmh_ptmass,phii,epoti,ekini,einti,etoti) - - call ionisation_fraction(rhopart*unit_density,temp,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) - - temp_profile(9,iprofile) = vxyzu(4,i) * unit_ergg - temp_profile(10,iprofile) = ponrhoi * rhopart * unit_pressure - temp_profile(11,iprofile) = spsoundi * unit_velocity - temp_profile(12,iprofile) = temp - temp_profile(13,iprofile) = kappa - temp_profile(14,iprofile) = 1. / (kappa * rhopart * unit_density) - temp_profile(15,iprofile) = etoti * unit_energ - temp_profile(16,iprofile) = xh1 - temp_profile(17,iprofile) = xhe1 - temp_profile(18,iprofile) = xhe2 - endif - endif - endif - enddo - - allocate(profile(ncols,iprofile)) - profile(1:ncols,1:iprofile) = temp_profile(1:ncols,1:iprofile) - - call quicksort(profile, 1, iprofile, ncols, 1) - - do i=1,iprofile - if (i==1) profile(2,i) = particlemass - if (i > 1) profile(2,i) = profile(2,i-1) + particlemass - enddo - - deallocate(profile) - print*, "Profile completed" - -end subroutine stellar_profile - -!---------------------------------------------------------------- -!+ -! Calculate mass interior to companion -!+ -!---------------------------------------------------------------- -subroutine get_interior_mass(xyzh,vxyzu,donor_xyzm,companion_xyzm,particlemass,npart,iavgopt,interior_mass,com_xyz,com_vxyz) - real, intent(in) :: xyzh(:,:),vxyzu(:,:),donor_xyzm(4),companion_xyzm(4),particlemass - real, intent(out) :: interior_mass,com_xyz(3),com_vxyz(3) - integer, intent(in) :: npart,iavgopt - real :: sinksinksep,maxsep,sep,xyz_int(3,npart),vxyz_int(3,npart) - integer :: j,k,npart_int - integer, allocatable :: iorder(:) - - ! Calculate mass interior to companion - allocate(iorder(npart)) - call set_r2func_origin(donor_xyzm(1),donor_xyzm(2),donor_xyzm(3)) ! Order particles by distance from donor core - call indexxfunc(npart,r2func_origin,xyzh,iorder) - sinksinksep = separation(donor_xyzm(1:3), companion_xyzm(1:3)) - interior_mass = donor_xyzm(4) ! Include mass of donor core - select case(iavgopt) - case(5) ! Calculate mass interior to R/2 - maxsep = 2.*sinksinksep - case(6) ! Calculate mass interior to 2*R - maxsep = 0.5*sinksinksep - case default ! Calculate mass interior to R - maxsep = sinksinksep - end select - npart_int = 0 - do j = 1,npart - k = iorder(j) - sep = separation(donor_xyzm(1:3), xyzh(1:3,k)) - if (sep > maxsep) exit - npart_int = npart_int + 1 - xyz_int(1:3,npart_int) = xyzh(1:3,k) - vxyz_int(1:3,npart_int) = vxyzu(1:3,k) - enddo - interior_mass = npart_int * particlemass - - call get_centreofmass(com_xyz,com_vxyz,npart_int,xyz_int,vxyz_int,nptmass,xyzmh_ptmass,vxyz_ptmass) - deallocate(iorder) - -end subroutine get_interior_mass - -!---------------------------------------------------------------- -!+ -! Get CoM position and velocity of the two point masses plus -! gas particles radius = 2*sep from the donor, where sep is the -! distance between the donor and the CoM of just the point masses. -!+ -!---------------------------------------------------------------- -subroutine orbit_com(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,com_xyz,com_vxyz) - integer, intent(in) :: npart,nptmass - real, intent(in) :: xyzh(:,:),vxyzu(:,:),xyzmh_ptmass(:,:),vxyz_ptmass(:,:) - real, intent(out), dimension(3) :: com_xyz,com_vxyz - real, allocatable :: xyz_a(:,:) - real, allocatable :: vxyz_a(:,:) - integer, allocatable :: iorder(:) - integer :: npart_a - real :: sep - integer :: i,j,k - - allocate(iorder(npart),xyz_a(4,npart),vxyz_a(3,npart)) - - ! Get order of particles by distance from CoM of point masses - com_xyz(1) = sum(xyzmh_ptmass(1,:)*xyzmh_ptmass(4,:))/nptmass - com_xyz(2) = sum(xyzmh_ptmass(2,:)*xyzmh_ptmass(4,:))/nptmass - com_xyz(3) = sum(xyzmh_ptmass(3,:)*xyzmh_ptmass(4,:))/nptmass - call set_r2func_origin(com_xyz(1),com_xyz(2),com_xyz(3)) - call indexxfunc(npart,r2func_origin,xyzh,iorder) - ! Displacement of donor core from the CoM of point masses - sep = separation(xyzmh_ptmass(1:3,1),com_xyz(1:3)) - - ! Calculate CoM of orbit, including only gas particles within radius = 2*sep from donor core - ! The point is that by including some gas particles around the donor core, we get a more accurate - ! position of the CoM about which the stellar cores orbit - i = 1 - k = 1 - do while (i < npart+1) - j = iorder(i) ! Loop from particles closest to farthest from CoM - if (isdead_or_accreted(xyzh(4,j))) then - i = i + 1 - else - if (separation(xyzh(1:3,j),com_xyz(1:3)) > 2.*sep) exit - xyz_a(1:4,k) = xyzh(1:4,j) - vxyz_a(1:3,k) = vxyzu(1:3,j) - i = i + 1 - k = k + 1 - endif - enddo - npart_a = k - 1 - call get_centreofmass(com_xyz,com_vxyz,npart_a,xyz_a,vxyz_a,nptmass,xyzmh_ptmass,vxyz_ptmass) - deallocate(iorder,xyz_a,vxyz_a) - -end subroutine orbit_com - -subroutine average_in_vol(xyzh,vxyzu,npart,particlemass,com_xyz,com_vxyz,isink,icentreonCM,iavgopt,vel,cs,omega,volume,vol_mass,& - vol_npart) - real, intent(in) :: xyzh(:,:),vxyzu(:,:),com_xyz(:),com_vxyz(:),particlemass - logical, intent(in) :: icentreonCM - real, intent(out) :: vel(:),cs,omega,volume,vol_mass - integer, intent(out) :: vol_npart - integer, intent(in) :: npart,isink,iavgopt - real :: orbit_centre(3),orbit_centre_vel(3),sphere_centre(3),Rarray(size(xyzh(1,:))),zarray(size(xyzh(1,:))),vxyzu_copy(4) - real :: Rsphere,sep,omega_out,Rsinksink,dR,dz,vphi - integer :: i,j,k,iorder(size(xyzh(1,:))) - - i = isink - if (icentreonCM) then ! Centre on orbit CoM - orbit_centre = com_xyz - orbit_centre_vel = com_vxyz - else ! Centre on primary core - orbit_centre = xyzmh_ptmass(1:3,3-i) - orbit_centre_vel = vxyz_ptmass(1:3,3-i) - endif - - Rsphere = 0.2 * separation(orbit_centre, xyzmh_ptmass(1:3,i)) - Rsinksink = separation(xyzmh_ptmass(1:2,i), xyzmh_ptmass(1:2,3-i)) ! [(x2-x1)^2 + (y2-y1)^2]^0.5 - dR = 0.2*Rsinksink - dz = 0.2*Rsinksink - vol_npart = 0 - vol_mass = 0. - omega = 0. - cs = 0. - - ! If averaging over a sphere, get order of particles from closest to farthest from sphere centre - dr = 0. - dz = 0. - Rsinksink = 0. - vol_npart = 0 - Rsphere = 0. - select case(iavgopt) - case(1,2,5,6) - select case (iavgopt) - case(1) ! Use companion position - sphere_centre = xyzmh_ptmass(1:3,i) - case(2) ! Use companion position on the opposite side of orbit - sphere_centre = 2.*orbit_centre - xyzmh_ptmass(1:3,i) ! Just r1 - (r2 - r1) - case(5) ! Averaging twice as far on opposite side of orbit - sphere_centre = 2.*(orbit_centre - xyzmh_ptmass(1:3,i)) ! Just r1 - 2(r2 - r1) - case(6) ! Averaging half as far on opposite side of orbit - sphere_centre = 1.5*orbit_centre - 0.5*xyzmh_ptmass(1:3,i) ! Just r1 - 0.5*(r2 - r1) - end select - call set_r2func_origin(sphere_centre(1),sphere_centre(2),sphere_centre(3)) - call indexxfunc(npart,r2func_origin,xyzh,iorder) - - ! Sum velocities, cs, and densities of all particles within averaging sphere - do j = 1,npart - k = iorder(j) ! Only use particles within the averaging sphere - if (.not. isdead_or_accreted(xyzh(4,k))) then - sep = separation(xyzh(1:3,k), sphere_centre) - if (sep > Rsphere) exit - vel(1:3) = vel(1:3) + vxyzu(1:3,k) - vxyzu_copy = vxyzu(:,k) - cs = cs + get_spsound(ieos,xyzh(1:3,k),rhoh(xyzh(4,k),particlemass),vxyzu_copy) - call get_gas_omega(orbit_centre,orbit_centre_vel,xyzh(1:3,k),vxyzu(1:3,k),vphi,omega_out) - omega = omega + omega_out - endif - enddo - vol_npart = j-1 ! Number of (unaccreted) particles in the sphere - vol_mass = vol_npart * particlemass - if ((iavgopt == 2) .or. (iavgopt == 5) .or. (iavgopt == 6)) vel = -vel ! To-do: get rid of this line - - ! Averaging in annulus - case(3,4) - Rarray = sqrt( (xyzh(1,:) - xyzmh_ptmass(1,3-i))**2 + (xyzh(2,:) - xyzmh_ptmass(2,3-i))**2) ! [(x-x1)^2 + (y-y1)^2]^0.5 - zarray = xyzh(3,:) - xyzmh_ptmass(3,3-i) - if (iavgopt == 4) Rsphere = 0.2*separation(xyzmh_ptmass(1:3,3-i),xyzmh_ptmass(1:3,i)) - do k = 1,npart - if ( (iavgopt == 4) .and. (separation(xyzh(1:3,k), xyzmh_ptmass(1:3,i)) < Rsphere) ) cycle - if ( (abs(Rarray(k) - Rsinksink) < 0.5*dR) .and.& - (abs(zarray(k) - xyzmh_ptmass(3,3-i)) < 0.5*dz) ) then - vel = vel + vxyzu(1:3,k) - vxyzu_copy = vxyzu(:,k) - cs = cs + get_spsound(ieos,xyzh(1:3,k),rhoh(xyzh(4,k),particlemass),vxyzu_copy) - call get_gas_omega(orbit_centre,orbit_centre_vel,xyzh(1:3,k),vxyzu(1:3,k),vphi,omega_out) - omega = omega + omega_out - vol_npart = vol_npart + 1 - endif - enddo - vol_mass = vol_npart * particlemass - end select - - ! Calculate averaging volume based on averaging option - select case (iavgopt) - case (1,2,5,6) ! Spheres - volume = 4./3.*pi*Rsphere**3 - case(3) ! Annulus - volume = 2.*pi * Rsinksink * dR * dz - case(4) ! Annulus with sphere subtracted - volume = 2.*pi * Rsinksink * dR * dz - volume = volume - 0.4*dR*dz*Rsinksink - case default - volume = 0. - print*,'Unknown averaging option' - return - end select - - ! Calculate volume averages - if (vol_npart > 0) then - vel(1:3) = vel(1:3) / float(vol_npart) - omega = omega / float(vol_npart) - cs = cs / float(vol_npart) - endif - -end subroutine average_in_vol - - -!---------------------------------------------------------------- -!+ -! Returns hist, the radial or mass-coordinate profile of a -! quantity. -! -! Inputs: -! coord: Array of radius or mass-coordinate of each particle -! quant: Array containing quantity for each particle to be binned -! bin_min: Lower bin edge for coord -! bin_max: Upper bin edge for coord -! nbins: Number of bins for coord -! logbins: If true, produce log-uniform bins -! normalise_by_bincount: If true, normalises histogram by bin -! count, thus averaging the quantity -!+ -!---------------------------------------------------------------- -subroutine histogram_setup(coord,quant,hist,npart,bin_max,bin_min,nbins,normalise_by_bincount,logbins) - integer, intent(in) :: npart,nbins - real, intent(in) :: coord(npart),quant(npart),bin_max, bin_min - logical, intent(in) :: normalise_by_bincount,logbins - real, intent(out) :: hist(nbins) - integer :: i,j,bincount(nbins) - real :: bins(nbins) - - if (logbins) then ! Create log-uniform bins - bins = (/ (10**(bin_min + (i-1) * (bin_max-bin_min)/real(nbins)), i=1,nbins) /) - else ! Create linear bins - bins = (/ (bin_min + (i-1) * (bin_max-bin_min)/real(nbins), i=1,nbins) /) - endif - - hist = 0. - bincount = 0 - - do j=1,npart - do i=1,nbins-1 - if (coord(j) >= bins(i) .and. coord(j) < bins(i+1)) then - bincount(i) = bincount(i) + 1 - hist(i) = hist(i) + quant(j) - exit ! Move onto next particle - endif - enddo - enddo - - if (normalise_by_bincount) then - do i=1,nbins - if (bincount(i) > 0) then - hist(i) = hist(i) / real(bincount(i)) - endif - enddo - endif - -end subroutine histogram_setup - -subroutine write_file(name_in, dir_in, cols, data_in, npart, ncols, num) - !outputs a file from a single dump - character(len=*), intent(in) :: name_in, dir_in - integer, intent(in) :: npart, ncols, num - character(len=*), dimension(ncols), intent(in) :: cols - character(len=20), dimension(ncols) :: columns - character(len=40) :: data_formatter, column_formatter - character(len(name_in)+9) :: file_name - - real, dimension(ncols,npart), intent(in) :: data_in - integer :: i, unitnum - - unitnum = 1000 + num - if (dump_number == 0) then - call system('mkdir ' // dir_in ) - endif - - write(file_name, "(2a,i5.5,a)") trim(name_in), "_", num, ".ev" - - open(unit=unitnum, file='./'//dir_in//'/'//file_name, status='replace') - - write(column_formatter, "(a,I2.2,a)") "('#',2x,", ncols, "('[',a15,']',3x))" - write(data_formatter, "(a,I2.2,a)") "(", ncols, "(2x,es19.11e3))" - - do i=1,ncols - write(columns(i), "(I2.2,a)") i, cols(i) - enddo - - !set column headings - write(unitnum, column_formatter) columns(:) - - !Write data to file - do i=1,npart - write(unitnum,data_formatter) data_in(:ncols,i) - enddo - - close(unit=unitnum) -end subroutine write_file - - -subroutine write_time_file(name_in, cols, time, data_in, ncols, num) - !outputs a file over a series of dumps - character(len=*), intent(in) :: name_in - integer, intent(in) :: ncols, num - character(len=*), dimension(ncols), intent(in) :: cols - character(len=20), dimension(ncols) :: columns - character(len=40) :: data_formatter, column_formatter - character(len(name_in)+9) :: file_name - real, intent(in) :: time - real, dimension(ncols), intent(in) :: data_in - integer :: i, unitnum - - write(column_formatter, "(a,I2.2,a)") "('#',2x,", ncols+1, "('[',a15,']',3x))" - write(data_formatter, "(a,I2.2,a)") "(", ncols+1, "(2x,es18.11e2))" - write(file_name,"(2a,i3.3,a)") name_in, '.ev' - - if (num == 0) then - unitnum = 1000 - - open(unit=unitnum, file=file_name, status='replace') - do i=1,ncols - write(columns(i), "(I2,a)") i+1, cols(i) - enddo - - !set column headings - write(unitnum, column_formatter) '1 time', columns(:) - close(unit=unitnum) - endif - - unitnum=1001+num - - open(unit=unitnum, file=file_name, position='append') - - write(unitnum,data_formatter) time, data_in(:ncols) - - close(unit=unitnum) - -end subroutine write_time_file - -real function distance(a) - ! Return norm of a vector of arbitrary dimension - real, intent(in), dimension(:) :: a - - distance = sqrt(dot_product(a,a)) -end function distance - -subroutine unit_vector(a,b) - real, intent(in), dimension(3) :: a - real, intent(out), dimension(3) :: b - - b(1:3) = a(1:3) / distance(a(1:3)) -end subroutine unit_vector - -real function cos_vector_angle(a,b) - real, intent(in), dimension(3) :: a,b - if (distance(a) == 0 .or. distance(b) == 0) then - cos_vector_angle = 1. - else - cos_vector_angle = dot_product(a,b) / (distance(a) * distance(b)) - endif -end function cos_vector_angle - -subroutine separation_vector(a,b,c) - !return difference between two vectors - real, intent(in), dimension(3) :: a,b - real, intent(out), dimension(4) :: c - - c(1) = a(1) - b(1) - c(2) = a(2) - b(2) - c(3) = a(3) - b(3) - c(4) = distance(c(1:3)) -end subroutine separation_vector - -real function separation(a,b) - !return the distance between two vectors - real, intent(in), dimension(:) :: a,b - - separation = distance(a - b) -end function separation - -!Creates an array of SPH particle densities for each value of h. -elemental real function getParticleRho(h,particlemass) - real, intent(in) :: h,particlemass - getParticleRho=rhoh(h,particlemass) -end function getParticleRho - -!Performs SPH interpolation on the SPH particle property toInterpolate at the location interpolateXyz. -!The smoothing length used is the smoothing length of the closest SPH particle to interpolateXyz. -function sphInterpolation(npart,particlemass,particleRho,particleXyzh,interpolateXyz,toInterpolate) result(interpolatedData) - use kernel, only:wkern - integer, intent(in) :: npart - real, intent(in) :: particlemass - real, intent(in) :: particleRho(npart) - real, intent(in) :: particleXyzh(4,npart) - real, intent(in) :: interpolateXyz(3) - real, intent(in) :: toInterpolate(:,:) - real :: interpolatedData(size(toInterpolate,1)) - - integer :: i,j - integer, allocatable :: iorder(:) - real :: currentR,currentQ,currentQ2 - real :: nearestSphH - real :: currentParticleRho,currentSphSummandFactor - - interpolatedData=0.0 - allocate(iorder(npart)) - call set_r2func_origin(interpolateXyz(1),interpolateXyz(2),interpolateXyz(3)) - call indexxfunc(npart,r2func_origin,particleXyzh,iorder) !Gets the order of SPH particles from the interpolation point. - nearestSphH=particleXyzh(4,iorder(1)) !The smoothing length of the nearest SPH particle to the ineterpolation point. - - do i=1,npart - j=iorder(i) - - currentR=separation(interpolateXyz,particleXyzh(1:3,j)) - currentQ=currentR/nearestSphH !currentR is scaled in units of nearestSphH - currentQ2=currentQ**2.0 - - !All SPH particles beyond 2 smoothing lengths are ignored. - if (currentQ>2) then - exit - endif - - !SPH interpolation is done below. - currentParticleRho=particleRho(j) - currentSphSummandFactor=(particlemass/currentParticleRho)*((1.0/((nearestSphH**3.0)*pi))*wkern(currentQ2,currentQ)) - interpolatedData=interpolatedData+(currentSphSummandFactor*toInterpolate(:,j)) - enddo - deallocate(iorder) - -end function sphInterpolation - -!Sorting routines -recursive subroutine quicksort(a, first, last, ncols, sortcol) - integer, intent(in) :: first, last, ncols, sortcol - real, dimension(ncols,last-first+1), intent(inout) :: a - real :: x - integer :: i, j, k - - x = a(sortcol, (first+last) / 2 ) - i = first - j = last - do - do while (a(sortcol, i) < x) - i=i+1 - enddo - - do while (x < a(sortcol, j)) - j=j-1 - enddo - - if (i >= j) exit - - do k=1,ncols - call swap(a(k,i),a(k,j)) - enddo - - i=i+1 - j=j-1 - enddo - if (first < i-1) call quicksort(a, first, i-1, ncols, sortcol) - if (j+1 < last) call quicksort(a, j+1, last, ncols, sortcol) -end subroutine quicksort - -subroutine swap(a,b) - real, intent(inout) :: a,b - real :: c - - c = a - a = b - b = c - -end subroutine swap - - -!---------------------------------------------------------------- -!+ -! Determine ID of planet particles based on distance from host star core -!+ -!---------------------------------------------------------------- -subroutine get_planetIDs(nplanet,planetIDs) - integer, allocatable, intent(out) :: planetIDs(:) - integer, intent(out) :: nplanet - integer :: i - - ! Determine planet particle IDs (the nplanet particles initially farthest from the donor star) - nplanet = 1262 - call prompt('Enter number of planet particles:',nplanet,0) - allocate(planetIDs(nplanet)) - do i = 1,nplanet - planetIDs(i) = i - enddo - -end subroutine get_planetIDs - - -!---------------------------------------------------------------- -!+ -! Set EOS options for analysis -!+ -!---------------------------------------------------------------- -subroutine set_eos_options(analysis_to_perform) - integer, intent(in) :: analysis_to_perform - integer :: ierr - - ieos = 2 - call prompt('Enter ieos:',ieos) - select case(ieos) - 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 - case(10,20) - gamma = 5./3. - X_in = 0.69843 - Z_in = 0.01426 - call prompt('Enter hydrogen mass fraction:',X_in,0.,1.) - call prompt('Enter metallicity:',Z_in,0.,1.) - irecomb = 0 - if (ieos==20) call prompt('Using gas+rad+rec EoS. Enter irecomb:',irecomb,0,2) - case default - call fatal('analysis_common_envelope',"EOS type not supported") - end select - call init_eos(ieos,ierr) - if (ierr /= 0) call fatal('analysis_common_envelope',"Failed to initialise EOS") - -end subroutine set_eos_options - - -!---------------------------------------------------------------- -!+ -! Calculates escape velocity for all SPH particles given the potential energy -! of the system at that time -!+ -!---------------------------------------------------------------- -subroutine calc_escape_velocities(particlemass,poten,xyzh,vxyzu,xyzmh_ptmass,phii,epoti,v_esc) - use ptmass, only:get_accel_sink_gas - use part, only:nptmass - real, intent(in) :: particlemass - real(4), intent(in) :: poten - real, dimension(4), intent(in) :: xyzh,vxyzu - real, dimension(5,nptmass), intent(in) :: xyzmh_ptmass - real :: phii,epoti - real :: fxi,fyi,fzi - real, intent(out) :: v_esc - - phii = 0.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 - v_esc = sqrt(2*abs(epoti/particlemass)) - -end subroutine calc_escape_velocities - -end module analysis diff --git a/src/utils/analysis_dustywind.F90 b/src/utils/analysis_dustywind.F90 deleted file mode 100644 index 2485a4fad..000000000 --- a/src/utils/analysis_dustywind.F90 +++ /dev/null @@ -1,348 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module analysis -! -! Analysis routine for dusty wind testing -! -! :References: None -! -! :Owner: Lionel Siess -! -! :Runtime parameters: None -! -! :Dependencies: dim, dust_formation, kernel, part, units -! - - implicit none - character(len=20), parameter, public :: analysistype = 'dustywind' - - public :: do_analysis - - private - integer, parameter :: N = 1024 !32 - double precision, parameter :: theta = 0., phi = 0. - double precision, parameter :: u(3) = (/ sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta) /) - -contains - -subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) - - use part, only: nptmass,xyzmh_ptmass,vxyz_ptmass,iLum,iTeff,iReff - use part, only: dust_temp,isdead_or_accreted,nucleation - use dust_formation, only: set_abundances - - !general variables - character(len=*), intent(in) :: dumpfile - integer, intent(in) :: num,npart,iunit - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - real, intent(in) :: particlemass,time - - real :: L_star,T_star,R_star,xa,ya,za - integer :: j - - call set_abundances - !property of the sink particle - j = 1 - T_star = xyzmh_ptmass(iTeff,j) - L_star = xyzmh_ptmass(iLum,j) - R_star = xyzmh_ptmass(iReff,j) !sqrt(L_star/(4.*pi*steboltz*utime**3/umass*R_star**4)) - xa = xyzmh_ptmass(1,j) - ya = xyzmh_ptmass(2,j) - za = xyzmh_ptmass(3,j) - call get_Teq_from_Lucy(npart,xyzh,xa,ya,za,R_star,T_star,dust_temp) - - -end subroutine do_analysis - -!------------------------------------------------------------------------------- -!+ -! Calculates the radiative equilibrium temperature using the Lucy approximation -! Performs ray-tracing along 1 direction (could be generalized to include other directions) -!+ -!------------------------------------------------------------------------------- -subroutine get_Teq_from_Lucy(npart,xyzh,xa,ya,za,R_star,T_star,dust_temp) - use part, only:isdead_or_accreted,nucleation,idK3 - use dim, only:do_nucleation - integer, intent(in) :: npart - real, intent(in) :: xyzh(:,:),xa,ya,za,R_star,T_star - real, intent(out) :: dust_temp(:) - real :: r(3),r0(3),d,dmin,dmax,d2_axis,OR(N),Teq(N),K3(N),rho_over_r2(2*N+1),rho(N) - integer :: i,idx_axis(npart),naxis - - !.. find particles that lie within 2 smoothing lengths of the ray axis - r0(1:3) = (/xa, ya, za/) - dmin = 1.d99 - dmax = 0 - naxis = 0 -!$omp parallel do default(none) & -!$omp shared(npart,xyzh,r0,naxis,idx_axis) & -!$omp private(i,r,d,d2_axis) & -!$omp reduction(min:dmin) & -!$omp reduction(max:dmax) - do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - r = xyzh(1:3,i)-r0 - !d = r(1)**2+r(2)**2+r(3)**2 - d = dot_product(r,r) - dmin = min(d,dmin) - dmax = max(d,dmax) - !distance to the axis - !d2_axis = sq_distance_to_z(r) - d2_axis = sq_distance_to_line(r,u) - if (d2_axis < 4.*xyzh(4,i)*xyzh(4,i)) then - !$omp critical (crit_naxis_add) - naxis = naxis+1 - idx_axis(naxis) = i - !$omp end critical (crit_naxis_add) - endif - endif - enddo -!$omp end parallel do - dmin = sqrt(dmin) - dmax = sqrt(dmax) - - - if (do_nucleation) then - call density_along_line(npart, xyzh, r0, naxis, idx_axis, -dmax, dmax, R_star, N, rho, & - rho_over_r2, dust_temp, Teq, nucleation(idK3,:), K3) - call calculate_Teq(N, dmax, R_star, T_star, rho, rho_over_r2, OR, Teq, K3) - else - call density_along_line(npart, xyzh, r0, naxis, idx_axis, -dmax, dmax, R_star, N, rho, & - rho_over_r2, dust_temp, Teq) - call calculate_Teq(N, dmax, R_star, T_star, rho, rho_over_r2, OR, Teq) - endif - call interpolate_on_particles(npart, N, dmax, r0, Teq, dust_temp, xyzh) - -end subroutine get_Teq_from_Lucy - -!-------------------------------------------------------------------------- -!+ -! Calculates the radiative equilibrium temperature along the ray direction -!+ -!-------------------------------------------------------------------------- -subroutine calculate_Teq(N, dmax, R_star, T_star, rho, rho_over_r2, OR, Teq, K3) - use dust_formation, only : calc_kappa_dust,calc_kappa_bowen,idust_opacity - integer, intent(in) :: N - real, intent(in) :: dmax, R_star, T_star, rho(N), rho_over_r2(2*N+1) - real, optional, intent(in) :: K3(N) - real, intent(out) :: Teq(N) - - real :: OR(N),tau_prime(N),vTeq(N),kappa(N),dTeq,pTeq(N) - real :: dr, fact, rho_on_r2(N) - real, parameter :: tol = 1.d-2, kap_gas = 2.d-4 - integer :: i,istart,iter - - - tau_prime = 0. - iter = 0 - vTeq = 0. - dTeq = 1. - dr = dmax/N - forall(i=1:N) OR(i) = i*dr - OR(N) = dmax - fact = dr/2. * R_star**2 - do i = 1,N - if (OR(i) > R_star) exit - enddo - istart = i-1 - if (istart > 0) Teq(1:istart) = T_star - Teq(istart+1:N) = T_star*(0.5*(1.-sqrt(1.-(R_star/OR(istart+1:N))**2))) - vTeq = Teq - pTeq= Teq - rho_on_r2 = 0. - kappa = 0. - - do while (dTeq > tol .and. iter < 20) - if (iter == 0) dTeq = 0. - iter = iter+1 - do i=N-1,istart+1,-1 - if (idust_opacity == 2) then - if (rho(i) > 0.) then - kappa(i) = calc_kappa_dust(K3(i),Teq(i),rho(i)) - else - kappa(i) = 0.d0 - endif - elseif (idust_opacity == 1) then - kappa(i) = calc_kappa_bowen(Teq(i)) - endif - rho_on_r2(i) = rho_over_r2(N-i)+rho_over_r2(N-i+1)+rho_over_r2(N+i+1)+rho_over_r2(N+i+2) - !if (iter >= 1) print *,'teq loop',i,K3(i),Teq(i),kappa(i),rho_on_r2(i) - tau_prime(i) = tau_prime(i+1) + fact*(kappa(i)+kap_gas) *rho_on_r2(i) - - Teq(i) = T_star*(0.5*(1.-sqrt(1.-(R_star/OR(i))**2)) + 0.75*tau_prime(i))**(1./4.) - dTeq = max(dTeq,abs(1.-Teq(i)/(1.d-5+vTeq(i)))) - vTeq(i) = Teq(i) - enddo - print *,iter,dTeq - enddo - print *,iter - open(unit=220,file='Teq.dat') - write(220,*) '# ng z vTeq Teq tau kappa rho_on_r2' - do i = 1,N - write(220,*) i,OR(i),pTeq(i),Teq(i),tau_prime(i),kappa(i),rho_on_r2(i) - enddo - close(220) - -end subroutine calculate_Teq - -!----------------------------------------------------------------------- -!+ -! compute the mean properties along the ray -!+ -!----------------------------------------------------------------------- -subroutine density_along_line(npart, xyzh, r0, npart_axis, idx_axis, rmin, rmax, r_star, N, & - rho_cgs, rho_over_r2, T, Teq, K3, K3i) - use kernel, only:cnormk,wkern - use part, only:massoftype,igas,rhoh - use units, only:unit_density - integer, intent(in) :: npart,N - real, intent(in) :: xyzh(:,:), T(:), r0(3) - real, optional, intent(in) :: K3(:) - integer, intent(in) :: npart_axis, idx_axis(npart) - real, intent(in) :: rmin, rmax, R_star - real, intent(out) :: rho_over_r2(2*N+1), Teq(N), rho_cgs(N) - real, optional, intent(out) :: K3i(N) - real :: rhoi(2*N+1), OR(2*N+1), Ti(2*N+1), Ki(2*N+1), xnorm(2*N+1) - real :: OH, d2_axis, HR, q2, q, fact0, fact, h, h2, part_mass - real :: delta_r, rmin_o, rmin_p, rmax_p, dr, r(3), xfact, rhoinv - integer :: i, np, j, j_min, j_max, Nr - -! Discretization of the line of sight in N segments - Nr = 2*N+1 - dr = (rmax-rmin)/(Nr-1) - rmin_o = rmin - dr - do i=1,Nr - OR(i) = dr*i+rmin_o - print *,i,OR(i),R_star - enddo - print *,'*******',rmax,rmin,r_star - - open(unit=220,file='allpart.dat') - write(220,*) '# ng x y z rho T K' - do i = 1, npart - write (220,*) np,xyzh(1:3,i)-r0(3),rhoh(xyzh(4,i),part_mass),T(i),K3(i) - enddo - close(220) - rhoi(:) = 0. - Teq(:) = 0. - K3i(:) = 0. - Ki(:) = 0. - Ti(:) = 0. - xnorm(:) = 0. - part_mass = massoftype(igas) - fact0 = part_mass*cnormk - open(unit=221,file='part_axis.dat') - write(221,*) '# ng x y z rho T K' - do i = 1, npart_axis - np = idx_axis(i) - r = xyzh(1:3,np)-r0(3) - !distance to z-axis - !OH = r(3) - !d2_axis = sq_distance_to_z(r) - OH = dot_product(r,u) - d2_axis = sq_distance_to_line(r,u) - h = xyzh(4,np) - h2 = h*h - delta_r = sqrt(4.*h2 - d2_axis) - ! rmin_p and rmax_p are the positions on the line of the two intersections between the line and the interaction sphere - rmin_p = OH-delta_r - rmax_p = OH+delta_r - j_min = ceiling((rmin_p-rmin_o)/dr) - j_max = floor((rmax_p-rmin_o)/dr) - j_min = max(1, j_min) - j_max = min(Nr, j_max) - ! Adds the contribution of particle np to density at all the discretized locations in the interaction sphere - fact = fact0/h**3 - rhoinv = 1./rhoh(h,part_mass) - write (221,*) np,r,rhoh(h,part_mass),T(np),K3(np) - do j=j_min, j_max - HR = OR(j) - OH - q2 = (d2_axis+HR**2)/h2 - q = sqrt(q2) - xfact = fact*wkern(q2,q) - rhoi(j) = rhoi(j) + xfact - xnorm(j) = xnorm(j)+xfact*rhoinv - Ti(j) = Ti(j) + xfact*rhoinv*T(np) - if (present(K3)) Ki(j) = Ki(j) + xfact*rhoinv*K3(np) - !print *,j,Ti(j),T(np),part_mass/(rhoh(h,part_mass)*h**3)!rhoh(h,part_mass),part_mass,q,fact,wkern(q2,q) - enddo - enddo - close (221) -! rho_over_r2 = 0 inside the star so that we do not divide by zero! - open(unit=222,file='ray.dat') - write(222,*) '# ng z rho T K xnorm rho_over_r2' - do j=1,Nr - if (xnorm(j) > 0.) then - Ti(j) = Ti(j)/xnorm(j) - if (present(K3)) Ki(j) = Ki(j) /xnorm(j) - endif - if (abs(OR(j)) < r_star) then - rho_over_r2(j) = 0. - else - rho_over_r2(j) = rhoi(j)/OR(j)**2 - endif - print *,j,rho_over_r2(j) - write (222,*) j,OR(j),rhoi(j),Ti(j),Ki(j),xnorm(j),rho_over_r2(j) - enddo - close(222) - do j=1,N - rho_cgs(N+1-j) = (rhoi(j)+rhoi(2*N-j+2))*unit_density/2. - Teq(N+1-j) = (Ti(j)+Ti(2*N-j+2))/2. - if (present(K3)) K3i(N+1-j) = (Ki(j)+Ki(2*N-j+2))/2. -! print *,'k3i',j,k3i(j) - enddo - -end subroutine density_along_line - -!----------------------------------------------------------------------- -!+ -! Interpolates a quantity computed on the discretized line of sight for all SPH particles -! (spherical symmetry assumed) -!+ -!----------------------------------------------------------------------- -subroutine interpolate_on_particles(npart, N, dmax, r0, Teq, dust_temp, xyzh) - use part, only:isdead_or_accreted - integer, intent(in) :: npart, N - real, intent(in) :: dmax, r0(3), Teq(N), xyzh(:,:) - real, intent(out) :: dust_temp(:) - - real :: r(3), d, dr, d2 - integer :: i, j - - dr = dmax / N - !should start at nwall - do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - r = xyzh(1:3,i) - r0 - d2 = dot_product(r,r) - d = sqrt(d2) - j = min(int(d/dr),N-1) - dust_temp(i) = (d-dr*j)*(Teq(j+1)-Teq(j))/dr + Teq(j) - endif - enddo - open(unit=220,file='all_final.dat') - write(220,*) '# ng x y z T' - do i = 1, npart - write (220,*) i,xyzh(1:3,i)-r0(3),dust_temp(i) - enddo - close(220) -end subroutine interpolate_on_particles - -real function sq_distance_to_z(r) - real, intent(in) :: r(3) - sq_distance_to_z = r(1)*r(1)+r(2)*r(2) -end function sq_distance_to_z - -real function sq_distance_to_line(r,u) - real, intent(in) :: r(3),u(3) - real :: p,d(3) - p = dot_product(r,u) - d = r-p*u - sq_distance_to_line = dot_product(d,d) -end function sq_distance_to_line - -end module analysis diff --git a/src/utils/analysis_kdtree.F90 b/src/utils/analysis_kdtree.F90 index 9ebd7492d..ef83ee5e3 100644 --- a/src/utils/analysis_kdtree.F90 +++ b/src/utils/analysis_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_protostar_environ.F90 b/src/utils/analysis_protostar_environ.F90 index 94c362c9c..6ac1dcd41 100644 --- a/src/utils/analysis_protostar_environ.F90 +++ b/src/utils/analysis_protostar_environ.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/analysis_write_kdtree.F90 b/src/utils/analysis_write_kdtree.F90 index 777dcbf29..a185c915d 100644 --- a/src/utils/analysis_write_kdtree.F90 +++ b/src/utils/analysis_write_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module analysis ! diff --git a/src/utils/interpolate3D_amr.F90 b/src/utils/interpolate3D_amr.F90 index 6bc232f05..49a9eb8b7 100644 --- a/src/utils/interpolate3D_amr.F90 +++ b/src/utils/interpolate3D_amr.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module interpolations3D_amr ! diff --git a/src/utils/struct_part.F90 b/src/utils/struct_part.F90 deleted file mode 100644 index 44ffa447e..000000000 --- a/src/utils/struct_part.F90 +++ /dev/null @@ -1,269 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module structurefn_part -! -! module for obtaining structure functions -! direct from SPH particles -! -! :References: None -! -! :Owner: Daniel Price -! -! :Runtime parameters: None -! -! :Dependencies: random, timing -! - implicit none - -contains - -subroutine get_structure_fn(sf,nbins,norder,distmin,distmax,xbins,ncount,npart,xyz,vel,& - rho,dxbox,dybox,dzbox,massweighted,ierr) - !use fastmath, only:finvsqrt - use timing, only:get_timings,print_time - use random, only:ran2 - integer, intent(in) :: npart,nbins,norder - real, intent(in) :: xyz(:,:) - real, intent(in) :: vel(:,:) - real, intent(in) :: rho(:) - real(kind=8), intent(out) :: sf(2,norder,nbins) - real, intent(out) :: xbins(nbins) - integer(kind=8), intent(out) :: ncount(nbins) - real, intent(in) :: distmax,distmin - real, intent(in) :: dxbox,dybox,dzbox - logical, intent(in) :: massweighted - integer, intent(out) :: ierr - - real(kind=8) :: sfprev(2,norder,nbins) - integer, allocatable :: list(:) - integer :: i,iran,ipart,ipt,iorder,ibin,iseed,npts,isf,nptstot,its - real :: err(norder),sfmax(norder) - real :: xpt(3),velpt(3) - real :: dxbin,dvx,dvy,dvz,dx,dy,dz,rij1,rij - real(kind=4) :: t1,t2,tcpu1,tcpu2 - real :: rij2,distmin2,ddxbin,minusdistminddxbin - real :: dvdotr,dvterm,dvtrans,rhomax,errtot,temp - real(kind=8) :: dvdotrterm,dvtransterm -!$ integer :: omp_get_num_threads - logical :: converged -! -!--set up the distance bins (linear) -! - dxbin = (distmax-distmin)/float(nbins-1) - do ibin=1,nbins - xbins(ibin) = distmin + (ibin-0.5)*dxbin - enddo - distmin2 = distmin*distmin - ddxbin = 1./dxbin - minusdistminddxbin = -distmin*ddxbin - ierr = 0 -! -!--set structure functions to zero -! - sf(:,:,:) = 0. - sfprev(:,:,:) = 0. - ncount(:) = 0 - iseed = -128 - npts = min(128,npart) - nptstot = 0 - its = 0 -! -!--start with a low number of points, and we keep adding more -! points until the structure function calculation is converged -! - converged = .false. - !$omp parallel - !$omp master -!$ print*,' Using ',omp_get_num_threads(),' cpus' - !$omp end master - !$omp end parallel - - iterations: do while(nptstot <= npart .and. .not.converged) - - its = its + 1 - nptstot = nptstot + npts - print "(a,i2,2(a,i10),a)",' Iteration ',its,': adding ',npts,' sample particles (',nptstot,' in total)' - if (allocated(list)) deallocate(list) - allocate(list(npts),stat=ierr) - if (ierr /= 0) then - print*,' error: cannot allocate memory for ',npts,' sample particles ' - sf = sfprev - return - endif - print*,' iseed = ',iseed,' ncount(1:10) = ',ncount(1:10) - - ! - !--choose a random selection of npts particles - ! - if (massweighted) then - ! - !--select particles randomly according to particle id - ! (this preferentially selects particles in dense regions) - ! - do ipt=1,npts - iran = int(ran2(iseed)*npart) + 1 - list(ipt) = iran - enddo - else - ! - !--alternatively, select particles but weight selection by - ! the volume element m/rho, i.e., inversely proportional to rho - ! - rhomax = 0. - !$omp parallel do schedule(static) private(i) reduction(max:rhomax) - do i=1,npart - rhomax = max(rho(i),rhomax) - enddo - if (rhomax <= 0.) then - print*,' ERROR: max density on particles <= 0' - print*,' cannot use volume element weighting for structure fns' - return - endif - ipt = 0 - write(*,"(2x,a,i8,a)",ADVANCE='NO') 'choosing ',npts,' volume-weighted points...' - do while(ipt < npts) -!--first random number chooses the particle - iran = int(ran2(iseed)*npart) + 1 -!--then select particle if rho/rhomax (0..1) is less than -! a second random number - if (rho(iran)/rhomax < ran2(iseed)) then - ipt = ipt + 1 - list(ipt) = iran - endif - enddo - print*,' done' - endif - - call get_timings(t1,tcpu1) - !$omp parallel do schedule(runtime) default(none) & - !$omp shared(npts,xyz,vel,list,npart) & - !$omp firstprivate(distmin2,dxbox,dybox,dzbox,ddxbin,norder,minusdistminddxbin) & - !$omp private(ipt,xpt,velpt,dx,dy,dz,rij2,rij1,rij,dvdotr) & - !$omp private(i,dvx,dvy,dvz) & - !$omp private(dvterm,dvtrans,dvdotrterm,dvtransterm,ibin) & - !$omp reduction(+:ncount) & - !$omp reduction(+:sf) - do ipt=1,npts -#ifndef _OPENMP - if (mod(ipt,100)==0) then - call cpu_time(tcpu2) - print*,' ipt = ',ipt,tcpu2-tcpu1 - endif -#endif - i = list(ipt) - xpt(1) = xyz(1,i) - xpt(2) = xyz(2,i) - xpt(3) = xyz(3,i) - velpt(1) = vel(1,i) - velpt(2) = vel(2,i) - velpt(3) = vel(3,i) - - do ipart=1,npart - dx = xyz(1,ipart) - xpt(1) - dy = xyz(2,ipart) - xpt(2) - dz = xyz(3,ipart) - xpt(3) - !--mod distances with periodic boundary - if (abs(dx) > 0.5*dxbox) dx = dx - dxbox*sign(1.0,dx) - if (abs(dy) > 0.5*dybox) dy = dy - dybox*sign(1.0,dy) - if (abs(dz) > 0.5*dzbox) dz = dz - dzbox*sign(1.0,dz) - - rij2 = dx*dx + dy*dy + dz*dz -! -!--work out which distance bin this pair lies in -! exclude pairs which lie closer than the minimum -! separation bin -! - if (rij2 > distmin2) then - dvx = vel(1,ipart) - velpt(1) - dvy = vel(2,ipart) - velpt(2) - dvz = vel(3,ipart) - velpt(3) - - ! rij1 = finvsqrt(rij2) - rij1 = 1./sqrt(rij2) - - dvdotr = abs((dvx*dx + dvy*dy + dvz*dz)*rij1) - dvterm = (dvx*dvx + dvy*dvy + dvz*dvz) - dvdotr*dvdotr - if (dvterm < 0.) dvterm = 0. - dvtrans = sqrt(dvterm) - - rij = 1./rij1 - ibin = int(rij*ddxbin + minusdistminddxbin) + 1 - !if (ibin < 1 .or. ibin > nbins) stop 'ibin out of range' - - dvdotrterm = 1.0d0 - dvtransterm = 1.0d0 - do iorder=1,norder - dvdotrterm = dvdotrterm*dvdotr ! dvdotrterm = dvdotr**iorder - dvtransterm = dvtransterm*dvtrans ! dvtransterm = dvtrans**iorder - - sf(1,iorder,ibin) = sf(1,iorder,ibin) + dvdotrterm - sf(2,iorder,ibin) = sf(2,iorder,ibin) + dvtransterm - enddo - ncount(ibin) = ncount(ibin) + 1_8 - endif - enddo - enddo - !$omp end parallel do - call get_timings(t2,tcpu2) - call print_time(t2-t1,' wall time :') - call print_time(tcpu2-tcpu1,' cpu time :') - - err(:) = 0. - sfmax(:) = 0. - !$omp parallel do schedule(runtime) private(ibin) & - !$omp reduction(+:err) & - !$omp reduction(max:sfmax) - do ibin=1,nbins - if (ncount(ibin) > 0) then - do iorder=1,norder - do isf=1,2 - temp = sf(isf,iorder,ibin)/real(ncount(ibin)) - err(iorder) = err(iorder) + (temp - sfprev(isf,iorder,ibin))**2 - sfmax(iorder) = max(sfmax(iorder),temp) - sfprev(isf,iorder,ibin) = temp - enddo - enddo - else - sfprev(:,:,ibin) = 0. - endif - enddo - !$omp end parallel do - - errtot = 0. - do iorder=1,norder - if (sfmax(iorder) > 0.) then - err(iorder) = err(iorder)/sfmax(iorder)**2/real(nbins*2) - endif - errtot = errtot + err(iorder) - print*,' Error in structure function of order ',iorder,' = ',sqrt(err(iorder)) - enddo - errtot = sqrt(errtot/real(norder)) - print*,' mean square error = ',errtot - converged = maxval(sqrt(err(1:norder))) < 1.e-2 .and. errtot < 1.e-2 - npts = min(nptstot,npart-nptstot) - - ! - !--write the iterations to file (debugging only) - ! - !do i=1,nbins - ! write(10+its,*) xbins(i),(sfprev(1,iorder,i),iorder=1,norder) - !enddo - - enddo iterations - - print*,' Converged!' - - !$omp parallel do schedule(static) private(ibin) - do ibin=1,nbins - sf(:,:,ibin) = sfprev(:,:,ibin) - enddo - - if (allocated(list)) deallocate(list) - -end subroutine get_structure_fn - -end module structurefn_part diff --git a/src/utils/utils_getneighbours.F90 b/src/utils/utils_getneighbours.F90 index 6dde04c82..0e889d282 100644 --- a/src/utils/utils_getneighbours.F90 +++ b/src/utils/utils_getneighbours.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module getneighbours ! diff --git a/src/utils/utils_raytracer_all.F90 b/src/utils/utils_raytracer_all.F90 deleted file mode 100644 index fbf41e28f..000000000 --- a/src/utils/utils_raytracer_all.F90 +++ /dev/null @@ -1,1199 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module raytracer_all -! -! raytracer_all -! -! :References: Esseldeurs M., Siess L. et al, 2023, A&A, 674, A122 -! -! :Owner: Mats Esseldeurs -! -! :Runtime parameters: None -! -! :Dependencies: healpix, kernel, linklist, part, units -! - use healpix - implicit none - public :: get_all_tau_outwards, get_all_tau_inwards, get_all_tau_adaptive - private -contains - - !*********************************************************************! - !*************************** ADAPTIVE ****************************! - !*********************************************************************! - - !-------------------------------------------------------------------------- - !+ - ! Calculate the optical depth of each particle, using the adaptive ray- - ! tracing scheme - !+ - ! IN: npart: The number of SPH particles - ! IN: primary: The xyz coordinates of the primary star - ! IN: xyzh: The array containing the particles position+smooting lenght - ! IN: kappa: The array containing the kappa of all SPH particles - ! IN: Rstar: The radius of the star - ! IN: minOrder: The minimal order in which the rays are sampled - ! IN: refineLevel: The amount of orders in which the rays can be - ! sampled deeper - ! IN: refineScheme: The refinement scheme used for adaptive ray selection - !+ - ! OUT: taus: The list of optical depths for each particle - !+ - ! OPT: companion: The xyz coordinates of the companion - ! OPT: Rcomp: The radius of the companion - !+ - !-------------------------------------------------------------------------- -subroutine get_all_tau_adaptive(npart, primary, xyzh, kappa, Rstar, minOrder,& - refineLevel, refineScheme, taus, companion, Rcomp) - integer, intent(in) :: npart, minOrder, refineLevel, refineScheme - real, intent(in) :: primary(3), kappa(:), xyzh(:,:), Rstar - real, optional :: Rcomp, companion(3) - real, intent(out) :: taus(:) - - integer :: i, nrays, nsides, index - real :: normCompanion, theta0, unitCompanion(3), theta, root, dist, vec(3), dir(3) - real, dimension(:,:), allocatable :: dirs - real, dimension(:,:), allocatable :: listsOfDists, listsOfTaus - integer, dimension(:), allocatable :: indices, rays_dim - real, dimension(:), allocatable :: tau, dists - - if (present(companion) .and. present(Rcomp)) then - unitCompanion = companion-primary - normCompanion = norm2(unitCompanion) - theta0 = asin(Rcomp/normCompanion) - unitCompanion = unitCompanion/normCompanion - - call get_rays(npart, primary, companion, Rcomp, xyzh, minOrder, refineLevel, refineScheme, dirs, indices, nrays) - allocate(listsOfDists(200, nrays)) - allocate(listsOfTaus(size(listsOfDists(:,1)), nrays)) - allocate(tau(size(listsOfDists(:,1)))) - allocate(dists(size(listsOfDists(:,1)))) - allocate(rays_dim(nrays)) - - !$omp parallel do private(tau,dist,dir,dists,root,theta) - do i = 1, nrays - tau=0. - dists=0. - dir = dirs(:,i) - theta = acos(dot_product(unitCompanion, dir)) - if (theta < theta0) then - root = sqrt(normCompanion**2*cos(theta)**2-normCompanion**2+Rcomp**2) - dist = normCompanion*cos(theta)-root - call ray_tracer(primary, dir, xyzh, kappa, Rstar, tau, dists, rays_dim(i), dist) - else - call ray_tracer(primary, dir, xyzh, kappa, Rstar, tau, dists, rays_dim(i)) - endif - listsOfTaus(:,i) = tau - listsOfDists(:,i) = dists - enddo - !$omp end parallel do - - nsides = 2**(minOrder+refineLevel) - taus = 0. - !$omp parallel do private(index,vec) - do i = 1, npart - vec = xyzh(1:3,i)-primary - call vec2pix_nest(nsides, vec, index) - index = indices(index + 1) - call get_tau_on_ray(norm2(vec), listsOfTaus(:,index), listsOfDists(:,index), rays_dim(index), taus(i)) - enddo - !$omp end parallel do - - else - call get_all_tau_outwards_single(npart, primary, xyzh, kappa, & - Rstar, minOrder+refineLevel, 0, taus) - endif -end subroutine get_all_tau_adaptive - - !-------------------------------------------------------------------------- - !+ - ! Return all the directions of the rays that need to be traced for the - ! adaptive ray-tracing scheme - !+ - ! IN: npart: The number of SPH particles - ! IN: primary: The xyz coordinates of the primary star - ! IN: companion: The xyz coordinates of the companion - ! IN: Rcomp: The radius of the companion - ! IN: xyzh: The array containing the particles position+smooting lenght - ! IN: minOrder: The minimal order in which the rays are sampled - ! IN: refineLevel: The amount of orders in which the rays can be - ! sampled deeper - ! IN: refineScheme: The refinement scheme used for adaptive ray selection - !+ - ! OUT: rays: A list containing the rays that need to be traced - ! in the adaptive ray-tracing scheme - ! OUT: indices: A list containing a link between the index in the - ! deepest order and the rays in the adaptive ray-tracing scheme - ! OUT: nrays: The number of rays after the ray selection - !+ - !-------------------------------------------------------------------------- -subroutine get_rays(npart, primary, companion, Rcomp, xyzh, minOrder, refineLevel, refineScheme, rays, indices, nrays) - integer, intent(in) :: npart, minOrder, refineLevel, refineScheme - real, intent(in) :: primary(3), companion(3), xyzh(:,:), Rcomp - real, allocatable, intent(out) :: rays(:,:) - integer, allocatable, intent(out) :: indices(:) - integer, intent(out) :: nrays - - real :: theta, dist, phi, cosphi, sinphi - real, dimension(:,:), allocatable :: circ - integer :: i, j, minNsides, minNrays, ind,n, maxOrder, max, distr(12*4**(minOrder+refineLevel)) - integer, dimension(:,:), allocatable :: distrs - - maxOrder = minOrder+refineLevel - nrays = 12*4**(maxOrder) - allocate(rays(3, nrays)) - allocate(indices(12*4**(maxOrder))) - rays = 0. - indices = 0 - - !If there is no refinement, just return the uniform ray distribution - minNsides = 2**minOrder - minNrays = 12*4**minOrder - if (refineLevel == 0) then - do i=1, minNrays - call pix2vec_nest(minNsides,i-1, rays(:,i)) - indices(i) = i - enddo - return - endif - - !Fill a list to have the number distribution in angular space - distr = 0 - !$omp parallel do private(ind) - do i = 1, npart - call vec2pix_nest(2**maxOrder, xyzh(1:3, i)-primary, ind) - distr(ind+1) = distr(ind+1)+1 - enddo - max = maxval(distr) - - !Make sure the companion is described using the highest refinement - dist = norm2(primary-companion) - theta = asin(Rcomp/dist) - phi = atan2(companion(2)-primary(2),companion(1)-primary(1)) - cosphi = cos(phi) - sinphi = sin(phi) - dist = dist*cos(theta) - n = int(theta*6*2**(minOrder+refineLevel))+4 - allocate(circ(n,3)) - do i=1, n !Define boundary of the companion - circ(i,1) = dist*cos(theta) - circ(i,2) = dist*sin(theta)*cos(twopi*i/n) - circ(i,3) = dist*sin(theta)*sin(twopi*i/n) - circ(i,:) = (/cosphi*circ(i,1) - sinphi*circ(i,2),sinphi*circ(i,1) + cosphi*circ(i,2), circ(i,3)/) - enddo - do i=1, n !Make sure the boundary is maximally refined - call vec2pix_nest(2**maxOrder,circ(i,:),ind) - distr(ind+1) = max - enddo - - !Calculate the number distribution in all the orders needed - allocate(distrs(12*4**(minOrder+refineLevel),refineLevel+1)) - distrs = 0 - distrs(:,1) = distr - do i = 1, refineLevel - do j = 1, 12*4**(maxOrder-i) - distrs(j,i+1) = distrs(4*j,i)+distrs(4*j+1,i)+distrs(4*j+2,i)+distrs(4*j+3,i) - enddo - enddo - max = maxval(distrs(:,refineLevel+1))+1 - - !Fill the rays array walking through the orders - ind=1 - - ! refine half in each order - if (refineScheme == 1) then - do i=0, refineLevel-1 - call merge_argsort(distrs(1:12*4**(minOrder+i),refineLevel-i+1), distr) - do j=1, 6*4**minOrder*2**(i) - call pix2vec_nest(2**(minOrder+i), distr(j)-1, rays(:,ind)) - indices(4**(refineLevel-i)*(distr(j)-1)+1:4**(refineLevel-i)*distr(j)) = ind - ind=ind+1 - distrs(4*(distr(j)-1)+1:4*(distr(j)), refineLevel-i) = max - enddo - do j = j+1, 12*4**(minOrder+i) - if (distrs(distr(j),refineLevel-i+1) == max) then - distrs(4*(distr(j)-1)+1:4*(distr(j)), refineLevel-i) = max - endif - enddo - enddo - - ! refine overdens regions in each order - elseif (refineScheme == 2) then - do i=0, refineLevel-1 - call merge_argsort(distrs(1:12*4**(minOrder+i),refineLevel-i+1), distr) - j=1 - do while (distrs(distr(j),refineLevel-i+1) 0.) then - tau = tautemp/distRay_sq - weight = 1./distRay_sq - else - ! the particle sits exactly on the ray, no need to get the neighbours - tau = tautemp - return - endif - - !returns the number nneigh and list of vectors (n) neighbouring the ray number index - call neighbours_nest(nsides, rayIndex, neighbours, nneigh) - !for each neighbouring ray calculate its distance to the particle - do i=1,nneigh - call pix2vec_nest(nsides, neighbours(i), ray) - vectemp = vec - vec_norm2*ray - tempdist(i) = norm2(vectemp) - enddo - neighbours = neighbours+1 - mask = .true. - if (nneigh <8) mask(nneigh+1:8) = .false. - !take tau contribution from the 3 closest rays - do i=1,3 - k = minloc(tempdist,1,mask) - mask(k) = .false. - call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & - rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) - tau = tau + tautemp/tempdist(k) - weight = weight + 1./tempdist(k) - enddo - tau = tau / weight - - ! 9 rays, linear interpolation - elseif (raypolation==2) then - vec_norm2 = norm2(vec) - !returns rayIndex, the index of the ray vector that points to the particle (direction vec) - call vec2pix_nest(nsides, vec, rayIndex) - !returns ray(3), the unit vector identifying the ray with index number rayIndex - call pix2vec_nest(nsides, rayIndex, ray) - vectemp = vec - vec_norm2*ray - distRay_sq = norm2(vectemp) - call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) - if (distRay_sq > 0.) then - tau = tautemp/distRay_sq - weight = 1./distRay_sq - else - ! the particle sits exactly on the ray, no need to get the neighbours - tau = tautemp - return - endif - - !returns the number nneigh and list of vectors (n) neighbouring the ray number index - call neighbours_nest(nsides, rayIndex, neighbours, nneigh) - !for each neighbouring ray calculate its distance to the particle - do i=1,nneigh - call pix2vec_nest(nsides, neighbours(i), ray) - vectemp = vec - vec_norm2*ray - tempdist(i) = norm2(vectemp) - enddo - neighbours = neighbours+1 - mask = .true. - if (nneigh <8) mask(nneigh+1:8) = .false. - !take tau contribution from the 3 closest rays - do i=1,nneigh - k = minloc(tempdist,1,mask) - mask(k) = .false. - call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & - rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) - tau = tau + tautemp/tempdist(k) - weight = weight + 1./tempdist(k) - enddo - tau = tau / weight - - ! 4 rays, square interpolation - elseif (raypolation==3) then - vec_norm2 = norm2(vec) - !returns rayIndex, the index of the ray vector that points to the particle (direction vec) - call vec2pix_nest(nsides, vec, rayIndex) - !returns ray(3), the unit vector identifying the ray with index number rayIndex - call pix2vec_nest(nsides, rayIndex, ray) - vectemp = vec - vec_norm2*ray - distRay_sq = dot_product(vectemp,vectemp) - call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) - if (distRay_sq > 0.) then - tau = tautemp/distRay_sq - weight = 1./distRay_sq - else - ! the particle sits exactly on the ray, no need to get the neighbours - tau = tautemp - return - endif - - !returns the number nneigh and list of vectors (n) neighbouring the ray number index - call neighbours_nest(nsides, rayIndex, neighbours, nneigh) - !for each neighbouring ray calculate its distance to the particle - do i=1,nneigh - call pix2vec_nest(nsides, neighbours(i), ray) - vectemp = vec - vec_norm2*ray - tempdist(i) = dot_product(vectemp,vectemp) - enddo - neighbours = neighbours+1 - mask = .true. - if (nneigh <8) mask(nneigh+1:8) = .false. - !take tau contribution from the 3 closest rays - do i=1,3 - k = minloc(tempdist,1,mask) - mask(k) = .false. - call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & - rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) - tau = tau + tautemp/tempdist(k) - weight = weight + 1./tempdist(k) - enddo - tau = tau / weight - - ! 9 rays, square interpolation - elseif (raypolation==4) then - vec_norm2 = norm2(vec) - !returns rayIndex, the index of the ray vector that points to the particle (direction vec) - call vec2pix_nest(nsides, vec, rayIndex) - !returns ray(3), the unit vector identifying the ray with index number rayIndex - call pix2vec_nest(nsides, rayIndex, ray) - vectemp = vec - vec_norm2*ray - distRay_sq = dot_product(vectemp,vectemp) - call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) - if (distRay_sq > 0.) then - tau = tautemp/distRay_sq - weight = 1./distRay_sq - else - ! the particle sits exactly on the ray, no need to get the neighbours - tau = tautemp - return - endif - - !returns the number nneigh and list of vectors (n) neighbouring the ray number index - call neighbours_nest(nsides, rayIndex, neighbours, nneigh) - !for each neighbouring ray calculate its distance to the particle - do i=1,nneigh - call pix2vec_nest(nsides, neighbours(i), ray) - vectemp = vec - vec_norm2*ray - tempdist(i) = dot_product(vectemp,vectemp) - enddo - neighbours = neighbours+1 - mask = .true. - if (nneigh <8) mask(nneigh+1:8) = .false. - !take tau contribution from the 3 closest rays - do i=1,nneigh - k = minloc(tempdist,1,mask) - mask(k) = .false. - call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & - rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) - tau = tau + tautemp/tempdist(k) - weight = weight + 1./tempdist(k) - enddo - tau = tau / weight - - ! 4 rays, cubed interpolation - elseif (raypolation==5) then - vec_norm2 = norm2(vec) - !returns rayIndex, the index of the ray vector that points to the particle (direction vec) - call vec2pix_nest(nsides, vec, rayIndex) - !returns ray(3), the unit vector identifying the ray with index number rayIndex - call pix2vec_nest(nsides, rayIndex, ray) - vectemp = vec - vec_norm2*ray - distRay_sq = norm2(vectemp)**3 - call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) - if (distRay_sq > 0.) then - tau = tautemp/distRay_sq - weight = 1./distRay_sq - else - ! the particle sits exactly on the ray, no need to get the neighbours - tau = tautemp - return - endif - - !returns the number nneigh and list of vectors (n) neighbouring the ray number index - call neighbours_nest(nsides, rayIndex, neighbours, nneigh) - !for each neighbouring ray calculate its distance to the particle - do i=1,nneigh - call pix2vec_nest(nsides, neighbours(i), ray) - vectemp = vec - vec_norm2*ray - tempdist(i) = norm2(vectemp)**3 - enddo - neighbours = neighbours+1 - mask = .true. - if (nneigh <8) mask(nneigh+1:8) = .false. - !take tau contribution from the 3 closest rays - do i=1,3 - k = minloc(tempdist,1,mask) - mask(k) = .false. - call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & - rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) - tau = tau + tautemp/tempdist(k) - weight = weight + 1./tempdist(k) - enddo - tau = tau / weight - - ! 9 rays, cubed interpolation - elseif (raypolation==6) then - vec_norm2 = norm2(vec) - !returns rayIndex, the index of the ray vector that points to the particle (direction vec) - call vec2pix_nest(nsides, vec, rayIndex) - !returns ray(3), the unit vector identifying the ray with index number rayIndex - call pix2vec_nest(nsides, rayIndex, ray) - vectemp = vec - vec_norm2*ray - distRay_sq = norm2(vectemp)**3 - call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) - if (distRay_sq > 0.) then - tau = tautemp/distRay_sq - weight = 1./distRay_sq - else - ! the particle sits exactly on the ray, no need to get the neighbours - tau = tautemp - return - endif - - !returns the number nneigh and list of vectors (n) neighbouring the ray number index - call neighbours_nest(nsides, rayIndex, neighbours, nneigh) - !for each neighbouring ray calculate its distance to the particle - do i=1,nneigh - call pix2vec_nest(nsides, neighbours(i), ray) - vectemp = vec - vec_norm2*ray - tempdist(i) = norm2(vectemp)**3 - enddo - neighbours = neighbours+1 - mask = .true. - if (nneigh <8) mask(nneigh+1:8) = .false. - !take tau contribution from the 3 closest rays - do i=1,nneigh - k = minloc(tempdist,1,mask) - mask(k) = .false. - call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & - rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) - tau = tau + tautemp/tempdist(k) - weight = weight + 1./tempdist(k) - enddo - tau = tau / weight - endif -end subroutine interpolate_tau - - - !-------------------------------------------------------------------------- - !+ - ! Interpolation of the optical depth for an arbitrary point on the ray, - ! with a given distance to the starting point of the ray. - !+ - ! IN: distance: The distance from the staring point of the ray to a - ! point on the ray - ! IN: tau_along_ray: The vector of cumulative optical depths along the ray - ! IN: dist_along_ray: The vector of distances from the primary along the ray - ! IN: len: The length of listOfTau and listOfDist - !+ - ! OUT: tau: The optical depth to the given distance along the ray - !+ - !-------------------------------------------------------------------------- -subroutine get_tau_on_ray(distance, tau_along_ray, dist_along_ray, len, tau) - real, intent(in) :: distance, tau_along_ray(:), dist_along_ray(:) - integer, intent(in) :: len - real, intent(out) :: tau - - integer :: L, R, m ! left, right and middle index for binary search - - if (distance < dist_along_ray(1)) then - tau = 0. - elseif (distance > dist_along_ray(len)) then - tau = 99. - else - L = 2 - R = len-1 - !bysection search for the index of the closest ray location to the particle - do while (L < R) - m = (L + R)/2 - if (dist_along_ray(m) > distance) then - R = m - else - L = m + 1 - endif - enddo - !interpolate linearly ray properties to get the particle's optical depth - tau = tau_along_ray(L-1)+(tau_along_ray(L)-tau_along_ray(L-1))/ & - (dist_along_ray(L)-dist_along_ray(L-1))*(distance-dist_along_ray(L-1)) - endif -end subroutine get_tau_on_ray - - !-------------------------------------------------------------------------- - !+ - ! Calculate the optical depth along a given ray - !+ - ! IN: primary: The location of the primary star - ! IN: ray: The unit vector of the direction in which the - ! optical depts will be calculated - ! IN: xyzh: The array containing the particles position+smooting lenght - ! IN: kappa: The array containing the particles opacity - ! IN: Rstar: The radius of the primary star - !+ - ! OUT: taus: The distribution of optical depths throughout the ray - ! OUT: listOfDists: The distribution of distances throughout the ray - ! OUT: len: The length of tau_along_ray and dist_along_ray - !+ - ! OPT: maxDistance: The maximal distance the ray needs to be traced - !+ - !-------------------------------------------------------------------------- -subroutine ray_tracer(primary, ray, xyzh, kappa, Rstar, tau_along_ray, dist_along_ray, len, maxDistance) - use linklist, only:getneigh_pos,ifirstincell,listneigh - use kernel, only:radkern - use units, only:umass,udist - real, intent(in) :: primary(3), ray(3), Rstar, xyzh(:,:), kappa(:) - real, optional :: maxDistance - real, intent(out) :: dist_along_ray(:), tau_along_ray(:) - integer, intent(out) :: len - - integer, parameter :: maxcache = 0 - real, allocatable :: xyzcache(:,:) - real :: distance, h, dtaudr, previousdtaudr, nextdtaudr - integer :: nneigh, inext, i - - distance = Rstar - - h = Rstar/100. - inext=0 - do while (inext==0) - h = h*2. - call getneigh_pos(primary+Rstar*ray,0.,h,3,listneigh,nneigh,xyzh,xyzcache,maxcache,ifirstincell) - call find_next(primary, ray, distance, xyzh, listneigh, inext, nneigh) - enddo - call calc_opacity(primary+Rstar*ray, xyzh, kappa, listneigh, nneigh, previousdtaudr) - - i = 1 - tau_along_ray(i) = 0. - distance = Rstar - dist_along_ray(i) = distance - do while (hasNext(inext,tau_along_ray(i),distance,maxDistance)) - i = i + 1 - call getneigh_pos(primary + distance*ray,0.,xyzh(4,inext)*radkern, & - 3,listneigh,nneigh,xyzh,xyzcache,maxcache,ifirstincell) - call calc_opacity(primary + distance*ray, xyzh, kappa, listneigh, nneigh, nextdtaudr) - dtaudr = (nextdtaudr+previousdtaudr)/2 - previousdtaudr = nextdtaudr - tau_along_ray(i) = tau_along_ray(i-1)+(distance-dist_along_ray(i-1))*dtaudr - dist_along_ray(i) = distance - call find_next(primary, ray, distance, xyzh, listneigh, inext,nneigh) - enddo - len = i - tau_along_ray = tau_along_ray*umass/(udist**2) -end subroutine ray_tracer - -logical function hasNext(inext, tau, distance, maxDistance) - integer, intent(in) :: inext - real, intent(in) :: distance, tau - real, optional :: maxDistance - real, parameter :: tau_max = 99. - if (present(maxDistance)) then - hasNext = inext /= 0 .and. distance < maxDistance .and. tau < tau_max - else - hasNext = inext /= 0 .and. tau < tau_max - endif -end function hasNext - - !*********************************************************************! - !**************************** INWARDS ****************************! - !*********************************************************************! - - !-------------------------------------------------------------------------- - !+ - ! Calculate the optical depth of each particle, using the inwards ray- - ! tracing scheme - !+ - ! IN: npart: The number of SPH particles - ! IN: primary: The xyz coordinates of the primary star - ! IN: xyzh: The array containing the particles position+smooting lenght - ! IN: neighbors: A list containing the indices of the neighbors of - ! each particle - ! IN: kappa: The array containing the opacity of all the SPH particles - ! IN: Rstar: The radius of the primary star - !+ - ! OUT: tau: The array of optical depths for each SPH particle - !+ - ! OPT: companion: The location of the companion - ! OPT: R: The radius of the companion - !+ - !-------------------------------------------------------------------------- -subroutine get_all_tau_inwards(npart, primary, xyzh, neighbors, kappa, Rstar, tau, companion, R) - real, intent(in) :: primary(3), kappa(:), Rstar, xyzh(:,:) - integer, intent(in) :: npart, neighbors(:,:) - real, optional :: R, companion(3) - real, intent(out) :: tau(:) - - if (present(companion) .and. present(R)) then - call get_all_tau_inwards_companion(npart, primary, xyzh, neighbors, kappa, Rstar, companion, R, tau) - else - call get_all_tau_inwards_single(npart, primary, xyzh, neighbors, kappa, Rstar, tau) - endif -end subroutine get_all_tau_inwards - - !-------------------------------------------------------------------------- - !+ - ! Calculate the optical depth of each particle, using the inwards ray- - ! tracing scheme concerning only a single star - !+ - ! IN: npart: The number of SPH particles - ! IN: primary: The xyz coordinates of the primary star - ! IN: xyzh: The array containing the particles position+smooting lenght - ! IN: neighbors: A list containing the indices of the neighbors of - ! each particle - ! IN: kappa: The array containing the opacity of all the SPH particles - ! IN: Rstar: The radius of the primary star - !+ - ! OUT: taus: The list of optical depths for each particle - !+ - !-------------------------------------------------------------------------- -subroutine get_all_tau_inwards_single(npart, primary, xyzh, neighbors, kappa, Rstar, tau) - real, intent(in) :: primary(3), kappa(:), Rstar, xyzh(:,:) - integer, intent(in) :: npart, neighbors(:,:) - real, intent(out) :: tau(:) - - integer :: i - - !$omp parallel do - do i = 1, npart - call get_tau_inwards(i, primary, xyzh, neighbors, kappa, Rstar, tau(i)) - enddo - !$omp end parallel do -end subroutine get_all_tau_inwards_single - - !-------------------------------------------------------------------------- - !+ - ! Calculate the optical depth of each particle, using the inwards ray- - ! tracing scheme concerning a binary system - !+ - ! IN: npart: The number of SPH particles - ! IN: primary: The xyz coordinates of the primary star - ! IN: xyzh: The array containing the particles position+smooting lenght - ! IN: neighbors: A list containing the indices of the neighbors of - ! each particle - ! IN: kappa: The array containing the opacity of all the SPH particles - ! IN: Rstar: The radius of the primary star - ! IN: companion: The xyz coordinates of the companion - ! IN: Rcomp: The radius of the companion - !+ - ! OUT: tau: The array of optical depths for each SPH particle - !+ - !-------------------------------------------------------------------------- -subroutine get_all_tau_inwards_companion(npart, primary, xyzh, neighbors, kappa, Rstar, companion, Rcomp, tau) - real, intent(in) :: primary(3), companion(3), kappa(:), Rstar, xyzh(:,:), Rcomp - integer, intent(in) :: npart, neighbors(:,:) - real, intent(out) :: tau(:) - - integer :: i - real :: normCompanion, theta0, uvecCompanion(3), norm, theta, root, norm0 - - uvecCompanion = companion-primary - normCompanion = norm2(uvecCompanion) - uvecCompanion = uvecCompanion/normCompanion - theta0 = asin(Rcomp/normCompanion) - - !$omp parallel do private(norm,theta,root,norm0) - do i = 1, npart - norm = norm2(xyzh(1:3,i)-primary) - theta = acos(dot_product(uvecCompanion, xyzh(1:3,i)-primary)/norm) - if (theta < theta0) then - root = sqrt(normCompanion**2*cos(theta)**2-normCompanion**2+Rcomp**2) - norm0 = normCompanion*cos(theta)-root - if (norm > norm0) then - tau(i) = 99. - else - call get_tau_inwards(i, primary, xyzh, neighbors, kappa, Rstar, tau(i)) - endif - else - call get_tau_inwards(i, primary, xyzh, neighbors, kappa, Rstar, tau(i)) - endif - enddo - !$omp end parallel do -end subroutine get_all_tau_inwards_companion - - !-------------------------------------------------------------------------- - !+ - ! Calculate the optical depth for a given particle, using the inwards ray- - ! tracing scheme - !+ - ! IN: point: The index of the point that needs to be calculated - ! IN: primary: The location of the primary star - ! IN: xyzh: The array containing the particles position+smooting lenght - ! IN: neighbors: A list containing the indices of the neighbors of - ! each particle - ! IN: kappa: The array containing the opacity of all the SPH particles - ! IN: Rstar: The radius of the star - !+ - ! OUT: tau: The list of optical depth of the given particle - !+ - !-------------------------------------------------------------------------- -subroutine get_tau_inwards(point, primary, xyzh, neighbors, kappa, Rstar, tau) - use linklist, only:getneigh_pos,ifirstincell,listneigh - use kernel, only:radkern - use units, only:umass,udist - real, intent(in) :: primary(3), xyzh(:,:), kappa(:), Rstar - integer, intent(in) :: point, neighbors(:,:) - real, intent(out) :: tau - - integer :: i, next, previous, nneigh - integer, parameter :: nmaxcache = 0 - real :: xyzcache(0,nmaxcache) - real :: ray(3), nextDist, previousDist, maxDist, dtaudr, previousdtaudr, nextdtaudr - - ray = primary - xyzh(1:3,point) - maxDist = norm2(ray) - ray = ray / maxDist - maxDist=max(maxDist-Rstar,0.) - next=point - call getneigh_pos(xyzh(1:3,point),0.,xyzh(4,point)*radkern, & - 3,listneigh,nneigh,xyzh,xyzcache,nmaxcache,ifirstincell) - call calc_opacity(xyzh(1:3,point), xyzh, kappa, listneigh, nneigh, nextdtaudr) - nextDist=0. - - tau = 0. - i=1 - do while (nextDist < maxDist .and. next /=0) - i = i + 1 - previous = next - previousDist = nextDist - call find_next(xyzh(1:3,point), ray, nextDist, xyzh, neighbors(next,:), next) - if (nextDist > maxDist) then - nextDist = maxDist - endif - call getneigh_pos(xyzh(1:3,point) + nextDist*ray,0.,xyzh(4,previous)*radkern, & - 3,listneigh,nneigh,xyzh,xyzcache,nmaxcache,ifirstincell) - previousdtaudr=nextdtaudr - call calc_opacity(xyzh(1:3,point) + nextDist*ray, xyzh, kappa, listneigh, nneigh, nextdtaudr) - dtaudr = (nextdtaudr+previousdtaudr)/2 - tau = tau + (nextDist-previousDist)*dtaudr - enddo - !fix units for tau (kappa is in cgs while rho & r are in code units) - tau = tau*umass/(udist**2) -end subroutine get_tau_inwards - - !*********************************************************************! - !**************************** COMMON *****************************! - !*********************************************************************! - - !-------------------------------------------------------------------------- - !+ - ! Find the next point on a ray - !+ - ! IN: inpoint: The coordinate of the initial point projected on the - ! ray for which the next point will be calculated - ! IN: ray: The unit vector of the direction in which the next - ! point will be calculated - ! IN: xyzh: The array containing the particles position+smoothing length - ! IN: neighbors: A list containing the indices of the neighbors of - ! the initial point - ! IN: inext: The index of the initial point - ! (this point will not be considered as possible next point) - !+ - ! OPT: nneighin: The amount of neighbors - !+ - ! OUT: inext: The index of the next point on the ray - !+ - !-------------------------------------------------------------------------- -subroutine find_next(inpoint, ray, dist, xyzh, neighbors, inext, nneighin) - integer, intent(in) :: neighbors(:) - real, intent(in) :: xyzh(:,:), inpoint(:), ray(:) - integer, intent(inout) :: inext - real, intent(inout) :: dist - integer, optional :: nneighin - - real :: trace_point(3), dmin, vec(3), tempdist, raydist - real :: nextdist - integer :: i, nneigh, prev - - dmin = huge(0.) - if (present(nneighin)) then - nneigh = nneighin - else - nneigh = size(neighbors) - endif - - prev=inext - inext=0 - nextDist=dist - trace_point = inpoint + dist*ray - - i = 1 - do while (i <= nneigh .and. neighbors(i) /= 0) - if (neighbors(i) /= prev) then - vec=xyzh(1:3,neighbors(i)) - trace_point - tempdist = dot_product(vec,ray) - if (tempdist>0.) then - raydist = dot_product(vec,vec) - tempdist**2 - if (raydist < dmin) then - dmin = raydist - inext = neighbors(i) - nextdist = dist+tempdist - endif - endif - endif - i = i+1 - enddo - dist=nextdist -end subroutine find_next - - !-------------------------------------------------------------------------- - !+ - ! Calculate the opacity in a given location - !+ - ! IN: r0: The location where the opacity will be calculated - ! IN: xyzh: The xyzh of all the particles - ! IN: opacities: The list of the opacities of the particles - ! IN: neighbors: A list containing the indices of the neighbors of - ! the initial point - ! IN: nneigh: The amount of neighbors - !+ - ! OUT: dtaudr: The local optical depth derivative at the given location (inpoint) - !+ - !-------------------------------------------------------------------------- -subroutine calc_opacity(r0, xyzh, opacities, neighbors, nneigh, dtaudr) - use kernel, only:cnormk,wkern - use part, only:hfact,rhoh,massoftype,igas - real, intent(in) :: r0(:), xyzh(:,:), opacities(:) - integer, intent(in) :: neighbors(:), nneigh - real, intent(out) :: dtaudr - - integer :: i - real :: q - - dtaudr=0 - do i=1,nneigh - q = norm2(r0 - xyzh(1:3,neighbors(i)))/xyzh(4,neighbors(i)) - dtaudr=dtaudr+wkern(q*q,q)*opacities(neighbors(i))*rhoh(xyzh(4,neighbors(i)), massoftype(igas)) - enddo - dtaudr = dtaudr*cnormk/hfact**3 -end subroutine calc_opacity -end module raytracer_all From b373d4d9a10bdafaf6c5807f34c33923f8d226cf Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 11 Apr 2024 12:31:27 +0100 Subject: [PATCH 104/182] restoring upstream changes part 4 --- src/setup/setup_bondi.F90 | 295 ----------- src/setup/setup_photoevap.f90 | 97 ---- src/setup/setup_sphere.f90 | 848 ------------------------------ src/setup/setup_wind.F90 | 828 ----------------------------- src/tests/directsum.f90 | 2 +- src/tests/phantomtest.f90 | 2 +- src/tests/test_cooling.f90 | 2 +- src/tests/test_corotate.f90 | 2 +- src/tests/test_damping.f90 | 2 +- src/tests/test_derivs.F90 | 2 +- src/tests/test_dust.f90 | 2 +- src/tests/test_eos.f90 | 2 +- src/tests/test_eos_stratified.f90 | 2 +- src/tests/test_externf.f90 | 2 +- src/tests/test_externf_gr.f90 | 2 +- src/tests/test_fastmath.F90 | 162 ------ src/tests/test_geometry.f90 | 2 +- src/tests/test_gnewton.f90 | 2 +- src/tests/test_gr.F90 | 557 -------------------- src/tests/test_gravity.F90 | 642 ---------------------- src/tests/test_growth.F90 | 406 -------------- src/tests/test_hierarchical.f90 | 2 +- src/tests/test_indtstep.F90 | 2 +- src/tests/test_kdtree.F90 | 2 +- src/tests/test_kernel.f90 | 2 +- src/tests/test_link.F90 | 2 +- src/tests/test_luminosity.F90 | 2 +- src/tests/test_mpi.F90 | 100 ---- src/tests/test_nonidealmhd.F90 | 2 +- src/tests/test_part.f90 | 2 +- src/tests/test_poly.f90 | 2 +- src/tests/test_ptmass.f90 | 2 +- src/tests/test_radiation.f90 | 5 +- src/tests/test_rwdump.F90 | 2 +- src/tests/test_sedov.F90 | 4 +- src/tests/test_setdisc.f90 | 2 +- src/tests/test_smol.F90 | 2 +- src/tests/test_step.F90 | 2 +- src/tests/utils_testsuite.f90 | 2 +- 39 files changed, 33 insertions(+), 3967 deletions(-) delete mode 100644 src/setup/setup_bondi.F90 delete mode 100644 src/setup/setup_photoevap.f90 delete mode 100644 src/setup/setup_sphere.f90 delete mode 100644 src/setup/setup_wind.F90 delete mode 100644 src/tests/test_fastmath.F90 delete mode 100644 src/tests/test_gr.F90 delete mode 100644 src/tests/test_gravity.F90 delete mode 100644 src/tests/test_growth.F90 delete mode 100644 src/tests/test_mpi.F90 diff --git a/src/setup/setup_bondi.F90 b/src/setup/setup_bondi.F90 deleted file mode 100644 index 10b56c781..000000000 --- a/src/setup/setup_bondi.F90 +++ /dev/null @@ -1,295 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module setup -! -! Setup for Bondi flow problem, for both relativistic and non-relativistic solution -! -! :References: Liptai & Price (2019), MNRAS 485, 819-842 -! -! :Owner: David Liptai -! -! :Runtime parameters: -! - isol : *(1 = geodesic flow | 2 = sonic point flow)* -! - iswind : *wind option (logical)* -! - np : *desired number of particles (stretch-mapping will only give this approx.)* -! - rmax : *outer edge* -! - rmin : *inner edge* -! -! :Dependencies: bondiexact, centreofmass, dim, externalforces, -! infile_utils, io, kernel, metric_tools, options, part, physcon, -! prompting, setup_params, spherical, stretchmap, timestep, units -! - use physcon, only:pi - use externalforces, only:accradius1,accradius1_hard - use dim, only:gr,maxvxyzu - use metric_tools, only:imet_schwarzschild,imetric - use externalforces, only:mass1 - use setup_params, only:rhozero,npart_total - use io, only:master,fatal - use spherical, only:set_sphere - use options, only:ieos,iexternalforce,nfulldump - use timestep, only:tmax,dtmax - use centreofmass, only:reset_centreofmass - use units, only:set_units,get_G_code - use physcon, only:pc,solarm,gg - use part, only:xyzmh_ptmass,vxyz_ptmass,nptmass,ihacc,igas,set_particle_type,iboundary - use stretchmap, only:get_mass_r,rho_func - use kernel, only:radkern - use prompting, only:prompt - use bondiexact, only:get_bondi_solution,rcrit,isol,iswind - implicit none - - public :: setpart - - private - - real :: gamma_eos,rmax,rmin - integer :: np - - logical, parameter :: set_boundary_particles = .false. - -contains - -!---------------------------------------------------------------- -!+ -! setup for bondi accretion -!+ -!---------------------------------------------------------------- -subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) - integer, intent(in) :: id - integer, intent(inout) :: npart - integer, intent(out) :: npartoftype(:) - real, intent(out) :: xyzh(:,:) - real, intent(out) :: massoftype(:) - real, intent(out) :: vxyzu(:,:) - real, intent(out) :: polyk,gamma,hfact - real, intent(inout) :: time - character(len=20), intent(in) :: fileprefix - integer, parameter :: ntab=10000 - real :: rhotab(ntab) - real :: vol,psep,tff,rhor,vr,ur - real :: r,pos(3),cs2,totmass,approx_m,approx_h - integer :: i,ierr,nx,nbound - character(len=100) :: filename - logical :: iexist - procedure(rho_func), pointer :: density_func -! -!-- Set code units -! - call set_units(G=1.d0,c=1.d0) - print*,' G in code units = ',get_G_code() - -! -!--Set general parameters -! - time = 0. - iexternalforce = 1 - - rmin = 7. - rmax = 8. - np = 10000 - - if (gr) then - if (imetric/=imet_schwarzschild) call fatal('setup_bondi',& - 'You are not using the Schwarzschild metric.') - endif - -! -!-- Read things from setup file -! - filename=trim(fileprefix)//'.setup' - print "(/,1x,63('-'),1(/,1x,a),/,1x,63('-'),/)", 'Bondi Flow.' - inquire(file=filename,exist=iexist) - if (iexist) then - call read_setupfile(filename,ierr) - if (ierr /= 0) then - if (id==master) call write_setupfile(filename) - call fatal('setup','failed to read in all the data from .setup. Aborting') - endif - elseif (id==master) then - print "(a,/)",trim(filename)//' not found: using interactive setup' - if (gr) then - call prompt(' Enter solution type isol (1 = geodesic | 2 = sonic point flow) ',isol,1,2) - call prompt(' Do you want a wind (y/n)? ',iswind) - endif - call prompt(' Enter inner edge: ',rmin,0.) - call prompt(' Enter outer edge: ',rmax,rmin) - call prompt(' Enter the desired number of particles: ',np,0) - call write_setupfile(filename) - print*,' Edit '//trim(filename)//' and rerun phantomsetup' - stop - endif - - if (gr) then - ieos = 2 - gamma = 5./3. - polyk = 1. - else - gamma = 1. - ieos = 1 - cs2 = mass1/(2.*rcrit) - polyk = cs2 - endif - - gamma_eos = gamma ! Note, since non rel bondi is isothermal, solution doesn't depend on gamma - accradius1 = 0. - accradius1_hard = 0. - - if (gr) then - rmin = rmin*mass1 - rmax = rmax*mass1 - endif - - vol = 4./3.*pi*(rmax**3 - rmin**3) - nx = int(np**(1./3.)) - psep = vol**(1./3.)/real(nx) - - call get_rhotab(rhotab,rmin,rmax,mass1,gamma) - - density_func => rhofunc - totmass = get_mass_r(density_func,rmax,rmin) - approx_m = totmass/np - approx_h = hfact*(approx_m/rhofunc(rmin))**(1./3.) - rhozero = totmass/vol - - tff = sqrt(3.*pi/(32.*rhozero)) - tmax = 10.*tff - dtmax = tmax/150. - - print*,'' - print*,' Setup for gas: ' - print*,' min,max radius = ',rmin,rmax - print*,' volume = ',vol ,' particle separation = ',psep - print*,' vol/psep**3 = ',vol/psep**3,' totmass = ',totmass - print*,' free fall time = ',tff ,' tmax = ',tmax - print*,'' - -!--- Add stretched sphere - npart = 0 - npart_total = 0 - call set_sphere('closepacked',id,master,rmin,rmax,psep,hfact,npart,& - xyzh,rhotab=rhotab,nptot=npart_total) - massoftype(:) = totmass/npart - print "(a,i0,/)",' npart = ',npart - - nbound = 0 - do i=1,npart - - pos = xyzh(1:3,i) - r = sqrt(dot_product(pos,pos)) - call get_bondi_solution(rhor,vr,ur,r,mass1,gamma) - vxyzu(1:3,i) = vr*pos/r - if (maxvxyzu >= 4) vxyzu(4,i) = ur - - if (set_boundary_particles) then - if (r + radkern*xyzh(4,i)>rmax .or. r - radkern*xyzh(4,i) 1) then - !--grainsizes - call prompt('Enter minimum grain size in cm',smincgs,0.) - call prompt('Enter maximum grain size in cm',smaxcgs,0.) - !--mass distribution - call prompt('Enter power-law index, e.g. MRN',sindex) - !--grain density - call prompt('Enter grain density in g/cm^3',graindenscgs,0.) - else - call prompt('Enter grain size in cm',grainsizecgs,0.) - call prompt('Enter grain density in g/cm^3',graindenscgs,0.) - endif - endif - - if (binary) then - rho_pert_amp = 0.1 - call prompt('Enter the amplitute of the density perturbation ',rho_pert_amp,0.0,0.4) - endif - - ! ask about sink particle details; these will not be saved to the .setup file since they exist in the .in file - ! - call prompt('Do you wish to dynamically create sink particles? ',make_sinks) - if (make_sinks) then - if (binary) then - h_acc_char = '3.35au' - else - h_acc_char = '1.0d-2' - endif - call prompt('Enter the accretion radius of the sink (with units; e.g. au,pc,kpc,0.1pc) ',h_acc_char) - call select_unit(h_acc_char,h_acc_in,ierr) - h_acc_setup = h_acc_in - if (ierr==0 ) h_acc_setup = h_acc_setup/udist - r_crit_setup = 5.0*h_acc_setup - icreate_sinks_setup = 1 - if (binary) h_soft_sinksink_setup = 0.4*h_acc_setup - else - icreate_sinks_setup = 0 - rhofinal_setup = 0.15 - call prompt('Enter final maximum density in g/cm^3 (ignored for <= 0) ',rhofinal_setup) - endif - if (id==master) call write_setupfile(filename) - stop 'please edit .setup file and rerun phantomsetup' - else - stop ! MPI, stop on other threads, interactive on master - endif - ! - ! units - ! - call set_units(dist=udist,mass=umass,G=1.d0) - ! - ! set dust properties - ! - if (use_dust) then - use_dustfrac = .true. - ndustsmall = ndusttypes - if (ndusttypes > 1) then - call set_dustbinfrac(smincgs,smaxcgs,sindex,dustbinfrac(1:ndusttypes),grainsize(1:ndusttypes)) - grainsize(1:ndusttypes) = grainsize(1:ndusttypes)/udist - graindens(1:ndusttypes) = graindenscgs/umass*udist**3 - else - grainsize(1) = grainsizecgs/udist - graindens(1) = graindenscgs/umass*udist**3 - endif - endif - - - - ! general parameters - ! - - vol_sphere = 4./3.*pi*r_sphere**3 - rhozero = totmass_sphere / vol_sphere - dens_sphere = rhozero - - ! call EOS - ieos = 21 - ierr = 0 - call read_optab(eos_file,ierr) - call getintenerg_opdep(T_sphere, dens_sphere*unit_density, u_sphere) - call getopac_opdep(u_sphere,dens_sphere,kappaBar,kappaPart,T_sphere,gmwi) - u_sphere = u_sphere/unit_ergg - time = 0. - if (use_dust) dust_method = 1 - hfact = hfact_default - hfact_out = hfact_default - print *, 'gamma =', gamma, 'u_sphere = ',u_sphere,T_sphere - - rmax = r_sphere - if (angvel_not_betar) then - angvel_code = angvel*utime - else - angvel_code = sqrt(3.0*totmass_sphere*beta_r/r_sphere**3) - angvel = angvel_code/utime - endif - - - totmass = totmass_sphere - t_ff = sqrt(3.*pi/(32.*dens_sphere)) - - przero = dens_sphere * kb_on_mh * T_sphere/gmwi ! code units - gammai = 1.d0 + (przero/u_sphere/dens_sphere) - cs_sphere = sqrt(gammai * przero/dens_sphere) - cs_sphere_cgs = cs_sphere * unit_velocity - polyk = cs_sphere**2 - gamma = 5./3. ! not used but set to keep Phantom happy. - ! - ! setup particles in the sphere; use this routine to get N_sphere as close to np as possible - ! - if (BEsphere) then - call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh, & - rhotab=rhotab(1:iBElast),rtab=rtab(1:iBElast),nptot=npart_total,& - exactN=.true.,np_requested=np,mask=i_belong) - else - call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& - exactN=.true.,np_requested=np,mask=i_belong) - if (trim(lattice)/='random') print "(a,es10.3)",' Particle separation in sphere = ',psep - endif - print "(a)",' Initialised sphere' - npartsphere = npart_total - - ! - ! set particle properties - ! - npartoftype(:) = 0 - npartoftype(igas) = npart - dustfrac = 0. - if (massoftype(igas) < epsilon(massoftype(igas))) massoftype(igas) = totmass/npart_total - do i = 1,npartoftype(igas) - call set_particle_type(i,igas) - if (use_dust .and. dust_method==1) then - if (ndusttypes > 1) then - dustfrac(1:ndusttypes,i) = dustbinfrac(1:ndusttypes)*dtg - else - dustfrac(1,i) = dtg/(1.+dtg) ! call set_dustfrac(dtg,dustfrac(:,i)) - endif - endif - enddo - ! - ! Set two-fluid dust - ! (currently deactivated; will need to re-test before use to ensure it is fully compatible with the current dust algorithms) - ! - if (use_dust .and. dust_method==2) then - ! particle separation in dust sphere & sdjust for close-packed lattice - pmass_dusttogas = 10.*dtg*massoftype(igas) - psep = (vol_sphere/pmass_dusttogas/real(np))**(1./3.) - psep = psep*sqrt(2.)**(1./3.) - call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& - exactN=.true.,np_requested=np/10,mask=i_belong) - npartoftype(idust) = int(npart_total) - npartoftype(igas) - massoftype(idust) = totmass_sphere*dtg/npartoftype(idust) - - do i = npartoftype(igas)+1,npart - call set_particle_type(i,idust) - enddo - - print "(a,4(i10,1x))", ' particle numbers: (gas_total, gas_sphere, dust, total): ' & - , npartoftype(igas),npartsphere,npartoftype(idust),npart - print "(a,2es10.3)" , ' particle masses: (gas,dust): ',massoftype(igas),massoftype(idust) - else - print "(a,3(i10,1x))", ' particle numbers: (sphere, low-density medium, total): ' & - , npartsphere, npart-npartsphere,npart - print "(a,es10.3)",' particle mass = ',massoftype(igas) - endif - ! - ! shuffle particles - ! - if (shuffle_parts) then - print*, "lets shuffle!" - if (BEsphere) then - call shuffleparticles(iprint,npart,xyzh,massoftype(igas),dmedium=dens_medium,ntab=iBElast, & - rtab=rtab,dtab=rhotab,dcontrast=density_contrast,is_setup=.true.,prefix=trim(fileprefix)) - else - call shuffleparticles(iprint,npart,xyzh,massoftype(igas), & - rsphere=rmax,dsphere=dens_sphere,dmedium=dens_medium,is_setup=.true.,prefix=trim(fileprefix)) - endif - endif - if (BEsphere) deallocate(rtab,rhotab) - ! - ! reset to centre of mass - ! (if random or shuffling, recentering may shift particles outside of the defined range) - ! - if (trim(lattice)/='random' .and. .not.shuffle_parts) call reset_centreofmass(npart,xyzh,vxyzu) - - ! - !--Stretching the spatial distribution to perturb the density profile, if requested - ! - if (binary) then - do i = 1,npart - rxy2 = xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) - rxyz2 = rxy2 + xyzh(3,i)*xyzh(3,i) - if (rxyz2 <= r_sphere**2) then - phi = atan(xyzh(2,i)/xyzh(1,i)) - if (xyzh(1,i) < 0.0) phi = phi + pi - dphi = 0.5*rho_pert_amp*sin(2.0*phi) - phi = phi - dphi - xyzh(1,i) = sqrt(rxy2)*cos(phi) - xyzh(2,i) = sqrt(rxy2)*sin(phi) - endif - enddo - endif - ! - ! Velocity: Turbulent velocity field - ! - vxyzu = 0. - if (rms_mach > 0.) then - call getcwd(cwd) - ! personal hack for J. Wurster since different computer clusters required different velocity fields - if (index(cwd,'gpfs1/scratch/astro/jhw5') > 0 .or. index(cwd,'data/dp187/dc-wurs1') > 0 ) then - ! Kennedy or Dial - filex = find_phantom_datafile(filevx,'velfield_sphng') - filey = find_phantom_datafile(filevy,'velfield_sphng') - filez = find_phantom_datafile(filevz,'velfield_sphng') - else - filex = find_phantom_datafile(filevx,'velfield') - filey = find_phantom_datafile(filevy,'velfield') - filez = find_phantom_datafile(filevz,'velfield') - endif - - call set_velfield_from_cubes(xyzh(:,1:npartsphere),vxyzu(:,:npartsphere),npartsphere, & - filex,filey,filez,1.,r_sphere,.false.,ierr) - if (ierr /= 0) call fatal('setup','error setting up velocity field on clouds') - - rmsmach = 0.0 - print*, 'Turbulence being set by user' - do i = 1,npartsphere - v2i = dot_product(vxyzu(1:3,i),vxyzu(1:3,i)) - rmsmach = rmsmach + v2i/cs_sphere**2 - enddo - rmsmach = sqrt(rmsmach/npartsphere) - if (rmsmach > 0.) then - turbfac = rms_mach/rmsmach ! normalise the energy to the desired mach number - else - turbfac = 0. - endif - do i = 1,npartsphere - vxyzu(1:3,i) = turbfac*vxyzu(1:3,i) - enddo - endif - ! - ! Velocity: uniform rotation (thermal energy & magnetic field too) - ! - do i=1,npart - r2 = dot_product(xyzh(1:3,i),xyzh(1:3,i)) - if (r2 < r_sphere**2) then - vxyzu(1,i) = vxyzu(1,i) - angvel_code*xyzh(2,i) - vxyzu(2,i) = vxyzu(2,i) + angvel_code*xyzh(1,i) - ui = u_sphere - if (maxvxyzu >= 4) vxyzu(4,i) = ui - else - if (maxvxyzu >= 4) vxyzu(4,i) = 1.5*polyk2 - endif - enddo - ! - ! set default runtime parameters if .in file does not exist - ! - filename=trim(fileprefix)//'.in' - inquire(file=filename,exist=iexist) - dtmax = t_ff/100. ! Since this variable can change, always reset it if running phantomsetup - if (.not. iexist) then - if (binary) then - tmax = 1.50*t_ff ! = 13.33 for default settings (Wurster, Price & Bate 2017) - else - tmax = 1.21*t_ff ! = 10.75 for default settings (Wurster, Price & Bate 2016) - endif - ieos = 21 - nfulldump = 1 - calc_erot = .true. - dtmax_dratio = 1.258 - icreate_sinks = icreate_sinks_setup - r_crit = r_crit_setup - h_acc = h_acc_setup - if (binary) h_soft_sinksink = h_soft_sinksink_setup - hdivbbmax_max = 1.0 ! 512. - if (icreate_sinks==1) then - dtmax_min = dtmax/8.0 - else - dtmax_min = 0.0 - rhofinal_cgs = rhofinal_setup - endif - ilimitdustflux = .true. - endif - ! - !--Summarise the sphere - ! - print "(a,i10)",' Input npart_sphere = ',np - print "(1x,50('-'))" - print "(a)",' Quantity (code units) (physical units)' - print "(1x,50('-'))" - fmt = "((a,1pg10.3,3x,1pg10.3),a)" - print fmt,' Total mass : ',totmass,totmass*umass,' g' - print fmt,' Mass in sphere : ',totmass_sphere,totmass_sphere*umass,' g' - print fmt,' Radius of sphere : ',r_sphere,r_sphere*udist,' cm' - if (BEsphere) then - print fmt,' Mean rho sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' - print fmt,' central density : ',central_density,central_density*unit_density,' g/cm^3' - print fmt,' edge density : ',edge_density,edge_density*unit_density,' g/cm^3' - print fmt,' Mean rho medium : ',dens_medium,dens_medium*unit_density,' g/cm^3' - else - print fmt,' Density sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' - endif - print fmt,' cs in sphere : ',cs_sphere,cs_sphere_cgs,' cm/s' - print fmt,' Free fall time : ',t_ff,t_ff*utime/years,' yrs' - print fmt,' Angular velocity : ',angvel_code,angvel,' rad/s' - print fmt,' Turbulent Mach no: ',rms_mach - print fmt,' Omega*t_ff : ',angvel_code*t_ff - - if (use_dust) then - print fmt,' dust-to-gas ratio: ',dtg,dtg,' ' - endif - print "(1x,50('-'))" - -end subroutine setpart - -!---------------------------------------------------------------- -!+ -! write parameters to setup file -!+ -!---------------------------------------------------------------- -subroutine write_setupfile(filename) - use infile_utils, only: write_inopt - character(len=*), intent(in) :: filename - integer, parameter :: iunit = 20 - integer :: i - - print "(a)",' writing setup options file '//trim(filename) - open(unit=iunit,file=filename,status='replace',form='formatted') - write(iunit,"(a)") '# input file for sphere-in-box setup routines' - write(iunit,"(/,a)") '# units' - call write_inopt(dist_unit,'dist_unit','distance unit (e.g. au)',iunit) - call write_inopt(mass_unit,'mass_unit','mass unit (e.g. solarm)',iunit) - - write(iunit,"(/,a)") '# particle resolution & placement' - call write_inopt(np,'np','requested number of particles in sphere',iunit) - call write_inopt(lattice,'lattice','particle lattice (random,cubic,closepacked,hcp,hexagonal)',iunit) - call write_inopt(shuffle_parts,'shuffle_parts','relax particles by shuffling',iunit) - - write(iunit,"(/,a)") '# options for box' - if (.not.BEsphere .and. .not.is_cube) then - ! left here for backwards compatibility and for simplicity if the user requires a rectangle in the future - do i=1,3 - call write_inopt(xmini(i),labelx(i)//'min',labelx(i)//' min',iunit) - call write_inopt(xmaxi(i),labelx(i)//'max',labelx(i)//' max',iunit) - enddo - else - call write_inopt(lbox,'lbox','length of a box side in terms of spherical radii',iunit) - endif - - write(iunit,"(/,a)") '# intended result' - call write_inopt(binary,'form_binary','the intent is to form a central binary',iunit) - - write(iunit,"(/,a)") '# options for sphere' - call write_inopt(BEsphere,'use_BE_sphere','centrally condense as a BE sphere',iunit) - if (.not. BEsphere) then - call write_inopt(r_sphere,'r_sphere','radius of sphere in code units',iunit) - call write_inopt(totmass_sphere,'totmass_sphere','mass of sphere in code units',iunit) - else - call write_inopt(iBEparam,'iBE_options','The set of parameters to define the BE sphere',iunit) - if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) & - call write_inopt(BErho_cen,'BErho_cen','central density of the BE sphere [code units]',iunit) - if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) & - call write_inopt(BErad_phys,'BErad_phys','physical radius of the BE sphere [code units]',iunit) - if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) & - call write_inopt(BErad_norm,'BErad_norm','normalised radius of the BE sphere',iunit) - if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) & - call write_inopt(BEmass,'BEmass','mass radius of the BE sphere [code units]',iunit) - if (iBEparam==4 .or. iBEparam==5) & - call write_inopt(BEfac,'BEfac','over-density factor of the BE sphere [code units]',iunit) - endif - call write_inopt(density_contrast,'density_contrast','density contrast in code units',iunit) - call write_inopt(T_sphere,'T_sphere','temperature in sphere',iunit) - if (angvel_not_betar) then - call write_inopt(angvel,'angvel','angular velocity in rad/s',iunit) - else - call write_inopt(beta_r,'beta_r','rotational-to-gravitational energy ratio',iunit) - endif - call write_inopt(rms_mach,'rms_mach','turbulent rms mach number',iunit) - if (mhd) then - if (mu_not_B) then - call write_inopt(masstoflux,'masstoflux','mass-to-magnetic flux ratio in units of critical value',iunit) - else - call write_inopt(Bzero_G,'Bzero','Magnetic field strength in Gauss',iunit) - endif - call write_inopt(ang_Bomega,'ang_Bomega','Angle (degrees) between B and rotation axis',iunit) - endif - if (use_dust) then - write(iunit,"(/,a)") '# Dust properties' - call write_inopt(dtg,'dust_to_gas_ratio','dust-to-gas ratio',iunit) - call write_inopt(ndusttypes,'ndusttypes','number of grain sizes',iunit) - if (ndusttypes > 1) then - call write_inopt(smincgs,'smincgs','minimum grain size [cm]',iunit) - call write_inopt(smaxcgs,'smaxcgs','maximum grain size [cm]',iunit) - call write_inopt(sindex, 'sindex', 'power-law index, e.g. MRN',iunit) - call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) - else - call write_inopt(grainsizecgs,'grainsizecgs','grain size in [cm]',iunit) - call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) - endif - endif - if (binary) then - call write_inopt(rho_pert_amp,'rho_pert_amp','amplitude of density perturbation',iunit) - endif - write(iunit,"(/,a)") '# Sink properties (values in .in file, if present, will take precedence)' - call write_inopt(icreate_sinks_setup,'icreate_sinks','1: create sinks. 0: do not create sinks',iunit) - if (icreate_sinks_setup==1) then - call write_inopt(h_acc_setup,'h_acc','accretion radius (code units)',iunit) - call write_inopt(r_crit_setup,'r_crit','critical radius (code units)',iunit) - if (binary) then - call write_inopt(h_soft_sinksink_setup,'h_soft_sinksink','sink-sink softening radius (code units)',iunit) - endif - else - call write_inopt(rhofinal_setup,'rho_final','final maximum density (<=0 to ignore) (cgs units)',iunit) - endif - close(iunit) - -end subroutine write_setupfile - -!---------------------------------------------------------------- -!+ -! Read parameters from setup file -!+ -!---------------------------------------------------------------- -subroutine read_setupfile(filename,ierr) - use infile_utils, only: open_db_from_file,inopts,read_inopt,close_db - use unifdis, only: is_valid_lattice - use io, only: error - use units, only: select_unit - character(len=*), intent(in) :: filename - integer, intent(out) :: ierr - integer, parameter :: iunit = 21 - integer :: i,nerr,kerr,jerr - type(inopts), allocatable :: db(:) - - !--Read values - print "(a)",' reading setup options from '//trim(filename) - call open_db_from_file(db,filename,iunit,ierr) - call read_inopt(mass_unit,'mass_unit',db,ierr) - call read_inopt(dist_unit,'dist_unit',db,ierr) - call read_inopt(BEsphere,'use_BE_sphere',db,ierr) - call read_inopt(binary,'form_binary',db,ierr) - call read_inopt(np,'np',db,ierr) - call read_inopt(lattice,'lattice',db,ierr) - if (ierr/=0 .or. .not. is_valid_lattice(trim(lattice))) then - print*, ' invalid lattice. Setting to closepacked' - lattice = 'closepacked' - endif - call read_inopt(shuffle_parts,'shuffle_parts',db,ierr) - - call read_inopt(lbox,'lbox',db,jerr) ! for backwards compatibility - if (jerr /= 0) then - do i=1,3 - call read_inopt(xmini(i),labelx(i)//'min',db,ierr) - call read_inopt(xmaxi(i),labelx(i)//'max',db,ierr) - enddo - lbox = -2.0*xmini(1)/r_sphere - endif - - if (.not. BEsphere) then - call read_inopt(r_sphere,'r_sphere',db,ierr) - call read_inopt(totmass_sphere,'totmass_sphere',db,ierr) - else - call read_inopt(iBEparam,'iBE_options',db,ierr) - if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) call read_inopt(BErho_cen,'BErho_cen',db,ierr) - if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) call read_inopt(BErad_phys,'BErad_phys',db,ierr) - if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) call read_inopt(BErad_norm,'BErad_norm',db,ierr) - if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) call read_inopt(BEmass,'BEmass',db,ierr) - if (iBEparam==4 .or. iBEparam==5) call read_inopt(BEfac,'BEfac',db,ierr) - endif - - call read_inopt(T_sphere,'T_sphere',db,jerr) - cs_in_code = .false. ! for backwards compatibility - if (jerr /= 0 .and. kerr == 0) then - cs_in_code = .false. - elseif (jerr == 0 .and. kerr /= 0) then - cs_in_code = .true. - else - ierr = ierr + 1 - endif - call read_inopt(angvel,'angvel',db,jerr) - call read_inopt(beta_r,'beta_r',db,kerr) - angvel_not_betar = .true. - if (jerr /= 0 .and. kerr == 0) then - angvel_not_betar = .false. - elseif (jerr == 0 .and. kerr /= 0) then - angvel_not_betar = .true. - else - ierr = ierr + 1 - endif - call read_inopt(rms_mach,'rms_mach',db,ierr) - mu_not_B = .true. - if (mhd) then - call read_inopt(masstoflux,'masstoflux',db,jerr) - call read_inopt(Bzero_G, 'Bzero', db,kerr) - call read_inopt(ang_Bomega,'ang_Bomega',db,ierr) - if (jerr /= 0 .and. kerr == 0) then - mu_not_B = .false. - elseif (jerr == 0 .and. kerr /= 0) then - mu_not_B = .true. - else - ierr = ierr + 1 - endif - endif - if (use_dust) then - call read_inopt(dtg,'dust_to_gas_ratio',db,ierr) - call read_inopt(ndusttypes,'ndusttypes',db,ierr) - if (ndusttypes > 1) then - call read_inopt(smincgs,'smincgs',db,ierr) - call read_inopt(smaxcgs,'smaxcgs',db,ierr) - call read_inopt(sindex,'cs_sphere',db,ierr) - call read_inopt(graindenscgs,'graindenscgs',db,ierr) - else - call read_inopt(grainsizecgs,'grainsizecgs',db,ierr) - call read_inopt(graindenscgs,'graindenscgs',db,ierr) - endif - endif - if (binary) then - call read_inopt(rho_pert_amp,'rho_pert_amp',db,ierr) - endif - call read_inopt(icreate_sinks_setup,'icreate_sinks',db,ierr) - if (icreate_sinks_setup==1) then - call read_inopt(h_acc_setup,'h_acc',db,ierr) - call read_inopt(r_crit_setup,'r_crit',db,ierr) - if (binary) then - call read_inopt(h_soft_sinksink_setup,'h_soft_sinksink',db,ierr) - endif - else - call read_inopt(rhofinal_setup,'rho_final',db,ierr) - endif - call close_db(db) - ! - ! parse units - ! - call select_unit(mass_unit,umass,nerr) - if (nerr /= 0) then - call error('setup_sphereinbox','mass unit not recognised') - ierr = ierr + 1 - endif - call select_unit(dist_unit,udist,nerr) - if (nerr /= 0) then - call error('setup_sphereinbox','length unit not recognised') - ierr = ierr + 1 - endif - - if (ierr > 0) then - print "(1x,a,i2,a)",'Setup_sphereinbox: ',nerr,' error(s) during read of setup file. Re-writing.' - endif - -end subroutine read_setupfile -!---------------------------------------------------------------- - !--Magnetic flux justification - ! This shows how the critical mass-to-flux values translates from CGS to code units. - ! - ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) ! cgs units of g G^-1 cm^-2 - ! convert base units from cgs to code: - ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *unit_Bfield*udist**2/umass - ! where - ! unit_Bfield = umass/(utime*sqrt(umass*udist/4*pi)) = sqrt(4.*pi*umass)/(utime*sqrt(udist)) - ! therefore - ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *sqrt(4.*pi*umass)*udist**2/(utime*sqrt(udist)*umass) - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*sqrt(umass)*udist**2/(utime*sqrt(udist)*umass) - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*udist**1.5/ (sqrt(umass)*utime) - ! where - ! G [cgs] = 1 * udist**3/(umass*utime**2) - ! therefore - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) *udist**1.5/ (sqrt(umass)*utime) / sqrt(udist**3/(umass*utime**2)) - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) ! code units - -!---------------------------------------------------------------- -end module setup diff --git a/src/setup/setup_wind.F90 b/src/setup/setup_wind.F90 deleted file mode 100644 index 012d95aea..000000000 --- a/src/setup/setup_wind.F90 +++ /dev/null @@ -1,828 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module setup -! -! initial conditions for binary wind accretion / AGB star wind injection -! -! :References: -! Siess et al. 2022, A&A, 667, 75 -! -! :Owner: Lionel Siess -! -! :Runtime parameters: -! - Reff2a : *tight binary primary effective radius (au)* -! - Reff2b : *tight binary secondary effective radius (au)* -! - T_wind : *wind temperature (K)* -! - Teff2a : *tight binary primary effective temperature (K)* -! - Teff2b : *tight binary secondary effective temperature (K)* -! - binary2_a : *tight binary semi-major axis* -! - binary2_e : *tight binary eccentricity* -! - eccentricity : *eccentricity of the binary system* -! - icompanion_star : *set to 1 for a binary system, 2 for a triple system* -! - inclination : *inclination of the tight binary system w.r.t. outer binary (deg)* -! - lum2a : *tight binary primary luminosity (Lsun)* -! - lum2b : *tight binary secondary luminosity (Lsun)* -! - mass_of_particles : *particle mass (Msun, overwritten if iwind_resolution <>0)* -! - primary_Reff : *primary star effective radius (au)* -! - primary_Teff : *primary star effective temperature (K)* -! - primary_lum : *primary star luminosity (Lsun)* -! - primary_mass : *primary star mass (Msun)* -! - primary_racc : *primary star accretion radius (au)* -! - q2 : *tight binary mass ratio* -! - racc2a : *tight binary primary accretion radius* -! - racc2b : *tight binary secondary accretion radius* -! - secondary_Reff : *secondary star effective radius (au)* -! - secondary_Teff : *secondary star effective temperature)* -! - secondary_lum : *secondary star luminosity (Lsun)* -! - secondary_mass : *secondary star mass (Msun)* -! - secondary_racc : *secondary star accretion radius (au)* -! - semi_major_axis : *semi-major axis of the binary system (au)* -! - subst : *star to substitute* -! - temp_exponent : *temperature profile T(r) = T_wind*(r/Reff)^(-temp_exponent)* -! - wind_gamma : *adiabatic index (initial if Krome chemistry used)* -! -! :Dependencies: dim, eos, infile_utils, inject, io, part, physcon, -! prompting, setbinary, sethierarchical, spherical, timestep, units -! - use dim, only:isothermal - implicit none - public :: setpart - - private - real, public :: wind_gamma - real, public :: T_wind - real :: temp_exponent - integer :: icompanion_star,iwind - real :: semi_major_axis,semi_major_axis_au,eccentricity - real :: default_particle_mass - real :: primary_lum_lsun,primary_mass_msun,primary_Reff_au,primary_racc_au - real :: secondary_lum_lsun,secondary_mass_msun,secondary_Reff_au,secondary_racc_au - real :: lum2a_lsun,lum2b_lsun,Teff2a,Teff2b,Reff2a_au,Reff2b_au - real :: binary2_a_au,racc2a_au,racc2b_au,binary2_i,q2 - real :: primary_Reff,primary_Teff,primary_lum,primary_mass,primary_racc - real :: secondary_Reff,secondary_Teff,secondary_lum,secondary_mass,secondary_racc - real :: Reff2a,Reff2b - real :: racc2a,racc2b - real :: lum2a,lum2b - real :: binary2_a - real :: binary2_e - integer :: subst - -contains -!---------------------------------------------------------------- -!+ -! default parameter choices -!+ -!---------------------------------------------------------------- -subroutine set_default_parameters_wind() - - wind_gamma = 5./3. - if (isothermal) then - T_wind = 30000. - temp_exponent = 0.5 - ! primary_racc_au = 0.465 - ! primary_mass_msun = 1.5 - ! primary_lum_lsun = 0. - ! primary_Reff_au = 0.465240177008 !100 Rsun - else - T_wind = 3000. - !primary_racc_au = 1. - !primary_mass_msun = 1.5 - !primary_lum_lsun = 20000. - !primary_Reff_au = 0. - endif - icompanion_star = 0 - semi_major_axis = 4.0 - eccentricity = 0. - primary_Teff = 3000. - secondary_Teff = 0. - semi_major_axis_au = 4.0 - default_particle_mass = 1.e-11 - primary_lum_lsun = 5315. - primary_mass_msun = 1.5 - primary_Reff_au = 1. - primary_racc_au = 1. - secondary_lum_lsun = 0. - secondary_mass_msun = 1.0 - secondary_Reff_au = 0. - secondary_racc_au = 0.1 - lum2a_lsun = 0. - lum2b_lsun = 0. - Teff2a = 0. - Teff2b = 0. - Reff2a_au = 0. - Reff2b_au = 0. - binary2_a_au = 0.3 - racc2a_au = 0.1 - racc2b_au = 0.1 - binary2_i = 0. - -end subroutine set_default_parameters_wind - -!---------------------------------------------------------------- -!+ -! setup for uniform particle distributions -!+ -!---------------------------------------------------------------- -subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) - use part, only: xyzmh_ptmass, vxyz_ptmass, nptmass, igas, iTeff, iLum, iReff - use physcon, only: au, solarm, mass_proton_cgs, kboltz, solarl - use units, only: umass,set_units,unit_velocity,utime,unit_energ,udist - use inject, only: init_inject,set_default_options_inject - use setbinary, only: set_binary - use sethierarchical, only: set_multiple - use io, only: master - use eos, only: gmw,ieos,isink,qfacdisc - use spherical, only: set_sphere - use timestep, only: tmax!,dtmax - integer, intent(in) :: id - integer, intent(inout) :: npart - integer, intent(out) :: npartoftype(:) - real, intent(out) :: xyzh(:,:) - real, intent(out) :: vxyzu(:,:) - real, intent(out) :: massoftype(:) - real, intent(out) :: polyk,gamma,hfact - real, intent(inout) :: time - character(len=*), intent(in) :: fileprefix - character(len=len(fileprefix)+6) :: filename - integer :: ierr,k - logical :: iexist - - call set_units(dist=au,mass=solarm,G=1.) - call set_default_parameters_wind() - filename = trim(fileprefix)//'.in' - inquire(file=filename,exist=iexist) - if (.not. iexist) call set_default_options_inject - -!--general parameters -! - time = 0. - filename = trim(fileprefix)//'.setup' - inquire(file=filename,exist=iexist) - if (iexist) call read_setupfile(filename,ierr) - if (.not. iexist .or. ierr /= 0) then - if (id==master) then - call setup_interactive() - call write_setupfile(filename) - endif - endif - -! -!--space available for injected gas particles -! - npart = 0 - npartoftype(:) = 0 - xyzh(:,:) = 0. - vxyzu(:,:) = 0. - xyzmh_ptmass(:,:) = 0. - vxyz_ptmass(:,:) = 0. - - if (icompanion_star == 1) then - call set_binary(primary_mass, & - secondary_mass, & - semi_major_axis, & - eccentricity, & - primary_racc, & - secondary_racc, & - xyzmh_ptmass, vxyz_ptmass, nptmass, ierr) - xyzmh_ptmass(iTeff,1) = primary_Teff - xyzmh_ptmass(iReff,1) = primary_Reff - xyzmh_ptmass(iLum,1) = primary_lum - xyzmh_ptmass(iTeff,2) = secondary_Teff - xyzmh_ptmass(iReff,2) = secondary_Reff - xyzmh_ptmass(iLum,2) = secondary_lum - elseif (icompanion_star == 2) then - !-- hierarchical triple - nptmass = 0 - print "(/,a)",'----------- Hierarchical triple -----------' - print "(a,g10.3,a)",' First hierarchical level primary mass: ', primary_mass_msun - print "(a,g10.3,a)",' First hierarchical level secondary mass: ', secondary_mass_msun - print "(a,g10.3)", ' Wide binary mass ratio: ', secondary_mass/primary_mass - print "(a,g10.3)", ' Tight binary mass ratio: ', q2 - print "(a,g10.3)", ' Star to be substituted: ', abs(subst) -! print "(a,g10.3,a)",' Accretion Radius 1: ', primary_racc!, trim(dist_unit) -! print "(a,g10.3,a)",' Accretion Radius 2a: ', racc2a!, trim(dist_unit) -! print "(a,g10.3,a)",' Accretion Radius 2b: ', racc2b!, trim(dist_unit) - - if (subst>0) then - print "(a,g10.3,a)",' Tight binary orientation referred to: substituted star orbital plane' - else - print "(a,g10.3,a)",' Tight binary orientation referred to: sky' - endif - - - call set_multiple(primary_mass,secondary_mass,semimajoraxis=semi_major_axis,eccentricity=eccentricity, & - accretion_radius1=primary_racc,accretion_radius2=secondary_racc, & - xyzmh_ptmass=xyzmh_ptmass,vxyz_ptmass=vxyz_ptmass,nptmass=nptmass,ierr=ierr) - - if (subst == 12) then - call set_multiple(secondary_mass/(q2+1),secondary_mass*q2/(q2+1),semimajoraxis=binary2_a,eccentricity=binary2_e, & - accretion_radius1=racc2a,accretion_radius2=racc2b, & - xyzmh_ptmass=xyzmh_ptmass,vxyz_ptmass=vxyz_ptmass,nptmass=nptmass,& - posang_ascnode=0.,arg_peri=0.,incl=binary2_i,subst=subst,ierr=ierr) - - xyzmh_ptmass(iTeff,1) = primary_Teff - xyzmh_ptmass(iReff,1) = primary_Reff - xyzmh_ptmass(iLum,1) = primary_lum - xyzmh_ptmass(iTeff,2) = Teff2a - xyzmh_ptmass(iReff,2) = Reff2a - xyzmh_ptmass(iLum,2) = lum2a - xyzmh_ptmass(iTeff,3) = Teff2b - xyzmh_ptmass(iReff,3) = Reff2b - xyzmh_ptmass(iLum,3) = lum2b - - elseif (subst == 11) then - call set_multiple(primary_mass*q2/(q2+1),primary_mass/(q2+1),semimajoraxis=binary2_a,eccentricity=binary2_e, & - accretion_radius1=racc2b,accretion_radius2=primary_racc, & - xyzmh_ptmass=xyzmh_ptmass,vxyz_ptmass=vxyz_ptmass,nptmass=nptmass,& - posang_ascnode=0.,arg_peri=0.,incl=binary2_i,subst=subst,ierr=ierr) - - xyzmh_ptmass(iTeff,1) = primary_Teff - xyzmh_ptmass(iReff,1) = primary_Reff - xyzmh_ptmass(iLum,1) = primary_lum - xyzmh_ptmass(iTeff,2) = secondary_Teff - xyzmh_ptmass(iReff,2) = secondary_Reff - xyzmh_ptmass(iLum,2) = secondary_lum - xyzmh_ptmass(iTeff,3) = Teff2b - xyzmh_ptmass(iReff,3) = Reff2b - xyzmh_ptmass(iLum,3) = lum2b - endif - - print *,'Sink particles summary' - print *,' # mass racc lum Reff' - do k=1,nptmass - print '(i4,2(2x,f9.5),2(2x,es10.3))',k,xyzmh_ptmass(4:5,k),xyzmh_ptmass(iLum,k)/(solarl*utime/unit_energ),& - xyzmh_ptmass(iReff,k)*udist/au - enddo - print *,'' - - else - nptmass = 1 - xyzmh_ptmass(4,1) = primary_mass - xyzmh_ptmass(5,1) = primary_racc - xyzmh_ptmass(iTeff,1) = primary_Teff - xyzmh_ptmass(iReff,1) = primary_Reff - xyzmh_ptmass(iLum,1) = primary_lum - endif - - ! - ! for binary wind simulations the particle mass is IRRELEVANT - ! since it will be over-written on the first call to init_inject - ! - massoftype(igas) = default_particle_mass * (solarm / umass) - - if (isothermal) then - gamma = 1. - if (iwind == 3) then - ieos = 6 - qfacdisc = 0.5*temp_exponent - isink = 1 - T_wind = primary_Teff - else - isink = 1 - ieos = 1 - endif - else - T_wind = 0. - gamma = wind_gamma - endif - polyk = kboltz*T_wind/(mass_proton_cgs * gmw * unit_velocity**2) - - ! - ! avoid failures in the setup by ensuring that tmax and dtmax are large enough - ! - tmax = max(tmax,100.) - !dtmax = max(tmax/10.,dtmax) - -end subroutine setpart - -!---------------------------------------------------------------- -!+ -! determine which problem to set up interactively -!+ -!---------------------------------------------------------------- -subroutine setup_interactive() - use prompting, only:prompt - use physcon, only:au,solarm - use units, only:umass,udist - use io, only:fatal - integer :: ichoice - - if (isothermal) then - iwind = 2 - else - iwind = 1 - call prompt('Type of wind: 1=adia, 2=isoT, 3=T(r)',iwind,1,3) - if (iwind == 2 .or. iwind == 3) then - call fatal('setup','If you choose options 2 or 3, the code must be compiled with SETUP=isowind') - endif - if (iwind == 3) T_wind = primary_Teff - endif - - icompanion_star = 0 - call prompt('Add binary?',icompanion_star,0,2) - - !Hierarchical triple system - if (icompanion_star == 2) then - !select the tight binary - ichoice = 1 - print "(a)",'Star to be substituted by a tight binary' - print "(a)",' 1: primary (2+1)' ,' 2: companion (1+2)' - call prompt('Select star to be substituted',ichoice,1,2) - subst = ichoice+10 - - !select orbital parameters for outer binary - semi_major_axis_au = 15. - eccentricity = 0. - ichoice = 1 - print "(a)",'Orbital parameters first hierarchical level binary' - print "(a)",' 1: semi-axis = 15 au, eccentricity = 0',' 0: custom' - call prompt('select semi-major axis and ecccentricity',ichoice,0,1) - if (ichoice == 0) then - call prompt('enter semi-major axis in au',semi_major_axis_au,0.,100.) - call prompt('enter eccentricity',eccentricity,0.) - endif - semi_major_axis = semi_major_axis_au * au / udist - ichoice = 1 - - !replace companion by tight binary system : 1+2 - if (subst == 12) then - print "(a)",'Primary star parameters (the single wind launching central star)' - print "(a)",' 2: Mass = 1.2 Msun, accretion radius = 0.2568 au',& - ' 1: Mass = 1.5 Msun, accretion radius = 1.2568 au', & - ' 0: custom' - call prompt('select mass and radius of primary',ichoice,0,2) - select case(ichoice) - case(2) - primary_mass_msun = 1.2 - primary_racc_au = 0.2568 - case(1) - primary_mass_msun = 1.5 - primary_racc_au = 1.2568 - case default - primary_mass_msun = 1.5 - primary_racc_au = 1. - call prompt('enter primary mass',primary_mass_msun,0.,100.) - call prompt('enter accretion radius in au ',primary_racc_au,0.) - end select - primary_mass = primary_mass_msun * (solarm / umass) - primary_racc = primary_racc_au * (au / udist) - - ichoice = 1 - print "(a)",'Total mass of tight binary system (1+2)' - print "(a)",' 1: Total mass tight binary = 1.0 Msun',' 0: custom' - secondary_mass_msun = 1. - call prompt('select mass',ichoice,0,1) - select case(ichoice) - case(0) - call prompt('enter total mass tigh binary',secondary_mass_msun,0.,100.) - end select - secondary_mass = secondary_mass_msun * (solarm / umass) - - ichoice = 1 - print "(a)",'Mass ratio and accretion radii of stars in tight orbit:' - print "(a)",' 1: mass ratio m2b/m2a = 1, accretion radius a = 0.01 au, accretion radius b = 0.01 au',' 0: custom' - call prompt('select mass ratio and accretion radii of tight binary',ichoice,0,1) - select case(ichoice) - case(1) - q2 = 1. - racc2a_au = 0.1 - racc2b_au = 0.1 - case default - q2 = 1. - racc2a_au = 0.1 - racc2b_au = 0.1 - call prompt('enter tight binary mass ratio',q2,0.) - call prompt('enter accretion radius a in au ',racc2a_au,0.) - call prompt('enter accretion radius b in au ',racc2b_au,0.) - end select - racc2a = racc2a_au * (au / udist) - racc2b = racc2b_au * (au / udist) - secondary_racc = racc2a !needs to be /=0 otherwise NaNs in set_multiple - - !replace primary by tight binary system : 2+1 - elseif (subst == 11) then - print "(a)",'Stellar parameters of the remote single star (2+1)' - print "(a)",' 1: Mass = 1.0 Msun, accretion radius = 0.1 au',' 0: custom' - call prompt('select mass and radius of remote single star',ichoice,0,1) - select case(ichoice) - case(1) - secondary_mass_msun = 1. - secondary_racc_au = 0.1 - case default - secondary_mass_msun = 1. - secondary_racc_au = 0.1 - call prompt('enter mass of remote single star',secondary_mass_msun,0.,100.) - call prompt('enter accretion radius in au ',secondary_racc_au,0.) - end select - secondary_mass = secondary_mass_msun * (solarm / umass) - secondary_racc = secondary_racc_au * (au / udist) - - ichoice = 1 - print "(a)",'wind-launching star accretion radius in tigh orbit (called primary)' - print "(a)",' 2: accretion radius primary = 0.2568 au',& - ' 1: accretion radius primary = 1.2568 au', & - ' 0: custom' - call prompt('select accretion radius of wind launching star',ichoice,0,2) - select case(ichoice) - case(2) - primary_racc_au = 0.2568 - case(1) - primary_racc_au = 1.2568 - case default - primary_racc_au = 1. - call prompt('enter accretion radius in au ',primary_racc_au,0.) - end select - primary_racc = primary_racc_au * (au / udist) - - ichoice = 1 - print "(a)",'Total mass of the tight binary system (2+1):' - print "(a)",' 2: Total mass tight binary = 1.2 Msun',& - ' 1: Total mass tight binary = 1.5 Msun', & - ' 0: custom' - call prompt('select total mass tight binary',ichoice,0,2) - select case(ichoice) - case(2) - primary_mass_msun = 1.2 - case(1) - primary_mass_msun = 1.5 - case default - primary_mass_msun = 1.5 - call prompt('enter primary mass',primary_mass_msun,0.,100.) - end select - primary_mass = primary_mass_msun * (solarm / umass) - - ichoice = 1 - print "(a)",'Mass ratio and accretion radius of secondary in tight orbit:' - print "(a)",' 1: mass ratio m1b/m1a = 0.3, accretion radius b = 0.01 au',' 0: custom' - call prompt('select mass ratio and accretion radius of tight binary',ichoice,0,1) - select case(ichoice) - case(1) - q2 = 0.3 - racc2b_au = 0.1 - case default - q2 = 0.3 - racc2b_au = 0.1 - call prompt('enter tight binary mass ratio',q2,0.) - call prompt('enter accretion radius b in au ',racc2b_au,0.) - end select - racc2b = racc2b_au * (au / udist) - endif - - ichoice = 1 - print "(a)",'Orbital parameters of tight system:' - print "(a)",' 1: semi-axis = 4 au, eccentricity = 0',' 0: custom' - call prompt('select tight binary semi-major axis and eccentricity',ichoice,0,1) - select case(ichoice) - case(1) - binary2_a_au = 4. - binary2_e = 0. - case default - binary2_a_au = 4. - binary2_e = 0. - call prompt('enter semi-major axis in au',binary2_a_au,0.,semi_major_axis_au) - call prompt('enter eccentricity',binary2_e,0.) - end select - binary2_a = binary2_a_au * au / udist - - ichoice = 1 - print "(a)",'inclination of orbit tight binary w.r.t. outer binary:' - print "(a)",' 1: inclination = 0 deg',' 0: custom' - call prompt('select inclination',ichoice,0,1) - select case(ichoice) - case(1) - binary2_i = 0. - case default - binary2_i = 0. - call prompt('enter inclination',binary2_i,0.,90.) - end select - - !binary or single star case - else - if (icompanion_star == 1) then - print "(a)",'Primary star parameters' - else - print "(a)",'Stellar parameters' - endif - ichoice = 2 - print "(a)",' 3: Mass = 1.2 Msun, accretion radius = 1. au (trans-sonic)',& - ' 2: Mass = 1.2 Msun, accretion radius = 0.2568 au',& - ' 1: Mass = 1.0 Msun, accretion radius = 1.2568 au', & - ' 0: custom' - call prompt('select mass and radius of primary',ichoice,0,3) - select case(ichoice) - case(3) - primary_lum_lsun = 2.d4 - primary_Teff = 5.d4 - primary_mass_msun = 1.2 - primary_racc_au = 1. - wind_gamma = 1.4 - case(2) - primary_mass_msun = 1.2 - primary_racc_au = 0.2568 - case(1) - primary_mass_msun = 1. - primary_racc_au = 1.2568 - case default - primary_mass_msun = 1. - primary_racc_au = 1. - call prompt('enter primary mass',primary_mass_msun,0.,100.) - call prompt('enter accretion radius in au ',primary_racc_au,0.) - end select - primary_mass = primary_mass_msun * (solarm / umass) - primary_racc = primary_racc_au * (au / udist) - - if (icompanion_star == 1) then - ichoice = 1 - print "(a)",'Secondary star parameters' - print "(a)",' 1: Mass = 1.0 Msun, accretion radius = 0.1 au',' 0: custom' - call prompt('select mass and radius of secondary',ichoice,0,1) - select case(ichoice) - case(1) - secondary_mass_msun = 1. - secondary_racc_au = 0.1 - case default - secondary_mass_msun = 1. - secondary_racc_au = 0.1 - call prompt('enter secondary mass',secondary_mass_msun,0.,100.) - call prompt('enter accretion radius in au ',secondary_racc_au,0.) - end select - secondary_mass = secondary_mass_msun * (solarm / umass) - secondary_racc = secondary_racc_au * (au / udist) - - ichoice = 1 - print "(a)",'Orbital parameters' - print "(a)",' 1: semi-axis = 3.7 au, eccentricity = 0',' 0: custom' - call prompt('select semi-major axis and ecccentricity',ichoice,0,1) - select case(ichoice) - case(1) - semi_major_axis_au = 3.7 - eccentricity = 0. - case default - semi_major_axis_au = 1. - eccentricity = 0. - call prompt('enter semi-major axis in au',semi_major_axis_au,0.,100.) - call prompt('enter eccentricity',eccentricity,0.) - end select - semi_major_axis = semi_major_axis_au * au / udist - endif - endif - -end subroutine setup_interactive - -!---------------------------------------------------------------- -!+ -! get luminosity and effective radius in code units -! from various combinations of L, Teff and Reff in physical inuts -!+ -!---------------------------------------------------------------- -subroutine get_lum_and_Reff(lum_lsun,reff_au,Teff,lum,Reff) - use physcon, only:au,steboltz,solarl,pi - use units, only:udist,unit_luminosity - real, intent(inout) :: lum_lsun,reff_au,Teff - real, intent(out) :: lum,Reff - - if (Teff <= tiny(0.) .and. lum_lsun > 0. .and. Reff_au > 0.) then - primary_Teff = (lum_lsun*solarl/(4.*pi*steboltz*(Reff_au*au)**2))**0.25 - elseif (Reff_au <= 0. .and. lum_lsun > 0. .and. Teff > 0.) then - Reff_au = sqrt(lum_lsun*solarl/(4.*pi*steboltz*Teff**4))/au - elseif (Reff_au > 0. .and. lum_lsun <= 0. .and. Teff > 0.) then - lum_lsun = 4.*pi*steboltz*Teff**4*(primary_Reff_au*au)**2/solarl - endif - - lum = lum_lsun*(solarl/unit_luminosity) - Reff = Reff_au*(au/udist) - -end subroutine get_lum_and_Reff - -!---------------------------------------------------------------- -!+ -! write parameters to setup file -!+ -!---------------------------------------------------------------- -subroutine write_setupfile(filename) - use infile_utils, only:write_inopt - character(len=*), intent(in) :: filename - integer, parameter :: iunit = 20 - - print "(a)",' writing setup options file '//trim(filename) - open(unit=iunit,file=filename,status='replace',form='formatted') - write(iunit,"(a)") '# input file for wind setup routine' - - call get_lum_and_Reff(primary_lum_lsun,primary_Reff_au,primary_Teff,primary_lum,primary_Reff) - - if (icompanion_star == 2) then - call get_lum_and_Reff(secondary_lum_lsun,secondary_Reff_au,secondary_Teff,secondary_lum,secondary_Reff) - - call write_inopt(icompanion_star,'icompanion_star','set to 1 for a binary system, 2 for a triple system',iunit) - !-- hierarchical triple - write(iunit,"(/,a)") '# options for hierarchical triple' - call write_inopt(subst,'subst','star to substitute',iunit) - write(iunit,"(/,a)") '# input of primary (wind launching star)' - if (subst == 12) then - call write_inopt(primary_mass_msun,'primary_mass','primary star mass (Msun)',iunit) - call write_inopt(primary_racc_au,'primary_racc','primary star accretion radius (au)',iunit) - call write_inopt(primary_lum_lsun,'primary_lum','primary star luminosity (Lsun)',iunit) - call write_inopt(primary_Teff,'primary_Teff','primary star effective temperature (K)',iunit) - call write_inopt(primary_Reff_au,'primary_Reff','primary star effective radius (au)',iunit) - call write_inopt(semi_major_axis_au,'semi_major_axis','semi-major axis of the binary system (au)',iunit) - call write_inopt(eccentricity,'eccentricity','eccentricity of the binary system',iunit) - write(iunit,"(/,a)") '# input secondary to be replaced by tight binary' - call write_inopt(secondary_mass_msun,'secondary_mass','total mass of secondary tight binary (Msun)',iunit) - call write_inopt(q2,'q2','tight binary mass ratio',iunit) - !-- tight orbital parameters - call write_inopt(binary2_a,'binary2_a','tight binary semi-major axis',iunit) - call write_inopt(binary2_e,'binary2_e','tight binary eccentricity',iunit) - !-- accretion radii, luminosity, radii - call write_inopt(racc2a_au,'racc2a','tight binary primary accretion radius',iunit) - call write_inopt(racc2b_au,'racc2b','tight binary secondary accretion radius',iunit) - call write_inopt(lum2a_lsun,'lum2a','tight binary primary luminosity (Lsun)',iunit) - call write_inopt(lum2b_lsun,'lum2b','tight binary secondary luminosity (Lsun)',iunit) - call write_inopt(Teff2a,'Teff2a','tight binary primary effective temperature (K)',iunit) - call write_inopt(Teff2b,'Teff2b','tight binary secondary effective temperature (K)',iunit) - call write_inopt(Reff2a_au,'Reff2a','tight binary primary effective radius (au)',iunit) - call write_inopt(Reff2b_au,'Reff2b','tight binary secondary effective radius (au)',iunit) - elseif (subst == 11) then - call write_inopt(primary_racc_au,'primary_racc','primary star accretion radius (au)',iunit) - call write_inopt(primary_lum_lsun,'primary_lum','primary star luminosity (Lsun)',iunit) - call write_inopt(primary_Teff,'primary_Teff','primary star effective temperature (K)',iunit) - call write_inopt(primary_Reff_au,'primary_Reff','primary star effective radius (au)',iunit) - write(iunit,"(/,a)") '# input tight binary to create close companion' - call write_inopt(primary_mass_msun,'primary_mass','primary star mass (Msun)',iunit) - call write_inopt(q2,'q2','tight binary mass ratio',iunit) - !-- tight orbital parameters - call write_inopt(binary2_a,'binary2_a','tight binary semi-major axis',iunit) - call write_inopt(binary2_e,'binary2_e','tight binary eccentricity',iunit) - !-- accretion radii - call write_inopt(racc2b_au,'racc2b','tight binary secondary accretion radius',iunit) - call write_inopt(lum2b_lsun,'lum2b','tight binary secondary luminosity (Lsun)',iunit) - call write_inopt(Teff2b,'Teff2b','tight binary secondary effective temperature (K)',iunit) - call write_inopt(Reff2b_au,'Reff2b','tight binary secondary effective radius (au)',iunit) - write(iunit,"(/,a)") '# input of secondary, outer binary' - call write_inopt(secondary_mass_msun,'secondary_mass','secondary star mass (Msun)',iunit) - call write_inopt(secondary_racc_au,'secondary_racc','secondary star accretion radius (au)',iunit) - call write_inopt(secondary_lum_lsun,'secondary_lum','secondary star luminosity (Lsun)',iunit) - call write_inopt(secondary_Teff,'secondary_Teff','secondary star effective temperature)',iunit) - call write_inopt(secondary_Reff_au,'secondary_Reff','secondary star effective radius (au)',iunit) - call write_inopt(semi_major_axis_au,'semi_major_axis','semi-major axis of the binary system (au)',iunit) - call write_inopt(eccentricity,'eccentricity','eccentricity of the binary system',iunit) - endif - call write_inopt(binary2_i,'inclination','inclination of the tight binary system w.r.t. outer binary (deg)',iunit) - !binary or single star - else - call write_inopt(primary_mass_msun,'primary_mass','primary star mass (Msun)',iunit) - call write_inopt(primary_racc_au,'primary_racc','primary star accretion radius (au)',iunit) - call write_inopt(primary_lum_lsun,'primary_lum','primary star luminosity (Lsun)',iunit) - call write_inopt(primary_Teff,'primary_Teff','primary star effective temperature (K)',iunit) - call write_inopt(primary_Reff_au,'primary_Reff','primary star effective radius (au)',iunit) - call write_inopt(icompanion_star,'icompanion_star','set to 1 for a binary system, 2 for a triple system',iunit) - if (icompanion_star == 1) then - call get_lum_and_Reff(secondary_lum_lsun,secondary_Reff_au,secondary_Teff,secondary_lum,secondary_Reff) - - call write_inopt(secondary_mass_msun,'secondary_mass','secondary star mass (Msun)',iunit) - call write_inopt(secondary_racc_au,'secondary_racc','secondary star accretion radius (au)',iunit) - call write_inopt(secondary_lum_lsun,'secondary_lum','secondary star luminosity (Lsun)',iunit) - call write_inopt(secondary_Teff,'secondary_Teff','secondary star effective temperature)',iunit) - call write_inopt(secondary_Reff_au,'secondary_Reff','secondary star effective radius (au)',iunit) - call write_inopt(semi_major_axis_au,'semi_major_axis','semi-major axis of the binary system (au)',iunit) - call write_inopt(eccentricity,'eccentricity','eccentricity of the binary system',iunit) - endif - endif - - call write_inopt(default_particle_mass,'mass_of_particles','particle mass (Msun, overwritten if iwind_resolution <>0)',iunit) - - if (isothermal) then - wind_gamma = 1. - if (iwind == 3) then - call write_inopt(primary_Teff,'T_wind','wind temperature at injection radius (K)',iunit) - call write_inopt(temp_exponent,'temp_exponent','temperature profile T(r) = T_wind*(r/Reff)^(-temp_exponent)',iunit) - else - call write_inopt(T_wind,'T_wind','wind temperature (K)',iunit) - endif - else - call write_inopt(wind_gamma,'wind_gamma','adiabatic index (initial if Krome chemistry used)',iunit) - endif - close(iunit) - -end subroutine write_setupfile - -!---------------------------------------------------------------- -!+ -! Read parameters from setup file -!+ -!---------------------------------------------------------------- -subroutine read_setupfile(filename,ierr) - use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db - use physcon, only:au,steboltz,solarl,solarm,pi - use units, only:udist,umass,utime,unit_energ - character(len=*), intent(in) :: filename - integer, intent(out) :: ierr - integer, parameter :: iunit = 21 - type(inopts), allocatable :: db(:) - integer :: nerr,ichange - - nerr = 0 - ichange = 0 - print "(a)",' reading setup options from '//trim(filename) - call open_db_from_file(db,filename,iunit,ierr) - call read_inopt(primary_mass_msun,'primary_mass',db,min=0.,max=1000.,errcount=nerr) - primary_mass = primary_mass_msun * (solarm / umass) - call read_inopt(primary_lum_lsun,'primary_lum',db,min=0.,max=1e7,errcount=nerr) - primary_lum = primary_lum_lsun * (solarl * utime / unit_energ) - call read_inopt(primary_Teff,'primary_Teff',db,min=0.,errcount=nerr) - call read_inopt(primary_Reff_au,'primary_Reff',db,min=0.,errcount=nerr) - primary_Reff = primary_Reff_au * au / udist - call read_inopt(primary_racc_au,'primary_racc',db,min=0.,errcount=nerr) - primary_racc = primary_racc_au * au / udist - if (primary_racc < tiny(0.)) then - print *,'ERROR: primary accretion radius not defined' - nerr = nerr+1 - endif - - call read_inopt(icompanion_star,'icompanion_star',db,min=0,errcount=nerr) - if (icompanion_star == 1) then - call read_inopt(secondary_mass_msun,'secondary_mass',db,min=0.,max=1000.,errcount=nerr) - secondary_mass = secondary_mass_msun * (solarm / umass) - call read_inopt(secondary_lum_lsun,'secondary_lum',db,min=0.,max=1e7,errcount=nerr) - secondary_lum = secondary_lum_lsun * (solarl * utime / unit_energ) - call read_inopt(secondary_Teff,'secondary_Teff',db,min=0.,errcount=nerr) - call read_inopt(secondary_Reff_au,'secondary_Reff',db,min=0.,errcount=nerr) - secondary_Reff = secondary_Reff_au * au / udist - call read_inopt(secondary_racc_au,'secondary_racc',db,min=0.,errcount=nerr) - secondary_racc = secondary_racc_au * au / udist - if (secondary_racc < tiny(0.)) then - print *,'ERROR: secondary accretion radius not defined' - nerr = nerr+1 - endif - call read_inopt(semi_major_axis_au,'semi_major_axis',db,min=0.,errcount=nerr) - semi_major_axis = semi_major_axis_au * au / udist - call read_inopt(eccentricity,'eccentricity',db,min=0.,errcount=nerr) - elseif (icompanion_star == 2) then - !-- hierarchical triple - call read_inopt(subst,'subst',db,errcount=nerr) - !replace primary by tight binary system : 2+1 - if (subst == 11) then - call read_inopt(secondary_lum_lsun,'secondary_lum',db,min=0.,max=1000.,errcount=nerr) - secondary_lum = secondary_lum_lsun * (solarl * utime / unit_energ) - call read_inopt(secondary_Teff,'secondary_Teff',db,min=0.,max=1000.,errcount=nerr) - call read_inopt(secondary_Reff_au,'secondary_Reff',db,min=0.,max=1000.,errcount=nerr) - secondary_Reff = secondary_Reff_au * au / udist - call read_inopt(secondary_racc_au,'secondary_racc',db,min=0.,max=1000.,errcount=nerr) - secondary_racc = secondary_racc_au * au / udist - elseif (subst == 12) then - call read_inopt(lum2a_lsun,'lum2a',db,errcount=nerr) - lum2a = lum2a_lsun * (solarl * utime / unit_energ) - !secondary_lum_lsun = lum2a_lsun - call read_inopt(Teff2a,'Teff2a',db,errcount=nerr) - call read_inopt(Reff2a_au,'Reff2a',db,errcount=nerr) - Reff2a = Reff2a_au * au / udist - !secondary_Reff = Reff2a - call read_inopt(racc2a_au,'racc2a',db,errcount=nerr) - racc2a = racc2a_au * au / udist - endif - call read_inopt(secondary_mass_msun,'secondary_mass',db,min=0.,max=1000.,errcount=nerr) - secondary_mass = secondary_mass_msun * (solarm / umass) - call read_inopt(semi_major_axis_au,'semi_major_axis',db,min=0.,errcount=nerr) - semi_major_axis = semi_major_axis_au * au / udist - call read_inopt(eccentricity,'eccentricity',db,min=0.,errcount=nerr) - !-- masses - call read_inopt(q2,'q2',db,min=0.,max=1.,errcount=nerr) - !-- tight parameters - call read_inopt(binary2_a_au,'binary2_a',db,errcount=nerr) - binary2_a = binary2_a_au * au / udist - call read_inopt(binary2_e,'binary2_e',db,errcount=nerr) - !-- accretion radii,... - call read_inopt(racc2b_au,'racc2b',db,errcount=nerr) - racc2b = racc2b_au * au / udist - if (racc2b < tiny(0.)) then - print *,'WARNING: secondary accretion radius not defined' - !nerr = nerr+1 - endif - call read_inopt(lum2b_lsun,'lum2b',db,errcount=nerr) - lum2b = lum2b_lsun * (solarl * utime / unit_energ) - call read_inopt(Teff2b,'Teff2b',db,errcount=nerr) - call read_inopt(Reff2b_au,'Reff2b',db,errcount=nerr) - Reff2b = Reff2b_au * au / udist - call read_inopt(binary2_i,'inclination',db,errcount=nerr) - endif - - call read_inopt(default_particle_mass,'mass_of_particles',db,min=0.,errcount=nerr) - - if (isothermal) then - wind_gamma = 1. - call read_inopt(T_wind,'T_wind',db,min=0.,errcount=nerr) - if (iwind == 3) call read_inopt(temp_exponent,'temp_exponent',db,min=0.,max=5.,errcount=nerr) - else - call read_inopt(wind_gamma,'wind_gamma',db,min=1.,max=4.,errcount=nerr) - endif - call close_db(db) - ierr = nerr - call write_setupfile(filename) - -end subroutine read_setupfile - -end module setup diff --git a/src/tests/directsum.f90 b/src/tests/directsum.f90 index e79acc2cc..c99024b0c 100644 --- a/src/tests/directsum.f90 +++ b/src/tests/directsum.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module directsum ! diff --git a/src/tests/phantomtest.f90 b/src/tests/phantomtest.f90 index 2233c4967..dd310aa6f 100644 --- a/src/tests/phantomtest.f90 +++ b/src/tests/phantomtest.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantomtest ! diff --git a/src/tests/test_cooling.f90 b/src/tests/test_cooling.f90 index bf4d502bd..41db26289 100644 --- a/src/tests/test_cooling.f90 +++ b/src/tests/test_cooling.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testcooling ! diff --git a/src/tests/test_corotate.f90 b/src/tests/test_corotate.f90 index f42abe572..95d1d1b00 100644 --- a/src/tests/test_corotate.f90 +++ b/src/tests/test_corotate.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testcorotate ! diff --git a/src/tests/test_damping.f90 b/src/tests/test_damping.f90 index 14c2b9ac5..ca00a1b95 100644 --- a/src/tests/test_damping.f90 +++ b/src/tests/test_damping.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testdamping ! diff --git a/src/tests/test_derivs.F90 b/src/tests/test_derivs.F90 index 1f59eb848..4423158f5 100644 --- a/src/tests/test_derivs.F90 +++ b/src/tests/test_derivs.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testderivs ! diff --git a/src/tests/test_dust.f90 b/src/tests/test_dust.f90 index e89dfacd3..371059769 100644 --- a/src/tests/test_dust.f90 +++ b/src/tests/test_dust.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testdust ! diff --git a/src/tests/test_eos.f90 b/src/tests/test_eos.f90 index 6a6014b56..23a1372a7 100644 --- a/src/tests/test_eos.f90 +++ b/src/tests/test_eos.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testeos ! diff --git a/src/tests/test_eos_stratified.f90 b/src/tests/test_eos_stratified.f90 index a61ea477a..f8aaf1936 100644 --- a/src/tests/test_eos_stratified.f90 +++ b/src/tests/test_eos_stratified.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testeos_stratified ! diff --git a/src/tests/test_externf.f90 b/src/tests/test_externf.f90 index d2465227a..f6bb79410 100644 --- a/src/tests/test_externf.f90 +++ b/src/tests/test_externf.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testexternf ! diff --git a/src/tests/test_externf_gr.f90 b/src/tests/test_externf_gr.f90 index f1bf27461..ca7529063 100644 --- a/src/tests/test_externf_gr.f90 +++ b/src/tests/test_externf_gr.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testexternf ! diff --git a/src/tests/test_fastmath.F90 b/src/tests/test_fastmath.F90 deleted file mode 100644 index 76d7a2b0a..000000000 --- a/src/tests/test_fastmath.F90 +++ /dev/null @@ -1,162 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module testmath -! -! This module performs unit tests of the fast sqrt routines -! -! :References: None -! -! :Owner: Daniel Price -! -! :Runtime parameters: None -! -! :Dependencies: fastmath, io, mpiutils, random -! - implicit none - public :: test_math - - private - -contains - -subroutine test_math(ntests,npass,usefsqrt,usefinvsqrt) - use io, only:id,master - use fastmath, only:checksqrt,testsqrt,finvsqrt - use random, only:ran2 - use mpiutils, only:barrier_mpi - integer, intent(inout) :: ntests,npass - logical, intent(out) :: usefsqrt,usefinvsqrt - integer, parameter :: n = 1000000 - integer, parameter :: stderr = 0 - integer :: ierr,iseed,nerr,i - real, allocatable :: x(:),f(:),y(:) - real :: t1,t2,errmax,tnative - - if (id==master) write(*,"(a,/)") '--> TESTING FAST SQRT ROUTINES' - - usefsqrt = .true. - usefinvsqrt = .true. -! -!--check for errors first -! - call testsqrt(ierr,output=.false.) - if (ierr /= 0) then - ! report errors on any threads - write(*, "(a)") ' *** ERROR with fast sqrt on this architecture ***' - usefsqrt = .false. - usefinvsqrt = .false. - write(*,"(/,a,/)") '<-- FAST SQRT TEST FAILED' - return - endif - - allocate(x(n),f(n),y(n),stat=ierr) - if (ierr /= 0) return - - iseed = -5234 - do i=1,n - x(i) = ran2(iseed)*1.e8 - enddo - - ntests = ntests + 1 - nerr = 0 - do i=1,n - call checksqrt(x(i),5.e-7*x(i),ierr,.false.) - nerr = max(ierr,nerr) - enddo - if (nerr > 0) then - usefsqrt = .false. - usefinvsqrt = .false. - else - npass = npass + 1 - endif - -! -!--check timings for inverse sqrt -! - call cpu_time(t1) - do i=1,n - f(i) = 1./sqrt(x(i)) - enddo - call cpu_time(t2) - tnative = t2-t1 - if (id==master) write(*,"(a,es10.3,a)") ' native 1/sqrt done in ',tnative,' cpu-s' - y = f - - call barrier_mpi - - call cpu_time(t1) - do i=1,n - f(i) = finvsqrt(x(i)) - enddo - call cpu_time(t2) - - ! run tests on all threads, but only report detailed results on master thread - if (id==master) write(*,"(a,es10.3,a)") ' fast 1/sqrt done in ',t2-t1,' cpu-s' - - if ((t2-t1) > tnative) then - if (id==master) write(*,"(a,f4.1)") ' so finvsqrt(x) is SLOWER than 1/sqrt(x) by factor of ',& - (t2-t1)/tnative - usefinvsqrt = .false. - else - if (id==master) write(*,"(a,f4.1)") ' so finvsqrt(x) is FASTER than 1/sqrt(x) by factor of ', & - tnative/(t2-t1) - endif - - errmax = 0. - do i=1,n - errmax = max(errmax,abs(y(i) - f(i))/y(i)) - enddo - if (id==master) write(*,"(1x,a,es10.3)") 'max relative error is ',errmax - if (errmax > 1.e-7) usefinvsqrt = .false. - - if (id==master) write(*,*) - call barrier_mpi -! -!--check timings for sqrt -! - call cpu_time(t1) - do i=1,n - f(i) = sqrt(x(i)) - enddo - call cpu_time(t2) - tnative = t2-t1 - if (id==master) write(*,"(a,es10.3,a)") ' native sqrt done in ',tnative,' cpu-s' - y = f - call barrier_mpi - - call cpu_time(t1) - do i=1,n - f(i) = x(i)*finvsqrt(x(i)) - enddo - call cpu_time(t2) - if (id==master) write(*,"(a,es10.3,a)") ' x*finvsqrt(x) done in ',t2-t1,' cpu-s' - - if ((t2-t1) > tnative) then - if (id==master) write(*,"(a,f4.1)") ' so x*finvsqrt(x) is SLOWER than sqrt(x) by factor of ',& - (t2-t1)/tnative - usefsqrt = .false. - else - if (id==master) write(*,"(a,f4.1)") ' so x*finvsqrt(x) is FASTER than sqrt(x) by factor of ',tnative/(t2-t1) - endif - - errmax = 0. - do i=1,n - errmax = max(errmax,abs(y(i) - f(i))/(y(i) + epsilon(y))) - enddo - if (id==master) write(*,"(1x,a,es10.3)") 'max relative error is ',errmax - if (errmax > 1.e-7) usefinvsqrt = .false. - - if (allocated(x)) deallocate(x) - if (allocated(f)) deallocate(f) - if (allocated(y)) deallocate(y) - - if (id==master) write(*,"(/,a,/)") '<-- FAST SQRT TEST COMPLETE' - call barrier_mpi - -end subroutine test_math - -end module testmath diff --git a/src/tests/test_geometry.f90 b/src/tests/test_geometry.f90 index 91e66acbf..b32735f05 100644 --- a/src/tests/test_geometry.f90 +++ b/src/tests/test_geometry.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testgeometry ! diff --git a/src/tests/test_gnewton.f90 b/src/tests/test_gnewton.f90 index 19fd7b6ab..3dff7afa3 100644 --- a/src/tests/test_gnewton.f90 +++ b/src/tests/test_gnewton.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testgnewton ! diff --git a/src/tests/test_gr.F90 b/src/tests/test_gr.F90 deleted file mode 100644 index 5327c7042..000000000 --- a/src/tests/test_gr.F90 +++ /dev/null @@ -1,557 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module testgr -! -! Unit tests of General Relativity -! -! :References: Liptai & Price (2019), MNRAS -! -! :Owner: David Liptai -! -! :Runtime parameters: None -! -! :Dependencies: cons2prim, cons2primsolver, eos, extern_gr, inverse4x4, -! io, metric, metric_tools, part, physcon, step_lf_global, testutils, -! units, utils_gr, vectorutils -! - use testutils, only:checkval,checkvalbuf,checkvalbuf_end,update_test_scores - implicit none - - public :: test_gr - - private - -contains -!----------------------------------------------------------------------- -!+ -! Unit tests for General Relativity -!+ -!----------------------------------------------------------------------- -subroutine test_gr(ntests,npass) - use io, only:id,master - use units, only:set_units - use physcon, only:solarm - integer, intent(inout) :: ntests,npass - - call set_units(mass=1.d6*solarm,G=1.d0,c=1.d0) - if (id==master) write(*,"(/,a,/)") '--> TESTING GENERAL RELATIVITY' - call test_combinations_all(ntests,npass) - call test_precession(ntests,npass) - call test_inccirc(ntests,npass) - if (id==master) write(*,"(/,a)") '<-- GR TESTS COMPLETE' - -end subroutine test_gr - -!----------------------------------------------------------------------- -!+ -! Test of orbital precession in the Kerr metric -!+ -!----------------------------------------------------------------------- -subroutine test_precession(ntests,npass) - use metric_tools, only:imetric,imet_kerr,imet_schwarzschild - use metric, only:a - integer, intent(inout) :: ntests,npass - integer :: nerr(6),norbits,nstepsperorbit - real :: dt,period,x0,vy0,tmax,angtol,postol - real :: angmom(3),angmom0(3),xyz(3),vxyz(3) - - write(*,'(/,a)') '--> testing step_extern_gr (precession)' - if (imetric /= imet_kerr .and. imetric /= imet_schwarzschild) then - write(*,'(/,a)') ' Skipping test! Metric is not Kerr (or Schwarzschild).' - return - endif - - a = 0. - x0 = 90. - vy0 = 0.0521157 - xyz = (/x0,0. ,0./) - vxyz = (/0.,vy0,0./) - period = 2390. ! approximate - norbits = 4 - tmax = norbits*period - nstepsperorbit = 1000 - dt = 0.239 !period/nstepsperorbit - - call integrate_geodesic(tmax,dt,xyz,vxyz,angmom0,angmom) - - angtol = 1.08e-15 - postol = 1.4e-5 - call checkval(angmom(1),angmom0(1),angtol,nerr(1),'error in angmomx') - call checkval(angmom(2),angmom0(2),angtol,nerr(2),'error in angmomy') - call checkval(angmom(3),angmom0(3),angtol,nerr(3),'error in angmomz') - call checkval(xyz(1), 77.606726748045929,postol,nerr(4),'error in final x position') - call checkval(xyz(2),-45.576259888019351,postol,nerr(5),'error in final y position') - call checkval(xyz(3),0.0 ,postol,nerr(6),'error in final z position') - - call update_test_scores(ntests,nerr,npass) - -end subroutine test_precession - -!----------------------------------------------------------------------- -!+ -! Test of inclined circular orbit in the Kerr metric -!+ -!----------------------------------------------------------------------- -subroutine test_inccirc(ntests,npass) - use physcon, only:pi - use metric_tools, only:imetric,imet_kerr - use metric, only:a - integer, intent(inout) :: ntests,npass - integer :: nerr(6),norbits,nstepsperorbit - real :: dt,period,tmax - real :: angmom(3),angmom0(3),xyz(3),vxyz(3) - real :: m,omega,phi,q,r,rdot,rho2,theta,thetadot,vx,vy,vz,x1,y1,z1 - real :: R2,rfinal - - write(*,'(/,a)') '--> testing step_extern_gr (inclined circular orbit)' - - if (imetric /= imet_kerr) then - write(*,'(/,a)') ' Skipping test! Metric is not Kerr.' - return - endif - - a = 1. - r = 10. - theta = 45.*pi/180. ! convert to radians - phi = 0. - m = 1. - q = sqrt(r**2 - a**2*cos(theta)**2) - rho2 = r**2 + a**2*cos(theta)**2 - omega = q*sqrt(m)/(sin(theta)*(rho2*sqrt(r)+a*q*sqrt(m)*sin(theta))) !shakura 1987 - rdot = 0. - thetadot = 0. - - ! Cartesian coordinates - x1 = sqrt(r**2+a**2)*sin(theta)*cos(phi) - y1 = sqrt(r**2+a**2)*sin(theta)*sin(phi) - z1 = r*cos(theta) - vx = r/sqrt(r**2+a**2)*sin(theta)*cos(phi)*rdot + sqrt(r**2+a**2)*(cos(theta)*cos(phi)*thetadot-sin(theta)*sin(phi)*omega) - vy = r/sqrt(r**2+a**2)*sin(theta)*sin(phi)*rdot + sqrt(r**2+a**2)*(cos(theta)*sin(phi)*thetadot+sin(theta)*cos(phi)*omega) - vz = cos(theta)*rdot-r*sin(theta)*thetadot - - xyz = (/x1,y1,z1/) - vxyz = (/vx,vy,vz/) - - period = 2390. ! approximate - norbits = 4 - tmax = norbits*period - nstepsperorbit = 1000 - dt = 0.239 !period/nstepsperorbit - - call integrate_geodesic(tmax,dt,xyz,vxyz,angmom0,angmom) - - R2 = dot_product(xyz,xyz) - rfinal = sqrt(0.5*(R2-a**2) + 0.5*sqrt((R2-a**2)**2 + 4.*a**2*xyz(3)**2)) - - nerr = 0 - call checkval(angmom(1),angmom0(1),6.e-10,nerr(1),'error in angmomx') - call checkval(angmom(2),angmom0(2),6.e-10,nerr(2),'error in angmomy') - call checkval(angmom(3),angmom0(3),6.e-10,nerr(3),'error in angmomz') - call checkval(rfinal ,r ,5.08e-6,nerr(4),'error in final r position') - - call update_test_scores(ntests,nerr,npass) - -end subroutine test_inccirc - -!----------------------------------------------------------------------- -!+ -! test the geodesic integrator using test particle integration -! and the step_extern_gr routine -!+ -!----------------------------------------------------------------------- -subroutine integrate_geodesic(tmax,dt,xyz,vxyz,angmom0,angmom) - use io, only:iverbose - use part, only:igas,npartoftype,massoftype,set_particle_type,get_ntypes,ien_type - use step_lf_global, only:step_extern_gr - use eos, only:ieos - use cons2prim, only:prim2consall - use metric_tools, only:init_metric,unpack_metric - use extern_gr, only:get_grforce_all - real, intent(in) :: tmax,dt - real, intent(inout) :: xyz(3), vxyz(3) - real, intent(out) :: angmom0(3),angmom(3) - integer :: nsteps,ntypes,npart - real :: time,dtextforce,massi,blah - real :: xyzh(4,1),vxyzu(4,1),fext(3,1),pxyzu(4,1),dens(1),metrics(0:3,0:3,2,1),metricderivs(0:3,0:3,3,1) - - npart = 1 - - xyzh = 0. - vxyzu = 0. - pxyzu = 0. - fext = 0. - metrics = 0. - metricderivs = 0. - - xyzh(1:3,1) = xyz(:) - vxyzu(1:3,1) = vxyz(:) - xyzh(4,:) = 1. - vxyzu(4,:) = 0. - massi = 1.e-10 - call set_particle_type(1,igas) - - npartoftype(igas) = npart - massoftype(igas) = massi - ntypes = get_ntypes(npartoftype) - - ! - ! initialise runtime parameters - ! - ieos = 11 - iverbose = 1 - time = 0 - blah = dt - ien_type = 1 - - call init_metric(npart,xyzh,metrics,metricderivs) - call prim2consall(npart,xyzh,metrics,vxyzu,dens,pxyzu,use_dens=.false.) - call get_grforce_all(npart,xyzh,metrics,metricderivs,vxyzu,dens,fext,dtextforce) - call calculate_angmom(xyzh(1:3,1),metrics(:,:,:,1),massi,vxyzu(1:3,1),angmom0) - - nsteps = 0 - do while (time <= tmax) - nsteps = nsteps + 1 - time = time + dt - dtextforce = blah - call step_extern_gr(npart,ntypes,dt,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,time) - enddo - - call calculate_angmom(xyzh(1:3,1),metrics(:,:,:,1),massi,vxyzu(1:3,1),angmom) - - xyz(:) = xyzh(1:3,1) - vxyz(:) = vxyzu(1:3,1) - -end subroutine integrate_geodesic - -!----------------------------------------------------------------------- -!+ -! compute the angular momentum for the orbit -!+ -!----------------------------------------------------------------------- -subroutine calculate_angmom(xyzi,metrici,massi,vxyzi,angmomi) - use metric_tools, only:unpack_metric - use vectorutils, only:cross_product3D - use utils_gr, only:dot_product_gr - real, intent(in) :: xyzi(3),metrici(:,:,:),massi,vxyzi(3) - real, intent(out) :: angmomi(3) - real :: alpha_gr,beta_gr_UP(3),bigvi(3),fourvel_space(3),lorentzi,v2i,gammaijdown(3,3) - - call unpack_metric(metrici,betaUP=beta_gr_UP,alpha=alpha_gr,gammaijdown=gammaijdown) - bigvi = (vxyzi+beta_gr_UP)/alpha_gr - v2i = dot_product_gr(bigvi,bigvi,gammaijdown) - lorentzi = 1./sqrt(1.-v2i) - fourvel_space = (lorentzi/alpha_gr)*vxyzi - call cross_product3D(xyzi,fourvel_space,angmomi) ! position cross with four-velocity - angmomi=angmomi*massi - -end subroutine calculate_angmom - -!----------------------------------------------------------------------- -!+ -! Test various combinations of position, velocity and fluid quantities -!+ -!----------------------------------------------------------------------- -subroutine test_combinations_all(ntests,npass) - use eos, only:ieos - integer, intent(inout) :: ntests,npass - integer, parameter :: eos_to_test(2) = (/2,12/) - integer :: i - - do i = 1,size(eos_to_test) - ieos = eos_to_test(i) - call test_combinations(ntests,npass) - enddo - -end subroutine test_combinations_all - -!----------------------------------------------------------------------- -!+ -! Test various combinations of position, velocity and fluid quantities -!+ -!----------------------------------------------------------------------- -subroutine test_combinations(ntests,npass) - use physcon, only:pi - use eos, only:gamma,equationofstate,ieos - use utils_gr, only:dot_product_gr - use metric_tools, only:get_metric,get_metric_derivs,imetric,imet_kerr - use metric, only:metric_type - integer, intent(inout) :: ntests,npass - real :: radii(5),theta(5),phi(5),vx(5),vy(5),vz(5) - real :: utherm(7),density(7),errmax,errmaxg,errmaxc,errmaxd - real :: position(3),v(3),v4(0:3),sqrtg,gcov(0:3,0:3),gcon(0:3,0:3) - real :: ri,thetai,phii,vxi,vyi,vzi,x,y,z,p,t,dens,u,pondens,spsound - real :: dgdx1(0:3,0:3),dgdx2(0:3,0:3),dgdx3(0:3,0:3) - integer :: i,j,k,l,m,n,ii,jj - integer :: ncheck_metric,nfail_metric,ncheck_cons2prim,nfail_cons2prim - integer :: ncheckg,nfailg,ncheckd,nfaild - real, parameter :: tol = 2.e-15 - real, parameter :: tolc = 1.e-12 - real, parameter :: told = 4.e-7 - - write(*,'(/,a)') '--> testing metric and cons2prim with combinations of variables' - write(*,'(a)') ' metric type = '//trim(metric_type) - write(*,'(a,I4,/)') ' eos = ', ieos - - ntests = ntests + 4 - ncheck_metric = 0 - nfail_metric = 0 - ncheckg = 0 - nfailg = 0 - ncheck_cons2prim = 0 - nfail_cons2prim = 0 - ncheckd = 0 - nfaild = 0 - errmax = 0. - errmaxg = 0. - errmaxc = 0. - errmaxd = 0. - - ! ieos=12 - gamma = 5./3. - - radii = (/2.1,2.5,3.0,5.0,10.0/) - theta = (/0.,pi/4.,pi/2.,3.*pi/4.,pi/) - phi = (/0.,pi/4.,pi/2.,pi,3.*pi/2./) - - vx = (/0.,0.25,0.5,0.75,1./) - vy = vx - vz = vx - - utherm = (/1.e-3,1.,10.,100.,1000.,1.e5,1.e7/) - density = (/1.e-10,1.e-5,1.e-3,1.,10.,100.,1000./) - - t = -1. ! initial temperature guess to avoid complier warning - - do i=1,size(radii) - ri = radii(i) - do j=1,size(theta) - thetai = theta(j) - do k=1,size(phi) - phii = phi(k) - x = ri*sin(thetai)*cos(phii) - y = ri*sin(thetai)*sin(phii) - z = ri*cos(thetai) - position = (/x,y,z/) - - call get_metric(position,gcov,gcon,sqrtg) - call test_metric_i(gcov,gcon,sqrtg,ncheck_metric,nfail_metric,errmax,ncheckg,nfailg,errmaxg,tol) - - ! Check below is because Kerr metric derivatives currently badly behaved at the poles - ! Would be nice to remove this... - if ((imetric /= imet_kerr) .or. (x**2 + y**2 > 1.e-12)) then - call get_metric_derivs(position,dgdx1,dgdx2,dgdx3) - call test_metric_derivs_i(position,dgdx1,dgdx2,dgdx3,ncheckd,nfaild,errmaxd,told) - endif - - do l=1,size(vx) - vxi=vx(l) - do m=1,size(vy) - vyi=vy(m) - do n=1,size(vz) - vzi=vz(n) - - v = (/vxi,vyi,vzi/) - v4(0) = 1. - v4(1:3) = v(:) - - ! Only allow valid combinations of position and velocity to be tested. - ! i.e. Not faster than the speed of light locally (U0 real, not imaginary). - if (dot_product_gr(v4,v4,gcov) < 0.) then - do ii=1,size(utherm) - u = utherm(ii) - do jj=1,size(density) - dens = density(jj) - call equationofstate(ieos,pondens,spsound,dens,x,y,z,t,u) - p = pondens*dens - call test_cons2prim_i(position,v,dens,u,p,ncheck_cons2prim,nfail_cons2prim,errmaxc,tolc) - enddo - enddo - endif - - enddo - enddo - enddo - enddo - enddo - enddo - - call checkvalbuf_end('inv * metric = identity',ncheck_metric,nfail_metric,errmax,tol) - call checkvalbuf_end('sqrt g = -det(g)',ncheckg,nfailg,errmaxg,tol) - call checkvalbuf_end('d/dx^i g_munu',ncheckd,nfaild,errmaxd,told) - call checkvalbuf_end('conservative to primitive',ncheck_cons2prim,nfail_cons2prim,errmaxc,tolc) - if (nfail_metric==0) npass = npass + 1 - if (nfailg==0) npass = npass + 1 - if (nfaild==0) npass = npass + 1 - if (nfail_cons2prim==0) npass = npass + 1 - -end subroutine test_combinations - -!---------------------------------------------------------------- -!+ -! Test of the metric -!+ -!---------------------------------------------------------------- -subroutine test_metric_i(gcov,gcon,sqrtg,ncheck,nfail,errmax,ncheckg,nfailg,errmaxg,tol) - use inverse4x4, only:inv4x4 - integer, intent(inout) :: ncheck,nfail,ncheckg,nfailg - real, intent(in) :: gcov(0:3,0:3),gcon(0:3,0:3),sqrtg,tol - real, intent(inout) :: errmax,errmaxg - real, dimension(0:3,0:3) :: gg - real :: sum,det - integer :: i,j - - ! Product of metric and its inverse - gg = 0. - gg = matmul(gcov,gcon) - sum = 0 - do j=0,3 - do i=0,3 - sum = sum + gg(i,j) - enddo - enddo - - ! Check to see that the product is 4 (trace of identity) - call checkvalbuf(sum,4.,tol,'[F]: gddgUU ',nfail,ncheck,errmax) - - !if (nfail /= 0) then - ! print*,' metric ' - ! print "(4(es10.3,1x))",gcov - ! print*,' inverse ' - ! print "(4(es10.3,1x))",gcon - ! print*,' gg ' - ! print "(4(es10.3,1x))",gg - ! print*, 'gdown*gup /= Identity' - !endif - - ! Check that the determinant of the metric matches the one returned - call inv4x4(gcov,gg,det) - call checkvalbuf(-det,sqrtg,tol,'sqrt(g) ',nfailg,ncheckg,errmaxg) - -end subroutine test_metric_i - -!---------------------------------------------------------------- -!+ -! Check that analytic metric derivs give similar answer to -! numerical differences of the metric -!+ -!---------------------------------------------------------------- -subroutine test_metric_derivs_i(x,dgdx1,dgdx2,dgdx3,ncheck,nfail,errmax,tol) - use metric_tools, only:numerical_metric_derivs - real, intent(in) :: x(1:3),dgdx1(0:3,0:3),dgdx2(0:3,0:3),dgdx3(0:3,0:3),tol - integer, intent(inout) :: ncheck,nfail - real, intent(inout) :: errmax - real :: dgdx_1(0:3,0:3),dgdx_2(0:3,0:3),dgdx_3(0:3,0:3) - integer :: j,i - - call numerical_metric_derivs(x,dgdx_1,dgdx_2,dgdx_3) - do j=0,3 - do i=0,3 - call checkvalbuf(dgdx1(i,j),dgdx_1(i,j),tol,'dgcov/dx',nfail,ncheck,errmax) - call checkvalbuf(dgdx2(i,j),dgdx_2(i,j),tol,'dgcov/dy',nfail,ncheck,errmax) - call checkvalbuf(dgdx3(i,j),dgdx_3(i,j),tol,'dgcov/dz',nfail,ncheck,errmax) - enddo - enddo - -end subroutine test_metric_derivs_i - -!---------------------------------------------------------------- -!+ -! Test of the conservative to primitive variable solver -!+ -!---------------------------------------------------------------- -subroutine test_cons2prim_i(x,v,dens,u,p,ncheck,nfail,errmax,tol) - use cons2primsolver, only:conservative2primitive,primitive2conservative - 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 - - real, intent(in) :: x(1:3),v(1:3),dens,p,tol - real, intent(inout) :: u - integer, intent(inout) :: ncheck,nfail - real, intent(inout) :: errmax - real :: metrici(0:3,0:3,2) - real :: rho2,pmom2(1:3),en2,temp - real :: p2,u2,t2,dens2,gamma2,v2(1:3) - real :: pondens2,spsound2 - real :: v_out(1:3),dens_out,u_out,p_out,gamma_out - real :: toli - integer :: ierr,i,j,nfailprev,ien_type - real, parameter :: tolg = 1.e-7, tolp = 1.5e-6 - - ! perturb the state - dens2 = 2.*dens - u2 = 2.*u - t2 = -1. - - call equationofstate(ieos,pondens2,spsound2,dens2,x(1),x(2),x(3),t2,u2) - P2 = pondens2 * dens2 - v2 = v - - over_energy_variables: do i = 1,3 - ! Used for initial guess in conservative2primitive - v_out = v - dens_out = dens - u_out = u - p_out = p - gamma_out = 1. + p/(dens*u) - errmax = 0. - nfailprev = nfail - temp = 1.e7 ! arbitrary initial guess - gamma2 = 1. + P2/(dens2*u2) - - call pack_metric(x,metrici) - if (ieos == 12 .and. i /= 3) then - ! entropy_K and etotal cannot use with gasplusrad eos - cycle - elseif (i == 1) then - ien_type = ien_entropy - toli = 1.5e-11 - elseif (i == 2) then - ien_type = ien_etotal - toli = 1.5e-9 - else - ien_type = ien_entropy_s - toli = 1.5e-11 - endif - - call primitive2conservative(x,metrici,v,dens2,u2,P2,rho2,pmom2,en2,ien_type) - call conservative2primitive(x,metrici,v_out,dens_out,u_out,p_out,temp,gamma_out,rho2,pmom2,en2,ierr,ien_type) - - call checkvalbuf(ierr,0,0,'[F]: ierr (convergence)',nfail,ncheck) - do j=1,3 - call checkvalbuf(v_out(j),v2(j),toli,'[F]: v_out',nfail,ncheck,errmax) - enddo - call checkvalbuf(dens_out,dens2,toli,'[F]: dens_out',nfail,ncheck,errmax) - call checkvalbuf(u_out,u2,toli,'[F]: u_out',nfail,ncheck,errmax) - call checkvalbuf(p_out,p2,tolp,'[F]: p_out',nfail,ncheck,errmax) - call checkvalbuf(gamma_out,gamma2,tolg,'[F]: gamma_out',nfail,ncheck,errmax) - - if (nfail > nfailprev .and. nfail < 10) then - print*,'-- cons2prim test failed with' - print*,' ien_type =',ien_type - print*,' ieos =',ieos - print*,' - IN:' - print*,' x =',x - print*,' v =',v2 - print*,' dens =',dens2 - print*,' u =',u2 - print*,' p =',p2 - print*,' gamma=',gamma2 - print*,' - OUT:' - print*,' v =',v_out - print*,' dens =',dens_out - print*,' u =',u_out - print*,' p =',p_out - print*,' gamma=',gamma_out - print*,'' - endif - enddo over_energy_variables - -end subroutine test_cons2prim_i - -end module testgr diff --git a/src/tests/test_gravity.F90 b/src/tests/test_gravity.F90 deleted file mode 100644 index 196d998b5..000000000 --- a/src/tests/test_gravity.F90 +++ /dev/null @@ -1,642 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module testgravity -! -! Unit tests of self-gravity -! -! :References: None -! -! :Owner: Daniel Price -! -! :Runtime parameters: None -! -! :Dependencies: deriv, dim, directsum, energies, eos, io, kdtree, -! linklist, mpibalance, mpiutils, options, part, physcon, ptmass, -! sort_particles, spherical, testutils, timing -! - use io, only:id,master - implicit none - public :: test_gravity - - private - -contains -!----------------------------------------------------------------------- -!+ -! Unit tests for Newtonian gravity (i.e. Poisson solver) -!+ -!----------------------------------------------------------------------- -subroutine test_gravity(ntests,npass,string) - use dim, only:gravity - integer, intent(inout) :: ntests,npass - character(len=*), intent(in) :: string - logical :: testdirectsum,testpolytrope,testtaylorseries,testall - - testdirectsum = .false. - testtaylorseries = .false. - testpolytrope = .false. - testall = .false. - select case(string) - case('taylorseries') - testtaylorseries = .true. - case('directsum') - testdirectsum = .true. - case('polytrope') - testpolytrope = .true. - case default - testall = .true. - end select - - if (gravity) then - if (id==master) write(*,"(/,a,/)") '--> TESTING SELF-GRAVITY' - ! - !--unit test of Taylor series expansions in the treecode - ! - if (testtaylorseries .or. testall) call test_taylorseries(ntests,npass) - ! - !--unit tests of treecode gravity by direct summation - ! - if (testdirectsum .or. testall) call test_directsum(ntests,npass) - - if (id==master) write(*,"(/,a)") '<-- SELF-GRAVITY TESTS COMPLETE' - else - if (id==master) write(*,"(/,a)") '--> SKIPPING SELF-GRAVITY TESTS (need -DGRAVITY)' - endif - -end subroutine test_gravity - -!----------------------------------------------------------------------- -!+ -! Unit tests of the Taylor series expansion about local and distant nodes -!+ -!----------------------------------------------------------------------- -subroutine test_taylorseries(ntests,npass) - use kdtree, only:compute_fnode,expand_fgrav_in_taylor_series - use testutils, only:checkval,update_test_scores - integer, intent(inout) :: ntests,npass - integer :: nfailed(18),i,npnode - real :: xposi(3),xposj(3),x0(3),dx(3),fexact(3),f0(3) - real :: xposjd(3,3),dfdx_approx(3,3),d2f(3,3),dpot(3) - real :: fnode(20),quads(6) - real :: dr,dr2,phi,phiexact,pmassi,tol,totmass - - if (id==master) write(*,"(/,a)") '--> testing taylor series expansion about current node' - totmass = 5. - xposi = (/0.05,-0.04,-0.05/) ! position to evaluate the force at - xposj = (/1., 1., 1./) ! position of distant node - x0 = 0. ! position of nearest node centre - - call get_dx_dr(xposi,xposj,dx,dr) - fexact = -totmass*dr**3*dx ! exact force between i and j - phiexact = -totmass*dr ! exact potential between i and j - - call get_dx_dr(x0,xposj,dx,dr) - fnode = 0. - quads = 0. - call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode) - - dx = xposi - x0 ! perform expansion about x0 - call expand_fgrav_in_taylor_series(fnode,dx(1),dx(2),dx(3),f0(1),f0(2),f0(3),phi) - !print*,' exact force = ',fexact,' phi = ',phiexact - !print*,' force at origin = ',fnode(1:3), ' phi = ',fnode(20) - !print*,'force w. taylor series = ',f0, ' phi = ',phi - nfailed(:) = 0 - call checkval(f0(1),fexact(1),3.e-4,nfailed(1),'fx taylor series about f0') - call checkval(f0(2),fexact(2),1.1e-4,nfailed(2),'fy taylor series about f0') - call checkval(f0(3),fexact(3),9.e-5,nfailed(3),'fz taylor series about f0') - call checkval(phi,phiexact,8.e-4,nfailed(4),'phi taylor series about f0') - call update_test_scores(ntests,nfailed,npass) - - if (id==master) write(*,"(/,a)") '--> testing taylor series expansion about distant node' - totmass = 5. - npnode = 3 - xposjd(:,1) = (/1.03, 0.98, 1.01/) ! position of distant particle 1 - xposjd(:,2) = (/0.95, 1.01, 1.03/) ! position of distant particle 2 - xposjd(:,3) = (/0.99, 0.95, 0.95/) ! position of distant particle 3 - xposj = 0. - pmassi = totmass/real(npnode) - do i=1,npnode - xposj = xposj + pmassi*xposjd(:,i) ! centre of mass of distant node - enddo - xposj = xposj/totmass - !print*,' centre of mass of distant node = ',xposj - !--compute quadrupole moments - quads = 0. - do i=1,npnode - dx(:) = xposjd(:,i) - xposj - dr2 = dot_product(dx,dx) - quads(1) = quads(1) + pmassi*(3.*dx(1)*dx(1) - dr2) - quads(2) = quads(2) + pmassi*(3.*dx(1)*dx(2)) - quads(3) = quads(3) + pmassi*(3.*dx(1)*dx(3)) - quads(4) = quads(4) + pmassi*(3.*dx(2)*dx(2) - dr2) - quads(5) = quads(5) + pmassi*(3.*dx(2)*dx(3)) - quads(6) = quads(6) + pmassi*(3.*dx(3)*dx(3) - dr2) - enddo - - x0 = 0. ! position of nearest node centre - xposi = x0 ! position to evaluate the force at - fexact = 0. - phiexact = 0. - do i=1,npnode - dx = xposi - xposjd(:,i) - dr = 1./sqrt(dot_product(dx,dx)) - fexact = fexact - dr**3*dx ! exact force between i and j - phiexact = phiexact - dr ! exact force between i and j - enddo - fexact = fexact*pmassi - phiexact = phiexact*pmassi - - call get_dx_dr(x0,xposj,dx,dr) - fnode = 0. - call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode) - - dx = xposi - x0 ! perform expansion about x0 - call expand_fgrav_in_taylor_series(fnode,dx(1),dx(2),dx(3),f0(1),f0(2),f0(3),phi) - !print*,' exact force = ',fexact,' phi = ',phiexact - !print*,' force at origin = ',fnode(1:3), ' phi = ',fnode(20) - !print*,'force w. taylor series = ',f0, ' phi = ',phi - nfailed(:) = 0 - call checkval(f0(1),fexact(1),8.7e-5,nfailed(1),'fx taylor series about f0') - call checkval(f0(2),fexact(2),1.5e-6,nfailed(2),'fy taylor series about f0') - call checkval(f0(3),fexact(3),1.6e-5,nfailed(3),'fz taylor series about f0') - call checkval(phi,phiexact,5.9e-6,nfailed(4),'phi taylor series about f0') - call update_test_scores(ntests,nfailed,npass) - - if (id==master) write(*,"(/,a)") '--> checking results of compute_fnode routine' - ! - ! check that components of fnode are derivatives of each other - ! - tol = 1.e-6 - call get_finite_diff(3,x0,xposj,totmass,quads,fnode,dfdx_approx,dpot,d2f,tol) - nfailed(:) = 0 - call checkval(fnode(1),dpot(1),tol,nfailed(1),'fx=-dphi/dx') - call checkval(fnode(2),dpot(2),tol,nfailed(2),'fy=-dphi/dy') - call checkval(fnode(3),dpot(3),tol,nfailed(3),'fz=-dphi/dz') - call checkval(fnode(4),dfdx_approx(1,1),tol,nfailed(4),'dfx/dx') - call checkval(fnode(5),dfdx_approx(1,2),tol,nfailed(5),'dfx/dy') - call checkval(fnode(6),dfdx_approx(1,3),tol,nfailed(6),'dfx/dz') - call checkval(fnode(7),dfdx_approx(2,2),tol,nfailed(7),'dfy/dy') - call checkval(fnode(8),dfdx_approx(2,3),tol,nfailed(8),'dfx/dz') - call checkval(fnode(9),dfdx_approx(3,3),tol,nfailed(9),'dfz/dz') - call checkval(fnode(10),d2f(1,1),1.e-3,nfailed(10),'d^2fx/dx^2') - call checkval(fnode(13),d2f(1,2),1.1e-3,nfailed(11),'d^2fx/dy^2') - call checkval(fnode(15),d2f(1,3),1.e-3,nfailed(12),'d^2fx/dz^2') - call checkval(fnode(11),d2f(2,1),1.e-3,nfailed(13),'d^2fy/dx^2') - call checkval(fnode(16),d2f(2,2),1.e-3,nfailed(14),'d^2fy/dy^2') - call checkval(fnode(18),d2f(2,3),1.e-3,nfailed(15),'d^2fy/dz^2') - call checkval(fnode(12),d2f(3,1),1.e-3,nfailed(16),'d^2fz/dx^2') - call checkval(fnode(17),d2f(3,2),1.2e-3,nfailed(17),'d^2fz/dy^2') - call checkval(fnode(19),d2f(3,3),1.e-3,nfailed(18),'d^2fz/dz^2') - call update_test_scores(ntests,nfailed,npass) - - if (id==master) write(*,"(/,a)") '--> testing taylor series expansion about both current and distant nodes' - x0 = 0. ! position of nearest node centre - xposi = (/0.05,0.05,-0.05/) ! position to evaluate the force at - fexact = 0. - phiexact = 0. - do i=1,npnode - dx = xposi - xposjd(:,i) - dr = 1./sqrt(dot_product(dx,dx)) - fexact = fexact - dr**3*dx ! exact force between i and j - phiexact = phiexact - dr ! exact force between i and j - enddo - fexact = fexact*pmassi - phiexact = phiexact*pmassi - - dx = x0 - xposj - dr = 1./sqrt(dot_product(dx,dx)) ! compute approx force between node and j - fnode = 0. - call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode) - - dx = xposi - x0 ! perform expansion about x0 - call expand_fgrav_in_taylor_series(fnode,dx(1),dx(2),dx(3),f0(1),f0(2),f0(3),phi) - !print*,' exact force = ',fexact,' phi = ',phiexact - !print*,' force at origin = ',fnode(1:3), ' phi = ',fnode(20) - !print*,'force w. taylor series = ',f0, ' phi = ',phi - nfailed(:) = 0 - call checkval(f0(1),fexact(1),4.3e-5,nfailed(1),'fx taylor series about f0') - call checkval(f0(2),fexact(2),1.4e-4,nfailed(2),'fy taylor series about f0') - call checkval(f0(3),fexact(3),3.2e-4,nfailed(3),'fz taylor series about f0') - call checkval(phi,phiexact,9.7e-4,nfailed(4),'phi taylor series about f0') - call update_test_scores(ntests,nfailed,npass) - -end subroutine test_taylorseries - -!----------------------------------------------------------------------- -!+ -! Unit tests of the tree code gravity, checking it agrees with -! gravity computed via direct summation -!+ -!----------------------------------------------------------------------- -subroutine test_directsum(ntests,npass) - use io, only:id,master - use dim, only:maxp,maxptmass,mpi - use part, only:init_part,npart,npartoftype,massoftype,xyzh,hfact,vxyzu,fxyzu, & - gradh,poten,iphase,isetphase,maxphase,labeltype,& - nptmass,xyzmh_ptmass,fxyz_ptmass,dsdt_ptmass,ibelong - use eos, only:polyk,gamma - use options, only:ieos,alpha,alphau,alphaB,tolh - use spherical, only:set_sphere - use deriv, only:get_derivs_global - use physcon, only:pi - use timing, only:getused,printused - use directsum, only:directsum_grav - use energies, only:compute_energies,epot - use kdtree, only:tree_accuracy - use testutils, only:checkval,checkvalbuf_end,update_test_scores - use ptmass, only:get_accel_sink_sink,get_accel_sink_gas,h_soft_sinksink - use mpiutils, only:reduceall_mpi,bcast_mpi - use linklist, only:set_linklist - use sort_particles, only:sort_part_id - use mpibalance, only:balancedomains - - integer, intent(inout) :: ntests,npass - integer :: nfailed(18) - integer :: maxvxyzu,nx,np,i,k,merge_n,merge_ij(maxptmass),nfgrav - real :: psep,totvol,totmass,rhozero,tol,pmassi - real :: time,rmin,rmax,phitot,dtsinksink,fonrmax,phii,epot_gas_sink - real(kind=4) :: t1,t2 - real :: epoti,tree_acc_prev - real, allocatable :: fgrav(:,:),fxyz_ptmass_gas(:,:) - - maxvxyzu = size(vxyzu(:,1)) - tree_acc_prev = tree_accuracy - do k = 1,6 - if (labeltype(k)/='bound') then - if (id==master) write(*,"(/,3a)") '--> testing gravity force in densityforce for ',labeltype(k),' particles' -! -!--general parameters -! - time = 0. - hfact = 1.2 - gamma = 5./3. - rmin = 0. - rmax = 1. - ieos = 2 - tree_accuracy = 0.5 -! -!--setup particles -! - call init_part() - np = 1000 - totvol = 4./3.*pi*rmax**3 - nx = int(np**(1./3.)) - psep = totvol**(1./3.)/real(nx) - psep = 0.18 - npart = 0 - ! only set up particles on master, otherwise we will end up with n duplicates - if (id==master) then - call set_sphere('cubic',id,master,rmin,rmax,psep,hfact,npart,xyzh) - endif - np = npart -! -!--set particle properties -! - totmass = 1. - rhozero = totmass/totvol - npartoftype(:) = 0 - npartoftype(k) = int(reduceall_mpi('+',npart),kind=kind(npartoftype)) - massoftype(:) = 0.0 - massoftype(k) = totmass/npartoftype(k) - if (maxphase==maxp) then - do i=1,npart - iphase(i) = isetphase(k,iactive=.true.) - enddo - endif -! -!--set thermal terms and velocity to zero, so only force is gravity -! - polyk = 0. - vxyzu(:,:) = 0. -! -!--make sure AV is off -! - alpha = 0. - alphau = 0. - alphaB = 0. - tolh = 1.e-5 - - fxyzu = 0.0 -! -!--call derivs to get everything initialised -! - call get_derivs_global() -! -!--reset force to zero -! - fxyzu = 0.0 -! -!--move particles to master and sort for direct summation -! - if (mpi) then - ibelong(:) = 0 - call balancedomains(npart) - endif - call sort_part_id -! -!--allocate array for storing direct sum gravitational force -! - allocate(fgrav(maxvxyzu,npart)) - fgrav = 0.0 -! -!--compute gravitational forces by direct summation -! - if (id == master) then - call directsum_grav(xyzh,gradh,fgrav,phitot,npart) - endif -! -!--send phitot to all tasks -! - call bcast_mpi(phitot) -! -!--calculate derivatives -! - call getused(t1) - call get_derivs_global() - call getused(t2) - if (id==master) call printused(t1) -! -!--move particles to master and sort for test comparison -! - if (mpi) then - ibelong(:) = 0 - call balancedomains(npart) - endif - call sort_part_id -! -!--compare the results -! - call checkval(npart,fxyzu(1,:),fgrav(1,:),5.e-3,nfailed(1),'fgrav(x)') - call checkval(npart,fxyzu(2,:),fgrav(2,:),6.e-3,nfailed(2),'fgrav(y)') - call checkval(npart,fxyzu(3,:),fgrav(3,:),9.4e-3,nfailed(3),'fgrav(z)') - deallocate(fgrav) - epoti = 0. - do i=1,npart - epoti = epoti + poten(i) - enddo - epoti = reduceall_mpi('+',epoti) - call checkval(epoti,phitot,5.2e-4,nfailed(4),'potential') - call checkval(epoti,-3./5.*totmass**2/rmax,3.6e-2,nfailed(5),'potential=-3/5 GMM/R') - ! check that potential energy computed via compute_energies is also correct - call compute_energies(0.) - call checkval(epot,phitot,5.2e-4,nfailed(6),'epot in compute_energies') - call update_test_scores(ntests,nfailed(1:6),npass) - endif - enddo - - -!--test that the same results can be obtained from a cloud of sink particles -! with softening lengths equal to the original SPH particle smoothing lengths -! - if (maxptmass >= npart) then - if (id==master) write(*,"(/,3a)") '--> testing gravity in uniform cloud of softened sink particles' -! -!--move particles to master for sink creation -! - if (mpi) then - ibelong(:) = 0 - call balancedomains(npart) - endif -! -!--sort particles so that they can be compared at the end -! - call sort_part_id - - pmassi = totmass/reduceall_mpi('+',npart) - call copy_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,pmassi) - h_soft_sinksink = hfact*psep -! -!--compute direct sum for comparison, but with fixed h and hence gradh terms switched off -! - do i=1,npart - xyzh(4,i) = h_soft_sinksink - gradh(1,i) = 1. - gradh(2,i) = 0. - vxyzu(:,i) = 0. - enddo - allocate(fgrav(maxvxyzu,npart)) - fgrav = 0.0 - call directsum_grav(xyzh,gradh,fgrav,phitot,npart) - call bcast_mpi(phitot) -! -!--compute gravity on the sink particles -! - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epoti,& - dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) - call bcast_mpi(epoti) -! -!--compare the results -! - tol = 1.e-14 - call checkval(npart,fxyz_ptmass(1,:),fgrav(1,:),tol,nfailed(1),'fgrav(x)') - call checkval(npart,fxyz_ptmass(2,:),fgrav(2,:),tol,nfailed(2),'fgrav(y)') - call checkval(npart,fxyz_ptmass(3,:),fgrav(3,:),tol,nfailed(3),'fgrav(z)') - call checkval(epoti,phitot,8e-3,nfailed(4),'potential') - call checkval(epoti,-3./5.*totmass**2/rmax,4.1e-2,nfailed(5),'potential=-3/5 GMM/R') - call update_test_scores(ntests,nfailed(1:5),npass) - - -! -!--now perform the same test, but with HALF the cloud made of sink particles -! and HALF the cloud made of gas particles. Do not re-evaluate smoothing lengths -! so that the results should be identical to the previous test -! - if (id==master) write(*,"(/,3a)") & - '--> testing softened gravity in uniform sphere with half sinks and half gas' - -!--sort the particles by ID so that the first half will have the same order -! even after half the particles have been converted into sinks. This sort is -! not really necessary because the order shouldn't have changed since the -! last test because derivs hasn't been called since. - call sort_part_id - call copy_half_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,pmassi) - - print*,' Using ',npart,' SPH particles and ',nptmass,' point masses' - call get_derivs_global() - - epoti = 0.0 - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epoti,& - dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) -! -!--prevent double counting of sink contribution to potential due to MPI -! - if (id /= master) epoti = 0.0 -! -!--allocate an array for the gas contribution to sink acceleration -! - allocate(fxyz_ptmass_gas(size(fxyz_ptmass,dim=1),nptmass)) - fxyz_ptmass_gas = 0.0 - - epot_gas_sink = 0.0 - do i=1,npart - call get_accel_sink_gas(nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& - xyzmh_ptmass,fxyzu(1,i),fxyzu(2,i),fxyzu(3,i),& - phii,pmassi,fxyz_ptmass_gas,dsdt_ptmass,fonrmax,dtsinksink) - epot_gas_sink = epot_gas_sink + pmassi*phii - epoti = epoti + poten(i) - enddo -! -!--the gas contribution to sink acceleration has to be added afterwards to -! prevent double counting the sink contribution when calling reduceall_mpi -! - fxyz_ptmass_gas = reduceall_mpi('+',fxyz_ptmass_gas) - fxyz_ptmass(:,1:nptmass) = fxyz_ptmass(:,1:nptmass) + fxyz_ptmass_gas(:,1:nptmass) - deallocate(fxyz_ptmass_gas) -! -!--sum up potentials across MPI tasks -! - epoti = reduceall_mpi('+',epoti) - epot_gas_sink = reduceall_mpi('+',epot_gas_sink) - -! -!--move particles to master for comparison -! - if (mpi) then - ibelong(:) = 0 - call balancedomains(npart) - endif - call sort_part_id - - call checkval(npart,fxyzu(1,:),fgrav(1,:),5.e-2,nfailed(1),'fgrav(x)') - call checkval(npart,fxyzu(2,:),fgrav(2,:),6.e-2,nfailed(2),'fgrav(y)') - call checkval(npart,fxyzu(3,:),fgrav(3,:),9.4e-2,nfailed(3),'fgrav(z)') - -! -!--fgrav doesn't exist on worker tasks, so it needs to be sent from master -! - call bcast_mpi(npart) - if (id == master) nfgrav = size(fgrav,dim=2) - call bcast_mpi(nfgrav) - if (id /= master) then - deallocate(fgrav) - allocate(fgrav(maxvxyzu,nfgrav)) - endif - call bcast_mpi(fgrav) - - call checkval(nptmass,fxyz_ptmass(1,:),fgrav(1,npart+1:2*npart),2.3e-2,nfailed(4),'fgrav(xsink)') - call checkval(nptmass,fxyz_ptmass(2,:),fgrav(2,npart+1:2*npart),2.9e-2,nfailed(5),'fgrav(ysink)') - call checkval(nptmass,fxyz_ptmass(3,:),fgrav(3,npart+1:2*npart),3.7e-2,nfailed(6),'fgrav(zsink)') - - call checkval(epoti+epot_gas_sink,phitot,8e-3,nfailed(7),'potential') - call checkval(epoti+epot_gas_sink,-3./5.*totmass**2/rmax,4.1e-2,nfailed(8),'potential=-3/5 GMM/R') - call update_test_scores(ntests,nfailed(1:8),npass) - deallocate(fgrav) - endif -! -!--clean up doggie-doos -! - npartoftype(:) = 0 - massoftype(:) = 0. - tree_accuracy = tree_acc_prev - fxyzu = 0. - vxyzu = 0. - -end subroutine test_directsum - -subroutine copy_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,massi) - integer, intent(in) :: npart - integer, intent(out) :: nptmass - real, intent(in) :: xyzh(:,:),massi - real, intent(out) :: xyzmh_ptmass(:,:) - integer :: i - - nptmass = npart - do i=1,npart - ! make a sink particle with the position of each SPH particle - xyzmh_ptmass(1:3,i) = xyzh(1:3,i) - xyzmh_ptmass(4,i) = massi ! same mass as SPH particles - xyzmh_ptmass(5:,i) = 0. - enddo - -end subroutine copy_gas_particles_to_sinks - -subroutine copy_half_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,massi) - use io, only: id,master,fatal - use mpiutils, only: bcast_mpi - integer, intent(inout) :: npart - integer, intent(out) :: nptmass - real, intent(in) :: xyzh(:,:),massi - real, intent(out) :: xyzmh_ptmass(:,:) - integer :: i, nparthalf - - nptmass = 0 - nparthalf = npart/2 - - call bcast_mpi(nparthalf) - - if (id==master) then - ! Assuming all gas particles are already on master, - ! create sinks here and send them to other tasks - - ! remove half the particles by changing npart - npart = nparthalf - - do i=npart+1,2*npart - nptmass = nptmass + 1 - call bcast_mpi(nptmass) - ! make a sink particle with the position of each SPH particle - xyzmh_ptmass(1:3,nptmass) = xyzh(1:3,i) - xyzmh_ptmass(4,nptmass) = massi ! same mass as SPH particles - xyzmh_ptmass(5:,nptmass) = 0. - call bcast_mpi(xyzmh_ptmass(1:5,nptmass)) - enddo - else - ! Assuming there are no gas particles here, - ! get sinks from master - - if (npart /= 0) call fatal("copy_half_gas_particles_to_sinks","there are particles on a non-master task") - - ! Get nparthalf from master, but don't change npart from zero - do i=nparthalf+1,2*nparthalf - call bcast_mpi(nptmass) - call bcast_mpi(xyzmh_ptmass(1:5,nptmass)) - enddo - endif - -end subroutine copy_half_gas_particles_to_sinks - -subroutine get_dx_dr(x1,x2,dx,dr) - real, intent(in) :: x1(3),x2(3) - real, intent(out) :: dx(3),dr - - dx = x1 - x2 - dr = 1./sqrt(dot_product(dx,dx)) - -end subroutine get_dx_dr - -subroutine get_finite_diff(ndim,x0,xposj,totmass,quads,fnode,dfdx,dpot,d2f,eps) - use kdtree, only:compute_fnode - integer, intent(in) :: ndim - real, intent(in) :: x0(ndim),xposj(ndim),totmass,quads(6),fnode(20),eps - real, intent(out) :: dfdx(ndim,ndim),dpot(ndim),d2f(ndim,ndim) - integer :: i,j - real :: dx(ndim),x0_plus(ndim),x0_minus(ndim) - real :: dr,fnode_plus(20),fnode_minus(20) - - do j=1,ndim - x0_plus = x0 - x0_plus(j) = x0(j) + eps - x0_minus = x0 - x0_minus(j) = x0(j) - eps - do i=1,ndim - call get_dx_dr(x0_plus,xposj,dx,dr) - fnode_plus = 0. - call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode_plus) - - call get_dx_dr(x0_minus,xposj,dx,dr) - fnode_minus = 0. - call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode_minus) - - dfdx(i,j) = (fnode_plus(i) - fnode_minus(i))/(2.*eps) - d2f(i,j) = (fnode_plus(i) - 2.*fnode(i) + fnode_minus(i))/(eps*eps) - enddo - dpot(j) = -(fnode_plus(20) - fnode_minus(20))/(2.*eps) - enddo - -end subroutine get_finite_diff - -end module testgravity diff --git a/src/tests/test_growth.F90 b/src/tests/test_growth.F90 deleted file mode 100644 index a0d4c6e24..000000000 --- a/src/tests/test_growth.F90 +++ /dev/null @@ -1,406 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module testgrowth -! -! Unit tests of the growth module -! -! :References: -! -! :Owner: Arnaud Vericel -! -! :Runtime parameters: None -! -! :Dependencies: boundary, checksetup, deriv, dim, dust, energies, eos, -! growth, io, kernel, mpidomain, mpiutils, options, part, physcon, -! step_lf_global, testdust, testutils, timestep, unifdis, units, -! viscosity -! - use testutils, only:checkval,update_test_scores - use io, only:id,master -#ifdef DUST -#ifdef DUSTGROWTH - use testdust, only:test_dustybox -#endif -#endif - implicit none - public :: test_growth - - private - -contains -!----------------------------------------------------------------------- -!+ -! Unit tests for dust growth using Stepinksi & Valageas method -!+ -!----------------------------------------------------------------------- -subroutine test_growth(ntests,npass) -#ifdef DUST -#ifdef DUSTGROWTH - use growth, only:init_growth,ifrag,isnow - use physcon, only:solarm,au - use units, only:set_units - use mpiutils, only:barrier_mpi -#endif -#endif - integer, intent(inout) :: ntests,npass - -#ifdef DUST -#ifdef DUSTGROWTH - integer :: nfailed(5),ierr !don't forget the dimension of nfailed - logical, dimension(2) :: logic = (/.false., .true./) - integer :: i,j - - if (id==master) write(*,"(/,a)") '--> TESTING DUSTGROWTH MODULE' - - call set_units(mass=solarm,dist=au,G=1.d0) - - if (id==master) write(*,"(/,a)") '--> testing growth initialisation' - - nfailed = 0 - do ifrag=0,2 - do isnow=0,2 - call init_growth(ierr) - call checkval(ierr,0,0,nfailed(ifrag+isnow+1),'growth initialisation') - enddo - enddo - call update_test_scores(ntests,nfailed,npass) - - ! - ! The return of the dustybox test - ! - call test_dustybox(ntests,npass) - call barrier_mpi() - - ! - ! testing farmingbox with several config. - ! - do i=1,2 - do j=1,2 - call test_farmingbox(ntests,npass,frag=logic(i),onefluid=logic(j)) - call barrier_mpi() - enddo - enddo - - if (id==master) write(*,"(/,a)") '<-- DUSTGROWTH TEST COMPLETE' -#else - if (id==master) write(*,"(/,a)") '--> SKIPPING DUSTGROWTH TEST (REQUIRES -DDUST -DDUSTGROWTH)' -#endif -#endif - -end subroutine test_growth - -#ifdef DUST -#ifdef DUSTGROWTH - -!------------------- -!------------------- -!------------------- - -subroutine test_farmingbox(ntests,npass,frag,onefluid) - use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound - use kernel, only:hfact_default - use part, only:init_part,igas,idust,npart,xyzh,vxyzu,npartoftype,massoftype,set_particle_type,& - fxyzu,fext,Bevol,dBevol,dustprop,ddustprop,& - dustfrac,dustevol,ddustevol,iphase,maxtypes,& - VrelVf,dustgasprop,Omega_k,alphaind,iamtype,& - ndustlarge,ndustsmall,rhoh,deltav,this_is_a_test,periodic, & - npartoftypetot,update_npartoftypetot - use step_lf_global, only:step,init_step - use deriv, only:get_derivs_global - use energies, only:compute_energies - use testutils, only:checkvalbuf,checkvalbuf_end - use eos, only:ieos,polyk,gamma,get_spsound - use dust, only:idrag,init_drag - use growth, only:ifrag,init_growth,isnow,vfrag,gsizemincgs,get_size - use options, only:alpha,alphamax,use_dustfrac - use unifdis, only:set_unifdis - use dim, only:periodic,mhd,use_dust,maxp,maxalpha - use timestep, only:dtmax - use io, only:iverbose - use mpiutils, only:reduceall_mpi - use physcon, only:au,solarm,Ro,pi,fourpi - use viscosity, only:shearparam - use units, only:set_units,udist,unit_density!,unit_velocity - use mpidomain, only:i_belong - use checksetup, only:check_setup - - integer, intent(inout) :: ntests,npass - logical, intent(in) :: frag,onefluid - - integer :: nx,nerror,nwarn - integer :: itype,npart_previous,i,j,nsteps,modu,noutputs - integer :: ncheck(4),nerr(4) - real :: errmax(4) - integer :: ierr,iam - - logical :: do_output = .false. - real :: deltax,dz,hfact,totmass,rhozero - real :: Stcomp(20000),Stini(20000) - real :: cscomp(20000),tau(20000) - real :: s(20000),time,timelim(20000) - real :: sinit,dens,t,tmax,dt,dtext,dtnew,guillaume,dtgratio,rhog,rhod - - real, parameter :: tolst = 5.e-4 - real, parameter :: tolcs = 5.e-4 - real, parameter :: tols = 5.e-4 - real, parameter :: tolrho = 5.e-4 - - character(len=15) :: stringfrag - character(len=15) :: stringmethod - - ! initialise particle arrays to zero - call init_part() - - if (frag) then - sinit = 1./udist - gsizemincgs = 1.e-3 - dtgratio = 0.5 - stringfrag = "fragmentation" - else - sinit = 3.e-2/udist - dtgratio = 1. - stringfrag = "growth" - endif - - if (onefluid) then - use_dustfrac = .true. - stringmethod = "one fluid" - ndustsmall = 1 - ndustlarge = 0 - dtgratio = 1.e-1 - else - use_dustfrac = .false. - stringmethod = "two fluid" - ndustsmall = 0 - ndustlarge = 1 - endif - dens = 1./unit_density - - write(*,*)'--> testing FARMINGBOX using: ',trim(stringfrag),' and ',trim(stringmethod), ' dust method' - write(*,*)'------------------------------------------------------------------------' - - ! - ! initialise - ! - this_is_a_test = .true. - - ! - ! setup for dustybox problem - ! - nx = 32 - deltax = 1./nx - dz = 2.*sqrt(6.)/nx - call set_boundary(-0.5,0.5,-0.25,0.25,-dz,dz) - hfact = hfact_default - rhozero = 1.e-11/unit_density - totmass = rhozero*dxbound*dybound*dzbound - if (onefluid) then - rhog = rhozero * (1-dtgratio) - rhod = dtgratio * rhozero - else - rhog = rhozero - rhod = dtgratio * rhozero - endif - npart = 0 - fxyzu = 0. - dustprop = 0. - ddustprop = 0. - ddustevol = 0. - dBevol = 0. - if (maxalpha==maxp) alphaind(:,:) = 0. - - !- setting gas particles - itype = igas - npart_previous = npart - call set_unifdis('closepacked',id,master,xmin,xmax,ymin,ymax,zmin,zmax,& - deltax,hfact,npart,xyzh,periodic,verbose=.false.,mask=i_belong) - do i=npart_previous+1,npart - vxyzu(:,i) = 0. - fext(:,i) = 0. - if (mhd) Bevol(:,i) = 0. - if (use_dust) then - dustevol(:,i) = 0. - dustfrac(:,i) = 0. - deltav(:,:,i) = 0. - dustgasprop(:,i) = 0. - VrelVf(i) = 0. - if (use_dustfrac) then - dustfrac(1,i) = dtgratio - dustprop(1,i) = fourpi/3.*dens*sinit**3 - dustprop(2,i) = dens - else - dustprop(:,i) = 0. - dustfrac(:,i) = 0. - endif - endif - call set_particle_type(i,itype) - enddo - npartoftype(itype) = npart - npart_previous - call update_npartoftypetot - massoftype(itype) = totmass/npartoftypetot(itype) - - !- setting dust particles if not one fluid - if (.not. use_dustfrac) then - itype = idust - npart_previous = npart - call set_unifdis('closepacked',id,master,xmin,xmax,ymin,ymax,zmin,zmax,& - deltax,hfact,npart,xyzh,periodic,verbose=.false.,mask=i_belong) - do i=npart_previous+1,npart - vxyzu(:,i) = 0. - fext(:,i) = 0. - if (mhd) Bevol(:,i) = 0. - if (use_dust) then - dustevol(:,i) = 0. - dustfrac(:,i) = 0. - dustprop(1,i) = fourpi/3.*dens*sinit**3 - dustprop(2,i) = dens - dustgasprop(:,i) = 0. - VrelVf(i) = 0. - endif - call set_particle_type(i,itype) - enddo - npartoftype(itype) = npart - npart_previous - npartoftypetot(itype) = reduceall_mpi('+',npartoftype(itype)) - massoftype(itype) = dtgratio*totmass/npartoftypetot(itype) - endif - - ! - ! check that particle setup is sensible - ! - call check_setup(nerror,nwarn) - - ! - ! runtime parameters - ! - - ieos = 1 - idrag = 1 - if (frag) then - ifrag = 1 - shearparam = 2.5e-2 - else - ifrag = 0 - shearparam = 1.e-2 - endif - isnow = 0 - vfrag = 1.e-11 - gsizemincgs = 1.e-2 - polyk = 1.e-3 - gamma = 1. - alpha = 0. - alphamax = 0. - iverbose = 0 - - !- timestepping - dt = 1.e-3 - tmax = 0.2 - nsteps = int(tmax/dt) - noutputs = 150 - if (noutputs > nsteps) noutputs = nsteps - modu = int(nsteps/noutputs) - dtmax = nsteps*dt - - timelim(:) = 1.e3 - ncheck(:) = 0 - nerr(:) = 0 - errmax(:) = 0. - - t = 0. - - call init_drag(ierr) - call init_growth(ierr) - - call get_derivs_global() - - call init_step(npart,t,dtmax) - - do j=1,npart - iam = iamtype(iphase(j)) - if (iam == idust .or. (use_dustfrac .and. iam == igas)) then - cscomp(j) = get_spsound(ieos,xyzh(:,j),rhog,vxyzu(:,j)) - Stini(j) = sqrt(pi*gamma/8)*dens*sinit/((rhog+rhod)*cscomp(j)) * Omega_k(j) - Stcomp(j) = Stini(j) - tau(j) = 1/(sqrt(2**1.5*Ro*shearparam)*Omega_k(j))*(rhog+rhod)/rhod/sqrt(pi*gamma/8.) - s(j) = sinit - timelim(j) = 2*sqrt(Stini(j))*(1.+Stini(j)/3.)*tau(j) - endif - enddo - if (frag) write(*,"(a,f5.1,a)") "Analytical solution no longer valid after t = ", minval(timelim), " (size < 0)" - - ! - ! run farmingbox problem - ! - do i=1,nsteps - dtext = dt - call step(npart,npart,t,dt,dtext,dtnew) - t = t + dt - if (do_output .and. mod(i,modu)==0) then - call write_file_err(i,t,xyzh,dustprop(1,:)*udist,s*udist,dustgasprop(3,:),Stcomp,npart,"farmingbox_") - endif - do j=1,npart - iam = iamtype(iphase(j)) - if (iam == idust .or. (iam == igas .and. use_dustfrac)) then - if (frag) then - time = - t/tau(j) + 2.*sqrt(Stini(j))*(1.+Stini(j)/3.) - else - time = 2.*sqrt(Stini(j))*(1.+Stini(j)/3.) + t/tau(j) - endif - guillaume = (8.+9.*time*time+3.*time*sqrt(16.+9.*time*time))**(1./3.) - Stcomp(j) = guillaume/2. + 2./guillaume - 2 - s(j) = Stcomp(j)/(sqrt(pi*gamma/8)*dens/((rhog+rhod)*cscomp(j))*Omega_k(j)) - if (onefluid) then - call checkvalbuf(dustgasprop(3,j)/Stcomp(j),1.,tolst,'St',nerr(1),ncheck(1),errmax(1)) - call checkvalbuf(get_size(dustprop(1,j),dustprop(2,j))/s(j),1.,tols,'size',nerr(2),ncheck(2),errmax(2)) - else - call checkvalbuf(dustgasprop(3,j)/Stcomp(j),1.,tolst,'St',nerr(1),ncheck(1),errmax(1)) - call checkvalbuf(get_size(dustprop(1,j),dustprop(2,j))/s(j),1.,tols,'size',nerr(2),ncheck(2),errmax(2)) - call checkvalbuf(dustgasprop(1,j)/cscomp(j),1.,tolcs,'csound',nerr(3),ncheck(3),errmax(3)) - call checkvalbuf(dustgasprop(2,j)/rhozero,1.,tolrho,'rhogas',nerr(4),ncheck(4),errmax(4)) - endif - endif - enddo - enddo - if (onefluid) then - call checkvalbuf_end('Stokes number evaluation matches exact solution',ncheck(1),nerr(1),errmax(1),tolst) - call checkvalbuf_end('size evaluation matches exact solution',ncheck(2),nerr(2),errmax(2),tols) - else - call checkvalbuf_end('Stokes number interpolation matches exact solution',ncheck(1),nerr(1),errmax(1),tolst) - call checkvalbuf_end('size evaluation matches exact solution',ncheck(2),nerr(2),errmax(2),tols) - call checkvalbuf_end('sound speed interpolation matches exact number',ncheck(3),nerr(3),errmax(3),tolcs) - call checkvalbuf_end('rhogas interpolation matches exact number',ncheck(4),nerr(4),errmax(4),tolrho) - endif - - call update_test_scores(ntests,nerr,npass) - -end subroutine test_farmingbox - -subroutine write_file_err(step,t,xyzh,size,size_exact,St,St_exact,npart,prefix) - use part, only:iamdust,iphase,iamgas - real, intent(in) :: t - real, intent(in) :: xyzh(:,:) - real, intent(in) :: St(:),St_exact(:),size(:),size_exact(:) - character(len=*), intent(in) :: prefix - integer, intent(in) :: npart,step - character(len=30) :: filename,str - integer :: i,lu - - write(str,"(i000.4)") step - filename = prefix//'dust_'//trim(adjustl(str))//'.txt' - open(newunit=lu,file=filename,status='replace') - write(lu,*) t - do i=1,npart - if (iamdust(iphase(i))) write(lu,*) xyzh(1,i),xyzh(2,i),xyzh(3,i),size(i),size_exact(i),& - St(i),St_exact(i) - enddo - close(lu) - -end subroutine write_file_err - -#endif -#endif - -end module testgrowth diff --git a/src/tests/test_hierarchical.f90 b/src/tests/test_hierarchical.f90 index 8cd40fced..9d5f6899a 100644 --- a/src/tests/test_hierarchical.f90 +++ b/src/tests/test_hierarchical.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testsethier ! diff --git a/src/tests/test_indtstep.F90 b/src/tests/test_indtstep.F90 index ecd84373c..30d101661 100644 --- a/src/tests/test_indtstep.F90 +++ b/src/tests/test_indtstep.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testindtstep ! diff --git a/src/tests/test_kdtree.F90 b/src/tests/test_kdtree.F90 index 6971b69b5..4d5cfa0ab 100644 --- a/src/tests/test_kdtree.F90 +++ b/src/tests/test_kdtree.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testkdtree ! diff --git a/src/tests/test_kernel.f90 b/src/tests/test_kernel.f90 index 285dbef0e..6169a18f7 100644 --- a/src/tests/test_kernel.f90 +++ b/src/tests/test_kernel.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testkernel ! diff --git a/src/tests/test_link.F90 b/src/tests/test_link.F90 index d8852dde5..95c8a961a 100644 --- a/src/tests/test_link.F90 +++ b/src/tests/test_link.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testlink ! diff --git a/src/tests/test_luminosity.F90 b/src/tests/test_luminosity.F90 index 89941749c..dab7dc68f 100644 --- a/src/tests/test_luminosity.F90 +++ b/src/tests/test_luminosity.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testlum ! diff --git a/src/tests/test_mpi.F90 b/src/tests/test_mpi.F90 deleted file mode 100644 index f4b685f29..000000000 --- a/src/tests/test_mpi.F90 +++ /dev/null @@ -1,100 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module testmpi -! -! MPI unit tests -! -! :References: None -! -! :Owner: David Liptai -! -! :Runtime parameters: None -! -! :Dependencies: io, mpiforce, mpimemory, physcon, testutils, units -! - use testutils, only:checkval,checkvalbuf,checkvalbuf_end,update_test_scores - implicit none - - public :: test_mpi - - private - -contains - -subroutine test_mpi(ntests,npass) - use io, only:id,master - use units, only:set_units - use physcon, only:solarm - integer, intent(inout) :: ntests,npass - - call set_units(mass=1.d6*solarm,G=1.d0,c=1.d0) - if (id==master) write(*,"(/,a,/)") '--> TESTING MPI' - call test_increase_mpi_memory(ntests,npass) - if (id==master) write(*,"(/,a)") '<-- MPI TESTS COMPLETE' - -end subroutine test_mpi - -subroutine test_increase_mpi_memory(ntests,npass) - use mpimemory, only:allocate_mpi_memory,increase_mpi_memory,& - deallocate_mpi_memory,stacksize,force_stack_1,& - push_onto_stack - use mpiforce, only:cellforce - integer, intent(inout) :: ntests,npass - integer, parameter :: new_stacksize=100 - type(cellforce) :: cell - integer :: nerr(3), ncheck(3), i, stacksize_orig - real :: maxerr(3) - - nerr = 0 - ncheck = 0 - maxerr = 0. - - ! Save original stacksize, assuming they're the same for dens and force - stacksize_orig = stacksize - - ! Deallocate existing stack - call deallocate_mpi_memory - - ! Allocate the stacks again at a smaller size. - call allocate_mpi_memory(stacksize_in=new_stacksize) - - ! Write some data to each cell - do i=1,new_stacksize - cell%xpos = [1.,2.,3.] * i - call push_onto_stack(force_stack_1, cell) - enddo - - ! Ensure size of force_stack_1 is what we expect it to be - call checkval(force_stack_1%n,new_stacksize,0,nerr(1),'stacksize after pushing cells') - call update_test_scores(ntests,nerr,npass) - - ! Trigger a stacksize increase - if this doesn't segfault, that's a good sign - call increase_mpi_memory - - ! Ensure stack size hasn't changed - call checkval(force_stack_1%n,new_stacksize,0,nerr(1),'stacksize after mem increase') - call update_test_scores(ntests,nerr,npass) - - ! Check cell data is the same as what was written into cells above - do i=1,new_stacksize - call checkvalbuf(force_stack_1%cells(i)%xpos(1),1.*i,1.e-15,'error in xpos(1) after mem increase',nerr(1),ncheck(1),maxerr(1)) - call checkvalbuf(force_stack_1%cells(i)%xpos(2),2.*i,1.e-15,'error in xpos(2) after mem increase',nerr(2),ncheck(2),maxerr(2)) - call checkvalbuf(force_stack_1%cells(i)%xpos(3),3.*i,1.e-15,'error in xpos(3) after mem increase',nerr(3),ncheck(3),maxerr(3)) - enddo - - call checkvalbuf_end('error in xpos(1) after mem increase asfgd',ncheck(1),nerr(1),maxerr(1),1.e-15) - call checkvalbuf_end('error in xpos(2) after mem increase asfgd',ncheck(2),nerr(2),maxerr(2),1.e-15) - call checkvalbuf_end('error in xpos(3) after mem increase asfgd',ncheck(3),nerr(3),maxerr(3),1.e-15) - call update_test_scores(ntests,nerr,npass) - - ! Reallocate previous stack - call deallocate_mpi_memory - call allocate_mpi_memory(stacksize_in=stacksize_orig) - -end subroutine test_increase_mpi_memory - -end module testmpi diff --git a/src/tests/test_nonidealmhd.F90 b/src/tests/test_nonidealmhd.F90 index 9a49c3518..e03bab93d 100644 --- a/src/tests/test_nonidealmhd.F90 +++ b/src/tests/test_nonidealmhd.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testnimhd ! diff --git a/src/tests/test_part.f90 b/src/tests/test_part.f90 index 62add8a8c..aa4086b6f 100644 --- a/src/tests/test_part.f90 +++ b/src/tests/test_part.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testpart ! diff --git a/src/tests/test_poly.f90 b/src/tests/test_poly.f90 index 7053c571d..a5bb1b56c 100644 --- a/src/tests/test_poly.f90 +++ b/src/tests/test_poly.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testpoly ! diff --git a/src/tests/test_ptmass.f90 b/src/tests/test_ptmass.f90 index 04b35b897..2096c3d5d 100644 --- a/src/tests/test_ptmass.f90 +++ b/src/tests/test_ptmass.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testptmass ! diff --git a/src/tests/test_radiation.f90 b/src/tests/test_radiation.f90 index 8d1778ebd..36c299cfd 100644 --- a/src/tests/test_radiation.f90 +++ b/src/tests/test_radiation.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testradiation ! @@ -411,6 +411,7 @@ subroutine test_radiation_diffusion(ntests,npass) ! reset various things call init_part() limit_radiation_flux = .true. + drad = 0. end subroutine test_radiation_diffusion @@ -451,7 +452,7 @@ subroutine setup_radiation_diffusion_problem_sinusoid(kappa_code,c_code,xi0,rho0 rho0 = 2.5e-24 massoftype(igas) = rho0*dxbound*dybound*dzbound/nptot pmassi = massoftype(igas) - if (maxphase==maxp) iphase(:) = isetphase(igas,iactive=.true.) + if (maxphase==maxp) iphase(1:npart) = isetphase(igas,iactive=.true.) npartoftype(:) = 0 npartoftype(igas) = npart nactive = npart diff --git a/src/tests/test_rwdump.F90 b/src/tests/test_rwdump.F90 index 49dfedfcd..febdb7eb0 100644 --- a/src/tests/test_rwdump.F90 +++ b/src/tests/test_rwdump.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testrwdump ! diff --git a/src/tests/test_sedov.F90 b/src/tests/test_sedov.F90 index 687fb4732..d12efb34a 100644 --- a/src/tests/test_sedov.F90 +++ b/src/tests/test_sedov.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testsedov ! @@ -167,7 +167,7 @@ subroutine test_sedov(ntests,npass) angtot_in = angtot totmom_in = totmom mdust_in = mdust - call evol('test.in',logfile,evfile,dumpfile) + call evol('test.in',logfile,evfile,dumpfile,1) call write_evfile(time,dt) etotend = etot momtotend = totmom diff --git a/src/tests/test_setdisc.f90 b/src/tests/test_setdisc.f90 index 392fb0d70..2f7bf026f 100644 --- a/src/tests/test_setdisc.f90 +++ b/src/tests/test_setdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testsetdisc ! diff --git a/src/tests/test_smol.F90 b/src/tests/test_smol.F90 index 014c51969..7b26c1b65 100644 --- a/src/tests/test_smol.F90 +++ b/src/tests/test_smol.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testsmol ! diff --git a/src/tests/test_step.F90 b/src/tests/test_step.F90 index eceb5ceb2..9bd8f7ad8 100644 --- a/src/tests/test_step.F90 +++ b/src/tests/test_step.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module teststep ! diff --git a/src/tests/utils_testsuite.f90 b/src/tests/utils_testsuite.f90 index 0c8efdf46..8f05a7d0c 100644 --- a/src/tests/utils_testsuite.f90 +++ b/src/tests/utils_testsuite.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module testutils ! From 3be9f366c21cb58cad4121d7292939001815a9e2 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 11 Apr 2024 15:16:08 +0100 Subject: [PATCH 105/182] restoring upstream changes part5. Passes test suite! --- build/Makefile | 3 +- src/main/cons2prim.f90 | 3 +- src/main/cooling.F90 | 26 +- src/main/cooling_stamatellos.f90 | 2 +- src/main/eos.F90 | 4 +- src/main/eos_stamatellos.f90 | 3 +- src/main/force.F90 | 185 +++------ src/main/readwrite_infile.F90 | 11 +- src/main/step_leapfrog.F90 | 7 +- src/tests/test_gravity.f90 | 642 +++++++++++++++++++++++++++++++ src/tests/test_growth.f90 | 394 +++++++++++++++++++ 11 files changed, 1113 insertions(+), 167 deletions(-) create mode 100644 src/tests/test_gravity.f90 create mode 100644 src/tests/test_growth.f90 diff --git a/build/Makefile b/build/Makefile index 32282cb91..0ca66f007 100644 --- a/build/Makefile +++ b/build/Makefile @@ -498,6 +498,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ cooling_koyamainutsuka.f90 \ cooling_ism.f90 \ cooling_molecular.f90 \ + cooling_stamatellos.f90\ cooling_functions.f90 \ cooling_solver.f90 \ h2chem.f90 cooling.f90 @@ -505,7 +506,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos.f90 +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.f90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 151dc9337..9c1130f8e 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -177,8 +177,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& iohm,ihall,nden_nimhd,eta_nimhd,iambi,get_partinfo,iphase,this_is_a_test,& ndustsmall,itemp,ikappa,idmu,idgamma,icv use part, only:nucleation,igamma - use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,& - gamma + use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,gamma use radiation_utils, only:radiation_equation_of_state,get_opacity use dim, only:mhd,maxvxyzu,maxphase,maxp,use_dustgrowth,& do_radiation,nalpha,mhd_nonideal,do_nucleation,use_krome,update_muGamma diff --git a/src/main/cooling.F90 b/src/main/cooling.F90 index 582838213..aa2dda90b 100644 --- a/src/main/cooling.F90 +++ b/src/main/cooling.F90 @@ -84,20 +84,16 @@ subroutine init_cooling(id,master,iprint,ierr) if (id==master) write(iprint,*) 'initialising ISM cooling functions...' abund_default(iHI) = 1. call init_cooling_ism() - else - select case(icooling) - case(9) - if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=9 requires ieos=21',& - 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) - if (do_radiation) then - call fatal('cooling','Do radiation was switched on!') - endif + if (icooling==8) cooling_in_step = .false. + case(9) + if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=9 requires ieos=21',& + 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) @@ -110,8 +106,6 @@ subroutine init_cooling(id,master,iprint,ierr) case(7) ! Gammie PL cooling_in_step = .false. - case(8) - cooling_in_step = .false. case default call init_cooling_solver(ierr) end select diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 75b0b2412..52705cc45 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_stamatellos ! diff --git a/src/main/eos.F90 b/src/main/eos.F90 index e90d18aeb..55ae32e93 100644 --- a/src/main/eos.F90 +++ b/src/main/eos.F90 @@ -461,7 +461,7 @@ end subroutine equationofstate subroutine init_eos(eos_type,ierr) use units, only:unit_velocity use physcon, only:Rg - use io, only:error,warning + use io, only:error,warning,fatal use eos_mesa, only:init_eos_mesa use eos_helmholtz, only:eos_helmholtz_init use eos_piecewise, only:init_eos_piecewise @@ -547,7 +547,7 @@ subroutine init_eos(eos_type,ierr) endif case(21) call read_optab(eos_file,ierr) - if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) + if (ierr > 0) call fatal('init_eos','Failed to read EOS file') call init_S07cool end select diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index a5586f7be..060633d6a 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module eos_stamatellos ! @@ -20,6 +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(:) character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file logical,parameter,public :: doFLD = .True. integer,public :: iunitst=19 diff --git a/src/main/force.F90 b/src/main/force.F90 index 2caa4f23f..3d7b3fc33 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -39,7 +39,7 @@ module forces ! ! :Runtime parameters: None ! -! :Dependencies: boundary, cooling, dim, dust, eos, eos_shen, eos_stamatellos,fastmath, +! :Dependencies: boundary, cooling, dim, dust, eos, eos_shen, fastmath, ! growth, io, io_summary, kdtree, kernel, linklist, metric_tools, ! mpiderivs, mpiforce, mpimemory, mpiutils, nicil, omputils, options, ! part, physcon, ptmass, ptmass_heating, radiation_utils, timestep, @@ -53,8 +53,6 @@ module forces use part, only:iradxi,ifluxx,ifluxy,ifluxz,ikappa,ien_type,ien_entropy,ien_etotal,ien_entropy_s implicit none - character(len=80), parameter, public :: & ! module version - modid="$Id$" integer, parameter :: maxcellcache = 1000 @@ -898,14 +896,14 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g #ifdef FINVSQRT use fastmath, only:finvsqrt #endif - use kernel, only:grkern,cnormk,radkern2,wkern + use kernel, only:grkern,cnormk,radkern2 use part, only:igas,idust,iohm,ihall,iambi,maxphase,iactive,& iamtype,iamdust,get_partinfo,mhd,maxvxyzu,maxdvdx,igasP,ics,iradP,itemp use dim, only:maxalpha,maxp,mhd_nonideal,gravity,gr use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt - use eos, only:ieos,eos_is_non_ideal,gamma - use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,getopac_opdep,get_k_fld + use eos, only:ieos,eos_is_non_ideal + use eos_stamatellos, only:gradP_cool,Gpot_cool #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -913,18 +911,21 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g #ifdef PERIODIC use boundary, only:dxbound,dybound,dzbound #endif - use dim, only:use_dust,use_dustgrowth,ind_timesteps>>>>>>> upstream/master + use dim, only:use_dust,use_dustgrowth,ind_timesteps + use dust, only:get_ts,idrag,icut_backreaction,ilimitdustflux,irecon,drag_implicit + use kernel, only:wkern_drag,cnormk_drag,wkern,cnormk + use part, only:ndustsmall,grainsize,graindens,ndustsmall,grainsize,graindens,filfac + use options, only:use_porosity,icooling + use growth, only:get_size use kernel, only:wkern,cnormk #ifdef IND_TIMESTEPS use part, only:ibin_old,iamboundary use timestep_ind,only:get_dt #endif use timestep, only:bignumber - use options, only:overcleanfac,use_dustfrac,ireconav,icooling,limit_radiation_flux + use options, only:overcleanfac,use_dustfrac,ireconav,limit_radiation_flux use units, only:get_c_code -#ifdef GR use metric_tools,only:imet_minkowski,imetric -#endif use utils_gr, only:get_bigv use radiation_utils, only:get_rad_R integer, intent(in) :: i @@ -987,16 +988,11 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g #ifdef KROME real :: gammaj #endif -#ifdef DUST integer :: iregime,idusttype,l real :: dragterm,dragheating,wdrag,dv2,tsijtmp real :: grkernav,tsj(maxdusttypes),dustfracterms(maxdusttypes),term real :: projvstar,projf_drag,epstsj,sdrag1,sdrag2!,rhogas1i - !real :: Dav(maxdusttypes),vsigeps,depsdissterm(maxdusttypes) -#ifdef DUSTGROWTH real :: winter -#endif -#endif real :: dBevolx,dBevoly,dBevolz,divBsymmterm,divBdiffterm real :: rho21i,rho21j,Bxi,Byi,Bzi,psii,pmjrho21grkerni,pmjrho21grkernj real :: auterm,avBterm,mrhoi5,vsigB @@ -1027,8 +1023,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi,wkernj,wkerni,gradpx,gradpy,gradpz - real :: gradP_cooli,gradP_coolj,kfldi,kfldj,Ti,Tj,diffterm,gmwi + real :: radPj,fgravxi,fgravyi,fgravzi + real :: gradpx,gradpy,gradpz,gradP_cooli,gradP_coolj ! unpack xi = xpartveci(ixi) @@ -1133,8 +1129,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g Bzi = 0.0 psii = 0.0 endif - if (use_dustfrac) then -#ifdef DUST + if (use_dust .and. use_dustfrac) then dustfraci(:) = xpartveci(idustfraci:idustfraciend) dustfracisum = sum(dustfraci(:)) if (ilimitdustflux) then @@ -1143,17 +1138,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g tsi(:) = xpartveci(itstop:itstopend) endif epstsi = sum(dustfraci(:)*tsi(:)) -!------------------------------------------------ -!--sqrt(rho*epsilon) method -! sqrtrhodustfraci(:) = sqrt(rhoi*dustfraci(:)) -!------------------------------------------------ !--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) sqrtrhodustfraci(:) = sqrt(dustfraci(:)/(1.-dustfraci(:))) -!------------------------------------------------ -!--asin(sqrt(epsilon)) method -! sqrtrhodustfraci(:) = asin(sqrt(dustfraci(:))) -!------------------------------------------------ -#endif else dustfraci(:) = 0. dustfracisum = 0. @@ -1201,17 +1187,11 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (icooling == 9) then gradP_cool(i) = 0d0 Gpot_cool(i) = 0d0 - duFLD(i) = 0d0 gradpx = 0d0 gradpy = 0d0 gradpz = 0d0 - diffterm = 0d0 - if (dt > 0d0) then - ! print *, "rhoi,eni,i,kfldi,Ti", rhoi,eni,i - call get_k_fld(rhoi,eni,i,kfldi,Ti) - endif endif - + loop_over_neighbours2: do n = 1,nneigh j = abs(listneigh(n)) @@ -1336,11 +1316,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g ibin_wake(j) = max(ibinnow_m1,ibin_wake(j)) ibin_neighi = max(ibin_neighi,ibin_old(j)) endif -#ifdef DUST - if (drag_implicit) then + if (use_dust .and. drag_implicit) then dti = min(dti,get_dt(dt,ibin_old(j))) endif -#endif #endif endif pmassj = massoftype(iamtypej) @@ -1370,7 +1348,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (iamgasj .and. maxvxyzu >= 4) then enj = vxyzu(4,j) - if (eos_is_non_ideal(ieos)) then ! Is this condition required, or should this be always true? + if (eos_is_non_ideal(ieos)) then ! only do this if eos requires temperature in physical units tempj = eos_vars(itemp,j) denij = 0.5*(eni/tempi + enj/tempj)*(tempi - tempj) ! dU = c_V * dT else @@ -1378,6 +1356,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif else denij = 0. + enj = 0. endif if (gr) then @@ -1455,16 +1434,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g dustfracj(:) = dustfrac(:,j) dustfracjsum = sum(dustfracj(:)) rhogasj = rhoj*(1. - dustfracjsum) -!------------------------------------------------ -!--sqrt(rho*epsilon) method -! sqrtrhodustfracj(:) = sqrt(rhoj*dustfracj(:)) -!------------------------------------------------ -!--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) + !--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) sqrtrhodustfracj(:) = sqrt(dustfracj(:)/(1.-dustfracj(:))) -!------------------------------------------------ -!--asin(sqrt(epsilon)) method -! sqrtrhodustfracj(:) = asin(sqrt(dustfracj(:))) -!------------------------------------------------ else dustfracj(:) = 0. dustfracjsum = 0. @@ -1474,7 +1445,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (maxalpha==maxp) alphaj = alphaind(1,j) - if (gr) densj = dens(j) prj = eos_vars(igasP,j) spsoundj = eos_vars(ics,j) radPj = 0. @@ -1511,7 +1481,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g !rhoj = 0. rho1j = 0. rho21j = 0. - densj = 0. mrhoj5 = 0. autermj = 0. @@ -1543,6 +1512,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g qrho2i = 0. qrho2j = 0. if (gr) then + densj = dens(j) enthi = 1.+eni+pri/densi enthj = 1.+enj+prj/densj endif @@ -1617,27 +1587,26 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g gradP_cooli = pmassj*pri*rho1i*rho1i*grkerni gradP_coolj = 0d0 if (usej) then - gradp_coolj = pmassj*prj*rho1j*rho1j*grkernj + gradp_coolj = pmassj*prj*rho1j*rho1j*grkernj endif endif + !--artificial thermal conductivity (need j term) if (maxvxyzu >= 4) then -#ifdef GR - denij = alphagri*eni/lorentzi - alphagrj*enj/lorentzj - if (imetric==imet_minkowski) then ! Eq 60 in LP19 - rhoav1 = 2./(enthi*densi + enthj*densj) - vsigu = min(1.,sqrt(abs(pri-prj)*rhoav1)) - else - vsigu = abs(vij) ! Eq 61 in LP19 - endif -#else - if (gravity) then + if (gr) then + denij = alphagri*eni/lorentzi - alphagrj*enj/lorentzj + if (imetric==imet_minkowski) then ! Eq 60 in LP19 + rhoav1 = 2./(enthi*densi + enthj*densj) + vsigu = min(1.,sqrt(abs(pri-prj)*rhoav1)) + else + vsigu = abs(vij) ! Eq 61 in LP19 + endif + elseif (gravity) then vsigu = abs(projv) else rhoav1 = 2./(rhoi + rhoj) vsigu = sqrt(abs(pri - prj)*rhoav1) endif -#endif dendissterm = vsigu*denij*(auterm*grkerni + autermj*grkernj) endif @@ -1727,12 +1696,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g projsy = projsyi + projsyj projsz = projszi + projszj - fsum(ifxi) = fsum(ifxi) - runix*(gradp + fgrav) - projsx fsum(ifyi) = fsum(ifyi) - runiy*(gradp + fgrav) - projsy fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) - if (icooling == 9) then Gpot_cool(i) = Gpot_cool(i) + pmassj*phii gradpx = gradpx + runix*(gradP_cooli + gradP_coolj) @@ -1748,31 +1715,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idudtdissi) = fsum(idudtdissi) + dudtdissi + dudtresist !--energy dissipation due to conductivity fsum(idendtdissi) = fsum(idendtdissi) + dendissterm - if (icooling == 9) then - Gpot_cool(i) = Gpot_cool(i) + pmassj*phii - if (doFLD .and. dt > 0.) then - !print *, rhoj, "calling k_fld for j", j, enj - call get_k_fld(rhoj,enj,j,kfldj,Tj) - if ((kfldj + kfldi) == 0.) then - diffterm = 0d0 - elseif (rhoj == 0.) then - diffterm = 0d0 - else - diffterm = 4d0*pmassj/rhoi/rhoj - diffterm = diffterm * kfldi * kfldj / (kfldi+kfldj) - diffterm = diffterm * (Ti - Tj) / rij2 - diffterm = diffterm*cnormk*grkerni*(runix*dx + runiy*dy + runiz*dz) - endif - duFLD(i) = duFLD(i) + diffterm - if (isnan(duFLD(i))) then - print *, "FLD is nan for particle i=, j = ", i,j - print *, "rhoi,rhoj,rij2,diffterm",rhoi,rhoj,rij2,diffterm - print *, "kfldi, kfldj, Ti,Tj", kfldi,kfldj, Ti,Tj - stop - endif - ! call calc_FLD(duFLD(i),i,j,q2j,qj,hi121,hi1,pmassj,eos_vars(itemp,j),eos_vars(itemp,j),rhoj) - endif - endif endif !--add contribution to particle i's force @@ -1812,7 +1754,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g radDi = c_code*radlambdai/radkappai/rhoi - ! TWO FIRST DERIVATES ! + ! TWO FIRST DERIVATIVES ! radDFWi = pmassj*radDi*grkerni*rho21i*& (radFi(1)*runix + radFi(2)*runiy + radFi(3)*runiz) @@ -1823,8 +1765,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g ! (rhoi*radeni-rhoj*radenj)*grkerni*rij1 endif -#ifdef DUST - if (use_dustfrac) then + if (use_dust .and. use_dustfrac) then tsj = 0. do l=1,ndustsmall ! get stopping time - for one fluid dust we do not know deltav, but it is small by definition @@ -1854,20 +1795,18 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g do l=1,ndustsmall if (dustfraci(l) > 0. .or. dustfracj(l) > 0.) then - ! define averages of diffusion coefficient and kernels - !Dav(l) = dustfraci(l)*tsi(l) + dustfracj(l)*tsj(l) + ! define average of kernels grkernav = 0.5*(grkerni + grkernj) -!------------------------------------------------ -!--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) + !--sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) dustfracterms(l) = pmassj*sqrtrhodustfracj(l)*rho1j & *((tsi(l)-epstsi)*(1.-dustfraci(l))/(1.-dustfracisum) & +(tsj(l)-epstsj)*(1.-dustfracj(l))/(1.-dustfracjsum)) & *(pri - prj)*grkernav*rij1 fsum(iddustevoli+(l-1)) = fsum(iddustevoli+(l-1)) - dustfracterms(l) -!------------------------------------------------ -!--sqrt(rho*epsilon) method and sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) + + !--sqrt(rho*epsilon) method and sqrt(epsilon/1-epsilon) method (Ballabio et al. 2018) if (maxvxyzu >= 4) fsum(idudtdusti+(l-1)) = fsum(idudtdusti+(l-1)) - sqrtrhodustfraci(l)*dustfracterms(l)*denij endif ! Equation 270 in Phantom paper @@ -1879,7 +1818,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif enddo endif -#endif else !ifgas ! @@ -1889,11 +1827,11 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifyi) = fsum(ifyi) - fgrav*runiy fsum(ifzi) = fsum(ifzi) - fgrav*runiz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) -#ifdef DUST + ! ! gas-dust: compute drag terms ! - if (idrag>0) then + if (use_dust .and. idrag>0) then if (iamgasi .and. iamdustj .and. icut_backreaction==0) then projvstar = projv if (irecon >= 0) call reconstruct_dv(projv,dx,dy,dz,runix,runiy,runiz,dvdxi,dvdxj,projvstar,irecon) @@ -1964,10 +1902,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (q2i < q2j) then winter = wkern(q2i,qi)*hi21*hi1*cnormk else + winter = wkern(q2j,qj)*hj21*hj1*cnormk endif !--following quantities are weighted by mass rather than mass/density fsum(idensgasi) = fsum(idensgasi) + pmassj*winter - winter = wkern(q2j,qj)*hj21*hj1*cnormk fsum(idvix) = fsum(idvix) + pmassj*dvx*winter fsum(idviy) = fsum(idviy) + pmassj*dvy*winter fsum(idviz) = fsum(idviz) + pmassj*dvz*winter @@ -2000,7 +1938,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifdragzi) = fsum(ifdragzi) - dragterm*runiz endif endif -#endif endif ifgas !--self gravity contribution to total energy equation @@ -2037,7 +1974,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g !-- add contribution of 'distant neighbour' (outside r_kernel) gas particle to potential if (iamtypej == igas .and. icooling == 9) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii - + !--self gravity contribution to total energy equation if (gr .and. gravity .and. ien_type == ien_etotal) then fgravxi = fgravxi - dx*fgravj @@ -2048,15 +1985,13 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif is_sph_neighbour enddo loop_over_neighbours2 - - if (icooling == 9) gradP_cool(i) = sqrt(gradpx*gradpx + gradpy*gradpy + gradpz*gradpz) - + if (icooling == 9) gradP_cool(i) = sqrt(gradpx*gradpx + gradpy*gradpy + gradpz*gradpz) + if (gr .and. gravity .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fgravxi + vyi*fgravyi + vzi*fgravzi endif - return end subroutine compute_forces !---------------------------------------------------------------- @@ -2165,7 +2100,6 @@ subroutine get_stress(pri,spsoundi,rhoi,rho1i,xi,yi,zi, & endif endif - return end subroutine get_stress !---------------------------------------------------------------- @@ -2187,9 +2121,9 @@ subroutine start_cell(cell,iphase,xyzh,vxyzu,gradh,divcurlv,divcurlB,dvdx,Bevol, use growth, only:get_size use part, only:ibin_old use timestep_ind, only:get_dt - use nicil, only:nimhd_get_jcbcb + use nicil, only:nimhd_get_jcbcb use radiation_utils, only:get_rad_R - use eos, only:utherm + use eos_stamatellos, only:Gpot_cool type(cellforce), intent(inout) :: cell integer(kind=1), intent(in) :: iphase(:) real, intent(in) :: xyzh(:,:) @@ -2268,10 +2202,9 @@ subroutine start_cell(cell,iphase,xyzh,vxyzu,gradh,divcurlv,divcurlB,dvdx,Bevol, if (iamgasi) then if (ndivcurlv >= 1) divcurlvi(:) = real(divcurlv(:,i),kind=kind(divcurlvi)) if (maxvxyzu >= 4) then - !eni = utherm(vxyzu(:,i),rhoi,gamma) - eni = vxyzu(4,i) + eni = vxyzu(4,i) else - eni = 0.0 + eni = 0.0 endif ! @@ -2615,9 +2548,6 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv rad,drad,radprop,dtrad) use io, only:fatal,warning -#ifdef FINVSQRT - use fastmath, only:finvsqrt -#endif use dim, only:mhd,mhd_nonideal,lightcurve,use_dust,maxdvdx,use_dustgrowth,gr,use_krome,& store_dust_temperature,do_nucleation,update_muGamma,h2chemistry use eos, only:ieos,iopacity_type @@ -2652,14 +2582,8 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use physcon, only:fourpi use options, only:use_porosity use part, only:Omega_k -#endif use io, only:warning use physcon, only:c,kboltz -#ifdef GR - use part, only:pxyzu -#endif - use eos_stamatellos, only:Gpot_cool - integer, intent(in) :: icall type(cellforce), intent(inout) :: cell real, intent(inout) :: fxyzu(:,:) @@ -2695,7 +2619,8 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv integer, intent(inout) :: ndustres real, intent(inout) :: dustresfacmean,dustresfacmax real, intent(in) :: rad(:,:),radprop(:,:) - real, intent(out) :: drad(:,:),dtrad + real, intent(out) :: drad(:,:) + real, intent(inout) :: dtrad real :: c_code,dtradi,radlambdai,radkappai real :: xpartveci(maxxpartveciforce),fsum(maxfsum) real :: rhoi,rho1i,rhogasi,hi,hi1,pmassi,tempi,gammai @@ -2857,7 +2782,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv !--add self-contribution call kernel_softening(0.,0.,potensoft0,dum) epoti = 0.5*pmassi*(fsum(ipot) + pmassi*potensoft0*hi1) - if (icooling == 9 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + pmassi*potensoft0*hi1 + if (icooling==9 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + pmassi*potensoft0*hi1 ! !--add contribution from distant nodes, expand these in Taylor series about node centre ! use xcen directly, -1 is placeholder @@ -2867,7 +2792,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi - if (icooling == 9 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes + if (icooling==9 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif @@ -3137,8 +3062,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv endif else ! not gas -#ifdef DUSTGROWTH - if (iamdusti) then + if (use_dustgrowth .and. iamdusti) then !- return interpolations to their respective arrays dustgasprop(2,i) = fsum(idensgasi) !- rhogas !- interpolations are mass weigthed, divide result by rhog,i @@ -3159,7 +3083,6 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv endif dustgasprop(3,i) = tstopint * Omega_k(i) !- Stokes number endif -#endif if (maxvxyzu > 4) fxyzu(4,i) = 0. ! timestep based on Courant condition for non-gas particles @@ -3175,11 +3098,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv ! timestep based on force condition if (abs(f2i) > epsilon(f2i)) then -#ifdef FINVSQRT - dtf = C_force*sqrt(hi*finvsqrt(f2i)) -#else dtf = C_force*sqrt(hi/sqrt(f2i)) -#endif endif ! one fluid dust timestep diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index 08820a848..a1705b37c 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module readwrite_infile ! @@ -343,10 +343,6 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) use options, only:use_porosity use porosity, only:read_options_porosity use metric, only:read_options_metric -#endif -#ifdef PHOTO - use photoevap, only:read_options_photoevap -#endif #ifdef INJECT_PARTICLES use inject, only:read_options_inject #endif @@ -711,8 +707,6 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (beta < 0.) call fatal(label,'beta < 0') if (beta > 4.) call warn(label,'very high beta viscosity set') #ifndef MCFOST - if (maxvxyzu >= 4 .and. (ieos /= 2 .and. ieos /= 4 .and. ieos /= 10 .and. ieos /=11 .and. & - ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 20 .and. ieos/=21)) & if (maxvxyzu >= 4 .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /= 4 .and. ieos /= 10 .and. & ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 20 .and. ieos/=21)) & call fatal(label,'only ieos=2 makes sense if storing thermal energy') @@ -721,7 +715,8 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (shearparam < 0.) call fatal(label,'stupid value for shear parameter (< 0)') if (irealvisc==2 .and. shearparam > 1) call error(label,'alpha > 1 for shakura-sunyaev viscosity') if (iverbose > 99 .or. iverbose < -9) call fatal(label,'invalid verboseness setting (two digits only)') - if (icooling > 0 .and. .not.(ieos == 2 .or. ieos == 5 .or. ieos ==21)) call fatal(label,'cooling requires adiabatic eos (ieos=2)') + if (icooling > 0 .and. .not.(ieos == 2 .or. ieos == 5 .or. ieos ==21)) & + call fatal(label,'cooling requires adiabatic eos (ieos=2)') if (icooling > 0 .and. (ipdv_heating <= 0 .or. ishock_heating <= 0)) & call fatal(label,'cooling requires shock and work contributions') if (((isink_radiation == 1 .or. isink_radiation == 3 ) .and. idust_opacity == 0 ) & diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 9f878498e..2de7b5a88 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -612,7 +612,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none)& !$omp private(i) & !$omp shared(npart,hdtsph)& -!$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase) & +!$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase,icooling) & !$omp shared(Bevol,dBevol,Bpred,pxyzu,ppred) & !$omp shared(dustprop,ddustprop,dustproppred,use_dustfrac,dustevol,dustpred,ddustevol) & !$omp shared(filfac,filfacpred,use_porosity) & @@ -1234,7 +1234,7 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, fonrmax = 0. !$omp parallel default(none) & !$omp shared(maxp,maxphase) & - !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype) & + !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype,fxyzu) & !$omp shared(eos_vars,dust_temp,store_dust_temperature) & !$omp shared(dt,hdt,timei,iexternalforce,extf_is_velocity_dependent,cooling_in_step,icooling) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,idamp,damp_fac) & @@ -1381,7 +1381,8 @@ subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time, endif 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,dudti_sph=fxyzu(4,i),part_id=i) + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,& + divcurlv(1,i),dudtcool,dudti_sph=fxyzu(4,i),part_id=i) endif endif #endif diff --git a/src/tests/test_gravity.f90 b/src/tests/test_gravity.f90 new file mode 100644 index 000000000..db00c260a --- /dev/null +++ b/src/tests/test_gravity.f90 @@ -0,0 +1,642 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module testgravity +! +! Unit tests of self-gravity +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: deriv, dim, directsum, energies, eos, io, kdtree, +! linklist, mpibalance, mpiutils, options, part, physcon, ptmass, +! sort_particles, spherical, testutils, timing +! + use io, only:id,master + implicit none + public :: test_gravity + + private + +contains +!----------------------------------------------------------------------- +!+ +! Unit tests for Newtonian gravity (i.e. Poisson solver) +!+ +!----------------------------------------------------------------------- +subroutine test_gravity(ntests,npass,string) + use dim, only:gravity + integer, intent(inout) :: ntests,npass + character(len=*), intent(in) :: string + logical :: testdirectsum,testpolytrope,testtaylorseries,testall + + testdirectsum = .false. + testtaylorseries = .false. + testpolytrope = .false. + testall = .false. + select case(string) + case('taylorseries') + testtaylorseries = .true. + case('directsum') + testdirectsum = .true. + case('polytrope') + testpolytrope = .true. + case default + testall = .true. + end select + + if (gravity) then + if (id==master) write(*,"(/,a,/)") '--> TESTING SELF-GRAVITY' + ! + !--unit test of Taylor series expansions in the treecode + ! + if (testtaylorseries .or. testall) call test_taylorseries(ntests,npass) + ! + !--unit tests of treecode gravity by direct summation + ! + if (testdirectsum .or. testall) call test_directsum(ntests,npass) + + if (id==master) write(*,"(/,a)") '<-- SELF-GRAVITY TESTS COMPLETE' + else + if (id==master) write(*,"(/,a)") '--> SKIPPING SELF-GRAVITY TESTS (need -DGRAVITY)' + endif + +end subroutine test_gravity + +!----------------------------------------------------------------------- +!+ +! Unit tests of the Taylor series expansion about local and distant nodes +!+ +!----------------------------------------------------------------------- +subroutine test_taylorseries(ntests,npass) + use kdtree, only:compute_fnode,expand_fgrav_in_taylor_series + use testutils, only:checkval,update_test_scores + integer, intent(inout) :: ntests,npass + integer :: nfailed(18),i,npnode + real :: xposi(3),xposj(3),x0(3),dx(3),fexact(3),f0(3) + real :: xposjd(3,3),dfdx_approx(3,3),d2f(3,3),dpot(3) + real :: fnode(20),quads(6) + real :: dr,dr2,phi,phiexact,pmassi,tol,totmass + + if (id==master) write(*,"(/,a)") '--> testing taylor series expansion about current node' + totmass = 5. + xposi = (/0.05,-0.04,-0.05/) ! position to evaluate the force at + xposj = (/1., 1., 1./) ! position of distant node + x0 = 0. ! position of nearest node centre + + call get_dx_dr(xposi,xposj,dx,dr) + fexact = -totmass*dr**3*dx ! exact force between i and j + phiexact = -totmass*dr ! exact potential between i and j + + call get_dx_dr(x0,xposj,dx,dr) + fnode = 0. + quads = 0. + call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode) + + dx = xposi - x0 ! perform expansion about x0 + call expand_fgrav_in_taylor_series(fnode,dx(1),dx(2),dx(3),f0(1),f0(2),f0(3),phi) + !print*,' exact force = ',fexact,' phi = ',phiexact + !print*,' force at origin = ',fnode(1:3), ' phi = ',fnode(20) + !print*,'force w. taylor series = ',f0, ' phi = ',phi + nfailed(:) = 0 + call checkval(f0(1),fexact(1),3.e-4,nfailed(1),'fx taylor series about f0') + call checkval(f0(2),fexact(2),1.1e-4,nfailed(2),'fy taylor series about f0') + call checkval(f0(3),fexact(3),9.e-5,nfailed(3),'fz taylor series about f0') + call checkval(phi,phiexact,8.e-4,nfailed(4),'phi taylor series about f0') + call update_test_scores(ntests,nfailed,npass) + + if (id==master) write(*,"(/,a)") '--> testing taylor series expansion about distant node' + totmass = 5. + npnode = 3 + xposjd(:,1) = (/1.03, 0.98, 1.01/) ! position of distant particle 1 + xposjd(:,2) = (/0.95, 1.01, 1.03/) ! position of distant particle 2 + xposjd(:,3) = (/0.99, 0.95, 0.95/) ! position of distant particle 3 + xposj = 0. + pmassi = totmass/real(npnode) + do i=1,npnode + xposj = xposj + pmassi*xposjd(:,i) ! centre of mass of distant node + enddo + xposj = xposj/totmass + !print*,' centre of mass of distant node = ',xposj + !--compute quadrupole moments + quads = 0. + do i=1,npnode + dx(:) = xposjd(:,i) - xposj + dr2 = dot_product(dx,dx) + quads(1) = quads(1) + pmassi*(3.*dx(1)*dx(1) - dr2) + quads(2) = quads(2) + pmassi*(3.*dx(1)*dx(2)) + quads(3) = quads(3) + pmassi*(3.*dx(1)*dx(3)) + quads(4) = quads(4) + pmassi*(3.*dx(2)*dx(2) - dr2) + quads(5) = quads(5) + pmassi*(3.*dx(2)*dx(3)) + quads(6) = quads(6) + pmassi*(3.*dx(3)*dx(3) - dr2) + enddo + + x0 = 0. ! position of nearest node centre + xposi = x0 ! position to evaluate the force at + fexact = 0. + phiexact = 0. + do i=1,npnode + dx = xposi - xposjd(:,i) + dr = 1./sqrt(dot_product(dx,dx)) + fexact = fexact - dr**3*dx ! exact force between i and j + phiexact = phiexact - dr ! exact force between i and j + enddo + fexact = fexact*pmassi + phiexact = phiexact*pmassi + + call get_dx_dr(x0,xposj,dx,dr) + fnode = 0. + call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode) + + dx = xposi - x0 ! perform expansion about x0 + call expand_fgrav_in_taylor_series(fnode,dx(1),dx(2),dx(3),f0(1),f0(2),f0(3),phi) + !print*,' exact force = ',fexact,' phi = ',phiexact + !print*,' force at origin = ',fnode(1:3), ' phi = ',fnode(20) + !print*,'force w. taylor series = ',f0, ' phi = ',phi + nfailed(:) = 0 + call checkval(f0(1),fexact(1),8.7e-5,nfailed(1),'fx taylor series about f0') + call checkval(f0(2),fexact(2),1.5e-6,nfailed(2),'fy taylor series about f0') + call checkval(f0(3),fexact(3),1.6e-5,nfailed(3),'fz taylor series about f0') + call checkval(phi,phiexact,5.9e-6,nfailed(4),'phi taylor series about f0') + call update_test_scores(ntests,nfailed,npass) + + if (id==master) write(*,"(/,a)") '--> checking results of compute_fnode routine' + ! + ! check that components of fnode are derivatives of each other + ! + tol = 1.e-6 + call get_finite_diff(3,x0,xposj,totmass,quads,fnode,dfdx_approx,dpot,d2f,tol) + nfailed(:) = 0 + call checkval(fnode(1),dpot(1),tol,nfailed(1),'fx=-dphi/dx') + call checkval(fnode(2),dpot(2),tol,nfailed(2),'fy=-dphi/dy') + call checkval(fnode(3),dpot(3),tol,nfailed(3),'fz=-dphi/dz') + call checkval(fnode(4),dfdx_approx(1,1),tol,nfailed(4),'dfx/dx') + call checkval(fnode(5),dfdx_approx(1,2),tol,nfailed(5),'dfx/dy') + call checkval(fnode(6),dfdx_approx(1,3),tol,nfailed(6),'dfx/dz') + call checkval(fnode(7),dfdx_approx(2,2),tol,nfailed(7),'dfy/dy') + call checkval(fnode(8),dfdx_approx(2,3),tol,nfailed(8),'dfx/dz') + call checkval(fnode(9),dfdx_approx(3,3),tol,nfailed(9),'dfz/dz') + call checkval(fnode(10),d2f(1,1),1.e-3,nfailed(10),'d^2fx/dx^2') + call checkval(fnode(13),d2f(1,2),1.1e-3,nfailed(11),'d^2fx/dy^2') + call checkval(fnode(15),d2f(1,3),1.e-3,nfailed(12),'d^2fx/dz^2') + call checkval(fnode(11),d2f(2,1),1.e-3,nfailed(13),'d^2fy/dx^2') + call checkval(fnode(16),d2f(2,2),1.e-3,nfailed(14),'d^2fy/dy^2') + call checkval(fnode(18),d2f(2,3),1.e-3,nfailed(15),'d^2fy/dz^2') + call checkval(fnode(12),d2f(3,1),1.e-3,nfailed(16),'d^2fz/dx^2') + call checkval(fnode(17),d2f(3,2),1.2e-3,nfailed(17),'d^2fz/dy^2') + call checkval(fnode(19),d2f(3,3),1.e-3,nfailed(18),'d^2fz/dz^2') + call update_test_scores(ntests,nfailed,npass) + + if (id==master) write(*,"(/,a)") '--> testing taylor series expansion about both current and distant nodes' + x0 = 0. ! position of nearest node centre + xposi = (/0.05,0.05,-0.05/) ! position to evaluate the force at + fexact = 0. + phiexact = 0. + do i=1,npnode + dx = xposi - xposjd(:,i) + dr = 1./sqrt(dot_product(dx,dx)) + fexact = fexact - dr**3*dx ! exact force between i and j + phiexact = phiexact - dr ! exact force between i and j + enddo + fexact = fexact*pmassi + phiexact = phiexact*pmassi + + dx = x0 - xposj + dr = 1./sqrt(dot_product(dx,dx)) ! compute approx force between node and j + fnode = 0. + call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode) + + dx = xposi - x0 ! perform expansion about x0 + call expand_fgrav_in_taylor_series(fnode,dx(1),dx(2),dx(3),f0(1),f0(2),f0(3),phi) + !print*,' exact force = ',fexact,' phi = ',phiexact + !print*,' force at origin = ',fnode(1:3), ' phi = ',fnode(20) + !print*,'force w. taylor series = ',f0, ' phi = ',phi + nfailed(:) = 0 + call checkval(f0(1),fexact(1),4.3e-5,nfailed(1),'fx taylor series about f0') + call checkval(f0(2),fexact(2),1.4e-4,nfailed(2),'fy taylor series about f0') + call checkval(f0(3),fexact(3),3.2e-4,nfailed(3),'fz taylor series about f0') + call checkval(phi,phiexact,9.7e-4,nfailed(4),'phi taylor series about f0') + call update_test_scores(ntests,nfailed,npass) + +end subroutine test_taylorseries + +!----------------------------------------------------------------------- +!+ +! Unit tests of the tree code gravity, checking it agrees with +! gravity computed via direct summation +!+ +!----------------------------------------------------------------------- +subroutine test_directsum(ntests,npass) + use io, only:id,master + use dim, only:maxp,maxptmass,mpi + use part, only:init_part,npart,npartoftype,massoftype,xyzh,hfact,vxyzu,fxyzu, & + gradh,poten,iphase,isetphase,maxphase,labeltype,& + nptmass,xyzmh_ptmass,fxyz_ptmass,dsdt_ptmass,ibelong + use eos, only:polyk,gamma + use options, only:ieos,alpha,alphau,alphaB,tolh + use spherical, only:set_sphere + use deriv, only:get_derivs_global + use physcon, only:pi + use timing, only:getused,printused + use directsum, only:directsum_grav + use energies, only:compute_energies,epot + use kdtree, only:tree_accuracy + use testutils, only:checkval,checkvalbuf_end,update_test_scores + use ptmass, only:get_accel_sink_sink,get_accel_sink_gas,h_soft_sinksink + use mpiutils, only:reduceall_mpi,bcast_mpi + use linklist, only:set_linklist + use sort_particles, only:sort_part_id + use mpibalance, only:balancedomains + + integer, intent(inout) :: ntests,npass + integer :: nfailed(18) + integer :: maxvxyzu,nx,np,i,k,merge_n,merge_ij(maxptmass),nfgrav + real :: psep,totvol,totmass,rhozero,tol,pmassi + real :: time,rmin,rmax,phitot,dtsinksink,fonrmax,phii,epot_gas_sink + real(kind=4) :: t1,t2 + real :: epoti,tree_acc_prev + real, allocatable :: fgrav(:,:),fxyz_ptmass_gas(:,:) + + maxvxyzu = size(vxyzu(:,1)) + tree_acc_prev = tree_accuracy + do k = 1,6 + if (labeltype(k)/='bound') then + if (id==master) write(*,"(/,3a)") '--> testing gravity force in densityforce for ',labeltype(k),' particles' +! +!--general parameters +! + time = 0. + hfact = 1.2 + gamma = 5./3. + rmin = 0. + rmax = 1. + ieos = 2 + tree_accuracy = 0.5 +! +!--setup particles +! + call init_part() + np = 1000 + totvol = 4./3.*pi*rmax**3 + nx = int(np**(1./3.)) + psep = totvol**(1./3.)/real(nx) + psep = 0.18 + npart = 0 + ! only set up particles on master, otherwise we will end up with n duplicates + if (id==master) then + call set_sphere('cubic',id,master,rmin,rmax,psep,hfact,npart,xyzh) + endif + np = npart +! +!--set particle properties +! + totmass = 1. + rhozero = totmass/totvol + npartoftype(:) = 0 + npartoftype(k) = int(reduceall_mpi('+',npart),kind=kind(npartoftype)) + massoftype(:) = 0.0 + massoftype(k) = totmass/npartoftype(k) + if (maxphase==maxp) then + do i=1,npart + iphase(i) = isetphase(k,iactive=.true.) + enddo + endif +! +!--set thermal terms and velocity to zero, so only force is gravity +! + polyk = 0. + vxyzu(:,:) = 0. +! +!--make sure AV is off +! + alpha = 0. + alphau = 0. + alphaB = 0. + tolh = 1.e-5 + + fxyzu = 0.0 +! +!--call derivs to get everything initialised +! + call get_derivs_global() +! +!--reset force to zero +! + fxyzu = 0.0 +! +!--move particles to master and sort for direct summation +! + if (mpi) then + ibelong(:) = 0 + call balancedomains(npart) + endif + call sort_part_id +! +!--allocate array for storing direct sum gravitational force +! + allocate(fgrav(maxvxyzu,npart)) + fgrav = 0.0 +! +!--compute gravitational forces by direct summation +! + if (id == master) then + call directsum_grav(xyzh,gradh,fgrav,phitot,npart) + endif +! +!--send phitot to all tasks +! + call bcast_mpi(phitot) +! +!--calculate derivatives +! + call getused(t1) + call get_derivs_global() + call getused(t2) + if (id==master) call printused(t1) +! +!--move particles to master and sort for test comparison +! + if (mpi) then + ibelong(:) = 0 + call balancedomains(npart) + endif + call sort_part_id +! +!--compare the results +! + call checkval(npart,fxyzu(1,:),fgrav(1,:),5.e-3,nfailed(1),'fgrav(x)') + call checkval(npart,fxyzu(2,:),fgrav(2,:),6.e-3,nfailed(2),'fgrav(y)') + call checkval(npart,fxyzu(3,:),fgrav(3,:),9.4e-3,nfailed(3),'fgrav(z)') + deallocate(fgrav) + epoti = 0. + do i=1,npart + epoti = epoti + poten(i) + enddo + epoti = reduceall_mpi('+',epoti) + call checkval(epoti,phitot,5.2e-4,nfailed(4),'potential') + call checkval(epoti,-3./5.*totmass**2/rmax,3.6e-2,nfailed(5),'potential=-3/5 GMM/R') + ! check that potential energy computed via compute_energies is also correct + call compute_energies(0.) + call checkval(epot,phitot,5.2e-4,nfailed(6),'epot in compute_energies') + call update_test_scores(ntests,nfailed(1:6),npass) + endif + enddo + + +!--test that the same results can be obtained from a cloud of sink particles +! with softening lengths equal to the original SPH particle smoothing lengths +! + if (maxptmass >= npart) then + if (id==master) write(*,"(/,3a)") '--> testing gravity in uniform cloud of softened sink particles' +! +!--move particles to master for sink creation +! + if (mpi) then + ibelong(:) = 0 + call balancedomains(npart) + endif +! +!--sort particles so that they can be compared at the end +! + call sort_part_id + + pmassi = totmass/reduceall_mpi('+',npart) + call copy_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,pmassi) + h_soft_sinksink = hfact*psep +! +!--compute direct sum for comparison, but with fixed h and hence gradh terms switched off +! + do i=1,npart + xyzh(4,i) = h_soft_sinksink + gradh(1,i) = 1. + gradh(2,i) = 0. + vxyzu(:,i) = 0. + enddo + allocate(fgrav(maxvxyzu,npart)) + fgrav = 0.0 + call directsum_grav(xyzh,gradh,fgrav,phitot,npart) + call bcast_mpi(phitot) +! +!--compute gravity on the sink particles +! + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epoti,& + dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) + call bcast_mpi(epoti) +! +!--compare the results +! + tol = 1.e-14 + call checkval(npart,fxyz_ptmass(1,:),fgrav(1,:),tol,nfailed(1),'fgrav(x)') + call checkval(npart,fxyz_ptmass(2,:),fgrav(2,:),tol,nfailed(2),'fgrav(y)') + call checkval(npart,fxyz_ptmass(3,:),fgrav(3,:),tol,nfailed(3),'fgrav(z)') + call checkval(epoti,phitot,8e-3,nfailed(4),'potential') + call checkval(epoti,-3./5.*totmass**2/rmax,4.1e-2,nfailed(5),'potential=-3/5 GMM/R') + call update_test_scores(ntests,nfailed(1:5),npass) + + +! +!--now perform the same test, but with HALF the cloud made of sink particles +! and HALF the cloud made of gas particles. Do not re-evaluate smoothing lengths +! so that the results should be identical to the previous test +! + if (id==master) write(*,"(/,3a)") & + '--> testing softened gravity in uniform sphere with half sinks and half gas' + +!--sort the particles by ID so that the first half will have the same order +! even after half the particles have been converted into sinks. This sort is +! not really necessary because the order shouldn't have changed since the +! last test because derivs hasn't been called since. + call sort_part_id + call copy_half_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,pmassi) + + print*,' Using ',npart,' SPH particles and ',nptmass,' point masses' + call get_derivs_global() + + epoti = 0.0 + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epoti,& + dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) +! +!--prevent double counting of sink contribution to potential due to MPI +! + if (id /= master) epoti = 0.0 +! +!--allocate an array for the gas contribution to sink acceleration +! + allocate(fxyz_ptmass_gas(size(fxyz_ptmass,dim=1),nptmass)) + fxyz_ptmass_gas = 0.0 + + epot_gas_sink = 0.0 + do i=1,npart + call get_accel_sink_gas(nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& + xyzmh_ptmass,fxyzu(1,i),fxyzu(2,i),fxyzu(3,i),& + phii,pmassi,fxyz_ptmass_gas,dsdt_ptmass,fonrmax,dtsinksink) + epot_gas_sink = epot_gas_sink + pmassi*phii + epoti = epoti + poten(i) + enddo +! +!--the gas contribution to sink acceleration has to be added afterwards to +! prevent double counting the sink contribution when calling reduceall_mpi +! + fxyz_ptmass_gas = reduceall_mpi('+',fxyz_ptmass_gas) + fxyz_ptmass(:,1:nptmass) = fxyz_ptmass(:,1:nptmass) + fxyz_ptmass_gas(:,1:nptmass) + deallocate(fxyz_ptmass_gas) +! +!--sum up potentials across MPI tasks +! + epoti = reduceall_mpi('+',epoti) + epot_gas_sink = reduceall_mpi('+',epot_gas_sink) + +! +!--move particles to master for comparison +! + if (mpi) then + ibelong(:) = 0 + call balancedomains(npart) + endif + call sort_part_id + + call checkval(npart,fxyzu(1,:),fgrav(1,:),5.e-2,nfailed(1),'fgrav(x)') + call checkval(npart,fxyzu(2,:),fgrav(2,:),6.e-2,nfailed(2),'fgrav(y)') + call checkval(npart,fxyzu(3,:),fgrav(3,:),9.4e-2,nfailed(3),'fgrav(z)') + +! +!--fgrav doesn't exist on worker tasks, so it needs to be sent from master +! + call bcast_mpi(npart) + if (id == master) nfgrav = size(fgrav,dim=2) + call bcast_mpi(nfgrav) + if (id /= master) then + deallocate(fgrav) + allocate(fgrav(maxvxyzu,nfgrav)) + endif + call bcast_mpi(fgrav) + + call checkval(nptmass,fxyz_ptmass(1,:),fgrav(1,npart+1:2*npart),2.3e-2,nfailed(4),'fgrav(xsink)') + call checkval(nptmass,fxyz_ptmass(2,:),fgrav(2,npart+1:2*npart),2.9e-2,nfailed(5),'fgrav(ysink)') + call checkval(nptmass,fxyz_ptmass(3,:),fgrav(3,npart+1:2*npart),3.7e-2,nfailed(6),'fgrav(zsink)') + + call checkval(epoti+epot_gas_sink,phitot,8e-3,nfailed(7),'potential') + call checkval(epoti+epot_gas_sink,-3./5.*totmass**2/rmax,4.1e-2,nfailed(8),'potential=-3/5 GMM/R') + call update_test_scores(ntests,nfailed(1:8),npass) + deallocate(fgrav) + endif +! +!--clean up doggie-doos +! + npartoftype(:) = 0 + massoftype(:) = 0. + tree_accuracy = tree_acc_prev + fxyzu = 0. + vxyzu = 0. + +end subroutine test_directsum + +subroutine copy_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,massi) + integer, intent(in) :: npart + integer, intent(out) :: nptmass + real, intent(in) :: xyzh(:,:),massi + real, intent(out) :: xyzmh_ptmass(:,:) + integer :: i + + nptmass = npart + do i=1,npart + ! make a sink particle with the position of each SPH particle + xyzmh_ptmass(1:3,i) = xyzh(1:3,i) + xyzmh_ptmass(4,i) = massi ! same mass as SPH particles + xyzmh_ptmass(5:,i) = 0. + enddo + +end subroutine copy_gas_particles_to_sinks + +subroutine copy_half_gas_particles_to_sinks(npart,nptmass,xyzh,xyzmh_ptmass,massi) + use io, only: id,master,fatal + use mpiutils, only: bcast_mpi + integer, intent(inout) :: npart + integer, intent(out) :: nptmass + real, intent(in) :: xyzh(:,:),massi + real, intent(out) :: xyzmh_ptmass(:,:) + integer :: i, nparthalf + + nptmass = 0 + nparthalf = npart/2 + + call bcast_mpi(nparthalf) + + if (id==master) then + ! Assuming all gas particles are already on master, + ! create sinks here and send them to other tasks + + ! remove half the particles by changing npart + npart = nparthalf + + do i=npart+1,2*npart + nptmass = nptmass + 1 + call bcast_mpi(nptmass) + ! make a sink particle with the position of each SPH particle + xyzmh_ptmass(1:3,nptmass) = xyzh(1:3,i) + xyzmh_ptmass(4,nptmass) = massi ! same mass as SPH particles + xyzmh_ptmass(5:,nptmass) = 0. + call bcast_mpi(xyzmh_ptmass(1:5,nptmass)) + enddo + else + ! Assuming there are no gas particles here, + ! get sinks from master + + if (npart /= 0) call fatal("copy_half_gas_particles_to_sinks","there are particles on a non-master task") + + ! Get nparthalf from master, but don't change npart from zero + do i=nparthalf+1,2*nparthalf + call bcast_mpi(nptmass) + call bcast_mpi(xyzmh_ptmass(1:5,nptmass)) + enddo + endif + +end subroutine copy_half_gas_particles_to_sinks + +subroutine get_dx_dr(x1,x2,dx,dr) + real, intent(in) :: x1(3),x2(3) + real, intent(out) :: dx(3),dr + + dx = x1 - x2 + dr = 1./sqrt(dot_product(dx,dx)) + +end subroutine get_dx_dr + +subroutine get_finite_diff(ndim,x0,xposj,totmass,quads,fnode,dfdx,dpot,d2f,eps) + use kdtree, only:compute_fnode + integer, intent(in) :: ndim + real, intent(in) :: x0(ndim),xposj(ndim),totmass,quads(6),fnode(20),eps + real, intent(out) :: dfdx(ndim,ndim),dpot(ndim),d2f(ndim,ndim) + integer :: i,j + real :: dx(ndim),x0_plus(ndim),x0_minus(ndim) + real :: dr,fnode_plus(20),fnode_minus(20) + + do j=1,ndim + x0_plus = x0 + x0_plus(j) = x0(j) + eps + x0_minus = x0 + x0_minus(j) = x0(j) - eps + do i=1,ndim + call get_dx_dr(x0_plus,xposj,dx,dr) + fnode_plus = 0. + call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode_plus) + + call get_dx_dr(x0_minus,xposj,dx,dr) + fnode_minus = 0. + call compute_fnode(dx(1),dx(2),dx(3),dr,totmass,quads,fnode_minus) + + dfdx(i,j) = (fnode_plus(i) - fnode_minus(i))/(2.*eps) + d2f(i,j) = (fnode_plus(i) - 2.*fnode(i) + fnode_minus(i))/(eps*eps) + enddo + dpot(j) = -(fnode_plus(20) - fnode_minus(20))/(2.*eps) + enddo + +end subroutine get_finite_diff + +end module testgravity diff --git a/src/tests/test_growth.f90 b/src/tests/test_growth.f90 new file mode 100644 index 000000000..01190a85b --- /dev/null +++ b/src/tests/test_growth.f90 @@ -0,0 +1,394 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module testgrowth +! +! Unit tests of the growth module +! +! :References: +! +! :Owner: Arnaud Vericel +! +! :Runtime parameters: None +! +! :Dependencies: boundary, checksetup, deriv, dim, dust, energies, eos, +! growth, io, kernel, mpidomain, mpiutils, options, part, physcon, +! step_lf_global, testdust, testutils, timestep, unifdis, units, +! viscosity +! + use testutils, only:checkval,update_test_scores + use io, only:id,master + use testdust, only:test_dustybox + implicit none + public :: test_growth + + private + +contains +!----------------------------------------------------------------------- +!+ +! Unit tests for dust growth using Stepinksi & Valageas method +!+ +!----------------------------------------------------------------------- +subroutine test_growth(ntests,npass) + use dim, only:use_dust,use_dustgrowth + use growth, only:init_growth,ifrag,isnow + use physcon, only:solarm,au + use units, only:set_units + use mpiutils, only:barrier_mpi + integer, intent(inout) :: ntests,npass + integer :: nfailed(5),ierr !don't forget the dimension of nfailed + logical, dimension(2) :: logic = (/.false., .true./) + integer :: i,j + + if (use_dust .and. use_dustgrowth) then + if (id==master) write(*,"(/,a)") '--> TESTING DUSTGROWTH MODULE' + else + if (id==master) write(*,"(/,a)") '--> SKIPPING DUSTGROWTH TEST (REQUIRES -DDUST -DDUSTGROWTH)' + return + endif + + call set_units(mass=solarm,dist=au,G=1.d0) + + if (id==master) write(*,"(/,a)") '--> testing growth initialisation' + + nfailed = 0 + do ifrag=0,2 + do isnow=0,2 + call init_growth(ierr) + call checkval(ierr,0,0,nfailed(ifrag+isnow+1),'growth initialisation') + enddo + enddo + call update_test_scores(ntests,nfailed,npass) + + ! + ! The return of the dustybox test + ! + call test_dustybox(ntests,npass) + call barrier_mpi() + + ! + ! testing farmingbox with several config. + ! + do i=1,2 + do j=1,2 + call test_farmingbox(ntests,npass,frag=logic(i),onefluid=logic(j)) + call barrier_mpi() + enddo + enddo + + if (id==master) write(*,"(/,a)") '<-- DUSTGROWTH TEST COMPLETE' + +end subroutine test_growth + +!------------------- +!------------------- +!------------------- + +subroutine test_farmingbox(ntests,npass,frag,onefluid) + use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound + use kernel, only:hfact_default + use part, only:init_part,igas,idust,npart,xyzh,vxyzu,npartoftype,& + massoftype,set_particle_type,& + fxyzu,fext,Bevol,dBevol,dustprop,ddustprop,& + dustfrac,dustevol,ddustevol,iphase,maxtypes,& + VrelVf,dustgasprop,Omega_k,alphaind,iamtype,& + ndustlarge,ndustsmall,rhoh,deltav,this_is_a_test,periodic, & + npartoftypetot,update_npartoftypetot + use step_lf_global, only:step,init_step + use deriv, only:get_derivs_global + use energies, only:compute_energies + use testutils, only:checkvalbuf,checkvalbuf_end + use eos, only:ieos,polyk,gamma,get_spsound + use dust, only:idrag,init_drag + use growth, only:ifrag,init_growth,isnow,vfrag,gsizemincgs,get_size + use options, only:alpha,alphamax,use_dustfrac + use unifdis, only:set_unifdis + use dim, only:periodic,mhd,use_dust,maxp,maxalpha + use timestep, only:dtmax + use io, only:iverbose + use mpiutils, only:reduceall_mpi + use physcon, only:au,solarm,Ro,pi,fourpi + use viscosity, only:shearparam + use units, only:set_units,udist,unit_density!,unit_velocity + use mpidomain, only:i_belong + use checksetup, only:check_setup + + integer, intent(inout) :: ntests,npass + logical, intent(in) :: frag,onefluid + + integer :: nx,nerror,nwarn + integer :: itype,npart_previous,i,j,nsteps,modu,noutputs + integer :: ncheck(4),nerr(4) + real :: errmax(4) + integer :: ierr,iam + integer, parameter :: ngrid = 20000 + + logical :: do_output = .false. + real :: deltax,dz,hfact,totmass,rhozero + real :: Stcomp(ngrid),Stini(ngrid) + real :: cscomp(ngrid),tau(ngrid) + real :: s(ngrid),time,timelim(ngrid) + real :: sinit,dens,t,tmax,dt,dtext,dtnew,guillaume,dtgratio,rhog,rhod + + real, parameter :: tolst = 5.e-4 + real, parameter :: tolcs = 5.e-4 + real, parameter :: tols = 5.e-4 + real, parameter :: tolrho = 5.e-4 + + character(len=15) :: stringfrag + character(len=15) :: stringmethod + + ! initialise particle arrays to zero + call init_part() + + if (frag) then + sinit = 1./udist + gsizemincgs = 1.e-3 + dtgratio = 0.5 + stringfrag = "fragmentation" + else + sinit = 3.e-2/udist + dtgratio = 1. + stringfrag = "growth" + endif + + if (onefluid) then + use_dustfrac = .true. + stringmethod = "one fluid" + ndustsmall = 1 + ndustlarge = 0 + dtgratio = 1.e-1 + else + use_dustfrac = .false. + stringmethod = "two fluid" + ndustsmall = 0 + ndustlarge = 1 + endif + dens = 1./unit_density + + write(*,"(/,a)") '--> testing FARMINGBOX using: '//trim(stringfrag)//& + ' and '//trim(stringmethod)//' dust method' + ! + ! initialise + ! + this_is_a_test = .true. + + ! + ! setup for dustybox problem + ! + nx = 16 + deltax = 1./nx + dz = 2.*sqrt(6.)/nx + call set_boundary(-0.5,0.5,-0.25,0.25,-dz,dz) + hfact = hfact_default + rhozero = 1.e-11/unit_density + totmass = rhozero*dxbound*dybound*dzbound + if (onefluid) then + rhog = rhozero * (1-dtgratio) + rhod = dtgratio * rhozero + else + rhog = rhozero + rhod = dtgratio * rhozero + endif + npart = 0 + fxyzu = 0. + dustprop = 0. + ddustprop = 0. + ddustevol = 0. + dBevol = 0. + if (maxalpha==maxp) alphaind(:,:) = 0. + + !- setting gas particles + itype = igas + npart_previous = npart + call set_unifdis('closepacked',id,master,xmin,xmax,ymin,ymax,zmin,zmax,& + deltax,hfact,npart,xyzh,periodic,verbose=.false.,mask=i_belong) + do i=npart_previous+1,npart + vxyzu(:,i) = 0. + fext(:,i) = 0. + if (mhd) Bevol(:,i) = 0. + if (use_dust) then + dustevol(:,i) = 0. + dustfrac(:,i) = 0. + deltav(:,:,i) = 0. + dustgasprop(:,i) = 0. + VrelVf(i) = 0. + if (use_dustfrac) then + dustfrac(1,i) = dtgratio + dustprop(1,i) = fourpi/3.*dens*sinit**3 + dustprop(2,i) = dens + else + dustprop(:,i) = 0. + dustfrac(:,i) = 0. + endif + endif + call set_particle_type(i,itype) + enddo + npartoftype(itype) = npart - npart_previous + call update_npartoftypetot + massoftype(itype) = totmass/npartoftypetot(itype) + + !- setting dust particles if not one fluid + if (.not. use_dustfrac) then + itype = idust + npart_previous = npart + call set_unifdis('closepacked',id,master,xmin,xmax,ymin,ymax,zmin,zmax,& + deltax,hfact,npart,xyzh,periodic,verbose=.false.,mask=i_belong) + do i=npart_previous+1,npart + vxyzu(:,i) = 0. + fext(:,i) = 0. + if (mhd) Bevol(:,i) = 0. + if (use_dust) then + dustevol(:,i) = 0. + dustfrac(:,i) = 0. + dustprop(1,i) = fourpi/3.*dens*sinit**3 + dustprop(2,i) = dens + dustgasprop(:,i) = 0. + VrelVf(i) = 0. + endif + call set_particle_type(i,itype) + enddo + npartoftype(itype) = npart - npart_previous + npartoftypetot(itype) = reduceall_mpi('+',npartoftype(itype)) + massoftype(itype) = dtgratio*totmass/npartoftypetot(itype) + endif + + ! + ! check that particle setup is sensible + ! + call check_setup(nerror,nwarn) + + ! + ! runtime parameters + ! + + ieos = 1 + idrag = 1 + if (frag) then + ifrag = 1 + shearparam = 2.5e-2 + else + ifrag = 0 + shearparam = 1.e-2 + endif + isnow = 0 + vfrag = 1.e-11 + gsizemincgs = 1.e-2 + polyk = 1.e-3 + gamma = 1. + alpha = 0. + alphamax = 0. + iverbose = 0 + + !- timestepping + dt = 1.e-3 + tmax = 0.2 + nsteps = int(tmax/dt) + noutputs = 150 + if (noutputs > nsteps) noutputs = nsteps + modu = int(nsteps/noutputs) + dtmax = nsteps*dt + + timelim(:) = 1.e3 + ncheck(:) = 0 + nerr(:) = 0 + errmax(:) = 0. + + t = 0. + + call init_drag(ierr) + call init_growth(ierr) + + call get_derivs_global() + + call init_step(npart,t,dtmax) + + do j=1,npart + iam = iamtype(iphase(j)) + if (iam == idust .or. (use_dustfrac .and. iam == igas)) then + cscomp(j) = get_spsound(ieos,xyzh(:,j),rhog,vxyzu(:,j)) + Stini(j) = sqrt(pi*gamma/8)*dens*sinit/((rhog+rhod)*cscomp(j)) * Omega_k(j) + Stcomp(j) = Stini(j) + tau(j) = 1/(sqrt(2**1.5*Ro*shearparam)*Omega_k(j))*(rhog+rhod)/rhod/sqrt(pi*gamma/8.) + s(j) = sinit + timelim(j) = 2*sqrt(Stini(j))*(1.+Stini(j)/3.)*tau(j) + endif + enddo + if (frag) write(*,"(a,f5.1,a)") "Analytical solution no longer valid after t = ", minval(timelim), " (size < 0)" + + ! + ! run farmingbox problem + ! + do i=1,nsteps + dtext = dt + call step(npart,npart,t,dt,dtext,dtnew) + t = t + dt + if (do_output .and. mod(i,modu)==0) then + call write_file_err(i,t,xyzh,dustprop(1,:)*udist,s*udist,& + dustgasprop(3,:),Stcomp,npart,"farmingbox_") + endif + do j=1,npart + iam = iamtype(iphase(j)) + if (iam == idust .or. (iam == igas .and. use_dustfrac)) then + if (frag) then + time = - t/tau(j) + 2.*sqrt(Stini(j))*(1.+Stini(j)/3.) + else + time = 2.*sqrt(Stini(j))*(1.+Stini(j)/3.) + t/tau(j) + endif + guillaume = (8.+9.*time*time+3.*time*sqrt(16.+9.*time*time))**(1./3.) + Stcomp(j) = guillaume/2. + 2./guillaume - 2 + s(j) = Stcomp(j)/(sqrt(pi*gamma/8)*dens/((rhog+rhod)*cscomp(j))*Omega_k(j)) + if (onefluid) then + call checkvalbuf(dustgasprop(3,j)/Stcomp(j),1.,tolst,'St',nerr(1),ncheck(1),errmax(1)) + call checkvalbuf(get_size(dustprop(1,j),dustprop(2,j))/s(j),1.,tols,'size',nerr(2),ncheck(2),errmax(2)) + else + call checkvalbuf(dustgasprop(3,j)/Stcomp(j),1.,tolst,'St',nerr(1),ncheck(1),errmax(1)) + call checkvalbuf(get_size(dustprop(1,j),dustprop(2,j))/s(j),1.,tols,'size',nerr(2),ncheck(2),errmax(2)) + call checkvalbuf(dustgasprop(1,j)/cscomp(j),1.,tolcs,'csound',nerr(3),ncheck(3),errmax(3)) + call checkvalbuf(dustgasprop(2,j)/rhozero,1.,tolrho,'rhogas',nerr(4),ncheck(4),errmax(4)) + endif + endif + enddo + enddo + if (onefluid) then + call checkvalbuf_end('Stokes number evaluation matches exact solution',ncheck(1),nerr(1),errmax(1),tolst) + call checkvalbuf_end('size evaluation matches exact solution',ncheck(2),nerr(2),errmax(2),tols) + else + call checkvalbuf_end('Stokes number interpolation matches exact solution',ncheck(1),nerr(1),errmax(1),tolst) + call checkvalbuf_end('size evaluation matches exact solution',ncheck(2),nerr(2),errmax(2),tols) + call checkvalbuf_end('sound speed interpolation matches exact number',ncheck(3),nerr(3),errmax(3),tolcs) + call checkvalbuf_end('rhogas interpolation matches exact number',ncheck(4),nerr(4),errmax(4),tolrho) + endif + + call update_test_scores(ntests,nerr,npass) + +end subroutine test_farmingbox + +subroutine write_file_err(step,t,xyzh,gsize,gsize_exact,St,St_exact,npart,prefix) + use part, only:iamdust,iphase,iamgas + real, intent(in) :: t + real, intent(in) :: xyzh(:,:) + real, intent(in) :: St(:),St_exact(:) + real(kind=8), intent(in) :: gsize(:),gsize_exact(:) + character(len=*), intent(in) :: prefix + integer, intent(in) :: npart,step + character(len=30) :: filename,str + integer :: i,lu + + write(str,"(i000.4)") step + filename = prefix//'dust_'//trim(adjustl(str))//'.txt' + open(newunit=lu,file=filename,status='replace') + write(lu,*) t + do i=1,npart + if (iamdust(iphase(i))) write(lu,*) xyzh(1,i),xyzh(2,i),xyzh(3,i),gsize(i),gsize_exact(i),& + St(i),St_exact(i) + enddo + close(lu) + +end subroutine write_file_err + +end module testgrowth From c67364c12b2bc9cafa92adb8bb8ea29e09536b30 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 15 Apr 2024 14:55:12 +0100 Subject: [PATCH 106/182] Edits to analysis_disc_stresses.f90 for variable gamma (eos = 21) and more accurate H --- src/main/cooling_stamatellos.f90 | 6 +- src/main/readwrite_dumps_fortran.F90 | 4 +- src/utils/analysis_disc_stresses.f90 | 92 +++++++++++++++++++++------- 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index beedaf568..5d5223344 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -205,7 +205,8 @@ subroutine write_options_cooling_stamatellos(iunit) !N.B. Tfloor handled in cooling.F90 call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) - call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) Stamatellos (2) Lombardi (3) combined (4) modified Lombardi',iunit) + call write_inopt(od_method,'OD method','Method for estimating optical depth: (1)'& + 'Stamatellos (2) Lombardi (3) combined (4) modified Lombardi',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) call write_inopt(FLD_opt,'do FLD','Do FLD? (1) yes (0) no',iunit) @@ -229,7 +230,8 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie case('OD method') read(valstring,*,iostat=ierr) od_method if (od_method < 1 .or. od_method > 4) then - call fatal('cooling options','od_method must be 1, 2, 3 or 4',var='od_method',ival=od_method) + call fatal('cooling options','od_method must be 1, 2, 3 or 4', & + var='od_method',ival=od_method) endif ngot = ngot + 1 case('EOS_file') diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.F90 index 5628665b1..28b276c0b 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.F90 @@ -1286,9 +1286,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto if (eos_outputs_gasP(ieos) .or. eos_is_non_ideal(ieos)) then call read_array(eos_vars(igasP,:),eos_vars_label(igasP),got_gasP,ik,i1,i2,noffset,idisk1,tag,match,ierr) endif - if (eos_is_non_ideal(ieos)) then +! if (eos_is_non_ideal(ieos)) then call read_array(eos_vars(itemp,:),eos_vars_label(itemp),got_temp,ik,i1,i2,noffset,idisk1,tag,match,ierr) - endif + ! endif call read_array(eos_vars(iX,:),eos_vars_label(iX),got_x,ik,i1,i2,noffset,idisk1,tag,match,ierr) call read_array(eos_vars(iZ,:),eos_vars_label(iZ),got_z,ik,i1,i2,noffset,idisk1,tag,match,ierr) call read_array(eos_vars(imu,:),eos_vars_label(imu),got_mu,ik,i1,i2,noffset,idisk1,tag,match,ierr) diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index ffb966aab..f2d546564 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -6,7 +6,8 @@ !--------------------------------------------------------------------------! module analysis ! -! Analysis routine for discs by DF, adapted from a routine by CJN +! Analysis routine for discs by DF, adapted from a routine by CJN. +! Edited for use with variable gammai and mui and more accurate alpha_ss calc by AKY ! ! :References: None ! @@ -28,7 +29,7 @@ module analysis real :: rin, rout,dr integer, allocatable,dimension(:) :: ipartbin real, allocatable,dimension(:) :: rad,ninbin,sigma,csbin,vrbin,vphibin, omega - real, allocatable,dimension(:) :: H, toomre_q,epicyc + real, allocatable,dimension(:) :: H, toomre_q,epicyc,part_scaleheight real, allocatable,dimension(:) :: alpha_reyn,alpha_grav,alpha_mag,alpha_art real, allocatable,dimension(:) :: rpart,phipart,vrpart,vphipart, gr,gphi,Br,Bphi real, allocatable,dimension(:,:) :: gravxyz @@ -42,7 +43,7 @@ module analysis subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) use io, only:fatal - use part, only:gravity,mhd + use part, only:gravity,mhd,eos_vars character(len=*), intent(in) :: dumpfile real, intent(in) :: xyzh(:,:),vxyzu(:,:) @@ -82,7 +83,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) call transform_to_cylindrical(npart,xyzh,vxyzu) ! Bin particles by radius - call radial_binning(npart,xyzh,vxyzu,pmass) + call radial_binning(npart,xyzh,vxyzu,pmass,eos_vars) ! Calculate stresses call calc_stresses(npart,xyzh,vxyzu,pmass) @@ -350,18 +351,21 @@ end subroutine transform_to_cylindrical !+ !--------------------------------------------------------------- -subroutine radial_binning(npart,xyzh,vxyzu,pmass) - use physcon, only:pi - use eos, only: gamma +subroutine radial_binning(npart,xyzh,vxyzu,pmass,eos_vars) + use physcon, only:pi,kb_on_mh + use eos, only:gamma,ieos + use part, only:itemp,imu + use units, only:udist implicit none integer,intent(in) :: npart real,intent(in) :: pmass - real,intent(in) :: xyzh(:,:),vxyzu(:,:) + real,intent(in) :: xyzh(:,:),vxyzu(:,:),eos_vars(:,:) - integer :: ibin,ipart,nbinned + integer :: ibin,ipart,nbinned,iallocerr real :: area + real,allocatable :: zsetgas(:,:) print '(a,I4)', 'Carrying out radial binning, number of bins: ',nbins @@ -373,6 +377,7 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) allocate(omega(nbins)) allocate(vrbin(nbins)) allocate(vphibin(nbins)) + allocate(part_scaleheight(nbins)) ipartbin(:) = 0 ninbin(:) = 0.0 @@ -381,6 +386,15 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) omega(:) = 0.0 vrbin(:) = 0.0 vphibin(:) = 0.0 + part_scaleheight(:) = 0.0 + + allocate(zsetgas(npart,nbins),stat=iallocerr) + ! If you don't have enough memory to allocate zsetgas, then calculate H the slow way with less memory. + if (iallocerr/=0) then + write(*,'(/,a)') ' WARNING: Could not allocate memory for array zsetgas!' + write(*,'(a)') ' (It possibly requires too much memory)' + write(*,'(a,/)') ' Try calculate scaleheight the slow way.' + endif ! Set up radial bins @@ -409,8 +423,14 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) ninbin(ibin) = ninbin(ibin) +1 ipartbin(ipart) = ibin - - csbin(ibin) = csbin(ibin) + sqrt(gamma*(gamma-1)*vxyzu(4,ipart)) + if (ieos==21) then + csbin(ibin) = csbin(ibin) + sqrt(kb_on_mh * eos_vars(itemp,ipart) / eos_vars(imu,ipart)) + if (csbin(ibin) == 0) then + print *, eos_vars(itemp,ipart) + endif + else + csbin(ibin) = csbin(ibin) + sqrt(gamma*(gamma-1)*vxyzu(4,ipart)) + endif area = pi*((rad(ibin)+0.5*dr)**2-(rad(ibin)- 0.5*dr)**2) sigma(ibin) = sigma(ibin) + pmass/area @@ -418,11 +438,13 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) vrbin(ibin) = vrbin(ibin) + vrpart(ipart) vphibin(ibin) = vphibin(ibin) + vphipart(ipart) omega(ibin) = omega(ibin) + vphipart(ipart)/rad(ibin) - + zsetgas(int(ninbin(ibin)),ibin) = xyzh(3,ipart) endif enddo + call calculate_H(nbins,part_scaleheight,zsetgas,int(ninbin)) + part_scaleheight(:) = part_scaleheight(:) print*, nbinned, ' particles have been binned' where(ninbin(:)/=0) @@ -443,11 +465,11 @@ end subroutine radial_binning !+ !-------------------------------------------------------------- subroutine calc_stresses(npart,xyzh,vxyzu,pmass) - use physcon, only: pi,gg + use physcon, only: pi,gg,kb_on_mh use units, only: print_units, umass,udist,utime,unit_velocity,unit_density,unit_Bfield use dim, only: gravity - use part, only: mhd,rhoh,alphaind - use eos, only: gamma + use part, only: mhd,rhoh,alphaind,eos_vars,imu,itemp + use eos, only: gamma,ieos implicit none @@ -481,7 +503,9 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) call print_units sigma(:) = sigma(:)*umass/(udist*udist) - csbin(:) = csbin(:)*unit_velocity + if (ieos /= 21) then + csbin(:) = csbin(:)*unit_velocity + endif omega(:) = omega(:)/utime Keplog = 1.5 @@ -500,9 +524,8 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) do ipart=1,npart ibin = ipartbin(ipart) - if (ibin<=0) cycle - - cs2 = gamma*(gamma-1)*vxyzu(4,ipart)*unit_velocity*unit_velocity + if (ibin<=0) cycle + dvr = (vrpart(ipart) - vrbin(ibin))*unit_velocity dvphi = (vphipart(ipart) -vphibin(ibin))*unit_velocity @@ -510,6 +533,7 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) alpha_reyn(ibin) = alpha_reyn(ibin) + dvr*dvphi +! Handle constant alpha_sph alpha_art(ibin) = alpha_art(ibin) + alphaind(1,ipart)*xyzh(4,ipart)*udist if (gravity) alpha_grav(ibin) = alpha_grav(ibin) + gr(ipart)*gphi(ipart)/rhopart @@ -587,7 +611,7 @@ subroutine write_radial_data(iunit,output,time) print '(a,a)', 'Writing to file ',output open(iunit,file=output) write(iunit,'("# Disc Stress data at t = ",es20.12)') time - write(iunit,"('#',11(1x,'[',i2.2,1x,a11,']',2x))") & + write(iunit,"('#',12(1x,'[',i2.2,1x,a11,']',2x))") & 1,'radius (AU)', & 2,'sigma (cgs)', & 3,'cs (cgs)', & @@ -598,12 +622,13 @@ subroutine write_radial_data(iunit,output,time) 8,'alpha_reyn',& 9,'alpha_grav',& 10,'alpha_mag',& - 11,'alpha_art' + 11,'alpha_art',& + 12,'particle H (au)' do ibin=1,nbins - write(iunit,'(11(es18.10,1X))') rad(ibin),sigma(ibin),csbin(ibin), & + write(iunit,'(12(es18.10,1X))') rad(ibin),sigma(ibin),csbin(ibin), & omega(ibin),epicyc(ibin),H(ibin), abs(toomre_q(ibin)),alpha_reyn(ibin), & - alpha_grav(ibin),alpha_mag(ibin),alpha_art(ibin) + alpha_grav(ibin),alpha_mag(ibin),alpha_art(ibin),part_scaleheight(ibin) enddo close(iunit) @@ -612,6 +637,26 @@ subroutine write_radial_data(iunit,output,time) end subroutine write_radial_data +subroutine calculate_H(nbin,H,zsetgas,ninbin) +! copied from utils disc + integer, intent(in) :: nbin + real, intent(out) :: H(:) + real, intent(in) :: zsetgas(:,:) + integer, intent(in) :: ninbin(:) + integer :: ii + real :: meanzii + + do ii = 1,nbin + if (ninbin(ii)==0) then + meanzii = 0. + else + meanzii = sum(zsetgas(1:ninbin(ii),ii))/real(ninbin(ii)) + endif + H(ii) = sqrt(sum(((zsetgas(1:ninbin(ii),ii)-meanzii)**2)/(real(ninbin(ii)-1)))) + enddo + +end subroutine calculate_H + !-------------------------------------------------------- !+ ! Deallocate arrays @@ -628,6 +673,7 @@ subroutine deallocate_arrays deallocate(gr,gphi,Br,Bphi,vrbin,vphibin) deallocate(sigma,csbin,H,toomre_q,omega,epicyc) deallocate(alpha_reyn,alpha_grav,alpha_mag,alpha_art) + deallocate(part_scaleheight) end subroutine deallocate_arrays !------------------------------------------------------- From f4449442d9ea3fe10364fcae98cb2ad0987a7047 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 1 May 2024 16:16:24 +0100 Subject: [PATCH 107/182] Fixing bugs in ModLom cooling --- src/main/cooling_stamatellos.f90 | 138 +++++++++++++------- src/main/dens.F90 | 2 +- src/main/eos_stamatellos.f90 | 17 ++- src/main/force.F90 | 47 ++++++- src/setup/density_profiles.f90 | 2 +- src/setup/libsetup.f90 | 2 +- src/setup/phantomsetup.F90 | 26 ++-- src/setup/readwrite_kepler.f90 | 2 +- src/setup/readwrite_mesa.f90 | 181 +++++++++++++++------------ src/setup/relax_star.f90 | 32 ++--- src/setup/set_Bfield.f90 | 2 +- src/setup/set_binary.f90 | 173 +++++++++++++++++-------- src/setup/set_cubic_core.f90 | 2 +- src/setup/set_disc.F90 | 6 +- src/setup/set_dust.f90 | 2 +- src/setup/set_dust_options.f90 | 2 +- src/setup/set_fixedentropycore.f90 | 2 +- src/setup/set_flyby.f90 | 4 +- src/setup/set_hierarchical.f90 | 34 +++-- src/setup/set_hierarchical_utils.f90 | 2 +- src/setup/set_planets.f90 | 2 +- src/setup/set_shock.f90 | 2 +- src/setup/set_slab.f90 | 2 +- src/setup/set_softened_core.f90 | 2 +- src/setup/set_sphere.f90 | 2 +- src/setup/set_star_utils.f90 | 15 ++- src/setup/set_unifdis.f90 | 2 +- src/setup/set_units.f90 | 2 +- src/setup/set_vfield.f90 | 2 +- src/setup/setup_BHL.f90 | 2 +- src/setup/setup_alfvenwave.f90 | 2 +- src/setup/setup_asteroidwind.f90 | 2 +- src/setup/setup_blob.f90 | 2 +- src/setup/setup_bondiinject.f90 | 2 +- src/setup/setup_chinchen.f90 | 2 +- src/setup/setup_cluster.f90 | 2 +- src/setup/setup_collidingclouds.f90 | 50 +++----- src/setup/setup_common.f90 | 2 +- src/setup/setup_disc.f90 | 6 +- src/setup/setup_dustsettle.f90 | 2 +- src/setup/setup_dustybox.f90 | 2 +- src/setup/setup_dustysedov.f90 | 2 +- src/setup/setup_empty.f90 | 2 +- src/setup/setup_firehose.f90 | 2 +- src/setup/setup_galaxies.f90 | 2 +- src/setup/setup_galcen_stars.f90 | 2 +- src/setup/setup_galdisc.f90 | 12 +- src/setup/setup_grdisc.F90 | 2 +- src/setup/setup_grtde.f90 | 2 +- src/setup/setup_gwdisc.f90 | 2 +- src/setup/setup_hierarchical.f90 | 2 +- src/setup/setup_jadvect.f90 | 2 +- src/setup/setup_kh.f90 | 2 +- src/setup/setup_mhdblast.f90 | 2 +- src/setup/setup_mhdrotor.f90 | 2 +- src/setup/setup_mhdsine.f90 | 2 +- src/setup/setup_mhdvortex.f90 | 2 +- src/setup/setup_mhdwave.f90 | 2 +- src/setup/setup_nsdisc.f90 | 4 +- src/setup/setup_orstang.f90 | 2 +- src/setup/setup_params.f90 | 2 +- src/setup/setup_planetdisc.f90 | 2 +- src/setup/setup_prtest.f90 | 28 ++--- src/setup/setup_quebec.f90 | 2 +- src/setup/setup_radiativebox.f90 | 2 +- src/setup/setup_sedov.f90 | 2 +- src/setup/setup_solarsystem.f90 | 2 +- src/setup/setup_sphereinbox.f90 | 4 +- src/setup/setup_srblast.f90 | 2 +- src/setup/setup_srpolytrope.f90 | 2 +- src/setup/setup_star.f90 | 2 +- src/setup/setup_taylorgreen.f90 | 2 +- src/setup/setup_testparticles.f90 | 24 ++-- src/setup/setup_tokamak.f90 | 2 +- src/setup/setup_torus.f90 | 2 +- src/setup/setup_turb.f90 | 2 +- src/setup/setup_unifdis.f90 | 35 ++++-- src/setup/setup_wave.f90 | 11 +- src/setup/setup_wavedamp.f90 | 48 ++++--- src/setup/setup_wddisc.f90 | 2 +- src/setup/stretchmap.f90 | 2 +- src/setup/velfield_fromcubes.f90 | 2 +- 82 files changed, 607 insertions(+), 410 deletions(-) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 52705cc45..53988e395 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! module cooling_stamatellos ! @@ -20,9 +20,10 @@ module cooling_stamatellos ! implicit none - real, public :: Lstar ! in units of L_sun + real, public :: Lstar=0.0 ! in units of L_sun integer :: isink_star ! index of sink to use as illuminating star - integer :: od_method = 1 ! default = Stamatellos+ 2007 method + integer :: od_method = 4 ! default = Stamatellos+ 2007 method + integer :: fld_opt = 1 ! by default FLD is switched on public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star @@ -30,12 +31,16 @@ module cooling_stamatellos subroutine init_star() use part, only:nptmass,xyzmh_ptmass + use io, only:fatal integer :: i,imin real :: rsink2,rsink2min rsink2min = 0d0 - if (nptmass == 0 .or. Lstar == 0.0) then - isink_star = 0 ! no stellar heating + + isink_star = 0 + if (od_method == 4 .and. nptmass == 0) then + print *, "NO central star and using od_method = 4" + elseif (nptmass == 0) then print *, "No stellar heating." elseif (nptmass == 1) then isink_star = 1 @@ -50,7 +55,7 @@ subroutine init_star() isink_star = imin endif if (isink_star > 0) print *, "Using sink no. ", isink_star,& - "at (xyz)",xyzmh_ptmass(1:3,isink_star),"as illuminating star." + "at (xyz)",xyzmh_ptmass(1:3,isink_star)!"as illuminating star." end subroutine init_star ! @@ -58,32 +63,27 @@ end subroutine init_star ! subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) use io, only:warning - use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh + 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 + duFLD,doFLD,ttherm_store,teqi_store,opac_store use part, only:xyzmh_ptmass + real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt integer,intent(in) :: i real,intent(out) :: dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 - real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,du_tot - real :: tcool,ueqi,umini,tthermi,poti,presi,du_FLDi + real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,Hstam,HLom,du_tot + real :: cs2,Om2,Hmod2 + real :: opac,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi poti = Gpot_cool(i) du_FLDi = duFLD(i) -! Tfloor is from input parameters and is background heating -! Stellar heating - if (isink_star > 0 .and. Lstar > 0.d0) then + if (isink_star > 0) then ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & - + (yi-xyzmh_ptmass(2,isink_star))**2d0 & - + (zi-xyzmh_ptmass(3,isink_star))**2d0 - ri2 = ri2 *udist*udist -! Tfloor + stellar heating - Tmini4 = Tfloor**4d0 + (Lstar*solarl/(16d0*pi*steboltz*ri2)) - else - Tmini4 = Tfloor**4d0 + + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + + (zi-xyzmh_ptmass(3,isink_star))**2d0 endif ! get opacities & Ti for ui @@ -92,30 +92,67 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) presi = kb_on_mh*rhoi*unit_density*Ti/gmwi ! cgs presi = presi/unit_pressure !code units + if (isnan(kappaBari)) then + print *, "kappaBari is NaN\n", " ui(erg) = ", ui*unit_ergg, "rhoi=", rhoi*unit_density, "Ti=", Ti, & + "i=", i + stop + endif + 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+ method of estimating the mean column density - coldensi = 1.014d0 * presi / abs(gradP_cool(i))! 1.014d0 * P/(-gradP/rho) Lombardi+ 2015 - coldensi = coldensi * umass/udist/udist ! physical units +! 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) + !Q3D = Om2/(4.d0*pi*rhoi) + !Hmod2 = (cs2/Om2) * piontwo /(1d0 + (1d0/(rpiontwo*Q3D))) + Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/Hmod2)) + coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units end select - tcool = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units - dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/tcool/unit_ergg*utime! code units +! Tfloor is from input parameters and is background heating +! Stellar heating + if (isink_star > 0 .and. Lstar > 0.d0) then +! Tfloor + stellar heating + Tmini4 = Tfloor**4d0 + exp(-coldensi*kappaBari)*(Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) + else + Tmini4 = Tfloor**4d0 + endif -! calculate Teqi + opac = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units + opac_store(i) = opac + dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opac/unit_ergg*utime! code units if (doFLD) then ! include term from FLD - Teqi = (du_FLDi + dudti_sph) *tcool*unit_ergg/utime ! physical units + Teqi = (du_FLDi + dudti_sph) *opac*unit_ergg/utime ! physical units du_tot = dudti_sph + dudt_rad + du_FLDi else - Teqi = dudti_sph*tcool*unit_ergg/utime + Teqi = dudti_sph*opac*unit_ergg/utime du_tot = dudti_sph + dudt_rad endif + Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini4 if (Teqi < Tmini4) then @@ -123,36 +160,35 @@ subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) else Teqi = Teqi**(1.0/4.0) endif - + teqi_store(i) = Teqi call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg - - - !if (Ti > 6d0) print *, "eq temps:", Teqi,Ti ! calculate thermalization timescale and -! internal energy update -> put in form where it'll work as dudtcool +! internal energy update -> in form where it'll work as dudtcool if ((du_tot) == 0.d0) then tthermi = 0d0 else tthermi = abs((ueqi - ui)/(du_tot)) endif + + ttherm_store(i) = tthermi + if (tthermi == 0d0) then dudti_cool = 0.d0 ! condition if denominator above is zero else dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units endif - - + if (isnan(dudti_cool)) then - print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti +! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti print *, "rhoi=",rhoi, "Ti=", Ti - print *, "tcool=",tcool,"coldensi=",coldensi,"dudti_sph",dudti_sph + print *, "opac=",opac,"coldensi=",coldensi,"dudti_sph",dudti_sph print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad + print *, "dudt_rad=", dudt_rad ,"dudt_dlf=",du_fldi,"ueqi=",ueqi,"ui=",ui call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then @@ -169,43 +205,51 @@ subroutine write_options_cooling_stamatellos(iunit) !N.B. Tfloor handled in cooling.F90 call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) - call write_inopt(od_method,'OD method','Method for estimating optical depth: (1) potential (2) pressure',iunit) + call write_inopt(od_method,'OD method',& + 'Method for estimating optical depth:(1)Stamatellos (2)Lombardi (3)combined (4)modified Lombardi',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) + call write_inopt(FLD_opt,'do FLD','Do FLD? (1) yes (0) no',iunit) end subroutine write_options_cooling_stamatellos subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) use io, only:warning,fatal - use eos_stamatellos, only: eos_file + use eos_stamatellos, only: eos_file,doFLD character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallstam integer, intent(out) :: ierr integer, save :: ngot = 0 - imatch = .true. igotallstam = .false. ! cooling options are compulsory select case(trim(name)) case('Lstar') read(valstring,*,iostat=ierr) Lstar + if (Lstar < 0.) call fatal('Lstar','Luminosity cannot be negative') ngot = ngot + 1 case('OD method') read(valstring,*,iostat=ierr) od_method - if (od_method < 1 .or. od_method > 2) then - call fatal('cooling options','od_method must be 1 or 2',var='od_method',ival=od_method) + if (od_method < 1 .or. od_method > 4) then + call fatal('cooling options','od_method must be 1, 2, 3 or 4',var='od_method',ival=od_method) endif ngot = ngot + 1 case('EOS_file') read(valstring,*,iostat=ierr) eos_file ngot = ngot + 1 + case('do FLD') + read(valstring,*,iostat=ierr) FLD_opt + if (FLD_opt < 0) call fatal('FLD_opt','FLD option out of range') + if (FLD_opt == 0) then + doFLD = .false. + elseif (FLD_opt == 1) then + doFLD = .true. + endif + ngot = ngot + 1 case default imatch = .false. end select - if (od_method /= 1 .and. od_method /= 2) then - call warning('cooling_stamatellos','optical depth method unknown') - endif - if (ngot >= 3) igotallstam = .true. + if (ngot >= 4) igotallstam = .true. end subroutine read_options_cooling_stamatellos diff --git a/src/main/dens.F90 b/src/main/dens.F90 index daece1767..60d90ed93 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -268,7 +268,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol !$omp shared(thread_complete) & !$omp shared(ncomplete_mpi) & !$omp shared(icooling) & -!$omp shared(lambda_FLD,urad_FLD) & +!$omp shared(lambda_FLD,urad_FLD,doFLD) & !$omp reduction(+:nlocal) & !$omp private(do_export) & !$omp private(j) & diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 060633d6a..d97e0227a 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -22,12 +22,13 @@ module eos_stamatellos 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(:) character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file - logical,parameter,public :: doFLD = .True. + logical,public :: doFLD = .True., floor_energy = .False. integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep,finish_S07cool public :: get_k_fld + contains subroutine init_S07cool() @@ -38,9 +39,16 @@ subroutine init_S07cool() allocate(duFLD(npart)) allocate(lambda_fld(npart)) allocate(urad_FLD(npart)) + allocate(ttherm_store(npart)) + allocate(teqi_store(npart)) + allocate(opac_store(npart)) urad_FLD(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') - if (doFLD) print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" + if (doFLD) then + print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" + else + print *, "NOT using FLD. Using cooling only" + endif end subroutine init_S07cool subroutine finish_S07cool() @@ -50,6 +58,9 @@ subroutine finish_S07cool() 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(opac_store)) deallocate(opac_store) close(iunitst) end subroutine finish_S07cool diff --git a/src/main/force.F90 b/src/main/force.F90 index 3d7b3fc33..b542aafef 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -903,7 +903,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt use eos, only:ieos,eos_is_non_ideal - use eos_stamatellos, only:gradP_cool,Gpot_cool + use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,getopac_opdep,get_k_fld #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -928,6 +928,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use metric_tools,only:imet_minkowski,imetric use utils_gr, only:get_bigv use radiation_utils, only:get_rad_R + use io, only:fatal integer, intent(in) :: i logical, intent(in) :: iamgasi,iamdusti real, intent(in) :: xpartveci(:) @@ -1023,8 +1024,8 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi - real :: gradpx,gradpy,gradpz,gradP_cooli,gradP_coolj + real :: radPj,fgravxi,fgravyi,fgravzi,kfldi,kfldj,Ti,Tj,diffterm,gmwi + real :: gradpx,gradpy,gradpz,gradP_cooli=0d0,gradP_coolj=0d0 ! unpack xi = xpartveci(ixi) @@ -1187,9 +1188,20 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (icooling == 9) then gradP_cool(i) = 0d0 Gpot_cool(i) = 0d0 + if (doFLD) then + duFLD(i) = 0d0 + kfldi = 0d0 + kfldj = 0d0 + endif gradpx = 0d0 gradpy = 0d0 gradpz = 0d0 + diffterm = 0d0 + Ti=0 + Tj=0 + if (doFLD .and. dt > 0d0) then + call get_k_fld(rhoi,eni,i,kfldi,Ti) + endif endif loop_over_neighbours2: do n = 1,nneigh @@ -1588,6 +1600,25 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g gradP_coolj = 0d0 if (usej) then gradp_coolj = pmassj*prj*rho1j*rho1j*grkernj + if (doFLD .and. dt > 0.) then + call get_k_fld(rhoj,enj,j,kfldj,Tj) + if (rhoj == 0d0) then + diffterm = 0d0 + print *, "setting diffterm = 0", i, j, rhoj + elseif ((kfldj + kfldi) == 0.) then + diffterm = 0d0 + else + diffterm = 4d0*pmassj/rhoi/rhoj + diffterm = diffterm * kfldi * kfldj / (kfldi+kfldj) + diffterm = diffterm * (Ti - Tj) / rij2 + diffterm = diffterm*cnormk*grkerni*(runix*dx + runiy*dy + runiz*dz) + endif + duFLD(i) = duFLD(i) + diffterm + if (isnan(duFLD(i))) then + print *, "kfldi, kfldj, Ti,Tj,diffterm", kfldi,kfldj, Ti,Tj,diffterm + call fatal('force','duFLD is nan') + endif + endif endif endif @@ -1717,6 +1748,10 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idendtdissi) = fsum(idendtdissi) + dendissterm endif + if (icooling == 9) then + Gpot_cool(i) = Gpot_cool(i) + pmassj*phii + endif + !--add contribution to particle i's force if (mhd) then !--div B in symmetric form (for source term subtraction) @@ -2123,7 +2158,6 @@ subroutine start_cell(cell,iphase,xyzh,vxyzu,gradh,divcurlv,divcurlB,dvdx,Bevol, use timestep_ind, only:get_dt use nicil, only:nimhd_get_jcbcb use radiation_utils, only:get_rad_R - use eos_stamatellos, only:Gpot_cool type(cellforce), intent(inout) :: cell integer(kind=1), intent(in) :: iphase(:) real, intent(in) :: xyzh(:,:) @@ -2584,6 +2618,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use part, only:Omega_k use io, only:warning use physcon, only:c,kboltz + use eos_stamatellos, only:Gpot_cool integer, intent(in) :: icall type(cellforce), intent(inout) :: cell real, intent(inout) :: fxyzu(:,:) @@ -2782,7 +2817,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv !--add self-contribution call kernel_softening(0.,0.,potensoft0,dum) epoti = 0.5*pmassi*(fsum(ipot) + pmassi*potensoft0*hi1) - if (icooling==9 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + pmassi*potensoft0*hi1 + if ((icooling==9) .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + pmassi*potensoft0*hi1 ! !--add contribution from distant nodes, expand these in Taylor series about node centre ! use xcen directly, -1 is placeholder @@ -2792,7 +2827,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi - if (icooling==9 .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes + if ((icooling==9) .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif diff --git a/src/setup/density_profiles.f90 b/src/setup/density_profiles.f90 index f8506a172..b06e9b2f1 100644 --- a/src/setup/density_profiles.f90 +++ b/src/setup/density_profiles.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module rho_profile ! diff --git a/src/setup/libsetup.f90 b/src/setup/libsetup.f90 index 8089288f9..fc36e5e26 100644 --- a/src/setup/libsetup.f90 +++ b/src/setup/libsetup.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module libsetup ! diff --git a/src/setup/phantomsetup.F90 b/src/setup/phantomsetup.F90 index 6b27c6037..e24b9669a 100644 --- a/src/setup/phantomsetup.F90 +++ b/src/setup/phantomsetup.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantomsetup ! @@ -20,13 +20,13 @@ program phantomsetup ! setup_params, systemutils, timestep, units ! use memory, only:allocate_memory,deallocate_memory - use dim, only:tagline,maxp,maxvxyzu,mpi,& + use dim, only:tagline,maxvxyzu,mpi,& ndivcurlv,ndivcurlB,maxp_hard use part, only:xyzh,massoftype,hfact,vxyzu,npart,npartoftype, & - Bxyz,Bextx,Bexty,Bextz,rhoh,iphase,maxphase,& + Bxyz,Bextx,Bexty,Bextz,rhoh,& isetphase,igas,iamtype,labeltype,mhd,init_part use setBfield, only:set_Bfield - use eos, only:polyk,gamma,en_from_utherm + use eos, only:polyk,gamma use io, only:set_io_unit_numbers,id,master,nprocs,iwritein,fatal,warning use readwrite_dumps, only:init_readwrite_dumps,write_fulldump use readwrite_infile,only:write_infile,read_infile @@ -47,12 +47,11 @@ program phantomsetup use krome_interface, only:write_KromeSetupFile #endif implicit none - integer :: nargs,i,nprocsfake,nerr,nwarn,myid,myid1 + integer :: nargs,nprocsfake,nerr,nwarn,myid,myid1 integer(kind=8) :: ntotal,n_alloc integer, parameter :: lenprefix = 120 character(len=lenprefix) :: fileprefix character(len=lenprefix+10) :: dumpfile,infile,evfile,logfile - real :: pmassi logical :: iexist nprocs = 1 ! for MPI, this is not initialised until init_mpi, but an initialised value is required for init_part @@ -135,20 +134,9 @@ program phantomsetup !--perform sanity checks on the output of setpart routine ! call check_setup(nerr,nwarn) + if (nwarn > 0) call warning('initial','warnings during particle setup',var='warnings',ival=nwarn) if (nerr > 0) call fatal('initial','errors in particle setup',var='errors',ival=nerr) -! -!--setup defines thermal energy: if we are using the entropy then -! we need to convert this into the entropy variable before writing the dump file -! (the dump file write converts back to utherm) -! - if (maxvxyzu==4) then - pmassi = massoftype(igas) - do i=1,npart - if (maxphase==maxp) pmassi = massoftype(iamtype(iphase(i))) - vxyzu(maxvxyzu,i) = en_from_utherm(vxyzu(:,i),rhoh(xyzh(4,i),pmassi),gamma) - enddo - endif if (nprocsfake > 1) then ntotal = npart_total @@ -159,7 +147,7 @@ program phantomsetup ! if code is run in relativistic units (c=1) if (c_is_unity()) calc_gravitwaves = .true. - if (id==master) call print_units() + if (id==master .and. nerr==0 .and. nwarn==0) call print_units() ! !--dumpfile name should end in .tmp unless density has been calculated ! (never true using phantomsetup) diff --git a/src/setup/readwrite_kepler.f90 b/src/setup/readwrite_kepler.f90 index 89b04b013..21d138b8b 100644 --- a/src/setup/readwrite_kepler.f90 +++ b/src/setup/readwrite_kepler.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module readwrite_kepler ! diff --git a/src/setup/readwrite_mesa.f90 b/src/setup/readwrite_mesa.f90 index 372de7fc7..a053eb985 100644 --- a/src/setup/readwrite_mesa.f90 +++ b/src/setup/readwrite_mesa.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module readwrite_mesa ! @@ -31,23 +31,22 @@ module readwrite_mesa !----------------------------------------------------------------------- subroutine read_mesa(filepath,rho,r,pres,m,ene,temp,X_in,Z_in,Xfrac,Yfrac,Mstar,ierr,cgsunits) use physcon, only:solarm,solarr - use fileutils, only:get_nlines,get_ncolumns,string_delete,lcase + use fileutils, only:get_nlines,get_ncolumns,string_delete,lcase,read_column_labels use datafiles, only:find_phantom_datafile use units, only:udist,umass,unit_density,unit_pressure,unit_ergg - integer :: lines,rows,i,ncols,nheaderlines,iu character(len=*), intent(in) :: filepath - logical, intent(in), optional :: cgsunits integer, intent(out) :: ierr - character(len=10000) :: dumc + real, intent(in) :: X_in,Z_in + real, allocatable,dimension(:),intent(out) :: rho,r,pres,m,ene,temp,Xfrac,Yfrac + real, intent(out) :: Mstar + logical, intent(in), optional :: cgsunits + integer :: lines,i,ncols,nheaderlines,nlabels + integer :: idir,iu character(len=120) :: fullfilepath - character(len=24),allocatable :: header(:),dum(:) + character(len=24),allocatable :: header(:) logical :: iexist,usecgs,ismesafile,got_column real,allocatable,dimension(:,:) :: dat - real, intent(in) :: X_in,Z_in - real,allocatable,dimension(:),intent(out) :: rho,r,pres,m,ene,temp,Xfrac,Yfrac - real, intent(out) :: Mstar - rows = 0 usecgs = .false. if (present(cgsunits)) usecgs = cgsunits ! @@ -63,93 +62,119 @@ subroutine read_mesa(filepath,rho,r,pres,m,ene,temp,X_in,Z_in,Xfrac,Yfrac,Mstar, lines = get_nlines(fullfilepath) ! total number of lines in file print "(1x,a)",trim(fullfilepath) - open(newunit=iu,file=fullfilepath,status='old') + open(newunit=iu,file=fullfilepath,status='old',iostat=ierr) + if (ierr /= 0) then + print "(a,/)",' ERROR opening file '//trim(fullfilepath) + return + endif + call get_ncolumns(iu,ncols,nheaderlines) if (nheaderlines == 6) then ! Assume file is a MESA profile, and so it has 6 header lines, and (row=3, col=2) = number of zones - read(iu,'()') - read(iu,'()') - read(iu,*) lines,lines - read(iu,'()') - read(iu,'()') + read(iu,'()',iostat=ierr) + read(iu,'()',iostat=ierr) + read(iu,*,iostat=ierr) lines,lines + read(iu,'()',iostat=ierr) + read(iu,'()',iostat=ierr) + if (ierr /= 0) then + print "(a,/)",' ERROR reading MESA file header' + return + endif ismesafile = .true. else ismesafile = .false. lines = lines - nheaderlines do i = 1,nheaderlines-1 - read(iu,'()') + read(iu,'()',iostat=ierr) enddo + if (ierr /= 0) then + print "(a,/)",' ERROR reading file header [not MESA format]' + return + endif endif if (lines <= 0) then ! file not found ierr = 1 return endif - read(iu,'(a)') dumc! counting rows - call string_delete(dumc,'[') - call string_delete(dumc,']') - allocate(dum(500)) ; dum = 'aaa' - read(dumc,*,end=101) dum -101 continue - do i = 1,500 - if (dum(i)=='aaa') then - rows = i-1 - exit - endif - enddo - allocate(header(rows),dat(lines,rows)) - header(1:rows) = dum(1:rows) - deallocate(dum) - do i = 1,lines - read(iu,*) dat(lines-i+1,1:rows) - enddo + ! extract column labels from the file header + allocate(header(ncols),dat(lines,ncols)) + call read_column_labels(iu,nheaderlines,ncols,nlabels,header) + if (nlabels /= ncols) print*,' WARNING: different number of labels compared to columns' allocate(m(lines),r(lines),pres(lines),rho(lines),ene(lines), & - temp(lines),Xfrac(lines),Yfrac(lines)) + temp(lines),Xfrac(lines),Yfrac(lines)) - close(iu) - ! Set mass fractions to fixed inputs if not in file - Xfrac = X_in - Yfrac = 1. - X_in - Z_in - do i = 1,rows - if (header(i)(1:1) == '#' .and. .not. trim(lcase(header(i)))=='#mass') then - print '("Detected wrong header entry : ",A," in file ",A)',trim(lcase(header(i))),trim(fullfilepath) - ierr = 2 + over_directions: do idir=1,2 ! try backwards, then forwards + if (idir==1) then + ! read MESA file backwards, from surface to centre + do i = 1,lines + read(iu,*,iostat=ierr) dat(lines-i+1,1:ncols) + enddo + else + ! read file forwards, from centre to surface + do i = 1,lines + read(iu,*,iostat=ierr) dat(i,1:ncols) + enddo + endif + if (ierr /= 0) then + print "(a,/)",' ERROR reading data from file: reached end of file?' return endif - got_column = .true. - select case(trim(lcase(header(i)))) - case('mass_grams') - m = dat(1:lines,i) - case('mass','#mass') - m = dat(1:lines,i) - if (ismesafile) m = m * solarm ! If reading MESA profile, 'mass' is in units of Msun - case('rho','density') - rho = dat(1:lines,i) - case('logrho') - rho = 10**(dat(1:lines,i)) - case('energy','e_int','e_internal') - ene = dat(1:lines,i) - case('radius_cm') - r = dat(1:lines,i) - case('radius') - r = dat(1:lines,i) - if (ismesafile) r = r * solarr - case('logr') - r = (10**dat(1:lines,i)) * solarr - case('pressure') - pres = dat(1:lines,i) - case('temperature') - temp = dat(1:lines,i) - case('x_mass_fraction_h','xfrac') - Xfrac = dat(1:lines,i) - case('y_mass_fraction_he','yfrac') - Yfrac = dat(1:lines,i) - case default - got_column = .false. - end select - if (got_column) print "(1x,i0,': ',a)",i,trim(header(i)) - enddo - print "(a)" + + ! Set mass fractions to fixed inputs if not in file + Xfrac = X_in + Yfrac = 1. - X_in - Z_in + do i = 1,ncols + if (header(i)(1:1) == '#' .and. .not. trim(lcase(header(i)))=='#mass') then + print '("Detected wrong header entry : ",a," in file ",a)',trim(lcase(header(i))),trim(fullfilepath) + ierr = 2 + return + endif + got_column = .true. + select case(trim(lcase(header(i)))) + case('mass_grams') + m = dat(1:lines,i) + case('mass','#mass','m') + m = dat(1:lines,i) + if (ismesafile .or. maxval(m) < 1.e-10*solarm) m = m * solarm ! If reading MESA profile, 'mass' is in units of Msun + case('rho','density') + rho = dat(1:lines,i) + case('logrho') + rho = 10**(dat(1:lines,i)) + case('energy','e_int','e_internal') + ene = dat(1:lines,i) + case('radius_cm') + r = dat(1:lines,i) + case('radius','r') + r = dat(1:lines,i) + if (ismesafile .or. maxval(r) < 1e-10*solarr) r = r * solarr + case('logr') + r = (10**dat(1:lines,i)) * solarr + case('pressure','p') + pres = dat(1:lines,i) + case('temperature','t') + temp = dat(1:lines,i) + case('x_mass_fraction_h','xfrac') + Xfrac = dat(1:lines,i) + case('y_mass_fraction_he','yfrac') + Yfrac = dat(1:lines,i) + case default + got_column = .false. + end select + if (got_column .and. idir==1) print "(1x,i0,': ',a)",i,trim(header(i)) + enddo + if (idir==1) print "(a)" + + ! quit the loop over directions if the radius increases + if (idir==1 .and. r(2) > r(1)) exit over_directions + + ! otherwise rewind and re-skip header + rewind(iu) + do i=1,nheaderlines + read(iu,*,iostat=ierr) + enddo + enddo over_directions + close(iu) if (.not. usecgs) then m = m / umass diff --git a/src/setup/relax_star.f90 b/src/setup/relax_star.f90 index 62b062c93..a4bb589ec 100644 --- a/src/setup/relax_star.f90 +++ b/src/setup/relax_star.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module relaxstar ! @@ -15,7 +15,6 @@ module relaxstar ! ! :Runtime parameters: ! - maxits : *maximum number of relaxation iterations* -! - tol_dens : *% error in density to stop relaxation* ! - tol_ekin : *tolerance on ekin/epot to stop relaxation* ! ! :Dependencies: checksetup, damping, deriv, dim, dump_utils, energies, @@ -27,7 +26,6 @@ module relaxstar public :: relax_star,write_options_relax,read_options_relax real, private :: tol_ekin = 1.e-7 ! criteria for being converged - real, private :: tol_dens = 1. ! allow 1% RMS error in density integer, private :: maxits = 1000 real, private :: gammaprev,hfactprev,mass1prev @@ -177,9 +175,9 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np ierr = ierr_unbound return endif - if (id==master) print "(/,3(a,1pg11.3),/,a,0pf6.2,a,es11.3,a,i4)",& + if (id==master) print "(/,3(a,1pg11.3),/,a,1pg11.3,a,i4)",& ' RELAX-A-STAR-O-MATIC: Etherm:',etherm,' Epot:',Epot, ' R*:',maxval(r), & - ' WILL stop WHEN: dens error < ',tol_dens,'% AND Ekin/Epot < ',tol_ekin,' OR Iter=',maxits + ' WILL stop when Ekin/Epot < ',tol_ekin,' OR Iter=',maxits if (write_files) then if (.not.restart) call write_fulldump(t,filename) @@ -215,18 +213,22 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np ! compute energies and check for convergence ! call compute_energies(t) - converged = (ekin > 0. .and. ekin/abs(epot) < tol_ekin .and. rmserr < 0.01*tol_dens) + converged = (ekin > 0. .and. ekin/abs(epot) < tol_ekin) !.and. rmserr < 0.01*tol_dens) ! ! print information to screen ! if (use_step) then - if (id==master) print "(a,es10.3,a,2pf6.2,2(a,1pg11.3))",& - ' Relaxing star: t/dyn:',t/tdyn,', dens error:',rmserr,'%, R*:',rmax, & - ' Ekin/Epot:',ekin/abs(epot) + if (id==master .and. mod(nits,10)==0 .or. nits==1) then + print "(a,es10.3,a,2pf6.2,2(a,1pg11.3))",& + ' Relaxing star: t/dyn:',t/tdyn,', dens error:',rmserr,'%, R*:',rmax, & + ' Ekin/Epot:',ekin/abs(epot) + endif else - if (id==master) print "(a,i4,a,i4,a,2pf6.2,2(a,1pg11.3))",& - ' Relaxing star: Iter',nits,'/',maxits, & - ', dens error:',rmserr,'%, R*:',rmax,' Ekin/Epot:',ekin/abs(epot) + if (id==master .and. mod(nits,10)==0 .or. nits==1) then + print "(a,i4,a,i4,a,2pf6.2,2(a,1pg11.3))",& + ' Relaxing star: Iter',nits,'/',maxits, & + ', dens error:',rmserr,'%, R*:',rmax,' Ekin/Epot:',ekin/abs(epot) + endif endif ! ! additional diagnostic output, mainly for debugging/checking @@ -439,7 +441,7 @@ subroutine check_for_existing_file(filename,npart,mgas,xyzh,vxyzu,restart,ierr) real, intent(inout) :: xyzh(:,:),vxyzu(:,:) logical, intent(out) :: restart integer, intent(out) :: ierr - logical :: iexist,tagged + logical :: iexist character(len=len(filename)) :: restart_file,filetmp character(len=lenid) :: fileid type(dump_h) :: hdr @@ -464,7 +466,7 @@ subroutine check_for_existing_file(filename,npart,mgas,xyzh,vxyzu,restart,ierr) print "(/,1x,a)",'>> RESTARTING relaxation from '//trim(restart_file) call open_dumpfile_r(idump,restart_file,fileid,ierr) - call read_header(idump,hdr,tagged,ierr) + call read_header(idump,hdr,ierr) close(idump) if (ierr /= 0) then print "(a)",' ERROR: could not read file header' @@ -545,7 +547,6 @@ subroutine write_options_relax(iunit) integer, intent(in) :: iunit call write_inopt(tol_ekin,'tol_ekin','tolerance on ekin/epot to stop relaxation',iunit) - call write_inopt(tol_dens,'tol_dens','% error in density to stop relaxation',iunit) call write_inopt(maxits,'maxits','maximum number of relaxation iterations',iunit) end subroutine write_options_relax @@ -561,7 +562,6 @@ subroutine read_options_relax(db,nerr) integer, intent(inout) :: nerr call read_inopt(tol_ekin,'tol_ekin',db,errcount=nerr) - call read_inopt(tol_dens,'tol_dens',db,errcount=nerr) call read_inopt(maxits,'maxits',db,errcount=nerr) end subroutine read_options_relax diff --git a/src/setup/set_Bfield.f90 b/src/setup/set_Bfield.f90 index 08dfe4093..489904342 100644 --- a/src/setup/set_Bfield.f90 +++ b/src/setup/set_Bfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setBfield ! diff --git a/src/setup/set_binary.f90 b/src/setup/set_binary.f90 index 2120c228c..e1208a837 100644 --- a/src/setup/set_binary.f90 +++ b/src/setup/set_binary.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setbinary ! @@ -47,16 +47,31 @@ module setbinary contains -!---------------------------------------------------------------- +!------------------------------------------------------------------------------ !+ -! setup for a binary +! setup for a binary orbit +! +! INPUT: +! m1 - mass of object 1 +! m2 - mass of object 2 +! semimajoraxis - semimajor axis (e/=1) or pericentre distance (e=1) +! eccentricity - eccentricity +! accretion_radius1 - accretion radius for point mass 1 +! accretion_radius2 - accretion radius for point mass 2 +! [optional] posang_ascnode - position angle of the ascending node (Omega, deg) +! [optional] arg_peri - argument of periapsis (w, deg) +! [optional] incl - orbital inclination (i, deg) +! [optional] f - true anomaly (nu, deg) +! [optional] mean_anomaly - mean anomaly (M, deg; replaces true anomaly) +! +! OUTPUT: cartesian positions and velocities for both objects !+ -!---------------------------------------------------------------- +!------------------------------------------------------------------------------ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & accretion_radius1,accretion_radius2, & xyzmh_ptmass,vxyz_ptmass,nptmass,ierr,omega_corotate,& posang_ascnode,arg_peri,incl,f,mean_anomaly,verbose) - use binaryutils, only:get_E,get_E_from_mean_anomaly + use binaryutils, only:get_E,get_E_from_mean_anomaly,get_E_from_true_anomaly real, intent(in) :: m1,m2 real, intent(in) :: semimajoraxis,eccentricity real, intent(in) :: accretion_radius1,accretion_radius2 @@ -67,10 +82,12 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & real, intent(out), optional :: omega_corotate logical, intent(in), optional :: verbose integer :: i1,i2,i - real :: mtot,dx(3),dv(3),Rochelobe1,Rochelobe2,period,bigM + real :: mtot,dx(3),dv(3),Rochelobe1,Rochelobe2,period,bigM,rperi,rapo real :: x1(3),x2(3),v1(3),v2(3),omega0,cosi,sini,xangle,reducedmass,angmbin - real :: a,E,E_dot,P(3),Q(3),omega,big_omega,inc,ecc,tperi,term1,term2,theta + real :: a,E,E_dot,P(3),Q(3),omega,big_omega,inc,ecc,tperi + real :: term1,term2,term3,term4,theta,theta_max,energy logical :: do_verbose + character(len=12) :: orbit_type ierr = 0 do_verbose = .true. @@ -82,12 +99,67 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & ! masses mtot = m1 + m2 - - Rochelobe1 = Rochelobe_estimate(m2,m1,semimajoraxis) - Rochelobe2 = Rochelobe_estimate(m1,m2,semimajoraxis) - period = sqrt(4.*pi**2*semimajoraxis**3/mtot) reducedmass = m1*m2/mtot - angmbin = reducedmass*sqrt(mtot*semimajoraxis*(1. - eccentricity**2)) + + ! check for stupid parameter choices + if (m1 <= 0.) then + print "(1x,a)",'ERROR: set_binary: primary mass <= 0' + ierr = ierr_m1 + endif + if (m2 < 0.) then + print "(1x,a)",'ERROR: set_binary: secondary mass < 0' + ierr = ierr_m2 + endif + if (abs(semimajoraxis) <= tiny(0.)) then + print "(1x,a)",'ERROR: set_binary: semi-major axis = 0' + ierr = ierr_semi + endif + if (semimajoraxis < 0. .and. eccentricity <= 1.) then + print "(1x,a)",'ERROR: set_binary: using a < 0 requires e > 1' + ierr = ierr_semi + endif + if (eccentricity < 0.) then + print "(1x,a)",'ERROR: set_binary: eccentricity must be positive' + ierr = ierr_ecc + endif + if (eccentricity > 1. .and. present(f)) then + theta = f*pi/180. + theta_max = acos(-1./eccentricity) + if (abs(theta) > theta_max) then + print "(1x,2(a,f8.2))",'ERROR: max true anomaly for e = ',eccentricity, & + ' is |nu| < ',theta_max*180./pi + ierr = ierr_ecc + endif + endif + ! exit routine if cannot continue + if (ierr /= 0) return + + ! set parameters that depend on the orbit type + if (eccentricity < 1.) then + a = abs(semimajoraxis) + rperi = a*(1. - eccentricity) + rapo = semimajoraxis*(1. + eccentricity) + period = sqrt(4.*pi**2*a**3/mtot) + angmbin = reducedmass*sqrt(mtot*a*(1. - eccentricity**2)) + energy = -mtot/(2.*a) + elseif (eccentricity > 1.) then + a = -abs(semimajoraxis) + rperi = a*(1. - eccentricity) + rapo = huge(rapo) + period = huge(period) + angmbin = reducedmass*sqrt(mtot*a*(1. - eccentricity**2)) + energy = -mtot/(2.*a) + else + a = huge(a) + rperi = abs(semimajoraxis) ! for parabolic orbit we must give the pericentre distance + rapo = huge(rapo) + period = huge(period) + angmbin = reducedmass*sqrt(2.*mtot*rperi) + energy = 0. + endif + + Rochelobe1 = Rochelobe_estimate(m2,m1,rperi) + Rochelobe2 = Rochelobe_estimate(m1,m2,rperi) if (do_verbose) then print "(/,2x,a)",'---------- binary parameters ----------- ' @@ -96,45 +168,23 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & 'secondary mass :',m2, & 'mass ratio m2/m1 :',m2/m1, & 'reduced mass :',reducedmass, & - 'semi-major axis :',semimajoraxis, & + 'semi-major axis :',a, & 'period :',period, & 'eccentricity :',eccentricity, & - 'pericentre :',semimajoraxis*(1. - eccentricity), & - 'apocentre :',semimajoraxis*(1. + eccentricity) + 'pericentre :',rperi, & + 'apocentre :',rapo endif if (accretion_radius1 > Rochelobe1) then - print "(1x,a)",'WARNING: set_binary: accretion radius of primary > Roche lobe' + print "(1x,a)",'WARNING: set_binary: accretion radius of primary > Roche lobe at periastron' endif if (accretion_radius2 > Rochelobe2) then - print "(1x,a)",'WARNING: set_binary: accretion radius of secondary > Roche lobe' - endif -! -!--check for stupid parameter choices -! - if (m1 <= 0.) then - print "(1x,a)",'ERROR: set_binary: primary mass <= 0' - ierr = ierr_m1 + print "(1x,a)",'WARNING: set_binary: accretion radius of secondary > Roche lobe at periastron' endif - if (m2 < 0.) then - print "(1x,a)",'ERROR: set_binary: secondary mass <= 0' - ierr = ierr_m2 - endif - if (semimajoraxis <= 0.) then - print "(1x,a)",'ERROR: set_binary: semi-major axis <= 0' - ierr = ierr_semi - endif - if (eccentricity > 1. .or. eccentricity < 0.) then - print "(1x,a)",'ERROR: set_binary: eccentricity must be between 0 and 1' - ierr = ierr_ecc - endif - ! exit routine if cannot continue - if (ierr /= 0) return dx = 0. dv = 0. if (present(posang_ascnode) .and. present(arg_peri) .and. present(incl)) then ! Campbell elements - a = semimajoraxis ecc = eccentricity omega = arg_peri*pi/180. ! our conventions here are Omega is measured East of North @@ -142,10 +192,10 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & inc = incl*pi/180. if (present(f)) then - ! get eccentric anomaly from true anomaly + ! get eccentric, parabolic or hyperbolic anomaly from true anomaly ! (https://en.wikipedia.org/wiki/Eccentric_anomaly#From_the_true_anomaly) theta = f*pi/180. - E = atan2(sqrt(1. - ecc**2)*sin(theta),(ecc + cos(theta))) + E = get_E_from_true_anomaly(theta,ecc) elseif (present(mean_anomaly)) then ! get eccentric anomaly from mean anomaly by solving Kepler equation bigM = mean_anomaly*pi/180. @@ -166,17 +216,36 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & Q(2) = -sin(omega)*sin(big_omega) + cos(omega)*cos(inc)*cos(big_omega) Q(3) = sin(inc)*cos(omega) - term1 = cos(E)-eccentricity - term2 = sqrt(1.-(eccentricity*eccentricity))*sin(E) - E_dot = sqrt((m1 + m2)/(a**3))/(1.-eccentricity*cos(E)) + if (eccentricity < 1.) then ! eccentric + orbit_type = 'Eccentric' + term1 = a*(cos(E)-ecc) + term2 = a*(sqrt(1. - ecc*ecc)*sin(E)) + E_dot = sqrt((m1 + m2)/(a**3))/(1.-ecc*cos(E)) + term3 = a*(-sin(E)*E_dot) + term4 = a*(sqrt(1.- ecc*ecc)*cos(E)*E_dot) + elseif (eccentricity > 1.) then ! hyperbolic + orbit_type = 'Hyperbolic' + term1 = a*(cosh(E)-ecc) + term2 = -a*(sqrt(ecc*ecc - 1.)*sinh(E)) + E_dot = sqrt((m1 + m2)/(abs(a)**3))/(ecc*cosh(E)-1.) + term3 = a*(sinh(E)*E_dot) + term4 = -a*(sqrt(ecc*ecc - 1.)*cosh(E)*E_dot) + else ! parabolic + orbit_type = 'Parabolic' + term1 = rperi*(1. - E*E) + term2 = rperi*(2.*E) + E_dot = sqrt(2.*(m1 + m2)/(rperi**3))/(1. + E*E) + term3 = -E*(rperi*E_dot) + term4 = rperi*E_dot + endif if (do_verbose) then print "(4(2x,a,1pg14.6,/),2x,a,1pg14.6)", & - 'Eccentric anomaly:',E, & + trim(orbit_type)//' anomaly:',E, & 'E_dot :',E_dot, & 'inclination (i, deg):',incl, & 'angle asc. node (O, deg):',posang_ascnode, & - 'arg. pericentre (w, deg):',arg_peri + 'arg. periapsis (w, deg):',arg_peri if (present(f)) print "(2x,a,1pg14.6)", & 'true anomaly (f, deg):',f if (present(mean_anomaly)) print "(2x,a,1pg14.6)", & @@ -185,10 +254,10 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & ! Rotating everything ! Set the positions for the primary and the central secondary - dx(:) = a*(term1*P(:) + term2*Q(:)) ! + xyzmh_ptmass(1,1) + dx(:) = term1*P(:) + term2*Q(:) ! Set the velocities - dv(:) = -a*sin(E)*E_dot*P(:) + a*sqrt(1.-(ecc*ecc))*cos(E)*E_dot*Q(:) + dv(:) = term3*P(:) + term4*Q(:) else ! set binary at apastron @@ -201,14 +270,16 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & x2 = dx*m1/mtot ! velocities - v1 = -dv*m2/mtot !(/0.,-m2/mtot*vmag,0./) - v2 = dv*m1/mtot !(/0.,m1/mtot*vmag,0./) + v1 = -dv*m2/mtot + v2 = dv*m1/mtot omega0 = v2(2)/x2(1) ! print info about positions and velocities if (do_verbose) then - print "(7(2x,a,1pg14.6,/),2x,a,1pg14.6)", & + print "(9(2x,a,1pg14.6,/),2x,a,1pg14.6)", & + 'energy (mtot/2a) :',energy,& + 'energy (KE+PE) :',-mtot/sqrt(dot_product(dx,dx)) + 0.5*dot_product(dv,dv),& 'angular momentum :',angmbin, & 'mean ang. speed :',omega0, & 'Omega_0 (prim) :',v2(2)/x2(1), & diff --git a/src/setup/set_cubic_core.f90 b/src/setup/set_cubic_core.f90 index e5687e455..0daa194be 100644 --- a/src/setup/set_cubic_core.f90 +++ b/src/setup/set_cubic_core.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setcubiccore ! diff --git a/src/setup/set_disc.F90 b/src/setup/set_disc.F90 index 2234d3692..505713346 100644 --- a/src/setup/set_disc.F90 +++ b/src/setup/set_disc.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setdisc ! @@ -74,8 +74,8 @@ subroutine set_disc(id,master,mixture,nparttot,npart,npart_start,rmin,rmax, & particle_type,particle_mass,hfact,xyzh,vxyzu,polyk, & position_angle,inclination,ismooth,alpha,rwarp,warp_smoothl, & bh_spin,bh_spin_angle,rref,enc_mass,r_grid,writefile,ierr,prefix,verbose) - use io, only:stdout - use part, only:maxp,idust,maxtypes + use io, only:stdout + use part, only:maxp,idust,maxtypes use centreofmass, only:get_total_angular_momentum integer, intent(in) :: id,master integer, optional, intent(in) :: nparttot diff --git a/src/setup/set_dust.f90 b/src/setup/set_dust.f90 index f8b2088d4..346b1ae8b 100644 --- a/src/setup/set_dust.f90 +++ b/src/setup/set_dust.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module set_dust ! diff --git a/src/setup/set_dust_options.f90 b/src/setup/set_dust_options.f90 index 94fca2f77..c97bbf0ca 100644 --- a/src/setup/set_dust_options.f90 +++ b/src/setup/set_dust_options.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module set_dust_options ! diff --git a/src/setup/set_fixedentropycore.f90 b/src/setup/set_fixedentropycore.f90 index dba3393f7..5466782fd 100644 --- a/src/setup/set_fixedentropycore.f90 +++ b/src/setup/set_fixedentropycore.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setfixedentropycore ! diff --git a/src/setup/set_flyby.f90 b/src/setup/set_flyby.f90 index cd69fa817..783ae37a9 100644 --- a/src/setup/set_flyby.f90 +++ b/src/setup/set_flyby.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setflyby ! @@ -191,7 +191,7 @@ function get_T_flyby(m1,m2,dma,n0) result(T) xi = -2*sqrt(n0-1.0)*dma yi = dma*(1.0-(xi/p)**2) - !--graviational parameter + !--gravitational parameter G = 1.0 ! we assume code units where G=1 mu = G*(m1+m2) diff --git a/src/setup/set_hierarchical.f90 b/src/setup/set_hierarchical.f90 index 32a01cc64..22dad2a68 100644 --- a/src/setup/set_hierarchical.f90 +++ b/src/setup/set_hierarchical.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module sethierarchical ! @@ -19,7 +19,8 @@ module sethierarchical ! ! :Owner: Simone Ceppi ! -! :Runtime parameters: None +! :Runtime parameters: +! - hierarchy : *string definining the hierarchy (e.g. 111,112,121,1221,1222)* ! ! :Dependencies: infile_utils, setbinary, sethier_utils ! @@ -110,24 +111,35 @@ subroutine write_hierarchical_setupfile(iunit) integer :: i write(iunit,"(/,a)") '# options for hierarchical system' - call write_inopt(hierarchy, 'hierarchy','', iunit) + call write_inopt(hierarchy, 'hierarchy','string definining the hierarchy (e.g. 111,112,121,1221,1222)', iunit) hs%labels = process_hierarchy(hierarchy) write(iunit,"(/,a)") '# sink properties' do i=1,hs%labels%sink_num - call write_inopt(hs%sinks(i)%mass, trim(hs%labels%sink(i))//'_mass','', iunit) - call write_inopt(hs%sinks(i)%accr, trim(hs%labels%sink(i))//'_accr','', iunit) + call write_inopt(hs%sinks(i)%mass, trim(hs%labels%sink(i))//'_mass',& + 'mass of object '//trim(hs%labels%sink(i)), iunit) + enddo + do i=1,hs%labels%sink_num + call write_inopt(hs%sinks(i)%accr, trim(hs%labels%sink(i))//'_accr',& + 'accretion radius for object '//trim(hs%labels%sink(i)), iunit) enddo write(iunit,"(/,a)") '# orbit properties' do i=1,hs%labels%hl_num - call write_inopt(hs%levels(i)%a, trim(hs%labels%hl(i))//'_a','',iunit) - call write_inopt(hs%levels(i)%e, trim(hs%labels%hl(i))//'_e','',iunit) - call write_inopt(hs%levels(i)%inc, trim(hs%labels%hl(i))//'_i','',iunit) - call write_inopt(hs%levels(i)%O, trim(hs%labels%hl(i))//'_O','',iunit) - call write_inopt(hs%levels(i)%w, trim(hs%labels%hl(i))//'_w','',iunit) - call write_inopt(hs%levels(i)%f, trim(hs%labels%hl(i))//'_f','',iunit) + write(iunit,"(a)") '# binary '//trim(hs%labels%hl(i)) + call write_inopt(hs%levels(i)%a, trim(hs%labels%hl(i))//'_a',& + 'semi-major axis for binary '//trim(hs%labels%hl(i)),iunit) + call write_inopt(hs%levels(i)%e, trim(hs%labels%hl(i))//'_e',& + 'eccentricity for binary '//trim(hs%labels%hl(i)),iunit) + call write_inopt(hs%levels(i)%inc, trim(hs%labels%hl(i))//'_i',& + 'i [deg] inclination for binary '//trim(hs%labels%hl(i)),iunit) + call write_inopt(hs%levels(i)%O, trim(hs%labels%hl(i))//'_O',& + 'Omega [deg] PA of ascending node for binary '//trim(hs%labels%hl(i)),iunit) + call write_inopt(hs%levels(i)%w, trim(hs%labels%hl(i))//'_w',& + 'w [deg] argument of periapsis for binary '//trim(hs%labels%hl(i)),iunit) + call write_inopt(hs%levels(i)%f, trim(hs%labels%hl(i))//'_f',& + 'f [deg] true anomaly for binary '//trim(hs%labels%hl(i)),iunit) enddo end subroutine write_hierarchical_setupfile diff --git a/src/setup/set_hierarchical_utils.f90 b/src/setup/set_hierarchical_utils.f90 index 875744c4a..50aa1866e 100644 --- a/src/setup/set_hierarchical_utils.f90 +++ b/src/setup/set_hierarchical_utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module sethier_utils ! diff --git a/src/setup/set_planets.f90 b/src/setup/set_planets.f90 index d1486e074..8abcb545c 100644 --- a/src/setup/set_planets.f90 +++ b/src/setup/set_planets.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setplanets ! diff --git a/src/setup/set_shock.f90 b/src/setup/set_shock.f90 index 1c17bbb52..e0623f797 100644 --- a/src/setup/set_shock.f90 +++ b/src/setup/set_shock.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setshock ! diff --git a/src/setup/set_slab.f90 b/src/setup/set_slab.f90 index 8601631cc..61c00f7ce 100644 --- a/src/setup/set_slab.f90 +++ b/src/setup/set_slab.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module slab ! diff --git a/src/setup/set_softened_core.f90 b/src/setup/set_softened_core.f90 index 93f2f83aa..a7d546658 100644 --- a/src/setup/set_softened_core.f90 +++ b/src/setup/set_softened_core.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setsoftenedcore ! diff --git a/src/setup/set_sphere.f90 b/src/setup/set_sphere.f90 index 23ffd0297..e3358f9fd 100644 --- a/src/setup/set_sphere.f90 +++ b/src/setup/set_sphere.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module spherical ! diff --git a/src/setup/set_star_utils.f90 b/src/setup/set_star_utils.f90 index de23febf0..73a5d7017 100644 --- a/src/setup/set_star_utils.f90 +++ b/src/setup/set_star_utils.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setstar_utils ! @@ -304,11 +304,13 @@ end subroutine set_star_density ! Add a sink particle as a stellar core !+ !----------------------------------------------------------------------- -subroutine set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,ihsoft,mcore,hsoft,ierr) +subroutine set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,ihsoft,mcore,& + hsoft,ilum,lcore,ierr) integer, intent(out) :: nptmass,ierr real, intent(out) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) - real, intent(in) :: mcore,hsoft - integer :: n,ihsoft + real, intent(in) :: mcore,hsoft,lcore + integer, intent(in) :: ihsoft,ilum + integer :: n ierr = 0 ! Check for sensible values @@ -320,12 +322,17 @@ subroutine set_stellar_core(nptmass,xyzmh_ptmass,vxyz_ptmass,ihsoft,mcore,hsoft, ierr = 2 return endif + if (lcore < 0.) then + ierr = 3 + return + endif nptmass = 1 n = nptmass xyzmh_ptmass(:,n) = 0. ! zero all quantities by default xyzmh_ptmass(4,n) = mcore xyzmh_ptmass(ihsoft,n) = hsoft + xyzmh_ptmass(ilum,n) = lcore vxyz_ptmass(:,n) = 0. end subroutine set_stellar_core diff --git a/src/setup/set_unifdis.f90 b/src/setup/set_unifdis.f90 index c7ff9e663..b4dece1de 100644 --- a/src/setup/set_unifdis.f90 +++ b/src/setup/set_unifdis.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module unifdis ! diff --git a/src/setup/set_units.f90 b/src/setup/set_units.f90 index 41f600e51..5c6de9e7e 100644 --- a/src/setup/set_units.f90 +++ b/src/setup/set_units.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setunits ! diff --git a/src/setup/set_vfield.f90 b/src/setup/set_vfield.f90 index 17e56305c..68d2d03e3 100644 --- a/src/setup/set_vfield.f90 +++ b/src/setup/set_vfield.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setvfield ! diff --git a/src/setup/setup_BHL.f90 b/src/setup/setup_BHL.f90 index b8c4b0aff..560081f1b 100644 --- a/src/setup/setup_BHL.f90 +++ b/src/setup/setup_BHL.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_alfvenwave.f90 b/src/setup/setup_alfvenwave.f90 index e53eaf40f..8bc9e10f9 100644 --- a/src/setup/setup_alfvenwave.f90 +++ b/src/setup/setup_alfvenwave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_asteroidwind.f90 b/src/setup/setup_asteroidwind.f90 index e8445fdcd..8ccc75fb8 100644 --- a/src/setup/setup_asteroidwind.f90 +++ b/src/setup/setup_asteroidwind.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_blob.f90 b/src/setup/setup_blob.f90 index 7e52dcc6e..d569cfb5b 100644 --- a/src/setup/setup_blob.f90 +++ b/src/setup/setup_blob.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_bondiinject.f90 b/src/setup/setup_bondiinject.f90 index 7089b359c..cd39849b1 100644 --- a/src/setup/setup_bondiinject.f90 +++ b/src/setup/setup_bondiinject.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_chinchen.f90 b/src/setup/setup_chinchen.f90 index e5cd24024..708700567 100644 --- a/src/setup/setup_chinchen.f90 +++ b/src/setup/setup_chinchen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_cluster.f90 b/src/setup/setup_cluster.f90 index ea18bc5c3..cd3e60944 100644 --- a/src/setup/setup_cluster.f90 +++ b/src/setup/setup_cluster.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_collidingclouds.f90 b/src/setup/setup_collidingclouds.f90 index 03ded6bea..ff9553b42 100644 --- a/src/setup/setup_collidingclouds.f90 +++ b/src/setup/setup_collidingclouds.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -50,7 +50,6 @@ module setup real :: cs_cloud(Ncloud_max) real :: rms_mach(Ncloud_max),density_contrast,T_bkg,plasmaB,Bzero,angB(3) real :: r_crit_setup,h_acc_setup,h_soft_sinksink_setup,rho_crit_cgs_setup - real(kind=8) :: udist,umass logical :: input_plasmaB character(len= 1), parameter :: labelx(4) = (/'x','y','z','r'/) @@ -70,7 +69,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound use boundary_dyn, only:width_bkg,rho_thresh_bdy,rho_bkg_ini,dxyz,vbdyx,vbdyy,vbdyz,in_domain,irho_bkg_ini use prompting, only:prompt - use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity + use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity,umass,udist use eos, only:polyk2,gmw use part, only:Bxyz,Bextx,Bexty,Bextz,igas,idust,set_particle_type,periodic use timestep, only:dtmax,tmax @@ -81,7 +80,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use mpidomain, only:i_belong use ptmass, only:icreate_sinks,r_crit,h_acc,h_soft_sinksink,rho_crit_cgs use cooling, only:Tfloor - use setunits, only:dist_unit,mass_unit + use setunits, only:dist_unit,mass_unit,set_units_interactive integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -109,7 +108,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, logical :: iexist,in_cloud,make_sinks logical :: moving_bkg = .true. ! For each component, will set the background velocity to that of the clouds, if the clouds are the same character(len=120) :: filex,filey,filez - character(len=100) :: filename,cwd + character(len=100) :: filename character(len= 40) :: fmt,lattice character(len= 10) :: h_acc_char ! @@ -129,19 +128,12 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, input_plasmaB = .false. make_sinks = .true. dynamic_bdy = .true. + dist_unit = 'pc' + mass_unit = 'solarm' - call getcwd(cwd) - print*, index(cwd,'gpfs1/scratch/astro/jhw5') - if (index(cwd,'gpfs1/scratch/astro/jhw5') > 0 .or. index(cwd,'data/dp187/dc-wurs1') > 0 ) then - ! Kennedy or Dial - filex = find_phantom_datafile(filevx,'velfield_sphng') - filey = find_phantom_datafile(filevy,'velfield_sphng') - filez = find_phantom_datafile(filevz,'velfield_sphng') - else - filex = find_phantom_datafile(filevx,'velfield') - filey = find_phantom_datafile(filevy,'velfield') - filez = find_phantom_datafile(filevz,'velfield') - endif + filex = find_phantom_datafile(filevx,'velfield') + filey = find_phantom_datafile(filevy,'velfield') + filez = find_phantom_datafile(filevz,'velfield') ! !--Read setup file, else prep prompt user for inputs ! @@ -156,36 +148,19 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, if (id==master) call write_setupfile(filename) stop endif - do i = 1,Ncloud - v2max = max(v2max,v_cloud(1,i)**2 + v_cloud(2,i)**2 +v_cloud(3,i)**2) - enddo elseif (id==master) then print "(a,/)",trim(filename)//' not found: using interactive setup' - dist_unit = 'pc' - mass_unit = 'solarm' - ierr = 1 - do while (ierr /= 0) - call prompt('Enter mass unit (e.g. solarm,jupiterm,earthm)',mass_unit) - call select_unit(mass_unit,umass,ierr) - if (ierr /= 0) print "(a)",' ERROR: mass unit not recognised' - enddo - ierr = 1 - do while (ierr /= 0) - call prompt('Enter distance unit (e.g. au,pc,kpc,0.1pc)',dist_unit) - call select_unit(dist_unit,udist,ierr) - if (ierr /= 0) print "(a)",' ERROR: length unit not recognised' - enddo ! ! units ! - call set_units(dist=udist,mass=umass,G=1.d0) + call set_units_interactive() ! ! prompt user for settings ! Ncloud = 2 npmax = int(2.0/3.0*size(xyzh(1,:)))/(2*Ncloud) ! approx max number allowed in sphere given size(xyzh(1,:)) np = npmax - np = 30000 + np = 10000 v_cloud = 0.0 ! velocity in km/s r_cloud(1,:) = 50.0 ! semi-major-axis (x) in pc r_cloud(2,:) = 12.5 ! semi-minor-axis (y) in pc @@ -343,6 +318,9 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ! !--general parameters of the cloud ! + do i = 1,Ncloud + v2max = max(v2max,v_cloud(1,i)**2 + v_cloud(2,i)**2 +v_cloud(3,i)**2) + enddo v_cloud = v_cloud/(unit_velocity*1.d-5) ! from km/s -> code units v2max = v2max /(unit_velocity*1.d-5)**2 ! from km/s -> code units vol_cloud = 4./3.*pi*r_cloud(1,:)*r_cloud(2,:)*r_cloud(3,:) diff --git a/src/setup/setup_common.f90 b/src/setup/setup_common.f90 index e12fe98f4..9a51767e0 100644 --- a/src/setup/setup_common.f90 +++ b/src/setup/setup_common.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 423594c6d..590f8a2b4 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -420,7 +420,7 @@ subroutine set_default_options()!id) !--gas disc R_in = 1. R_out = 150. - R_ref = 1. + R_ref = 10. R_c = 150. R_warp = 0. H_warp = 0. @@ -2211,7 +2211,7 @@ subroutine setup_interactive(id) !--gas disc R_in = accr1 - R_ref = R_in + R_ref = min(10.*R_in,R_out) R_c = R_out disc_mfac = 1. if (ndiscs > 1) qindex = 0. diff --git a/src/setup/setup_dustsettle.f90 b/src/setup/setup_dustsettle.f90 index d0eea0842..5a58e68c5 100644 --- a/src/setup/setup_dustsettle.f90 +++ b/src/setup/setup_dustsettle.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_dustybox.f90 b/src/setup/setup_dustybox.f90 index 28ddbfcc3..00d9bae08 100644 --- a/src/setup/setup_dustybox.f90 +++ b/src/setup/setup_dustybox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_dustysedov.f90 b/src/setup/setup_dustysedov.f90 index 39985f0f2..918becd15 100644 --- a/src/setup/setup_dustysedov.f90 +++ b/src/setup/setup_dustysedov.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_empty.f90 b/src/setup/setup_empty.f90 index 5e93904fa..22c3a0893 100644 --- a/src/setup/setup_empty.f90 +++ b/src/setup/setup_empty.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_firehose.f90 b/src/setup/setup_firehose.f90 index f77c04039..c6256bcf0 100644 --- a/src/setup/setup_firehose.f90 +++ b/src/setup/setup_firehose.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_galaxies.f90 b/src/setup/setup_galaxies.f90 index 3a1986f79..ea8d68924 100644 --- a/src/setup/setup_galaxies.f90 +++ b/src/setup/setup_galaxies.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_galcen_stars.f90 b/src/setup/setup_galcen_stars.f90 index c76dc906e..b7d08a395 100644 --- a/src/setup/setup_galcen_stars.f90 +++ b/src/setup/setup_galcen_stars.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_galdisc.f90 b/src/setup/setup_galdisc.f90 index d0e62c0f4..e6dbcd55b 100644 --- a/src/setup/setup_galdisc.f90 +++ b/src/setup/setup_galdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -14,7 +14,7 @@ module setup ! ! :Runtime parameters: None ! -! :Dependencies: datafiles, dim, extern_spiral, externalforces, io, +! :Dependencies: datafiles, dim, extern_spiral, externalforces, io, kernel, ! mpiutils, options, part, physcon, prompting, random, set_dust, ! setup_params, units ! @@ -62,6 +62,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use io, only:fatal use prompting, only:prompt use set_dust, only:set_dustfrac + use kernel, only:hfact_default integer, intent(in) :: id integer, intent(out) :: npart integer, intent(out) :: npartoftype(:) @@ -100,7 +101,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--initialising units and flags ! ! set code units - call set_units(dist=100.*pc,mass=1.d05*solarm,G=1.) + call set_units(dist=100.*pc,mass=1.d5*solarm,G=1.d0) ! !--set input file options !--maxvxyzu(3-4) and therefore ieos(1-2) are set in dim_galdisc @@ -108,7 +109,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, icooling = 0 !1=cooling on, 0=off nfulldump = 1 - hfact = 1.2 + hfact = hfact_default ! !-------------------------Setting-energies------------------------- @@ -403,7 +404,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, print "(a,i10)",' random seed = ',iseed print "(3(a,f10.3),a)",' galactic disc setup... rmin = ',rcylin,' rmax = ',rcyl,' in units of ',udist/kpc,' kpc' xi = ran2(iseed) - npart = maxp + npart = min(maxp,500000) call prompt('Enter number of particles ',npart,1,maxp) call bcast_mpi(npart) if (npart > maxp) call fatal('setup','npart > maxp; use ./phantomsetup --maxp=10000000') @@ -576,7 +577,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, enddo endif - return end subroutine setpart !/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ diff --git a/src/setup/setup_grdisc.F90 b/src/setup/setup_grdisc.F90 index dbd5baae0..e6fa50dc4 100644 --- a/src/setup/setup_grdisc.F90 +++ b/src/setup/setup_grdisc.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_grtde.f90 b/src/setup/setup_grtde.f90 index bf8a674bd..a6d04d9ef 100644 --- a/src/setup/setup_grtde.f90 +++ b/src/setup/setup_grtde.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_gwdisc.f90 b/src/setup/setup_gwdisc.f90 index a44065c5b..6f74be36a 100644 --- a/src/setup/setup_gwdisc.f90 +++ b/src/setup/setup_gwdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_hierarchical.f90 b/src/setup/setup_hierarchical.f90 index a8d9f1178..cad18867d 100644 --- a/src/setup/setup_hierarchical.f90 +++ b/src/setup/setup_hierarchical.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_jadvect.f90 b/src/setup/setup_jadvect.f90 index 276198ad1..15b8fc00e 100644 --- a/src/setup/setup_jadvect.f90 +++ b/src/setup/setup_jadvect.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_kh.f90 b/src/setup/setup_kh.f90 index 51a39488e..5e847d5f8 100644 --- a/src/setup/setup_kh.f90 +++ b/src/setup/setup_kh.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdblast.f90 b/src/setup/setup_mhdblast.f90 index abae51c2d..12189204f 100644 --- a/src/setup/setup_mhdblast.f90 +++ b/src/setup/setup_mhdblast.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdrotor.f90 b/src/setup/setup_mhdrotor.f90 index d746a5556..25f1d5402 100644 --- a/src/setup/setup_mhdrotor.f90 +++ b/src/setup/setup_mhdrotor.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdsine.f90 b/src/setup/setup_mhdsine.f90 index a5bfcf7d4..0c1fa5b0a 100644 --- a/src/setup/setup_mhdsine.f90 +++ b/src/setup/setup_mhdsine.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdvortex.f90 b/src/setup/setup_mhdvortex.f90 index 4814ff8db..8ea65ad98 100644 --- a/src/setup/setup_mhdvortex.f90 +++ b/src/setup/setup_mhdvortex.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_mhdwave.f90 b/src/setup/setup_mhdwave.f90 index fab049d64..db858458b 100644 --- a/src/setup/setup_mhdwave.f90 +++ b/src/setup/setup_mhdwave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_nsdisc.f90 b/src/setup/setup_nsdisc.f90 index fdbbc576f..bb9577f02 100644 --- a/src/setup/setup_nsdisc.f90 +++ b/src/setup/setup_nsdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -52,7 +52,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, udist_km = 1.e5/udist ! code units are cm gamma = 1.0 - npart = size(xyzh(1,:)) + npart = 1e5 npartoftype(1) = npart hfact = 1.2 time = 0. diff --git a/src/setup/setup_orstang.f90 b/src/setup/setup_orstang.f90 index b8453a703..04645cf0b 100644 --- a/src/setup/setup_orstang.f90 +++ b/src/setup/setup_orstang.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_params.f90 b/src/setup/setup_params.f90 index cbacb8066..9be2eadb7 100644 --- a/src/setup/setup_params.f90 +++ b/src/setup/setup_params.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup_params ! diff --git a/src/setup/setup_planetdisc.f90 b/src/setup/setup_planetdisc.f90 index c606ebc72..8e8ecb444 100644 --- a/src/setup/setup_planetdisc.f90 +++ b/src/setup/setup_planetdisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_prtest.f90 b/src/setup/setup_prtest.f90 index 8988df726..4ad6b335a 100644 --- a/src/setup/setup_prtest.f90 +++ b/src/setup/setup_prtest.f90 @@ -2,20 +2,20 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! -! this module does setup +! test of Poynting-Robertson drag, as per Figure 18 of Price et al. (2018) ! -! :References: None +! :References: Price et al. (2018), PASA 35, e031 ! ! :Owner: Daniel Price ! ! :Runtime parameters: None ! -! :Dependencies: externalforces, io, options, physcon, setup_params, -! spherical, units +! :Dependencies: externalforces, io, kernel, options, physcon, +! setup_params, spherical, units ! implicit none public :: setpart @@ -36,8 +36,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use externalforces,only:mass1,iext_prdrag use spherical, only:set_sphere use units, only:set_units - use physcon, only:km - real, parameter :: pi = 3.1415926536 + use physcon, only:km,pi + use kernel, only:hfact_default integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -48,23 +48,22 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, character(len=20), intent(in) :: fileprefix real, intent(out) :: vxyzu(:,:) real :: totmass,totvol,psep,rmax,rmin,xyz_orig(3) - real :: r, vphi, phi + real :: r,vphi,phi integer :: i,np,nx,maxvxyzu - call set_units(dist=10.*km,c=1.) + call set_units(dist=10.*km,c=1.d0) ! !--general parameters ! time = 0. - hfact = 1.2 + hfact = hfact_default gamma = 1. rmin = 0. rmax = 0.05 - ! !--setup particles ! - np = 100 !size(xyzh(1,:)) + np = 100 maxvxyzu = size(vxyzu(:,1)) totvol = 4./3.*pi*rmax**3 nx = int(np**(1./3.)) @@ -76,7 +75,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, npart = 0 npart_total = 0 - xyz_orig(:) = (/0.,100.,0./) + xyz_orig(:) = (/0.,200.,0./) call set_sphere('closepacked',id,master,rmin,rmax,psep,hfact,npart,xyzh, & nptot=npart_total,xyz_origin=xyz_orig) @@ -108,7 +107,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call warning('setup_prtest','maxvxyzu should not be 4, so set temp=0 for you') endif enddo - ! ! --- set input defaults for nonviscous particles in prdrag ! @@ -117,8 +115,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, alpha=0. beta=0. - end subroutine setpart end module setup - diff --git a/src/setup/setup_quebec.f90 b/src/setup/setup_quebec.f90 index c3d852cbd..0ce9bde95 100644 --- a/src/setup/setup_quebec.f90 +++ b/src/setup/setup_quebec.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_radiativebox.f90 b/src/setup/setup_radiativebox.f90 index 6a6e40df2..b30ea361b 100644 --- a/src/setup/setup_radiativebox.f90 +++ b/src/setup/setup_radiativebox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_sedov.f90 b/src/setup/setup_sedov.f90 index 2532e070e..49884983f 100644 --- a/src/setup/setup_sedov.f90 +++ b/src/setup/setup_sedov.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_solarsystem.f90 b/src/setup/setup_solarsystem.f90 index f10f8a090..5b06d37af 100644 --- a/src/setup/setup_solarsystem.f90 +++ b/src/setup/setup_solarsystem.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_sphereinbox.f90 b/src/setup/setup_sphereinbox.f90 index 00d27d28c..98a4a9156 100644 --- a/src/setup/setup_sphereinbox.f90 +++ b/src/setup/setup_sphereinbox.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -658,7 +658,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_ if (.not. iexist) then ! default values tmax = 1.21*t_ff ! = 10.75 for default settings (Wurster, Price & Bate 2016) - ieos = 8 + if (maxvxyzu < 4) ieos = 8 nfulldump = 1 calc_erot = .true. icreate_sinks = icreate_sinks_setup diff --git a/src/setup/setup_srblast.f90 b/src/setup/setup_srblast.f90 index 03aa4c39c..79e38118b 100644 --- a/src/setup/setup_srblast.f90 +++ b/src/setup/setup_srblast.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_srpolytrope.f90 b/src/setup/setup_srpolytrope.f90 index 4e22d9180..f387060b3 100644 --- a/src/setup/setup_srpolytrope.f90 +++ b/src/setup/setup_srpolytrope.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_star.f90 b/src/setup/setup_star.f90 index a18aeb5ac..e6fa4a8eb 100644 --- a/src/setup/setup_star.f90 +++ b/src/setup/setup_star.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_taylorgreen.f90 b/src/setup/setup_taylorgreen.f90 index 3a9743f84..32f7ae24d 100644 --- a/src/setup/setup_taylorgreen.f90 +++ b/src/setup/setup_taylorgreen.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_testparticles.f90 b/src/setup/setup_testparticles.f90 index 93a914925..edbd8ab47 100644 --- a/src/setup/setup_testparticles.f90 +++ b/src/setup/setup_testparticles.f90 @@ -2,11 +2,11 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! -! None +! setup for test particles ! ! :References: None ! @@ -41,12 +41,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use options, only:iexternalforce,alpha,alphamax,alphau,beta,nfulldump use units, only:set_units use physcon, only:solarm -#ifdef GR - use externalforces, only:iext_gr - use metric, only:a -#else use externalforces, only:iext_star -#endif + use metric, only:a use eos, only:ieos use physcon, only:pi use prompting, only:prompt @@ -70,7 +66,11 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ! general parameters ! time = 0. - gamma = 1. + if (gr) then + gamma = 5./3. ! GR cannot have gamma=1 + else + gamma = 1. + endif polyk = 0. npart = 10 ieos = 11 @@ -192,12 +192,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, vxyzu(1:3,i) = rtan*vcirc enddo -#ifdef GR - iexternalforce = iext_gr - a = spin -#else - iexternalforce = iext_star -#endif + a = spin + if (.not.gr) iexternalforce = iext_star end subroutine setpart diff --git a/src/setup/setup_tokamak.f90 b/src/setup/setup_tokamak.f90 index a095fa798..6fe6d3ebb 100644 --- a/src/setup/setup_tokamak.f90 +++ b/src/setup/setup_tokamak.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_torus.f90 b/src/setup/setup_torus.f90 index 3393e2b91..ed8b9470f 100644 --- a/src/setup/setup_torus.f90 +++ b/src/setup/setup_torus.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_turb.f90 b/src/setup/setup_turb.f90 index 5b02c8734..6910265f4 100644 --- a/src/setup/setup_turb.f90 +++ b/src/setup/setup_turb.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/setup_unifdis.f90 b/src/setup/setup_unifdis.f90 index 9a43b16a9..45b2c1abe 100644 --- a/src/setup/setup_unifdis.f90 +++ b/src/setup/setup_unifdis.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -27,8 +27,8 @@ module setup ! - zmin : *zmin boundary* ! ! :Dependencies: boundary, cooling, cooling_ism, dim, eos, infile_utils, -! io, mpidomain, options, part, physcon, prompting, set_dust, setunits, -! setup_params, timestep, unifdis, units +! io, mpidomain, options, part, physcon, prompting, radiation_utils, +! set_dust, setunits, setup_params, timestep, unifdis, units ! use dim, only:use_dust,mhd,gr use options, only:use_dustfrac @@ -55,12 +55,13 @@ module setup !+ !---------------------------------------------------------------- subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) - use dim, only:maxvxyzu,h2chemistry + use dim, only:maxvxyzu,h2chemistry,use_dustgrowth,do_radiation use setup_params, only:npart_total,ihavesetupB use io, only:master use unifdis, only:set_unifdis,latticetype,get_xyzmin_xyzmax_exact use boundary, only:xmin,ymin,zmin,xmax,ymax,zmax,dxbound,dybound,dzbound,set_boundary - use part, only:Bxyz,periodic,abundance,igas,iHI,dustfrac,ndustsmall,ndusttypes,grainsize,graindens + use part, only:Bxyz,periodic,abundance,igas,iHI,dustfrac,ndustsmall,& + ndusttypes,grainsize,graindens,dustprop,rad use physcon, only:pi,mass_proton_cgs,kboltz,years,pc,solarm,micron use set_dust, only:set_dustfrac use setunits, only:dist_unit,mass_unit @@ -71,6 +72,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use timestep, only:dtmax,tmax,C_cour,C_force,C_cool,tolv use cooling, only:Tfloor use cooling_ism, only:abundc,abundo,abundsi,abunde,dust_to_gas_ratio,iphoto + use radiation_utils, only:set_radiation_and_gas_temperature_equal integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -226,6 +228,13 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, enddo endif + if (use_dustgrowth) then + do i=1,npart + dustprop(1,i) = grainsize(1) + dustprop(2,i) = graindens(1) + enddo + endif + if (h2chemistry) then do i=1,npart abundance(:,i) = 0. @@ -241,6 +250,10 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ihavesetupB = .true. endif + if (do_radiation) then + call set_radiation_and_gas_temperature_equal(npart,xyzh,vxyzu,massoftype,rad) + endif + end subroutine setpart !------------------------------------------------------------------------ @@ -292,9 +305,9 @@ subroutine setup_interactive() end subroutine setup_interactive !------------------------------------------------------------------------ -! -! write setup file -! +!+ +! write setup file +!+ !------------------------------------------------------------------------ subroutine write_setupfile(filename) use infile_utils, only:write_inopt @@ -336,9 +349,9 @@ subroutine write_setupfile(filename) end subroutine write_setupfile !------------------------------------------------------------------------ -! -! read setup file -! +!+ +! read setup file +!+ !------------------------------------------------------------------------ subroutine read_setupfile(filename,ierr) use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db diff --git a/src/setup/setup_wave.f90 b/src/setup/setup_wave.f90 index 3ff919caf..3a0816ee0 100644 --- a/src/setup/setup_wave.f90 +++ b/src/setup/setup_wave.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! @@ -35,7 +35,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use unifdis, only:set_unifdis,rho_func use boundary, only:set_boundary,xmin,ymin,zmin,xmax,ymax,zmax,dxbound,dybound,dzbound use mpiutils, only:bcast_mpi - use part, only:labeltype,set_particle_type,igas,idust,dustfrac,periodic + use part, only:labeltype,set_particle_type,igas,idust,dustfrac,periodic,ndustsmall,ndustlarge,ndusttypes use physcon, only:pi use kernel, only:radkern use dim, only:maxvxyzu,use_dust,maxp @@ -73,6 +73,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, cs = 1. ampl = 1.d-4 use_dustfrac = .false. + ndustsmall = 0 + ndustlarge = 0 if (id==master) then itype = 1 print "(/,a,/)",' >>> Setting up particles for linear wave test <<<' @@ -92,11 +94,16 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call prompt('Enter constant drag coefficient',K_code(1),0.) if (use_dustfrac) then massfac = 1. + dtg + ndustsmall = 1 else ntypes = 2 + ndustlarge = 1 endif endif endif + call bcast_mpi(ndustsmall) + call bcast_mpi(ndustlarge) + ndusttypes = ndustsmall + ndustlarge call bcast_mpi(npartx) ! ! boundaries diff --git a/src/setup/setup_wavedamp.f90 b/src/setup/setup_wavedamp.f90 index d31770e24..8b6901518 100644 --- a/src/setup/setup_wavedamp.f90 +++ b/src/setup/setup_wavedamp.f90 @@ -2,14 +2,16 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! ! This module initialises the wave damping test, as per ! Choi et al. 2009 (has been generalised for additional studies) ! -! :References: None +! :References: +! Wurster, Price & Ayliffe (2014), MNRAS 444, 1104 (Section 4.1) +! Wurster, Price & Bate (2016), MNRAS 457, 1037 ! ! :Owner: Daniel Price ! @@ -25,7 +27,7 @@ module setup ! - nx : *Particles in the x-direction* ! - ohmtest : *Testing Ohmic resistivity* ! - polyk : *Initial polyk* -! - realvals : *Using physical values (F: arbitrary values)* +! - realvals : *Using physical units (F: arbitrary units)* ! - rect : *Using rectangular cp grid (F: cubic cp grid)* ! - rhoin : *Initial density* ! - viscoff : *Using no viscosity (F: using viscosity* @@ -35,21 +37,20 @@ module setup ! nicil, options, part, physcon, prompting, setup_params, timestep, ! unifdis, units ! - use part, only:mhd - use nicil, only:use_ohm,use_hall,use_ambi - use nicil, only:eta_constant,eta_const_type,C_OR,C_HE,C_AD,icnstphys,icnstsemi,icnst - use nicil, only:n_e_cnst,rho_i_cnst,rho_n_cnst,gamma_AD,alpha_AD,hall_lt_zero - ! + use part, only:mhd + use nicil, only:use_ohm,use_hall,use_ambi + use nicil, only:eta_constant,eta_const_type,C_OR,C_HE,C_AD,icnstphys,icnstsemi,icnst + use nicil, only:n_e_cnst,rho_i_cnst,rho_n_cnst,gamma_AD,alpha_AD,hall_lt_zero implicit none integer, private :: nx real, private :: kwave,amplitude,polykin,rhoin0,Bxin0 logical, private :: realvals,geo_cp,rect logical, private :: isowave,kx_kxy,vx_vz,viscoff,ambitest,halltest,ohmtest - ! + public :: setpart - ! + private - ! + contains !---------------------------------------------------------------- !+ @@ -114,9 +115,10 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--Prompt the user for relevant input to create .setup if file does not already exist ! setupname=trim(fileprefix)//'.setup' - print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)", ' Wave-damping test.' + print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)", ' Wave damping test.' inquire(file=setupname,exist=jexist) if (jexist) call read_setupfile(setupname,ierr) + if ( (ierr /= 0 .or. .not.iexist .or. .not.jexist) .and. id==master) then ! Set defaults realvals = .false. @@ -360,7 +362,12 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, write(*,*) "setup: total volume = ",dxbound*dybound*dzbound end subroutine setpart -!----------------------------------------------------------------------- + +!------------------------------------------------------------------------ +!+ +! write options to .setup file +!+ +!------------------------------------------------------------------------ subroutine write_setupfile(filename) use infile_utils, only: write_inopt character(len=*), intent(in) :: filename @@ -368,13 +375,15 @@ subroutine write_setupfile(filename) print "(a)",' writing setup options file '//trim(filename) open(unit=iunit,file=filename,status='replace',form='formatted') - write(iunit,"(a)") '# input file for wave-dampening setup routines' + write(iunit,"(a)") '# input file for wave damping setup routines' + write(iunit,"(/,a)") '# units and orientation' - call write_inopt(realvals,'realvals','Using physical values (F: arbitrary values)',iunit) + call write_inopt(realvals,'realvals','Using physical units (F: arbitrary units)',iunit) if (mhd) call write_inopt(isowave,'isowave','Modelling a sound wave (F: Alfven wave)',iunit) call write_inopt(kx_kxy,'kx_kxy','Using wavenumber in x only (F: initialise in x,y)',iunit) call write_inopt(vx_vz,'vx_vz','Using velocity in x (F: initialise in z)',iunit) call write_inopt(viscoff,'viscoff','Using no viscosity (F: using viscosity',iunit) + write(iunit,"(/,a)") '# Grid setup' call write_inopt(geo_cp,'geo_cp','Using close-packed grid (F: cubic).',iunit) if (geo_cp) call write_inopt(rect,'rect','Using rectangular cp grid (F: cubic cp grid)',iunit) @@ -384,6 +393,7 @@ subroutine write_setupfile(filename) if (mhd .and. .not. isowave) call write_inopt(Bxin0,'Bxin','Initial x-magnetic field',iunit) call write_inopt(amplitude,'amplitude','Initial wave amplitude',iunit) call write_inopt(kwave,'kwave','Wavenumber (k/pi)',iunit) + write(iunit,"(/,a)") '# Test problem and values' if (mhd) then call write_inopt(ambitest,'ambitest','Testing ambipolar diffusion',iunit) @@ -393,7 +403,12 @@ subroutine write_setupfile(filename) close(iunit) end subroutine write_setupfile -!----------------------------------------------------------------------- + +!------------------------------------------------------------------------ +!+ +! read options from .setup file +!+ +!------------------------------------------------------------------------ subroutine read_setupfile(filename,ierr) use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db character(len=*), intent(in) :: filename @@ -424,7 +439,6 @@ subroutine read_setupfile(filename,ierr) call read_inopt(ohmtest, 'ohmtest', db,ierr) if (ohmtest) use_ohm = .true. endif - call close_db(db) end subroutine read_setupfile diff --git a/src/setup/setup_wddisc.f90 b/src/setup/setup_wddisc.f90 index 8077ec24b..39d9101a1 100644 --- a/src/setup/setup_wddisc.f90 +++ b/src/setup/setup_wddisc.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module setup ! diff --git a/src/setup/stretchmap.f90 b/src/setup/stretchmap.f90 index b2ea9a42f..cea129eca 100644 --- a/src/setup/stretchmap.f90 +++ b/src/setup/stretchmap.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module stretchmap ! diff --git a/src/setup/velfield_fromcubes.f90 b/src/setup/velfield_fromcubes.f90 index d16396d9f..9145c4c04 100644 --- a/src/setup/velfield_fromcubes.f90 +++ b/src/setup/velfield_fromcubes.f90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module velfield ! From 2fcb4f666815f4b13f3d05bba8f5d3268e370fd4 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 1 May 2024 20:50:22 +0100 Subject: [PATCH 108/182] partial update to main repo --- src/main/checkconserved.f90 | 41 +- src/main/checksetup.f90 | 31 +- src/main/config.F90 | 1 - src/main/cons2prim.f90 | 4 +- src/main/{cooling.F90 => cooling.f90} | 0 src/main/cooling_koyamainutsuka.f90 | 2 + src/main/cooling_molecular.f90 | 12 +- src/main/dtype_kdtree.F90 | 2 + src/main/dust_formation.f90 | 2 +- src/main/energies.F90 | 15 +- src/main/eos.f90 | 1560 +++++++++++++++++++++++++ src/main/tmunu2grid.f90 | 190 +-- src/main/utils_dumpfiles.f90 | 279 +++-- src/main/utils_filenames.f90 | 2 +- src/main/utils_omp.F90 | 14 +- 15 files changed, 1846 insertions(+), 309 deletions(-) rename src/main/{cooling.F90 => cooling.f90} (100%) create mode 100644 src/main/eos.f90 diff --git a/src/main/checkconserved.f90 b/src/main/checkconserved.f90 index e47e96955..a5538d537 100644 --- a/src/main/checkconserved.f90 +++ b/src/main/checkconserved.f90 @@ -95,7 +95,6 @@ subroutine check_conservation_error(val,ref,tol,label,decrease) character(len=*), intent(in) :: label logical, intent(in), optional :: decrease real :: err - character(len=20) :: string if (abs(ref) > 1.e-3) then err = (val - ref)/abs(ref) @@ -113,12 +112,7 @@ subroutine check_conservation_error(val,ref,tol,label,decrease) call error('evolve',trim(label)//' is not being conserved due to corotating frame',var='err',val=err) else call error('evolve','Large error in '//trim(label)//' conservation ',var='err',val=err) - call get_environment_variable('I_WILL_NOT_PUBLISH_CRAP',string) - if (.not. (trim(string)=='yes')) then - print "(2(/,a))",' You can ignore this error and continue by setting the ',& - ' environment variable I_WILL_NOT_PUBLISH_CRAP=yes to continue' - call fatal('evolve',' Conservation errors too large to continue simulation') - endif + call do_not_publish_crap('evolve','Conservation errors too large to continue simulation') endif else if (iverbose >= 2) print "(a,es10.3)",trim(label)//' error is ',err @@ -133,24 +127,31 @@ end subroutine check_conservation_error ! so is related to the checks performed here !+ !---------------------------------------------------------------- -subroutine check_magnetic_stability(hdivBB_xa) - use options, only:hdivbbmax_max +subroutine check_magnetic_stability(hdivBonB_ave,hdivBonB_max) use io, only:fatal - real, intent(in) :: hdivBB_xa(:) + real, intent(in) :: hdivBonB_ave,hdivBonB_max - if (hdivbbmax_max < 1.1) then - ! In this regime, we assume the user has not modified this value, - ! either by choice or by being unaware of this. This warning will - ! appear in this case. - if (hdivBB_xa(1) > 100 .or. hdivBB_xa(2) > 0.1) then - ! Tricco, Price & Bate (2016) suggest the average should remain lower than 0.01, - ! but we will increase it here due to the nature of the exiting the code - ! The suggestion of 512 was empirically determined in Dobbs & Wurster (2021) - call fatal('evolve','h|divb|/b is too large; recommend hdivbbmax_max = 512; set >1.2 to suppress this message.') - endif + if (hdivBonB_max > 100 .or. hdivBonB_ave > 0.1) then + ! Tricco, Price & Bate (2016) suggest the average should remain lower than 0.01, + ! but we will increase it here due to the nature of the exiting the code + ! The suggestion of 512 was empirically determined in Dobbs & Wurster (2021) + call do_not_publish_crap('evolve','h|divb|/b is too large; recommend to increase the overcleanfac') endif end subroutine check_magnetic_stability +subroutine do_not_publish_crap(subr,msg) + use io, only:fatal + character(len=*), intent(in) :: subr,msg + character(len=20) :: string + + call get_environment_variable('I_WILL_NOT_PUBLISH_CRAP',string) + if (.not. (trim(string)=='yes')) then + print "(2(/,a))",' You can ignore this error and continue by setting the ',& + ' environment variable I_WILL_NOT_PUBLISH_CRAP=yes to continue' + call fatal(subr,msg) + endif + +end subroutine do_not_publish_crap !---------------------------------------------------------------- end module checkconserved diff --git a/src/main/checksetup.f90 b/src/main/checksetup.f90 index a14201b96..39ac95b9b 100644 --- a/src/main/checksetup.f90 +++ b/src/main/checksetup.f90 @@ -16,7 +16,7 @@ module checksetup ! ! :Dependencies: boundary, boundary_dyn, centreofmass, dim, dust, eos, ! externalforces, io, metric_tools, nicil, options, part, physcon, -! ptmass_radiation, sortutils, timestep, units, utils_gr +! ptmass, ptmass_radiation, sortutils, timestep, units, utils_gr ! implicit none public :: check_setup @@ -429,6 +429,10 @@ subroutine check_setup(nerror,nwarn,restart) !--check centre of mass ! call get_centreofmass(xcom,vcom,npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass) +! +!--check Forward symplectic integration method imcompatiblity +! + call check_vdep_extf (nwarn,iexternalforce) if (.not.h2chemistry .and. maxvxyzu >= 4 .and. icooling == 3 .and. iexternalforce/=iext_corotate .and. nptmass==0) then if (dot_product(xcom,xcom) > 1.e-2) then @@ -522,11 +526,15 @@ subroutine check_setup_ptmass(nerror,nwarn,hmin) use part, only:nptmass,xyzmh_ptmass,ihacc,ihsoft,gr,iTeff,sinks_have_luminosity,& ilum,iJ2,ispinx,ispinz,iReff use ptmass_radiation, only:isink_radiation + use ptmass, only:use_fourthorder integer, intent(inout) :: nerror,nwarn real, intent(in) :: hmin integer :: i,j,n real :: dx(3) real :: r,hsink,hsoft,J2 + logical :: isoblate + + isoblate = .false. if (gr .and. nptmass > 0) then print*,' ERROR: nptmass = ',nptmass, ' should be = 0 for GR' @@ -615,6 +623,7 @@ subroutine check_setup_ptmass(nerror,nwarn,hmin) ! in order to specify the rotation direction ! if (J2 > 0.) then + isoblate = .true. if (dot_product(xyzmh_ptmass(ispinx:ispinz,i),xyzmh_ptmass(ispinx:ispinz,i)) < tiny(0.)) then nerror = nerror + 1 print*,'ERROR! non-zero J2 requires non-zero spin on sink particle ',i @@ -625,6 +634,13 @@ subroutine check_setup_ptmass(nerror,nwarn,hmin) endif endif enddo + + if (isoblate .and. use_fourthorder) then + nwarn = nwarn + 1 + print*, 'WARNING: Substepping integration switched back to leapfrog due to oblateness' + use_fourthorder = .false. + endif + ! ! check that radiation properties are sensible ! @@ -999,4 +1015,17 @@ subroutine check_setup_radiation(npart,nerror,nwarn,radprop,rad) end subroutine check_setup_radiation +subroutine check_vdep_extf(nwarn,iexternalforce) + use externalforces, only: is_velocity_dependent + use ptmass, only : use_fourthorder + integer, intent(inout) :: nwarn + integer, intent(in) :: iexternalforce + if (is_velocity_dependent(iexternalforce) .and. use_fourthorder) then + print "(/,a,/)","Warning: velocity dependant external forces are not compatible with FSI switch back to Leapfrog..." + nwarn = nwarn + 1 + use_fourthorder = .false. + endif + +end subroutine check_vdep_extf + end module checksetup diff --git a/src/main/config.F90 b/src/main/config.F90 index 069005dd4..5acb64234 100644 --- a/src/main/config.F90 +++ b/src/main/config.F90 @@ -121,7 +121,6 @@ module dim #else logical, parameter :: do_radiation = .false. #endif - ! rhosum integer, parameter :: maxrhosum = 39 + & maxdustlarge - 1 + & diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 9c1130f8e..261b5a24f 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -123,7 +123,7 @@ subroutine cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) use part, only:isdead_or_accreted,massoftype,igas,rhoh,igasP,ics,ien_type,& itemp,igamma use io, only:fatal - use eos, only:ieos,gamma,done_init_eos,init_eos,get_spsound + use eos, only:ieos,done_init_eos,init_eos,get_spsound integer, intent(in) :: npart real, intent(in) :: pxyzu(:,:),xyzh(:,:),metrics(:,:,:,:) real, intent(inout) :: vxyzu(:,:),dens(:) @@ -135,7 +135,7 @@ subroutine cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) !$omp parallel do default (none) & !$omp shared(xyzh,metrics,vxyzu,dens,pxyzu,npart,massoftype) & -!$omp shared(ieos,gamma,eos_vars,ien_type) & +!$omp shared(ieos,eos_vars,ien_type) & !$omp private(i,ierr,spsound,pondens,p_guess,rhoi,tempi,gammai) do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then diff --git a/src/main/cooling.F90 b/src/main/cooling.f90 similarity index 100% rename from src/main/cooling.F90 rename to src/main/cooling.f90 diff --git a/src/main/cooling_koyamainutsuka.f90 b/src/main/cooling_koyamainutsuka.f90 index eee002b73..2548d180c 100644 --- a/src/main/cooling_koyamainutsuka.f90 +++ b/src/main/cooling_koyamainutsuka.f90 @@ -45,6 +45,7 @@ subroutine init_cooling_KI02(ierr) use units, only:utime,umass,udist integer, intent(out) :: ierr + ierr = 0 LambdaKI_coef = GammaKI_cgs*umass*utime**3/(mass_proton_cgs**2 * udist**5) GammaKI = GammaKI_cgs*utime**3/(mass_proton_cgs*udist**2) call init_hv4table(ierr) @@ -229,6 +230,7 @@ subroutine read_options_cooling_KI02(name,valstring,imatch,igotall,ierr) imatch = .true. igotall = .true. ! nothing to read + ierr = 0 end subroutine read_options_cooling_KI02 diff --git a/src/main/cooling_molecular.f90 b/src/main/cooling_molecular.f90 index 48055b2c9..e953a3175 100644 --- a/src/main/cooling_molecular.f90 +++ b/src/main/cooling_molecular.f90 @@ -210,7 +210,7 @@ subroutine loadCoolingTable(data_array) iunit = 1 filename = find_phantom_datafile('radcool_all.dat','cooling') - OPEN(unit=iunit, file=trim(filename), STATUS="OLD", ACTION="read", & + open(unit=iunit,file=trim(filename),status="OLD", ACTION="read", & iostat=istat, IOMSG=imsg) ! Begin loading in data @@ -218,13 +218,13 @@ subroutine loadCoolingTable(data_array) !!! Skip header rewind(unit=iunit) do o = 1, headerLines - read(iunit, *, iostat=istat, IOMSG = imsg) + read(iunit, *,iostat=istat, IOMSG = imsg) enddo ! Read data skipheaderif: if ((istat == 0)) then readdo: do - read(iunit, *, iostat=istat) i, j, k, T, n_H, N_coolant, lambda_CO, lambda_H2O, lambda_HCN + read(iunit, *,iostat=istat) i, j, k, T, n_H, N_coolant, lambda_CO, lambda_H2O, lambda_HCN if (istat /= 0) exit data_array(i, j, k, :) = [T, n_H, N_coolant, lambda_CO, lambda_H2O, lambda_HCN] @@ -275,20 +275,20 @@ subroutine loadCDTable(data_array) iunit = 1 filename = find_phantom_datafile('table_cd.dat','cooling') - open(unit=iunit, file=filename, STATUS="OLD", iostat=istat, IOMSG=imsg) + open(unit=iunit,file=filename,status="OLD",iostat=istat, IOMSG=imsg) ! Begin loading in data openif: if (istat == 0) then !!! Skip header rewind(unit=iunit) do o = 1, headerLines - read(iunit, *, iostat=istat, IOMSG = imsg) + read(iunit, *,iostat=istat, IOMSG = imsg) enddo !!! Read data skipheaderif: if ((istat == 0)) then readdo: do - read(iunit, *, iostat=istat) i, j, k, l, r_part, widthLine, m_exp, r_sep, N_H + read(iunit, *,iostat=istat) i, j, k, l, r_part, widthLine, m_exp, r_sep, N_H if (istat /= 0) exit data_array(i, j, k, l, :) = [r_part, widthLine, m_exp, r_sep, N_H] diff --git a/src/main/dtype_kdtree.F90 b/src/main/dtype_kdtree.F90 index 6cf50144f..fcb1a04f5 100644 --- a/src/main/dtype_kdtree.F90 +++ b/src/main/dtype_kdtree.F90 @@ -51,9 +51,11 @@ module dtypekdtree real :: xcen(ndimtree) real :: size real :: hmax + real :: dum ! avoid ifort warning: align on 4-byte boundary integer :: leftchild integer :: rightchild integer :: parent + integer :: idum ! avoid ifort warning: align on 4-byte boundary #ifdef GRAVITY real :: mass real :: quads(6) diff --git a/src/main/dust_formation.f90 b/src/main/dust_formation.f90 index e594658ca..5598f85fb 100644 --- a/src/main/dust_formation.f90 +++ b/src/main/dust_formation.f90 @@ -405,7 +405,7 @@ subroutine calc_muGamma(rho_cgs, T, mu, gamma, pH, pH_tot) pH2 = KH2*pH**2 mu = (1.+4.*eps(iHe))/(.5+eps(iHe)+0.5*pH/pH_tot) x = 2.*(1.+4.*eps(iHe))/mu - gamma = (3.*x+4.-3.*eps(iHe))/(x+4.+eps(iHe)) + gamma = (3.*x+4.+4.*eps(iHe))/(x+4.+4.*eps(iHe)) converged = (abs(T-T_old)/T_old) < tol if (i == 1) then mu_old = mu diff --git a/src/main/energies.F90 b/src/main/energies.F90 index 27684ce97..d71e70db1 100644 --- a/src/main/energies.F90 +++ b/src/main/energies.F90 @@ -26,7 +26,8 @@ module energies implicit none logical, public :: gas_only,track_mass,track_lum - real, public :: ekin,etherm,emag,epot,etot,totmom,angtot,mtot,xyzcom(3),hdivBB_xa(2) + real, public :: ekin,etherm,emag,epot,etot,totmom,angtot,mtot,xyzcom(3) + real, public :: hdivBonB_ave,hdivBonB_max real, public :: vrms,rmsmach,accretedmass,mdust(maxdusttypes),mgas real, public :: xmom,ymom,zmom real, public :: totlum @@ -96,11 +97,11 @@ subroutine compute_energies(t) real, intent(in) :: t integer :: iregime,idusttype,ierr real :: ev_data_thread(4,0:inumev) - real :: xi,yi,zi,hi,vxi,vyi,vzi,v2i,vi1,Bxi,Byi,Bzi,Bi,B2i,rhoi,angx,angy,angz + real :: xi,yi,zi,hi,vxi,vyi,vzi,v2i,Bxi,Byi,Bzi,Bi,B2i,rhoi,angx,angy,angz real :: xmomacc,ymomacc,zmomacc,angaccx,angaccy,angaccz,xcom,ycom,zcom,dm real :: epoti,pmassi,dnptot,dnpgas,tsi real :: xmomall,ymomall,zmomall,angxall,angyall,angzall,rho1i,vsigi - real :: ponrhoi,spsoundi,spsound2i,va2cs2,rho1cs2,dumx,dumy,dumz,gammai + real :: ponrhoi,spsoundi,dumx,dumy,dumz,gammai real :: divBi,hdivBonBi,alphai,valfven2i,betai real :: n_total,n_total1,n_ion,shearparam_art,shearparam_phys,ratio_phys_to_av real :: gasfrac,rhogasi,dustfracisum,dustfraci(maxdusttypes),dust_to_gas(maxdusttypes) @@ -175,8 +176,8 @@ subroutine compute_energies(t) !$omp shared(iev_etaa,iev_vel,iev_vhall,iev_vion,iev_n) & !$omp shared(iev_dtg,iev_ts,iev_macc,iev_totlum,iev_erot,iev_viscrat) & !$omp shared(eos_vars,grainsize,graindens,ndustsmall,metrics) & -!$omp private(i,j,xi,yi,zi,hi,rhoi,vxi,vyi,vzi,Bxi,Byi,Bzi,Bi,B2i,epoti,vsigi,v2i,vi1) & -!$omp private(ponrhoi,spsoundi,gammai,spsound2i,va2cs2,rho1cs2,ethermi,dumx,dumy,dumz,valfven2i,divBi,hdivBonBi,curlBi) & +!$omp private(i,j,xi,yi,zi,hi,rhoi,vxi,vyi,vzi,Bxi,Byi,Bzi,Bi,B2i,epoti,vsigi,v2i) & +!$omp private(ponrhoi,spsoundi,gammai,ethermi,dumx,dumy,dumz,valfven2i,divBi,hdivBonBi,curlBi) & !$omp private(rho1i,shearparam_art,shearparam_phys,ratio_phys_to_av,betai) & !$omp private(gasfrac,rhogasi,dustfracisum,dustfraci,dust_to_gas,n_total,n_total1,n_ion) & !$omp private(etaohm,etahall,etaambi,vhalli,vhall,vioni,vion,data_out) & @@ -730,8 +731,8 @@ subroutine compute_energies(t) endif if (mhd) then - hdivBB_xa(1) = ev_data(iev_max,iev_hdivB) - hdivBB_xa(2) = ev_data(iev_ave,iev_hdivB) + hdivBonB_max = ev_data(iev_max,iev_hdivB) + hdivBonB_ave = ev_data(iev_ave,iev_hdivB) endif if (maxp==maxp_hard) then diff --git a/src/main/eos.f90 b/src/main/eos.f90 new file mode 100644 index 000000000..b68bf45b6 --- /dev/null +++ b/src/main/eos.f90 @@ -0,0 +1,1560 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module eos +! +! This module contains stuff to do with the equation of state +! Current options: +! 1 = isothermal eos +! 2 = adiabatic/polytropic eos +! 3 = eos for a locally isothermal disc as in Lodato & Pringle (2007) +! 4 = GR isothermal +! 5 = polytropic EOS with vary mu and gamma depending on H2 formation +! 6 = eos for a locally isothermal disc as in Lodato & Pringle (2007), +! centered on a sink particle +! 7 = z-dependent locally isothermal eos +! 8 = Barotropic eos +! 9 = Piecewise polytrope +! 10 = MESA EoS +! 11 = isothermal eos with zero pressure +! 12 = ideal gas with radiation pressure +! 13 = locally isothermal prescription from Farris et al. (2014) generalised for generic hierarchical systems +! 14 = locally isothermal prescription from Farris et al. (2014) for binary system +! 15 = Helmholtz free energy eos +! 16 = Shen eos +! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) +! 21 = read tabulated eos (for use with icooling == 9) +! +! :References: +! Lodato & Pringle (2007) +! Hirai et al. (2020) +! +! :Owner: Daniel Price +! +! :Runtime parameters: +! - X : *H mass fraction (ignored if variable composition)* +! - Z : *metallicity (ignored if variable composition)* +! - ieos : *eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)* +! - metallicity : *metallicity* +! - mu : *mean molecular weight* +! +! :Dependencies: dim, dump_utils, eos_barotropic, eos_gasradrec, +! eos_helmholtz, eos_idealplusrad, eos_mesa, eos_piecewise, eos_shen, +! eos_stratified, infile_utils, io, mesa_microphysics, part, physcon, +! units +! + use part, only:ien_etotal,ien_entropy,ien_type + use dim, only:gr + implicit none + integer, parameter, public :: maxeos = 21 + real, public :: polyk, polyk2, gamma + real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 + logical, public :: extract_eos_from_hdr = .false. + integer, public :: isink = 0. + + public :: equationofstate,setpolyk,eosinfo,get_mean_molecular_weight + public :: get_TempPresCs,get_spsound,get_temperature,get_pressure,get_cv + public :: eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP + public :: get_local_u_internal,get_temperature_from_u + public :: calc_rec_ene,calc_temp_and_ene,entropy,get_rho_from_p_s,get_u_from_rhoT + public :: calc_rho_from_PT,get_entropy,get_p_from_rho_s + public :: init_eos,finish_eos,write_options_eos,read_options_eos + public :: write_headeropts_eos, read_headeropts_eos + + private + + integer, public :: ieos = 1 + integer, public :: iopacity_type = 0 ! used for radiation + real, public :: gmw = 2.381 ! default mean molecular weight + real, public :: X_in = 0.74 ! default metallicities + real, public :: Z_in = 0.02 ! default metallicities + logical, public :: use_var_comp = .false. ! use variable composition + real, public :: temperature_coef + + logical, public :: done_init_eos = .false. + ! + ! error codes for calls to init_eos + ! + integer, public, parameter :: & + ierr_file_not_found = 1, & + ierr_option_conflict = 2, & + ierr_units_not_set = 3, & + ierr_isink_not_set = 4 + +! +! Default temperature prescription for vertical stratification (0=MAPS, 1=Dartois) +! + integer, public:: istrat = 0. +! +! 2D temperature structure fit parameters for HD 163296 +! + real, public :: z0 = 1. + real, public :: alpha_z = 3.01 + real, public :: beta_z = 0.42 + +contains + +!---------------------------------------------------------------- +!+ +! subroutine returns pressure/density as a function of density +! (and position in the case of the isothermal disc) +!+ +!---------------------------------------------------------------- +subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gamma_local,mu_local,Xlocal,Zlocal) + use io, only:fatal,error,warning + use part, only:xyzmh_ptmass, nptmass + use units, only:unit_density,unit_pressure,unit_ergg,unit_velocity + use physcon, only:Rg,radconst + use eos_mesa, only:get_eos_pressure_temp_gamma1_mesa,get_eos_1overmu_mesa + use eos_helmholtz, only:eos_helmholtz_pres_sound + use eos_shen, only:eos_shen_NL3 + use eos_idealplusrad + use eos_gasradrec, only:equationofstate_gasradrec + use eos_stratified, only:get_eos_stratified + use eos_barotropic, only:get_eos_barotropic + use eos_piecewise, only:get_eos_piecewise + use eos_stamatellos + integer, intent(in) :: eos_type + real, intent(in) :: rhoi,xi,yi,zi + real, intent(out) :: ponrhoi,spsoundi + real, intent(inout) :: tempi + real, intent(in), optional :: eni + real, intent(inout), optional :: mu_local,gamma_local + real, intent(in) , optional :: Xlocal,Zlocal + integer :: ierr, i + real :: r1,r2 + real :: mass_r, mass ! defined for generalised Farris prescription + real :: gammai,temperaturei,mui,imui,X_i,Z_i + real :: cgsrhoi,cgseni,cgspresi,presi,gam1,cgsspsoundi + real :: uthermconst,kappaBar,kappaPart,gmwi + real :: enthi,pondensi + ! + ! Check to see if equation of state is compatible with GR cons2prim routines + ! + if (gr .and. .not.any((/2,4,11,12/)==eos_type)) then + ponrhoi = 0.; spsoundi = 0. ! avoid compiler warning + call fatal('eos','GR currently only works for ieos=2,12 or 11',& + var='eos_type',val=real(eos_type)) + endif + + gammai = gamma + mui = gmw + X_i = X_in + Z_i = Z_in + if (present(gamma_local)) gammai = gamma_local + if (present(mu_local)) mui = mu_local + if (present(Xlocal)) X_i = Xlocal + if (present(Zlocal)) Z_i = Zlocal + + select case(eos_type) + case(1) +! +!--Isothermal eos +! +! :math:`P = c_s^2 \rho` +! +! where :math:`c_s^2 \equiv K` is a constant stored in the dump file header +! + ponrhoi = polyk + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(2,5) +! +!--Adiabatic equation of state (code default) +! +! :math:`P = (\gamma - 1) \rho u` +! +! if the code is compiled with ISOTHERMAL=yes, ieos=2 gives a polytropic eos: +! +! :math:`P = K \rho^\gamma` +! +! where K is a global constant specified in the dump header +! + if (gammai < tiny(gammai)) call fatal('eos','gamma not set for adiabatic eos',var='gamma',val=gammai) + + if (gr) then + if (.not. present(eni)) call fatal('eos','GR call to equationofstate requires thermal energy as input!') + if (eni < 0.) call fatal('eos','utherm < 0',var='u',val=eni) + if (gammai <= 1.) then + spsoundi = 0.; ponrhoi = 0. ! avoid compiler warning + call fatal('eos','GR not compatible with isothermal equation of state, yet...',var='gamma',val=gammai) + elseif (gammai > 1.0001) then + pondensi = (gammai-1.)*eni ! eni is the thermal energy + enthi = 1. + eni + pondensi ! enthalpy + spsoundi = sqrt(gammai*pondensi/enthi) + ponrhoi = pondensi ! With GR this routine actually outputs pondensi (i.e. pressure on primitive density, not conserved.) + endif + else + if (present(eni)) then + if (eni < 0.) then + !write(iprint,'(a,Es18.4,a,4Es18.4)')'Warning: eos: u = ',eni,' < 0 at {x,y,z,rho} = ',xi,yi,zi,rhoi + call fatal('eos','utherm < 0',var='u',val=eni) + endif + if (gammai > 1.0001) then + ponrhoi = (gammai-1.)*eni ! use this if en is thermal energy + else + ponrhoi = 2./3.*eni ! en is thermal energy and gamma = 1 + endif + else + ponrhoi = polyk*rhoi**(gammai-1.) + endif + spsoundi = sqrt(gammai*ponrhoi) + endif + + tempi = temperature_coef*mui*ponrhoi + + case(3) +! +!--Locally isothermal disc as in Lodato & Pringle (2007) where +! +! :math:`P = c_s^2 (r) \rho` +! +! sound speed (temperature) is prescribed as a function of radius using: +! +! :math:`c_s = c_{s,0} r^{-q}` where :math:`r = \sqrt{x^2 + y^2 + z^2}` +! + ponrhoi = polyk*(xi**2 + yi**2 + zi**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(4) +! +!--Isothermal equation of state for GR, enforcing cs = constant +! +! .. WARNING:: this is experimental: use with caution +! + uthermconst = polyk + ponrhoi = (gammai-1.)*uthermconst + spsoundi = sqrt(ponrhoi/(1.+uthermconst)) + tempi = temperature_coef*mui*ponrhoi + + case(6) +! +!--Locally isothermal disc centred on sink particle +! +! As in ieos=3 but in this version radius is taken with respect to a designated +! sink particle (by default the first sink particle in the simulation) +! + ponrhoi = polyk*((xi-xyzmh_ptmass(1,isink))**2 + (yi-xyzmh_ptmass(2,isink))**2 + & + (zi-xyzmh_ptmass(3,isink))**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(7) +! +!--Vertically stratified equation of state +! +! sound speed is prescribed as a function of (cylindrical) radius R and +! height z above the x-y plane +! +! .. WARNING:: should not be used for misaligned discs +! + call get_eos_stratified(istrat,xi,yi,zi,polyk,polyk2,qfacdisc,qfacdisc2,alpha_z,beta_z,z0,ponrhoi,spsoundi) + tempi = temperature_coef*mui*ponrhoi + + case(8) +! +!--Barotropic equation of state +! +! :math:`P = K \rho^\gamma` +! +! where the value of gamma (and K) are a prescribed function of density +! + call get_eos_barotropic(rhoi,polyk,polyk2,ponrhoi,spsoundi,gammai) + tempi = temperature_coef*mui*ponrhoi + + case(9) +! +!--Piecewise Polytropic equation of state +! +! :math:`P = K \rho^\gamma` +! +! where the value of gamma (and K) are a prescribed function of density. +! Similar to ieos=8 but with different defaults and slightly different +! functional form +! + call get_eos_piecewise(rhoi,ponrhoi,spsoundi,gammai) + tempi = temperature_coef*mui*ponrhoi + + case(10) +! +!--MESA equation of state +! +! a tabulated equation of state including gas, radiation pressure +! and ionisation/dissociation. MESA is a stellar evolution code, so +! this equation of state is designed for matter inside stars +! + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + call get_eos_pressure_temp_gamma1_mesa(cgsrhoi,cgseni,cgspresi,temperaturei,gam1,ierr) + presi = cgspresi / unit_pressure + + ponrhoi = presi / rhoi + spsoundi = sqrt(gam1*ponrhoi) + tempi = temperaturei + if (present(gamma_local)) gamma_local = gam1 ! gamma is an output + if (present(mu_local)) mu_local = 1./get_eos_1overmu_mesa(cgsrhoi,cgseni) + if (ierr /= 0) call warning('eos_mesa','extrapolating off tables') + + case(11) +! +!--Isothermal equation of state with pressure and temperature equal to zero +! +! :math:`P = 0` +! +! useful for simulating test particle dynamics using SPH particles +! + ponrhoi = 0. + spsoundi = sqrt(polyk) + tempi = 0. + + case(12) +! +!--Ideal gas plus radiation pressure +! +! :math:`P = (\gamma - 1) \rho u` +! +! but solved by first solving the quartic equation: +! +! :math:`u = \frac32 \frac{k_b T}{\mu m_H} + \frac{a T^4}{\rho}` +! +! for temperature (given u), then solving for pressure using +! +! :math:`P = \frac{k_b T}{\mu m_H} + \frac13 a T^4` +! +! hence in this equation of state gamma (and temperature) are an output +! + temperaturei = tempi ! Required as initial guess + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + call get_idealplusrad_temp(cgsrhoi,cgseni,mui,temperaturei,ierr) + call get_idealplusrad_pres(cgsrhoi,temperaturei,mui,cgspresi) + call get_idealplusrad_spsoundi(cgsrhoi,cgspresi,cgseni,spsoundi,gammai) + if (present(gamma_local)) gamma_local = gammai ! gamma is an output + spsoundi = spsoundi / unit_velocity + presi = cgspresi / unit_pressure + ponrhoi = presi / rhoi + tempi = temperaturei + if (ierr /= 0) call warning('eos_idealplusrad','temperature iteration did not converge') + + + case(13) +! +!--Locally isothermal eos for generic hierarchical system +! +! Assuming all sink particles are stars. +! Generalisation of Farris et al. (2014; for binaries) to N stars. +! For two sink particles this is identical to ieos=14 +! + mass_r = 0 + mass = 0 + + do i=1,nptmass + mass_r = mass_r+xyzmh_ptmass(4,i)/sqrt((xi-xyzmh_ptmass(1,i))**2 + (yi-xyzmh_ptmass(2,i))**2 + (zi-xyzmh_ptmass(3,i))**2) + mass = mass + xyzmh_ptmass(4,i) + enddo + ponrhoi=polyk*(mass_r)**(2*qfacdisc)/mass**(2*qfacdisc) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + + case(14) +! +!--Locally isothermal eos from Farris et al. (2014) for binary system +! +! uses the locations of the first two sink particles +! + r1 = sqrt((xi-xyzmh_ptmass(1,1))**2+(yi-xyzmh_ptmass(2,1))**2 + (zi-xyzmh_ptmass(3,1))**2) + r2 = sqrt((xi-xyzmh_ptmass(1,2))**2+(yi-xyzmh_ptmass(2,2))**2 + (zi-xyzmh_ptmass(3,2))**2) + ponrhoi=polyk*(xyzmh_ptmass(4,1)/r1+xyzmh_ptmass(4,2)/r2)**(2*qfacdisc)/(xyzmh_ptmass(4,1)+xyzmh_ptmass(4,2))**(2*qfacdisc) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(15) +! +!--Helmholtz equation of state (computed live, not tabulated) +! +! .. WARNING:: not widely tested in phantom, better to use ieos=10 +! + call eos_helmholtz_pres_sound(tempi, rhoi, ponrhoi, spsoundi, eni) + + case(16) +! +!--Shen (2012) equation of state for neutron stars +! +! this equation of state requires evolving temperature as the energy variable +! +! .. WARNING:: not tested: use with caution +! + if (present(eni)) then + cgsrhoi = rhoi * unit_density + !note eni is actually tempi + call eos_shen_NL3(cgsrhoi,eni,0.05,cgspresi,cgsspsoundi) + spsoundi=cgsspsoundi / unit_velocity + presi = cgspresi / unit_pressure + ponrhoi = presi / rhoi + tempi = eni + call warning('eos','Not sure if this is correct now that temperature is always passed into eos') + else + spsoundi = 0.; presi = 0.; ponrhoi = 0.; tempi = 0. ! to avoid compiler warnings + call fatal('eos','tried to call NL3 eos without passing temperature') + endif + + case(20) +! +!--Gas + radiation + various forms of recombination +! +! from HORMONE, Hirai+2020, as used in Lau+2022b +! + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + imui = 1./mui + if (tempi > 0.) then + temperaturei = tempi + else + temperaturei = min(0.67 * cgseni * mui / Rg, (cgseni*cgsrhoi/radconst)**0.25) + endif + call equationofstate_gasradrec(cgsrhoi,cgseni*cgsrhoi,temperaturei,imui,X_i,1.-X_i-Z_i,cgspresi,cgsspsoundi,gammai) + ponrhoi = real(cgspresi / (unit_pressure * rhoi)) + spsoundi = real(cgsspsoundi / unit_velocity) + tempi = temperaturei + if (present(mu_local)) mu_local = 1./imui + if (present(gamma_local)) gamma_local = gammai + + case(21) +! +!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=9 +! + if (eni < 0.) then + call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) + endif + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) + cgspresi = kb_on_mh*cgsrhoi*tempi/mui + presi = cgspresi/unit_pressure + ponrhoi = presi/rhoi + gammai = 1.d0 + presi/(eni*rhoi) + !if (gammai < 1.d0 .or. gammai > 2.d0) then + ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi + !endif + spsoundi = sqrt(gammai*ponrhoi) + + + case default + spsoundi = 0. ! avoids compiler warnings + ponrhoi = 0. + tempi = 0. + call fatal('eos','unknown equation of state') + end select + +end subroutine equationofstate + +!----------------------------------------------------------------------- +!+ +! initialise equation of state (read tables etc.) +!+ +!----------------------------------------------------------------------- +subroutine init_eos(eos_type,ierr) + use units, only:unit_velocity + use physcon, only:Rg + use io, only:error,warning,fatal + use eos_mesa, only:init_eos_mesa + use eos_helmholtz, only:eos_helmholtz_init + use eos_piecewise, only:init_eos_piecewise + use eos_barotropic, only:init_eos_barotropic + use eos_shen, only:init_eos_shen_NL3 + use eos_gasradrec, only:init_eos_gasradrec + use eos_stamatellos,only:read_optab,init_S07cool,eos_file + use dim, only:maxvxyzu,do_radiation + integer, intent(in) :: eos_type + integer, intent(out) :: ierr + integer :: ierr_mesakapp + + ierr = 0 + ! + !--Set coefficient to convert P/rho into temperature + ! calculation will be in cgs; the mean molecular weight, gmw, will be + ! included in the function call rather than here + ! c_s^2 = gamma*P/rho = gamma*kT/(gmw*m_p) -> T = P/rho * (gmw*m_p)/k + ! + temperature_coef = unit_velocity**2 / Rg + + select case(eos_type) + case(6) + ! + !--Check that if using ieos=6, then isink is set properly + ! + if (isink==0) then + call error('eos','ieos=6, but isink is not set') + ierr = ierr_isink_not_set + return + endif + + case(8) + ! + ! barotropic equation of state + ! + call init_eos_barotropic(polyk,polyk2,ierr) + + case(9) + ! + ! piecewise polytropic equation of state (similar to barotropic) + ! + call init_eos_piecewise(ierr) + + case(10) + ! + !--MESA EoS initialisation + ! + write(*,'(1x,a,f7.5,a,f7.5)') 'Initialising MESA EoS with X = ',X_in,', Z = ',Z_in + call init_eos_mesa(X_in,Z_in,ierr) + if (do_radiation .and. ierr==0) then + call error('eos','ieos=10, cannot use eos with radiation, will double count radiation pressure') + ierr=ierr_option_conflict !return error if using radiation and mesa EOS, shouldn't use mesa eos, as it will double count rad pres + endif + + case(12) + ! + ! ideal plus radiation + ! + write(*,'(1x,a,f7.5)') 'Using ideal plus radiation EoS with mu = ',gmw + if (do_radiation) then + call error('eos','ieos=12, cannot use eos with radiation, will double count radiation pressure') + ierr = ierr_option_conflict + endif + + case(15) + + call eos_helmholtz_init(ierr) + + case(16) + + call init_eos_shen_NL3(ierr) + + case(20) + + call init_eos_gasradrec(ierr) + if (.not. use_var_comp) then + write(*,'(a,f7.5,a,f7.5)') 'Assuming fixed composition X = ',X_in,', Z = ',Z_in + endif + if (do_radiation) then + call error('eos','ieos=20, cannot use eos with radiation, will double count radiation pressure') + ierr = ierr_option_conflict + endif + + case(21) + + call read_optab(eos_file,ierr) + if (ierr > 0) call fatal('init_eos','Failed to read EOS file') + call init_S07cool + + end select + done_init_eos = .true. + + if (do_radiation .and. iopacity_type==1) then + write(*,'(1x,a,f7.5,a,f7.5)') 'Using radiation with MESA opacities. Initialising MESA EoS with X = ',X_in,', Z = ',Z_in + call init_eos_mesa(X_in,Z_in,ierr_mesakapp) + ierr = max(ierr,ierr_mesakapp) + endif + +end subroutine init_eos + +!----------------------------------------------------------------------- +!+ +! finish equation of state +!+ +!----------------------------------------------------------------------- +subroutine finish_eos(eos_type,ierr) + use eos_mesa, only: finish_eos_mesa + use eos_stamatellos, only: finish_S07cool + + integer, intent(in) :: eos_type + integer, intent(out) :: ierr + + ierr = 0 + + select case(eos_type) + case(10) + ! + !--MESA EoS deallocation + ! + call finish_eos_mesa + + case(21) + ! Stamatellos deallocation + call finish_S07cool + + end select + done_init_eos=.false. + +end subroutine finish_eos + +!----------------------------------------------------------------------- +!+ +! Calculate gas temperature, sound speed, and pressure. +! This will be required for various analysis routines if eos_vars +! is not saved in the dump files +!+ +!----------------------------------------------------------------------- +subroutine get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi,spsoundi,gammai,mui,Xi,Zi) + use dim, only:maxvxyzu + integer, intent(in) :: eos_type + real, intent(in) :: vxyzui(:),xyzi(:),rhoi + real, intent(inout) :: tempi + real, intent(out), optional :: presi,spsoundi + real, intent(inout), optional :: gammai,mui + real, intent(in), optional :: Xi,Zi + real :: csi,ponrhoi,mu,X,Z + logical :: use_gamma + + mu = gmw + X = X_in + Z = Z_in + if (present(mui)) mu = mui + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + use_gamma = .false. + if (present(gammai)) then + if (gammai > 0.) use_gamma = .true. + endif + + if (maxvxyzu==4) then + 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) + else + call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,vxyzui(4),& + mu_local=mu,Xlocal=X,Zlocal=Z) + endif + else + call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,mu_local=mu) + endif + + if (present(presi)) presi = ponrhoi*rhoi + if (present(spsoundi)) spsoundi = csi + if (present(mui)) mui = mu + if (present(gammai)) gammai = gamma + +end subroutine get_TempPresCs + +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate sound speed +!+ +!----------------------------------------------------------------------- +real function get_spsound(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xyzi(:),rhoi + real, intent(in) :: vxyzui(:) + real, intent(in), optional :: Xi,Zi + real, intent(inout), optional :: gammai,mui + real :: spsoundi,tempi,gam,mu,X,Z + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,spsoundi=spsoundi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_spsound = spsoundi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + +end function get_spsound + +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate temperature +!+ +!----------------------------------------------------------------------- +real function get_temperature(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xyzi(:),rhoi + real, intent(in) :: vxyzui(:) + real, intent(in), optional :: Xi,Zi + real, intent(inout),optional :: gammai,mui + real :: tempi,gam,mu,X,Z + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_temperature = tempi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + +end function get_temperature + + +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate temperature +!+ +!----------------------------------------------------------------------- +real function get_temperature_from_u(eos_type,xpi,ypi,zpi,rhoi,ui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xpi,ypi,zpi,rhoi + real, intent(in) :: ui + real, intent(in), optional :: Xi,Zi + real, intent(inout),optional :: gammai,mui + real :: tempi,gam,mu,X,Z + real :: vxyzui(4),xyzi(3) + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + vxyzui = (/0.,0.,0.,ui/) + xyzi = (/xpi,ypi,zpi/) + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_temperature_from_u = tempi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + + +end function get_temperature_from_u +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate pressure +!+ +!----------------------------------------------------------------------- +real function get_pressure(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xyzi(:),rhoi,vxyzui(:) + real, intent(in), optional :: Xi,Zi + real, intent(inout),optional :: gammai,mui + real :: presi,tempi,gam,mu,X,Z + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(mui)) mu = mui + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi=presi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_pressure = presi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + +end function get_pressure + +!----------------------------------------------------------------------- +!+ +! query function to return the internal energy for calculations with a +! local mean molecular weight and local adiabatic index +!+ +!----------------------------------------------------------------------- +real function get_local_u_internal(gammai, gmwi, gas_temp_local) + real, intent(in) :: gammai, gmwi, gas_temp_local + real :: ponrhoi + + ponrhoi = gas_temp_local/(gmwi*temperature_coef) + get_local_u_internal = ponrhoi/(gammai-1.) + +end function get_local_u_internal + +!----------------------------------------------------------------------- +!+ +! get u from rho, T +!+ +!----------------------------------------------------------------------- +real function get_u_from_rhoT(rho,temp,eos_type,uguess) result(u) + use eos_mesa, only:get_eos_u_from_rhoT_mesa + integer, intent(in) :: eos_type + real, intent(in) :: rho,temp + real, intent(in), optional :: uguess + + select case (eos_type) + case(10) ! MESA EoS + if (present(uguess)) then + call get_eos_u_from_rhoT_mesa(rho,temp,u,uguess) + else + call get_eos_u_from_rhoT_mesa(rho,temp,u) + endif + + case default + u = temp/(gmw*temperature_coef*(gamma-1.)) + end select + +end function get_u_from_rhoT + +!----------------------------------------------------------------------- +!+ +! Get recombination energy (per unit mass) assumming complete +! ionisation +!+ +!----------------------------------------------------------------------- +subroutine calc_rec_ene(XX,YY,e_rec) + real, intent(in) :: XX, YY + real, intent(out) :: e_rec + real :: e_H2,e_HI,e_HeI,e_HeII + real, parameter :: e_ion_H2 = 1.312e13, & ! ionisation energies in erg/mol + e_ion_HI = 4.36e12, & + e_ion_HeI = 2.3723e13, & + e_ion_HeII = 5.2505e13 + + ! XX : Hydrogen mass fraction + ! YY : Helium mass fraction + ! e_rec : Total ionisation energy due to H2, HI, HeI, and HeII + + e_H2 = 0.5 * XX * e_ion_H2 + e_HI = XX * e_ion_HI + e_HeI = 0.25 * YY * e_ion_HeI + e_HeII = 0.25 * YY * e_ion_HeII + e_rec = e_H2 + e_HI + e_HeI + e_HeII + +end subroutine calc_rec_ene + +!----------------------------------------------------------------------- +!+ +! Calculate temperature and specific internal energy from +! pressure and density. Inputs and outputs are in cgs units. +! +! Note on composition: +! For ieos=2, 5 and 12, mu_local is an input, X & Z are not used +! For ieos=10, mu_local is not used +! For ieos=20, mu_local is not used but available as an output +!+ +!----------------------------------------------------------------------- +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 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 + integer, intent(in) :: eos_type + real, intent(in) :: rho,pres + real, intent(inout) :: ene,temp + real, intent(in), optional :: guesseint,X_local,Z_local + real, intent(inout), optional :: mu_local + integer, intent(out) :: ierr + real :: mu,X,Z + + ierr = 0 + mu = gmw + X = X_in + Z = Z_in + if (present(mu_local)) mu = mu_local + if (present(X_local)) X = X_local + if (present(Z_local)) Z = Z_local + select case(eos_type) + case(2,5) ! Ideal gas + temp = pres / (rho * kb_on_mh) * mu + ene = pres / ( (gamma-1.) * rho) + case(12) ! Ideal gas + radiation + call get_idealgasplusrad_tempfrompres(pres,rho,mu,temp) + call get_idealplusrad_enfromtemp(rho,temp,mu,ene) + case(10) ! MESA EoS + call get_eos_eT_from_rhop_mesa(rho,pres,ene,temp,guesseint) + case(20) ! Ideal gas + radiation + recombination (from HORMONE, Hirai et al., 2020) + call calc_uT_from_rhoP_gasradrec(rho,pres,X,1.-X-Z,temp,ene,mu,ierr) + if (present(mu_local)) mu_local = mu + case default + ierr = 1 + end select + +end subroutine calc_temp_and_ene + +!----------------------------------------------------------------------- +!+ +! Calculate density from pressure and temperature. Inputs and outputs +! are in cgs units. +! +! Note on composition: +! For ieos=2 and 12, mu_local is an input, X & Z are not used +! For ieos=10, mu_local is not used +! For ieos=20, mu_local is not used but available as an output +!+ +!----------------------------------------------------------------------- +subroutine calc_rho_from_PT(eos_type,pres,temp,rho,ierr,mu_local,X_local,Z_local) + use physcon, only:kb_on_mh + 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 + integer, intent(in) :: eos_type + real, intent(in) :: pres,temp + real, intent(inout) :: rho + real, intent(in), optional :: X_local,Z_local + real, intent(inout), optional :: mu_local + integer, intent(out) :: ierr + real :: mu,X,Z + + ierr = 0 + mu = gmw + X = X_in + Z = Z_in + if (present(mu_local)) mu = mu_local + if (present(X_local)) X = X_local + if (present(Z_local)) Z = Z_local + select case(eos_type) + case(2) ! Ideal gas + rho = pres / (temp * kb_on_mh) * mu + case(12) ! Ideal gas + radiation + call get_idealplusrad_rhofrompresT(pres,temp,mu,rho) + case default + ierr = 1 + end select + +end subroutine calc_rho_from_PT + +!----------------------------------------------------------------------- +!+ +! Calculates specific entropy (gas + radiation + recombination) +! up to an additive integration constant, from density and pressure. +!+ +!----------------------------------------------------------------------- +function entropy(rho,pres,mu_in,ientropy,eint_in,ierr) + use io, only:fatal,warning + use physcon, only:radconst,kb_on_mh + 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 + integer, intent(in) :: ientropy + integer, intent(out), optional :: ierr + real :: mu,entropy,logentropy,temp,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) + + ! check temp + if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') + + 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) + + ! check temp + if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') + + 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') + + if (present(eint_in)) then + eint = eint_in + else + call get_eos_eT_from_rhop_mesa(rho,pres,eint,temp) + endif + + ! Get entropy from rho and eint from MESA tables + if (present(ierr)) then + call getvalue_mesa(rho,eint,9,logentropy,ierr) + else + call getvalue_mesa(rho,eint,9,logentropy) + endif + entropy = 10.**logentropy + + case default + entropy = 0. + call fatal('eos','Unknown ientropy (can only be 1, 2, or 3)') + end select + +end function entropy + +real function get_entropy(rho,pres,mu_in,ieos) + use units, only:unit_density,unit_pressure,unit_ergg + use physcon, only:kboltz + integer, intent(in) :: ieos + real, intent(in) :: rho,pres,mu_in + real :: cgsrho,cgspres,cgss + + cgsrho = rho * unit_density + cgspres = pres * unit_pressure + select case (ieos) + case (12) + cgss = entropy(cgsrho,cgspres,mu_in,2) + case (10, 20) + cgss = entropy(cgsrho,cgspres,mu_in,3) + case default + cgss = entropy(cgsrho,cgspres,mu_in,1) + end select + cgss = cgss/kboltz ! s/kb + get_entropy = cgss/unit_ergg + +end function get_entropy + +!----------------------------------------------------------------------- +!+ +! Calculate density given pressure and entropy using Newton-Raphson +! method +!+ +!----------------------------------------------------------------------- +subroutine get_rho_from_p_s(pres,S,rho,mu,rhoguess,ientropy) + real, intent(in) :: pres,S,mu,rhoguess + real, intent(inout) :: rho + real :: srho,srho_plus_dsrho,S_plus_dS,dSdsrho + real(kind=8) :: corr + real, parameter :: eoserr=1e-9,dfac=1e-12 + integer, intent(in) :: ientropy + + ! We apply the Newton-Raphson method directly to rho^1/2 ("srho") instead + ! of rho since S(rho) cannot take a negative argument. + srho = sqrt(rhoguess) ! Initial guess + corr = huge(corr); + do while (abs(corr) > eoserr*abs(srho)) + ! First calculate dS/dsrho + srho_plus_dsrho = srho * (1. + dfac) + S_plus_dS = entropy(srho_plus_dsrho**2,pres,mu,ientropy) + dSdsrho = (S_plus_dS - entropy(srho**2,pres,mu,ientropy)) / (srho_plus_dsrho - srho) + corr = ( entropy(srho**2,pres,mu,ientropy) - S ) / dSdsrho + srho = srho - corr + enddo + rho = srho**2 + +end subroutine get_rho_from_p_s + +!----------------------------------------------------------------------- +!+ +! Calculate temperature given density and entropy using Newton-Raphson +! method +!+ +!----------------------------------------------------------------------- +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 io, only:fatal + use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_pres + use units, only:unit_density,unit_pressure,unit_ergg + real, intent(in) :: S,mu,rho + real, intent(inout) :: temp + real, intent(out) :: P + integer, intent(in) :: ieos + real :: corr,df,f,temp_new,cgsrho,cgsp,cgss + real, parameter :: eoserr=1e-12 + integer :: niter + integer, parameter :: nitermax = 1000 + + ! change to cgs unit + cgsrho = rho*unit_density + cgss = s*unit_ergg + + niter = 0 + select case (ieos) + case (2,5) + temp = (cgsrho * exp(mu*cgss*mass_proton_cgs))**(2./3.) + cgsP = cgsrho*kb_on_mh*temp / mu + case (12) + corr = huge(corr) + do while (abs(corr) > eoserr .and. niter < nitermax) + f = 1. / (mu*mass_proton_cgs) * log(temp**1.5/cgsrho) + 4.*radconst*temp**3 / (3.*cgsrho*kboltz) - cgss + df = 1.5 / (mu*temp*mass_proton_cgs) + 4.*radconst*temp**2 / (cgsrho*kboltz) + corr = f/df + temp_new = temp - corr + if (temp_new > 1.2 * temp) then + temp = 1.2 * temp + elseif (temp_new < 0.8 * temp) then + temp = 0.8 * temp + else + temp = temp_new + endif + niter = niter + 1 + enddo + call get_idealplusrad_pres(cgsrho,temp,mu,cgsP) + case default + cgsP = 0. + call fatal('eos','[get_p_from_rho_s] only implemented for eos 2 and 12') + end select + + ! check temp + if (temp > huge(0.)) call fatal('entropy','entropy too large gives infinte temperature, & + &reducing entropy factor C_ent for one dump') + + ! change back to code unit + P = cgsP / unit_pressure + +end subroutine get_p_from_rho_s + +!----------------------------------------------------------------------- +!+ +! Calculate mean molecular weight from X and Z, assuming complete +! ionisation +!+ +!----------------------------------------------------------------------- +real function get_mean_molecular_weight(XX,ZZ) result(mu) + real, intent(in) :: XX,ZZ + real :: YY + + YY = 1.-XX-ZZ + mu = 1./(2.*XX + 0.75*YY + 0.5*ZZ) + +end function get_mean_molecular_weight + +!--------------------------------------------------------- +!+ +! return cv from rho, u in code units +!+ +!--------------------------------------------------------- +real function get_cv(rho,u,cv_type) result(cv) + use mesa_microphysics, only:getvalue_mesa + use units, only:unit_ergg,unit_density + use physcon, only:Rg + real, intent(in) :: rho,u + integer, intent(in) :: cv_type + real :: rho_cgs,u_cgs,temp + + select case (cv_type) + + case(1) ! MESA EoS + rho_cgs = rho*unit_density + u_cgs = u*unit_ergg + call getvalue_mesa(rho_cgs,u_cgs,4,temp) + cv = u_cgs/temp / unit_ergg + case default ! constant cv + cv = Rg/((gamma-1.)*gmw*unit_ergg) + end select + +end function get_cv + +!----------------------------------------------------------------------- +!+ +! subroutine sets polyk based on utherm/positions +! read from an sphNG dump file +!+ +!----------------------------------------------------------------------- +subroutine setpolyk(eos_type,iprint,utherm,xyzhi,npart) + use part, only:xyzmh_ptmass + use io, only:id,master + integer, intent(in) :: eos_type,iprint + real, intent(in) :: utherm(:) + real, intent(in) :: xyzhi(:,:) + integer, intent(in) :: npart + integer :: ipart + real :: r2,polykalt + + !-- pick a random particle from which to extract polyk + ipart = npart/2 + + select case(eos_type) + case(1,8) +! +!--isothermal eos +! + polykalt = 2./3.*utherm(ipart) + !--check all other utherms identical + if (any(utherm(1:npart) /= utherm(ipart)) .and. id==master) then + write(iprint,*) 'WARNING! different utherms but run is isothermal' + endif + + case(2,5) +! +!--adiabatic/polytropic eos +! this routine is ONLY called if utherm is NOT stored, so polyk matters +! + if (id==master) write(iprint,*) 'Using polytropic equation of state, gamma = ',gamma + polykalt = 2./3.*utherm(ipart) + if (gamma <= 1.00000001) then + stop 'silly to use gamma==1 without using isothermal eos' + endif + + case(3) +! +!--locally isothermal disc as in Lodato & Pringle (2007) +! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) +! + r2 = xyzhi(1,ipart)*xyzhi(1,ipart) + xyzhi(2,ipart)*xyzhi(2,ipart) & + + xyzhi(3,ipart)*xyzhi(3,ipart) + polykalt = 2./3.*utherm(ipart)*r2**qfacdisc + + case(6) +! +!--locally isothermal disc as in Lodato & Pringle (2007), centered on specified sink particle +! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) +! + r2 = (xyzhi(1,ipart)-xyzmh_ptmass(1,isink))**2 + & + (xyzhi(2,ipart)-xyzmh_ptmass(2,isink))**2 + & + (xyzhi(3,ipart)-xyzmh_ptmass(3,isink))**2 + + polykalt = 2./3.*utherm(ipart)*r2**qfacdisc + case default +! +!--don't die in this routine as it can be called from readdump +! (ie. not necessarily as part of a run) +! + if (id==master) write(iprint,*) ' WARNING! unknown equation of state in setpolyk' + polykalt = polyk + + end select + + if (diff(polykalt,polyk) .and. id==master) then + write(iprint,*) 'WARNING! polyk set using RK2 in dump differs from that set using thermal energy' + write(iprint,*) 'using polyk = ',polykalt, ' (from RK2 = ',polyk,')' + endif + polyk = polykalt +! +!--warn if polyk is zero, die if negative +! + if (polyk < 0.) then + write(iprint,*) 'ERROR: polyk < 0 in setting equation of state' + stop + elseif (polyk < tiny(polyk) .and. id==master) then + write(iprint,*) 'WARNING: polyk = 0 in equation of state' + endif + +end subroutine setpolyk +!----------------------------------------------------------------------- +!+ +! small utility returns whether two real numbers differ +!+ +!----------------------------------------------------------------------- +logical pure function diff(r1,r2) + real, intent(in) :: r1,r2 + + diff = abs(r1-r2) > tiny(r1) + +end function diff + +!----------------------------------------------------------------------- +!+ +! Query function to return whether an EoS is non-ideal +! Mainly used to decide whether it is necessary to write +! things like pressure and temperature in the dump file or not +!+ +!----------------------------------------------------------------------- +logical function eos_is_non_ideal(ieos) + integer, intent(in) :: ieos + + select case(ieos) + case(10,12,15,20) + eos_is_non_ideal = .true. + case default + eos_is_non_ideal = .false. + end select + +end function eos_is_non_ideal + +!----------------------------------------------------------------------- +!+ +! Query function to return whether an EoS outputs mean molecular weight +!+ +!----------------------------------------------------------------------- +logical function eos_outputs_mu(ieos) + integer, intent(in) :: ieos + + select case(ieos) + case(20) + eos_outputs_mu = .true. + case default + eos_outputs_mu = .false. + end select + +end function eos_outputs_mu + +!----------------------------------------------------------------------- +!+ +! Query function to whether to print pressure to dump file +!+ +!----------------------------------------------------------------------- +logical function eos_outputs_gasP(ieos) + integer, intent(in) :: ieos + + select case(ieos) + case(8,9,10,15) + eos_outputs_gasP = .true. + case default + eos_outputs_gasP = .false. + end select + +end function eos_outputs_gasP + +!----------------------------------------------------------------------- +!+ +! prints equation of state info in the run header +!+ +!----------------------------------------------------------------------- +subroutine eosinfo(eos_type,iprint) + use dim, only:maxvxyzu + use io, only:fatal,id,master + use eos_helmholtz, only:eos_helmholtz_eosinfo + use eos_barotropic, only:eos_info_barotropic + use eos_piecewise, only:eos_info_piecewise + use eos_gasradrec, only:eos_info_gasradrec + integer, intent(in) :: eos_type,iprint + + if (id/=master) return + + select case(eos_type) + case(1,11) + if (1.0d-5 < polyk .and. polyk < 1.0d3) then + write(iprint,"(/,a,f10.6)") ' Isothermal equation of state: cs^2 = ',polyk + else + write(iprint,"(/,a,Es13.6)") ' Isothermal equation of state: cs^2 = ',polyk + endif + if (eos_type==11) write(iprint,*) ' (ZERO PRESSURE) ' + case(2) + if (maxvxyzu >= 4) then + write(iprint,"(/,a,f10.6,a,f10.6)") ' Adiabatic equation of state: P = (gamma-1)*rho*u, gamma = ',& + gamma,' gmw = ',gmw + else + write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6)") ' Polytropic equation of state: P = ',polyk,'*rho^',gamma,' gmw = ',gmw + endif + case(3) + write(iprint,"(/,a,f10.6,a,f10.6)") ' Locally isothermal eq of state (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc + case(5) + if (maxvxyzu >= 4) then + write(iprint,"(' Adiabatic equation of state: P = (gamma-1)*rho*u, where gamma & mu depend on the formation of H2')") + else + stop '[stop eos] eos = 5 cannot assume isothermal conditions' + endif + case(6) + write(iprint,"(/,a,i2,a,f10.6,a,f10.6)") ' Locally (on sink ',isink, & + ') isothermal eos (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc + case(8) + call eos_info_barotropic(polyk,polyk2,iprint) + case(9) + call eos_info_piecewise(iprint) + case(10) + write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6,a)") ' MESA EoS: X = ',X_in,' Z = ',Z_in,' (1-X-Z = ',1.-X_in-Z_in,')' + case(12) + write(iprint,"(/,a,f10.6,a,f10.6)") ' Gas + radiation equation of state: gmw = ',gmw,' gamma = ',gamma + case(15) + call eos_helmholtz_eosinfo(iprint) + case(20) + call eos_info_gasradrec(iprint) + if (use_var_comp) then + write(*,'(1x,a,i1,a)') 'Using variable composition' + else + write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in + endif + end select + write(iprint,*) + +end subroutine eosinfo + +!----------------------------------------------------------------------- +!+ +! write relevant options to the header of the dump file +!+ +!----------------------------------------------------------------------- +subroutine write_headeropts_eos(ieos,hdr,ierr) + use dump_utils, only:dump_h,add_to_rheader,add_to_iheader + integer, intent(in) :: ieos + type(dump_h), intent(inout) :: hdr + integer, intent(out) :: ierr + + call add_to_iheader(isink,'isink',hdr,ierr) + call add_to_rheader(gamma,'gamma',hdr,ierr) + call add_to_rheader(1.5*polyk,'RK2',hdr,ierr) + call add_to_rheader(polyk2,'polyk2',hdr,ierr) + call add_to_rheader(qfacdisc,'qfacdisc',hdr,ierr) + call add_to_rheader(qfacdisc2,'qfacdisc2',hdr,ierr) + + if (ieos==7) then + call add_to_iheader(istrat,'istrat',hdr,ierr) + call add_to_rheader(alpha_z,'alpha_z',hdr,ierr) + call add_to_rheader(beta_z,'beta_z',hdr,ierr) + call add_to_rheader(z0,'z0',hdr,ierr) + endif + +end subroutine write_headeropts_eos + +!----------------------------------------------------------------------- +!+ +! read relevant options from the header of the dump file +!+ +!----------------------------------------------------------------------- +subroutine read_headeropts_eos(ieos,hdr,ierr) + use dump_utils, only:dump_h, extract + use io, only:iprint,id,master + use dim, only:use_krome,maxvxyzu + integer, intent(in) :: ieos + type(dump_h), intent(in) :: hdr + integer, intent(out) :: ierr + real :: RK2 + + + call extract('gamma',gamma,hdr,ierr) + call extract('RK2',rk2,hdr,ierr) + polyk = 2./3.*rk2 + if (id==master) then + if (maxvxyzu >= 4) then + if (use_krome) then + write(iprint,*) 'KROME eos: initial gamma = 1.666667' + else + write(iprint,*) 'adiabatic eos: gamma = ',gamma + endif + else + write(iprint,*) 'setting isothermal sound speed^2 (polyk) = ',polyk,' gamma = ',gamma + if (polyk <= tiny(polyk)) write(iprint,*) 'WARNING! sound speed zero in dump!, polyk = ',polyk + endif + endif + call extract('polyk2',polyk2,hdr,ierr) + call extract('qfacdisc',qfacdisc,hdr,ierr) + call extract('qfacdisc2',qfacdisc2,hdr,ierr) + call extract('isink',isink,hdr,ierr) + + if (abs(gamma-1.) > tiny(gamma) .and. maxvxyzu < 4) then + write(*,*) 'WARNING! compiled for isothermal equation of state but gamma /= 1, gamma=',gamma + endif + + ierr = 0 + if (ieos==3 .or. ieos==6 .or. ieos==7) then + if (qfacdisc <= tiny(qfacdisc)) then + if (id==master) write(iprint,*) 'ERROR: qfacdisc <= 0' + ierr = 2 + else + if (id==master) write(iprint,*) 'qfacdisc = ',qfacdisc + endif + endif + + if (ieos==7) then + call extract('istrat',istrat,hdr,ierr) + call extract('alpha_z',alpha_z,hdr,ierr) + call extract('beta_z', beta_z, hdr,ierr) + call extract('z0',z0,hdr,ierr) + if (abs(qfacdisc2) <= tiny(qfacdisc2)) then + if (id==master) write(iprint,*) 'ERROR: qfacdisc2 == 0' + ierr = 2 + else + if (id==master) write(iprint,*) 'qfacdisc2 = ',qfacdisc2 + endif + endif + +end subroutine read_headeropts_eos + +!----------------------------------------------------------------------- +!+ +! writes equation of state options to the input file +!+ +!----------------------------------------------------------------------- +subroutine write_options_eos(iunit) + use dim, only:use_krome + use infile_utils, only:write_inopt + use eos_helmholtz, only:eos_helmholtz_write_inopt + use eos_barotropic, only:write_options_eos_barotropic + use eos_piecewise, only:write_options_eos_piecewise + use eos_gasradrec, only:write_options_eos_gasradrec + integer, intent(in) :: iunit + + write(iunit,"(/,a)") '# options controlling equation of state' + call write_inopt(ieos,'ieos','eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)',iunit) + + if (.not.use_krome .or. .not.eos_outputs_mu(ieos)) then + call write_inopt(gmw,'mu','mean molecular weight',iunit) + endif + + select case(ieos) + case(8) + call write_options_eos_barotropic(iunit) + case(9) + call write_options_eos_piecewise(iunit) + case(10) + call write_inopt(X_in,'X','hydrogen mass fraction',iunit) + call write_inopt(Z_in,'Z','metallicity',iunit) + case(15) ! helmholtz eos + call eos_helmholtz_write_inopt(iunit) + case(20) + call write_options_eos_gasradrec(iunit) + if (.not. use_var_comp) then + call write_inopt(X_in,'X','H mass fraction (ignored if variable composition)',iunit) + call write_inopt(Z_in,'Z','metallicity (ignored if variable composition)',iunit) + endif + end select + +end subroutine write_options_eos + +!----------------------------------------------------------------------- +!+ +! reads equation of state options from the input file +!+ +!----------------------------------------------------------------------- +subroutine read_options_eos(name,valstring,imatch,igotall,ierr) + use dim, only:store_dust_temperature,update_muGamma + use io, only:fatal + use eos_barotropic, only:read_options_eos_barotropic + use eos_piecewise, only:read_options_eos_piecewise + use eos_gasradrec, only:read_options_eos_gasradrec + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotall + integer, intent(out) :: ierr + integer, save :: ngot = 0 + character(len=30), parameter :: label = 'read_options_eos' + logical :: igotall_barotropic,igotall_piecewise,igotall_gasradrec + + imatch = .true. + igotall_barotropic = .true. + igotall_piecewise = .true. + igotall_gasradrec = .true. + + select case(trim(name)) + case('ieos') + read(valstring,*,iostat=ierr) ieos + ngot = ngot + 1 + if (ieos <= 0 .or. ieos > maxeos) call fatal(label,'equation of state choice out of range') + if (ieos == 5) then + store_dust_temperature = .true. + update_muGamma = .true. + endif + if (ieos == 21) update_muGamma = .true. + case('mu') + read(valstring,*,iostat=ierr) gmw + ! not compulsory to read in + if (gmw <= 0.) call fatal(label,'mu <= 0') + case('X') + read(valstring,*,iostat=ierr) X_in + if (X_in <= 0. .or. X_in >= 1.) call fatal(label,'X must be between 0 and 1') + ngot = ngot + 1 + case('Z') + read(valstring,*,iostat=ierr) Z_in + if (Z_in <= 0. .or. Z_in > 1.) call fatal(label,'Z must be between 0 and 1') + ngot = ngot + 1 + case default + imatch = .false. + end select + if (.not.imatch .and. ieos== 8) call read_options_eos_barotropic(name,valstring,imatch,igotall_barotropic,ierr) + if (.not.imatch .and. ieos== 9) call read_options_eos_piecewise( name,valstring,imatch,igotall_piecewise, ierr) + if (.not.imatch .and. ieos==20) call read_options_eos_gasradrec( name,valstring,imatch,igotall_gasradrec, ierr) + + !--make sure we have got all compulsory options (otherwise, rewrite input file) + igotall = (ngot >= 1) .and. igotall_piecewise .and. igotall_barotropic .and. igotall_gasradrec + +end subroutine read_options_eos + + +!----------------------------------------------------------------------- + +end module eos diff --git a/src/main/tmunu2grid.f90 b/src/main/tmunu2grid.f90 index 5d41bbe10..754f63a6d 100644 --- a/src/main/tmunu2grid.f90 +++ b/src/main/tmunu2grid.f90 @@ -19,7 +19,7 @@ module tmunu2grid implicit none contains -subroutine get_tmunugrid_all(npart,xyzh,vxyzu,tmunus,calc_cfac) +subroutine get_tmunugrid_all(npart,xyzh,vxyzu,tmunus) use einsteintk_utils, only: dxgrid, gridorigin,gridsize,tmunugrid,rhostargrid use interpolations3D, only: interpolate3D,interpolate3D_vecexact use boundary, only: xmin,ymin,zmin,xmax,ymax,zmax @@ -27,10 +27,8 @@ subroutine get_tmunugrid_all(npart,xyzh,vxyzu,tmunus,calc_cfac) integer, intent(in) :: npart real, intent(in) :: vxyzu(:,:), tmunus(:,:,:) real, intent(inout) :: xyzh(:,:) - logical, intent(in), optional :: calc_cfac real :: weight,h,rho,pmass real :: weights(npart) - real, save :: cfac real :: xmininterp(3) integer :: ngrid(3) real,allocatable :: datsmooth(:,:,:,:), dat(:,:) @@ -58,24 +56,17 @@ subroutine get_tmunugrid_all(npart,xyzh,vxyzu,tmunus,calc_cfac) ! Get density rho = rhoh(h,pmass) call get_weight(pmass,h,rho,weight) - ! Correct for Kernel Bias, find correction factor - ! Wrap this into it's own subroutine - if (present(calc_cfac)) then - if (calc_cfac) call get_cfac(cfac,rho) - endif weights = weight itype = 1 - !call get_cfac(cfac,rho) - !print*, "Weighting for particle smoothing is: ", weight - !weight = 1. + ! For now we can set this to the origin, but it might need to be ! set to the grid origin of the CCTK_grid since we have boundary points ! TODO This should also be the proper phantom values and not a magic number !xmin(:) = gridorigin(:) - 0.5*dxgrid(:) ! We move the origin back by 0.5*dx to make a pseudo cell-centered grid - xmininterp(1) = xmin -dxgrid(1) !- 0.5*dxgrid(1) - xmininterp(2) = ymin -dxgrid(2) !- 0.5*dxgrid(2) - xmininterp(3) = zmin-dxgrid(3) !- 0.5*dxgrid(3) + xmininterp(1) = xmin - dxgrid(1) !- 0.5*dxgrid(1) + xmininterp(2) = ymin - dxgrid(2) !- 0.5*dxgrid(2) + xmininterp(3) = zmin - dxgrid(3) !- 0.5*dxgrid(3) call get_particle_domain(gridorigin(1),xmin,xmax,dxgrid(1),ilower,iupper) call get_particle_domain(gridorigin(2),ymin,ymax,dxgrid(2),jlower,jupper) @@ -97,10 +88,7 @@ subroutine get_tmunugrid_all(npart,xyzh,vxyzu,tmunus,calc_cfac) periodicy = .true. periodicz = .true. - - ! tt component - tmunugrid = 0. datsmooth = 0. @@ -119,7 +107,6 @@ subroutine get_tmunugrid_all(npart,xyzh,vxyzu,tmunus,calc_cfac) enddo enddo enddo -!stop ilendat = 16 call interpolate3D_vecexact(xyzh,weights,dat,ilendat,itype,npart,& @@ -139,113 +126,6 @@ subroutine get_tmunugrid_all(npart,xyzh,vxyzu,tmunus,calc_cfac) !print*, datsmooth((i-1)*4 + j, 10,10,10) enddo enddo -!stop -! do k=1,4 -! do j=1,4 -! do i=1,4 -! print*, "Lock index is: ", (k-1)*16+ (j-1)*4 + i -! enddo -! enddo -! enddo - -! tmunugrid(0,0,:,:,:) = datsmooth(1,:,:,:) - - ! TODO Unroll this loop for speed + using symmetries - ! Possiblly cleanup the messy indexing -! do k=1,4 -! do j=1,4 -! do i=1, npart -! dat(i) = tmunus(k,j,i) -! enddo - -! ! Get the position of the first grid cell x,y,z -! ! Call to interpolate 3D -! ! COMMENTED OUT AS NOT USED BY NEW INTERPOLATE ROUTINE -! ! call interpolate3D(xyzh,weight,npart, & -! ! xmininterp,tmunugrid(k-1,j-1,ilower:iupper,jlower:jupper,klower:kupper), & -! ! nnodes,dxgrid,normalise,dat,ngrid,vertexcen) - -! !print*, "Interpolated grid values are: ", datsmooth(4:38,4:38,4:38) -! !stop -! ! NEW INTERPOLATION ROUTINE -! call interpolate3D(xyzh,weights,dat,itype,npart,& -! xmininterp(1),xmininterp(2),xmininterp(3), & -! tmunugrid(k-1,j-1,ilower:iupper,jlower:jupper,klower:kupper),& -! ngrid(1),ngrid(2),ngrid(3),dxgrid(1),dxgrid(2),dxgrid(3),& -! normalise,periodicx,periodicy,periodicz) -! enddo -! enddo - - ! RHOSTARGRID CALCULATION IS NOW HANDLED BY AN EXTERNAL ROUTINE - ! THIS IS COMMENTED OUT IN CASE I BREAK EVERYTHING AND NEED TO GO BACK - ! Get the conserved density on the particles - ! dat = 0. - ! do i=1, npart - ! ! Get the smoothing length - ! h = xyzh(4,i) - ! ! Get pmass - ! pmass = massoftype(igas) - ! rho = rhoh(h,pmass) - ! dat(i) = rho - ! enddo - - ! Commented out as not used by new interpolate routine - ! call interpolate3D(xyzh,weight,npart, & - ! xmininterp,rhostargrid(ilower:iupper,jlower:jupper,klower:kupper), & - ! nnodes,dxgrid,.true.,dat,ngrid,vertexcen) - - - ! Calculate the total mass on the grid - !totalmassgrid = 0. - ! do i=ilower,iupper - ! do j=jlower,jupper - ! do k=klower, kupper - ! totalmassgrid = totalmassgrid + dxgrid(1)*dxgrid(2)*dxgrid(3)*rhostargrid(i,j,k) - - ! enddo - ! enddo - ! enddo - ! Explicitly set pressure to be 0 - ! Need to do this in the phantom setup file later - ! tmunugrid(1,0:3,:,:,:) = 0. - ! tmunugrid(2,0:3,:,:,:) = 0. - ! tmunugrid(3,0:3,:,:,:) = 0. - !tmunugrid(0,0,:,:,:) = tmunus(1,1,1) - ! Correction for kernel bias code - ! Hardcoded values for the cubic spline computed using - ! a constant density flrw universe. - ! Ideally this should be in a more general form - ! cfac = totalmass/totalmassgrid - ! ! Output total mass on grid, total mass on particles - ! ! and the residuals - ! !cfac = 0.99917535781746514D0 - ! tmunugrid = tmunugrid*cfac - ! if (iteration==0) then - ! write(666,*) "iteration ", "Mass(Grid) ", "Mass(Particles) ", "Mass(Grid-Particles)" - ! endif - ! write(666,*) iteration, totalmassgrid, totalmass, abs(totalmassgrid-totalmass) - ! close(unit=666) - ! iteration = iteration + 1 - - ! New rho/smoothing length calc based on correction?? - ! not sure that this is a valid thing to do - ! do i=1, npart - ! rho = rhoh(xyzh(i,4),pmass) - ! rho = rho*cfac - ! xyzh(i,4) = hfact*(pmass/rho)**(1./3.) - - ! enddo - - ! Correct rhostargrid using cfac - !rhostargrid = cfac*rhostargrid - - ! Calculate rho(prim), P and e on the grid - ! Apply kernel correction to primatives?? - ! Then calculate a stress energy tensor per grid and fill tmunu - ! A good consistency check would be to do it both ways and compare values - - ! Primative density - end subroutine get_tmunugrid_all @@ -257,38 +137,6 @@ subroutine get_weight(pmass,h,rhoi,weight) end subroutine get_weight -subroutine get_dat(tmunus,dat) - real, intent(in) :: tmunus - real, intent(out) :: dat - -end subroutine get_dat - - ! subroutine get_primdens(dens,dat) - ! real, intent(in) :: dens - ! real, intent(out) :: dat - ! integer :: i, npart - - ! ! Get the primative density on the particles - ! dat = 0. - ! do i=1, npart - ! dat(i) = dens(i) - ! enddo - - ! end subroutine get_primdens - - ! subroutine get_4velocity(vxyzu,dat) - ! real, intent(in) :: vxyzu(:,:) - ! real, intent(out) :: dat(:,:) - ! integer :: i,npart - - ! ! Get the primative density on the particles - ! dat = 0. - ! do i=1, npart - ! dat(:,i) = vxyzu(1:3,i) - ! enddo - - ! end subroutine get_4velocity - subroutine get_particle_domain(gridorigin,xmin,xmax,dxgrid,ilower,iupper) real, intent(in) :: gridorigin, xmin,xmax, dxgrid integer, intent(out) :: ilower, iupper @@ -301,23 +149,12 @@ subroutine get_particle_domain(gridorigin,xmin,xmax,dxgrid,ilower,iupper) ! domain but the upper is not; can't have both? end subroutine get_particle_domain -subroutine get_cfac(cfac,rho) - real, intent(in) :: rho - real, intent(out) :: cfac - real :: rhoexact - rhoexact = 13.294563008157013D0 - cfac = rhoexact/rho - -end subroutine get_cfac - subroutine interpolate_to_grid(gridarray,dat) use einsteintk_utils, only: dxgrid, gridorigin use interpolations3D, only: interpolate3D use boundary, only: xmin,ymin,zmin,xmax,ymax,zmax use part, only:npart,xyzh,massoftype,igas,rhoh real :: weight,h,rho,pmass - !real, save :: cfac - !integer, save :: iteration = 0 real :: xmininterp(3) integer :: ngrid(3) integer :: nnodes,i, ilower, iupper, jlower, jupper, klower, kupper @@ -329,7 +166,6 @@ subroutine interpolate_to_grid(gridarray,dat) real, intent(in) :: dat(:) ! The particle data to interpolate to grid real, allocatable :: interparray(:,:,:) - xmininterp(1) = xmin - dxgrid(1)!- 0.5*dxgrid(1) xmininterp(2) = ymin - dxgrid(2) !- 0.5*dxgrid(2) xmininterp(3) = zmin - dxgrid(3) !- 0.5*dxgrid(3) @@ -355,8 +191,6 @@ subroutine interpolate_to_grid(gridarray,dat) periodicy = .true. periodicz = .true. - - do i=1, npart h = xyzh(4,i) ! Get pmass @@ -372,26 +206,21 @@ subroutine interpolate_to_grid(gridarray,dat) ! nnodes,dxgrid,normalise,dat,ngrid,vertexcen) call interpolate3D(xyzh,weights,dat,itype,npart,& xmininterp(1),xmininterp(2),xmininterp(3), & - !interparray, & gridarray(ilower:iupper,jlower:jupper,klower:kupper),& ngrid(1),ngrid(2),ngrid(3),dxgrid(1),dxgrid(2),dxgrid(3),& normalise,periodicx,periodicy,periodicz) - - - end subroutine interpolate_to_grid subroutine check_conserved_dens(rhostargrid,cfac) use part, only:npart,massoftype,igas use einsteintk_utils, only: dxgrid, gridorigin use boundary, only:xmin,xmax,ymin,ymax,zmin,zmax - real, intent(in) :: rhostargrid(:,:,:) - real(kind=16), intent(out) :: cfac + real, intent(in) :: rhostargrid(:,:,:) + real, intent(out) :: cfac real :: totalmassgrid,totalmasspart integer :: i,j,k,ilower,iupper,jlower,jupper,klower,kupper - call get_particle_domain(gridorigin(1),xmin,xmax,dxgrid(1),ilower,iupper) call get_particle_domain(gridorigin(2),ymin,ymax,dxgrid(2),jlower,jupper) call get_particle_domain(gridorigin(3),zmin,zmax,dxgrid(3),klower,kupper) @@ -401,7 +230,6 @@ subroutine check_conserved_dens(rhostargrid,cfac) do j=jlower,jupper do k=klower, kupper totalmassgrid = totalmassgrid + dxgrid(1)*dxgrid(2)*dxgrid(3)*rhostargrid(i,j,k) - enddo enddo enddo @@ -422,8 +250,8 @@ subroutine check_conserved_p(pgrid,cfac) use part, only:npart,massoftype,igas use einsteintk_utils, only: dxgrid, gridorigin use boundary, only:xmin,xmax,ymin,ymax,zmin,zmax - real, intent(in) :: pgrid(:,:,:) - real(kind=16), intent(out) :: cfac + real, intent(in) :: pgrid(:,:,:) + real, intent(out) :: cfac real :: totalmomentumgrid,totalmomentumpart integer :: i,j,k,ilower,iupper,jlower,jupper,klower,kupper diff --git a/src/main/utils_dumpfiles.f90 b/src/main/utils_dumpfiles.f90 index 7691ea5c7..aef612992 100644 --- a/src/main/utils_dumpfiles.f90 +++ b/src/main/utils_dumpfiles.f90 @@ -24,7 +24,7 @@ module dump_utils public :: open_dumpfile_w, open_dumpfile_r, get_error_text public :: tag,check_tag,match_tag public :: skipblock,skip_arrays,skip_headerblock - public :: get_dumpname + public :: get_dumpname,get_dump_size public :: add_to_header,add_to_rheader,add_to_iheader public :: num_in_header,reset_header,extract public :: read_array_from_file @@ -100,6 +100,7 @@ module dump_utils public :: write_header, read_header public :: allocate_header, free_header public :: print_header + public :: get_blocklimits ! generic interface to extract quantities from header interface extract @@ -174,6 +175,23 @@ function get_dumpname(filename,id) end function get_dumpname +!-------------------------------------------------------------------- +!+ +! extract dump size (full or small) from the fileid string +!+ +!-------------------------------------------------------------------- +subroutine get_dump_size(fileid,smalldump) + character(len=lenid), intent(in) :: fileid + logical, intent(out) :: smalldump + ! + if (fileid(1:1)=='S') then + smalldump = .true. + else + smalldump = .false. + endif + +end subroutine get_dump_size + !-------------------------------------------------------------------- !+ ! small utility to skip an entire block in a file @@ -1150,9 +1168,9 @@ subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags,tag !--read output file ! if (r4) then - read (iunit, iostat=ierr1) int1i,r1s,int2i,iversion_file,int3i + read (iunit,iostat=ierr1) int1i,r1s,int2i,iversion_file,int3i else - read (iunit, iostat=ierr1) int1i,r1i,int2i,iversion_file,int3i + read (iunit,iostat=ierr1) int1i,r1i,int2i,iversion_file,int3i endif if (int1i /= int1 .and. int1i /= int1o) then ierr = ierr_endian @@ -1169,7 +1187,7 @@ subroutine open_dumpfile_r(iunit,filename,fileid,ierr,singleprec,requiretags,tag ierr = ierr_version endif - read (iunit, iostat=ierr1) fileid + read (iunit,iostat=ierr1) fileid if (int2i /= int2 .and. int2i /= int2o) then ierr = ierr_realsize @@ -1253,7 +1271,7 @@ subroutine read_header(iunit,hdr,ierr,singleprec,tagged) if (present(tagged)) tags = tagged do i=1,ndatatypes - read (iunit, iostat=ierr) n + read (iunit,iostat=ierr) n if (n < 0) n = 0 hdr%nums(i) = n select case(i) @@ -1261,64 +1279,64 @@ subroutine read_header(iunit,hdr,ierr,singleprec,tagged) allocate(hdr%inttags(n),hdr%intvals(n),stat=ierr) if (n > 0) then hdr%inttags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%inttags - read(iunit, iostat=ierr) hdr%intvals + if (tags) read(iunit,iostat=ierr) hdr%inttags + read(iunit,iostat=ierr) hdr%intvals endif case(i_int1) allocate(hdr%int1tags(n),hdr%int1vals(n),stat=ierr) if (n > 0) then hdr%int1tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int1tags - read(iunit, iostat=ierr) hdr%int1vals + if (tags) read(iunit,iostat=ierr) hdr%int1tags + read(iunit,iostat=ierr) hdr%int1vals endif case(i_int2) allocate(hdr%int2tags(n),hdr%int2vals(n),stat=ierr) if (n > 0) then hdr%int2tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int2tags - read(iunit, iostat=ierr) hdr%int2vals + if (tags) read(iunit,iostat=ierr) hdr%int2tags + read(iunit,iostat=ierr) hdr%int2vals endif case(i_int4) allocate(hdr%int4tags(n),hdr%int4vals(n),stat=ierr) if (n > 0) then hdr%int4tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int4tags - read(iunit, iostat=ierr) hdr%int4vals + if (tags) read(iunit,iostat=ierr) hdr%int4tags + read(iunit,iostat=ierr) hdr%int4vals endif case(i_int8) allocate(hdr%int8tags(n),hdr%int8vals(n),stat=ierr) if (n > 0) then hdr%int8tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%int8tags - read(iunit, iostat=ierr) hdr%int8vals + if (tags) read(iunit,iostat=ierr) hdr%int8tags + read(iunit,iostat=ierr) hdr%int8vals endif case(i_real) allocate(hdr%realtags(n),hdr%realvals(n),stat=ierr) if (n > 0) then hdr%realtags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%realtags + if (tags) read(iunit,iostat=ierr) hdr%realtags if (convert_prec .and. kind(0.) /= 4) then allocate(dumr4(n),stat=ierr) - read(iunit, iostat=ierr) dumr4 + read(iunit,iostat=ierr) dumr4 hdr%realvals(1:n) = real(dumr4(1:n)) deallocate(dumr4) else - read(iunit, iostat=ierr) hdr%realvals + read(iunit,iostat=ierr) hdr%realvals endif endif case(i_real4) allocate(hdr%real4tags(n),hdr%real4vals(n),stat=ierr) if (n > 0) then hdr%real4tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%real4tags - read(iunit, iostat=ierr) hdr%real4vals + if (tags) read(iunit,iostat=ierr) hdr%real4tags + read(iunit,iostat=ierr) hdr%real4vals endif case(i_real8) allocate(hdr%real8tags(n),hdr%real8vals(n),stat=ierr) if (n > 0) then hdr%real8tags(:) = '' - if (tags) read(iunit, iostat=ierr) hdr%real8tags - read(iunit, iostat=ierr) hdr%real8vals + if (tags) read(iunit,iostat=ierr) hdr%real8tags + read(iunit,iostat=ierr) hdr%real8vals endif end select enddo @@ -1588,12 +1606,12 @@ end subroutine write_header ! Write int*1 array to block header (ipass=1) or to file (ipass=2) !+ !--------------------------------------------------------------------- -subroutine write_array_int1(ib,iarr,my_tag,len,ikind,ipass,iunit,nums,ierr,func) +subroutine write_array_int1(ib,iarr,my_tag,len,ikind,ipass,iunit,nums,nerr,func) integer(kind=1), intent(in) :: iarr(:) character(len=*), intent(in) :: my_tag integer, intent(in) :: ib,len,ikind,ipass,iunit integer, intent(inout) :: nums(:,:) - integer, intent(out) :: ierr + integer, intent(inout) :: nerr !procedure(integer(kind=1)), pointer, optional :: func interface integer(kind=1) pure function func(x) @@ -1602,7 +1620,7 @@ end function func end interface optional :: func !integer(kind=1), optional :: func - integer :: i + integer :: i,ierr ierr = 0 ! check if kind matches @@ -1610,14 +1628,15 @@ end function func if (ipass==1) then nums(i_int1,ib) = nums(i_int1,ib) + 1 elseif (ipass==2) then - write(iunit, iostat=ierr) tag(my_tag) + write(iunit,iostat=ierr) tag(my_tag) if (present(func)) then - write(iunit, iostat=ierr) (func(iarr(i)),i=1,len) + write(iunit,iostat=ierr) (func(iarr(i)),i=1,len) else - write(iunit, iostat=ierr) iarr(1:len) + write(iunit,iostat=ierr) iarr(1:len) endif endif endif + if (ierr /= 0) nerr = nerr + 1 end subroutine write_array_int1 @@ -1626,12 +1645,12 @@ end subroutine write_array_int1 ! Write int*4 array to block header (ipass=1) or to file (ipass=2) !+ !--------------------------------------------------------------------- -subroutine write_array_int4(ib,iarr,my_tag,len,ikind,ipass,iunit,nums,ierr,func) +subroutine write_array_int4(ib,iarr,my_tag,len,ikind,ipass,iunit,nums,nerr,func) integer(kind=4), intent(in) :: iarr(:) character(len=*), intent(in) :: my_tag integer, intent(in) :: ib,len,ikind,ipass,iunit integer, intent(inout) :: nums(:,:) - integer, intent(out) :: ierr + integer, intent(inout) :: nerr !procedure(integer(kind=1)), pointer, optional :: func interface integer(kind=4) pure function func(x) @@ -1640,7 +1659,7 @@ end function func end interface optional :: func !integer(kind=1), optional :: func - integer :: i + integer :: i,ierr ierr = 0 ! check if kind matches @@ -1648,14 +1667,15 @@ end function func if (ipass==1) then nums(i_int4,ib) = nums(i_int4,ib) + 1 elseif (ipass==2) then - write(iunit, iostat=ierr) tag(my_tag) + write(iunit,iostat=ierr) tag(my_tag) if (present(func)) then - write(iunit, iostat=ierr) (func(iarr(i)),i=1,len) + write(iunit,iostat=ierr) (func(iarr(i)),i=1,len) else - write(iunit, iostat=ierr) iarr(1:len) + write(iunit,iostat=ierr) iarr(1:len) endif endif endif + if (ierr /= 0) nerr = nerr + 1 end subroutine write_array_int4 @@ -1664,12 +1684,12 @@ end subroutine write_array_int4 ! Write int*4 array to block header (ipass=1) or to file (ipass=2) !+ !--------------------------------------------------------------------- -subroutine write_array_int8(ib,iarr,my_tag,len,ikind,ipass,iunit,nums,ierr,func) +subroutine write_array_int8(ib,iarr,my_tag,len,ikind,ipass,iunit,nums,nerr,func) integer(kind=8), intent(in) :: iarr(:) character(len=*), intent(in) :: my_tag integer, intent(in) :: ib,len,ikind,ipass,iunit integer, intent(inout) :: nums(:,:) - integer, intent(out) :: ierr + integer, intent(inout) :: nerr !procedure(integer(kind=1)), pointer, optional :: func interface integer(kind=8) pure function func(x) @@ -1678,7 +1698,7 @@ end function func end interface optional :: func !integer(kind=1), optional :: func - integer :: i + integer :: i,ierr ierr = 0 ! check if kind matches @@ -1686,14 +1706,15 @@ end function func if (ipass==1) then nums(i_int8,ib) = nums(i_int8,ib) + 1 elseif (ipass==2) then - write(iunit, iostat=ierr) tag(my_tag) + write(iunit,iostat=ierr) tag(my_tag) if (present(func)) then - write(iunit, iostat=ierr) (func(iarr(i)),i=1,len) + write(iunit,iostat=ierr) (func(iarr(i)),i=1,len) else - write(iunit, iostat=ierr) iarr(1:len) + write(iunit,iostat=ierr) iarr(1:len) endif endif endif + if (ierr /= 0) nerr = nerr + 1 end subroutine write_array_int8 @@ -1702,12 +1723,12 @@ end subroutine write_array_int8 ! Write real*4 array to block header (ipass=1) or to file (ipass=2) !+ !--------------------------------------------------------------------- -subroutine write_array_real4(ib,arr,my_tag,len,ikind,ipass,iunit,nums,ierr,func,use_kind,singleprec) +subroutine write_array_real4(ib,arr,my_tag,len,ikind,ipass,iunit,nums,nerr,func,use_kind,singleprec) real(kind=4), intent(in) :: arr(:) character(len=*), intent(in) :: my_tag integer, intent(in) :: ib,len,ikind,ipass,iunit integer, intent(inout) :: nums(:,:) - integer, intent(out) :: ierr + integer, intent(inout) :: nerr interface real(kind=4) pure function func(x) real(kind=4), intent(in) :: x @@ -1717,7 +1738,7 @@ end function func !real(kind=4), optional :: func integer, intent(in), optional :: use_kind logical, intent(in), optional :: singleprec - integer :: i,imatch + integer :: i,imatch,ierr ierr = 0 ! use default real if it matches, unless kind is specified @@ -1731,14 +1752,15 @@ end function func if (ipass==1) then nums(imatch,ib) = nums(imatch,ib) + 1 elseif (ipass==2) then - write(iunit, iostat=ierr) tag(my_tag) + write(iunit,iostat=ierr) tag(my_tag) if (present(func)) then - write(iunit, iostat=ierr) (func(arr(i)),i=1,len) + write(iunit,iostat=ierr) (func(arr(i)),i=1,len) else - write(iunit, iostat=ierr) arr(1:len) + write(iunit,iostat=ierr) arr(1:len) endif endif endif + if (ierr /= 0) nerr = nerr + 1 end subroutine write_array_real4 @@ -1747,12 +1769,12 @@ end subroutine write_array_real4 ! Write real*4 array to block header (ipass=1) or to file (ipass=2) !+ !--------------------------------------------------------------------- -subroutine write_array_real8(ib,arr,my_tag,len,ikind,ipass,iunit,nums,ierr,func,use_kind,singleprec) +subroutine write_array_real8(ib,arr,my_tag,len,ikind,ipass,iunit,nums,nerr,func,use_kind,singleprec) real(kind=8), intent(in) :: arr(:) character(len=*), intent(in) :: my_tag integer, intent(in) :: ib,len,ikind,ipass,iunit integer, intent(inout) :: nums(:,:) - integer, intent(out) :: ierr + integer, intent(inout) :: nerr interface real(kind=8) pure function func(x) real(kind=8), intent(in) :: x @@ -1762,7 +1784,7 @@ end function func !real(kind=8), optional :: func integer, intent(in), optional :: use_kind logical, intent(in), optional :: singleprec - integer :: i,imatch + integer :: i,imatch,ierr logical :: use_singleprec ierr = 0 @@ -1786,18 +1808,19 @@ end function func if (ipass==1) then nums(imatch,ib) = nums(imatch,ib) + 1 elseif (ipass==2) then - write(iunit, iostat=ierr) tag(my_tag) + write(iunit,iostat=ierr) tag(my_tag) if (present(func)) then - write(iunit, iostat=ierr) (func(arr(i)),i=1,len) + write(iunit,iostat=ierr) (func(arr(i)),i=1,len) else if (imatch==i_real4 .or. use_singleprec) then - write(iunit, iostat=ierr) (real(arr(i),kind=4),i=1,len) + write(iunit,iostat=ierr) (real(arr(i),kind=4),i=1,len) else - write(iunit, iostat=ierr) arr(1:len) + write(iunit,iostat=ierr) arr(1:len) endif endif endif endif + if (ierr /= 0) nerr = nerr + 1 end subroutine write_array_real8 @@ -1807,15 +1830,15 @@ end subroutine write_array_real8 ! to block header (ipass=1) or to file (ipass=2) !+ !--------------------------------------------------------------------- -subroutine write_array_real4arr(ib,arr,my_tag,len1,len2,ikind,ipass,iunit,nums,ierr,use_kind,index,singleprec) +subroutine write_array_real4arr(ib,arr,my_tag,len1,len2,ikind,ipass,iunit,nums,nerr,use_kind,index,singleprec) real(kind=4), intent(in) :: arr(:,:) character(len=*), intent(in) :: my_tag(:) integer, intent(in) :: ib,len1,len2,ikind,ipass,iunit integer, intent(inout) :: nums(:,:) - integer, intent(out) :: ierr + integer, intent(inout) :: nerr integer, intent(in), optional :: use_kind,index logical, intent(in), optional :: singleprec - integer :: j,i,imatch,istart,iend + integer :: j,i,imatch,istart,iend,ierr ierr = 0 ! use default real if it matches, unless kind is specified @@ -1838,11 +1861,12 @@ subroutine write_array_real4arr(ib,arr,my_tag,len1,len2,ikind,ipass,iunit,nums,i nums(imatch,ib) = nums(imatch,ib) + (iend - istart) + 1 elseif (ipass==2) then do j=istart,iend - write(iunit, iostat=ierr) tag(my_tag(j)) - write(iunit, iostat=ierr) (arr(j,i),i=1,len2) + write(iunit,iostat=ierr) tag(my_tag(j)) + write(iunit,iostat=ierr) (arr(j,i),i=1,len2) enddo endif endif + if (ierr /= 0) nerr = nerr + 1 end subroutine write_array_real4arr @@ -1852,15 +1876,15 @@ end subroutine write_array_real4arr ! to block header (ipass=1) or to file (ipass=2) !+ !--------------------------------------------------------------------- -subroutine write_array_real8arr(ib,arr,my_tag,len1,len2,ikind,ipass,iunit,nums,ierr,use_kind,index,singleprec) +subroutine write_array_real8arr(ib,arr,my_tag,len1,len2,ikind,ipass,iunit,nums,nerr,use_kind,index,singleprec) real(kind=8), intent(in) :: arr(:,:) character(len=*), intent(in) :: my_tag(:) integer, intent(in) :: ib,len1,len2,ikind,ipass,iunit integer, intent(inout) :: nums(:,:) - integer, intent(out) :: ierr + integer, intent(inout) :: nerr integer, intent(in), optional :: use_kind,index logical, intent(in), optional :: singleprec - integer :: j,i,imatch,istart,iend + integer :: j,i,imatch,istart,iend,ierr logical :: use_singleprec ierr = 0 @@ -1892,16 +1916,17 @@ subroutine write_array_real8arr(ib,arr,my_tag,len1,len2,ikind,ipass,iunit,nums,i nums(imatch,ib) = nums(imatch,ib) + (iend - istart) + 1 elseif (ipass==2) then do j=istart,iend - write(iunit, iostat=ierr) tag(my_tag(j)) + write(iunit,iostat=ierr) tag(my_tag(j)) if (imatch==i_real4 .or. use_singleprec) then !print*, "done ", my_tag(j), " | ", tag(my_tag(j)) - write(iunit, iostat=ierr) (real(arr(j,i),kind=4),i=1,len2) + write(iunit,iostat=ierr) (real(arr(j,i),kind=4),i=1,len2) else - write(iunit, iostat=ierr) (arr(j,i),i=1,len2) + write(iunit,iostat=ierr) (arr(j,i),i=1,len2) endif enddo endif endif + if (ierr /= 0) nerr = nerr + 1 end subroutine write_array_real8arr @@ -1918,7 +1943,7 @@ subroutine write_block_header(nblocks,number,nums,iunit,ierr) integer :: iblock do iblock=1,nblocks - write(iunit, iostat=ierr) number(iblock), nums(1:ndatatypes,iblock) + write(iunit,iostat=ierr) number(iblock), nums(1:ndatatypes,iblock) enddo end subroutine write_block_header @@ -1939,11 +1964,99 @@ subroutine read_block_header(nblocks,number,nums,iunit,ierr) number(:) = 0 nums(:,:) = 0 do iblock=1,nblocks - read(iunit, iostat=ierr) number(iblock), nums(1:ndatatypes,iblock) + read(iunit,iostat=ierr) number(iblock), nums(1:ndatatypes,iblock) enddo end subroutine read_block_header +!-------------------------------------------------------------------- +!+ +! utility to determine whether to read a particular block +! in the dump file, in whole or in part. +! Allows limited changes to number of threads. +!+ +!-------------------------------------------------------------------- +subroutine get_blocklimits(npartblock,nblocks,nthreads,id,iblock,noffset,npartread,ierr) + integer(kind=8), intent(in) :: npartblock + integer, intent(in) :: nblocks,nthreads,id,iblock + integer, intent(out) :: noffset,npartread,ierr + integer :: nblocksperthread,nthreadsperblock + character(len=15), parameter :: tag = 'get_blocklimits' +! +!--check for errors in input +! + ierr = 0 + if (npartblock < 0) then + write(*,*) 'get_blocklimits: block in dump file has npartinblock < 0' + ierr = 1 + elseif (npartblock > huge(npartread)) then + write(*,*) 'get_blocklimits: number of particles in block exceeds 32 bit limit' + ierr = 2 + endif + if (ierr /= 0) return +! +!--usual situation: nblocks = nprocessors +! read whole block if id = iblock +! + if (nblocks==nthreads) then + if (id==iblock-1) then + !--read whole block + npartread = int(npartblock) + noffset = 0 + else + !--do not read block + npartread = 0 + noffset = 0 + endif + + elseif (nblocks > nthreads .and. mod(nblocks,nthreads)==0) then +! +!--if more blocks than processes and nblocks exactly divisible by nthreads, +! then just read more than one block per thread +! + nblocksperthread = nblocks/nthreads + if (id==(iblock-1)/nblocksperthread) then + npartread = int(npartblock) + noffset = 0 + else + npartread = 0 + noffset = 0 + endif + + elseif (nthreads > nblocks .and. mod(nthreads,nblocks)==0) then +! +!--if more threads than blocks, and exactly divisible, read fractions of blocks only +! + nthreadsperblock = nthreads/nblocks + if (id/nthreadsperblock==iblock-1) then + npartread = int((npartblock-1)/nthreadsperblock) + 1 + noffset = mod(id,nthreadsperblock)*npartread + + if (mod(id,nthreadsperblock)==nthreadsperblock-1) then + !--last thread has remainder for non-exactly divisible numbers of particles + npartread = int(npartblock) - (nthreadsperblock-1)*npartread + !--die if we would need to load balance between more than the last processor. + if (npartread < 0) then + print*,' npart to read from last block =',npartread + print*,trim(tag)//' error assigning npart to last thread' + ierr = 3 + return + endif + endif + else + npartread = 0 + noffset = 0 + endif + else + noffset = 0 + npartread = 0 + ierr = 4 + print*,' ERROR: rearrangement of ',nblocks,' blocks to ',nthreads,' threads not implemented' + return + endif + +end subroutine get_blocklimits + !-------------------------------------------------------------------- !+ ! Routine for extracting int*1 array from main block in dump files @@ -2286,7 +2399,7 @@ subroutine open_dumpfile_rh(iunit,filename,nblocks,narraylengths,ierr,singleprec if (ierr /= 0) return enddo - read (iunit, iostat=ierr) number + read (iunit,iostat=ierr) number if (ierr /= 0) return narraylengths = number/nblocks @@ -2332,17 +2445,17 @@ subroutine read_array_from_file_r8(iunit,filename,tag,array,ierr,use_block) !print*,' data type ',i,' arrays = ',nums(i,j) do k=1,nums(i,j) if (i==i_real) then - read(iunit, iostat=ierr) mytag + read(iunit,iostat=ierr) mytag if (trim(mytag)==trim(tag)) then - read(iunit, iostat=ierr) array(1:min(int(number8(j)),size(array))) + read(iunit,iostat=ierr) array(1:min(int(number8(j)),size(array))) print*,'->',mytag else print*,' ',mytag - read(iunit, iostat=ierr) + read(iunit,iostat=ierr) endif else - read(iunit, iostat=ierr) mytag ! tag - read(iunit, iostat=ierr) ! array + read(iunit,iostat=ierr) mytag ! tag + read(iunit,iostat=ierr) ! array endif enddo enddo @@ -2393,17 +2506,17 @@ subroutine read_array_from_file_r4(iunit,filename,tag,array,ierr,use_block) !print*,' data type ',i,' arrays = ',nums(i,j) do k=1,nums(i,j) if (i==i_real4) then - read(iunit, iostat=ierr) mytag + read(iunit,iostat=ierr) mytag if (trim(mytag)==trim(tag)) then - read(iunit, iostat=ierr) array(1:min(int(number8(j)),size(array))) + read(iunit,iostat=ierr) array(1:min(int(number8(j)),size(array))) print*,'->',mytag else print*,' ',mytag - read(iunit, iostat=ierr) + read(iunit,iostat=ierr) endif else - read(iunit, iostat=ierr) mytag ! tag - read(iunit, iostat=ierr) ! array + read(iunit,iostat=ierr) mytag ! tag + read(iunit,iostat=ierr) ! array endif enddo enddo @@ -2458,25 +2571,25 @@ subroutine print_arrays_in_file(iunit,filename) if (nread >= int(number8(j))) str = ']' do i=1,ndatatypes do k=1,nums(i,j) - read(iunit, iostat=ierr) mytag + read(iunit,iostat=ierr) mytag select case(i) case(i_int1) - read(iunit, iostat=ierr) i1(1:nread) + read(iunit,iostat=ierr) i1(1:nread) print*,mytag,datatype_label(i),' [',i1(1:nread),str case(i_real) if (singleprec) then - read(iunit, iostat=ierr) x4(1:nread) + read(iunit,iostat=ierr) x4(1:nread) print*,mytag,datatype_label(i),' [',x4(1:nread),str else - read(iunit, iostat=ierr) x(1:nread) + read(iunit,iostat=ierr) x(1:nread) print*,mytag,datatype_label(i),' [',x(1:nread),str endif case(i_real4) - read(iunit, iostat=ierr) x4(1:nread) + read(iunit,iostat=ierr) x4(1:nread) print*,mytag,datatype_label(i),' [',x4(1:nread),str case default print*,mytag,datatype_label(i) - read(iunit, iostat=ierr) ! skip actual array + read(iunit,iostat=ierr) ! skip actual array end select enddo enddo diff --git a/src/main/utils_filenames.f90 b/src/main/utils_filenames.f90 index 2c2c22ee5..108eb2a52 100644 --- a/src/main/utils_filenames.f90 +++ b/src/main/utils_filenames.f90 @@ -216,7 +216,7 @@ function get_nlines(string,skip_comments,n_columns,n_headerlines) result(n) integer, optional, intent(out) :: n_columns integer, optional, intent(out) :: n_headerlines - open(newunit=iunit, file=string,status='old',iostat=ierr) + open(newunit=iunit,file=string,status='old',iostat=ierr) do_skip = .false. if (present(skip_comments)) do_skip = skip_comments diff --git a/src/main/utils_omp.F90 b/src/main/utils_omp.F90 index 07b462298..eca6876fc 100644 --- a/src/main/utils_omp.F90 +++ b/src/main/utils_omp.F90 @@ -33,7 +33,7 @@ module omputils !---------------------------------------------------------------- subroutine info_omp #ifdef _OPENMP - integer omp_get_num_threads + integer, external :: omp_get_num_threads !$omp parallel !$omp master @@ -57,7 +57,8 @@ end subroutine info_omp subroutine init_omp #ifdef _OPENMP !$ integer :: i - integer :: omp_get_num_threads +!$ external :: omp_init_lock + integer, external :: omp_get_num_threads !$ do i = 0, nlocks !$ call omp_init_lock(ipart_omp_lock(i)) @@ -83,8 +84,8 @@ subroutine limits_omp (n1,n2,i1,i2) integer, intent(in) :: n1,n2 integer, intent(out) :: i1,i2 #ifdef _OPENMP - integer :: omp_get_num_threads, omp_get_thread_num - logical :: omp_in_parallel + integer, external :: omp_get_num_threads, omp_get_thread_num + logical, external :: omp_in_parallel if (omp_in_parallel()) then i1 = n1 + ((omp_get_thread_num() )*n2)/omp_get_num_threads() @@ -112,7 +113,8 @@ subroutine limits_omp_work (n1,n2,i1,i2,work,mask,iskip) integer, intent(in) :: mask(n2) #ifdef _OPENMP - integer :: omp_get_num_threads, omp_get_thread_num, num_threads,id + integer, external :: omp_get_num_threads, omp_get_thread_num + integer :: num_threads,id real :: chunk,my_chunk integer :: my_thread,i @@ -158,7 +160,7 @@ end subroutine limits_omp_work integer function omp_thread_num() #ifdef _OPENMP - integer :: omp_get_thread_num + integer, external :: omp_get_thread_num omp_thread_num = omp_get_thread_num() #else omp_thread_num = 0 From 2ea5679d74cbe7a63454fc0765dfc0f6e1b94911 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 2 May 2024 10:40:07 +0100 Subject: [PATCH 109/182] Further updates from Upstream --- .github/workflows/build.yml | 2 +- .github/workflows/krome.yml | 2 +- .github/workflows/mpi.yml | 2 +- .github/workflows/test.yml | 2 +- AUTHORS | 31 +- LICENCE | 17 +- build/Makefile | 7 +- build/Makefile_setups | 16 +- data/starcluster/README | 1 + docs/developer-guide/vscode.rst | 10 +- docs/external-utilities/mcfost.rst | 80 +- docs/images/vscode-findent-flags.png | Bin 44635 -> 96394 bytes docs/images/vscode-format-on-save.png | Bin 0 -> 41262 bytes scripts/bots.sh | 29 + scripts/kernels.py | 96 +- scripts/stats.sh | 22 +- src/main/eos.F90 | 1617 ----------------- src/main/eos.f90 | 1560 ---------------- src/utils/analysis_getneighbours.f90 | 4 +- src/utils/analysis_gws.f90 | 12 +- src/utils/analysis_kepler.f90 | 12 +- src/utils/analysis_protostar_environ.F90 | 22 +- src/utils/analysis_raytracer.f90 | 86 +- src/utils/analysis_sphere.f90 | 2 +- .../analysis_velocitydispersion_vs_scale.f90 | 8 +- src/utils/einsteintk_wrapper.f90 | 132 +- src/utils/interpolate3D.f90 | 4 +- src/utils/io_structurefn.f90 | 2 +- src/utils/moddump_growthtomultigrain.f90 | 2 +- src/utils/moddump_removeparticles_radius.f90 | 4 +- src/utils/moddump_sink.f90 | 70 +- src/utils/powerspectrums.f90 | 2 +- src/utils/prompting.f90 | 4 +- src/utils/struct_part.f90 | 269 +++ src/utils/utils_getneighbours.F90 | 16 +- src/utils/utils_gravwave.f90 | 4 +- src/utils/utils_raytracer_all.f90 | 1199 ++++++++++++ 37 files changed, 1857 insertions(+), 3491 deletions(-) create mode 100644 data/starcluster/README create mode 100644 docs/images/vscode-format-on-save.png delete mode 100644 src/main/eos.F90 delete mode 100644 src/main/eos.f90 create mode 100644 src/utils/struct_part.f90 create mode 100644 src/utils/utils_raytracer_all.f90 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2acd7ba98..dccaebd65 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,7 +35,7 @@ jobs: nbatch: ${{ steps.set-sequence.outputs.nbatch }} steps: - name: Check out repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Generate sequence of batch numbers for normal tests, or run sequentially for scheduled tests id: set-sequence run: | diff --git a/.github/workflows/krome.yml b/.github/workflows/krome.yml index 25204531a..51302f869 100644 --- a/.github/workflows/krome.yml +++ b/.github/workflows/krome.yml @@ -32,7 +32,7 @@ jobs: compiler: ${{ matrix.toolchain.compiler }} - name: "Clone phantom" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Clone krome" run: git clone https://bitbucket.org/tgrassi/krome.git krome diff --git a/.github/workflows/mpi.yml b/.github/workflows/mpi.yml index 46099c9f2..1eb06909e 100644 --- a/.github/workflows/mpi.yml +++ b/.github/workflows/mpi.yml @@ -53,7 +53,7 @@ jobs: sudo apt-get --yes install gfortran openmpi-bin openmpi-common libopenmpi-dev # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Compile with MPI run: make SETUP=${{ matrix.input[0] }} MPI=yes DEBUG=${{ matrix.debug }} OPENMP=${{ matrix.openmp }} phantomtest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8526cebfd..d78ab7eb4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -87,7 +87,7 @@ jobs: printenv >> $GITHUB_ENV - name: "Clone phantom" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Compile phantom" run: make SETUP=${{ matrix.input[0] }} DEBUG=${{ matrix.debug }} phantomtest diff --git a/AUTHORS b/AUTHORS index 4b972f1d7..b139408e6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,48 +24,49 @@ Christophe Pinte Terrence Tricco Stephane Michoulier Simone Ceppi +Yrisch Spencer Magnall -Caitlyn Hardiman Enrico Ragusa +Caitlyn Hardiman Sergei Biriukov Cristiano Longarini Giovanni Dipierro Roberto Iaconi -Hauke Worpel Amena Faruqi +Hauke Worpel Alison Young Stephen Neilson <36410751+s-neilson@users.noreply.github.com> Martina Toscani Benedetta Veronesi -Sahl Rowther Simon Glover +Sahl Rowther Thomas Reichardt Jean-François Gonzalez Christopher Russell -Alessia Franchini Alex Pettitt +Alessia Franchini Jolien Malfait Phantom benchmark bot -Kieran Hirsh Nicole Rodrigues -David Trevascus -Nicolás Cuello +Kieran Hirsh Farzana Meru +Nicolás Cuello +David Trevascus Mike Lau -Chris Nixon Miguel Gonzalez-Bolivar +Chris Nixon Orsola De Marco Maxime Lombart Joe Fisher -Zachary Pellow -Benoit Commercon Giulia Ballabio +Benoit Commercon +Zachary Pellow s-neilson <36410751+s-neilson@users.noreply.github.com> -MICHOULIER Stephane Steven Rieder -Jeremy Smallwood -Cox, Samuel -Jorge Cuadra -Stéven Toupin Taj Jankovič Chunliang Mu +MICHOULIER Stephane +Jorge Cuadra +Cox, Samuel +Jeremy Smallwood +Stéven Toupin diff --git a/LICENCE b/LICENCE index 0562f6af7..ab1e73561 100644 --- a/LICENCE +++ b/LICENCE @@ -1,22 +1,19 @@ !------------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code ! -! Copyright (c) 2007-2019 Daniel Price and contributors (see AUTHORS file) ! +! Copyright (c) 2007-2024 Daniel Price and contributors (see AUTHORS file) ! !------------------------------------------------------------------------------! ! ! Phantom is free software; you can redistribute it and/or modify ! it under the terms of the GNU General Public License as published by ! the Free Software Foundation; either version 3 of the License, or ! (at your option) any later version, supplemented by the -! following two conditions under section 7c of GPLv3: +! following condition under section 7c of GPLv3: ! -! 1) The Phantom code paper should be cited in scientific -! publications using the code (Price et al. 2018; PASA 35, e031) -! -! 2) Any redistribution of substantial fractions of the code as a -! different project should preserve the word "Phantom" in the name -! of the code (in addition to the GPLv3 condition that this copyright -! notice be retained both here and in the source file headers) to -! prohibit misrepresentation of a redistribution as entirely new work +! * Any redistribution of substantial fractions of the code as a +! different project should preserve the word "Phantom" in the name +! of the code (in addition to the GPLv3 condition that this copyright +! notice be retained both here and in the source file headers) to +! prohibit misrepresentation of a redistribution as entirely new work ! ! Phantom is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/build/Makefile b/build/Makefile index 0ca66f007..e248ee4b9 100644 --- a/build/Makefile +++ b/build/Makefile @@ -465,7 +465,7 @@ SRCPOTS= extern_gr.F90 \ extern_spiral.f90 \ extern_lensethirring.f90 \ extern_gnewton.f90 \ - lumin_nsdisc.f90 extern_prdrag.f90 \ + extern_prdrag.f90 \ extern_Bfield.f90 \ extern_densprofile.f90 \ extern_staticsine.f90 \ @@ -538,7 +538,7 @@ SOURCES= physcon.f90 ${CONFIG} ${SRCKERNEL} io.F90 units.f90 \ ${SRCKROME} memory.f90 ${SRCREADWRITE_DUMPS} \ quitdump.f90 ptmass.F90 \ readwrite_infile.F90 dens.F90 force.F90 deriv.F90 energies.F90 sort_particles.f90 \ - utils_shuffleparticles.F90 evwrite.f90 step_leapfrog.F90 writeheader.F90 ${SRCAN} step_supertimestep.F90 \ + utils_shuffleparticles.F90 evwrite.f90 substepping.F90 step_leapfrog.F90 writeheader.F90 ${SRCAN} step_supertimestep.F90 \ mf_write.f90 evolve.F90 utils_orbits.f90 utils_linalg.f90 \ checksetup.f90 initial.F90 @@ -680,6 +680,7 @@ else SRCTESTMPI = endif +# 22/4/24: added setup_params to avoid weird build failure with ifort on Mac OS SRCTESTS=utils_testsuite.f90 ${TEST_FASTMATH} test_kernel.f90 \ test_dust.f90 test_growth.f90 test_smol.F90 \ test_nonidealmhd.F90 directsum.f90 test_gravity.f90 \ @@ -690,7 +691,7 @@ SRCTESTS=utils_testsuite.f90 ${TEST_FASTMATH} test_kernel.f90 \ test_link.F90 test_kdtree.F90 test_part.f90 test_ptmass.f90 test_luminosity.F90\ test_gnewton.f90 test_corotate.f90 test_geometry.f90 \ ${SRCTESTMPI} test_sedov.F90 test_poly.f90 test_radiation.F90 \ - testsuite.F90 phantomtest.f90 + testsuite.F90 setup_params.f90 phantomtest.f90 ifeq (X$(SRCTEST), X) SRCTEST=${SRCTESTS} diff --git a/build/Makefile_setups b/build/Makefile_setups index 85ccc0e0e..55347ffb0 100644 --- a/build/Makefile_setups +++ b/build/Makefile_setups @@ -256,7 +256,6 @@ ifeq ($(SETUP), gwdisc) DISC_VISCOSITY=yes SETUPFILE= setup_gwdisc.f90 ANALYSIS= analysis_disc.f90 - MAXP=2000000 IND_TIMESTEPS=yes ISOTHERMAL=yes MULTIRUNFILE= multirun.f90 @@ -266,7 +265,6 @@ endif ifeq ($(SETUP), nshwdisc) # disc around a neutron star - FPPFLAGS= -DPRDRAG SETUPFILE= setup_nsdisc.f90 ANALYSIS= analysis_disc.f90 MODFILE= moddump_changemass.f90 @@ -290,7 +288,6 @@ ifeq ($(SETUP), binarydiscMFlow) SETUPFILE= setup_disc.f90 ANALYSIS= analysis_disc_MFlow.f90 # ANALYSIS= analysis_binarydisc.f90 - MAXP=1000000 ISOTHERMAL=yes CURLV=yes LIVE_ANALYSIS=no @@ -345,6 +342,12 @@ ifeq ($(SETUP), galcen) KNOWN_SETUP=yes endif +ifeq ($(SETUP), starcluster) +# Cluster of stars (ptmass) + SETUPFILE= setup_starcluster.f90 + KNOWN_SETUP=yes +endif + #--- Bondi accretion/wind --------------------------- ifeq ($(SETUP), bondi) # Bondi accretion flow @@ -473,7 +476,6 @@ ifeq ($(SETUP), srshock) GR=yes METRIC=minkowski KNOWN_SETUP=yes - MAXP=900000 CONST_AV=yes endif @@ -481,7 +483,6 @@ ifeq ($(SETUP), testparticles) # test particles SETUPFILE= setup_testparticles.f90 KNOWN_SETUP=yes - MAXP=500000 ANALYSIS= analysis_1particle.f90 endif @@ -491,7 +492,6 @@ ifeq ($(SETUP), gr_testparticles) GR=yes METRIC=kerr KNOWN_SETUP=yes - MAXP=1000 ANALYSIS= analysis_1particle.f90 endif @@ -591,7 +591,6 @@ ifeq ($(SETUP), sedov) SETUPFILE= setup_sedov.f90 IND_TIMESTEPS=yes KNOWN_SETUP=yes - MAXP=2100000 endif ifeq ($(SETUP), srblast) @@ -688,7 +687,6 @@ ifeq ($(SETUP), mhdblast) PERIODIC=yes MHD=yes KNOWN_SETUP=yes - MAXP=3000000 endif ifeq ($(SETUP), mhdwave) @@ -697,7 +695,6 @@ ifeq ($(SETUP), mhdwave) PERIODIC=yes MHD=yes KNOWN_SETUP=yes - MAXP=3000000 endif ifeq ($(SETUP), cluster) @@ -710,7 +707,6 @@ ifeq ($(SETUP), cluster) IND_TIMESTEPS=yes KNOWN_SETUP=yes MAXPTMASS=1000 - MAXP=3500000 endif ifeq ($(SETUP), binary) diff --git a/data/starcluster/README b/data/starcluster/README new file mode 100644 index 000000000..fd80156c9 --- /dev/null +++ b/data/starcluster/README @@ -0,0 +1 @@ +file with mass position and velocity... (should have 7 column per ptmass) \ No newline at end of file diff --git a/docs/developer-guide/vscode.rst b/docs/developer-guide/vscode.rst index 2e32d871a..1922b1068 100644 --- a/docs/developer-guide/vscode.rst +++ b/docs/developer-guide/vscode.rst @@ -2,14 +2,16 @@ Coding Phantom in VSCode or Cursor AI ===================================== In VSCode or Cursor there are several helpful settings when editing Phantom source files. After installing a modern Fortran extension, to enforce the indentation conventions in Phantom you should use `findent `_ as in the indentation engine: +and pass it the same options as used in `the bots script `_: -.. image:: ../images/vscode-findent.png +.. image:: ../images/vscode-findent-flags.png :width: 800 - :alt: findent option in VSCode + :alt: findent flags in VSCode -and pass it the same options as used in `the bots script `_: +and yes, you do have to type each flag in a separate box. Then it is useful to select the "format on save" option in Settings->Text Editor->Formatting: -.. image:: ../images/vscode-findent-flags.png +.. image:: ../images/vscode-format-on-save.png :width: 800 :alt: findent flags in VSCode +Thanks to Yann Bernard for getting this working! \ No newline at end of file diff --git a/docs/external-utilities/mcfost.rst b/docs/external-utilities/mcfost.rst index 4b6cbf11e..b153f85e1 100644 --- a/docs/external-utilities/mcfost.rst +++ b/docs/external-utilities/mcfost.rst @@ -121,10 +121,12 @@ You first need to compile libmcfost: cd mcfost/src make all -then simply set MCFOST=yes when compiling PHANTOM. +then simply set MCFOST=yes when compiling PHANTOM. + + +Compiling and running Phantom+MCFOST on Ozstar +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Using Phantom+MCFOST on Ozstar -------------------------------- There is a copy of mcfost and libmcfost.a compiled in /fred/oz015/cpinte/mcfost To compile phantom with mcfost on ozstar using this pre-compiled version, you will need:: @@ -142,8 +144,8 @@ To run the code with MCFOST you will need:: You will also need a disc.para file -Using Phantom+MCFOST on Mac OS with mcfost installed using homebrew --------------------------------------------------------------------------- +Compiling and running Phantom+MCFOST on Mac OS with mcfost installed using homebrew +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A simple way to install mcfost from source on Mac OS is to use the homebrew package:: brew tap danieljprice/all @@ -174,3 +176,71 @@ To run the code with MCFOST you will need to create a directory where MCFOST uti You will also need a disc.para file + +Runtime options for phantom+MCFOST +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First, when using MCFOST, you should NOT let the temperature evolve between MCFOST calls, hence +the following options should be switched off when MCFOST is activated:: + + ipdv_heating = 0 ! heating from PdV work (0=off, 1=on) + ishock_heating = 0 ! shock heating (0=off, 1=on) + +This is because we assume radiative equilibrium at all times, so the temperature is set by the +balance between heating and cooling, and this is computed by MCFOST, not phantom. The temperature +is updated every dtmax. + +After compiling phantom+MCFOST as above, you should also find several new options appearing in the .in file:: + + use_mcfost = T ! use the mcfost library + +use this option to switch the call to MCFOST on or off. Beware that the code is compiled with energy +STORED, so running with use_mcfost = F will revert to an ADIABATIC equation of state, but where u=const +on particles if ipdv_heating and ishoc_heating are off (this is not the same as the locally isothermal +equation of state used in normal simulations of discs). + +:: + + use_mcfost_stars = F ! Fix the stellar parameters to mcfost values or update using sink mass + +either use the stellar spectra in the MCFOST .para file, or look up spectra based on Siess+2000 isochrones +based on the mass of each sink particle. You should manually set the stellar parameters in the .para file +if you are trying to model a known source (e.g. HD 142527). + +:: + + mcfost_computes_Lacc = F ! Should mcfost compute the accretion luminosity + +Accretion luminosity adds an additional radiation source based assuming mass accreted by each sink particle +is converted into radiation on the stellar surface. This is emitted as a blackbody with temperature set by dividing +the accretion luminosity by 4*pi*R^2, where R is the stellar radius (set in the .para file). + +:: + + mcfost_uses_PdV = T ! Should mcfost use the PdV work and shock heating? + +The only source of photons in MCFOST by default is from stars (ie. sink particles). If you want to include heating +from shocks and PdV work, you should set this to T. This will add the pdV work and shock heating as source terms +in the Monte Carlo radiative transfer. Recall that when using MCFOST we are assuming radiative equilibrium at +all times, so the temperature is set by the balance between heating and cooling. See Figure A1 in +`Borchert et al. 2022b `__ for an example of the effect +of PdV work and shock heating on the temperature structure of a disc. Typically it is small. + +:: + + mcfost_keep_part = 0.999 ! Fraction of particles to keep for MCFOST + +MCFOST throws away very distant particles by default when constructing the Voronoi mesh. Set this to 1.0 to keep all particles. + +:: + + ISM = 0 ! ISM heating : 0 -> no ISM radiation field, 1 -> ProDiMo, 2 -> Bate & Keto + +include additional source of UV from the background interstellar medium, so there is some low temperature even if +no sink particles are present in the simulation + +:: + + mcfost_dust_subl = F ! Should mcfost do dust sublimation (experimental!) + +attempts to remove dust in regions where the temperature exceeds the sublimation temperature (1500K). This is experimental. diff --git a/docs/images/vscode-findent-flags.png b/docs/images/vscode-findent-flags.png index 39595e0c32f67c6ac9de3859b932566b47b35ede..19dc44f180418c3c41c6364b31c853d04f63ba4c 100644 GIT binary patch literal 96394 zcmX_o2RxPi`~OWU*(+oxA;cjen~=RTvdP|iQwrH3WUr9y>`q8RR+5lSCo3!2`+w>A z{{GMFyq>4mc}~ZD-=ELty58#&p{{z55RV2AK@dU(c^ORv!GS+wbKzpce=x1e`3S;< zD9A`@`(&(4dYe+*OG6#~7P_O5_~PCjYZffBJC{(Y=c6wP)NKd{)bX@X?Rf2e@n3KD zuU{7P_s%@0`qIXYQbU^Q`BSp)J2Cus!n4*+PHb+KB;j;WpR*rXXXL*vHgsPM`}b1N z8@vI#S|lXLUz!9bgozk^nFL3Q1m~Dtoud8iig(4u)3y7OU*jlM22sc(CfpFF#nuL% z{9xo9f_uPC9p?K(<=?xw2VP&pClUDn|6UAq)QIH2FOvEihf9F`_b$`oJ)8^3e{Yj) zUBia&`0w)vq^+OKH`<)qj<1qMC@CuP)2x1emSy(x=qTjMEh|DoLf@vW@W~qI4-1>R zrF!&aWPJSmJ}o-l|NCh<3SteGk|usjL(iT)8yovQiEhc*bF#BL_&djW9=mk|bFad< z?0xtFIeFr6slKy7x`>E~kLXF{lcxi zeaY#9w8Fw;<6{rjbIqo0+9QXQl0~ifuJl>CySoqWy5jxs`hSWxAWS!J8Wm`k45d{x zkKNPw-r$Xohqt+je-zZB>b*IIjnH-O2Z+aY-qrZNysgJYS@6vXMcwQuh9mXq(G}GYnUuQG`@4TI`E3wp20@A z8)cc}zht+}>}^CD8H z)krIBsjBrtulA;DU1(zuVIqt0IM_;f{d%!Iig9`U?4Kt0b0`9f(QyHvyv>FFG-a!j zp>HFC%~m*4)M5LvzEabA{gWn?|K0pz#pIKzOVm=&N2?c7Qc^_dc1&k$YzJ@CtbTej z`0d-RTh*3)S5$84l*~;u@>P#g1PHRqrKAYT7HbdiJEEc=a3xn+4=nxUr-|vaT3xic zh&*R$G;L)LWtL$f8(k$z?D9F-iVz_vy%A|=Z(m&A{H3Y1v~+KdC-^cf=ZhEo{QM~U zVZ%nlsmaNL!FGToT1Fj&{dc0<%%~z{+S_kYM1I{| z=#i7#G7Qx$c9?p9K0rKpcP;bk)$YALpC_#-e*T%weFUM2sjIA%FVG~%S#tT2o<{R~ zd08(xCMv4GFVmdw3XhR+f6Rz=Um7g~gRxOyjFOrr$9-AZL6;06uN4wmjojSsj~|)K z1fp4diNf>C$_nc0(hf}>9FD#h4;~!&`G^L|$WVklsNtu+CIgh77ktyhWRb>#fCJ7tNI&0rnMg}L+9C;-9C^9zoWai24iWe=y z#IN1xib?M6F7#i>_hMTw$(0NJiJa;tj$rY z$K~jF^MAz(_n_532Mdwi7ZDzVD;ylW)zibXA7G3~Y7EqT{>+{~FyrzgKi_jAUPD8J z=lvfyJw2a$_wM=b!}iqFARioYHe1c`58EEJZR>p*z4YCa`^}t@5TpR(DTN{rD=IDjn^WE2($f zb==6PjHJ!(dVhWtdiYae7jf6kBk%6R2Uf%;Pf;p2Ntf@7wyQ=l2uo{*NdOd(rl z+~jp~6zWvJ{57{CEbKy5l=Z6uOVRybb@TJAQSH6k(j|mY9XL5fCI<&6Cnf?UnjikJ z2*mH?Xg#vCD=#W6w6?S?8Tx&4B2LhDi|_3(xAr8?%gpiYK0jXEkk!!Oy>{(@Slp+m zq=X##Iz7GH%^94Xl$5XjRF7-^{rek1EvG-KuKDk-VI%wk0-~o!N=r+riCG>tHkEmK z@6qVZt))cd(YtrFrzh*DxdS#B4EY)>@+>;~L8Du(HpeX*!gJ>W4X?JL1f9OW-~7Tj z=_H7l4!x=6<$d?%OYHRNNxe?VdBhYI?J#wuEiIj=S^Une;O(o2h0>&HnVJ6kZg;|F z_4P-^vnvYb<{R8?Yt2$qM;YRFKRiB$WjE8Wdv`F_a(WmnBik+`E1Rx-dvek!G;~l} zS{gyFU#}*?aYY-MSFvz&H&<6*6BfQ8_5Am5d!g9=j630ZNAL}k_0EEAsF)Z+o|dEf zhzNzjLKO+G6^PI9o2iueTTb zk(kR&37q6l^iP(jtAd{^sEzKw`r9%*@83YNH{<46dkf?(5@Zr(EO zJ^Qh7XGegJ4MD`S>+|z7X^+n#{4_U1m>x@-?yNMn8oSJ0y_zfNEU>e?J3p_gATR%> zwDcukfh0!~{OH*9d;&yXSvf(mfMSj+s-07(^a7H@{?kJkL9SfUhh;KE>)hAoH!6y1 zM{)7;4lHce)lBq$`Ev6{>gecbd`8AkFZ9KW7coD7`icfINpey|&h_YG0gBi=7DpuQ z?EFy3;_`B6e(=ACmcy8Iksd)2Xqg0G6BDzT?;T}RV^C63BF4vec4{6S86g)9W5P{U zj%0eKQ!-g;hAA`0k<|#xZ8vw-ei6$gpVCt>LVQu;Hb4I-LKn8~-d^J>b5B1%;aGBl zwy*p#X4E}Xwn+>GZM*~pwofe|4=z#D(Y-Ei4BGpHg&I|qjhY0{r=cj6c&l3%=_p{1?REWRr(4GRj(>gK+=ACRTT zl_lsb&4 zyJmb93*i?OJU=okMe@iDN9E#$3kU7y3QQzS3Yx5mqYgT2u%luzi5?d_BcK3VT3KC* z3H$pu%D5st4|{X|CN4fc`tCJ)qQimw@WaDHEJPr^w!VJBYv6pieaBqSWg{bc3)Psz z0CA@m)02~y{4_s*{sf#=^FW1(L@4-V;*(#7YSHxif7Q$KWyQs{3B`Odu}K6;?D{c2 zo|u-FmXVRC%~4@gV&~}Sg*I|)bbvyIF!?o2ne!TOu}0!i$8!A2bvkiWLJ25msIxTbW4La;BT6T_pY{(E!3!KmMmdts;~NhyV!=cdt{ z!FEDoVgdf|Dy2nbW$jkgmqMBI2lO;tBP{hPWZm62^Yii=sM{O_c6WCR3Jd$7e)Llr zzV{I)!Tmlm(wE(03jNus9$i$FUbqw%=2tOtEna@rYaIGyqaWX`YR`9iMT5R6ng2t` zK|Tynpb#P7zk4C)3wU{j)2#gb(VdQu&LcLqjkbJ!c*Mlh?>xsxtBV{34nxl4L+KxL zs9PQ>**cglFOLlg$@}*0`eS5hdRow;W2L5MOQD_&ABR1vy>uw7?$9W8eI#In7jhjU(obYVk`&JLkR#tP3kB?i_k5|8S+Y2}u zD$#Y)Qk(uDdHUi;sQqwhqC5-KEMMRA1qD%e?8UN6|}>G>Qqrs;QJ-RH;VG6m40DW)zzCf-MbPB>}n4N)x7xyhNq|3 z?*2zUf^RaYBBp#-oF`s$-$eSPVg%wvG;twWzMH3Fl2CW=f^8@o{C=bBL*j$0r+pjwFu6 zE+NsQ?N?KiXz#G6PhS;TJ4`f$rtct#jh!99-rgoJy8qFvlJJQ3pBLQ=|NOyyVph}K z{N*7ZHUdXao!!CF@s4+Sw1{MZCfcyPurTcL`l(9rK)9ao&ej38QKEXJ;JI|PGf`d)&-p!m|Cnmh#XjmQ=_HK4Ix2{en zyT1oj(`N-pSvdG)<%49)UKww{a24gjX`mtG|Cc zI6399ch9+bdU~2t&wIQp)#;g;nVIWJ*;yIAtUTw9HsVMcv#LHXh!nEpb-LD%8|mv0 zOip?(qrBDB1Vfk@;>NA2i3kaeTY@|nzVtVWy*!VdE6HTztI zOpGS<4#|6|$CYP0w(6x8p#F&InI4zf%dTnqi)}9P@{1cjA=lQ|&&6V-bN_e|p6EQ4 zzA8n+ox(|i8<64$TSeh76b0|niy=AV@$#>PGh@-bSf_bsOdzh|o*42dhY{su5g9Qj zm%jl;YRznf_*?Xq>R)dApZ>Odi^T|?tW-;6-nK6vvfJOo5SJS^9wDl4v^k2@cv2hw zV%2}=+jSs0TYJ`Rm-#b7j_5T9480=tv9|7vp}oxzw=nevTF+SpCnQ{5SrK*px#(?= z*)?yEyl+=)W$t_Lp1-4G%!q#+eakvv9G!B*Yb3bkCM{mucGq=Zt3NH(s{-yi*`U#O zlPfImwLD7)N|~J^^yyRamvw+w9e-3Ra3n=@7TL~!im-^&Mk?Lr(tiD-$RBXoTAZE9 zc%6`-4|Ml9C|G~AI9)KE!3qB=Zb*=WDWDkQ7l+^1YU@Kmby%^xFyhs1%^FR3R> z_1&fKCXq#K4GC4u)om5%RUprz#-;NPTABwj~{gnTU4DvFDZt*fcQIrnI3 zu&6(~oZPXwacSGN5cvv~=kVqylD%+EcRw6?w| zD4XT4#600+w9`%st!AakSY_dG|59{<>+t&qy@gV*RdxRYVU`#Nhp@OfmTVQE3MkvAcF!f5v`dESg}Hk_e|8gcP*I7& z3zcS$hodt)YnG&#l$t8Wmj}qG3q_!iP+YtOthJ-#U|=A=icOY8rU-5;rh3$&tgNp! zhVPeKqhdh^ib9H{N{@~_zxqKLf+Q)%VDu`#T2Cz==5*ONRl%t6dnF>Zc z9PGx%eX@vG<>kYsCal4KA|*3S9&VEYKI>nqS<|!oj|Z zFkQdCy&w@>R$YzJZ8?~$?iWukuAUw?g@nS?`T4@PZwKv1%17+lPy_|+Z|ds&I%A3Hi7rZ!XceiN z)HxJr7Jqb&HhU?_gedt61&Gl@|NosAK%|mYY}dv zcOOvEGR&jz_q+Zn8_Wc4*pD9#E(v)oewb=P=jB@jZKh90wv!=`47r2nQx^!rh8P34 zrto>*v!sOQut(-CzPWEt$!!?0_*FMM_#{G)YqY_2Fi%!VK0$_rg#?#?Xy& z1{m^c+HHGY0txr|?-_U86%s~9M$UK=_02O_ispEoBkTpZuSq9zJWwoc4z|eB3a5h(iK)XPWXvOE(vp&5%wF~{T*EbF zB6;=dRhbcb7Fc#m$89}!iZa7SVOUo|qGq3sqo&EUm}k!>;BjSSh!V8DH|A;kYF;ID z{krGjPImM04kH?k#=$;mh$Y9lvXU>)qQh~YUuDyWCDQ!PoyHqCikahoENuSu5q&Hv zcA~n$f9I^`fgHw^_XcRp58n>ZdH*0p#<*Fwj9+k z#{`@DZZ#Jt1s)68jW!fZ7lu1jhWRq?Q{V!IHl3Ia8Rmhp+U1gx3X#k++)PNDrOt65 zL0YESlDa8*f(RzkR6h(=+71ra)DVQXNs&B+-skLpg^HVN^1Uyo_YFFta2aOOsCG5c zs`Ik(P5!&;FHD%@ee z>DiATdg3N1r@Hba^!VE#~rZv(6L0k1A3B+LU_($9RSXUpYQ9tZ}@p& zXh>hjYixZNm=^nu8+QZ*f&i$mx16f}xdxFA*05U~K8#V`A4q+M{Z3F>AO;vSvb6-6BOhyU}Y#JEg1s?%U78DJjKX8`-6LiWR z0Jd6Qb~b$HVdmn3ASk{(6A-oJS-{B<4Q_Vu@mciZ#K#DMV&Jv2Vv9V#Uos3BBUL#o zBSX``z{pVaZm~8mf%~Qv25JyXmq9}%zo@ABieP9S^{&BVjQ2sf@SQvRKyL8D9uS2e zSND4{;eI?%4Jhz){1a%;3JN#yDY+7Q=71{$jBa+#XWg4SL;WINpO&}lYWS5{Ox6kR zYMjuEh;RCc0+CfxRwl!f6%!K!(Q*6m7*yYb%1W0^Zk=4*f#q;8Kmx^E+RXu^su^-y ztEx_cey`ZlNq_57jRy;6Bcb;+xI9!#uX;7C}>B7;5va|%9 zumYrnf`WpiWNuQt(BtF4!`*e>^gh6>F9phku3qJp2=4yzzEJX!xXX-Eld*HP{<@L? z4G#EDgn-!=uU=D_vWP3gZ6?6Mmdkhb@p+w-gUD*2CwIoDPddQ)I#XFr_OpZK5`NX# zw!>l(2mSgSfA?@_m8ki<&Bul<+WPUpeYgD|?!KZ~{Sv3I-u%Yfefw`SQ^b<<^76Vh zel+JDU-hbe04k;p|Cnj{(ag*TAmZqE!mf1v-QDw9(lT;#ULG}Z%Su{WnB|Joeu)!I z%WLi5x+cfr_0uPJb#*)Gg_|8lyJwUl^P=V2{`^rlo}vh0GU6U-4n#K=8bf1Rt(TbD zJP+N`;@qRQaN?ltp()oPz{YXneiaoJ^;K2k;^G=bQA5k&AT~}846sr}Qt}uplDtwZ zxPZ`!`Ry$ZvYi2eJ`XyP!i^40&qanLX#tIQK-32Y<4#Tb~ z-gFfs{`0*G+9Di@hPfh`ZJ31PDbdNMn(4z#!@%NFjNef3iZ=a8Jzl^UIro7`EsLt&xe_i)Z3 z6(gJQHOn0x7uGC;PAJyGBO@b?(9J+$`O^Rfrxn7v05^gBOza0!Ptr7Tdp2Hzhf5=_Yp}a zCs5xL3YUh5hb12+D_V|}-=F*SOQGP~)>d?tkvK@QBR9^f+SCUG31Q$1GwYc8LX3kw zK{RN{@vIXwD|d=K0#V#)u~_|SbXhJu2JZfLLQDvc28B^WWexZS%B+~peH-VdhvN?@ z0)$Ituytvm)%GV{DD$sT>)9^;* zA654NYz2*X1J}!`GCkvZsXcQ?+Z86XB9_DE`F?}e z(s4sv&_+)6wvHN>F^0`0q~1cX{=yyO#}fdI34ot+w7-pAHOn z4Af7ir>D=BR@oyr6n zTe=U66p6RKk6^=jW$0Iye50TsLYV{rF!?S9moMmRbl#%iT9mTJ3u6gUr=01bq4p#Y zp)QmtDl1FFC3~%qKUrr7CRak(i7KtCnw|8XwsUey6ZSml58A<}pl6gbrxw^KCf()i zKAxDI>=U#5QEjb@Do|k|0|f3rML`S_MjFLgH76bVsxIh0PZuv=W7$&&ls7pE@T4HvGWc7growCLc~1c%w(bEG*DWO;2Z}rS_9nyN(im) zBdQd*$w)cRnq!ESmX_9o2Vv^$hBY=-Bg;E}P2g0_ZtQXOTu2OA!*?RQLeQqnnh*9% zPdXVDmBbDLq84F(Vj}##LBcT7`~hk%Wkp3*6%|1mLd=?4@U<{A8X6jNa}ViUo3^kR z@Ofu9d_Yujm?8}`Ea?I;W`*;XlfqZBnrRFmCR+RCoC+?$CpP;9QWg$XSzH~c}0c)YHjv(g}@p12e&lm z-uKj7MR|GVAkE|9NB#Z#mlS6<*|M~(jA%_!q5UQ*M?b)I$xA5q11UZad^QTmORXNioCX1Fpi{oZ#IyhI0q<)$GmFGeKLzqrir-PO@ePx+98V(nmnwpF&?!iH- zHEY>xw+DE2#$G|h7iFkdX4NhJe)cXEPnQ3Bled$1q(T*!|DTzlMnfG``3faxc3ILbp$6t2g`iu=*3 zT1VFeZ9)jHR0x9XCb;2AeGT+Lv#bseCufRCEU&F$KWcZSYeR*Z{r+vYyRx5PkiFp5 zb@ke{Yk-a#Z*yu;%*h2M&aY)l1lN_9Cl{W>k&-X?wzl?VYKj3t{CmnMPulw@vdQ~F zCu=_XTWxZBPz%rtLlkuyy|njBjPc6A`czYO^T~y_uhe0)LRiS+%F5o+rdq>jc71v{ zsyyJ^&a~n~Yb@kmES;T0sWo*P3&4c2(NTsBqwei5%i9^ko*!-aE4iZb*z5DlMwZ3E zWmsIa0ply)fDIe77NE9rO&1u5*XmfK|8B}ce|FjHhMM5hEbr;#!7{@DN@QmH08p4- z^0vPhq*x_9Iji=kjAIh9|u`!yw_hFbgp<;lVb5KW8rgK<1jz~#pvPUxG zetc{CP5))9#VvYWkN<8tGZ$f3%_2M;L z>4b+eGOs3`Zl(7bUaEic<0a*ZZ$p3P))&WS9{PJEGF+7R?sYQZ@(Bq&tk&Q$!vpyTC4j{C}an^yZ=rfueCI4fo2#T8>=cDf1neJTTec^%6&}= zl=pa=m<}6$B7&{BGCbKTgP5bJ9-x>AlitnxYgkl&k1a3ZULa$S3=IqWJQoR$K*dPU z?P$x?s>x1NbSLIKHdf2DL?Ocq76lwBF$V9-=lxVN_d4ZSer9DcM77hspZ6ZMJOfd* zt;meitkB8vO)=8TmopO+!NgU~7Pl2hS5!**v09gwW>+ynOP-&8+uqA^ZVqkon=~Zn z-b5IoTB%{<1z8P<$x zHm}|Kvy3Qi2RS~6*Zw^5wTt! zBlJQar$E+VeM$f~q?zqP+aj&=dt+_>o40SPaHkv|fB*Amrq=%cxpT+FXj{0ZFf zqIw&Dy>w=5G!qm1T~Wu8QdG1uX>c)HS>0S3RMO_y{`3TbXK$^lm}s+awloajlKspSy~2r6zL%uYj~kCpEI``8~KZDv%NvvsszZKw)X zR+>a`?pZeD*-na*#m-C&?5#L1QKoP6dJ|ap`o(YUow84Mao3H#Z@la zq+OWlC&q%r<*k0vqMHT7D2sTMF zsq5?W3P_t$gFcMihKkH{fl?U&UANA$|JS_gtU%*K{b6(7L>AwJEd@lvI(vvJ(3zQZ>tbJ&`;C7ow|84L3?*04sAy@{G1-1Yd;xzI4Jo2fNO?0!@ z{edHO{YwZjuydsCfYu6zF{rO>SFc_|m?)K!ZyEp|J0l;k=^;+JDR~Zw{99jF_iKR) z?jtG1WXrD!c?5Xj+O>Rw3s2h2;vypEVxuDln)ZHj+SS(8*3Q8~^QC(1toVk8f`@gA zUT>b;^d-f)s*t5z_`0;z#-S9_QaoH42T(`A1-g58a}W$9sEE zA-M%$$-(YTi_7eL9a;g%k!55|td3^~pB{U6^i`-REC1TuS1qzIH8nL?#e()iU}PJ4cCoSaCB;|`h>yP)Ns8dMS_rkEHSb??Yj^M!WsZ} zuuWk11}%Nt-<|UJ?|u<-nNug9{a|N2*rU-9A{Q9$u^+wcwGTFbMpZlw4J9Vn$`o>q zX8L@`eZKwEqJZPr16|$2PKjm>*aYAbsupeTww#ttpAy~*13Cx0Er&7pVkWi+MovXe z4vtx}V!_h-db_KrnAly`M8VrhN-RHT%s|E6SRzAY5Bm$PNY%5weRdrzawJ@7_fowYIiGM(Mdc%LEpP%fdzuP?2e! zkFu1Cc&Q1->%>Y1+rz@|d3bxrI6|87gX@G{Ef~7WE3&9f3E{|9kr&PW&LJs)_;m3YNkr@^oKOh>XxvFV^dE5wu;v_R!L5tKZZ4 z?=0pp#y}WnFQEC|yRnZSi^2RnJoK*}tAylMvSssu-Fos(H8;Qm%t_ty3E>zSv)S+P zF$B`Xq&V?CbD+DIP z9)&1r&s)U;#RAPZe8eWrY_y_ibt+fHyb5&n*k}T1e(gyOhF<_VfQbeE=|orx@(A3& z*w_l)4Z(C3%Bbu7+BXur8jVov#>&yLEM2p+tuuSgWo2{3!9I7HNCGVW{O<%w&9q(w zWr3gnJH!-0I1uvNasfgmm*3=D?dtNUUvTVF$aBT(2vYl?+HZTz^iE_Rze<#hi3EF& zEo%dc2)Khnf~9_XADQSBW@BP39?&Z@Gcy(f3+&;s^-`F34TBl8t$K-#rN|r)f?8dj zz;w9?P0R%;5&#GSDz7UlQtU;go*PE=FSrZ0Fyv@a2##a9xYIUY&Q-@nD#uq_2M74e zMu-E){r+z;%Kl46*}VZ?Q36Spj5`oNX#|U|x!GyOE%~wJBlPX5@88w$dtTRzH4|$4 z3i>1YvWF0zQ$4<{MkY6rtcKI6Z-M3=FW0MyT{y_=H}Cia#4fbCv`kNb;|qE=Jum>m z?+eAG2W4{%6gbnG#oA{)8@1A#I%t^b))?SW*sNH9jp%VDA2z$A1U00%DC2Ij;9|=T zI8R(7_+J4>km&=~EpI_#VK7gVbl0&kj#zszJm5Xm0@A ztK_824%du+DrMm}R@7FerXSXKiwZ2cOqvyowL3c5;13+);#Yl?y}hY=-a>qDZjP!^ zxIgP=8!DQ~h1-<6$DFsmz8-kF^VHGSROLz_fT1jdWjuiu z&}<4pJLFMTmQ%%udv^I~Hd<06s7wIje5srfF){x8b1lb3!3QG-TJ(B|9)+wz!uyt@ zGsXk2AZmt>o0it`2RndH2yI(3SvZc4{lz* zJjb2lZk`E{{yGcGuer-`M|QuzFR>`R8KS8lr_Z>BLVcAG7AB*mtq(lJ2hOqW*94j| z7e|^f>gxy?AbeLk@B94vJPRi;Rk_)BGZEV2n>X*^0>r%6j^4iqjRhQsgX18GpiNDI zL)BzEm=fk&^&5ZZl#Glrck8kKbsed%Cg^Z-7&IvS{re42MnBOkFc;M(gzJlo zH=qIgE*0oPiVE^v`pNBQbu2?X@aJ%rAx6TSpGN#(@m%tG2(~_dPLf7s*lY-q&&bF^ zx1s6xqYci}YuQH+@0yuufRK#n5wyj~VH(}78%vK};iA3QPu!NiSqf*a6&GcVzMZ>4 zA?uRif}R9?CgJ-R2l-%Cz4l{c;8wqbnxdlb->xG4UG^BgVaMu0X&Ba|z8S9gzz$mu1zW3lk$G3tW$R8f| z-ZF6V_WHNVk!{b0$|0=F?hXn{Lp! z1u5z>ft9~=e20sYvMYAB!Fx3 zGXcgfE=PP~P23o(8w-xRW&n`2cYp zrvXOUke|N_BK_sdDGkKJbg{X)R}sC$E`A{)l-Gsx|HY1QATafhlDe?5M}o8*W+uwe zPrnAv>wI5&i+MXuBwmK7Z)w3CYflKMEHSi#x$HYXqsBX(Dx%K(_J(xfC!IYH-Kz9f zJcP@1dR|3{;fBB+(RGS3>;`5ZiYzV3FuO95y!1%JI!ge9oiy$K{Oq72NGyg$A%Vr0 zc)3xGSueT37TmGJfM)c5#h=!h`O0{f2n;dX-Pu`l>W+oY{o|7=&V0$QyR#a^$Xb>p z)805#fRzAe-0zAcs36O9xs9a55h)?_r?|Dt3ecU z8A7oTLWWe9*Ifp_w8G4@lxXk|!pA|M84U5h?%pK9-P+kPrIsUks?2(iZEy7wo$Pef8fnzeDoz1AIC|X)tV!9uK zYd7QNKRJ3`a)oZ*HtXZ@wmOILCF6rw`jqc`l?GT+-j;o7o-mJq!Lv=f19`ck>>v+k z&yMzXwaf<-qoc<6J?9=D_s73@@!n|?1Kp8{WQKJ^!b2!F!?dL7}HV``hrauoG39 z^Ha>;>e{irwCw1OG5MGmW>VA7w?Ec0q?utMOP9Le*Zk4CoOz9Pq^VXwLWT44<{O$Y z!>siURxyPH;u#)U2M0qdE25r|2&@nAEj`zdN-0zfUt!-JXw~rd^~@eTwwdc75qf9p z2V1<8$5ZpMf*cbWX=)-3CGAx3@&GH{}$hJrdSN%t*eAvV*9!0A)BBp!;u6r zS%^CdD8-oBlne#*ds1FjF?i>p51|gI!54RwB?JV-nVCPDR~^j~x70tlNj(3`o0S3& z%=MuqbIAQ(IEO%*|A$473agfp(Ik-HHpkh!uXOAg{2lf|v_c_!RSHT7e z?@}P2KfQnHk~%cIN?RA_AN6722kxD?Pc&nMe2XVNUR^r`)F^IZ%1^WA zVgcEVL>60qFG2qA$FhT@GTge)+RecU@=^;rOk~21VeNg$=O?;mdNmefSKDDq4H`RN zY6gn}tX0(&94U?@#gZXDfmjgA&T7etTSFKe&jg&v*cKsC28ehG(Rro!c^yWT@}??V zjQfhPM}~!Qkm59MdZN!ku2=gFL6}B%zhEJuXpGz~Vd0OLnQ>tZ1|sT}51AR_sL06d z_)1%?PM3a~M+>{xZ;KF%MZT@#!6#7ogR5YbXIJ^a?!mW=c?s;!p%V)3+mF78#_ z2~*U>+FN-R&0KXGRJ7_*D4T+2!M7g{Iz@x7;abWEYQq_MK1MR1hYqF^Q-swi2$L@L z4zJs5nz%VEz6nir6bp;n8H)B-;+_=~5WKB@)oyRHID(Om_nlqZ1$k`RuW@m7C<=X) zm~s9KL+3>a@7i=TJjO-x7-bR2^qGARz^y?`8S_IvA<>Ckn;yP)cuXt?r>6&I6T| z0Z0Q;1-PJFq2qS<1B9fLICa}UeKM#1g4&ufJuNp9f!t6smp;H>xBk~1rgZEQ{p`>I79k?nf-OAqz7)BO>bEe0X8=*m8!wPT1LVQ+hP0l@9 znLM0}p{jZK1F$ShQV1$8~ zQCxEH@mctelM^NgQ#hvrHtD01b4Zy z0r9j3?(i^tc(s`zkcg-q&f~3 ztRJK@z~~`%x|j-J+;3YL@{W1zDz`vELwl{#(XCuWKF|F%Ir^y!a}iZl&97}Be>+lc z1X-NnB@g5gNG*cX0Yxn>yMitIJRwY=J%35PmC{dD$@Rx?5=PEo6i-~hCt-1A-=y zB|*8GMq98e2{d90!Lhj@g(#TfhU~F@-*=2>x#PVS0)vkbo5qoXslx5$ z5hA)D3vPF?kbcokLoctX4NUmvUp%nxBJ&_t3R|$axbaJ1Ad5n|el^?_M_i``bzxIe z-@>7nzTCz@?uF{*k3&w0L+23GOCtm!kVQhi*84>=Ka0ytts0pfuD$N^f~6Aa+dB#- zqG<%k*c5aiGOxgl`$3(8X{I;HDcRE2FTjzE^a?Z8e({I+O-G^>VgzO9m5UpKVOOcP z=#OPW+B&GDzwTcA7ZHq%Q}fvwU4YqXIwEwtd3@JHm|%e9Z~a+5%E+ipogK!Y-5Qy% zU+-J;XfWh%nO@&$IERIYkl?Cwr}QjuV}Iy=__neVm85tcsnp}*PKnBU4MJPJgKs3- z7kp&Jf;2Ek)!74%w@>9Xv~zI@@$pUGKD?tc2w7=%3b}io4xnV2z3fTp=@bCXAg;6T zxJY#{dVKYlQ`^G)JQS7pFbkNf%$=gdt=pS%$Dmldd81?5syd<*6CN5mz)#MYZCX8A zsuKm7Lj^uAuIR$0m(-c9C`FAE2wtnCXRWNSW3nzhlgWd?Ik}p{hL0$C;%<#cNxCPh z`2#PN<%$MxBq_o=y-*y2Ko7C(z8Hhx?&<51ZS@U2m zT^jBWc>3Y7Ij`<(ITF*_2ViDQuLGqUZ9d-rH~qTk*7!ov(soIcj!pdNk5OdaL%vj< z5*XVf#IeaAkk@#jLt7WHuSnMk2?ETvpR*W;*`!lZCx*ehXL!yHh6N#o*=X2$-GdZI zLz_Rde*v=dvCDjsdE@mh&r?#I`DwT)tJT>Rm6U?Ppz&YGl$d-!N=-xaW+*Hsa|vd% z!HiuixvHR zUlf)|%&nzr!ifXSedBtkCp~lDmbZmsVeJZf*`hmJo>6$pi^R0ZABl#B$uzjLI&w7hv}1#;f&4xbKRB{vJl^f$_Xry znjoL6M>SOw*U7yom<|U^lQfQn7mKl8SX7iuHxw5OKUznyC*+Q76&dNeol&q~-UF&D z9~Vd+jq<4~cKrgdfC_2W-q`q!p&Hl3yx8DXOpoj(W@%eUMV~R(#9|7hlU+r+fm~&WRMm0 zs>L<93Ole5oqc_{a!8jNCwSl1@Az=gn_B zAD=yl7m#1Ma+xXx#eJ5dTW{Lcv0eHG;dJl`0-@M#90o$ytLjXKIeqZ|q4^UK5xpub z6g$}~1pf~%bZvBVyU#R)3GAtN9!t_DCKc`GIwz;_J3@T4M^aIL+}AUw&~o2iNBgal z$v&H^YV9DZv+bxFiOp1bOUst-@D{z_+?Uv&&cOENU5aTmA+^IG`n5FnCC}V2{@*Zm zwREdKFxZg#Aqf+T3AMfs(bRYDJ&oR0p90r?`~5xqo|0tq2)X9@OgA^d?+5^%3ZYTI zrjxI^$1vPVL@e0!=cAHvCQvY#yKT4T2ExEBJEEIluMbi$E4_EaaudW1394T#G-PNh%q)yD2 z?r#0s->INKG);XSFiZV>FT_$qUmwyo#cONa=)i~by?1c065NHD>GkVu00m(dBxtWK z7^3DN=}c5%Hcw7YK7PD{PsN=j;OOV>uI0KhJ0lWw} zJluEt_WiT@^d%RelZD`*y9q42{DQBGi>uJ+@rRKw#REGa+D{@4CWv`eLw?&g7(csj zkNHW~J5Qb7S7*_=&>2US-Zy{Se)yiOEc7d2T`IojgJnCI?Ekr1%xP)_Xnbl>8=@!+;ySEO%Ou3xC$XTd8;{Sv9+Bs6au zy%=mg-kmEXu{5kPX89F?^FGSxnl3hit%h3uJ9sT1$WGDf;iFgQ13o%vqMIIDSl`6W zRc~^b`?&Roq@aiV&jGe(#D~B;%SJ^BqIFEyxfMqQ7bz}9=xdqR+I9JlbC5{iaJ{-Q zAY3b*VLI%8{6gmQt$Q|M_e3vm2bLtivcFGOrr3S$PeCvq^K&g^-Kp zU#=>PphzmKru&mMHR$;8p73ogt|3~tnbbE!8|&#>sYX8Xfoi<_K5_UP#*a(7%kabW zG$S+2AssJhnMz*6Z*wUkMpXHm|A2;;f0OmMC$=N$BUk#D)<*5qXs#<5_bTvF5nRd1 z2?Y6LOvhm=$up?@*|#^R9d~0Z8X{)>^g%GJj(!L+3RD8K!q#@lcXP=Kdn3|<_7fyY zP)%b|=w#zI%gV$&ylWxy1~mXC7D0veg&f~q$EF;~2ns4VRr9ohX^HSd*xS!;-MY22$aZ1H z3o3lv4^DE%VjM_I#3>Dn_$|N0c>2Xls z9USgLM>0L_JJ(PFuV|o>OmOx10^~A^UL1Z^r$`IfiWixcgAQd2ZHziscLy1wmE*Yl zRMg$b;6K(XB@2to%F1$BY`vaT2mHQ0J$0h!ar&bc*3Ys zDxf|(Ihm{R1O8bYEy&pZl81Af z-JJ#I_e^xH3_^8|7c?~mH}2+oZ%*~ck0@IEMC%P(psfo`sGmXv7`{*i`ugl&! zb?n%eQKz8Ww;`WUh~K!Tt{y-$HaU4c^Gv3CPD5=i#Z+S2s6xEBrLFC5UiQno*d?1| z#B;j>%e$UU<2}JUgDvpJ;-q$&UT@e9m!)l-bRpFLbM3cJ;Xm_Uo96FxR8i=9fBazTiNWOT)fbII^Rw>DzU2Zr{Ovl|daYbn zf@QksgSZCOdt?sgvPg_BHLI1Xv-Q$bkB7xPMupk zae-iW1$zPmfm4*tEiJX((+>UvBF@6-3K*FScj)8oPa$=NSkO&9?Hr!NdAINU{pL|7 zM(X<}Y!bdMaLK~>L=m{<)`fIzYMGe?>iMytRG;Z}i*LC5Qa^o~J2EoTp~T4K!@-FR z1I_3YF3*%W{YC6cyW17N4Z~|ai4BDz{oQ2$)}1Bt9+XwIL}*#Kxh*006^PT}-2Z!J z3$J+GGNpo!@Gc_f$&)7qek+TqF&(EN0yhMInuvEyy+xtc@w`i6(nt1&FjMVzU5cPd z=CqvdVH~`#1A>okyg6*J{&mgL#?Rpsoppl~4oY6CBBdN58glG_0V%P2*cU}fzD8N) zaDAKY4??slN}8v_&K?*%%F91#9Bv)o!y7ZVw&K`sb{y3az#EEj0yj~yV2}eV%+Kn! zOTml1-#F5++}gHejcsQ5wJ5ohdqawk3MzcJR-d{H0sypk${F9r_w2f@jD?U_d0N_u zZ7x}AnVpl7^#=fT(SC30)%_nCR@uqPqQb(*_;T2Ue~4ly3J3JaSF+5)!H*|do&OZE zn%7>Y(k$f3OljZPc>OzPGWyw84x^Frk3NMB-a8bF-iZCGo}%^jJ7xzBYX0Q|hte!3 zUrn9wc|TZ~A2a8_U-_bB>|@ifehmqGZ(N`_!WHyxHkM)!9f2*-GX9SXtJN{CH@3Bd zi{#G^lM&5_n~nv3jYvH4=!(>;qM(8o4Sy9ssVon@0%d?#IVQ4oCIUsBVvAfpSR2kv z!eY!*k2wiVu~s(r=*Bf0!b~Y$yM)AeFQ4)ZKf@llF_VAPJ0QHFG?Q7sQSCjyYVWs- zar1o*ujop%USErltsR(~>5B~xirx^bdAxOhcdHP06otj(Yqf#fv#me$AEgjI)8j{z zcm8b}4a%0%j`I$=j?dV{CT4GsMn8?r+)n1}zU;4eQg2BkTJJH-R`ha zRP>Tyaz$3R-bM9$6sdl~oPdV>*4Or9gKRL{T2NL|_|u6d%>FpvL}rI=xnAj_W`^p} z(kj>8w_%UdFjs&s?YD6FMT(I$rzdiG@@g6O)%Z6{= zN#X2=;u;3ebpYFf*dZzvIMjZ~pT^@we~z&SZSH2Kudl z%CFzQYwGGcPd?^2)KNSOpYRud|BSA$SWvYK)H{CobxV|Yg$6?>{tgi z_mVUHYW1(7;kT2E_Xg*euW*YLv+v`m{z`e`-K*T`=E&1@-ekMjozh-pCYQ%N8=05g z8g9&8;#N8DW}`rsIP*s~*L-i9bEegyu?fbIh_)NYZVMJ_AE|0pEb_Ic-cE33B$Zfs z_L~Z(nr${kR)xa3%b)zN6_N~q#r;W@>G1<^?4wU!oH6?xdo=Qn>*OEH`sfBQFEU%# zf6{HHwpv!yg^(}I&%e=8WVuSiz|hv|IhrUKCXL0Sw6yg;t`v97Q9eIDBa@-p+M-&v zI;D+y2t`uj=9&a(K{;BEZ(mH(yIvV|62{UUV*$Rb>t$~KmNU>{}^8=TNz@EiV~{pFTcg; zC94q)1-OQnmzSmGfXF3;sGQR4)yyNhf_*2GaM52+;#-p?} z>BnXtdp;crgd4I@R}kLN%G{$Q&#N*P$$h6iaTSl!JG3oR&5C?WQvG1T_bi*D_*LG( z;CTOsH!@YZGgQqAsXRre7#n%&osZhf3fRr`m1Fr|XYyM!-wbQh*hh~KTS&_my7Ro2yTQavh+I07>wDS3HCn{^lKI-rum%7Fs1^Cd^)hAH& z)ctaO_FC*xe#;Efgu(ef@@h|7Nz4s80^>i8MC7*%E6L z_oXMN;U&M#Tyd!T4y)fPf{yc_tBX0kFG}wZ>Sq^TseGtVd3LKEb=O-FdICR}u!x8q z6ZGmZeSfrvG&)N&|7jx~Mh297bX_^Q6`FZMF&vXiE$@*iI2Ud&#hsa%Df<9oLeza) z*;9&zZ?m&oN1a}@j!A_^W1;8IrpoQ?v!M!e{P*wfGE|iVv&&xM^?7IE7cAUMZYUUZ z?AWm#>J*D%U{>m#sfxs-%YM+QBfcEloF6^?{yj9=pF%?FDptD_F@*DFUFxB&vCmL- zDT|NA;vu~`sd+Sp&-cmrcAy(pE2(`7TqZqU?s`}=0Nc1$c69tz?(^rXtyv^Q*0yur z&Fhreze~!-=BX0r2YcMSv-LN-Y<*X2(i8Pg&#u=F?n+W}DtpEjn(A%xA^PdlxW|uC zZ=*W?sC%>0U#enb!HTbJ-n&Gnsk3u^G(Em}$EHy(IlJJwj>gs`=&g7{9qMP zyXV(Y3L@uzUj2>Y3v7^4GIgFfCRU z*=%+^=XoU$549Ijb-6W!vxrDF$(3~U|F(~Lnc=-`l-@92;nb<1Oj*Uhmo{z8OAmmU4Ic=GN)rj`K{(4;w#6%);Rt9bdreC$igvKq$V-eBR+4kRxZ# zthZNeBw}PWV(y4pTJtE+NwL#{g60BJ_e!q=wn4O3R)(5t^S^?EUo-voX&$K-Z&Fjw z18)J785oF<>JNb7u;tcFxM;i#STuWBBz&A&U)+EqjDeZ?G@yl;Opr)HUn`7j+C&_1 zTkLIbkGX&UQGER7`t%&v-Ji!U(U-pOGw_v{pBRXcI7CMW5p)b(%_wqp6yxMKpl5Aq zQDqi(>KkbaXlfez_3M%T#&31NhP=cjpzvm+5j?Ah<=U3Y)@~m7q)DFo#KzTXzK!gh zoTV4)jfpw3SNXKxx{Vq~h(*T6{<1rV!2q<}SFY?6`aJOd_MaKMX8h)iCUaWiwrwf^ zAKo;HweBrmgd&xcm2ixs<}ebUe?Ujb_HJ3n-h4jqwUbhOv*6 z>&0%lh2`bt*uNf*gt5lU&F#rfC0b%YK*08ZQ|#*rr3GJJ>_$|W`G~)-aFcL?8)fpQa8p5rHwb{hj*xitju)B9zSXh3P%!M-Qkma;b zF0Jm_KG5j9k%%c5T1)H?>gu?Xk_@k3j{+k>@#Hhk7ca&{g(iM6zNa}zmk}8f!XBUg zW>ot2GqmafDI0_{H!LY5E*Ne%_19$O;W<6FOI2twaBMIq>#4)g+v zrcI=36ylrOOhZGz(G5w~b8PW{N2#?EBg1gn;fZGJIs8J!^eS^o@3D+ll+Jhx78Zy0 zZ5Fdg=sk&wI(<{C|8!#(H1!7bXCXcYrYQ0ew|HW$te|vo#^I_nahDBmGPezw3LV-b zrTjVW#g}B!xrd?O8iky$?N3pYQy#b^u`=e>?zfM;q~(ZVtan{+Xqm z;k7n<91dapLra7Pytll22i1g>vBO}_r;O~EFS9Z-6fZ-ta^(j7AB<&qH{B<$nLj42 z%XN5#;toRs{Fz@K#hI+^b5-urx5q+h-aPR4TCo%Q+`IlmlLTnZ5yFB@MN(kq#*Y3Vl(9%vxm!DwJ=R{{8!tI@Nv(a$Ms}O5Ev#w0WY( z8-lL`;I=$-3qA@!!-=;2dSZ44fO;lK_!@e7 z8F_gfCPK%&gz}<7lqa@qtrt?&7LKC{jSUS~t~M%h{?hj;@y1E8g-qhuv9qFG9}+f3 zn~z^j5I#SZRW(q$;e9eFi7PIWCsa!~h<6*I>(ju|c+{R&466>xRWYCC7XQ>8N!Na0 zyhp3>QJG-kg%}M^4W-yu);8QyO){DE5}Fr&$J9oH3>Go z>M}NhibwFq3OgB$ev>KLQYom=-lm2LH9$SNy&rNa;wj(EU%n)$usOiW3b+C8tz0T; z?13I09zQzy($dm;l_}qaFHy-!u6}ry13U3FF%hb2Odrp$6KO!7p-D z^su~CGf%|3KS2pyN@Rgw|7-Bhd+S}j*0SyPPL75dyS16PD=F`|9&=@n36Aamp3$E% zE6sAN$hA{3N}uYDMj(wc*M}=+M_1RLNhrBqC)kxWXWKAvemb4cV_8VK<0WednVpaU zh-y7dqsJvyAiRWOa0PA3TZnA#WksDxMA?Bs7vQ@eCYgW2-jJ_&qvQ4D>6b1G-DYQN zY&vFid83SY9&q@sk8e75TBMjcW@+%?6Y*<`{#}uVTQNK*lzaBP(RpdF{?1;MgF`i^ z{X~>paFt=cCRC%vB71H29t|=C1UiQy=|s#47)@k3@;WCmlf;xFy%~jU?ot+g(5RCK z1dqxYGSb%G-rjpdRN4BdfkGFx$yNig4@^}513#q>U(<-K8+E!D@6GYBZqIgXG=DnG zo+l=KHQ*mx@CcE#EQ%l%gw)jb3WIYi$5c2JRCMaDQC*w?6w3VZ*x1;wDeC>ZQl(QC z;96X(q+o|%M9m5!=MwIRyKW0`aDYK3lAvfKeY#K!M%s7Ys}%lU%?lvAuL=30xLas< ztSra3(fM7szfCW}ZZrn|TIYIA|kOAI_Q z1woz9j~<~X*L(Ng5DpHGmg%K!GAed%qUB(Tjqg#;aKfAE)FMuLo@eo@6w?`3UHZTvcoUJk}MIqjXTt?V=uc&@$EyY(z7tJGeueYtz!1n8w3Ys079j{V;D#z z^K<8Fy}$V%2g}^MRrY7S{=QsrN-+{Sb53U>$^CJ5(HGd@V*WPl~&(lR7y!w~qQ)rY0 z>&v(g{(gUHzd*=;zO|F!MYjJ|bGCkGsUrtb;b#SKfFTAZ*nfJNLD%RWFkwPaK!M)>2#Bs-i?oPK)=| zyg(qX%aVC)dRm=3io9}s#9W5LUOyE_%%Bo)J;Pojr*qObUtekUQRO}()E!?x$Ur}` zw7L!%;h=-wY7E{l-FWqV$+WAN%~}r7GoD@>4ItF6VRtAYC6o~}|tA2uPnWj#uEcfpzMp`^%kU|!1{9# zU9asl4LtLV!U=|G<_FqTO9p=b-lgZWvcsX|2}fP7Z~PXr&CHyQnI9F;_RZUFE?!A# zDt4WovVSN94DJZ(afj+m>4fpB`Dj+U8Iq3W58=!a+LL+)f!9;<<2% z)d^Q7jtGBA7GfNUfwJ>Vd&BJ7?3p<<>9^d$#h&V>xsz2unS z0VTHE+4)RV)B&^vq2Xs^q7ql?%Oq;OP835vgyr@ z@kL4;d!LGFN5{kfR?T%67l6)E*Y?7Flw^csFW!3UYs7 z{q~XPn${25uaZF$+n%L)wOKHz``Oj5>81X2FPlfx<>NfSk+6ZF83XFlwR^*I$1k`Q zkAj{hNKY)T$mgj?J?Opo{diZH_(hrs(LAr&pQbwA=0S!yATQ+_01(!%*f^i6T)lA8 ztxPXWdJgN#k_rLr3wDxkk&?pgR80NUtK#Ju=y^Erf`(!#dnYoU2I(LSltF+(^~UQx zw~CXeg&_@iKYw5;B*M!Izb{Q;O4VGj~+P!kSXWGI@AfR!f)MXm2EoVp#))- z@)F)P6rc@Xz9`7b-UAwKZiS9lkm=m3oL6>3*y}fqFLW&=SqSsx^cA-Ibho!NB2~q< z2Um*72M-P&IM8stdq{B;0K9GxOij&?e*0WUGuaRnAZW;a)Ct$By;5fA0oaiIu@?U4M>;r4_=X{*8kE5gQ zfB&+#@oK$y2%xqj#n-$6QtNs=JG(RI?e9woioIQ3Fm$m~RtL;mP>+RjJ5r_8V$kkfQ**ZD|YF-yYBA z=27M|p}R2hJYoE#J7kjid3pG7Q8Np}kS652kqjLVEUl5IamYr|VMLKq{mtjk{A(bV zFgQmn38+>(uuey3&B-hN-juW*IQTeZ(LdZ)&*YF_7Qpp!{uOuJ>x& zP0Y>h20l`keCgdy$FKq1*HuYLRkvabH#bg+3aC%6tEsI`+WH!5F0QRO#MBo$3_k2K z_6$_I)?^(bsjRQR6yfV-P)Mb&rba>jez2YuzUN{lteL*5>rZx6_)cFB>q54II(=uq z9n7JOltEx7jBg_dC-^LkEf{b5sa?PB19>triSx`E3_ao0;}WVf1$^T~&Kf^}xn<0IbCR4j)}JI&vpVhMx|%Rod$$DPaN`ntC$!&v`+?j;~6#{PX|_WM-ZKd%*nh zi_FZyWRoDna2Bz*=$vm8LufF�HxbiSWjxPQZqGdjMG#f3_OklY=b-vsg{)cD`R+ zyyESM>%Dkl44a#B#=OT3NgC9f^qpJ(Q>vvU0^@j2(aG64Tip;j z#BOG4^CPsM{_BjCRhTuLK701;ks}XJd_Bm@io5zwe~Rq{%1b+TN4bfz1RF!3q<`ip zH_lIlqjbp6yWCHHo*+_TKyL<-6Hooq^D22}4IX!sN$fy_-=8H(ArJcTadBsy$L666 zlUGn^AK!zkUgghb3U-!=ngi{u+U}3jEK0k>X$0crNvP4i6%za|Kb3=xAEogf{md1` zoum|K82g=x@qp>j!R^!c1|7DkcRxwXuo@?SXkuVJm}n5yJ3cx-?me8a$?Qp6EJJ6O zf2fK-*x1SX8^mSDtM~yn&QR48?~+{AE8!kuVya2>@n}H8Px0|TIsvC9ti+ml>ODl& z&)%{o@%IS?KO2i5}1oF(_tmmAGXRK@>6og+4yB~!I zCJG7*9iBFKlZzRh0@yiXgfR6RDl&I=t^H!*3!sV<%v%lOur@npr(;V%iM^x#+t@bdOp zGD}lf2>zI#muISBqN)iS-g%6|$lBU58_Zq!Y)F;fN_Af!A)@AVyzwz*u|0oZi0Chy z^GEOw13EnQJ%28qX#vv3E73d7RD}7KyLg_nm z%JIp`smV!citDP6hKCOR`t@tQS)xow*#SEXQ;0tIh6u(U^fuNM1xm>ifnA`6Qi|kvtVN56-7nl zgqT}f(+fF+y11L&gr6R32GZ#vV5)Vovc+Hr_Q|BL_S5Gt5oM&MQA+~najSj&d#>?# z;owUKM!vTYyyukvX$HF$%9B8vpnhDAI$wK#y#5iB4M`l@u9DqD4ch!SzK90iZxx=^3z;VYZhU+SH+5#zP#-y`P?gjNJp zgy2*705V-{vn!%zomAu`UuYNkvod#}zdx+g9hzu8}Ab+xs5^b@^x zbk=b5z~uG}WmU)I5#zCIuaquQ{(VjNLMhT3x^5zUtEdQZLXS_-k2wkN^fxzuK5SM^ zq~O~B2`Z2`Z?tSCavIE->FL=nf3sws8Xv!T^X7L{nBY8heG*iF*3o`n9!4LyhM}JT zNe3tk%&VxWsMrGEl$L_B+d29Adln7~Vo)Fo8yxy1MKQYY2NqwjCvx-G#unHQUh%|@ zw{J!>RoNnc4{*r~^EzU46c_t+GLq5U+lN+uw|{vVo2i`NY*>NH zu(G!9D6)-cAJ5g`!PN{YJd(-imVf_ttn7wXF1|raSGO8;X42P;-TQme113fN(soS4 zyZRvmu}^<>VApN(%DI)d?eTrl_36hi3((B;cE8r!5o8EiNX>wISx>HUf-Pl@J!O^6 zn{v`}t!sF$@`&%>N93nn^8EV^{#6{n(s%wda&1UoMZ32A`-Z@B_@T-+5MBmA#Xb-s z>1wBiD4*pvWBQMiE>(R(gz}vvu><+Ja4SKETn(?X%5nU~kGBm`N4@TxR2&XVYau6e zk@61Zx1iWK7}{-9R6pn+tO4Y$J^4kl#Keaum)^$?z~2fuI@OmDXN@3*#o8){uYx z{P|!isj|(DPRgpTF{)~#*`Pg*tLq!c#VSflnzAW4M0(_&S#Bunf_97>-*2u!v#^yaK zlmXD|Bqcjf5e^Dsdh^OUS%~EChWHzTL8MX)V|VYhSsCD8dcA^4zq?pyDu)0~)~6qZ zjX{C*Tgf(IHmE3ch^mys5fp_*#*eIBS&(~ElrzvM_+j8;d%?426 z`E-WAVSL}(W`+#DF6zox;4_DYx|Zl*aQOG2_mMfUZX#k)me-eo0?bn%zG}cyV;?Cii75h0r!mRZ zz3wBS&}<@pEolQ4E~m-hqQ#W|T@Iw)oYscoK8kwX@rB zY!u-A>W{4h{~;-dq(kT)^q9eq{8;mZTE=d9kkBY5y%x5Rzm&5HkllS~@Ge+O9%ncgr zk4;Vec(b6Af8Na8oQ6HnP(w`(KF#r}swzzglBAneRUfT@kb|T{bSuad!942xd3TSp zTQvjt@q=4mzrJ$qS%N=Cb7E%zJNSi^Rk9C&soPke)=%N&K781yEsHeF zMf)kBLxe<%{yl#n&3k)FcKIBkJCdM$rYNRkv;j8ikPNH$1ez`kRGh~ONN+%toRw83 zk|>bhxqEjgKtuJ;qvyS`!pA+kZF~>n>mb^#tIIfbDi=8q0AH9}SbXGXVmA?xax3cr zbrGM4(dHYHGV$u!9%(OMPJIX&@TtgoZtema*U6KkqoY4PwnHhZLlr#Gd{sznb1hU; z^E|2*+nkDx^jzvDuM_$i-YDjNZ6W$2yTKtE!Ei?SZ`dj>F>>d)6K=a1B`tk!~ z{bY+b1qIJ=uB@IB7dPyFvj=U_aHBfYc?aZpdi{-8%D^uFQ>X1_LaET+&}xA=>)|iV zFaRK6vDj(!_h|EOP#N04D$y}ARyYj07HA<7sIDnR=JQZ2PCSI2k-TB>>YQC-delhA z_5oUs{Is;Zq9UQ=$8-KOc+oiAS>}1;`t?D8&C}r>eERg7#<_ux+?1s?FF&=AJzHS=Ym&8bwE)psodeai(3j3m4!3ne&?r{9r8;NIrv(^ig%aK6rD=N~TJtIvamnZgAy#jPi z2!*l~g|mwbe7KIdx}sIbmeBgF)x}Cx7_hO={PE*)skZ`dUvIvB+gsGRzBb2)#qNVT z6W@(F*6llX&=BEdse2%!=QVo(KgNY=0z=t6?OpGRde`?7YE2v>Widd&KEr=ETqmW< z8G_4Jo}QiM-k!&rQ!HkdTnBBaQ9)oBO1$wYEkHDu~T~;Lbk}o4DhS-yUV1MZRB-64?SF zdx9NN1VUC!djgdZ=i*k(1)9;ZV+Xeo_)DzMcEWP)FHzcUlc9QdfIgx|g>yeF!C4c^ zT3>4KU=xj;ozT_m>CIO-lpk=&$V^t=&dyfg;^M-{wQ`-Bnz|6RqlCJ;`uPM!=x19k zwY8@kR>%nD*Db9wdwn+(ST|<$G36^?D)Yq$bu+Pd8lfgDW3A&DjD<6IhBKW%_x&b$ zUy@w~Ia0|YI4&dHS1e$7|AB^sp;GV}RoOEMF;p#1cESvH+Yp`F33YLIcPU;vBHHy5 z0#c5(cnrmYrnJvWdjBK-Q>3H&UZI?B4u%xRDBT}d(I}LcUr{$r-t1# zTW#&k_Ho=}^~=}nZxh)`Yelh(eTO4QSac2%Z2TCvR;|l7Q(oTAFCRpM)Di?$V6S-T z($>l-1iAQM>Va1PS}~5jCw2df{H(4ozD<4$*H?ae|M(8;*L}xqiXIx$Pj$NTec3~p zxv8qHy*?CgOR{-G>f$pSs*fv8mR?zS@^g$XS5f{XJw8iV`iN5nn@~(pqU4wl9lEZf z(r{ALV;-0Kixlt_R99C!y8eIW#uyg`ot)kG?I8)7+_o(T# zMi#aQDmge<;u6#@1XzjXlt%2L=OB$)8Zr$^`#AQ=ybr-=-1_E6O zjrH9Jcfg$m82}^~ov%+~826TS7t_|6`?vrRGMzgH?04UOk1h|5%^xrEz^_9MtVaSN zio`654Q>|C=(_dI&v6fO0|J4&xcvM5?Vu1QP9P4JXMZBHEH~a$^eJ+LppLZ?iW4v6 zJbLt|ot*(9h*=^K=Lbeoh81mNOWqVAG14m%!kdNZF#NpNh~E{=BuUo^Hs#RkUpnadqbn- zU+PPk%3VE*AkG(W*PzY9EqrWkCDdhlgL@eXW2XUhI1~h<;{^)f)T2#dg+h8{@hO5) zE)d2*552{GCe73xc0EUj-^5E*J)YAiZ3^sV@7UvhZp z0Xo)Q$>iJ&IYO5$ygt^}z%nk3q?~}9f{qUXvqO!*9mf^{zjrcv5r-CIO^83CI^7;% z2+shfOmG;2L*VP#dDM3H+OiYzhpDNir0Fdz zd%MZEq?~H8WEQvo*&(^u+uI9MLxEPe|F+Q2Lmj9AvvP9Ew2vcZhu|kNEWV4tdDm+^ zTL_uviII_ofPg~AX;*()052%tc|2W5&j-7otK#2_QO;y#b!BDg1k%*!L1utq_V@^* zt@G+v86{jxP}D$*qM2)i?1e{bYg`oUP$#UeVx^dZ4qK>x1);kDR+{Cn!0^Kt2+syU z{JU;H&^}+hQ=Xb~DhpX+kYU=*$VvO?>nAE_FfcI@DbO0DyzB5V4d~mNnl`HGI-v>0qRVcuh_rqG9V78lcQxxfQ`Nw%>;vcs=OEsE z9M4EgM4M=2F+Dn(#K~Q}iLM(A?m>!3j+NEk3go#sdX$l|FM6cVlKL0BipqbDu@z)^ z$x@+VANdQl!UjIn-XVR^5ag&nc=T$Vz!?z{b)IN`$^nU*>bp;b;s+FzUZsZFD#JiK2|fXxwhPF#cV;MZIfCLfUVFVwK6p z^Z@D-VU?klBrCqT#6vo#Y+2DHF9%Jf?EfzpP>%WzoB{X zsr}#f&2I;@`1gM!HMHd-h@SZSHA8djf4=hzructq$R7rnYBB}$vEeT=P*&M71&6p2 zmXA#}3;aj$Dh1AbX_b_e-57lS85zOgC)TdJ5J~O%f4BU{$fT}8gqxuXh(w*uZUR9R zigV}EZmMA8|NVc08;1ij21(DwZu;Ubfqzfx|8)rPzb}KGzFnd4^!p$*KrBL~yg z*byR;96d&6=H~AfNt|QhLezgB)o;gpZ`JKi*!E-7)A)qzJ2dWvInabJ85Hy8qZ_*qu@O%?Mi-xdGumrXRpyRxSQ~atM)3ZZby*WrXV}IU>6@5?*{XGkp3R%OlU%(WI)4&#bNNMtTDGiAEVo zNrtc_QI_6Or$^Dzs@D^!Sx%iek^bBqcCek~wNq2!s8&&lyEd)SImd)X_5FK!topW)JxG=<)CwToD@8=;YC=fM0Zddse;#_ePPbn^l@o4? zs~XX9r&7!@RLsi41y}KEBhZS{@NE*4un{3~@SjFStph_d2O2G96*k=M*_{AYUu>o% z0<0|pU*Gxj5bFLLW?&N6=V7n~_|unK$!eJ}kn3Sf1RE3v_N=~J0~5#Z^`+j7 z%uMe;qh~}}HZdeg=oUB1{|?U^k)C*`b5D^_wwk_{mcvY+c(z&*05<{bzcSL*pl{9z z4vv57#QXyyuZk*H+PN?3Th|9wb)@P%>w& zAp>&e1}=FtzgNAD+ZWwz1Xlk29gM|xoFl~E>Adotm4(Gf^P|b#`}Koeds!l4o<6mg ziT`&v-f=9uY$tT(dok7Q3A*3e0R<8Z6BEQpjA!58fAD~TmUiLS!>d5W^p2YSn*rM8 zbn6HB!MSL;K=QS_7{V9S@q29_a>lUu(#qD%{b?T}>9FCoa`L84ZUN-z?(x7EuRb3~d=Pm;`6)5X2Se&m>D!W$j2B~Th0XI0@%PsE==v=7 z_W0zMlt6rn=W)Z#Y_o4iFThq^yNuP#EpJpZLs*Nt;g452XhArVkJGFyxiepIlSVBA zh5w$k-;R&o`w39Hl5$ONw)yz_vJ#)aecLtYfX@GKqeR6lY+i(d#>R#j)1j7(eIWkZ z6dehaebDu0A%A1Tr>y5fb3y0i;mf~~O$IqNX{{0!lbGK*39dk83a01GqQ$-ac5H#< zTMSVmRfnFe2?uqGh}hr;Gu^yjw1HnoMn=kt|4u`3b}+{_nLn90+a+}_{74{uP)TYw zW?_&yC011_pe+^id<}_%rQnbBrykPTZPq<&r#_Sa8~n5AEM231*KL^6S@cFdz*V+WYq)`*{XoLiMmaXqBoyFCifsF9)60z^pyf_*foT zrRekdM1*-Bc4I(I`m*UQf_UlQ_xx=|jvx&G{d!l-_CMeK|Ct#7@6F=>!#(fs z3f{bN$cz7X^<%MoTW9m`02tX7xcus^J_4Tg?Lu2G7`_Sjq;;_-SCo|GP-uooA3M1& zVw7A$qJ$L3UdZ|%#l)b+3jA7N(R_(`k0R;q+qbAKV?Rs(ePqAj9-LDn3qc@pTg7;a zvSh2dPIo#QUlpBA0A&6FN0DvsYxlXDuJ;i5(&@Qje1;1%gpMbpT>`(xojzJpvJG7) zO6`X~O#U6#sdNHc?O*R*UZc--H9dAn6olCMG8OkrYl#>nj@) zp2N&6)y}+Yr%!i!PXB0q;o5Svh0qj#ikY$N%9C@s#>dM;BzogLA9iu{Dy;rwjOp_W z3p+(GZ~M`Son}loQ%~L7b9!$5lv_5%t(|>@#T7B1HS;fT9e;e`9Tpotsl$t65h1!@ zvYtIFH!}%8OUrVw#2QuA zE0nDSLY(|T3Vbw>&z1ijvVsG#)G?TmRj1Xjo{{*^$>&MgJMe{k@j!+wpqUS zrPI`K!O`HRywc_hMEI3bny?D}@L?HlBL;>s0)b;M zs^iThCC>M=UqklQ$X%gB(LXelhTHLGy2SdSD7n+|3c|YD($W~-|Mu`+SSW;73E9^w z4h{l|eEjs3%*>P8MdkY_mdWs777Js}7}VhfRvT&ZM9o{e?J1?uBfR^A@_{%4q1|@RG{nGs67&2 zXCmk8n}~m3i9Z@8r^~AjPRETz?;p+03ikj+T|hIA{ngj&kWFJI$$ziq`}f(!PTP$u z64WFi3yw`~(Vf+6WU;j57ts+FA;u?C7ARwT7`4!3A=4AUd)TcXOTI_EgQ>uI!iChk zG!%gZLV)3eN(0mp7!&2R$45th8FUCS7e&tX9NfS*uzw1G=tm$m24hIAJ*YN6cn7DoU9Ric@0yfh_J95xgAcz z2x!Fa7hCs*KLqsB94AjENFKH*yhiYQwa>-m8S0&NOtZ-eh&>sLlsW5IqVrQtRTW7O zgLB)!$mOK$!kFXlNl@ZFC9{p~FcCDTA2X?XIXN$1s&ZeC5L@I3u7V02cjtZk_5u9P zs}8H4IOdlrDMzGJ*w-lH8xA2C>bv#&`g*0oea>gf8C1b#g@u|N4={s)c@aj*Q>U6p z`$^zG58Wnm@$kUu2?LSVr^kzg?DD5xooJ8G$XW+8Br@>i+r|rWBH-LR44@b#zaO}wKn4rgxM31LGRSZS-Ob7Wt)~OEuW=64?4rx)gPKkG0fc$e>fx)PRQkXF|wL(41+n~2)*aLo1`r5=*W@6-ghRT>;HZA<=R~liyZrR z-L5nU+DvIaMDTm|jN_*bh88L+Tf>9DJXv{feU=QM+Gg{^>1{KWJ31K{8Ic-TKS)W3 zd`K`j+{zFJjyLV{qk^JwJ0`TyhpBe`r4>AUxG#oRw?Knu=gyFdKdrXtN(&7tiSLVH zN$JiuRFuC5C=fb>(>D}pr>Y4As$dlj4N2=o(21a>!w-Uj{$P-`L-^2^f1g2$U*i2f zqGWJJcZs}r`Ft#WI$l-sL@!~&&!=mRPVFSpj%CpJ+R#0(AjV-NCCq5MZDcU?8?74&Vtm3}l34NBu=K|X>WHkJE z9?YtzqUK`1{zu_|=%27yOdDw%U0wok8fC+jqv@^(}Ni+EPrHvitnhm(}&$^ zqIct;SxCNbyF32|9mZ>nln>Jt69nmxO*^|{^->ii1DooPPG?;2%gY!Z$z9je6TeMF zE{(aBRY_@g0O^7%_UqO)0{2n29`A1M2*)b~z&pQ}r{w5rRSUe*7fvW4|o zPh8dE+r#!MXY+fTJ(Gm}&t>e;%muY11GQ4`LIozuf`he{%)8zV$=9jM-xmfw*1sN4 zoOlu)J=J#c+M_y?2eKSF?ILH=d)BM+8-1=Gj$@x(!lrMko3(fG-Lx=V#NVwE#LgQ7 zZ5UmihBf6SUEZShaWVotEZ_5Y&&}=bvWaOjN8Z`KP5*Mtq;GaDLr?oyjb+z1q{TQ+ zb&ZBGvLXi%ACMi?J^(A&ri4sPbm0$8`C}=!uiJ1DL|Le-Wc6}t5DKEBd^pmk;}zE# z=jitF?h;2Cs5Es)38c@)JMT1tj!62`*|$H;^2-<6;(`10($ZpxZ!pY1Pl|_jUHLs& zu{Ici{!DFR!M2~1X$L9X<57(Mr~3MoCUd#ePXn{^^7pQ!3hWKp|FZ9A^=^2rVIII` zo+h~ENEpVKTh6^pB@zl zB+P1AZg(UPD`b-YzVI+EPHaFp7KzK8EuDHhP)CUU89A7%@vW;%Ht_kI-rCQfkq6Qq zb2=_d^_^1;@KqVlQuJw#}rBgN+ zi+uZL-6kjB=&z5_3DJFlsQR__QCe5Sp0_JXWPTUe?w8hjKO;Or_Fa1V4gvnhLe<~J_l3@YuGw(f+r zibc#LwqdBad#bK(C*d7FXyx9CfWMrL&sGbqAN=w9rj@!nQv0N7oV>iOG45q&50O7M zzHmvh@cQ)wdO4nLS(FT6R0J6Kwi56t5fVL3y}fj_NzybpNZLF@A3y#AKn&Q zHG5s>NNrJo5@$ze=jlQd0|UQWS#M9fbFizk@87lJRmr?G#rW&bEo!QsCVT>{&&u#b z1G1W=M9*uI+kxv%RsSyX!^yazAlS#r!2!{IT_eNe@m1!6dn>HcPDs z_YBRUM0uk^Pr03RgI$Qg(YV>UakkLJ+S;l8Wkgyu?x`rpZdiusNfcYP%LE=L&?XNf z97AQBf2D!0?oD0Y$%3IQwQ&Fl)1n2>wh5hW3+9848vmq=6d0s+Tx|o(I7VeYwc`uYQq|8@ zX}4ENVza2AaI~pPglT!&XQ@}^%9@XF@ef!JmzUij$xX%?p@G+=pm1O|3b5A8SK@CE zxS^g@R(^nfhne}jlezD;CZ-adDJNlMOryj~PDX09im|b`m6fAj&&2YwByUV-Z*ON? zo7{)ZZKOnvf&wStMPg1&xU7zhyi!a@t|U2O|Ni|*(%3ued*(5iw`W~lT_a_mp~u^G zdkf*t9VIMEN+7|*K@m`{@3*Tpd7!~_h?yA`VfY=TPV3hj8$I9%*4D}vbvF0*YF~G5 zwJtx{2rcvQ-~mXmAISbfz*<^b5G0!1QNoD+?0>IGAVAEW(XzejS(RZ$ouFQs$Kd+X zruf3Mrcoy{0t)j(lxE7x$}+*>@@ZMRrB5pj!o$K~h=AO(RyG@*)K?{aP0fp+&-=4s zTN@Xr37^=&EV7x8RCQFI)|Dx%;hB@J%eIKiMg+I$MzwSwmB ziVBS5oc#78f%2$fsA&3E+_Ocfg#BKA#7i$ZgJ&h?GqN74g8>BS;ZKQWc_o|f!dx#!5M z%htipr~LBrTD{h#Pw_~iH@K-u9~H3#)>F2+Ha1dztXSe;mB8i}P^xV9LPSWbx3AA_ zYoi;WD(8tzjB%~4#sv~|ax|Ik_<$>{IwsrNc4}X&2ks5yf`;xLLsl9-L`dfR2oI;! z&eBPp?YUprVRbx41%cctKa53^@*y5i*E%C8NUYRMn!a!OwtB~j$eA~pMXt@5wUyK7 z9YShMXhRfmQ0xtqcXM-Vczjm)_Aeam@PP2^y%*!-Lrx_YB_$=R5EWpG-zHqJ@&)u6 zd3*aB$}FP8(9!5wO2de4_q+mfDE+G_MZb4;uD70_DSR(Xm|?ed)3v=Lhf)sXh}5ji;;ju zUVLt${m-H~&1hv|2??Tmh%=_xZNXHHv%yU0pQm)fpPtW;A2s$CJJ&`Z+f70cO4t~Q z^FgQNIVKVJk57GleJwScM;lMVR5XU}+qk#|caKsa^rA^gM@R@fx>ApxJQ;E-Ui_De z^MOo`gn%a!d0CQo|8kv7$hYaHV2}5O-07aC8u0MQpHyW8GzhM$uY%jg;5?)*0Gjky9?VSZ#EztrsH988O+Edr7%cRNnPPY8f=P#Hi7<5Ga<> zJeSd9ErsIgnCkna0&KmU5^}mg6_t!f58^bQ#f)DuWCO-GMIZe6{6i>X+>i)NM z@^iv(I9CYH{jvW6 zcDUI)0CEIb3*mpw$t*vAt^g(vls{BX8R(Gah#xaE^A?i&<=CUwHp?;S%2x8nesz=T z$E4b1-Z0W|^E8zdeTj%K=xELuYP93PE>iQjo}MnGaoBNc$sa=F>cK1>MAbUu-cL(2 zMOC2+2b4C9%*>CKUjPLV(keBnd4=$l=H@%88qaiI351)8BynYV9W4VviqRfR(&u>`a0hOzdePPYz4Q z*O=h#xRetKD>I-q46%38EU{?N(k8x5jvAObq4$KAISL8wFc)>(h@|j?Zd(|Q)zvW& zIlND1wJOTQ)RdMC`P%B4c-nv_sPB_{kes~!dH64DNa}C*2qia+v`$Ee)%;ml`)SvS@`};sZo)i=q@-;$i?Xqi z5O8Yh=_NWyEdoTS{i1|f$!E1X?ijl;viZ2^aWG{9dV$&Qa99meKJZ~A#u|Yqf$HT^ z^`MCG_lnKsB+*0Y?ZLI+gFZEqZ02^E~HDZ z|Ji%|xN~(2%43?F)uWZAq@}%`cf^*JZN$fS%?@=8zODE-sVYi$N8+f@_WBRgS}Ig} zBg^0CmCmbR@-rzd$Vd2mEwtO_Uk!i1g{>{1r_Jt`evK@h!CP^>*Z5+;8t{#sXPIV| z55u40A8onuLiarGJRrCMGPTfpY;4ZVV6ugGzcAlCJxsv_CYWE9<^1JhYZIBfCtUt@ zb&ad?du=Nvqum`x5V@a=i_5r+ZB|x3NI^iNc6R;3J1d9h(7R=`zFbk-hgADAtB%7I zfmVgRGXKW?(dgDXv6!;?X8<{epXTv0E2RyJL7SR@OY7IdPW0+=G#AyG%_r*@$YJUB zC)FXaKJcIneGZ?)plXGTtU_H#_;*qQ8gd7#cRMh_9S=bgFE4MZR$fujYSx)2XFWK} z{#A$@=B|ui*|5fP@xNSv*6Km$7bPW$U%t3=#-JFq*s?v%fG?_Pl#~Dj3O6VZ0hzr4 z*UB13pl78E`OFnMzqVmXfj>`ltruvs(!dx;tXVY^GAwZ!OgZYRqa#eHoW4W67Rbxp z@Ij@kUO}CDx{!(0zFW)f0p`{lZC-=1|&rM8X-%y_%G zT~n;N$r+Q7lq3VYDP-O8^2qlWN%9&S+_=tnOJAP{RXlST8-W0k$$_W{eNLQ5vAspH z$oLHx)ed*(-@4*B_hdG*6kX$jQGC2wz`v}ltVtwb5?o4tWMu3Ll$X0ohSnjGB$SB|l+DfWsHrg#?pYkH ze%sji#B^sVU{vS zBrMcI*VM{bjXqEJdIh$ zt00I64j(?Op0ed>VKKY>>4iM;N!a_}lMvoAR_Z$E*%g3zK)TZP&wh;~PVQ37LqF>3 z1dPXpPOT1KRFlpC9OLd@-lP7*f*nN~LdTECDzN(=sja^)_9sB--Y{EXFHx?+_9L*< zR6xzJ+<<|W7W<;JlM}E^yZ0Q3|Ij|V2e-Mk^?t&=>cM*_TWtsg?+TRO0Vw?xDBOr~ zXQ^XIOr3*@n(WQ-s-<ja z2oSKwGAhs~uASXR08Msq{fix##*2l2J3q8_bac0-?)AYJHNyFcIZEWv zTCj&aki>oyAPC8u5F@9TG=C~@{m2F8C~AU{0He5g@r`nn4HFb0f;(!*4vaJ{U7RV> z=f|7-H6|yHAE(`_#p#06m_P{FMjI_WzpO5rq!j}!KM3_^bU+~qV#(?i+dZ!n)iR6( zXg=gv+1L<^OC25er11ZmTSc)60;D0r>&qMVpLcQ{qQJOwPIf1Ow7Aw)>MynQ>iUw$ zgMcfQ-)a5`ACBl!!N+(veZp;FbiZSOyN3tJ3NLAUt4Ut=m7liw`VJzG$t17I+*z?E zHpxaAGC*v>EB~BKT>h)!i>X(pZ$np&tm~Znm8+OhE?hWFc$SkBtMLXqD$w>D>%Wf5 zyUHN%fHOuht(APIeIj*bPFi~b5*Snde)I0L5n0>xhK@6>RfGQcXhOYNV5!3A^ScPZ zjj(poo;XcTN<+49*AC3xl9pcFz){85^nULkqQ%}LB$qPV@nL0f6SU{ty>zoLv(min zelq)-j*rRsP*8QbZSMeH8o0@_be_h?e>M{;=o!Z@4!LZ=4G|&~@MFgT0ubPvHa2QR z;^a_Z;BgdnGTzTIC=Tsm9|E+sZ?TaN%@qxJE?gQOHl?K{ zh6YJaGMb;f|+-xL^8NA{fw_KGH-nyp&-mo_ijhB zvZ7aWA~Pi{GLn{}COTU0B>}+K3>6Uo`>Tx-N*;QOUH)_Ub0}R92!9kG4^bHmX&u>D z?B<^}j4Zl`T)f$Y#wCqR>*GUGhOlpt$e!cW{*gOimVd3FhpRwh{(~gW_$#@Fz~LtE zl%l*{S6lnGM{gUxTS$Hk`0fI5qX>i#i-VJMzjWfrNL=~Wn*RN+HpoVfh)50HDP=!a z;8g7N>Rz`E=kh1Kv+%KZl$4ar&xbLD1#*R>GiYrj1=lW(<~93d4KA0p`Qtev7g%XV zM@HcCLja^uf_!}Dejz040h>llX@pWW#MH1X|80)9m$kQVnVl7&-7!gI!#{sUP$LY# zd-whlLp^VNY%H=$p^bhJA3wgb8@M*!76{f@wpV4e{V(0 z^pv|$RJjW_)Qj0}UvA~{!}nWp`S;J0v$ylz<$zu$H*ra z+<16$4O2XSsdMr3V`azs`ohePi=HwN)|w>sTle_;*wAAc{zZi$tj0(HeQU@SQLGus z%hU8X_NyNJX0hn!$Ie6zx9h;mkRz6|csPs&;xVi|Yd@qQ@D1HddnqWgzFQaDpQL|< znr&hUF;6UQVLGAl+j7J|B^^->!ZupxyVVj5qqUu~M-KX&pfe zIK?0bUH!}oa!j`vF0-bz=-;>@de`oxe-#%muWlB5#z`XYXOf4&Q-N>x!rlceGj~c+ zM2~N|%SK&Jt`#J)MEkc{^eSs*y@yE&6Cw7*;W>k1r;PV5#;)Wj|3xIrgZkfyJ;gi5 zcpuz+P__5qr!~oyHMA=|*iBA+qgKK}lBKo&au72Ywng_fQkxE@IXcVB3kAxP5LR5v zuDp4aB5~V~=G#=z?GjzWy}m8#lZD{hf8@+S`VLfOFF{DGi<*Evp+>+aQE>~E#*R#Y zeOf2NjRd-SdhlABnhf#c12wsQz(X&(F`#urJqd||LkSZew3k&5;Yw)X~UTUy>1M$XAKP;pWfc)7Z{{e`4{T zx@Bo%f+BTXQ2iEDCAi^Q#xAL=lM+0oZ=hSxzlxD@^+Hi;X_&$%uq)B;a$ZeN!o3xj zt{Uek_EUpPSV%|Qimhn5a}G|s9P}gsAry*lneq-3jagHW!xIGgZ=@#Rnb4p zMgLx}!u`n7ztquDPRet8rV?dYk+Y!dUxhOxz_@FPubD37MMZ_Z>(v{e>8!R)nW)d4 zIYayOt8RA3*g`?!6uQm~w>vZmq0bLrd|@cFnl!NSP>u5#IZ9K%nh71`GmtNnC*1q+ z;W2`sQUIMQX6a~gJ(6WbA`}&iwCl*%eV4_EcciW#5`R4Uc9Z|s4>Vb55j?zude@?) z_w6g(FIp|6nEB~Hg#?^0++q!V&K2sNvnCe$+<>oT*s;YT#)}&H@&R)nJFNBu$(Nut z_v_fg6ZI2=T@uGWtI-81F>8~0aqsX_&ed(+3j&*v94k#{wJYXZ+ zSQth-*Lh_pF{YsEL(PuM{FtBEo&5mFwia>Gzq-l`5@J{N@9E?PqObLZk$}TNXM4@8 z?_(+3-g0u$*pQt^!#;Z4MRtbteBJ1$PbP%QH`iGLZykW7q7BIqeRe4sQlPKv?vlBZ z5`2HoKv18Tm)GkmKu^(kq3a2ZtRhKvXnk~W`*3h7bI~IVmUyCGeb|+>eMMejyQ~<)@loa<11daXk-JIn ziZ4RMdX$+tLxbql3_0=Cdt)v$I5^u^)(BN1t8;1FTz?V-@ADFI*YlN7B7FS2gKR#> zFIhL>VI6_G`>>IjV_hR9^;EL@ZWtBug9>$zEnHFyM+MK!Kt*AG{-)u|UpXLwy~A?? z36!W{=G4YbQ&;D3bEE^R8ks+rD2Wmc!o_>wrkbydlK6S*(}sK|^?jg}w$ooOs9G8r zX~i|;v%&u*7$e?nhwr@(E8yzB`4}!)+wXD8f%l4ChKT zscc%SrSPlX>GBYs{=0huYE0m~5=x+>+=b+wKD*LVOAW-@5pN*Y0lB}&b{Z{=)*=7| zLxRtIeX~bjoCjrs+DSgXYj2J6E*y{}1-p{*ggO9^>(fYr66?{#E-wv>G z3}MrAMfUx^V9Xmv=DB%tv5B@%--)h&1j1I-&J*3FNK?oFEx`+86(eOv?{rCYA3f27 zPo!W?zMbWcMLi$B!RYQ=N+h7?9lBD_(*5_DV5h3{e?dTWU~^I-m@g?dyIh=TLCegisIjqw3=9l{35~L>VnWaDt*uX;Opuh2 zcn9{1)YqZm@d?Dq699tewKTqT4kjE+*X}0s z{Db_44Ey(=M{W%B-P^aZtX<}gg{lRt78${aarxUh>e`y)-z;1z21JE~-q{b>vG`MseMHck!xh#tHZ?IJeS0#X!)hnNqM#K9&BE^2 zK>lDMqo*h?E8{(RGEn^%FavI>6EOL;XPhGUgZLSP7H$aOW}4}ttT89yzb!2tM&)L} zVF9ETft@NZXXcK5)oQWny}h-W^69Pn|9{S?*{Q=xX%1z1jl}v4JBWE#un?Z8WgzF& zQS3=ysmv|{Fhe9HeI0R1)d(II3pM!_)Nf?|s z=pg+g5V~wI6;XxY-mEj;$$I?wDIqO@pc>b%VROCVF})N_ew&Lp`$Crk#$AK!XP#+k zlleJKm+78;z`;HVJZu>|r-`AHxmx3JgdO(Y5|?QCRJeh@0lpQaL^mQxa&hs?9CWq= zTm9jC;tlxFycH6rim-a&gz(RX>$_QOOob8xpk?nVnu{)WR;4A|M@Fg;XuxM*8)=J7 zeqIKk5AGlPF)h)BAVdStgqe_=iAh^mm-1B-F21Ld9(St7$6q##pec^X`70?gM2iNg zal+U~dJna&bz=*tq6LD%dHgt#5CTnh$5(UbturZ-|9fP~fB&7YnSPbq8cSNw+z-SfLhNuF;(--7Lqn`ZV#k;C%W*m?XW@UNNQya^~gWb0B| zYU-P3&s;lRok0@PIncD#|B&|o(fiwAk@@Bgy%M9rPsb5~^QW61dd2oO^HX~7%?3Z! zK(dOd4Vh8G?kIqPj0W*om`u}Jaa%u%jXk$|Rh#P(>=YD%5=hOIdOc9K22}=AQqywH z!IZ)eA_wW|4<3x;y;0s~A_%PNFyS66bVjz;)*n6B9vaHL=%nsXZaMIOXI<_HWG;CA zckS9$QX=8uQA#2UutHByBCg>a4Tw2;bE9Y5{?uE4SJuI|0>VFdN>45G^hx>)o}PXh zT<`QwfrPQJx8Fh3Ys|ZXQC!rwfvB!#&;jhFh^Xk0SbuvvK1WoeLJmPNTK+>yub7lH z1v>+*-39N3^>ZGBevGUg-a!c7LBbGrdqS%lI+sP)vgzq*q}kvUA08UIW%Cz>-t-h_ zcz7h)*pS=ZI^uN7u%ge&=D{asiy&%c%yqQmvby8>C_`GkAlzk|E*+*pMJntJ~yEX<;!GJJf# z8bFV*qa!KhC<{wzatrnU|MZ-EX7O~wy^F^LmA`l{ZwVzxF-KJo67Cr>GKhrP+uH6a zeKWb_?<;#x;nPc*HK4}|~q$(rS zKak03(C;L0#nO8F-~z{IMLUm76hz`3qsMQ<6|GE=g~4l~W&0k@vsMcNq!82LP2hjf zKCq3LKY)`s>Kzf8Bzsj$=zN+c0O}iD1lS)txfm2hR3H+fkEy^hSOC*tiwI1a%z)%z=M@$W8R2B^H6MyTGM*= zWMReQ=g-Bd&n_Y;qe_4m!UiXNNvNGOJIF}$>(`m1@o$w+XPeq*r< zs5b*ie2h#Ev;wH?13bEjL;|4=9WSGjyrxceM4JWs9%Fh%M<%#_4o9dzQVVOtYW8p4 z!`XQO%#Nk7o{0(iT9L~1OLc*nQ2F}W#Gu`NuVXPP=z{n{@qfbv4*C0}K)F>_;S}-< z4V`b#ytL-&%^bA?+Hh~+bA7j;Rs{eh;g{BV1xge>#MR%e_6gNYveY8fC9{Mips?)_ zrIMp#h|>P7_5x;cr{LgwYv_YyG;G4;Z&jcPQ=3v6GVKYnNWo5O;{4lVql?519VO5C zdiCTtOAV7y_WD&FdLD>cPiP9#TEBh&j^`JG#+jKTjN@?^(m{Wjm=2>xx@ceq;#qLb zIoa83uO!GEi+`$T4l6AbcVYY;9UUs+eIrf~CEOkG@^Eo+wF<-@ z4pGck4&n$KP7{>=`O?>qe;bYhVMP>!Oo1Cwgu8MAAIP&-1tCVt(mq3d{q~+7QUVtj z*N~H2;i~K1yP2&P*f??YE@JgM#h?nn8eh;`%pA^Qf7Cbuzks44Djp!JU~s&`LFZgt z2BTzGmn?4)T)fJQv41tSwSkf&PoVhD^uMr!E$FMjOvDpYPwLA`fEW+NHJKbF6QK9b ziOs`O0Udaknb7j0%cZHDtGsTLS+|9}^wBW8<2i9hUYmW} zKjK6}0M-H+xVDy9CihEe!Kknoj5EU1#c!#fOm2ph6A8o|cKfKOU=)Iq@!h)x1r;n8 z=H|NazCtB+s`)f-DzzPony4{O)j%HfjvTxW%#^#}oIx6-AT=NhUn$w2Hz){xtf0N4 z&wo%m1=YU2eJ3>V32KH~LY-p^iV82s8c)^;{9(wRo|qs4Au!*?B}%AfM*uyb+|@qp z*gioiUpe>|SIcp_39xfBpF`4s7j11QN-?K&O`r>1Bq>6HeQcyjB(s!8ZT2*`OciN{qcGc65kOBka!ua@z+rV&QEsm zbgq2J$+>A_f@yB^*KQf)Ys%w`)!^dhdkWF_$ddc*5)nw;Qc}?Dg)o(!gzp_4;5^`5 zo?G+Vd$76BlUqGSx&RpyP~?2NoTvfA33>((N8ACLhJEr4k{lwqd3g~AdwNtGipvN3 zByu#!2uRgn9#5Ac@nhwn+fyxoz>56tU)0CQNZp+^vbM9fgzi0HexV5eAimBPu4qZ^qZ3Y&mRAR=r^VnK8%hyzjrlJQ4JzkrgtAw!+2 zF4l>k}?PN0sSgn)S?#k&M;#g`QoYk(IZ2dcNPwRL$gs5i5D zYzb~F{NxW~wD;Yw#}O3RfCBqUlRV_X+|UxrePMbO*mAXR4d-1J7 zzgS~}PxX)w9g1V*<>`W|-{j;7CYUQP5HHP@9oXY=5(Pp)HFe!%&;CcC2oFWkztkLTux|e$8eGE6AG2E~|iy9j$_*jGTRTq7h0M>vrt$!pH0^##GpQ zGw&*9zToFXA>r?ahK4djdlwhpn0m~Kz^r*0l3K<@&zvD85VhhEOnvzxn81sQy^aq2 zADRj6G?uR(nMaX1@G5i|`Bw=is7a?F+ysuzUYpJ#(%9H!0FYJ%_v_7|W6AF}xaJ0k zfApCIEMiz~;B;oCfh8I(LBfg9IAGZfI`9;;WZ~6D{GlqNA_F^rV+8&tuI~0Qdgime zIY}f#+(xtXF}KwsF)4|ghX<}94K9OsW`_vBzQ#5LP(}`4zI+Ap0$@VJt4sQlcuVl_>3$Rx zyP`K5TQ}~yqlXWNhkrLWH%IVVOuf$a>ne2sV{k6eZKmXHS>nDyoJbm1s4-d-T{nNc zZWt+Xo!baM0JS69J=S*}7>q%&_I)jVDj?K22pFbh=yL!Vju>dCjvSF1Kv% z)@}lU+z)C~Us=Xwp$cZcICR$?qU0nHK= z$yBTFfEZJxEUQ_*_yDQ@gI*)N;%jS2UOAQGIp1n4RSq-(aviQv7)b88ydQ|=b1W{y z$4V3Ox%95j&u+II^;8Xz6fbppj_O7lcZJ_iB=>8qZ+-FkEBkK)GR2Dwoh%<>cb*d? zJYzj(qT=XzbGULY?0Tn+D-TDlG6TaG9T6%WVafrOG5BC<_l{{A=XXvh^zJJV?k#Roh4cdaZn_UM2E_eyIbK5fz8ROC%b8lPWvIXg`3dU!O; zPnE3nTvJ7gYV*U919KCHcUJh+x%Qr+p}&=t#!ePzy)L=C@ic{jjIggP2Yskt)h`HY zaMTP@NjenLgmAzH*6ywKzQ^J}zNbIiP!95j<{cS?pCSm-ILyL=km`tFjhOluaL>R{ zl9^TZ;rzm0eCWsN@;aw-UcEw!;_Fu>?pL^j5EPKb{(Z6zOCd7*4rL)w z3`Z>0!0~8hOzQ@3jPhVjceAkAb?!A{asuV65YfPyW+>Ctyc=Q8sWg$S!MaCKq(@5z z>5Hf+F!<3?CHfjQ&X~?AMa@TI7SCJ90a=pz1~-}a+WeTCn|u0{&!i^gxdjvgtTc>= z4(Vo}kxxZ0FnksGQm@)WQUy6a&e|sPBsHb9Rz@n3+s-s(n%tMs7us@gbrT0?TW6ay=R}_JU=Cm8Qgi@1r-cdX4l@4X#IU)Z2)_p1;3j zKS^A}f9#3*tQ~+&cT*dZ^rSj#UziG?AyfR zf4O-V7`uQ~BFTJgFR3pf&)FtV?S>=f<AAzY=T_ZX!m-%aCs*uR6MHJTFRU|JCC&a{5K%WY;6akvQUAxya|1QH;d*y~#(+o8+zwdhKopbO^ zO4gGC5*q^M(EJ?!1j7|R~Hw-X!BnLaqG_)SJ;Q2mzdHs6cz(> zp?c=_Vy299X&=DHxw#O`vIHZMBx;s^pN&;b0wJ!U_pPzEO1%L)8}@#Ttf+z#^Vw?b ze9AlW`*-g3QfVPARmNj(Qcou*vk@V5EV30g^2-F8kKW)+8LHoY{ThlE1E3p-??2D$ zLsAKxw#eYA4tH<E{#LT&X4mP0&Y++m2==y_Sy4EqK@G{yo^$W6g*EVH?| z|5Fbl&Cf#z2FD!^>8re02WD18MMbx^Rw`h_ggg7vgo^|L1U|ak@=8k=mO5{!A}@Eb z^%Umh&k5nZ({^@t|Hji+GSh!TT_*FdHA}GGr=}A)Du7?TdJPdkXR~g)4;kZ9SXo8+9Ovu=2NG$k)<0_MTRKLyL zpXEb&_@Y204Rvg`Mj4V2HvZnNKx-I+6WoSEZsCR+EGz*9`1EXPaKREZ!bqJ$6#MY- zen1KU2vt=VkiG^E+scX?|7A#SYL$T7{O>$Km;q!%szD%=X1epkf{z_MdUOE_$bbR% zih+UF)ZUNl!*FOqyu{ANwud0gscq;neY;{{WiV(4(mm4vFN|N=x^E1Kk$F)vTMrc2 z&#wK>FD@>=;q8oug@P2%cQFo|dWCjguw5+Qxvmg^85#BNL_V2XV&DK#C?rEmp{Qqz zPDD5&=hk;1)*XEI;4f8*K&R^aa09y7*t}0oHRPhtNN)nrJsA5~_egJxKV-zk0VgPauQd{YXa^Z&t*z1F;c5jE??91zdG$fu^(hd|fn&Q!tDqx= zJ?C1!5O8c5A7JVk9867W+z}{$?W22+E^_J_E$r+bDZc>RhY1eHQ~)XP)d;0_t2D@J zpm{=cB>tblAoI|NVjS{->H*It5n^p_(U>(^9aG$rU2SN7>!Q#Ut$)xH*WW`faPa!rYSfBC!aZb(& z7u&OE&#I`@*F&c4%9I2yEVyulm9_8?DFH~SbMUqoZoSruTV80BOU^kZ$M z^(=VO@Jw4iRm18D8R6H`&Ryqo>@FEuI;wd-3eYIA(px-{u}b*;qAu)R+N-2RdFHdy z7u3=pJmDK?T_}0nyhlD$Eu4-oDW=lARf7!P<=GRE7lA-}%NwC|daX(dv_QWX|t59w~?IkM7 zhmfrNZW|yBybSA~LrkSp?pj#LvPVmAt!i5pn7gN;y24>l`+9>CNDD0|D+ z<~BCEkyQtvhbrjov134$DdQTJAbtLG=ZN1k0xKp3^Za5sc|3&xHZvPMBXZfQcu;W} zU>E}-gG~?teCb-K^i<~Xyo$HO;LRTt-4Ipcir5hm)!NHw_{sd{$mg1xsBp^dxv1^9 zt{}tr78Ag>Bu(}4o7;-?mbs-Pr~&(5u^}kb(Xp0{R*PFLPm$$*#Q6K1&sGaR7(hhy z%%zjU<_*bfB`AFYAvX33L{^u5WgjFaibzNxw+OxPI2JEGm7*d%XgC02_Y8_9U0fEM z4&WCMlaPQs#ph2Ktx4%7wqpGcHi}M87hKPTvyOM?pD48Vi7G-4X=k9kCLELlTgxJj zck+NdVl&#-UWj5OeIUh{ukf0L?=yj|CH-^N3`^Jz_Bh3aX z7Gwl_&DE$7?jgZ+W_v5;`SXYQw=UgvG1wb_T1aT)#`ehJ| z|9xGS$Q3b8Y zKsZT^q|qwl=hF93oQ#wI;=p8cEtZ7vwnu7rxy9D@pT4_B1|0=l8(z(e{W=-Srzdp_ z%r39=JK8g<5qA5r%|7&qiCceYQ2xHbt6ueQ+`4k==lHIBwm*N{6|cOqx@^r6(epCy zWTLe5*Y)9exw?z@qRp%~x8!br})C+lXC*p$3=fhPw ze&6R(IPIL~W^hNfv}Wu?%hu>1VnjSllq-*xByQsLjr(-PqdtI6f#b{u? zAX^JxgOTx7mD~FFp3S!%yTY$*JIy#gc{emrDpvlziQzki&(=262PujKqhIY))sp$C zU1nru;N&S5*JP46JJH>$EwqoEEwf>zwBm+q9lw^PWnPEXMb#vD@FSV(Z(Ufl>z+4P z2q-Tuo9VK6TcbG`{o7t&b0#LCzOMe!(=(62ttqyVik_ZEq!I9w`@MYi%5|yZ z)P;1UQ|6<*Kv`4A(y}$zdx=F;Q`4!q4AyuDF}waUZ}_In548XWGW5Ew3g%9Je12pv zQMhUUZeWIb>qo(d4@mg17VepxeC6k7N}l@ueF*$;94deN*4Kd0)5=Fj|HCuygH*t! z$&QAq%~6~t-rMWj_j1@sTqR^l36(El1K)KHk{+anq14&jS=HJ)OfM%v#%C~D@{Cv{ zM(f0kiy7|bi%~SMP}Cyr^;j>*xcoA)YZ{OwnYCfE^!2we*M0joYfp1YA;6IDN|C`| z{5Vz7KXdd&wYA&d>)F25hl)ZsP$*&YEOViJs*(IzAmQNpiw)jX(Hv!9;Ebt9*#F#W z)dCPJ#u8|d5mwBkw@5> z&DTd0#>O{>KkgmS0%Z%7?hL)Cl$ZLQQ~u}>@y;FLMf99|B z5MSIe4h}WGZKo^qU%yhAQ|J<wNS(dz=wJS%n!kAMra%K(Qzz{(f zLRtM5Fib!|>5&hJw?_VzqS9oy&GI?Adjz@U($;6%4H;&PT%polIaF-F=XNz-N4fox z!d|a^mC0}E6sS>;#1`xz^r9L_v3`A$o?mVaQ=TB|Ogwz>0XQ6EEk zjIEwv$Td&T^rEctbbg*Q^0}AkFTekAyPH;Cdb`u`c7!o5a9Q#*!op;CJ>dcsPHJ-h z$aehr^k`G*neot2yFUGmLWEVX87DU7peB=xUgS(d{CS_Hr6uxKh=f#xwzpR9(xS|r z>*PsAzBp_v#{%M2EUI7VBFYloEBI&cmYrlWQ56y6wN`pvTN_r=_1ivFgnM~=kc*{+ ze!QD@-w|c7H7dFtLW6+&YR8{O!N~3Ai&N#IM>(G>0fJ;;#(sNb&0dhO(LX7!Lg>S~ z`5swU*LZn0Xl4C*7<;Bgf~tW+*O&;N)>wA`Smnrkv7KJ=Sb*RH105ab>#KR@L!aT= zJHm!w{kjUZDgT4yApgLFNP9|YLH0o7KSiZWm*U_J z(Az^$q4Tcr`R0-8@Puj?@(B|@ZU|6@)X)(*Bgce8{gmb-vMw%-2h$vSrk2RAKn>v? z`kYy7!DV~v;}KD57KRMN0;}oyk!%c{_I)Lq8V*m2^S2zFio<0d zmm{yXWBGCT2b=Oka=0d${=K5*@ z7Y_1SPrvmZc6v^XaG;|lYwhV_viUPH0T#kWL=uVA@r1>dfm=?R4rfGE=!7rEaE#m; z=!=VZUiZrn(V3_SDln;;oOL)8IZWP4%~!D~3&j>IaEA>KpTZ^g&4c^i56lEjOA=hI z{yV^s$cxO3@$6$Fi5Z`&J0>P#_zc8UX~-f?8za9{N~g4pcwhS*)175o*C*{OyV^8_ zFfwnSd)-sQVnmXvQKNE(+EY++WNWW`jY)mzfo$-GunnTQeAD{|9RE^o-1)C(2QjB( z@Zq8%pPZWFeOxYk51csUxjq`(TU*|_olt3=Ieh)CX3meFrDs3=+T8ay`TA*34iznW z+rr+jUoZGY@G=BtWZ4_UZhwie1~k^5*h4{BM>I`&8G5H~?xo!$<8h4^#Cg9r=U+d!d!x=eK!(^hG7Ln1(4z9d51KqiA^JS!zK=ekZMz?QJhn z?R&u)mZSTI8I@9NwRb1f#{_L`qEQ1VO}mRjl=5Qb#UDWjloSHI0fr!eJ|Y6C_f&qY zu2S9tqDMF%zTgT4rBP++O^(R3CY__JdYPmIsgtY-ICc3YX8k3+TlgXbG4KD|c~@8d@^$w2o98WN>#)Ue-aN?AZ}jE3RRM6m!h(cN?}6&w-z2Upz{REV5U9HQ z@RxlLIdonwEJ*&lZmvx++6(e5+tN|0>Z?fv_h|?T;E< ziGrq&b+h+MA4hduhGoJZ2n_=?E?nqw@GIsAXomDz-%3=VxqHm02Luyc3ySza2A}vI z8r`|lW18QMiOQGYxauISs3~#%GYSxi%Dd=j@hADH5Z;fy1c@LAv@PK?;ikWkm~r@U zc|V^Xv23*L{K~mHbK?K%V*G=yjt=ykoM=p=lfFT-f4}5v@wec?ch{JfimTQifWB$crP|dmcUan@Lt8cPzdu zn1j&`htP^Dno|s65T`S%KEZLki+CKLx3bc6EkfoCnlShE3z-;IK8+I#?-fO-`;w9jTw}F+1UX^y}C$fX|+A|uxnqMx&jX=rknV~J}Zh36b^iDIm`zPXm;O8nfu2#ysY6kY_;X}v^Lyft_*0$J)?Kxx)OkfNEE#vpY zuDeH_$z7}h&B_>N!o$L91s=iRilaNI;&)wiHKGDw3)TOy@iwm&w88v>;2uTjVO=JKlKGw&6o?nS8q-Hz0epgF$RFqen*9BH2xzz?QY68wq>ZM& z$5o%62hfPUc6ks~YrrtF_exjio~K6%!w4FFW^g%OC~ zeG-n367FSEau5jNk@Yc|!8Pch`uFNpZg`G|yE{q|ZkGhB#Jp>MdiKEn{inVDy+&s} zfK;fTqLqI;P?DYSh9(ZySG5#r=PEx%#PA>+hBM|`&g0$FbLf}u?PO7>La1K-6e_5xzxzOU%f?&KF+%Q`D`qke*x)s60jaYPK)gtZ}>N}Xo9=&0S zeE9G=e!7<(lW{k^JBH_=c0Zp%tPBaF8o}ZY4WE^;UVw(BWeEJNRx|1puU@{4KVyyI zb_pdEZ?5KnJb+v$=;^$1{I8fkNAHW&W!RO0em$Ki}8 zPs+Nw!~$sYle%ic#{76bv4mXv{@yREuc2*lGRAOe~U2s<|rvOvGqz z;jcRi zO$8Kk^b3vAMklj55k(^p%*)M98`E0Z+Gx~Xibz;*evh|Sn3<$Z~7awx$+jY*~{?fH;d9}l6 zM$660(#?_w$bR3LSm*KDZ0ZMfyrnp{ykp1mb8}Zlo2K~U!uE(k-^@{uw1I!_rjCxO zC@CX`ZHgy1`}qx%$*p?!_ZBt)DEV#`ap6E)m&L1>TrBfDCjR~{an97sjgrSbUs6yo zf!^W65kG81PM>STON9&yM@QPzeLIOYppc2GKb3M^noP%|4*Xp6sw;8NRO965<_1Ig zzSp*gAQ(XNO=1v1WFacNG;YNXG(Pc57E0-W$a4Dw*0|yx8IIO>LR@<|S8L z{ck3!-Wh7(nYUfu-!d~RF=*B=wAC31 zdGO;>SeMQ6gNsw>mElu8%6{0v{j2qi_C+nW!ILjYA94r=NIk8b?%@k~aDneZsN24r zP21~t$C}Phn0d=+nodsqy({{D*|M5LimGAwSTo`-?I*Oql11cfo=V9CxPK(y5BY8ps%GbVoNJZBT2+#hxv1fx-9bGTgv z1E|H=3pu(|{>|I0RbNApMi*VEjA=r`^ovbc4U7n5YN@fs&IfIJ7TGUqBe1Sw-y2V|erdTjX`=X5Xx%aS(&NG5?DMBV}a14tH$ll%p6Ewa>J_`b(`q)&Sne zTlP|WQ>q8wUj0**9mEpSG6otps`jjafWrVa&JGNdxmTh_j|{$Z#F&2f-^NPPK#TdH z)5(;kPrIK;NAb@V{4LAB>KZJsO!MM)WdrX)Dp*te3x9em1Q@)zaA0U<9embZ9c5f} zdEHDI^M5{`PdGcn70R@61m;d)3Rip%;D&4-bU4M(K;D96gm3|6Bo8*0hoPiUH8ae0 zeR=@?6sV>8`XYv16%@!Khtt!KZ!g{OVVoW(Aio{D)f)G!w%<%|flzt%^nC^rz)5*m|2T>7KB%m8L+TOS1HfGeYzCo{)h~96t!eX_{Y5fL!j;00 zyeHKQ7cwmWeM?2)xu}h6vyGiNa;!{!q|xe)*4$m0?Rg$6x1y{E4B(%mtp8do zWn)W45J;k-{b~)rH(CI)$*VCTql4CM&DQ(^Tr;PEU?ZUtqCRWunO|b4jULc{_xn&{ z1|r<-eiosENXGOFZ*HeE(jv@nrQ3(s4kO5#mJGn&m!Iqxl$G_~8quoIffQ!kdZJ0F zJk~1Q*WP}1HD#|rh6eo^0RdLHSq%6hhmXBw{w1mSkR!iu-fOIT2cdGm8Rc;T8yg$< zWh5KgTD+9;6qD&f^XfTy`2!TkqeOqwc^?tAJIwfYWpPpX3{vlxmXu<$s!S$OWTrqK z7?gclh|}%k)1jeHNFIkd?NlHxNonsqIMU0zfqk((!ofr1GxTV)Qdl$NnO z)Lw@hbXcf=Y!GWka&l6+LJtifei5zY<>gz*@jrc14s$bLPgOtG```0`(D5>O7*%=? z_{>2p5LV+PRxV_W#`4gbArJ_!eL9gh-7Hy=!DUr<@fdXS^b|)UeRp3mse+JZfThUZ zk_tKL=J`jdc5e)j69gW&3SXr8TsN~HIqbjWzUY$5whOD!Niq90CEkV;gWCOF)bJ|i zP|N^D2FxlCckEckI08%Dpjf%X;6ns;Fx3Xi4?4GeG%C=epooM;6SF6h>yeMpJKB`{ zrRF#?XVB0%nXQi)4S?tPB$|?ZzWp%oFJ9RHkb_1Z8zJ}<`1Y$E8;9pGk0eWb2^GD= zm~y-R;Vr}`-XCO+Dt-A9EM>m%MOdz-L`C5e(xxv!%X|K<7D?|70l5c&g=UuAw^1Q; znxA^_-Wvs05qdcz4qehI12%SNT^+V7?;T~M$D-u9#+{gfR_ulO42WMs*|D-wvosfW z+uSfXdlQ{;6oC}Aj)lFKbzG*}()SK%S|Xtn|I9u*tMaP7o@?-4)kxKusD!o7!4hIL{{9cS7N56b!gV_~O*kE;#sNzgi?Btc;TH)VB$C znA6T68-z7j_8yWovA|FS4q@1@vnxCq`wEKq5QW62Poet%uOA+QCh*f3vpl8kAzRb8 z-^|9*t`1}e8GS&2AU082&i`K*!6gpQ_d6KB+7-ehO6lAfYsfR-njZ-Rra1Y1LR>uN8n3RE z)hiuvemrXnDch@mOMTwFc>~S};R`snQ+&!7;OQ|h>^=2(3*3G!(juu&NAIboalRe! z4bFZ}^~Uk3DM$qJw>Me_h-BiR16*2s`X8hi@5xrKxJpUh@!XiYu|40I5Cb11DjB(B zDcFQC18k5;hsaUOPfz{oQ=5d_pNa>pJe~(dRySdF-5+jKAM8w6>L39`P zC{FF_2WgO*u}7~0K8MTZ82R&zjFOKZH}Ti31P3dB?AN&Jir_4EbT_=~okok(IYVgy z0oc{!53S*5Sb01GoCSn3?x58eY=$iaFP^)<)GyJqRgYknVTh~8b#--($sTzwVPQ(P&)+2=JH`s7iz92Ldfw!}Us-_H zRFDLJ5L`T7@`#WSVgu@ZHM;}>wmoeBmZ#tS`twZk?yL2G|JaW$!6MLmXNZt*Y5zeVAxV z-?{fO_=xigg;#51c5$UL203p$5LWX zs2~rITT|+uF{uX6^++8D63eGS^2pZ1X1gf zvwL#Pn$Cdd;a6<-Z)LLwy^()+LRck1#yb_R@(9=3)wLJmFk&J?P$ylS)7tCeiex#% z+fdDR(2rCNO!_PmJdWT5zD4x)_fJbvG1elVEElnApYl2IR^aMK^~CcP1CyT8V?m59 zTG}zNRbyvk+jNaxSVcgibnJZRz@#|S_H=a-TO;u%09_`ZVzKpRUfP;_sI0tr>F;3# zibkAGyKW)8|9DvG^_FXT*%~a}oAURsT`r-UwQ6)1fpWk%0k3>*;c7o_02jb$v!=q{ z-d^wdTK$ef$CH`g@Z9ILjv$7pu&_vUWZ5f0mIbukhvdYkPYagw_z-i{oDm6CV4=sn z5=wiK7^tg&>%oP+QFGYtjU;ovEQ@BYiLRoet-AUYoUk`u+vn-&Nqqw2Q5=;<3{Hzq zgZC%(OFRtwJ~rDA@PQe*ZQC?r)8IhF7nzG@S4?{YBTeH!&Ilx+Objm?qJ(hVI5{~{ z&vO6w?VP82XJIPgqOTpD8W^wzWGId2n!6>{FI_^c&@|!T#q|KQR~z~Z?1EPdKRsC?=mH-4Lw5B7PXA#Wph|?gtw=X{KSJ3Egm@af+W3=?A3n6dFuVf$eHE2@YwyJwQ-4a%%nh#f z__dO*@L<3QkFrR2@4ij?GPqGef{pU8B?T}X>AqXmXD82=(_!WQCr=cN){`V-$a6tK z`%^&qp>d9z)Px%XM~)w#elsAlH%Nhg>$%g9kiU+HIrpU^vU20NCMF zJE@_O)-=d4pMgE%=%GV>?QfdgXGZqTXZVEr8!`xeJK&pY7Cry5hhZ*zbpaS#!-q|j z#d0I9jzNh)BGbuZ+gt8%UR|<0`@Zk*lM93IZgh;5HoV=>7kT)hQioN8&roWvChr@a z9vd+X`Mg#p6FS@0RokYk_d69~D%JGf#2zH+4l8y=yVKWb%AZ`=8{CVw!97F}2$j4l zqNi<=Wmz7au0T{!=L)>wYx`O)zAeUYle~+-%X40TbLZxK%Yrs+sFs=Q9;<8N4BxD< zO8I16c+sDXlMqT)cs4EL*)vJIUj{6sceWmbU;1F~1G)48&#AJogAKp>&!RbrRY*o_ z3{j?ZLN<_?6JpWkp75PShRR(buSW} z0Qc(^PW81T%exM8B>2zLoW#!axLZ?EQNaFpX8sDYm~`LR*<$o(ltay0n4dojvjtoX z>T$U7926AXS$!E?QSe~KFcS@CmbyoZ=4Ul)ec2}%MOAH!#(B}H6^bovz<~kM+;rk)6pTL%(JyMw6pt&Rt~-tcr<9qZl3CZ zV4?lnx$|Qk%TA*2MxS-84*hkCw^;CG<~B&fq>(D@iHG!2|MI&b=gy~-Ut29>TMeiT z!%%~o_L10yqxcl?%JikHSRY$Pp>h z_!R~|x-B@x4+Q|07bJ7z>8%&_hAom5^A43Jaw5N^4(z-zD^OBZhvzvtQHc^HTQ{}? zT_gPAo<5~y3~zu3`yiVfn}DAoA`lt|1ez95u1-LtSWEHxm2Y}=o*Vql2)O$@dy70v zpmCuA%tmPqcer*pHLcHIqU@97b3vKZgmV5&k)Oy(D(kKa3;PMacv6z~!Gj=?s$t8y zE_e)N(F>g6d-m+nD{|VvTJfCeo9Qe3cL4E^xy?Vtx`Kd+`)zG4s-gY>VqEXh_6>ZI z6su@?`Fucy;17p~heJ~S3gB7YUd)7b<0b%BgFoES(IFVc%dltiz;^$pwzgd7u>q9w zj3O3bpMLuI@zBwuhq=Y7`u@VI?P&`m=IYrxZ=N@ridwoMcB|!ECtSiIbxshv)``Oz z7i&LoR)rD*$AGPX;l;qf7$_)Ere1z+k)oAZUmu63WWH;uzYFFW{^RG$a(;OQb4ZxpVy~-PUYx!6eG_#FJF3cSd7_kc^)6que!@07v`2AWm`depuOw7I(r`+T-{6mF{>%{~Yjs`!K2*Y4S{a(={@hF=Byy z7VeF_^mu~7BDvyKnvEZm)G3BmRxw;Kikbjc$rSA0hKBCd<@@X;(2dvtwYuKI$L^b@ z^X5TVn1bq8;0Ui?zh?0b3x_o#+nmQb|8f<0v}QB|d2Go#*Va}~OziCJ#FF`N+DDo5 z3Y*-W60hYUbjZZSm6esvyTZWSN12B?PfJG!5G3-ehJimrLq=I%(?h$HbH15A&(k_$ zA+q@K;Tf>?C7DHec=qwE?Lruk?9<*%AUj;U1|fY@cj}KH=KX;f$3e*npV<)j&mjvO zv$NqL^G&nD`>vNVXeXnyT5wBNNJay+`)&nTPSq1|&TP?h_ZfVw&ST32OAENOn%Ro) zH<>ISeGjQ6?B_lH%r359CqrfsS~x|-G$D)wiQ$2_{r&L>3k2r^jjCm;wAEqh?iGVb zx9z*B(WlQX&Z1h`Exprj0yLX%zu%!)0(p@6LQXq#4qHk=dN z$4bY$Y3e?Ry!a{?c)b%ISK!DpU)b=wzn+m2-F}{%hI$FD!hSo4(}qlel>wwMrK`X_ z>rJjOfUAo3FDjYAuSu9q@d68pI(ub&+%($jtJnx1ysu%!&8DhQ^~8WZu#!`e%u6rS z6~-Y?(!X+b;N{iB0G4?o50l6oieH35JCkCb9d97S%b_UKEt0mhvML#C1dYRaYz5KB z&c;4#$KEari-Uw6)h4+>I?r;3BikYIe8JV)9boLA%wMdfeNje|D)3fUrz1bj%}vhF zuO6O;KTB_Q2!^VX-`AD%-(rb9>#wx?uggitH#$H-;p!CU>?JX0C#+JW^U441ct!~? zO@m1;H1Mo+0cii+rhXe@8s+yCGUIKjySmMq!Bs?1u=HweRS`H3&upF6E0txxcd53_P4W&i*pJH+?^Lce!SV>4x8fp9vc$1VSbw!(^&@x zVM;Xt3%II^3aiegA*7~mpG;k8fjR1+-EkB_Xvpo4=eI!^5Pd}3i-9?7Z@;1q(~jUV z3|c~}VF`>fba~km6-l<}Q}t)n%>NK8m%^Y-E&_v}yxebnPsiHsDlB}TO|x*|#1oFg z9Qt%fuO%+?&ImQ|YUi4Gg16aWb;T_}?mh63Q@3yDn?`@Ej{}BeetisMA2#3M{Sxre zMNliOHf8vZ96{PJWo4ay(vr0;?$nfKdx@@yrIzQVOEak|N2{v2FabjMgt@b{>1>Ys zyoVmmNsO6eM2gjQJTgj3J`Fm6MU9I|Rewf4c@hSx6&B9px)uMzb>lCg)_-i~YpAKN z?x6lv!{o0fuP5eH`Z-39aB6IAcl&i(8nFfE_B=^Z5oSoD^o=3jZ>y)k3=g<-2Nr>)f)g1rm)!NuLVP$x`&Qw?6)c7-}l{Z*Ys*V+$Z~ku*Y1=z=@s* zL#}<-&&7(p#$NX7)xB4*Xrfbrn*)0GFK1@@;ylj3ma|BZyoegnX2Ai_Ze{VGI&qEg zbi>6NOYohL%|=W_e*p0jC@DUBR=zdw1*w~MZ~7kaH2srHIyKcM`=)*a{QLgLskoB` zzS+#@yuH009XI5*TyS=t7bshm4XR(dSscy+R5lP&>pV54|NOpG5x+B0NJY8B- z?f1g;;j?KcvqcdsgEo-W0lW_czhqwG+Ig30`za{p6q0vu*h zpzZmuA?Y^rPj4P-4DJztc3E_wUc10~EX#AzK!cb6US39N5F`GGUj{N_L z`@CUG{Vy_W!oovCV_S*n>^#m{x!gK%}?JQu&ID`lPy@ocMdXrE96Js}r-D181+n?kKkv5MCF8gnUy&n+6R^aKM2o-N9Ed zyE%Rz(5LK{!*q5cF-=WP0DCykDz8=^T`84ifdbP)Btt3Xi@75{iqhqYkkV2RKj4dn z_6jvy^8Phwuj(nS3Q~ukaPvs&=X$9n2j9+qEEkIeA z9_oW0h5s-$rHqSOcKfy{Mh_)uHbO)F;B>#XYM)SUCO&@Qbu5ZQ zz?3Nv$#MJFHR|3AQ#GvnVa2DHjXa>uJ2W8U&TsSSeN;wDX&J^-jzWV(A+T3eJh^|L zbW;{I135NZ7!}JQG5X2Pq^Ghh80vzOfFV4JDwa)zbJTp1h`P)=&%IGJT6r4`W$RjW zb#*12mclviLRA?hbnSW`E%+mlbEa|+jrT0UW>uPl17wkV3L}&Yb$NepitaHG_4n^% zno{dEUt3(os2aIV#hx}yYhFADu`R=d$#s$*c3?*@|5ZLwCV->|X|#NJy`-e~K)&jt zkD)(J$*lMI{rM&$FyNh1A1{SMODSD_8vXIe;`;6w;tmb(G54cz{-?2$^epT~V_N6Y z0pp%9YVw^V?taB+99b(&rqMI=ZyEdy8ASeuQnuLcyFyV7?5F6;gvmH4<95z+Gdbk^g9?C1)NPg%v0zHephs=%<57u zJ{5moU)X(~#+0#aU~*=98mp}=2>pFowom#P%XuLTSSiWm+;p90mX>G=TSC01!k<5n z#ULLe#QWRnwX_#{rb%WT+WLb$D*Q+mr*}1DG9#3lOK5g?Bddjth+m76R16= z(fA*qjDuAC5z|vsZzn%lD;y_Me!;yR$wG1%78bcp3kFu=In9z|W43#cItZL-Tsxtm zw$6q@XDl}9gS*~zN97tELwKiV^mQ~8L6najB*N$ahYNtRKVAK~R$fGHpT|K?rjR># zXwI5O)b3VF2}>O;D_ZL#@e50Cs-7V{zf>C~#0BIQ8nu_3`27sAA(?bbJ_1qnW?lOpQ9Weq4u!a^WX~`umHnUQNM=tmk11v}3;= z2&}Hqc%T=7sv(@~9Htmx0Zz}(1}Vi7?j->vTY`-Ewbqfc2xN%a{yy*JJR7;SeRbU5 z8PoJD$%nopy=HNytrYptDJf=h@Zv&?@<{akW`fjQ1Q2+D$x<4aO$LNXlk zvKt54V1d+Om64Hg-MrAurO@?Tb~^gw)NRUF$(RAqSUYn4PBj`A{VUJ zjt>B3KRl|#62NxmOd$S@{jnDA6xdg)vrRdyqPXKzoWvvp z+kej4^z{$_{yX6qPAS;aju#Ve71*ambKC`YFoS}I*koOzCZlg%jJ9fwtKPFEf!kx8chL&jSF;@4sbSrYqZ!WqmmSEz<78D zx6{zjNQe9jU&!@W7@c;5??$oS*!>x}2E_4w8JL7sp)ctKHKg8%85%DPiIih=9euOs z$%V^aDx1a%nJ;I$pkz7u$vRI9IoX$Vb&o$;o*yU`HMVr z!L^&>6Qo1M5?M=&b}5YGCW&+BT?~E0!ooICmC3BWY3{Q-M7ISg&|y!idqGbY(?Kc% zdhJJ#nD*|Sui?U=)64h1EDM5y8T=@57L(x|wp}p`5F(E|&U>6NGP(fioR=b-JMv?9L7N-_Ae2|L8J|P`(4gZL0du{0`z8~pyl?!*ge$lUcVkGz*2QD)-ePhSn8gJ7#iY5*W=$r)`czsAr`LyZl=eA-2=29X8mdYsr(kkog{{ZGh*O0tLCTyV_k!1+bfo@D$%VZjOLdLGh2cjiyFWjTc8NzbfE=qXK3EuB8-E3cjh2qid+5`EhAjZ9 z6`~LHocf&zhZNuYI(+*1qph%shpdMr2MzaVM*<8$9`gLE+*8`nV}m&gB6-+-v7EB? zia!~ff6uuBZP{Alj8x2{M+hX2fBEu@^?X%X_*rf`1%-X^qyVqwg=$7~W#vI?s+Ds8 z$=Q)sQiQkVEtqpx(2vZGa?L=0ni>`mu5sAUF0237w2LE!zi4j@v$`!g!?m%@sG~t3U z*Yn(h3`rOv;`!<_&%;b{&>@slO)8uK3u6{OKA7K)wm~YEe?6}-Hn#oq=NAzX5!S0& zW#NaVz1{~NwL->dC4X$HS!Asvx*8bRI>L65w!pSm>+J0_ab)+rwZpAl~xC2uXq9*P2G225mW%q`SlT+jo;YI5Rh{a{nbn^Ij7!z$DD5Sc{ zA}$`0YK9T_aM@Pq< zcR3Jy4Kffh(R-=4I6gl9oJ@yw!Riym%R<*aaVoxi`qai@?a+DmT?EH2vgE?bGz^Cf46Rp%m z<-%*wLgYH~Ecqw+W3*pecUAF5$MUlt!l#z>6r|hE#>Sf@9&RzXvfaPWeOJPPzosINdymbVs(RUW2Y?4-Riulse7QiXSYmZ`znEn zA9CX_=UR=nyCPZ$`)yfioJx#dtkAXi(;Pt5J*3AVUIiPDx#I)nH0BoxGNl59j+qzS zXnAN(GWfCkBCZ2PJd~^}_ch=zlB4NM+V|E&ghYgSF?DH*+1J+jcWtX{=7dORJ3`cJ z>9fNwx&&Jf{kO3%VHz5C2*5*uB#TSfix>P9^UY)Os^G4JOLQiq*(^^SHc9lUsG<%Y ztUURVH0VGJhC=n_^mH?151P^4tsvrQyFoIy5QhJV4=c)V*bzf)1=2KdaG=;QadUIq zc!Gqe_42vKTUJlBN_I|!XlWs4v8-9uRaFu52y#hiC_F3>E*~AeZ>-~%EN=wlRZP`+T9z&a(PkAC$AC@O zU$r#vMGy`MgBPEXqEo?~=Q^0;3tKO)G;~y2yvsga$6T~PUV@7_KOdi$P4a1uLdRhf z3|VZnWXcC7|Fq4{-xmUB=m-+jZ2JKPYiM4$7^1q`U2`?}vUL~V)zrcb0x1cn!;B-++h=b>9s)Mfa>{mGC)@A72_XRe^fl-`}=};k+CX=?daZ>!CssR*{Gc{_-Wsz2QpERFMw6Y+%d;jnRr)KpFjZ|6C|^O1r$57nEPY2gGnhj#zn*lF ze514OUm@tnV88js**z2Bg_W}TQd1?KP20M8bER#&>0A3bo0U72a56&m4MwjE8eNhcpC<*t++^06lBx%x94^4NV) zNd2+{Y2hosC&+53PocJ&a+5O2-OCCwP-{~Yg1_PQW!MuG>egg%4`ep&SEe<$Hf+s! zhVN^^x&%`Vq?e90Aw#}aCcKx$#b;6?MUbabQdA_t%j*F;9E{tM02zk5njnTGoKUJXJ+bud!J^uaJ}9l)okkiN?mB# z{?lRKi=4q^i9L25tP?AwiIAV>=MTU&TA#N%PALr8G95j9*v#4*M%IO1%Rf+&V-Ub6>I`QV2pQlR zfq3JoK{d>nUzJn(*LRP6fH#J|xqu5!Xb|0pI8pb}wiDT+zo%8pv`2`I9Ew_*m%so< zpHKuAkun_SjMb^gQ5W|2o^mMzG zv$uCbqf2$qoSnFugM+f1+!Khc_l@yy-Tdf}Zrs^ZW@ZyMo$L&1|94Qd+Kyb@IsSg@ zQ5Y56ZY3gP6tV8`0V=M0B8W%^llnq%yAaIDRDCF5XmIclx0ut<3W5B#X-x{&2-=A8 zFCd{+cdO$G{4fPpNX9M<9Ax$nY}cmUPC~KMZ0>rmWvz!+GpWnOiPes9uzi2;n-epd zsZM%RUPW@}%5Of(Hx$aihW{h_$p2S_lo8q@bT7}eGEoFlpJ4G_^3p$b%AG=MR8`*e zkOu_}a+igV9oy~&T?!=m92{Rw--5!2Qqp6II!_B@wq-9F`)99Ti=c)}9i(*!t%dR> zc~^mNolDQ{NCXbGTZx{4m;~J@@}-lLdwWAxX^Hp?R6(F+m|eYE*|oYd+MOtwaFl|F zxw%yVZ9{4^@J~uQRkV2H*sNzLVXmmCXlQu#fcxxThDt}i?W=WlGtD#2qt8a4Juj4_ z9h%}Kbr|qd;h3B2tWb;{eh~Ak#LL>l`X?io?asEcjw%s`nC(07Z0B(x?Hnq$(*I+= zI9j(_{(U&_oiJm~qk&m7xboKtu}jBZ>wf^!Qn5*{S>5Owa74J_{^|Qc0(vCYU(;?d ze(*D7+I}uW1rbeP43E9dtue`k#&3;ucPj2QNlx<-=;NEIseDP$VobO&_(A%W-*&rK zET&#jNvY9192HWkO7;esL;pT5g2LV+OmBb9F21&2eg4+tC>ail$ai*VeYxpnZW`{u zCH0Y_%v6j=Wme~h<|nVwLMD}|r(0;#lZ0-HNyh6{PEJpj+`j?PyJBnQT{q6J#rrgH zDL;A?5dp19iHaJX{6+PVGs+aZQ-~bNR0OZnfS}+Et2Tm^_jrZhzYmxEBlPwj9!Uzx*faz0+<^|q%lq-m zm$&rT*FGDA2LdWEbydCak`leZ;KxsMiU^lT%*^7Bt1&(o;{V+B-DNi`&o5qBqUxpu z5G@1hO=PA%iw7j3&;;#-JGt?N<8U>7plhAgrW>{=RMo-Q>+Y5{N)nNhqBMkXC4-R{ zC7|MW-iw9B#ZR&6#~7x1_phy)l8`Dl;(2H1NF;X0gMUI^aup%Y7&pU|60aUdR z0S6Hy^B;d++is_&EYB{DE5$Uw(Q5y`DqDImyJZnRZ(nL}P>uUk8<3!{8Cq^cggELrfzz?@6nR#P-(`C@T$YTd6*C4t9FVYL`LR!jI)4U&_$>BA0$^`V$ z6b2GpVSoQ-fD2W%Oo_U_{vNFZobM?AsQc1AGb&kCZU?6^ZVp!;-Jqui8v+)R_6M+) z4inZf9N6g7^EuIHdRjlGVyF1~`aZkm->1%j84(ti;Jp%wrM8v+!M*4ys>NGt$mOMb zx>V!Y-o;f$IUv-Qq?568HD^pGx>J2-3J$ewd(Cv*?rC1$2G%Dn!_srzy3kL+3ADv$ zqk%G*i|}=7SE`3O;*&FKK9`P(DgU?0KbjDOLuLOY`#Nv;E^r zDL-#x|41oi-xvd7?!;Z4*)zAwlc`opX7!lHG%5d;py0zQyY>yC{lC+|Zt4GWBWM3R zEG!85?@8tP-&x}5e+iQ|2mU)jT>LMe^8fWE`Kv~hE??e-oaMN){#|3Ih^~^OkaPN+ zI2ZP7fBqZW-Yb}u;Krh!>e5{s4-p7U20^-1FW}2nA(vU(_hc6#yXBhjzKxqUiCDUU z($O*Hz*N0;Ynp<5C6i=9mr>5=+c0H^Dk(E__y3GQttxQ@fOD6`jezwD7t(tG4hp*> z@8AE>XNLec{W9rgQNx_?0D&M#K&>O1xrW^n2nAWVvn2A(8{P<8>+5r;1)U?~iSYy& zoSe#!9wg|??de3SqJ>CIrBSb#ZAUUPg$E|#gnm5)e%evW3aTG0L>jveWL5V4g*A1f zDU7T0y|4Y}1~66$uOq@$-+8R_xb4qhXeVIj~ZJ_@-kNl#mCJW6501lzslzt@Lf%H0G9GRLC7UL4v@zaN#S~-||XKh|*f= zMCgtevI6Jl4u@iH>pc>}puV-V`1i_@Z#nhXwU$xKuAQP*=H?tV1o=<~h3w06s$VrG z{SfgDhYREce)vF4Xh;w?3m_*h{IT}N>4S0H&&pZ=npMVv^(I09#?;|&wKt}|HQzeF zx)+l^AdU*q98#?dtR#m$(aKcKIK~_@kgETmnyX+>&^4-e1O8^h`@%TtO+c&1%vkBn z88x1Z7t-r2L|A=sU+$0)){Q)c&k%sXs7(};F74MIU)$R;XDumMw=ucY8!Godc=s37 znp!ds2O`V#^yvbJK_g&wcrN)O-MeL7RaAD9zrHdPN!}m|nQSdyZ-FX*>!qv(CS*Y+R^dGg%;3o5Mgr?j&0ihDQQhS(UOy;US%_F77F zzhnHAW5uR{p@|y)w{RJl+E_k}lLd7yiZa~sBa!}?vm(7c-nXjD+>%r-9?S$v1M?4BfACj933O!Z3~s`mQaqU2M=~0NRW+$ zp?Z3=t#pF5vGK2>5at_2EU?_>*co*19t;u~6JykAwrxW+Z1KyNNyWu+%;(pppEif9 z>~}xD4rN|bS_W1)9b*POb&H%VcQC`v)NT1ZI$KOOuy$SNOM-)6Gv7$##6@~@bP0b%Vr5+ihtIeh+NUXS5$gV)TJgdH=lC{@L~ z7St?=PH^bmLbH(_^ZPGPYPQ@~N@IL$)6@P`V-Y=BetuE@Y=%Z6)_3y0#$iXdV!l@u z79##m6DJ29PKtM&H?8?_XL+c3A*ORHp$kSmM__)zW^0-#$996)IR8vxmv=8cdSW@Y zgLkqs4cv!?`q!5A>Kt?ZI)wR9w3bR&>ExMZyg>bMealW|a1V)oF{0ieV4d9B)}~EM z#_y(+m&cCn{9${vu$i5gm#V#eFQDDp+F6kI{Wy_SDp9bW@{S0ypJ%z(*}RDb<9Gjl zOUT@g9lO{I($EzU7J+V!7WxAZ!t%y8iEX8K#T}Tz^gc{%z`025RLg7-M&>kSP~kaLyy71plAa zH|g5tK4!VyU&y}yIiih#i2IU?$4hIBmzomvo@EqCb_!6=&2BwPHPz(|^sre&A26=c zxrX~nS7|nuTZlx}_k(WS+^oBA>^J4bZ9*t|4)+^~mRXuSH~XgzFv;dykW(of30rGb zYyv5&koX>_A{fS2NvzSI+S?4GY$*R4`{4g!J@$WVd4wX1f(UzP4^?lue&w{PDbtig{S z*BiG2dPo?APdP3XOs8TNmJlj+Frq(fNQW-P*(OMnaYHbmH;k z$KwefS@4^0ts+GUmIVgr9$5U)_(?cwwa*1*68Ij*};QznxjxULPk>`o#FI z4)dozyVGIt9Mjd^56=p5@0Ip~ittc@vf*int2>0(olj>|I#Ww}4>t9PjTm_cEO%hO ze2t$$A=&n4MGgGgnYN2cN;3Vc8E=gFpz@PrqfIzqB0Piy8g%vjFzEt6nr=&{m%AEB zZT0)!!Ba(!?azpX_v*4UZZJcI$E*RvYm3(P2wnmm)~$Hu<3nc7@coR8;2zP!i@R1| z+FEdLwL}$Tj@A)8q2}fbUs7si=6@xBK6&t9AO8#fV&4Uf8B(`S*!pYvN`?O#Sv98jxUUW=0sW248{s6@#Dd zn+r%@Iq-uwxVNWg3r#sfW>~sQX9^koZu=kR4iIFRa@c%=q?Gb;Y!-r|Fpg}-Om&`e zek9f&3fSj(r_8|D|1j8SroM?2+;mF5_w}+DQ>%alYH1ao=f>we!f3rzZl1^HD;!-g z5brJxZ6yF$92W;1k0&%-6N$-c1KS%&vaz5pBM%ub$V0cKr~^7=>w{iXeeC<0Uw>)+ zkq4z1u((SxlBk4XKvvYjR~TDwaxPlZrn#K6zYG<6Edr!u69j5yTIYHec0c|8q`?mgh zjmWi(l$5*MV`_}0$KUzjIxR#ZlRkvfg81O-IIUR7UTeTVP!}cPKC@>+jEUWUhX%8> zj$-w$fbt&VZ8l$&w0j0SVQiX~<__*G-Wh%1ahEqJjS&CHAI0m-9aI0>eKr^a^96hx zFXfKoz0yKtQ~CYs-puE`GIqc4O^@9hfKi7x`oMPk<0p856f`$;iCV98S52_{^3$9- zeOjmJ^}X7@jZ_o?F+MZwV*7RjSwv~FbxW!e$IFqCLl-Y{4gP)pTv0Hp-GnhKqX@-6 zc2Rm>%_mLUivNC0_`PKp*I6%=Q*5Es)dC3(&PZ5 z?+xB7WQ*s8FaIJCNrILPH@0&!%e;O)P?Ottm95IG?G1~~1=&<`Y`zRMRIC+7IUhfY z(C>-FhZ0#UPpZKBKPNT)Tq_gMomIXBiO2%Q=Z&^Me;131iI;Qx5!~F1J^;n_7^Sk# z)SexWJw7QwbCP)IAryO0(OErHr^SEnwPp9c^jtH~L?vBmch5w@`kS(-cglCb*<4%p zR5DU>*^|Fz=^l;rmxu!yKlJ|nx$uM~tc=iL&~ckFT}3_#?AnsJ^TbCRPbFxUcpUVs z+^|&%yN}V8W_V5_{sPlvMCoZ+draP z$W+eH8J?of^UoHKlSGta4rv)KHd`XHO3PSO23$mQ)?+h1zZ4t0giVl(`16N03Ls%I zG0+c?o;@thKY806elNJVz;A!FOEZV zE6aXqJR1ezYZt|ZT9d-klJySuh(<10L2 zkV?SR6G+jW+CKW-DyZ95?(G!<>#54b9#;-B?zuQ|RlSlO<)1;A03}3?8p0kPW98$+3LczxyD9tV{{0)h5G8YE z@4tt%tbo8hTc~ekXbgi61K(VP62XmK+I=P#UYS)@88Atf)CrA`Z)|CiF#BT691=qM zVje!X#Gl_57Zw&k0^MN9`LFjHqTO9`EOj&C1V23-l@MR=%g-FbMHfK4WolXgTfHDs zL?|+V1+}%c!Q?xsY7A1prKKa7ym0ta385@IAJZx^o$Bs2?SzdtTB&6D2JkB8x zTXL+VD-(sqKY_ixwy)k>PCyZAV_;w(F@HrlvAv3(3hl`6#N1;E~40IZoVgL&m=R86n!ovJO!osrG zLmo2ELo|U{d$AO!p*+jB2;})bTH4?8GMqdL+jV;^IkrwN*8z9fZ>yg z{qM^k&_$FP`1xlZ@LpnFmN zP6`T`Is^uu0m&M98Mti)Nk;lcN%X8(_qTRXvsU!|<)^9XvkT+Uj-S_VOv=Kwj zRizQCsa{PR$&jYO&%=&WV=+|+Br8pF8%y^G(SS=Ll*oAanadEA5bvH@MRskJR|G=JY zG&DHh;?BZL&$i?{|ysC-`ChCZf&r zuyNX!32J>fqSYAd#vn6$eYNdIAKK>>45nkMZI-0|;SerVQb0Tz8mF+C8Ju1EA&a?&TdiD*4EY5 zuJ4`Lx%1Uw4e3Ym@s~Bl@{)`WNQFPDG4|_xj8`t|z@aRuGcnhD4oMeb9N2UQckD~% zJE8hDv-%v2vdbPm;11a0>DB_JS!_&9Le%jSyb*Z3TmLxWsnL@d+{^0Q3o9}XMZeDA zhJk#oBhm>wSigRE0SUCK>e;Sc;YLPZEiI3LNn?_WYz#2op=SpMGddc>w`cL>F2)SK zVhZ+_1++idnU_*g%&{``9w$6#G<~A~3I?jUEp|UE6kT06pf5Gatr>KHqZ53eJjct5 zTH;;*NU9fg^iR8iH0ZrNyjn2&H?n0P^XrA>638GCe6%CqMd^OiV3K}N)6sr2WlkY> zb{M*8T#OqT8v0OMYmL~WVSRn(Jkf7?bX)r17fVXg^IksSz;QNh5}Aj9#bJKyOI}BQ znwgpR)bvNnnLYZhSErPsiHT4YAot8wvU7*D%fPRiURc%vDEnLMUEDioJ$v&rEK|hn z`(q&#{_lKsX!@!>RN#78t`FJa`6AfEAaRmGL zc#pEI#B{7o4^9`t^OrvG;(3bN8+3|NvqvRmk40lta9HD3!sg1)P?>WQDI?2G2`d*g z#U5rgeft*B>vG~mV!42k@IIttUb}WmQ&SWCWdt;2d9StdgwgK>nN-Focnz$3WnGi5#(Y;gNG&|0Z%|gueVv0iw3zOKOIvtu#xba z)RB4SQ}*FwG=gPAn5AG%52_h#b)_7KrnnM3;0(}$IGd{~Xe_ao;hev}86L*^z@5B@+dMd z`5BbMYq-N}Rwre=5li>1+5C#pS5akx)y`EF>(!W%&SIgX**EkuuC-+C@0vQ8n36IN z03H-(KJ6JKRA+ZFm(_T? z!D<*sO@3D=%uq3zLw@vN7$9)8dY^~qb=r0vta-OMRtn`WE(jh8H%ah@1x>2+wPkJO ziD2o2uPO!|N+v(WpdUx84%nTRte1^0@5f31?O&P^->n9&ui2MhOG{*5xN@Q^TN%mC zoT8^r#5C~c`aU}OBU-P7;bNxOyOT1a?CbdxcECOkAK-l(7kW8#H%vMLBuZN%V79mnc8~<7Q+u zolLI!t@c%;A!Lnk`f*_LTHT|#_;^L{-GhUJd`G)lKHJ=;ENi8sT;?!>2eH5uUoPMG zF=sL4El+wL=2d>-wOkGgF360aRvapD*iG4I-yM0c&eQx|M=|poe^ebh`Owhph&!RD zIlvbtjXOIzp$7!rl9`z~3z314P+N%LV#@eXD1_Ji0u+~cbPi}V!U!Y%uP~U1#7wyr zR~n_d#~~;X&tJEJ_wU`b@6i&H6JflI9?n>BXxc5t@{u&=32=8rS>j_Kj8R99rcs{O zJ%#c}fit_er06h@Iu$*?6nIvY?nlX*N&xr>Q#H-TVicq?DqT|-ViEGid6qW}=ZRXSI)I=Uq0oB#xbj$aMQNo6R@JGw({q1RdvY8sk1nD($@)Hz}k5-juzu z!on{sEXK23aAFBP4_PglQvdo!+N{KfP}Z=IA22ccS27)h=|vhA&Lo0RI_ z(Xp}QGvMlgSfS1X+78YmQ{kcM!tTj3{b3Z7%a+uYo*k=got-lkyBJ+1SDMbPJ}oGyFcw^zZ#W9VTzqHQKFS^H z{)QPV;hpDCzJmmr#nw`prE&J!h|JG}4zQC785&aSDzT;fT)TgjJ(mH25X3@Exgc-t z#RTtla>-0Ldf9v}?;xFm`;cne*|o0E_ZHyJiL?vy zNLyS@Z05X84|2@vfQ1x8+;r)7JOttM9}gcbcQT_~ zK*2hcK@8qg=!<4soQfu0N`ABkmG^v>L4U%`wBX&L);+z37Ff~r!|h^!kyWI6UoA+@*OUjqykBwY1Y5JV5THJr&R_VvuoDmJqRSjY9TkUw+(;b%gxj zB<|9#)f%ptko^)n={a4d8mlo%5$-%e!ScG}sR0qsQg1<+i;MK~R5*65boH63rUuS~ zDfgV!*WT&uI}!__gyI2)6s^*zdd`IefbB?SQqa+P+xDkqV$_22bA*-+;WyUJ1$*W* z-dw{8J@O5R|Isx4Z%y+*eE+ka|EdxMcAHn4hCwHp0g^lCQ6dm%$aGf@zUPM!om&GZ zazgHX&(=wYO;X}Duo4jr zU#!>l+2-oV=s&4ldrTGII?XqBjvyM3C)|{MXO6u1Dv)}RlXit(;l48GVV-ErQ7|MQ zon0Io%KHjp{;?EZ=#exBZ)x}AiOFWPB+!q7?=C-yX z`+;j~qf5|DU`UG3GQ8${VkR=Rsn@PoX7DpHfzNm<##C}}42RJ<%@L`z?7D=kwuFbNl2 z)j$5&AgB$oy>%3=slo~4J_1hY@wiFjV_l`$6rveE-=rjv@ED;Tc=?hOvleL46VD@# zF|g93!%2(@_Yh+tY(jhxjxhK|DOaibn6I@5iRaxUnUfpA+I$hqVzbfbCh0x@NVJ;R zmfP_IKP@x{07?oEWjq_%jfeUBqM%?9WqNF5SlnSxpk2G@#Dup#J@J{y3O~k zB9@Sth#oRwWol1OPBi$W3+!ua6LXNxN1TMj(_xaXe_gDsyu7>;$%z#d3e_9QrLs*e zPtvXlMk$9q!PG~3+2PEYGrQzf0W_5^{|N+1R;10wq@Q}D5BzqvGjStb{Y+#QQpbs` zMI9@jBx0cI;|`D`))@c2m~rWvu`#Sa-PD(HUZOjmp7%H>J+JKK1jVl$v3TlBf)3xT z_i~H1#cM;L!bX)J;o1Lr9mZKjPJapz3!dj%nYk6wLHu<_0-_>%DQA|vR^mb_$w zy#+RFv(d8q!uaVo1$%`X_wctPKsS*xwL~AXckQj-$ljYzeZvoq*LOxY@f7SieDT$bR5FN(n4aI_YY}@uyb6pT;)^iIe%HbickbHtI z6hKY&0q=#p7CnFty>@SKhXVpqL+;%JPY<*DOV@!vo+8ba`Rv|aeWzRiE`ZztCG? zSGH+v<1l{2Q@ta95t1ozK$L&-5wPmjSyPYM1@tcvWYh{!a!J&xdqxu!= z0WLi_$)FShf|GGU{<&_^+2p%N`S@Iyr%RjC;9&&RcfXX|Y2JwE+8Pn}A3GLFK|S}z zrU&7YAK61BIe~`!cmj+cDBmG9J6LhUIPSXnGfZEkex*J!R=nDG6HVL9>}+I2gesle zpS)7-O!}e@>8nbg9vphZ7kPblbpN$aUqANsAlv?|ii-A|zhzLHB}kOi!-59vD^N@@ zkg0Dt${(Y$W`CuzFGxS=sJMM9_+iO1Qzu*hGD!%mAt*qq1AKiH16S=eX%ue057a(hC;{#|pszl8aOigW^{nPwsR(Tjk&fHK*!Wuwo^QSbRuhzwxXk*-d^ zckjc{&^(N-rl&PfjW$sV=+A>q$6zg66Lyv7qA{uvtxO=l?Js&7QM2OEMzQ@x1s0J| z;H&nA0+KKP*DYe2Z+x$mU_eg1!?A%9{sVL$uaw}mpy=%l%L2H116zLbM0#-~WblU$ z-;QcqXc2lR26qNlGBF)I7Y0*tz>D8mXIvyH%*R}y1F4lL|7R8PC{gTe?dpQuP?RRiq(1LdkbZo4kQgQQ+qB9MxapFX+v(} z^mNNAGh+rA187CTk=cc$h_kW0B%;@JhCYigM8VFZ5Lpf&rzI>p8iz#Q4~{pI9w3QY z<-50J{c(_BXP-f!UTA3O=PIPvq1?Crv&JhR+*s_uMu!iqAwCYBHLEXBC}89}sZWeK z0wW?)og&gw)6&mW21GFU#njVhG?S0E_>hvg?Y=IK4S)J{mH&}guo_+8M1jw3>4XrD z^+fQL2Y#sW)36ga%ESChNSJ`3nTY;1+eA!@5L@0bu!TzJ1q@C z-)|%(xwx#C7yNhae8m=Oiioos;|p|svx|s_p#)NF_usX9x2~2}#KU6(N3&TT5im>x zmMVNqcbnyEdYadR*jSIaw0{r$yJJ;zTM1WTs5*=&1B6n$kK}Nn1;VO>XWx5-cEv$r z;EaLAY?t@I522I`gPHnOMgo|PZ1ma7n6a52hQx{I!H)LHm|*ec9|=74flmH1FK0ji zoVwhGGexc3?v|8v!dAaed$S2f6ByE9veXcpPML(Hw+v%m3mkU$7Q}kqYZ-R`6mn6ob~m)yHYxyE1p{V?Qf)TaSQ{go@2u83&LR8V?|$Crx$o<~1`xY}801F-F|ZZC zj&}nBx9@ys+u@6{7!F}0-M_JD0~Cz%6kLb^7*q!ynn+%|)-4OL7tVk;hhluM+Py{G z13pD)24G#&GO9>KzXdK5L7}YI9+q2s_r?%Y(B6NIqlZevz3$PkEZr00X77HEj|;KY zLc5LO*L4y1&21zT50Jn+11H1xN2MxpK>W6aw7ZV{CO0Vd&C0pao}bH zcY^T~RC7)KAcwEaH$KnGx?Lpoo6Oj=y+4poO6mYcE|`a&O+VKOQi}{A!a7UXrna@4 z?5&+7eZG#3RsVWrlE-DWxyY8NsZ&Huo6Ykj>4{)#abZ5oNUa1DJsFuE`~6r>x>+&C z^X#=#u*{CCx5|$mrFGcUFi5d+S6vWALTz9*xCXPweQ2s7>(UW`>l%CL#avXuLrs^f zD67zN1DD`Yb#-&oW>U)KKmrz8<)UsYVdfXQXKgFp)G$1+!4yt1My(BXu(-IbgzsN% zVP?|F!Jea{qB6VWh0X*(^LNf$<$EyFpeG{5Qm%4;*Gstb6YtK3FU?=S?Qq1Y_Xrhj zDD~pXch9MzLI+;XQ!D*inY}4F;|wQMH`z-4v|z_n zo&dF>^1d(WZ+V@C5?pv4?qxncW|;Qankgtyl-X=n=ap_mlFBGaKEpTa=@JrIk zW8VkxO+x=Ra!{ZqPdsVa0pfo!2Xk%c{$kfC(zghH$DKW?2(Y@VLtgC1{&6!=kS$=_ z9>yc}J>M_iT9_FQ{Jw9~NIzRi*Km!80PA>2tC^IpbHI?@_Ht`=WDkUcQhZ8y)u*CbMD*tLPfU|7EG_Tm6qwft z&<0*KE(gNd^F$aHpvchLMXhA@i>%DpEh@+9Fk3DB$-~3XkBuE^Z)uBH1pUs={UAwmG9Txk^HKgCpxDM93fZp|Ww z5d5{hot5Y%vUujnJ>UnY)2gglPZPJ0|7>dN-&Yi$Wby`#@1#cfkOemmuh_r)*FN^0 zEn3)u)P#L9`XGED(0Rf!*lT_1_3=eoz`hp*B4ODoS?+!x1G|Vbk)3ugJMF5DH8BK1 zz;qZbXGi`u#E=p}DIab)^gVANKRx~D;^KSk^;~y}w>gO9)p=KsytjPG#m(Jd&6pt2 zL!F|1@q zIB7MGiC@X70V+S-KM`f@AtfuDl9BNnPHn6=O5`}eO5_cnYMY2HFCCLrAgw9FB!zQ# z7U8B$BJ?}h^Xea;s5H$Z!2wRaULw1iH_N_#=TQS8 z$ef<$5f4n3;Y3sY;DN;5hl*TP!k_Jn;9Jlf@{q^C;HFBX~0)}Z*Q0FI1(@kzJWk02Xf^;j?H&lkRXUd6-_Zyo6fkl-Laop`(B<*z|*Wr4!3 zpJ+v~RLal5xD%1zS5Xk!pGwifQO0d}jo}pRv-&Y#RpT9N+Yr~*ZVr`Qwp3H2dBDiC zcjWKin=60S0c2u?0L=+8h3=%+0_3m66i^b-?ccoj4yw0TAmGWTC=%-%8Zb!#3+5N# zn;DOZ@&9$57d9TZ+^ZE;f5Essw86SDuE>vv0u4c(`pSKpt>;OC^wsz86~pUfWb9sb z{}qivX!9UGDnPTwx#245AUUCx{|wO`GPv-mz$Y|cUldZX&72wzdIW=j3gr?f(Vb^} z5^HW}YVhehh}4zdw<+k}%mc6}*b%4pAuMbsQ0Fj}6N$OJLKe)tk!P;QCwq1PM#h^~ zgkr4DQat7}*1VXryrt#rWM1olBTL9uVBPe=17=yh_HNSqNd6lFBm$a!p895Pr$0t^ z|J4q{VG?}_PRaW<<`Qw3HF-t|=HLUH4!mWI>Tp*z zGA$e(AL6b=i;T5x`-$m0=~B*|xmRP}I(7q2`rO=Ob$q_FzzUOpSLCj7yY*0AbwlU9^~mh6QHTY1gk`#}$I4$)lPmd+7v< zHIV+((=Fq!y}>Z%eb68vnpv$yQbTwlVYT+81o}ac#V`uGA)Np#XVPvF7n_5?6F1Xj zfbxg+wVVbkL9W`nKPkCo$F=XPK6-jKMnQ_}t3K_7Uku*)k)2A^DwC`P>s+9A^h;SRbyYR7NxkW`77yX4W zDoN%hM0;5;WE|n#e@jlw=&d8dIE!8q_#X_S+0j({_S>aIQ?|3``}d4i-pI#~4;(l! zJT&Cc{n~2c`z4qRu&5gWMXCRV9snj1;9DYfd3~u-@9f!nuwziO`792ULgJ9|@2p<+ z^NtItggo$iys5B#Ay(ST)Lq74nW>*c~(|_f}VCLYysJ8pg zG#s1t@P_p(X0>%csi?XzRYN&q*SFpoBUZRc7;DZYExwV5Zdt8h`fQ*Kz8FMZJC&Z! zl-mvfTj|=hqoi3(ldbsB&`?~%2RV*@$KZ#S1WtH>G=Hf_`27=Wi;Tne|B~Q{uFh*I|ea>%fx<8oVEurz_Ij@f*xx*NNEWgZilD{Nk@{i4ja6b>3|CO6j4b@2}$vxwY^PEj#EFDR#&<5 z^_`Yo)L|%7^!A^M+VMz9IHh0p0POzU005&_z=lUv_NE~l3Bsx6%uP7zV$^uo))VV2 zw~mdtlnj_{2cCN!bgYFHB(vd++KD@^k`}Zws+pt*v?49d;UPhbY1f}^fs0)N$EuVZ zh_`Q<@zZlq+`6h+yrcc1QXsX|Jx8`o{(E(nkACjSqAKpSFEh5u*B=QzNK9$!Wa8QT zrsg4jprTrsnNn%MBvIq{oHV3&q0tC$#pv9p-#GW!o7BxJl<+3E$CVs~0k~#@M*2>_ zzXhSDGIHarznIcahbxC12XuUR@V4tlA1{(Tbk*F#q8e8{x<%yL>w%JzvmiIi-+t`l z#_lq>OOWCgK}nnP6y;e*Hq@pr1r!trpwI)-sq@@)%ae1Fj~+?L*cIaupX5rZ_k(#E zTdfGqhA1Jp#=O_`fVzjDy1sr#5+Yh5PS#cyp>dXElYDSh{CbuAGo5wyAXp?u{r0Iw3sgEdx=E+$3r3cATaQdB-@u`a}`jjwT%9Be1i=UdM*xnA*`cl zx`#Ycl9IT;00zK2#X>0iG6JulWsCxBEP*fD>45%+aUiD18*QRQd%=0@ia{$=_S$TY#>{-vH z>jv`lvJD|*ky{8?(wTX%l6gp^Nbn#*t^b__) zD?`IxV)s%}wlnVAmjL(Vf}}Or6~;6U+gNLGs7@nylb90D7YfmqQTBtCB45vOuwZnv zP>E)wr#ngZAZgblmvFbKzu!+c?yb*S004WqpADC^U%7e}XCqJ?62kB79InQTVv6e0 zC7b%kp^%oM;@MaXHGyRmHm=L!*WuAMIdJA~6X`f-<|LlhZWfPGD~CoBWJXYTV5*A^ z_Yl*W(Aw~r7$v%?4PGb?N1C}&3&FBo;DVy2W)ZX_Dk`ACSr&uF|b(xV&H{rvOawh)J6b0koj@+w~s=t&F(ds0!k~` zHWb?g$jK^BGiqu+LF%G9ZLNy4vzR>pfdg}Od`X~&zJ|h@hMv^K5f)QQLg3r4VBO))_xK@ZuU7Pj=O(cyCL`nQ}nc+`*6ZBe0Ctkgn>_J zH~jU<%yGAI;)7Hvm!~i;he^uq+o^a~G5;y2RQ0)$g4sO4`V-S1EdX)i(1OS)XWSfH z>*SqNdU~~w5AV-5ER^Owy^k?1ga4DQI7v2LUQSDLKL9XD8T-aKX`es z@M*+@3ki28Ha5t1bh27!*R;Rg*xi!*TpC#?u<*wL)2!f)B4oVxIM^q_^dME)cTP7m zY7#9hT9=mmiQ0gr$;m{;#17HFS$em+M<^bV>KKY}ZT>SFSnM`IlD29@3qQ-t`;VuN z#Ht7nrehb(EIJGYprmug>zwhgz;zKl0@N1yDA4wCk}*?I>IuZWdXRgt(sA+k^d)Nd zKd&>WJzI>wx@EP5IK~q)_6kL@h9HcL7+AfNc$Y?D8~Lq#5qkOe=4b&P z)`!DrzI}{p>m7?h*k2t)*q%HRQ$V^R^J^Rqlux-{>I^QeL>wb+phfr9{<-$%iXvRrjmV}xj zy^Qo_lQ$(|x5jU>ksI!`JmYsGEy00Usdm^d@zm$K_U!Y?cN@f1e15-I-bLPY|5nJw zKcq`v5XA2(8Q%MA@_x-v-&~$8$GTP$l{idx+;>XRa_+sj$hA-A;r5%)sc5eg-wMaA z4xUS8Fg{rKu<{+v$4Whx&0j&g`73tWa$F#nk@(#3woG$~itGvHqq~($^Cl1W8oHOn z3x0aHlMF96l6VX6U_pX*`%sK(FgXi{0$D&1`-hp1hk|cB+Sj=SjOdam%w<*F8QB=F zJM=t@*!Hu#=N3WbCP)8jKQrlF&fe+Yu-jQuv`gR=ub=E5;?3m8r(CIL-E-Nk81*A} z+`RH`Se}Ras4hok@Kv*7sxz~98~wGIV(n;FhQ1Q0=-PJqsj3nxU)aYDg#N{rPyEY(G_ZQFGgf?xIRUDo=SxsDf7lyM$CLq}ze2@iC11j@$oAiRxk`Vw9n2AT)#Zfl+Ooa(`q<2n zPk3!&EkC7NVM@BVca($_PlFPs*@N`Kl}g(!7OEJvqcb?og$9ENgox*+H7@eaj^*1l zT*S_?%RE%4p3@5?(1_|sDBm@b?4`=|VCLMmJ4W@^dPa$B;6R_I7@bx1SFf*j{tH*5 zO_>O$bK=oC{>FQ}+CEC&5k8(E_{l$V%g=cKy|b5MCbNgq)G=Urp6omiYSMBwaqoHK`sLg0X`QWw4QCH^4cQ)B- zYlO*St&Gy;%;DK8K6SOEZM1Gxe%o!g8oqFR!MfEuFL&2Fk%v@rm5FcbNsnZTNQMg~ zEPNs#fBE=X9CRx5L@v^3#E!}QAty-0t#w#vevT1aSe)Wsng44RJ=GH75T=pox%4Xu zW|b3NbNP+KWm8lZnA#$<4b6N}H;6z$(#HP$VP+o5yzJpLs5r9ipcp+ZtDrG|JApu1 zT}jZftPB%MwtYxNMvyk@54rTrVY__pebt@5ahy-d2(d5JCcCL0(9eeY$xm|+)~S+l z(!CLkzQ&`pe8{(kWp5tQ@?efG>#SS^IpM!%`ZT}Ps(s}5$Oy@MiM4W-Thv;2;(c{n z{$?NqDK38&8>_Fk0a`~JsL-N=^xGHlD?@P`Fawojvp4=Oo}iHw7l*Kr!70_m)k9Hy zaSc*56!IyPfxLv`;udyqmk>D)VxU6MBk;*)mabe8n&??F<9BgxJi9a2&Pd`Xu9w>7 zVJ0V`(t?6aB@B<7c&XgSZ3IWF{?!|sKHmzsh3=D=Yw@mv^-QSpV z*qGmjtY)_f`_f)l2*gw?Rw|T$W7G~Rr8Vc|2od_H-Y^8|Wb5V{&e3zibjM`e#cxD* z&XIN?ziJ;LlkW7y(_Q9TD#9j@@;`+od$L`JyU7P;Y8>C4mm z+3IZXm$4ITD_H{;p2x5+w5HJ*-K-2Ht(fEX_ZSGpMzYtsT<+c5FXgm&hwe2QfiwN3 z)Az@RkBrV;hA{{tvz}*{8C~>T>T(7bQ9kUqqojGh?GME#=W2w5TSlYvjv(%;JrilS zNsXS>&lGX?#i(KBfx)@Z4u?BXT5=gqX6gLSOfuHHP?-Gc)t@d(4k;-Efk*?vJ3(pz z^f0gCisF-EbFJ8@&AkFP%auZ2mXH!7g?9E|Q|^Y@2$3o_Qh*WS#as2ie$QP-3JqAK z%C&yu?BujeS2#7QrzEU3>sxP>70gW*2$;7$jF8}^-x5n^A;4^@H^230rkuyu*3(;+ z{m4F^XAFtX2QYjuGI?nrcP?@=cU8Fmjtb4WbW>fqdSPLjJSv?hr^*Aq8OEHaD4Gt! z0^}5z%HSu-!UcC9VxrzbGkf3+a{$;95nB9e>K8y0BUD1hXQ-_`HQLf=*F7Hvs;8Y?V(`(guMTQ3H~a?&sb3X#>l0a$di5g8isQ zgv|0ttTMa7B|W|H*yrCyXF(5HnRi3H&!>8u6YGoNuq?fs$A1qqkd6L3NKeZKSmX`2 zGbEPudCi!RK}6@!IgQz_w4-TX)twbGjw23ThjQNzId=4UFZ@;EdFk})Id+B_cP|2z zb+Ej&1D868Qb8ax+jwme8KshJwAD~_gAL}b{D94znU{~xttI2Ikx*_yL0P)xRzUOa zlP%yReE(4tG`{tKfYv8d9zw{23A;bORn+Umk#G)m>dciC{(WE1_xnrzG@|1k2&bl) z{IJ@*;GWz|YrX5OuF{t|QF5UO8+x*ZZFhG*@k`}APsVz-|0{>M zY5Hrf_AH%?k$6jtaf1^UrSi7V)tiOnAm$lxgz#SoJ?w{IC!whAuqt7b^%?=vZ0q1a zfo+B>9QkG+?Q|41gx_SN-AD)0lKrXXF((C|Z7p(eOj1dRGb zW8OY}Y6)Wo5|M8o)^JVD6Qp~cd-kpU1KN;$pS9BkQneEcy!Ok(pP%)-x_p)^kM&XA zPk_sI5}DcAN3}84vlLzW9J6cdo$HpC@2?b6-l=-|ayo?dn3c6P1R3k=vauN%nvK5W z#SOgY+dh8G)8ZH8=U0nQeEb+>?zs4PBO{|n9hpzxdOem;Nq+jK{^)G~9XjkE#HjkQ z-@n<|*wg^Mm(GtuRly_l4bUg1j#Y!F`C5Vrggp%;F2K|a-K_2tk7A!2!EoAt`+fq3 zIY%NteQgnY{(SdW@oV||<(F!M$FJFucRu4_yxmKY&D|%(l$nyTU!QWwDva!;mt)ZN zEgali+P-icn&D*jmpD!^s@rRKsza}lCRol;^ua%1lmuIdG|>Rfe^4`h7r zr7s;K6R%0=SK(v3x`m)0LDAUAx&0+4TVPtYW1Z{V?A2{U(N}#x98@4xlz&B(xC!Fw zn6ocV)wXLSCFZvN#y}s)7lvEC&CNq|#%`$^GVHlIvd;aLKF@TPVWP-NgSl+QwQkSC zLhxn&!1P!}{Q~%wU%nigi9$x+(o8EdZ=ohtQaaEmQ&5ia$(uK`02SEUr;+vuJ8KJz zwZs#pe_TDy%$o6kwr{@=UcnI@uV%td#j6Vy8++u@;!H2eKM@65y;9I9yKm1Ve1-6Q zDW5h%XT3CRg5>~*Cp^D@96JyTg2&RZK*|$TBfNHz{#G$jn!36=0D;s>0Px8C($jge zb!`d_XP3nZ%xr8wor?YamEc9+n0N^f*rPhjEWMN3#%u?)aIwLK zqkZ;86Wv8C9@~ADPY0Y_cUS(ASXf@(W-8p;-ku;eqb|vI#V**z&Fx8sK*LacGbLtz z>rfMvo&bwegEhMj!V-} z>`M%qXeO&>>31UF%Wg+uR{vs$GKf+_xwbAJ;z}17LLgc7cI%RFX+DiFoNP z%|z`z)6mYCD7yS!njwgQoj$bIf&j<=v}Ph9*gHQ8srRKKzRJqon=0Or!B|+-V5BUc zV%zz0*Y@3lXPD0LFc4H^+>#zP4ui#_Krk)nWC;3Z`xy?mu<=a?AL_%0LsEX|;Ioqw z6G2iy5J`tp5gb#*)e%SP&vnE0BW^^7<`E9dsAk)jhKKPi7#G*IyZ#+Z#KH6m%}b@yKa zeaPvRmFw$ANsEx4Jo+W2A95~>jqas#g?)sr3mF(4BXgH?%jW3}vq8(&h$g5>ZeR4A zpW9osqAsIBMu^7Q=F*FW?<+H5+$IN%K_kscdS8mx zMfsZ5`{2}rT4;yAf_wlgK{comW zHm)b_SdW2$0imhAT`b2C8HmEnsri@b1%7g336F{5OieyFY2>CF9 zC_b`TUTSQPU@St{E4@#s{bBo<_A_w^E0QmlWM$P4?uD*KlttZsfk@yR|hHPmtoSU6EkJG=BPowB27&euGhdNMJ}@qOD@CZGTQkN^V z2)X*+TyZUhliu^zPUm4=6r;FMi1ro-TE(m*5~OcTSJQ1sn+>Aulaj)zB=`=_(bLn| zTab~~)g@!*O$r9_giQ|~_kFabjl=3^&ziin+!EISq#Ua*HUpnf!ONF5KkQH%gMgUS z*xu5T5Ou69J>AZ|BeG+{L`ZXaF4tFCdn)_l##g9S8jkS+s}mKaxl7{f$SdNYyp@X&{TKWwJ8La z+g*<7zwYxxP$=rWzP>oi=gCROt5@q`b{?xgST8(V#ChokG?e-Jt7x=w^R1mFs)aWL zN<-m5&$tT!VeKH?cT2pM&ZT0jv#+^l7N#OD{u93S1bUjSZsR>9l`uSRpSQ9En7tcl z!s^Fera%qm*_f!g=vDQ?U{}y~*3eq;S=UB0S9nSkC%*5^-#y$^6MLQG4@0oex=ax zUMhqg9}WkcKCf1^zQ2=vr$WuP*X!dRH{3tneid1<^Z87MXx<93+Py23_K)wHM(r)E z-QJK4drFR5X3-!s;ZJwF5d+9}{daV<{Cl&b zlmT6wwjhpQWw3JvJC1=%dkUPd{>Bz8z zsI|G1%NMaK)V|$uoZ>{L0oSi|yIcOJMRek)>CUC39N$MIZHiILK|BPE{FA(0P2cTZ zCH5vT$KLbwtm^j6q&S83*0lDE?-2otAdY;}_WX$QneWVOe_U?~Rx0+xx5kYPukQT2lxw6TOpyy-BLj{d z=6ls5glW#>;%f&FMZ%!y!LR!LUek3p0Re1?2S1`bQGCq4XSI^zEW)Q(5U*H@bgT8H zJveItzf=n&olYVSo6x<0fD#DvLs+*~3V+5 z8%qdcS>gSnp{LglKQ3r@4=@B#-Ex%ln*S36H>$wu0h^@WHlys2)L!&@p9UK&q`lx>LowH z$5n8n2vZ^XsW@A2iK^cM16t(n!u9D(PL4)g0}IX8$TJsCooXI2*tM&`U*7EedG5e! z$ROq}T-Xi`DEx^l^cm3j+GnA=s!b(Y`XE^R50LL$+YJEw|`bhSmc5x_#xeQdxR9;aq- zI*kfDNoQv#fu7o*cj}Pbzda+v4*3nEaLDWi*zjve!*j_B7Yo{)l;^yfvT`Xj(9FoU zg_}Ec@)vYI=VX^*lBD}s>VOgwhnHc4)9^eRF%FV!FovDPuv@j|Gg5aFJ+AaNOcd9d z=L6w@oy&hU=6Lwieub&bhHJ{g+ZMT|J{1#s70ZP>0w)054A#=sntub67QRfn22v9} z#aHfI<-z>XRQPdZBq%=YgrUzde7o--Ki-YX;{5sZwev^a>@Vo*zOE6STwl2e^8it? z5MUyrF)sxK1l;~~j5~IaQNu@@WQ_*4QO0FMAmE;;v%-0wmb zJMZ1ruU~swS}Y`N&hmUkgYmb!Zyy_5p5eBQ`JzVBW3+a{sko=uIZMK>Bws&1G7_=Z<*U=q2q=4$I=S@L#Me8%dLSKI zG{sZ|k78g5ikUyxQTP>Px4n8LuB`)m2?7CTN(2Ict0IdcQk#aOBPp)rn%u#A(k>(Q zX#2m!9=({>3|JI}pFpGs)+cz4W4W5~vTJkrD8qpcMOr;jeCOe9D9mi<;PB+>8+}2{ zCIK^utMeJ&SLDLyymD*~DZ*Is51%R!&6qPvOULfeeGgUSO1tqv*6PS%3_sG-`EiTH zyR@C0sFNDcXSLE)qbf%!qWt9Cn2QIT`gSx@#8C^cM%Byk1arWpFS1CD{gEKi)HKPu1_CphpJuBXi-k7CLS^jB%rIw z_(2V}yB@u7%jnnl=GT8vc`GQar7GRW%mWJ^3JsK?!Kc#*{Vvk)2J+54K_Yjl*Af>2 zO=(Mp`o_9O^}xsBr2TJ}+MQaz8F}E;K-3g;yH)l{rWen}X27E>CN2(0{WG2C?lQ7w zgDF}~=J_8jr}0E&<>n^j@+{I6>$Pev(_7!Vaf+nIJ>MJMRK zN=ImIwL#vII7>mI=lIREW<_nC3$4gCI9_}T8VqcTY0Wwp3j5*n;!|;iyL$3xcq1lm z`z7-xAao))F3&zAjS#f7qTTED&1)O4->x!saM0Ay7zZ4O7^KXK3YhI9Pw2#AKm1VZ z;cJMryO*6WWRr?g&1pFSsct2QaQiv%? zjP4J{lww=9D8Y{f{zqyCpyn176hH-~-7t^`o7@9!HErLFSlC?;e7Ytv25xa56s{A} z3F|R7iCf^)-qPM49%dH(p5t=tI{Z!bvORw0*Cz4{2uyjD0ZzJ7m{C@iU0i%nn~#37 z{hLwZ@uGXFPZJY!pxV6J9aKBm+M4O?JQIAnB`bH`+ra_Pp-9ZhYQmwc_AT|va{o7m4hf`{`g4Tn+p z9(6HjFm&QGo{iNgU}s|AzmVF8(au@u?=0)4QAsH#WMl*Y+&9R6+*|;~5cr~8VUsZP zQEngoN1Ou6v zYy&heF8=LFrj23tohsAG-8tf$MXh|hk~m94#Juu;Cc^$+T24g}TOtLb>W_+w z2A3{x9yS<^{XR`#U=9Gi81>28DH{ys9zEJCogjO%BDu7*Wn#g`n&mSI2w0zMujM=O z5f2oMt;hZf(+s-8@@XOanE$`}F5NV=_u@>>E^2>}jGdjF&{(0n-`uQVB!JMtob2r4 zmgdb)fYYTh`u9P(BKhpL$B(}>jkOSA27gXZ@3?T2TjrgAZ+^ts=?E#`g!B=oTzp^B jg4%!cl`?4mZx^wClIwE0wxjSrqME9bhGLGq>Fxgks+~x#%XL@cY1!D{^#DC>^yt2XTERd z+*A7#Zmq38Ug#`ftL6DLZRR#fp5C#DOMTG_fKKX>X=K}%)yJRUMq9`RILZs+q zZ)Ry@3IZY-mXrdes&atp_x5=Pj}G}DXe~}2gqpY>1Z-MJRTx#0iirXOqqeR&fF?W~ znhLI&DtF@$c32A;u2HNzz*`9OovSYGqT)|D-rm#Bt2G|`@w6vj^V8?6iP4rfE@#kO z2&evE@R~4wvP#KhB;BC|SUG}22%xmNps0f2bch-s%tAs#K}5~wyGGiULDF^XH5CRQ z@9y5zRNcL(u|TL$Hche&q%c8BM82##cqF^Wx1p#f5y6l=FOwC^UxiA^ zXB)A4{Gj|05X^`V!kg9?R|qE9D13ZvWA_0yl=ov`?H|N{#MKVlPy~^3lx(egQ5}jPY-%EI0NS2|E{DnW|h03vA@>`gy9EJs%%@8+UzW%tCB-;n76D zgGm|mn<&J+u1e|S(wZwdSuDcCdCYj{nE2B&dWN(ptM|fRad!4xcHra@vt*K7n~!Xn z)E1bfGTcOD8h)RKe)vd@is>A}75~%O^kB-V&2J)kXaYraVBDdRk-{aU=pe4Aj-R$g zmn0%~ZvyMx{b=?PLp7huV~S_6&BGe4kZNxGr*WHCFBE6?udMRfcrj;397kw$cUa~R z!xO0HK_f2@IG|2#tUSt{9B>bu=64|@pHl~6U~>$+!GwvxykcQE{Sd+Y89+WhV|+{q zu1OBpkPa#hpyftuvGwBC?r*5gUtV5X24(bcD;5alaQk{nCfYZ#-U$J6%wZiN zb}HzN55ju#F=NVn8x{j}@>3E`f{DWNWC9XA5tvvmEUO-Xa&7NCL%_xqJcMumYY#7u>?1dSm)popXTZca!* zm@>C+(zFDs6%Ij=bkcesEi&MH&4&u`jBaN`$kCv{O)7VkOjw3M=M7$W8XZ`TzR(S` zds;7y&Ubfx6Prxvf^mwhiTpos2Lx*s4ND+YVWk7K0zU{Q<(4T$m9VQ)9zvE8-hkbp zM2V?Pxzw{Q;p2aa7I&T+nY5nNo;2ML+&8=SxJI}J@kD>Y5b3cnre(6jW~V?*2>%%U zeJIhuifM=mi?NAOB-KrmHaUcCpw$4p_F|Fs_`@;gv7QZDBmQzAet-0)11CZz`8YUM z$kxU;hlggqW|3x=X1x{UQ}FDdg}&vjmkSto6d&+T2>lp=sIviqff%$z=s^e$VQha1 zO(`mpW6FAzDzp&jEm6~a>Zw3%F)-CSl-|U z*d5q0*bZ0*44Cl2aM^)@aISFj@FDbSnodO$sx+$FL{4ez#2-oWR5#R7)GA3QiG7JI zNljD>H2UfU>OG~YCHJN0s+X!(s^g{b%1WvtA0mDf*%h7^>*XSr8mY;t{VcOA3oZ*) zYg3h&Q=NT3XEdu`l2o3hd{mrgLBYyS7pN}EBi$zV#42Hq=#1z)zRMNm?77#jv7mgX zzE_S_!cn@e{8lKma6Tisuvj&ff1!w0X_?m|=-jf)KL(f1P_Nps($K8+PD`TU)Ut00 za|vasyxzLL+A`)~{}5vTi|g%v=8Q+4%*@Ta+{|j}XDv6;n6kZ6%Gu>oH}NwZ-KgL!DuEV(2#|7+NC;se@O|igSt0l#1>&CKS5Zz;xRIwg zXpuOBU|Xw$S%YVCvT{ap>}mC>@EK(p-{hQS@ni{8l}6h~lhf2PR#}JASw?5Z?$X_~ zyD{Z4!6KX@j*@GN>WU_vs!d}s27k;+o2c2&naeerX_;$tXd*36+6ddQFV-)%XIisz z7@pp?WI1;&asM=1JZDN^1?BOxQvxy3)k zBd=QgAfJ)Ro!QCR#wnADmnESSsS~gBLFW;>EYe{RbC6skvOMNUYayYEa5Z!F+e&on z%ck8)_Nm?(KktMKf$!R@M<4+t!TXpGF+K{d=J9)X*)MvJdhe^Ps)yD>)_Bjf&WdH7 z&2X=fuZm(SWBT`+Cq5_RS+kX|V(s8+11k?WQ(R6Z}j> z!N}?G*?>?xbj)<2Rw7U*KpiRzi2_OjGUc5BVl8xBQ2kiw9@N-6)0ei(=d2F5=3hDWdZdoe`H|AHrJ+Z87O0PQNHcN=24N zcn}`pX}@14XJFQ?H=5cRNRME_ z%+bnk4yxPMM5Ul+FXcaAp^Q`+!;vwg)F6v-`na;Xvd3$`Ccg%~9;iR+oBk_KIg>f_ zFs_xQ%MCWFsI;X?!qZ~Y^R#LvlC2ah3Erf5!?&aK6R$PAW)HO(KWId0sw(R> zTRe7V-oIrMs^@7qYPfD6?p00TYmVvYHb816w0||O++1pJ5IF*y$JbHN$?1GeL1@Ga z=V)KWZmXqJptRRr+u#6QXWgdRmbrXlZ?P|X#(b$fU#=QM%(%08)#|2cR<_XARKE9s za~nxIJMN@;u`{y%F<(Wpm+!q?vn;x7XMeZkQ={3!S?umG^o&2obHD@lsdKf#WMKz& zDE`N4|LV8Zmm=b#%FmIvHp^EnvWlO|SBl$9h1-mr2cA0GJ35})@7UB2RWa3l9`){D zvda9*cC8W)<8f`|K8+>3Fg@}38ayj%lz-ILeA@Bb7kuma61aDyb9i{za1?>N0r|0S zIImx1HPjoaiCv3Booy-|HpY+i8|j3P?Bm7l)J6gR5cUwRFY{~ZFU}ixA(q+pZyxnx zlhfr2ig`=SyVpO-IkY<>70l;2Dqs2fzoio=Sp?>->Fd`um7oih_=zj%CZCSHna4Ov6?e=ZjPONK5%c z>&VT#-NI>Owg+GF=MK+_wet?g3yP=RIqkeAPdkbA&Y6_O1>aCN^Lx9&RgJrEXHo0= zcOX}}8+p@x@e)fhWxi~04W;WXZ?k@9-3>!=F=t3lP&scDFDF-uYiK_b;)^{MjzUgC z6{7EBTm-c5ZT4I4AMPWb*OPp!-7Rk~iv`->n%QwVxUZ!zt$y7kbKu$|w!3;QGhy=I z?(6QhUEIARWaWSVJbb_SKz%zibFq`-m?P7b>TCIg`+UBHrR6+AyG zdk`MZ;TwGtImeouXfZ1x@r3xWFplBlFDy_SGVA^Q?j!yEDOzMdKZDeFWn>>vzKa;W z9C&0TLd*t7+sI+&J9{e{^sO>r2A4RWxKW7P!`ZU&B0mAZu92yxl$o3y$OqsU8Uzd! z6$BhO0tJ3SLM=fc{yGK$p#a`NK)~ZeK%jtkRNzlB7wkW0A%t_m|8oqK2Y!T9M5LsE zcNJqNQ&T%<3wxKxPZ0os2IIF>)pXI6ljSzHx1~2Uu{ScMcei!;T?B;Jof|l`HFYs0 za<{dybLMvEBl+tJZs7R$#|$Jye_i5Y%}1gsr${7X?_^5EPR~fsNWu?GL`1~vWMamx zEGqu*;=q4=Bo;0%4%`e3Zf*2fdCxyi{ZaIH8@LsmEP>k@ z{_aG6CSHdB>$87f&&%+;hyUpDe+}nfp915_56jE&-?_mLd(uLO0|FulA|)!M>JECG z^-dG>Bi2v~aw2k#pkgiDa|PQxW?P%aK=-M7e|Ik;yy|gx72EvjDLsTLG71^Q!Tl=( z*3i$pcMzgtFB5$%pHDmX2A|FJ?y|Y|)|6P7m>vS5U}8c3=k?4BG3%S1=Tt~02=+g( zTp~f1kcl392|-<5UAZWQS9`a0kDmWt(uE2tzw1-f_TBn{*`L|;2R@(Y?*5bt1w~6& zg&YDZ5$Jzj{_s+QEF#h2fj_=LAmVe!k;`Dt#p$-YuZ`PfTD{&)lxkGxRaKovU`?E@ zcTsu{`Qfozz(4#*lCfX+6e&?ENDc`ZB=ogVt2D%3Ed)PF1VgP0Bl8B4w1ynm|yb@t|SI2(3(baSij&gGL#N=0R{Klv&! zV!geHFzE#I`H_tSfz{Q8}Qg|RI79bYiny4s&vyh9anONL^9ZI zPEJm~Jh_Q{ytc4>5MWJWF_)JclZ}gutJd$r<*@62x;tC0KbR~}K?s3jV+AuG zNuo(Cbw z0yGSaU?{Vxe2;tye0*K)WvL?RB%x+4Ny+o+q6qF!&pd9YD|e@>_#AeHlbdP(8E9aD zHh9n^r}4m#Na*RSREpV|n3$$hAMXf_3=MHGZ!d=9M3l{#g*&|-62e7M8yE@4;z-Sz z>AXy*{6Ix&xWVe?Bw`38<=E_2+MV~h37bJC`AIUio_O~k$pl*cZ- z*qSafZVf5K(+g-f9;>UnUhOeVwz+Yb^osgN7}oyhxAKp5kM7Z; zDpbK~us9qjt1x(wY0&I_{sdFOlcK3Om(IJR!6pOYN&O(P;LD{RSL*!y_PRRkqzBve z6bjkx$PW8Q<^ycKvcgyv`X-mMe=OVc7Z|b@6&xFES&j@2d%7rUpsE_f!fgd&hWCKOwG;A%*@Rtm@8vKY$RGt=Ehw^9ld*~!5oaL3j|3S zio{XzygPl}{%%YLhe^w7G0CWeV$Q2{?rO8zio!h<{X(--FkdLOg+-eR4hNc6W4N-q z8iI&lS^B((D?lcbj=vc-AFl3*8^)o3!$Uq9G(60s|1S)c~vbmjBOisqs z7$%mnNd4LREEuwbD1V&5JXX6Ele4ufBiWNB*F>c8>2I@>c?Adv2u4OmIlLYw_V%G% zB?&WH5PKW=?Tw9}o^I*Ly+_}fk7phoK8~*WD1VPnh9+lbWep;}xW5pQDz;mF%;Iqy zfV1BQihI3y?mgb%^-#|?SVPGwe7-#n#Br|H(?v0zZE@xp=JRwBa$8%|d$_`yo}24A zx&qb+pSy#;l_GRAGVQ^jjJK+&yg%4G!~8D?%<=Ag0+#U|rKLD#i)ZUka@oAZZgwo2 zYJ%s}BPplGgH)Jb%*U*nKb=r8H3q}&t+l#}u)gAD*O{?l^V|wp8%Glggl`CfKt%0~ zq-?ASVKW!5_XG|Z8YeQm6=zQSfwJ4#Rb6J@Yei$xX9iA|C?%kh(-Ij(@xzAzOPSqz z9`$Z~R&_HIhqVOgB_`vLmpD?&I9lCS+QE&32QA+E%}vAD;H3->J>m1ayAO$ML@U#Vn{e6ah`g<=y!f^$Zm9@z*K2=%jpWsnO)7aKxjgn zNVqKNqz|N2CF+&ju{5eBK|9FElUc!HrG24DoIKS*LPoZ>q*@6%hCBmCx}=IEkBHaj{trjW(mVl<$< zC}6}DI{bz(;SNGV(pw~e4dMsFBA(0X{TPJ2!E$ly1CC>sH{64hR>ls0S=*F434@3j z0#c5_9ytsHr-Gg1u>HkkB-vKIdJP2pV6m1Z6p{Lv{C#f#s?*Z=*;+@^2NDRBZ>`+y zrmuY~yaMBzsH8U7!!^MUC&=!9hVf@XFey)CMhZ8#J79b_A5)nJ8f|`FLf0+TTfSs+ z!Sy@X+Mrt#d@~yh$6BM)Zlu?$Zyrt=1&L#2{=sj*W<<*jL;+f-AIWr3)(|qS112aV zJ#Wu-B$r2X)?dDtSDt7t!e~_Mg`B9ieOe8KLNb618$fkCTN~7ZQ&5;FQ!6Lre?|(3 z{&coRzZ9B8LJ|y%MXy|E21FDAQrUys6TB}x0ghmMAfp6}x^v|VsN9-?h@clvKfjsw zsm_hkGI$A1Wb=tpP^@SQ(a*NG>)Efh6MRcc!|9DeRwsLK4(dH~9$e5+O}USlqww=H zy+eg1e&c|U+5Dx#rwr}9#0td=lFw}eqp5fvQ`(pulDWT+U5Xj0CpFjyg40-^2o8#e zJ)DsEXN>O@@ZWA{!XB$N4&9*aq3tprqWAIfAt11uMt-`%tG8WVW3y)Okq-04&pz+e zadLqkMCoLe}laP0@sDp0tWO(u)gR=PyDQ&~oTqQ3T@?H)s4<(9GNw4&$M z0Bwpo3niY+$v~PKg9!%AAr}Ub1XgC4@qvhFSdpyjvf}Gk#6ZlbZo=trrd#4shX$20 z`L@C;Y=je$R=ZfvdhPCr_}G^54?!<82BE&SBp81KB|nHxYJY~&liQQ!KsM(2`3^&Y z?(o=<0NeD#*;2QI=?7r%b={woZm&<4-T_lD%oOl#^mz$kv!c==XACm1k!<7L`JSLa zMG69waW0Kf8<@rzid-0^S&hqPW%Qjh*~J+0XX(uPB@tn%G&9(3i|5m=ZQG};nng(M zWJ3-;sTQ|0AI%Ovhg<~p%Wjyf3*#@UiHS;N)QYjtI_>Uy!vzuw-DQ;6sC^+(gRp2O z;SI0xX6eDBX$`@~l$_X4>`-}GQVHnUtPdz?Xi;R@YPH|qeVYtYtkjBPO(g^-tA4$J z>*44?ga)vC9daO1qqDkG{Ea~guLeP+SILuB+T5__n}{G`937qTb-+e3-hZ(Q z%#lEUc%tFuW$dU~6R(oxq6VwM6vQs75xYC)a{1NYvO9)>$7@gtcS|T!re1c5B20l< zVt@of8_DJK{2mNHNvqlW3DapqdAaS5G1*usBu4&NU8COOqCjE-n72Zu(w9;d88_S$~Ev&DMh z7GME%I?d=23RQX?-)xuFw+mDtP&Ol9AY|QUE5cWT7(U#iWU^W%pmt#5>YAnnLBY)=iyy>YJWj#ZBfCXG*Q|Z%3lT_ofhiyfxI!UYt3OU1I6w8`@Z zRzN_1>Px*2)Uv=AHSUu9%1XL2K}vf0>+JKDAFY^NFvcRT$1zRz>vmpaXfYP$>T&~W zg(m0U*s0_Hpi706ploPp39L<_wnH@@Oab4fC&7|CbMp@~v1J}+<_&NMiOM#_c#Iak zyuFhk!OxJtwmX0pwd}0dk?3e{P~(&wAcFGnZ*2;>?cg!Tum`-AzR2YG$KN*vQLd z{*fZxqqInkzTNJ~s$t&L$W>-W@pyXp+t&xibnqFGELzb)e?w^>LNHv1;%9!15gKxT zRg~^eV2grC1lXL;8>YQK2p1V0CV&2n>f=aMo0$i+fY0y{7K6|5Zehk`|6PfH9mJwY`V=##k%;|4qW(HD zj1819iG1o-`ZK%%$Azf?CqpmDC;7Yf-&Y6@0wk5fcm*mt;P1x$-t&kCfQkySF);po zdf)^zBxpJl&KAD|`hSV+zYeG=fQkl6N+kcllK>%(WrDWYKR6)gj;D}I$HT?#^w=V2 zU}I;uo6PpELw^#1{Ay^X*mzP>KbaZrz$Dx4_&^8Y>gq~a%qA}Wv$wBrZg%!?&f2fK7zm$y2;RVA7+SbnjUx?J;s8)7m-DWy z6lrv{{N8xh&lYEG>BLfz|83nl9}Jo0V0VcB%VfL9QO9Sua8T3nOaOV`;bc~xpf57Q zVU2gV9DsQqFW4()ao+%u-f^?HMHK<$lvHQn@y5DJzw1Lar^`NwhqBr@K(_!^S@tkW z{Ev2RLd3HeGd2%KWk{OIwtd3i=^IO=o|!FWfyJZ^kafGmN}z~}2@l6*F%w>Ee_%G9 z4p=vyuduADnm9hemz9$cbU2@{c47U5~BgUV*x7;0opM6n<}R-X)a`EZGOY&g$okmWm~wTxHm`?Y$#gtyY;4x^ z6}l}>NmaT$k_}Y9wvf_zaBL3Iz2rlm)87rx?=kSUAv-jVPp0>p)c zTA;6;iG#smqq{Q@>W)}|sC#|>6Eo(K@d79rpai&{u2@3Pm8n&0)=qzwJ2H?aJ^-}+ z%}q$58$chLFV|qus8H18X|h|jn6G#TUpW**I505q`0ya4SlRpjfA<)FLKz}17D!T_ zPsfVOjrdG;XN$FPUvJ`>Ktf@pf$^HJ(uD$>&)I<2fFCzB%;Vfbww3`9X+&Y$=K$h3 z)zys+gFF}xXb5+IAaZ?qe_&%}71Ei_?@jAOz~>2)XCgHM@D{;tOcN3TA|ghK==Z|% zuaT>ZL8ahq*akdqb_#kqMgQ1(1Twp^MuCm5!E$D5sg;A5;AoyprZ2e1Z~t4RHixj# z4^>oTElfN-?G8`6Ae%g($zO#xBV1oz)+Ho{h~|&heKD3J!i;Z^-)WA0GaZ4v&Jgew zsx|3S%=fO5?{eZIgHZ=pcL9-%v^Y z1em#am|`w2*HZ;KQLu}Y{QUd?o4&lh?oZJK7=99|#4Q2et2*vU8cQ+IaT}y`U#6JZ z*)fW!OFwUPp8`QF2G6_+z$&wcGv@X22YezjSd5x8nwJl)U5eT!*6JVKx1KI| zX(mhCy58)Fk2$E*;fX^LgdL^1V{gsld3zjeJhVi@0w5PaZ$efilMdbu$B@zMx&>yZ zmZ<1mcP56)94RfKHf)GPjOd|ZApDA#rwfY)yQ-+X9aFRreFfhixV-C)&Z z;BO2_3|mJRqW`=9#wtOVq@|{MjcL}{hy#PUzAi8&E*_JOOhB-^-;7*zUa~=x46NkX z#Dr=ZT+u~r8#1+&F8~W}Y)r1tq?lS$$qsY)X7lqK9JqK{Q648NDJf~;d)R+;5RSj# z6Vh72trw8aBED4D)S{ll+d>-?y`R!IqPaDEbUJjkrU ze!{TZaoK;&4noNd>kcOU_uR=_8YPNSDk?AIS<5S3_Yut{|Im-m#lY5AA|HN1|MP?( zSSd+v_6OS!34cJV-+O5{5~U!^ZsT$C@*E<$gmHx2&;Ul;V3md{kt}g^KN2F zN-=LJ^WUiD*%Kn3)i|Bi^7S-p;^s(WXTiqCMyJ7Q3<$OPlG!yp-=tDSASPePtRqh$u4p(05&dvvN3GyBRxk)$1LuKxGu-Db>A<+!KRvvLx5=gU0X_e zJY|AcA^S}eU&`_;ngye%sE3jKtYBe0p6idK9<)@?ir=~6fx?b35 zbF%=y&vQv(tnBpUBvsn9z3Md^xcpVDfvU;(cyd6u%zx*>Ow`?_-4tzU$CVZi==M|1 zip}m9I?U+@YKb%{wb9YhCPLKYGv!!~f8ZJ^l*!R_wxduaLe&VvzKxU5SG$!!455~0 zVhKbjD0|3q=H=r9&ZdUQJ8us^h)~Q}Vp|PXpyJ^8)A`tQs^x^@iu-yzeWN zLYpk`_b2A1+ueP~$~wDg?D$D9ObbxVP}h17X7+g99k3=ccw0OhW_}Hfy&0?@zLw(>Ygk$&;URRfYk<{3wZ9?4eJHm9o_`6aB?`EwsTQ~0K|5Cx{3r2QVWH2 z8im8c%g+Ak^_jd#`sM6L(g+}T&&^yVWv$*fSaY8t>t=>`Vv*lM;UDz>+zq{MjWHA`R}lzS|_L39F;qDs|94xb1k`JTU@1yWI z;-r@wo+ctpMpezm(vN<9Gk?16h>oVY;8wTj-Kw>mxy|CatJZ2jWRF)}{ZU4+D?1GI zwDW4~OGnZWOWwG7mzy)K7{4>1cr+EUhl(D^`5iaIFtg}Ca0kB zR3X;gkvPWlp<{$$dlt}Aj#{Y%Gw9$zSB1xbcNB=GVmnp3 zm5w3a%=T*)z_Y>QFryw_Qp&%Fi!ge5qytu==s~*&A|p5nDd|RAcMO<<43I(r@Czb^ znVH9CQZFeKn+K`_o6~ma;oK$`#5*0t-A5xCkUZawZvMp&?!!BCj*I>o^MaW2Uy<0VGjOWfAa=L)F3d6(~+N>yA{Z-4)eO7 zV^^fR8w#|`0<@rpg~<<4yVOb)Ef1!}ieyr3=gR0t$%YjZC>t7B`lN!ts#ojz=L1ZX zs2RP1Xsg-xji5??nD=kQBbW|jAubw3srGYqwL=s}1{+4@>tZsUHUUEjhpm=?d35h_ zPazZwhHNDw!AdCEuS;87N@Ltmtfth?#ii(hYxJ{?O+1t+4vR@_G+GIXfykjL$Ia;? zn$1jWs=?K-n(yZXY{fexxj|vs)=7_2CsL@&0~)|1~4PTIZk+ZBqSu+@z}7t zm-9>m<_^O^qh5qQm;|mo+BHJbZgDclLC%42Fa`#N(Ilo#5uKTnG6NzgPiqU6!`=@r+_4n}D}jU#FqC*oc9akB@J~&afQFW5YLbYO{+OU`GRrd>li3 znYsSDTW^Sv(%mT^jYbs-Q>YNlL0jvGNKn>j799xXPUOjV6%-JDKNsQs{L56+%RmcG zfpqi^-TmW-+gfNu#JKUAMdI>O>Usl}o~0g^0?B^D>3acFuZONOjpE8m1eY2^#h-nB z2$Etn?ux-EsTKuqub=n(LW$5}^kW&(FSG>_z102v{c9SW_Si98?N?ig?a8Pll~5`s zu@c2l0)7PH7~9z)9;tdd`b{(FQM5}b1|q;nq*);BO&5(o;|NGmC;Xwn6{ZQs%RGxk z3`OHxEjN?f@9Xt508VTW346%_!dK?i5D-%vHF3G+Uxm8tfDRkk>r_uw@;Zn2l{M+oN$2VZ!F1bOK+D{k&7ad$d( zOIK2px49mL?a(mNovwB8SAh75e`6sSFc*hVPprEYAQNwk(PFo z-DM&ja&HW@IGj%m^il7xEEm)7W&y7lVnF4%&2dv{=mX^6)!v4^(eE* zYczq8DWHL9?cRtzjHE(WT(G^=vR6ibn+R4+)zQrt)VRQU0Z|zaS-JCCOb_mgm=-sA zkH~>=(~tyeP#G|SK!e89cqtJu8ZhquYHTz{UY>7teUi^=^{R!%5ZnMFqh?L5#T1Z+ zW$2*{c@IHCAx**i9x~>2v9_`8lWk0Nbn;P2IgR>TADsUrEw81+fI%ozi?A{?ufWV# zu5NW4o=@2DWrefb57dM;?drFs-K?4>bMbRdo<(Wzg$QPQ^VNp>7%kuzrHOU`Z(+&$lgRwPbN&=9FPJt z;$r@FAcj#9?I&a2|AmRs>2Se5Xy97&k)+`^32aRpi(UsJVq`1p!we%5zq2?>@>drk zap<$gDIUyR8VpMdDzoWSy{&ib^U5?y%+%1`4r;>wV->*O5tH%~h06vy2f&PQ%})1* zH!9;*lx!T@vq3@#D#<7SUW$;Wegg!0YHfDXm3LE9#dY~iO5~kCCn)=+Z;lpbmRchY z%dqnjFF{A1gmszNgFbqn9>+|4qgrjS##I4j%r(|~obOqTms3g#UtL&=g- z>h$KYDz#BQgI!8P!|h~g4A7=9tIwx$dAYnFZ8)71`BV4z_k)ta%kbz)$wqtg z(YXf_tw)lhfT$=K1Fg^-A_*tZ(J{yzqEhFi z$j1A|#ly)wHNgI~!wvX|LXW7^@KHonx;AkZYZbEMBWRTni6W_eP{o$q2?`mzL|vz8 zSa!hWJ0yWiOXbM_d(Fatf82l74nc0zT%3ex#-HeaSMitraYu9>O#ZrV41N3uI{g>b zQ5NwtleMx?O8L8Oe<>s2$Us$~c3`3ZP+wwk!B~xzMIu`Np^V`80f`iN2Q*HIzqi=m zVu=6j?}~7>X376oydMVnossd&=qCP$+Fcj|R5Ux8PyfGd5QHSk%_}ZW0S)Q-tAyYq z@^D4v$D?ZD%EOd0#SdqpF(^K-gj04?0bD%nbk0})<~lluo|c+*?q6kb^W$dco`se$ zWcI8-uIGyn1hjsvU(tJd%T;>Lt1e#cy3)rMw9qV^#zyTBlIH%;+UdrEDV)Mn0n8vk zwgjGlw_QAHN&lGC8-teat;uSR8!(+*+a_0%E95$EnE~V~;kBaTki7b>QU(s=1CS25 zbUk9XwzTv;>h$Tj_1z?lQ>Tb(*~+-F(U=kxaOP(z0Q0B|Th>I00IpO$ayUfGp~ql(yNp zO>1DQ`dC@c$5PLq@n7d{UsZpIPSd6cC0#y@Br>XfkUoT@E@k?Uqe-7E_dyIn?VT*4 zoZMJ`e*Wz2EWo1YI=zc8wj>~-pvtX$A~FH(4-b$TaL~}uuIQG`Gr~~!*E%Te++<}d zs1RUbd0h|P^V7@HNF}1@rlzvkZR4$!(w)VlaEq&RZU7VxP&G?CGIETaKn{S~J7_XG z@6H0deNmxZ$h75biDkLE?c?=&waQJygh#o2D0MDBsJ> zGopnmk}G%{wp9-lr&nJq!wvCJeN1=^Eqy|SRH8WZV!Le=rHnsp(OBv zMoi(j>H78crVLBB>nVg6?GmlY4Ik28{f8)XDPCdO_y6ejlG%b~W2s67gMA?%TbzD| zp$$#CoGht>L&BfTm7nE{UB#b;6$$Y8`@Zo3S>`fU9kJ6DGj8sW(~3-KA3oOM>U8a~~*^5qc%lwnF#L&b?4?F#_t3rG-Tzy=alA&8PL` zL(3f0D&y1eea@PWOE*P?vsxTfYNa;(#bYUupUTb5jF53~R=sE0x2;X5->=oRn%1tw zD(HXGZM(t^dNvdHkcB7OW@DS4RR!@ldIHr=#lgeIHS2*x{C>2vc~G4p_Ss*TWq%{J z>G7C_L!Wpnb00yAvvzpg3irEH ze8axnmYHIOB-)R#EM!wIT|VIDYUQOxMK`Z6pWEwwULG-ay~fA!085Nsm5xWVBH&y( z-C%qH+*y+vYE>H5hA{*kKt{~QQ0cci6desG5tFS5AkKS2a|?_8=_0sleT`>U{19K0-OjxF@qN!X2uM=Ez+Xg!`O`BpjJxUSKj%)?TV4Sa*z`wX65r?B zk9A*L+S=sOO_2JqS@Q1AUI25Y->1RIv{*_7y=`o~jG!Qhv!8WW8$IBcGM^lOR+g52 zERt@JPI?7$X9&2NfXE6YSvPV&Uv4vb0?0{>^fLNzzA}bgiN<_f$I#FafQ|=0XCUo5 zhKD67DTjdIo98_jYJ0jeFueiDd$UC{93@eN_IH;>PpM3#ll&&U&lcN2xTjI)%vUX4 z2k`Q+1ieYAk&Vqtop}tP_XH@7Wi*)pen8u3&$`_;ncU6D5!~g+uDl#(3wEL@V_Aif7e&}wS`%`^@EYUA19*M1z zA5;_-^{dt4w{_-3`|MzbGJt`(wj2J}xuSz~DXHE(SG6Thaj(5r=&2#irRGT%>1 zAI1l{ZX&QogNJF(+z3zkZ$qX6h)QHQ_|6%Zk?cXVcScPYa$`{F4z-}YE2?l-I?DEz zb5|u!*~(R>?Ib(+x7+~P413>{V7{(3JNh>G=rn004e3k`d~iAl)K%8$upnP8srNq6 z;b#2ko%MM5*Z!aX^^9(8_ZR(KUfyhRb<#RIISF1*tg4ERnb2-$^gQ3-zXtL+OD4SWB*B#9yvX9&-<- zOJNDsTU!aaCB=P!@@c=@jzWKVS63YCaa&-XWAuz*h3@@2jdg7nBLl)S+lqVmOSAJq zxjWQh8C0Ew+E1jBpo5N?8&~bxwZU3lxncqZmXp#oP_O;ET&;9+{-r7K*9&iyRnp|l znAh6@UMb0c(7$A&;Nkorkf1OEbG-QF`)b~9^Yd4!3T6JyrxWhEQkA#aQnd3?gHBH8 zT^$o)LUGA7X49<9WPtq_J8b6DY1K$cM95~YVnM*}W1dI(-dM8vCF;lU}#DIhsDRh^a9VIjH}XMx7j`*3AmUS3YB zdH}@GngYN=0r(`KUPKAmA2t9F1$m~@a#LF_!*vAZ`&(?tF!Qw^Wp)|tCu&b>xLoli zoB$8zJ(NkIUu$zS2l6XG79naK&WFN6Zl6?7USD6KfsNer_O`Cuw-0g;$n9WJDO&tU z#3>>15v}=zNuL?Pfe5%CX%%ycd^`c?eK0kc5ukiwbZmG5wldiQIyxDl!D>7uXX&m} zAbrro510mmrgpy@)5EunrqxMm2X>!#2NK`F^`V+=M&r}(qeEITKL7$GIBR=lH$Du^ zgP(Q`6Xn}EE1){cra1u~fqntbK&TkOr)j`6w_x5|HIt&>Ei*asiR0B~4`1luh{HeQ zcCFp%si=?|Mk{T$dd-{7X;7dpOWtrzpV5a{?y40twTI!On@`b5k}Z^-gcv16^{tgY z6F0@D$i5z3iBnqv7pz@SFZ_J!MaI73lcCYq?chD5o8kMGP$rOikMmh$rqrDb2I&`A zPlD#qKZu}nS<*#x)+ee3ozsSco`=9`~L+>b%(iAc)RW9-$nYqG9TwPf~R{c7Q z9^V`eEJvZ#&TBHy#HTESKKS%{tOfU%PD+#JFi}?o*M<~5P?3{6{gxN$ZFKetrFy|= za7qHZMQ7vNA2XXMQwU{P5^-Zey62oisk`pNI^)53r%2hJBK)p9?`poto+H7yZu@gYNS>~?9j&y?AOp@By;`Fpxr}-8GWd7z z0lnd35Cx2)4M@@T)g!&}bOCvC3cggo!SeHKaOhdUgy5TRJj$O!uWMqbx6$qIUBeO= zrfp`;gOjjucZNYs1GqWjzK$>g`T18rU-8-C9iqwvM~Bo9+0no{(~%I&(a}rTtS?`_ zcwCtYg!&5W1d{q2L;-%3ayN#bAErh4@69K&g=fabFuap!?kGd}%*SQhnL|C)YmIia8Y%$i zFX+1>pEyzhK%OWEggAwWwl=)WO@&xlu$FW(ng$95AhQF3IXjjC8>(>e3sbF(O0O@% z_)wKcKwur<{N2uTxk9Aa;n6K$cI%yCkN}m0iFfZp#>e-*J;qTY8?VtkFBnOt zdm4z?8_#)Dh|`ga2dqtDUt?KWMy?k0VeC)iRL4TScQ!Zuu`sE`yf)@5+s?s<1kfcZ zZqB>IMJ&fNxft|2O^l5ZJ|1)*Jx`ufX+*7pBBgRj zM`i3X`|((>L5MXcHYP)ke{K2J>Ha_vFyg=bMK2H;9W`2z`F)YAF z;GtP>zW}}h<2scO8weU&epCk}u7tW@FskU<33@Ag1R@<40E>dh&0*9<_!}2-z^RBN z#5b_Oq=E(Y79A90_tR6j;snEaTBAG0#m_7$If6+vO?*0hUc`wXsunSFmvY|GBz=bh z)vhSCXjVhrL0JxFn!1eHr?%0pu`IF9Uh9(sFO79_t z@77BHcEkc-SSlQk6rx4Y>XA`lGHnMeUKA#PiroX}y4|E>*;jWCLx(`rrbrM z!W{t$2Yh{o!%n9UNJ?}S=8{o0P>`dLLdnU#1lv+q3Cmu`A>l!qk9wkbY59PO z1*CQp2?!v%di2I}x^fle4>x+49xIAU--nL7(k{3D^AX;-d!QJc-}Qg{yILur!omDf&tw$R4zrH3{Z|v{B5)Y z)cOrSu&ev!l-z^8Vs{k3zU5`@74^j+At7vK;jPY2dz4@*7iFhG5}Z8s_E;u*xDhQ; z<_{ml7quL`4YH7!H`RL|eq^OM)Ieu-=e|9EdA(x6SYCI#D6xyhKQ=ZN$YdAEGg*he_?1%X6_KJ*(2P&y z&^%*M3mEj>KXnZm!PADNF&QKNN>|p?urNx4`s&G8SW64V1*mI7q~TnSR?AWkeH3QN zrx%^*_YgIf+GURcN04*|MzH3jA9}rnu@{G8VCxW^RVw2AK>A2YNP70A%N*NrLEZqz z6o~;Xbyni`*~$S}Uo~Jq05Y7hNo5AH;83^zYym|KUrzD(Jf9b9Nhho0lzQzz<2T7Z z^y1%<_;?`Aqi>2!e$BG-aX5zxiV4?pxbIfJxqP%Cra}-QtDPPkx8qIRd^(&deycGo zXme45Fe*CpFJ~DpOC8(lj{csGdnoL)hXp?ZX=p}5JN ztw5r!d8>e(EhSv_o%{5*07B41>0u$+P=1NyM(F>c>?^~nXuGxn0qJf;x|A*frMtU3 zMM6rE?vzHPRJuV@6lqC8kdP9j1yMSr<6Ay=`~Ld)!LbjN*?WeW>ssrqrEZbKSQ>B` z^+>CX;1PB6+spkuP7}NE&>O}gvZ%snBTpvI$w<(ptL}?72PcpgYWr_49FE^2yBRls zDdfTN@G?CA74DBeaHcaiWP%Ia7wv29mrrr2gw?Ceb6l6!w|U5T^^B%_J#PkleNX$! zWo=xg>0UT%u+TDid{wpZpc(Nod_^%k!^)bU>EBB(x8 zzy@exqoa0&rKNA8sr19*3GVEi*-l0iSPWe5SZ;_Gf
    yk1}drv6V+uiXbF{Iurs zSFYmdWUSK1VO|M;hCg9cpvb>YHv}ewDiSWA`_r#Q`rAR3+hK)%HDA*~vDfoLR6ilS zO8AUy7^gcspI!}s(m-C46HL9Q+Q?T3X5%wOoXqvmFr{w<2g+Om71{P7^4YD*chM-{ zhAQ&pww)s*Yg~r$wTdY%7@s&=h#9kDE&JLsEsi)W^pCBV_BkXnb z=x!JKVjy+e=@%Z?87h=9q`y?K& z-BNcm>V3#SeqB{sH4dBylulNksJZ<$H55Z7SA?ooyFAoQ)*D{;E!*?xTo>_)W~pCj zb`YmdH7HVCXnAo1)35Rk#v_#{Q(cMioZB>lDqo}h1~W!EqBdr#%HNMpiqE#ZO~+4* zwiEGcDQ()@7V#w^L><0(f{r7iL$&fJ=ok1ru<%YI0r_<@HeFCQbL*0dQ@d9#^~67x zzt3D$;Msg~I5*SiQP+)Sb$QVYT|K_LV6mV5wOmP6ZG*x>bu%!m+4|Jp_KIa2DpnQ#xn&5VcF(vk01CA7S3-;{O|SUsE3BJ`=L?#zf1XymCgz_s zdF2XDf7njhgNx(4@VVK)eKbMKy5b?NuB8>DIGbTVGVZaz{uz_IQ3hX^kQPCCb)HSE z^C##nn!u1NAaHIjI@21UR^f7X)T%Gxzxl<$t1#h>N2I2bD&KyOz+>~+(tJ^UpvR4>X=`<|8cMW)r6dpzFa0=C zUe3Z~D?2^gHvfdi7LX<2L^6dei+HAm%X-53nnp^S`1Q7?9evFDUaQj1*iu$a-R%lh zGW|Cud7ApdH7)~hC1%PnUIq+`a^K>2)GzZ~n(7*kj5l-9*Jrq%b(FGLR`&e)8#79= zw!VAemRe7W?zcp!F-x1%p?46+YmJqT?L@qwtaef2rdht7X&JoWtX+|`M0b64$bC@v zFHbo;U!x!+q2T@rU?1^-DdS0KeH`anAKx|sK4;Dj2?;*Wt^%#LdMLXczIbIaXW6-d zauknY$1}ZtLs7lFF#(X{MPaT1-^;WUEAAe3v+lvi{EH+ zmk3@a*)g@XzgyhOs>)^4pkgJ=K-Wt7B|`bg_sdb5`di~q_3&}VpZHvjY}&(HBYDrf8ijXB9cy?3W3 z2}$W8aa9g3EnmVp=a88QGZ?9Hzr=F+SM3B&UJ*A%CU2#3+zzZ)EI5;XvJ)?dqkkHe z!jyrohQ{`WH9DT2Kv_DBv9vHFYH+6QvDQf_%jm0DeEll1vnME5dz_hRbVesW3H0V% z?y4ZXW_`k=#h82}#b+^Fn9RN*fSpgLBl{0sW1E^Z&DboNt5X`Ph}xpm3X9_L9X7_k zUQX7FDE-S)sV-?_QBt*i9@o65Oz)B?9?vHxB;6zF?1>yPHqlnzx6q`+dCOPLuE} z3xa~qKg6)Vs^{Stg;(shz}>w^rvhVS(jBl>odc+04RlWC5O>J#D zj!*f!t%aQ9Dzu1>;VXep9gS5y;P|+K6pEbo=@nv(t(N8rIhSmtVvF!_>5GNe0^XZ@CqDz4*^B zY<~d4XYa!oMN_o@FgRx%K=_<-Jj$5(i-`E+*Z%(xFMo@dNvlw~BrGZXM#)C-$$#En z9I5qskoGffd;1?pT1XboVr#3zyubkK^r;6))Tq*M z&5ylLzU|z-pJ|rq4C)F6cXxNM!lbhaGaagHE0^bw9wlaRW=RS;&wedsscU2S&nd$7 z2@JGtP+y&EO$AHv^c!cUPln*P-??j<1aeVqb)y#F-sKOZUmpNMQ`#_L8`9?CXjTD#wdn){B6O|VPceGKuQ86*V z_dLJltN>!z%Oj}`C|4i;7}e67u=`x2p|3w#>8HmtHTEvt>+(WmQ(l&mtOqo(30R2i z>@PvQ_9;dI6+ik9VBX&p>HD5P)hFZfiCbJ;$Y>xweUDAShl7qj4#HclLgQN7mv=E&!_{WkP??FoU?(#y0;7;7>Q`e={8!!a7iD@Dj@0Y4l}y2&t}fPIq(v}h`T5SaQ-EhK zw4x&OJyD;6jzRO(JxI&|uhY!TOd&`*E9tB=1K1ED8H4N3fwl3M3K}Xm{78|Y+3Ps8zD7lw`$ov!);B_Qpnta=WuHpe zlJwtyNb>ZyLjfzzuEqC>At3lGHEYd@ieg>t`Fb{u>)hRq#IX}g1aa}T8?$fCX1Tu-Y_U=u#Ya$|k(%B2AMcZ9eVi%Qs zT>9+~^m{ZC-}0o^7*#Sh#JwX($}hL?_Z=%MJp z$uAj%?C*sHzL+nq0r5XbpVwIT1`paVT;2UZIFItDv?K7jIK@Qw`)5amHE#}|VN;HO z%oOqKiF^6VqJ{OxsDLPNuD6_OiV zgY|Uq?F0oqzMdtjvrhId1lgYu$wd`HkVSv;+B{~LM1*EGieF>9V|}L4 z;c#;U5_OhV>*Yr{b;|`sW4$+~h|f&wT}W<=N7B7=bas9Ob|1MOl#GmYKnmA3FOaBY zq@{D^k`>w2X@bl$5i-vZuQ-B>iRq1Xl@4lBl}i;9cIKejbtKM&Kku-w$VW(Osv&L- z_@0L!uR78Cv(eEZamD~NiEjzIVG{Tzgjz(-=Jgi;?8K9l44Io7Nf?6?MB~DEv6g znU6E}f7fU}8n$p>e0<_0S_Hkviw;G*^wrn89%+CZZFk3N6^xhP`VCleKUi83Ka9ZH zpe7=UJOg6lSw_advu}8FQ{Pgm6>hmn*MjAOHZKfxu3cr|Txz94bo3p`mFduZnQ?S{ zeC|Oyi1`EKS=ZDJ+W#pujGaHJEcWrH4JUn!4Y|14Z=w1e)uaKh?F+L-dTC6dtkd7>HCizxAW1GCC%O2m{Q>}Z7X`9Q9k*2 zUUU05)eE&e&6uq+$WeD((;#>f3rAgzDM%vy)`l6hi#8Hz!lnBxz!>&2WYJaVef70diw`dbc zcx8!WQ&Ps^FS7fMGnBIiMA0}E1ilQ?dU}JOy_SGZ00|2z*{YcRC>O)lm$wFm%3i>n zLg>Kp>FF)UNn{<R4o*!FvL6ku$8a81N} z669SiSK|?BqD(3H?2^R-f?&ZPEt{y4i=Tyc^@dps(v-v!FnfU%EmxhLx6JMBA2<8q zpXvVLyS@LVzR(-}|9E>1(DH4f0#^FdtDP#2LJ&igUT|A^1R;e%$GiIV71o^1v)hmG zc`VB8?CrtF48*Zvljpl4>k>w#6|;s13ze;<<0V?SyC4gID}ZK%qGR46Eho3|f%cas zybG>7@Q&Z$;X14R5@xIqf=mO)lA5*?4HPnW?_oy0qyS6L-uqQ64 z`A>0n+by~T66asZLEFrz4=&C=7buaYKO+@%F^6cK(*$z7d2kkz>p~XRW3^hR>DMSL zSCIu}UBFAV1~ntd@W9RW6KpPFA|b7XDn@Nd5+$)Jw{oI5b>Nyb*bOg&e(Z3^D_Ys} zq07Nx05t_gVcwGj>A15r;jxc{gNNYB;oxXoC^o3IeOg_;6Gt_TLw#}8UP3~`s#`f> zO-q#)@n`_d9#BD$GlyABD}z zxt59B9^9-%al zkMGrfRvnDbn zNk0-g@`v;Df|LVnl0uM~liCMQmlAdCv2*R?6$|5q zCd;lQs1SV5$O!Q8fPvR$HOqlb`@a|U8$-6OrDc*S{lv(~`1m*m4$ege>TqOc=Jk}_ zoBX+Xc_Cc97SG$Pu9#up;Z+na?H$fz4vmNq>JBh1RHI)1@Fm-M?z-__DaK==e-~N| z+l2V?5!pQ7?ZHO6&CK|TDH|o=Qko)>lAX);Yp=EN?zRg!U96to7|YHpDM5F}bxN~# zsgC^5r}M`^`u;t(H;pu=`RWbr;{1{l|8E~RlG%!S)AZhH{G);VU*Ro}?C-}b+o1is zW3?4EXy0J*(xGZz=RdtH0{R)zukMuSO;pIg9E!hgjU#2~a_^EP|L01<+Kd4*NdL#v zof3cRZ2vf-FXTO}@M0?d=K_c$iJ|;*ly*5S()_l_ixNV&oQ}fy`)wEul|j~`fNR2U z2g*YKl^fxwS|D!!rQQIbbaQiYj0e2AiokJ$u*axO*94-oZoMG|TP3+`@-@Q$cBtYb z$fL^2%1In5`PSfIgBUb}Mh_i28*!y-&1)bSKZFZL!vq0%m_dLqo$TQm+5X zOL+u>_PMRt*p;xUgr|mvXqcD|K)-Wv-~rKrs;Umn&CRfA=a-c&E$w+M_t|jKiszX$ z;($g89wm42K(XDQKYxOGX%zS|u(mu}8`qdOd~^Rp>*e*S7C(nvcCZSL&Cb3X9pw`c z*o5txOLb-NQ9Tsv;IS=KeW6ihj?cHad0{z{zvHGBos&b$MvkTSz!lu9ay>E-Nhr-T z{J6@+dw=yDQcf_VHPtKBb4F6wDRHjfLGat3EE)_9y5bZZB369BQt5edW+2xSmMi!B z_B|3Ne!{jBflWw7#qXTi5p>0eosDh!)xC&!kTTGYAn1D(Si7f4pXWF}F7O`489WAu z_rbQyGv2!^;JSNE$_Zf;`p>Uu$tfurHROX(Bl1kzC{xHiv%0z$+=~BXImqJwn3^8E zp`N`Rj{R|MqLM>BdnlQeHy@Su==Ag|Dk_Mb{dd29ui}Hd<>QOn8=IRc+Ffi0HEm52 zau7lhA%T*IStlI=APMyDvdV_JB7HYEKi6uBqW1lE^O>p9_%(402+VL12`bDs?F4HT zz`kQ?4P7R94p85^EYLxcMYy?*&Mh9E5g@g`!pCX1%F9W7&RQ_#)^yLJ$*M;HAB%*D zh|jhkd6>#u=;4pffoHc8*i66VDn2cxGZO}LfL&W)&gH4uJwY!=#}g616YD;r>9n*o z>l;&3abbudBym)?M<5Z8Ol*5Q?HTE0YXB#YmZrv!7yok5{CXJ08}I-tC^T!8sIwmn zk_gu4;peXtyJ*W=+}_(G1PAOR-wSFXx35P>+|t&I>swo?ymvWROKuduett8R`&V8V zrpf0$uy(ohmc!=Rl7)4gbm5n!=s%j z;8Wp7FV@F_0c=}YXd2JYd>1|k8qxFZ)9>fyS(&3)3=8@4%VUtL4hDEZ*39G-_7r1>qi`1wf3jl8v1kZ!EYy8VdB3cjvrT5q)X-nfC!tW49K4#FXH15efa(}F0KYe{N-6-+yA6`^cGxuk_ zBW-RdVBepp*xjH;~>+PwzCF!igDT9A+ zg`gMd?k>#boD}#w|H1ck+-G%2L&(i~Yk0}|9s`&&@l>HwTZi(;Dp5I_#-(g%V8Vbrn`zLZQNrVk!b$Tie%7X=fR1$zTCSlLGDj|$_{k8pA4fM-{ z=})R2f<66~dAd05@Z*|y%&&sp&3p6n@qrJAxkgi8gW}3xGP+-)`Cq#EO6G(ggJw)) zj0fb9q}j1zqQDw?24=DL&q%kwLcS&P)0YOdam@1tEAG{c+A z8y(e#tl5L59(1!;%3crcVgDl&Mg8~sBgPs;ZQgyBpYPvn@hRr`=O%0Aze)svAA0?~ zcW+5-ubJ2usRmGsc%ugBhwrbMQ2qPA!8SfpqeWg~ql^S5@prc4I5?j`tRF)xN5LW-sh&8K>;#F3j~4%_O2luV+nJ|+)z;1NmSq?M)M}C)O#1=gIu_mZ+L*HO z6=DW-XsNpnc2X9dQa;gP_x)A;N4I1$gjfL-;|n*nK~ zj+8}D1Oj$TrhoS5GbCid_%XjocQKY5zr7Ym>Z?Iy^kzZLcnm~~G}>jlwZ6w#+?6EqOZmZ0bt^aovOoHJrr;gG(^H6+r^eLZWSaxAyA&68<(!XojQe0w| z%>(eM_;dmLXsxm|tu7)g%;E>z`Zb6YQ-{m%^e$K?j{5SA?#n4ls*mB=)2|_D?DPN| zD2U9=%3pCnxFe$_9@~51i)kMkLaReUI-|N)=;h@#HKhtUpq=1Q0xNDQ1V_a`|Cr8u zrOYoMu`Njbm7Obf)*JN{o@L3tt86E~bmVW{mZ9Qc5&yIIA2}}jo{AoB%|(nPfx2*e zdmE&`^rQBd7kQs+dM_y5R)^5b?+<3a&=ix04eLv1C((eD(?(x1>rI`7&D*zco3*Ti zi2NrAEce$Y+{eq0^;u<`To!y`#o`*|F!7fjBxF{-Y1TqVKoe89KFeNvw*48fN05CYN*6x8R#;w}T86OVQCOm^Cw4NOs zP;yT-d36-2=ufn_Yn}yR1XY-$l%@H0@S`SA-tZ`>H zJqq#{2|S!~1%P8^-#%c3CSps>6Vj^GZS&g$m|wl9A}h1(>Vw7Nt?QC=IgS)G%-;bI z+Sze_SzaE2MScOvs#R57>mROSkp*jnV^an(wuNo|7`uszD#T65a$T?T?)Uyk)F3*dRbhlgR5U^Pg{jVzm5FkYhnlRLqFcLZ)oZXW&er3t4=LydG)67F?m z$-K7q1?)%#sW%c4>J{1Mcl^)rZegy;d`k%W7_&Ag#)*vlMJJ8y>_puS+!{mT?mNZV z$a@kbk4W|_O!h)5g3--;11|lj9%Ij6;pxPi)q3kTM#`B9k-t=rIf!ig$XcDH0$jJxMg97^ z3K04Du$Y~3ByoY)G^{d5_xPG8i``}MX^XPp{JffQw#DxgyzP+wdTY)Dh@T+6uK~g? z8Dj_)&m3ZbRq^U*!trvd*ROS5-t+291X;?-yzDXH6Uu;Ud;R(t;tclZgZevZv%)m! zoNTu)HBG5v2#P!1vU#HD5kuLSY%LPyUX)FKdCPMJlf#Zko2UVtcp~g znUrWg1td;dM&`%b+T7bE&deu}STpsRIPgxt%E1B75R0#`F0D~jwp0+(fn9LG(fh@( zuvIkDgYw3IRbD_q0OE*>O&YH&0znsJ7KUk0yW$QR9H7Xd^(b?irXGBLtdax`I`KZC zb-?*gH2;PBsV79l2Cp6K5~@Mij`ZX$NZ~SF>_pQ7ix)Zn*=CD%tO8LR#W^eQO={qO zdZT83v_0&3j@!!QD6*4D*!AAGyh|%8KR6DJeM=Q-<8wW5%h_h&x<6J zk$p|*lR=Uacd!REr_$69pCVuVRD)2~$T4-<2hSVdw?dtaiYj_;QvY)zs%6GdN%lsY zCN2N)*g2O|iMqR_*F$xNKpbH#3Q=z&{0R)8%JS zrtuvGi=pUzQD4iI@eYsqEy|)Ru~QDBW%%N~w*g{!k5rN?4VJ)7lr9-|E$4GCo^B1` zcS?gX4Xy^Ne~BfwU*H{8p=+7Cz}LHA6j#$9m93jel``^yFH9~%L#2IueAdN)Kzw7_ zWr>yzK@~`oR~A+oq!l4@ss8Su=;Xwr6#49|5)IQF`lqbaHo%qVWyXutF5!lxnMXv$ z3!Ps&f8^_H494IEYR|>c^%sXl#*?Pb=Xi^pYv@vBA2+9)e(Y?8xGnid&H*A^P z{Vpd#zAXSZDk0%lkO6IwQFy>d^*b){p@Ds7Palyq6fm&eV}io^bK{}eC3g_keUaqc z8#<*XExy0T4QM)BSX8?d~wf^m*O!a7Cn@*()DPs zkK}2dBWQ4g@bz+kA^*`2O+BD|n!tXdO6f3K%xe7fS9mk5RvM?XyeujQFh0f3G)J-k zgBXvKHaa5FyAhtj7c?hLCXI2CR1v8e#om`U*ChB9*4EC=@bU2>dpTsP@ES3_bUy9u zn<0%`7RS{L7MI7+d)&#^=Mm#HikQ zh+^;!B#5x-kiz}e#BSDtW|>REL}905Yr8U%{FN~GR*AI#N=ewr*G~j41R>RY+}t_F zZ!s8^gcnHUovvd42niUjimh*GSSSvsy8U{dmEinCEZxK6T89abE}gd( z#Eu3O!RUVhz(HHj136lJiwNGuQME#6Nk;o#kPU6tl3DG#98zNzI$<}|uY?l)BcxnR zs?UGSt541}WA?cwtIxG;t`2orX@lTsfiRd)wJ$hAp(oBs8>h3qQbs(KLq6}>!M3EZ zcL!04^ao_q=8jnPP&K>zbkr0%H0b=OlwTr8w`N(i{SL|x2*>a6om9W-&(n-*SIoIo z3c7}2fIV}tcB@{SwMfLr<7}r#=&bDCr$P~BJV7Kxm3c457jJTMBH~NiT~W{!gJ!db z`oM*$Gj+Rk!6106Sd!V$Rxa+$48RxxC&Q~cR~rcF;H$Lsc zdse}7$HZXwlhUiKs+H=YcttAImqfay31dSWKiB*PKQ{picyxt(Rq~m@OVZselL!g; zyp_`5Fj@r#41K6jop{STve~cU!;Bzg8`OY=Fyco5JdgOA&llj(5C8Mfh|?vsP+S>C z!L;qrn(O=;@*`NPf4=tXQf;X!73p*E%8D)BXUtcI0BQ82lZz;;&k)ochCqzGczR+= zBv)Y5)Z^T;e7twpXTLsH&|iAoVngu7V)K*PTVfAY{}Lj|&#&PR<#)?-oO-Us(4>E^ zC6)ik%*{P~yf?k{go;H%xfQKhoFY{pGebT)xTr;&gP2DGi6J`)p{WUPCBNoI8A*6( z=zLXOd4q68^j{>(d@D`1fPid=xh57?+~f8#%MB`9zWv@(PPKXWu5RDsba&~$?!aH@ z6WoMM4$2L7opL85#CdUG^&uCRwct3`l{Qal<^FN6zl^NTG1O(7yyJ94T$kBMQ*g+$l1 zY^9&=OtL~aXDgQ)PX?Tyl;yf#oHIN7Y2U>7J5$T|4YFPA@qK4MS(5vAQv=!pX`zlU zc8uAz`Jnrh?R&oZ&8Oc!+y#ueA%oxHCK~V!!EU}PIyrZ&KD#b88JqZ6mpc{O+1S|$ zx-LGzD>JM+VOI6*O?pavL%UC(S>U*TB@V*LOn06O)jVZ+ek)aBN=u{CaAD=AqOW6? z&Ex5_$t~5x z@juG(0HL|IDuaaqjm zFW;3_7CYNE2(|mU*G_oObXKZ@o2A4QALcrsh%%t;R=fsFQ*uE;SBX{+fGwlFzA3vF z9kLS9DGgBBE1Vus<+J@$17sy4yyz39?`NCUIavQ3O_b;qur}db?>v`@Rems5mf(Nx z{Wv@&#mjA3QOnc+@|^F&I=h4IlXRwRLv&5u0QL3jukX+Nc)<7+1q*xUyW!^o;{rbg z)ey&VFO`k*e#=FIb*F)0E;c%j8%!-m)4OAR)AXnFu19D5-|}&a;vIdDvx;CZWH(W? z9;|5nHaXC7cQbM-gBVkwRHr;pg~RV0w^G~9dV+c+FI-FG=KHfv%2yVZ)C4*oh*yUz za=)D|UEdTF{5nWQKyur4A?lVZI*QZ4M!A~=O>3+Wku5{8RNm4eVPXOYZ>=$mKbd{& z-l)9`k*bc4SlF@oAKBUWR(k1;P&og3AcF=~#a~iR9ah$ztbhwh>kA^I z^k6#J?|&88%gxhEv)$0IL^Czdtn+`cSD0PIQ7N6c8~JpBp_LNYdDWE1I)?h`>Q)#1PqLf(4nUb zxhuN4?MC8TEexU_`yQ8DS>+vWO#AGw(xSbw8!q)bjoT(tR91#g_dU$=%138mNM_{j zfb7|MqY5bM<)lNwW|aLW{g?g;!JzzOXQwqJO#?aaJXWewX*wev!DR#KsE(i#bLsIu z-VMvM!he7DYAa+=JsQmP!@|M>?iw=x;tAeEpi!&s0CmmXTWGie;1SseBzv@SuGr_% zVe4fJ6eKcic$dgPDq^iYz7xxCBoK35?2m)F@W+e9PL;oglieVuqhV@ z@P{`yU67KHgts?5TmxEStg{oSN?QnXhBO8Ok;u6kMkmxqm9!&Ta(t4DoyUPHtrrh( zb1|^8E=MThc<2`H?&^9egWJa5(sBFECFa_l!WV`qBJSTs`4S#~^f+(S^&uzlTit)L zTi{5AkzZ1`ggWZ}>W!e+MW&AF6I3xGbl+><3qR=Hd8M=nuh>bScsG3W4f&z_=)q<6 zNR3K>D&?4d41cjvM)XXnQ_Hu?JIPE{79AeNx4^0apfW`!clrLetRg`{A|%t*F~9@5 znn?~(290`?J_6j(=yS+%{}VXoATd7m`E!^aQV4l&!onoPxW@pm487eY;LtWtR)Oo?<; zm+dnI^tU^PM#q(uMAg;tKUe{ZuDh%2;g7Ev7J^l@_;`3+0T=6mfsH_G2fHzPZE zY68RZ{1jb7iaG7mKAdI-PY{`BQ=)|89900 z#^%g)_JqXSA9Dd*Y}z2!Lt-q4jXREOL2GJevVEA*d=JRB z*jx5=vy5u@coaj=ksr%>etpJW8^12%zc<)=9kaLnAVuaH8*bLYT+?OcvBSq!zh{$G zw%jEho%vr8O;5)+8+O-iwEZ2@@of_(E($0)>9|4K&7B@Sab00ozCWFpm||(**(FWT z`qy6Gs^=gCt1#WbzBv#>?ykYIiMg2kRCS?T{SYHG8L1Q|pUhz*@U!6OBrJtA z4o*&29K!J+YG%Y++(I~%8#dB!^eTU$`IjM>Klg&e8GpNFjvA*eMUQhTY0iNT1> zMw4$)n}QG)8m)AtX`NJ;o;qvn`t`hQil}hVgrg$X3rReQaI3eCeRBt!kdQYLhD5;- zk`Vy$r3t^2rj#8W36>jXpDsig##4(KHtLeteEs&wrX$=*kkbOZg6|cTo=mkLd2N{@ z)S#8(hbD^po#b=9Zqv80v58I!$F`W0H>kE`9RV-~Qjal~l-1QUL`cH8-bzb%N#)7Q zE6XA=em8xz+1fCFh-az6?Yx8e=9RCP^1Qjn@rhPgG0V3_7}D)66QO8ht!wsPKP@0~ zCaW5R+%;@5KUBWl*3vQ%dj6R%&&ECSah#SA`5k7@Ied}>3Urs+H;)oB^^aDdGh&Kb zsW+GH$P1PZ!yw+d?RUa3Ii6jQL&1l2S%P?6Rkcmdy8^ioWK1^8%ot=#i?i7|_56>v zPON}dsZ127H9WsKCD*S?1n}K@tn}Urn{|O};)={)^>H>MVx4`==*3LqBTv7{e1+PP z0wtv|x}ZxV&@($O_dRq`#K*aTfkaW`Ss8VBvN3%bnr2m>`>qo8vi6bN4Vdw;1(yeI z3mj4$z8?P%9~`cE5V))a)y7V`!k|!uIKB|npO9M2{F(-2u%Y?UN>X|gn}vn8p3KcQ zAG)=QRLw(>q=JU(S3a5`Q@;h3qa*<(zGHoJQ@2Cf^)ezfv^}Lyh3t4SnKx5~*2&Z@ z^YZ8yRvA6I6IvhMRAH{Jt<^H97%Fljq4aaKFQD>JS2qXsWK4|pJJcc5&^sO*@-#?@ zYF(k|PjYm5xH~g0~9PC!sn_5HQ8j$9VihzuMIh-ATDcDk0-E3SmlEosG()*E4lF`w%xxbgAgRQvBUY~pl8-w-_V)KqfcrK=BB2)qwPSF*Z0Y3QlgaD_OR%D-5-&GEX!^hWecQ+ zH$6Nx=dtOqt0q#3$il*5zYKjeRI2jZ(Rcj#Nqr;2_YW^XZh^_R#uDp!XVQevM}YowVgLtea^KUm7_3R zi=D-L;XGaz*!P?=S%$CS_{&GSLdLHf1V3TV)I9#HX&3iFvL7RJd;o&kSQQ4-p%hL| z_iFV+G4rD#QU#GV3?6mz@$%0!;SmHQ)mD^YCE{%ZFK-FMjLB{$2t+&eq-D3hBhn+O zCqdEtPNZXS>&6J9qF_{HG$C`G$M+E`3}OMV$*}b~PWSmljx;o`Ywf7&NQdzSN_y>r zpg>-^F7jpJB9z9liM|I?RGt8lZH2R{V*f$90oj}ZQHlkt_0nG#jlMYB_ZY)GP9*?1 z|KQ;3O@5SDH#A1u*|KYl{j-OL@a))JN*X+OnzV8F(Vav@nAuJ5P}{TnriX6G5G1IH zOURHkYRcnK3TU<{(!PxS3IqvWNtg@g5zg|Ub37W!Fi2W!ZXLR$OxHQw&TJb!T*c5u z2pb-$nW(%(x#U=7Pvtz7T$cI<%#$8_X&${=-rd0#z_K%V?@|QcHIJ>XN-$s^HK9R$ zS_8Zz1yP|JPNs|<#b4Ux!_&rop>s$RWX zpPn#TW-$1BxL7tetoT?IOV8=nJLb=JVL}9emF=pzHF9LamX;%TM5>hVI7}0y4GVnj zvxIkcT(^nLc0@mtB}qo$hf{SDo4bcgrm1gZmVJQyB$$_sTEx`!Om3mYuW|Wyk0>Rj zpdDu}9uffI@p#H2f|h6lTXVQEv9Tb05jLHsmo*NhdwQ&E7=&)3h#J&vR zk@GVV=1DL%BIcS9iO%JjJ5}}f#g?+0sotPOenTCw4y+jE99Pg@8cW0#-1fX-N;bD4 zH5Z~ZG~J+<(DHg|jL#6@2ZNgQq?hLHSV!9tj!cL&wBaGI_C{u6%wna4J+FRM)GhMSshBxlFGz(4a)C=)UKD z?s3?dx^8-97>iO1UQ{zZS1vDSFb%ACVzag zGO)H&jOom%Alo9;U*u9!s-8p8uL7H({L3WWM5aha7&%_#wI`r%tN!5h;H6ZA=tu7; z`Y!+LhL17x6E1vMM6}G?nYIRs9UZ9t+teD%?d=M*k8z z?S$A^KVGkze&d4{&B(KxH%n)4sWtw*k;TF%>SB&-JlY+f6|R`J5*uT6ZPT zy-p8I6cq_n+hy2u8!(AnRw1H8fRT&*;o89yNy6vi^XtYGu0*ihbVP3~bo7|tjhV=W znou|445xPYs*A;Op-9s8as}v18!BrzG%s)=_)Htq=2Q=E$AyS0d z(syEPi#Nj)gQ(3i*7({Xx6967jBp8;{n;hV-)7G4rO3mHO-!@^y~cJoX@*oRg_!we zgLN;`!**(;xS8w9j4)rv|74$48^@QJvU*~3ljqhsp!43|s-2m{5o0$VfXeG$6I%pN zt>3Bb-ETFUn|`3;+Fh&k!CQ^r639kxVYGg*kAOhqs30w&T@m?cjBA7D=Ts;^G6I{RoS!40BBO?zl6i zqLZYN-nJJrm{eS@$&pOG7`rZi#p%&D*>avox1l|g;5`+uq^vg#9HNK;+6Uwm6&t%U zd!eEEr}3|JzGmymmxlEX*Rg6JOD~wdpOdRkSxE8@DXlEuP^we@8+o=Zy`L$y<0s}@8^+cSaFv@0U7?5z@=w^ zZ0#t_BPu)EMlqhv=@%y}5{sTs2XR)rN2n(PeozQ~)%wN;r|FrLzhI#P0&-O?HCHxs z(a0XvGh2oNk4W)_jZcGNVyNU@pCPTx0Md-CC!5a8)}+ z2jA7?Z)y`>%rOPU=v%e)D_XaZ?(9(CCJ}vmUai9Nn;SpjE!wJ0#do*Y|Nhngz2*-e z{0)p3XQCJ9XL>TjrTSluy?mfOR@NU{(!ak4Da!`hD>F4(JpV0S8DWe}^vZ8%CSjwHg9`5>kEVQ=O5!T;-yFXr7^B{d59e4wq zG%!DdSz>C6if7-lTB${SX&B0MUuHgk{s5?#5{urX0!PPn)htmMOe5?vUj+mhcz?Tk zdX7&_u`n^8bf*0&mHp@R1|@&tq_6I|V43Y=M+9f;}**XA_0JHfkp$o*lz9~^Pguk6K0Uq+G@KZ)+W{{QEgG?1# zVcctzcO4uKKdG7205DZub3l-U)#z$fKp)nx`<}8umw= zRtQE*!T6-o_QLV|h#8G;vv=%+u>Z@HOcAQDX*11*fu<6$@Q#iS8L%ne16Mx-A|)jy zD|;4;aXncLry1%8Ql8(&l8GZ_$-@Q7D=N~1z~%ZB1AYBuPBZ)t5KO9J+1}6mFz_;- zuPQTh6CQyAN06<8g88vvdJ^M{#ib?uRZbml;FbPM-DLejqC+Yy9s-UpBgcFUk*>Er z9HF^q?*^Rb`}RUeesxdWPwB|kWOl7W$3(g=yybwkaqP~+4oa0$%fHFzzXq|1z6dnr zNA*a9$e)v=@{>t!i0<*(GHvU5o$IShhd|m1GXo^H!fu=zjE_}WSg~~9{dktLFnjG9 z23WWd?goR`Z)bN|>HC3|tu2VLm1t3|@+!Bo1j{*RbZ?-zeSII40|CK1M>~0Q{Q z?fdN0a(Rm%61a1piTDI1CUO&ntLa&p6Fk3tmC_j@K`BMV}LqhUw$p`9KS*d@3DVqDiD%!RD3jk8>bg6Ho{Ug~6QkJASf718L zOx~^Li>$(_ZF0XP^7H44oTlrs>^_#3?RO1e1VdvEdT3blMe^*IFWw8MF9D@J-|5kX zPN$36*n)GUumdj4YrA2PC9PC-1C`JMz~j`bBx^kLgAbe^G&Pgp`kgJsvx7YB;OzJl zsN2aYDV2E4*jypkE{@8mgXl^JSo-KeNO{~9z9RmwtN0ncxUTzbU(4ue2sZhMS&r|) z`uAL9$~v@@$dw{i`c?{VRJvq=dVHEay0K2o+oN%^&j}uLDpwhBthVd?` zryRcz<3Qn$W(95x?51#Yyg*^k-hPZ8d%7E(>C*Jx9fF{f&MQYTOCXx3A+#w2S|g@A zu%ryrIAXR<{^lPx2uz~G+VjDsus>S`u-xy5?o~o55g9 zOAb_bvE;tCJguOR?Ko;J&hz6Ew?_8`mh;jx2Yc6vkF0WHUq9B;CR=j7M@!hVeH@5b zjFRm`>jYpzNoDH2T>LDG)?M(!D$q<6B;SID>N=;khn=blvGyYZ=}R)r zO2HYYrD1(z03~}dF%$?PO*J+2m~oZk+G=hON#JqvCD*(_27e;@e9bKFZN2a6xw)42hq%3R!5lyE_Tm8{6ilP4lI_-nzVM@HA)cU&y1rqV4(p`neiE6Gjcx(Aw z)E{-vy1-`Im$MgNFHgm z+jL;9k@r=FUE``z?>uCM*wJj}8`nITjPi+vXX;4)k09N^0jfF1W5<@;9;N$F&;*al z=^54`5kR()^OQl4yP8fd-&MHky7OK;d@2e*llipz zGtK0(Oo<@pP1{&+$7xQUR zub7KvJGj!7R-!p$6BEBuwB&$<(vbkR)ivRz$q+|ODDP@WvS_-Xg$x~nYJG0SPa%nz z?I&s{E3-ka)_Z5Ov@0`3P~^$pF5%RicrUl2Uvjc5)d9xYMB+Y-+(L$an@nXtNkNfy zftyLyU$$$;A``#r)O=jIpitWC$pOTN3VSkx(8y6Q>TN~E`zTqE*=znnONrb<# z!$Z*{GH!k>yKhS3SF4E z^AD&C_l0KN9Glv0HE!9>&CS|Gr3_-e9bk}$YT-K1LILv~ypR>SyFb1p2Pq(6qdqZ_ z2#ddZkk@tH`7^oyi$DF<_hsIzLz{M%zX2pr;Q%9{nwHU2L7kne$0ED;#33Q_?`z2aXXCZ}XymybW3dfLDS@6-+)tsH+?ejP(pH_2 zrJ>zu8!YVr0rJ$;6dvyPtOayX6P!*Fh|3uld>4j~<-llwaB>P$gcMt58K0V)Z{2gi zGw`X-Q=%e;l+h=el!W9x5QG$v5ef@SW{QJ-+rM|K+^K)KF))(8E11g4j@|jqj&1)M zSDpkJxwNOd(_ogKp&^ev7E}VcWe%I+;j6HJOGuzmO-)T5Z&(y0cGGQwjTjRX(|C9A zgBI{c3_Md^``@_>Uw0oZHl6U;*}OV=mTUYR0Kuw6DDQ1+YinA^l@KY=FDIZlb;`!Z z=4>!xL0D82?(y*9goE|=zh8ra7y!r03cr5O^uvRt#--N_P6pW!gu^2Gf)8Er1bw^{ zs4|UFzS&hy=S>?H05r+oyVn4$On#j8WVLcrks@RF0y~D(!_R^8*Ol2=D%!p6{-amD ztQ+J0dV?By_XS;WgeAnqr9BVZ;i930Egd-QfgGpepA&M;^QR`jLDLQ~Y=*$V$Cj=Q-J6U*0n-=X@*Y9LfAH z_g`bYr@FaKQah0u2+x?k5h1lw`nAIsF-{3H`S_bpdw~wUc`vVVL}@PO8|YRt#7@>4 zrp_Ctp84QY+@1cM#;meY6 ztyo9*T#jdRX(;Ta5PgH%%D@@$=r(=`kRS$tuL)GzyEreaw}ao?1X*-Q3qwI@cUIvHGt9xnd)dnULn zRWaBl$#1*o*#|OjcXji8vfA@jO?!o2l7T6 zxtU`Jv>F0wcu61l(HYeGB^>^!t%>(VhOJIr*0DWKIe5o=lJC~>@=D{N>-4_aq~JXi zDS6FQ|H5m!>ht`OhM$ew*Yy^<^oqCKYMf02zt=0Ke-yMq3ADx_W~IDMHhl9>NQ-vl zUE{Y%>8hA@xj3#;*Nu&iTs86koEuhmzIdLKYmutwMVS@NVF{!)7cTNlx26|gc~7Mi zee&m_3SIYXiq88}iKEIz*DU1&tc)i3lD+5!=2+PR@OpImb0A#9~=2kBmwz+SvCS|g;SEH|m%lL7+7eRbB0XJM??p)=;Px%re{ad$^Y zzT4DS5Ck1RaUuafEnQ=_-(ms+2SKKT@@V&KeZZ-s_fB=#HO{SZPqgwfcIGC=H9g+K@6vtm^`luQC^1ftxwB0A(_92q<@}GxKf4W8W7g`wGXICzI zV_LdOmPa%i*x1-0mx_s+I@h@tN_p=6JTncEvJ3d&e#hvGdOaI5iSL8S{Wc#PR*y=B9+URZdJ%oWF@dpQCi4z+C!W zmKK);kzB_;Dnohm_AVJL1;%*8DeLk$gFP1&{#YTuK|9Ae^LFvXo>v|ciW}P^4bn<6 zspmN@d~+g*(o!CET5T-0H|C<1PF*-qaYoD0ux9d#6MT&T!|qg6RR0-|HB+T73cX$Qyg+8b{DT$ z7XgoRQ~!HIRko=vHY@J{gaUJoplJ;eF+863qqtStvs4L>e%e@NfUL!k$L!d!Z~0fT z`=ADdiMU6m5?K#&HKBXWp-}aE6Y!b{DhQ`J)O#b}Z>j&@+r~z_#vH~7>lc(jgw<9I3clkv5ocRq~H^aEZ5$D}pv zyTkA8gpxWyV3k?E_M}>D-gup-)r`6kvVDCi)o;rN2a^U$lk1DvZoxGmTxY%vWr8j< zUrbyalqD_TQ9ui2U25wrzyLl2mhD(WbMFf>h6J9g#NQF%)R9+^Me#xLIvDVa%Qi6cL`>?Z_F$;IR3op0(xYS`wT=C6ckie_CgW` zoD+T<-_z~i*n+VZ2@9iWVPRn?;ZC6I9vA>C`1Q%=T96^zy?stEOK z3Nn9P&eIbosF85_lEPWJq97kc5|?XMU!_2R2f?0X`*6+jjjZz+ z51p{3F4_pUB=+_hL6i) zU)`_FB;+TSh618wz+~r?>lGOa=L=_KSnb#EjszeqEerO|x+|z= zK~0)ft3;?;8-3!J!B5PJrzMxOPe98DY1-N4N8kDJC1j4p*$np80|>?1`wy2tRGu$8 zqe6atGxE`X8U_PJ30H0H&%ia4@x~y~6Y7cw7r(9d@{@eUN_A?g3wP++%bFSqHrAcq zBZ}5fF5G!2%Xaqc%3yXFPXMQSoCfOdx}%p{fd%9Zbj26SZNjmqLwz6;|BZE6G~ji3 z>~32KWi*}YZoknzfo2AmXhmy=t?*X%8`d2z`E zh)zp$;+@lpEx+NXAlD6YC*kX}eV;(mXeReL29fMa*fRLqpfZxX}K60gBkeR z$Vp}kq2>ws)1(+mdn9i_Wp+Op=kyEpvv2>1xj)Y$+M)1VOTukoSS^@h22z_goRhoL znvZG>ere^i6bo!>4$%O%`9uH+I;S4u9PNA=qxC>TB>P_cAnHrz_);^9&Ev$Og~NxF zsuq!#1Q{i^oAQJ$o3wK-UR0S{6t-&jzFzHQWmWE&{4MUqv~}|F1lN|pX_&oEa>_cq z^GVzNxxQ4-sX_C=xbvC@BR%GUe$7N+CHTg;xo9o;GJVgv z(o*3kJnUla$NIGKEU6!>N2_{K%@Nqz*1FdDOEPKREF3#YkPMxHUsOdySaZ180xDnI zW=(2j60aKDLb_EeNiP1^psEz^Y@69LttG@;?tg}$4$(sw09KqJe9_i6yCeZeh8j_# zO!d^rM)7k)JRlIvsfbgp4g*2?+}uRem)xa=L3Bo;i$SkGv2z zT5EJav^?3zl_AG~VQZF1)L=h6f&~<*!8-EYtCyyK2d!A|J9^4idS{0I`tMIW>~l?G z%X|ihA%+~TQ4%aF`F%WUMgOLcQucjBy}!Ej{$fPrXt;nHJw9$K@H^D>zwxw;3+Em< zQ{wp?-WBDRdyK*sOg)b0aZJ|Qwr9S2smt>LfU`;w;I*xUd=bUqZ^VgtvtNcvzz!dssk{7Jmn7_th%^TS9-r>Lx)oJ408 z)#&^w1>#wr-WtrB0l^SFEqO#mMPK=hf}wyOt^~-@g{g9N25%^ZLZby?v&I*1J*fy{ z;Ifs4n!|5a0KcYO>^1tTO(412SsXFFy&j%R3+tno=olDYGg&(pePF{}eO>8-r9>vd zG8Hrb=F{6s_8ygVX-_3G2tf8fffwKQsR3eo(*;a7vw<_Hbx-!wouxWN0q%b`o41H| ZShTvbNpFa94IY6XHKogn#qySc{|8+{b3Xt8 diff --git a/docs/images/vscode-format-on-save.png b/docs/images/vscode-format-on-save.png new file mode 100644 index 0000000000000000000000000000000000000000..a03349b6f8d55325bc40f55d9974b86e12989b26 GIT binary patch literal 41262 zcmeFZWq4dWmIZ2Nierp1W-c=`GsnyrGc(&UJ7#8vn3#)_Dp~CCVhXs zUvJ8%Tq+&yBOOU4?Y-8j3YC`?LxlST2Lb|uC?PJa2m%6y08CH7Kmq@6Z&KobfFN*~ z2?@zd2ni9&+uN9!SsH_Yh=(SqLaQkaV`OT^M)QBok%Dc9oi2?>(a4vC#`z43A{pYB zZ2$;|tI(#=6H*mH(^lr652L`q0QJyDQIMbS_t$od18X^_-blMh<9dHR81tD(=W@8f z15uu+3hcpEM)%bc@S`9j@y(1+7bL$0MJNXQWD9<0DcceK0S^yJ58LcrXMG(aB){E+ zeCo;c-G|m(ONSR4gyhpUvo$X{=5`*)COU3TF$hTRH?|A~!gxJ3zaSVWm@7uuiRdjj zSlPI(Ud6N~EV90F5DJRwrCbD%_?6FcfL$Yg#65u!JP5505D;|EzK-T*H?0t*&kg>p zf+3_&_+}eNMlUiQBH(#X@)`( zl5Wh7Ui2{fYy-2I9wE!vL!1b821b#?5>`%8_WFmsa-5Ec$b=?zjl%Q2NjvbvYIm^h zUsY4M6SWAG=td%>z9oZItAFPEjA~#Ua&}W|*t^TR6V8|tL(EEK7eV696k_P=9}SYi ztCCCy7a6mXw7VZQhPe_mY$`HhXC+{wRZPRD#uQBZonQje;s6%wikP$QCI2#}+1AZZ zpr+Z-i(A06OzWV%ijYv06{85oA$RYt2^K&u+>^$C8mo&%O%P6w)&)s9GdL3nIb~PF zew9me_wB1X_k%eKQZgaRPd}`A=4j{|kWQ;?Z;N)S(uZ`HA_sqM_M$n9s^JLF)<=(g@mU*X~KZu5J?;m6OQ(04O z_Py`^jzXTh&j5ztl}FMcS4%DhlC@#T>aU*9rXJf0jtkRcF={gc>jC+gb10Qj%?}V=|1bznT=3-O<7YBPY2;pPL zkdAJEYQYAgu<993V-=R~l}B)JaFovukvS-P3$FG1$p-tVRgKGeKOSy%vHZYREIeoj zsq&`m3}jFjnp*cGdv|3r+adUWVyJdiciHVRn!h;`x3Nt9f&haD4!#m<0 z`!W8cXGY5KH_4uvB65UnL0$W%k_-Kl^B0XfWV@ep&g9f*1ii3i43mf@eSEBs;XR5~ zj?&-8dnKzF%TP%-C{TL#x_S;72)J9zAe-LUurI1TSojKd`jn z5cGAT7DIUX({_h<5s`dggkgf||HjyZ-^0-3)|BK9YZEG*i!l{@h;(nj$Pmt+*5u!m z;2Po@v?y@;87W4bL_3ytI2cXDAP!EvKYu(QJbxx%RuOR2?w{));~ytjB^c(Lfnu!LP9rm~6OE^b@DKRj$Lj39nC!7@HsGA^M{k~-mzDnp?q?^mj1frk8R z3FR!I$GEOp>;}GL1se7s9EUk6)wD7cvDv|S4 ziS98$N#lzX*0dsHzzTt zQ$KOby;mvdRg{@nm$+lfJ#R*I@-WpAiYK@ubX}T&d7cf41q0`T*_!Fi$iNKMre

    ~N&M>Q_~(1*=M90_)D9j`g>G_F6m2o%sk0?EAUyxzB_8jlDc#PJ^(K;kY<> zx*SXFcIhJ-6yPB>KXx$rb*9rS9BdZeDmb+EPrddUs7MSTi&P1N^6vW7Q$d{WR;>v>MJ zot5v_Pq)(h(uJDgnoF7oA&>nn1spQ<*T>qBa>}dJ7FpITo`Q}7a_OfsJxP2dy@mXs zUSe#}HA8(+T`-?85-~fnV(52CO=z=j>nNHIla?MVCr%4F1{^RZjxtA+ zTOIHj0aiLQo->b9`}cG(>Qy$MjrH$(HZVD8G+GbGxBL3POCcoEs7>D}4av>*kM!qm zYf7~zS?dM?b^sQd=WU)h*OjEJv7-e@1;zzgsNIMsOWc0zOo5 ze{j}o>eI>ia@BGnF}|32WGX>9yC|26V({$v51g{evI}!@>qBkgUf~sSzH(0Lz_&SX zah^OS;KZ{AAL<|%9X#&53}$&Gap&+-dYJ#J`!QK^A?#!8^IR)2>7E6j<@1T+P3deh z3{wRV`L_42dZIV2cOf-3x}{33bJDT?Jg_G-Bme7XZ)39!Upuv1<+Jw&bQCfz!ACyc zSLPk2qnkp&yzZyYAg^}5bS`chqwvLPT~GuSW*$6WRS(c?GI0KYcer?onwzXT!WyPh zG{5(6#-_q%cHr4itg#!e``92zz2;lU_4+uFE9^eLoLo`!F}10`v?wWsU6B^I2n8}k z#k!(IocCYo&IvRL6`Vl%8s5P^(|S^H7wrCyB@&I*Bur#vK&XIe7!XKMR1k1r3KaMU z0{RIA@*ims5J^y+|4J)@Qv6j035Z0ulYZ)WRg zW@AnG`?~rDHcpN_L`1(U`me`7+iC1-_TM#GJN$K9z#9boJ_BH&qX+zNW{zeie=z%f z=AUN&xUYX!$Nl?aobqO_#+GWrW>&zi1~!eCfrXi!`yciEzfS#kOaE#5#lhHK$i@n2 z>B#%vgY}p3zn}b{hX1Hj{lDvEq-Xv2D*x@wzghmi2Tny}2OCSL-+lPS+RTxcksI*8 zW&ckr_5U{GWngCh%jn;8|EGo8|7!8?x&PBb&fW~z5Bk5G#>?|lxyK(P!P8K(8#F#ZaL2{AS7D}y{FCLa14Fdb0kC!4?qX)SS9-B-Eao_)V@PEke z_C@#mk7a;Y;Qy)DCCLv)@;65S=*izTE!r1YVZwiI)bF!U;ParUgnx5L_*!69efrOR z0Xz$AJm=rE9E_w38>$Ta?`{w*7DOAh`u}SDJ^%jy(W}0k(VvB&6iVk=hztiJ%25Ai zhFoTmL?3n9F3>}?yTx|y)&pRAU5D$D$BV;rlp`p`mp~&>9S2=v(d48xZJ{`PHAU%yWagU7>QRaW)CQYU3FSm+aAD4D`w2(h|6Dh zV9?gXi2TEcmQWj}?_0OtW>+_n=|nmxI2PZV*VQDS4|F;&FRzYriQ>3qr_BcMsGjXb z`#rTGD3Zxgw8E;74>W`8WvR-tk5abVji$)+9WsQcROefZRs_MjPS;Tiy(^f@>XayN z+_Olxf1nYM<2x=utBJ6|W`m4OCY8|p)k*ylTkJ9d4xK8jLYv@&@kso~$D0FHCObt% z#lFyws-%+WLP@1CN=!eBOXzx>IVseA zWiYPlYgQ_f{Q&GXq}|z&0<)jlF~vIVK_keMk%E6*iew>HKS>tlDTK8i|0qqU;r%(9 zK%-7Y5#ZP9$!4=okuAPZW3|GHr>q%Y?r>0{vic47B3veoRpVJz5kxeu#&{G`Yj=0o z=o13>*V~f?-FP}}(S8H6kt+QF9z}=-ct}Q*hTXB0(W`G`DNNyE=+vQ~h1OBHoGme< zc;;o&IUEKUtTaT|ombAbQ%p0_?dt7;uA$A7TPQp zDyT2lrxbIAhkX&C9@^(BH{`Pl8@~Kd{@&8vr2=yP$Cb?&8O)hBJ4*O{|4`RErASmP zi`z}`b+}b%(@oZA+g`+5;R4BoIo)>mTcH*kEHK`; z2ZyWyut{l!gN~PLoETb7=Sd;6mMC>duP5#cV;b8QiU@0Bu}EjmUzHI70!7B7DkbYU zSc-q#P&Oq$qkLpSkXFN_OP8C29Bpy37+2~+io$!AU3Ak5#V%97Nm^{QshrGxe>|Yd z8gwOO2E!`hvs{Epd;Z)MqF!%akj$`yQ|)qr&jJroQ8SW2ZKF*h7Kv*Q@osxHs}!Yf zXNDaTC5J*0K$)z5vlYD4zg%x&ggqM8V6_rTCS%2wt2Ji)gYNaff(u_%~yc)#lovl)|-?^Db5J|$1k?~i_xYb{Q58jzek$-LL%nC+#< z6vvcW?oKE3LjAom3eR_VxNB+xZr*cWR7*BwOB9VEjz_%8+l{A1V%g8kRCN^;>rh&HiBgX-#zr;F-TWQ}24y}FIt+~6$cvuKk%_p#`& zTfqdy3cY75eA#Ff^M0d#n$~8Nm(bXpzrGm9H+hOvJ_I3PlO==%I>y&~9p(goQP*+Z zQU~<=B++RX5IsOqpD|7TYU74mE6^JRjWC*rQ)sF)o61dicsw9Th+W}ifCI%cdb%f| zSlcnWY0Ox?pXBWSkV;-pD!6^_vu zI!JIqiGD`hHk@0hXUea9Y&jV4QcUEOp!3P6s%Er>}V2h)S|>pnax z%BrHQ-SB?a1}t#H!onVNY^A?G--kY*TLfq8Hs7kKu1$qv(52fjVH~x(gf`Zq{zn2_>42bT8KRq?~Qeq0f80 z&5gEjF_`f!(_?iK-!3|s;GAr^u6eYc_`UP}P3@@R$id=$N{j&0Wz8vS{Ln8zyTwsy z@)(%YfSq3UF#ti&3rKYZb7nf-uibMFJckJ{owrs7sHVi=OTGiQG$r6>FnZ-kBh6#b z$E6cKNKUScVmKJ-%st4&s4>P}IqLNXSJrRw^JS%4?`EdQvecf9p~PG{{d~x1JS904 zlBdi?;SvU%BSlL_1msgL#pvah%_wB%t04iqZ53|HDJ#a|O?5xT(`TWeQ7c0?U7*%{k<^SQnHV2)4lw)zy`s>Q7EA4&pbIZ=*bVY63t)?c6< zF3qsG>k{EbP){~R`VAHO69R_;2Mu#|GesGu$X@_f*H0A z>BiVDeo*4jkI*DkT1_EZRS!&l*km~{CZJ|!(|u>L5`+5TDQx}WttN>21nDoZBda;R zLcF69G4Ec_cMfHZYAf4kjf1Y(@U}c{V(xdRw5Hlii2Rwx5*8+z3p>1j2%`8cQ7WfHry)y)OU)HCd|9x&bPqU{?9tw{bm-LSaW->;TMmtMR)Btmx}E7{=9haIOhwsT z^i$xj*gVGAF9}5q8UcwCZ+tRO3-*|@UGl5*q@vX-95IW_MWsyVHP}8XfV*y!mw{S% z6u6!C@x7PT@ByD`?0Q>pU>- z6VhhAVDoub_J_)5=IIY|Gf0X;2-?csMULa zd$pf^+)0c@hmUKpz)ZJ5G3s!=61;U8rKK&KnheR}eU)OcS&xFzuzx;#Cx4x86^qQ` z@eri~A*hQ_4unHT1#W6_Oz>LP22?6#G_TF73LV4c(w2T`^-X0(+h`K=<(lMPHL6vL zHj7o=aL_o1Keq&$>AGkmi~Md{FCuFqZ;x)$#|gN!X7!YtF`Aa$&YOW9@QLWoQn47ULfE z(ZWUnVLycf7MJtsV#T%f&rQ)%>vUc(Nyp>aZj~So2X6)M)fg=A-Foh4OB?ib2E#;S z+pg`7rxwnP&T@`z+@l7|rBgt&)2Xl4MK?F51+Qf+JPMZt&;v3%bnV(kVq?Oxsw^=7 z(mEwL$YoUxQ+sp=O;g!i*zhFe-o&9%z3sC-Bgbd2)d^aW_p1d5xL?K7#bhdlbDdax z$6-?_pYij;0u95UEyVE3WIdC*+6>4jH$}*LdwL|c8ci%OGhAdd#oY9+*V`AkSm)`_ z@~N0tnC6*;K5h(#p%0|alAmYp(!jhuVN-tWxlK9v1fC3=4_OiGetVqf(%t}c#Ah(r z?6#o|u6O0inpAc1h`yt;{qVx7dAjq`xwhj`!ji432%`*uLX5WXd@0Md-ybXSMowng zk;?5KTe!uR`$KSn!UeI~+izGTZH~r;W+>~U<~ono^!C$V;T6#Kb5K!{2!Dig3`$(e zY_%zr_Sp|yw;=+O-FCAJGz|>Ju3WQKbb$DjlF8J&a-QZgV(=|VS2hv;=8Y=*bRf4n z%bRnUQk~yU9$yIi0*r$A@C+-1)Be07PnpC*1(CXKVzqWck#bJap= zc7>72nSOd%8N)FDeJW4vJDOmH*w4vjIayf@zBl%jWib$VQj4RtX9*7KywIoCn+dMA z5nmC5dOb8A1e6%mCK5*Doq^l^ib;Btl4OHx$@=pg@J~eX^B*#lP48wywQUwA5qQ|Rx@81dd zCO9EQp(*z3na%8Lff0by+VEx3j7o{3OvQV2wo8KkC^N=pmoF%Ql8o~M0-k$fs7Ybe zmP_$>$dCYqQdL0X2a%$gm9LC53%iMb3XPp%g=KL*6?iZwcr}s4Cu-1}zXC&3;LbOZ z^&XBZp*6f5D9x-M;dq@TQn=i-vs782)N>KY{4u7Vil{YEunT0!a0jLeQSL}fxBw`DPGAzp5FXx(v>rz$K+ep{{H z_l@J%hc@(AX#?($Ym_NrQqrq?H)rW&FBx>+Z$T2={T~EE0B?@xN`I&KG>~2ZqrFC$D)bFDSg$?!Mi@e$HB40O-t4T z=zRHMpSPoq#f`jbN}`S8rek=b@@xr9;idGkDT3j<6a~47T7FWOtFIIHWpIr?=ml_{ z*6e4{R;{;Ol6+cmX$`MI9R?8{-|^J-cLA9%ELJIRkyI>Av>@X@nYSuaqR#`ffc-iJ zPjKS3z;s&?K+nFZo`)dI6#MJ3#HvU(gUD3b@yk7^F?R$p+uCej>Yi^sxgyh>+neb2 z&JG^nx`xYxKa{bXpuWrgM-OD4Nhc-rMyQ;32`dI31-j~LkeWyx8U&uk3$D^X= z?dOZm1nY0}#fK-AmE=Hh$(pP>ut@e*>k~rI5B8T1`kC!z3kyv%@Ap?96)ZoXt2P9g z)v9J^)6Swbmj0MgPjCd1Ns6I7PzEiYM7Oqk3U==fuj|9ZGbeSv(m0v8e_UD`#^GSH zv|VL5LDJR1D%?dI!=VIO%R45L8H2IS5!a25<7M*Hviir#Mh3be=9tM1+5rzW-E8HnzJfVQ~M18pr=N|+uW!e zzDfbIV5)5Lk>->-ZOPYb75BFo;pA!lA}NLv6+qX+3To(dskZO=A_{$3&9_FSRE2nx z$b+s6Zz$B~wSGDAbT0|IgayqqCdp;9u~WO%!z!2?)3E_BVpI11Jc{yO(3WAg^PPVW zY>@Iz0ygr&Y=-qhW)U?X3(>9?SB6-(Oi? zchzTgzy*&AJU7yE@uwB;wB4e?I9wA`ukPLHIg9)lvtJOoOsXEK$l4T?(3sxC(}~$U zgRWl!wNE3Sy}L_xgqoTKiKo>HvLkf(sP|~;+N1OP=cepeGFQB z{Yt4RZUbUsh=W(+mu>x+y20vZhtz2l-Dx!3{-I!3@#34uOH}rm#<2HU}?Zy_R z^g*>Uc^m05{L`{=Bt^Kdg}OJMCP&%xs*lb0#&fk3<)9pEw<8*^khfkd8rkbKT%}LE z#|eX3;Ln)XX$i&&l|)e3RX?~ptP4kx1&wqH0J`5a`{U0F{2$bF1W6N^fyBf1nhRgF zS!_Hb%jfQLH8KCk8=o4juw*xA)bqvaS`cCw1ZrfSS#_#JXb5|AHM1ZDw=bS=kIJLB zsAyfaCa?LPUB9=-{bz!XonXXT>ek*C*Ke{qo!%MBbvjiTOIE=f9ph?QV;ml08eagvQooBU&hd4Rjn&ye&1nS1JUc)cE^mRt#sdH3$ zDFVPyibkXwI}2m0+2J5$z5Q8Zj~{!(%O#!N?n8mepf<9w`=nG2t1|FonNQG24{j1ut`KCTvr$kx?C6PPl&-P ze6DwgsmHJdi;F&zML3L+CyO_s^aw5&N~g20uioN#?TEsk_Y@{(%Qs`JPPmYkzIspSbjVZ%4YJT8WLU0rXx#31#Mkb7drqHuGG zgzS8JxV_=1d#n^C;!mt@2rL+bK0Uo-7^uM2ue7%no6!P~7+A$-w~3t>v})HYu-^n# z!$Uk;`)_| zy$>=PfppcAOQTWC54(}U2nR{{d5!er$OA9G_Qa{Y4GaQr_Vs-nfIE`BA1_aMjy+r9wZ?9J>dpj$dcmyHDkw(GncNe>SaKDYeDI=exJAym}_l$!NgOMgT|50AT}ljD@*?$C!v zonz85Cl&geE~RPzlmnKgKZeH75Zk+g-RsMFi-5*SRD*oBRVV@VCa-7Kqtu~ttvfeG z6zI*y-~3~<2?Hh=Ypw5d0+0s%VNZyk=aFL+rL4XQ-y!-vb^D@oVHty%bu@ZjKVm2t zo~*0{WaBA~%_dgz7mu0OQpkQ(%sD!>ipt)dF@(gKfAUrggP~{|!PD%-6?f#5Mys=S zGnBAdJq#dz0EobS5v7tdZarw8S_Nn}q&M9ybN;aIWtj;>@02p^aTfzmF>R*z06Ss+ zy4M2O@jY)3^R^#1~G-ohq68AUY(^x>NKUIszuGOLUfIfk@Ty4_HXT1^8g=aFM zQti+ff9n2(y#EBlDPz7u9iwi3-?#Ipjlu83!vZz}SgTbb(cg#~Q0Za&zDW_)@*~9k z!Fm5LT2MF(1QBY=bb|U%p4VR``Nx1V55j$XSa{(-taAU7M@*6P2MGL1xe5Ezef*V= z;sEiLKBQT!2Q214Hj!N;r zxfcd8U#Ng&4-y)bzp48Fy752tg> z`i1!qx5slIDJdzpU+*_QVghuenNaJ^wW&EBUF9v;TGS)(o-1~oMiObsD>^$ei7Z*nXa>yTmAmTw-N0E=kR^DT#3?S&pEo!ZmkBZTBf<~oWgEWy=6O{$xt%I$j z!{s*)?y})kNwouH48!rb8pO)m-s|D(t=B~3Y19>Q*=^;e)9(6x&hEfFHfYpqLMpUd z!<(Aes~wL}tKDy@PPBAy7bOY7JC?1m8I4fnxUb?pp$hs234AE#E3^$WF&wt2%iE4X zQLMh-9887-H~NCdy~he^ylOtta?M6`nbcJp?U zd^ql&wX$258lS2bw~Jul&NgF+=fWy=%`Po<1c_P z<9k(0=XPTpKR*HrMwG(Frwc~IfGByG+l_afcIlVW`CO% z^nfk)6mkSbJ|WP2LU_@H0n+#a2>35SL&*$zPExS2SIk&y%m&mbCYi{oAhCn`i z&I*%Kk=Yz7VD=v)hEAo73am$IFHj&2Dxj{k`nS5L9(p2^M<~FLV654GFEOltpGu@q zI>izST=!PZ^q_JLD$qDj^!pdZ-I-&m)oQE&r4Fv$J@WM|X`Ev1!X-L014 z;oFyP()^NJq z6{}pRxtoYQ*LdVZiIHf!y*I4Y22aZ|`zzlq?g z-y}38J2J10qT#+O;8OY>o+OgByR#*Tt z;{YK%9?s!bD-94@bdKUOhTTBox$o|51&sH7Bee>sn@}n8+8xq2Ge>)BWQ?ePKHl)j zHm32la|BW)+m)Sf5%mV5?c7JVvR+4|3pZ-DCiOtL;Ygv=Mu+|h!vAsI)%zk>S3@TT zqKAA_Jxa-<(X9}<6Jl#GT0@g!egtQIEy%|iDErQ+X!6#>MUfCz^p^-r+dQF8PQp{LGMKF*)6W54yH{1^=5OzmBDbbl$0}tuB4`(*wBA&(< zH%vxoDfXBj+$=UK-;ikB#c(yB%UxQSBSR;ZB++bm6pcn=CY?#g7>6{^QoEyTzqE> zQjthpj=3u!4222wDlsPcHU=fL*8QLmter}xB6+IYQ>bp>o}zTT^DJ#+@t+BhA9}$X2bglq2h7`WPy6A z_CVeRC}og1lHAT=b|Q5q-IA5Cf~tZtXy%+}ibADWB7G>y9oR6e(lc#h)5df(b$j#= z90f7blk60ZhH^0+Vgh!T3x|kLGDEtu@h#6@pJ@$#M9}wcTh(>u!HIw*9Ubo+;uZ6thoX6cqJ3|=s=z;W`1|uP> zyEMC8SQ{f;YPEvo87?<=>K2B7+#6LzYh0aHY&lD|${6JT1=9tnIKo+IvrnL!D_c{q z^{(pahR7}p&@%!34%r=TxJ(_&zc-?)-mhJMjQj~6xXwlcjq>l>ukPE!btv6PQDLI~ zIYNlUcT-1gio253HX3&2Urs)yRqMSzIT`%S1~oqeyGbpy5N;Clyy{O9X|z5U&@#~o z%9Gn{z34!H$a~>}(PD4VJWYQ4I%^FTKp$0h&59;m4x-Q^U)L;p)L?MO7?{RuiVeTH zZh9~));2%LUS$+PVXKYF(hI^Cd%yhLH;mUARy$pcf=FpAp6~4?Q?|nnU1s- zfQLzbJ=da&R!lx4A@HzaLJy=PeR12KW1lmziTns*jbIqPQb~M{OH5}qActOF9v$pC zPirIL@qBLQlsVit*7Scvv7LL}?l3^vk}~`S2DOTo-iJE9Js>9hgS)CpSVO!-v0%=i zh(47a)>GAh1RbOFCSl-++sCdc2`J2=#U!r4Mg8dGwu2=qW3g0in1%#Z|2+<1J5+60 z^4!|%06FM>`w4~{@Q{b3qUeFd*$Lz_#GRdHpAb1GRt+G45wZ5gO;d_WFi-`WcT8~| z*&v+jE%L`YQ3a9-eP)@2SBmg_w4l&HAmD=f_R);-g(k^j|kxm zr)|`d4Z>@reUBaGME-3ebsevEanI+=*Y0PCjS4+d)CDn*9NCN(dld1&Y;UgaL>APe zE9=l-_k8I#^d{@MYXMeGsG-hjbl{?;d21Tg2BdiCKUv$C1-H1ty$o~e0tC%Y4o@Ik zMBXLgF*tGQH$?!3ppiB}DPG&vfL?}j3&c42d0TBp{RO~x12WTv-ip=dv7nzJ{=>$S z{7A?>?#of0_77772qjTZa0Z7Duk2RoNc%5()7x)9kp?`dl6mv2h4Lb%z6wD*$Yq*U zV?ZBk((m=X>I>XI-D+EzV)gqcsQoywv%}syJToA&$SH-?>JiptG@77V5Tq!r$f8V} z)zvz$h1QBhND&t79-)fzoeUKeq?t`4b+L;nxBbHMgqt3aFt!9AW-0O`4B@I`X{Tdi zGM=YXoI+mUyQPa{9EaHFei-5naP)^Gu?+roGuovvUE-Rg=I#~*(S0u3LPW#4?hUe# znUzF!vv4+#DY$3&?97tq;p5EiO+fohb(x5^4)(WnFMGXETx}bmo=H$LjIl6-t4bjw zvs@Xkvy*Z*=G)7jNFukQ=|{_U7pm+mc5aU*B}IfwE-6C^_*cE+4HB=?oVyP_kNZ2z z8kHfQM4z{Q-4id(Bj4&67zFw0gn+YMEn9&1AI%hbu1{|F!_Vbve;w;NAmeNXih3Ih z#GrpjC0Vl)Jcvi9rEVLk-bn=4XUNH7; z&04W;T`LuUVErw5t~D8-O+s+>07_71d(?rtOREE1K5ywZAf^Ng5RZt1M!?FCH@udi zKJRG#J_3|+50si3nDClJcq}h%c7wmtsUa40J4`OoW+zMJy7|BFM7cE93`*@Tnd-_T z+Lbxz!%auxzc#cLIhoYK{Nived$g_qtzZ*FoH?-XhvX#}IGCSQy1SpJ~1E0d;Wm zZ%T4J81a)!^2e&hogYf0y}@ipne@6!kMGmBuImIyI$f`FA8r?nN5(Nl5!~T8MdWyw zM(tG#qk!rq*>PS*ZF26nhd4oiJdiZ<;KfA8XW9oZRaz{W0dKgUdcAj1z9n?nr+HE| zZ}o7=eL^H9JFn?~UOrm7F|(kB%h*3}y@=~9c%D56@@L`IhHI0U1Z6->dIVVwJLBb= zRiqh%pXWwvceNJj+5Nz^Q0k%u|B&lT0EkrE&21~%)dSwyYO_$=)A1-MEfS3J-brQD zPxT+P9kfqtwN57{kJk3oI*x)AsnCe-+LQyUc=AgR@pQA7<(FRwJbC2G?ioGqq>rw5 zh`mCU8+Qg|&>n9vQTFc#xXq^XCuc9fHyVJ#$bCSE2eQ(T|V7!p5! zu-^E&e?@NgD%)2t^ayprxZxn@G1XwjwZetmc>#p*#i2HijdV1N+;P9QB7!sUzPW~t zI4sqWZkIO(dF=UYc;U4zOFXm_@OcBjB)}*8a<^h%=`j6+7ERnu$PH?%AwbaT#MKX; z5Nw0~Yy^EH(KPGq?DmbV_HidF0SvtMmj*Q3hG+OVEx~bybshrNrT^EZYv=lk^d;z? z+}-5RYoPep#N-TX;4~Oh*HZ*fv(@?gwuf?WZe3VCZT4ERA)j(pw$n@h4UN|rE z6Gi43>#xsK2iK>q%Z%5Hj}JSOdwRvEHCA?N6}JohJHX#~hz5S0;mSQL6DYBlPQL8u zvYD6odDrd1ZnNHYU6uA>89a{M2h~=$7RaR4$auuHKy(m4WG4F`L>wS?i>q?mD2?3^ z__U>+zT?s(m(tJI3uZ7QLb_u7#_y9Xw7eKQz5qo&0L-V3`FXxx53})9KI4sdmL=zw z?6^{^{F7$d8(SBnwAxK4%USwf~2o<1znQFf_gh;(1KNE z6XC9iaxDiZtqyj}eyVLE+Z*&o8Ei~emR7wb)!U*g6nF0sb%a=ee!=rOI)yzt{u;(! z^CX35Yz5Eern1}75-85$BWn42>aFn7upsQOTr5PF!AHv~*VHQskI8_&;}BY_;EV$S z=^@~z`?OvTHhgh>b?eaAU0~R*b!QYSd1{~0sUm?)hhN_CXzo%cx=Nt-kjQ>_f8WEj z*6&ax?1$4L>GK3xK8pJ;rek=;rC8)8yIZoXk+{c@_WASU*Ie=RHQnZ^YT0Q&;J%Y{ zLV(fyW1UWq9;k(SH_i9RZoh#F4>yfE`KoZ5s45%@$ENWN6Yn+jy4v79D@#INa1O=k zg1*3oeX#R3dHM=3kX3Uqs4B8_M^M6oSQQD4AbSvLsdU7HtO zE5lJTJINXco-RSUO9F7s7dmEb{qZ6efmQg6YQEoyF!o6x1Ay?W+dFRT!j!`6n|#M( zOWR^@=kpLT&#cS9EOo9AkJnRD!(FsnW~VLt>#O|A)7!|$V}{m5mRYSHc4Rod@~<4u zry&mq1U7p=Oz&QwJF_{d536vwOfDYu9U;&x_WhfmJekdL*sQ5=!~lmB7Nt0CSb_AO z4=X<$%v3N)`i5c~*WDLb-MNLJT);<1PVKw6HzwY!90=SG^`{EQwHriZ zcq1pEFvu*{UsQnZ4aWC%>$TMp&>IrRMQFrNKXkB6+B$6urI(M-JA9O;P8=(qaf|W< z=L4iCpy>vW-E%*-zdfay_eBn?6ZF=)?iLOIF;f^_e$qz5!x@cQDantLY`k7-h zG;rv!J+GGz^)kcEC|{llMZ;P^a=8rqZTOXHxOllr}) z?oOQA_c-LHxLO4Wl80C+2J`wp7r0E?G_$w-8zsdz^gXQRvx_I%VH*lZ)5iVJ7jiXd zfn+$7w&tAx-N9--7KHV?9ea0+ju-p7eeqJdlm#KY0J|QgP+w+O3?M3_Liusr;U$pG zTB{N%Pse>iaVU)~>-M?J2A&vM2DBH*T$fTzB6Y}Oj_?F&nBKB@S>-+AFlUuKuk5|8 zKT_pk6AWLcJ_cQ%^*%mv`Q0Y!eVrQsW4hq)+0r4990Tejw+mK#>T{IcZ)EPJ6@B(n zIBq;n=+Pu(!S+yJ&V}d=8CVQKrwjJDK0F3LAr3TSiGvlCtBdyS+^^LbQ|m`kh_zA5 z-Y(vxSrm$?Wf{KVJMu8j2tJh+Xs z)HlRd>a=rax4idb#wB#)k>}EWQ?Sz*I5o&ab$j02{Nh9)jd7tu=-M3@!aB3&N8l=d-%yao4v~e z>Hg4-7wz8FN2S!+ZTE+r_Uj684wY)a_Z)HQ=8G!;X+@m*r!NCXyaAlL?JOU2aVNQn z6Kbwq_9=m&45}R8+TfKNv(>Wn8u2o0=6%RL*;8t}2j4+T!Oq+J+kGi|B_g!SHv}!G zxi9nQ<7{lTJ)FKvEhrQw=@F1@>x;r28|RnD!CUIT!J|};>>I{Lp`f-L6W}izeB9af zE!Qx&{eRedtEjl5Y->2dgA)jDfh4#EcSvx82X{ztcPF?*@ZfI2f_oJbBxvxUg2~zx{7#6ve82_St*wv(}n(uKWz@b-8)hiTl0<4xJN%bX$@H&~u_n zAnYYtP?&WeUnTuWLb7{cJLtW&?oB77o)xS%`+6z<{4Fspj^7MP`D3JusCjNtynGlR zO7zn67QBX7ROYGM^aek3>+WxK3M&^N#^pWvO}Rz1f=?X&yQGfhPuW?>wri#oQd&20 z76v_UMm|Pi2M7-H;G=%dP%=hnRm8b1D9jK`XI?dsVSU9#OD$~aWW}60dWE@in*!iH zH&5$~+gEfxZ}ouEurr=Z-Jy#SdKW+a1z_i>*Ujh5Kt*p8)Iz(m{ zP54bFZNt|1lkzPo1hV}Rw+?LqgYT{)>NC|pjz=<1-Ai}WJ$bg(Fs7bg#ppiYLFZcm ztmcMdh+7VSL;_=5K)SFNid}z%sZBo zx40h|aL9&wrYbBw%hfG+os^S7G+6l8%0v{IE&v1u1+~b5EdW=;L=jvwsY&V{jdq2_ z(OE_GlXN?b3H+7Ya=g5HS9~<~i%DqzcTE;e29J@nF=kvXiP%pOCMkzN3Xu84G^ibo z$XxYalJhM-rcx}1g3@nV5CDf@CX=yK$-V{Yv^s&*i&s4KSteV#$Q_-}2Y>hMmP2Q1 zf;L-EM7+-d}kF)AGk$7)}=x_TPG6gS$>-_H21qt(0GJge;Pz!AyEv~S<0EJYuc6c1U z$^RWL5p)I=KNQ|C2&w%o^_J_J^C}|a02Kn7#H$0{R9yPh{7}EW0(P4>*mMwI$41^t zlZo8!0O7<6W9RSmWP6TMD_`;gZ|(O9-jiO1C0>zAhe2!y<8xAa38~0+x&!Z>QHDu>qAGss%ZcjOcz=JP zBE$%tQ5x3a-x8YnmlnVmjQar+woDG_(({UZwt`{JPOoQI6jWmO_ICk$JDx-|=iQF@ z^uH$Mdu1_#A%ZfI?=CM;NJiNwuTZ%yiP`U^?}4~$_(~Iq9!e7F(p_jc0j}gi8?<8l z=HB!5?BByh=Lvq%Gg<~^N^O}>_whD!oicCzB~q9)l)FwQ_x+EWp61Hg!GZGm+f~sT z0!?(h;}(OpJ3U#{`R*q0V?el1dXbT-2L+L-m5IpRmd0D-mLT%Dmoo&_p+QNAvb>$) z3=HAV{*JF8{Yo>!$Y`5}9UemQCXFu)j_=P$LIoB_=VD+W2K!)iaPKiOr&O3mi*L1hROdbca#E+A`rE}YaqvZ4U+ z)G9<0CxGw{J~Do$Qw)Aw_Y0Xc3NO?efn5cToB-6awbtyq#gB2<;ZFrgpS7%n+nS1U zbvDpiVO1O4b(qCDvaJfHvS_EtZhRzf6eT3|tZ3YyCC1z(D-W&=>}mO%qiL-r@hb;F z%yaTV*aK5hT>1nu(ip3cx!msV_X`b{pF2Fmvz1OOZ3qh;b|y~L<4tyqZ;o>`sS${3 zfPYifGGBR3nsSi~dD-ZD_2kFVQj2hVrTZ|Af3d)VOoZKHqa+#mk0I_w92{~Ub%;sI zi<9hHaPCej>Ue*Z5h+g^t1c@shY_uAN-AWpG~E(DP_cjo5F89CMSXrk{YHZ$^8LSD zGl4qXp+*dWW&D+VY>RH3a=^nZGTKEWTqjq%ix%m>qC!`>A7KAQ*5<`9^F2%w$$6tB z-6(P3C$$*>+0wc$Pk?o{xmu1aK=W8W3ogF=OG&()t<+X&%E*DKYRSC)BJ>3!)@sTl zj;*4%c0R(R3`G=(#d{=DxBjqS(xS3oDzp!~7J_ZxvaeCh74(JJm|z?~l?nMw-N5*l zlySiEw)X?dCC%?$8FBKE&ic=;Y`1Ze;qc6<>rqDLarZ~OKJ)4YOHIA6Kj>x6a8RcD0NTPP$hFIjLVa{%b}YT z7E#>khTVHHTi*}0222ZKw2(Zf_Cu^2kx+Y2LeB;Vqmf)SQC4{RG) zTIvc;j5q76=z(6%=)`eJ4ai!GsP3j}l_JKmu!@p4MUhDe z^+ss+l{3>_)%3oRa~S}DE%*GYKDFj3vw2tFRC(^4rM^%I1mugi3?a0u6_pE@7aeqLIe`vY^Ne4~MzcOELs2Sb0Aj z2by|L22W+_h@%8(8}Cyxrx?*whFsN=T#mRcMj2-#KQd4}3VBE&kH7vFk4*AGkC;ub zJOxJDUqT@l#H!!{t={A8*jjP~t5g1n2wwoIu%8(Lu}3=GIZij?cLerBf-YO-?m{wP zp*Z5Y=cG?RU>SlDH1sk<1gm9T8=MMQ2#J?g5@Hvl8fkFq*2lZ!4#(L&qgWl;qI)35 zNsQ|;ZT7p0uied0=xAmdmi~GSypA@i8RBVJHFY9jCf1$01s=|R+ruwh$WLWm#Fg*H zX7+!C1wEY(O->pgA~@};Ry!0pf!3DAOo+kX@wSg8%9})rYg8b=W=L7P+^U4x|Pv03=(#Jwx=HkiRzF+t%+@g3^AShtpGm|VDkeBP6yK9Dq znJcfZo+K3Nh*~4+OebXQ>=LfQw8Z3S= ztHY^WSmXc{?mCXqmi9@nOfe5)(!4L&A6wmiZrd~7l&31K&*?TW{yo!RU0fsh9|Weh z`~h;DiU;wrQDP*@$&Re~dkKIp8k%fPZiC)FKUy<+wd_GrGuw92H}`rlfyNS!Sl5qy zDnv?!-7|#f2{Be%zqG*$yTJa~!|{mKOhu%iKiFyX!?ba?>He-v@vQLX!T#oO!M;ft zVA?T*L!g~W?-LQD+@jUZ{4m1u5GN*pO67gg+plyG+)ROuhR=8+ii5VJ=T2%s7@02` zN|tVA2@qQ~$1Pm&NWZM3ps_vV^shZ<2nm7;F>P$88-GQMh_kr?UN=8J#1PQSR6JE| zoj6{hNktC+U3*E4ZE-MJl(lVyGmki^w6>99!-jsd297G2N5Sy4%8e#6y_48tVe%WL zANB9_@wfW`V&m8S#iod>r9KJr>J)%66?0e{+c5s#m&|?!ehj5u8g{M+YjV%NEyM}) zd=@ZG%JW&F!J;LzWB5sEbFBlvWKb={mNatnmFk9xL`DFyTuAd==rbCY5H#%PCYag^ z_@m9CrWnBjjnhsl_?Lv169~!cK!`T7Fy|WGOVh@;*ySh#V7XaWdc_x`*|IJ$@ka=x z4;)CBbY0b~%r%}BP5zi?W+-I0_>HMlX z?;92A0bY5IXs0Hu%$QlBJjE*sN0%`$6J$-2cv_S3ZIRJ%FL^{OBD_%xWV z8`7)nbJDSIq|Q$Y*FE-n&!n8!8%In`USARpW%GjFFGqW>v;>;|hI((|q}~aeQIN}e zXE9n5=5a><+uf=^QY(1NWI2K+^CbIzqAd|xe$4g5yiAR1=nY(_=r>}PTfHOl9oo^! zSvy!W{tQ8IR?dNw&nF`L>=%DNcg64syn2mbuOH$?dmgQLGc~n`;;Bb6k)wLo+nOKi z?eZq5tmn!0d`(=u;%0Cf6{Rg)=KB6jT7SIe_v(#btc%_SG_8890yF-hbj8 zwc~_5fZ$M<;6nm|oZe{omv}6Tm;n+L(58}k&^U73Dk|0`MuWiMez6?gp{3lTVMwwf@T>ku`tHs_VnN1*n$T4Iud!FlmT2kng<__FuNfDrqO4m*eQ# zU3{1Lr$kZqisXA;cdq&3@oa@_j{DQw^1*Uj74Q9$0EMXV+w<+5>OY{|5KANY_0h!v zC!1lr&Kp-==HE=e0kiBfo85n&o>g%GUCTQ9Ws&7j?~75r+Qb#)o&{iR3umvlE(wj_t6P%_Su)mmfY+MDM>296-XnRW#r z$5Zu#?3RDdooBVtz}KD%5Z-Y!f?w{J9LPaHU3PLAzkKn<1jx|NGa&D zXVnC-zQday?=SqTf8a{2BW?1a?4rToDj$|h#?KDRq5engPa1MZZxTI_gB-JtKUBuX z2KKC)7avrqp=j=0!f-OTF?h1IPGaT!;itHMH!Cg3T~sWFuWH2|vf=(U9Gv!f-wtv~sx!&9mVvim+H8)xHZlRa0R8c+nJRJ;Z4MAO0 zS%rU{fFF-%uLnGDPQXoX*~Uktb2Y>`c_ixaxGb}wjqK?XHSXw0T=|=wKp9~;=pEko z6RffP$^tDzM+H=HC8>CoaER z#|+}|uL@jaQmvseKm@Vqt?H+B9=BVRiZoZ?UPGSjG#!#NX*1ZMcoBF)I@AJaj zlZyQ4_mRG*Gd`YTr+2WnVKkNf#VMI}n!}15%!3m5$_>iiDRySZ6>i^d>+%h=sWsmV z>Djw#dyKJnevmA88 zF%n@rk5}_HS#=WW*0-lG=R6x#3+RLvPx!JC0j$ke+;?3|jFddWP8P`Ye-w-AiYP?% zyf;z?0nG>L&4IC*0^6DjdP83?{Sfz}!3!YwZ|Gpr>$`8(Bg?==Az(Y_m9CiA@Ok7- z$)BGi;3~JiP_!2D9>(N&D&dM(R@niUlb;0r-P$O*>gC+oCx^gE#WtEZSU_@OB~JQ+ z`nTL5kG~u4Rix2{K<{6-B*d5?iaL54q1FZPV$MaXu1z_=JSV4j^Lr+%eaWXTiPcS51u_S>Lf#7&3-c0jqy>E!^6ySR$e&l3TKYrs^$Gyp=*=aRt z=CY+u&8s-TQ~G&y57AZFfTqns8kZ1HeS3gcy1y}$ZD_*$EB|Mg671_W0|3jq@DwOF zcWQVl88KnKC>&o6=uh3}(LHXkdTK`UZ$otEC-=bz%-ZH)#q{H;)TKwJmQSk8w{Wy? z2E90N7!}}%J1^dK{LLzxzuw5~SPb%a zs(Uf)`C5Hm{Iz9-py4Bs$bY-atB;0uA@S3%%(wlu&17N8Xz$g-!#cWW8T(g1_e{Bf z$G$tXqU!uO3&g79w~CJ?3cQB*Jdn9+C^=O;)*VH^n9YoSz{vCJW>tZS?h7=(E(-sv z7j%1vNAjf9&SDniA2NA# zuOqZ8J#GMQae8?C1%my^3tJ{!_}Ho_z9$YDyPNbfKMwp2C!8$rTi6qlSO6FC(YjL0 zovCQOaCYX|HEQLxuQ{8Z)Zr@O6$?il#T2nK1}@e(F#xz@tz2 z5cu)KjY2pXb&%YYm}7vKcJZq`ZM2uhen~1+&vnmJ6GyOG;SIU-eZ6zKF6sDW8?Mo@ zE~Th*JVWjasqrk;j)tL@Mis{l47&1fEhj9)G_dmT7f-{aV{?91$?lxROtB>pPh63^ zbxu_CkRPVUD4e7_#Ji+baI7JiZ6|GP(7uSFLjzNi90EPYyapy|Biw#>d`^?e!q#<- ziq-8FjObpZ&>MAUkFSQWHmydAMD99$y84*&VXNFL2D48f$q)A9McynYX*X(O@~0VY zZj*1x4HV;4E5|9U`K@x$zma(cDsD>x{sI3Z9*x85r13(BXUmrW^mYq|n=*?#0^BAr zO{KlRHcRgXdr@mbSbWpRsyzhlL90Z|&fb#`l2@|YDJ}~wc@Db08EoLZ+3n-v1zIK4rKf(av@uce>Aw-$!0v!^C9H)?!r>E$PR8o zTD9zLDLnfl{3)~E^9tCDeaO)7f?D}`(vymD5}{@QB=|89;PqC?ou_gozM8@m@uID}HKV45j z^JhADe`AH0oFJeX2I;cG+2s&@!iejkLsTZ8JK44gQ8>++>Z_!G#HLL)ZNdpoFEFS5aP5mfI(x6DeX+j5! zY!n%5V26yumv&ReW8phl)^m&YY}hSQKn|lR$^UMfL`&f76Htp&oYPTL6WgW)?QVuO zr};p7ci1NfYtHUbol9;Jbhq2A>Nq|M8L4+?s;xh4EjnwVw=w*(GxW7Hi$u4p03V{) zhR_u4CqRy?6nlP*{2+fX3Baa{maj)Mx782eED>U8oA_ug-G8u-IY~{RHkQSVBr#S+ z&DO5z05~vP2xmfm!tBhFNXY9n9~5gJ0~LIRrfSu80>TyAbA^sL5d!YS=)SjZ#q6ev zWRwxSUKO?iOS}k3Ikv>JCu&2%-cBUEb((iMKDD5_T+B@dT{LyajhqEq>>D;|`fsa> zoi-cXpO}Oq;%j|wKcvvT7)%@L@zdR6w8vOxz9Z7z`LxeLjfKZR)V9dAQ1WTlXD>tG zb(7o6(_gyBGKt`L11wec9~5kDPKzrHN{n8b-RZoRxvwa^zmauICnp;u*$RiUo!{jx zx63`eto;kiqkQ4;{0=I%rN^Up@LZwUU*8U~#bByanfUcdB|T}f}G#Q zLz5}j#d9=d479Dgx9n>I!-ZG;e^ic^VtLyC;RDi}pS)IL0A5@Z+_$GnR>X-|-iCew z-`Fz_ui!`H2WhAy4I`(%#Se0+)~+4g9?B`<6OXeR(yZ}IHRy!CuqA#+d&i};htf@s zwE_erj82@3=+n_f^oiBR>nUV3;m0e&Bho|Ss>BBKR^Hn2q<3!cqw4LM#;7TpE?=Ve zfDmHIAN-K)gw>*_WxrwLKKUyTPC-6ABfm9+f7o2}UBA z@nk(fuP|JiU7xSP{W0+L)53NIyq$g}U-JEn1V|h>JV7C4{IRAHvX-i~>K4#xY78j< z?C636kJ2#ca~g%|NLTWUW7wWOP#l8eD0D!HW~MGUjiTRcbLJrE{#1~qZXHx#V^9qV zkl)cZ3i?SScIbeP$_+)KuWveBZqq=Ywu_mBb$E8jL}wwtZLB2sLkEOTNl&i|L>|{d zzD>ZIyG}c-jIu08Dn4zI8QPH2HObs!f4)c1n{vcBO>bT9ewVg@JFA0KjpPL1k`=eNcgLIFYOcKOAvzH z(24p7ncQmKx6;2o6NUF{i<~E z%+L8{J%t6a12(J}rB?Ib-Q$=sE#x|HRy%BF;_i}s?zV&KbK7N`WWO(48-jb87>)y* z4MMR4t@g}kHXa|0^%pXn;(`bE?!^3aNjN%BtJ<-#*+~gddwLfgyRJ%)$jsaSZ2g)B zgcJi?iHYQN1SqJ84JO=VdE5_(mY4z`yJXx&2<`v{*6nw{8tezBZP2$xfW+`yR^a^X z-ubO5kogOVuIUrEqqHGl#D?s+G+58a`AM<-Y=T%6 zjLqV2Z&KeRojJY#2nLPZMiQtaECw^@jPA8n-=r5r`Rf-7!qr^q`?Gm(&ev! zYHyp|L-o10rPkS6q^DOgifzdr-*5T^x3kOw$_l6yOCC4eFr3tYL(JHFFf3}8%bZW5 zc-Ui3r+hBkek~)=Pwd9?S&fz%z-vCfPs~wR$o&d2^r&?i?3YjfAgy`1;6Ls|R_j`b zpUCCPm)Me4>4-f388e|zI%#7COF+$pi+ zx+#MI`H|au zavZA(?D#geq&WZ$dOXeag@C_Z5>tAhJE-=K?b*Ggd1l2(i8A+o{Z_F;LSmPXjak(5 zYiZL_Z0L-097t*zfL@HgCwKRJsPFI05}=^*z#c^c*3vM>=j9kvx_~B+O;mz*gz{Wx>0^8r^>${jHcsK61FO2%zsc@teNq_WNDNd zr?Q{{I*DRPifOD#vg$LFTGhutEYv45E<)S~+TCkzxC}S|y>-ogbNf2EVIb{WeaQKB zLxH4~d@8BB)%HikDu2sDOxO)#;_J)gj2z7Og0Yh`U+ts~(P*1C&s5rM+bBIf0uLGI zM5C>jL^~j#|8y62lWpYSM4qV!RmukBEu7S7H^)wyGU&^Dc8Q%2TG~v0p4Rz7_nAda zI6p~ppQb8%`L@ViAxc;VgOu}LzNXSaGX}eo=e)zsCtdO7$w{_TLXV+FoAUIGam_H> zy+t~gz7e!FH!6usEZs#q3|Z$7>=w4bXa01fA@y>M^e%g~8T*%%!+sj0m?K#tQ$*#7 z`{BvS$Id$yisJe$CMNJphZ8i5%tqXZBAVDsex~2PaWni7H%CV!3YmbaF6175{;#|N z?~YCeZS=)gaL~RaB;x4(?rsNOvVG>8`*|MIjeMlz1Dw15{C>t$rUpps$(9USZ5egJ z{*3qI%4qUA_+4z@5@i)Gvp9bxXfKF)3xkf{jS!2gf5-?k`52yj4)TYif9#{N9`zjr zaggy?MH=+2VYQXdTE>3{l;KQsd;ks}3uR>xWZSGvkJ|4?!}g>4pecOO_Wkyd^ZW>3 zHd2hvgX?6JM$ng7$zlQj0|tdTUK^FjI)7-u)Xj{xkIV`DG?N z&t<438|#05K+b*k%xAa_ieW*r?4JHeuuU3=1LZ(zu)DOXla4V^(AHM2d33r#>SsY2 zReE%(A$k{oz|JNHxBCw0xU`dUntYAN_3d!T>2MZu+jFX|Sl?^C-k+XmA3vC_takE2 z@2!SbbZIas-%HJAsTB>Bt3~ZRydy9l7jgM6Y~fS(!$WP`jdez#W#g@~$#-z_C7@qF zOFvU$0(xB&MrTOnK1v*7w`8F$W8%h!0wF#^d%}%J$Mmlan)M$W6g5D9k!_x>rSU76 zY93=@d&Dq@H*i-5s?!QF5p6}YUtaC%0;gMvf2`JH(`zZJL4IEx04{u31>m5yP)~s1 zTeC2uMYeN=J>mq$D`*bu^+z+}Coz!{u%}{d0aUKOFEa17qA}m%BJLaXD_jAZOZ5V+ zvNur5&Kh2eHNQnDe>)A*sOO1#uY1*k>=4B{MHS3TbUGTGh)rgI%;*%q57XEU;;lj= zAY~s;uU$*MoYjudgG?MPtvoPHgnnZ?v>ttz1%wrrRmG(QbJ5sz`SYZ`Rz5QXDm}Cv z&Qm1}i-cC()@_f7`0o#wzZf*Od9_7QZh*>|iAPPirR~hVU$%w)B2g8 zc^9|KZD})CZATXW3SX9Epuna23DdP_Gn8%|g4gwj>;87P^5F|fo>#>ht4?hPixEh8 zoaXAG<5Wmjb_ii`J#{5@T&Xv#2Gw=5%XCO)r@(efe9ra>qLkJ{lv3ms)1x)hMw)5* zg*U75)6ikH%8*`T>6m7sawU*!@tFQolu*{(PyS+2RC&P8TdHoUxNadNZ=7C|ebKOZ z-_=K(67fKPm*{*|Sv|yqk-gab(}gV59n<8AQxbMYL$n|7NfU04XgQAC8*|4Hxi@W3 zoR2H-Dd^&>a|+J;_0YU)?Q472JO)gko^iw3Z|+JE-vL;RmiMSc4@G;_c@9V`ur)v+ zi5S+S3YK4AmMsR|kzSgS)3{{-I;^WU6#MY$K|lMx{ga5LIay%>2tW3WWETDNB&O#X zp;>>`$xAr;aa?A8jLhPSEo)Y4X=9x^EH=vjl@nk`Q`2C3p7r(XYGGoKdf`wP7<(#{{$VJ=fdf>4Y0O>2!(KOgVOQ-QYM=ZXh64S1XBU@U!&d7nTCzCTaS#MN#&zOwNM&0UO#NWZG3 zIu;GppV#m$d#8pP<^!-Be`YzxCt*y+>=Oc42)nv zH=^)ho23?;ShXBL7L3iUFVG_1=OCN5C1NSL*ZQA z$N(J01E3(TLI%D(j0C!bEGQ3ltx**v^wn+zA*0(__pZoS3S}9AdsMxPrM=Z?rY@G! zSLaoZbk}lLt8}q!U*S*rwtrJ(OK23M9_RN0R!hlJ;>-F-XO~OY_tx3tY-=89C%pjP zFd7h0OrPub91ZLZy$RFm_1K?MYMMVoMAQ=5dm=4z zL9@G42EYQ)i=Hi%jv3~wjxnW`mJol&?d+Zfh~mSCAabr;<^%jLhF`{PibWQc>=&0m zmq>y%N+5s+gkzqEVd6%>;k#x2R(J(Cwrexas~>|MxMMt69x{0GDe! zRw`kvinXW!NDydrth9?3!f3IG@2g<-R{GZff?b&z;E>H>qCeMpJ^%DC@uM;)2+_sF zqIF-hT$(?+=oCrzCXr~AFKh{;mAAiY1W?LKwy(~c?S*i57eJu7f{BIk(&w;>ZB$fS zo9KZpZib)xR3lYY*Bq2g(L8}_N9lGCr2_REgw8&2N0(22%83n~Gu|IP$5!i=G3dVf z9Yj*zWvk>Hgi(kx#XDwlB&i&}_?1qQFM7Eom00w_pCJ8pC8N_rADwHnpUe86*Bcud z<^U%A(eXq%|Bw+X6%?o|H;RjGLW^NakV>Bq;ueF%_6cIsA2`eGM%71dQasho;rtRD zzd5aDp-Of=i(;heWC-=`-Cw*qyAeUcQtE!?epBv?0sKA8(Gv zyZrBF1y@=eX0^9ZhF7us{H4DhsETpxSnmfo$a&2Uy-eDF7xXQA%mwKdwU>kL`?#_zFs>G!}P zn)|TBf=Y_kHThD{=_(0sYrD8!EnB)5>2=lnIO-6sqD;sQ{-g4MQ(NWL&gZ+^LX+iB zEL-LtceV2#13+RdP7#ZFg?^w9812A7%8ic;%a{9~7-S zm^v&5?@X=XAwEbhlh=qC@WINZqjl4Jp?2%O5vEK;Mm?n9F8M)i$z(yaVS2HQ=2zyG zUW&UTI1YYoR7N6dXDv|#<0bCCAzcr3&ziWu6jjcBK^A#pxNY=?NsQY z*TQyA-r+H8Tb@C!?zsf@Va&w%3_oRBnL(Y2QQvE`6=6yzuT{14Eq^>^?g50N-d)xm z6B4O;edqBvLFI8VC|8y7^{0c%&Ao6IM^0yfV?5mJ>=|0$R0fq8M^BAvDpkpdLC`aYvS`d^uNl z6M=l-1##D%)jJQ!Y4~xx7sY2f_NhXp;Z|BkJQcA!DWRKX*LqyP%~#yafeK(N@w)6| z1pH)Vkq+E0Qn7#5`bTg*^f=~sj>n>4;1vD2_vK^+p4CdrvWtdRh)Mc=F9)b|Q`Yo; z7SDCZK(noAxHZvZ=w*b(QMStH;=pCOK5r|3o!$7e zseAhzPH<0Tr?Ph(LcLY#z6%T_2b^hB(?K3DRq{AgzVjf~LT+|<C+{;6-G*rSHpUqJ+DH$7OD^pZPZm^XeW!{X4r8dD_tB z=7o#*-1G0o4nx>5HJy7+YTeDQgpXz}h)mB;Rr<$v@RFnmxt+T@AFd~>*2_B+st~YW zu*rmguMVAOu)eIN{AF z1Y^fb%D`>Y?V^^F3b>=Ld2x2>HX^!1r#=2K_dVYOX zje`-j!^p_enK1XR+wPX>b1{eTxw7g&aV}pv5Gm~YzUnB=_xT#7+TwoxoQ!Ls^Gu?# z=Sri&G-ul4Qe(lE4v*>&TWO$#cu!lnFx;?xq^ChW8a(ymdf&M0S%2GSM0=jWehN@9U-jfU*6~O+dpu%o(qXbOSW0id__8_WFHY zd~4L%zDiy$L?regCNBK;H=AA~XO7p#U_;inXyUBPqL=zbFVXePhJcSwbKW)a@W02MNj0yJK!Q`y#9=`Hv%UjNMfe_^lnYCO6Ay zb9-+)ieXk_%zXR8-O_~Lj)u4X&9)24{>HDI)^%c%lI?}rMfM?^QW2vMiyMPdA~=3M0HA-i(KZTA;O(EyN=B8yEEZPGEW{M? z1?VEj@pBUjNato@Keq!I{(Wm4h;NubU}M1Y@DYeYh$}0AOv}*w1-v?Ln-hMA!#m2k zHx~42W1>h{{hW@gO8r)S^B7Yr9!q0gVk6SMw+2R@E6ax++u3I7CG+RIJOSN&u)VwZC~wX9_3!)954wktWBZ$Xj`+9&k-3)Z9N1|e zUJ0P6;Cz8oz6uu*(+4!r&VJb7F5BIyC za|0vvV`Nl9&d6fziQ$!AY`gRW6x**$Ne2C6`C<3C+5zaU$1x(r+bp}n zrFd?n<3~4JbvKsn-;6r>hF$%d)7YRDTp9=w9tFsJL&#(ct4H(&hGR@$i%bf-|3H>nA}LFPAEHnAR3fg=lW)wqjOCHZe=l+ZjCsTh$s(o znUWv0R8f0uocFE{5CtIcZXSg9Bf3Yyji*dY$Y60;4c zYUG;nNK15djxEMk$NqH8O;#3SmmX|cXfdjtaULUq7(?gW^C;kOu_#FK*%#dhp$)x< zVHS=N8(+~G+m&s8Xg#E^&d(rX2JejOD&g@qgUv?l+VbO8gBM#Zw+)to&wdzAZA2f( zHN2uMx3S-nTP*O5R=Eh0>3oELv7z@lzi%@^TuW%Y{k#kYomX=RE-%{;U#);$Fsi2| zB)Gu7(VUpmNGXNLKy(RI#Tej6!hr!NfNyojy%gX$pPjcg&Z*&3hFsh+?T827q*~wA zf|mS?TE2bja?m-m({tG*v%V_y^({?1e)h@J%67VADh(P(j>3UBUu<+%Vsg^ZdqW&> z7dF^nfA7D#0CW(}lHEYtsqe5X(@}Z&o$AwUC|-My2&;PkXOH7$I0;Q_jfidKW|*z^ z@)MdheDA;mn1;p-?H{wDxt0yEgJO*1xPy!5Y;{Lx^|{xB!tllLW{F#v+L>PFtZ2Kp zG0`^bjySyGVhSt6d(uFYOEh=G*saf6w}BszB)Q(p?Bt{uhog2VSfZ??b$!LQT-^C8 zvu!&|Q{`Sn^lD{u>L5UfEB=j_QLCl0p4S7D^=3O;V9Rb$jM=O|>6L;8m?Qc#Mdtv* z(B-0R8q3o-XVyn&g;x3+Cy&arE{_Cp`ty+c^wFmzN@67`Yh0P2n+4Alv26I5Y2`6*nq%ODaPo&;2GBttld`d>_wC-U8ji*b2$wq*Fvrz-g zS3_(!4a^X+i7?qR|FK)Vaj!LQ?%(D!bxAofmVGe-KeRO#<`3L!5MgVk0YBUD`?JR{ zotU@Llnt>6IN^7#rkRhDCfiugEC8gF^2EAi{TSy2q@a;Dp?|rVt45Dl9IPXbu$g(r zKZ~WMN=sr#P4lbXyGfH^NjHf}h-7Qim1d5(`@u{nvj+;^Mqy>f%iN?@`xdeVjmDyS z3OTHcozzTSV^#`w_+f*iQQSjR)k3ko>6BeATt8s+8<#i5`DDe?!R$iRV+BJ?EB=Y& zoz{2^LlMv-twjX?df9ard`~|y$-eM2D*2q|=~;*qXP*D&1tJtwfPCi1U8^h@ly*8xzpAk9m20m+O0+%1@6E zi8;$@Wg8YI`fR(SQ+u8xWIk}L+aSj6k{lF}24gm!A&xm2Y<+5kAXw0b1t}*ykd2i| zyAn8?o9gEjp=C~3OySLQEq$L@Ghqv-2Um;TH2J{euB9($iFOlOb;NeQ(Kllh^XZkQ zPNVta#=CAqjap;_sG}*2o!PC@ZQBYzIGgjru)ZhNT8!h38DYJ+qZ)=DR#Rypcg;n; z9T*$2n7FB1LBVb@30^zVB-<+=}e`8~0df zGZ$hfwg9*Al_5qC_YClM#xi*}eP=xWiFs5Wf4JZ)ODnHz?=4uxtu%_QFUjX89sM>b z8YXPCiOcV5n;%#0K87Po!~A((zZlc#?|TPy>RD;5^c^Y%Z!bBl?$ue}&lpaZR~0R^ z-nDXd+zEf|`*t>2;OPN{rKZFDp8H+4%3Cj|>@Q63n_pPOoR`L+c@?#(1<1y&vNI3Q zAfd-iVedBXHP8;f*v6W^;`oe5n?fB-Id0G2aa>3E$S9q4O;Jzri=w`?5bdp0n`}bP z*Q1lGg#csWuhPCHapsoG@!Zp`)(drl9)1BA52-H{r$;!%5|3uCTUSWEDZv*Y>*Z_i z`ib%SMu!E*2J#oPHibKb4~;7g=H}iWePY6V;cXv^xclmo%gVSm>nH9G#NGG__+pnR z?py4;^M~@akx(%3X(hfqd5ZM#tP^OM(bZO)VMTom3U88!>#vF+q3AK-OBPwZ zdvi=$W6(w?JvL=8%7aOY{R%G*2@P4-NbjEpB!r*E+Lw(EVLknq#UN%RAm#H*_yl-R zkd%34s8K14q5JH%CUJWBlOSR&DL7&>4IzmxO|i4E*}vel;y%Aqiy-))!JuF?Dob?d zyI(hd_&c`0gXEM8D*q1G4!oN0N<$!Sz`|8y0hf#4_)#!;UOUaG(a0CcT)9=;>=h*x z=RF*bm(E$6{(C4ps3_Q({EcY;{=l9U|A81Ftg5eqd>bhcn>3KG$6Yta_Sslj^b#gN zkS4j-TAerRudj_i+^l$dMt?D`4BxBbf<*%z*_Ed_y|!@u!T%Hn34at-GAT0|33l$ zpRWKDyGkrB08QHXaJ^LajPOk{(5|XUNVr+$Uu%Xl6v@!g(E4bx$@=bm+xh`^^}f}j zlI}krc~Akdm3235Fe)INS}D<^dZKwnS=#;N3I2n;l;lS!{Xf6k7$qTs|JHfq=l%Lu z%Uo}n-}y?{F?RpC_VN=Y6p_)?8fXKgYIGakRO{5y0YJ$LHEN}Q*}x|)KmwW$Do>Xx zjf9{%AKlzvOeFkH8shuU6(nSwU*bUg_19ggK}(GhW!ps>Z41^e z3swKmeU<-!sz=Vr2xC=k$bY~i5`6W~L1Sy>x6ZNDJfL+@kNn#s{T*}nDP|*&31_Et zgU7#o$$yUF?;gni{^g6LCe!}E_rw3bkU+=6Aay$(*W~#x22?eH{rNq`?Z0iG5MX-> zdF?Wj|KA_}=d&wkrZrL3R1o?v=70AfA)!%qy1t0}FAnJA3w+LU=GRpJ#r&QLu>EmY z+oEOuwO0OfQT)I5u0EdWwT+jDBI~H+B|=5%!Ko=PC2y6Nko4ju!&;>yMxu=j)9mSu z4($W{e~CcxO9O9EQBD>|mDHHP5}LX4dD~^WXE|*kIuRLAfwz4C-0}D`-wYT%| z-(g$`(DO$YKuO_E9Zn~5jpF9&93Rzv7wskxywZ$wH+o`dM z96>Kjdw~FK5Qbt#4=J_2CRHyKlEXo()ShZDxD+X$R33ZL1Sgu5IkZ~M(qN_8MaVNS zDk^ZHlcfDG#SWFuwbI=8jT%om2UHEBl0$Jx)pu)9d=b=Hhyw9#yp!C1t<8!!()_~U zbN#uk=~t@I@ZyMCPY=CsB)E(m(mvcqE$G|0CG)O`F3?A$%kb>U=D7hSdd6VeH(C>e zl=nT9I^oT+3E(4=+ zv#f10;{;yQQy)q6gGkEda2R-Z$ztRurBP-fKf3qh%(1M+KhzlTXil%;ydjB}g5|&0 z8FtnBL>O5Ab&70P*+GY;#lBgAr8)Sl%vJxF$tm9Wvo^@?NMX)T9m{E&uFkn{HKQCT z;QN?N9N2dFuEGje1m(&)_^-!5y||csEp0S;3)AoAV0q&nf(1H=%3~B!@n?l{;S*;Kkrd3-z?ofK#w=^IrnU_>CLz1lHb~>;-;^_a!!KzY-9h_Cb4=sq zR-a#~D%;zNytvUSSH-yb;fx`-d7bP1huNV^Gjo<1k$v+MfqgWc(f8n0n=PnT$7Joy zl8Or_67ug{0GFVg5}E-M9ELGLqpy^{PbHBB;K(gc_x=Hk?|mzvy?)9DXx0rf)5m|)k$1O6g zX88dNgKBLJ1(`8ieK|;wg~Jz!;UbhPc#K5Gt0Yb4TI-9gmT*p(Pl9vao;gDlE2{W#Qp-8g)!b{pr!I5{QXMk-=evu^ zKbLpXXR9WPk}@3gPh_UkwM>KDE&6ZZ8Ap{q7h3j+(xU8Q*%Io9GFntlosvz?c~^XI z1hK>L>;`t?wxd2Oc0Y&>3QT}F3!JtyZR0BN-ivccV}t&ZUkHu#;CU5?uAt7ldC}qv zfZNSvgxi+pZkstYe)cAk##NIah83YR9#PIiPpy zn@8XVu{|xBiyWFC3!FGxX+@9gbLruX^_pgR&)TeWEgM9rl0ZE$K=r3Gy3|{>z*vxz z!&BWagY}T<<~n8}-IirhKcKGqLOwO^@u3*C5YXYUvb;(g{0={w!y&qo4gVyFV#$xd zeG*SBoBjv&+AAX_&hgryPV7Jeg|}-JVG6Hu z2T7}VlZdSTFJtc!tYa~ejxrpg<3VYOqwFp3>_?`MTQ7n=m+P37q84)J4r|W}FCps4{?8{RzKI($=T~;();sCu!s@ya8HL zXG_W?iVpE)xC8)4m4E6KuXJ$VZ7w $out;; 'header' ) diff --git a/scripts/kernels.py b/scripts/kernels.py index 124b5d4e8..8e766d2da 100755 --- a/scripts/kernels.py +++ b/scripts/kernels.py @@ -84,6 +84,8 @@ def getkernelfuncs(w,R): #--work out the integration constant for the potential # parg = list(pot.args) + lastarg = len(pot.args) - 1 + parg[lastarg] = (sympify(-1/(q)),pot.args[lastarg].cond) if isinstance(pot, Piecewise): for i, (e, c) in reversed(list(enumerate(pot.args))): if i < len(pot.args) - 1: @@ -98,15 +100,28 @@ def getkernelfuncs(w,R): #--derivative of potential with respect to h # dpotdh = pot - parg = list(pot.args) + pharg = list(pot.args) if isinstance(pot, Piecewise): for i, (e, c) in enumerate(pot.args): ep = simplify(-e - q*diff(e,q)) - parg[i] = (ep, c) - tuple(parg) - dpotdh = Piecewise(*parg) + pharg[i] = (ep, c) + tuple(pharg) + dpotdh = Piecewise(*pharg) - return (dw, d2w, c1D, c2D, c3D, fsoft, pot, dpotdh) + # + #--kernel function needed in gradient acceleration + # for 4th order Forward Symplectic Integrator + # + farg = list(fsoft.args) + if isinstance(fsoft, Piecewise): + for i, (e, c) in enumerate(fsoft.args): + ep = simplify(q*diff(e,q) - e) + farg[i] = (ep, c) + tuple(farg) + gsoft = Piecewise(*farg) + + #gsoft = piecewise_fold(simplify(diff(q*fsoft,q) - fsoft)) + return (dw, d2w, c1D, c2D, c3D, fsoft, pot, dpotdh, gsoft) #--------------------------------------------- # function to get the variance of the kernel @@ -225,11 +240,12 @@ def printvariances(w,R): # function to print basic kernel information to the screen #----------------------------------------------------------- def printkernel(w,R): - dw, d2w, c1D, c2D, c3D, fsoft, pot, dpotdh = getkernelfuncs(w,R) + dw, d2w, c1D, c2D, c3D, fsoft, pot, dpotdh, gsoft = getkernelfuncs(w,R) print ("\n%s W:" %name) print (w) print ("\nFirst derivative:") print (dw) + #print (fmt(dw)) print ("\n2nd derivative:") print (d2w) print ("\nnormalisation:") @@ -241,6 +257,8 @@ def printkernel(w,R): avnorm = -pi/8*c2D*integrate(q*q*dw,(q,0,R)) print (avnorm) printvariances(w,R) + print ("\n gradient acceleration term:") + print (gsoft) return #------------------------------------------------------------- @@ -290,6 +308,10 @@ def fmt(e): # replace 15*x with 15.*x as long as it is not **15*x s = re.sub("(?!\*\d+)(\D\d+)\*","\g<1>.*", s) + # replace " 2)" with " 2.)" + # Use re.sub to replace " digit)" with " digit.)" + s = re.sub(r" (\d)\)", r" \1.)", s) + f = sympify(s) # # expand if it makes it shorter @@ -302,6 +324,9 @@ def fmt(e): # replace 1.4000000 with 1.4 g = re.sub("(\.[1-9]*)(0+)(\D|$)","\g<1>\g<3>", g) + # replace " 2)" with " 2.)" + # Use re.sub to replace " digit)" with " digit.)" + g = re.sub(r" (\d)\)", r" \1.)", g) # only return simplify-ed strings if no fully expanded floats 0.345242545.. if re.search("(\.\d\d\d\d\d+)",g): @@ -614,7 +639,7 @@ def print_decl(w): #--------------------------------- def printkernel_phantom(w,R,name): import datetime - dw, d2w, c1D, c2D, c3D, fsoft, pot, dpotdh = getkernelfuncs(w,R) + dw, d2w, c1D, c2D, c3D, fsoft, pot, dpotdh, gsoft = getkernelfuncs(w,R) w0 = w.subs(q,0) dpotdh0 = dpotdh.subs(q,0) #print("GOT dpotdh0",simplify(dpotdh0)) @@ -627,31 +652,26 @@ def printkernel_phantom(w,R,name): lb = "!"+"-"*62 print ("!--------------------------------------------------------------------------!") print ("! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. !") - print ("! Copyright (c) 2007-2019 The Authors (see AUTHORS) !") + print ("! Copyright (c) 2007-2024 The Authors (see AUTHORS) !") print ("! See LICENCE file for usage and distribution conditions !") - print ("! http://phantomsph.bitbucket.io/ !") + print ("! http://phantomsph.github.io/ !") print ("!--------------------------------------------------------------------------!") - print ("!+") - print ("! MODULE: kernel") + print ("module kernel") print ("!") - print ("! DESCRIPTION:") - print ("! This module implements the %s kernel" %name) + print ("! This module implements the %s kernel" %name) print ("! DO NOT EDIT - auto-generated by kernels.py") print ("!") - print ("! REFERENCES: None") + print ("! :References: None") print ("!") - print ("! OWNER: Daniel Price") + print ("! :Owner: Daniel Price") print ("!") - print ("! $Id:$") + print ("! :Runtime parameters: None") print ("!") - print ("! RUNTIME PARAMETERS: None") + print ("! :Dependencies: physcon") print ("!") - print ("! DEPENDENCIES: physcon") + print ("! :Generated:",datetime.datetime.now()) print ("!") - print ("! GENERATED:",datetime.datetime.now()) - print ("!+") print ("!--------------------------------------------------------------------------") - print ("module kernel") print (" use physcon, only:pi") print (" implicit none") print (" character(len=%i), public :: kernelname = '%s'" %(len(name),name)) @@ -660,9 +680,9 @@ def printkernel_phantom(w,R,name): print (" real, parameter, public :: cnormk = %s" %fmt(c3D)) print (" real, parameter, public :: wab0 = %s, gradh0 = -3.*wab0" %fmt(w0)) print (" real, parameter, public :: dphidh0 = %s" %fmtp(dpotdh0)) - print (" real, parameter, public :: cnormk_drag = %s " %fmt(c3Ddrag)) + print (" real, parameter, public :: cnormk_drag = %s" %fmt(c3Ddrag)) var, relvar, reldev = getvar(w,R) - print (" real, parameter, public :: hfact_default = %.1f " %(1.2/reldev[2])) + print (" real, parameter, public :: hfact_default = %.1f" %(1.2/reldev[2])) #print " real, parameter, public :: hfact_default = %s " %fmt(reldev[2]) print (" real, parameter, public :: av_factor = %s" %fmt(avratio)) print ("\ncontains\n") @@ -774,7 +794,7 @@ def printkernel_phantom(w,R,name): print ("pure subroutine kernel_softening(q2,q,potensoft,fsoft)") print (" real, intent(in) :: q2,q") print (" real, intent(out) :: potensoft,fsoft") - print_decl(pot) + print_decl(fsoft) if isinstance(dw, Piecewise): for i, (de, c) in enumerate(dw.args): (pote, potc) = pot.args[i] @@ -793,6 +813,30 @@ def printkernel_phantom(w,R,name): print (" potensoft = %s" %fmtp(pot)) print (" fsoft = %s" %fmtp(fsoft)) print ("\nend subroutine kernel_softening\n") + + print ("!------------------------------------------") + print ("! gradient acceleration kernel needed for") + print ("! use in Forward symplectic integrator") + print ("!------------------------------------------") + print ("pure subroutine kernel_grad_soft(q2,q,gsoft)") + print (" real, intent(in) :: q2,q") + print (" real, intent(out) :: gsoft") + print_decl(gsoft) + if isinstance(dw, Piecewise): + for i, (de, c) in enumerate(dw.args): + (ge, gc) = gsoft.args[i] + if i == 0: + print (" if (%s) then" %fmt(c)) + elif i == len(dw.args)-1 and c == True: + print (" else") + else: + print (" elseif (%s) then" %fmt(c)) + print_defs(4,fmtp(ge)) + print (" gsoft = %s" %fmtp(ge)) + print (" endif") + else: + print (" gsoft = %s" %fmtp(gsoft)) + print ("\nend subroutine kernel_grad_soft\n") print ("!------------------------------------------") print ("! double-humped version of the kernel for") print ("! use in drag force calculations") @@ -956,8 +1000,8 @@ def f6(R): # define which kernel to use #f, name = sinq(R,3) -#f, name = m5(R) -f, name = w6(R) +f, name = m4(R) +#f, name = w6(R) #print_avdiss(f,R) #printvariances(f,R) diff --git a/scripts/stats.sh b/scripts/stats.sh index 9c9cc7d94..070486499 100755 --- a/scripts/stats.sh +++ b/scripts/stats.sh @@ -42,6 +42,11 @@ count_unique_matches() n=`cd $phantomdir; grep "$1" src/*/*.*90 | cut -d':' -f 2 | sort -u | wc -l`; echo "$n"; } +count_files_ending_in() +{ + n=`cd $phantomdir; ls src/*/*$1 | wc -l`; + echo "$n"; +} get_subroutine_count() { nsub=$(count_matches 'end subroutine'); @@ -59,12 +64,12 @@ get_lines_of_code() } get_setup_count() { - nsetup=`cd $phantomdir; grep 'ifeq ($(SETUP)' build/Makefile | grep -v skip | cut -d, -f 2 | cut -d')' -f 1 | wc -l`; + nsetup=`cd $phantomdir; grep 'ifeq ($(SETUP)' build/Makefile_setups | grep -v skip | cut -d, -f 2 | cut -d')' -f 1 | wc -l`; echo "$nsetup"; } get_system_count() { - nsystem=`cd $phantomdir; grep 'ifeq ($(SYSTEM)' build/Makefile | cut -d, -f 2 | cut -d')' -f 1 | wc -l`; + nsystem=`cd $phantomdir; grep 'ifeq ($(SYSTEM)' build/Makefile_systems | cut -d, -f 2 | cut -d')' -f 1 | wc -l`; echo $nsystem; } # @@ -126,12 +131,21 @@ get_build_status_from_git_tags() nauthors=$(get_author_count); ncode="$(get_lines_of_code)"; nifdef="$(count_unique_matches '#ifdef')"; +nifdefall="$(count_matches '#ifdef')"; +nfiles="$(count_files_ending_in '.*90')"; +nf90="$(count_files_ending_in '.f90')"; +nF90="$(count_files_ending_in '.F90')"; subcount="$(get_subroutine_count)"; nsetup="$(get_setup_count)"; nsystem="$(get_system_count)"; -echo "Lines of code: $ncode"; +echo "Lines of code: main setup tests utils"; +echo " $ncode"; echo "Number of modules, subroutines, functions: $subcount"; -echo "Number of #ifdef statements : $nifdef"; +echo "Number of source files (.f90, .F90): $nfiles"; +echo "Number of .f90 files : $nf90"; +echo "Number of .F90 files : $nF90"; +echo "Number of unique #ifdef statements : $nifdef"; +echo "Number of total #ifdef statements : $nifdefall"; echo "Number of authors : $nauthors"; echo "Number of SETUP= options : $nsetup"; echo "Number of SYSTEM= options : $nsystem"; diff --git a/src/main/eos.F90 b/src/main/eos.F90 deleted file mode 100644 index 55ae32e93..000000000 --- a/src/main/eos.F90 +++ /dev/null @@ -1,1617 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module eos -! -! This module contains stuff to do with the equation of state -! Current options: -! 1 = isothermal eos -! 2 = adiabatic/polytropic eos -! 3 = eos for a locally isothermal disc as in Lodato & Pringle (2007) -! 4 = GR isothermal -! 5 = polytropic EOS with vary mu and gamma depending on H2 formation -! 6 = eos for a locally isothermal disc as in Lodato & Pringle (2007), -! centered on a sink particle -! 7 = z-dependent locally isothermal eos -! 8 = Barotropic eos -! 9 = Piecewise polytrope -! 10 = MESA EoS -! 11 = isothermal eos with zero pressure -! 12 = ideal gas with radiation pressure -! 13 = locally isothermal prescription from Farris et al. (2014) generalised for generic hierarchical systems -! 14 = locally isothermal prescription from Farris et al. (2014) for binary system -! 15 = Helmholtz free energy eos -! 16 = Shen eos -! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) -! 21 = read tabulated eos (for use with icooling == 9) -! -! :References: -! Lodato & Pringle (2007) -! Hirai et al. (2020) -! -! :Owner: Daniel Price -! -! :Runtime parameters: -! - X : *H mass fraction (ignored if variable composition)* -! - Z : *metallicity (ignored if variable composition)* -! - ieos : *eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)* -! - metallicity : *metallicity* -! - mu : *mean molecular weight* -! -! :Dependencies: dim, dump_utils, eos_barotropic, eos_gasradrec, -! eos_helmholtz, eos_idealplusrad, eos_mesa, eos_piecewise, eos_shen, -! eos_stamatellos, eos_stratified, infile_utils, io, mesa_microphysics, -! part, physcon, units -! - use part, only:ien_etotal,ien_entropy,ien_type - use dim, only:gr - implicit none - integer, parameter, public :: maxeos = 21 - real, public :: polyk, polyk2, gamma - real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 - logical, public :: extract_eos_from_hdr = .false. - integer, public :: isink = 0. - - public :: equationofstate,setpolyk,eosinfo,utherm,en_from_utherm,get_mean_molecular_weight - public :: get_TempPresCs,get_spsound,get_temperature,get_pressure,get_cv - public :: eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP - public :: get_local_u_internal,get_temperature_from_u - public :: calc_rec_ene,calc_temp_and_ene,entropy,get_rho_from_p_s,get_u_from_rhoT - public :: calc_rho_from_PT,get_entropy,get_p_from_rho_s - public :: init_eos,finish_eos,write_options_eos,read_options_eos - public :: write_headeropts_eos, read_headeropts_eos - - private - - integer, public :: ieos = 1 - integer, public :: iopacity_type = 0 ! used for radiation - real, public :: gmw = 2.381 ! default mean molecular weight - real, public :: X_in = 0.74 ! default metallicities - real, public :: Z_in = 0.02 ! default metallicities - logical, public :: use_var_comp = .false. ! use variable composition - real, public :: temperature_coef - - logical, public :: done_init_eos = .false. - ! - ! error codes for calls to init_eos - ! - integer, public, parameter :: & - ierr_file_not_found = 1, & - ierr_option_conflict = 2, & - ierr_units_not_set = 3, & - ierr_isink_not_set = 4 - -! -! Default temperature prescription for vertical stratification (0=MAPS, 1=Dartois) -! - integer, public:: istrat = 0. -! -! 2D temperature structure fit parameters for HD 163296 -! - real, public :: z0 = 1. - real, public :: alpha_z = 3.01 - real, public :: beta_z = 0.42 - -contains - -!---------------------------------------------------------------- -!+ -! subroutine returns pressure/density as a function of density -! (and position in the case of the isothermal disc) -!+ -!---------------------------------------------------------------- -subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gamma_local,mu_local,Xlocal,Zlocal) - use io, only:fatal,error,warning - use part, only:xyzmh_ptmass, nptmass - use units, only:unit_density,unit_pressure,unit_ergg,unit_velocity - use physcon, only:kb_on_mh,radconst - use eos_mesa, only:get_eos_pressure_temp_gamma1_mesa,get_eos_1overmu_mesa - use eos_helmholtz, only:eos_helmholtz_pres_sound - use eos_shen, only:eos_shen_NL3 - use eos_idealplusrad - use eos_gasradrec, only:equationofstate_gasradrec - use eos_stratified, only:get_eos_stratified - use eos_barotropic, only:get_eos_barotropic - use eos_piecewise, only:get_eos_piecewise - use eos_stamatellos - integer, intent(in) :: eos_type - real, intent(in) :: rhoi,xi,yi,zi - real, intent(out) :: ponrhoi,spsoundi - real, intent(inout) :: tempi - real, intent(in), optional :: eni - real, intent(inout), optional :: mu_local,gamma_local - real, intent(in) , optional :: Xlocal,Zlocal - integer :: ierr, i - real :: r1,r2 - real :: mass_r, mass ! defined for generalised Farris prescription - real :: gammai,temperaturei,mui,imui,X_i,Z_i - real :: cgsrhoi,cgseni,cgspresi,presi,gam1,cgsspsoundi - real :: uthermconst,kappaBar,kappaPart,gmwi - real :: enthi,pondensi - ! - ! Check to see if equation of state is compatible with GR cons2prim routines - ! - if (gr .and. .not.any((/2,4,11,12/)==eos_type)) then - ponrhoi = 0.; spsoundi = 0. ! avoid compiler warning - call fatal('eos','GR currently only works for ieos=2,12 or 11',& - var='eos_type',val=real(eos_type)) - endif - - gammai = gamma - mui = gmw - X_i = X_in - Z_i = Z_in - if (present(gamma_local)) gammai = gamma_local - if (present(mu_local)) mui = mu_local - if (present(Xlocal)) X_i = Xlocal - if (present(Zlocal)) Z_i = Zlocal - - select case(eos_type) - case(1) -! -!--Isothermal eos -! -! :math:`P = c_s^2 \rho` -! -! where :math:`c_s^2 \equiv K` is a constant stored in the dump file header -! - ponrhoi = polyk - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(2,5) -! -!--Adiabatic equation of state (code default) -! -! :math:`P = (\gamma - 1) \rho u` -! -! if the code is compiled with ISOTHERMAL=yes, ieos=2 gives a polytropic eos: -! -! :math:`P = K \rho^\gamma` -! -! where K is a global constant specified in the dump header -! - if (gammai < tiny(gammai)) call fatal('eos','gamma not set for adiabatic eos',var='gamma',val=gammai) - - if (gr) then - if (.not. present(eni)) call fatal('eos','GR call to equationofstate requires thermal energy as input!') - if (eni < 0.) call fatal('eos','utherm < 0',var='u',val=eni) - if (gammai <= 1.) then - spsoundi = 0.; ponrhoi = 0. ! avoid compiler warning - call fatal('eos','GR not compatible with isothermal equation of state, yet...',var='gamma',val=gammai) - elseif (gammai > 1.0001) then - pondensi = (gammai-1.)*eni ! eni is the thermal energy - enthi = 1. + eni + pondensi ! enthalpy - spsoundi = sqrt(gammai*pondensi/enthi) - ponrhoi = pondensi ! With GR this routine actually outputs pondensi (i.e. pressure on primitive density, not conserved.) - endif - else - if (present(eni)) then - if (eni < 0.) then - !write(iprint,'(a,Es18.4,a,4Es18.4)')'Warning: eos: u = ',eni,' < 0 at {x,y,z,rho} = ',xi,yi,zi,rhoi - call fatal('eos','utherm < 0',var='u',val=eni) - endif - if (gammai > 1.0001) then - ponrhoi = (gammai-1.)*eni ! use this if en is thermal energy - else - ponrhoi = 2./3.*eni ! en is thermal energy and gamma = 1 - endif - else - ponrhoi = polyk*rhoi**(gammai-1.) - endif - spsoundi = sqrt(gammai*ponrhoi) - endif - - tempi = temperature_coef*mui*ponrhoi - - case(3) -! -!--Locally isothermal disc as in Lodato & Pringle (2007) where -! -! :math:`P = c_s^2 (r) \rho` -! -! sound speed (temperature) is prescribed as a function of radius using: -! -! :math:`c_s = c_{s,0} r^{-q}` where :math:`r = \sqrt{x^2 + y^2 + z^2}` -! - ponrhoi = polyk*(xi**2 + yi**2 + zi**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(4) -! -!--Isothermal equation of state for GR, enforcing cs = constant -! -! .. WARNING:: this is experimental: use with caution -! - uthermconst = polyk - ponrhoi = (gammai-1.)*uthermconst - spsoundi = sqrt(ponrhoi/(1.+uthermconst)) - tempi = temperature_coef*mui*ponrhoi - - case(6) -! -!--Locally isothermal disc centred on sink particle -! -! As in ieos=3 but in this version radius is taken with respect to a designated -! sink particle (by default the first sink particle in the simulation) -! - ponrhoi = polyk*((xi-xyzmh_ptmass(1,isink))**2 + (yi-xyzmh_ptmass(2,isink))**2 + & - (zi-xyzmh_ptmass(3,isink))**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(7) -! -!--Vertically stratified equation of state -! -! sound speed is prescribed as a function of (cylindrical) radius R and -! height z above the x-y plane -! -! .. WARNING:: should not be used for misaligned discs -! - call get_eos_stratified(istrat,xi,yi,zi,polyk,polyk2,qfacdisc,qfacdisc2,alpha_z,beta_z,z0,ponrhoi,spsoundi) - tempi = temperature_coef*mui*ponrhoi - - case(8) -! -!--Barotropic equation of state -! -! :math:`P = K \rho^\gamma` -! -! where the value of gamma (and K) are a prescribed function of density -! - call get_eos_barotropic(rhoi,polyk,polyk2,ponrhoi,spsoundi,gammai) - tempi = temperature_coef*mui*ponrhoi - - case(9) -! -!--Piecewise Polytropic equation of state -! -! :math:`P = K \rho^\gamma` -! -! where the value of gamma (and K) are a prescribed function of density. -! Similar to ieos=8 but with different defaults and slightly different -! functional form -! - call get_eos_piecewise(rhoi,ponrhoi,spsoundi,gammai) - tempi = temperature_coef*mui*ponrhoi - - case(10) -! -!--MESA equation of state -! -! a tabulated equation of state including gas, radiation pressure -! and ionisation/dissociation. MESA is a stellar evolution code, so -! this equation of state is designed for matter inside stars -! - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - call get_eos_pressure_temp_gamma1_mesa(cgsrhoi,cgseni,cgspresi,temperaturei,gam1,ierr) - presi = cgspresi / unit_pressure - - ponrhoi = presi / rhoi - spsoundi = sqrt(gam1*ponrhoi) - tempi = temperaturei - if (present(gamma_local)) gamma_local = gam1 ! gamma is an output - if (present(mu_local)) mu_local = 1./get_eos_1overmu_mesa(cgsrhoi,cgseni) - if (ierr /= 0) call warning('eos_mesa','extrapolating off tables') - - case(11) -! -!--Isothermal equation of state with pressure and temperature equal to zero -! -! :math:`P = 0` -! -! useful for simulating test particle dynamics using SPH particles -! - ponrhoi = 0. - spsoundi = sqrt(polyk) - tempi = 0. - - case(12) -! -!--Ideal gas plus radiation pressure -! -! :math:`P = (\gamma - 1) \rho u` -! -! but solved by first solving the quartic equation: -! -! :math:`u = \frac32 \frac{k_b T}{\mu m_H} + \frac{a T^4}{\rho}` -! -! for temperature (given u), then solving for pressure using -! -! :math:`P = \frac{k_b T}{\mu m_H} + \frac13 a T^4` -! -! hence in this equation of state gamma (and temperature) are an output -! - temperaturei = tempi ! Required as initial guess - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - call get_idealplusrad_temp(cgsrhoi,cgseni,mui,temperaturei,ierr) - call get_idealplusrad_pres(cgsrhoi,temperaturei,mui,cgspresi) - call get_idealplusrad_spsoundi(cgsrhoi,cgspresi,cgseni,spsoundi,gammai) - if (present(gamma_local)) gamma_local = gammai ! gamma is an output - spsoundi = spsoundi / unit_velocity - presi = cgspresi / unit_pressure - ponrhoi = presi / rhoi - tempi = temperaturei - if (ierr /= 0) call warning('eos_idealplusrad','temperature iteration did not converge') - - - case(13) -! -!--Locally isothermal eos for generic hierarchical system -! -! Assuming all sink particles are stars. -! Generalisation of Farris et al. (2014; for binaries) to N stars. -! For two sink particles this is identical to ieos=14 -! - mass_r = 0 - mass = 0 - - do i=1,nptmass - mass_r = mass_r+xyzmh_ptmass(4,i)/sqrt((xi-xyzmh_ptmass(1,i))**2 + (yi-xyzmh_ptmass(2,i))**2 + (zi-xyzmh_ptmass(3,i))**2) - mass = mass + xyzmh_ptmass(4,i) - enddo - ponrhoi=polyk*(mass_r)**(2*qfacdisc)/mass**(2*qfacdisc) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - - case(14) -! -!--Locally isothermal eos from Farris et al. (2014) for binary system -! -! uses the locations of the first two sink particles -! - r1 = sqrt((xi-xyzmh_ptmass(1,1))**2+(yi-xyzmh_ptmass(2,1))**2 + (zi-xyzmh_ptmass(3,1))**2) - r2 = sqrt((xi-xyzmh_ptmass(1,2))**2+(yi-xyzmh_ptmass(2,2))**2 + (zi-xyzmh_ptmass(3,2))**2) - ponrhoi=polyk*(xyzmh_ptmass(4,1)/r1+xyzmh_ptmass(4,2)/r2)**(2*qfacdisc)/(xyzmh_ptmass(4,1)+xyzmh_ptmass(4,2))**(2*qfacdisc) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(15) -! -!--Helmholtz equation of state (computed live, not tabulated) -! -! .. WARNING:: not widely tested in phantom, better to use ieos=10 -! - call eos_helmholtz_pres_sound(tempi, rhoi, ponrhoi, spsoundi, eni) - - case(16) -! -!--Shen (2012) equation of state for neutron stars -! -! this equation of state requires evolving temperature as the energy variable -! -! .. WARNING:: not tested: use with caution -! - if (present(eni)) then - cgsrhoi = rhoi * unit_density - !note eni is actually tempi - call eos_shen_NL3(cgsrhoi,eni,0.05,cgspresi,cgsspsoundi) - spsoundi=cgsspsoundi / unit_velocity - presi = cgspresi / unit_pressure - ponrhoi = presi / rhoi - tempi = eni - call warning('eos','Not sure if this is correct now that temperature is always passed into eos') - else - spsoundi = 0.; presi = 0.; ponrhoi = 0.; tempi = 0. ! to avoid compiler warnings - call fatal('eos','tried to call NL3 eos without passing temperature') - endif - - case(20) -! -!--Gas + radiation + various forms of recombination -! -! from HORMONE, Hirai+2020, as used in Lau+2022b -! - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - imui = 1./mui - if (tempi > 0.) then - temperaturei = tempi - else - temperaturei = min(0.67 * cgseni * mui / kb_on_mh, (cgseni*cgsrhoi/radconst)**0.25) - endif - call equationofstate_gasradrec(cgsrhoi,cgseni*cgsrhoi,temperaturei,imui,X_i,1.-X_i-Z_i,cgspresi,cgsspsoundi,gammai) - ponrhoi = real(cgspresi / (unit_pressure * rhoi)) - spsoundi = real(cgsspsoundi / unit_velocity) - tempi = temperaturei - if (present(mu_local)) mu_local = 1./imui - if (present(gamma_local)) gamma_local = gammai - - case(21) -! -!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=9 -! - if (eni < 0.) then - call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) - endif - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) - cgspresi = kb_on_mh*cgsrhoi*tempi/mui - presi = cgspresi/unit_pressure - ponrhoi = presi/rhoi - gammai = 1.d0 + presi/(eni*rhoi) - !if (gammai < 1.d0 .or. gammai > 2.d0) then - ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi - !endif - spsoundi = sqrt(gammai*ponrhoi) - - case default - spsoundi = 0. ! avoids compiler warnings - ponrhoi = 0. - tempi = 0. - call fatal('eos','unknown equation of state') - end select - -end subroutine equationofstate - -!----------------------------------------------------------------------- -!+ -! initialise equation of state (read tables etc.) -!+ -!----------------------------------------------------------------------- -subroutine init_eos(eos_type,ierr) - use units, only:unit_velocity - use physcon, only:Rg - use io, only:error,warning,fatal - use eos_mesa, only:init_eos_mesa - use eos_helmholtz, only:eos_helmholtz_init - use eos_piecewise, only:init_eos_piecewise - use eos_barotropic, only:init_eos_barotropic - use eos_shen, only:init_eos_shen_NL3 - use eos_gasradrec, only:init_eos_gasradrec - use eos_stamatellos,only:read_optab,init_S07cool,eos_file - use dim, only:maxvxyzu,do_radiation - integer, intent(in) :: eos_type - integer, intent(out) :: ierr - integer :: ierr_mesakapp - - ierr = 0 - ! - !--Set coefficient to convert P/rho into temperature - ! calculation will be in cgs; the mean molecular weight, gmw, will be - ! included in the function call rather than here - ! c_s^2 = gamma*P/rho = gamma*kT/(gmw*m_p) -> T = P/rho * (gmw*m_p)/k - ! - temperature_coef = unit_velocity**2 / Rg - - select case(eos_type) - case(6) - ! - !--Check that if using ieos=6, then isink is set properly - ! - if (isink==0) then - call error('eos','ieos=6, but isink is not set') - ierr = ierr_isink_not_set - return - endif - - case(8) - ! - ! barotropic equation of state - ! - call init_eos_barotropic(polyk,polyk2,ierr) - - case(9) - ! - ! piecewise polytropic equation of state (similar to barotropic) - ! - call init_eos_piecewise(ierr) - - case(10) - ! - !--MESA EoS initialisation - ! - write(*,'(1x,a,f7.5,a,f7.5)') 'Initialising MESA EoS with X = ',X_in,', Z = ',Z_in - call init_eos_mesa(X_in,Z_in,ierr) - if (do_radiation .and. ierr==0) then - call error('eos','ieos=10, cannot use eos with radiation, will double count radiation pressure') - ierr=ierr_option_conflict !return error if using radiation and mesa EOS, shouldn't use mesa eos, as it will double count rad pres - endif - - case(12) - ! - ! ideal plus radiation - ! - write(*,'(1x,a,f7.5)') 'Using ideal plus radiation EoS with mu = ',gmw - if (do_radiation) then - call error('eos','ieos=12, cannot use eos with radiation, will double count radiation pressure') - ierr = ierr_option_conflict - endif - - case(15) - - call eos_helmholtz_init(ierr) - - case(16) - - call init_eos_shen_NL3(ierr) - - case(20) - - call init_eos_gasradrec(ierr) - if (.not. use_var_comp) then - write(*,'(a,f7.5,a,f7.5)') 'Assuming fixed composition X = ',X_in,', Z = ',Z_in - endif - if (do_radiation) then - call error('eos','ieos=20, cannot use eos with radiation, will double count radiation pressure') - ierr = ierr_option_conflict - endif - case(21) - call read_optab(eos_file,ierr) - if (ierr > 0) call fatal('init_eos','Failed to read EOS file') - call init_S07cool - - end select - done_init_eos = .true. - - if (do_radiation .and. iopacity_type==1) then - write(*,'(1x,a,f7.5,a,f7.5)') 'Using radiation with MESA opacities. Initialising MESA EoS with X = ',X_in,', Z = ',Z_in - call init_eos_mesa(X_in,Z_in,ierr_mesakapp) - ierr = max(ierr,ierr_mesakapp) - endif - -end subroutine init_eos - -!----------------------------------------------------------------------- -!+ -! finish equation of state -!+ -!----------------------------------------------------------------------- -subroutine finish_eos(eos_type,ierr) - use eos_mesa, only: finish_eos_mesa - use eos_stamatellos, only: finish_S07cool - - integer, intent(in) :: eos_type - integer, intent(out) :: ierr - - ierr = 0 - - select case(eos_type) - case(10) - ! - !--MESA EoS deallocation - ! - call finish_eos_mesa - - case(21) - ! Stamatellos deallocation - call finish_S07cool - end select - done_init_eos=.false. - -end subroutine finish_eos - -!----------------------------------------------------------------------- -!+ -! Calculate gas temperature, sound speed, and pressure. -! This will be required for various analysis routines if eos_vars -! is not saved in the dump files -!+ -!----------------------------------------------------------------------- -subroutine get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi,spsoundi,gammai,mui,Xi,Zi) - use dim, only:maxvxyzu - integer, intent(in) :: eos_type - real, intent(in) :: vxyzui(:),xyzi(:),rhoi - real, intent(inout) :: tempi - real, intent(out), optional :: presi,spsoundi - real, intent(inout), optional :: gammai,mui - real, intent(in), optional :: Xi,Zi - real :: csi,ponrhoi,mu,X,Z - logical :: use_gamma - - mu = gmw - X = X_in - Z = Z_in - if (present(mui)) mu = mui - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - use_gamma = .false. - if (present(gammai)) then - if (gammai > 0.) use_gamma = .true. - endif - - if (maxvxyzu==4) then - 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) - else - call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,vxyzui(4),& - mu_local=mu,Xlocal=X,Zlocal=Z) - endif - else - call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,mu_local=mu) - endif - - if (present(presi)) presi = ponrhoi*rhoi - if (present(spsoundi)) spsoundi = csi - if (present(mui)) mui = mu - if (present(gammai)) gammai = gamma - -end subroutine get_TempPresCs - -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate sound speed -!+ -!----------------------------------------------------------------------- -real function get_spsound(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xyzi(:),rhoi - real, intent(in) :: vxyzui(:) - real, intent(in), optional :: Xi,Zi - real, intent(inout), optional :: gammai,mui - real :: spsoundi,tempi,gam,mu,X,Z - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,spsoundi=spsoundi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_spsound = spsoundi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - -end function get_spsound - -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate temperature -!+ -!----------------------------------------------------------------------- -real function get_temperature(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xyzi(:),rhoi - real, intent(in) :: vxyzui(:) - real, intent(in), optional :: Xi,Zi - real, intent(inout),optional :: gammai,mui - real :: tempi,gam,mu,X,Z - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_temperature = tempi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - -end function get_temperature - - -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate temperature -!+ -!----------------------------------------------------------------------- -real function get_temperature_from_u(eos_type,xpi,ypi,zpi,rhoi,ui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xpi,ypi,zpi,rhoi - real, intent(in) :: ui - real, intent(in), optional :: Xi,Zi - real, intent(inout),optional :: gammai,mui - real :: tempi,gam,mu,X,Z - real :: vxyzui(4),xyzi(3) - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - vxyzui = (/0.,0.,0.,ui/) - xyzi = (/xpi,ypi,zpi/) - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_temperature_from_u = tempi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - - -end function get_temperature_from_u -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate pressure -!+ -!----------------------------------------------------------------------- -real function get_pressure(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xyzi(:),rhoi,vxyzui(:) - real, intent(in), optional :: Xi,Zi - real, intent(inout),optional :: gammai,mui - real :: presi,tempi,gam,mu,X,Z - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(mui)) mu = mui - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi=presi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_pressure = presi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - -end function get_pressure - -!----------------------------------------------------------------------- -!+ -! query function to return the internal energy for calculations with a -! local mean molecular weight and local adiabatic index -!+ -!----------------------------------------------------------------------- -real function get_local_u_internal(gammai, gmwi, gas_temp_local) - real, intent(in) :: gammai, gmwi, gas_temp_local - real :: ponrhoi - - ponrhoi = gas_temp_local/(gmwi*temperature_coef) - get_local_u_internal = ponrhoi/(gammai-1.) - -end function get_local_u_internal - -!----------------------------------------------------------------------- -!+ -! get u from rho, T -!+ -!----------------------------------------------------------------------- -real function get_u_from_rhoT(rho,temp,eos_type,uguess) result(u) - use eos_mesa, only:get_eos_u_from_rhoT_mesa - integer, intent(in) :: eos_type - real, intent(in) :: rho,temp - real, intent(in), optional :: uguess - - select case (eos_type) - case(10) ! MESA EoS - if (present(uguess)) then - call get_eos_u_from_rhoT_mesa(rho,temp,u,uguess) - else - call get_eos_u_from_rhoT_mesa(rho,temp,u) - endif - - case default - u = temp/(gmw*temperature_coef*(gamma-1.)) - end select - -end function get_u_from_rhoT - - -!----------------------------------------------------------------------- -!+ -! the following two functions transparently handle evolution -! of the entropy instead of the thermal energy -!+ -!----------------------------------------------------------------------- -real function utherm(vxyzui,rho,gammai) - real, intent(in) :: vxyzui(4),rho,gammai - real :: gamm1,en - - en = vxyzui(4) - if (gr) then - utherm = en - elseif (ien_type == ien_entropy) then - gamm1 = (gammai - 1.) - if (gamm1 > tiny(gamm1)) then - utherm = (en/gamm1)*rho**gamm1 - else - stop 'gamma=1 using entropy evolution' - endif - elseif (ien_type == ien_etotal) then - utherm = en - 0.5*dot_product(vxyzui(1:3),vxyzui(1:3)) - else - utherm = en - endif - -end function utherm - -!----------------------------------------------------------------------- -!+ -! function to transparently handle evolution of the entropy -! instead of the thermal energy -!+ -!----------------------------------------------------------------------- -real function en_from_utherm(vxyzui,rho,gammai) - real, intent(in) :: vxyzui(4),rho,gammai - real :: gamm1,utherm - - utherm = vxyzui(4) - if (gr) then - en_from_utherm = utherm - elseif (ien_type == ien_entropy) then - gamm1 = gammai - 1. - if (gamm1 > tiny(gamm1)) then - en_from_utherm = gamm1*utherm*rho**(1.-gamma) - else - stop 'gamma=1 using entropy evolution' - endif - elseif (ien_type == ien_etotal) then - en_from_utherm = utherm + 0.5*dot_product(vxyzui(1:3),vxyzui(1:3)) - else - en_from_utherm = utherm - endif - -end function en_from_utherm - -!----------------------------------------------------------------------- -!+ -! Get recombination energy (per unit mass) assumming complete -! ionisation -!+ -!----------------------------------------------------------------------- -subroutine calc_rec_ene(XX,YY,e_rec) - real, intent(in) :: XX, YY - real, intent(out) :: e_rec - real :: e_H2,e_HI,e_HeI,e_HeII - real, parameter :: e_ion_H2 = 1.312e13, & ! ionisation energies in erg/mol - e_ion_HI = 4.36e12, & - e_ion_HeI = 2.3723e13, & - e_ion_HeII = 5.2505e13 - - ! XX : Hydrogen mass fraction - ! YY : Helium mass fraction - ! e_rec : Total ionisation energy due to H2, HI, HeI, and HeII - - e_H2 = 0.5 * XX * e_ion_H2 - e_HI = XX * e_ion_HI - e_HeI = 0.25 * YY * e_ion_HeI - e_HeII = 0.25 * YY * e_ion_HeII - e_rec = e_H2 + e_HI + e_HeI + e_HeII - -end subroutine calc_rec_ene - -!----------------------------------------------------------------------- -!+ -! Calculate temperature and specific internal energy from -! pressure and density. Inputs and outputs are in cgs units. -! -! Note on composition: -! For ieos=2, 5 and 12, mu_local is an input, X & Z are not used -! For ieos=10, mu_local is not used -! For ieos=20, mu_local is not used but available as an output -!+ -!----------------------------------------------------------------------- -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 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 - integer, intent(in) :: eos_type - real, intent(in) :: rho,pres - real, intent(inout) :: ene,temp - real, intent(in), optional :: guesseint,X_local,Z_local - real, intent(inout), optional :: mu_local - integer, intent(out) :: ierr - real :: mu,X,Z - - ierr = 0 - mu = gmw - X = X_in - Z = Z_in - if (present(mu_local)) mu = mu_local - if (present(X_local)) X = X_local - if (present(Z_local)) Z = Z_local - select case(eos_type) - case(2,5) ! Ideal gas - temp = pres / (rho * kb_on_mh) * mu - ene = pres / ( (gamma-1.) * rho) - case(12) ! Ideal gas + radiation - call get_idealgasplusrad_tempfrompres(pres,rho,mu,temp) - call get_idealplusrad_enfromtemp(rho,temp,mu,ene) - case(10) ! MESA EoS - call get_eos_eT_from_rhop_mesa(rho,pres,ene,temp,guesseint) - case(20) ! Ideal gas + radiation + recombination (from HORMONE, Hirai et al., 2020) - call calc_uT_from_rhoP_gasradrec(rho,pres,X,1.-X-Z,temp,ene,mu,ierr) - if (present(mu_local)) mu_local = mu - case default - ierr = 1 - end select - -end subroutine calc_temp_and_ene - -!----------------------------------------------------------------------- -!+ -! Calculate density from pressure and temperature. Inputs and outputs -! are in cgs units. -! -! Note on composition: -! For ieos=2 and 12, mu_local is an input, X & Z are not used -! For ieos=10, mu_local is not used -! For ieos=20, mu_local is not used but available as an output -!+ -!----------------------------------------------------------------------- -subroutine calc_rho_from_PT(eos_type,pres,temp,rho,ierr,mu_local,X_local,Z_local) - use physcon, only:kb_on_mh - 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 - integer, intent(in) :: eos_type - real, intent(in) :: pres,temp - real, intent(inout) :: rho - real, intent(in), optional :: X_local,Z_local - real, intent(inout), optional :: mu_local - integer, intent(out) :: ierr - real :: mu,X,Z - - ierr = 0 - mu = gmw - X = X_in - Z = Z_in - if (present(mu_local)) mu = mu_local - if (present(X_local)) X = X_local - if (present(Z_local)) Z = Z_local - select case(eos_type) - case(2) ! Ideal gas - rho = pres / (temp * kb_on_mh) * mu - case(12) ! Ideal gas + radiation - call get_idealplusrad_rhofrompresT(pres,temp,mu,rho) - case default - ierr = 1 - end select - -end subroutine calc_rho_from_PT - -!----------------------------------------------------------------------- -!+ -! Calculates specific entropy (gas + radiation + recombination) -! up to an additive integration constant, from density and pressure. -!+ -!----------------------------------------------------------------------- -function entropy(rho,pres,mu_in,ientropy,eint_in,ierr) - use io, only:fatal,warning - use physcon, only:radconst,kb_on_mh - 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 - integer, intent(in) :: ientropy - integer, intent(out), optional :: ierr - real :: mu,entropy,logentropy,temp,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) - - ! check temp - if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') - - 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) - - ! check temp - if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') - - 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') - - if (present(eint_in)) then - eint = eint_in - else - call get_eos_eT_from_rhop_mesa(rho,pres,eint,temp) - endif - - ! Get entropy from rho and eint from MESA tables - if (present(ierr)) then - call getvalue_mesa(rho,eint,9,logentropy,ierr) - else - call getvalue_mesa(rho,eint,9,logentropy) - endif - entropy = 10.**logentropy - - case default - entropy = 0. - call fatal('eos','Unknown ientropy (can only be 1, 2, or 3)') - end select - -end function entropy - -real function get_entropy(rho,pres,mu_in,ieos) - use units, only:unit_density,unit_pressure,unit_ergg - use physcon, only:kboltz - integer, intent(in) :: ieos - real, intent(in) :: rho,pres,mu_in - real :: cgsrho,cgspres,cgss - - cgsrho = rho * unit_density - cgspres = pres * unit_pressure - select case (ieos) - case (12) - cgss = entropy(cgsrho,cgspres,mu_in,2) - case (10, 20) - cgss = entropy(cgsrho,cgspres,mu_in,3) - case default - cgss = entropy(cgsrho,cgspres,mu_in,1) - end select - cgss = cgss/kboltz ! s/kb - get_entropy = cgss/unit_ergg - -end function get_entropy - -!----------------------------------------------------------------------- -!+ -! Calculate density given pressure and entropy using Newton-Raphson -! method -!+ -!----------------------------------------------------------------------- -subroutine get_rho_from_p_s(pres,S,rho,mu,rhoguess,ientropy) - real, intent(in) :: pres,S,mu,rhoguess - real, intent(inout) :: rho - real :: srho,srho_plus_dsrho,S_plus_dS,dSdsrho - real(kind=8) :: corr - real, parameter :: eoserr=1e-9,dfac=1e-12 - integer, intent(in) :: ientropy - - ! We apply the Newton-Raphson method directly to rho^1/2 ("srho") instead - ! of rho since S(rho) cannot take a negative argument. - srho = sqrt(rhoguess) ! Initial guess - corr = huge(corr); - do while (abs(corr) > eoserr*abs(srho)) - ! First calculate dS/dsrho - srho_plus_dsrho = srho * (1. + dfac) - S_plus_dS = entropy(srho_plus_dsrho**2,pres,mu,ientropy) - dSdsrho = (S_plus_dS - entropy(srho**2,pres,mu,ientropy)) / (srho_plus_dsrho - srho) - corr = ( entropy(srho**2,pres,mu,ientropy) - S ) / dSdsrho - srho = srho - corr - enddo - rho = srho**2 - -end subroutine get_rho_from_p_s - -!----------------------------------------------------------------------- -!+ -! Calculate temperature given density and entropy using Newton-Raphson -! method -!+ -!----------------------------------------------------------------------- -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 io, only:fatal - use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_pres - use units, only:unit_density,unit_pressure,unit_ergg - real, intent(in) :: S,mu,rho - real, intent(inout) :: temp - real, intent(out) :: P - integer, intent(in) :: ieos - real :: corr,df,f,temp_new,cgsrho,cgsp,cgss - real, parameter :: eoserr=1e-12 - integer :: niter - integer, parameter :: nitermax = 1000 - - ! change to cgs unit - cgsrho = rho*unit_density - cgss = s*unit_ergg - - niter = 0 - select case (ieos) - case (2,5) - temp = (cgsrho * exp(mu*cgss*mass_proton_cgs))**(2./3.) - cgsP = cgsrho*kb_on_mh*temp / mu - case (12) - corr = huge(corr) - do while (abs(corr) > eoserr .and. niter < nitermax) - f = 1. / (mu*mass_proton_cgs) * log(temp**1.5/cgsrho) + 4.*radconst*temp**3 / (3.*cgsrho*kboltz) - cgss - df = 1.5 / (mu*temp*mass_proton_cgs) + 4.*radconst*temp**2 / (cgsrho*kboltz) - corr = f/df - temp_new = temp - corr - if (temp_new > 1.2 * temp) then - temp = 1.2 * temp - elseif (temp_new < 0.8 * temp) then - temp = 0.8 * temp - else - temp = temp_new - endif - niter = niter + 1 - enddo - call get_idealplusrad_pres(cgsrho,temp,mu,cgsP) - case default - cgsP = 0. - call fatal('eos','[get_p_from_rho_s] only implemented for eos 2 and 12') - end select - - ! check temp - if (temp > huge(0.)) call fatal('entropy','entropy too large gives infinte temperature, & - &reducing entropy factor C_ent for one dump') - - ! change back to code unit - P = cgsP / unit_pressure - -end subroutine get_p_from_rho_s - -!----------------------------------------------------------------------- -!+ -! Calculate mean molecular weight from X and Z, assuming complete -! ionisation -!+ -!----------------------------------------------------------------------- -real function get_mean_molecular_weight(XX,ZZ) result(mu) - real, intent(in) :: XX,ZZ - real :: YY - - YY = 1.-XX-ZZ - mu = 1./(2.*XX + 0.75*YY + 0.5*ZZ) - -end function get_mean_molecular_weight - -!--------------------------------------------------------- -!+ -! return cv from rho, u in code units -!+ -!--------------------------------------------------------- -real function get_cv(rho,u,cv_type) result(cv) - use mesa_microphysics, only:getvalue_mesa - use units, only:unit_ergg,unit_density - use physcon, only:Rg - real, intent(in) :: rho,u - integer, intent(in) :: cv_type - real :: rho_cgs,u_cgs,temp - - select case (cv_type) - - case(1) ! MESA EoS - rho_cgs = rho*unit_density - u_cgs = u*unit_ergg - call getvalue_mesa(rho_cgs,u_cgs,4,temp) - cv = u_cgs/temp / unit_ergg - case default ! constant cv - cv = Rg/((gamma-1.)*gmw*unit_ergg) - end select - -end function get_cv - -!----------------------------------------------------------------------- -!+ -! subroutine sets polyk based on utherm/positions -! read from an sphNG dump file -!+ -!----------------------------------------------------------------------- -subroutine setpolyk(eos_type,iprint,utherm,xyzhi,npart) - use part, only:xyzmh_ptmass - use io, only:id,master - integer, intent(in) :: eos_type,iprint - real, intent(in) :: utherm(:) - real, intent(in) :: xyzhi(:,:) - integer, intent(in) :: npart - integer :: ipart - real :: r2,polykalt - - !-- pick a random particle from which to extract polyk - ipart = npart/2 - - select case(eos_type) - case(1,8) -! -!--isothermal eos -! - polykalt = 2./3.*utherm(ipart) - !--check all other utherms identical - if (any(utherm(1:npart) /= utherm(ipart)) .and. id==master) then - write(iprint,*) 'WARNING! different utherms but run is isothermal' - endif - - case(2,5) -! -!--adiabatic/polytropic eos -! this routine is ONLY called if utherm is NOT stored, so polyk matters -! - if (id==master) write(iprint,*) 'Using polytropic equation of state, gamma = ',gamma - polykalt = 2./3.*utherm(ipart) - if (gamma <= 1.00000001) then - stop 'silly to use gamma==1 without using isothermal eos' - endif - - case(3) -! -!--locally isothermal disc as in Lodato & Pringle (2007) -! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) -! - r2 = xyzhi(1,ipart)*xyzhi(1,ipart) + xyzhi(2,ipart)*xyzhi(2,ipart) & - + xyzhi(3,ipart)*xyzhi(3,ipart) - polykalt = 2./3.*utherm(ipart)*r2**qfacdisc - - case(6) -! -!--locally isothermal disc as in Lodato & Pringle (2007), centered on specified sink particle -! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) -! - r2 = (xyzhi(1,ipart)-xyzmh_ptmass(1,isink))**2 + & - (xyzhi(2,ipart)-xyzmh_ptmass(2,isink))**2 + & - (xyzhi(3,ipart)-xyzmh_ptmass(3,isink))**2 - - polykalt = 2./3.*utherm(ipart)*r2**qfacdisc - case default -! -!--don't die in this routine as it can be called from readdump -! (ie. not necessarily as part of a run) -! - if (id==master) write(iprint,*) ' WARNING! unknown equation of state in setpolyk' - polykalt = polyk - - end select - - if (diff(polykalt,polyk) .and. id==master) then - write(iprint,*) 'WARNING! polyk set using RK2 in dump differs from that set using thermal energy' - write(iprint,*) 'using polyk = ',polykalt, ' (from RK2 = ',polyk,')' - endif - polyk = polykalt -! -!--warn if polyk is zero, die if negative -! - if (polyk < 0.) then - write(iprint,*) 'ERROR: polyk < 0 in setting equation of state' - stop - elseif (polyk < tiny(polyk) .and. id==master) then - write(iprint,*) 'WARNING: polyk = 0 in equation of state' - endif - -end subroutine setpolyk -!----------------------------------------------------------------------- -!+ -! small utility returns whether two real numbers differ -!+ -!----------------------------------------------------------------------- -logical pure function diff(r1,r2) - real, intent(in) :: r1,r2 - - diff = abs(r1-r2) > tiny(r1) - -end function diff - -!----------------------------------------------------------------------- -!+ -! Query function to return whether an EoS is non-ideal -! Mainly used to decide whether it is necessary to write -! things like pressure and temperature in the dump file or not -!+ -!----------------------------------------------------------------------- -logical function eos_is_non_ideal(ieos) - integer, intent(in) :: ieos - - select case(ieos) - case(10,12,15,20) - eos_is_non_ideal = .true. - case default - eos_is_non_ideal = .false. - end select - -end function eos_is_non_ideal - -!----------------------------------------------------------------------- -!+ -! Query function to return whether an EoS outputs mean molecular weight -!+ -!----------------------------------------------------------------------- -logical function eos_outputs_mu(ieos) - integer, intent(in) :: ieos - - select case(ieos) - case(20) - eos_outputs_mu = .true. - case(21) - eos_outputs_mu = .true. - case default - eos_outputs_mu = .false. - end select - -end function eos_outputs_mu - -!----------------------------------------------------------------------- -!+ -! Query function to whether to print pressure to dump file -!+ -!----------------------------------------------------------------------- -logical function eos_outputs_gasP(ieos) - integer, intent(in) :: ieos - - select case(ieos) - case(8,9,10,15) - eos_outputs_gasP = .true. - case default - eos_outputs_gasP = .false. - end select - -end function eos_outputs_gasP - -!----------------------------------------------------------------------- -!+ -! prints equation of state info in the run header -!+ -!----------------------------------------------------------------------- -subroutine eosinfo(eos_type,iprint) - use dim, only:maxvxyzu - use io, only:fatal,id,master - use eos_helmholtz, only:eos_helmholtz_eosinfo - use eos_barotropic, only:eos_info_barotropic - use eos_piecewise, only:eos_info_piecewise - use eos_gasradrec, only:eos_info_gasradrec - use eos_stamatellos, only:eos_file - integer, intent(in) :: eos_type,iprint - - if (id/=master) return - - select case(eos_type) - case(1,11) - if (1.0d-5 < polyk .and. polyk < 1.0d3) then - write(iprint,"(/,a,f10.6)") ' Isothermal equation of state: cs^2 = ',polyk - else - write(iprint,"(/,a,Es13.6)") ' Isothermal equation of state: cs^2 = ',polyk - endif - if (eos_type==11) write(iprint,*) ' (ZERO PRESSURE) ' - case(2) - if (maxvxyzu >= 4) then - write(iprint,"(/,a,f10.6,a,f10.6)") ' Adiabatic equation of state: P = (gamma-1)*rho*u, gamma = ',& - gamma,' gmw = ',gmw - else - write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6)") ' Polytropic equation of state: P = ',polyk,'*rho^',gamma,' gmw = ',gmw - endif - case(3) - write(iprint,"(/,a,f10.6,a,f10.6)") ' Locally isothermal eq of state (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc - case(5) - if (maxvxyzu >= 4) then - write(iprint,"(' Adiabatic equation of state: P = (gamma-1)*rho*u, where gamma & mu depend on the formation of H2')") - else - stop '[stop eos] eos = 5 cannot assume isothermal conditions' - endif - case(6) - write(iprint,"(/,a,i2,a,f10.6,a,f10.6)") ' Locally (on sink ',isink, & - ') isothermal eos (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc - case(8) - call eos_info_barotropic(polyk,polyk2,iprint) - case(9) - call eos_info_piecewise(iprint) - case(10) - write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6,a)") ' MESA EoS: X = ',X_in,' Z = ',Z_in,' (1-X-Z = ',1.-X_in-Z_in,')' - case(12) - write(iprint,"(/,a,f10.6,a,f10.6)") ' Gas + radiation equation of state: gmw = ',gmw,' gamma = ',gamma - case(15) - call eos_helmholtz_eosinfo(iprint) - case(20) - call eos_info_gasradrec(iprint) - if (use_var_comp) then - write(*,'(1x,a,i1,a)') 'Using variable composition' - else - write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in - endif - case(21) - write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file, 'and calculated gamma.' - end select - write(iprint,*) - -end subroutine eosinfo - -!----------------------------------------------------------------------- -!+ -! write relevant options to the header of the dump file -!+ -!----------------------------------------------------------------------- -subroutine write_headeropts_eos(ieos,hdr,ierr) - use dump_utils, only:dump_h,add_to_rheader,add_to_iheader - integer, intent(in) :: ieos - type(dump_h), intent(inout) :: hdr - integer, intent(out) :: ierr - - call add_to_iheader(isink,'isink',hdr,ierr) - call add_to_rheader(gamma,'gamma',hdr,ierr) - call add_to_rheader(1.5*polyk,'RK2',hdr,ierr) - call add_to_rheader(polyk2,'polyk2',hdr,ierr) - call add_to_rheader(qfacdisc,'qfacdisc',hdr,ierr) - call add_to_rheader(qfacdisc2,'qfacdisc2',hdr,ierr) - - if (ieos==7) then - call add_to_iheader(istrat,'istrat',hdr,ierr) - call add_to_rheader(alpha_z,'alpha_z',hdr,ierr) - call add_to_rheader(beta_z,'beta_z',hdr,ierr) - call add_to_rheader(z0,'z0',hdr,ierr) - endif - -end subroutine write_headeropts_eos - -!----------------------------------------------------------------------- -!+ -! read relevant options from the header of the dump file -!+ -!----------------------------------------------------------------------- -subroutine read_headeropts_eos(ieos,hdr,ierr) - use dump_utils, only:dump_h, extract - use io, only:iprint,id,master - use dim, only:use_krome,maxvxyzu - integer, intent(in) :: ieos - type(dump_h), intent(in) :: hdr - integer, intent(out) :: ierr - real :: RK2 - - - call extract('gamma',gamma,hdr,ierr) - call extract('RK2',rk2,hdr,ierr) - polyk = 2./3.*rk2 - if (id==master) then - if (maxvxyzu >= 4) then - if (use_krome) then - write(iprint,*) 'KROME eos: initial gamma = 1.666667' - elseif (ieos==21) then - write(iprint,*) 'Tabulated eos with derived gamma' - else - write(iprint,*) 'adiabatic eos: gamma = ',gamma - endif - else - write(iprint,*) 'setting isothermal sound speed^2 (polyk) = ',polyk,' gamma = ',gamma - if (polyk <= tiny(polyk)) write(iprint,*) 'WARNING! sound speed zero in dump!, polyk = ',polyk - endif - endif - call extract('polyk2',polyk2,hdr,ierr) - call extract('qfacdisc',qfacdisc,hdr,ierr) - call extract('qfacdisc2',qfacdisc2,hdr,ierr) - call extract('isink',isink,hdr,ierr) - - if (abs(gamma-1.) > tiny(gamma) .and. maxvxyzu < 4) then - write(*,*) 'WARNING! compiled for isothermal equation of state but gamma /= 1, gamma=',gamma - endif - - ierr = 0 - if (ieos==3 .or. ieos==6 .or. ieos==7) then - if (qfacdisc <= tiny(qfacdisc)) then - if (id==master) write(iprint,*) 'ERROR: qfacdisc <= 0' - ierr = 2 - else - if (id==master) write(iprint,*) 'qfacdisc = ',qfacdisc - endif - endif - - if (ieos==7) then - call extract('istrat',istrat,hdr,ierr) - call extract('alpha_z',alpha_z,hdr,ierr) - call extract('beta_z', beta_z, hdr,ierr) - call extract('z0',z0,hdr,ierr) - if (abs(qfacdisc2) <= tiny(qfacdisc2)) then - if (id==master) write(iprint,*) 'ERROR: qfacdisc2 == 0' - ierr = 2 - else - if (id==master) write(iprint,*) 'qfacdisc2 = ',qfacdisc2 - endif - endif - -end subroutine read_headeropts_eos - -!----------------------------------------------------------------------- -!+ -! writes equation of state options to the input file -!+ -!----------------------------------------------------------------------- -subroutine write_options_eos(iunit) - use infile_utils, only:write_inopt - use eos_helmholtz, only:eos_helmholtz_write_inopt - use eos_barotropic, only:write_options_eos_barotropic - use eos_piecewise, only:write_options_eos_piecewise - use eos_gasradrec, only:write_options_eos_gasradrec - integer, intent(in) :: iunit - - write(iunit,"(/,a)") '# options controlling equation of state' - call write_inopt(ieos,'ieos','eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)',iunit) -#ifndef KROME - if (.not. eos_outputs_mu(ieos)) call write_inopt(gmw,'mu','mean molecular weight',iunit) -#endif - select case(ieos) - case(8) - call write_options_eos_barotropic(iunit) - case(9) - call write_options_eos_piecewise(iunit) - case(10) - call write_inopt(X_in,'X','hydrogen mass fraction',iunit) - call write_inopt(Z_in,'Z','metallicity',iunit) - case(15) ! helmholtz eos - call eos_helmholtz_write_inopt(iunit) - case(20) - call write_options_eos_gasradrec(iunit) - if (.not. use_var_comp) then - call write_inopt(X_in,'X','H mass fraction (ignored if variable composition)',iunit) - call write_inopt(Z_in,'Z','metallicity (ignored if variable composition)',iunit) - endif - end select - -end subroutine write_options_eos - -!----------------------------------------------------------------------- -!+ -! reads equation of state options from the input file -!+ -!----------------------------------------------------------------------- -subroutine read_options_eos(name,valstring,imatch,igotall,ierr) - use dim, only:store_dust_temperature,update_muGamma - use io, only:fatal - use eos_barotropic, only:read_options_eos_barotropic - use eos_piecewise, only:read_options_eos_piecewise - use eos_gasradrec, only:read_options_eos_gasradrec - character(len=*), intent(in) :: name,valstring - logical, intent(out) :: imatch,igotall - integer, intent(out) :: ierr - integer, save :: ngot = 0 - character(len=30), parameter :: label = 'read_options_eos' - logical :: igotall_barotropic,igotall_piecewise,igotall_gasradrec - - imatch = .true. - igotall_barotropic = .true. - igotall_piecewise = .true. - igotall_gasradrec = .true. - - select case(trim(name)) - case('ieos') - read(valstring,*,iostat=ierr) ieos - ngot = ngot + 1 - if (ieos <= 0 .or. ieos > maxeos) call fatal(label,'equation of state choice out of range') - if (ieos == 5) then - store_dust_temperature = .true. - update_muGamma = .true. - endif - if (ieos == 21) update_muGamma = .true. - case('mu') - read(valstring,*,iostat=ierr) gmw - ! not compulsory to read in - if (gmw <= 0.) call fatal(label,'mu <= 0') - case('X') - read(valstring,*,iostat=ierr) X_in - if (X_in <= 0. .or. X_in >= 1.) call fatal(label,'X must be between 0 and 1') - ngot = ngot + 1 - case('Z') - read(valstring,*,iostat=ierr) Z_in - if (Z_in <= 0. .or. Z_in > 1.) call fatal(label,'Z must be between 0 and 1') - ngot = ngot + 1 - case default - imatch = .false. - end select - if (.not.imatch .and. ieos== 8) call read_options_eos_barotropic(name,valstring,imatch,igotall_barotropic,ierr) - if (.not.imatch .and. ieos== 9) call read_options_eos_piecewise( name,valstring,imatch,igotall_piecewise, ierr) - if (.not.imatch .and. ieos==20) call read_options_eos_gasradrec( name,valstring,imatch,igotall_gasradrec, ierr) - - !--make sure we have got all compulsory options (otherwise, rewrite input file) - igotall = (ngot >= 1) .and. igotall_piecewise .and. igotall_barotropic .and. igotall_gasradrec - -end subroutine read_options_eos - - -!----------------------------------------------------------------------- - -end module eos diff --git a/src/main/eos.f90 b/src/main/eos.f90 deleted file mode 100644 index b68bf45b6..000000000 --- a/src/main/eos.f90 +++ /dev/null @@ -1,1560 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module eos -! -! This module contains stuff to do with the equation of state -! Current options: -! 1 = isothermal eos -! 2 = adiabatic/polytropic eos -! 3 = eos for a locally isothermal disc as in Lodato & Pringle (2007) -! 4 = GR isothermal -! 5 = polytropic EOS with vary mu and gamma depending on H2 formation -! 6 = eos for a locally isothermal disc as in Lodato & Pringle (2007), -! centered on a sink particle -! 7 = z-dependent locally isothermal eos -! 8 = Barotropic eos -! 9 = Piecewise polytrope -! 10 = MESA EoS -! 11 = isothermal eos with zero pressure -! 12 = ideal gas with radiation pressure -! 13 = locally isothermal prescription from Farris et al. (2014) generalised for generic hierarchical systems -! 14 = locally isothermal prescription from Farris et al. (2014) for binary system -! 15 = Helmholtz free energy eos -! 16 = Shen eos -! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) -! 21 = read tabulated eos (for use with icooling == 9) -! -! :References: -! Lodato & Pringle (2007) -! Hirai et al. (2020) -! -! :Owner: Daniel Price -! -! :Runtime parameters: -! - X : *H mass fraction (ignored if variable composition)* -! - Z : *metallicity (ignored if variable composition)* -! - ieos : *eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)* -! - metallicity : *metallicity* -! - mu : *mean molecular weight* -! -! :Dependencies: dim, dump_utils, eos_barotropic, eos_gasradrec, -! eos_helmholtz, eos_idealplusrad, eos_mesa, eos_piecewise, eos_shen, -! eos_stratified, infile_utils, io, mesa_microphysics, part, physcon, -! units -! - use part, only:ien_etotal,ien_entropy,ien_type - use dim, only:gr - implicit none - integer, parameter, public :: maxeos = 21 - real, public :: polyk, polyk2, gamma - real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 - logical, public :: extract_eos_from_hdr = .false. - integer, public :: isink = 0. - - public :: equationofstate,setpolyk,eosinfo,get_mean_molecular_weight - public :: get_TempPresCs,get_spsound,get_temperature,get_pressure,get_cv - public :: eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP - public :: get_local_u_internal,get_temperature_from_u - public :: calc_rec_ene,calc_temp_and_ene,entropy,get_rho_from_p_s,get_u_from_rhoT - public :: calc_rho_from_PT,get_entropy,get_p_from_rho_s - public :: init_eos,finish_eos,write_options_eos,read_options_eos - public :: write_headeropts_eos, read_headeropts_eos - - private - - integer, public :: ieos = 1 - integer, public :: iopacity_type = 0 ! used for radiation - real, public :: gmw = 2.381 ! default mean molecular weight - real, public :: X_in = 0.74 ! default metallicities - real, public :: Z_in = 0.02 ! default metallicities - logical, public :: use_var_comp = .false. ! use variable composition - real, public :: temperature_coef - - logical, public :: done_init_eos = .false. - ! - ! error codes for calls to init_eos - ! - integer, public, parameter :: & - ierr_file_not_found = 1, & - ierr_option_conflict = 2, & - ierr_units_not_set = 3, & - ierr_isink_not_set = 4 - -! -! Default temperature prescription for vertical stratification (0=MAPS, 1=Dartois) -! - integer, public:: istrat = 0. -! -! 2D temperature structure fit parameters for HD 163296 -! - real, public :: z0 = 1. - real, public :: alpha_z = 3.01 - real, public :: beta_z = 0.42 - -contains - -!---------------------------------------------------------------- -!+ -! subroutine returns pressure/density as a function of density -! (and position in the case of the isothermal disc) -!+ -!---------------------------------------------------------------- -subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gamma_local,mu_local,Xlocal,Zlocal) - use io, only:fatal,error,warning - use part, only:xyzmh_ptmass, nptmass - use units, only:unit_density,unit_pressure,unit_ergg,unit_velocity - use physcon, only:Rg,radconst - use eos_mesa, only:get_eos_pressure_temp_gamma1_mesa,get_eos_1overmu_mesa - use eos_helmholtz, only:eos_helmholtz_pres_sound - use eos_shen, only:eos_shen_NL3 - use eos_idealplusrad - use eos_gasradrec, only:equationofstate_gasradrec - use eos_stratified, only:get_eos_stratified - use eos_barotropic, only:get_eos_barotropic - use eos_piecewise, only:get_eos_piecewise - use eos_stamatellos - integer, intent(in) :: eos_type - real, intent(in) :: rhoi,xi,yi,zi - real, intent(out) :: ponrhoi,spsoundi - real, intent(inout) :: tempi - real, intent(in), optional :: eni - real, intent(inout), optional :: mu_local,gamma_local - real, intent(in) , optional :: Xlocal,Zlocal - integer :: ierr, i - real :: r1,r2 - real :: mass_r, mass ! defined for generalised Farris prescription - real :: gammai,temperaturei,mui,imui,X_i,Z_i - real :: cgsrhoi,cgseni,cgspresi,presi,gam1,cgsspsoundi - real :: uthermconst,kappaBar,kappaPart,gmwi - real :: enthi,pondensi - ! - ! Check to see if equation of state is compatible with GR cons2prim routines - ! - if (gr .and. .not.any((/2,4,11,12/)==eos_type)) then - ponrhoi = 0.; spsoundi = 0. ! avoid compiler warning - call fatal('eos','GR currently only works for ieos=2,12 or 11',& - var='eos_type',val=real(eos_type)) - endif - - gammai = gamma - mui = gmw - X_i = X_in - Z_i = Z_in - if (present(gamma_local)) gammai = gamma_local - if (present(mu_local)) mui = mu_local - if (present(Xlocal)) X_i = Xlocal - if (present(Zlocal)) Z_i = Zlocal - - select case(eos_type) - case(1) -! -!--Isothermal eos -! -! :math:`P = c_s^2 \rho` -! -! where :math:`c_s^2 \equiv K` is a constant stored in the dump file header -! - ponrhoi = polyk - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(2,5) -! -!--Adiabatic equation of state (code default) -! -! :math:`P = (\gamma - 1) \rho u` -! -! if the code is compiled with ISOTHERMAL=yes, ieos=2 gives a polytropic eos: -! -! :math:`P = K \rho^\gamma` -! -! where K is a global constant specified in the dump header -! - if (gammai < tiny(gammai)) call fatal('eos','gamma not set for adiabatic eos',var='gamma',val=gammai) - - if (gr) then - if (.not. present(eni)) call fatal('eos','GR call to equationofstate requires thermal energy as input!') - if (eni < 0.) call fatal('eos','utherm < 0',var='u',val=eni) - if (gammai <= 1.) then - spsoundi = 0.; ponrhoi = 0. ! avoid compiler warning - call fatal('eos','GR not compatible with isothermal equation of state, yet...',var='gamma',val=gammai) - elseif (gammai > 1.0001) then - pondensi = (gammai-1.)*eni ! eni is the thermal energy - enthi = 1. + eni + pondensi ! enthalpy - spsoundi = sqrt(gammai*pondensi/enthi) - ponrhoi = pondensi ! With GR this routine actually outputs pondensi (i.e. pressure on primitive density, not conserved.) - endif - else - if (present(eni)) then - if (eni < 0.) then - !write(iprint,'(a,Es18.4,a,4Es18.4)')'Warning: eos: u = ',eni,' < 0 at {x,y,z,rho} = ',xi,yi,zi,rhoi - call fatal('eos','utherm < 0',var='u',val=eni) - endif - if (gammai > 1.0001) then - ponrhoi = (gammai-1.)*eni ! use this if en is thermal energy - else - ponrhoi = 2./3.*eni ! en is thermal energy and gamma = 1 - endif - else - ponrhoi = polyk*rhoi**(gammai-1.) - endif - spsoundi = sqrt(gammai*ponrhoi) - endif - - tempi = temperature_coef*mui*ponrhoi - - case(3) -! -!--Locally isothermal disc as in Lodato & Pringle (2007) where -! -! :math:`P = c_s^2 (r) \rho` -! -! sound speed (temperature) is prescribed as a function of radius using: -! -! :math:`c_s = c_{s,0} r^{-q}` where :math:`r = \sqrt{x^2 + y^2 + z^2}` -! - ponrhoi = polyk*(xi**2 + yi**2 + zi**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(4) -! -!--Isothermal equation of state for GR, enforcing cs = constant -! -! .. WARNING:: this is experimental: use with caution -! - uthermconst = polyk - ponrhoi = (gammai-1.)*uthermconst - spsoundi = sqrt(ponrhoi/(1.+uthermconst)) - tempi = temperature_coef*mui*ponrhoi - - case(6) -! -!--Locally isothermal disc centred on sink particle -! -! As in ieos=3 but in this version radius is taken with respect to a designated -! sink particle (by default the first sink particle in the simulation) -! - ponrhoi = polyk*((xi-xyzmh_ptmass(1,isink))**2 + (yi-xyzmh_ptmass(2,isink))**2 + & - (zi-xyzmh_ptmass(3,isink))**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(7) -! -!--Vertically stratified equation of state -! -! sound speed is prescribed as a function of (cylindrical) radius R and -! height z above the x-y plane -! -! .. WARNING:: should not be used for misaligned discs -! - call get_eos_stratified(istrat,xi,yi,zi,polyk,polyk2,qfacdisc,qfacdisc2,alpha_z,beta_z,z0,ponrhoi,spsoundi) - tempi = temperature_coef*mui*ponrhoi - - case(8) -! -!--Barotropic equation of state -! -! :math:`P = K \rho^\gamma` -! -! where the value of gamma (and K) are a prescribed function of density -! - call get_eos_barotropic(rhoi,polyk,polyk2,ponrhoi,spsoundi,gammai) - tempi = temperature_coef*mui*ponrhoi - - case(9) -! -!--Piecewise Polytropic equation of state -! -! :math:`P = K \rho^\gamma` -! -! where the value of gamma (and K) are a prescribed function of density. -! Similar to ieos=8 but with different defaults and slightly different -! functional form -! - call get_eos_piecewise(rhoi,ponrhoi,spsoundi,gammai) - tempi = temperature_coef*mui*ponrhoi - - case(10) -! -!--MESA equation of state -! -! a tabulated equation of state including gas, radiation pressure -! and ionisation/dissociation. MESA is a stellar evolution code, so -! this equation of state is designed for matter inside stars -! - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - call get_eos_pressure_temp_gamma1_mesa(cgsrhoi,cgseni,cgspresi,temperaturei,gam1,ierr) - presi = cgspresi / unit_pressure - - ponrhoi = presi / rhoi - spsoundi = sqrt(gam1*ponrhoi) - tempi = temperaturei - if (present(gamma_local)) gamma_local = gam1 ! gamma is an output - if (present(mu_local)) mu_local = 1./get_eos_1overmu_mesa(cgsrhoi,cgseni) - if (ierr /= 0) call warning('eos_mesa','extrapolating off tables') - - case(11) -! -!--Isothermal equation of state with pressure and temperature equal to zero -! -! :math:`P = 0` -! -! useful for simulating test particle dynamics using SPH particles -! - ponrhoi = 0. - spsoundi = sqrt(polyk) - tempi = 0. - - case(12) -! -!--Ideal gas plus radiation pressure -! -! :math:`P = (\gamma - 1) \rho u` -! -! but solved by first solving the quartic equation: -! -! :math:`u = \frac32 \frac{k_b T}{\mu m_H} + \frac{a T^4}{\rho}` -! -! for temperature (given u), then solving for pressure using -! -! :math:`P = \frac{k_b T}{\mu m_H} + \frac13 a T^4` -! -! hence in this equation of state gamma (and temperature) are an output -! - temperaturei = tempi ! Required as initial guess - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - call get_idealplusrad_temp(cgsrhoi,cgseni,mui,temperaturei,ierr) - call get_idealplusrad_pres(cgsrhoi,temperaturei,mui,cgspresi) - call get_idealplusrad_spsoundi(cgsrhoi,cgspresi,cgseni,spsoundi,gammai) - if (present(gamma_local)) gamma_local = gammai ! gamma is an output - spsoundi = spsoundi / unit_velocity - presi = cgspresi / unit_pressure - ponrhoi = presi / rhoi - tempi = temperaturei - if (ierr /= 0) call warning('eos_idealplusrad','temperature iteration did not converge') - - - case(13) -! -!--Locally isothermal eos for generic hierarchical system -! -! Assuming all sink particles are stars. -! Generalisation of Farris et al. (2014; for binaries) to N stars. -! For two sink particles this is identical to ieos=14 -! - mass_r = 0 - mass = 0 - - do i=1,nptmass - mass_r = mass_r+xyzmh_ptmass(4,i)/sqrt((xi-xyzmh_ptmass(1,i))**2 + (yi-xyzmh_ptmass(2,i))**2 + (zi-xyzmh_ptmass(3,i))**2) - mass = mass + xyzmh_ptmass(4,i) - enddo - ponrhoi=polyk*(mass_r)**(2*qfacdisc)/mass**(2*qfacdisc) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - - case(14) -! -!--Locally isothermal eos from Farris et al. (2014) for binary system -! -! uses the locations of the first two sink particles -! - r1 = sqrt((xi-xyzmh_ptmass(1,1))**2+(yi-xyzmh_ptmass(2,1))**2 + (zi-xyzmh_ptmass(3,1))**2) - r2 = sqrt((xi-xyzmh_ptmass(1,2))**2+(yi-xyzmh_ptmass(2,2))**2 + (zi-xyzmh_ptmass(3,2))**2) - ponrhoi=polyk*(xyzmh_ptmass(4,1)/r1+xyzmh_ptmass(4,2)/r2)**(2*qfacdisc)/(xyzmh_ptmass(4,1)+xyzmh_ptmass(4,2))**(2*qfacdisc) - spsoundi = sqrt(ponrhoi) - tempi = temperature_coef*mui*ponrhoi - - case(15) -! -!--Helmholtz equation of state (computed live, not tabulated) -! -! .. WARNING:: not widely tested in phantom, better to use ieos=10 -! - call eos_helmholtz_pres_sound(tempi, rhoi, ponrhoi, spsoundi, eni) - - case(16) -! -!--Shen (2012) equation of state for neutron stars -! -! this equation of state requires evolving temperature as the energy variable -! -! .. WARNING:: not tested: use with caution -! - if (present(eni)) then - cgsrhoi = rhoi * unit_density - !note eni is actually tempi - call eos_shen_NL3(cgsrhoi,eni,0.05,cgspresi,cgsspsoundi) - spsoundi=cgsspsoundi / unit_velocity - presi = cgspresi / unit_pressure - ponrhoi = presi / rhoi - tempi = eni - call warning('eos','Not sure if this is correct now that temperature is always passed into eos') - else - spsoundi = 0.; presi = 0.; ponrhoi = 0.; tempi = 0. ! to avoid compiler warnings - call fatal('eos','tried to call NL3 eos without passing temperature') - endif - - case(20) -! -!--Gas + radiation + various forms of recombination -! -! from HORMONE, Hirai+2020, as used in Lau+2022b -! - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - imui = 1./mui - if (tempi > 0.) then - temperaturei = tempi - else - temperaturei = min(0.67 * cgseni * mui / Rg, (cgseni*cgsrhoi/radconst)**0.25) - endif - call equationofstate_gasradrec(cgsrhoi,cgseni*cgsrhoi,temperaturei,imui,X_i,1.-X_i-Z_i,cgspresi,cgsspsoundi,gammai) - ponrhoi = real(cgspresi / (unit_pressure * rhoi)) - spsoundi = real(cgsspsoundi / unit_velocity) - tempi = temperaturei - if (present(mu_local)) mu_local = 1./imui - if (present(gamma_local)) gamma_local = gammai - - case(21) -! -!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=9 -! - if (eni < 0.) then - call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) - endif - cgsrhoi = rhoi * unit_density - cgseni = eni * unit_ergg - call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) - cgspresi = kb_on_mh*cgsrhoi*tempi/mui - presi = cgspresi/unit_pressure - ponrhoi = presi/rhoi - gammai = 1.d0 + presi/(eni*rhoi) - !if (gammai < 1.d0 .or. gammai > 2.d0) then - ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi - !endif - spsoundi = sqrt(gammai*ponrhoi) - - - case default - spsoundi = 0. ! avoids compiler warnings - ponrhoi = 0. - tempi = 0. - call fatal('eos','unknown equation of state') - end select - -end subroutine equationofstate - -!----------------------------------------------------------------------- -!+ -! initialise equation of state (read tables etc.) -!+ -!----------------------------------------------------------------------- -subroutine init_eos(eos_type,ierr) - use units, only:unit_velocity - use physcon, only:Rg - use io, only:error,warning,fatal - use eos_mesa, only:init_eos_mesa - use eos_helmholtz, only:eos_helmholtz_init - use eos_piecewise, only:init_eos_piecewise - use eos_barotropic, only:init_eos_barotropic - use eos_shen, only:init_eos_shen_NL3 - use eos_gasradrec, only:init_eos_gasradrec - use eos_stamatellos,only:read_optab,init_S07cool,eos_file - use dim, only:maxvxyzu,do_radiation - integer, intent(in) :: eos_type - integer, intent(out) :: ierr - integer :: ierr_mesakapp - - ierr = 0 - ! - !--Set coefficient to convert P/rho into temperature - ! calculation will be in cgs; the mean molecular weight, gmw, will be - ! included in the function call rather than here - ! c_s^2 = gamma*P/rho = gamma*kT/(gmw*m_p) -> T = P/rho * (gmw*m_p)/k - ! - temperature_coef = unit_velocity**2 / Rg - - select case(eos_type) - case(6) - ! - !--Check that if using ieos=6, then isink is set properly - ! - if (isink==0) then - call error('eos','ieos=6, but isink is not set') - ierr = ierr_isink_not_set - return - endif - - case(8) - ! - ! barotropic equation of state - ! - call init_eos_barotropic(polyk,polyk2,ierr) - - case(9) - ! - ! piecewise polytropic equation of state (similar to barotropic) - ! - call init_eos_piecewise(ierr) - - case(10) - ! - !--MESA EoS initialisation - ! - write(*,'(1x,a,f7.5,a,f7.5)') 'Initialising MESA EoS with X = ',X_in,', Z = ',Z_in - call init_eos_mesa(X_in,Z_in,ierr) - if (do_radiation .and. ierr==0) then - call error('eos','ieos=10, cannot use eos with radiation, will double count radiation pressure') - ierr=ierr_option_conflict !return error if using radiation and mesa EOS, shouldn't use mesa eos, as it will double count rad pres - endif - - case(12) - ! - ! ideal plus radiation - ! - write(*,'(1x,a,f7.5)') 'Using ideal plus radiation EoS with mu = ',gmw - if (do_radiation) then - call error('eos','ieos=12, cannot use eos with radiation, will double count radiation pressure') - ierr = ierr_option_conflict - endif - - case(15) - - call eos_helmholtz_init(ierr) - - case(16) - - call init_eos_shen_NL3(ierr) - - case(20) - - call init_eos_gasradrec(ierr) - if (.not. use_var_comp) then - write(*,'(a,f7.5,a,f7.5)') 'Assuming fixed composition X = ',X_in,', Z = ',Z_in - endif - if (do_radiation) then - call error('eos','ieos=20, cannot use eos with radiation, will double count radiation pressure') - ierr = ierr_option_conflict - endif - - case(21) - - call read_optab(eos_file,ierr) - if (ierr > 0) call fatal('init_eos','Failed to read EOS file') - call init_S07cool - - end select - done_init_eos = .true. - - if (do_radiation .and. iopacity_type==1) then - write(*,'(1x,a,f7.5,a,f7.5)') 'Using radiation with MESA opacities. Initialising MESA EoS with X = ',X_in,', Z = ',Z_in - call init_eos_mesa(X_in,Z_in,ierr_mesakapp) - ierr = max(ierr,ierr_mesakapp) - endif - -end subroutine init_eos - -!----------------------------------------------------------------------- -!+ -! finish equation of state -!+ -!----------------------------------------------------------------------- -subroutine finish_eos(eos_type,ierr) - use eos_mesa, only: finish_eos_mesa - use eos_stamatellos, only: finish_S07cool - - integer, intent(in) :: eos_type - integer, intent(out) :: ierr - - ierr = 0 - - select case(eos_type) - case(10) - ! - !--MESA EoS deallocation - ! - call finish_eos_mesa - - case(21) - ! Stamatellos deallocation - call finish_S07cool - - end select - done_init_eos=.false. - -end subroutine finish_eos - -!----------------------------------------------------------------------- -!+ -! Calculate gas temperature, sound speed, and pressure. -! This will be required for various analysis routines if eos_vars -! is not saved in the dump files -!+ -!----------------------------------------------------------------------- -subroutine get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi,spsoundi,gammai,mui,Xi,Zi) - use dim, only:maxvxyzu - integer, intent(in) :: eos_type - real, intent(in) :: vxyzui(:),xyzi(:),rhoi - real, intent(inout) :: tempi - real, intent(out), optional :: presi,spsoundi - real, intent(inout), optional :: gammai,mui - real, intent(in), optional :: Xi,Zi - real :: csi,ponrhoi,mu,X,Z - logical :: use_gamma - - mu = gmw - X = X_in - Z = Z_in - if (present(mui)) mu = mui - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - use_gamma = .false. - if (present(gammai)) then - if (gammai > 0.) use_gamma = .true. - endif - - if (maxvxyzu==4) then - 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) - else - call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,vxyzui(4),& - mu_local=mu,Xlocal=X,Zlocal=Z) - endif - else - call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,mu_local=mu) - endif - - if (present(presi)) presi = ponrhoi*rhoi - if (present(spsoundi)) spsoundi = csi - if (present(mui)) mui = mu - if (present(gammai)) gammai = gamma - -end subroutine get_TempPresCs - -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate sound speed -!+ -!----------------------------------------------------------------------- -real function get_spsound(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xyzi(:),rhoi - real, intent(in) :: vxyzui(:) - real, intent(in), optional :: Xi,Zi - real, intent(inout), optional :: gammai,mui - real :: spsoundi,tempi,gam,mu,X,Z - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,spsoundi=spsoundi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_spsound = spsoundi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - -end function get_spsound - -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate temperature -!+ -!----------------------------------------------------------------------- -real function get_temperature(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xyzi(:),rhoi - real, intent(in) :: vxyzui(:) - real, intent(in), optional :: Xi,Zi - real, intent(inout),optional :: gammai,mui - real :: tempi,gam,mu,X,Z - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_temperature = tempi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - -end function get_temperature - - -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate temperature -!+ -!----------------------------------------------------------------------- -real function get_temperature_from_u(eos_type,xpi,ypi,zpi,rhoi,ui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xpi,ypi,zpi,rhoi - real, intent(in) :: ui - real, intent(in), optional :: Xi,Zi - real, intent(inout),optional :: gammai,mui - real :: tempi,gam,mu,X,Z - real :: vxyzui(4),xyzi(3) - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - vxyzui = (/0.,0.,0.,ui/) - xyzi = (/xpi,ypi,zpi/) - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_temperature_from_u = tempi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - - -end function get_temperature_from_u -!----------------------------------------------------------------------- -!+ -! Wrapper function to calculate pressure -!+ -!----------------------------------------------------------------------- -real function get_pressure(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) - integer, intent(in) :: eos_type - real, intent(in) :: xyzi(:),rhoi,vxyzui(:) - real, intent(in), optional :: Xi,Zi - real, intent(inout),optional :: gammai,mui - real :: presi,tempi,gam,mu,X,Z - - !set defaults for variables not passed in - mu = gmw - X = X_in - Z = Z_in - tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess - gam = -1. ! to indicate gamma is not being passed in - if (present(mui)) mu = mui - if (present(Xi)) X = Xi - if (present(Zi)) Z = Zi - if (present(gammai)) gam = gammai - if (present(mui)) mu = mui - - call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi=presi,gammai=gam,mui=mu,Xi=X,Zi=Z) - - get_pressure = presi - - if (present(mui)) mui = mu - if (present(gammai)) gammai = gam - -end function get_pressure - -!----------------------------------------------------------------------- -!+ -! query function to return the internal energy for calculations with a -! local mean molecular weight and local adiabatic index -!+ -!----------------------------------------------------------------------- -real function get_local_u_internal(gammai, gmwi, gas_temp_local) - real, intent(in) :: gammai, gmwi, gas_temp_local - real :: ponrhoi - - ponrhoi = gas_temp_local/(gmwi*temperature_coef) - get_local_u_internal = ponrhoi/(gammai-1.) - -end function get_local_u_internal - -!----------------------------------------------------------------------- -!+ -! get u from rho, T -!+ -!----------------------------------------------------------------------- -real function get_u_from_rhoT(rho,temp,eos_type,uguess) result(u) - use eos_mesa, only:get_eos_u_from_rhoT_mesa - integer, intent(in) :: eos_type - real, intent(in) :: rho,temp - real, intent(in), optional :: uguess - - select case (eos_type) - case(10) ! MESA EoS - if (present(uguess)) then - call get_eos_u_from_rhoT_mesa(rho,temp,u,uguess) - else - call get_eos_u_from_rhoT_mesa(rho,temp,u) - endif - - case default - u = temp/(gmw*temperature_coef*(gamma-1.)) - end select - -end function get_u_from_rhoT - -!----------------------------------------------------------------------- -!+ -! Get recombination energy (per unit mass) assumming complete -! ionisation -!+ -!----------------------------------------------------------------------- -subroutine calc_rec_ene(XX,YY,e_rec) - real, intent(in) :: XX, YY - real, intent(out) :: e_rec - real :: e_H2,e_HI,e_HeI,e_HeII - real, parameter :: e_ion_H2 = 1.312e13, & ! ionisation energies in erg/mol - e_ion_HI = 4.36e12, & - e_ion_HeI = 2.3723e13, & - e_ion_HeII = 5.2505e13 - - ! XX : Hydrogen mass fraction - ! YY : Helium mass fraction - ! e_rec : Total ionisation energy due to H2, HI, HeI, and HeII - - e_H2 = 0.5 * XX * e_ion_H2 - e_HI = XX * e_ion_HI - e_HeI = 0.25 * YY * e_ion_HeI - e_HeII = 0.25 * YY * e_ion_HeII - e_rec = e_H2 + e_HI + e_HeI + e_HeII - -end subroutine calc_rec_ene - -!----------------------------------------------------------------------- -!+ -! Calculate temperature and specific internal energy from -! pressure and density. Inputs and outputs are in cgs units. -! -! Note on composition: -! For ieos=2, 5 and 12, mu_local is an input, X & Z are not used -! For ieos=10, mu_local is not used -! For ieos=20, mu_local is not used but available as an output -!+ -!----------------------------------------------------------------------- -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 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 - integer, intent(in) :: eos_type - real, intent(in) :: rho,pres - real, intent(inout) :: ene,temp - real, intent(in), optional :: guesseint,X_local,Z_local - real, intent(inout), optional :: mu_local - integer, intent(out) :: ierr - real :: mu,X,Z - - ierr = 0 - mu = gmw - X = X_in - Z = Z_in - if (present(mu_local)) mu = mu_local - if (present(X_local)) X = X_local - if (present(Z_local)) Z = Z_local - select case(eos_type) - case(2,5) ! Ideal gas - temp = pres / (rho * kb_on_mh) * mu - ene = pres / ( (gamma-1.) * rho) - case(12) ! Ideal gas + radiation - call get_idealgasplusrad_tempfrompres(pres,rho,mu,temp) - call get_idealplusrad_enfromtemp(rho,temp,mu,ene) - case(10) ! MESA EoS - call get_eos_eT_from_rhop_mesa(rho,pres,ene,temp,guesseint) - case(20) ! Ideal gas + radiation + recombination (from HORMONE, Hirai et al., 2020) - call calc_uT_from_rhoP_gasradrec(rho,pres,X,1.-X-Z,temp,ene,mu,ierr) - if (present(mu_local)) mu_local = mu - case default - ierr = 1 - end select - -end subroutine calc_temp_and_ene - -!----------------------------------------------------------------------- -!+ -! Calculate density from pressure and temperature. Inputs and outputs -! are in cgs units. -! -! Note on composition: -! For ieos=2 and 12, mu_local is an input, X & Z are not used -! For ieos=10, mu_local is not used -! For ieos=20, mu_local is not used but available as an output -!+ -!----------------------------------------------------------------------- -subroutine calc_rho_from_PT(eos_type,pres,temp,rho,ierr,mu_local,X_local,Z_local) - use physcon, only:kb_on_mh - 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 - integer, intent(in) :: eos_type - real, intent(in) :: pres,temp - real, intent(inout) :: rho - real, intent(in), optional :: X_local,Z_local - real, intent(inout), optional :: mu_local - integer, intent(out) :: ierr - real :: mu,X,Z - - ierr = 0 - mu = gmw - X = X_in - Z = Z_in - if (present(mu_local)) mu = mu_local - if (present(X_local)) X = X_local - if (present(Z_local)) Z = Z_local - select case(eos_type) - case(2) ! Ideal gas - rho = pres / (temp * kb_on_mh) * mu - case(12) ! Ideal gas + radiation - call get_idealplusrad_rhofrompresT(pres,temp,mu,rho) - case default - ierr = 1 - end select - -end subroutine calc_rho_from_PT - -!----------------------------------------------------------------------- -!+ -! Calculates specific entropy (gas + radiation + recombination) -! up to an additive integration constant, from density and pressure. -!+ -!----------------------------------------------------------------------- -function entropy(rho,pres,mu_in,ientropy,eint_in,ierr) - use io, only:fatal,warning - use physcon, only:radconst,kb_on_mh - 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 - integer, intent(in) :: ientropy - integer, intent(out), optional :: ierr - real :: mu,entropy,logentropy,temp,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) - - ! check temp - if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') - - 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) - - ! check temp - if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') - - 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') - - if (present(eint_in)) then - eint = eint_in - else - call get_eos_eT_from_rhop_mesa(rho,pres,eint,temp) - endif - - ! Get entropy from rho and eint from MESA tables - if (present(ierr)) then - call getvalue_mesa(rho,eint,9,logentropy,ierr) - else - call getvalue_mesa(rho,eint,9,logentropy) - endif - entropy = 10.**logentropy - - case default - entropy = 0. - call fatal('eos','Unknown ientropy (can only be 1, 2, or 3)') - end select - -end function entropy - -real function get_entropy(rho,pres,mu_in,ieos) - use units, only:unit_density,unit_pressure,unit_ergg - use physcon, only:kboltz - integer, intent(in) :: ieos - real, intent(in) :: rho,pres,mu_in - real :: cgsrho,cgspres,cgss - - cgsrho = rho * unit_density - cgspres = pres * unit_pressure - select case (ieos) - case (12) - cgss = entropy(cgsrho,cgspres,mu_in,2) - case (10, 20) - cgss = entropy(cgsrho,cgspres,mu_in,3) - case default - cgss = entropy(cgsrho,cgspres,mu_in,1) - end select - cgss = cgss/kboltz ! s/kb - get_entropy = cgss/unit_ergg - -end function get_entropy - -!----------------------------------------------------------------------- -!+ -! Calculate density given pressure and entropy using Newton-Raphson -! method -!+ -!----------------------------------------------------------------------- -subroutine get_rho_from_p_s(pres,S,rho,mu,rhoguess,ientropy) - real, intent(in) :: pres,S,mu,rhoguess - real, intent(inout) :: rho - real :: srho,srho_plus_dsrho,S_plus_dS,dSdsrho - real(kind=8) :: corr - real, parameter :: eoserr=1e-9,dfac=1e-12 - integer, intent(in) :: ientropy - - ! We apply the Newton-Raphson method directly to rho^1/2 ("srho") instead - ! of rho since S(rho) cannot take a negative argument. - srho = sqrt(rhoguess) ! Initial guess - corr = huge(corr); - do while (abs(corr) > eoserr*abs(srho)) - ! First calculate dS/dsrho - srho_plus_dsrho = srho * (1. + dfac) - S_plus_dS = entropy(srho_plus_dsrho**2,pres,mu,ientropy) - dSdsrho = (S_plus_dS - entropy(srho**2,pres,mu,ientropy)) / (srho_plus_dsrho - srho) - corr = ( entropy(srho**2,pres,mu,ientropy) - S ) / dSdsrho - srho = srho - corr - enddo - rho = srho**2 - -end subroutine get_rho_from_p_s - -!----------------------------------------------------------------------- -!+ -! Calculate temperature given density and entropy using Newton-Raphson -! method -!+ -!----------------------------------------------------------------------- -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 io, only:fatal - use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_pres - use units, only:unit_density,unit_pressure,unit_ergg - real, intent(in) :: S,mu,rho - real, intent(inout) :: temp - real, intent(out) :: P - integer, intent(in) :: ieos - real :: corr,df,f,temp_new,cgsrho,cgsp,cgss - real, parameter :: eoserr=1e-12 - integer :: niter - integer, parameter :: nitermax = 1000 - - ! change to cgs unit - cgsrho = rho*unit_density - cgss = s*unit_ergg - - niter = 0 - select case (ieos) - case (2,5) - temp = (cgsrho * exp(mu*cgss*mass_proton_cgs))**(2./3.) - cgsP = cgsrho*kb_on_mh*temp / mu - case (12) - corr = huge(corr) - do while (abs(corr) > eoserr .and. niter < nitermax) - f = 1. / (mu*mass_proton_cgs) * log(temp**1.5/cgsrho) + 4.*radconst*temp**3 / (3.*cgsrho*kboltz) - cgss - df = 1.5 / (mu*temp*mass_proton_cgs) + 4.*radconst*temp**2 / (cgsrho*kboltz) - corr = f/df - temp_new = temp - corr - if (temp_new > 1.2 * temp) then - temp = 1.2 * temp - elseif (temp_new < 0.8 * temp) then - temp = 0.8 * temp - else - temp = temp_new - endif - niter = niter + 1 - enddo - call get_idealplusrad_pres(cgsrho,temp,mu,cgsP) - case default - cgsP = 0. - call fatal('eos','[get_p_from_rho_s] only implemented for eos 2 and 12') - end select - - ! check temp - if (temp > huge(0.)) call fatal('entropy','entropy too large gives infinte temperature, & - &reducing entropy factor C_ent for one dump') - - ! change back to code unit - P = cgsP / unit_pressure - -end subroutine get_p_from_rho_s - -!----------------------------------------------------------------------- -!+ -! Calculate mean molecular weight from X and Z, assuming complete -! ionisation -!+ -!----------------------------------------------------------------------- -real function get_mean_molecular_weight(XX,ZZ) result(mu) - real, intent(in) :: XX,ZZ - real :: YY - - YY = 1.-XX-ZZ - mu = 1./(2.*XX + 0.75*YY + 0.5*ZZ) - -end function get_mean_molecular_weight - -!--------------------------------------------------------- -!+ -! return cv from rho, u in code units -!+ -!--------------------------------------------------------- -real function get_cv(rho,u,cv_type) result(cv) - use mesa_microphysics, only:getvalue_mesa - use units, only:unit_ergg,unit_density - use physcon, only:Rg - real, intent(in) :: rho,u - integer, intent(in) :: cv_type - real :: rho_cgs,u_cgs,temp - - select case (cv_type) - - case(1) ! MESA EoS - rho_cgs = rho*unit_density - u_cgs = u*unit_ergg - call getvalue_mesa(rho_cgs,u_cgs,4,temp) - cv = u_cgs/temp / unit_ergg - case default ! constant cv - cv = Rg/((gamma-1.)*gmw*unit_ergg) - end select - -end function get_cv - -!----------------------------------------------------------------------- -!+ -! subroutine sets polyk based on utherm/positions -! read from an sphNG dump file -!+ -!----------------------------------------------------------------------- -subroutine setpolyk(eos_type,iprint,utherm,xyzhi,npart) - use part, only:xyzmh_ptmass - use io, only:id,master - integer, intent(in) :: eos_type,iprint - real, intent(in) :: utherm(:) - real, intent(in) :: xyzhi(:,:) - integer, intent(in) :: npart - integer :: ipart - real :: r2,polykalt - - !-- pick a random particle from which to extract polyk - ipart = npart/2 - - select case(eos_type) - case(1,8) -! -!--isothermal eos -! - polykalt = 2./3.*utherm(ipart) - !--check all other utherms identical - if (any(utherm(1:npart) /= utherm(ipart)) .and. id==master) then - write(iprint,*) 'WARNING! different utherms but run is isothermal' - endif - - case(2,5) -! -!--adiabatic/polytropic eos -! this routine is ONLY called if utherm is NOT stored, so polyk matters -! - if (id==master) write(iprint,*) 'Using polytropic equation of state, gamma = ',gamma - polykalt = 2./3.*utherm(ipart) - if (gamma <= 1.00000001) then - stop 'silly to use gamma==1 without using isothermal eos' - endif - - case(3) -! -!--locally isothermal disc as in Lodato & Pringle (2007) -! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) -! - r2 = xyzhi(1,ipart)*xyzhi(1,ipart) + xyzhi(2,ipart)*xyzhi(2,ipart) & - + xyzhi(3,ipart)*xyzhi(3,ipart) - polykalt = 2./3.*utherm(ipart)*r2**qfacdisc - - case(6) -! -!--locally isothermal disc as in Lodato & Pringle (2007), centered on specified sink particle -! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) -! - r2 = (xyzhi(1,ipart)-xyzmh_ptmass(1,isink))**2 + & - (xyzhi(2,ipart)-xyzmh_ptmass(2,isink))**2 + & - (xyzhi(3,ipart)-xyzmh_ptmass(3,isink))**2 - - polykalt = 2./3.*utherm(ipart)*r2**qfacdisc - case default -! -!--don't die in this routine as it can be called from readdump -! (ie. not necessarily as part of a run) -! - if (id==master) write(iprint,*) ' WARNING! unknown equation of state in setpolyk' - polykalt = polyk - - end select - - if (diff(polykalt,polyk) .and. id==master) then - write(iprint,*) 'WARNING! polyk set using RK2 in dump differs from that set using thermal energy' - write(iprint,*) 'using polyk = ',polykalt, ' (from RK2 = ',polyk,')' - endif - polyk = polykalt -! -!--warn if polyk is zero, die if negative -! - if (polyk < 0.) then - write(iprint,*) 'ERROR: polyk < 0 in setting equation of state' - stop - elseif (polyk < tiny(polyk) .and. id==master) then - write(iprint,*) 'WARNING: polyk = 0 in equation of state' - endif - -end subroutine setpolyk -!----------------------------------------------------------------------- -!+ -! small utility returns whether two real numbers differ -!+ -!----------------------------------------------------------------------- -logical pure function diff(r1,r2) - real, intent(in) :: r1,r2 - - diff = abs(r1-r2) > tiny(r1) - -end function diff - -!----------------------------------------------------------------------- -!+ -! Query function to return whether an EoS is non-ideal -! Mainly used to decide whether it is necessary to write -! things like pressure and temperature in the dump file or not -!+ -!----------------------------------------------------------------------- -logical function eos_is_non_ideal(ieos) - integer, intent(in) :: ieos - - select case(ieos) - case(10,12,15,20) - eos_is_non_ideal = .true. - case default - eos_is_non_ideal = .false. - end select - -end function eos_is_non_ideal - -!----------------------------------------------------------------------- -!+ -! Query function to return whether an EoS outputs mean molecular weight -!+ -!----------------------------------------------------------------------- -logical function eos_outputs_mu(ieos) - integer, intent(in) :: ieos - - select case(ieos) - case(20) - eos_outputs_mu = .true. - case default - eos_outputs_mu = .false. - end select - -end function eos_outputs_mu - -!----------------------------------------------------------------------- -!+ -! Query function to whether to print pressure to dump file -!+ -!----------------------------------------------------------------------- -logical function eos_outputs_gasP(ieos) - integer, intent(in) :: ieos - - select case(ieos) - case(8,9,10,15) - eos_outputs_gasP = .true. - case default - eos_outputs_gasP = .false. - end select - -end function eos_outputs_gasP - -!----------------------------------------------------------------------- -!+ -! prints equation of state info in the run header -!+ -!----------------------------------------------------------------------- -subroutine eosinfo(eos_type,iprint) - use dim, only:maxvxyzu - use io, only:fatal,id,master - use eos_helmholtz, only:eos_helmholtz_eosinfo - use eos_barotropic, only:eos_info_barotropic - use eos_piecewise, only:eos_info_piecewise - use eos_gasradrec, only:eos_info_gasradrec - integer, intent(in) :: eos_type,iprint - - if (id/=master) return - - select case(eos_type) - case(1,11) - if (1.0d-5 < polyk .and. polyk < 1.0d3) then - write(iprint,"(/,a,f10.6)") ' Isothermal equation of state: cs^2 = ',polyk - else - write(iprint,"(/,a,Es13.6)") ' Isothermal equation of state: cs^2 = ',polyk - endif - if (eos_type==11) write(iprint,*) ' (ZERO PRESSURE) ' - case(2) - if (maxvxyzu >= 4) then - write(iprint,"(/,a,f10.6,a,f10.6)") ' Adiabatic equation of state: P = (gamma-1)*rho*u, gamma = ',& - gamma,' gmw = ',gmw - else - write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6)") ' Polytropic equation of state: P = ',polyk,'*rho^',gamma,' gmw = ',gmw - endif - case(3) - write(iprint,"(/,a,f10.6,a,f10.6)") ' Locally isothermal eq of state (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc - case(5) - if (maxvxyzu >= 4) then - write(iprint,"(' Adiabatic equation of state: P = (gamma-1)*rho*u, where gamma & mu depend on the formation of H2')") - else - stop '[stop eos] eos = 5 cannot assume isothermal conditions' - endif - case(6) - write(iprint,"(/,a,i2,a,f10.6,a,f10.6)") ' Locally (on sink ',isink, & - ') isothermal eos (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc - case(8) - call eos_info_barotropic(polyk,polyk2,iprint) - case(9) - call eos_info_piecewise(iprint) - case(10) - write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6,a)") ' MESA EoS: X = ',X_in,' Z = ',Z_in,' (1-X-Z = ',1.-X_in-Z_in,')' - case(12) - write(iprint,"(/,a,f10.6,a,f10.6)") ' Gas + radiation equation of state: gmw = ',gmw,' gamma = ',gamma - case(15) - call eos_helmholtz_eosinfo(iprint) - case(20) - call eos_info_gasradrec(iprint) - if (use_var_comp) then - write(*,'(1x,a,i1,a)') 'Using variable composition' - else - write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in - endif - end select - write(iprint,*) - -end subroutine eosinfo - -!----------------------------------------------------------------------- -!+ -! write relevant options to the header of the dump file -!+ -!----------------------------------------------------------------------- -subroutine write_headeropts_eos(ieos,hdr,ierr) - use dump_utils, only:dump_h,add_to_rheader,add_to_iheader - integer, intent(in) :: ieos - type(dump_h), intent(inout) :: hdr - integer, intent(out) :: ierr - - call add_to_iheader(isink,'isink',hdr,ierr) - call add_to_rheader(gamma,'gamma',hdr,ierr) - call add_to_rheader(1.5*polyk,'RK2',hdr,ierr) - call add_to_rheader(polyk2,'polyk2',hdr,ierr) - call add_to_rheader(qfacdisc,'qfacdisc',hdr,ierr) - call add_to_rheader(qfacdisc2,'qfacdisc2',hdr,ierr) - - if (ieos==7) then - call add_to_iheader(istrat,'istrat',hdr,ierr) - call add_to_rheader(alpha_z,'alpha_z',hdr,ierr) - call add_to_rheader(beta_z,'beta_z',hdr,ierr) - call add_to_rheader(z0,'z0',hdr,ierr) - endif - -end subroutine write_headeropts_eos - -!----------------------------------------------------------------------- -!+ -! read relevant options from the header of the dump file -!+ -!----------------------------------------------------------------------- -subroutine read_headeropts_eos(ieos,hdr,ierr) - use dump_utils, only:dump_h, extract - use io, only:iprint,id,master - use dim, only:use_krome,maxvxyzu - integer, intent(in) :: ieos - type(dump_h), intent(in) :: hdr - integer, intent(out) :: ierr - real :: RK2 - - - call extract('gamma',gamma,hdr,ierr) - call extract('RK2',rk2,hdr,ierr) - polyk = 2./3.*rk2 - if (id==master) then - if (maxvxyzu >= 4) then - if (use_krome) then - write(iprint,*) 'KROME eos: initial gamma = 1.666667' - else - write(iprint,*) 'adiabatic eos: gamma = ',gamma - endif - else - write(iprint,*) 'setting isothermal sound speed^2 (polyk) = ',polyk,' gamma = ',gamma - if (polyk <= tiny(polyk)) write(iprint,*) 'WARNING! sound speed zero in dump!, polyk = ',polyk - endif - endif - call extract('polyk2',polyk2,hdr,ierr) - call extract('qfacdisc',qfacdisc,hdr,ierr) - call extract('qfacdisc2',qfacdisc2,hdr,ierr) - call extract('isink',isink,hdr,ierr) - - if (abs(gamma-1.) > tiny(gamma) .and. maxvxyzu < 4) then - write(*,*) 'WARNING! compiled for isothermal equation of state but gamma /= 1, gamma=',gamma - endif - - ierr = 0 - if (ieos==3 .or. ieos==6 .or. ieos==7) then - if (qfacdisc <= tiny(qfacdisc)) then - if (id==master) write(iprint,*) 'ERROR: qfacdisc <= 0' - ierr = 2 - else - if (id==master) write(iprint,*) 'qfacdisc = ',qfacdisc - endif - endif - - if (ieos==7) then - call extract('istrat',istrat,hdr,ierr) - call extract('alpha_z',alpha_z,hdr,ierr) - call extract('beta_z', beta_z, hdr,ierr) - call extract('z0',z0,hdr,ierr) - if (abs(qfacdisc2) <= tiny(qfacdisc2)) then - if (id==master) write(iprint,*) 'ERROR: qfacdisc2 == 0' - ierr = 2 - else - if (id==master) write(iprint,*) 'qfacdisc2 = ',qfacdisc2 - endif - endif - -end subroutine read_headeropts_eos - -!----------------------------------------------------------------------- -!+ -! writes equation of state options to the input file -!+ -!----------------------------------------------------------------------- -subroutine write_options_eos(iunit) - use dim, only:use_krome - use infile_utils, only:write_inopt - use eos_helmholtz, only:eos_helmholtz_write_inopt - use eos_barotropic, only:write_options_eos_barotropic - use eos_piecewise, only:write_options_eos_piecewise - use eos_gasradrec, only:write_options_eos_gasradrec - integer, intent(in) :: iunit - - write(iunit,"(/,a)") '# options controlling equation of state' - call write_inopt(ieos,'ieos','eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)',iunit) - - if (.not.use_krome .or. .not.eos_outputs_mu(ieos)) then - call write_inopt(gmw,'mu','mean molecular weight',iunit) - endif - - select case(ieos) - case(8) - call write_options_eos_barotropic(iunit) - case(9) - call write_options_eos_piecewise(iunit) - case(10) - call write_inopt(X_in,'X','hydrogen mass fraction',iunit) - call write_inopt(Z_in,'Z','metallicity',iunit) - case(15) ! helmholtz eos - call eos_helmholtz_write_inopt(iunit) - case(20) - call write_options_eos_gasradrec(iunit) - if (.not. use_var_comp) then - call write_inopt(X_in,'X','H mass fraction (ignored if variable composition)',iunit) - call write_inopt(Z_in,'Z','metallicity (ignored if variable composition)',iunit) - endif - end select - -end subroutine write_options_eos - -!----------------------------------------------------------------------- -!+ -! reads equation of state options from the input file -!+ -!----------------------------------------------------------------------- -subroutine read_options_eos(name,valstring,imatch,igotall,ierr) - use dim, only:store_dust_temperature,update_muGamma - use io, only:fatal - use eos_barotropic, only:read_options_eos_barotropic - use eos_piecewise, only:read_options_eos_piecewise - use eos_gasradrec, only:read_options_eos_gasradrec - character(len=*), intent(in) :: name,valstring - logical, intent(out) :: imatch,igotall - integer, intent(out) :: ierr - integer, save :: ngot = 0 - character(len=30), parameter :: label = 'read_options_eos' - logical :: igotall_barotropic,igotall_piecewise,igotall_gasradrec - - imatch = .true. - igotall_barotropic = .true. - igotall_piecewise = .true. - igotall_gasradrec = .true. - - select case(trim(name)) - case('ieos') - read(valstring,*,iostat=ierr) ieos - ngot = ngot + 1 - if (ieos <= 0 .or. ieos > maxeos) call fatal(label,'equation of state choice out of range') - if (ieos == 5) then - store_dust_temperature = .true. - update_muGamma = .true. - endif - if (ieos == 21) update_muGamma = .true. - case('mu') - read(valstring,*,iostat=ierr) gmw - ! not compulsory to read in - if (gmw <= 0.) call fatal(label,'mu <= 0') - case('X') - read(valstring,*,iostat=ierr) X_in - if (X_in <= 0. .or. X_in >= 1.) call fatal(label,'X must be between 0 and 1') - ngot = ngot + 1 - case('Z') - read(valstring,*,iostat=ierr) Z_in - if (Z_in <= 0. .or. Z_in > 1.) call fatal(label,'Z must be between 0 and 1') - ngot = ngot + 1 - case default - imatch = .false. - end select - if (.not.imatch .and. ieos== 8) call read_options_eos_barotropic(name,valstring,imatch,igotall_barotropic,ierr) - if (.not.imatch .and. ieos== 9) call read_options_eos_piecewise( name,valstring,imatch,igotall_piecewise, ierr) - if (.not.imatch .and. ieos==20) call read_options_eos_gasradrec( name,valstring,imatch,igotall_gasradrec, ierr) - - !--make sure we have got all compulsory options (otherwise, rewrite input file) - igotall = (ngot >= 1) .and. igotall_piecewise .and. igotall_barotropic .and. igotall_gasradrec - -end subroutine read_options_eos - - -!----------------------------------------------------------------------- - -end module eos diff --git a/src/utils/analysis_getneighbours.f90 b/src/utils/analysis_getneighbours.f90 index fb20606c7..f5fffe2a0 100644 --- a/src/utils/analysis_getneighbours.f90 +++ b/src/utils/analysis_getneighbours.f90 @@ -44,10 +44,10 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! Output neighbour lists to file !************************************** - neighbourfile = 'neigh_'//TRIM(dumpfile) + neighbourfile = 'neigh_'//trim(dumpfile) call write_neighbours(neighbourfile, npart) - print*, 'Neighbour finding complete for file ', TRIM(dumpfile) + print*, 'Neighbour finding complete for file ', trim(dumpfile) end subroutine do_analysis !-------------------------------------------------------------------------- diff --git a/src/utils/analysis_gws.f90 b/src/utils/analysis_gws.f90 index 9be0e4330..70b12ab2b 100644 --- a/src/utils/analysis_gws.f90 +++ b/src/utils/analysis_gws.f90 @@ -87,7 +87,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunitone) ! Write a file where I append all the values of the strain wrt time if (first) then first = .false. - open(unit=iu, file='strain.gw',status='replace') + open(unit=iu,file='strain.gw',status='replace') write(iu,"('#',9(1x,'[',i2.2,1x,a11,']',2x))") & 1, 'time', & 2, 'hx_0', & @@ -99,7 +99,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunitone) 8, 'hx_{90}', & 9, 'hx_{90}' else - open(unit=iu, file='strain.gw',position='append') + open(unit=iu,file='strain.gw',position='append') endif print*, 'time', time @@ -125,7 +125,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunitone) ! Write a file where I append all the values of the strain wrt time if (firstdump) then firstdump = .false. - open(unit=iuu, file='quadrupole.txt',status='replace') + open(unit=iuu,file='quadrupole.txt',status='replace') write(iuu,"('#',6(1x,'[',i2.2,1x,a11,']',2x))") & 1, 'q11', & 2, 'q12', & @@ -134,14 +134,14 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunitone) 5, 'q23', & 6, 'q33' else - open(unit=iuu, file='quadrupole.txt',position='append') + open(unit=iuu,file='quadrupole.txt',position='append') endif write(iuu,'(6(es18.10,1X))') q(1), q(2), q(3), q(4), q(5), q(6) if (firstdumpa) then firstdumpa = .false. - open(unit=iuuu, file='second_time_quadrupole.txt',status='replace') + open(unit=iuuu,file='second_time_quadrupole.txt',status='replace') write(iuuu,"('#',7(1x,'[',i2.2,1x,a11,']',2x))") & 1, 'time',& 2, 'ddq_xy(1,1)', & @@ -151,7 +151,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunitone) 6, 'ddq_xy(2,3)', & 7, 'ddq_xy(3,3)' else - open(unit=iuuu, file='second_time_quadrupole.txt',position='append') + open(unit=iuuu,file='second_time_quadrupole.txt',position='append') endif write(iuuu,'(7(es18.10,1X))') time,ddq_xy(1,1),ddq_xy(1,2),ddq_xy(1,3),ddq_xy(2,2),ddq_xy(2,3),ddq_xy(3,3) diff --git a/src/utils/analysis_kepler.f90 b/src/utils/analysis_kepler.f90 index e6e63d942..e057510cb 100644 --- a/src/utils/analysis_kepler.f90 +++ b/src/utils/analysis_kepler.f90 @@ -641,16 +641,16 @@ subroutine composition_array(interpolate_comp,columns_compo,comp_label) !Save composition read from file. allocate(interpolate_comp(columns_compo,n_rows)) - open(12, file=filename) + open(12,file=filename) ierr = 0 !get column labels and send them back. - read(12, '(a)', iostat=ierr) line + read(12, '(a)',iostat=ierr) line allocate(comp_label(columns_compo)) call get_column_labels(line,n_labels,comp_label) close(12) print*,"comp_label ",comp_label - open(13, file=filename) + open(13,file=filename) call skip_header(13,nheader,ierr) do k = 1, n_rows read(13,*,iostat=ierr) interpolate_comp(:,k) @@ -673,7 +673,7 @@ subroutine assign_atomic_mass_and_number(comp_label,A_array,Z_array) real,allocatable :: A_array(:), Z_array(:) integer :: size_to_allocate, i - if ( ANY( comp_label=="nt1" ) ) then + if ( any( comp_label=="nt1" ) ) then size_to_allocate = size(comp_label(:))-1 else @@ -814,14 +814,14 @@ subroutine write_dump_info(fileno,density,temperature,mass,xpos,rad,distance,pos ! open the file for appending or creating if (file_exists) then - open(unit=file_id, file=filename, status='old', position="append", action="write", iostat=status) + open(unit=file_id,file=filename,status='old', position="append",action="write",iostat=status) if (status /= 0) then write(*,*) 'Error opening file: ', filename stop endif else - open(unit=file_id, file=filename, status='new', action='write', iostat=status) + open(unit=file_id,file=filename,status='new',action='write',iostat=status) if (status /= 0) then write(*,*) 'Error creating file: ', filename stop diff --git a/src/utils/analysis_protostar_environ.F90 b/src/utils/analysis_protostar_environ.F90 index 6ac1dcd41..895d04933 100644 --- a/src/utils/analysis_protostar_environ.F90 +++ b/src/utils/analysis_protostar_environ.F90 @@ -294,7 +294,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) + (xyzmh_ptmass(2,isink)-xyzmh_ptmass(2,j))**2 & + (xyzmh_ptmass(3,isink)-xyzmh_ptmass(3,j))**2 if (rtmp2 < rmerge2) then - write(filelog,'(3a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'.log' + write(filelog,'(3a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'.log' inquire(file=filelog,exist=iexist) if ( firstlog .or. .not.iexist ) then firstlog = .false. @@ -315,13 +315,13 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) write(rval, '(I3.3)') rthreshAU write(csink,'(I3.3)') isink if (isink==0) then - write(fileout1,'(3a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_discRM.dat' - write(fileout2,'(3a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_discRMnx.dat' - write(fileout3,'(5a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_vol',rval,'RM.dat' + write(fileout1,'(3a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_discRM.dat' + write(fileout2,'(3a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_discRMnx.dat' + write(fileout3,'(5a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_vol',rval,'RM.dat' else - write(fileout1,'(5a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_S',csink,'discRM.dat' - write(fileout2,'(5a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_S',csink,'discRMnx.dat' - write(fileout3,'(7a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_S',csink,'vol',rval,'RM.dat' + write(fileout1,'(5a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_S',csink,'discRM.dat' + write(fileout2,'(5a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_S',csink,'discRMnx.dat' + write(fileout3,'(7a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_S',csink,'vol',rval,'RM.dat' endif if ( no_file(isink) ) then open(iunit,file=fileout1,status='replace') @@ -473,7 +473,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! Print the globally averaged eta-values, for particles with rho > rho_crit if (calc_eta) then - write(fileout6,'(3a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_eta.dat' + write(fileout6,'(3a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_eta.dat' if ( no_file(maxptmass+1) ) then open(eunit,file=fileout6,status='replace') call write_header_file6(eunit) @@ -504,9 +504,9 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) call get_mu(npart,nptmass,nmu_global,rmu_global,mu_global,mass_mu_global,B_mu_global, & xyzh,xyzmh_ptmass,Bxyz,particlemass) - write(fileout7,'(3a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_mu.dat' - write(fileout8,'(3a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_mu_mass.dat' - write(fileout9,'(3a)') 'analysisout_',trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_mu_B.dat' + write(fileout7,'(3a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_mu.dat' + write(fileout8,'(3a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_mu_mass.dat' + write(fileout9,'(3a)') 'analysisout_',trim(dumpfile(1:index(dumpfile,'_')-1)),'_mu_B.dat' if ( no_file(maxptmass+1) ) then open(eunit,file=fileout7,status='replace') call write_header_file7(eunit) diff --git a/src/utils/analysis_raytracer.f90 b/src/utils/analysis_raytracer.f90 index 2a8305c9e..f70a7589a 100644 --- a/src/utils/analysis_raytracer.f90 +++ b/src/utils/analysis_raytracer.f90 @@ -229,10 +229,10 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) if (analyses == 2 .and. method==1) then ! get neighbours if (SPH) then - neighbourfile = 'neigh_'//TRIM(dumpfile) + neighbourfile = 'neigh_'//trim(dumpfile) inquire(file=neighbourfile,exist = existneigh) if (existneigh) then - print*, 'SPH neighbour file ', TRIM(neighbourfile), ' found' + print*, 'SPH neighbour file ', trim(neighbourfile), ' found' call read_neighbours(neighbourfile,npart2) else ! If there is no neighbour file, generate the list @@ -243,7 +243,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) totalTime = (finish-start)/1000. print*,'Time = ',totalTime,' seconds.' call write_neighbours(neighbourfile, npart2) - print*, 'Neighbour finding complete for file ', TRIM(dumpfile) + print*, 'Neighbour finding complete for file ', trim(dumpfile) endif else allocate(neighb(npart2+2,100)) @@ -254,7 +254,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) else call execute_command_line('python3 getNeigh.py -f '//'points_'//dumpfile//'.txt') endif - open(newunit=iu4, file='neighbors_tess.txt', status='old', action='read') + open(newunit=iu4,file='neighbors_tess.txt',status='old',action='read') do i=1, npart2+2 read(iu4,*) neighb(i,:) enddo @@ -266,10 +266,10 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! INWARD INTEGRATION ANALYSIS if (method == 1) then - neighbourfile = 'neigh_'//TRIM(dumpfile) + neighbourfile = 'neigh_'//trim(dumpfile) inquire(file=neighbourfile,exist = existneigh) if (existneigh) then - print*, 'SPH neighbour file ', TRIM(neighbourfile), ' found' + print*, 'SPH neighbour file ', trim(neighbourfile), ' found' call read_neighbours(neighbourfile,npart2) else ! If there is no neighbour file, generate the list @@ -280,7 +280,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) totalTime = (finish-start)/1000. print*,'Time = ',totalTime,' seconds.' call write_neighbours(neighbourfile, npart2) - print*, 'Neighbour finding complete for file ', TRIM(dumpfile) + print*, 'Neighbour finding complete for file ', trim(dumpfile) endif print*,'' print*, 'Start calculating optical depth inward SPH' @@ -295,11 +295,11 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu4, file='times_inwards_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu4,file='times_inwards_'//dumpfile//'.txt',status='replace',action='write') write(iu4, *) timeTau close(iu4) totalTime = timeTau - open(newunit=iu2, file='taus_inwards_SPH_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_inwards_SPH_'//dumpfile//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo @@ -313,7 +313,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) else call execute_command_line('python3 getNeigh.py -f '//'points_'//dumpfile//'.txt') endif - open(newunit=iu4, file='neighbors_tess.txt', status='old', action='read') + open(newunit=iu4,file='neighbors_tess.txt',status='old',action='read') do i=1, npart2+2 read(iu4,*) neighb(i,:) enddo @@ -331,18 +331,18 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu4, file='times_inwards_'//dumpfile//'.txt',position='append', status='old', action='write') + open(newunit=iu4,file='times_inwards_'//dumpfile//'.txt',position='append',status='old',action='write') write(iu4, *) timeTau close(iu4) totalTime = timeTau - open(newunit=iu2, file='taus_inwards_Del_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_inwards_Del_'//dumpfile//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo ! OUTWARD INTEGRATION realTIME ANALYSIS elseif (method == 2) then - open(newunit=iu4, file='times_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu4,file='times_'//dumpfile//'.txt',status='replace',action='write') close(iu4) totalTime=0 @@ -361,11 +361,11 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu4, file='times_'//dumpfile//'.txt',position='append', status='old', action='write') + open(newunit=iu4,file='times_'//dumpfile//'.txt',position='append',status='old',action='write') write(iu4, *) timeTau close(iu4) totalTime = totalTime + timeTau - open(newunit=iu2, file='taus_'//dumpfile//'_'//trim(jstring)//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_'//trim(jstring)//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo @@ -376,7 +376,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! OUTWARD INTEGRATION INTERPOLATION ANALYSIS elseif (method == 3) then - open(newunit=iu4, file='times_interpolation_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu4,file='times_interpolation_'//dumpfile//'.txt',status='replace',action='write') close(iu4) totalTime=0 @@ -395,12 +395,12 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu4, file='times_interpolation_'//dumpfile//'.txt',position='append', status='old', action='write') + open(newunit=iu4,file='times_interpolation_'//dumpfile//'.txt',position='append',status='old',action='write') write(iu4, *) timeTau close(iu4) totalTime = totalTime + timeTau - open(newunit=iu2, file='taus_'//dumpfile//'_'//trim(jstring)//'_int_'//trim(kstring)//'.txt', & - status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_'//trim(jstring)//'_int_'//trim(kstring)//'.txt', & + status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo @@ -411,7 +411,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! OUTWARD INTEGRATION INTERPOLATION ANALYSIS elseif (method == 4) then - open(newunit=iu4, file='times_interpolation_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu4,file='times_interpolation_'//dumpfile//'.txt',status='replace',action='write') close(iu4) totalTime=0 @@ -434,14 +434,14 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) print*,'Time = ',timeTau,' seconds.' times(k+1) = timeTau totalTime = totalTime + timeTau - open(newunit=iu2, file='taus_'//dumpfile//'_'//trim(jstring)//'_int_'//trim(kstring)//'.txt', & - status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_'//trim(jstring)//'_int_'//trim(kstring)//'.txt', & + status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo close(iu2) enddo - open(newunit=iu4, file='times_interpolation_'//dumpfile//'.txt',position='append', status='old', action='write') + open(newunit=iu4,file='times_interpolation_'//dumpfile//'.txt',position='append',status='old',action='write') write(iu4, *) times(1:7) close(iu4) enddo @@ -450,7 +450,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) !ADAPTIVE (OUTWARD) INTEGRATION ANALYSIS elseif (method == 5) then - open(newunit=iu4, file='times_adapt_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu4,file='times_adapt_'//dumpfile//'.txt',status='replace',action='write') close(iu4) totalTime=0 @@ -475,14 +475,14 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) print*,'Time = ',timeTau,' seconds.' times(k-minOrder+1) = timeTau totalTime = totalTime + timeTau - open(newunit=iu2, file='taus_'//dumpfile//'_adapt_'//trim(jstring)// & - '_'//trim(kstring)//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_adapt_'//trim(jstring)// & + '_'//trim(kstring)//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo close(iu2) enddo - open(newunit=iu4, file='times_adapt_'//dumpfile//'.txt',position='append', status='old', action='write') + open(newunit=iu4,file='times_adapt_'//dumpfile//'.txt',position='append',status='old',action='write') write(iu4, *) times(1:maxOrder-minOrder+1) close(iu4) enddo @@ -493,7 +493,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) elseif (method == 6) then order = 5 print*,'Start doing scaling analysis with order =',order - open(newunit=iu4, file='times_'//dumpfile//'_scaling.txt', status='replace', action='write') + open(newunit=iu4,file='times_'//dumpfile//'_scaling.txt',status='replace',action='write') close(iu4) do i=1, omp_get_max_threads() call omp_set_num_threads(i) @@ -511,7 +511,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'nthread = ',omp_get_max_threads(),': Time = ',timeTau,' seconds.' - open(newunit=iu4, file='times_'//dumpfile//'_scaling.txt',position='append', status='old', action='write') + open(newunit=iu4,file='times_'//dumpfile//'_scaling.txt',position='append',status='old',action='write') write(iu4, *) omp_get_max_threads(), timeTau close(iu4) enddo @@ -531,14 +531,14 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu1, file='npart_wind.txt',position='append', action='write') + open(newunit=iu1,file='npart_wind.txt',position='append',action='write') write(iu1, *) npart2 close(iu1) - open(newunit=iu4, file='times_wind.txt',position='append', action='write') + open(newunit=iu4,file='times_wind.txt',position='append',action='write') write(iu4, *) timeTau close(iu4) totalTime = totalTime + timeTau - open(newunit=iu2, file='taus_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo @@ -562,9 +562,9 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' if (SPH) then - open(newunit=iu2, file='taus_'//dumpfile//'_inwards.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_inwards.txt',status='replace',action='write') else - open(newunit=iu2, file='taus_'//dumpfile//'_tess_inwards.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_tess_inwards.txt',status='replace',action='write') endif do i=1, size(tau) write(iu2, *) tau(i) @@ -584,7 +584,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu2, file='taus_'//dumpfile//'_'//trim(jstring)//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_'//trim(jstring)//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo @@ -603,7 +603,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu2, file='taus_'//dumpfile//'_'//trim(jstring)//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_'//trim(jstring)//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo @@ -623,8 +623,8 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' totalTime = totalTime + timeTau - open(newunit=iu2, file='taus_'//dumpfile//'_adapt_'//trim(jstring)// & - '_'//trim(kstring)//'.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_adapt_'//trim(jstring)// & + '_'//trim(kstring)//'.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo @@ -646,7 +646,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' - open(newunit=iu4, file='taus_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu4,file='taus_'//dumpfile//'.txt',status='replace',action='write') do i=1, size(tau) write(iu4, *) tau(i) enddo @@ -660,7 +660,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) enddo ! allocate(neighb(npart2+2,100)) ! neighb = 0 - ! open(newunit=iu4, file='neighbors_tess.txt', status='old', action='read') + ! open(newunit=iu4,file='neighbors_tess.txt',status='old',action='read') ! do i=1, npart2+2 ! read(iu4,*) neighb(i,:) ! enddo @@ -674,20 +674,20 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) timeTau = (finish-start)/1000. print*,'Time = ',timeTau,' seconds.' totalTime = totalTime + timeTau - open(newunit=iu2, file='taus_'//dumpfile//'_raypolation_7.txt', status='replace', action='write') + open(newunit=iu2,file='taus_'//dumpfile//'_raypolation_7.txt',status='replace',action='write') do i=1, size(tau) write(iu2, *) tau(i) enddo close(iu2) elseif (analyses == 5) then - open(newunit=iu1, file='points_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu1,file='points_'//dumpfile//'.txt',status='replace',action='write') do i=1, npart2+2 write(iu1, *) xyzh2(1:3,i) enddo close(iu1) - open(newunit=iu3, file='rho_'//dumpfile//'.txt', status='replace', action='write') + open(newunit=iu3,file='rho_'//dumpfile//'.txt',status='replace',action='write') do i=1,npart2 rho(i) = rhoh(xyzh2(4,i), particlemass) write(iu3, *) rho(i) diff --git a/src/utils/analysis_sphere.f90 b/src/utils/analysis_sphere.f90 index 837a5257a..a74eab303 100644 --- a/src/utils/analysis_sphere.f90 +++ b/src/utils/analysis_sphere.f90 @@ -222,7 +222,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) enddo close(iunit) - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_AM.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_AM.dat' inquire(file=fileout,exist=iexist) if ( .not.iexist .or. firstcall ) then firstcall = .false. diff --git a/src/utils/analysis_velocitydispersion_vs_scale.f90 b/src/utils/analysis_velocitydispersion_vs_scale.f90 index 7bd2daa9d..ec46ee0b6 100644 --- a/src/utils/analysis_velocitydispersion_vs_scale.f90 +++ b/src/utils/analysis_velocitydispersion_vs_scale.f90 @@ -96,11 +96,11 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) ! Check if a neighbour file is present - neighbourfile = 'neigh_'//TRIM(dumpfile) + neighbourfile = 'neigh_'//trim(dumpfile) inquire(file=neighbourfile,exist = existneigh) if (existneigh.eqv..true.) then - print*, 'Neighbour file ', TRIM(neighbourfile), ' found' + print*, 'Neighbour file ', trim(neighbourfile), ' found' call read_neighbours(neighbourfile,npart) else @@ -358,7 +358,7 @@ subroutine read_analysis_options print '(a,a,a)', "Parameter file ",inputfile, " found: reading analysis options" - open(10,file=inputfile, form='formatted') + open(10,file=inputfile,form='formatted') read(10,*) nscale read(10,*) rscalemin read(10,*) rscalemax @@ -376,7 +376,7 @@ subroutine read_analysis_options ! Write choices to new inputfile - open(10,file=inputfile, status='new', form='formatted') + open(10,file=inputfile,status='new',form='formatted') write(10,*) nscale, " Number of scale evaluations" write(10,*) rscalemin, " Minimum scale (code units)" write(10,*) rscalemax, " Maximum scale (code units)" diff --git a/src/utils/einsteintk_wrapper.f90 b/src/utils/einsteintk_wrapper.f90 index 8bd6b847b..28580cd41 100644 --- a/src/utils/einsteintk_wrapper.f90 +++ b/src/utils/einsteintk_wrapper.f90 @@ -29,37 +29,16 @@ subroutine init_et2phantom(infilestart,dt_et,nophantompart,dtout) use io, only:id,master,nprocs,set_io_unit_numbers,die use mpiutils, only:init_mpi,finalise_mpi use initial, only:initialise,finalise,startrun,endrun - !use evolve, only:evol_init use tmunu2grid use einsteintk_utils use extern_gr use metric - use part, only:npart!, tmunus - - + use part, only:npart implicit none character(len=*), intent(in) :: infilestart real, intent(in) :: dt_et integer, intent(inout) :: nophantompart real, intent(out) :: dtout - !character(len=500) :: logfile,evfile,dumpfile,path - !integer :: i,j,k,pathstringlength - - ! For now we just hardcode the infile, to see if startrun actually works! - ! I'm not sure what the best way to actually do this is? - ! Do we store the phantom.in file in par and have it read from there? - !infile = "/Users/spencer/phantomET/phantom/test/flrw.in" - !infile = trim(infile)//'.in' - !print*, "phantom_path: ", phantom_path - !infile = phantom_path // "flrw.in" - !infile = trim(path) // "flrw.in" - !infile = 'flrw.in' - !infile = trim(infile) - !print*, "Phantom path is: ", path - !print*, "Infile is: ", infile - ! Use system call to copy phantom files to simulation directory - ! This is a digusting temporary fix - !call SYSTEM('cp ~/phantomET/phantom/test/flrw* ./') ! The infile from ET infilestor = infilestart @@ -72,26 +51,11 @@ subroutine init_et2phantom(infilestart,dt_et,nophantompart,dtout) ! setup io call set_io_unit_numbers ! routine that starts a phantom run - print*, "Start run called!" - ! Do we want to pass dt in here?? call startrun(infilestor,logfilestor,evfilestor,dumpfilestor) - print*, "Start run finished!" - !print*, "tmunugrid: ", tmunugrid(1,1,6,6,6) - !stop - ! Intialises values for the evol routine: t, dt, etc.. - !call evol_init(infilestor,logfilestor,evfilestor,dumpfilestor,dt_et,nophantompart) - !print*, "Evolve init finished!" + nophantompart = npart - ! Calculate the stress energy tensor for each particle - ! Might be better to do this in evolve init - !call get_tmunugrid_all - ! Calculate the stress energy tensor + call get_metricderivs_all(dtout,dt_et) ! commented out to try and fix prim2cons - !call get_tmunu_all(npart,xyzh,metrics,vxyzu,metricderivs,dens,tmunus) ! commented out to try and fix prim2cons - !call get_tmunu_all_exact(npart,xyzh,metrics,vxyzu,metricderivs,dens,tmunus) - ! Interpolate stress energy tensor from particles back - ! to grid - !call get_tmunugrid_all(npart,xyzh,vxyzu,tmunus,calc_cfac=.true.) ! commented out to try and fix cons2prim call get_phantom_dt(dtout) @@ -122,29 +86,6 @@ subroutine et2phantom(rho,nx,ny,nz) ! send grid limits end subroutine et2phantom - ! DONT THINK THIS IS USED ANYWHERE!!! - ! subroutine step_et2phantom(infile,dt_et) - ! use einsteintk_utils - ! use evolve, only:evol_step - ! use tmunu2grid - ! character(len=*), intent(in) :: infile - ! real, intent(inout) :: dt_et - ! character(len=500) :: logfile,evfile,dumpfile,path - - - ! ! Print the values of logfile, evfile, dumpfile to check they are sensible - ! !print*, "logfile, evfile, dumpfile: ", logfile, evfile, dumpfile - ! print*, "stored values of logfile, evfile, dumpfile: ", logfilestor, evfilestor, dumpfilestor - - ! ! Interpolation stuff - ! ! Call et2phantom (construct global grid, metric, metric derivs, determinant) - ! ! Run phantom for a step - ! call evol_step(infile,logfilestor,evfilestor,dumpfilestor,dt_et) - ! ! Interpolation stuff back to et - ! !call get_tmunugrid_all() - ! ! call phantom2et (Tmunu_grid) - - ! end subroutine step_et2phantom subroutine phantom2et() ! should take in the cctk_array for tmunu?? @@ -190,7 +131,6 @@ subroutine step_et2phantom_MoL(infile,dt_et,dtout) ! to grid call get_phantom_dt(dtout) - end subroutine step_et2phantom_MoL subroutine et2phantom_tmunu() @@ -208,7 +148,7 @@ subroutine et2phantom_tmunu() use linklist, only:set_linklist real :: stressmax - real(kind=16) :: cfac + real :: cfac stressmax = 0. @@ -237,15 +177,13 @@ subroutine et2phantom_tmunu() call check_conserved_dens(rhostargrid,cfac) ! Correct Tmunu - ! Convert to 8byte real to stop compiler warning - tmunugrid = real(cfac)*tmunugrid - + tmunugrid = cfac*tmunugrid end subroutine et2phantom_tmunu subroutine phantom2et_consvar() - use part, only:npart,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& - Bevol,rad,radprop,metrics,igas,rhoh,alphaind,dvdx,gradh + use part, only:npart,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& + Bevol,rad,radprop,metrics,igas,rhoh,alphaind,dvdx,gradh use densityforce, only:densityiterate use metric_tools, only:init_metric use linklist, only:set_linklist @@ -253,7 +191,7 @@ subroutine phantom2et_consvar() use tmunu2grid, only:check_conserved_dens real :: stressmax - real(kind=16) :: cfac + real :: cfac ! Init metric call init_metric(npart,xyzh,metrics) @@ -276,7 +214,6 @@ subroutine phantom2et_consvar() ! Interpolate entropy to grid call phantom2et_entropy - ! Conserved quantity checks + corrections ! Density check vs particles @@ -285,12 +222,9 @@ subroutine phantom2et_consvar() ! Momentum check vs particles ! Correct momentum and Density - ! Conversion of cfac to 8byte real to avoid - ! compiler warning - rhostargrid = real(cfac)*rhostargrid - pxgrid = real(cfac)*pxgrid - entropygrid = real(cfac)*entropygrid - + rhostargrid = cfac*rhostargrid + pxgrid = cfac*pxgrid + entropygrid = cfac*entropygrid end subroutine phantom2et_consvar @@ -320,9 +254,9 @@ subroutine phantom2et_rhostar() ! Get the conserved density on the particles dat = 0. pmass = massoftype(igas) - ! $omp parallel do default(none) & - ! $omp shared(npart,xyzh,dat,pmass) & - ! $omp private(i,h,rho) + !$omp parallel do default(none) & + !$omp shared(npart,xyzh,dat,pmass) & + !$omp private(i,h,rho) do i=1, npart ! Get the smoothing length h = xyzh(4,i) @@ -331,7 +265,7 @@ subroutine phantom2et_rhostar() rho = rhoh(h,pmass) dat(i) = rho enddo - ! $omp end parallel do + !$omp end parallel do rhostargrid = 0. call interpolate_to_grid(rhostargrid,dat) @@ -348,7 +282,6 @@ subroutine phantom2et_entropy() real :: dat(npart) integer :: i - ! Get new cons density from new particle positions somehow (maybe)? ! Set linklist to update the tree for neighbour finding ! Calculate the density for the new particle positions @@ -385,7 +318,6 @@ subroutine phantom2et_momentum() real :: dat(3,npart) integer :: i - ! Pi is directly updated at the end of each MoL add ! Interpolate from particles to grid @@ -410,12 +342,8 @@ subroutine phantom2et_momentum() ! pz component call interpolate_to_grid(pxgrid(3,:,:,:),dat(3,:)) - - end subroutine phantom2et_momentum - - ! Subroutine for performing a phantom dump from einstein toolkit subroutine et2phantom_dumphydro(time,dt_et,checkpointfile) use einsteintk_utils @@ -424,9 +352,6 @@ subroutine et2phantom_dumphydro(time,dt_et,checkpointfile) use fileutils, only:getnextfilename use tmunu2grid, only:check_conserved_dens real, intent(in) :: time, dt_et - !real(kind=16) :: cfac - !logical, intent(in), optional :: checkpoint - !integer, intent(in) :: checkpointno character(*),optional, intent(in) :: checkpointfile logical :: createcheckpoint @@ -451,15 +376,6 @@ subroutine et2phantom_dumphydro(time,dt_et,checkpointfile) call write_fulldump(time,checkpointfile) endif - ! Quick and dirty write cfac to txtfile - - ! Density check vs particles -! call check_conserved_dens(rhostargrid,cfac) -! open(unit=777, file="cfac.txt", action='write', position='append') -! print*, time, cfac -! write(777,*) time, cfac -! close(unit=777) - end subroutine et2phantom_dumphydro ! Provides the RHS derivs for a particle at index i @@ -506,7 +422,7 @@ subroutine get_metricderivs_all(dtextforce_min,dt_et) dtextforce_min = bignumber !$omp parallel do default(none) & - !$omp shared(npart, xyzh,metrics,metricderivs,vxyzu,dens,C_force,fext) & + !$omp shared(npart,xyzh,metrics,metricderivs,vxyzu,dens,C_force,fext) & !$omp firstprivate(pri) & !$omp private(i,dtf) & !$omp reduction(min:dtextforce_min) @@ -517,26 +433,18 @@ subroutine get_metricderivs_all(dtextforce_min,dt_et) dtextforce_min = min(dtextforce_min,C_force*dtf) enddo !$omp end parallel do - ! manually add v contribution from gr - ! do i=1, npart - ! !fxyzu(:,i) = fxyzu(:,i) + fext(:,i) - ! vxyzu(1:3,i) = vxyzu(1:3,i) + fext(:,i)*dt_et - ! enddo + end subroutine get_metricderivs_all subroutine get_eos_quantities(densi,en) use cons2prim, only:cons2primall - use part, only:dens,vxyzu,npart,metrics,xyzh,pxyzu,eos_vars + use part, only:dens,vxyzu,npart,metrics,xyzh,pxyzu,eos_vars real, intent(out) :: densi,en - !call h2dens(densi,xyzhi,metrici,vi) ! Compute dens from h - densi = dens(1) ! Feed the newly computed dens back out of the routine - !call cons2primall(npart,xyzh,metrics,vxyzu,dens,pxyzu,.true.) + densi = dens(1) ! Feed the newly computed dens back out of the routine call cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) - ! print*,"pxyzu: ",pxyzu(:,1) - ! print*, "vxyzu: ",vxyzu(:,1) en = vxyzu(4,1) -end subroutine get_eos_quantities +end subroutine get_eos_quantities end module einsteintk_wrapper diff --git a/src/utils/interpolate3D.f90 b/src/utils/interpolate3D.f90 index 95fe2d7d6..3b9e849f5 100644 --- a/src/utils/interpolate3D.f90 +++ b/src/utils/interpolate3D.f90 @@ -85,7 +85,7 @@ subroutine interpolate3D(xyzh,weight,dat,itype,npart,& !logical, parameter :: exact_rendering = .true. ! use exact rendering y/n integer :: usedpart, negflag -!$ integer :: omp_get_num_threads,omp_get_thread_num +!$ integer, external :: omp_get_num_threads,omp_get_thread_num integer(kind=selected_int_kind(10)) :: iprogress,j ! up to 10 digits ! Fill the particle data with xyzh @@ -425,7 +425,7 @@ subroutine interpolate3D_vecexact(xyzh,weight,dat,ilendat,itype,npart,& integer :: usedpart, negflag -!$ integer :: omp_get_num_threads,omp_get_thread_num +!$ integer, external :: omp_get_num_threads,omp_get_thread_num integer(kind=selected_int_kind(10)) :: iprogress,j ! up to 10 digits ! Fill the particle data with xyzh diff --git a/src/utils/io_structurefn.f90 b/src/utils/io_structurefn.f90 index ca736c360..00af14e20 100644 --- a/src/utils/io_structurefn.f90 +++ b/src/utils/io_structurefn.f90 @@ -242,7 +242,7 @@ subroutine openw_sf (file,origin,n_lag,lag,n_order,n_rho_power) real, intent(in) :: lag(n_lag) namelist /structurefn/n_lag,n_order,n_rho_power,origin ! - open (power_unit,file=trim(file),status='unknown',form='formatted') ! open unit + open(power_unit,file=trim(file),status='unknown',form='formatted') ! open unit write (power_unit,structurefn) ! dimensions info write (power_unit,'(1x,8g15.7)') lag ! lag vector end subroutine openw_sf diff --git a/src/utils/moddump_growthtomultigrain.f90 b/src/utils/moddump_growthtomultigrain.f90 index 0c5e599df..bcc8ab7c4 100644 --- a/src/utils/moddump_growthtomultigrain.f90 +++ b/src/utils/moddump_growthtomultigrain.f90 @@ -62,7 +62,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) call prompt('Enter number of bins per dex',bins_per_dex,1) else !- file created by phantom/scripts/growthtomcfost.py module - open (unit=420, file=infile) + open(unit=420,file=infile) read(420,*) force_smax, smax_user, bins_per_dex close(unit=420) endif diff --git a/src/utils/moddump_removeparticles_radius.f90 b/src/utils/moddump_removeparticles_radius.f90 index d9bbd3e94..65bad1b90 100644 --- a/src/utils/moddump_removeparticles_radius.f90 +++ b/src/utils/moddump_removeparticles_radius.f90 @@ -42,13 +42,13 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) call prompt('Deleting particles inside a given radius ?',icutinside) call prompt('Deleting particles outside a given radius ?',icutoutside) if (icutinside) then - call prompt('Enter inward radius in au',inradius,0.) + call prompt('Enter inward radius in code units',inradius,0.) call prompt('Enter x coordinate of the center of that sphere',incenter(1)) call prompt('Enter y coordinate of the center of that sphere',incenter(2)) call prompt('Enter z coordinate of the center of that sphere',incenter(3)) endif if (icutoutside) then - call prompt('Enter outward radius in au',outradius,0.) + call prompt('Enter outward radius in code units',outradius,0.) call prompt('Enter x coordinate of the center of that sphere',outcenter(1)) call prompt('Enter y coordinate of the center of that sphere',outcenter(2)) call prompt('Enter z coordinate of the center of that sphere',outcenter(3)) diff --git a/src/utils/moddump_sink.f90 b/src/utils/moddump_sink.f90 index 444a45e22..01c4c3506 100644 --- a/src/utils/moddump_sink.f90 +++ b/src/utils/moddump_sink.f90 @@ -30,12 +30,12 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) real, intent(inout) :: xyzh(:,:),vxyzu(:,:),massoftype(:) integer :: i,isinkpart real :: racc,hsoft,mass,mass_old,newx,Lnuc_cgs - logical :: iresetCM + logical :: reset_CM,delete_sink print*,'Sink particles in dump:' do i=1,nptmass print "(a,1x,i4,a)",'Sink',i,':' - print "(7(a5,1x,a,1x,f13.7,/))",& + print "(7(a5,1x,a,1x,es24.16e3,/))",& 'x','=',xyzmh_ptmass(1,i),& 'y','=',xyzmh_ptmass(2,i),& 'z','=',xyzmh_ptmass(3,i),& @@ -54,39 +54,51 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) call prompt('Enter the sink particle number to modify (0 to exit):',isinkpart,0,nptmass) if (isinkpart <= 0) exit - mass = xyzmh_ptmass(4,isinkpart) - mass_old = mass - call prompt('Enter new mass for the sink:',mass,0.) - print*,'Mass changed to ',mass - xyzmh_ptmass(4,isinkpart) = mass + call prompt('Delete sink?',delete_sink,.false.) + if (delete_sink) then + if (isinkpart==nptmass) then + xyzmh_ptmass(:,isinkpart) = 0. + vxyz_ptmass(:,isinkpart) = 0. + else + xyzmh_ptmass(:,isinkpart:nptmass-1) = xyzmh_ptmass(:,isinkpart+1:nptmass) + vxyz_ptmass(:,isinkpart:nptmass-1) = vxyz_ptmass(:,isinkpart+1:nptmass) + endif + nptmass = nptmass - 1 + else + mass = xyzmh_ptmass(4,isinkpart) + mass_old = mass + call prompt('Enter new mass for the sink:',mass,0.) + print*,'Mass changed to ',mass + xyzmh_ptmass(4,isinkpart) = mass - racc = xyzmh_ptmass(ihacc,isinkpart) - ! rescaling accretion radius for updated mass - racc = racc * (mass/mass_old)**(1./3) - call prompt('Enter new accretion radius for the sink:',racc,0.) - print*,'Accretion radius changed to ',racc - xyzmh_ptmass(ihacc,isinkpart) = racc + racc = xyzmh_ptmass(ihacc,isinkpart) + ! rescaling accretion radius for updated mass + racc = racc * (mass/mass_old)**(1./3) + call prompt('Enter new accretion radius for the sink:',racc,0.) + print*,'Accretion radius changed to ',racc + xyzmh_ptmass(ihacc,isinkpart) = racc - hsoft = xyzmh_ptmass(ihsoft,isinkpart) - call prompt('Enter new softening length for the sink:',hsoft,0.) - print*,'Softening length changed to ',hsoft - xyzmh_ptmass(ihsoft,isinkpart) = hsoft + hsoft = xyzmh_ptmass(ihsoft,isinkpart) + call prompt('Enter new softening length for the sink:',hsoft,0.) + print*,'Softening length changed to ',hsoft + xyzmh_ptmass(ihsoft,isinkpart) = hsoft - newx = xyzmh_ptmass(1,isinkpart) - call prompt('Enter new x-coordinate for the sink in code units:',newx,0.) - xyzmh_ptmass(1,isinkpart) = newx - print*,'x-coordinate changed to ',xyzmh_ptmass(1,isinkpart) + newx = xyzmh_ptmass(1,isinkpart) + call prompt('Enter new x-coordinate for the sink in code units:',newx,0.) + xyzmh_ptmass(1,isinkpart) = newx + print*,'x-coordinate changed to ',xyzmh_ptmass(1,isinkpart) - Lnuc = xyzmh_ptmass(ilum,isinkpart) - Lnuc_cgs = Lnuc * unit_energ / utime - call prompt('Enter new sink heating luminosity in erg/s:',Lnuc_cgs,0.) - xyzmh_ptmass(ilum,isinkpart) = Lnuc_cgs / unit_energ * utime - print*,'Luminosity [erg/s] changed to ',xyzmh_ptmass(ilum,isinkpart) * unit_energ / utime + Lnuc = xyzmh_ptmass(ilum,isinkpart) + Lnuc_cgs = Lnuc * unit_energ / utime + call prompt('Enter new sink heating luminosity in erg/s:',Lnuc_cgs,0.) + xyzmh_ptmass(ilum,isinkpart) = Lnuc_cgs / unit_energ * utime + print*,'Luminosity [erg/s] changed to ',xyzmh_ptmass(ilum,isinkpart) * unit_energ / utime + endif enddo - iresetCM = .false. - call prompt('Reset centre of mass?',iresetCM) - if (iresetCM) call reset_centreofmass(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass) + reset_CM = .false. + call prompt('Reset centre of mass?',reset_CM) + if (reset_CM) call reset_centreofmass(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass) return end subroutine modify_dump diff --git a/src/utils/powerspectrums.f90 b/src/utils/powerspectrums.f90 index 0ffd56515..de772a8b6 100644 --- a/src/utils/powerspectrums.f90 +++ b/src/utils/powerspectrums.f90 @@ -89,7 +89,7 @@ subroutine power_fourier(npts,x,dat,omega,power) sum1 = sum1 + dat(i)*cos(-omega*x(i)) sum2 = sum2 + dat(i)*sin(-omega*x(i)) enddo - power= sqrt(sum1**2 + sum2**2)/REAL(npts) + power= sqrt(sum1**2 + sum2**2)/real(npts) return end subroutine power_fourier diff --git a/src/utils/prompting.f90 b/src/utils/prompting.f90 index c87e5f77c..b68033c5f 100644 --- a/src/utils/prompting.f90 +++ b/src/utils/prompting.f90 @@ -104,7 +104,7 @@ module prompting ! 06/05/11: D. Price: ! Added prompt for integer arrays ! - + implicit none private ! @@ -492,7 +492,7 @@ recursive subroutine string_prompt(text, string, length, case, noblank, list) integer, optional, intent(out) :: length integer, optional, intent(in) :: case logical, optional, intent(in) :: noblank - integer :: is, ia + integer :: is,ia,i integer, parameter :: aoffset = 32 logical :: allowblank,inlist character(len=*), intent(in), optional :: list(:) diff --git a/src/utils/struct_part.f90 b/src/utils/struct_part.f90 new file mode 100644 index 000000000..781a3c2fd --- /dev/null +++ b/src/utils/struct_part.f90 @@ -0,0 +1,269 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module structurefn_part +! +! module for obtaining structure functions +! direct from SPH particles +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: random, timing +! + implicit none + +contains + +subroutine get_structure_fn(sf,nbins,norder,distmin,distmax,xbins,ncount,npart,xyz,vel,& + rho,dxbox,dybox,dzbox,massweighted,ierr) + !use fastmath, only:finvsqrt + use timing, only:get_timings,print_time + use random, only:ran2 + integer, intent(in) :: npart,nbins,norder + real, intent(in) :: xyz(:,:) + real, intent(in) :: vel(:,:) + real, intent(in) :: rho(:) + real(kind=8), intent(out) :: sf(2,norder,nbins) + real, intent(out) :: xbins(nbins) + integer(kind=8), intent(out) :: ncount(nbins) + real, intent(in) :: distmax,distmin + real, intent(in) :: dxbox,dybox,dzbox + logical, intent(in) :: massweighted + integer, intent(out) :: ierr + + real(kind=8) :: sfprev(2,norder,nbins) + integer, allocatable :: list(:) + integer :: i,iran,ipart,ipt,iorder,ibin,iseed,npts,isf,nptstot,its + real :: err(norder),sfmax(norder) + real :: xpt(3),velpt(3) + real :: dxbin,dvx,dvy,dvz,dx,dy,dz,rij1,rij + real(kind=4) :: t1,t2,tcpu1,tcpu2 + real :: rij2,distmin2,ddxbin,minusdistminddxbin + real :: dvdotr,dvterm,dvtrans,rhomax,errtot,temp + real(kind=8) :: dvdotrterm,dvtransterm +!$ integer :: omp_get_num_threads + logical :: converged +! +!--set up the distance bins (linear) +! + dxbin = (distmax-distmin)/float(nbins-1) + do ibin=1,nbins + xbins(ibin) = distmin + (ibin-0.5)*dxbin + enddo + distmin2 = distmin*distmin + ddxbin = 1./dxbin + minusdistminddxbin = -distmin*ddxbin + ierr = 0 +! +!--set structure functions to zero +! + sf(:,:,:) = 0. + sfprev(:,:,:) = 0. + ncount(:) = 0 + iseed = -128 + npts = min(128,npart) + nptstot = 0 + its = 0 +! +!--start with a low number of points, and we keep adding more +! points until the structure function calculation is converged +! + converged = .false. + !$omp parallel + !$omp master +!$ print*,' Using ',omp_get_num_threads(),' cpus' + !$omp end master + !$omp end parallel + + iterations: do while(nptstot <= npart .and. .not.converged) + + its = its + 1 + nptstot = nptstot + npts + print "(a,i2,2(a,i10),a)",' Iteration ',its,': adding ',npts,' sample particles (',nptstot,' in total)' + if (allocated(list)) deallocate(list) + allocate(list(npts),stat=ierr) + if (ierr /= 0) then + print*,' error: cannot allocate memory for ',npts,' sample particles ' + sf = sfprev + return + endif + print*,' iseed = ',iseed,' ncount(1:10) = ',ncount(1:10) + + ! + !--choose a random selection of npts particles + ! + if (massweighted) then + ! + !--select particles randomly according to particle id + ! (this preferentially selects particles in dense regions) + ! + do ipt=1,npts + iran = int(ran2(iseed)*npart) + 1 + list(ipt) = iran + enddo + else + ! + !--alternatively, select particles but weight selection by + ! the volume element m/rho, i.e., inversely proportional to rho + ! + rhomax = 0. + !$omp parallel do schedule(static) private(i) reduction(max:rhomax) + do i=1,npart + rhomax = max(rho(i),rhomax) + enddo + if (rhomax <= 0.) then + print*,' ERROR: max density on particles <= 0' + print*,' cannot use volume element weighting for structure fns' + return + endif + ipt = 0 + write(*,"(2x,a,i8,a)",ADVANCE='NO') 'choosing ',npts,' volume-weighted points...' + do while(ipt < npts) +!--first random number chooses the particle + iran = int(ran2(iseed)*npart) + 1 +!--then select particle if rho/rhomax (0..1) is less than +! a second random number + if (rho(iran)/rhomax < ran2(iseed)) then + ipt = ipt + 1 + list(ipt) = iran + endif + enddo + print*,' done' + endif + + call get_timings(t1,tcpu1) + !$omp parallel do schedule(runtime) default(none) & + !$omp shared(npts,xyz,vel,list,npart,tcpu1) & + !$omp firstprivate(distmin2,dxbox,dybox,dzbox,ddxbin,norder,minusdistminddxbin) & + !$omp private(ipt,xpt,velpt,dx,dy,dz,rij2,rij1,rij,dvdotr) & + !$omp private(i,dvx,dvy,dvz,tcpu2) & + !$omp private(dvterm,dvtrans,dvdotrterm,dvtransterm,ibin) & + !$omp reduction(+:ncount) & + !$omp reduction(+:sf) + do ipt=1,npts +!$ if (.false.) then + if (mod(ipt,100)==0) then + call cpu_time(tcpu2) + print*,' ipt = ',ipt,tcpu2-tcpu1 + endif +!$ endif + i = list(ipt) + xpt(1) = xyz(1,i) + xpt(2) = xyz(2,i) + xpt(3) = xyz(3,i) + velpt(1) = vel(1,i) + velpt(2) = vel(2,i) + velpt(3) = vel(3,i) + + do ipart=1,npart + dx = xyz(1,ipart) - xpt(1) + dy = xyz(2,ipart) - xpt(2) + dz = xyz(3,ipart) - xpt(3) + !--mod distances with periodic boundary + if (abs(dx) > 0.5*dxbox) dx = dx - dxbox*sign(1.0,dx) + if (abs(dy) > 0.5*dybox) dy = dy - dybox*sign(1.0,dy) + if (abs(dz) > 0.5*dzbox) dz = dz - dzbox*sign(1.0,dz) + + rij2 = dx*dx + dy*dy + dz*dz +! +!--work out which distance bin this pair lies in +! exclude pairs which lie closer than the minimum +! separation bin +! + if (rij2 > distmin2) then + dvx = vel(1,ipart) - velpt(1) + dvy = vel(2,ipart) - velpt(2) + dvz = vel(3,ipart) - velpt(3) + + ! rij1 = finvsqrt(rij2) + rij1 = 1./sqrt(rij2) + + dvdotr = abs((dvx*dx + dvy*dy + dvz*dz)*rij1) + dvterm = (dvx*dvx + dvy*dvy + dvz*dvz) - dvdotr*dvdotr + if (dvterm < 0.) dvterm = 0. + dvtrans = sqrt(dvterm) + + rij = 1./rij1 + ibin = int(rij*ddxbin + minusdistminddxbin) + 1 + !if (ibin < 1 .or. ibin > nbins) stop 'ibin out of range' + + dvdotrterm = 1.0d0 + dvtransterm = 1.0d0 + do iorder=1,norder + dvdotrterm = dvdotrterm*dvdotr ! dvdotrterm = dvdotr**iorder + dvtransterm = dvtransterm*dvtrans ! dvtransterm = dvtrans**iorder + + sf(1,iorder,ibin) = sf(1,iorder,ibin) + dvdotrterm + sf(2,iorder,ibin) = sf(2,iorder,ibin) + dvtransterm + enddo + ncount(ibin) = ncount(ibin) + 1_8 + endif + enddo + enddo + !$omp end parallel do + call get_timings(t2,tcpu2) + call print_time(t2-t1,' wall time :') + call print_time(tcpu2-tcpu1,' cpu time :') + + err(:) = 0. + sfmax(:) = 0. + !$omp parallel do schedule(runtime) private(ibin) & + !$omp reduction(+:err) & + !$omp reduction(max:sfmax) + do ibin=1,nbins + if (ncount(ibin) > 0) then + do iorder=1,norder + do isf=1,2 + temp = sf(isf,iorder,ibin)/real(ncount(ibin)) + err(iorder) = err(iorder) + (temp - sfprev(isf,iorder,ibin))**2 + sfmax(iorder) = max(sfmax(iorder),temp) + sfprev(isf,iorder,ibin) = temp + enddo + enddo + else + sfprev(:,:,ibin) = 0. + endif + enddo + !$omp end parallel do + + errtot = 0. + do iorder=1,norder + if (sfmax(iorder) > 0.) then + err(iorder) = err(iorder)/sfmax(iorder)**2/real(nbins*2) + endif + errtot = errtot + err(iorder) + print*,' Error in structure function of order ',iorder,' = ',sqrt(err(iorder)) + enddo + errtot = sqrt(errtot/real(norder)) + print*,' mean square error = ',errtot + converged = maxval(sqrt(err(1:norder))) < 1.e-2 .and. errtot < 1.e-2 + npts = min(nptstot,npart-nptstot) + + ! + !--write the iterations to file (debugging only) + ! + !do i=1,nbins + ! write(10+its,*) xbins(i),(sfprev(1,iorder,i),iorder=1,norder) + !enddo + + enddo iterations + + print*,' Converged!' + + !$omp parallel do schedule(static) private(ibin) + do ibin=1,nbins + sf(:,:,ibin) = sfprev(:,:,ibin) + enddo + + if (allocated(list)) deallocate(list) + +end subroutine get_structure_fn + +end module structurefn_part diff --git a/src/utils/utils_getneighbours.F90 b/src/utils/utils_getneighbours.F90 index 0e889d282..d63d33e1c 100644 --- a/src/utils/utils_getneighbours.F90 +++ b/src/utils/utils_getneighbours.F90 @@ -183,9 +183,9 @@ subroutine generate_neighbour_lists(xyzh,vxyzu,npart,dumpfile,write_neighbour_li ! 3. Output neighbour lists to file (if requested; these files can become very big) !************************************** if (write_neighbour_list) then - neighbourfile = 'neigh_'//TRIM(dumpfile) + neighbourfile = 'neigh_'//trim(dumpfile) call write_neighbours(neighbourfile, npart) - print*, 'Neighbour finding complete for file ', TRIM(dumpfile) + print*, 'Neighbour finding complete for file ', trim(dumpfile) endif deallocate(dumxyzh) @@ -214,7 +214,7 @@ subroutine neighbours_stats(npart) stop endif - meanneigh = sum(neighcount)/REAL(npart) + meanneigh = sum(neighcount)/real(npart) sdneigh = 0.0 !$omp parallel default(none) & @@ -228,7 +228,7 @@ subroutine neighbours_stats(npart) !$omp enddo !$omp end parallel - sdneigh = sqrt(sdneigh/REAL(npart)) + sdneigh = sqrt(sdneigh/real(npart)) print*, 'Mean neighbour number is ', meanneigh print*, 'Standard Deviation: ', sdneigh @@ -250,8 +250,8 @@ subroutine read_neighbours(neighbourfile,npart) neighcount(:) = 0 neighb(:,:) = 0 - print*, 'Reading neighbour file ', TRIM(neighbourfile) - open(2, file= neighbourfile, form = 'UNFORMATTED') + print*, 'Reading neighbour file ', trim(neighbourfile) + open(2,file= neighbourfile, form = 'UNFORMATTED') read(2) neighcheck, tolcheck, meanneigh,sdneigh,neighcrit if (neighcheck/=neighmax) print*, 'WARNING: mismatch in neighmax: ', neighmax, neighcheck read(2) (neighcount(i), i=1,npart) @@ -287,10 +287,10 @@ subroutine write_neighbours(neighbourfile,npart) real, parameter :: tolerance = 2.0e0 ! A dummy parameter used to keep file format similar to other codes (Probably delete later) neigh_overload = .false. - neighbourfile = TRIM(neighbourfile) + neighbourfile = trim(neighbourfile) print*, 'Writing neighbours to file ', neighbourfile - open (2, file=neighbourfile, form='unformatted') + open(2,file=neighbourfile,form='unformatted') write(2) neighmax, tolerance, meanneigh,sdneigh,neighcrit write(2) (neighcount(i), i=1,npart) do i=1,npart diff --git a/src/utils/utils_gravwave.f90 b/src/utils/utils_gravwave.f90 index 225f091b6..5f568aaad 100644 --- a/src/utils/utils_gravwave.f90 +++ b/src/utils/utils_gravwave.f90 @@ -272,7 +272,7 @@ subroutine write_rotated_strain_components(time,ddq_xy) ! Write a file where I append all the values of the strain wrt time if (firstdump) then firstdump = .false. - open(newunit=iuu, file='quadrupole_plane_xy.txt',status='replace') + open(newunit=iuu,file='quadrupole_plane_xy.txt',status='replace') write(iuu,"('#',7(1x,'[',i2.2,1x,a11,']',2x))") & 1, 'time', & 2, 'ddm11', & @@ -282,7 +282,7 @@ subroutine write_rotated_strain_components(time,ddq_xy) 6, 'ddm23', & 7, 'ddm33' else - open(newunit=iuu, file='quadrupole_plane_xy.txt',position='append') + open(newunit=iuu,file='quadrupole_plane_xy.txt',position='append') endif write(iuu,'(7(es18.10,1X))') time, ddq_xy(1,1),ddq_xy(1,2),ddq_xy(1,3),& ddq_xy(2,2),ddq_xy(2,3),ddq_xy(3,3) diff --git a/src/utils/utils_raytracer_all.f90 b/src/utils/utils_raytracer_all.f90 new file mode 100644 index 000000000..a257b00c4 --- /dev/null +++ b/src/utils/utils_raytracer_all.f90 @@ -0,0 +1,1199 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module raytracer_all +! +! raytracer_all +! +! :References: Esseldeurs M., Siess L. et al, 2023, A&A, 674, A122 +! +! :Owner: Mats Esseldeurs +! +! :Runtime parameters: None +! +! :Dependencies: healpix, kernel, linklist, part, units +! + use healpix + implicit none + public :: get_all_tau_outwards, get_all_tau_inwards, get_all_tau_adaptive + private +contains + + !*********************************************************************! + !*************************** ADAPTIVE ****************************! + !*********************************************************************! + + !-------------------------------------------------------------------------- + !+ + ! Calculate the optical depth of each particle, using the adaptive ray- + ! tracing scheme + !+ + ! IN: npart: The number of SPH particles + ! IN: primary: The xyz coordinates of the primary star + ! IN: xyzh: The array containing the particles position+smooting lenght + ! IN: kappa: The array containing the kappa of all SPH particles + ! IN: Rstar: The radius of the star + ! IN: minOrder: The minimal order in which the rays are sampled + ! IN: refineLevel: The amount of orders in which the rays can be + ! sampled deeper + ! IN: refineScheme: The refinement scheme used for adaptive ray selection + !+ + ! OUT: taus: The list of optical depths for each particle + !+ + ! OPT: companion: The xyz coordinates of the companion + ! OPT: Rcomp: The radius of the companion + !+ + !-------------------------------------------------------------------------- +subroutine get_all_tau_adaptive(npart, primary, xyzh, kappa, Rstar, minOrder,& + refineLevel, refineScheme, taus, companion, Rcomp) + integer, intent(in) :: npart, minOrder, refineLevel, refineScheme + real, intent(in) :: primary(3), kappa(:), xyzh(:,:), Rstar + real, optional :: Rcomp, companion(3) + real, intent(out) :: taus(:) + + integer :: i, nrays, nsides, index + real :: normCompanion, theta0, unitCompanion(3), theta, root, dist, vec(3), dir(3) + real, dimension(:,:), allocatable :: dirs + real, dimension(:,:), allocatable :: listsOfDists, listsOfTaus + integer, dimension(:), allocatable :: indices, rays_dim + real, dimension(:), allocatable :: tau, dists + + if (present(companion) .and. present(Rcomp)) then + unitCompanion = companion-primary + normCompanion = norm2(unitCompanion) + theta0 = asin(Rcomp/normCompanion) + unitCompanion = unitCompanion/normCompanion + + call get_rays(npart, primary, companion, Rcomp, xyzh, minOrder, refineLevel, refineScheme, dirs, indices, nrays) + allocate(listsOfDists(200, nrays)) + allocate(listsOfTaus(size(listsOfDists(:,1)), nrays)) + allocate(tau(size(listsOfDists(:,1)))) + allocate(dists(size(listsOfDists(:,1)))) + allocate(rays_dim(nrays)) + + !$omp parallel do private(tau,dist,dir,dists,root,theta) + do i = 1, nrays + tau=0. + dists=0. + dir = dirs(:,i) + theta = acos(dot_product(unitCompanion, dir)) + if (theta < theta0) then + root = sqrt(normCompanion**2*cos(theta)**2-normCompanion**2+Rcomp**2) + dist = normCompanion*cos(theta)-root + call ray_tracer(primary, dir, xyzh, kappa, Rstar, tau, dists, rays_dim(i), dist) + else + call ray_tracer(primary, dir, xyzh, kappa, Rstar, tau, dists, rays_dim(i)) + endif + listsOfTaus(:,i) = tau + listsOfDists(:,i) = dists + enddo + !$omp end parallel do + + nsides = 2**(minOrder+refineLevel) + taus = 0. + !$omp parallel do private(index,vec) + do i = 1, npart + vec = xyzh(1:3,i)-primary + call vec2pix_nest(nsides, vec, index) + index = indices(index + 1) + call get_tau_on_ray(norm2(vec), listsOfTaus(:,index), listsOfDists(:,index), rays_dim(index), taus(i)) + enddo + !$omp end parallel do + + else + call get_all_tau_outwards_single(npart, primary, xyzh, kappa, & + Rstar, minOrder+refineLevel, 0, taus) + endif +end subroutine get_all_tau_adaptive + + !-------------------------------------------------------------------------- + !+ + ! Return all the directions of the rays that need to be traced for the + ! adaptive ray-tracing scheme + !+ + ! IN: npart: The number of SPH particles + ! IN: primary: The xyz coordinates of the primary star + ! IN: companion: The xyz coordinates of the companion + ! IN: Rcomp: The radius of the companion + ! IN: xyzh: The array containing the particles position+smooting lenght + ! IN: minOrder: The minimal order in which the rays are sampled + ! IN: refineLevel: The amount of orders in which the rays can be + ! sampled deeper + ! IN: refineScheme: The refinement scheme used for adaptive ray selection + !+ + ! OUT: rays: A list containing the rays that need to be traced + ! in the adaptive ray-tracing scheme + ! OUT: indices: A list containing a link between the index in the + ! deepest order and the rays in the adaptive ray-tracing scheme + ! OUT: nrays: The number of rays after the ray selection + !+ + !-------------------------------------------------------------------------- +subroutine get_rays(npart, primary, companion, Rcomp, xyzh, minOrder, refineLevel, refineScheme, rays, indices, nrays) + integer, intent(in) :: npart, minOrder, refineLevel, refineScheme + real, intent(in) :: primary(3), companion(3), xyzh(:,:), Rcomp + real, allocatable, intent(out) :: rays(:,:) + integer, allocatable, intent(out) :: indices(:) + integer, intent(out) :: nrays + + real :: theta, dist, phi, cosphi, sinphi + real, dimension(:,:), allocatable :: circ + integer :: i, j, minNsides, minNrays, ind,n, maxOrder, max, distr(12*4**(minOrder+refineLevel)) + integer, dimension(:,:), allocatable :: distrs + + maxOrder = minOrder+refineLevel + nrays = 12*4**(maxOrder) + allocate(rays(3, nrays)) + allocate(indices(12*4**(maxOrder))) + rays = 0. + indices = 0 + + !If there is no refinement, just return the uniform ray distribution + minNsides = 2**minOrder + minNrays = 12*4**minOrder + if (refineLevel == 0) then + do i=1, minNrays + call pix2vec_nest(minNsides,i-1, rays(:,i)) + indices(i) = i + enddo + return + endif + + !Fill a list to have the number distribution in angular space + distr = 0 + !$omp parallel do private(ind) + do i = 1, npart + call vec2pix_nest(2**maxOrder, xyzh(1:3, i)-primary, ind) + distr(ind+1) = distr(ind+1)+1 + enddo + max = maxval(distr) + + !Make sure the companion is described using the highest refinement + dist = norm2(primary-companion) + theta = asin(Rcomp/dist) + phi = atan2(companion(2)-primary(2),companion(1)-primary(1)) + cosphi = cos(phi) + sinphi = sin(phi) + dist = dist*cos(theta) + n = int(theta*6*2**(minOrder+refineLevel))+4 + allocate(circ(n,3)) + do i=1, n !Define boundary of the companion + circ(i,1) = dist*cos(theta) + circ(i,2) = dist*sin(theta)*cos(twopi*i/n) + circ(i,3) = dist*sin(theta)*sin(twopi*i/n) + circ(i,:) = (/cosphi*circ(i,1) - sinphi*circ(i,2),sinphi*circ(i,1) + cosphi*circ(i,2), circ(i,3)/) + enddo + do i=1, n !Make sure the boundary is maximally refined + call vec2pix_nest(2**maxOrder,circ(i,:),ind) + distr(ind+1) = max + enddo + + !Calculate the number distribution in all the orders needed + allocate(distrs(12*4**(minOrder+refineLevel),refineLevel+1)) + distrs = 0 + distrs(:,1) = distr + do i = 1, refineLevel + do j = 1, 12*4**(maxOrder-i) + distrs(j,i+1) = distrs(4*j,i)+distrs(4*j+1,i)+distrs(4*j+2,i)+distrs(4*j+3,i) + enddo + enddo + max = maxval(distrs(:,refineLevel+1))+1 + + !Fill the rays array walking through the orders + ind=1 + + ! refine half in each order + if (refineScheme == 1) then + do i=0, refineLevel-1 + call merge_argsort(distrs(1:12*4**(minOrder+i),refineLevel-i+1), distr) + do j=1, 6*4**minOrder*2**(i) + call pix2vec_nest(2**(minOrder+i), distr(j)-1, rays(:,ind)) + indices(4**(refineLevel-i)*(distr(j)-1)+1:4**(refineLevel-i)*distr(j)) = ind + ind=ind+1 + distrs(4*(distr(j)-1)+1:4*(distr(j)), refineLevel-i) = max + enddo + do j = j+1, 12*4**(minOrder+i) + if (distrs(distr(j),refineLevel-i+1) == max) then + distrs(4*(distr(j)-1)+1:4*(distr(j)), refineLevel-i) = max + endif + enddo + enddo + + ! refine overdens regions in each order + elseif (refineScheme == 2) then + do i=0, refineLevel-1 + call merge_argsort(distrs(1:12*4**(minOrder+i),refineLevel-i+1), distr) + j=1 + do while (distrs(distr(j),refineLevel-i+1) 0.) then + tau = tautemp/distRay_sq + weight = 1./distRay_sq + else + ! the particle sits exactly on the ray, no need to get the neighbours + tau = tautemp + return + endif + + !returns the number nneigh and list of vectors (n) neighbouring the ray number index + call neighbours_nest(nsides, rayIndex, neighbours, nneigh) + !for each neighbouring ray calculate its distance to the particle + do i=1,nneigh + call pix2vec_nest(nsides, neighbours(i), ray) + vectemp = vec - vec_norm2*ray + tempdist(i) = norm2(vectemp) + enddo + neighbours = neighbours+1 + mask = .true. + if (nneigh <8) mask(nneigh+1:8) = .false. + !take tau contribution from the 3 closest rays + do i=1,3 + k = minloc(tempdist,1,mask) + mask(k) = .false. + call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & + rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) + tau = tau + tautemp/tempdist(k) + weight = weight + 1./tempdist(k) + enddo + tau = tau / weight + + ! 9 rays, linear interpolation + elseif (raypolation==2) then + vec_norm2 = norm2(vec) + !returns rayIndex, the index of the ray vector that points to the particle (direction vec) + call vec2pix_nest(nsides, vec, rayIndex) + !returns ray(3), the unit vector identifying the ray with index number rayIndex + call pix2vec_nest(nsides, rayIndex, ray) + vectemp = vec - vec_norm2*ray + distRay_sq = norm2(vectemp) + call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) + if (distRay_sq > 0.) then + tau = tautemp/distRay_sq + weight = 1./distRay_sq + else + ! the particle sits exactly on the ray, no need to get the neighbours + tau = tautemp + return + endif + + !returns the number nneigh and list of vectors (n) neighbouring the ray number index + call neighbours_nest(nsides, rayIndex, neighbours, nneigh) + !for each neighbouring ray calculate its distance to the particle + do i=1,nneigh + call pix2vec_nest(nsides, neighbours(i), ray) + vectemp = vec - vec_norm2*ray + tempdist(i) = norm2(vectemp) + enddo + neighbours = neighbours+1 + mask = .true. + if (nneigh <8) mask(nneigh+1:8) = .false. + !take tau contribution from the 3 closest rays + do i=1,nneigh + k = minloc(tempdist,1,mask) + mask(k) = .false. + call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & + rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) + tau = tau + tautemp/tempdist(k) + weight = weight + 1./tempdist(k) + enddo + tau = tau / weight + + ! 4 rays, square interpolation + elseif (raypolation==3) then + vec_norm2 = norm2(vec) + !returns rayIndex, the index of the ray vector that points to the particle (direction vec) + call vec2pix_nest(nsides, vec, rayIndex) + !returns ray(3), the unit vector identifying the ray with index number rayIndex + call pix2vec_nest(nsides, rayIndex, ray) + vectemp = vec - vec_norm2*ray + distRay_sq = dot_product(vectemp,vectemp) + call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) + if (distRay_sq > 0.) then + tau = tautemp/distRay_sq + weight = 1./distRay_sq + else + ! the particle sits exactly on the ray, no need to get the neighbours + tau = tautemp + return + endif + + !returns the number nneigh and list of vectors (n) neighbouring the ray number index + call neighbours_nest(nsides, rayIndex, neighbours, nneigh) + !for each neighbouring ray calculate its distance to the particle + do i=1,nneigh + call pix2vec_nest(nsides, neighbours(i), ray) + vectemp = vec - vec_norm2*ray + tempdist(i) = dot_product(vectemp,vectemp) + enddo + neighbours = neighbours+1 + mask = .true. + if (nneigh <8) mask(nneigh+1:8) = .false. + !take tau contribution from the 3 closest rays + do i=1,3 + k = minloc(tempdist,1,mask) + mask(k) = .false. + call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & + rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) + tau = tau + tautemp/tempdist(k) + weight = weight + 1./tempdist(k) + enddo + tau = tau / weight + + ! 9 rays, square interpolation + elseif (raypolation==4) then + vec_norm2 = norm2(vec) + !returns rayIndex, the index of the ray vector that points to the particle (direction vec) + call vec2pix_nest(nsides, vec, rayIndex) + !returns ray(3), the unit vector identifying the ray with index number rayIndex + call pix2vec_nest(nsides, rayIndex, ray) + vectemp = vec - vec_norm2*ray + distRay_sq = dot_product(vectemp,vectemp) + call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) + if (distRay_sq > 0.) then + tau = tautemp/distRay_sq + weight = 1./distRay_sq + else + ! the particle sits exactly on the ray, no need to get the neighbours + tau = tautemp + return + endif + + !returns the number nneigh and list of vectors (n) neighbouring the ray number index + call neighbours_nest(nsides, rayIndex, neighbours, nneigh) + !for each neighbouring ray calculate its distance to the particle + do i=1,nneigh + call pix2vec_nest(nsides, neighbours(i), ray) + vectemp = vec - vec_norm2*ray + tempdist(i) = dot_product(vectemp,vectemp) + enddo + neighbours = neighbours+1 + mask = .true. + if (nneigh <8) mask(nneigh+1:8) = .false. + !take tau contribution from the 3 closest rays + do i=1,nneigh + k = minloc(tempdist,1,mask) + mask(k) = .false. + call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & + rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) + tau = tau + tautemp/tempdist(k) + weight = weight + 1./tempdist(k) + enddo + tau = tau / weight + + ! 4 rays, cubed interpolation + elseif (raypolation==5) then + vec_norm2 = norm2(vec) + !returns rayIndex, the index of the ray vector that points to the particle (direction vec) + call vec2pix_nest(nsides, vec, rayIndex) + !returns ray(3), the unit vector identifying the ray with index number rayIndex + call pix2vec_nest(nsides, rayIndex, ray) + vectemp = vec - vec_norm2*ray + distRay_sq = norm2(vectemp)**3 + call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) + if (distRay_sq > 0.) then + tau = tautemp/distRay_sq + weight = 1./distRay_sq + else + ! the particle sits exactly on the ray, no need to get the neighbours + tau = tautemp + return + endif + + !returns the number nneigh and list of vectors (n) neighbouring the ray number index + call neighbours_nest(nsides, rayIndex, neighbours, nneigh) + !for each neighbouring ray calculate its distance to the particle + do i=1,nneigh + call pix2vec_nest(nsides, neighbours(i), ray) + vectemp = vec - vec_norm2*ray + tempdist(i) = norm2(vectemp)**3 + enddo + neighbours = neighbours+1 + mask = .true. + if (nneigh <8) mask(nneigh+1:8) = .false. + !take tau contribution from the 3 closest rays + do i=1,3 + k = minloc(tempdist,1,mask) + mask(k) = .false. + call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & + rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) + tau = tau + tautemp/tempdist(k) + weight = weight + 1./tempdist(k) + enddo + tau = tau / weight + + ! 9 rays, cubed interpolation + elseif (raypolation==6) then + vec_norm2 = norm2(vec) + !returns rayIndex, the index of the ray vector that points to the particle (direction vec) + call vec2pix_nest(nsides, vec, rayIndex) + !returns ray(3), the unit vector identifying the ray with index number rayIndex + call pix2vec_nest(nsides, rayIndex, ray) + vectemp = vec - vec_norm2*ray + distRay_sq = norm2(vectemp)**3 + call get_tau_on_ray(vec_norm2, rays_tau(:,rayIndex+1), rays_dist(:,rayIndex+1), rays_dim(rayIndex+1), tautemp) + if (distRay_sq > 0.) then + tau = tautemp/distRay_sq + weight = 1./distRay_sq + else + ! the particle sits exactly on the ray, no need to get the neighbours + tau = tautemp + return + endif + + !returns the number nneigh and list of vectors (n) neighbouring the ray number index + call neighbours_nest(nsides, rayIndex, neighbours, nneigh) + !for each neighbouring ray calculate its distance to the particle + do i=1,nneigh + call pix2vec_nest(nsides, neighbours(i), ray) + vectemp = vec - vec_norm2*ray + tempdist(i) = norm2(vectemp)**3 + enddo + neighbours = neighbours+1 + mask = .true. + if (nneigh <8) mask(nneigh+1:8) = .false. + !take tau contribution from the 3 closest rays + do i=1,nneigh + k = minloc(tempdist,1,mask) + mask(k) = .false. + call get_tau_on_ray(vec_norm2, rays_tau(:,neighbours(k)), & + rays_dist(:,neighbours(k)), rays_dim(neighbours(k)), tautemp) + tau = tau + tautemp/tempdist(k) + weight = weight + 1./tempdist(k) + enddo + tau = tau / weight + endif +end subroutine interpolate_tau + + + !-------------------------------------------------------------------------- + !+ + ! Interpolation of the optical depth for an arbitrary point on the ray, + ! with a given distance to the starting point of the ray. + !+ + ! IN: distance: The distance from the staring point of the ray to a + ! point on the ray + ! IN: tau_along_ray: The vector of cumulative optical depths along the ray + ! IN: dist_along_ray: The vector of distances from the primary along the ray + ! IN: len: The length of listOfTau and listOfDist + !+ + ! OUT: tau: The optical depth to the given distance along the ray + !+ + !-------------------------------------------------------------------------- +subroutine get_tau_on_ray(distance, tau_along_ray, dist_along_ray, len, tau) + real, intent(in) :: distance, tau_along_ray(:), dist_along_ray(:) + integer, intent(in) :: len + real, intent(out) :: tau + + integer :: L, R, m ! left, right and middle index for binary search + + if (distance < dist_along_ray(1)) then + tau = 0. + elseif (distance > dist_along_ray(len)) then + tau = 99. + else + L = 2 + R = len-1 + !bysection search for the index of the closest ray location to the particle + do while (L < R) + m = (L + R)/2 + if (dist_along_ray(m) > distance) then + R = m + else + L = m + 1 + endif + enddo + !interpolate linearly ray properties to get the particle's optical depth + tau = tau_along_ray(L-1)+(tau_along_ray(L)-tau_along_ray(L-1))/ & + (dist_along_ray(L)-dist_along_ray(L-1))*(distance-dist_along_ray(L-1)) + endif +end subroutine get_tau_on_ray + + !-------------------------------------------------------------------------- + !+ + ! Calculate the optical depth along a given ray + !+ + ! IN: primary: The location of the primary star + ! IN: ray: The unit vector of the direction in which the + ! optical depts will be calculated + ! IN: xyzh: The array containing the particles position+smooting lenght + ! IN: kappa: The array containing the particles opacity + ! IN: Rstar: The radius of the primary star + !+ + ! OUT: taus: The distribution of optical depths throughout the ray + ! OUT: listOfDists: The distribution of distances throughout the ray + ! OUT: len: The length of tau_along_ray and dist_along_ray + !+ + ! OPT: maxDistance: The maximal distance the ray needs to be traced + !+ + !-------------------------------------------------------------------------- +subroutine ray_tracer(primary, ray, xyzh, kappa, Rstar, tau_along_ray, dist_along_ray, len, maxDistance) + use linklist, only:getneigh_pos,ifirstincell,listneigh + use kernel, only:radkern + use units, only:umass,udist + real, intent(in) :: primary(3), ray(3), Rstar, xyzh(:,:), kappa(:) + real, optional :: maxDistance + real, intent(out) :: dist_along_ray(:), tau_along_ray(:) + integer, intent(out) :: len + + integer, parameter :: maxcache = 0 + real, allocatable :: xyzcache(:,:) + real :: distance, h, dtaudr, previousdtaudr, nextdtaudr + integer :: nneigh, inext, i + + distance = Rstar + + h = Rstar/100. + inext=0 + do while (inext==0) + h = h*2. + call getneigh_pos(primary+Rstar*ray,0.,h,3,listneigh,nneigh,xyzh,xyzcache,maxcache,ifirstincell) + call find_next(primary, ray, distance, xyzh, listneigh, inext, nneigh) + enddo + call calc_opacity(primary+Rstar*ray, xyzh, kappa, listneigh, nneigh, previousdtaudr) + + i = 1 + tau_along_ray(i) = 0. + distance = Rstar + dist_along_ray(i) = distance + do while (hasNext(inext,tau_along_ray(i),distance,maxDistance)) + i = i + 1 + call getneigh_pos(primary + distance*ray,0.,xyzh(4,inext)*radkern, & + 3,listneigh,nneigh,xyzh,xyzcache,maxcache,ifirstincell) + call calc_opacity(primary + distance*ray, xyzh, kappa, listneigh, nneigh, nextdtaudr) + dtaudr = (nextdtaudr+previousdtaudr)/2 + previousdtaudr = nextdtaudr + tau_along_ray(i) = tau_along_ray(i-1)+(distance-dist_along_ray(i-1))*dtaudr + dist_along_ray(i) = distance + call find_next(primary, ray, distance, xyzh, listneigh, inext,nneigh) + enddo + len = i + tau_along_ray = tau_along_ray*umass/(udist**2) +end subroutine ray_tracer + +logical function hasNext(inext, tau, distance, maxDistance) + integer, intent(in) :: inext + real, intent(in) :: distance, tau + real, optional :: maxDistance + real, parameter :: tau_max = 99. + if (present(maxDistance)) then + hasNext = inext /= 0 .and. distance < maxDistance .and. tau < tau_max + else + hasNext = inext /= 0 .and. tau < tau_max + endif +end function hasNext + + !*********************************************************************! + !**************************** INWARDS ****************************! + !*********************************************************************! + + !-------------------------------------------------------------------------- + !+ + ! Calculate the optical depth of each particle, using the inwards ray- + ! tracing scheme + !+ + ! IN: npart: The number of SPH particles + ! IN: primary: The xyz coordinates of the primary star + ! IN: xyzh: The array containing the particles position+smooting lenght + ! IN: neighbors: A list containing the indices of the neighbors of + ! each particle + ! IN: kappa: The array containing the opacity of all the SPH particles + ! IN: Rstar: The radius of the primary star + !+ + ! OUT: tau: The array of optical depths for each SPH particle + !+ + ! OPT: companion: The location of the companion + ! OPT: R: The radius of the companion + !+ + !-------------------------------------------------------------------------- +subroutine get_all_tau_inwards(npart, primary, xyzh, neighbors, kappa, Rstar, tau, companion, R) + real, intent(in) :: primary(3), kappa(:), Rstar, xyzh(:,:) + integer, intent(in) :: npart, neighbors(:,:) + real, optional :: R, companion(3) + real, intent(out) :: tau(:) + + if (present(companion) .and. present(R)) then + call get_all_tau_inwards_companion(npart, primary, xyzh, neighbors, kappa, Rstar, companion, R, tau) + else + call get_all_tau_inwards_single(npart, primary, xyzh, neighbors, kappa, Rstar, tau) + endif +end subroutine get_all_tau_inwards + + !-------------------------------------------------------------------------- + !+ + ! Calculate the optical depth of each particle, using the inwards ray- + ! tracing scheme concerning only a single star + !+ + ! IN: npart: The number of SPH particles + ! IN: primary: The xyz coordinates of the primary star + ! IN: xyzh: The array containing the particles position+smooting lenght + ! IN: neighbors: A list containing the indices of the neighbors of + ! each particle + ! IN: kappa: The array containing the opacity of all the SPH particles + ! IN: Rstar: The radius of the primary star + !+ + ! OUT: taus: The list of optical depths for each particle + !+ + !-------------------------------------------------------------------------- +subroutine get_all_tau_inwards_single(npart, primary, xyzh, neighbors, kappa, Rstar, tau) + real, intent(in) :: primary(3), kappa(:), Rstar, xyzh(:,:) + integer, intent(in) :: npart, neighbors(:,:) + real, intent(out) :: tau(:) + + integer :: i + + !$omp parallel do + do i = 1, npart + call get_tau_inwards(i, primary, xyzh, neighbors, kappa, Rstar, tau(i)) + enddo + !$omp end parallel do +end subroutine get_all_tau_inwards_single + + !-------------------------------------------------------------------------- + !+ + ! Calculate the optical depth of each particle, using the inwards ray- + ! tracing scheme concerning a binary system + !+ + ! IN: npart: The number of SPH particles + ! IN: primary: The xyz coordinates of the primary star + ! IN: xyzh: The array containing the particles position+smooting lenght + ! IN: neighbors: A list containing the indices of the neighbors of + ! each particle + ! IN: kappa: The array containing the opacity of all the SPH particles + ! IN: Rstar: The radius of the primary star + ! IN: companion: The xyz coordinates of the companion + ! IN: Rcomp: The radius of the companion + !+ + ! OUT: tau: The array of optical depths for each SPH particle + !+ + !-------------------------------------------------------------------------- +subroutine get_all_tau_inwards_companion(npart, primary, xyzh, neighbors, kappa, Rstar, companion, Rcomp, tau) + real, intent(in) :: primary(3), companion(3), kappa(:), Rstar, xyzh(:,:), Rcomp + integer, intent(in) :: npart, neighbors(:,:) + real, intent(out) :: tau(:) + + integer :: i + real :: normCompanion, theta0, uvecCompanion(3), norm, theta, root, norm0 + + uvecCompanion = companion-primary + normCompanion = norm2(uvecCompanion) + uvecCompanion = uvecCompanion/normCompanion + theta0 = asin(Rcomp/normCompanion) + + !$omp parallel do private(norm,theta,root,norm0) + do i = 1, npart + norm = norm2(xyzh(1:3,i)-primary) + theta = acos(dot_product(uvecCompanion, xyzh(1:3,i)-primary)/norm) + if (theta < theta0) then + root = sqrt(normCompanion**2*cos(theta)**2-normCompanion**2+Rcomp**2) + norm0 = normCompanion*cos(theta)-root + if (norm > norm0) then + tau(i) = 99. + else + call get_tau_inwards(i, primary, xyzh, neighbors, kappa, Rstar, tau(i)) + endif + else + call get_tau_inwards(i, primary, xyzh, neighbors, kappa, Rstar, tau(i)) + endif + enddo + !$omp end parallel do +end subroutine get_all_tau_inwards_companion + + !-------------------------------------------------------------------------- + !+ + ! Calculate the optical depth for a given particle, using the inwards ray- + ! tracing scheme + !+ + ! IN: point: The index of the point that needs to be calculated + ! IN: primary: The location of the primary star + ! IN: xyzh: The array containing the particles position+smooting lenght + ! IN: neighbors: A list containing the indices of the neighbors of + ! each particle + ! IN: kappa: The array containing the opacity of all the SPH particles + ! IN: Rstar: The radius of the star + !+ + ! OUT: tau: The list of optical depth of the given particle + !+ + !-------------------------------------------------------------------------- +subroutine get_tau_inwards(point, primary, xyzh, neighbors, kappa, Rstar, tau) + use linklist, only:getneigh_pos,ifirstincell,listneigh + use kernel, only:radkern + use units, only:umass,udist + real, intent(in) :: primary(3), xyzh(:,:), kappa(:), Rstar + integer, intent(in) :: point, neighbors(:,:) + real, intent(out) :: tau + + integer :: i, next, previous, nneigh + integer, parameter :: nmaxcache = 0 + real :: xyzcache(0,nmaxcache) + real :: ray(3), nextDist, previousDist, maxDist, dtaudr, previousdtaudr, nextdtaudr + + ray = primary - xyzh(1:3,point) + maxDist = norm2(ray) + ray = ray / maxDist + maxDist=max(maxDist-Rstar,0.) + next=point + call getneigh_pos(xyzh(1:3,point),0.,xyzh(4,point)*radkern, & + 3,listneigh,nneigh,xyzh,xyzcache,nmaxcache,ifirstincell) + call calc_opacity(xyzh(1:3,point), xyzh, kappa, listneigh, nneigh, nextdtaudr) + nextDist=0. + + tau = 0. + i=1 + do while (nextDist < maxDist .and. next /=0) + i = i + 1 + previous = next + previousDist = nextDist + call find_next(xyzh(1:3,point), ray, nextDist, xyzh, neighbors(next,:), next) + if (nextDist > maxDist) then + nextDist = maxDist + endif + call getneigh_pos(xyzh(1:3,point) + nextDist*ray,0.,xyzh(4,previous)*radkern, & + 3,listneigh,nneigh,xyzh,xyzcache,nmaxcache,ifirstincell) + previousdtaudr=nextdtaudr + call calc_opacity(xyzh(1:3,point) + nextDist*ray, xyzh, kappa, listneigh, nneigh, nextdtaudr) + dtaudr = (nextdtaudr+previousdtaudr)/2 + tau = tau + (nextDist-previousDist)*dtaudr + enddo + !fix units for tau (kappa is in cgs while rho & r are in code units) + tau = tau*umass/(udist**2) +end subroutine get_tau_inwards + + !*********************************************************************! + !**************************** COMMON *****************************! + !*********************************************************************! + + !-------------------------------------------------------------------------- + !+ + ! Find the next point on a ray + !+ + ! IN: inpoint: The coordinate of the initial point projected on the + ! ray for which the next point will be calculated + ! IN: ray: The unit vector of the direction in which the next + ! point will be calculated + ! IN: xyzh: The array containing the particles position+smoothing length + ! IN: neighbors: A list containing the indices of the neighbors of + ! the initial point + ! IN: inext: The index of the initial point + ! (this point will not be considered as possible next point) + !+ + ! OPT: nneighin: The amount of neighbors + !+ + ! OUT: inext: The index of the next point on the ray + !+ + !-------------------------------------------------------------------------- +subroutine find_next(inpoint, ray, dist, xyzh, neighbors, inext, nneighin) + integer, intent(in) :: neighbors(:) + real, intent(in) :: xyzh(:,:), inpoint(:), ray(:) + integer, intent(inout) :: inext + real, intent(inout) :: dist + integer, optional :: nneighin + + real :: trace_point(3), dmin, vec(3), tempdist, raydist + real :: nextdist + integer :: i, nneigh, prev + + dmin = huge(0.) + if (present(nneighin)) then + nneigh = nneighin + else + nneigh = size(neighbors) + endif + + prev=inext + inext=0 + nextDist=dist + trace_point = inpoint + dist*ray + + i = 1 + do while (i <= nneigh .and. neighbors(i) /= 0) + if (neighbors(i) /= prev) then + vec=xyzh(1:3,neighbors(i)) - trace_point + tempdist = dot_product(vec,ray) + if (tempdist>0.) then + raydist = dot_product(vec,vec) - tempdist**2 + if (raydist < dmin) then + dmin = raydist + inext = neighbors(i) + nextdist = dist+tempdist + endif + endif + endif + i = i+1 + enddo + dist=nextdist +end subroutine find_next + + !-------------------------------------------------------------------------- + !+ + ! Calculate the opacity in a given location + !+ + ! IN: r0: The location where the opacity will be calculated + ! IN: xyzh: The xyzh of all the particles + ! IN: opacities: The list of the opacities of the particles + ! IN: neighbors: A list containing the indices of the neighbors of + ! the initial point + ! IN: nneigh: The amount of neighbors + !+ + ! OUT: dtaudr: The local optical depth derivative at the given location (inpoint) + !+ + !-------------------------------------------------------------------------- +subroutine calc_opacity(r0, xyzh, opacities, neighbors, nneigh, dtaudr) + use kernel, only:cnormk,wkern + use part, only:hfact,rhoh,massoftype,igas + real, intent(in) :: r0(:), xyzh(:,:), opacities(:) + integer, intent(in) :: neighbors(:), nneigh + real, intent(out) :: dtaudr + + integer :: i + real :: q + + dtaudr=0 + do i=1,nneigh + q = norm2(r0 - xyzh(1:3,neighbors(i)))/xyzh(4,neighbors(i)) + dtaudr=dtaudr+wkern(q*q,q)*opacities(neighbors(i))*rhoh(xyzh(4,neighbors(i)), massoftype(igas)) + enddo + dtaudr = dtaudr*cnormk/hfact**3 +end subroutine calc_opacity +end module raytracer_all From 39e3c11ca12111656c5f1384f5b3eb1cbc704310 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 2 May 2024 11:29:20 +0100 Subject: [PATCH 110/182] Incomplete updates from Upstream --- src/main/eos.f90 | 1565 +++++++++++++++++++++++++++++ src/main/eos_gasradrec.f90 | 4 +- src/main/eos_idealplusrad.f90 | 12 +- src/main/extern_corotate.f90 | 24 +- src/main/extern_gnewton.f90 | 19 +- src/main/extern_lensethirring.f90 | 25 +- src/main/extern_prdrag.f90 | 117 ++- src/main/externalforces.f90 | 39 +- src/main/part.F90 | 8 +- src/main/ptmass.F90 | 290 +++--- src/main/readwrite_infile.F90 | 32 +- 11 files changed, 1876 insertions(+), 259 deletions(-) create mode 100644 src/main/eos.f90 diff --git a/src/main/eos.f90 b/src/main/eos.f90 new file mode 100644 index 000000000..92b6ec4b7 --- /dev/null +++ b/src/main/eos.f90 @@ -0,0 +1,1565 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module eos +! +! This module contains stuff to do with the equation of state +! Current options: +! 1 = isothermal eos +! 2 = adiabatic/polytropic eos +! 3 = eos for a locally isothermal disc as in Lodato & Pringle (2007) +! 4 = GR isothermal +! 5 = polytropic EOS with vary mu and gamma depending on H2 formation +! 6 = eos for a locally isothermal disc as in Lodato & Pringle (2007), +! centered on a sink particle +! 7 = z-dependent locally isothermal eos +! 8 = Barotropic eos +! 9 = Piecewise polytrope +! 10 = MESA EoS +! 11 = isothermal eos with zero pressure +! 12 = ideal gas with radiation pressure +! 13 = locally isothermal prescription from Farris et al. (2014) generalised for generic hierarchical systems +! 14 = locally isothermal prescription from Farris et al. (2014) for binary system +! 15 = Helmholtz free energy eos +! 16 = Shen eos +! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) +! 21 = read tabulated eos (for use with icooling == 8) +! +! :References: +! Lodato & Pringle (2007) +! Hirai et al. (2020) +! +! :Owner: Daniel Price +! +! :Runtime parameters: +! - X : *H mass fraction (ignored if variable composition)* +! - Z : *metallicity (ignored if variable composition)* +! - ieos : *eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)* +! - metallicity : *metallicity* +! - mu : *mean molecular weight* +! +! :Dependencies: dim, dump_utils, eos_barotropic, eos_gasradrec, +! eos_helmholtz, eos_idealplusrad, eos_mesa, eos_piecewise, eos_shen, +! eos_stratified, infile_utils, io, mesa_microphysics, part, physcon, +! units +! + use part, only:ien_etotal,ien_entropy,ien_type + use dim, only:gr + implicit none + integer, parameter, public :: maxeos = 21 + real, public :: polyk, polyk2, gamma + real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 + logical, public :: extract_eos_from_hdr = .false. + integer, public :: isink = 0. + + public :: equationofstate,setpolyk,eosinfo,get_mean_molecular_weight + public :: get_TempPresCs,get_spsound,get_temperature,get_pressure,get_cv + public :: eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP + public :: get_local_u_internal,get_temperature_from_u + public :: calc_rec_ene,calc_temp_and_ene,entropy,get_rho_from_p_s,get_u_from_rhoT + public :: calc_rho_from_PT,get_entropy,get_p_from_rho_s + public :: init_eos,finish_eos,write_options_eos,read_options_eos + public :: write_headeropts_eos, read_headeropts_eos + + private + + integer, public :: ieos = 1 + integer, public :: iopacity_type = 0 ! used for radiation + real, public :: gmw = 2.381 ! default mean molecular weight + real, public :: X_in = 0.74 ! default metallicities + real, public :: Z_in = 0.02 ! default metallicities + logical, public :: use_var_comp = .false. ! use variable composition + real, public :: temperature_coef + + logical, public :: done_init_eos = .false. + ! + ! error codes for calls to init_eos + ! + integer, public, parameter :: & + ierr_file_not_found = 1, & + ierr_option_conflict = 2, & + ierr_units_not_set = 3, & + ierr_isink_not_set = 4 + +! +! Default temperature prescription for vertical stratification (0=MAPS, 1=Dartois) +! + integer, public:: istrat = 0. +! +! 2D temperature structure fit parameters for HD 163296 +! + real, public :: z0 = 1. + real, public :: alpha_z = 3.01 + real, public :: beta_z = 0.42 + +contains + +!---------------------------------------------------------------- +!+ +! subroutine returns pressure/density as a function of density +! (and position in the case of the isothermal disc) +!+ +!---------------------------------------------------------------- +subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gamma_local,mu_local,Xlocal,Zlocal) + use io, only:fatal,error,warning + use part, only:xyzmh_ptmass, nptmass + use units, only:unit_density,unit_pressure,unit_ergg,unit_velocity + use physcon, only:Rg,radconst,kb_on_mh + use eos_mesa, only:get_eos_pressure_temp_gamma1_mesa,get_eos_1overmu_mesa + use eos_helmholtz, only:eos_helmholtz_pres_sound + use eos_shen, only:eos_shen_NL3 + use eos_idealplusrad + use eos_gasradrec, only:equationofstate_gasradrec + use eos_stratified, only:get_eos_stratified + use eos_barotropic, only:get_eos_barotropic + use eos_piecewise, only:get_eos_piecewise + use eos_stamatellos + integer, intent(in) :: eos_type + real, intent(in) :: rhoi,xi,yi,zi + real, intent(out) :: ponrhoi,spsoundi + real, intent(inout) :: tempi + real, intent(in), optional :: eni + real, intent(inout), optional :: mu_local,gamma_local + real, intent(in) , optional :: Xlocal,Zlocal + integer :: ierr, i + real :: r1,r2 + real :: mass_r, mass ! defined for generalised Farris prescription + real :: gammai,temperaturei,mui,imui,X_i,Z_i + real :: cgsrhoi,cgseni,cgspresi,presi,gam1,cgsspsoundi + real :: uthermconst,kappaBar,kappaPart + real :: enthi,pondensi + ! + ! Check to see if equation of state is compatible with GR cons2prim routines + ! + if (gr .and. .not.any((/2,4,11,12/)==eos_type)) then + ponrhoi = 0.; spsoundi = 0. ! avoid compiler warning + call fatal('eos','GR currently only works for ieos=2,12 or 11',& + var='eos_type',val=real(eos_type)) + endif + + gammai = gamma + mui = gmw + X_i = X_in + Z_i = Z_in + if (present(gamma_local)) gammai = gamma_local + if (present(mu_local)) mui = mu_local + if (present(Xlocal)) X_i = Xlocal + if (present(Zlocal)) Z_i = Zlocal + + select case(eos_type) + case(1) +! +!--Isothermal eos +! +! :math:`P = c_s^2 \rho` +! +! where :math:`c_s^2 \equiv K` is a constant stored in the dump file header +! + ponrhoi = polyk + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(2,5) +! +!--Adiabatic equation of state (code default) +! +! :math:`P = (\gamma - 1) \rho u` +! +! if the code is compiled with ISOTHERMAL=yes, ieos=2 gives a polytropic eos: +! +! :math:`P = K \rho^\gamma` +! +! where K is a global constant specified in the dump header +! + if (gammai < tiny(gammai)) call fatal('eos','gamma not set for adiabatic eos',var='gamma',val=gammai) + + if (gr) then + if (.not. present(eni)) call fatal('eos','GR call to equationofstate requires thermal energy as input!') + if (eni < 0.) call fatal('eos','utherm < 0',var='u',val=eni) + if (gammai <= 1.) then + spsoundi = 0.; ponrhoi = 0. ! avoid compiler warning + call fatal('eos','GR not compatible with isothermal equation of state, yet...',var='gamma',val=gammai) + elseif (gammai > 1.0001) then + pondensi = (gammai-1.)*eni ! eni is the thermal energy + enthi = 1. + eni + pondensi ! enthalpy + spsoundi = sqrt(gammai*pondensi/enthi) + ponrhoi = pondensi ! With GR this routine actually outputs pondensi (i.e. pressure on primitive density, not conserved.) + endif + else + if (present(eni)) then + if (eni < 0.) then + !write(iprint,'(a,Es18.4,a,4Es18.4)')'Warning: eos: u = ',eni,' < 0 at {x,y,z,rho} = ',xi,yi,zi,rhoi + call fatal('eos','utherm < 0',var='u',val=eni) + endif + if (gammai > 1.0001) then + ponrhoi = (gammai-1.)*eni ! use this if en is thermal energy + else + ponrhoi = 2./3.*eni ! en is thermal energy and gamma = 1 + endif + else + ponrhoi = polyk*rhoi**(gammai-1.) + endif + spsoundi = sqrt(gammai*ponrhoi) + endif + + tempi = temperature_coef*mui*ponrhoi + + case(3) +! +!--Locally isothermal disc as in Lodato & Pringle (2007) where +! +! :math:`P = c_s^2 (r) \rho` +! +! sound speed (temperature) is prescribed as a function of radius using: +! +! :math:`c_s = c_{s,0} r^{-q}` where :math:`r = \sqrt{x^2 + y^2 + z^2}` +! + ponrhoi = polyk*(xi**2 + yi**2 + zi**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(4) +! +!--Isothermal equation of state for GR, enforcing cs = constant +! +! .. WARNING:: this is experimental: use with caution +! + uthermconst = polyk + ponrhoi = (gammai-1.)*uthermconst + spsoundi = sqrt(ponrhoi/(1.+uthermconst)) + tempi = temperature_coef*mui*ponrhoi + + case(6) +! +!--Locally isothermal disc centred on sink particle +! +! As in ieos=3 but in this version radius is taken with respect to a designated +! sink particle (by default the first sink particle in the simulation) +! + ponrhoi = polyk*((xi-xyzmh_ptmass(1,isink))**2 + (yi-xyzmh_ptmass(2,isink))**2 + & + (zi-xyzmh_ptmass(3,isink))**2)**(-qfacdisc) ! polyk is cs^2, so this is (R^2)^(-q) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(7) +! +!--Vertically stratified equation of state +! +! sound speed is prescribed as a function of (cylindrical) radius R and +! height z above the x-y plane +! +! .. WARNING:: should not be used for misaligned discs +! + call get_eos_stratified(istrat,xi,yi,zi,polyk,polyk2,qfacdisc,qfacdisc2,alpha_z,beta_z,z0,ponrhoi,spsoundi) + tempi = temperature_coef*mui*ponrhoi + + case(8) +! +!--Barotropic equation of state +! +! :math:`P = K \rho^\gamma` +! +! where the value of gamma (and K) are a prescribed function of density +! + call get_eos_barotropic(rhoi,polyk,polyk2,ponrhoi,spsoundi,gammai) + tempi = temperature_coef*mui*ponrhoi + + case(9) +! +!--Piecewise Polytropic equation of state +! +! :math:`P = K \rho^\gamma` +! +! where the value of gamma (and K) are a prescribed function of density. +! Similar to ieos=8 but with different defaults and slightly different +! functional form +! + call get_eos_piecewise(rhoi,ponrhoi,spsoundi,gammai) + tempi = temperature_coef*mui*ponrhoi + + case(10) +! +!--MESA equation of state +! +! a tabulated equation of state including gas, radiation pressure +! and ionisation/dissociation. MESA is a stellar evolution code, so +! this equation of state is designed for matter inside stars +! + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + call get_eos_pressure_temp_gamma1_mesa(cgsrhoi,cgseni,cgspresi,temperaturei,gam1,ierr) + presi = cgspresi / unit_pressure + + ponrhoi = presi / rhoi + spsoundi = sqrt(gam1*ponrhoi) + tempi = temperaturei + if (present(gamma_local)) gamma_local = gam1 ! gamma is an output + if (present(mu_local)) mu_local = 1./get_eos_1overmu_mesa(cgsrhoi,cgseni) + if (ierr /= 0) call warning('eos_mesa','extrapolating off tables') + + case(11) +! +!--Isothermal equation of state with pressure and temperature equal to zero +! +! :math:`P = 0` +! +! useful for simulating test particle dynamics using SPH particles +! + ponrhoi = 0. + spsoundi = sqrt(polyk) + tempi = 0. + + case(12) +! +!--Ideal gas plus radiation pressure +! +! :math:`P = (\gamma - 1) \rho u` +! +! but solved by first solving the quartic equation: +! +! :math:`u = \frac32 \frac{k_b T}{\mu m_H} + \frac{a T^4}{\rho}` +! +! for temperature (given u), then solving for pressure using +! +! :math:`P = \frac{k_b T}{\mu m_H} + \frac13 a T^4` +! +! hence in this equation of state gamma (and temperature) are an output +! + temperaturei = tempi ! Required as initial guess + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + call get_idealplusrad_temp(cgsrhoi,cgseni,mui,temperaturei,ierr) + call get_idealplusrad_pres(cgsrhoi,temperaturei,mui,cgspresi) + call get_idealplusrad_spsoundi(cgsrhoi,cgspresi,cgseni,spsoundi,gammai) + if (present(gamma_local)) gamma_local = gammai ! gamma is an output + spsoundi = spsoundi / unit_velocity + presi = cgspresi / unit_pressure + ponrhoi = presi / rhoi + tempi = temperaturei + if (ierr /= 0) call warning('eos_idealplusrad','temperature iteration did not converge') + + + case(13) +! +!--Locally isothermal eos for generic hierarchical system +! +! Assuming all sink particles are stars. +! Generalisation of Farris et al. (2014; for binaries) to N stars. +! For two sink particles this is identical to ieos=14 +! + mass_r = 0 + mass = 0 + + do i=1,nptmass + mass_r = mass_r+xyzmh_ptmass(4,i)/sqrt((xi-xyzmh_ptmass(1,i))**2 + (yi-xyzmh_ptmass(2,i))**2 + (zi-xyzmh_ptmass(3,i))**2) + mass = mass + xyzmh_ptmass(4,i) + enddo + ponrhoi=polyk*(mass_r)**(2*qfacdisc)/mass**(2*qfacdisc) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + + case(14) +! +!--Locally isothermal eos from Farris et al. (2014) for binary system +! +! uses the locations of the first two sink particles +! + r1 = sqrt((xi-xyzmh_ptmass(1,1))**2+(yi-xyzmh_ptmass(2,1))**2 + (zi-xyzmh_ptmass(3,1))**2) + r2 = sqrt((xi-xyzmh_ptmass(1,2))**2+(yi-xyzmh_ptmass(2,2))**2 + (zi-xyzmh_ptmass(3,2))**2) + ponrhoi=polyk*(xyzmh_ptmass(4,1)/r1+xyzmh_ptmass(4,2)/r2)**(2*qfacdisc)/(xyzmh_ptmass(4,1)+xyzmh_ptmass(4,2))**(2*qfacdisc) + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + + case(15) +! +!--Helmholtz equation of state (computed live, not tabulated) +! +! .. WARNING:: not widely tested in phantom, better to use ieos=10 +! + call eos_helmholtz_pres_sound(tempi, rhoi, ponrhoi, spsoundi, eni) + + case(16) +! +!--Shen (2012) equation of state for neutron stars +! +! this equation of state requires evolving temperature as the energy variable +! +! .. WARNING:: not tested: use with caution +! + if (present(eni)) then + cgsrhoi = rhoi * unit_density + !note eni is actually tempi + call eos_shen_NL3(cgsrhoi,eni,0.05,cgspresi,cgsspsoundi) + spsoundi=cgsspsoundi / unit_velocity + presi = cgspresi / unit_pressure + ponrhoi = presi / rhoi + tempi = eni + call warning('eos','Not sure if this is correct now that temperature is always passed into eos') + else + spsoundi = 0.; presi = 0.; ponrhoi = 0.; tempi = 0. ! to avoid compiler warnings + call fatal('eos','tried to call NL3 eos without passing temperature') + endif + + case(20) +! +!--Gas + radiation + various forms of recombination +! +! from HORMONE, Hirai+2020, as used in Lau+2022b +! + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + imui = 1./mui + if (tempi > 0.) then + temperaturei = tempi + else + temperaturei = min(0.67 * cgseni * mui / Rg, (cgseni*cgsrhoi/radconst)**0.25) + endif + call equationofstate_gasradrec(cgsrhoi,cgseni*cgsrhoi,temperaturei,imui,X_i,1.-X_i-Z_i,cgspresi,cgsspsoundi,gammai) + ponrhoi = real(cgspresi / (unit_pressure * rhoi)) + spsoundi = real(cgsspsoundi / unit_velocity) + tempi = temperaturei + if (present(mu_local)) mu_local = 1./imui + if (present(gamma_local)) gamma_local = gammai + + case(21) +! +!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=8 +! + if (eni < 0.) then + call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) + endif + cgsrhoi = rhoi * unit_density + cgseni = eni * unit_ergg + call getopac_opdep(cgseni,cgsrhoi,kappaBar,kappaPart,tempi,mui) + cgspresi = kb_on_mh*cgsrhoi*tempi/mui + presi = cgspresi/unit_pressure + ponrhoi = presi/rhoi + gammai = 1.d0 + presi/(eni*rhoi) + !if (gammai < 1.d0 .or. gammai > 2.d0) then + ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi + !endif + spsoundi = sqrt(gammai*ponrhoi) + + case default + spsoundi = 0. ! avoids compiler warnings + ponrhoi = 0. + tempi = 0. + call fatal('eos','unknown equation of state') + end select + +end subroutine equationofstate + +!----------------------------------------------------------------------- +!+ +! initialise equation of state (read tables etc.) +!+ +!----------------------------------------------------------------------- +subroutine init_eos(eos_type,ierr) + use units, only:unit_velocity + use physcon, only:Rg + use io, only:error,warning,fatal + use eos_mesa, only:init_eos_mesa + use eos_helmholtz, only:eos_helmholtz_init + use eos_piecewise, only:init_eos_piecewise + use eos_barotropic, only:init_eos_barotropic + use eos_shen, only:init_eos_shen_NL3 + use eos_gasradrec, only:init_eos_gasradrec + use eos_stamatellos,only:read_optab,init_S07cool,eos_file + use dim, only:maxvxyzu,do_radiation + integer, intent(in) :: eos_type + integer, intent(out) :: ierr + integer :: ierr_mesakapp + + ierr = 0 + ! + !--Set coefficient to convert P/rho into temperature + ! calculation will be in cgs; the mean molecular weight, gmw, will be + ! included in the function call rather than here + ! c_s^2 = gamma*P/rho = gamma*kT/(gmw*m_p) -> T = P/rho * (gmw*m_p)/k + ! + temperature_coef = unit_velocity**2 / Rg + + select case(eos_type) + case(6) + ! + !--Check that if using ieos=6, then isink is set properly + ! + if (isink==0) then + call error('eos','ieos=6, but isink is not set') + ierr = ierr_isink_not_set + return + endif + + case(8) + ! + ! barotropic equation of state + ! + call init_eos_barotropic(polyk,polyk2,ierr) + + case(9) + ! + ! piecewise polytropic equation of state (similar to barotropic) + ! + call init_eos_piecewise(ierr) + + case(10) + ! + !--MESA EoS initialisation + ! + write(*,'(1x,a,f7.5,a,f7.5)') 'Initialising MESA EoS with X = ',X_in,', Z = ',Z_in + call init_eos_mesa(X_in,Z_in,ierr) + if (do_radiation .and. ierr==0) then + call error('eos','ieos=10, cannot use eos with radiation, will double count radiation pressure') + ierr=ierr_option_conflict !return error if using radiation and mesa EOS, shouldn't use mesa eos, as it will double count rad pres + endif + + case(12) + ! + ! ideal plus radiation + ! + write(*,'(1x,a,f7.5)') 'Using ideal plus radiation EoS with mu = ',gmw + if (do_radiation) then + call error('eos','ieos=12, cannot use eos with radiation, will double count radiation pressure') + ierr = ierr_option_conflict + endif + + case(15) + + call eos_helmholtz_init(ierr) + + case(16) + + call init_eos_shen_NL3(ierr) + + case(20) + + call init_eos_gasradrec(ierr) + if (.not. use_var_comp) then + write(*,'(a,f7.5,a,f7.5)') 'Assuming fixed composition X = ',X_in,', Z = ',Z_in + endif + if (do_radiation) then + call error('eos','ieos=20, cannot use eos with radiation, will double count radiation pressure') + ierr = ierr_option_conflict + endif + + case(21) + call read_optab(eos_file,ierr) + if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) + call init_S07cool + + end select + done_init_eos = .true. + + if (do_radiation .and. iopacity_type==1) then + write(*,'(1x,a,f7.5,a,f7.5)') 'Using radiation with MESA opacities. Initialising MESA EoS with X = ',X_in,', Z = ',Z_in + call init_eos_mesa(X_in,Z_in,ierr_mesakapp) + ierr = max(ierr,ierr_mesakapp) + endif + +end subroutine init_eos + +!----------------------------------------------------------------------- +!+ +! finish equation of state +!+ +!----------------------------------------------------------------------- +subroutine finish_eos(eos_type,ierr) + use eos_mesa, only: finish_eos_mesa + use eos_stamatellos, only: finish_S07cool + + integer, intent(in) :: eos_type + integer, intent(out) :: ierr + + ierr = 0 + + select case(eos_type) + case(10) + ! + !--MESA EoS deallocation + ! + call finish_eos_mesa + + case(21) + ! Stamatellos deallocation + call finish_S07cool + + end select + done_init_eos=.false. + +end subroutine finish_eos + +!----------------------------------------------------------------------- +!+ +! Calculate gas temperature, sound speed, and pressure. +! This will be required for various analysis routines if eos_vars +! is not saved in the dump files +!+ +!----------------------------------------------------------------------- +subroutine get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi,spsoundi,gammai,mui,Xi,Zi) + use dim, only:maxvxyzu + integer, intent(in) :: eos_type + real, intent(in) :: vxyzui(:),xyzi(:),rhoi + real, intent(inout) :: tempi + real, intent(out), optional :: presi,spsoundi + real, intent(inout), optional :: gammai,mui + real, intent(in), optional :: Xi,Zi + real :: csi,ponrhoi,mu,X,Z + logical :: use_gamma + + mu = gmw + X = X_in + Z = Z_in + if (present(mui)) mu = mui + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + use_gamma = .false. + if (present(gammai)) then + if (gammai > 0.) use_gamma = .true. + endif + + if (maxvxyzu==4) then + 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) + else + call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,vxyzui(4),& + mu_local=mu,Xlocal=X,Zlocal=Z) + endif + else + call equationofstate(eos_type,ponrhoi,csi,rhoi,xyzi(1),xyzi(2),xyzi(3),tempi,mu_local=mu) + endif + + if (present(presi)) presi = ponrhoi*rhoi + if (present(spsoundi)) spsoundi = csi + if (present(mui)) mui = mu + if (present(gammai)) gammai = gamma + +end subroutine get_TempPresCs + +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate sound speed +!+ +!----------------------------------------------------------------------- +real function get_spsound(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xyzi(:),rhoi + real, intent(in) :: vxyzui(:) + real, intent(in), optional :: Xi,Zi + real, intent(inout), optional :: gammai,mui + real :: spsoundi,tempi,gam,mu,X,Z + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,spsoundi=spsoundi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_spsound = spsoundi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + +end function get_spsound + +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate temperature +!+ +!----------------------------------------------------------------------- +real function get_temperature(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xyzi(:),rhoi + real, intent(in) :: vxyzui(:) + real, intent(in), optional :: Xi,Zi + real, intent(inout),optional :: gammai,mui + real :: tempi,gam,mu,X,Z + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_temperature = tempi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + +end function get_temperature + + +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate temperature +!+ +!----------------------------------------------------------------------- +real function get_temperature_from_u(eos_type,xpi,ypi,zpi,rhoi,ui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xpi,ypi,zpi,rhoi + real, intent(in) :: ui + real, intent(in), optional :: Xi,Zi + real, intent(inout),optional :: gammai,mui + real :: tempi,gam,mu,X,Z + real :: vxyzui(4),xyzi(3) + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + vxyzui = (/0.,0.,0.,ui/) + xyzi = (/xpi,ypi,zpi/) + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_temperature_from_u = tempi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + + +end function get_temperature_from_u +!----------------------------------------------------------------------- +!+ +! Wrapper function to calculate pressure +!+ +!----------------------------------------------------------------------- +real function get_pressure(eos_type,xyzi,rhoi,vxyzui,gammai,mui,Xi,Zi) + integer, intent(in) :: eos_type + real, intent(in) :: xyzi(:),rhoi,vxyzui(:) + real, intent(in), optional :: Xi,Zi + real, intent(inout),optional :: gammai,mui + real :: presi,tempi,gam,mu,X,Z + + !set defaults for variables not passed in + mu = gmw + X = X_in + Z = Z_in + tempi = -1. ! needed because temperature is an in/out to some equations of state, -ve == use own guess + gam = -1. ! to indicate gamma is not being passed in + if (present(mui)) mu = mui + if (present(Xi)) X = Xi + if (present(Zi)) Z = Zi + if (present(gammai)) gam = gammai + if (present(mui)) mu = mui + + call get_TempPresCs(eos_type,xyzi,vxyzui,rhoi,tempi,presi=presi,gammai=gam,mui=mu,Xi=X,Zi=Z) + + get_pressure = presi + + if (present(mui)) mui = mu + if (present(gammai)) gammai = gam + +end function get_pressure + +!----------------------------------------------------------------------- +!+ +! query function to return the internal energy for calculations with a +! local mean molecular weight and local adiabatic index +!+ +!----------------------------------------------------------------------- +real function get_local_u_internal(gammai, gmwi, gas_temp_local) + real, intent(in) :: gammai, gmwi, gas_temp_local + real :: ponrhoi + + ponrhoi = gas_temp_local/(gmwi*temperature_coef) + get_local_u_internal = ponrhoi/(gammai-1.) + +end function get_local_u_internal + +!----------------------------------------------------------------------- +!+ +! get u from rho, T +!+ +!----------------------------------------------------------------------- +real function get_u_from_rhoT(rho,temp,eos_type,uguess) result(u) + use eos_mesa, only:get_eos_u_from_rhoT_mesa + integer, intent(in) :: eos_type + real, intent(in) :: rho,temp + real, intent(in), optional :: uguess + + select case (eos_type) + case(10) ! MESA EoS + if (present(uguess)) then + call get_eos_u_from_rhoT_mesa(rho,temp,u,uguess) + else + call get_eos_u_from_rhoT_mesa(rho,temp,u) + endif + + case default + u = temp/(gmw*temperature_coef*(gamma-1.)) + end select + +end function get_u_from_rhoT + +!----------------------------------------------------------------------- +!+ +! Get recombination energy (per unit mass) assumming complete +! ionisation +!+ +!----------------------------------------------------------------------- +subroutine calc_rec_ene(XX,YY,e_rec) + real, intent(in) :: XX, YY + real, intent(out) :: e_rec + real :: e_H2,e_HI,e_HeI,e_HeII + real, parameter :: e_ion_H2 = 1.312e13, & ! ionisation energies in erg/mol + e_ion_HI = 4.36e12, & + e_ion_HeI = 2.3723e13, & + e_ion_HeII = 5.2505e13 + + ! XX : Hydrogen mass fraction + ! YY : Helium mass fraction + ! e_rec : Total ionisation energy due to H2, HI, HeI, and HeII + + e_H2 = 0.5 * XX * e_ion_H2 + e_HI = XX * e_ion_HI + e_HeI = 0.25 * YY * e_ion_HeI + e_HeII = 0.25 * YY * e_ion_HeII + e_rec = e_H2 + e_HI + e_HeI + e_HeII + +end subroutine calc_rec_ene + +!----------------------------------------------------------------------- +!+ +! Calculate temperature and specific internal energy from +! pressure and density. Inputs and outputs are in cgs units. +! +! Note on composition: +! For ieos=2, 5 and 12, mu_local is an input, X & Z are not used +! For ieos=10, mu_local is not used +! For ieos=20, mu_local is not used but available as an output +!+ +!----------------------------------------------------------------------- +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 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 + integer, intent(in) :: eos_type + real, intent(in) :: rho,pres + real, intent(inout) :: ene,temp + real, intent(in), optional :: guesseint,X_local,Z_local + real, intent(inout), optional :: mu_local + integer, intent(out) :: ierr + real :: mu,X,Z + + ierr = 0 + mu = gmw + X = X_in + Z = Z_in + if (present(mu_local)) mu = mu_local + if (present(X_local)) X = X_local + if (present(Z_local)) Z = Z_local + select case(eos_type) + case(2,5) ! Ideal gas + temp = pres / (rho * kb_on_mh) * mu + ene = pres / ( (gamma-1.) * rho) + case(12) ! Ideal gas + radiation + call get_idealgasplusrad_tempfrompres(pres,rho,mu,temp) + call get_idealplusrad_enfromtemp(rho,temp,mu,ene) + case(10) ! MESA EoS + call get_eos_eT_from_rhop_mesa(rho,pres,ene,temp,guesseint) + case(20) ! Ideal gas + radiation + recombination (from HORMONE, Hirai et al., 2020) + call calc_uT_from_rhoP_gasradrec(rho,pres,X,1.-X-Z,temp,ene,mu,ierr) + if (present(mu_local)) mu_local = mu + case default + ierr = 1 + end select + +end subroutine calc_temp_and_ene + +!----------------------------------------------------------------------- +!+ +! Calculate density from pressure and temperature. Inputs and outputs +! are in cgs units. +! +! Note on composition: +! For ieos=2 and 12, mu_local is an input, X & Z are not used +! For ieos=10, mu_local is not used +! For ieos=20, mu_local is not used but available as an output +!+ +!----------------------------------------------------------------------- +subroutine calc_rho_from_PT(eos_type,pres,temp,rho,ierr,mu_local,X_local,Z_local) + use physcon, only:kb_on_mh + 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 + integer, intent(in) :: eos_type + real, intent(in) :: pres,temp + real, intent(inout) :: rho + real, intent(in), optional :: X_local,Z_local + real, intent(inout), optional :: mu_local + integer, intent(out) :: ierr + real :: mu,X,Z + + ierr = 0 + mu = gmw + X = X_in + Z = Z_in + if (present(mu_local)) mu = mu_local + if (present(X_local)) X = X_local + if (present(Z_local)) Z = Z_local + select case(eos_type) + case(2) ! Ideal gas + rho = pres / (temp * kb_on_mh) * mu + case(12) ! Ideal gas + radiation + call get_idealplusrad_rhofrompresT(pres,temp,mu,rho) + case default + ierr = 1 + end select + +end subroutine calc_rho_from_PT + +!----------------------------------------------------------------------- +!+ +! Calculates specific entropy (gas + radiation + recombination) +! up to an additive integration constant, from density and pressure. +!+ +!----------------------------------------------------------------------- +function entropy(rho,pres,mu_in,ientropy,eint_in,ierr) + use io, only:fatal,warning + use physcon, only:radconst,kb_on_mh + 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 + integer, intent(in) :: ientropy + integer, intent(out), optional :: ierr + real :: mu,entropy,logentropy,temp,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) + + ! check temp + if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') + + 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) + + ! check temp + if (temp < tiny(0.)) call warning('entropy','temperature = 0 will give minus infinity with s entropy') + + 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') + + if (present(eint_in)) then + eint = eint_in + else + call get_eos_eT_from_rhop_mesa(rho,pres,eint,temp) + endif + + ! Get entropy from rho and eint from MESA tables + if (present(ierr)) then + call getvalue_mesa(rho,eint,9,logentropy,ierr) + else + call getvalue_mesa(rho,eint,9,logentropy) + endif + entropy = 10.**logentropy + + case default + entropy = 0. + call fatal('eos','Unknown ientropy (can only be 1, 2, or 3)') + end select + +end function entropy + +real function get_entropy(rho,pres,mu_in,ieos) + use units, only:unit_density,unit_pressure,unit_ergg + use physcon, only:kboltz + integer, intent(in) :: ieos + real, intent(in) :: rho,pres,mu_in + real :: cgsrho,cgspres,cgss + + cgsrho = rho * unit_density + cgspres = pres * unit_pressure + select case (ieos) + case (12) + cgss = entropy(cgsrho,cgspres,mu_in,2) + case (10, 20) + cgss = entropy(cgsrho,cgspres,mu_in,3) + case default + cgss = entropy(cgsrho,cgspres,mu_in,1) + end select + cgss = cgss/kboltz ! s/kb + get_entropy = cgss/unit_ergg + +end function get_entropy + +!----------------------------------------------------------------------- +!+ +! Calculate density given pressure and entropy using Newton-Raphson +! method +!+ +!----------------------------------------------------------------------- +subroutine get_rho_from_p_s(pres,S,rho,mu,rhoguess,ientropy) + real, intent(in) :: pres,S,mu,rhoguess + real, intent(inout) :: rho + real :: srho,srho_plus_dsrho,S_plus_dS,dSdsrho + real(kind=8) :: corr + real, parameter :: eoserr=1e-9,dfac=1e-12 + integer, intent(in) :: ientropy + + ! We apply the Newton-Raphson method directly to rho^1/2 ("srho") instead + ! of rho since S(rho) cannot take a negative argument. + srho = sqrt(rhoguess) ! Initial guess + corr = huge(corr); + do while (abs(corr) > eoserr*abs(srho)) + ! First calculate dS/dsrho + srho_plus_dsrho = srho * (1. + dfac) + S_plus_dS = entropy(srho_plus_dsrho**2,pres,mu,ientropy) + dSdsrho = (S_plus_dS - entropy(srho**2,pres,mu,ientropy)) / (srho_plus_dsrho - srho) + corr = ( entropy(srho**2,pres,mu,ientropy) - S ) / dSdsrho + srho = srho - corr + enddo + rho = srho**2 + +end subroutine get_rho_from_p_s + +!----------------------------------------------------------------------- +!+ +! Calculate temperature given density and entropy using Newton-Raphson +! method +!+ +!----------------------------------------------------------------------- +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 io, only:fatal + use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_pres + use units, only:unit_density,unit_pressure,unit_ergg + real, intent(in) :: S,mu,rho + real, intent(inout) :: temp + real, intent(out) :: P + integer, intent(in) :: ieos + real :: corr,df,f,temp_new,cgsrho,cgsp,cgss + real, parameter :: eoserr=1e-12 + integer :: niter + integer, parameter :: nitermax = 1000 + + ! change to cgs unit + cgsrho = rho*unit_density + cgss = s*unit_ergg + + niter = 0 + select case (ieos) + case (2,5) + temp = (cgsrho * exp(mu*cgss*mass_proton_cgs))**(2./3.) + cgsP = cgsrho*kb_on_mh*temp / mu + case (12) + corr = huge(corr) + do while (abs(corr) > eoserr .and. niter < nitermax) + f = 1. / (mu*mass_proton_cgs) * log(temp**1.5/cgsrho) + 4.*radconst*temp**3 / (3.*cgsrho*kboltz) - cgss + df = 1.5 / (mu*temp*mass_proton_cgs) + 4.*radconst*temp**2 / (cgsrho*kboltz) + corr = f/df + temp_new = temp - corr + if (temp_new > 1.2 * temp) then + temp = 1.2 * temp + elseif (temp_new < 0.8 * temp) then + temp = 0.8 * temp + else + temp = temp_new + endif + niter = niter + 1 + enddo + call get_idealplusrad_pres(cgsrho,temp,mu,cgsP) + case default + cgsP = 0. + call fatal('eos','[get_p_from_rho_s] only implemented for eos 2 and 12') + end select + + ! check temp + if (temp > huge(0.)) call fatal('entropy','entropy too large gives infinte temperature, & + &reducing entropy factor C_ent for one dump') + + ! change back to code unit + P = cgsP / unit_pressure + +end subroutine get_p_from_rho_s + +!----------------------------------------------------------------------- +!+ +! Calculate mean molecular weight from X and Z, assuming complete +! ionisation +!+ +!----------------------------------------------------------------------- +real function get_mean_molecular_weight(XX,ZZ) result(mu) + real, intent(in) :: XX,ZZ + real :: YY + + YY = 1.-XX-ZZ + mu = 1./(2.*XX + 0.75*YY + 0.5*ZZ) + +end function get_mean_molecular_weight + +!--------------------------------------------------------- +!+ +! return cv from rho, u in code units +!+ +!--------------------------------------------------------- +real function get_cv(rho,u,cv_type) result(cv) + use mesa_microphysics, only:getvalue_mesa + use units, only:unit_ergg,unit_density + use physcon, only:Rg + real, intent(in) :: rho,u + integer, intent(in) :: cv_type + real :: rho_cgs,u_cgs,temp + + select case (cv_type) + + case(1) ! MESA EoS + rho_cgs = rho*unit_density + u_cgs = u*unit_ergg + call getvalue_mesa(rho_cgs,u_cgs,4,temp) + cv = u_cgs/temp / unit_ergg + case default ! constant cv + cv = Rg/((gamma-1.)*gmw*unit_ergg) + end select + +end function get_cv + +!----------------------------------------------------------------------- +!+ +! subroutine sets polyk based on utherm/positions +! read from an sphNG dump file +!+ +!----------------------------------------------------------------------- +subroutine setpolyk(eos_type,iprint,utherm,xyzhi,npart) + use part, only:xyzmh_ptmass + use io, only:id,master + integer, intent(in) :: eos_type,iprint + real, intent(in) :: utherm(:) + real, intent(in) :: xyzhi(:,:) + integer, intent(in) :: npart + integer :: ipart + real :: r2,polykalt + + !-- pick a random particle from which to extract polyk + ipart = npart/2 + + select case(eos_type) + case(1,8) +! +!--isothermal eos +! + polykalt = 2./3.*utherm(ipart) + !--check all other utherms identical + if (any(utherm(1:npart) /= utherm(ipart)) .and. id==master) then + write(iprint,*) 'WARNING! different utherms but run is isothermal' + endif + + case(2,5) +! +!--adiabatic/polytropic eos +! this routine is ONLY called if utherm is NOT stored, so polyk matters +! + if (id==master) write(iprint,*) 'Using polytropic equation of state, gamma = ',gamma + polykalt = 2./3.*utherm(ipart) + if (gamma <= 1.00000001) then + stop 'silly to use gamma==1 without using isothermal eos' + endif + + case(3) +! +!--locally isothermal disc as in Lodato & Pringle (2007) +! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) +! + r2 = xyzhi(1,ipart)*xyzhi(1,ipart) + xyzhi(2,ipart)*xyzhi(2,ipart) & + + xyzhi(3,ipart)*xyzhi(3,ipart) + polykalt = 2./3.*utherm(ipart)*r2**qfacdisc + + case(6) +! +!--locally isothermal disc as in Lodato & Pringle (2007), centered on specified sink particle +! cs = cs_0*R^(-q) -- polyk is cs^2, so this is (R^2)^(-q) +! + r2 = (xyzhi(1,ipart)-xyzmh_ptmass(1,isink))**2 + & + (xyzhi(2,ipart)-xyzmh_ptmass(2,isink))**2 + & + (xyzhi(3,ipart)-xyzmh_ptmass(3,isink))**2 + + polykalt = 2./3.*utherm(ipart)*r2**qfacdisc + case default +! +!--don't die in this routine as it can be called from readdump +! (ie. not necessarily as part of a run) +! + if (id==master) write(iprint,*) ' WARNING! unknown equation of state in setpolyk' + polykalt = polyk + + end select + + if (diff(polykalt,polyk) .and. id==master) then + write(iprint,*) 'WARNING! polyk set using RK2 in dump differs from that set using thermal energy' + write(iprint,*) 'using polyk = ',polykalt, ' (from RK2 = ',polyk,')' + endif + polyk = polykalt +! +!--warn if polyk is zero, die if negative +! + if (polyk < 0.) then + write(iprint,*) 'ERROR: polyk < 0 in setting equation of state' + stop + elseif (polyk < tiny(polyk) .and. id==master) then + write(iprint,*) 'WARNING: polyk = 0 in equation of state' + endif + +end subroutine setpolyk +!----------------------------------------------------------------------- +!+ +! small utility returns whether two real numbers differ +!+ +!----------------------------------------------------------------------- +logical pure function diff(r1,r2) + real, intent(in) :: r1,r2 + + diff = abs(r1-r2) > tiny(r1) + +end function diff + +!----------------------------------------------------------------------- +!+ +! Query function to return whether an EoS is non-ideal +! Mainly used to decide whether it is necessary to write +! things like pressure and temperature in the dump file or not +!+ +!----------------------------------------------------------------------- +logical function eos_is_non_ideal(ieos) + integer, intent(in) :: ieos + + select case(ieos) + case(10,12,15,20) + eos_is_non_ideal = .true. + case default + eos_is_non_ideal = .false. + end select + +end function eos_is_non_ideal + +!----------------------------------------------------------------------- +!+ +! Query function to return whether an EoS outputs mean molecular weight +!+ +!----------------------------------------------------------------------- +logical function eos_outputs_mu(ieos) + integer, intent(in) :: ieos + + select case(ieos) + case(20) + eos_outputs_mu = .true. + case(21) + eos_outputs_mu = .true. +case default + eos_outputs_mu = .false. + end select + +end function eos_outputs_mu + +!----------------------------------------------------------------------- +!+ +! Query function to whether to print pressure to dump file +!+ +!----------------------------------------------------------------------- +logical function eos_outputs_gasP(ieos) + integer, intent(in) :: ieos + + select case(ieos) + case(8,9,10,15) + eos_outputs_gasP = .true. + case default + eos_outputs_gasP = .false. + end select + +end function eos_outputs_gasP + +!----------------------------------------------------------------------- +!+ +! prints equation of state info in the run header +!+ +!----------------------------------------------------------------------- +subroutine eosinfo(eos_type,iprint) + use dim, only:maxvxyzu + use io, only:fatal,id,master + use eos_helmholtz, only:eos_helmholtz_eosinfo + use eos_barotropic, only:eos_info_barotropic + use eos_piecewise, only:eos_info_piecewise + use eos_gasradrec, only:eos_info_gasradrec + use eos_stamatellos, only:eos_file + integer, intent(in) :: eos_type,iprint + + if (id/=master) return + + select case(eos_type) + case(1,11) + if (1.0d-5 < polyk .and. polyk < 1.0d3) then + write(iprint,"(/,a,f10.6)") ' Isothermal equation of state: cs^2 = ',polyk + else + write(iprint,"(/,a,Es13.6)") ' Isothermal equation of state: cs^2 = ',polyk + endif + if (eos_type==11) write(iprint,*) ' (ZERO PRESSURE) ' + case(2) + if (maxvxyzu >= 4) then + write(iprint,"(/,a,f10.6,a,f10.6)") ' Adiabatic equation of state: P = (gamma-1)*rho*u, gamma = ',& + gamma,' gmw = ',gmw + else + write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6)") ' Polytropic equation of state: P = ',polyk,'*rho^',gamma,' gmw = ',gmw + endif + case(3) + write(iprint,"(/,a,f10.6,a,f10.6)") ' Locally isothermal eq of state (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc + case(5) + if (maxvxyzu >= 4) then + write(iprint,"(' Adiabatic equation of state: P = (gamma-1)*rho*u, where gamma & mu depend on the formation of H2')") + else + stop '[stop eos] eos = 5 cannot assume isothermal conditions' + endif + case(6) + write(iprint,"(/,a,i2,a,f10.6,a,f10.6)") ' Locally (on sink ',isink, & + ') isothermal eos (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc + case(8) + call eos_info_barotropic(polyk,polyk2,iprint) + case(9) + call eos_info_piecewise(iprint) + case(10) + write(iprint,"(/,a,f10.6,a,f10.6,a,f10.6,a)") ' MESA EoS: X = ',X_in,' Z = ',Z_in,' (1-X-Z = ',1.-X_in-Z_in,')' + case(12) + write(iprint,"(/,a,f10.6,a,f10.6)") ' Gas + radiation equation of state: gmw = ',gmw,' gamma = ',gamma + case(15) + call eos_helmholtz_eosinfo(iprint) + case(20) + call eos_info_gasradrec(iprint) + if (use_var_comp) then + write(*,'(1x,a,i1,a)') 'Using variable composition' + else + write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in + endif + + case(21) + write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file, 'and calculated gamma.' + end select + write(iprint,*) + +end subroutine eosinfo + +!----------------------------------------------------------------------- +!+ +! write relevant options to the header of the dump file +!+ +!----------------------------------------------------------------------- +subroutine write_headeropts_eos(ieos,hdr,ierr) + use dump_utils, only:dump_h,add_to_rheader,add_to_iheader + integer, intent(in) :: ieos + type(dump_h), intent(inout) :: hdr + integer, intent(out) :: ierr + + call add_to_iheader(isink,'isink',hdr,ierr) + call add_to_rheader(gamma,'gamma',hdr,ierr) + call add_to_rheader(1.5*polyk,'RK2',hdr,ierr) + call add_to_rheader(polyk2,'polyk2',hdr,ierr) + call add_to_rheader(qfacdisc,'qfacdisc',hdr,ierr) + call add_to_rheader(qfacdisc2,'qfacdisc2',hdr,ierr) + + if (ieos==7) then + call add_to_iheader(istrat,'istrat',hdr,ierr) + call add_to_rheader(alpha_z,'alpha_z',hdr,ierr) + call add_to_rheader(beta_z,'beta_z',hdr,ierr) + call add_to_rheader(z0,'z0',hdr,ierr) + endif + +end subroutine write_headeropts_eos + +!----------------------------------------------------------------------- +!+ +! read relevant options from the header of the dump file +!+ +!----------------------------------------------------------------------- +subroutine read_headeropts_eos(ieos,hdr,ierr) + use dump_utils, only:dump_h, extract + use io, only:iprint,id,master + use dim, only:use_krome,maxvxyzu + integer, intent(in) :: ieos + type(dump_h), intent(in) :: hdr + integer, intent(out) :: ierr + real :: RK2 + + + call extract('gamma',gamma,hdr,ierr) + call extract('RK2',rk2,hdr,ierr) + polyk = 2./3.*rk2 + if (id==master) then + if (maxvxyzu >= 4) then + if (use_krome) then + write(iprint,*) 'KROME eos: initial gamma = 1.666667' + elseif (ieos==21) then + write(iprint,*) 'Tabulated eos with derived gamma' + else + write(iprint,*) 'adiabatic eos: gamma = ',gamma + endif + else + write(iprint,*) 'setting isothermal sound speed^2 (polyk) = ',polyk,' gamma = ',gamma + if (polyk <= tiny(polyk)) write(iprint,*) 'WARNING! sound speed zero in dump!, polyk = ',polyk + endif + endif + call extract('polyk2',polyk2,hdr,ierr) + call extract('qfacdisc',qfacdisc,hdr,ierr) + call extract('qfacdisc2',qfacdisc2,hdr,ierr) + call extract('isink',isink,hdr,ierr) + + if (abs(gamma-1.) > tiny(gamma) .and. maxvxyzu < 4) then + write(*,*) 'WARNING! compiled for isothermal equation of state but gamma /= 1, gamma=',gamma + endif + + ierr = 0 + if (ieos==3 .or. ieos==6 .or. ieos==7) then + if (qfacdisc <= tiny(qfacdisc)) then + if (id==master) write(iprint,*) 'ERROR: qfacdisc <= 0' + ierr = 2 + else + if (id==master) write(iprint,*) 'qfacdisc = ',qfacdisc + endif + endif + + if (ieos==7) then + call extract('istrat',istrat,hdr,ierr) + call extract('alpha_z',alpha_z,hdr,ierr) + call extract('beta_z', beta_z, hdr,ierr) + call extract('z0',z0,hdr,ierr) + if (abs(qfacdisc2) <= tiny(qfacdisc2)) then + if (id==master) write(iprint,*) 'ERROR: qfacdisc2 == 0' + ierr = 2 + else + if (id==master) write(iprint,*) 'qfacdisc2 = ',qfacdisc2 + endif + endif + +end subroutine read_headeropts_eos + +!----------------------------------------------------------------------- +!+ +! writes equation of state options to the input file +!+ +!----------------------------------------------------------------------- +subroutine write_options_eos(iunit) + use dim, only:use_krome + use infile_utils, only:write_inopt + use eos_helmholtz, only:eos_helmholtz_write_inopt + use eos_barotropic, only:write_options_eos_barotropic + use eos_piecewise, only:write_options_eos_piecewise + use eos_gasradrec, only:write_options_eos_gasradrec + integer, intent(in) :: iunit + + write(iunit,"(/,a)") '# options controlling equation of state' + call write_inopt(ieos,'ieos','eqn of state (1=isoth;2=adiab;3=locally iso;8=barotropic)',iunit) + + if (.not.use_krome .or. .not.eos_outputs_mu(ieos)) then + call write_inopt(gmw,'mu','mean molecular weight',iunit) + endif + + select case(ieos) + case(8) + call write_options_eos_barotropic(iunit) + case(9) + call write_options_eos_piecewise(iunit) + case(10) + call write_inopt(X_in,'X','hydrogen mass fraction',iunit) + call write_inopt(Z_in,'Z','metallicity',iunit) + case(15) ! helmholtz eos + call eos_helmholtz_write_inopt(iunit) + case(20) + call write_options_eos_gasradrec(iunit) + if (.not. use_var_comp) then + call write_inopt(X_in,'X','H mass fraction (ignored if variable composition)',iunit) + call write_inopt(Z_in,'Z','metallicity (ignored if variable composition)',iunit) + endif + end select + +end subroutine write_options_eos + +!----------------------------------------------------------------------- +!+ +! reads equation of state options from the input file +!+ +!----------------------------------------------------------------------- +subroutine read_options_eos(name,valstring,imatch,igotall,ierr) + use dim, only:store_dust_temperature,update_muGamma + use io, only:fatal + use eos_barotropic, only:read_options_eos_barotropic + use eos_piecewise, only:read_options_eos_piecewise + use eos_gasradrec, only:read_options_eos_gasradrec + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotall + integer, intent(out) :: ierr + integer, save :: ngot = 0 + character(len=30), parameter :: label = 'read_options_eos' + logical :: igotall_barotropic,igotall_piecewise,igotall_gasradrec + + imatch = .true. + igotall_barotropic = .true. + igotall_piecewise = .true. + igotall_gasradrec = .true. + + select case(trim(name)) + case('ieos') + read(valstring,*,iostat=ierr) ieos + ngot = ngot + 1 + if (ieos <= 0 .or. ieos > maxeos) call fatal(label,'equation of state choice out of range') + if (ieos == 5) then + store_dust_temperature = .true. + update_muGamma = .true. + endif + case('mu') + read(valstring,*,iostat=ierr) gmw + ! not compulsory to read in + if (gmw <= 0.) call fatal(label,'mu <= 0') + case('X') + read(valstring,*,iostat=ierr) X_in + if (X_in <= 0. .or. X_in >= 1.) call fatal(label,'X must be between 0 and 1') + ngot = ngot + 1 + case('Z') + read(valstring,*,iostat=ierr) Z_in + if (Z_in <= 0. .or. Z_in > 1.) call fatal(label,'Z must be between 0 and 1') + ngot = ngot + 1 + case default + imatch = .false. + end select + if (.not.imatch .and. ieos== 8) call read_options_eos_barotropic(name,valstring,imatch,igotall_barotropic,ierr) + if (.not.imatch .and. ieos== 9) call read_options_eos_piecewise( name,valstring,imatch,igotall_piecewise, ierr) + if (.not.imatch .and. ieos==20) call read_options_eos_gasradrec( name,valstring,imatch,igotall_gasradrec, ierr) + + !--make sure we have got all compulsory options (otherwise, rewrite input file) + igotall = (ngot >= 1) .and. igotall_piecewise .and. igotall_barotropic .and. igotall_gasradrec + +end subroutine read_options_eos + + +!----------------------------------------------------------------------- + +end module eos diff --git a/src/main/eos_gasradrec.f90 b/src/main/eos_gasradrec.f90 index d8e949aba..831a9302e 100644 --- a/src/main/eos_gasradrec.f90 +++ b/src/main/eos_gasradrec.f90 @@ -23,6 +23,7 @@ module eos_gasradrec public :: equationofstate_gasradrec,calc_uT_from_rhoP_gasradrec,read_options_eos_gasradrec,& write_options_eos_gasradrec,eos_info_gasradrec,init_eos_gasradrec private + real, parameter :: eoserr=1.e-15,W4err=1.e-2 contains !----------------------------------------------------------------------- @@ -39,7 +40,6 @@ subroutine equationofstate_gasradrec(d,eint,T,imu,X,Y,p,cf,gamma_eff) real, intent(in) :: X,Y real, intent(out) :: p,cf,gamma_eff real :: corr,erec,derecdT,dimurecdT,Tdot,logd,dt,Tguess - real, parameter :: W4err=1.e-2,eoserr=1.e-13 integer, parameter :: nmax = 500 integer n @@ -69,6 +69,7 @@ subroutine equationofstate_gasradrec(d,eint,T,imu,X,Y,p,cf,gamma_eff) print*,'d=',d,'eint=',eint/d,'Tguess=',Tguess,'mu=',1./imu,'T=',T,'erec=',erec call fatal('eos_gasradrec','Failed to converge on temperature in equationofstate_gasradrec') endif + call get_erec_imurec(logd,T,X,Y,erec,imu) p = ( Rg*imu*d + radconst*T**3/3. )*T gamma_eff = 1.+p/(eint-d*erec) cf = sqrt(gamma_eff*p/d) @@ -92,7 +93,6 @@ subroutine calc_uT_from_rhoP_gasradrec(rhoi,presi,X,Y,T,eni,mui,ierr) integer, intent(out) :: ierr integer :: n real :: logrhoi,imu,dimurecdT,dT,Tdot,corr - real, parameter :: W4err=1.e-2,eoserr=1.e-13 if (T <= 0.) T = min((3.*presi/radconst)**0.25, presi/(rhoi*Rg)) ! initial guess for temperature ierr = 0 diff --git a/src/main/eos_idealplusrad.f90 b/src/main/eos_idealplusrad.f90 index b48c73974..e2a6c10aa 100644 --- a/src/main/eos_idealplusrad.f90 +++ b/src/main/eos_idealplusrad.f90 @@ -20,7 +20,7 @@ module eos_idealplusrad ! use physcon, only:Rg,radconst implicit none - real, parameter :: tolerance = 1e-15 + real, parameter :: tolerance = 1.e-15 public :: get_idealplusrad_temp,get_idealplusrad_pres,get_idealplusrad_spsoundi,& get_idealgasplusrad_tempfrompres,get_idealplusrad_enfromtemp,& @@ -64,19 +64,17 @@ end subroutine get_idealplusrad_temp subroutine get_idealplusrad_pres(rhoi,tempi,mu,presi) - real, intent(in) :: rhoi,mu - real, intent(in) :: tempi + real, intent(in) :: rhoi,tempi,mu real, intent(out) :: presi - presi = Rg*rhoi*tempi/mu + 1./3.*radconst*tempi**4 ! Eq 13.2 (Kippenhahn et al.) + presi = (Rg*rhoi/mu + radconst*tempi**3/3.)*tempi ! Eq 13.2 (Kippenhahn et al.) end subroutine get_idealplusrad_pres subroutine get_idealplusrad_spsoundi(rhoi,presi,eni,spsoundi,gammai) real, intent(in) :: rhoi,presi,eni - real, intent(out) :: spsoundi - real, intent(out) :: gammai + real, intent(out) :: spsoundi,gammai gammai = 1. + presi/(eni*rhoi) spsoundi = sqrt(gammai*presi/rhoi) @@ -127,7 +125,7 @@ subroutine get_idealplusrad_enfromtemp(densi,tempi,mu,eni) real, intent(in) :: densi,tempi,mu real, intent(out) :: eni - eni = 3./2.*Rg*tempi/mu + radconst*tempi**4/densi + eni = 1.5*Rg*tempi/mu + radconst*tempi**4/densi end subroutine get_idealplusrad_enfromtemp diff --git a/src/main/extern_corotate.f90 b/src/main/extern_corotate.f90 index 72eedd4e5..e8d9bfff8 100644 --- a/src/main/extern_corotate.f90 +++ b/src/main/extern_corotate.f90 @@ -39,7 +39,7 @@ module extern_corotate real, public :: primarycore_xpos = 1., primarycore_mass = 1. integer, public :: icompanion_grav = 0 - public :: update_coriolis_leapfrog + public :: update_coriolis public :: get_coriolis_force,get_centrifugal_force,get_companion_force public :: write_options_corotate, read_options_corotate private @@ -132,17 +132,16 @@ end subroutine get_coriolis_force ! returning the forces plus the Coriolis force. !+ !--------------------------------------------------------------- -subroutine update_coriolis_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& - vcrossomega,dt) +subroutine update_coriolis(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& + vcrossomega,dkdt) use vectorutils, only:cross_product3D,matrixinvert3D use io, only:fatal - real, intent(in) :: dt + real, intent(in) :: dkdt real, intent(in) :: vhalfx,vhalfy,vhalfz real, intent(inout) :: fxi,fyi,fzi real, intent(out) :: vcrossomega(3) integer :: ierr - real :: dton2 real :: A(3),v1(3),Omegap(3) real :: Rmat(3,3),Rinv(3,3) @@ -161,15 +160,14 @@ subroutine update_coriolis_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& ! ! and fxi,fyi,fzi are the components of f1_sph !-------------------------------------------------- - dton2 = 0.5*dt - A(1) = vhalfx + dton2*fxi - A(2) = vhalfy + dton2*fyi - A(3) = vhalfz + dton2*fzi + A(1) = vhalfx + dkdt*fxi + A(2) = vhalfy + dkdt*fyi + A(3) = vhalfz + dkdt*fzi ! This is the matrix from the equation for v1: [Rmat][v1] = [A] - Rmat = reshape((/1., -dton2*Omegap(3), dton2*Omegap(2), & - dton2*Omegap(3), 1., -dton2*Omegap(1), & - -dton2*Omegap(2), dton2*Omegap(1), 1. /),(/3,3/)) + Rmat = reshape((/1., -dkdt*Omegap(3), dkdt*Omegap(2), & + dkdt*Omegap(3), 1., -dkdt*Omegap(1), & + -dkdt*Omegap(2), dkdt*Omegap(1), 1. /),(/3,3/)) ! Get the inverse matrix call matrixinvert3D(Rmat,Rinv,ierr) @@ -188,7 +186,7 @@ subroutine update_coriolis_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& fyi = fyi + vcrossomega(2) fzi = fzi + vcrossomega(3) -end subroutine update_coriolis_leapfrog +end subroutine update_coriolis !----------------------------------------------------------------------- !+ diff --git a/src/main/extern_gnewton.f90 b/src/main/extern_gnewton.f90 index 75a8563e9..8d60fe62e 100644 --- a/src/main/extern_gnewton.f90 +++ b/src/main/extern_gnewton.f90 @@ -21,7 +21,7 @@ module extern_gnewton ! implicit none public :: get_gnewton_spatial_force, get_gnewton_vdependent_force - public :: update_gnewton_leapfrog + public :: update_gnewton public :: get_gnewton_energy private @@ -99,18 +99,18 @@ subroutine get_gnewton_vdependent_force(xyzi,veli,mass,fexti) end subroutine get_gnewton_vdependent_force -subroutine update_gnewton_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,mass) +subroutine update_gnewton(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dkdt,xi,yi,zi,mass) use io, only:fatal - real, intent(in) :: dt,xi,yi,zi, mass + real, intent(in) :: dkdt,xi,yi,zi, mass real, intent(in) :: vhalfx,vhalfy,vhalfz real, intent(inout) :: fxi,fyi,fzi real, intent(inout) :: fexti(3) real :: fextv(3) - real :: v1x, v1y, v1z, v1xold, v1yold, v1zold, vhalf2, erri, dton2 + real :: v1x, v1y, v1z, v1xold, v1yold, v1zold, vhalf2, erri logical :: converged integer :: its, itsmax integer, parameter :: maxitsext = 50 ! maximum number of iterations on external force - character(len=30), parameter :: label = 'update_gnewton_leapfrog' + character(len=30), parameter :: label = 'update_gnewton' real, parameter :: tolv = 1.e-2 real, parameter :: tolv2 = tolv*tolv real,dimension(3) :: pos,vel @@ -118,7 +118,6 @@ subroutine update_gnewton_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi, itsmax = maxitsext its = 0 converged = .false. - dton2 = 0.5*dt v1x = vhalfx v1y = vhalfy @@ -142,9 +141,9 @@ subroutine update_gnewton_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi, v1y = vel(2) v1z = vel(3) - v1x = vhalfx + dton2*(fxi + fextv(1)) - v1y = vhalfy + dton2*(fyi + fextv(2)) - v1z = vhalfz + dton2*(fzi + fextv(3)) + v1x = vhalfx + dkdt*(fxi + fextv(1)) + v1y = vhalfy + dkdt*(fyi + fextv(2)) + v1z = vhalfz + dkdt*(fzi + fextv(3)) erri = (v1x - v1xold)**2 + (v1y - v1yold)**2 + (v1z - v1zold)**2 erri = erri / vhalf2 @@ -162,7 +161,7 @@ subroutine update_gnewton_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi, fyi = fyi + fexti(2) fzi = fzi + fexti(3) -end subroutine update_gnewton_leapfrog +end subroutine update_gnewton !----------------------------------------------------------------------- diff --git a/src/main/extern_lensethirring.f90 b/src/main/extern_lensethirring.f90 index cfc6b9b03..e1f318e46 100644 --- a/src/main/extern_lensethirring.f90 +++ b/src/main/extern_lensethirring.f90 @@ -31,7 +31,7 @@ module extern_lensethirring real, public :: blackhole_spin_angle = 0. real, public :: cos_spinangle = 1., sin_spinangle = 0. - public :: update_ltforce_leapfrog + public :: update_ltforce public :: get_lense_thirring_force,check_lense_thirring_settings public :: write_options_ltforce, read_options_ltforce private @@ -111,25 +111,22 @@ end subroutine get_lense_thirring_force ! returning the forces plust the Lense-Thirring force. !+ !--------------------------------------------------------------- -subroutine update_ltforce_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& - vcrossomega,dt,xi,yi,zi,bh_mass) +subroutine update_ltforce(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& + vcrossomega,dkdt,xi,yi,zi,bh_mass) use vectorutils, only : cross_product3D,matrixinvert3D use io, only : fatal,warning - real, intent(in) :: dt,xi,yi,zi,bh_mass + real, intent(in) :: dkdt,xi,yi,zi,bh_mass real, intent(in) :: vhalfx,vhalfy,vhalfz real, intent(inout) :: fxi,fyi,fzi real, intent(out) :: vcrossomega(3) integer :: ierr - real :: dton2,dton2sq !,f2,flt2 real :: A(3),v1(3),Omegap(3) !,v1check real :: Rmat(3,3),Rinv(3,3) ! Half the timestep and compute its square - dton2 = 0.5*dt - dton2sq = dton2**2 ! Equation we are solving is: v1 = v0 + 0.5dt*(f0 + f1_sph + v1 cross Omega) ! vhalf = v0 + 0.5*dt*f0 @@ -142,14 +139,14 @@ subroutine update_ltforce_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& !---------------------------------------------------------------------- ! Third attempt with matrix inversion. !---------------------------------------------------------------------- - A(1) = vhalfx + dton2*fxi - A(2) = vhalfy + dton2*fyi - A(3) = vhalfz + dton2*fzi + A(1) = vhalfx + dkdt*fxi + A(2) = vhalfy + dkdt*fyi + A(3) = vhalfz + dkdt*fzi ! This is the matrix from the equation for v1: [Rmat][v1] = [A] - Rmat = reshape((/1., -dton2*Omegap(3), dton2*Omegap(2), & - dton2*Omegap(3), 1., -dton2*Omegap(1), & - -dton2*Omegap(2), dton2*Omegap(1), 1. /),(/3,3/)) + Rmat = reshape((/1., -dkdt*Omegap(3), dkdt*Omegap(2), & + dkdt*Omegap(3), 1., -dkdt*Omegap(1), & + -dkdt*Omegap(2), dkdt*Omegap(1), 1. /),(/3,3/)) ! Get the inverse matrix call matrixinvert3D(Rmat,Rinv,ierr) @@ -189,7 +186,7 @@ subroutine update_ltforce_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,& ! call warning('extern_lensethirring',' lense-thirring force > 10% of total force') ! endif -end subroutine update_ltforce_leapfrog +end subroutine update_ltforce !--------------------------------------------------------------- !+ diff --git a/src/main/extern_prdrag.f90 b/src/main/extern_prdrag.f90 index 78456bd68..da3f311ff 100644 --- a/src/main/extern_prdrag.f90 +++ b/src/main/extern_prdrag.f90 @@ -19,7 +19,7 @@ module extern_prdrag ! ! subroutine get_prdrag_spatial_force-- use beta_module, only:beta ! subroutine get_prdrag_vdependent_force-- use beta_module, only:beta -! subroutine update_prdrag_leapfrog-- use beta_module, only:beta +! subroutine update_prdrag-- use beta_module, only:beta ! subroutine write_options_prdrag-- use beta_module, only:write_options_beta ! subroutine read_options_prdrag-- use beta_module, only:read_options_beta ! @@ -27,9 +27,10 @@ module extern_prdrag ! ! :Owner: Daniel Price ! -! :Runtime parameters: None +! :Runtime parameters: +! - beta : *beta parameter* ! -! :Dependencies: eos, infile_utils, io, lumin_nsdisc, units +! :Dependencies: eos, infile_utils, io, units, vectorutils ! use eos, only:qfacdisc @@ -41,9 +42,10 @@ module extern_prdrag real, private :: k2 = 1. ! transverse drag real, private :: k0 = 1. ! radiation pressure real, private :: k1 = 1. ! redshift + real, private :: beta = 0.01 public :: get_prdrag_spatial_force, get_prdrag_vdependent_force - public :: update_prdrag_leapfrog + public :: update_prdrag public :: read_options_prdrag, write_options_prdrag private @@ -56,7 +58,6 @@ module extern_prdrag !+ !------------------------------------------------ subroutine get_prdrag_spatial_force(xi,yi,zi,MStar,fextxi,fextyi,fextzi,phi) - use lumin_nsdisc, only:beta use units, only:get_G_code real, intent(in) :: xi,yi,zi,Mstar real, intent(inout) :: fextxi,fextyi,fextzi @@ -66,7 +67,7 @@ subroutine get_prdrag_spatial_force(xi,yi,zi,MStar,fextxi,fextyi,fextzi,phi) gcode = get_G_code() r2 = xi*xi + yi*yi + zi*zi - betai = beta(xi,yi,zi) + betai = beta rbetai = k0*betai if (r2 > epsilon(r2)) then dr = 1./sqrt(r2) @@ -86,8 +87,7 @@ end subroutine get_prdrag_spatial_force !+ !----------------------------------------------------------------------- subroutine get_prdrag_vdependent_force(xyzi,vel,Mstar,fexti) - use lumin_nsdisc, only:beta !Change your Poynting-Robertson here. - use units, only:get_c_code,get_G_code + use units, only:get_c_code,get_G_code real, intent(in) :: xyzi(3), vel(3) real, intent(in) :: Mstar real, intent(out) :: fexti(3) @@ -104,63 +104,79 @@ subroutine get_prdrag_vdependent_force(xyzi,vel,Mstar,fexti) rhat = xyzi/r vr = dot_product(vel, rhat) - betai = beta( xyzi(1), xyzi(2), xyzi(3) ) + betai = beta fexti = (-betai*Mstar*gcode/ccode)* & ( (vr/r3)*xyzi*k1 + vel/r2*k2 ) end subroutine get_prdrag_vdependent_force -subroutine update_prdrag_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,Mstar) - use lumin_nsdisc, only:beta - use units, only:get_c_code - use io, only:warn - real, intent(in) :: dt,xi,yi,zi, Mstar +!----------------------------------------------------------------------- +!+ +! solve for the velocity update in the leapfrog corrector step +! i.e. v^n+1 = vhalf + 0.5*dt*f_sph + 0.5*dt*f_pr(x,v^n+1) +!+ +!----------------------------------------------------------------------- +subroutine update_prdrag(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dkdt,xi,yi,zi,Mstar) + use units, only:get_c_code,get_G_code + use io, only:warn,fatal + use vectorutils, only:matrixinvert3D + real, intent(in) :: dkdt,xi,yi,zi,Mstar real, intent(in) :: vhalfx,vhalfy,vhalfz real, intent(inout) :: fxi,fyi,fzi real, intent(inout) :: fexti(3) - real :: r, r2, r3, Q, betai - real :: Tx, Ty, Tz, vonex, voney, vonez - real :: denominator, vrhalf, vrone, twoQondt - real :: xi2, yi2, zi2, ccode, kd - character(len=30), parameter :: label = 'update_prdrag_leapfrog' + integer :: ierr + real :: r2,dr,rx,ry,rz + real :: gcode,ccode,betai,bterm,b,vr + real :: rhat(3),vel(3),A(3),Rmat(3,3),Rinv(3,3) + character(len=30), parameter :: label = 'update_prdrag' ccode = get_c_code() + gcode = get_G_code() - xi2 = xi*xi - yi2 = yi*yi - zi2 = zi*zi - kd = k1 - k2 - r2 = (xi2 + yi2 + zi2) - r = sqrt(r2) - r3 = r*r2 - vrhalf = vhalfx*xi + vhalfy*yi + vhalfz*zi + r2 = xi*xi + yi*yi + zi*zi + dr = 1./sqrt(r2) + rx = xi*dr + ry = yi*dr + rz = zi*dr + rhat = (/rx,ry,rz/) - betai = beta( xi, yi, zi ) - Q = Mstar*betai*dt/(2.*ccode*r*r) - twoQondt = 2.*Q/dt - denominator = -r2*( k2*kd*Q*Q + (kd-k2)*Q - 1 ) + ! solve for v^1 using matrix inversion of [Rmat][v1] = [A] + A(1) = vhalfx + dkdt*fxi + A(2) = vhalfy + dkdt*fyi + A(3) = vhalfz + dkdt*fzi - Tx = vhalfx + 0.5*dt*fxi - Ty = vhalfy + 0.5*dt*fyi - Tz = vhalfz + 0.5*dt*fzi + betai = beta + bterm = betai*gcode*Mstar/(ccode*r2) + b = dkdt*bterm - vonex = (-(Q*k1*xi)*(Ty*yi+Tz*zi)+Q*kd*Tx*r2-Tx*(r2+Q*k1*xi2))/denominator - voney = (-(Q*k1*yi)*(Tx*xi+Tz*zi)+Q*kd*Ty*r2-Ty*(r2+Q*k1*yi2))/denominator - vonez = (-(Q*k1*zi)*(Tx*xi+Ty*yi)+Q*kd*Tz*r2-Tz*(r2+Q*k1*zi2))/denominator + ! This is the matrix from the equation for v1: [Rmat][v1] = [A] + Rmat = reshape((/1. + b*(k2 + k1*rx*rx), b*k1*ry*rx, b*k1*rz*rx, & + b*k1*rx*ry, 1. + b*(k2 + k1*ry*ry), b*k1*rz*ry, & + b*k1*rx*rz, b*k1*ry*rz, 1. + b*(k2 + k1*rz*rz)/),(/3,3/)) - vrone = (vonex*xi + voney*yi + vonez*zi)/r ! vr = rhat dot v +! Get the inverse matrix + call matrixinvert3D(Rmat,Rinv,ierr) + if (ierr /= 0) then + call fatal('extern_prdrag','Error: determinant = 0 in matrix inversion') + endif + +! Compute v1 via matrix multiplication. + vel(:) = matmul(A,Rinv) + + vr = dot_product(vel,rhat) - fexti(1) = twoQondt * (vonex*k2 + k1*vrone*xi/r) - fexti(2) = twoQondt * (voney*k2 + k1*vrone*yi/r) - fexti(3) = twoQondt * (vonez*k2 + k1*vrone*zi/r) + ! velocity dependent part of the P-R drag force (e.g. equation 142 of Klacka 1992) + fexti(:) = -bterm*(vr*rhat*k1 + vel*k2) - fxi = fxi + fexti(1) - fyi = fyi + fexti(2) - fzi = fzi + fexti(3) + !v1check(:) = A(:) + dton2*fexti(:) ! this should match expression for v1 -end subroutine update_prdrag_leapfrog + fxi = fxi + fexti(1) + fyi = fyi + fexti(2) + fzi = fzi + fexti(3) + +end subroutine update_prdrag !----------------------------------------------------------------------- !+ @@ -169,11 +185,11 @@ end subroutine update_prdrag_leapfrog !----------------------------------------------------------------------- subroutine write_options_prdrag(iunit) use infile_utils, only:write_inopt - use lumin_nsdisc, only:write_options_lumin_nsdisc integer, intent(in) :: iunit write(iunit,"(/,a)") '# options relating to Poynting-Robertson drag' + call write_inopt(beta,'beta','beta parameter',iunit) call write_inopt(k0, 'RadiationPressure', & 'Radiation pressure multiplier', iunit) call write_inopt(k2, 'TransverseDrag', & @@ -181,8 +197,6 @@ subroutine write_options_prdrag(iunit) call write_inopt(k1, 'Redshift', & 'Redshift multiplier', iunit) - call write_options_lumin_nsdisc(iunit) - end subroutine write_options_prdrag !----------------------------------------------------------------------- @@ -191,8 +205,7 @@ end subroutine write_options_prdrag !+ !----------------------------------------------------------------------- subroutine read_options_prdrag(name,valstring,imatch,igotall,ierr) - use io, only:fatal, warning - use lumin_nsdisc, only:read_options_lumin_nsdisc + use io, only:fatal, warning character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr @@ -203,6 +216,9 @@ subroutine read_options_prdrag(name,valstring,imatch,igotall,ierr) igotall = .false. select case(trim(name)) + case('beta') + read(valstring,*,iostat=ierr) beta + ngot = ngot + 1 case('RadiationPressure') read(valstring,*,iostat=ierr) k0 ngot = ngot + 1 @@ -214,7 +230,6 @@ subroutine read_options_prdrag(name,valstring,imatch,igotall,ierr) ngot = ngot + 1 case default imatch = .false. - call read_options_lumin_nsdisc(name,valstring,imatch,igotall,ierr) end select igotall = (ngot >= 1) diff --git a/src/main/externalforces.f90 b/src/main/externalforces.f90 index 51f3ecd3c..aa5aad3ba 100644 --- a/src/main/externalforces.f90 +++ b/src/main/externalforces.f90 @@ -21,7 +21,7 @@ module externalforces ! :Dependencies: dump_utils, extern_Bfield, extern_binary, extern_corotate, ! extern_densprofile, extern_geopot, extern_gnewton, extern_gwinspiral, ! extern_lensethirring, extern_prdrag, extern_spiral, extern_staticsine, -! infile_utils, io, lumin_nsdisc, part, units +! infile_utils, io, part, units ! use extern_binary, only:accradius1,mass1,accretedmass1,accretedmass2 use extern_corotate, only:omega_corotate ! so public from this module @@ -33,7 +33,7 @@ module externalforces public :: accradius1,omega_corotate,accretedmass1,accretedmass2 public :: write_options_externalforces,read_options_externalforces public :: initialise_externalforces,is_velocity_dependent - public :: update_vdependent_extforce_leapfrog + public :: update_vdependent_extforce public :: update_externalforce public :: write_headeropts_extern,read_headeropts_extern @@ -493,14 +493,14 @@ end subroutine externalforce_vdependent ! necessary for using v-dependent forces in leapfrog !+ !----------------------------------------------------------------------- -subroutine update_vdependent_extforce_leapfrog(iexternalforce, & - vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,densi,ui) - use extern_corotate, only:update_coriolis_leapfrog - use extern_prdrag, only:update_prdrag_leapfrog - use extern_lensethirring, only:update_ltforce_leapfrog - use extern_gnewton, only:update_gnewton_leapfrog +subroutine update_vdependent_extforce(iexternalforce, & + vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dkdt,xi,yi,zi,densi,ui) + use extern_corotate, only:update_coriolis + use extern_prdrag, only:update_prdrag + use extern_lensethirring, only:update_ltforce + use extern_gnewton, only:update_gnewton integer, intent(in) :: iexternalforce - real, intent(in) :: dt,xi,yi,zi + real, intent(in) :: dkdt,xi,yi,zi real, intent(in) :: vhalfx,vhalfy,vhalfz real, intent(inout) :: fxi,fyi,fzi real, intent(out) :: fexti(3) @@ -508,16 +508,16 @@ subroutine update_vdependent_extforce_leapfrog(iexternalforce, & select case(iexternalforce) case(iext_corotate,iext_corot_binary) - call update_coriolis_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt) + call update_coriolis(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dkdt) case(iext_prdrag) - call update_prdrag_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,mass1) + call update_prdrag(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dkdt,xi,yi,zi,mass1) case(iext_lensethirring,iext_einsteinprec) - call update_ltforce_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,mass1) + call update_ltforce(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dkdt,xi,yi,zi,mass1) case(iext_gnewton) - call update_gnewton_leapfrog(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,mass1) + call update_gnewton(vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dkdt,xi,yi,zi,mass1) end select -end subroutine update_vdependent_extforce_leapfrog +end subroutine update_vdependent_extforce !----------------------------------------------------------------------- !+ @@ -525,9 +525,8 @@ end subroutine update_vdependent_extforce_leapfrog !+ !----------------------------------------------------------------------- subroutine update_externalforce(iexternalforce,ti,dmdt) - use io, only:iprint,iverbose,warn - use lumin_nsdisc, only:set_Lstar,BurstProfile,LumAcc,make_beta_grids - use part, only:xyzh,vxyzu,massoftype,npartoftype,igas,npart,nptmass,& + use io, only:warn + use part, only:xyzh,vxyzu,igas,npart,nptmass,& xyzmh_ptmass,vxyz_ptmass use extern_gwinspiral, only:gw_still_inspiralling,get_gw_force use extern_binary, only:update_binary @@ -538,12 +537,6 @@ subroutine update_externalforce(iexternalforce,ti,dmdt) select case(iexternalforce) case(iext_binary,iext_corot_binary) call update_binary(ti) - case(iext_prdrag) - call make_beta_grids( xyzh, massoftype(igas), npartoftype(igas) ) - call set_Lstar( BurstProfile, ti, dmdt, mass1 ) - if (iverbose >= 1) then - write(iprint,*) 'updating prdrag at t = ',ti,' Mdot = ',dmdt,' LAcc = ',LumAcc - endif case(iext_gwinspiral) call gw_still_inspiralling(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,stopped_now) call get_gw_force() diff --git a/src/main/part.F90 b/src/main/part.F90 index 652935668..362587bc2 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -204,10 +204,12 @@ module part integer, parameter :: i_mlast = 17 ! accreted mass of last time integer, parameter :: imassenc = 18 ! mass enclosed in sink softening radius integer, parameter :: iJ2 = 19 ! 2nd gravity moment due to oblateness + integer, parameter :: ndptmass = 13 ! number of properties to conserve after a accretion phase or merge real, allocatable :: xyzmh_ptmass(:,:) real, allocatable :: vxyz_ptmass(:,:) - real, allocatable :: fxyz_ptmass(:,:),fxyz_ptmass_sinksink(:,:) + real, allocatable :: fxyz_ptmass(:,:),fxyz_ptmass_sinksink(:,:),fsink_old(:,:) real, allocatable :: dsdt_ptmass(:,:),dsdt_ptmass_sinksink(:,:) + real, allocatable :: dptmass(:,:) integer :: nptmass = 0 ! zero by default real :: epot_sinksink character(len=*), parameter :: xyzmh_ptmass_label(nsinkproperties) = & @@ -431,6 +433,8 @@ subroutine allocate_part call allocate_array('vxyz_ptmass', vxyz_ptmass, 3, maxptmass) call allocate_array('fxyz_ptmass', fxyz_ptmass, 4, maxptmass) call allocate_array('fxyz_ptmass_sinksink', fxyz_ptmass_sinksink, 4, maxptmass) + call allocate_array('fsink_old', fsink_old, 4, maxptmass) + call allocate_array('dptmass', dptmass, ndptmass,maxptmass) call allocate_array('dsdt_ptmass', dsdt_ptmass, 3, maxptmass) call allocate_array('dsdt_ptmass_sinksink', dsdt_ptmass_sinksink, 3, maxptmass) call allocate_array('poten', poten, maxgrav) @@ -517,6 +521,8 @@ subroutine deallocate_part if (allocated(vxyz_ptmass)) deallocate(vxyz_ptmass) if (allocated(fxyz_ptmass)) deallocate(fxyz_ptmass) if (allocated(fxyz_ptmass_sinksink)) deallocate(fxyz_ptmass_sinksink) + if (allocated(fsink_old)) deallocate(fsink_old) + if (allocated(dptmass)) deallocate(dptmass) if (allocated(dsdt_ptmass)) deallocate(dsdt_ptmass) if (allocated(dsdt_ptmass_sinksink)) deallocate(dsdt_ptmass_sinksink) if (allocated(poten)) deallocate(poten) diff --git a/src/main/ptmass.F90 b/src/main/ptmass.F90 index e36d26066..9d536862e 100644 --- a/src/main/ptmass.F90 +++ b/src/main/ptmass.F90 @@ -47,7 +47,7 @@ module ptmass public :: pt_write_sinkev, pt_close_sinkev public :: get_accel_sink_gas, get_accel_sink_sink public :: merge_sinks - public :: ptmass_predictor, ptmass_corrector + public :: ptmass_kick, ptmass_drift,ptmass_vdependent_correction public :: ptmass_not_obscured public :: ptmass_accrete, ptmass_create public :: write_options_ptmass, read_options_ptmass @@ -55,6 +55,7 @@ module ptmass public :: calculate_mdot public :: ptmass_calc_enclosed_mass public :: ptmass_boundary_crossing + public :: set_integration_precision ! settings affecting routines in module (read from/written to input file) integer, public :: icreate_sinks = 0 @@ -67,6 +68,19 @@ module ptmass real, public :: r_merge_uncond = 0.0 ! sinks will unconditionally merge if they touch real, public :: r_merge_cond = 0.0 ! sinks will merge if bound within this radius real, public :: f_crit_override = 0.0 ! 1000. + + + logical, public :: use_fourthorder = .true. + integer, public :: n_force_order = 3 + real, public, parameter :: dk2(3) = (/0.5,0.5,0.0/) + real, public, parameter :: ck2(2) = (/1.,0.0/) + real, public, parameter :: dk4(3) = (/1./6.,2./3.,1./6./) + real, public, parameter :: ck4(2) = (/0.5,0.5/) + + real, public :: dk(3) + real, public :: ck(2) + + ! Note for above: if f_crit_override > 0, then will unconditionally make a sink when rho > f_crit_override*rho_crit_cgs ! This is a dangerous parameter since failure to form a sink might be indicative of another problem. ! This is a hard-coded parameter due to this danger, but will appear in the .in file if set > 0. @@ -81,8 +95,14 @@ module ptmass ! calibration of timestep control on sink-sink and sink-gas orbital integration ! this is hardwired because can be adjusted by changing C_force ! just means that with the default setting of C_force the orbits are accurate - real, parameter :: dtfacphi = 0.05 - real, parameter :: dtfacphi2 = dtfacphi*dtfacphi + real, parameter :: dtfacphilf = 0.05 + real, parameter :: dtfacphi2lf = dtfacphilf**2 + real, parameter :: dtfacphifsi = 0.15 + real, parameter :: dtfacphi2fsi = dtfacphifsi**2 + + real :: dtfacphi = dtfacphifsi + real :: dtfacphi2 = dtfacphifsi + ! parameters to control output regarding sink particles logical, private, parameter :: record_created = .false. ! verbose tracking of why sinks are not created @@ -91,7 +111,6 @@ module ptmass character(len=50), private :: pt_prefix = 'Sink' character(len=50), private :: pt_suffix = '00.sink' ! will be overwritten to .ev for write_one_ptfile = .false. - integer, public, parameter :: ndptmass = 13 integer, public, parameter :: & idxmsi = 1, & idymsi = 2, & @@ -121,7 +140,8 @@ module ptmass !+ !---------------------------------------------------------------- subroutine get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,fxi,fyi,fzi,phi, & - pmassi,fxyz_ptmass,dsdt_ptmass,fonrmax,dtphi2) + pmassi,fxyz_ptmass,dsdt_ptmass,fonrmax, & + dtphi2,extrapfac,fsink_old) #ifdef FINVSQRT use fastmath, only:finvsqrt #endif @@ -132,15 +152,16 @@ subroutine get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,fxi,fyi,fzi,phi, real, intent(in) :: xi,yi,zi,hi real, intent(inout) :: fxi,fyi,fzi,phi real, intent(in) :: xyzmh_ptmass(nsinkproperties,nptmass) - real, optional, intent(in) :: pmassi + real, optional, intent(in) :: pmassi,extrapfac real, optional, intent(inout) :: fxyz_ptmass(4,nptmass),dsdt_ptmass(3,nptmass) + real, optional, intent(in) :: fsink_old(4,nptmass) real, optional, intent(out) :: fonrmax,dtphi2 real :: ftmpxi,ftmpyi,ftmpzi real :: dx,dy,dz,rr2,ddr,dr3,f1,f2,pmassj,J2,shat(3),Rsink real :: hsoft,hsoft1,hsoft21,q2i,qi,psoft,fsoft real :: fxj,fyj,fzj,dsx,dsy,dsz integer :: j - logical :: tofrom + logical :: tofrom,extrap ! ! Determine if acceleration is from/to gas, or to gas ! @@ -151,6 +172,14 @@ subroutine get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,fxi,fyi,fzi,phi, tofrom = .false. endif + ! check if it is a force computed using Omelyan extrapolation method for FSI + if (present(extrapfac)) then + extrap = .true. + else + extrap = .false. + endif + + ftmpxi = 0. ! use temporary summation variable ftmpyi = 0. ! (better for round-off, plus we need this bit of ftmpzi = 0. ! the force to calculate the dtphi timestep) @@ -158,9 +187,15 @@ subroutine get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,fxi,fyi,fzi,phi, f2 = 0. do j=1,nptmass - dx = xi - xyzmh_ptmass(1,j) - dy = yi - xyzmh_ptmass(2,j) - dz = zi - xyzmh_ptmass(3,j) + if (extrap) then + dx = xi - (xyzmh_ptmass(1,j) + extrapfac*fsink_old(1,j)) + dy = yi - (xyzmh_ptmass(2,j) + extrapfac*fsink_old(2,j)) + dz = zi - (xyzmh_ptmass(3,j) + extrapfac*fsink_old(3,j)) + else + dx = xi - xyzmh_ptmass(1,j) + dy = yi - xyzmh_ptmass(2,j) + dz = zi - xyzmh_ptmass(3,j) + endif pmassj = xyzmh_ptmass(4,j) hsoft = xyzmh_ptmass(ihsoft,j) J2 = xyzmh_ptmass(iJ2,j) @@ -264,7 +299,7 @@ end subroutine get_accel_sink_gas !+ !---------------------------------------------------------------- subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksink,& - iexternalforce,ti,merge_ij,merge_n,dsdt_ptmass) + iexternalforce,ti,merge_ij,merge_n,dsdt_ptmass,extrapfac,fsink_old) #ifdef FINVSQRT use fastmath, only:finvsqrt #endif @@ -272,14 +307,16 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin use extern_geopot, only:get_geopot_force use kernel, only:kernel_softening,radkern use vectorutils, only:unitvec - integer, intent(in) :: nptmass - real, intent(in) :: xyzmh_ptmass(nsinkproperties,nptmass) - real, intent(out) :: fxyz_ptmass(4,nptmass) - real, intent(out) :: phitot,dtsinksink - integer, intent(in) :: iexternalforce - real, intent(in) :: ti - integer, intent(out) :: merge_ij(:),merge_n - real, intent(out) :: dsdt_ptmass(3,nptmass) + integer, intent(in) :: nptmass + real, intent(in) :: xyzmh_ptmass(nsinkproperties,nptmass) + real, intent(out) :: fxyz_ptmass(4,nptmass) + real, intent(out) :: phitot,dtsinksink + integer, intent(in) :: iexternalforce + real, intent(in) :: ti + integer, intent(out) :: merge_ij(:),merge_n + real, intent(out) :: dsdt_ptmass(3,nptmass) + real, optional, intent(in) :: extrapfac + real, optional, intent(in) :: fsink_old(4,nptmass) real :: xi,yi,zi,pmassi,pmassj,fxi,fyi,fzi,phii real :: ddr,dx,dy,dz,rr2,rr2j,dr3,f1,f2 real :: hsoft1,hsoft21,q2i,qi,psoft,fsoft @@ -288,6 +325,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin real :: J2i,rsinki,shati(3) real :: J2j,rsinkj,shatj(3) integer :: i,j + logical :: extrap dtsinksink = huge(dtsinksink) fxyz_ptmass(:,:) = 0. @@ -295,7 +333,13 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin phitot = 0. merge_n = 0 merge_ij = 0 - if (nptmass <= 1) return + if (nptmass <= 0) return + ! check if it is a force computed using Omelyan extrapolation method for FSI + if (present(extrapfac) .and. present(fsink_old)) then + extrap = .true. + else + extrap = .false. + endif ! !--get self-contribution to the potential if sink-sink softening is used ! @@ -314,6 +358,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin !$omp parallel do default(none) & !$omp shared(nptmass,xyzmh_ptmass,fxyz_ptmass,merge_ij,r_merge2,dsdt_ptmass) & !$omp shared(iexternalforce,ti,h_soft_sinksink,potensoft0,hsoft1,hsoft21) & + !$omp shared(extrapfac,extrap,fsink_old) & !$omp private(i,xi,yi,zi,pmassi,pmassj) & !$omp private(dx,dy,dz,rr2,rr2j,ddr,dr3,f1,f2) & !$omp private(fxi,fyi,fzi,phii,dsx,dsy,dsz) & @@ -323,9 +368,15 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin !$omp reduction(min:dtsinksink) & !$omp reduction(+:phitot,merge_n) do i=1,nptmass - xi = xyzmh_ptmass(1,i) - yi = xyzmh_ptmass(2,i) - zi = xyzmh_ptmass(3,i) + if (extrap) then + xi = xyzmh_ptmass(1,i) + extrapfac*fsink_old(1,i) + yi = xyzmh_ptmass(2,i) + extrapfac*fsink_old(2,i) + zi = xyzmh_ptmass(3,i) + extrapfac*fsink_old(3,i) + else + xi = xyzmh_ptmass(1,i) + yi = xyzmh_ptmass(2,i) + zi = xyzmh_ptmass(3,i) + endif pmassi = xyzmh_ptmass(4,i) !hsofti = xyzmh_ptmass(5,i) if (pmassi < 0.) cycle @@ -340,9 +391,15 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin dsz = 0. do j=1,nptmass if (i==j) cycle - dx = xi - xyzmh_ptmass(1,j) - dy = yi - xyzmh_ptmass(2,j) - dz = zi - xyzmh_ptmass(3,j) + if (extrap) then + dx = xi - (xyzmh_ptmass(1,j) + extrapfac*fsink_old(1,j)) + dy = yi - (xyzmh_ptmass(2,j) + extrapfac*fsink_old(2,j)) + dz = zi - (xyzmh_ptmass(3,j) + extrapfac*fsink_old(3,j)) + else + dx = xi - xyzmh_ptmass(1,j) + dy = yi - xyzmh_ptmass(2,j) + dz = zi - xyzmh_ptmass(3,j) + endif pmassj = xyzmh_ptmass(4,j) !hsoftj = xyzmh_ptmass(5,j) if (pmassj < 0.) cycle @@ -437,13 +494,13 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin ! !--store sink-sink forces (only) ! - fxyz_ptmass(1,i) = fxyz_ptmass(1,i) + fxi - fxyz_ptmass(2,i) = fxyz_ptmass(2,i) + fyi - fxyz_ptmass(3,i) = fxyz_ptmass(3,i) + fzi - fxyz_ptmass(4,i) = fxyz_ptmass(4,i) + phii - dsdt_ptmass(1,i) = dsdt_ptmass(1,i) + pmassi*dsx - dsdt_ptmass(2,i) = dsdt_ptmass(2,i) + pmassi*dsy - dsdt_ptmass(3,i) = dsdt_ptmass(3,i) + pmassi*dsz + fxyz_ptmass(1,i) = fxi + fxyz_ptmass(2,i) = fyi + fxyz_ptmass(3,i) = fzi + fxyz_ptmass(4,i) = phii + dsdt_ptmass(1,i) = pmassi*dsx + dsdt_ptmass(2,i) = pmassi*dsy + dsdt_ptmass(3,i) = pmassi*dsz enddo !$omp end parallel do @@ -463,12 +520,13 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin ! so that with the default C_force of ~0.25 we get a few ! hundred steps per orbit ! - if (f2 > 0. .and. nptmass > 1) then + if (f2 > 0. .and. (nptmass > 1 .or. iexternalforce > 0)) then dtsinksink = min(dtsinksink,dtfacphi*sqrt(abs(phii)/f2)) endif enddo end subroutine get_accel_sink_sink + !---------------------------------------------------------------- !+ ! Update position of sink particles if they cross the periodic boundary @@ -494,106 +552,94 @@ end subroutine ptmass_boundary_crossing ! (called from inside a parallel section) !+ !---------------------------------------------------------------- -subroutine ptmass_predictor(nptmass,dt,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass) +subroutine ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) integer, intent(in) :: nptmass - real, intent(in) :: dt + real, intent(in) :: ckdt real, intent(inout) :: xyzmh_ptmass(nsinkproperties,nptmass) real, intent(inout) :: vxyz_ptmass(3,nptmass) - real, intent(in) :: fxyz_ptmass(4,nptmass),dsdt_ptmass(3,nptmass) - real :: vxhalfi,vyhalfi,vzhalfi integer :: i !$omp parallel do schedule(static) default(none) & - !$omp shared(nptmass,dt,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass) & - !$omp private(i,vxhalfi,vyhalfi,vzhalfi) + !$omp shared(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) & + !$omp private(i) do i=1,nptmass if (xyzmh_ptmass(4,i) > 0.) then - vxhalfi = vxyz_ptmass(1,i) + 0.5*dt*fxyz_ptmass(1,i) - vyhalfi = vxyz_ptmass(2,i) + 0.5*dt*fxyz_ptmass(2,i) - vzhalfi = vxyz_ptmass(3,i) + 0.5*dt*fxyz_ptmass(3,i) - xyzmh_ptmass(1,i) = xyzmh_ptmass(1,i) + dt*vxhalfi - xyzmh_ptmass(2,i) = xyzmh_ptmass(2,i) + dt*vyhalfi - xyzmh_ptmass(3,i) = xyzmh_ptmass(3,i) + dt*vzhalfi - vxyz_ptmass(1,i) = vxhalfi - vxyz_ptmass(2,i) = vyhalfi - vxyz_ptmass(3,i) = vzhalfi - xyzmh_ptmass(ispinx,i) = xyzmh_ptmass(ispinx,i) + 0.5*dt*dsdt_ptmass(1,i) - xyzmh_ptmass(ispiny,i) = xyzmh_ptmass(ispiny,i) + 0.5*dt*dsdt_ptmass(2,i) - xyzmh_ptmass(ispinz,i) = xyzmh_ptmass(ispinz,i) + 0.5*dt*dsdt_ptmass(3,i) + xyzmh_ptmass(1,i) = xyzmh_ptmass(1,i) + ckdt*vxyz_ptmass(1,i) + xyzmh_ptmass(2,i) = xyzmh_ptmass(2,i) + ckdt*vxyz_ptmass(2,i) + xyzmh_ptmass(3,i) = xyzmh_ptmass(3,i) + ckdt*vxyz_ptmass(3,i) endif enddo !$omp end parallel do -end subroutine ptmass_predictor +end subroutine ptmass_drift !---------------------------------------------------------------- !+ -! corrector step for the point masses -! (called from inside a parallel section) +! kick step for the point masses !+ !---------------------------------------------------------------- -subroutine ptmass_corrector(nptmass,dt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dsdt_ptmass,iexternalforce) - use externalforces, only:update_vdependent_extforce_leapfrog,is_velocity_dependent +subroutine ptmass_kick(nptmass,dkdt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dsdt_ptmass) integer, intent(in) :: nptmass - real, intent(in) :: dt + real, intent(in) :: dkdt real, intent(inout) :: vxyz_ptmass(3,nptmass), xyzmh_ptmass(nsinkproperties,nptmass) real, intent(in) :: fxyz_ptmass(4,nptmass) real, intent(in) :: dsdt_ptmass(3,nptmass) + integer :: i + + + !$omp parallel do schedule(static) default(none) & + !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dkdt,nptmass) & + !$omp private(i) + do i=1,nptmass + if (xyzmh_ptmass(4,i) > 0.) then + vxyz_ptmass(1,i) = vxyz_ptmass(1,i) + dkdt*fxyz_ptmass(1,i) + vxyz_ptmass(2,i) = vxyz_ptmass(2,i) + dkdt*fxyz_ptmass(2,i) + vxyz_ptmass(3,i) = vxyz_ptmass(3,i) + dkdt*fxyz_ptmass(3,i) + xyzmh_ptmass(ispinx,i) = xyzmh_ptmass(ispinx,i) + dkdt*dsdt_ptmass(1,i) + xyzmh_ptmass(ispiny,i) = xyzmh_ptmass(ispiny,i) + dkdt*dsdt_ptmass(2,i) + xyzmh_ptmass(ispinz,i) = xyzmh_ptmass(ispinz,i) + dkdt*dsdt_ptmass(3,i) + endif + enddo + !$omp end parallel do + + +end subroutine ptmass_kick + +!---------------------------------------------------------------- +!+ +! force correction due to vdep force. +!+ +!---------------------------------------------------------------- +subroutine ptmass_vdependent_correction(nptmass,dkdt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,iexternalforce) + use externalforces, only:update_vdependent_extforce + integer, intent(in) :: nptmass + real, intent(in) :: dkdt + real, intent(inout) :: vxyz_ptmass(3,nptmass), xyzmh_ptmass(nsinkproperties,nptmass) + real, intent(inout) :: fxyz_ptmass(4,nptmass) integer, intent(in) :: iexternalforce - real :: vxhalfi,vyhalfi,vzhalfi real :: fxi,fyi,fzi,fextv(3) integer :: i - ! - ! handle special case of velocity-dependent external forces - ! in the leapfrog integrator - ! - if (is_velocity_dependent(iexternalforce)) then - !$omp parallel do schedule(static) default(none) & - !$omp shared(vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dsdt_ptmass,dt,nptmass,iexternalforce) & - !$omp private(vxhalfi,vyhalfi,vzhalfi,fxi,fyi,fzi,fextv) & - !$omp private(i) - do i=1,nptmass - if (xyzmh_ptmass(4,i) > 0.) then - vxhalfi = vxyz_ptmass(1,i) - vyhalfi = vxyz_ptmass(2,i) - vzhalfi = vxyz_ptmass(3,i) - fxi = fxyz_ptmass(1,i) - fyi = fxyz_ptmass(2,i) - fzi = fxyz_ptmass(3,i) - call update_vdependent_extforce_leapfrog(iexternalforce,& - vxhalfi,vyhalfi,vzhalfi,fxi,fyi,fzi,fextv,dt,& - xyzmh_ptmass(1,i),xyzmh_ptmass(2,i),xyzmh_ptmass(3,i)) - fxi = fxi + fextv(1) - fyi = fyi + fextv(2) - fzi = fzi + fextv(3) - vxyz_ptmass(1,i) = vxhalfi + 0.5*dt*fxi - vxyz_ptmass(2,i) = vyhalfi + 0.5*dt*fyi - vxyz_ptmass(3,i) = vzhalfi + 0.5*dt*fzi - xyzmh_ptmass(ispinx,i) = xyzmh_ptmass(ispinx,i) + 0.5*dt*dsdt_ptmass(1,i) - xyzmh_ptmass(ispiny,i) = xyzmh_ptmass(ispiny,i) + 0.5*dt*dsdt_ptmass(2,i) - xyzmh_ptmass(ispinz,i) = xyzmh_ptmass(ispinz,i) + 0.5*dt*dsdt_ptmass(3,i) - endif - enddo - !$omp end parallel do - else - !$omp parallel do schedule(static) default(none) & - !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,nptmass) & - !$omp private(i) - do i=1,nptmass - if (xyzmh_ptmass(4,i) > 0.) then - vxyz_ptmass(1,i) = vxyz_ptmass(1,i) + 0.5*dt*fxyz_ptmass(1,i) - vxyz_ptmass(2,i) = vxyz_ptmass(2,i) + 0.5*dt*fxyz_ptmass(2,i) - vxyz_ptmass(3,i) = vxyz_ptmass(3,i) + 0.5*dt*fxyz_ptmass(3,i) - xyzmh_ptmass(ispinx,i) = xyzmh_ptmass(ispinx,i) + 0.5*dt*dsdt_ptmass(1,i) - xyzmh_ptmass(ispiny,i) = xyzmh_ptmass(ispiny,i) + 0.5*dt*dsdt_ptmass(2,i) - xyzmh_ptmass(ispinz,i) = xyzmh_ptmass(ispinz,i) + 0.5*dt*dsdt_ptmass(3,i) - endif - enddo - !$omp end parallel do - endif - -end subroutine ptmass_corrector + !$omp parallel do schedule(static) default(none) & + !$omp shared(vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dkdt,nptmass,iexternalforce) & + !$omp private(fxi,fyi,fzi,fextv) & + !$omp private(i) + do i=1,nptmass + if (xyzmh_ptmass(4,i) > 0.) then + fxi = fxyz_ptmass(1,i) + fyi = fxyz_ptmass(2,i) + fzi = fxyz_ptmass(3,i) + call update_vdependent_extforce(iexternalforce,& + vxyz_ptmass(1,i),vxyz_ptmass(2,i),vxyz_ptmass(3,i), & + fxi,fyi,fzi,fextv,dkdt,xyzmh_ptmass(1,i),xyzmh_ptmass(2,i), & + xyzmh_ptmass(3,i)) + fxyz_ptmass(1,i) = fxi + fextv(1) + fxyz_ptmass(2,i) = fyi + fextv(2) + fxyz_ptmass(3,i) = fzi + fextv(3) + endif + enddo + !$omp end parallel do +end subroutine ptmass_vdependent_correction !---------------------------------------------------------------- !+ @@ -685,6 +731,7 @@ subroutine ptmass_accrete(is,nptmass,xi,yi,zi,hi,vxi,vyi,vzi,fxi,fyi,fzi, & integer :: j real :: mpt,drdv,angmom2,angmomh2,epart,dxj,dyj,dzj,dvxj,dvyj,dvzj,rj2,vj2,epartj logical :: mostbound +!$ external :: omp_set_lock,omp_unset_lock accreted = .false. ifail = 0 @@ -908,9 +955,9 @@ end subroutine update_ptmass !+ !------------------------------------------------------------------------- subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,poten,& - massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,time) + massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,time) use part, only:ihacc,ihsoft,igas,iamtype,get_partinfo,iphase,iactive,maxphase,rhoh, & - ispinx,ispiny,ispinz,fxyz_ptmass_sinksink,eos_vars,igasP,igamma + ispinx,ispiny,ispinz,fxyz_ptmass_sinksink,eos_vars,igasP,igamma,ndptmass use dim, only:maxp,maxneigh,maxvxyzu,maxptmass,ind_timesteps use kdtree, only:getneigh use kernel, only:kernel_softening,radkern @@ -935,14 +982,13 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote real, intent(in) :: vxyzu(:,:),fxyzu(:,:),fext(:,:),massoftype(:) real(4), intent(in) :: divcurlv(:,:),poten(:) real, intent(inout) :: xyzmh_ptmass(:,:) - real, intent(inout) :: vxyz_ptmass(:,:),fxyz_ptmass(:,:) + real, intent(inout) :: vxyz_ptmass(:,:),fxyz_ptmass(:,:),dptmass(ndptmass,nptmass+1) real, intent(in) :: time integer(kind=1) :: iphasei,ibin_wakei,ibin_itest integer :: nneigh integer, parameter :: maxcache = 12000 integer, parameter :: nneigh_thresh = 1024 ! approximate epot if neigh>neigh_thresh; (-ve for off) real, save :: xyzcache(maxcache,3) - real :: dptmass(ndptmass,nptmass+1) real :: xi,yi,zi,hi,hi1,hi21,xj,yj,zj,hj1,hj21,xk,yk,zk,hk1 real :: rij2,rik2,rjk2,dx,dy,dz real :: vxi,vyi,vzi,dv2,dvx,dvy,dvz,rhomax @@ -1585,6 +1631,24 @@ subroutine merge_sinks(time,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_i end subroutine merge_sinks +subroutine set_integration_precision + + if (use_fourthorder) then + n_force_order = 3 + ck = ck4 + dk = dk4 + dtfacphi = dtfacphifsi + dtfacphi2 = dtfacphi2fsi + else + n_force_order = 1 + ck = ck2 + dk = dk2 + dtfacphi = dtfacphilf + dtfacphi2 = dtfacphi2lf + endif + +end subroutine set_integration_precision + !----------------------------------------------------------------------- !+ ! Open files to track sink particle data diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index a1705b37c..aa2cccbf6 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -34,7 +34,6 @@ module readwrite_infile ! - dtwallmax : *maximum wall time between dumps (hhh:mm, 000:00=ignore)* ! - dumpfile : *dump file to start from* ! - flux_limiter : *limit radiation flux* -! - hdivbbmax_max : *max factor to decrease cleaning timestep propto B/(h|divB|)* ! - hfact : *h in units of particle spacing [h = hfact(m/rho)^(1/3)]* ! - ien_type : *energy variable (0=auto, 1=entropy, 2=energy, 3=entropy_s)* ! - implicit_radiation : *use implicit integration (Whitehouse, Bate & Monaghan 2005)* @@ -76,7 +75,7 @@ module readwrite_infile use options, only:nfulldump,nmaxdumps,twallmax,iexternalforce,tolh, & alpha,alphau,alphaB,beta,avdecayconst,damp,rkill, & ipdv_heating,ishock_heating,iresistive_heating,ireconav, & - icooling,psidecayfac,overcleanfac,hdivbbmax_max,alphamax,calc_erot,rhofinal_cgs, & + icooling,psidecayfac,overcleanfac,alphamax,calc_erot,rhofinal_cgs, & use_mcfost,use_Voronoi_limits_file,Voronoi_limits_file,use_mcfost_stellar_parameters,& exchange_radiation_energy,limit_radiation_flux,iopacity_type,mcfost_computes_Lacc,& mcfost_uses_PdV,implicit_radiation,mcfost_keep_part,ISM, mcfost_dust_subl @@ -84,7 +83,7 @@ module readwrite_infile use viscosity, only:irealvisc,shearparam,bulkvisc use part, only:hfact,ien_type use io, only:iverbose - use dim, only:do_radiation,nucleation,use_dust,use_dustgrowth + use dim, only:do_radiation,nucleation,use_dust,use_dustgrowth,mhd_nonideal implicit none logical :: incl_runtime2 = .false. @@ -112,12 +111,8 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) use inject, only:write_options_inject #endif use dust_formation, only:write_options_dust_formation -#ifdef NONIDEALMHD use nicil_sup, only:write_options_nicil -#endif -#ifdef GR use metric, only:write_options_metric -#endif use eos, only:write_options_eos,ieos,X_in,Z_in use ptmass, only:write_options_ptmass use ptmass_radiation,only:write_options_ptmass_radiation @@ -206,7 +201,6 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) call write_inopt(alphaB,'alphaB','shock resistivity parameter',iwritein) call write_inopt(psidecayfac,'psidecayfac','div B diffusion parameter',iwritein) call write_inopt(overcleanfac,'overcleanfac','factor to increase cleaning speed (decreases time step)',iwritein) - call write_inopt(hdivbbmax_max,'hdivbbmax_max','max factor to decrease cleaning timestep propto B/(h|divB|)',iwritein) endif call write_inopt(beta,'beta','beta viscosity',iwritein) if (maxalpha==maxp .and. maxp > 0) then @@ -272,10 +266,6 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) call write_options_porosity(iwritein) endif -#ifdef PHOTO - call write_options_photoevap(iwritein) -#endif - write(iwritein,"(/,a)") '# options for injecting/removing particles' #ifdef INJECT_PARTICLES call write_options_inject(iwritein) @@ -287,9 +277,8 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) write(iwritein,"(/,a)") '# options controling radiation pressure from sink particles' call write_options_ptmass_radiation(iwritein) endif -#ifdef NONIDEALMHD - call write_options_nicil(iwritein) -#endif + + if (mhd_nonideal) call write_options_nicil(iwritein) if (do_radiation) then write(iwritein,"(/,a)") '# options for radiation' @@ -309,16 +298,15 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) call write_inopt(cv_type,'cv_type','how to get cv and mean mol weight (0=constant,1=mesa)',iwritein) endif endif -#ifdef GR - call write_options_metric(iwritein) -#endif + + if (gr) call write_options_metric(iwritein) + call write_options_gravitationalwaves(iwritein) call write_options_boundary(iwritein) if (iwritein /= iprint) close(unit=iwritein) if (iwritein /= iprint) write(iprint,"(/,a)") ' input file '//trim(infile)//' written successfully.' - return end subroutine write_infile !----------------------------------------------------------------- @@ -347,9 +335,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) use inject, only:read_options_inject #endif use dust_formation, only:read_options_dust_formation,idust_opacity -#ifdef NONIDEALMHD use nicil_sup, only:read_options_nicil -#endif use part, only:mhd,nptmass use cooling, only:read_options_cooling use ptmass, only:read_options_ptmass @@ -494,8 +480,6 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) read(valstring,*,iostat=ierr) psidecayfac case('overcleanfac') read(valstring,*,iostat=ierr) overcleanfac - case('hdivbbmax_max') - read(valstring,*,iostat=ierr) hdivbbmax_max case('beta') read(valstring,*,iostat=ierr) beta case('ireconav') @@ -571,9 +555,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (.not.imatch .and. sink_radiation) then call read_options_ptmass_radiation(name,valstring,imatch,igotallprad,ierr) endif -#ifdef NONIDEALMHD if (.not.imatch) call read_options_nicil(name,valstring,imatch,igotallnonideal,ierr) -#endif if (.not.imatch) call read_options_eos(name,valstring,imatch,igotalleos,ierr) if (.not.imatch .and. maxvxyzu >= 4) call read_options_cooling(name,valstring,imatch,igotallcooling,ierr) if (.not.imatch) call read_options_damping(name,valstring,imatch,igotalldamping,ierr) From a037668cf00871e07174a0be404b4b95d7b4ccb4 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 2 May 2024 16:08:38 +0100 Subject: [PATCH 111/182] Further updates --- src/main/evolve.F90 | 16 +- src/main/force.F90 | 2 +- src/main/readwrite_infile.F90 | 13 +- src/main/step_leapfrog.F90 | 908 +---------------------- src/main/substepping.F90 | 1126 +++++++++++++++++++++++++++++ src/tests/test_derivs.F90 | 709 +++++++++--------- src/tests/test_dust.f90 | 2 +- src/tests/test_eos.f90 | 56 +- src/tests/test_eos_stratified.f90 | 10 +- src/tests/test_externf.f90 | 17 +- src/tests/test_gnewton.f90 | 6 +- src/tests/test_ptmass.f90 | 374 +++++++--- src/tests/testsuite.F90 | 5 +- src/tests/utils_testsuite.f90 | 9 +- 14 files changed, 1837 insertions(+), 1416 deletions(-) create mode 100644 src/main/substepping.F90 diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index 68cface6f..c96f339c1 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -37,7 +37,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) dtmax_ifactor,dtmax_ifactorWT,dtmax_dratio,check_dtmax_for_decrease,& idtmax_n,idtmax_frac,idtmax_n_next,idtmax_frac_next use evwrite, only:write_evfile,write_evlog - use energies, only:etot,totmom,angtot,mdust,np_cs_eq_0,np_e_eq_0,hdivBB_xa + use energies, only:etot,totmom,angtot,mdust,np_cs_eq_0,np_e_eq_0,hdivBonB_ave,hdivBonB_max use checkconserved, only:etot_in,angtot_in,totmom_in,mdust_in,& init_conservation_checks,check_conservation_error,& check_magnetic_stability @@ -88,10 +88,11 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use io, only:ianalysis #endif use part, only:npart,nptmass,xyzh,vxyzu,fxyzu,fext,divcurlv,massoftype, & - xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,gravity,iboundary, & + xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,gravity,iboundary, & fxyz_ptmass_sinksink,ntot,poten,ndustsmall,accrete_particles_outside_sphere use quitdump, only:quit - use ptmass, only:icreate_sinks,ptmass_create,ipart_rhomax,pt_write_sinkev,calculate_mdot + use ptmass, only:icreate_sinks,ptmass_create,ipart_rhomax,pt_write_sinkev,calculate_mdot, & + set_integration_precision use io_summary, only:iosum_nreal,summary_counter,summary_printout,summary_printnow use externalforces, only:iext_spiral use boundary_dyn, only:dynamic_bdy,update_boundaries @@ -162,6 +163,11 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) dtmax_log_dratio = 0.0 endif + ! + ! Set substepping integration precision depending on the system (default is FSI) + ! + call set_integration_precision + #ifdef IND_TIMESTEPS use_global_dt = .false. istepfrac = 0 @@ -270,7 +276,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) ! creation of new sink particles ! call ptmass_create(nptmass,npart,ipart_rhomax,xyzh,vxyzu,fxyzu,fext,divcurlv,& - poten,massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,time) + poten,massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,time) endif ! ! Strang splitting: implicit update for half step @@ -390,7 +396,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) call check_conservation_error(mdust(j),mdust_in(j),1.e-1,'dust mass',decrease=.true.) enddo endif - if (mhd) call check_magnetic_stability(hdivBB_xa) + if (mhd) call check_magnetic_stability(hdivBonB_ave,hdivBonB_max) if (id==master) then if (np_e_eq_0 > 0) call warning('evolve','N gas particles with energy = 0',var='N',ival=int(np_e_eq_0,kind=4)) if (np_cs_eq_0 > 0) call warning('evolve','N gas particles with sound speed = 0',var='N',ival=int(np_cs_eq_0,kind=4)) diff --git a/src/main/force.F90 b/src/main/force.F90 index b542aafef..011f6cf2b 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1024,7 +1024,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi,kfldi,kfldj,Ti,Tj,diffterm,gmwi + real :: radPj,fgravxi,fgravyi,fgravzi,kfldi,kfldj,Ti,Tj,diffterm real :: gradpx,gradpy,gradpz,gradP_cooli=0d0,gradP_coolj=0d0 ! unpack diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index aa2cccbf6..ec94e4cee 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module readwrite_infile ! @@ -270,9 +270,10 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) #ifdef INJECT_PARTICLES call write_options_inject(iwritein) #endif - if (nucleation) call write_options_dust_formation(iwritein) call write_inopt(rkill,'rkill','deactivate particles outside this radius (<0 is off)',iwritein) + if (nucleation) call write_options_dust_formation(iwritein) + if (sink_radiation) then write(iwritein,"(/,a)") '# options controling radiation pressure from sink particles' call write_options_ptmass_radiation(iwritein) @@ -298,9 +299,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) call write_inopt(cv_type,'cv_type','how to get cv and mean mol weight (0=constant,1=mesa)',iwritein) endif endif - if (gr) call write_options_metric(iwritein) - call write_options_gravitationalwaves(iwritein) call write_options_boundary(iwritein) @@ -555,7 +554,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (.not.imatch .and. sink_radiation) then call read_options_ptmass_radiation(name,valstring,imatch,igotallprad,ierr) endif - if (.not.imatch) call read_options_nicil(name,valstring,imatch,igotallnonideal,ierr) + if (.not.imatch .and. mhd_nonideal) call read_options_nicil(name,valstring,imatch,igotallnonideal,ierr) if (.not.imatch) call read_options_eos(name,valstring,imatch,igotalleos,ierr) if (.not.imatch .and. maxvxyzu >= 4) call read_options_cooling(name,valstring,imatch,igotallcooling,ierr) if (.not.imatch) call read_options_damping(name,valstring,imatch,igotalldamping,ierr) @@ -681,10 +680,6 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (psidecayfac < 0.) call fatal(label,'stupid value for psidecayfac') if (psidecayfac > 2.) call warn(label,'psidecayfac set outside recommended range (0.1-2.0)') if (overcleanfac < 1.0) call warn(label,'overcleanfac less than 1') - if (hdivbbmax_max < overcleanfac) then - call warn(label,'Resetting hdivbbmax_max = overcleanfac') - hdivbbmax_max = overcleanfac - endif endif if (beta < 0.) call fatal(label,'beta < 0') if (beta > 4.) call warn(label,'very high beta viscosity set') diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 2de7b5a88..500ea70d6 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -22,11 +22,10 @@ module step_lf_global ! ! :Runtime parameters: None ! -! :Dependencies: boundary_dyn, chem, cons2prim, cons2primsolver, cooling, -! cooling_ism, damping, deriv, dim, dust_formation, eos, extern_gr, -! externalforces, growth, io, io_summary, krome_interface, metric_tools, -! mpiutils, options, part, porosity, ptmass, ptmass_radiation, timestep, -! timestep_ind, timestep_sts, timing, units +! :Dependencies: boundary_dyn, cons2prim, cons2primsolver, cooling, +! damping, deriv, dim, eos, extern_gr, growth, io, io_summary, +! metric_tools, mpiutils, options, part, porosity, substepping, timestep, +! timestep_ind, timestep_sts, timing ! use dim, only:maxp,maxvxyzu,do_radiation,ind_timesteps use part, only:vpred,Bpred,dustpred,ppred @@ -100,11 +99,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& dustprop,ddustprop,dustproppred,pxyzu,dens,metrics,ics,& filfac,filfacpred,mprev,filfacprev - use options, only:avdecayconst,alpha,ieos,alphamax,icooling + use options, only:avdecayconst,alpha,ieos,alphamax use deriv, only:derivs use timestep, only:dterr,bignumber,tolv use mpiutils, only:reduceall_mpi - use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,ibin_wake + use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass, & + dsdt_ptmass,fsink_old,ibin_wake,dptmass use io_summary, only:summary_printout,summary_variable,iosumtvi,iowake, & iosumflrp,iosumflrps,iosumflrc use boundary_dyn, only:dynamic_bdy,update_xyzminmax @@ -119,11 +119,13 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use cooling, only:ufloor,cooling_in_step use timing, only:increment_timer,get_timings,itimer_extf use growth, only:check_dustprop - use options, only:use_porosity + use options, only:use_porosity,icooling use porosity, only:get_filfac use damping, only:idamp use cons2primsolver, only:conservative2primitive,primitive2conservative use eos, only:equationofstate + use substepping, only:substep,substep_gr, & + substep_sph_gr,substep_sph integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -169,9 +171,9 @@ 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) & + !$omp shared(dustprop,ddustprop,dustproppred,ufloor,icooling) & !$omp shared(mprev,filfacprev,filfac,use_porosity) & - !$omp shared(ibin,ibin_old,twas,timei,icooling) & + !$omp shared(ibin,ibin_old,twas,timei) & !$omp firstprivate(itype) & !$omp private(i,hdti) & !$omp reduction(+:nvfloorp) @@ -202,7 +204,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) 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 @@ -243,16 +245,17 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if ((iexternalforce > 0 .and. imetric /= imet_minkowski) .or. idamp > 0) then call cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) call get_grforce_all(npart,xyzh,metrics,metricderivs,vxyzu,dens,fext,dtextforce) - call step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,t) + call substep_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,t) else - call step_extern_sph_gr(dtsph,npart,xyzh,vxyzu,dens,pxyzu,metrics) + call substep_sph_gr(dtsph,npart,xyzh,vxyzu,dens,pxyzu,metrics) endif else if (nptmass > 0 .or. iexternalforce > 0 .or. h2chemistry .or. cooling_in_step .or. idamp > 0) then - call step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,t, & - nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,nbinmax,ibin_wake) + call substep(npart,ntypes,nptmass,dtsph,dtextforce,t,xyzh,vxyzu,& + fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,& + dptmass,fsink_old,nbinmax,ibin_wake) else - call step_extern_sph(dtsph,npart,xyzh,vxyzu) + call substep_sph(dtsph,npart,xyzh,vxyzu) endif endif call get_timings(t2,tcpu2) @@ -272,7 +275,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) & !$omp shared(twas,timei) & !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & @@ -476,7 +479,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) else - if (icooling /= 9) then + if (icooling /= 9) then vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) else vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) @@ -501,14 +504,16 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) - elseif (icooling /= 9) then - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) else - vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) + if (icooling /= 9) then + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + else + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,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 nvfloorc = nvfloorc + 1 @@ -575,7 +580,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(2,i) = vyi vxyzu(3,i) = vzi !--this is the energy equation if non-isothermal - if (maxvxyzu >= 4 .and. icooling/=9) vxyzu(4,i) = eni + if (maxvxyzu >= 4 .and. icooling /= 9) vxyzu(4,i) = eni endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) @@ -612,10 +617,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp parallel do default(none)& !$omp private(i) & !$omp shared(npart,hdtsph)& -!$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase,icooling) & +!$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase) & !$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(filfac,filfacpred,use_porosity,icooling) & !$omp shared(rad,drad,radpred) & !$omp firstprivate(itype) & !$omp schedule(static) @@ -653,10 +658,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) - elseif (icooling /= 9) then - vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) else - vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) + if (icooling /= 9 ) then + vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) + else + vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) + endif endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then @@ -715,851 +722,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) end subroutine step -subroutine step_extern_sph_gr(dt,npart,xyzh,vxyzu,dens,pxyzu,metrics) - use part, only:isdead_or_accreted,igas,massoftype,rhoh,eos_vars,igasP,& - ien_type,eos_vars,igamma,itemp - use cons2primsolver, only:conservative2primitive - use eos, only:ieos - use io, only:warning - use metric_tools, only:pack_metric - use timestep, only:xtol - real, intent(in) :: dt - integer, intent(in) :: npart - real, intent(inout) :: xyzh(:,:),dens(:),metrics(:,:,:,:) - real, intent(in) :: pxyzu(:,:) - real, intent(out) :: vxyzu(:,:) - integer, parameter :: nitermax = 50 - integer :: i,niter,ierr - real :: xpred(1:3),vold(1:3),diff - logical :: converged - real :: rhoi,pri,tempi,gammai - - !$omp parallel do default(none) & - !$omp shared(npart,xyzh,vxyzu,dens,dt,xtol) & - !$omp shared(pxyzu,metrics,ieos,massoftype,ien_type,eos_vars) & - !$omp private(i,niter,diff,xpred,vold,converged,ierr) & - !$omp private(pri,rhoi,tempi,gammai) - do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - - !-- unpack and compute values for initial guess in cons2prim - pri = eos_vars(igasP,i) - tempi = eos_vars(itemp,i) - gammai = eos_vars(igamma,i) - rhoi = rhoh(xyzh(4,i),massoftype(igas)) - - call conservative2primitive(xyzh(1:3,i),metrics(:,:,:,i),vxyzu(1:3,i),dens(i),vxyzu(4,i),& - pri,tempi,gammai,rhoi,pxyzu(1:3,i),pxyzu(4,i),ierr,ien_type) - if (ierr > 0) call warning('cons2primsolver [in step_extern_sph_gr (a)]','enthalpy did not converge',i=i) - ! - ! main position update - ! - xpred = xyzh(1:3,i) + dt*vxyzu(1:3,i) - vold = vxyzu(1:3,i) - converged = .false. - niter = 0 - do while (.not. converged .and. niter<=nitermax) - niter = niter + 1 - call conservative2primitive(xyzh(1:3,i),metrics(:,:,:,i),vxyzu(1:3,i),dens(i),vxyzu(4,i),& - pri,tempi,gammai,rhoi,pxyzu(1:3,i),pxyzu(4,i),ierr,ien_type) - if (ierr > 0) call warning('cons2primsolver [in step_extern_sph_gr (b)]','enthalpy did not converge',i=i) - xyzh(1:3,i) = xpred + 0.5*dt*(vxyzu(1:3,i)-vold) - diff = maxval(abs(xyzh(1:3,i)-xpred)/xpred) - if (diff < xtol) converged = .true. - ! UPDATE METRIC HERE - call pack_metric(xyzh(1:3,i),metrics(:,:,:,i)) - enddo - if (niter > nitermax) call warning('step_extern_sph_gr','Reached max number of x iterations. x_err ',val=diff) - - ! repack values - eos_vars(igasP,i) = pri - eos_vars(itemp,i) = tempi - eos_vars(igamma,i) = gammai - endif - enddo - !$omp end parallel do - -end subroutine step_extern_sph_gr - -subroutine step_extern_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,time) - use dim, only:maxptmass,maxp,maxvxyzu - use io, only:iverbose,id,master,iprint,warning,fatal - use externalforces, only:externalforce,accrete_particles,update_externalforce - use options, only:iexternalforce - use part, only:maxphase,isdead_or_accreted,iamboundary,igas,iphase,iamtype,& - massoftype,rhoh,ien_type,eos_vars,igamma,itemp,igasP - use io_summary, only:summary_variable,iosumextr,iosumextt,summary_accrete - use timestep, only:bignumber,C_force,xtol,ptol - use eos, only:equationofstate,ieos - use cons2primsolver,only:conservative2primitive - use extern_gr, only:get_grforce - use metric_tools, only:pack_metric,pack_metricderivs - use damping, only:calc_damp,apply_damp,idamp - integer, intent(in) :: npart,ntypes - real, intent(in) :: dtsph,time - real, intent(inout) :: dtextforce - real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:),pxyzu(:,:),dens(:),metrics(:,:,:,:),metricderivs(:,:,:,:) - integer :: i,itype,nsubsteps,naccreted,its,ierr,nlive - real :: timei,t_end_step,hdt,pmassi - real :: dt,dtf,dtextforcenew,dtextforce_min - real :: pri,spsoundi,pondensi,tempi,gammai - real, save :: pprev(3),xyz_prev(3),fstar(3),vxyz_star(3),xyz(3),pxyz(3),vxyz(3),fexti(3) -!$omp threadprivate(pprev,xyz_prev,fstar,vxyz_star,xyz,pxyz,vxyz,fexti) - real :: x_err,pmom_err,accretedmass,damp_fac - ! real, save :: dmdt = 0. - logical :: last_step,done,converged,accreted - integer, parameter :: itsmax = 50 - integer :: pitsmax,xitsmax - real :: perrmax,xerrmax - real :: rhoi,hi,eni,uui,densi - - pitsmax = 0 - xitsmax = 0 - perrmax = 0. - xerrmax = 0. - -! -! determine whether or not to use substepping -! - if (dtextforce < dtsph) then - dt = dtextforce - last_step = .false. - else - dt = dtsph - last_step = .true. - endif - - timei = time - itype = igas - pmassi = massoftype(igas) - t_end_step = timei + dtsph - nsubsteps = 0 - dtextforce_min = huge(dt) - done = .false. - substeps: do while (timei <= t_end_step .and. .not.done) - hdt = 0.5*dt - timei = timei + dt - nsubsteps = nsubsteps + 1 - dtextforcenew = bignumber - - call calc_damp(time, damp_fac) - - if (.not.last_step .and. iverbose > 1 .and. id==master) then - write(iprint,"(a,f14.6)") '> external forces only : t=',timei - endif - !--------------------------- - ! predictor during substeps - !--------------------------- - ! - ! predictor step for external forces, also recompute external forces - ! - !$omp parallel do default(none) & - !$omp shared(npart,xyzh,vxyzu,fext,iphase,ntypes,massoftype) & - !$omp shared(maxphase,maxp,eos_vars) & - !$omp shared(dt,hdt,xtol,ptol) & - !$omp shared(ieos,pxyzu,dens,metrics,metricderivs,ien_type) & - !$omp private(i,its,spsoundi,tempi,rhoi,hi,eni,uui,densi) & - !$omp private(converged,pmom_err,x_err,pri,ierr,gammai) & - !$omp firstprivate(pmassi,itype) & - !$omp reduction(max:xitsmax,pitsmax,perrmax,xerrmax) & - !$omp reduction(min:dtextforcenew) - predictor: do i=1,npart - xyz(1) = xyzh(1,i) - xyz(2) = xyzh(2,i) - xyz(3) = xyzh(3,i) - hi = xyzh(4,i) - if (.not.isdead_or_accreted(hi)) then - if (ntypes > 1 .and. maxphase==maxp) then - itype = iamtype(iphase(i)) - pmassi = massoftype(itype) - endif - - its = 0 - converged = .false. - ! - ! make local copies of array quantities - ! - pxyz(1:3) = pxyzu(1:3,i) - eni = pxyzu(4,i) - vxyz(1:3) = vxyzu(1:3,i) - uui = vxyzu(4,i) - fexti = fext(:,i) - - pxyz = pxyz + hdt*fexti - - !-- unpack thermo variables for the first guess in cons2prim - densi = dens(i) - pri = eos_vars(igasP,i) - gammai = eos_vars(igamma,i) - tempi = eos_vars(itemp,i) - rhoi = rhoh(hi,massoftype(igas)) - - ! Note: grforce needs derivatives of the metric, - ! which do not change between pmom iterations - pmom_iterations: do while (its <= itsmax .and. .not. converged) - its = its + 1 - pprev = pxyz - call conservative2primitive(xyz,metrics(:,:,:,i),vxyz,densi,uui,pri,& - tempi,gammai,rhoi,pxyz,eni,ierr,ien_type) - if (ierr > 0) call warning('cons2primsolver [in step_extern_gr (a)]','enthalpy did not converge',i=i) - call get_grforce(xyzh(:,i),metrics(:,:,:,i),metricderivs(:,:,:,i),vxyz,densi,uui,pri,fstar) - pxyz = pprev + hdt*(fstar - fexti) - pmom_err = maxval(abs(pxyz - pprev)) - if (pmom_err < ptol) converged = .true. - fexti = fstar - enddo pmom_iterations - if (its > itsmax ) call warning('step_extern_gr',& - 'max # of pmom iterations',var='pmom_err',val=pmom_err) - pitsmax = max(its,pitsmax) - perrmax = max(pmom_err,perrmax) - - call conservative2primitive(xyz,metrics(:,:,:,i),vxyz,densi,uui,pri,tempi,& - gammai,rhoi,pxyz,eni,ierr,ien_type) - if (ierr > 0) call warning('cons2primsolver [in step_extern_gr (b)]','enthalpy did not converge',i=i) - xyz = xyz + dt*vxyz - call pack_metric(xyz,metrics(:,:,:,i)) - - its = 0 - converged = .false. - vxyz_star = vxyz - ! Note: since particle positions change between iterations - ! the metric and its derivatives need to be updated. - ! cons2prim does not require derivatives of the metric, - ! so those can updated once the iterations are complete - ! in order to reduce the number of computations. - xyz_iterations: do while (its <= itsmax .and. .not. converged) - its = its+1 - xyz_prev = xyz - call conservative2primitive(xyz,metrics(:,:,:,i),vxyz_star,densi,uui,& - pri,tempi,gammai,rhoi,pxyz,eni,ierr,ien_type) - if (ierr > 0) call warning('cons2primsolver [in step_extern_gr (c)]','enthalpy did not converge',i=i) - xyz = xyz_prev + hdt*(vxyz_star - vxyz) - x_err = maxval(abs(xyz-xyz_prev)) - if (x_err < xtol) converged = .true. - vxyz = vxyz_star - ! UPDATE METRIC HERE - call pack_metric(xyz,metrics(:,:,:,i)) - enddo xyz_iterations - call pack_metricderivs(xyz,metricderivs(:,:,:,i)) - if (its > itsmax ) call warning('step_extern_gr','Reached max number of x iterations. x_err ',val=x_err) - xitsmax = max(its,xitsmax) - xerrmax = max(x_err,xerrmax) - - ! re-pack arrays back where they belong - xyzh(1:3,i) = xyz(1:3) - pxyzu(1:3,i) = pxyz(1:3) - vxyzu(1:3,i) = vxyz(1:3) - vxyzu(4,i) = uui - fext(:,i) = fexti - dens(i) = densi - eos_vars(igasP,i) = pri - eos_vars(itemp,i) = tempi - eos_vars(igamma,i) = gammai - - ! Skip remainder of update if boundary particle; note that fext==0 for these particles - if (iamboundary(itype)) cycle predictor - endif - enddo predictor - !$omp end parallel do - - if (iverbose >= 2 .and. id==master) then - write(iprint,*) '------ Iterations summary: -------------------------------' - write(iprint,"(a,i2,a,f14.6)") 'Most pmom iterations = ',pitsmax,' | max error = ',perrmax - write(iprint,"(a,i2,a,f14.6)") 'Most xyz iterations = ',xitsmax,' | max error = ',xerrmax - write(iprint,*) - endif - - ! - ! corrector step on gas particles (also accrete particles at end of step) - ! - accretedmass = 0. - naccreted = 0 - nlive = 0 - dtextforce_min = bignumber - !$omp parallel default(none) & - !$omp shared(npart,xyzh,metrics,metricderivs,vxyzu,fext,iphase,ntypes,massoftype,hdt,timei) & - !$omp shared(maxphase,maxp) & - !$omp private(i,accreted) & - !$omp shared(ieos,dens,pxyzu,iexternalforce,C_force) & - !$omp private(pri,pondensi,spsoundi,tempi,dtf) & - !$omp firstprivate(itype,pmassi) & - !$omp reduction(min:dtextforce_min) & - !$omp reduction(+:accretedmass,naccreted,nlive) & - !$omp shared(idamp,damp_fac) - !$omp do - accreteloop: do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - if (ntypes > 1 .and. maxphase==maxp) then - itype = iamtype(iphase(i)) - pmassi = massoftype(itype) - ! if (itype==iboundary) cycle accreteloop - 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) - dtextforce_min = min(dtextforce_min,C_force*dtf) - - if (idamp > 0) then - call apply_damp(fext(1,i), fext(2,i), fext(3,i), vxyzu(1:3,i), xyzh(1:3,i), damp_fac) - endif - - ! - ! correct v to the full step using only the external force - ! - pxyzu(1:3,i) = pxyzu(1:3,i) + hdt*fext(1:3,i) - ! Do we need call cons2prim here ?? - - if (iexternalforce > 0) then - call accrete_particles(iexternalforce,xyzh(1,i),xyzh(2,i), & - xyzh(3,i),xyzh(4,i),pmassi,timei,accreted,i) - if (accreted) then - accretedmass = accretedmass + pmassi - naccreted = naccreted + 1 - endif - endif - nlive = nlive + 1 - endif - enddo accreteloop - !$omp enddo - !$omp end parallel - - if (npart > 2 .and. nlive < 2) then - call fatal('step','all particles accreted',var='nlive',ival=nlive) - endif - - if (iverbose >= 2 .and. id==master .and. naccreted /= 0) write(iprint,"(a,es10.3,a,i4,a)") & - 'Step: at time ',timei,', ',naccreted,' particles were accreted. Mass accreted = ',accretedmass - - dtextforcenew = min(dtextforce_min,dtextforcenew) - dtextforce = dtextforcenew - - if (last_step) then - done = .true. - else - dt = dtextforce - if (timei + dt > t_end_step) then - dt = t_end_step - timei - last_step = .true. - endif - endif - - enddo substeps - - if (nsubsteps > 1) then - if (iverbose>=1 .and. id==master) then - write(iprint,"(a,i6,a,f8.2,a,es10.3,a,es10.3)") & - ' using ',nsubsteps,' substeps (dthydro/dtextf = ',dtsph/dtextforce_min,'), dt = ',dtextforce_min,' dtsph = ',dtsph - endif - call summary_variable('ext',iosumextr ,nsubsteps,dtsph/dtextforce_min) - call summary_variable('ext',iosumextt ,nsubsteps,dtextforce_min,1.0/dtextforce_min) - endif - -end subroutine step_extern_gr - -!---------------------------------------------------------------- -!+ -! This is the equivalent of the routine below when no external -! forces, sink particles or cooling are used -!+ -!---------------------------------------------------------------- -subroutine step_extern_sph(dt,npart,xyzh,vxyzu) - use part, only:isdead_or_accreted - real, intent(in) :: dt - integer, intent(in) :: npart - real, intent(inout) :: xyzh(:,:) - real, intent(in) :: vxyzu(:,:) - integer :: i - - !$omp parallel do default(none) & - !$omp shared(npart,xyzh,vxyzu,dt) & - !$omp private(i) - do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - ! - ! main position update - ! - xyzh(1,i) = xyzh(1,i) + dt*vxyzu(1,i) - xyzh(2,i) = xyzh(2,i) + dt*vxyzu(2,i) - xyzh(3,i) = xyzh(3,i) + dt*vxyzu(3,i) - endif - enddo - !$omp end parallel do - -end subroutine step_extern_sph - -!---------------------------------------------------------------- -!+ -! Substepping of external and sink particle forces. -! Also updates position of all particles even if no external -! forces applied. This is the internal loop of the RESPA -! algorithm over the "fast" forces. -!+ -!---------------------------------------------------------------- -subroutine step_extern(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,fext,fxyzu,time,nptmass, & - xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,nbinmax,ibin_wake) - use dim, only:maxptmass,maxp,maxvxyzu,store_dust_temperature,use_krome,itau_alloc,& - do_nucleation,update_muGamma,h2chemistry - use io, only:iverbose,id,master,iprint,warning,fatal - use externalforces, only:externalforce,accrete_particles,update_externalforce, & - update_vdependent_extforce_leapfrog,is_velocity_dependent - use ptmass, only:ptmass_predictor,ptmass_corrector,ptmass_accrete, & - get_accel_sink_gas,get_accel_sink_sink,merge_sinks,f_acc,pt_write_sinkev, & - idxmsi,idymsi,idzmsi,idmsi,idspinxsi,idspinysi,idspinzsi, & - idvxmsi,idvymsi,idvzmsi,idfxmsi,idfymsi,idfzmsi, & - ndptmass,update_ptmass - use options, only:iexternalforce,icooling - use part, only:maxphase,abundance,nabundances,eos_vars,epot_sinksink,eos_vars,& - isdead_or_accreted,iamboundary,igas,iphase,iamtype,massoftype,rhoh,divcurlv, & - fxyz_ptmass_sinksink,dsdt_ptmass_sinksink,dust_temp,tau,& - nucleation,idK2,idmu,idkappa,idgamma,imu,igamma - use chem, only:update_abundances,get_dphot - use cooling_ism, only:dphot0,energ_cooling_ism,dphotflag,abundsi,abundo,abunde,abundc,nabn - use io_summary, only:summary_variable,iosumextr,iosumextt,summary_accrete,summary_accrete_fail - use timestep, only:bignumber,C_force - use timestep_sts, only:sts_it_n - use mpiutils, only:bcast_mpi,reduce_in_place_mpi,reduceall_mpi - use damping, only:calc_damp,apply_damp,idamp - use ptmass_radiation,only:get_rad_accel_from_ptmass,isink_radiation - use cooling, only:energ_cooling,cooling_in_step - use dust_formation, only:evolve_dust,calc_muGamma - use units, only:unit_density -#ifdef KROME - use part, only: T_gas_cool - use krome_interface, only: update_krome -#endif - integer, intent(in) :: npart,ntypes,nptmass - real, intent(in) :: dtsph,time - real, intent(inout) :: dtextforce - real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:),fxyzu(:,:) - real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) - integer(kind=1), intent(in) :: nbinmax - integer(kind=1), intent(inout) :: ibin_wake(:) - integer :: i,itype,nsubsteps,naccreted,nfail,nfaili,merge_n,nlive - integer :: merge_ij(nptmass) - integer(kind=1) :: ibin_wakei - real :: timei,hdt,fextx,fexty,fextz,fextxi,fextyi,fextzi,phii,pmassi - real :: dtphi2,dtphi2i,vxhalfi,vyhalfi,vzhalfi,fxi,fyi,fzi - real :: dudtcool,fextv(3),poti,ui,rhoi,mui,gammai,ph,ph_tot - real :: dt,dtextforcenew,dtsinkgas,fonrmax,fonrmaxi - real :: dtf,accretedmass,t_end_step,dtextforce_min - real, allocatable :: dptmass(:,:) ! dptmass(ndptmass,nptmass) - real :: damp_fac,dphot - real, save :: dmdt = 0. - real :: abundi(nabn),gmwvar - logical :: accreted,extf_is_velocity_dependent - logical :: last_step,done - - -! -! determine whether or not to use substepping -! - if (dtextforce < dtsph) then - dt = dtextforce - last_step = .false. - else - dt = dtsph - last_step = .true. - endif - - timei = time - extf_is_velocity_dependent = is_velocity_dependent(iexternalforce) - accretedmass = 0. - itype = igas - pmassi = massoftype(igas) - t_end_step = timei + dtsph - nsubsteps = 0 - dtextforce_min = huge(dt) - done = .false. - ! allocate memory for dptmass array (avoids ifort bug) - allocate(dptmass(ndptmass,nptmass)) - - substeps: do while (timei <= t_end_step .and. .not.done) - hdt = 0.5*dt - timei = timei + dt - if (abs(dt) < tiny(0.)) call fatal('step_extern','dt <= 0 in sink-gas substepping',var='dt',val=dt) - nsubsteps = nsubsteps + 1 - dtextforcenew = bignumber - dtsinkgas = bignumber - dtphi2 = bignumber - - call calc_damp(time, damp_fac) - - if (.not.last_step .and. iverbose > 1 .and. id==master) then - write(iprint,"(a,f14.6)") '> external/ptmass forces only : t=',timei - endif - ! - ! update time-dependent external forces - ! - call update_externalforce(iexternalforce,timei,dmdt) - - !--------------------------- - ! predictor during substeps - !--------------------------- - ! - ! point mass predictor step - ! - if (nptmass > 0) then - if (id==master) then - call ptmass_predictor(nptmass,dt,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass) - ! - ! get sink-sink forces (and a new sink-sink timestep. Note: fxyz_ptmass is zeroed in this subroutine) - ! pass sink-sink forces to variable fxyz_ptmass_sinksink for later writing. - ! - if (iexternalforce==14) call update_externalforce(iexternalforce,timei,dmdt) - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& - dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) - if (merge_n > 0) then - call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& - dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) - endif - fxyz_ptmass_sinksink=fxyz_ptmass - dsdt_ptmass_sinksink=dsdt_ptmass - if (iverbose >= 2) write(iprint,*) 'dt(sink-sink) = ',C_force*dtf - else - fxyz_ptmass(:,:) = 0. - dsdt_ptmass(:,:) = 0. - endif - call bcast_mpi(xyzmh_ptmass(:,1:nptmass)) - call bcast_mpi(vxyz_ptmass(:,1:nptmass)) - call bcast_mpi(epot_sinksink) - call bcast_mpi(dtf) - dtextforcenew = min(dtextforcenew,C_force*dtf) - endif - - ! - ! predictor step for sink-gas and external forces, also recompute sink-gas and external forces - ! - fonrmax = 0. - !$omp parallel default(none) & - !$omp shared(maxp,maxphase) & - !$omp shared(npart,xyzh,vxyzu,fext,abundance,iphase,ntypes,massoftype,fxyzu) & - !$omp shared(eos_vars,dust_temp,store_dust_temperature) & - !$omp shared(dt,hdt,timei,iexternalforce,extf_is_velocity_dependent,cooling_in_step,icooling) & - !$omp shared(xyzmh_ptmass,vxyz_ptmass,idamp,damp_fac) & - !$omp shared(nptmass,nsubsteps,C_force,divcurlv,dphotflag,dphot0) & - !$omp shared(abundc,abundo,abundsi,abunde) & - !$omp shared(nucleation,do_nucleation,update_muGamma,h2chemistry,unit_density) & - !$omp private(dphot,abundi,gmwvar,ph,ph_tot) & - !$omp private(ui,rhoi, mui, gammai) & - !$omp private(i,dudtcool,fxi,fyi,fzi,phii) & - !$omp private(fextx,fexty,fextz,fextxi,fextyi,fextzi,poti,fextv,accreted) & - !$omp private(fonrmaxi,dtphi2i,dtf) & - !$omp private(vxhalfi,vyhalfi,vzhalfi) & - !$omp firstprivate(pmassi,itype) & -#ifdef KROME - !$omp shared(T_gas_cool) & -#endif - !$omp reduction(+:accretedmass) & - !$omp reduction(min:dtextforcenew,dtsinkgas,dtphi2) & - !$omp reduction(max:fonrmax) & - !$omp reduction(+:fxyz_ptmass,dsdt_ptmass) - !$omp do - predictor: do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - if (ntypes > 1 .and. maxphase==maxp) then - itype = iamtype(iphase(i)) - pmassi = massoftype(itype) - endif - ! - ! predict v to the half step - ! - vxyzu(1:3,i) = vxyzu(1:3,i) + hdt*fext(1:3,i) - ! - ! main position update - ! - xyzh(1,i) = xyzh(1,i) + dt*vxyzu(1,i) - xyzh(2,i) = xyzh(2,i) + dt*vxyzu(2,i) - xyzh(3,i) = xyzh(3,i) + dt*vxyzu(3,i) - ! - ! Skip remainder of update if boundary particle; note that fext==0 for these particles - if (iamboundary(itype)) cycle predictor - ! - ! compute and add sink-gas force - ! - fextx = 0. - fexty = 0. - fextz = 0. - if (nptmass > 0) then - call get_accel_sink_gas(nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass,& - fextx,fexty,fextz,phii,pmassi,fxyz_ptmass,dsdt_ptmass,fonrmaxi,dtphi2i) - fonrmax = max(fonrmax,fonrmaxi) - dtphi2 = min(dtphi2,dtphi2i) - endif - ! - ! compute and add external forces - ! - if (iexternalforce > 0) then - call externalforce(iexternalforce,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i), & - timei,fextxi,fextyi,fextzi,poti,dtf,i) - dtextforcenew = min(dtextforcenew,C_force*dtf) - - fextx = fextx + fextxi - fexty = fexty + fextyi - fextz = fextz + fextzi - ! - ! Velocity-dependent external forces require special handling - ! in leapfrog (corrector is implicit) - ! - if (extf_is_velocity_dependent) then - vxhalfi = vxyzu(1,i) - vyhalfi = vxyzu(2,i) - vzhalfi = vxyzu(3,i) - fxi = fextx - fyi = fexty - fzi = fextz - call update_vdependent_extforce_leapfrog(iexternalforce,& - vxhalfi,vyhalfi,vzhalfi, & - fxi,fyi,fzi,fextv,dt,xyzh(1,i),xyzh(2,i),xyzh(3,i)) - fextx = fextx + fextv(1) - fexty = fexty + fextv(2) - fextz = fextz + fextv(3) - endif - endif - if (idamp > 0) then - call apply_damp(fextx, fexty, fextz, vxyzu(1:3,i), xyzh(1:3,i), damp_fac) - endif - fext(1,i) = fextx - fext(2,i) = fexty - fext(3,i) = fextz - - if (maxvxyzu >= 4 .and. itype==igas) then - ! NOTE: The chemistry and cooling here is implicitly calculated. That is, - ! dt is *passed in* to the chemistry & cooling routines so that the - ! output will be at the correct time of time + dt. Since this is - ! implicit, there is no cooling timestep. Explicit cooling is - ! calculated in force and requires a cooling timestep. - - dudtcool = 0. - rhoi = rhoh(xyzh(4,i),pmassi) - ! - ! CHEMISTRY - ! - if (h2chemistry) then - ! - ! Get updated abundances of all species, updates 'chemarrays', - ! - dphot = get_dphot(dphotflag,dphot0,xyzh(1,i),xyzh(2,i),xyzh(3,i)) - call update_abundances(vxyzu(4,i),rhoi,abundance(:,i),nabundances,& - dphot,dt,abundi,nabn,eos_vars(imu,i),abundc,abunde,abundo,abundsi) - endif -#ifdef KROME - ! evolve chemical composition and determine new internal energy - ! Krome also computes cooling function but only associated with chemical processes - ui = vxyzu(4,i) - call update_krome(dt,xyzh(:,i),ui,rhoi,abundance(:,i),eos_vars(igamma,i),eos_vars(imu,i),T_gas_cool(i)) - dudtcool = (ui-vxyzu(4,i))/dt -#else - !evolve dust chemistry and compute dust cooling - if (do_nucleation) then - call evolve_dust(dt, xyzh(:,i), vxyzu(4,i), nucleation(:,i), dust_temp(i), rhoi) - eos_vars(imu,i) = nucleation(idmu,i) - eos_vars(igamma,i) = nucleation(idgamma,i) - endif - ! - ! COOLING - ! - if (icooling > 0 .and. cooling_in_step) then - if (h2chemistry) then - ! - ! Call cooling routine, requiring total density, some distance measure and - ! abundances in the 'abund' format - ! - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,& - dust_temp(i),eos_vars(imu,i), eos_vars(igamma,i),abund_in=abundi) - elseif (store_dust_temperature) then - ! cooling with stored dust temperature - if (do_nucleation) then - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,& - dust_temp(i),nucleation(idmu,i),nucleation(idgamma,i),nucleation(idK2,i),nucleation(idkappa,i)) - elseif (update_muGamma) then - call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,& - dust_temp(i),eos_vars(imu,i), eos_vars(igamma,i)) - 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 - 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,dudti_sph=fxyzu(4,i),part_id=i) - endif - endif -#endif - ! update internal energy - if (cooling_in_step .or. use_krome) vxyzu(4,i) = vxyzu(4,i) + dt * dudtcool - endif - endif - enddo predictor - !$omp enddo - !$omp end parallel - - if (nptmass > 0 .and. isink_radiation > 0) then - if (itau_alloc == 1) then - call get_rad_accel_from_ptmass(nptmass,npart,xyzh,xyzmh_ptmass,fext,tau) - else - call get_rad_accel_from_ptmass(nptmass,npart,xyzh,xyzmh_ptmass,fext) - endif - endif - - ! - ! reduction of sink-gas forces from each MPI thread - ! - if (nptmass > 0) then - call reduce_in_place_mpi('+',fxyz_ptmass(:,1:nptmass)) - call reduce_in_place_mpi('+',dsdt_ptmass(:,1:nptmass)) - endif - !--------------------------- - ! corrector during substeps - !--------------------------- - ! - ! corrector step on sinks (changes velocities only, does not change position) - ! - if (nptmass > 0) then - if (id==master) then - call ptmass_corrector(nptmass,dt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dsdt_ptmass,iexternalforce) - endif - call bcast_mpi(vxyz_ptmass(:,1:nptmass)) - endif - - ! - ! corrector step on gas particles (also accrete particles at end of step) - ! - accretedmass = 0. - nfail = 0 - naccreted = 0 - nlive = 0 - ibin_wakei = 0 - dptmass(:,:) = 0. - - !$omp parallel default(none) & - !$omp shared(maxp,maxphase) & - !$omp shared(npart,xyzh,vxyzu,fext,iphase,ntypes,massoftype,hdt,timei,nptmass,sts_it_n) & - !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,f_acc) & - !$omp shared(iexternalforce) & - !$omp shared(nbinmax,ibin_wake) & - !$omp reduction(+:dptmass) & - !$omp private(i,accreted,nfaili,fxi,fyi,fzi) & - !$omp firstprivate(itype,pmassi,ibin_wakei) & - !$omp reduction(+:accretedmass,nfail,naccreted,nlive) - !$omp do - accreteloop: do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - if (ntypes > 1 .and. maxphase==maxp) then - itype = iamtype(iphase(i)) - pmassi = massoftype(itype) - if (iamboundary(itype)) cycle accreteloop - endif - ! - ! correct v to the full step using only the external force - ! - vxyzu(1:3,i) = vxyzu(1:3,i) + hdt*fext(1:3,i) - - if (iexternalforce > 0) then - call accrete_particles(iexternalforce,xyzh(1,i),xyzh(2,i), & - xyzh(3,i),xyzh(4,i),pmassi,timei,accreted) - if (accreted) accretedmass = accretedmass + pmassi - endif - ! - ! accretion onto sink particles - ! need position, velocities and accelerations of both gas and sinks to be synchronised, - ! otherwise will not conserve momentum - ! Note: requiring sts_it_n since this is supertimestep with the most active particles - ! - if (nptmass > 0 .and. sts_it_n) then - fxi = fext(1,i) - fyi = fext(2,i) - fzi = fext(3,i) - if (ind_timesteps) ibin_wakei = ibin_wake(i) - - call ptmass_accrete(1,nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& - vxyzu(1,i),vxyzu(2,i),vxyzu(3,i),fxi,fyi,fzi,& - itype,pmassi,xyzmh_ptmass,vxyz_ptmass,& - accreted,dptmass,timei,f_acc,nbinmax,ibin_wakei,nfaili) - if (accreted) then - naccreted = naccreted + 1 - cycle accreteloop - else - if (ind_timesteps) ibin_wake(i) = ibin_wakei - endif - if (nfaili > 1) nfail = nfail + 1 - endif - nlive = nlive + 1 - endif - enddo accreteloop - !$omp enddo - !$omp end parallel - - if (npart > 2 .and. nlive < 2) then - call fatal('step','all particles accreted',var='nlive',ival=nlive) - endif - - ! - ! reduction of sink particle changes across MPI - ! - if (nptmass > 0) then - call reduce_in_place_mpi('+',dptmass(:,1:nptmass)) - - naccreted = int(reduceall_mpi('+',naccreted)) - nfail = int(reduceall_mpi('+',nfail)) - - if (id==master) call update_ptmass(dptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass) - - call bcast_mpi(xyzmh_ptmass(:,1:nptmass)) - call bcast_mpi(vxyz_ptmass(:,1:nptmass)) - call bcast_mpi(fxyz_ptmass(:,1:nptmass)) - endif - - if (iverbose >= 2 .and. id==master .and. naccreted /= 0) write(iprint,"(a,es10.3,a,i4,a,i4,a)") & - 'Step: at time ',timei,', ',naccreted,' particles were accreted amongst ',nptmass,' sink(s).' - - if (nptmass > 0) then - call summary_accrete_fail(nfail) - call summary_accrete(nptmass) - ! only write to .ev during substeps if no gas particles present - if (npart==0) call pt_write_sinkev(nptmass,timei,xyzmh_ptmass,vxyz_ptmass, & - fxyz_ptmass,fxyz_ptmass_sinksink) - endif - ! - ! check if timestep criterion was violated during substeps - ! - if (nptmass > 0) then - if (fonrmax > 0.) then - dtsinkgas = min(dtsinkgas,C_force*1./sqrt(fonrmax),C_force*sqrt(dtphi2)) - endif - if (iverbose >= 2) write(iprint,*) nsubsteps,'dt(ext/sink-sink) = ',dtextforcenew,', dt(sink-gas) = ',dtsinkgas - dtextforcenew = min(dtextforcenew,dtsinkgas) - endif - - dtextforcenew = reduceall_mpi('min',dtextforcenew) - - dtextforce_min = min(dtextforce_min,dtextforcenew) - dtextforce = dtextforcenew - - if (last_step) then - done = .true. - else - dt = dtextforce - if (timei + dt > t_end_step) then - dt = t_end_step - timei - last_step = .true. - endif - endif - enddo substeps - - deallocate(dptmass) - - if (nsubsteps > 1) then - if (iverbose>=1 .and. id==master) then - write(iprint,"(a,i6,a,f8.2,a,es10.3,a,es10.3)") & - ' using ',nsubsteps,' substeps (dthydro/dtextf = ',dtsph/dtextforce_min,'), dt = ',dtextforce_min,' dtsph = ',dtsph - endif - call summary_variable('ext',iosumextr ,nsubsteps,dtsph/dtextforce_min) - call summary_variable('ext',iosumextt ,nsubsteps,dtextforce_min,1.0/dtextforce_min) - endif - -end subroutine step_extern - !----------------------------------------------------- !+ ! Check error in v^1 compared to the predicted v^* diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 new file mode 100644 index 000000000..a3f9cd3f5 --- /dev/null +++ b/src/main/substepping.F90 @@ -0,0 +1,1126 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module substepping +! +! Computes sub-steps in the RESPA algorithm +! +! Multiple option of sub stepping can be choosed depending on +! the physics and the precision needed +! +! Only Hydro : substep_sph +! Hydro + GR : substep_sph_gr substep_gr +! 2nd order with all fast physics implemented : substep (use_fourthorder = false) +! 4th order without vdep forces and oblateness : substep (not yet implemented) +! +! :References: +! Verlet (1967), Phys. Rev. 159, 98-103 +! Tuckerman, Berne & Martyna (1992), J. Chem. Phys. 97, 1990-2001 +! Rantala + (2020) (2023),Chin (2007a) +! +! :Owner: Yrisch +! +! :Runtime parameters: None +! +! :Dependencies: chem, cons2primsolver, cooling, cooling_ism, damping, dim, +! dust_formation, eos, extern_gr, externalforces, io, io_summary, +! krome_interface, metric_tools, mpiutils, options, part, ptmass, +! ptmass_radiation, timestep, timestep_sts +! + implicit none + + public :: substep_gr + public :: substep_sph + public :: substep_sph_gr + public :: substep + + private + +contains + +subroutine substep_sph_gr(dt,npart,xyzh,vxyzu,dens,pxyzu,metrics) + use part, only:isdead_or_accreted,igas,massoftype,rhoh,eos_vars,igasP,& + ien_type,eos_vars,igamma,itemp + use cons2primsolver, only:conservative2primitive + use eos, only:ieos + use io, only:warning + use metric_tools, only:pack_metric + use timestep, only:xtol + real, intent(in) :: dt + integer, intent(in) :: npart + real, intent(inout) :: xyzh(:,:),dens(:),metrics(:,:,:,:) + real, intent(in) :: pxyzu(:,:) + real, intent(out) :: vxyzu(:,:) + integer, parameter :: nitermax = 50 + integer :: i,niter,ierr + real :: xpred(1:3),vold(1:3),diff + logical :: converged + real :: rhoi,pri,tempi,gammai + + !$omp parallel do default(none) & + !$omp shared(npart,xyzh,vxyzu,dens,dt,xtol) & + !$omp shared(pxyzu,metrics,ieos,massoftype,ien_type,eos_vars) & + !$omp private(i,niter,diff,xpred,vold,converged,ierr) & + !$omp private(pri,rhoi,tempi,gammai) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + + !-- unpack and compute values for initial guess in cons2prim + pri = eos_vars(igasP,i) + tempi = eos_vars(itemp,i) + gammai = eos_vars(igamma,i) + rhoi = rhoh(xyzh(4,i),massoftype(igas)) + + call conservative2primitive(xyzh(1:3,i),metrics(:,:,:,i),vxyzu(1:3,i),dens(i),vxyzu(4,i),& + pri,tempi,gammai,rhoi,pxyzu(1:3,i),pxyzu(4,i),ierr,ien_type) + if (ierr > 0) call warning('cons2primsolver [in substep_sph_gr (a)]','enthalpy did not converge',i=i) + ! + ! main position update + ! + xpred = xyzh(1:3,i) + dt*vxyzu(1:3,i) + vold = vxyzu(1:3,i) + converged = .false. + niter = 0 + do while (.not. converged .and. niter<=nitermax) + niter = niter + 1 + call conservative2primitive(xyzh(1:3,i),metrics(:,:,:,i),vxyzu(1:3,i),dens(i),vxyzu(4,i),& + pri,tempi,gammai,rhoi,pxyzu(1:3,i),pxyzu(4,i),ierr,ien_type) + if (ierr > 0) call warning('cons2primsolver [in substep_sph_gr (b)]','enthalpy did not converge',i=i) + xyzh(1:3,i) = xpred + 0.5*dt*(vxyzu(1:3,i)-vold) + diff = maxval(abs(xyzh(1:3,i)-xpred)/xpred) + if (diff < xtol) converged = .true. + ! UPDATE METRIC HERE + call pack_metric(xyzh(1:3,i),metrics(:,:,:,i)) + enddo + if (niter > nitermax) call warning('substep_sph_gr','Reached max number of x iterations. x_err ',val=diff) + + ! repack values + eos_vars(igasP,i) = pri + eos_vars(itemp,i) = tempi + eos_vars(igamma,i) = gammai + endif + enddo + !$omp end parallel do + +end subroutine substep_sph_gr + +subroutine substep_gr(npart,ntypes,dtsph,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,time) + use dim, only:maxptmass,maxp,maxvxyzu + use io, only:iverbose,id,master,iprint,warning,fatal + use externalforces, only:externalforce,accrete_particles,update_externalforce + use options, only:iexternalforce + use part, only:maxphase,isdead_or_accreted,iamboundary,igas,iphase,iamtype,& + massoftype,rhoh,ien_type,eos_vars,igamma,itemp,igasP + use io_summary, only:summary_variable,iosumextr,iosumextt,summary_accrete + use timestep, only:bignumber,C_force,xtol,ptol + use eos, only:equationofstate,ieos + use cons2primsolver,only:conservative2primitive + use extern_gr, only:get_grforce + use metric_tools, only:pack_metric,pack_metricderivs + use damping, only:calc_damp,apply_damp,idamp + integer, intent(in) :: npart,ntypes + real, intent(in) :: dtsph,time + real, intent(inout) :: dtextforce + real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:),pxyzu(:,:),dens(:),metrics(:,:,:,:),metricderivs(:,:,:,:) + integer :: i,itype,nsubsteps,naccreted,its,ierr,nlive + real :: timei,t_end_step,hdt,pmassi + real :: dt,dtf,dtextforcenew,dtextforce_min + real :: pri,spsoundi,pondensi,tempi,gammai + real, save :: pprev(3),xyz_prev(3),fstar(3),vxyz_star(3),xyz(3),pxyz(3),vxyz(3),fexti(3) + !$omp threadprivate(pprev,xyz_prev,fstar,vxyz_star,xyz,pxyz,vxyz,fexti) + real :: x_err,pmom_err,accretedmass,damp_fac + ! real, save :: dmdt = 0. + logical :: last_step,done,converged,accreted + integer, parameter :: itsmax = 50 + integer :: pitsmax,xitsmax + real :: perrmax,xerrmax + real :: rhoi,hi,eni,uui,densi + + pitsmax = 0 + xitsmax = 0 + perrmax = 0. + xerrmax = 0. + + ! + ! determine whether or not to use substepping + ! + if (dtextforce < dtsph) then + dt = dtextforce + last_step = .false. + else + dt = dtsph + last_step = .true. + endif + + timei = time + itype = igas + pmassi = massoftype(igas) + t_end_step = timei + dtsph + nsubsteps = 0 + dtextforce_min = huge(dt) + done = .false. + substeps: do while (timei <= t_end_step .and. .not.done) + hdt = 0.5*dt + timei = timei + dt + nsubsteps = nsubsteps + 1 + dtextforcenew = bignumber + + call calc_damp(time, damp_fac) + + if (.not.last_step .and. iverbose > 1 .and. id==master) then + write(iprint,"(a,f14.6)") '> external forces only : t=',timei + endif + !--------------------------- + ! predictor during substeps + !--------------------------- + ! + ! predictor step for external forces, also recompute external forces + ! + !$omp parallel do default(none) & + !$omp shared(npart,xyzh,vxyzu,fext,iphase,ntypes,massoftype) & + !$omp shared(maxphase,maxp,eos_vars) & + !$omp shared(dt,hdt,xtol,ptol) & + !$omp shared(ieos,pxyzu,dens,metrics,metricderivs,ien_type) & + !$omp private(i,its,spsoundi,tempi,rhoi,hi,eni,uui,densi) & + !$omp private(converged,pmom_err,x_err,pri,ierr,gammai) & + !$omp firstprivate(pmassi,itype) & + !$omp reduction(max:xitsmax,pitsmax,perrmax,xerrmax) & + !$omp reduction(min:dtextforcenew) + predictor: do i=1,npart + xyz(1) = xyzh(1,i) + xyz(2) = xyzh(2,i) + xyz(3) = xyzh(3,i) + hi = xyzh(4,i) + if (.not.isdead_or_accreted(hi)) then + if (ntypes > 1 .and. maxphase==maxp) then + itype = iamtype(iphase(i)) + pmassi = massoftype(itype) + endif + + its = 0 + converged = .false. + ! + ! make local copies of array quantities + ! + pxyz(1:3) = pxyzu(1:3,i) + eni = pxyzu(4,i) + vxyz(1:3) = vxyzu(1:3,i) + uui = vxyzu(4,i) + fexti = fext(:,i) + + pxyz = pxyz + hdt*fexti + + !-- unpack thermo variables for the first guess in cons2prim + densi = dens(i) + pri = eos_vars(igasP,i) + gammai = eos_vars(igamma,i) + tempi = eos_vars(itemp,i) + rhoi = rhoh(hi,massoftype(igas)) + + ! Note: grforce needs derivatives of the metric, + ! which do not change between pmom iterations + pmom_iterations: do while (its <= itsmax .and. .not. converged) + its = its + 1 + pprev = pxyz + call conservative2primitive(xyz,metrics(:,:,:,i),vxyz,densi,uui,pri,& + tempi,gammai,rhoi,pxyz,eni,ierr,ien_type) + if (ierr > 0) call warning('cons2primsolver [in substep_gr (a)]','enthalpy did not converge',i=i) + call get_grforce(xyzh(:,i),metrics(:,:,:,i),metricderivs(:,:,:,i),vxyz,densi,uui,pri,fstar) + pxyz = pprev + hdt*(fstar - fexti) + pmom_err = maxval(abs(pxyz - pprev)) + if (pmom_err < ptol) converged = .true. + fexti = fstar + enddo pmom_iterations + if (its > itsmax ) call warning('substep_gr',& + 'max # of pmom iterations',var='pmom_err',val=pmom_err) + pitsmax = max(its,pitsmax) + perrmax = max(pmom_err,perrmax) + + call conservative2primitive(xyz,metrics(:,:,:,i),vxyz,densi,uui,pri,tempi,& + gammai,rhoi,pxyz,eni,ierr,ien_type) + if (ierr > 0) call warning('cons2primsolver [in substep_gr (b)]','enthalpy did not converge',i=i) + xyz = xyz + dt*vxyz + call pack_metric(xyz,metrics(:,:,:,i)) + + its = 0 + converged = .false. + vxyz_star = vxyz + ! Note: since particle positions change between iterations + ! the metric and its derivatives need to be updated. + ! cons2prim does not require derivatives of the metric, + ! so those can updated once the iterations are complete + ! in order to reduce the number of computations. + xyz_iterations: do while (its <= itsmax .and. .not. converged) + its = its+1 + xyz_prev = xyz + call conservative2primitive(xyz,metrics(:,:,:,i),vxyz_star,densi,uui,& + pri,tempi,gammai,rhoi,pxyz,eni,ierr,ien_type) + if (ierr > 0) call warning('cons2primsolver [in substep_gr (c)]','enthalpy did not converge',i=i) + xyz = xyz_prev + hdt*(vxyz_star - vxyz) + x_err = maxval(abs(xyz-xyz_prev)) + if (x_err < xtol) converged = .true. + vxyz = vxyz_star + ! UPDATE METRIC HERE + call pack_metric(xyz,metrics(:,:,:,i)) + enddo xyz_iterations + call pack_metricderivs(xyz,metricderivs(:,:,:,i)) + if (its > itsmax ) call warning('substep_gr','Reached max number of x iterations. x_err ',val=x_err) + xitsmax = max(its,xitsmax) + xerrmax = max(x_err,xerrmax) + + ! re-pack arrays back where they belong + xyzh(1:3,i) = xyz(1:3) + pxyzu(1:3,i) = pxyz(1:3) + vxyzu(1:3,i) = vxyz(1:3) + vxyzu(4,i) = uui + fext(:,i) = fexti + dens(i) = densi + eos_vars(igasP,i) = pri + eos_vars(itemp,i) = tempi + eos_vars(igamma,i) = gammai + + ! Skip remainder of update if boundary particle; note that fext==0 for these particles + if (iamboundary(itype)) cycle predictor + endif + enddo predictor + !$omp end parallel do + + if (iverbose >= 2 .and. id==master) then + write(iprint,*) '------ Iterations summary: -------------------------------' + write(iprint,"(a,i2,a,f14.6)") 'Most pmom iterations = ',pitsmax,' | max error = ',perrmax + write(iprint,"(a,i2,a,f14.6)") 'Most xyz iterations = ',xitsmax,' | max error = ',xerrmax + write(iprint,*) + endif + + ! + ! corrector step on gas particles (also accrete particles at end of step) + ! + accretedmass = 0. + naccreted = 0 + nlive = 0 + dtextforce_min = bignumber + !$omp parallel default(none) & + !$omp shared(npart,xyzh,metrics,metricderivs,vxyzu,fext,iphase,ntypes,massoftype,hdt,timei) & + !$omp shared(maxphase,maxp) & + !$omp private(i,accreted) & + !$omp shared(ieos,dens,pxyzu,iexternalforce,C_force) & + !$omp private(pri,pondensi,spsoundi,tempi,dtf) & + !$omp firstprivate(itype,pmassi) & + !$omp reduction(min:dtextforce_min) & + !$omp reduction(+:accretedmass,naccreted,nlive) & + !$omp shared(idamp,damp_fac) + !$omp do + accreteloop: do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + if (ntypes > 1 .and. maxphase==maxp) then + itype = iamtype(iphase(i)) + pmassi = massoftype(itype) + ! if (itype==iboundary) cycle accreteloop + 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) + dtextforce_min = min(dtextforce_min,C_force*dtf) + + if (idamp > 0) then + call apply_damp(fext(1,i), fext(2,i), fext(3,i), vxyzu(1:3,i), xyzh(1:3,i), damp_fac) + endif + + ! + ! correct v to the full step using only the external force + ! + pxyzu(1:3,i) = pxyzu(1:3,i) + hdt*fext(1:3,i) + ! Do we need call cons2prim here ?? + + if (iexternalforce > 0) then + call accrete_particles(iexternalforce,xyzh(1,i),xyzh(2,i), & + xyzh(3,i),xyzh(4,i),pmassi,timei,accreted,i) + if (accreted) then + accretedmass = accretedmass + pmassi + naccreted = naccreted + 1 + endif + endif + nlive = nlive + 1 + endif + enddo accreteloop + !$omp enddo + !$omp end parallel + + if (npart > 2 .and. nlive < 2) then + call fatal('step','all particles accreted',var='nlive',ival=nlive) + endif + + if (iverbose >= 2 .and. id==master .and. naccreted /= 0) write(iprint,"(a,es10.3,a,i4,a)") & + 'Step: at time ',timei,', ',naccreted,' particles were accreted. Mass accreted = ',accretedmass + + dtextforcenew = min(dtextforce_min,dtextforcenew) + dtextforce = dtextforcenew + + if (last_step) then + done = .true. + else + dt = dtextforce + if (timei + dt > t_end_step) then + dt = t_end_step - timei + last_step = .true. + endif + endif + + enddo substeps + + if (nsubsteps > 1) then + if (iverbose>=1 .and. id==master) then + write(iprint,"(a,i6,a,f8.2,a,es10.3,a,es10.3)") & + ' using ',nsubsteps,' substeps (dthydro/dtextf = ',dtsph/dtextforce_min,'), dt = ',dtextforce_min,' dtsph = ',dtsph + endif + call summary_variable('ext',iosumextr ,nsubsteps,dtsph/dtextforce_min) + call summary_variable('ext',iosumextt ,nsubsteps,dtextforce_min,1.0/dtextforce_min) + endif + +end subroutine substep_gr + + !---------------------------------------------------------------- + !+ + ! This is the equivalent of the routine below when no external + ! forces, sink particles or cooling are used + !+ + !---------------------------------------------------------------- +subroutine substep_sph(dt,npart,xyzh,vxyzu) + use part, only:isdead_or_accreted + real, intent(in) :: dt + integer, intent(in) :: npart + real, intent(inout) :: xyzh(:,:) + real, intent(in) :: vxyzu(:,:) + integer :: i + + !$omp parallel do default(none) & + !$omp shared(npart,xyzh,vxyzu,dt) & + !$omp private(i) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + ! + ! main position update + ! + xyzh(1,i) = xyzh(1,i) + dt*vxyzu(1,i) + xyzh(2,i) = xyzh(2,i) + dt*vxyzu(2,i) + xyzh(3,i) = xyzh(3,i) + dt*vxyzu(3,i) + endif + enddo + !$omp end parallel do + +end subroutine substep_sph + +!---------------------------------------------------------------- + !+ + ! Substepping of external and sink particle forces. + ! Also updates position of all particles even if no external + ! forces applied. This is the internal loop of the RESPA + ! algorithm over the "fast" forces. + ! (Here it can be FSI or Leapfrog) + !+ + !---------------------------------------------------------------- +subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & + xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dptmass, & + fsink_old,nbinmax,ibin_wake) + use io, only:iverbose,id,master,iprint,fatal + use options, only:iexternalforce + use part, only:fxyz_ptmass_sinksink + use io_summary, only:summary_variable,iosumextr,iosumextt + use externalforces, only:is_velocity_dependent + use ptmass, only:use_fourthorder,ck,dk + integer, intent(in) :: npart,ntypes,nptmass + real, intent(in) :: dtsph,time + real, intent(inout) :: dtextforce + real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) + real, intent(inout) :: dptmass(:,:),fsink_old(:,:) + integer(kind=1), intent(in) :: nbinmax + integer(kind=1), intent(inout) :: ibin_wake(:) + logical :: extf_vdep_flag,done,last_step,accreted + integer :: force_count,nsubsteps + real :: timei,time_par,dt,t_end_step + real :: dtextforce_min +! +! determine whether or not to use substepping +! + if (dtextforce < dtsph) then + dt = dtextforce + last_step = .false. + else + dt = dtsph + last_step = .true. + endif + + timei = time + time_par = time + extf_vdep_flag = is_velocity_dependent(iexternalforce) + t_end_step = timei + dtsph + nsubsteps = 0 + dtextforce_min = huge(dt) + done = .false. + + substeps: do while (timei <= t_end_step .and. .not.done) + force_count = 0 + timei = timei + dt + if (abs(dt) < tiny(0.)) call fatal('substepping','dt <= 0 in sink-gas substepping',var='dt',val=dt) + nsubsteps = nsubsteps + 1 + + if (.not.last_step .and. iverbose > 1 .and. id==master) then + write(iprint,"(a,f14.6)") '> external/ptmass forces only : t=',timei + endif +! +! Main integration scheme +! + call kick(dk(1),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass) + + call drift(ck(1),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) + + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag) + + if (use_fourthorder) then !! FSI 4th order scheme + + ! FSI extrapolation method (Omelyan 2006) + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,fsink_old) + call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass) + + call drift(ck(2),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) + + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) + ! the last kick phase of the scheme will perform the accretion loop after velocity update + call kick(dk(3),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext, & + fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) + if (accreted) then + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) + endif + + else !! standard leapfrog scheme + + ! the last kick phase of the scheme will perform the accretion loop after velocity update + call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext, & + fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) + if (accreted) then + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag) + endif + + endif + + dtextforce_min = min(dtextforce_min,dtextforce) + + if (last_step) then + done = .true. + else + dt = dtextforce + if (timei + dt > t_end_step) then + dt = t_end_step - timei + last_step = .true. + endif + endif + enddo substeps + + if (nsubsteps > 1) then + if (iverbose >=1 .and. id==master) then + write(iprint,"(a,i6,3(a,es10.3))") ' using ',nsubsteps,' substeps '//& + '(dthydro/dtextf =',dtsph/dtextforce_min,'), dt =',dtextforce_min,' dtsph =',dtsph + endif + call summary_variable('ext',iosumextr ,nsubsteps,dtsph/dtextforce_min) + call summary_variable('ext',iosumextt ,nsubsteps,dtextforce_min,1.0/dtextforce_min) + endif + +end subroutine substep + + + !---------------------------------------------------------------- + !+ + ! drift routine for the whole system (part and ptmass) + !+ + !---------------------------------------------------------------- + +subroutine drift(cki,dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) + use part, only:isdead_or_accreted + use ptmass, only:ptmass_drift + use io , only:id,master + use mpiutils, only:bcast_mpi + real, intent(in) :: dt,cki + integer, intent(in) :: npart,nptmass,ntypes + real, intent(inout) :: time_par + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + real :: ckdt + integer :: i + + ckdt = cki*dt + + ! Drift gas particles + + !$omp parallel do default(none) & + !$omp shared(npart,xyzh,vxyzu,ckdt) & + !$omp private(i) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + xyzh(1,i) = xyzh(1,i) + ckdt*vxyzu(1,i) + xyzh(2,i) = xyzh(2,i) + ckdt*vxyzu(2,i) + xyzh(3,i) = xyzh(3,i) + ckdt*vxyzu(3,i) + endif + enddo + !$omp end parallel do + + ! Drift sink particles + if (nptmass>0) then + if (id==master) then + call ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) + endif + call bcast_mpi(xyzmh_ptmass(:,1:nptmass)) + endif + + time_par = time_par + ckdt !! update time for external potential in force routine + +end subroutine drift + + + !---------------------------------------------------------------- + !+ + ! kick routine for the whole system (part and ptmass) + !+ + !---------------------------------------------------------------- + +subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, & + fext,fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) + use part, only:isdead_or_accreted,massoftype,iamtype,iamboundary,iphase,ispinx,ispiny,ispinz,igas + use ptmass, only:f_acc,ptmass_accrete,pt_write_sinkev,update_ptmass,ptmass_kick + use externalforces, only:accrete_particles + use options, only:iexternalforce + use io , only:id,master,fatal,iprint,iverbose + use io_summary, only:summary_accrete,summary_accrete_fail + use mpiutils, only:bcast_mpi,reduce_in_place_mpi,reduceall_mpi + use dim, only:ind_timesteps,maxp,maxphase + use timestep_sts, only:sts_it_n + real, intent(in) :: dt,dki + integer, intent(in) :: npart,nptmass,ntypes + real, intent(inout) :: xyzh(:,:) + real, intent(inout) :: vxyzu(:,:),fext(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) + real, optional, intent(inout) :: dptmass(:,:),fxyz_ptmass_sinksink(:,:) + real, optional, intent(in) :: timei + integer(kind=1), optional, intent(inout) :: ibin_wake(:) + integer(kind=1), optional, intent(in) :: nbinmax + logical , optional, intent(inout) :: accreted + integer(kind=1) :: ibin_wakei + logical :: is_accretion + integer :: i,itype,nfaili + integer :: naccreted,nfail,nlive + real :: dkdt,pmassi,fxi,fyi,fzi,accretedmass + + if (present(dptmass) .and. present(timei) .and. present(ibin_wake) .and. present(nbinmax)) then + is_accretion = .true. + else + is_accretion = .false. + endif + + itype = iphase(igas) + pmassi = massoftype(igas) + + dkdt = dki*dt + + ! Kick sink particles + if (nptmass>0) then + if (id==master) then + call ptmass_kick(nptmass,dkdt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dsdt_ptmass) + endif + call bcast_mpi(vxyz_ptmass(:,1:nptmass)) + call bcast_mpi(xyzmh_ptmass(ispinx,1:nptmass)) + call bcast_mpi(xyzmh_ptmass(ispiny,1:nptmass)) + call bcast_mpi(xyzmh_ptmass(ispinz,1:nptmass)) + endif + + + ! Kick gas particles + + if (.not.is_accretion) then + !$omp parallel do default(none) & + !$omp shared(maxp,maxphase) & + !$omp shared(iphase,ntypes) & + !$omp shared(npart,fext,xyzh,vxyzu,dkdt) & + !$omp firstprivate(itype) & + !$omp private(i) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + if (ntypes > 1 .and. maxphase==maxp) then + itype = iamtype(iphase(i)) + if (iamboundary(itype)) cycle + endif + vxyzu(1,i) = vxyzu(1,i) + dkdt*fext(1,i) + vxyzu(2,i) = vxyzu(2,i) + dkdt*fext(2,i) + vxyzu(3,i) = vxyzu(3,i) + dkdt*fext(3,i) + endif + enddo + !$omp end parallel do + + else + accretedmass = 0. + nfail = 0 + naccreted = 0 + nlive = 0 + ibin_wakei = 0 + dptmass(:,1:nptmass) = 0. + !$omp parallel default(none) & + !$omp shared(maxp,maxphase) & + !$omp shared(npart,xyzh,vxyzu,fext,dkdt,iphase,ntypes,massoftype,timei,nptmass,sts_it_n) & + !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,f_acc) & + !$omp shared(iexternalforce) & + !$omp shared(nbinmax,ibin_wake) & + !$omp reduction(+:dptmass) & + !$omp private(i,accreted,nfaili,fxi,fyi,fzi) & + !$omp firstprivate(itype,pmassi,ibin_wakei) & + !$omp reduction(+:accretedmass,nfail,naccreted,nlive) + !$omp do + accreteloop: do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + if (ntypes > 1 .and. maxphase==maxp) then + itype = iamtype(iphase(i)) + pmassi = massoftype(itype) + if (iamboundary(itype)) cycle accreteloop + endif + ! + ! correct v to the full step using only the external force + ! + vxyzu(1,i) = vxyzu(1,i) + dkdt*fext(1,i) + vxyzu(2,i) = vxyzu(2,i) + dkdt*fext(2,i) + vxyzu(3,i) = vxyzu(3,i) + dkdt*fext(3,i) + + if (iexternalforce > 0) then + call accrete_particles(iexternalforce,xyzh(1,i),xyzh(2,i), & + xyzh(3,i),xyzh(4,i),pmassi,timei,accreted) + if (accreted) accretedmass = accretedmass + pmassi + endif + ! + ! accretion onto sink particles + ! need position, velocities and accelerations of both gas and sinks to be synchronised, + ! otherwise will not conserve momentum + ! Note: requiring sts_it_n since this is supertimestep with the most active particles + ! + if (nptmass > 0 .and. sts_it_n) then + fxi = fext(1,i) + fyi = fext(2,i) + fzi = fext(3,i) + if (ind_timesteps) ibin_wakei = ibin_wake(i) + + call ptmass_accrete(1,nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& + vxyzu(1,i),vxyzu(2,i),vxyzu(3,i),fxi,fyi,fzi,& + itype,pmassi,xyzmh_ptmass,vxyz_ptmass,& + accreted,dptmass,timei,f_acc,nbinmax,ibin_wakei,nfaili) + if (accreted) then + naccreted = naccreted + 1 + cycle accreteloop + else + if (ind_timesteps) ibin_wake(i) = ibin_wakei + endif + if (nfaili > 1) nfail = nfail + 1 + endif + nlive = nlive + 1 + endif + enddo accreteloop + !$omp enddo + !$omp end parallel + + if (npart > 2 .and. nlive < 2) then + call fatal('step','all particles accreted',var='nlive',ival=nlive) + endif + +! +! reduction of sink particle changes across MPI +! + accreted = .false. + if (nptmass > 0) then + call reduce_in_place_mpi('+',dptmass(:,1:nptmass)) + + naccreted = int(reduceall_mpi('+',naccreted)) + nfail = int(reduceall_mpi('+',nfail)) + if (naccreted > 0) accreted = .true. + + if (id==master) call update_ptmass(dptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass) + + call bcast_mpi(xyzmh_ptmass(:,1:nptmass)) + call bcast_mpi(vxyz_ptmass(:,1:nptmass)) + call bcast_mpi(fxyz_ptmass(:,1:nptmass)) + endif + + if (iverbose >= 2 .and. id==master .and. naccreted /= 0) write(iprint,"(a,es10.3,a,i4,a,i4,a)") & + 'Step: at time ',timei,', ',naccreted,' particles were accreted amongst ',nptmass,' sink(s).' + + if (nptmass > 0) then + call summary_accrete_fail(nfail) + call summary_accrete(nptmass) + ! only write to .ev during substeps if no gas particles present + if (npart==0) call pt_write_sinkev(nptmass,timei,xyzmh_ptmass,vxyz_ptmass, & + fxyz_ptmass,fxyz_ptmass_sinksink) + endif + endif + + +end subroutine kick + +!---------------------------------------------------------------- +!+ +! force routine for the whole system. First is computed the +! sink/sink interaction and extf on sink, then comes forces +! on gas. sink/gas, extf and dampening. Finally there is an +! update of abundances and temp depending on cooling method +! during the last force calculation of the substep. +!+ +!---------------------------------------------------------------- +subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, & + fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dki, & + force_count,extf_vdep_flag,fsink_old) + use io, only:iverbose,master,id,iprint,warning,fatal + use dim, only:maxp,maxvxyzu,itau_alloc + use ptmass, only:get_accel_sink_gas,get_accel_sink_sink,merge_sinks, & + ptmass_vdependent_correction,n_force_order + use options, only:iexternalforce + use part, only:maxphase,abundance,nabundances,epot_sinksink,eos_vars,& + isdead_or_accreted,iamboundary,igas,iphase,iamtype,massoftype,divcurlv, & + fxyz_ptmass_sinksink,dsdt_ptmass_sinksink,dust_temp,tau,& + nucleation,idK2,idmu,idkappa,idgamma,imu,igamma + use cooling_ism, only:dphot0,dphotflag,abundsi,abundo,abunde,abundc,nabn + use timestep, only:bignumber,C_force + use mpiutils, only:bcast_mpi,reduce_in_place_mpi,reduceall_mpi + use damping, only:apply_damp,idamp,calc_damp + use externalforces, only:update_externalforce + use ptmass_radiation,only:get_rad_accel_from_ptmass,isink_radiation + integer, intent(in) :: nptmass,npart,nsubsteps,ntypes + integer, intent(inout) :: force_count + real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(4,nptmass),dsdt_ptmass(3,nptmass) + real, intent(inout) :: dtextforce + real, intent(in) :: timei,dki,dt + logical, intent(in) :: extf_vdep_flag + real, optional, intent(inout) :: fsink_old(4,nptmass) + integer :: merge_ij(nptmass) + integer :: merge_n + integer :: i,itype + real, save :: dmdt = 0. + real :: dtf,dtextforcenew,dtsinkgas,dtphi2,fonrmax + real :: fextx,fexty,fextz,xi,yi,zi,pmassi,damp_fac + real :: fonrmaxi,phii,dtphi2i + real :: dkdt,extrapfac + logical :: extrap,last + + if (present(fsink_old)) then + fsink_old = fxyz_ptmass + extrap = .true. + else + extrap = .false. + endif + + force_count = force_count + 1 + extrapfac = (1./24.)*dt**2 + dkdt = dki*dt + itype = igas + pmassi = massoftype(igas) + dtextforcenew = bignumber + dtsinkgas = bignumber + dtphi2 = bignumber + fonrmax = 0 + last = (force_count == n_force_order) + + ! + ! update time-dependent external forces + ! + call calc_damp(timei, damp_fac) + call update_externalforce(iexternalforce,timei,dmdt) + ! + ! Sink-sink interactions (loop over ptmass in get_accel_sink_sink) + ! + if (nptmass > 0) then + if (id==master) then + if (extrap) then + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n, & + dsdt_ptmass,extrapfac,fsink_old) + if (merge_n > 0) then + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n, & + dsdt_ptmass,extrapfac,fsink_old) + endif + else + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) + if (merge_n > 0) then + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) + fxyz_ptmass_sinksink=fxyz_ptmass + dsdt_ptmass_sinksink=dsdt_ptmass + if (iverbose >= 2) write(iprint,*) 'dt(sink-sink) = ',C_force*dtf + endif + endif + else + fxyz_ptmass(:,:) = 0. + dsdt_ptmass(:,:) = 0. + endif + call bcast_mpi(epot_sinksink) + call bcast_mpi(dtf) + dtextforcenew = min(dtextforcenew,C_force*dtf) + endif + + ! + !-- Forces on gas particles (Sink/gas,extf,damp,cooling) + ! + + !$omp parallel default(none) & + !$omp shared(maxp,maxphase) & + !$omp shared(npart,nptmass,xyzh,vxyzu,xyzmh_ptmass,fext) & + !$omp shared(eos_vars,dust_temp,idamp,damp_fac,abundance,iphase,ntypes,massoftype) & + !$omp shared(dkdt,dt,timei,iexternalforce,extf_vdep_flag,last) & + !$omp shared(divcurlv,dphotflag,dphot0,nucleation,extrap) & + !$omp shared(abundc,abundo,abundsi,abunde,extrapfac,fsink_old) & + !$omp private(fextx,fexty,fextz,xi,yi,zi) & + !$omp private(i,fonrmaxi,dtphi2i,phii,dtf) & + !$omp firstprivate(pmassi,itype) & + !$omp reduction(min:dtextforcenew,dtphi2) & + !$omp reduction(max:fonrmax) & + !$omp reduction(+:fxyz_ptmass,dsdt_ptmass) + !$omp do + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + if (ntypes > 1 .and. maxphase==maxp) then + itype = iamtype(iphase(i)) + pmassi = massoftype(itype) + endif + fextx = 0. + fexty = 0. + fextz = 0. + if (extrap) then + xi = xyzh(1,i) + extrapfac*fext(1,i) + yi = xyzh(2,i) + extrapfac*fext(2,i) + zi = xyzh(3,i) + extrapfac*fext(3,i) + else + xi = xyzh(1,i) + yi = xyzh(2,i) + zi = xyzh(3,i) + endif + if (nptmass > 0) then + if (extrap) then + call get_accel_sink_gas(nptmass,xi,yi,zi,xyzh(4,i),xyzmh_ptmass,& + fextx,fexty,fextz,phii,pmassi,fxyz_ptmass, & + dsdt_ptmass,fonrmaxi,dtphi2i,extrapfac,fsink_old) + else + call get_accel_sink_gas(nptmass,xi,yi,zi,xyzh(4,i),xyzmh_ptmass,& + fextx,fexty,fextz,phii,pmassi,fxyz_ptmass,dsdt_ptmass,fonrmaxi,dtphi2i) + fonrmax = max(fonrmax,fonrmaxi) + dtphi2 = min(dtphi2,dtphi2i) + endif + endif + + ! + ! compute and add external forces + ! + if (iexternalforce > 0) then + call get_external_force_gas(xi,yi,zi,xyzh(4,i),vxyzu(1,i), & + vxyzu(2,i),vxyzu(3,i),timei,i, & + dtextforcenew,dtf,dkdt,fextx,fexty,fextz, & + extf_vdep_flag,iexternalforce) + endif + ! + ! damping + ! + if (idamp > 0) then + call apply_damp(fextx, fexty, fextz, vxyzu(1:3,i), (/xi,yi,zi/), damp_fac) + endif + + fext(1,i) = fextx + fext(2,i) = fexty + fext(3,i) = fextz + ! + ! temperature and abundances update (only done during the last force calculation of the substep) + ! + if (maxvxyzu >= 4 .and. itype==igas .and. last) then + call cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucleation,dust_temp, & + divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0) + endif + endif + enddo + !$omp enddo + !$omp end parallel + + if (nptmass > 0 .and. isink_radiation > 0 .and. .not.extrap) then + if (itau_alloc == 1) then + call get_rad_accel_from_ptmass(nptmass,npart,xyzh,xyzmh_ptmass,fext,tau) + else + call get_rad_accel_from_ptmass(nptmass,npart,xyzh,xyzmh_ptmass,fext) + endif + endif + + if (nptmass > 0) then + call reduce_in_place_mpi('+',fxyz_ptmass(:,1:nptmass)) + call reduce_in_place_mpi('+',dsdt_ptmass(:,1:nptmass)) + if (id==master .and. extf_vdep_flag) then + call ptmass_vdependent_correction(nptmass,dkdt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,iexternalforce) + endif + endif + + if (last) then + if (nptmass > 0) then + if (fonrmax > 0.) then + dtsinkgas = min(dtsinkgas,C_force*1./sqrt(fonrmax),C_force*sqrt(dtphi2)) + endif + if (iverbose >= 2) write(iprint,*) nsubsteps,'dt(ext/sink-sink) = ',dtextforcenew,', dt(sink-gas) = ',dtsinkgas + dtextforcenew = min(dtextforcenew,dtsinkgas) + endif + + dtextforcenew = reduceall_mpi('min',dtextforcenew) + dtextforce = dtextforcenew + endif + +end subroutine get_force + +!----------------------------------------------------------------------------------- +!+ +! Update of abundances and internal energy using cooling method (see cooling module) +! NOTE: The chemistry and cooling here is implicitly calculated. That is, +! dt is *passed in* to the chemistry & cooling routines so that the +! output will be at the correct time of time + dt. Since this is +! implicit, there is no cooling timestep. Explicit cooling is +! calculated in force and requires a cooling timestep. +!+ +!------------------------------------------------------------------------------------ +subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucleation,dust_temp, & + divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0) + use dim, only:h2chemistry,do_nucleation,use_krome,update_muGamma,store_dust_temperature + use part, only:idK2,idmu,idkappa,idgamma,imu,igamma,nabundances + use cooling_ism, only:nabn,dphotflag + use options, only:icooling + use chem, only:update_abundances,get_dphot + use dust_formation, only:evolve_dust + use cooling, only:energ_cooling,cooling_in_step + use part, only:rhoh +#ifdef KROME + use part, only: T_gas_cool + use krome_interface, only: update_krome + real :: ui +#endif + real, intent(inout) :: vxyzu(:,:),xyzh(:,:) + real, intent(inout) :: eos_vars(:,:),abundance(:,:) + real, intent(inout) :: nucleation(:,:),dust_temp(:) + real(kind=4), intent(in) :: divcurlv(:,:) + real, intent(inout) :: abundc,abunde,abundo,abundsi + real(kind=8), intent(in) :: dphot0 + real, intent(in) :: dt,pmassi + integer, intent(in) :: i + + real :: dudtcool,rhoi,dphot + real :: abundi(nabn) + + dudtcool = 0. + rhoi = rhoh(xyzh(4,i),pmassi) + ! + ! CHEMISTRY + ! + if (h2chemistry) then + ! + ! Get updated abundances of all species, updates 'chemarrays', + ! + dphot = get_dphot(dphotflag,dphot0,xyzh(1,i),xyzh(2,i),xyzh(3,i)) + call update_abundances(vxyzu(4,i),rhoi,abundance(:,i),nabundances,& + dphot,dt,abundi,nabn,eos_vars(imu,i),abundc,abunde,abundo,abundsi) + endif +#ifdef KROME + ! evolve chemical composition and determine new internal energy + ! Krome also computes cooling function but only associated with chemical processes + ui = vxyzu(4,i) + call update_krome(dt,xyzh(:,i),ui,rhoi,abundance(:,i),eos_vars(igamma,i),eos_vars(imu,i),T_gas_cool(i)) + dudtcool = (ui-vxyzu(4,i))/dt +#else + !evolve dust chemistry and compute dust cooling + if (do_nucleation) then + call evolve_dust(dt, xyzh(:,i), vxyzu(4,i), nucleation(:,i), dust_temp(i), rhoi) + eos_vars(imu,i) = nucleation(idmu,i) + eos_vars(igamma,i) = nucleation(idgamma,i) + endif + ! + ! COOLING + ! + if (icooling > 0 .and. cooling_in_step) then + if (h2chemistry) then + ! + ! Call cooling routine, requiring total density, some distance measure and + ! abundances in the 'abund' format + ! + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,& + dust_temp(i),eos_vars(imu,i), eos_vars(igamma,i),abund_in=abundi) + elseif (store_dust_temperature) then + ! cooling with stored dust temperature + if (do_nucleation) then + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,& + dust_temp(i),nucleation(idmu,i),nucleation(idgamma,i),nucleation(idK2,i),nucleation(idkappa,i)) + elseif (update_muGamma) then + call energ_cooling(xyzh(1,i),xyzh(2,i),xyzh(3,i),vxyzu(4,i),rhoi,dt,divcurlv(1,i),dudtcool,& + dust_temp(i),eos_vars(imu,i), eos_vars(igamma,i)) + 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 + 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) + endif + endif +#endif + ! update internal energy + if (cooling_in_step .or. use_krome) vxyzu(4,i) = vxyzu(4,i) + dt * dudtcool + + +end subroutine cooling_abundances_update + + !---------------------------------------------------------------- + !+ + ! routine for external force applied on gas particle + !+ + !---------------------------------------------------------------- + +subroutine get_external_force_gas(xi,yi,zi,hi,vxi,vyi,vzi,timei,i,dtextforcenew,dtf,dkdt, & + fextx,fexty,fextz,extf_is_velocity_dependent,iexternalforce) + use timestep, only:C_force + use externalforces, only: externalforce,update_vdependent_extforce + real, intent(in) :: xi,yi,zi,hi,vxi,vyi,vzi,timei,dkdt + real, intent(inout) :: dtextforcenew,dtf,fextx,fexty,fextz + integer, intent(in) :: iexternalforce,i + logical, intent(in) :: extf_is_velocity_dependent + real :: fextxi,fextyi,fextzi,poti + real :: fextv(3) + + call externalforce(iexternalforce,xi,yi,zi,hi, & + timei,fextxi,fextyi,fextzi,poti,dtf,i) + dtextforcenew = min(dtextforcenew,C_force*dtf) + + fextx = fextx + fextxi + fexty = fexty + fextyi + fextz = fextz + fextzi +! +! Velocity-dependent external forces require special handling +! in leapfrog (corrector is implicit) +! + if (extf_is_velocity_dependent) then + fextxi = fextx + fextyi = fexty + fextzi = fextz + call update_vdependent_extforce(iexternalforce,vxi,vyi,vzi, & + fextxi,fextyi,fextzi,fextv,dkdt,xi,yi,zi) + fextx = fextx + fextv(1) + fexty = fexty + fextv(2) + fextz = fextz + fextv(3) + endif + + +end subroutine get_external_force_gas + + +end module substepping diff --git a/src/tests/test_derivs.F90 b/src/tests/test_derivs.F90 index 4423158f5..271f8ccec 100644 --- a/src/tests/test_derivs.F90 +++ b/src/tests/test_derivs.F90 @@ -31,7 +31,7 @@ module testderivs subroutine test_derivs(ntests,npass,string) use dim, only:maxp,maxvxyzu,maxalpha,maxdvdx,ndivcurlv,nalpha,use_dust,& - maxdustsmall,periodic,mpi + maxdustsmall,periodic,mpi,ind_timesteps use boundary, only:dxbound,dybound,dzbound,xmin,xmax,ymin,ymax,zmin,zmax use eos, only:polyk,gamma,init_eos use io, only:iprint,id,master,fatal,iverbose,nprocs @@ -53,34 +53,24 @@ subroutine test_derivs(ntests,npass,string) use viscosity, only:bulkvisc,shearparam,irealvisc use part, only:iphase,isetphase,igas use nicil, only:use_ambi -#ifdef IND_TIMESTEPS use timestep_ind, only:nactive use part, only:ibin -#endif -#ifdef DUST use dust, only:init_drag,idrag,K_code use part, only:grainsize,graindens,ndustlarge,ndusttypes -#endif use units, only:set_units use testutils, only:checkval,checkvalf,update_test_scores use mpidomain, only:i_belong integer, intent(inout) :: ntests,npass character(len=*), intent(in) :: string real :: psep,time,hzero,totmass -#ifdef IND_TIMESTEPS - integer :: itest,ierr2,nptest + integer :: itest,ierr2,nptest,nstart,nend,nstep real :: fracactive,speedup real(kind=4) :: tallactive real, allocatable :: fxyzstore(:,:),dBdtstore(:,:) -#else - integer :: nactive -#endif real :: psepblob,hblob,rhoblob,rblob,totvol,rtest -#ifdef PERIODIC integer :: maxtrial,maxactual integer(kind=8) :: nrhocalc,nactual,nexact real :: trialmean,actualmean,realneigh -#endif real :: rcut real :: rho1i,deint,demag,dekin,dedust,dmdust(maxdustsmall),dustfraci(maxdustsmall),tol real(kind=4) :: tused @@ -91,11 +81,8 @@ subroutine test_derivs(ntests,npass,string) real :: stressmax,rhoi,sonrhoi(maxdustsmall),drhodti,depsdti(maxdustsmall),dustfracj integer(kind=8) :: nptot real, allocatable :: dummy(:) -#ifdef IND_TIMESTEPS real :: tolh_old -#endif - logical :: checkmask(maxp) - + logical, allocatable :: mask(:) if (id==master) write(*,"(a,/)") '--> TESTING DERIVS MODULE' @@ -134,6 +121,7 @@ subroutine test_derivs(ntests,npass,string) testgradh = (maxgradh==maxp .and. index(kernelname,'cubic') > 0) call init_part() + allocate(mask(maxp)) iprint = 6 iverbose = max(iverbose,2) psep = dxbound/100. @@ -159,13 +147,13 @@ subroutine test_derivs(ntests,npass,string) nptot = reduceall_mpi('+',npart) massoftype(1) = totmass/reduceall_mpi('+',npart) -#ifndef PERIODIC - ! exclude particles near edge - rcut = min(xmax,ymax,zmax) - 2.*radkern*hfact*psep -#else - ! include all - rcut = sqrt(huge(rcut)) -#endif + if (periodic) then + ! include all particles + rcut = sqrt(huge(rcut)) + else + ! exclude particles near edge + rcut = min(xmax,ymax,zmax) - 2.*radkern*hfact*psep + endif print*,'thread ',id,' npart = ',npart if (id==master) print "(a,g9.2)",' hfact = ',hfact @@ -197,14 +185,15 @@ subroutine test_derivs(ntests,npass,string) !--calculate pure hydro derivatives with velocity and ! pressure distributions (no viscosity) ! - if (id==master) write(*,"(/,a)") '--> testing Hydro derivatives ' + if (id==master) write(*,"(/,a)") '--> testing Hydro derivatives (derivshydro)' call set_velocity_and_energy call reset_mhd_to_zero + if (maxvxyzu < 4) polyk = 3. ! !--calculate derivatives ! call get_derivs_global(tused) - call rcut_checkmask(rcut,xyzh,npart,checkmask) + call rcut_mask(rcut,xyzh,npart,mask) ! !--check hydro quantities come out as they should do ! @@ -214,8 +203,8 @@ subroutine test_derivs(ntests,npass,string) ! !--also check that the number of neighbours is correct ! -#ifdef PERIODIC - if (id==master .and. index(kernelname,'cubic') > 0) then + + if (id==master .and. periodic .and. index(kernelname,'cubic') > 0) then call get_neighbour_stats(trialmean,actualmean,maxtrial,maxactual,nrhocalc,nactual) realneigh = 4./3.*pi*(hfact*radkern)**3 call checkval(actualmean,real(int(realneigh)),tiny(0.),nfailed(11),'mean nneigh') @@ -225,84 +214,85 @@ subroutine test_derivs(ntests,npass,string) nexact = nptot*int(realneigh) call checkval(nactual,nexact,0,nfailed(14),'total nneigh') endif -#endif ! !--check that the timestep bin has been set ! -#ifdef IND_TIMESTEPS - call checkval(all(ibin(1:npart) > 0),.true.,nfailed(15),'ibin > 0') -#endif + if (ind_timesteps) call checkval(all(ibin(1:npart) > 0),.true.,nfailed(15),'ibin > 0') call update_test_scores(ntests,nfailed,npass) -#ifdef IND_TIMESTEPS - tallactive = tused + if (ind_timesteps) then + tallactive = tused - do itest=0,nint(log10(real(nptot)))-1 - nactive = 10**itest - if (id==master) write(*,"(/,a,i10,a)") '--> testing Hydro derivatives (on ',nactive,' active particles)' - call set_velocity_and_energy - do i=1,npart - if (i <= nactive/nprocs) then - iphase(i) = isetphase(igas,iactive=.true.) - xyzh(4,i) = hzero - else - iphase(i) = isetphase(igas,iactive=.false.) - endif - enddo - call reset_mhd_to_zero - ! - !--check timing for one active particle - ! - call get_derivs_global(tused) - if (id==master) then - fracactive = nactive/real(npart) - speedup = (tused)/tallactive - write(*,"(1x,'(',3(a,f9.5,'%'),')')") & + do itest=0,nint(log10(real(nptot)))-1 + nactive = 10**itest + if (id==master) write(*,"(/,a,i10,a)") '--> testing Hydro derivatives (on ',nactive,' active particles)' + call set_velocity_and_energy + do i=1,npart + if (i <= nactive/nprocs) then + iphase(i) = isetphase(igas,iactive=.true.) + xyzh(4,i) = hzero + else + iphase(i) = isetphase(igas,iactive=.false.) + endif + enddo + call reset_mhd_to_zero + ! + !--check timing for one active particle + ! + call get_derivs_global(tused) + if (id==master) then + fracactive = nactive/real(npart) + speedup = (tused)/tallactive + write(*,"(1x,'(',3(a,f9.5,'%'),')')") & 'moved ',100.*fracactive,' of particles in ',100.*speedup, & ' of time, efficiency = ',100.*fracactive/speedup - endif + endif - ! - ! Note that we check ALL values, including the inactives. That is we check - ! that the inactives have preserved their values from last time they were - ! calculated (finds bug of mistakenly setting inactives to zero) - ! - nfailed(:) = 0; m = 0 - call check_hydro(np,nfailed,m) - if (maxvxyzu==4) call check_fxyzu(np,nfailed,m) + ! + ! Note that we check ALL values, including the inactives. That is we check + ! that the inactives have preserved their values from last time they were + ! calculated (finds bug of mistakenly setting inactives to zero) + ! + nfailed(:) = 0; m = 0 + call check_hydro(np,nfailed,m) + if (maxvxyzu==4) call check_fxyzu(np,nfailed,m) - call update_test_scores(ntests,nfailed,npass) - ! - !--reset all particles to active for subsequent tests - ! - call reset_allactive() - enddo -#endif + call update_test_scores(ntests,nfailed,npass) + call reset_allactive() ! reset all particles to active for subsequent tests + enddo + endif endif testhydro + ! + !--for subsequent tests involving individual timesteps, cycle + ! through different numbers of active particles + ! + if (ind_timesteps) then + nstart = nint(log10(real(nptot))); nend = 0; nstep = -2 + else + nstart = 1; nend=1; nstep=1 + endif + testavderivs: if (testav .or. testall) then -#ifdef IND_TIMESTEPS - do itest=nint(log10(real(nptot))),0,-2 - nactive = 10**itest -#endif + do itest=nstart,nend,nstep + nactive = npart + if (ind_timesteps) nactive = 10**itest ! !--check artificial viscosity terms (pressure + av) ! if (id==master) then #ifdef DISC_VISCOSITY - write(*,"(/,a)") '--> testing artificial viscosity terms (disc viscosity)' + write(*,"(/,a)") '--> testing artificial viscosity terms w/disc viscosity (derivsav)' #else if (maxalpha==maxp) then - write(*,"(/,a)") '--> testing artificial viscosity terms (individual alpha)' + write(*,"(/,a)") '--> testing artificial viscosity terms w/individual alpha (derivsav)' else - write(*,"(/,a)") '--> testing artificial viscosity terms (constant alpha)' + write(*,"(/,a)") '--> testing artificial viscosity terms w/constant alpha (derivsav)' endif #endif -#ifdef IND_TIMESTEPS if (nactive /= npart) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' -#endif endif if (maxvxyzu < 4) polyk = 3. call set_velocity_only @@ -316,18 +306,16 @@ subroutine test_derivs(ntests,npass,string) if (maxalpha==maxp) alphaind(1,:) = real(alpha,kind=kind(alphaind)) call get_derivs_global() - call rcut_checkmask(rcut,xyzh,npart,checkmask) + call rcut_mask(rcut,xyzh,npart,mask) nfailed(:) = 0; m = 0 call check_hydro(np,nfailed,m) - call checkvalf(np,xyzh,fxyzu(1,:),forceavx,5.7e-3,nfailed(m+1),'art. visc force(x)',checkmask) - call checkvalf(np,xyzh,fxyzu(2,:),forceavy,1.4e-2,nfailed(m+2),'art. visc force(y)',checkmask) - call checkvalf(np,xyzh,fxyzu(3,:),forceavz,1.3e-2,nfailed(m+3),'art. visc force(z)',checkmask) + call checkvalf(np,xyzh,fxyzu(1,:),forceavx,5.7e-3,nfailed(m+1),'art. visc force(x)',mask) + call checkvalf(np,xyzh,fxyzu(2,:),forceavy,1.4e-2,nfailed(m+2),'art. visc force(y)',mask) + call checkvalf(np,xyzh,fxyzu(3,:),forceavz,1.3e-2,nfailed(m+3),'art. visc force(z)',mask) call update_test_scores(ntests,nfailed,npass) -#ifdef IND_TIMESTEPS - call reset_allactive() + if (ind_timesteps) call reset_allactive() enddo -#endif endif testavderivs ! @@ -335,7 +323,7 @@ subroutine test_derivs(ntests,npass,string) ! testcdswitch: if (testcullendehnen .or. testall) then if (maxalpha==maxp .and. nalpha > 1) then - if (id==master) write(*,"(/,a)") '--> testing ddivv/dt in Cullen & Dehnen switch' + if (id==master) write(*,"(/,a)") '--> testing ddivv/dt in Cullen & Dehnen switch (derivscd)' call set_velocity_only do i=1,npart @@ -363,7 +351,7 @@ subroutine test_derivs(ntests,npass,string) call check_hydro(np,nfailed,m) if (nalpha >= 2) then ialphaloc = 2 - call checkvalf(np,xyzh,alphaind(ialphaloc,:),alphalocfunc,3.5e-4,nfailed(m+1),'alphaloc') + call checkvalf(np,xyzh,alphaind(ialphaloc,:),alphalocfunc,3.5e-4,nfailed(m+1),'alphaloc',mask) endif call update_test_scores(ntests,nfailed,npass) else @@ -377,9 +365,9 @@ subroutine test_derivs(ntests,npass,string) ! if (id==master) then if (maxdvdx==maxp) then - write(*,"(/,a)") '--> testing physical viscosity terms (two first derivatives)' + write(*,"(/,a)") '--> testing physical viscosity terms w/two first derivatives (derivsvisc)' else - write(*,"(/,a)") '--> testing physical viscosity terms (direct second derivatives)' + write(*,"(/,a)") '--> testing physical viscosity terms w/direct second derivatives (derivsvisc)' endif endif polyk = 0. @@ -391,30 +379,29 @@ subroutine test_derivs(ntests,npass,string) bulkvisc = 0.75 call get_derivs_global() - call rcut_checkmask(rcut,xyzh,npart,checkmask) + call rcut_mask(rcut,xyzh,npart,mask) nfailed(:) = 0; m = 0 call check_hydro(np,nfailed,m) if (maxdvdx==maxp) then - call checkvalf(np,xyzh,dvdx(1,:),dvxdx,1.7e-3,nfailed(m+1), 'dvxdx',checkmask) - call checkvalf(np,xyzh,dvdx(2,:),dvxdy,2.5e-15,nfailed(m+2), 'dvxdy',checkmask) - call checkvalf(np,xyzh,dvdx(3,:),dvxdz,2.5e-15,nfailed(m+3), 'dvxdz',checkmask) - call checkvalf(np,xyzh,dvdx(4,:),dvydx,1.e-3,nfailed(m+4), 'dvydx',checkmask) - call checkvalf(np,xyzh,dvdx(5,:),dvydy,2.5e-15,nfailed(m+5), 'dvydy',checkmask) - call checkvalf(np,xyzh,dvdx(6,:),dvydz,1.e-3,nfailed(m+6), 'dvydz',checkmask) - call checkvalf(np,xyzh,dvdx(7,:),dvzdx,2.5e-15,nfailed(m+7), 'dvzdx',checkmask) - call checkvalf(np,xyzh,dvdx(8,:),dvzdy,1.5e-3,nfailed(m+8), 'dvzdy',checkmask) - call checkvalf(np,xyzh,dvdx(9,:),dvzdz,2.5e-15,nfailed(m+9),'dvzdz',checkmask) + call checkvalf(np,xyzh,dvdx(1,:),dvxdx,1.7e-3,nfailed(m+1), 'dvxdx',mask) + call checkvalf(np,xyzh,dvdx(2,:),dvxdy,2.5e-15,nfailed(m+2),'dvxdy',mask) + call checkvalf(np,xyzh,dvdx(3,:),dvxdz,2.5e-15,nfailed(m+3),'dvxdz',mask) + call checkvalf(np,xyzh,dvdx(4,:),dvydx,1.e-3,nfailed(m+4), 'dvydx',mask) + call checkvalf(np,xyzh,dvdx(5,:),dvydy,2.5e-15,nfailed(m+5),'dvydy',mask) + call checkvalf(np,xyzh,dvdx(6,:),dvydz,1.e-3,nfailed(m+6), 'dvydz',mask) + call checkvalf(np,xyzh,dvdx(7,:),dvzdx,2.5e-15,nfailed(m+7),'dvzdx',mask) + call checkvalf(np,xyzh,dvdx(8,:),dvzdy,1.5e-3,nfailed(m+8), 'dvzdy',mask) + call checkvalf(np,xyzh,dvdx(9,:),dvzdz,2.5e-15,nfailed(m+9),'dvzdz',mask) endif - call checkvalf(np,xyzh,fxyzu(1,:),forceviscx,4.e-2,nfailed(m+10),'viscous force(x)',checkmask) - call checkvalf(np,xyzh,fxyzu(2,:),forceviscy,3.e-2,nfailed(m+11),'viscous force(y)',checkmask) - call checkvalf(np,xyzh,fxyzu(3,:),forceviscz,3.1e-2,nfailed(m+12),'viscous force(z)',checkmask) + call checkvalf(np,xyzh,fxyzu(1,:),forceviscx,4.e-2,nfailed(m+10),'viscous force(x)',mask) + call checkvalf(np,xyzh,fxyzu(2,:),forceviscy,3.e-2,nfailed(m+11),'viscous force(y)',mask) + call checkvalf(np,xyzh,fxyzu(3,:),forceviscz,3.1e-2,nfailed(m+12),'viscous force(z)',mask) ! !--also check that the number of neighbours is correct ! -#ifdef PERIODIC - if (id==master) then + if (id==master .and. periodic) then call get_neighbour_stats(trialmean,actualmean,maxtrial,maxactual,nrhocalc,nactual) realneigh = 4./3.*pi*(hfact*radkern)**3 if (testall) then @@ -428,7 +415,6 @@ subroutine test_derivs(ntests,npass,string) call checkval(nactual,nexact,0,nfailed(18),'total nneigh') endif endif -#endif ! !--check that \sum m (du/dt + v.dv/dt) = 0. ! only applies if all particles active - with individual timesteps @@ -464,24 +450,24 @@ subroutine test_derivs(ntests,npass,string) ! if (use_dust) use_dustfrac=.true. if (use_dustfrac) then - if (id==master) write(*,"(/,a)") '--> testing dust evolution terms' -#ifdef DUST - idrag = 2 - gamma = 5./3. - !--Warning, K_code is not well defined when using multiple dust grains - ! and ONLY makes sense IFF all dust grains are identical (although - ! potentially binned with unequal densities). - ! K_code and K_k are related via: K_k = eps_k/eps*K_code) - K_code = 10. - grainsize = 0.01 - graindens = 3. - ndustsmall = maxdustsmall - ndustlarge = 0 - ndusttypes = ndustsmall + ndustlarge - !need to set units if testing with physical drag - !call set_units(dist=au,mass=solarm,G=1.d0) - call init_drag(nfailed(1)) -#endif + if (id==master) write(*,"(/,a)") '--> testing dust evolution terms (derivsdust)' + if (use_dust) then + idrag = 2 + gamma = 5./3. + !--Warning, K_code is not well defined when using multiple dust grains + ! and ONLY makes sense IFF all dust grains are identical (although + ! potentially binned with unequal densities). + ! K_code and K_k are related via: K_k = eps_k/eps*K_code) + K_code = 10. + grainsize = 0.01 + graindens = 3. + ndustsmall = maxdustsmall + ndustlarge = 0 + ndusttypes = ndustsmall + ndustlarge + !need to set units if testing with physical drag + !call set_units(dist=au,mass=solarm,G=1.d0) + call init_drag(nfailed(1)) + endif polyk = 0. call reset_mhd_to_zero call reset_dissipation_to_zero @@ -494,17 +480,18 @@ subroutine test_derivs(ntests,npass,string) enddo call get_derivs_global() + call rcut_mask(rcut,xyzh,npart,mask) nfailed(:) = 0; m = 0 call check_hydro(np,nfailed,m) do j=1,1 !ndustsmall !--Only need one because all dust species are identical -#ifdef DUST - grainsizek = grainsize(j) - graindensk = graindens(j) -#endif - call checkvalf(np,xyzh,ddustevol(j,:),ddustevol_func,4.e-5,nfailed(m+1),'deps/dt') - if (maxvxyzu>=4) call checkvalf(np,xyzh,fxyzu(iu,:),dudtdust_func,1.e-3,nfailed(m+2),'du/dt') - call checkvalf(np,xyzh,deltav(1,j,:),deltavx_func,1.01e-3,nfailed(m+3),'deltavx') + if (use_dust) then + grainsizek = grainsize(j) + graindensk = graindens(j) + endif + call checkvalf(np,xyzh,ddustevol(j,:),ddustevol_func,4.e-5,nfailed(m+1),'deps/dt',mask) + if (maxvxyzu>=4) call checkvalf(np,xyzh,fxyzu(iu,:),dudtdust_func,1.e-3,nfailed(m+2),'du/dt',mask) + call checkvalf(np,xyzh,deltav(1,j,:),deltavx_func,1.01e-3,nfailed(m+3),'deltavx',mask) enddo call update_test_scores(ntests,nfailed,npass) @@ -556,162 +543,151 @@ subroutine test_derivs(ntests,npass,string) ! !--calculate derivatives with MHD forces ON, zero pressure ! - testmhd: if (testmhdderivs .or. testall) then + testmhd: if ((testmhdderivs .or. testall) .and. mhd) then if (.not.testall) call get_derivs_global() ! obtain smoothing lengths -#ifdef IND_TIMESTEPS - do itest=nint(log10(real(nptot))),0,-2 - nactive = 10**itest -#endif + do itest=nstart,nend,nstep + if (ind_timesteps) nactive = 10**itest polyk = 0. call reset_mhd_to_zero call reset_dissipation_to_zero - if (mhd) then - if (id==master) then - write(*,"(/,a)") '--> testing MHD derivatives (using B/rho directly)' - if (nactive /= np) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' - endif - Bextx = 2.0e-1 - Bexty = 3.0e-1 - Bextz = 0.5 - call set_velocity_only - call set_magnetic_field - do i=1,npart - Bevol(4,i) = 0. - enddo - call set_active(npart,nactive/nprocs,igas) - call get_derivs_global() - ! - !--check that various quantities come out as they should do - ! - nfailed(:) = 0 - call checkval(np,xyzh(4,:),hzero,3.e-4,nfailed(1),'h (density)') - - call checkvalf(np,xyzh,divBsymm(:),divBfunc,2.e-3,nfailed(2),'divB (symm)') - call checkvalf(np,xyzh,dBevol(1,:),dBxdt,2.e-3,nfailed(3),'dBx/dt') - call checkvalf(np,xyzh,dBevol(2,:),dBydt,2.e-3,nfailed(4),'dBy/dt') - call checkvalf(np,xyzh,dBevol(3,:),dBzdt,2.e-2,nfailed(5),'dBz/dt') - - call checkvalf(np,xyzh,fxyzu(1,:),forcemhdx,2.5e-2,nfailed(9),'mhd force(x)') - call checkvalf(np,xyzh,fxyzu(2,:),forcemhdy,2.5e-2,nfailed(10),'mhd force(y)') - call checkvalf(np,xyzh,fxyzu(3,:),forcemhdz,2.5e-2,nfailed(11),'mhd force(z)') - if (ndivcurlB >= 1) then - call checkvalf(np,xyzh,divcurlB(idivB,:),divBfunc,1.e-3,nfailed(12),'div B (diff)') - endif - if (ndivcurlB >= 4) then - call checkvalf(np,xyzh,divcurlB(icurlBx,:),curlBfuncx,1.e-3,nfailed(13),'curlB(x)') - call checkvalf(np,xyzh,divcurlB(icurlBy,:),curlBfuncy,1.e-3,nfailed(14),'curlB(y)') - call checkvalf(np,xyzh,divcurlB(icurlBz,:),curlBfuncz,1.e-3,nfailed(15),'curlB(z)') - endif - call update_test_scores(ntests,nfailed,npass) + if (id==master) then + write(*,"(/,a)") '--> testing MHD derivatives (derivsmhd)' + if (nactive /= np) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' + endif + Bextx = 2.0e-1 + Bexty = 3.0e-1 + Bextz = 0.5 + call set_velocity_only + call set_magnetic_field + do i=1,npart + Bevol(4,i) = 0. + enddo + call set_active(npart,nactive/nprocs,igas) + call get_derivs_global() + call rcut_mask(rcut,xyzh,npart,mask) + + ! + !--check that various quantities come out as they should do + ! + nfailed(:) = 0 + call checkval(np,xyzh(4,:),hzero,3.e-4,nfailed(1),'h (density)',mask) + + call checkvalf(np,xyzh,divBsymm(:),divBfunc,2.e-3,nfailed(2),'divB (symm)',mask) + call checkvalf(np,xyzh,dBevol(1,:),dBxdt,2.e-3,nfailed(3),'dBx/dt',mask) + call checkvalf(np,xyzh,dBevol(2,:),dBydt,2.e-3,nfailed(4),'dBy/dt',mask) + call checkvalf(np,xyzh,dBevol(3,:),dBzdt,2.e-2,nfailed(5),'dBz/dt',mask) + + call checkvalf(np,xyzh,fxyzu(1,:),forcemhdx,2.5e-2,nfailed(9),'mhd force(x)',mask) + call checkvalf(np,xyzh,fxyzu(2,:),forcemhdy,2.5e-2,nfailed(10),'mhd force(y)',mask) + call checkvalf(np,xyzh,fxyzu(3,:),forcemhdz,2.5e-2,nfailed(11),'mhd force(z)',mask) + if (ndivcurlB >= 1) then + call checkvalf(np,xyzh,divcurlB(idivB,:),divBfunc,1.e-3,nfailed(12),'div B (diff)',mask) endif -#ifdef IND_TIMESTEPS - call reset_allactive() + if (ndivcurlB >= 4) then + call checkvalf(np,xyzh,divcurlB(icurlBx,:),curlBfuncx,1.e-3,nfailed(13),'curlB(x)',mask) + call checkvalf(np,xyzh,divcurlB(icurlBy,:),curlBfuncy,1.e-3,nfailed(14),'curlB(y)',mask) + call checkvalf(np,xyzh,divcurlB(icurlBz,:),curlBfuncz,1.e-3,nfailed(15),'curlB(z)',mask) + endif + call update_test_scores(ntests,nfailed,npass) + if (ind_timesteps) call reset_allactive() enddo - do itest=nint(log10(real(nptot))),0,-2 - nactive = 10**itest -#endif - if (mhd) then - if (id==master) then - write(*,"(/,a)") '--> testing artificial resistivity terms' - if (nactive /= np) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' - endif - call reset_mhd_to_zero - call reset_dissipation_to_zero - alphaB = 0.214 - polyk = 0. - ieosprev = ieos - ieos = 1 ! isothermal eos, so that the PdV term is zero - call set_magnetic_field + do itest=nstart,nend,nstep + if (ind_timesteps) nactive = 10**itest + if (id==master) then + write(*,"(/,a)") '--> testing artificial resistivity terms (derivsmhd)' + if (nactive /= np) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' + endif + call reset_mhd_to_zero + call reset_dissipation_to_zero + alphaB = 0.214 + polyk = 0. + ieosprev = ieos + ieos = 1 ! isothermal eos, so that the PdV term is zero + call set_magnetic_field + do i=1,npart + vxyzu(:,i) = 0. ! v=0 for this test + Bevol(4,i) = 0. ! psi=0 for this test + enddo + call set_active(npart,nactive,igas) + call get_derivs_global() + call rcut_mask(rcut,xyzh,npart,mask) + ! + !--check that various quantities come out as they should do + ! + nfailed(:) = 0 + ! + !--resistivity test is very approximate + ! To do a proper test, multiply by h/rij in densityforce + ! + call checkvalf(np,xyzh,dBevol(1,:),dBxdtresist,3.7e-2,nfailed(1),'dBx/dt (resist)',mask) + call checkvalf(np,xyzh,dBevol(2,:),dBydtresist,3.4e-2,nfailed(2),'dBy/dt (resist)',mask) + call checkvalf(np,xyzh,dBevol(3,:),dBzdtresist,2.2e-1,nfailed(3),'dBz/dt (resist)',mask) + call update_test_scores(ntests,nfailed,npass) + ! + !--check that \sum m (du/dt + B/rho.dB/dt) = 0. + ! only applies if all particles active - with individual timesteps + ! we just hope that du/dt has not changed all that much on non-active particles + ! + if (maxvxyzu==4 .and. nactive==npart) then + deint = 0. + demag = 0. do i=1,npart - vxyzu(:,i) = 0. ! v=0 for this test - Bevol(4,i) = 0. ! psi=0 for this test + rho1i = 1./rhoh(xyzh(4,i),massoftype(1)) + deint = deint + fxyzu(iu,i) + demag = demag + dot_product(Bevol(1:3,i),dBevol(1:3,i))*rho1i enddo - call set_active(npart,nactive,igas) - call get_derivs_global() - call rcut_checkmask(rcut,xyzh,npart,checkmask) - ! - !--check that various quantities come out as they should do - ! nfailed(:) = 0 - ! - !--resistivity test is very approximate - ! To do a proper test, multiply by h/rij in densityforce - ! - call checkvalf(np,xyzh,dBevol(1,:),dBxdtresist,3.7e-2,nfailed(1),'dBx/dt (resist)',checkmask) - call checkvalf(np,xyzh,dBevol(2,:),dBydtresist,3.4e-2,nfailed(2),'dBy/dt (resist)',checkmask) - call checkvalf(np,xyzh,dBevol(3,:),dBzdtresist,2.2e-1,nfailed(3),'dBz/dt (resist)',checkmask) - call update_test_scores(ntests,nfailed,npass) - ! - !--check that \sum m (du/dt + B/rho.dB/dt) = 0. - ! only applies if all particles active - with individual timesteps - ! we just hope that du/dt has not changed all that much on non-active particles - ! - if (maxvxyzu==4 .and. nactive==npart) then - deint = 0. - demag = 0. - do i=1,npart - rho1i = 1./rhoh(xyzh(4,i),massoftype(1)) - deint = deint + fxyzu(iu,i) - demag = demag + dot_product(Bevol(1:3,i),dBevol(1:3,i))*rho1i - enddo - nfailed(:) = 0 - call checkval(deint + demag,0.,2.7e-3,nfailed(1),'\sum du/dt + B.dB/dt = 0') - call update_test_scores(ntests,nfailed(1:1),npass) - endif - - !--restore ieos - ieos = ieosprev - + call checkval(deint + demag,0.,2.7e-3,nfailed(1),'\sum du/dt + B.dB/dt = 0') + call update_test_scores(ntests,nfailed(1:1),npass) endif -#ifdef IND_TIMESTEPS - call reset_allactive() + + !--restore ieos + ieos = ieosprev + if (ind_timesteps) call reset_allactive() enddo tolh_old = tolh - tolh = 1.e-7 - do itest=nint(log10(real(nptot))),0,-2 - nactive = 10**itest -#endif - if (mhd) then - if (id==master) then - write(*,"(/,a)") '--> testing div B cleaning terms' - if (nactive /= np) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' - endif - call reset_mhd_to_zero - call reset_dissipation_to_zero - psidecayfac = 0.8 - polyk = 2. - ieosprev = ieos - ieos = 1 ! isothermal eos - call set_velocity_only - call set_magnetic_field - call set_active(npart,nactive,igas) - call get_derivs_global() - ! - !--check that various quantities come out as they should do - ! - nfailed(:) = 0 - call checkval(np,xyzh(4,:),hzero,3.e-4,nfailed(1),'h (density)') - call checkvalf(np,xyzh,divBsymm(:),divBfunc,1.e-3,nfailed(2),'divB') - call checkvalf(np,xyzh,dBevol(1,:),dpsidx,8.5e-4,nfailed(3),'gradpsi_x') - call checkvalf(np,xyzh,dBevol(2,:),dpsidy,9.3e-4,nfailed(4),'gradpsi_y') - call checkvalf(np,xyzh,dBevol(3,:),dpsidz,2.e-3,nfailed(5),'gradpsi_z') - !--can't do dpsi/dt check because we use vsigdtc = max over neighbours - !call checkvalf(np,xyzh,dBevol(4,:),dpsidt,6.e-3,nfailed(6),'dpsi/dt') - call update_test_scores(ntests,nfailed,npass) - - !--restore ieos - ieos = ieosprev + if (ind_timesteps) tolh = 1.e-7 + do itest=nstart,nend,nstep + if (ind_timesteps) nactive = 10**itest + if (id==master) then + write(*,"(/,a)") '--> testing div B cleaning terms (derivsmhd)' + if (nactive /= np) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' endif -#ifdef IND_TIMESTEPS - call reset_allactive() + call reset_mhd_to_zero + call reset_dissipation_to_zero + psidecayfac = 0.8 + polyk = 2. + ieosprev = ieos + ieos = 1 ! isothermal eos + call set_velocity_only + call set_magnetic_field + call set_active(npart,nactive,igas) + call get_derivs_global() + call rcut_mask(rcut,xyzh,npart,mask) + + ! + !--check that various quantities come out as they should do + ! + nfailed(:) = 0 + call checkval(np,xyzh(4,:),hzero,3.e-4,nfailed(1),'h (density)',mask) + call checkvalf(np,xyzh,divBsymm(:),divBfunc,1.e-3,nfailed(2),'divB',mask) + call checkvalf(np,xyzh,dBevol(1,:),dpsidx,8.5e-4,nfailed(3),'gradpsi_x',mask) + call checkvalf(np,xyzh,dBevol(2,:),dpsidy,9.3e-4,nfailed(4),'gradpsi_y',mask) + call checkvalf(np,xyzh,dBevol(3,:),dpsidz,2.e-3,nfailed(5),'gradpsi_z',mask) + !--can't do dpsi/dt check because we use vsigdtc = max over neighbours + !call checkvalf(np,xyzh,dBevol(4,:),dpsidt,6.e-3,nfailed(6),'dpsi/dt') + call update_test_scores(ntests,nfailed,npass) + + !--restore ieos + ieos = ieosprev + if (ind_timesteps) call reset_allactive() enddo tolh = tolh_old - do itest=nint(log10(real(nptot))),0,-2 - nactive = 10**itest -#endif - if (mhd .and. use_ambi .and. testambipolar) then + do itest=nstart,nend,nstep + if (ind_timesteps) nactive = 10**itest + if (use_ambi .and. testambipolar) then if (id==master) then - write(*,"(/,a)") '--> testing Ambipolar diffusion terms' + write(*,"(/,a)") '--> testing Ambipolar diffusion term (derivsambi)' if (nactive /= np) write(*,"(a,i10,a)") ' (on ',nactive,' active particles)' endif call reset_mhd_to_zero @@ -727,25 +703,24 @@ subroutine test_derivs(ntests,npass,string) enddo call set_active(npart,nactive,igas) call get_derivs_global() + call rcut_mask(rcut,xyzh,npart,mask) ! !--check that various quantities come out as they should do ! nfailed(:) = 0 - call checkval(np,xyzh(4,:),hzero,3.e-4,nfailed(1),'h (density)') - call checkvalf(np,xyzh,dBevol(1,:),dBambix,8.5e-4,nfailed(2),'dBambi_x') - call checkvalf(np,xyzh,dBevol(2,:),dBambiy,8.5e-4,nfailed(3),'dBambi_y') - call checkvalf(np,xyzh,dBevol(3,:),dBambiz,2.e-3,nfailed(4),'dBambi_z') + call checkval(np,xyzh(4,:),hzero,3.e-4,nfailed(1),'h (density)',mask) + call checkvalf(np,xyzh,dBevol(1,:),dBambix,8.5e-4,nfailed(2),'dBambi_x',mask) + call checkvalf(np,xyzh,dBevol(2,:),dBambiy,8.5e-4,nfailed(3),'dBambi_y',mask) + call checkvalf(np,xyzh,dBevol(3,:),dBambiz,2.e-3,nfailed(4),'dBambi_z',mask) call update_test_scores(ntests,nfailed,npass) !--restore ieos ieos = ieosprev endif - -#ifdef IND_TIMESTEPS - call reset_allactive() + if (ind_timesteps) call reset_allactive() enddo -#endif - + else + if (id==master) write(*,"(/,a)") '--> SKIPPING mhd terms (need -DMHD)' endif testmhd ! @@ -756,7 +731,7 @@ subroutine test_derivs(ntests,npass,string) ! and the 'test' particles cannot be identified using the current method ! testdenscontrast: if ((testdensitycontrast .or. testall) .and. (nprocs == 1)) then - if (id==master) write(*,"(/,a)") '--> testing Hydro derivs in setup with density contrast ' + if (id==master) write(*,"(/,a)") '--> testing Hydro derivs in setup with density contrast (derivscontrast)' npart = 0 psep = dxbound/50. @@ -813,8 +788,7 @@ subroutine test_derivs(ntests,npass,string) ! !--also check that the number of neighbours is correct ! -#ifdef PERIODIC - if (id==master .and. index(kernelname,'cubic') > 0) then + if (id==master .and. periodic .and. index(kernelname,'cubic') > 0) then call get_neighbour_stats(trialmean,actualmean,maxtrial,maxactual,nrhocalc,nactual) realneigh = 57.466651861721814 call checkval(actualmean,realneigh,1.e-17,nfailed(m+1),'mean nneigh') @@ -822,54 +796,50 @@ subroutine test_derivs(ntests,npass,string) ! !-- this test does not always give the same results: depends on how the tree is built ! - ! nexact = 1382952 ! got this from a reference calculation - ! call checkval(nrhocalc,nexact,0,nfailed(12),'n density calcs') nexact = 37263216 call checkval(nactual,nexact,0,nfailed(m+3),'total nneigh') endif -#endif call update_test_scores(ntests,nfailed,npass) -#ifdef IND_TIMESTEPS - tallactive = tused - do itest=1,nint(log10(real(nparttest))) - nactive = 10**itest - if (nactive > nparttest) nactive = nparttest - if (id==master) write(*,"(/,a,i6,a)") '--> testing Hydro derivs in setup with density contrast (nactive=',nactive,') ' + if (ind_timesteps) then + tallactive = tused + do itest=1,nint(log10(real(nparttest))) + nactive = 10**itest + if (nactive > nparttest) nactive = nparttest + if (id==master) write(*,"(/,a,i6,a)") '--> testing Hydro derivs in setup with density contrast (nactive=',nactive,') ' - call set_active(npart,nactive,igas) - call get_derivs_global(tused) - if (id==master) then - fracactive = nactive/real(npart) - speedup = tused/tallactive - write(*,"(1x,'(',3(a,f9.5,'%'),')')") & + call set_active(npart,nactive,igas) + call get_derivs_global(tused) + if (id==master) then + fracactive = nactive/real(npart) + speedup = tused/tallactive + write(*,"(1x,'(',3(a,f9.5,'%'),')')") & 'moved ',100.*fracactive,' of particles in ',100.*speedup, & ' of time, efficiency = ',100.*fracactive/speedup - endif - ! - !--check hydro quantities come out as they should do - ! - nfailed(:) = 0; m=5 - call checkval(nparttest,xyzh(4,:),hblob,4.e-4,nfailed(1),'h (density)') - call checkvalf(nparttest,xyzh,divcurlv(idivv,:),divvfunc,1.e-3,nfailed(2),'divv') - if (ndivcurlv >= 4) then - call checkvalf(nparttest,xyzh,divcurlv(icurlvxi,:),curlvfuncx,1.5e-3,nfailed(3),'curlv(x)') - call checkvalf(nparttest,xyzh,divcurlv(icurlvyi,:),curlvfuncy,1.e-3,nfailed(4),'curlv(y)') - call checkvalf(nparttest,xyzh,divcurlv(icurlvzi,:),curlvfuncz,1.e-3,nfailed(5),'curlv(z)') - endif - if (maxvxyzu==4) call check_fxyzu_nomask(nparttest,nfailed,m) - call update_test_scores(ntests,nfailed,npass) - enddo -#endif + endif + ! + !--check hydro quantities come out as they should do + ! + nfailed(:) = 0; m=5 + call checkval(nparttest,xyzh(4,:),hblob,4.e-4,nfailed(1),'h (density)') + call checkvalf(nparttest,xyzh,divcurlv(idivv,:),divvfunc,1.e-3,nfailed(2),'divv') + if (ndivcurlv >= 4) then + call checkvalf(nparttest,xyzh,divcurlv(icurlvxi,:),curlvfuncx,1.5e-3,nfailed(3),'curlv(x)') + call checkvalf(nparttest,xyzh,divcurlv(icurlvyi,:),curlvfuncy,1.e-3,nfailed(4),'curlv(y)') + call checkvalf(nparttest,xyzh,divcurlv(icurlvzi,:),curlvfuncz,1.e-3,nfailed(5),'curlv(z)') + endif + if (maxvxyzu==4) call check_fxyzu_nomask(nparttest,nfailed,m) + call update_test_scores(ntests,nfailed,npass) + enddo + endif endif testdenscontrast ! !--test force evaluation for individual timesteps when particles have very different smoothing lengths/ranges ! - testinddts: if (testindtimesteps .or. testall) then -#ifdef IND_TIMESTEPS - if (id==master) write(*,"(/,a,i6,a)") '--> testing force evaluation with ind_timesteps' + testinddts: if (ind_timesteps .and. (testindtimesteps .or. testall)) then + if (id==master) write(*,"(/,a,i6,a)") '--> testing force evaluation with ind_timesteps (derivsind)' polyk = 0. tolh = 1.e-9 call reset_mhd_to_zero @@ -945,14 +915,12 @@ subroutine test_derivs(ntests,npass,string) endif if (allocated(fxyzstore)) deallocate(fxyzstore) if (allocated(dBdtstore)) deallocate(dBdtstore) -#endif endif testinddts if (id==master) write(*,"(/,a)") '<-- DERIVS TEST COMPLETE' contains -#ifdef IND_TIMESTEPS subroutine reset_allactive ! !--reset all particles to active for subsequent tests @@ -963,22 +931,21 @@ subroutine reset_allactive nactive = npart end subroutine reset_allactive -#endif subroutine set_active(npart,nactive,itype) integer, intent(in) :: npart, nactive, itype ! ! set iphase for mixed active/inactive ! -#ifdef IND_TIMESTEPS - do i=1,npart - if (i <= nactive) then - iphase(i) = isetphase(itype,iactive=.true.) - else - iphase(i) = isetphase(itype,iactive=.false.) - endif - enddo -#endif + if (ind_timesteps) then + do i=1,npart + if (i <= nactive) then + iphase(i) = isetphase(itype,iactive=.true.) + else + iphase(i) = isetphase(itype,iactive=.false.) + endif + enddo + endif end subroutine set_active !-------------------------------------- @@ -1090,14 +1057,14 @@ subroutine check_hydro(n,nfailed,j) integer, intent(in) :: n integer, intent(inout) :: nfailed(:),j - call checkval(n,xyzh(4,1:np),hzero,3.e-4,nfailed(j+1),'h (density)',checkmask) - call checkvalf(n,xyzh,divcurlv(1,1:np),divvfunc,1.e-3,nfailed(j+2),'divv',checkmask) + call checkval(n,xyzh(4,1:np),hzero,3.e-4,nfailed(j+1),'h (density)',mask) + call checkvalf(n,xyzh,divcurlv(1,1:np),divvfunc,1.e-3,nfailed(j+2),'divv',mask) if (ndivcurlv >= 4) then - call checkvalf(n,xyzh,divcurlv(icurlvxi,1:np),curlvfuncx,1.5e-3,nfailed(j+3),'curlv(x)',checkmask) - call checkvalf(n,xyzh,divcurlv(icurlvyi,1:n),curlvfuncy,1.e-3,nfailed(j+4),'curlv(y)',checkmask) - call checkvalf(n,xyzh,divcurlv(icurlvzi,1:n),curlvfuncz,1.e-3,nfailed(j+5),'curlv(z)',checkmask) + call checkvalf(n,xyzh,divcurlv(icurlvxi,1:np),curlvfuncx,1.5e-3,nfailed(j+3),'curlv(x)',mask) + call checkvalf(n,xyzh,divcurlv(icurlvyi,1:n),curlvfuncy,1.e-3,nfailed(j+4),'curlv(y)',mask) + call checkvalf(n,xyzh,divcurlv(icurlvzi,1:n),curlvfuncz,1.e-3,nfailed(j+5),'curlv(z)',mask) endif - if (testgradh) call checkval(n,gradh(1,1:n),1.01948,1.e-5,nfailed(j+6),'gradh',checkmask) + if (testgradh) call checkval(n,gradh(1,1:n),1.01948,1.e-5,nfailed(j+6),'gradh',mask) j = j + 6 end subroutine check_hydro @@ -1112,15 +1079,15 @@ subroutine check_fxyzu(n,nfailed,j) integer, intent(in) :: n integer, intent(inout) :: nfailed(:),j - call checkvalf(n,xyzh,fxyzu(1,:),forcefuncx,1.e-3,nfailed(j+1),'force(x)',checkmask) - call checkvalf(n,xyzh,fxyzu(2,:),forcefuncy,1.e-3,nfailed(j+2),'force(y)',checkmask) - call checkvalf(n,xyzh,fxyzu(3,:),forcefuncz,1.e-3,nfailed(j+3),'force(z)',checkmask) + call checkvalf(n,xyzh,fxyzu(1,:),forcefuncx,1.e-3,nfailed(j+1),'force(x)',mask) + call checkvalf(n,xyzh,fxyzu(2,:),forcefuncy,1.e-3,nfailed(j+2),'force(y)',mask) + call checkvalf(n,xyzh,fxyzu(3,:),forcefuncz,1.e-3,nfailed(j+3),'force(z)',mask) if (ien_type == ien_entropy .or. ieos /= 2) then - call checkval(n,fxyzu(iu,:),0.,epsilon(fxyzu),nfailed(j+4),'den/dt',checkmask) + call checkval(n,fxyzu(iu,:),0.,epsilon(fxyzu),nfailed(j+4),'den/dt',mask) else allocate(dummy(n)) dummy(1:n) = fxyzu(iu,1:n)/((gamma-1.)*vxyzu(iu,1:n)) - call checkvalf(np,xyzh,dummy(1:n),dudtfunc,1.e-3,nfailed(j+4),'du/dt',checkmask) + call checkvalf(np,xyzh,dummy(1:n),dudtfunc,1.e-3,nfailed(j+4),'du/dt',mask) deallocate(dummy) endif j = j + 4 @@ -2499,19 +2466,14 @@ end function del2dustfrac real function ddustevol_func(xyzhi) use eos, only:gamma - use part, only:ndusttypes -#ifdef DUST + use part, only:use_dust,ndusttypes,rhoh use dust, only:get_ts,idrag,K_code -#endif - use part, only:rhoh real, intent(in) :: xyzhi(4) real :: dustfraci,uui,pri,tsi real :: gradu(3),gradeps(3),gradsumeps(3),gradp(3),gradts(3),gradepsts(3) real :: rhoi,rhogasi,rhodusti,spsoundi,del2P,du_dot_de,si real :: dustfracisum,del2dustfracsum -#ifdef DUST integer :: iregime -#endif rhoi = rhoh(xyzhi(4),massoftype(1)) dustfraci = dustfrac_func(xyzhi) @@ -2535,16 +2497,16 @@ real function ddustevol_func(xyzhi) del2P = (gamma-1.)*rhoi*((1. - dustfracisum)*del2u(xyzhi) - 2.*du_dot_de - uui*del2dustfracsum) tsi = 0. -#ifdef DUST - call get_ts(idrag,1,grainsizek,graindensk,rhogasi,rhodusti,spsoundi,0.,tsi,iregime) - ! - ! grad(ts) = grad((1-eps)*eps*rho/K_code) - ! = rho/K_code*(1-2*eps)*grad(eps) ! note the absence of eps_k - ! - gradts(:) = rhoi/K_code(1)*(1. - 2.*dustfracisum)*gradsumeps(:) -#else - gradts(:) = 0. -#endif + if (use_dust) then + call get_ts(idrag,1,grainsizek,graindensk,rhogasi,rhodusti,spsoundi,0.,tsi,iregime) + ! + ! grad(ts) = grad((1-eps)*eps*rho/K_code) + ! = rho/K_code*(1-2*eps)*grad(eps) ! note the absence of eps_k + ! + gradts(:) = rhoi/K_code(1)*(1. - 2.*dustfracisum)*gradsumeps(:) + else + gradts(:) = 0. + endif ! ! deps_k/dt = -1/rho \nabla.(eps_k ts (grad P)) ! note the presence of eps_k ! = -1/rho [eps_k ts \del^2 P + grad(eps_k ts).grad P] @@ -2572,19 +2534,14 @@ end function ddustevol_func real function dudtdust_func(xyzhi) use eos, only:gamma - use part, only:ndusttypes -#ifdef DUST + use part, only:use_dust,ndusttypes,rhoh use dust, only:get_ts,idrag -#endif - use part, only:rhoh real, intent(in) :: xyzhi(4) real :: dustfraci,uui,pri,tsi real :: gradp(3),gradu(3),gradeps(3),gradsumeps(3) real :: rhoi,rhogasi,rhodusti,spsoundi real :: dustfracisum -#ifdef DUST integer :: iregime -#endif rhoi = rhoh(xyzhi(4),massoftype(1)) dustfraci = dustfrac_func(xyzhi) @@ -2604,10 +2561,10 @@ real function dudtdust_func(xyzhi) gradp(:) = (gamma-1.)*(rhogasi*gradu - rhoi*uui*gradsumeps) tsi = 0. -#ifdef DUST - call get_ts(idrag,1,grainsizek,graindensk,rhogasi,rhodusti,spsoundi,0.,tsi,iregime) - if (iregime /= 0) stop 'iregime /= 0' -#endif + if (use_dust) then + call get_ts(idrag,1,grainsizek,graindensk,rhogasi,rhodusti,spsoundi,0.,tsi,iregime) + if (iregime /= 0) stop 'iregime /= 0' + endif ! this is equation (13) of Price & Laibe (2015) except ! that the sign on the second term is wrong in that paper ! (it is correct in Laibe & Price 2014a,b) @@ -2618,17 +2575,13 @@ end function dudtdust_func real function deltavx_func(xyzhi) use eos, only:gamma - use part, only:ndusttypes -#ifdef DUST + use part, only:ndusttypes,use_dust use dust, only:get_ts,idrag -#endif use part, only:rhoh real, intent(in) :: xyzhi(4) real :: rhoi,dustfraci,rhogasi,rhodusti,uui,pri,spsoundi,tsi,gradp real :: dustfracisum,gradsumeps,gradu -#ifdef DUST integer :: iregime -#endif rhoi = rhoh(xyzhi(4),massoftype(1)) dustfraci = dustfrac_func(xyzhi) @@ -2641,26 +2594,24 @@ real function deltavx_func(xyzhi) pri = (gamma-1.)*rhogasi*uui spsoundi = gamma*pri/rhogasi tsi = 0. -#ifdef DUST - call get_ts(idrag,1,grainsizek,graindensk,rhogasi,rhodusti,spsoundi,0.,tsi,iregime) -#endif + if (use_dust) call get_ts(idrag,1,grainsizek,graindensk,rhogasi,rhodusti,spsoundi,0.,tsi,iregime) gradp = (gamma-1.)*(rhogasi*gradu - rhoi*uui*gradsumeps) deltavx_func = tsi*gradp/rhogasi end function deltavx_func -subroutine rcut_checkmask(rcut,xyzh,npart,checkmask) +subroutine rcut_mask(rcut,xyzh,npart,mask) use part, only:isdead_or_accreted real, intent(in) :: rcut real, intent(in) :: xyzh(:,:) integer, intent(in) :: npart - logical, intent(out) :: checkmask(:) + logical, intent(out) :: mask(:) real :: rcut2,xi,yi,zi,hi,r2 integer :: i,ncheck ncheck = 0 rcut2 = rcut*rcut - checkmask(:) = .false. + mask(:) = .false. do i=1,npart xi = xyzh(1,i) yi = xyzh(2,i) @@ -2668,11 +2619,11 @@ subroutine rcut_checkmask(rcut,xyzh,npart,checkmask) hi = xyzh(4,i) r2 = xi*xi + yi*yi + zi*zi if (.not.isdead_or_accreted(hi) .and. r2 < rcut2) then - checkmask(i) = .true. + mask(i) = .true. ncheck = ncheck + 1 endif enddo -end subroutine rcut_checkmask +end subroutine rcut_mask end module testderivs diff --git a/src/tests/test_dust.f90 b/src/tests/test_dust.f90 index 371059769..c025207f5 100644 --- a/src/tests/test_dust.f90 +++ b/src/tests/test_dust.f90 @@ -103,7 +103,7 @@ subroutine test_dust(ntests,npass) ! call test_drag(ntests,npass) call barrier_mpi() - + ! ! DUSTYBOX test with explicit/implicit scheme ! diff --git a/src/tests/test_eos.f90 b/src/tests/test_eos.f90 index 23a1372a7..44f09afe8 100644 --- a/src/tests/test_eos.f90 +++ b/src/tests/test_eos.f90 @@ -10,7 +10,7 @@ module testeos ! ! :References: None ! -! :Owner: Daniel Price +! :Owner: Terrence Tricco ! ! :Runtime parameters: None ! @@ -23,6 +23,7 @@ module testeos public :: test_helmholtz ! to avoid compiler warning for unused routine private + logical :: use_rel_tol = .true. contains !---------------------------------------------------------- @@ -116,7 +117,7 @@ subroutine test_idealplusrad(ntests, npass) use eos_idealplusrad, only:get_idealplusrad_enfromtemp,get_idealplusrad_pres use testutils, only:checkval,checkvalbuf_start,checkvalbuf,checkvalbuf_end,update_test_scores use units, only:unit_density,unit_pressure,unit_ergg - use physcon, only:kb_on_mh + use physcon, only:Rg integer, intent(inout) :: ntests,npass integer :: npts,ieos,ierr,i,j,nfail(2),ncheck(2) real :: rhocodei,gamma,presi,dum,csound,eni,temp,ponrhoi,mu,tol,errmax(2),pres2,code_eni @@ -129,7 +130,7 @@ subroutine test_idealplusrad(ntests, npass) call get_rhoT_grid(npts,rhogrid,Tgrid) dum = 0. - tol = 1.e-12 + tol = 1.e-15 nfail = 0; ncheck = 0; errmax = 0. call init_eos(ieos,ierr) do i=1,npts @@ -140,13 +141,13 @@ subroutine test_idealplusrad(ntests, npass) ! Recalculate T, P, from rho, u code_eni = eni/unit_ergg - temp = eni*mu/kb_on_mh + temp = eni*mu/Rg ! guess rhocodei = rhogrid(i)/unit_density call equationofstate(ieos,ponrhoi,csound,rhocodei,dum,dum,dum,temp,code_eni,mu_local=mu,gamma_local=gamma) pres2 = ponrhoi * rhocodei * unit_pressure - call checkvalbuf(temp,Tgrid(j),tol,'Check recovery of T from rho, u',nfail(1),ncheck(1),errmax(1)) - call checkvalbuf(pres2,presi,tol,'Check recovery of P from rho, u',nfail(2),ncheck(2),errmax(2)) + call checkvalbuf(temp,Tgrid(j),tol,'Check recovery of T from rho, u',nfail(1),ncheck(1),errmax(1),use_rel_tol) + call checkvalbuf(pres2,presi,tol,'Check recovery of P from rho, u',nfail(2),ncheck(2),errmax(2),use_rel_tol) enddo enddo call checkvalbuf_end('Check recovery of T from rho, u',ncheck(1),nfail(1),errmax(1),tol) @@ -170,9 +171,9 @@ subroutine test_hormone(ntests, npass) use testutils, only:checkval,checkvalbuf_start,checkvalbuf,checkvalbuf_end,update_test_scores use units, only:unit_density,unit_pressure,unit_ergg integer, intent(inout) :: ntests,npass - integer :: npts,ieos,ierr,i,j,nfail(4),ncheck(4) - real :: imurec,mu,eni_code,presi,pres2,dum,csound,eni,tempi - real :: ponrhoi,X,Z,tol,errmax(4),gasrad_eni,eni2,rhocodei,gamma + integer :: npts,ieos,ierr,i,j,nfail(6),ncheck(6) + real :: imurec,mu,eni_code,presi,pres2,dum,csound,eni,tempi,gamma_eff + real :: ponrhoi,X,Z,tol,errmax(6),gasrad_eni,eni2,rhocodei,gamma,mu2 real, allocatable :: rhogrid(:),Tgrid(:) if (id==master) write(*,"(/,a)") '--> testing HORMONE equation of states' @@ -185,45 +186,44 @@ subroutine test_hormone(ntests, npass) ! Testing dum = 0. - tol = 1.e-12 + tol = 1.e-14 tempi = -1. nfail = 0; ncheck = 0; errmax = 0. call init_eos(ieos,ierr) - tempi = 1. - eni_code = 764437650.64783347/unit_ergg - rhocodei = 3.2276168501594796E-015/unit_density - call equationofstate(ieos,ponrhoi,csound,rhocodei,0.,0.,0.,tempi,eni_code,mu_local=mu,Xlocal=X,Zlocal=Z,gamma_local=gamma) do i=1,npts do j=1,npts gamma = 5./3. - ! Get mu from rho, T + ! Get mu, u, P from rho, T call get_imurec(log10(rhogrid(i)),Tgrid(j),X,1.-X-Z,imurec) mu = 1./imurec - - ! Get u, P from rho, T, mu call get_idealplusrad_enfromtemp(rhogrid(i),Tgrid(j),mu,gasrad_eni) eni = gasrad_eni + get_erec(log10(rhogrid(i)),Tgrid(j),X,1.-X-Z) call get_idealplusrad_pres(rhogrid(i),Tgrid(j),mu,presi) - ! Recalculate P, T from rho, u, mu + ! Recalculate P, T from rho, u tempi = 1. eni_code = eni/unit_ergg rhocodei = rhogrid(i)/unit_density - call equationofstate(ieos,ponrhoi,csound,rhocodei,0.,0.,0.,tempi,eni_code,mu_local=mu,Xlocal=X,Zlocal=Z,gamma_local=gamma) + call equationofstate(ieos,ponrhoi,csound,rhocodei,0.,0.,0.,tempi,eni_code,& + mu_local=mu2,Xlocal=X,Zlocal=Z,gamma_local=gamma_eff) ! mu and gamma_eff are outputs pres2 = ponrhoi * rhocodei * unit_pressure - call checkvalbuf(tempi,Tgrid(j),tol,'Check recovery of T from rho, u',nfail(1),ncheck(1),errmax(1)) - call checkvalbuf(pres2,presi,tol,'Check recovery of P from rho, u',nfail(2),ncheck(2),errmax(2)) + call checkvalbuf(mu2,mu,tol,'Check recovery of mu from rho, u',nfail(1),ncheck(1),errmax(1),use_rel_tol) + call checkvalbuf(tempi,Tgrid(j),tol,'Check recovery of T from rho, u',nfail(2),ncheck(2),errmax(2),use_rel_tol) + call checkvalbuf(pres2,presi,tol,'Check recovery of P from rho, u',nfail(3),ncheck(3),errmax(3),use_rel_tol) ! Recalculate u, T, mu from rho, P - call calc_uT_from_rhoP_gasradrec(rhogrid(i),presi,X,1.-X-Z,tempi,eni2,mu,ierr) - call checkvalbuf(tempi,Tgrid(j),tol,'Check recovery of T from rho, P',nfail(3),ncheck(3),errmax(3)) - call checkvalbuf(eni2,eni,tol,'Check recovery of u from rho, P',nfail(4),ncheck(4),errmax(4)) + call calc_uT_from_rhoP_gasradrec(rhogrid(i),presi,X,1.-X-Z,tempi,eni2,mu2,ierr) + call checkvalbuf(mu2,mu,tol,'Check recovery of mu from rho, P',nfail(4),ncheck(4),errmax(4),use_rel_tol) + call checkvalbuf(tempi,Tgrid(j),tol,'Check recovery of T from rho, P',nfail(5),ncheck(5),errmax(5),use_rel_tol) + call checkvalbuf(eni2,eni,tol,'Check recovery of u from rho, P',nfail(6),ncheck(6),errmax(6),use_rel_tol) enddo enddo - call checkvalbuf_end('Check recovery of T from rho, u',ncheck(1),nfail(1),errmax(1),tol) - call checkvalbuf_end('Check recovery of P from rho, u',ncheck(2),nfail(2),errmax(2),tol) - call checkvalbuf_end('Check recovery of T from rho, P',ncheck(3),nfail(3),errmax(3),tol) - call checkvalbuf_end('Check recovery of u from rho, P',ncheck(4),nfail(4),errmax(4),tol) + call checkvalbuf_end('Check recovery of mu from rho, u',ncheck(1),nfail(1),errmax(1),tol) + call checkvalbuf_end('Check recovery of T from rho, u',ncheck(2),nfail(2),errmax(2),tol) + call checkvalbuf_end('Check recovery of P from rho, u',ncheck(3),nfail(3),errmax(3),tol) + call checkvalbuf_end('Check recovery of mu from rho, P',ncheck(4),nfail(4),errmax(4),tol) + call checkvalbuf_end('Check recovery of T from rho, P',ncheck(5),nfail(5),errmax(5),tol) + call checkvalbuf_end('Check recovery of u from rho, P',ncheck(6),nfail(6),errmax(6),tol) call update_test_scores(ntests,nfail,npass) end subroutine test_hormone diff --git a/src/tests/test_eos_stratified.f90 b/src/tests/test_eos_stratified.f90 index f8aaf1936..20ecf3f4f 100644 --- a/src/tests/test_eos_stratified.f90 +++ b/src/tests/test_eos_stratified.f90 @@ -296,11 +296,11 @@ subroutine map_stratified_temps(ntests, npass) call eosinfo(ieos,stdout) - open(1, file='HD1632996_temps.txt', status = 'replace') - open(2, file='IMLup_temps.txt', status = 'replace') - open(3, file='GMAur_temps.txt', status = 'replace') - open(4, file='AS209_temps.txt', status = 'replace') - open(5, file='MWC480_temps.txt', status = 'replace') + open(1,file='HD1632996_temps.txt',status='replace') + open(2,file='IMLup_temps.txt',status='replace') + open(3,file='GMAur_temps.txt',status='replace') + open(4,file='AS209_temps.txt',status='replace') + open(5,file='MWC480_temps.txt',status='replace') do i=1,n call get_disc_params(i,gmw,qfacdisc,qfacdisc2,alpha_z,beta_z,z0,polyk,polyk2, & diff --git a/src/tests/test_externf.f90 b/src/tests/test_externf.f90 index f6bb79410..13433ddb4 100644 --- a/src/tests/test_externf.f90 +++ b/src/tests/test_externf.f90 @@ -35,7 +35,7 @@ subroutine test_externf(ntests,npass) use externalforces, only:externalforcetype,externalforce,accrete_particles, & was_accreted,iexternalforce_max,initialise_externalforces,& accradius1,update_externalforce,is_velocity_dependent,& - externalforce_vdependent,update_vdependent_extforce_leapfrog,& + externalforce_vdependent,update_vdependent_extforce,& iext_lensethirring,iext_prdrag,iext_einsteinprec,iext_spiral,& iext_densprofile,iext_staticsine,iext_gwinspiral use extern_corotate, only:omega_corotate @@ -52,7 +52,7 @@ subroutine test_externf(ntests,npass) real :: psep,fxi,fyi,fzi,dtf,time,pmassi,dhi real :: fextxi,fextyi,fextzi,dumx,dumy,dumz,pot1,pot2 real :: xerrmax,yerrmax,zerrmax,ferrmaxx,ferrmaxy,ferrmaxz - real :: xi(4),v1(3),fext_iteration(3),fexti(3),vhalfx,vhalfy,vhalfz,dt + real :: xi(4),v1(3),fext_iteration(3),fexti(3),vhalfx,vhalfy,vhalfz,dt,hdt real :: xmini(3),xmaxi(3),poti real, parameter :: tolf = 1.5e-3 real, parameter :: tolfold = 1.e-10 @@ -199,24 +199,25 @@ subroutine test_externf(ntests,npass) fxi = -0.0789 ! non-zero, but small so that v-dependent fyi = 0.036 ! part is dominant component of the force fzi = -0.01462 + hdt = 0.5*dt ! ! get an explicit evaluation of the external force ! and solve v^1 = v^1/2 + dt/2*[f1(x^1) + f1(x^1,v^1)] ! by iterating 20 times ! - v1 = (/vhalfx + 0.5*dt*fxi,vhalfy + 0.5*dt*fyi,vhalfz + 0.5*dt*fzi/) + v1 = (/vhalfx + hdt*fxi,vhalfy + hdt*fyi,vhalfz + hdt*fzi/) do i=1,30 call externalforce_vdependent(iextf,xi(1:3),v1,fext_iteration,poti) - v1(1) = vhalfx + 0.5*dt*(fxi + fext_iteration(1)) - v1(2) = vhalfy + 0.5*dt*(fyi + fext_iteration(2)) - v1(3) = vhalfz + 0.5*dt*(fzi + fext_iteration(3)) + v1(1) = vhalfx + hdt*(fxi + fext_iteration(1)) + v1(2) = vhalfy + hdt*(fyi + fext_iteration(2)) + v1(3) = vhalfz + hdt*(fzi + fext_iteration(3)) !print*,'fext_iteration = ',fext_iteration enddo ! ! call update_leapfrog routine to get analytic solution ! - call update_vdependent_extforce_leapfrog(iextf,vhalfx,vhalfy,vhalfz,& - fxi,fyi,fzi,fexti,dt,xi(1),xi(2),xi(3)) + call update_vdependent_extforce(iextf,vhalfx,vhalfy,vhalfz,& + fxi,fyi,fzi,fexti,hdt,xi(1),xi(2),xi(3)) ! ! check that these agree with each other ! diff --git a/src/tests/test_gnewton.f90 b/src/tests/test_gnewton.f90 index 3dff7afa3..ebc352296 100644 --- a/src/tests/test_gnewton.f90 +++ b/src/tests/test_gnewton.f90 @@ -157,7 +157,7 @@ end subroutine test_gnewton !+ !----------------------------------------------------------------------- subroutine step_lf(t,dt,dtnew) - use externalforces, only:externalforce,update_vdependent_extforce_leapfrog,externalforce_vdependent + use externalforces, only:externalforce,update_vdependent_extforce,externalforce_vdependent use timestep, only:C_force use part, only:xyzh,vxyzu use options, only:iexternalforce @@ -191,9 +191,9 @@ subroutine step_lf(t,dt,dtnew) fy = fexty fz = fextz - call update_vdependent_extforce_leapfrog(iexternalforce,& + call update_vdependent_extforce(iexternalforce,& vxhalf,vyhalf,vzhalf, & - fx,fy,fz,fextv,dt,xyzh(1,1),xyzh(2,1),xyzh(3,1)) + fx,fy,fz,fextv,hdt,xyzh(1,1),xyzh(2,1),xyzh(3,1)) vxyzu(1,1) = vxhalf + hdt*fx vxyzu(2,1) = vyhalf + hdt*fy diff --git a/src/tests/test_ptmass.f90 b/src/tests/test_ptmass.f90 index 2096c3d5d..7272f1276 100644 --- a/src/tests/test_ptmass.f90 +++ b/src/tests/test_ptmass.f90 @@ -15,9 +15,10 @@ module testptmass ! :Runtime parameters: None ! ! :Dependencies: boundary, checksetup, deriv, dim, energies, eos, -! gravwaveutils, io, kdtree, kernel, mpiutils, options, part, physcon, -! ptmass, random, setbinary, setdisc, spherical, step_lf_global, -! stretchmap, testutils, timestep, timing, units +! extern_binary, externalforces, gravwaveutils, io, kdtree, kernel, +! mpiutils, options, part, physcon, ptmass, random, setbinary, setdisc, +! spherical, step_lf_global, stretchmap, testutils, timestep, timing, +! units ! use testutils, only:checkval,update_test_scores implicit none @@ -27,23 +28,52 @@ module testptmass contains -subroutine test_ptmass(ntests,npass) +subroutine test_ptmass(ntests,npass,string) use io, only:id,master,iskfile use eos, only:polyk,gamma use part, only:nptmass use options, only:iexternalforce,alpha + use ptmass, only:use_fourthorder,set_integration_precision + character(len=*), intent(in) :: string character(len=20) :: filename + character(len=40) :: stringf integer, intent(inout) :: ntests,npass - integer :: itmp,ierr - logical :: do_test_binary,do_test_accretion,do_test_createsink,do_test_softening,do_test_merger + integer :: itmp,ierr,itest,istart + logical :: do_test_binary,do_test_accretion,do_test_createsink,do_test_softening + logical :: do_test_chinese_coin,do_test_merger + logical :: testall if (id==master) write(*,"(/,a,/)") '--> TESTING PTMASS MODULE' - do_test_binary = .true. - do_test_accretion = .true. - do_test_createsink = .true. - do_test_softening = .true. - do_test_merger = .true. + do_test_binary = .false. + do_test_accretion = .false. + do_test_createsink = .false. + do_test_softening = .false. + do_test_merger = .false. + do_test_chinese_coin = .false. + testall = .false. + istart = 1 + select case(trim(string)) + case('ptmassbinary') + do_test_binary = .true. + case('ptmassaccrete') + do_test_accretion = .true. + case('ptmasscreatesink') + do_test_createsink = .true. + case('ptmasssoftening') + do_test_softening = .true. + case('ptmassmerger') + do_test_merger = .true. + case('ptmasschinchen','ptmasscoin','chinchen','coin','chinesecoin') + do_test_chinese_coin = .true. + case('ptmassfsi','fsi') + istart = 2 + do_test_binary = .true. + do_test_softening = .true. + do_test_merger = .true. + case default + testall = .true. + end select ! !--general settings ! @@ -51,26 +81,47 @@ subroutine test_ptmass(ntests,npass) gamma = 1. iexternalforce = 0 alpha = 0.01 - ! - ! Tests of a sink particle binary - ! - if (do_test_binary) call test_binary(ntests,npass) - ! - ! Test of softening between sinks - ! - if (do_test_softening) call test_softening(ntests,npass) + do itest=istart,2 + ! + ! select order of integration + ! + if (itest == 2) then + use_fourthorder = .true. + stringf = ' with Forward Symplectic Integrator' + else + use_fourthorder = .false. + stringf = ' with Leapfrog integrator' + endif + call set_integration_precision + ! + ! Tests of a sink particle binary + ! + if (do_test_binary .or. testall) call test_binary(ntests,npass,stringf) + ! + ! Test of softening between sinks + ! + if (do_test_softening .or. testall) call test_softening(ntests,npass) + ! + ! Test of Chinese Coin problem + ! + if (do_test_chinese_coin .or. testall) call test_chinese_coin(ntests,npass,stringf) + ! + ! Test sink particle mergers + ! + if (do_test_merger .or. testall) call test_merger(ntests,npass) + enddo ! ! Tests of accrete_particle routine ! - if (do_test_accretion) call test_accretion(ntests,npass) + if (do_test_accretion .or. testall) then + do itest=1,2 + call test_accretion(ntests,npass,itest) + enddo + endif ! ! Test sink particle creation ! - if (do_test_createsink) call test_createsink(ntests,npass) - ! - ! Test sink particle mergers - ! - if (do_test_merger) call test_merger(ntests,npass) + if (do_test_createsink .or. testall) call test_createsink(ntests,npass) !reset stuff and clean up temporary files itmp = 201 @@ -92,12 +143,12 @@ end subroutine test_ptmass ! Unit tests of a sink particle binary orbit !+ !----------------------------------------------------------------------- -subroutine test_binary(ntests,npass) +subroutine test_binary(ntests,npass,string) use dim, only:periodic,gravity,ind_timesteps use io, only:id,master,iverbose use physcon, only:pi,deg_to_rad use ptmass, only:get_accel_sink_sink,h_soft_sinksink, & - get_accel_sink_gas,f_acc + get_accel_sink_gas,f_acc,use_fourthorder use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,fext,& npart,npartoftype,massoftype,xyzh,vxyzu,fxyzu,& hfact,igas,epot_sinksink,init_part,iJ2,ispinx,ispiny,ispinz,iReff,istar @@ -116,11 +167,12 @@ subroutine test_binary(ntests,npass) use deriv, only:get_derivs_global use timing, only:getused,printused use options, only:ipdv_heating,ishock_heating - integer, intent(inout) :: ntests,npass + integer, intent(inout) :: ntests,npass + character(len=*), intent(in) :: string integer :: i,ierr,itest,nfailed(3),nsteps,nerr,nwarn,norbits integer :: merge_ij(2),merge_n,nparttot,nfailgw(2),ncheckgw(2) integer, parameter :: nbinary_tests = 5 - real :: m1,m2,a,ecc,hacc1,hacc2,dt,dtext,t,dtnew,tolen,hp_exact,hx_exact + real :: m1,m2,a,ecc,hacc1,hacc2,dt,dtext,t,dtnew,tolen,tolmom,tolang,hp_exact,hx_exact real :: angmomin,etotin,totmomin,dum,dum2,omega,errmax,dtsinksink,fac,errgw(2) real :: angle,rin,rout real :: fxyz_sinksink(4,2),dsdt_sinksink(3,2) ! we only use 2 sink particles in the tests here @@ -138,25 +190,35 @@ subroutine test_binary(ntests,npass) ipdv_heating = 0 ishock_heating = 0 + tolv = 1e-2 + binary_tests: do itest = 1,nbinary_tests select case(itest) case(4) - if (id==master) write(*,"(/,a)") '--> testing integration of binary orbit with oblateness' + if (use_fourthorder) then + if (id==master) write(*,"(/,a)") '--> skipping integration of binary orbit with oblateness with FSI' + cycle binary_tests + else + if (id==master) write(*,"(/,a)") '--> testing integration of binary orbit with oblateness'//trim(string) + endif case(2,3,5) if (periodic) then if (id==master) write(*,"(/,a)") '--> skipping circumbinary disc test (-DPERIODIC is set)' cycle binary_tests + elseif (use_fourthorder .and. itest==5) then + if (id==master) write(*,"(/,a)") '--> skipping circumbinary disc around oblate star test with FSI' + cycle binary_tests else if (itest==5) then - if (id==master) write(*,"(/,a)") '--> testing integration of disc around oblate star' + if (id==master) write(*,"(/,a)") '--> testing integration of disc around oblate star'//trim(string) elseif (itest==3) then - if (id==master) write(*,"(/,a)") '--> testing integration of disc around eccentric binary' + if (id==master) write(*,"(/,a)") '--> testing integration of disc around eccentric binary'//trim(string) else - if (id==master) write(*,"(/,a)") '--> testing integration of circumbinary disc' + if (id==master) write(*,"(/,a)") '--> testing integration of circumbinary disc'//trim(string) endif endif case default - if (id==master) write(*,"(/,a)") '--> testing integration of binary orbit' + if (id==master) write(*,"(/,a)") '--> testing integration of binary orbit'//trim(string) end select ! !--setup sink-sink binary (no gas particles) @@ -183,6 +245,7 @@ subroutine test_binary(ntests,npass) hacc1 = 0.35 hacc2 = 0.35 C_force = 0.25 + if (itest==3) C_force = 0.25 omega = sqrt((m1+m2)/a**3) t = 0. call set_units(mass=1.d0,dist=1.d0,G=1.d0) @@ -217,7 +280,7 @@ subroutine test_binary(ntests,npass) call checkval(nerr,0,0,nfailed(1),'no errors during disc setup') call update_test_scores(ntests,nfailed,npass) - tolv = 1.e3 + tolv = 1.e-2 iverbose = 0 ieos = 3 fac = 1./get_G_on_dc4() @@ -297,58 +360,68 @@ subroutine test_binary(ntests,npass) if (id==master) call getused(t1) call init_step(npart,t,dtmax) do i=1,nsteps - t = t + dt dtext = dt if (id==master .and. iverbose > 2) write(*,*) ' t = ',t,' dt = ',dt call step(npart,npart,t,dt,dtext,dtnew) call compute_energies(t) errmax = max(errmax,abs(etot - etotin)) + !if (itest==3) print*,t,abs(angtot-angmomin)/angmomin ! ! Check the gravitational wave strain if the binary is circular. ! There is a phase error that grows with time, so only check the first 10 orbits ! if (calc_gravitwaves .and. abs(ecc) < epsilon(ecc) .and. itest==1 .and. t < 20.*pi/omega) then - call get_strain_from_circular_binary(t,m1,m2,a,0.,hx_exact,hp_exact) + call get_strain_from_circular_binary(t+dt,m1,m2,a,0.,hx_exact,hp_exact) call checkvalbuf(10.+hx(1)*fac,10.+hx_exact*fac,tolgw,& 'gw strain (x)',nfailgw(1),ncheckgw(1),errgw(1)) call checkvalbuf(10.+hp(1)*fac,10.+hp_exact*fac,tolgw,& 'gw strain (+)',nfailgw(2),ncheckgw(2),errgw(2)) endif + t = t + dt enddo call compute_energies(t) if (id==master) call printused(t1) nfailed(:) = 0 + tolmom = 2.e-14 + tolang = 2.e-14 select case(itest) + case(5) + tolen = 9.e-1 + case(4) + tolmom = 1.e-14 + tolen = 1.6e-2 case(3) if (ind_timesteps) then - call checkval(angtot,angmomin,2.1e-6,nfailed(3),'angular momentum') - call checkval(totmom,totmomin,5.e-6,nfailed(2),'linear momentum') + tolang = 2.1e-6 else - call checkval(angtot,angmomin,1.2e-6,nfailed(3),'angular momentum') - call checkval(totmom,totmomin,4.e-14,nfailed(2),'linear momentum') + tolang = 6.e-10 endif tolen = 1.2e-2 case(2) - call checkval(angtot,angmomin,4.e-7,nfailed(3),'angular momentum') - call checkval(totmom,totmomin,6.e-14,nfailed(2),'linear momentum') - tolen = 2.e-3 + tolen = 1.2e-3 if (gravity) tolen = 3.1e-3 + + if (use_fourthorder) then + tolang = 2.e-11 + endif case default if (calc_gravitwaves .and. itest==1) then call checkvalbuf_end('grav. wave strain (x)',ncheckgw(1),nfailgw(1),errgw(1),tolgw) call checkvalbuf_end('grav. wave strain (+)',ncheckgw(2),nfailgw(2),errgw(2),tolgw) call update_test_scores(ntests,nfailgw(1:2),npass) endif - call checkval(angtot,angmomin,4.e-13,nfailed(3),'angular momentum') - call checkval(totmom,totmomin,epsilon(0.),nfailed(2),'linear momentum') - tolen = 3.e-8 - if (itest==4) tolen = 1.6e-2 ! etot is small compared to ekin - if (itest==5) tolen = 9.e-1 + if (use_fourthorder) then + tolen = 1.e-13 + else + tolen = 3.e-8 + endif end select ! !--check energy conservation ! - call checkval(etotin+errmax,etotin,tolen,nfailed(1),'total energy') + call checkval(angtot,angmomin,tolang,nfailed(1),'angular momentum') + call checkval(totmom,totmomin,tolmom,nfailed(2),'linear momentum') + call checkval(etotin+errmax,etotin,tolen,nfailed(3),'total energy') do i=1,3 call update_test_scores(ntests,nfailed(i:i),npass) enddo @@ -462,34 +535,117 @@ subroutine test_softening(ntests,npass) end subroutine test_softening +!----------------------------------------------------------------------- +!+ +! Test Chinese Coin problem from Chin & Chen (2005) +!+ +!----------------------------------------------------------------------- +subroutine test_chinese_coin(ntests,npass,string) + use io, only:id,master,iverbose + use part, only:xyzmh_ptmass,vxyz_ptmass,ihacc,nptmass,npart,npartoftype,fxyz_ptmass,dsdt_ptmass + use extern_binary, only:mass1,mass2 + use options, only:iexternalforce + use externalforces, only:iext_binary,update_externalforce + use physcon, only:pi + use step_lf_global, only:step + use ptmass, only:use_fourthorder,get_accel_sink_sink + integer, intent(inout) :: ntests,npass + character(len=*), intent(in) :: string + character(len=10) :: tag + integer :: nfailed(3),merge_ij(1),merge_n,norbit + real :: t,dtorb,dtnew,dtext,tmax,epot_sinksink,y0,v0 + real :: tol_per_orbit_y,tol_per_orbit_v + + if (id==master) write(*,"(/,a)") '--> testing Chinese coin problem'//trim(string)//' (coin)' + + ! no gas + npart = 0 + npartoftype = 0 + + ! add a single sink particle + y0 = 0.0580752367; v0 = 0.489765446 + nptmass = 1 + xyzmh_ptmass = 0. + xyzmh_ptmass(2,1) = y0 + xyzmh_ptmass(4,1) = 1.0 + xyzmh_ptmass(ihacc,1) = 0.1 + vxyz_ptmass = 0. + vxyz_ptmass(1,1) = v0 + + ! external binary + iexternalforce = iext_binary + mass1 = 0.5 + mass2 = mass1 + dtorb = 9.*pi + tmax = 3.*dtorb + + t = 0. + dtext = 1.e-15 + iverbose = 1 + call update_externalforce(iexternalforce,t,0.) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtext,iexternalforce,t,merge_ij,merge_n,dsdt_ptmass) + + dtext = 1.e-15 ! take small first step + norbit = 0 + nfailed(:) = 0 + tol_per_orbit_y = 2.5e-2 + tol_per_orbit_v = 1.15e-2 + if (use_fourthorder) then + tol_per_orbit_y = 1.1e-3 + tol_per_orbit_v = 3.35e-4 + endif + do while (t < tmax) + ! do a whole orbit but with the substepping handling how many steps per orbit + call step(npart,npart,t,dtorb,dtext,dtnew) + t = t + dtorb + norbit = norbit + 1 + + write(tag,"(a,i1,a)") '(orbit ',norbit,')' + call checkval(xyzmh_ptmass(2,1),y0,norbit*tol_per_orbit_y,nfailed(1),'y pos of sink '//trim(tag)) + call checkval(vxyz_ptmass(1,1),v0,norbit*tol_per_orbit_v,nfailed(2),'x vel of sink '//trim(tag)) + enddo + + call update_test_scores(ntests,nfailed(1:2),npass) + iverbose = 0 ! reset verbosity + iexternalforce = 0 + +end subroutine test_chinese_coin + !----------------------------------------------------------------------- !+ ! Test accretion of gas particles onto sink particles !+ !----------------------------------------------------------------------- -subroutine test_accretion(ntests,npass) +subroutine test_accretion(ntests,npass,itest) use io, only:id,master use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,massoftype, & npart,npartoftype,xyzh,vxyzu,fxyzu,igas,ihacc,& - isdead_or_accreted,set_particle_type - use ptmass, only:ndptmass,ptmass_accrete,update_ptmass + isdead_or_accreted,set_particle_type,ndptmass,hfact + use ptmass, only:ptmass_accrete,update_ptmass use energies, only:compute_energies,angtot,etot,totmom use mpiutils, only:bcast_mpi,reduce_in_place_mpi use testutils, only:checkval,update_test_scores + use kernel, only:hfact_default + use eos, only:polyk + use setdisc, only:set_disc integer, intent(inout) :: ntests,npass - integer :: i,nfailed(11) + integer, intent(in) :: itest + integer :: i,nfailed(11),np_disc integer(kind=1) :: ibin_wakei + character(len=20) :: string logical :: accreted - real :: dr,t + real :: t real :: dptmass(ndptmass,1) real :: dptmass_thread(ndptmass,1) - real :: xyzm_ptmass_old(4,1),vxyz_ptmass_old(3,1) real :: angmomin,etotin,totmomin xyzmh_ptmass(:,:) = 0. vxyz_ptmass(:,:) = 0. - if (id==master) write(*,"(/,a)") '--> testing accretion onto sink particles' + string = 'of two particles' + if (itest==2) string = 'of a whole disc' + if (id==master) write(*,"(/,a)") '--> testing accretion '//trim(string)//' onto sink particles' nptmass = 1 !--setup 1 point mass at (-5,-5,-5) xyzmh_ptmass(1:3,1) = 1. @@ -497,23 +653,35 @@ subroutine test_accretion(ntests,npass) xyzmh_ptmass(ihacc,1) = 20. ! accretion radius vxyz_ptmass(1:3,1) = -40. fxyz_ptmass(1:3,1) = 40. - massoftype(1) = 10. - !--setup 1 SPH particle at (5,5,5) - if (id==master) then - call set_particle_type(1,igas) - npartoftype(igas) = 1 - npart = 1 - xyzh(1:3,1) = 5. - xyzh(4,1) = 0.01 - vxyzu(1:3,1) = 80. - fxyzu(1:3,1) = 20. + hfact = hfact_default + + if (itest==1) then + !--setup 2 SPH particles at (5,5,5) + if (id==master) then + call set_particle_type(1,igas) + call set_particle_type(2,igas) + npartoftype(igas) = 2 + npart = 2 + xyzh(1:3,1:2) = 5. + xyzh(4,1:2) = 0.01 + vxyzu(1:3,1) = [40.,40.,-10.] + vxyzu(1:3,2) = [120.,120.,-30.] + fxyzu(1:3,1:2) = 20. + massoftype(1) = 5. + else + npartoftype(igas) = 0 + npart = 0 + endif else - npartoftype(igas) = 0 - npart = 0 + ! eat a large portion of a disc + np_disc = 1000 + call set_disc(id,master,nparttot=np_disc,npart=npart,rmin=1.,rmax=2.*xyzmh_ptmass(ihacc,1),p_index=1.0,q_index=0.75,& + HoverR=0.1,disc_mass=0.5*xyzmh_ptmass(4,1),star_mass=xyzmh_ptmass(4,1),gamma=1.,& + particle_mass=massoftype(igas),hfact=hfact,xyzh=xyzh,vxyzu=vxyzu,& + polyk=polyk,verbose=.false.) + npartoftype(igas) = npart endif - xyzm_ptmass_old = xyzmh_ptmass(1:4,1:nptmass) - vxyz_ptmass_old = vxyz_ptmass (1:3,1:nptmass) - dr = sqrt(dot_product(xyzh(1:3,1) - xyzmh_ptmass(1:3,1),xyzh(1:3,1) - xyzmh_ptmass(1:3,1))) + !--perform a test of the accretion of the SPH particle by the point mass nfailed(:) = 0 !--check energies before accretion event @@ -529,10 +697,12 @@ subroutine test_accretion(ntests,npass) dptmass_thread(:,1:nptmass) = 0. !$omp do do i=1,npart - call ptmass_accrete(1,nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& - vxyzu(1,i),vxyzu(2,i),vxyzu(3,i),fxyzu(1,i),fxyzu(2,i),fxyzu(3,i), & - igas,massoftype(igas),xyzmh_ptmass,vxyz_ptmass, & - accreted,dptmass_thread,t,1.0,ibin_wakei,ibin_wakei) + if (.not.isdead_or_accreted(xyzh(4,i))) then + call ptmass_accrete(1,nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& + vxyzu(1,i),vxyzu(2,i),vxyzu(3,i),fxyzu(1,i),fxyzu(2,i),fxyzu(3,i), & + igas,massoftype(igas),xyzmh_ptmass,vxyz_ptmass, & + accreted,dptmass_thread,t,1.0,ibin_wakei,ibin_wakei) + endif enddo !$omp enddo !$omp critical(dptmassadd) @@ -548,31 +718,34 @@ subroutine test_accretion(ntests,npass) call bcast_mpi(vxyz_ptmass(:,1:nptmass)) call bcast_mpi(fxyz_ptmass(:,1:nptmass)) - if (id==master) then - call checkval(accreted,.true.,nfailed(1),'accretion flag') - !--check that h has been changed to indicate particle has been accreted - call checkval(isdead_or_accreted(xyzh(4,1)),.true.,nfailed(2),'isdead_or_accreted flag') - endif - call checkval(xyzmh_ptmass(1,1),3.,tiny(0.),nfailed(3),'x(ptmass) after accretion') - call checkval(xyzmh_ptmass(2,1),3.,tiny(0.),nfailed(4),'y(ptmass) after accretion') - call checkval(xyzmh_ptmass(3,1),3.,tiny(0.),nfailed(5),'z(ptmass) after accretion') - call checkval(vxyz_ptmass(1,1),20.,tiny(0.),nfailed(6),'vx(ptmass) after accretion') - call checkval(vxyz_ptmass(2,1),20.,tiny(0.),nfailed(7),'vy(ptmass) after accretion') - call checkval(vxyz_ptmass(3,1),20.,tiny(0.),nfailed(8),'vz(ptmass) after accretion') - call checkval(fxyz_ptmass(1,1),30.,tiny(0.),nfailed(9), 'fx(ptmass) after accretion') - call checkval(fxyz_ptmass(2,1),30.,tiny(0.),nfailed(10),'fy(ptmass) after accretion') - call checkval(fxyz_ptmass(3,1),30.,tiny(0.),nfailed(11),'fz(ptmass) after accretion') + if (itest==1) then + if (id==master) then + call checkval(accreted,.true.,nfailed(1),'accretion flag') + !--check that h has been changed to indicate particle has been accreted + call checkval(isdead_or_accreted(xyzh(4,1)),.true.,nfailed(2),'isdead_or_accreted flag(1)') + call checkval(isdead_or_accreted(xyzh(4,2)),.true.,nfailed(2),'isdead_or_accreted flag(2)') + endif + call checkval(xyzmh_ptmass(1,1),3.,tiny(0.),nfailed(3),'x(ptmass) after accretion') + call checkval(xyzmh_ptmass(2,1),3.,tiny(0.),nfailed(4),'y(ptmass) after accretion') + call checkval(xyzmh_ptmass(3,1),3.,tiny(0.),nfailed(5),'z(ptmass) after accretion') + call checkval(vxyz_ptmass(1,1),20.,tiny(0.),nfailed(6),'vx(ptmass) after accretion') + call checkval(vxyz_ptmass(2,1),20.,tiny(0.),nfailed(7),'vy(ptmass) after accretion') + call checkval(vxyz_ptmass(3,1),-30.,tiny(0.),nfailed(8),'vz(ptmass) after accretion') + call checkval(fxyz_ptmass(1,1),30.,tiny(0.),nfailed(9), 'fx(ptmass) after accretion') + call checkval(fxyz_ptmass(2,1),30.,tiny(0.),nfailed(10),'fy(ptmass) after accretion') + call checkval(fxyz_ptmass(3,1),30.,tiny(0.),nfailed(11),'fz(ptmass) after accretion') - call update_test_scores(ntests,nfailed(1:2),npass) - call update_test_scores(ntests,nfailed(3:5),npass) - call update_test_scores(ntests,nfailed(6:8),npass) - call update_test_scores(ntests,nfailed(9:11),npass) + call update_test_scores(ntests,nfailed(1:2),npass) + call update_test_scores(ntests,nfailed(3:5),npass) + call update_test_scores(ntests,nfailed(6:8),npass) + call update_test_scores(ntests,nfailed(9:11),npass) + endif - !--compute energies after accretion event + !--compute conserved quantities after accretion event nfailed(:) = 0 call compute_energies(t) - call checkval(angtot,angmomin,1.e-10,nfailed(3),'angular momentum') - call checkval(totmom,totmomin,epsilon(0.),nfailed(2),'linear momentum') + call checkval(angtot,angmomin,1.e-14,nfailed(3),'angular momentum') + call checkval(totmom,totmomin,2.*epsilon(0.),nfailed(2),'linear momentum') !call checkval(etot,etotin,1.e-6,'total energy',nfailed(1)) call update_test_scores(ntests,nfailed(3:3),npass) call update_test_scores(ntests,nfailed(2:2),npass) @@ -592,8 +765,9 @@ subroutine test_createsink(ntests,npass) use io, only:id,master,iverbose use part, only:init_part,npart,npartoftype,igas,xyzh,massoftype,hfact,rhoh,& iphase,isetphase,fext,divcurlv,vxyzu,fxyzu,poten, & - nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass - use ptmass, only:ndptmass,ptmass_accrete,update_ptmass,icreate_sinks,& + nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,ndptmass, & + dptmass + use ptmass, only:ptmass_accrete,update_ptmass,icreate_sinks,& ptmass_create,finish_ptmass,ipart_rhomax,h_acc,rho_crit,rho_crit_cgs use energies, only:compute_energies,angtot,etot,totmom use mpiutils, only:bcast_mpi,reduce_in_place_mpi,reduceloc_mpi,reduceall_mpi @@ -712,7 +886,7 @@ subroutine test_createsink(ntests,npass) call reduceloc_mpi('max',ipart_rhomax_global,id_rhomax) endif call ptmass_create(nptmass,npart,itestp,xyzh,vxyzu,fxyzu,fext,divcurlv,poten,& - massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,0.) + massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,0.) ! ! check that creation succeeded ! diff --git a/src/tests/testsuite.F90 b/src/tests/testsuite.F90 index 180e2708b..d3bf32d13 100644 --- a/src/tests/testsuite.F90 +++ b/src/tests/testsuite.F90 @@ -156,6 +156,7 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) if (index(string,'damp') /= 0) dodamp = .true. if (index(string,'wind') /= 0) dowind = .true. if (index(string,'iorig') /= 0) doiorig = .true. + if (index(string,'ptmass') /= 0) doptmass = .true. doany = any((/doderivs,dogravity,dodust,dogrowth,donimhd,dorwdump,& doptmass,docooling,dogeom,dogr,dosmol,doradiation,& @@ -170,7 +171,7 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) dokdtree = .true. case('step') dostep = .true. - case('ptmass','sink') + case('ptmass','sink','fsi','chinchen','coin') doptmass = .true. case('gnewton') dognewton = .true. @@ -327,7 +328,7 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) !--test of ptmass module ! if (doptmass.or.testall) then - call test_ptmass(ntests,npass) + call test_ptmass(ntests,npass,string) call set_default_options_testsuite(iverbose) ! restore defaults endif diff --git a/src/tests/utils_testsuite.f90 b/src/tests/utils_testsuite.f90 index 8f05a7d0c..512d25766 100644 --- a/src/tests/utils_testsuite.f90 +++ b/src/tests/utils_testsuite.f90 @@ -629,16 +629,21 @@ end subroutine checkvalbuf_int ! (buffered: reports on errors only and ndiff is a running total) !+ !---------------------------------------------------------------- -subroutine checkvalbuf_real(xi,val,tol,label,ndiff,ncheck,errmax) +subroutine checkvalbuf_real(xi,val,tol,label,ndiff,ncheck,errmax,use_rel_tol) real, intent(in) :: xi real, intent(in) :: val,tol character(len=*), intent(in) :: label integer, intent(inout) :: ndiff,ncheck real, intent(inout) :: errmax + logical, intent(in), optional :: use_rel_tol real :: erri + logical :: rel_tol + + rel_tol = .false. + if (present(use_rel_tol)) rel_tol = use_rel_tol erri = abs(xi-val) - if (abs(val) > smallval .and. erri > tol) erri = erri/abs(val) + if (rel_tol .or. (abs(val) > smallval .and. erri > tol)) erri = erri/abs(val) ncheck = ncheck + 1 if (erri > tol .or. erri /= erri) then From 77632d0a3c58f51cc4fb01af1c2f25a0ab18bd30 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 3 May 2024 14:24:22 +0100 Subject: [PATCH 112/182] Changing Stamatellos cooling implementation for new step_leapfrog and substepping code structure. --- src/main/cooling.f90 | 4 +- src/main/cooling_stamatellos.f90 | 239 +++++++++++++++++-------------- src/main/force.F90 | 2 +- src/main/step_leapfrog.F90 | 5 +- src/main/substepping.F90 | 2 +- 5 files changed, 138 insertions(+), 114 deletions(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index aa2dda90b..c85316524 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -143,7 +143,6 @@ 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_stamatellos, only:cooling_S07 real(kind=4), intent(in) :: divv ! in code units real, intent(in) :: xi,yi,zi,ui,rho,dt ! in code units @@ -178,7 +177,8 @@ subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2 select case (icooling) case (9) - call cooling_S07(rho,ui,dudt,xi,yi,zi,Tfloor,dudti_sph,dt,part_id) + ! should not occur! + call fatal('energ_cooling','cooling_S07 called from cooling.f90') case (6) call cooling_KoyamaInutsuka_implicit(ui,rho,dt,dudt) case (5) diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_stamatellos.f90 index 53988e395..2c9fb4c4f 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_stamatellos.f90 @@ -61,139 +61,160 @@ end subroutine init_star ! ! Do cooling calculation ! -subroutine cooling_S07(rhoi,ui,dudti_cool,xi,yi,zi,Tfloor,dudti_sph,dt,i) +! edit this to make a loop and update energy to return evolved energy array. +subroutine cooling_S07(npart,xyzh,energ,Tfloor,dudt_sph,dt) 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 + use part, only:xyzmh_ptmass,rhoh,massoftype,igas - real,intent(in) :: rhoi,ui,dudti_sph,xi,yi,zi,Tfloor,dt - integer,intent(in) :: i - real,intent(out) :: dudti_cool + integer,intent(in) :: npart + real,intent(in) :: dudt_sph(:),xyzh(:,:),Tfloor,dt + real,intent(inout) :: energ(:) + real :: dudti_cool,ui,rhoi real :: coldensi,kappaBari,kappaParti,ri2 - real :: gmwi,Tmini4,Ti,dudt_rad,Teqi,Hstam,HLom,du_tot - real :: cs2,Om2,Hmod2 - real :: opac,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi + real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot + real :: cs2,Om2,Hmod2,xi,yi,zi + real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi + integer :: i - poti = Gpot_cool(i) - du_FLDi = duFLD(i) - - if (isink_star > 0) then - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & - + (yi-xyzmh_ptmass(2,isink_star))**2d0 & - + (zi-xyzmh_ptmass(3,isink_star))**2d0 - endif + !omp parallel do default(none) & + !omp shared(npart,duFLD,xyzh,energ,rhoh,massoftype,igas,xyzmh_ptmass) & + !omp shared(isink_star,pi,steboltz,solarl,Rg,doFLD,ttherm_store,teqi_store) & + !omp shared(opac_store,Tfloor,dt,dudt_sph) + !omp private(i,poti,du_FLDi,xi,yi,zi,ui,rhoi,ri2,coldensi,kappaBari) & + !omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & + !omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,poti,presi,Hcomb) + overpart: do i=1,npart + poti = Gpot_cool(i) + du_FLDi = duFLD(i) + xi = xyzh(1,i) + yi = xyzh(2,i) + zi = xyzh(3,i) + ui = energ(i) + rhoi = rhoh(xyzh(4,i),massoftype(igas)) + + if (isink_star > 0) then + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + + (zi-xyzmh_ptmass(3,isink_star))**2d0 + endif -! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + ! get opacities & Ti for ui + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) - presi = kb_on_mh*rhoi*unit_density*Ti/gmwi ! cgs - presi = presi/unit_pressure !code units - - if (isnan(kappaBari)) then - print *, "kappaBari is NaN\n", " ui(erg) = ", ui*unit_ergg, "rhoi=", rhoi*unit_density, "Ti=", Ti, & - "i=", i - stop - endif + 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 + if (isnan(kappaBari)) then + print *, "kappaBari is NaN\n", " ui(erg) = ", ui*unit_ergg, "rhoi=", rhoi*unit_density, "Ti=", Ti, & + "i=", i + stop endif - Hmod2 = cs2 * piontwo / (Om2 + 8d0*rpiontwo*rhoi) - !Q3D = Om2/(4.d0*pi*rhoi) + + 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) + !Q3D = Om2/(4.d0*pi*rhoi) !Hmod2 = (cs2/Om2) * piontwo /(1d0 + (1d0/(rpiontwo*Q3D))) - Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/Hmod2)) - coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units - end select + Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/Hmod2)) + coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units + end select ! Tfloor is from input parameters and is background heating ! Stellar heating - if (isink_star > 0 .and. Lstar > 0.d0) then -! Tfloor + stellar heating - Tmini4 = Tfloor**4d0 + exp(-coldensi*kappaBari)*(Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) - else - Tmini4 = Tfloor**4d0 - endif + if (isink_star > 0 .and. Lstar > 0.d0) then + ! Tfloor + stellar heating + Tmini4 = Tfloor**4d0 + exp(-coldensi*kappaBari)*(Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) + else + Tmini4 = Tfloor**4d0 + endif - opac = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units - opac_store(i) = opac - dudt_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opac/unit_ergg*utime! code units + 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 - ! include term from FLD - Teqi = (du_FLDi + dudti_sph) *opac*unit_ergg/utime ! physical units - du_tot = dudti_sph + dudt_rad + du_FLDi - else - Teqi = dudti_sph*opac*unit_ergg/utime - du_tot = dudti_sph + dudt_rad - endif + if (doFLD) then + ! include term from FLD + Teqi = (du_FLDi + dudt_sph(i)) *opaci*unit_ergg/utime ! physical units + du_tot = dudt_sph(i) + dudti_rad + du_FLDi + else + Teqi = dudt_sph(i)*opaci*unit_ergg/utime + du_tot = dudt_sph(i) + dudti_rad + endif - 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 - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg + 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 + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg -! calculate thermalization timescale and -! internal energy update -> in form where it'll work as dudtcool - if ((du_tot) == 0.d0) then - tthermi = 0d0 - else - tthermi = abs((ueqi - ui)/(du_tot)) - endif + ! calculate thermalization timescale and + ! internal energy update -> in form where it'll work as dudtcool + if ((du_tot) == 0.d0) then + tthermi = 0d0 + else + tthermi = abs((ueqi - ui)/(du_tot)) + endif - ttherm_store(i) = tthermi + ttherm_store(i) = tthermi - if (tthermi == 0d0) then - dudti_cool = 0.d0 ! condition if denominator above is zero - else - dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units - endif + if (tthermi == 0d0) then + dudti_cool = 0.d0 ! condition if denominator above is zero + else + dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + endif - if (isnan(dudti_cool)) then -! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "rhoi=",rhoi, "Ti=", Ti - print *, "opac=",opac,"coldensi=",coldensi,"dudti_sph",dudti_sph - print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudt_rad=", dudt_rad ,"dudt_dlf=",du_fldi,"ueqi=",ueqi,"ui=",ui - call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) - stop - else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt - endif + if (isnan(dudti_cool)) then + ! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti + print *, "rhoi=",rhoi, "Ti=", Ti + print *, "opaci=",opaci,"coldensi=",coldensi,"dudt_sphi",dudt_sph(i) + print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini + print *, "dudti_rad=", dudti_rad ,"dudt_dlf=",du_fldi,"ueqi=",ueqi,"ui=",ui + call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) + stop + else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + dudti_cool = (umini - ui)/dt + endif + + ! evolve energy + energ(i) = energ(i) + dudti_cool * dt + + enddo overpart end subroutine cooling_S07 diff --git a/src/main/force.F90 b/src/main/force.F90 index 011f6cf2b..491b961a8 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1605,7 +1605,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g if (rhoj == 0d0) then diffterm = 0d0 print *, "setting diffterm = 0", i, j, rhoj - elseif ((kfldj + kfldi) == 0.) then + elseif ((kfldj + kfldi) < tiny(0.)) then diffterm = 0d0 else diffterm = 4d0*pmassj/rhoi/rhoj diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 500ea70d6..a3fcd831b 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -126,7 +126,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use eos, only:equationofstate use substepping, only:substep,substep_gr, & substep_sph_gr,substep_sph - + use cooling_stamatellos, only:cooling_S07 + use cooling, only:Tfloor + integer, intent(inout) :: npart integer, intent(in) :: nactive real, intent(in) :: t,dtsph @@ -254,6 +256,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) call substep(npart,ntypes,nptmass,dtsph,dtextforce,t,xyzh,vxyzu,& fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,& dptmass,fsink_old,nbinmax,ibin_wake) + if (icooling == 9) call cooling_S07(npart,xyzh,vxyzu(4,:),Tfloor,fxyzu(4,:),dtsph) else call substep_sph(dtsph,npart,xyzh,vxyzu) endif diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index a3f9cd3f5..89738c538 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -1049,7 +1049,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 From c52b4d030bbbf2110f6d6155f8fb0ff1c24801a4 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 7 May 2024 17:32:53 +0100 Subject: [PATCH 113/182] Move cooling icooling=9 call to derivs --- build/Makefile | 2 +- src/main/cooling.f90 | 10 ++--- ..._stamatellos.f90 => cooling_radapprox.f90} | 41 +++++++++++-------- src/main/deriv.F90 | 9 +++- src/main/eos.f90 | 5 +-- src/main/step_leapfrog.F90 | 7 +--- 6 files changed, 41 insertions(+), 33 deletions(-) rename src/main/{cooling_stamatellos.f90 => cooling_radapprox.f90} (88%) diff --git a/build/Makefile b/build/Makefile index e248ee4b9..6a833e926 100644 --- a/build/Makefile +++ b/build/Makefile @@ -498,7 +498,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ cooling_koyamainutsuka.f90 \ cooling_ism.f90 \ cooling_molecular.f90 \ - cooling_stamatellos.f90\ + cooling_radapprox.f90\ cooling_functions.f90 \ cooling_solver.f90 \ h2chem.f90 cooling.f90 diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index c85316524..8a69ed935 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -15,7 +15,7 @@ module cooling ! 5 = Koyama & Inutuska (2002) [explicit] ! 6 = Koyama & Inutuska (2002) [implicit] ! 7 = Gammie cooling power law [explicit] -! 9 = Stamatellos et al. (2007) [implicit] +! 9 = Young et al. (2024) [implicit] ! ! :References: ! Gail & Sedlmayr textbook Physics and chemistry of Circumstellar dust shells @@ -29,7 +29,7 @@ module cooling ! ! :Dependencies: chem, cooling_gammie, cooling_gammie_PL, cooling_ism, ! cooling_koyamainutsuka, cooling_molecular, cooling_solver, -! cooling_stamatellos, dim, eos, eos_stamatellos, infile_utils, io, +! cooling_radapprox, dim, eos, eos_stamatellos, infile_utils, io, ! options, part, physcon, timestep, units, viscosity ! @@ -70,7 +70,7 @@ subroutine init_cooling(id,master,iprint,ierr) use cooling_koyamainutsuka, only:init_cooling_KI02 use cooling_solver, only:init_cooling_solver use eos_stamatellos, only:read_optab,eos_file - use cooling_stamatellos, only: init_star,od_method + use cooling_radapprox, only: init_star,od_method use viscosity, only:irealvisc integer, intent(in) :: id,master,iprint @@ -207,7 +207,7 @@ subroutine write_options_cooling(iunit) use cooling_gammie_PL, only:write_options_cooling_gammie_PL use cooling_molecular, only:write_options_molecularcooling use cooling_solver, only:write_options_cooling_solver - use cooling_stamatellos, only:write_options_cooling_stamatellos + use cooling_radapprox, only:write_options_cooling_stamatellos integer, intent(in) :: iunit write(iunit,"(/,a)") '# options controlling cooling' @@ -244,7 +244,7 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) use cooling_ism, only:read_options_cooling_ism use cooling_molecular, only:read_options_molecular_cooling use cooling_solver, only:read_options_cooling_solver - use cooling_stamatellos, only:read_options_cooling_stamatellos + use cooling_radapprox, only:read_options_cooling_stamatellos character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr diff --git a/src/main/cooling_stamatellos.f90 b/src/main/cooling_radapprox.f90 similarity index 88% rename from src/main/cooling_stamatellos.f90 rename to src/main/cooling_radapprox.f90 index 2c9fb4c4f..e72825df2 100644 --- a/src/main/cooling_stamatellos.f90 +++ b/src/main/cooling_radapprox.f90 @@ -4,7 +4,7 @@ ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.bitbucket.io/ ! !--------------------------------------------------------------------------! -module cooling_stamatellos +module cooling_radapprox ! ! Cooling method of Stamatellos et al. 2007 ! @@ -24,7 +24,7 @@ module cooling_stamatellos integer :: isink_star ! index of sink to use as illuminating star integer :: od_method = 4 ! default = Stamatellos+ 2007 method integer :: fld_opt = 1 ! by default FLD is switched on - public :: cooling_S07,write_options_cooling_stamatellos,read_options_cooling_stamatellos + public :: radcool_update_energ,write_options_cooling_stamatellos,read_options_cooling_stamatellos public :: init_star contains @@ -61,8 +61,8 @@ end subroutine init_star ! ! Do cooling calculation ! -! edit this to make a loop and update energy to return evolved energy array. -subroutine cooling_S07(npart,xyzh,energ,Tfloor,dudt_sph,dt) +! update energy to return evolved energy array. +subroutine radcool_update_energ(dt,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 @@ -71,8 +71,8 @@ subroutine cooling_S07(npart,xyzh,energ,Tfloor,dudt_sph,dt) use part, only:xyzmh_ptmass,rhoh,massoftype,igas integer,intent(in) :: npart - real,intent(in) :: dudt_sph(:),xyzh(:,:),Tfloor,dt - real,intent(inout) :: energ(:) + real,intent(in) :: xyzh(:,:),dt,Tfloor + real,intent(inout) :: energ(:),dudt_sph(:) real :: dudti_cool,ui,rhoi real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot @@ -80,13 +80,13 @@ subroutine cooling_S07(npart,xyzh,energ,Tfloor,dudt_sph,dt) real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi integer :: i - !omp parallel do default(none) & - !omp shared(npart,duFLD,xyzh,energ,rhoh,massoftype,igas,xyzmh_ptmass) & - !omp shared(isink_star,pi,steboltz,solarl,Rg,doFLD,ttherm_store,teqi_store) & - !omp shared(opac_store,Tfloor,dt,dudt_sph) - !omp private(i,poti,du_FLDi,xi,yi,zi,ui,rhoi,ri2,coldensi,kappaBari) & - !omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & - !omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,poti,presi,Hcomb) + !$omp parallel do default(none) & + !$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) & + !$omp shared(opac_store,Tfloor,dt,dudt_sph,utime,udist,umass,unit_ergg,gradP_cool) & + !$omp private(i,poti,du_FLDi,xi,yi,zi,ui,rhoi,ri2,coldensi,kappaBari,Ti) & + !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & + !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,Lstar,dudti_cool) overpart: do i=1,npart poti = Gpot_cool(i) du_FLDi = duFLD(i) @@ -204,7 +204,7 @@ subroutine cooling_S07(npart,xyzh,energ,Tfloor,dudt_sph,dt) print *, "rhoi=",rhoi, "Ti=", Ti print *, "opaci=",opaci,"coldensi=",coldensi,"dudt_sphi",dudt_sph(i) print *, "dt=",dt,"tthermi=", tthermi,"umini=", umini - print *, "dudti_rad=", dudti_rad ,"dudt_dlf=",du_fldi,"ueqi=",ueqi,"ui=",ui + print *, "dudti_rad=", dudti_rad ,"dudt_fld=",du_fldi,"ueqi=",ueqi,"ui=",ui call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then @@ -213,10 +213,17 @@ subroutine cooling_S07(npart,xyzh,energ,Tfloor,dudt_sph,dt) ! evolve energy energ(i) = energ(i) + dudti_cool * dt - + enddo overpart + !$omp end parallel do + ! zero fxyzu(4,:) + !$omp parallel do shared(dudt_sph) private(i) schedule(runtime) + do i=1,npart + dudt_sph(i) = 0d0 + enddo + !$omp end parallel do -end subroutine cooling_S07 +end subroutine radcool_update_energ subroutine write_options_cooling_stamatellos(iunit) @@ -274,5 +281,5 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie end subroutine read_options_cooling_stamatellos -end module cooling_stamatellos +end module cooling_radapprox diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index fd6b06ceb..18d58ff12 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -61,7 +61,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use cons2prim, only:cons2primall,cons2prim_everything,prim2consall use metric_tools, only:init_metric use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge - use options, only:implicit_radiation,implicit_radiation_store_drad,use_porosity + use options, only:implicit_radiation,implicit_radiation_store_drad,use_porosity,icooling + use cooling_radapprox, only:radcool_update_energ + use cooling, only:Tfloor integer, intent(in) :: icall integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -181,6 +183,11 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& if (use_porosity) call get_probastick(npart,xyzh,ddustprop(1,:),dustprop,dustgasprop,filfac) endif +! +! update energy if using radiative cooling approx (icooling=9) and set fxyzu(4,:) to zero +! + if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) + ! ! compute dust temperature ! diff --git a/src/main/eos.f90 b/src/main/eos.f90 index 92b6ec4b7..f23945122 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -427,7 +427,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam case(21) ! -!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=8 +!--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=9 ! if (eni < 0.) then call fatal('eos (stamatellos)','utherm < 0',var='u',val=eni) @@ -439,9 +439,6 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam presi = cgspresi/unit_pressure ponrhoi = presi/rhoi gammai = 1.d0 + presi/(eni*rhoi) - !if (gammai < 1.d0 .or. gammai > 2.d0) then - ! print *, gammai, tempi, mui,cgseni,cgsrhoi,cgspresi - !endif spsoundi = sqrt(gammai*ponrhoi) case default diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index a3fcd831b..514bdc61a 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -126,8 +126,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use eos, only:equationofstate use substepping, only:substep,substep_gr, & substep_sph_gr,substep_sph - use cooling_stamatellos, only:cooling_S07 - use cooling, only:Tfloor integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -251,12 +249,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else call substep_sph_gr(dtsph,npart,xyzh,vxyzu,dens,pxyzu,metrics) endif - else + elseif (icooling /= 9) then 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,fsink_old,nbinmax,ibin_wake) - if (icooling == 9) call cooling_S07(npart,xyzh,vxyzu(4,:),Tfloor,fxyzu(4,:),dtsph) else call substep_sph(dtsph,npart,xyzh,vxyzu) endif @@ -394,7 +391,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) dustpred,ddustevol,filfacpred,dustfrac,eos_vars,timei,dtsph,dtnew,& ppred,dens,metrics) - if (do_radiation .and. implicit_radiation) then + if (do_radiation .and. implicit_radiation .or. icooling == 9) then rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif From c15c82aa69651ef1b2cbee10adf5822036815cf3 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 14 May 2024 13:53:19 +0100 Subject: [PATCH 114/182] Set fxyzu(4,:) =0 for step_leapfrog integration --- src/main/cooling.f90 | 8 ++--- src/main/cooling_radapprox.f90 | 63 +++++++++++++++++++--------------- src/main/deriv.F90 | 18 +++++++++- src/main/substepping.F90 | 2 +- 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 8a69ed935..67fec4e62 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -207,7 +207,7 @@ subroutine write_options_cooling(iunit) use cooling_gammie_PL, only:write_options_cooling_gammie_PL use cooling_molecular, only:write_options_molecularcooling use cooling_solver, only:write_options_cooling_solver - use cooling_radapprox, only:write_options_cooling_stamatellos + use cooling_radapprox, only:write_options_cooling_radapprox integer, intent(in) :: iunit write(iunit,"(/,a)") '# options controlling cooling' @@ -224,7 +224,7 @@ subroutine write_options_cooling(iunit) case(7) call write_options_cooling_gammie_PL(iunit) case(9) - call write_options_cooling_stamatellos(iunit) + call write_options_cooling_radapprox(iunit) case default call write_options_cooling_solver(iunit) end select @@ -244,7 +244,7 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) use cooling_ism, only:read_options_cooling_ism use cooling_molecular, only:read_options_molecular_cooling use cooling_solver, only:read_options_cooling_solver - use cooling_radapprox, only:read_options_cooling_stamatellos + use cooling_radapprox, only:read_options_cooling_radapprox character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr @@ -281,7 +281,7 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) case(7) call read_options_cooling_gammie_PL(name,valstring,imatch,igotallgammiePL,ierr) case(9) - call read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) + call read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr) case default call read_options_cooling_solver(name,valstring,imatch,igotallfunc,ierr) end select diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index e72825df2..d646111df 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -22,9 +22,9 @@ module cooling_radapprox implicit none real, public :: Lstar=0.0 ! in units of L_sun integer :: isink_star ! index of sink to use as illuminating star - integer :: od_method = 4 ! default = Stamatellos+ 2007 method + 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_stamatellos,read_options_cooling_stamatellos + public :: radcool_update_energ,write_options_cooling_radapprox,read_options_cooling_radapprox public :: init_star contains @@ -76,30 +76,34 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) real :: dudti_cool,ui,rhoi real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot - real :: cs2,Om2,Hmod2,xi,yi,zi + real :: cs2,Om2,Hmod2 real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi - integer :: i + integer :: i,ratefile + character(len=20) :: filename - !$omp parallel do default(none) & +! write (temp,'(E5.2)') dt + write (filename, 11) dt +11 format("coolrate_", E7.2,".dat") + + ratefile = 34 + open(unit=ratefile,file=filename,status="replace",form="formatted") + !$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) & + !$omp shared(isink_star,doFLD,ttherm_store,teqi_store,od_method,unit_pressure,ratefile) & !$omp shared(opac_store,Tfloor,dt,dudt_sph,utime,udist,umass,unit_ergg,gradP_cool) & - !$omp private(i,poti,du_FLDi,xi,yi,zi,ui,rhoi,ri2,coldensi,kappaBari,Ti) & + !$omp private(i,poti,du_FLDi,ui,rhoi,ri2,coldensi,kappaBari,Ti) & !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,Lstar,dudti_cool) overpart: do i=1,npart poti = Gpot_cool(i) du_FLDi = duFLD(i) - xi = xyzh(1,i) - yi = xyzh(2,i) - zi = xyzh(3,i) ui = energ(i) rhoi = rhoh(xyzh(4,i),massoftype(igas)) if (isink_star > 0) then - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & - + (yi-xyzmh_ptmass(2,isink_star))**2d0 & - + (zi-xyzmh_ptmass(3,isink_star))**2d0 + 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 endif ! get opacities & Ti for ui @@ -207,26 +211,29 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) print *, "dudti_rad=", dudti_rad ,"dudt_fld=",du_fldi,"ueqi=",ueqi,"ui=",ui call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) stop - else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - dudti_cool = (umini - ui)/dt +! else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then + ! dudti_cool = (umini - ui)/dt endif ! evolve energy - energ(i) = energ(i) + dudti_cool * dt - + energ(i) = ui + dudti_cool * dt + + !set fxyzu(4,i) for timestepping - or don't... + if (dudti_cool == 0d0) then + dudt_sph(i) = tiny(dudti_cool) + else + dudt_sph(i) = dudti_cool + endif + ! !$omp critical + ! write (ratefile,'(I6,1X,E15.4,E15.4)') i, dudt_sph(i), (ui - energ(i))/dt + ! !$omp end critical enddo overpart !$omp end parallel do - ! zero fxyzu(4,:) - !$omp parallel do shared(dudt_sph) private(i) schedule(runtime) - do i=1,npart - dudt_sph(i) = 0d0 - enddo - !$omp end parallel do - + close(ratefile) end subroutine radcool_update_energ -subroutine write_options_cooling_stamatellos(iunit) +subroutine write_options_cooling_radapprox(iunit) use infile_utils, only:write_inopt use eos_stamatellos, only: eos_file integer, intent(in) :: iunit @@ -238,9 +245,9 @@ subroutine write_options_cooling_stamatellos(iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) call write_inopt(FLD_opt,'do FLD','Do FLD? (1) yes (0) no',iunit) -end subroutine write_options_cooling_stamatellos +end subroutine write_options_cooling_radapprox -subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ierr) +subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr) use io, only:warning,fatal use eos_stamatellos, only: eos_file,doFLD character(len=*), intent(in) :: name,valstring @@ -279,7 +286,7 @@ subroutine read_options_cooling_stamatellos(name,valstring,imatch,igotallstam,ie if (ngot >= 4) igotallstam = .true. -end subroutine read_options_cooling_stamatellos +end subroutine read_options_cooling_radapprox end module cooling_radapprox diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 18d58ff12..a5e3654ee 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -162,6 +162,12 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& call do_timing('radiation',tlast,tcpulast) endif +! +! update energy if using radiative cooling approx (icooling=9) +! + if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) + + ! ! compute forces ! @@ -186,7 +192,8 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! ! update energy if using radiative cooling approx (icooling=9) and set fxyzu(4,:) to zero ! - if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) +! if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) + ! ! compute dust temperature @@ -203,6 +210,15 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& enddo !$omp end parallel do endif + + if (icooling == 9) then + !$omp parallel do shared(fxyzu,npart) private(i) + do i=1,npart + fxyzu(4,i) = 0. + enddo + !$omp end parallel do + endif + ! ! set new timestep from Courant/forces condition ! diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index 89738c538..1df9d19a9 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -1074,7 +1074,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl endif endif #endif - ! update internal energy + ! update internal energy if (cooling_in_step .or. use_krome) vxyzu(4,i) = vxyzu(4,i) + dt * dudtcool From 245b4a323b0b724b6630099d05b46f0d14850965 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 14 May 2024 13:57:15 +0100 Subject: [PATCH 115/182] Set fxyzu(4,:) =0 for step_leapfrog integration - part 2 --- src/main/step_leapfrog.F90 | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 514bdc61a..6fafd8703 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -196,11 +196,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - if (icooling /= 9) then - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) - else - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) - endif + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !--floor the thermal energy if requested and required @@ -249,7 +245,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else call substep_sph_gr(dtsph,npart,xyzh,vxyzu,dens,pxyzu,metrics) endif - elseif (icooling /= 9) then + 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,& @@ -479,10 +475,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) else - if (icooling /= 9) then - vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) - else - vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) + vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) + if (fxyzu(4,i) > TINY(fxyzu(4,i))) then + print *, "In step du/dt not zero" endif endif @@ -505,11 +500,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - if (icooling /= 9) then - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) - else - vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) - endif + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !--floor the thermal energy if requested and required @@ -659,11 +650,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) else - if (icooling /= 9 ) then - vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) - else - vxyzu(1:3,i) = vxyzu(1:3,i) - hdtsph*fxyzu(1:3,i) - endif + vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then From 170823e488b8300e872a7a179709c6adf3079a63 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 22 May 2024 17:14:30 +0100 Subject: [PATCH 116/182] bugfixes --- src/main/cooling_radapprox.f90 | 61 +++++++++++++++++----------------- src/main/deriv.F90 | 10 +++--- src/main/eos_stamatellos.f90 | 17 ++++++++++ src/main/step_leapfrog.F90 | 20 +++++++---- src/main/substepping.F90 | 2 ++ 5 files changed, 69 insertions(+), 41 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index d646111df..e13f97ff2 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -20,7 +20,7 @@ module cooling_radapprox ! implicit none - real, public :: Lstar=0.0 ! in units of L_sun + real :: Lstar = 0d0 ! in units of L_sun 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 @@ -73,8 +73,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) integer,intent(in) :: npart real,intent(in) :: xyzh(:,:),dt,Tfloor real,intent(inout) :: energ(:),dudt_sph(:) - real :: dudti_cool,ui,rhoi - real :: coldensi,kappaBari,kappaParti,ri2 + real :: ui,rhoi,coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot real :: cs2,Om2,Hmod2 real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi @@ -84,20 +83,22 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) ! write (temp,'(E5.2)') dt write (filename, 11) dt 11 format("coolrate_", E7.2,".dat") - + + print *, "In cooling" ratefile = 34 open(unit=ratefile,file=filename,status="replace",form="formatted") !$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,dt,dudt_sph,utime,udist,umass,unit_ergg,gradP_cool) & + !$omp shared(opac_store,Tfloor,dt,dudt_sph,utime,udist,umass,unit_ergg,gradP_cool,Lstar) & !$omp private(i,poti,du_FLDi,ui,rhoi,ri2,coldensi,kappaBari,Ti) & !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & - !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,Lstar,dudti_cool) + !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb) overpart: do i=1,npart 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 @@ -145,8 +146,6 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) Om2 = 0d0 endif Hmod2 = cs2 * piontwo / (Om2 + 8d0*rpiontwo*rhoi) - !Q3D = Om2/(4.d0*pi*rhoi) - !Hmod2 = (cs2/Om2) * piontwo /(1d0 + (1d0/(rpiontwo*Q3D))) Hcomb = 1.d0/sqrt((1.0d0/HLom)**2.0d0 + (1.0d0/Hmod2)) coldensi = 1.014d0 * Hcomb *rhoi*umass/udist/udist ! physical units end select @@ -154,7 +153,6 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) ! Tfloor is from input parameters and is background heating ! Stellar heating if (isink_star > 0 .and. Lstar > 0.d0) then - ! Tfloor + stellar heating Tmini4 = Tfloor**4d0 + exp(-coldensi*kappaBari)*(Lstar*solarl/(16d0*pi*steboltz*ri2*udist*udist)) else Tmini4 = Tfloor**4d0 @@ -164,8 +162,8 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) opac_store(i) = opaci dudti_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opaci/unit_ergg*utime! code units +! if (mod(i,100) == 0) print *, "dudt_sph", dudt_sph(i) if (doFLD) then - ! include term from FLD Teqi = (du_FLDi + dudt_sph(i)) *opaci*unit_ergg/utime ! physical units du_tot = dudt_sph(i) + dudti_rad + du_FLDi else @@ -181,14 +179,19 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) Teqi = Teqi**(1.0/4.0) endif teqi_store(i) = Teqi + + if (Teqi > 1e6) then + print *, "dudt_sph(i)=", dudt_sph(i), "duradi=", dudti_rad, "Ti=", Ti, & + "Tmini=", Tmini4**(1.0/4.0),du_tot,Hcomb + endif + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg - ! calculate thermalization timescale and - ! internal energy update -> in form where it'll work as dudtcool + ! calculate thermalization timescale if ((du_tot) == 0.d0) then tthermi = 0d0 else @@ -196,40 +199,36 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) endif ttherm_store(i) = tthermi - + + ! evolve energy if (tthermi == 0d0) then - dudti_cool = 0.d0 ! condition if denominator above is zero + energ(i) = ui ! condition if denominator above is zero + elseif ( (dt/tthermi) < TINY(ui) ) then + energ(i) = ui else - dudti_cool = (ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) -ui)/dt !code units + energ(i) = ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) !code units endif - if (isnan(dudti_cool)) then + if (isnan(energ(i)) .or. energ(i) < epsilon(ui)) then ! print *, "kappaBari=",kappaBari, "kappaParti=",kappaParti - print *, "rhoi=",rhoi, "Ti=", Ti + 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=",dt,"tthermi=", tthermi,"umini=", umini print *, "dudti_rad=", dudti_rad ,"dudt_fld=",du_fldi,"ueqi=",ueqi,"ui=",ui - call warning("In Stamatellos cooling","dudticool=NaN. ui",val=ui) + call warning("In Stamatellos cooling","energ=NaN or 0. ui",val=ui) stop -! else if (dudti_cool < 0.d0 .and. abs(dudti_cool) > ui/dt) then - ! dudti_cool = (umini - ui)/dt endif - ! evolve energy - energ(i) = ui + dudti_cool * dt - - !set fxyzu(4,i) for timestepping - or don't... - if (dudti_cool == 0d0) then - dudt_sph(i) = tiny(dudti_cool) - else - dudt_sph(i) = dudti_cool + if (abs(dudt_sph(i)) >1.) then + !$omp critical + write (ratefile,'(I6,1X,E15.4)') i, (ui - energ(i))/dt + !$omp end critical endif - ! !$omp critical - ! write (ratefile,'(I6,1X,E15.4,E15.4)') i, dudt_sph(i), (ui - energ(i))/dt - ! !$omp end critical enddo overpart !$omp end parallel do close(ratefile) +! print *, "min/max dudt_sph():", minval(dudt_sph), maxval(dudt_sph) end subroutine radcool_update_energ diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index a5e3654ee..2c72225da 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -146,6 +146,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& call do_timing('dens',tlast,tcpulast) endif + print *, "calling eos from deriv" if (gr) then call cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) else @@ -165,7 +166,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! ! update energy if using radiative cooling approx (icooling=9) ! - if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) +! if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) ! @@ -191,8 +192,9 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! ! update energy if using radiative cooling approx (icooling=9) and set fxyzu(4,:) to zero -! -! if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) + ! + print *, "min,max energy", minval(vxyzu(4,1:npart)), maxval(vxyzu(4,1:npart)) + if (icooling == 9 .and. dt > 0.0 .and. icall==1) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) ! @@ -211,7 +213,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& !$omp end parallel do endif - if (icooling == 9) then + if (icooling == 9 .and. icall==1) then !$omp parallel do shared(fxyzu,npart) private(i) do i=1,npart fxyzu(4,i) = 0. diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index d97e0227a..9611f9685 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -100,6 +100,7 @@ end subroutine read_optab ! Main subroutine for interpolating tables to get EOS values ! subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) + use io, only:fatal real, intent(in) :: ui,rhoi real, intent(out) :: kappaBar,kappaPart,Ti,gmwi @@ -115,6 +116,13 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) umin = OPTABLE(1,1,3) ! interpolate through OPTABLE to find corresponding kappaBar, kappaPart and T + ! check values are in range of tables + if (rhoi > OPTABLE(nx,1,1) .or. rhoi < OPTABLE(1,1,1)) then + call fatal('getopac_opdep','rhoi out of range',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) + endif + if (rhoi < rhomin) then rhoi_ = rhomin else @@ -204,6 +212,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) + use io, only:fatal real, intent(out) :: ueqi real, intent(in) :: Teqi,rhoi @@ -212,6 +221,13 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) integer i, j real rhoi_ + if (rhoi > OPTABLE(nx,1,1) .or. rhoi < OPTABLE(1,1,1)) then + call fatal('getintenerg_opdep','rhoi out of range',var='rhoi',val=rhoi) + elseif (Teqi > OPTABLE(1,ny,2) .or. Teqi < OPTABLE(1,1,2)) then + call fatal('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) + endif + + ! interpolate through OPTABLE to obtain equilibrium internal energy if (rhoi < 1.0e-24) then @@ -230,6 +246,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) j = j + 1 enddo + m = (OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3))/(OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2)) c = OPTABLE(i-1,j,3) - m*OPTABLE(i-1,j,2) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 6fafd8703..c0f5c83f4 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -198,6 +198,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + !Alison + if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L202", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0. .and. icooling /= 9) then @@ -271,7 +273,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) & +!$omp shared(eos_vars,ufloor,icooling) & !$omp shared(twas,timei) & !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & @@ -318,9 +320,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + !Alison + if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) !--floor the thermal energy if requested and required - if (ufloor > 0.) then + if (ufloor > 0. .and. icooling /= 9) then if (vpred(4,i) < ufloor) then vpred(4,i) = ufloor nvfloorps = nvfloorps + 1 @@ -476,10 +480,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) - if (fxyzu(4,i) > TINY(fxyzu(4,i))) then - print *, "In step du/dt not zero" - endif endif + !Alison + if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then @@ -502,6 +505,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif + !Alison + if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L509", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0. .and. icooling /= 9) then @@ -559,7 +564,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) 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) - + !Alison + if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 errmax = max(errmax,erri) @@ -652,6 +658,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif + !Alison + if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L662", fxyzu(4,i) if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) - hdtsph*dBevol(:,i) diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index 1df9d19a9..4df15c4d8 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -943,10 +943,12 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, ! ! temperature and abundances update (only done during the last force calculation of the substep) ! + if (maxvxyzu >= 4 .and. itype==igas .and. last) then call cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucleation,dust_temp, & divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0) endif + endif enddo !$omp enddo From 0f10f4db4ca4c023c8448ad6237bc015c1adc456 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 24 May 2024 11:55:27 +0100 Subject: [PATCH 117/182] edits so it passes tests again --- src/main/step_leapfrog.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index c0f5c83f4..3e78ba2c3 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -199,7 +199,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !Alison - if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L202", fxyzu(4,i) + if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L202", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0. .and. icooling /= 9) then @@ -321,7 +321,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !Alison - if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) + if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0. .and. icooling /= 9) then @@ -482,7 +482,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif !Alison - if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) + if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then @@ -565,7 +565,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vzi = vxyzu(3,i) + hdtsph*fxyzu(3,i) if (maxvxyzu >= 4) eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) !Alison - if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) + if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L568", fxyzu(4,i) erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 errmax = max(errmax,erri) @@ -659,7 +659,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif !Alison - if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L662", fxyzu(4,i) + if (icooling ==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L662", fxyzu(4,i) if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) - hdtsph*dBevol(:,i) From 324c1a1cf73450e75a08578e49951602fee3a11a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 18 Jun 2024 16:21:38 +0100 Subject: [PATCH 118/182] debug printouts --- src/main/cooling_radapprox.f90 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index e13f97ff2..c7e9e055b 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -68,8 +68,8 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) 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 - + use part, only:xyzmh_ptmass,rhoh,massoftype,igas,iactive,isdead_or_accreted + use part, only:iphase integer,intent(in) :: npart real,intent(in) :: xyzh(:,:),dt,Tfloor real,intent(inout) :: energ(:),dudt_sph(:) @@ -91,10 +91,11 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) !$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,dt,dudt_sph,utime,udist,umass,unit_ergg,gradP_cool,Lstar) & - !$omp private(i,poti,du_FLDi,ui,rhoi,ri2,coldensi,kappaBari,Ti) & + !$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) & !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb) overpart: do i=1,npart + if (.not. iactive(iphase(i)) .or. isdead_or_accreted(xyzh(4,i))) cycle poti = Gpot_cool(i) du_FLDi = duFLD(i) ui = energ(i) @@ -106,7 +107,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) + (xyzh(2,i)-xyzmh_ptmass(2,isink_star))**2d0 & + (xyzh(3,i)-xyzmh_ptmass(3,isink_star))**2d0 endif - + if (rhoi*unit_density > 1d0) print *, "rhoi > 1.", rhoi,i,sqrt(ri2) ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) @@ -181,8 +182,9 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) teqi_store(i) = Teqi if (Teqi > 1e6) then - print *, "dudt_sph(i)=", dudt_sph(i), "duradi=", dudti_rad, "Ti=", Ti, & - "Tmini=", Tmini4**(1.0/4.0),du_tot,Hcomb + 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 * dt=", dudt_sph(i)*dt endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) From 780d7c45243b204feb877024bc3c3441d7a43e62 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 20 Jun 2024 16:14:07 +0100 Subject: [PATCH 119/182] edit to when cooling called --- src/main/deriv.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 2c72225da..ef9375311 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -194,7 +194,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! update energy if using radiative cooling approx (icooling=9) and set fxyzu(4,:) to zero ! print *, "min,max energy", minval(vxyzu(4,1:npart)), maxval(vxyzu(4,1:npart)) - if (icooling == 9 .and. dt > 0.0 .and. icall==1) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) + if (icooling == 9 .and. dt > 0.0 .and. icall==2) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) ! From 79466cbbad61c55cfe078d1de00da8a4b61f1498 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 21 Jun 2024 16:17:31 +0100 Subject: [PATCH 120/182] Batch 1 of upstream changes added --- .github/workflows/build.yml | 67 +-- .github/workflows/krome.yml | 4 +- .github/workflows/mcfost.yml | 16 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 33 +- .gitignore | 4 + AUTHORS | 35 +- build/Makefile | 7 +- build/Makefile_setups | 13 +- docs/inject_sim.rst | 73 ++++ scripts/buildbot.sh | 10 +- src/main/checkconserved.f90 | 8 +- src/main/checksetup.f90 | 32 +- src/main/cooling.f90 | 19 +- src/main/cooling_radapprox.f90 | 4 + src/main/deriv.F90 | 37 +- src/main/dust_formation.f90 | 10 +- src/main/evolve.F90 | 2 +- src/main/inject_keplerian.f90 | 257 +++++++++++ src/main/part.F90 | 20 + src/main/ptmass.F90 | 93 ++-- src/main/subgroup.f90 | 756 +++++++++++++++++++++++++++++++++ src/main/substepping.F90 | 223 +++++++--- src/main/utils_dumpfiles.f90 | 86 ++-- src/main/utils_infiles.f90 | 20 +- src/main/utils_kepler.f90 | 139 ++++++ src/main/utils_subgroup.f90 | 35 ++ src/main/wind.F90 | 20 +- src/main/wind_equations.f90 | 5 +- src/setup/set_orbit.f90 | 285 +++++++++++++ 30 files changed, 1989 insertions(+), 326 deletions(-) create mode 100644 docs/inject_sim.rst create mode 100644 src/main/inject_keplerian.f90 create mode 100644 src/main/subgroup.f90 create mode 100644 src/main/utils_kepler.f90 create mode 100644 src/main/utils_subgroup.f90 create mode 100644 src/setup/set_orbit.f90 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dccaebd65..06cf95e96 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,8 +11,6 @@ on: paths-ignore: - 'docs/**' - 'README.md' -# schedule: -# - cron: "0 0 * * *" env: OMP_STACKSIZE: 512M @@ -22,13 +20,10 @@ env: WEB_SERVER: data.phantom.cloud.edu.au WEB_HTML_DIR: /var/www/html BUILD_LOG_DIR: /ci/build/logs - RSYNC_RSH: ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" NPARALLEL: 32 jobs: matrix_prep: - # Skip scheduled runs on forks - if: ${{ github.event_name != 'schedule' || github.repository == 'danieljprice/phantom' }} runs-on: ubuntu-latest outputs: batch: ${{ steps.set-sequence.outputs.batch }} @@ -70,40 +65,11 @@ jobs: - name: Update package list run: sudo apt-get update - - name: Setup Intel repo + - name: Setup Intel compiler if: matrix.system == 'ifort' - id: intel-repo - run: | - wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB - sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB - rm GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB - sudo echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list - sudo apt-get update - INTELVERSION=$(apt-cache show intel-oneapi-compiler-fortran | grep Version | head -1) - echo "::set-output name=intelversion::$INTELVERSION" - - - name: Cache intel installation - if: matrix.system == 'ifort' - id: cache-intel - uses: actions/cache@v3 + uses: fortran-lang/setup-fortran@v1 with: - path: | - /opt/intel - key: ${{ steps.intel-repo.outputs.intelversion }} - - - name: Install Intel compilers - if: ${{ steps.cache-intel.outputs.cache-hit != 'true' && matrix.system == 'ifort' }} - run: | - sudo apt-get install -y intel-oneapi-common-vars - sudo apt-get install -y intel-oneapi-compiler-fortran - sudo apt-get install -y intel-oneapi-mpi - sudo apt-get install -y intel-oneapi-mpi-devel - - - name: Setup Intel oneAPI environment - if: matrix.system == 'ifort' - run: | - source /opt/intel/oneapi/setvars.sh - printenv >> $GITHUB_ENV + compiler: intel-classic - name: Install numpy and matplotlib for analysis unit tests run: | @@ -111,10 +77,10 @@ jobs: sudo apt-get install -y python3-matplotlib - name: "Clone phantom" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Grab a copy of splash source code" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: danieljprice/splash path: splash @@ -123,12 +89,6 @@ jobs: if: github.event_name == 'schedule' run: mkdir logs -# - name: "Grab previous build logs from web server" -# if: github.event_name == 'schedule' -# env: -# WGET: wget --recursive --no-parent --reject "index.html*" --cut-dirs=2 --no-host-directories -# run: ${WGET} -A '*${{ matrix.system[1] }}.txt' http://${WEB_SERVER}${BUILD_LOG_DIR}/ || true - - name: "Run buildbot.sh" run: ./buildbot.sh --maxdim 17000000 --url http://${WEB_SERVER}/${BUILD_LOG_DIR} --parallel ${{ matrix.batch }} ${{ env.NPARALLEL }} working-directory: scripts @@ -136,23 +96,6 @@ jobs: SYSTEM: ${{ matrix.system }} RETURN_ERR: yes -# - name: "Install SSH Key" -# if: github.event_name == 'schedule' -# uses: webfactory/ssh-agent@v0.5.3 -# with: -# ssh-private-key: ${{ secrets.RUNNER_PRIVATE_KEY }} - -# - name: "Copy new build logs to web server" -# if: ${{ (success() || failure()) && github.event_name == 'schedule' }} -# run: rsync -vau logs/*.txt ${WEB_USER}@${WEB_SERVER}:${WEB_HTML_DIR}/${BUILD_LOG_DIR} - -# - name: "Copy HTML files to web server" -# if: ${{ (success() || failure()) && github.event_name == 'schedule' }} -# run: | -# export WEB_BUILD_DIR=${WEB_HTML_DIR}/nightly/build/$(date "+%Y%m%d") -# ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" ${WEB_USER}@${WEB_SERVER} -- mkdir -p ${WEB_BUILD_DIR} -# rsync -vau logs/*.html ${WEB_USER}@${WEB_SERVER}:${WEB_BUILD_DIR}/ - - name: logs/build-failures-${{ matrix.system }}.txt if: always() run: cat logs/build-failures-${{ matrix.system }}.txt || true diff --git a/.github/workflows/krome.yml b/.github/workflows/krome.yml index 51302f869..9aa573f2f 100644 --- a/.github/workflows/krome.yml +++ b/.github/workflows/krome.yml @@ -12,6 +12,7 @@ env: PREFIX: /usr/local/ PHANTOM_DIR: ${{ github.workspace }} KROMEPATH: ${{ github.workspace }}/krome + FC: gfortran # default if not overwritten by matrix # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -27,7 +28,8 @@ jobs: toolchain: {compiler: intel-classic} steps: - - uses: awvwgk/setup-fortran@v1 + - name: "Install gfortran compiler" + uses: fortran-lang/setup-fortran@v1 with: compiler: ${{ matrix.toolchain.compiler }} diff --git a/.github/workflows/mcfost.yml b/.github/workflows/mcfost.yml index 4860e7ed8..1aac9e0ef 100644 --- a/.github/workflows/mcfost.yml +++ b/.github/workflows/mcfost.yml @@ -9,7 +9,7 @@ on: - 'README.md' env: - PREFIX: /usr/local/ + PREFIX: /opt/homebrew MCFOST_GIT: 1 SYSTEM: gfortran HOMEBREW_NO_INSTALL_CLEANUP: 1 @@ -23,13 +23,13 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - - name: install gfortran - run: brew install gfortran + - name: install gfortran compiler + uses: fortran-lang/setup-fortran@v1 + with: + compiler: gcc - - name: soft link gfortran and check version - run: | - ln -s `ls $PREFIX/bin/gfortran-* | tail -1` $PREFIX/bin/gfortran - gfortran -v + - name: Check gfortran version + run: gfortran --version - name: tap the homebrew repo run: brew tap danieljprice/all @@ -38,7 +38,7 @@ jobs: run: brew install mcfost - name: "Clone phantom" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Compile phantom and link with mcfost" run: make SETUP=disc MCFOST=yes PREFIX=${PREFIX} LIBCXX=-lc++ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bdba8393f..ca868d95d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - name: checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d78ab7eb4..3c7a977e0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,38 +53,9 @@ jobs: - name: Setup Intel repo if: matrix.system == 'ifort' - id: intel-repo - run: | - wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB - sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB - rm GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB - sudo echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list - sudo apt-get update - INTELVERSION=$(apt-cache show intel-oneapi-compiler-fortran | grep Version | head -1) - echo "::set-output name=intelversion::$INTELVERSION" - - - name: Cache intel installation - if: matrix.system == 'ifort' - id: cache-intel - uses: actions/cache@v3 + uses: fortran-lang/setup-fortran@v1 with: - path: | - /opt/intel - key: ${{ steps.intel-repo.outputs.intelversion }} - - - name: Install Intel compilers - if: ${{ steps.cache-intel.outputs.cache-hit != 'true' && matrix.system == 'ifort' }} - run: | - sudo apt-get install -y intel-oneapi-common-vars - sudo apt-get install -y intel-oneapi-compiler-fortran - sudo apt-get install -y intel-oneapi-mpi - sudo apt-get install -y intel-oneapi-mpi-devel - - - name: Setup Intel oneAPI environment - if: matrix.system == 'ifort' - run: | - source /opt/intel/oneapi/setvars.sh - printenv >> $GITHUB_ENV + compiler: intel-classic - name: "Clone phantom" uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 992380c36..4b9ae030f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,7 @@ build/phantom-version.h *.tar .DS_Store _build +*.cmdx +*.cmod +*.ilm +*.stb diff --git a/AUTHORS b/AUTHORS index b139408e6..f236e7dc4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -21,10 +21,10 @@ Rebecca Nealon Elisabeth Borchert Ward Homan Christophe Pinte +Yrisch Terrence Tricco Stephane Michoulier Simone Ceppi -Yrisch Spencer Magnall Enrico Ragusa Caitlyn Hardiman @@ -32,41 +32,42 @@ Sergei Biriukov Cristiano Longarini Giovanni Dipierro Roberto Iaconi -Amena Faruqi Hauke Worpel +Amena Faruqi Alison Young Stephen Neilson <36410751+s-neilson@users.noreply.github.com> Martina Toscani Benedetta Veronesi -Simon Glover -Sahl Rowther Thomas Reichardt +Sahl Rowther +Simon Glover Jean-François Gonzalez Christopher Russell +Phantom benchmark bot +Jolien Malfait Alex Pettitt Alessia Franchini -Jolien Malfait -Phantom benchmark bot -Nicole Rodrigues Kieran Hirsh -Farzana Meru +Nicole Rodrigues +Mike Lau Nicolás Cuello +Farzana Meru David Trevascus -Mike Lau -Miguel Gonzalez-Bolivar Chris Nixon -Orsola De Marco +Miguel Gonzalez-Bolivar Maxime Lombart Joe Fisher Giulia Ballabio -Benoit Commercon Zachary Pellow s-neilson <36410751+s-neilson@users.noreply.github.com> -Steven Rieder -Taj Jankovič -Chunliang Mu +Benoit Commercon +Orsola De Marco MICHOULIER Stephane -Jorge Cuadra +Stéven Toupin +Taj Jankovič Cox, Samuel Jeremy Smallwood -Stéven Toupin +Hugh Griffiths +Chunliang Mu +Jorge Cuadra +Steven Rieder diff --git a/build/Makefile b/build/Makefile index 6a833e926..96454f9b3 100644 --- a/build/Makefile +++ b/build/Makefile @@ -534,8 +534,9 @@ SOURCES= physcon.f90 ${CONFIG} ${SRCKERNEL} io.F90 units.f90 \ mpi_memory.f90 mpi_derivs.F90 mpi_tree.F90 kdtree.F90 linklist_kdtree.F90 utils_healpix.f90 utils_raytracer.f90 \ partinject.F90 utils_inject.f90 dust_formation.f90 ptmass_radiation.f90 ptmass_heating.f90 \ utils_deriv.f90 utils_implicit.f90 radiation_implicit.f90 ${SRCTURB} \ - ${SRCINJECT_DEPS} wind_equations.f90 wind.F90 ${SRCINJECT} \ - ${SRCKROME} memory.f90 ${SRCREADWRITE_DUMPS} \ + ${SRCINJECT_DEPS} wind_equations.f90 wind.F90 \ + ${SRCKROME} memory.f90 ${SRCREADWRITE_DUMPS} ${SRCINJECT} \ + utils_subgroup.f90 utils_kepler.f90 subgroup.f90\ quitdump.f90 ptmass.F90 \ readwrite_infile.F90 dens.F90 force.F90 deriv.F90 energies.F90 sort_particles.f90 \ utils_shuffleparticles.F90 evwrite.f90 substepping.F90 step_leapfrog.F90 writeheader.F90 ${SRCAN} step_supertimestep.F90 \ @@ -653,7 +654,7 @@ phantomsetup: setup SRCSETUP= prompting.f90 utils_omp.F90 setup_params.f90 \ set_dust_options.f90 set_units.f90 \ density_profiles.f90 readwrite_kepler.f90 readwrite_mesa.f90 \ - set_slab.f90 set_disc.F90 \ + set_slab.f90 set_disc.F90 set_orbit.f90 \ set_cubic_core.f90 set_fixedentropycore.f90 set_softened_core.f90 \ set_star_utils.f90 relax_star.f90 set_star.f90 set_hierarchical.f90 \ set_vfield.f90 set_Bfield.f90 \ diff --git a/build/Makefile_setups b/build/Makefile_setups index 55347ffb0..d5f34b9a5 100644 --- a/build/Makefile_setups +++ b/build/Makefile_setups @@ -186,6 +186,7 @@ ifeq ($(SETUP), radiotde) IND_TIMESTEPS=no ANALYSIS=analysis_radiotde.f90 MODFILE=moddump_radiotde.f90 + SRCINJECT=inject_sim.f90 SYSTEM=gfortran endif @@ -455,7 +456,6 @@ ifeq ($(SETUP), nimhdshock) NONIDEALMHD=yes KERNEL=WendlandC4 ISOTHERMAL=yes - MAXP=6000000 KNOWN_SETUP=yes endif @@ -738,7 +738,6 @@ ifeq ($(SETUP), star) MODFILE= utils_binary.f90 set_binary.f90 moddump_binary.f90 ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 KNOWN_SETUP=yes - MAXP=10000000 GRAVITY=yes endif @@ -751,7 +750,6 @@ ifeq ($(SETUP), grstar) MODFILE= moddump_tidal.f90 ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 KNOWN_SETUP=yes - MAXP=100000000 GRAVITY=yes endif @@ -761,7 +759,6 @@ ifeq ($(SETUP), radstar) MODFILE= utils_binary.f90 set_binary.f90 moddump_binary.f90 ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 KNOWN_SETUP=yes - MAXP=10000000 GRAVITY=yes RADIATION=yes endif @@ -773,7 +770,6 @@ ifeq ($(SETUP), dustystar) MODFILE= utils_binary.f90 set_binary.f90 moddump_binary.f90 ANALYSIS= ${SRCNIMHD} utils_summary.o utils_omp.o ptmass.o energies.o analysis_common_envelope.f90 dust_formation.f90 KNOWN_SETUP=yes - MAXP=10000000 GRAVITY=yes SINK_RADIATION=yes endif @@ -927,10 +923,11 @@ ifeq ($(SETUP), isosgdisc) SETUPFILE= setup_disc.f90 GRAVITY=yes IND_TIMESTEPS=yes - ANALYSIS=analysis_dustydisc.f90 + #ANALYSIS=analysis_dustydisc.f90 ISOTHERMAL=yes - DISC_VISCOSITY=yes KNOWN_SETUP=yes + SRCINJECT= inject_keplerian.f90 + ANALYSIS = utils_getneighbours.F90 utils_omp.F90 analysis_disc_stresses.f90 endif ifeq ($(SETUP), dustyisosgdisc) @@ -941,7 +938,7 @@ ifeq ($(SETUP), dustyisosgdisc) IND_TIMESTEPS=yes ANALYSIS=analysis_dustydisc.f90 ISOTHERMAL=yes - DISC_VISCOSITY=yes + SRCINJECT= inject_keplerian.f90 KNOWN_SETUP=yes endif diff --git a/docs/inject_sim.rst b/docs/inject_sim.rst new file mode 100644 index 000000000..392cc783e --- /dev/null +++ b/docs/inject_sim.rst @@ -0,0 +1,73 @@ + +Injecting particles from existing simulations to new simulations +========================================================= + +Initial setup +------------- + +To ensure the particle mass and units are consistent in both existing & new simulations, + it is recommended to use 'phantommoddump' with existing simulations to setup new simulations + +:: + + make SRCINJECT=inject_sim.f90; make moddump SRCINJECT=inject_sim.f90 + ./phantommoddump YOUR_EXISTING_SIMULATION YOUR_NEW_SIMULATION TIME + +'phantommodump' might produce a parameter file depending on the setup, + in that case one would need to run +:: + + ./phantommoddump YOUR_EXISTING_SIMULATION YOUR_NEW_SIMULATION TIME' + +one more time after setting up the parameters + +At the end of these instructions, an initial dump of the new simulaton and a .in file are created. + +:: + +Content of the .in file +-------------------------- + +Options controlling particle injection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + # options controlling particle injection + start_dump = 'dump_00000' ! dumpfile to start for injection + r_inject = 5.000E+14 ! radius to inject tde outflow (in cm) + final_dump = 'dump_02000' ! stop injection after this dump + +Here’s a brief description of each of them + +:: + + start_dump = 'dump_00000' ! dumpfile to start for injection + +set the dump start to inject. The code will check the start_dump time and start injection when the time is reached in new simulations +Once a dump is used by injection, the dump number will automatically increased by 1. The new dump is written to .in file once a full dump is saved + +If the dumps are in a different directory, + +:: + + start_dump = 'PATH/TO/YOUR/OTHER/DIR/dump_00000' ! dumpfile to start for injection + +can read dumps from other directory. The path needs to be the RELATIVE path to the working directory +!!!--------------------------------------!!! +NOTE: qotation marks are NECESSARY with path +!!!--------------------------------------!!! + +:: + + r_inject = 5.000E+14 ! radius to inject tde outflow (in cm) + +set the radius for inject. For TDE outflow specifically, once a particle pass this radius from inside to outside in the existing simulations, it is injected to the new simulations + +:: + + final_dump = 'dump_02000' ! stop injection after this dump + +set the dump to stop injection. The injection dump number keep increasing by 1 after each injection and will stop once reaching this set final_dump. +If there is a PATH in start_dump, it is NECESSARY in final_dump as well. + diff --git a/scripts/buildbot.sh b/scripts/buildbot.sh index 0b503882c..09a1c8e19 100755 --- a/scripts/buildbot.sh +++ b/scripts/buildbot.sh @@ -13,7 +13,7 @@ # # Written by Daniel Price, 2012-2023, daniel.price@monash.edu # -if [ X$SYSTEM == X ]; then +if [ "X$SYSTEM" == "X" ]; then echo "Error: Need SYSTEM environment variable set to check PHANTOM build"; echo "Usage: $0 [max idim to check] [url]"; exit; @@ -77,7 +77,6 @@ listofcomponents='main setup analysis utils'; # get list of targets, components and setups to check # allsetups=`grep 'ifeq ($(SETUP)' $phantomdir/build/Makefile_setups | grep -v skip | cut -d, -f 2 | cut -d')' -f 1` -#allsetups='star' setuparr=($allsetups) batchsize=$(( ${#setuparr[@]} / $nbatch + 1 )) offset=$(( ($batch-1) * $batchsize )) @@ -184,9 +183,10 @@ check_phantomsetup () # myinput="\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; prefix="myrun"; + flags="--np=1000" echo -e "$myinput" > myinput.txt; sed '/-e/d' myinput.txt > mycleanin.txt - ./phantomsetup $prefix < mycleanin.txt > /dev/null; err=$?; + ./phantomsetup $prefix $flags < mycleanin.txt > /dev/null; err=$?; if [ $err -eq 0 ]; then print_result "runs" $pass; else @@ -197,8 +197,8 @@ check_phantomsetup () # run phantomsetup up to 3 times to successfully create/rewrite the .setup file # infile="${prefix}.in" - ./phantomsetup $prefix < myinput.txt > /dev/null; - ./phantomsetup $prefix < myinput.txt > /dev/null; + ./phantomsetup $prefix $flags < myinput.txt > /dev/null; + ./phantomsetup $prefix $flags < myinput.txt > /dev/null; if [ -e "$prefix.setup" ]; then print_result "creates .setup file" $pass; #test_setupfile_options "$prefix" "$prefix.setup" $infile; diff --git a/src/main/checkconserved.f90 b/src/main/checkconserved.f90 index a5538d537..9fb43c454 100644 --- a/src/main/checkconserved.f90 +++ b/src/main/checkconserved.f90 @@ -132,10 +132,10 @@ subroutine check_magnetic_stability(hdivBonB_ave,hdivBonB_max) real, intent(in) :: hdivBonB_ave,hdivBonB_max if (hdivBonB_max > 100 .or. hdivBonB_ave > 0.1) then - ! Tricco, Price & Bate (2016) suggest the average should remain lower than 0.01, - ! but we will increase it here due to the nature of the exiting the code - ! The suggestion of 512 was empirically determined in Dobbs & Wurster (2021) - call do_not_publish_crap('evolve','h|divb|/b is too large; recommend to increase the overcleanfac') + ! Tricco, Price & Bate (2016) suggest the average should remain lower than 0.01, + ! but we will increase it here due to the nature of the exiting the code + ! The suggestion of 512 was empirically determined in Dobbs & Wurster (2021) + call do_not_publish_crap('evolve','h|divb|/b is too large; recommend to increase the overcleanfac') endif end subroutine check_magnetic_stability diff --git a/src/main/checksetup.f90 b/src/main/checksetup.f90 index 39ac95b9b..9ab68cacf 100644 --- a/src/main/checksetup.f90 +++ b/src/main/checksetup.f90 @@ -105,7 +105,7 @@ subroutine check_setup(nerror,nwarn,restart) nerror = nerror + 1 endif else - if (polyk < tiny(0.) .and. ieos /= 2 .and. ieos /= 5) then + if (polyk < tiny(0.) .and. ieos /= 2 .and. ieos /= 5 .and. ieos /= 17) then print*,'WARNING! polyk = ',polyk,' in setup, speed of sound will be zero in equation of state' nwarn = nwarn + 1 endif @@ -239,7 +239,7 @@ subroutine check_setup(nerror,nwarn,restart) nerror = nerror + 1 endif else - if (abs(gamma-1.) > tiny(gamma) .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /=9)) then + if (abs(gamma-1.) > tiny(gamma) .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /=9 .and. ieos /= 17)) then print*,'*** ERROR: using isothermal EOS, but gamma = ',gamma gamma = 1. print*,'*** Resetting gamma to 1, gamma = ',gamma @@ -433,6 +433,10 @@ subroutine check_setup(nerror,nwarn,restart) !--check Forward symplectic integration method imcompatiblity ! call check_vdep_extf (nwarn,iexternalforce) +! +!--check Regularization imcompatibility +! + call check_regnbody (nerror) if (.not.h2chemistry .and. maxvxyzu >= 4 .and. icooling == 3 .and. iexternalforce/=iext_corotate .and. nptmass==0) then if (dot_product(xcom,xcom) > 1.e-2) then @@ -1016,16 +1020,30 @@ subroutine check_setup_radiation(npart,nerror,nwarn,radprop,rad) end subroutine check_setup_radiation subroutine check_vdep_extf(nwarn,iexternalforce) - use externalforces, only: is_velocity_dependent - use ptmass, only : use_fourthorder + use externalforces, only:is_velocity_dependent + use ptmass, only:use_fourthorder + use dim, only:gr integer, intent(inout) :: nwarn integer, intent(in) :: iexternalforce - if (is_velocity_dependent(iexternalforce) .and. use_fourthorder) then - print "(/,a,/)","Warning: velocity dependant external forces are not compatible with FSI switch back to Leapfrog..." - nwarn = nwarn + 1 + + if (iexternalforce > 0 .and. is_velocity_dependent(iexternalforce) .and. use_fourthorder) then + if (.not.gr) then ! do not give the warning in GR, just do it... + print "(/,1x,a,/)"," Warning: Switching to Leapfrog integrator for velocity-dependent external forces..." + nwarn = nwarn + 1 + endif use_fourthorder = .false. endif end subroutine check_vdep_extf +subroutine check_regnbody (nerror) + use ptmass, only:use_regnbody,use_fourthorder + integer, intent(inout) :: nerror + if (use_regnbody .and. .not.(use_fourthorder)) then + print "(/,a,/)","Error: TTL integration and regularization tools are not available without FSI. Turn off TTL..." + nerror = nerror + 1 + endif +end subroutine check_regnbody + + end module checksetup diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 67fec4e62..d333810e8 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -70,7 +70,7 @@ subroutine init_cooling(id,master,iprint,ierr) 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 cooling_radapprox, only:init_star,od_method use viscosity, only:irealvisc integer, intent(in) :: id,master,iprint @@ -86,7 +86,7 @@ subroutine init_cooling(id,master,iprint,ierr) call init_cooling_ism() if (icooling==8) cooling_in_step = .false. case(9) - if (ieos /= 21 .and. ieos /=2) call fatal('cooling','icooling=9 requires ieos=21',& + if (ieos /= 21 ) call fatal('cooling','icooling=9 requires ieos=21',& 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) @@ -132,7 +132,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,dudti_sph,part_id) +subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,abund_in) use io, only:fatal use dim, only:nabundances use eos, only:gmw,gamma,ieos,get_temperature_from_u @@ -147,8 +147,6 @@ subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2 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 :: dudti_sph ! in code units - integer, intent(in),optional :: part_id real, intent(in), optional :: abund_in(nabn) real, intent(out) :: dudt ! in code units real :: mui,gammai,Tgas,Tdust,K2,kappa @@ -176,9 +174,6 @@ subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2 if (present(Tdust_in)) Tdust = Tdust_in select case (icooling) - case (9) - ! should not occur! - call fatal('energ_cooling','cooling_S07 called from cooling.f90') case (6) call cooling_KoyamaInutsuka_implicit(ui,rho,dt,dudt) case (5) @@ -249,7 +244,7 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr integer, save :: ngot = 0 - logical :: igotallism,igotallmol,igotallgammie,igotallgammiePL,igotallfunc,igotallstam + logical :: igotallism,igotallmol,igotallgammie,igotallgammiePL,igotallfunc,igotallradapp imatch = .true. igotall = .false. ! cooling options are compulsory @@ -257,7 +252,7 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) igotallmol = .true. igotallgammie = .true. igotallfunc = .true. - igotallstam = .true. + igotallradapp = .true. select case(trim(name)) case('icooling') @@ -281,13 +276,13 @@ subroutine read_options_cooling(name,valstring,imatch,igotall,ierr) case(7) call read_options_cooling_gammie_PL(name,valstring,imatch,igotallgammiePL,ierr) case(9) - call read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr) + call read_options_cooling_radapprox(name,valstring,imatch,igotallradapp,ierr) case default call read_options_cooling_solver(name,valstring,imatch,igotallfunc,ierr) end select end select ierr = 0 - if (icooling >= 0 .and. ngot >= 2 .and. igotallgammie .and. igotallfunc .and. igotallism .and. igotallstam) then + if (icooling >= 0 .and. ngot >= 2 .and. igotallgammie .and. igotallfunc .and. igotallism .and. igotallradapp) then igotall = .true. else igotall = .false. diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index c7e9e055b..b7ea939e4 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -254,6 +254,7 @@ subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallstam integer, intent(out) :: ierr + integer :: ieosread integer, save :: ngot = 0 imatch = .true. @@ -281,6 +282,9 @@ subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr doFLD = .true. endif ngot = ngot + 1 + case('ieos') + read(valstring,*,iostat=ierr) ieosread + if (ieosread /= 21) call fatal('ieosread','For icooling=9, you need ieos=21') case default imatch = .false. end select diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index ef9375311..c66d27e5c 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -58,7 +58,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use forces, only:force use part, only:mhd,gradh,alphaind,igas,iradxi,ifluxx,ifluxy,ifluxz,ithick use derivutils, only:do_timing - use cons2prim, only:cons2primall,cons2prim_everything,prim2consall + use cons2prim, only:cons2primall,cons2prim_everything use metric_tools, only:init_metric use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge use options, only:implicit_radiation,implicit_radiation_store_drad,use_porosity,icooling @@ -117,7 +117,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& if (gr) then ! Recalculate the metric after moving particles to their new tasks call init_metric(npart,xyzh,metrics) - !call prim2consall(npart,xyzh,metrics,vxyzu,dens,pxyzu,use_dens=.false.) endif if (nptmass > 0 .and. periodic) call ptmass_boundary_crossing(nptmass,xyzmh_ptmass) @@ -146,7 +145,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& call do_timing('dens',tlast,tcpulast) endif - print *, "calling eos from deriv" if (gr) then call cons2primall(npart,xyzh,metrics,pxyzu,vxyzu,dens,eos_vars) else @@ -163,12 +161,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& call do_timing('radiation',tlast,tcpulast) endif -! -! update energy if using radiative cooling approx (icooling=9) -! -! if (icooling == 9 .and. dt > 0.0) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) - - ! ! compute forces ! @@ -191,12 +183,11 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& endif ! -! update energy if using radiative cooling approx (icooling=9) and set fxyzu(4,:) to zero - ! +! update energy if using radiative cooling approx (icooling=9) +! print *, "min,max energy", minval(vxyzu(4,1:npart)), maxval(vxyzu(4,1:npart)) - if (icooling == 9 .and. dt > 0.0 .and. icall==2) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) + if (icooling == 9 .and. dt > 0.0 .and. icall==1) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) - ! ! compute dust temperature ! @@ -213,6 +204,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& !$omp end parallel do endif +! Set dudt to zero because we evolved energy already for icooling=9 if (icooling == 9 .and. icall==1) then !$omp parallel do shared(fxyzu,npart) private(i) do i=1,npart @@ -246,11 +238,13 @@ end subroutine derivs !+ !-------------------------------------- subroutine get_derivs_global(tused,dt_new,dt) - use part, only:npart,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& - Bevol,dBevol,rad,drad,radprop,dustprop,ddustprop,filfac,& - dustfrac,ddustevol,eos_vars,pxyzu,dens,metrics,dustevol - use timing, only:printused,getused - use io, only:id,master + use part, only:npart,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& + Bevol,dBevol,rad,drad,radprop,dustprop,ddustprop,filfac,& + dustfrac,ddustevol,eos_vars,pxyzu,dens,metrics,dustevol,gr + use timing, only:printused,getused + use io, only:id,master + use cons2prim, only:prim2consall + use metric_tools, only:init_metric real(kind=4), intent(out), optional :: tused real, intent(out), optional :: dt_new real, intent(in), optional :: dt ! optional argument needed to test implicit radiation routine @@ -262,6 +256,13 @@ subroutine get_derivs_global(tused,dt_new,dt) dti = 0. if (present(dt)) dti = dt call getused(t1) + ! update conserved quantities in the GR code + if (gr) then + call init_metric(npart,xyzh,metrics) + call prim2consall(npart,xyzh,metrics,vxyzu,dens,pxyzu,use_dens=.false.) + endif + + ! evaluate derivatives call derivs(1,npart,npart,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,Bevol,dBevol,& rad,drad,radprop,dustprop,ddustprop,dustevol,ddustevol,filfac,dustfrac,& eos_vars,time,dti,dtnew,pxyzu,dens,metrics) diff --git a/src/main/dust_formation.f90 b/src/main/dust_formation.f90 index 5598f85fb..f32754011 100644 --- a/src/main/dust_formation.f90 +++ b/src/main/dust_formation.f90 @@ -372,7 +372,8 @@ end subroutine evol_K !---------------------------------------- subroutine calc_muGamma(rho_cgs, T, mu, gamma, pH, pH_tot) ! all quantities are in cgs - use io, only:fatal + use io, only:fatal + use eos, only:ieos real, intent(in) :: rho_cgs real, intent(inout) :: T, mu, gamma @@ -388,8 +389,8 @@ subroutine calc_muGamma(rho_cgs, T, mu, gamma, pH, pH_tot) T_old = T if (T > 1.d4) then mu = (1.+4.*eps(iHe))/(1.+eps(iHe)) - gamma = 5./3. pH = pH_tot + if (ieos /= 17) gamma = 5./3. elseif (T > 450.) then ! iterate to get consistently pH, T, mu and gamma tol = 1.d-3 @@ -404,6 +405,7 @@ subroutine calc_muGamma(rho_cgs, T, mu, gamma, pH, pH_tot) pH = solve_q(2.*KH2, 1., -pH_tot) pH2 = KH2*pH**2 mu = (1.+4.*eps(iHe))/(.5+eps(iHe)+0.5*pH/pH_tot) + if (ieos == 17) exit !only update mu, keep gamma constant x = 2.*(1.+4.*eps(iHe))/mu gamma = (3.*x+4.+4.*eps(iHe))/(x+4.+4.*eps(iHe)) converged = (abs(T-T_old)/T_old) < tol @@ -411,7 +413,7 @@ subroutine calc_muGamma(rho_cgs, T, mu, gamma, pH, pH_tot) mu_old = mu gamma_old = gamma else - T = 2.*T_old*mu/mu_old/(gamma_old-1.)*(x-eps(iHe))/(x+4.-eps(iHe)) + T = T_old*mu/mu_old/(gamma_old-1.)*2.*x/(x+4.+4.*eps(iHe)) if (i>=itermax .and. .not.converged) then if (isolve==0) then isolve = isolve+1 @@ -431,7 +433,7 @@ subroutine calc_muGamma(rho_cgs, T, mu, gamma, pH, pH_tot) pH2 = pH_tot/2. pH = 0. mu = (1.+4.*eps(iHe))/(0.5+eps(iHe)) - gamma = (5.*eps(iHe)+3.5)/(3.*eps(iHe)+2.5) + if (ieos /= 17) gamma = (5.*eps(iHe)+3.5)/(3.*eps(iHe)+2.5) endif end subroutine calc_muGamma diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index c96f339c1..92c22f776 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -276,7 +276,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) ! creation of new sink particles ! call ptmass_create(nptmass,npart,ipart_rhomax,xyzh,vxyzu,fxyzu,fext,divcurlv,& - poten,massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,time) + poten,massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,dptmass,time) endif ! ! Strang splitting: implicit update for half step diff --git a/src/main/inject_keplerian.f90 b/src/main/inject_keplerian.f90 new file mode 100644 index 000000000..7ade9b7b0 --- /dev/null +++ b/src/main/inject_keplerian.f90 @@ -0,0 +1,257 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module inject +! +! Injection of material at keplerian speed in an accretion disc +! +! :References: +! +! :Owner: Daniel Price +! +! :Runtime parameters: +! - datafile : *name of data file for wind injection* +! - outer_boundary : *kill gas particles outside this radius* +! +! :Dependencies: dim, eos, infile_utils, io, part, partinject, physcon, +! random, units +! + implicit none + character(len=*), parameter, public :: inject_type = 'keplerian' + + public :: init_inject,inject_particles,write_options_inject,read_options_inject,& + set_default_options_inject,update_injected_par + + real :: mdot = 0. + real :: rinj = 25. + real :: HonR_inj = 0.05 + logical :: follow_sink = .true. + integer, private :: iseed=-888 + +contains +!----------------------------------------------------------------------- +!+ +! Initialize global variables or arrays needed for injection routine +!+ +!----------------------------------------------------------------------- +subroutine init_inject(ierr) + use io, only:warning + use part, only:nptmass + integer, intent(out) :: ierr + ! + ! return without error + ! + ierr = 0 + if (nptmass > 1) call warning(inject_type,'Using first sink particle to compute Keplerian velocity') + +end subroutine init_inject + +!----------------------------------------------------------------------- +!+ +! set defaults +!+ +!----------------------------------------------------------------------- +subroutine set_default_options_inject(flag) + integer, optional, intent(in) :: flag + +end subroutine set_default_options_inject + +!----------------------------------------------------------------------- +!+ +! Main routine handling injection at a given radius rinj +!+ +!----------------------------------------------------------------------- +subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& + npart,npart_old,npartoftype,dtinject) + use io, only:fatal,iverbose,warning + use part, only:massoftype,igas,nptmass,isdead_or_accreted,maxvxyzu + use partinject, only:add_or_update_particle + use physcon, only:pi,solarm,years + use units, only:umass,utime + use random, only:ran2,gauss_random + use options, only:iexternalforce,ieos + use externalforces, only:mass1 + use eos, only:equationofstate,gamma + real, intent(in) :: time, dtlast + real, intent(inout) :: xyzh(:,:), vxyzu(:,:), xyzmh_ptmass(:,:), vxyz_ptmass(:,:) + integer, intent(inout) :: npart, npart_old + integer, intent(inout) :: npartoftype(:) + real, intent(out) :: dtinject + real :: Minject,Mdot_code + real :: frac_extra,deltat + real :: x0(3),v0(3),mstar,r2min,dr2,hguess,phi,cosphi,sinphi,r2,xyzi(3),vxyz(3),u + real :: vkep,vphi,zi,cs,bigH + real :: dum_ponrho,dum_rho,dum_temp + integer :: i,k,i_part,ninject + ! + ! convert mass loss rate from Msun/yr to code units + ! + Mdot_code = Mdot*(solarm/umass)*(utime/years) + + ! + ! get central mass + ! + x0 = 0. + v0 = 0. + if (iexternalforce > 0) then + mstar = mass1 + elseif (nptmass >= 1) then + if (follow_sink) then + x0 = xyzmh_ptmass(1:3,1) + v0 = vxyz_ptmass(1:3,1) + endif + mstar = xyzmh_ptmass(4,1) + else + mstar = 1. + call fatal(inject_type,'no central object to compute Keplerian velocity') + endif + + ! for the smoothing length, take it from the closest existing particle to the injection radius + hguess = 1. + r2min = huge(r2min) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + r2 = (xyzh(1,i)-x0(1))**2 + (xyzh(2,i)-x0(2))**2 + dr2 = abs(r2 - rinj*rinj) + if (dr2 < r2min) then + hguess = xyzh(4,i) + r2min = dr2 + endif + endif + enddo + + vkep = sqrt(mstar/rinj) + + ! for the temperature, call equation of state to get cs at this radius + if (maxvxyzu >= 4) then + ! use HonR parameter + cs = HonR_inj * vkep + else + dum_rho = 1. + dum_temp = 0. + if (gamma > 1.001) then + call warning(inject_type,'cannot get temp at r=rinj without knowing density, injecting at z=0') + cs = 0. + else + call equationofstate(ieos,dum_ponrho,cs,dum_rho,rinj,0.,0.,dum_temp) + endif + endif + + ! + ! calculate how much mass to inject based on + ! time interval since last injection + ! + deltat = dtlast + Minject = Mdot_code*deltat + ! + ! work out number of particles by divide by mass of gas particles + ! + ninject = int(Minject/massoftype(igas)) + ! + ! for the residual, roll the dice + ! + frac_extra = Minject/massoftype(igas) - 2*(ninject/2) + if (ran2(iseed) < 0.5*frac_extra) ninject = ninject + 2 + + if (iverbose >= 2) print*,' injecting ',& + ninject,Minject/massoftype(igas),massoftype(igas) + + if (ninject > 0) then + do k=1,ninject/2 + ! + ! get random position on ring + ! + phi = 2.*pi*(ran2(iseed) - 0.5) + + cosphi = cos(phi) + sinphi = sin(phi) + + bigH = cs*rinj/vkep + zi = gauss_random(iseed)*bigH + + vphi = vkep*(1. - (zi/rinj)**2)**(-0.75) ! see Martire et al. (2024) + + xyzi = (/rinj*cosphi,rinj*sinphi,zi/) + vxyz = (/-vphi*sinphi, vphi*cosphi, 0./) + + u = 1.5*cs**2 + + i_part = npart + 1! all particles are new + call add_or_update_particle(igas, xyzi+x0, vxyz+v0, hguess, u, i_part, npart, npartoftype, xyzh, vxyzu) + i_part = npart + 1! all particles are new + call add_or_update_particle(igas, -xyzi+x0, -vxyz+v0, hguess, u, i_part, npart, npartoftype, xyzh, vxyzu) + enddo + endif + + if (iverbose >= 2) then + print*,'npart = ',npart + endif + ! + !-- no constraint on timestep + ! + dtinject = huge(dtinject) + +end subroutine inject_particles + +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + +!----------------------------------------------------------------------- +!+ +! Writes input options to the input file. +!+ +!----------------------------------------------------------------------- +subroutine write_options_inject(iunit) + use infile_utils, only:write_inopt + use part, only:maxvxyzu,nptmass + integer, intent(in) :: iunit + + call write_inopt(mdot,'mdot','mass injection rate [msun/yr]',iunit) + call write_inopt(rinj,'rinj','injection radius',iunit) + if (maxvxyzu >= 4) then + call write_inopt(HonR_inj,'HonR_inj','aspect ratio to give temperature at rinj',iunit) +endif +if (nptmass >= 1) then + call write_inopt(follow_sink,'follow_sink','injection radius is relative to sink particle 1',iunit) +endif + +end subroutine write_options_inject + +!----------------------------------------------------------------------- +!+ +! Reads input options from the input file. +!+ +!----------------------------------------------------------------------- +subroutine read_options_inject(name,valstring,imatch,igotall,ierr) + use io, only:fatal,error,warning + use physcon, only:solarm,years + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotall + integer, intent(out) :: ierr + integer, save :: ngot = 0 + character(len=30), parameter :: label = 'read_options_inject' + + imatch = .true. + select case(trim(name)) + case('mdot') + read(valstring,*,iostat=ierr) mdot + case('rinj') + read(valstring,*,iostat=ierr) rinj + case('HonR_inj') + read(valstring,*,iostat=ierr) HonR_inj + case('follow_sink') + read(valstring,*,iostat=ierr) follow_sink + case default + imatch = .false. + end select + + igotall = (ngot >= 0) + +end subroutine read_options_inject + +end module inject diff --git a/src/main/part.F90 b/src/main/part.F90 index 362587bc2..5b5ae5f18 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -291,6 +291,20 @@ module part ! real(kind=4), allocatable :: luminosity(:) ! +!-- Regularisation algorithm allocation +! + integer, allocatable :: group_info(:,:) + integer(kind=1), allocatable :: nmatrix(:,:) + integer, parameter :: igarg = 1 ! idx of the particle member of a group + integer, parameter :: igcum = 2 ! cumulative sum of the indices to find the starting and ending point of a group + integer, parameter :: igid = 3 ! id of the group, correspond to the root of the group in the dfs/union find construction + ! needed for group identification and sorting + integer :: n_group = 0 + integer :: n_ingroup = 0 + integer :: n_sing = 0 + ! Gradient of the time transformation function + real, allocatable :: gtgrad(:,:) +! !--derivatives (only needed if derivs is called) ! real, allocatable :: fxyzu(:,:) @@ -480,6 +494,9 @@ subroutine allocate_part call allocate_array('abundance', abundance, nabundances, maxp_h2) endif call allocate_array('T_gas_cool', T_gas_cool, maxp_krome) + call allocate_array('group_info', group_info, 3, maxptmass) + call allocate_array("nmatrix", nmatrix, maxptmass, maxptmass) + call allocate_array("gtgrad", gtgrad, 3, maxptmass) end subroutine allocate_part @@ -560,6 +577,9 @@ subroutine deallocate_part if (allocated(ibelong)) deallocate(ibelong) if (allocated(istsactive)) deallocate(istsactive) if (allocated(ibin_sts)) deallocate(ibin_sts) + if (allocated(group_info)) deallocate(group_info) + if (allocated(nmatrix)) deallocate(nmatrix) + if (allocated(gtgrad)) deallocate(gtgrad) end subroutine deallocate_part diff --git a/src/main/ptmass.F90 b/src/main/ptmass.F90 index 9d536862e..65dab95a1 100644 --- a/src/main/ptmass.F90 +++ b/src/main/ptmass.F90 @@ -65,11 +65,12 @@ module ptmass real, public :: f_acc = 0.8 real, public :: h_soft_sinkgas = 0.0 real, public :: h_soft_sinksink = 0.0 - real, public :: r_merge_uncond = 0.0 ! sinks will unconditionally merge if they touch - real, public :: r_merge_cond = 0.0 ! sinks will merge if bound within this radius - real, public :: f_crit_override = 0.0 ! 1000. + real, public :: r_merge_uncond = 0.0 ! sinks will unconditionally merge if they touch + real, public :: r_merge_cond = 0.0 ! sinks will merge if bound within this radius + real, public :: f_crit_override = 0.0 ! 1000. + logical, public :: use_regnbody = .false. ! subsystems switch logical, public :: use_fourthorder = .true. integer, public :: n_force_order = 3 real, public, parameter :: dk2(3) = (/0.5,0.5,0.0/) @@ -299,7 +300,7 @@ end subroutine get_accel_sink_gas !+ !---------------------------------------------------------------- subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksink,& - iexternalforce,ti,merge_ij,merge_n,dsdt_ptmass,extrapfac,fsink_old) + iexternalforce,ti,merge_ij,merge_n,dsdt_ptmass,extrapfac,fsink_old,group_info) #ifdef FINVSQRT use fastmath, only:finvsqrt #endif @@ -307,6 +308,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin use extern_geopot, only:get_geopot_force use kernel, only:kernel_softening,radkern use vectorutils, only:unitvec + use part, only:igarg,igid integer, intent(in) :: nptmass real, intent(in) :: xyzmh_ptmass(nsinkproperties,nptmass) real, intent(out) :: fxyz_ptmass(4,nptmass) @@ -317,6 +319,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin real, intent(out) :: dsdt_ptmass(3,nptmass) real, optional, intent(in) :: extrapfac real, optional, intent(in) :: fsink_old(4,nptmass) + integer, optional, intent(in) :: group_info(3,nptmass) real :: xi,yi,zi,pmassi,pmassj,fxi,fyi,fzi,phii real :: ddr,dx,dy,dz,rr2,rr2j,dr3,f1,f2 real :: hsoft1,hsoft21,q2i,qi,psoft,fsoft @@ -324,8 +327,8 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin real :: fterm,pterm,potensoft0,dsx,dsy,dsz real :: J2i,rsinki,shati(3) real :: J2j,rsinkj,shatj(3) - integer :: i,j - logical :: extrap + integer :: k,l,i,j,gidi,gidj + logical :: extrap,subsys dtsinksink = huge(dtsinksink) fxyz_ptmass(:,:) = 0. @@ -340,6 +343,12 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin else extrap = .false. endif + + if (present(group_info)) then + subsys = .true. + else + subsys = .false. + endif ! !--get self-contribution to the potential if sink-sink softening is used ! @@ -356,10 +365,11 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin !--compute N^2 forces on point mass particles due to each other ! !$omp parallel do default(none) & - !$omp shared(nptmass,xyzmh_ptmass,fxyz_ptmass,merge_ij,r_merge2,dsdt_ptmass) & + !$omp shared(nptmass,xyzmh_ptmass,fxyz_ptmass,merge_ij,r_merge2,dsdt_ptmass,group_info,subsys) & !$omp shared(iexternalforce,ti,h_soft_sinksink,potensoft0,hsoft1,hsoft21) & !$omp shared(extrapfac,extrap,fsink_old) & - !$omp private(i,xi,yi,zi,pmassi,pmassj) & + !$omp private(i,j,xi,yi,zi,pmassi,pmassj) & + !$omp private(gidi,gidj) & !$omp private(dx,dy,dz,rr2,rr2j,ddr,dr3,f1,f2) & !$omp private(fxi,fyi,fzi,phii,dsx,dsy,dsz) & !$omp private(fextx,fexty,fextz,phiext) & @@ -367,7 +377,13 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin !$omp private(fterm,pterm,J2i,J2j,shati,shatj,rsinki,rsinkj) & !$omp reduction(min:dtsinksink) & !$omp reduction(+:phitot,merge_n) - do i=1,nptmass + do k=1,nptmass + if (subsys) then + i = group_info(igarg,k) + gidi = group_info(igid,k) + else + i = k + endif if (extrap) then xi = xyzmh_ptmass(1,i) + extrapfac*fsink_old(1,i) yi = xyzmh_ptmass(2,i) + extrapfac*fsink_old(2,i) @@ -389,7 +405,14 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin dsx = 0. dsy = 0. dsz = 0. - do j=1,nptmass + do l=1,nptmass + if (subsys) then + j = group_info(igarg,l) + gidj = group_info(igid,l) + if (gidi==gidj) cycle + else + j = l + endif if (i==j) cycle if (extrap) then dx = xi - (xyzmh_ptmass(1,j) + extrapfac*fsink_old(1,j)) @@ -552,17 +575,35 @@ end subroutine ptmass_boundary_crossing ! (called from inside a parallel section) !+ !---------------------------------------------------------------- -subroutine ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) +subroutine ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass,group_info,n_ingroup) + use part,only:igarg integer, intent(in) :: nptmass real, intent(in) :: ckdt real, intent(inout) :: xyzmh_ptmass(nsinkproperties,nptmass) real, intent(inout) :: vxyz_ptmass(3,nptmass) - integer :: i + integer, optional, intent(in) :: n_ingroup + integer, optional, intent(in) :: group_info(:,:) + integer :: i,k,istart_ptmass + logical :: woutsub + + if (present(n_ingroup)) then + istart_ptmass = n_ingroup + 1 + woutsub = .true. + else + istart_ptmass = 1 + woutsub = .false. + endif !$omp parallel do schedule(static) default(none) & !$omp shared(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) & - !$omp private(i) - do i=1,nptmass + !$omp shared(n_ingroup,group_info,woutsub,istart_ptmass) & + !$omp private(i,k) + do k=istart_ptmass,nptmass + if (woutsub) then + i = group_info(igarg,k) + else + i = k + endif if (xyzmh_ptmass(4,i) > 0.) then xyzmh_ptmass(1,i) = xyzmh_ptmass(1,i) + ckdt*vxyz_ptmass(1,i) xyzmh_ptmass(2,i) = xyzmh_ptmass(2,i) + ckdt*vxyz_ptmass(2,i) @@ -711,7 +752,7 @@ subroutine ptmass_accrete(is,nptmass,xi,yi,zi,hi,vxi,vyi,vzi,fxi,fyi,fzi, & dptmass,time,facc,nbinmax,ibin_wakei,nfaili) !$ use omputils, only:ipart_omp_lock - use part, only: ihacc + use part, only: ihacc,ndptmass use kernel, only: radkern2 use io, only: iprint,iverbose,fatal use io_summary, only: iosum_ptmass,maxisink,print_acc @@ -721,7 +762,7 @@ subroutine ptmass_accrete(is,nptmass,xi,yi,zi,hi,vxi,vyi,vzi,fxi,fyi,fzi, & real, intent(in) :: xyzmh_ptmass(nsinkproperties,nptmass) real, intent(in) :: vxyz_ptmass(3,nptmass) logical, intent(out) :: accreted - real, intent(inout) :: dptmass(:,:) + real, intent(inout) :: dptmass(ndptmass,nptmass) integer(kind=1), intent(in) :: nbinmax integer(kind=1), intent(inout) :: ibin_wakei integer, optional, intent(out) :: nfaili @@ -895,11 +936,13 @@ end subroutine ptmass_accrete !+ !----------------------------------------------------------------------- subroutine update_ptmass(dptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass) - real, intent(in) :: dptmass(:,:) + use part ,only:ndptmass + integer, intent(in) :: nptmass + real, intent(in) :: dptmass(ndptmass,nptmass) real, intent(inout) :: xyzmh_ptmass(:,:) real, intent(inout) :: vxyz_ptmass(:,:) real, intent(inout) :: fxyz_ptmass(:,:) - integer, intent(in) :: nptmass + real :: newptmass(nptmass),newptmass1(nptmass) @@ -955,9 +998,9 @@ end subroutine update_ptmass !+ !------------------------------------------------------------------------- subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,poten,& - massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,time) + massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,dptmass,time) use part, only:ihacc,ihsoft,igas,iamtype,get_partinfo,iphase,iactive,maxphase,rhoh, & - ispinx,ispiny,ispinz,fxyz_ptmass_sinksink,eos_vars,igasP,igamma,ndptmass + ispinx,ispiny,ispinz,eos_vars,igasP,igamma,ndptmass use dim, only:maxp,maxneigh,maxvxyzu,maxptmass,ind_timesteps use kdtree, only:getneigh use kernel, only:kernel_softening,radkern @@ -981,8 +1024,8 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote real, intent(inout) :: xyzh(:,:) real, intent(in) :: vxyzu(:,:),fxyzu(:,:),fext(:,:),massoftype(:) real(4), intent(in) :: divcurlv(:,:),poten(:) - real, intent(inout) :: xyzmh_ptmass(:,:) - real, intent(inout) :: vxyz_ptmass(:,:),fxyz_ptmass(:,:),dptmass(ndptmass,nptmass+1) + real, intent(inout) :: xyzmh_ptmass(:,:),dptmass(ndptmass,maxptmass) + real, intent(inout) :: vxyz_ptmass(:,:),fxyz_ptmass(4,maxptmass),fxyz_ptmass_sinksink(4,maxptmass) real, intent(in) :: time integer(kind=1) :: iphasei,ibin_wakei,ibin_itest integer :: nneigh @@ -1212,7 +1255,7 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote if (maxvxyzu >= 4) then etherm = etherm + pmassj*vxyzu(4,j) else - if (ieos==2 .and. gamma > 1.001) then + if ((ieos==2 .or. ieos==17) .and. gamma > 1.001) then etherm = etherm + pmassj*(eos_vars(igasP,j)/rhoj)/(gamma - 1.) elseif (ieos==5 .and. gamma > 1.001) then etherm = etherm + pmassj*(eos_vars(igasP,j)/rhoj)/(eos_vars(igamma,j) - 1.) @@ -1492,8 +1535,8 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote nacc = int(reduceall_mpi('+', nacc)) ! update ptmass position, spin, velocity, acceleration, and mass - fxyz_ptmass(:,nptmass) = 0.0 - fxyz_ptmass_sinksink(:,nptmass) = 0.0 + fxyz_ptmass(1:4,n) = 0.0 + fxyz_ptmass_sinksink(1:4,n) = 0.0 call update_ptmass(dptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass) if (id==id_rhomax) then diff --git a/src/main/subgroup.f90 b/src/main/subgroup.f90 new file mode 100644 index 000000000..a754e8d61 --- /dev/null +++ b/src/main/subgroup.f90 @@ -0,0 +1,756 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module subgroup +! +! this module contains everything to identify +! and integrate regularized groups... +! +! :References: Makkino et Aarseth 2002,Wang et al. 2020, Wang et al. 2021, Rantala et al. 2023 +! +! :Owner: Yrisch +! +! :Runtime parameters: None +! +! :Dependencies: io, mpiutils, part, utils_kepler, utils_subgroup +! + use utils_subgroup + implicit none + public :: group_identify + public :: evolve_groups + public :: get_pot_subsys + ! parameters for group identification + real, parameter :: eta_pert = 20 + real, parameter :: time_error = 2.5e-14 + real, parameter :: max_step = 100000000 + real, parameter, public :: r_neigh = 0.001 + real, public :: t_crit = 1.e-9 + real, public :: C_bin = 0.02 + real, public :: r_search = 100.*r_neigh + private +contains + +!----------------------------------------------- +! +! Group identification routines +! +!----------------------------------------------- +subroutine group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix) + use io ,only:id,master,iverbose,iprint + integer, intent(in) :: nptmass + real, intent(in) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + integer, intent(inout) :: group_info(3,nptmass) + integer(kind=1), intent(inout) :: nmatrix(nptmass,nptmass) + integer, intent(inout) :: n_group,n_ingroup,n_sing + + n_group = 0 + n_ingroup = 0 + n_sing = 0 + + call matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass) + call form_group(group_info,nmatrix,nptmass,n_group,n_ingroup,n_sing) + + if (id==master .and. iverbose>1) then + write(iprint,"(i6,a,i6,a,i6,a)") n_group," groups identified, ",n_ingroup," in a group, ",n_sing," singles..." + endif + +end subroutine group_identify + + +subroutine form_group(group_info,nmatrix,nptmass,n_group,n_ingroup,n_sing) + use part, only : igarg,igcum,igid + integer, intent(in) :: nptmass + integer(kind=1), intent(inout) :: nmatrix(nptmass,nptmass) + integer, intent(inout) :: group_info(3,nptmass) + integer, intent(inout) :: n_group,n_ingroup,n_sing + integer :: i,ncg + logical :: visited(nptmass) + visited = .false. + group_info(igcum,1) = 0 + do i=1,nptmass + if (.not.visited(i)) then + n_ingroup = n_ingroup + 1 + call dfs(i,visited,group_info,nmatrix,nptmass,n_ingroup,ncg) + if (ncg>1) then + n_group = n_group + 1 + group_info(igcum,n_group+1) = (ncg) + group_info(igcum,n_group) + else + n_ingroup = n_ingroup - 1 + group_info(igarg,nptmass-n_sing) = i + group_info(igid,nptmass-n_sing) = i + n_sing = n_sing + 1 + endif + endif + enddo +end subroutine form_group + +subroutine dfs(iroot,visited,group_info,nmatrix,nptmass,n_ingroup,ncg) + use part, only : igarg,igid + integer, intent(in) :: nptmass,iroot + integer, intent(out) :: ncg + integer(kind=1), intent(in) :: nmatrix(nptmass,nptmass) + integer, intent(inout) :: group_info(3,nptmass) + integer, intent(inout) :: n_ingroup + logical, intent(inout) :: visited(nptmass) + integer :: stack(nptmass) + integer :: j,stack_top,inode + + stack_top = 0 + ncg = 1 + inode = iroot + group_info(igarg,n_ingroup) = inode + group_info(igid,n_ingroup) = iroot + stack_top = stack_top + 1 + stack(stack_top) = inode + visited(inode) = .true. + do while(stack_top>0) + inode = stack(stack_top) + stack_top = stack_top - 1 + do j= 1,nptmass + if (nmatrix(inode,j)==1 .and. .not.(visited(j))) then + n_ingroup = n_ingroup + 1 + ncg = ncg + 1 + stack_top = stack_top + 1 + stack(stack_top) = j + visited(j) = .true. + group_info(igarg,n_ingroup) = j + group_info(igid,n_ingroup) = iroot + endif + enddo + enddo +end subroutine dfs + + +subroutine matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass) + use utils_kepler, only: Espec,extract_a,extract_e,extract_ea + integer, intent(in) :: nptmass + integer(kind=1), intent(out):: nmatrix(nptmass,nptmass) + real, intent(in) :: xyzmh_ptmass(:,:) + real, intent(in) :: vxyz_ptmass(:,:) + real :: xi,yi,zi,vxi,vyi,vzi,mi + real :: dx,dy,dz,dvx,dvy,dvz,r2,r,v2,mu + real :: aij,eij,B,rperi + integer :: i,j +! +!!TODO MPI Proof version of the matrix construction +! + + !$omp parallel do default(none) & + !$omp shared(nptmass,C_bin,t_crit,nmatrix) & + !$omp shared(xyzmh_ptmass,vxyz_ptmass,r_search) & + !$omp private(xi,yi,zi,mi,vxi,vyi,vzi,i,j) & + !$omp private(dx,dy,dz,r,r2) & + !$omp private(dvx,dvy,dvz,v2) & + !$omp private(mu,aij,eij,B,rperi) + do i=1,nptmass + xi = xyzmh_ptmass(1,i) + yi = xyzmh_ptmass(2,i) + zi = xyzmh_ptmass(3,i) + mi = xyzmh_ptmass(4,i) + vxi = vxyz_ptmass(1,i) + vyi = vxyz_ptmass(2,i) + vzi = vxyz_ptmass(3,i) + do j=1,nptmass + if (i==j) cycle + dx = xi - xyzmh_ptmass(1,j) + dy = yi - xyzmh_ptmass(2,j) + dz = zi - xyzmh_ptmass(3,j) + r2 = dx**2+dy**2+dz**2 + r = sqrt(r2) + if (rr_search) then + nmatrix(i,j) = 0 + cycle + endif + mu = mi + xyzmh_ptmass(4,j) + dvx = vxi - vxyz_ptmass(1,j) + dvy = vyi - vxyz_ptmass(2,j) + dvz = vzi - vxyz_ptmass(3,j) + v2 = dvx**2+dvy**2+dvz**2 + call Espec(v2,r,mu,B) + call extract_a(r,mu,v2,aij) + if (B<0) then + if (aij0) then + if (id==master) then + !$omp parallel do default(none)& + !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass)& + !$omp shared(tnext,time,group_info,gtgrad,n_group)& + !$omp private(i,start_id,end_id,gsize) + do i=1,n_group + start_id = group_info(igcum,i) + 1 + end_id = group_info(igcum,i+1) + gsize = (end_id - start_id) + 1 + call integrate_to_time(start_id,end_id,gsize,time,tnext,xyzmh_ptmass,vxyz_ptmass,group_info,fxyz_ptmass,gtgrad) + enddo + !$omp end parallel do + endif + endif + + call bcast_mpi(xyzmh_ptmass(:,1:nptmass)) + call bcast_mpi(vxyz_ptmass(:,1:nptmass)) + + +end subroutine evolve_groups + +subroutine integrate_to_time(start_id,end_id,gsize,time,tnext,xyzmh_ptmass,vxyz_ptmass,group_info,fxyz_ptmass,gtgrad) + use part, only: igarg + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:), & + fxyz_ptmass(:,:),gtgrad(:,:) + integer, intent(in) :: group_info(:,:) + integer, intent(in) :: start_id,end_id,gsize + real, intent(in) :: tnext,time + real, allocatable :: bdata(:) + real :: ds(2) + real :: time_table(ck_size) + integer :: switch + integer :: step_count_int,step_count_tsyn,n_step_end + real :: dt,ds_init,dt_end,step_modif,t_old,W_old + real :: W,tcoord + logical :: t_end_flag,backup_flag,ismultiple + integer :: i,prim,sec + + + tcoord = time + + ismultiple = gsize > 2 + + if (ismultiple) then + call get_force_TTL(xyzmh_ptmass,group_info,fxyz_ptmass,gtgrad,W,start_id,end_id,ds_init=ds_init) + else + prim = group_info(igarg,start_id) + sec = group_info(igarg,end_id) + call get_force_TTL_bin(xyzmh_ptmass,fxyz_ptmass,gtgrad,W,prim,sec,ds_init=ds_init) + endif + + + allocate(bdata(gsize*6)) + + step_count_int = 0 + step_count_tsyn = 0 + n_step_end = 0 + t_end_flag = .false. + backup_flag = .true. + ds(:) = ds_init + switch = 1 + + !print*,ds_init, tcoord,tnext,W + + do while (.true.) + + if (backup_flag) then + call backup_data(start_id,end_id,xyzmh_ptmass,vxyz_ptmass,group_info,bdata) + else + call restore_state(start_id,end_id,xyzmh_ptmass,vxyz_ptmass,group_info,tcoord,t_old,W,W_old,bdata) + endif + t_old = tcoord + W_old = W + if (ismultiple) then + do i=1,ck_size + call drift_TTL (tcoord,W,ds(switch)*cks(i),xyzmh_ptmass,vxyz_ptmass,group_info,start_id,end_id) + time_table(i) = tcoord + call kick_TTL (ds(switch)*dks(i),W,xyzmh_ptmass,vxyz_ptmass,group_info,fxyz_ptmass,gtgrad,start_id,end_id) + enddo + else + prim = group_info(igarg,start_id) + sec = group_info(igarg,end_id) + call oneStep_bin(tcoord,W,ds(switch),xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,gtgrad,time_table,prim,sec) + endif + dt = tcoord - t_old + + step_count_int = step_count_int + 1 + + if (step_count_int > max_step) then + print*,"MAX STEP NUMBER, ABORT !!!" + call abort + endif + + if ((.not.t_end_flag).and.(dt<0.)) then + !print*,"neg dt !!!",tnext,dt + call regularstepfactor((abs(tnext/dt))**(1./6.),step_modif) + step_modif = min(max(step_modif,0.0625),0.5) + ds(switch) = ds(switch)*step_modif + ds(3-switch) = ds(switch) + + backup_flag = .false. + continue + endif + + if (tcoord < tnext - time_error) then + if (t_end_flag .and. (ds(switch)==ds(3-switch))) then + step_count_tsyn = step_count_tsyn + 1 + dt_end = tnext - tcoord + if (dt<0.) then + call regularstepfactor((abs(tnext/dt))**(1./6.),step_modif) + step_modif = min(max(step_modif,0.0625),0.5) + ds(switch) = ds(switch)*step_modif + ds(3-switch) = ds(switch) + elseif ((n_step_end > 1) .and. (dt<0.3*dt_end)) then + ds(3-switch) = ds(switch) * dt_end/dt + else + n_step_end = n_step_end + 1 + endif + endif + ds(switch) = ds(3-switch) + switch = 3 - switch + if (dt>0) then + backup_flag = .true. + else + backup_flag = .false. + endif + + elseif (tcoord > tnext + time_error) then + t_end_flag = .true. + backup_flag = .false. + n_step_end = 0 + step_count_tsyn = step_count_tsyn + 1 + + call new_ds_sync_sup(ds,time_table,tnext,switch) + else + exit + endif + enddo + + !print*,step_count_int,tcoord,tnext,ds_init + + deallocate(bdata) + +end subroutine integrate_to_time + + +subroutine regularstepfactor(fac_in,fac_out) + real, intent(in) :: fac_in + real, intent(out):: fac_out + fac_out = 1.0 + if (fac_in<1) then + do while (fac_out>fac_in) + fac_out = fac_out*0.5 + enddo + else + do while(fac_out<=fac_in) + fac_out = fac_out *2 + enddo + fac_out = fac_out*0.5 + endif +end subroutine regularstepfactor + +subroutine new_ds_sync_sup(ds,time_table,tnext,switch) + real, intent(inout) :: ds(:) + real, intent(in) :: time_table(:) + real, intent(in) :: tnext + integer, intent(in) :: switch + integer :: i,k + real :: tp,dtc,dstmp + do i=1,ck_size + k = cck_sorted_id(i) + if (tnext 0.) then + dt_init = min(dt_init,0.00002*sqrt(abs(gtki)/f2)) + endif + endif + om = om + gtki*mi + enddo + + om = om*0.5 + if (init) ds_init = dt_init/om + +end subroutine get_force_TTL + +subroutine get_force_TTL_bin(xyzmh_ptmass,fxyz_ptmass,gtgrad,om,i,j,potonly,ds_init) + real, intent(in) :: xyzmh_ptmass(:,:) + real, intent(inout) :: fxyz_ptmass(:,:),gtgrad(:,:) + integer, intent(in) :: i,j + real, intent(out) :: om + logical, optional, intent(in) :: potonly + real, optional, intent(out) :: ds_init + real :: dx,dy,dz,r2,ddr,ddr3,mi,mj,dsi,dsj + real :: gravfi,gravfj,gtki,gtkj,fxi,fyi,fzi,fxj,fyj,fzj,f2i,f2j + + mi = xyzmh_ptmass(4,i) + mj = xyzmh_ptmass(4,j) + dx = xyzmh_ptmass(1,i) - xyzmh_ptmass(1,j) + dy = xyzmh_ptmass(2,i) - xyzmh_ptmass(2,j) + dz = xyzmh_ptmass(3,i) - xyzmh_ptmass(3,j) + r2 = dx**2+dy**2+dz**2 + ddr = 1./sqrt(r2) + ddr3 = ddr*ddr*ddr + gravfi = mj*ddr3 + gravfj = mi*ddr3 + gtki = mj*ddr + gtkj = mi*ddr + + + fxyz_ptmass(4,i) = -gtki + fxyz_ptmass(4,j) = -gtkj + if (.not.present(potonly)) then + fxi = -dx*gravfi + fyi = -dy*gravfi + fzi = -dz*gravfi + fxj = dx*gravfj + fyj = dy*gravfj + fzj = dz*gravfj + fxyz_ptmass(1,i) = fxi + fxyz_ptmass(2,i) = fyi + fxyz_ptmass(3,i) = fzi + fxyz_ptmass(1,j) = fxj + fxyz_ptmass(2,j) = fyj + fxyz_ptmass(3,j) = fzj + gtgrad(1,i) = -dx*gravfi*mi + gtgrad(2,i) = -dy*gravfi*mi + gtgrad(3,i) = -dz*gravfi*mi + gtgrad(1,j) = dx*gravfj*mj + gtgrad(2,j) = dy*gravfj*mj + gtgrad(3,j) = dz*gravfj*mj + endif + + om = gtki*mi + + if (present(ds_init) .and. .not.present(potonly)) then + f2i = fxi**2+fyi**2+fzi**2 + f2j = fxj**2+fyj**2+fzj**2 + dsi = sqrt(abs(gtki)/f2i) + dsj = sqrt(abs(gtkj)/f2j) + ds_init = 0.000125*min(dsi,dsj)*om + endif + + +end subroutine get_force_TTL_bin + + +subroutine get_pot_subsys(n_group,group_info,xyzmh_ptmass,fxyz_ptmass,gtgrad,epot_sinksink) + use part, only: igarg,igcum + use io, only: id,master + integer, intent(in) :: n_group + real, intent(inout) :: xyzmh_ptmass(:,:),fxyz_ptmass(:,:),gtgrad(:,:) + integer, intent(in) :: group_info(:,:) + real, intent(inout) :: epot_sinksink + integer :: i,start_id,end_id,gsize,prim,sec + real :: phitot,phigroup + phitot = 0. + if (n_group>0) then + if (id==master) then + !$omp parallel do default(none)& + !$omp shared(xyzmh_ptmass,fxyz_ptmass)& + !$omp shared(group_info,gtgrad,n_group)& + !$omp private(i,start_id,end_id,gsize,prim,sec,phigroup)& + !$omp reduction(+:phitot) + do i=1,n_group + start_id = group_info(igcum,i) + 1 + end_id = group_info(igcum,i+1) + gsize = (end_id - start_id) + 1 + if (gsize>2) then + call get_force_TTL(xyzmh_ptmass,group_info,fxyz_ptmass,gtgrad,phigroup,start_id,end_id,.true.) + else + prim = group_info(igarg,start_id) + sec = group_info(igarg,end_id) + call get_force_TTL_bin(xyzmh_ptmass,fxyz_ptmass,gtgrad,phigroup,prim,sec,.true.) + endif + phitot = phitot + phigroup + enddo + !$omp end parallel do + endif + endif + + epot_sinksink = epot_sinksink - phitot + + + +end subroutine get_pot_subsys + + +end module subgroup diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index 4df15c4d8..1040fe6fd 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -28,10 +28,11 @@ module substepping ! :Dependencies: chem, cons2primsolver, cooling, cooling_ism, damping, dim, ! dust_formation, eos, extern_gr, externalforces, io, io_summary, ! krome_interface, metric_tools, mpiutils, options, part, ptmass, -! ptmass_radiation, timestep, timestep_sts +! ptmass_radiation, subgroup, timestep, timestep_sts ! implicit none + public :: substep_gr public :: substep_sph public :: substep_sph_gr @@ -425,21 +426,25 @@ end subroutine substep_sph !---------------------------------------------------------------- subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dptmass, & - fsink_old,nbinmax,ibin_wake) + fsink_old,nbinmax,ibin_wake,gtgrad,group_info,nmatrix, & + n_group,n_ingroup,n_sing) use io, only:iverbose,id,master,iprint,fatal use options, only:iexternalforce - use part, only:fxyz_ptmass_sinksink + use part, only:fxyz_ptmass_sinksink,ndptmass use io_summary, only:summary_variable,iosumextr,iosumextt use externalforces, only:is_velocity_dependent - use ptmass, only:use_fourthorder,ck,dk + use ptmass, only:use_fourthorder,use_regnbody,ck,dk + use subgroup, only:group_identify,evolve_groups integer, intent(in) :: npart,ntypes,nptmass + integer, intent(inout) :: n_group,n_ingroup,n_sing + integer, intent(inout) :: group_info(:,:) real, intent(in) :: dtsph,time real, intent(inout) :: dtextforce real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:) real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) - real, intent(inout) :: dptmass(:,:),fsink_old(:,:) + real, intent(inout) :: dptmass(ndptmass,nptmass),fsink_old(:,:),gtgrad(:,:) integer(kind=1), intent(in) :: nbinmax - integer(kind=1), intent(inout) :: ibin_wake(:) + integer(kind=1), intent(inout) :: ibin_wake(:),nmatrix(nptmass,nptmass) logical :: extf_vdep_flag,done,last_step,accreted integer :: force_count,nsubsteps real :: timei,time_par,dt,t_end_step @@ -462,6 +467,7 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & nsubsteps = 0 dtextforce_min = huge(dt) done = .false. + accreted = .false. substeps: do while (timei <= t_end_step .and. .not.done) force_count = 0 @@ -475,34 +481,61 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & ! ! Main integration scheme ! - call kick(dk(1),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass) + call kick(dk(1),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass,dptmass) + + if (use_regnbody) then + call evolve_groups(n_group,nptmass,time_par,time_par+ck(1)*dt,group_info,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,gtgrad) + + call drift(ck(1),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass,n_ingroup,group_info) - call drift(ck(1),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,group_info=group_info) + else + call drift(ck(1),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) - call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag) + endif if (use_fourthorder) then !! FSI 4th order scheme ! FSI extrapolation method (Omelyan 2006) - call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,fsink_old) - call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass) + if (use_regnbody) then + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,fsink_old,group_info) - call drift(ck(2),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) + call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass,dptmass) - call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) - ! the last kick phase of the scheme will perform the accretion loop after velocity update - call kick(dk(3),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext, & - fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) - if (accreted) then + call evolve_groups(n_group,nptmass,time_par,time_par+ck(2)*dt,group_info,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,gtgrad) + + call drift(ck(2),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass,n_ingroup,group_info) + + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,group_info=group_info) + else call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,fsink_old) + call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass,dptmass) + + call drift(ck(2),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) + + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) + ! the last kick phase of the scheme will perform the accretion loop after velocity update endif - else !! standard leapfrog scheme + call kick(dk(3),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext, & + fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) + if (use_regnbody) then + call group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix) + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,group_info=group_info) + elseif (accreted) then + call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) + endif + else !! standard leapfrog scheme ! the last kick phase of the scheme will perform the accretion loop after velocity update call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext, & fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) @@ -510,7 +543,6 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag) endif - endif dtextforce_min = min(dtextforce_min,dtextforce) @@ -537,25 +569,26 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & end subroutine substep - !---------------------------------------------------------------- !+ ! drift routine for the whole system (part and ptmass) !+ !---------------------------------------------------------------- -subroutine drift(cki,dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) - use part, only:isdead_or_accreted +subroutine drift(cki,dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass,n_ingroup,group_info) + use part, only: isdead_or_accreted,ispinx,ispiny,ispinz,igarg use ptmass, only:ptmass_drift use io , only:id,master use mpiutils, only:bcast_mpi - real, intent(in) :: dt,cki - integer, intent(in) :: npart,nptmass,ntypes - real, intent(inout) :: time_par - real, intent(inout) :: xyzh(:,:),vxyzu(:,:) - real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) - real :: ckdt + real, intent(in) :: dt,cki + integer, intent(in) :: npart,nptmass,ntypes + real, intent(inout) :: time_par + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + integer, optional, intent(in) :: n_ingroup + integer, optional, intent(in) :: group_info(:,:) integer :: i + real :: ckdt ckdt = cki*dt @@ -576,7 +609,11 @@ subroutine drift(cki,dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vx ! Drift sink particles if (nptmass>0) then if (id==master) then - call ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) + if (present(n_ingroup)) then + call ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass,group_info,n_ingroup) + else + call ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) + endif endif call bcast_mpi(xyzmh_ptmass(:,1:nptmass)) endif @@ -585,7 +622,6 @@ subroutine drift(cki,dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vx end subroutine drift - !---------------------------------------------------------------- !+ ! kick routine for the whole system (part and ptmass) @@ -594,7 +630,7 @@ end subroutine drift subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, & fext,fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) - use part, only:isdead_or_accreted,massoftype,iamtype,iamboundary,iphase,ispinx,ispiny,ispinz,igas + use part, only:isdead_or_accreted,massoftype,iamtype,iamboundary,iphase,ispinx,ispiny,ispinz,igas,ndptmass use ptmass, only:f_acc,ptmass_accrete,pt_write_sinkev,update_ptmass,ptmass_kick use externalforces, only:accrete_particles use options, only:iexternalforce @@ -608,7 +644,8 @@ subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, real, intent(inout) :: xyzh(:,:) real, intent(inout) :: vxyzu(:,:),fext(:,:) real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) - real, optional, intent(inout) :: dptmass(:,:),fxyz_ptmass_sinksink(:,:) + real, intent(inout) :: dptmass(ndptmass,nptmass) + real, optional, intent(inout) :: fxyz_ptmass_sinksink(:,:) real, optional, intent(in) :: timei integer(kind=1), optional, intent(inout) :: ibin_wake(:) integer(kind=1), optional, intent(in) :: nbinmax @@ -619,7 +656,7 @@ subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, integer :: naccreted,nfail,nlive real :: dkdt,pmassi,fxi,fyi,fzi,accretedmass - if (present(dptmass) .and. present(timei) .and. present(ibin_wake) .and. present(nbinmax)) then + if (present(timei) .and. present(ibin_wake) .and. present(nbinmax)) then is_accretion = .true. else is_accretion = .false. @@ -671,17 +708,19 @@ subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, nlive = 0 ibin_wakei = 0 dptmass(:,1:nptmass) = 0. - !$omp parallel default(none) & + !$omp parallel do default(none) & !$omp shared(maxp,maxphase) & !$omp shared(npart,xyzh,vxyzu,fext,dkdt,iphase,ntypes,massoftype,timei,nptmass,sts_it_n) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,f_acc) & !$omp shared(iexternalforce) & !$omp shared(nbinmax,ibin_wake) & - !$omp reduction(+:dptmass) & !$omp private(i,accreted,nfaili,fxi,fyi,fzi) & !$omp firstprivate(itype,pmassi,ibin_wakei) & - !$omp reduction(+:accretedmass,nfail,naccreted,nlive) - !$omp do + !$omp reduction(+:accretedmass) & + !$omp reduction(+:nfail) & + !$omp reduction(+:naccreted) & + !$omp reduction(+:nlive) & + !$omp reduction(+:dptmass) accreteloop: do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then if (ntypes > 1 .and. maxphase==maxp) then @@ -728,8 +767,7 @@ subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, nlive = nlive + 1 endif enddo accreteloop - !$omp enddo - !$omp end parallel + !$omp end parallel do if (npart > 2 .and. nlive < 2) then call fatal('step','all particles accreted',var='nlive',ival=nlive) @@ -779,7 +817,7 @@ end subroutine kick !---------------------------------------------------------------- subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, & fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dki, & - force_count,extf_vdep_flag,fsink_old) + force_count,extf_vdep_flag,fsink_old,group_info) use io, only:iverbose,master,id,iprint,warning,fatal use dim, only:maxp,maxvxyzu,itau_alloc use ptmass, only:get_accel_sink_gas,get_accel_sink_sink,merge_sinks, & @@ -803,6 +841,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, real, intent(in) :: timei,dki,dt logical, intent(in) :: extf_vdep_flag real, optional, intent(inout) :: fsink_old(4,nptmass) + integer, optional, intent(in) :: group_info(:,:) integer :: merge_ij(nptmass) integer :: merge_n integer :: i,itype @@ -811,7 +850,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, real :: fextx,fexty,fextz,xi,yi,zi,pmassi,damp_fac real :: fonrmaxi,phii,dtphi2i real :: dkdt,extrapfac - logical :: extrap,last + logical :: extrap,last,wsub if (present(fsink_old)) then fsink_old = fxyz_ptmass @@ -820,6 +859,13 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, extrap = .false. endif + if (present(group_info)) then + wsub = .true. + else + wsub = .false. + endif + + force_count = force_count + 1 extrapfac = (1./24.)*dt**2 dkdt = dki*dt @@ -842,25 +888,50 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, if (nptmass > 0) then if (id==master) then if (extrap) then - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + if (wsub) then + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass, & + extrapfac,fsink_old,group_info) + if (merge_n > 0) then + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass, & + extrapfac,fsink_old,group_info) + endif + else + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n, & dsdt_ptmass,extrapfac,fsink_old) - if (merge_n > 0) then - call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + if (merge_n > 0) then + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n, & dsdt_ptmass,extrapfac,fsink_old) + endif endif else - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& - dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) - if (merge_n > 0) then - call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + if (wsub) then call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& - dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) - fxyz_ptmass_sinksink=fxyz_ptmass - dsdt_ptmass_sinksink=dsdt_ptmass - if (iverbose >= 2) write(iprint,*) 'dt(sink-sink) = ',C_force*dtf + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass,group_info=group_info) + if (merge_n > 0) then + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass,group_info=group_info) + fxyz_ptmass_sinksink=fxyz_ptmass + dsdt_ptmass_sinksink=dsdt_ptmass + if (iverbose >= 2) write(iprint,*) 'dt(sink-sink) = ',C_force*dtf + endif + else + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) + if (merge_n > 0) then + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& + dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) + fxyz_ptmass_sinksink=fxyz_ptmass + dsdt_ptmass_sinksink=dsdt_ptmass + if (iverbose >= 2) write(iprint,*) 'dt(sink-sink) = ',C_force*dtf + endif endif endif else @@ -873,7 +944,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, endif ! - !-- Forces on gas particles (Sink/gas,extf,damp,cooling) + !-- Forces on gas particles (Sink/gas,extf,damp,cooling,rad pressure) ! !$omp parallel default(none) & @@ -883,6 +954,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, !$omp shared(dkdt,dt,timei,iexternalforce,extf_vdep_flag,last) & !$omp shared(divcurlv,dphotflag,dphot0,nucleation,extrap) & !$omp shared(abundc,abundo,abundsi,abunde,extrapfac,fsink_old) & + !$omp shared(isink_radiation,itau_alloc,tau) & !$omp private(fextx,fexty,fextz,xi,yi,zi) & !$omp private(i,fonrmaxi,dtphi2i,phii,dtf) & !$omp firstprivate(pmassi,itype) & @@ -936,6 +1008,26 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, if (idamp > 0) then call apply_damp(fextx, fexty, fextz, vxyzu(1:3,i), (/xi,yi,zi/), damp_fac) endif + ! + ! Radiation pressure force with isink_radiation + ! + if (nptmass > 0 .and. isink_radiation > 0) then + if (extrap) then + if (itau_alloc == 1) then + call get_rad_accel_from_ptmass(nptmass,npart,i,xi,yi,zi,xyzmh_ptmass,fextx,fexty,fextz, & + tau=tau,fsink_old=fsink_old,extrapfac=extrapfac) + else + call get_rad_accel_from_ptmass(nptmass,npart,i,xi,yi,zi,xyzmh_ptmass,fextx,fexty,fextz, & + fsink_old=fsink_old,extrapfac=extrapfac) + endif + else + if (itau_alloc == 1) then + call get_rad_accel_from_ptmass(nptmass,npart,i,xi,yi,zi,xyzmh_ptmass,fextx,fexty,fextz,tau) + else + call get_rad_accel_from_ptmass(nptmass,npart,i,xi,yi,zi,xyzmh_ptmass,fextx,fexty,fextz) + endif + endif + endif fext(1,i) = fextx fext(2,i) = fexty @@ -943,24 +1035,15 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, ! ! temperature and abundances update (only done during the last force calculation of the substep) ! - if (maxvxyzu >= 4 .and. itype==igas .and. last) then call cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucleation,dust_temp, & divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0) endif - endif enddo !$omp enddo !$omp end parallel - if (nptmass > 0 .and. isink_radiation > 0 .and. .not.extrap) then - if (itau_alloc == 1) then - call get_rad_accel_from_ptmass(nptmass,npart,xyzh,xyzmh_ptmass,fext,tau) - else - call get_rad_accel_from_ptmass(nptmass,npart,xyzh,xyzmh_ptmass,fext) - endif - endif if (nptmass > 0) then call reduce_in_place_mpi('+',fxyz_ptmass(:,1:nptmass)) @@ -1002,7 +1085,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl use cooling_ism, only:nabn,dphotflag use options, only:icooling use chem, only:update_abundances,get_dphot - use dust_formation, only:evolve_dust + use dust_formation, only:evolve_dust,calc_muGamma use cooling, only:energ_cooling,cooling_in_step use part, only:rhoh #ifdef KROME @@ -1019,7 +1102,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl real, intent(in) :: dt,pmassi integer, intent(in) :: i - real :: dudtcool,rhoi,dphot + real :: dudtcool,rhoi,dphot,pH,pH_tot real :: abundi(nabn) dudtcool = 0. @@ -1047,6 +1130,8 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl call evolve_dust(dt, xyzh(:,i), vxyzu(4,i), nucleation(:,i), dust_temp(i), rhoi) eos_vars(imu,i) = nucleation(idmu,i) eos_vars(igamma,i) = nucleation(idgamma,i) + elseif (update_muGamma) then + call calc_muGamma(rhoi, dust_temp(i),eos_vars(imu,i),eos_vars(igamma,i), pH, pH_tot) endif ! ! COOLING @@ -1076,7 +1161,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl endif endif #endif - ! update internal energy + ! update internal energy if (cooling_in_step .or. use_krome) vxyzu(4,i) = vxyzu(4,i) + dt * dudtcool diff --git a/src/main/utils_dumpfiles.f90 b/src/main/utils_dumpfiles.f90 index aef612992..81b669cc8 100644 --- a/src/main/utils_dumpfiles.f90 +++ b/src/main/utils_dumpfiles.f90 @@ -155,7 +155,7 @@ module dump_utils ! generic interface for reading arrays from dumpfile interface read_array_from_file - module procedure read_array_from_file_r8, read_array_from_file_r4 + module procedure read_array_from_file_r4, read_array_from_file_r8 end interface read_array_from_file private @@ -1358,56 +1358,56 @@ function allocate_header(nint,nint1,nint2,nint4,nint8,nreal,nreal4,nreal8,err) r integer, intent(in), optional :: nint,nint1,nint2,nint4,nint8,nreal,nreal4,nreal8 integer, intent(out), optional :: err type(dump_h) :: hdr - integer :: size(ndatatypes) + integer :: size_type(ndatatypes) integer :: ierrs(ndatatypes) integer :: ierr ! make sure header is deallocated first call free_header(hdr,ierr) - size(:) = maxphead - if (present(nint)) size(i_int) = nint - if (present(nint1)) size(i_int1) = nint1 - if (present(nint2)) size(i_int2) = nint2 - if (present(nint4)) size(i_int4) = nint4 - if (present(nint8)) size(i_int8) = nint8 - if (present(nreal)) size(i_real) = nreal - if (present(nreal4)) size(i_real4) = nreal4 - if (present(nreal8)) size(i_real8) = nreal8 + size_type(:) = maxphead + if (present(nint)) size_type(i_int) = nint + if (present(nint1)) size_type(i_int1) = nint1 + if (present(nint2)) size_type(i_int2) = nint2 + if (present(nint4)) size_type(i_int4) = nint4 + if (present(nint8)) size_type(i_int8) = nint8 + if (present(nreal)) size_type(i_real) = nreal + if (present(nreal4)) size_type(i_real4) = nreal4 + if (present(nreal8)) size_type(i_real8) = nreal8 if (present(err)) err = 0 ierrs(:) = 0 hdr%nums(:) = 0 - if (size(i_int) > 0) then - allocate(hdr%inttags(size(i_int)),hdr%intvals(size(i_int)),stat=ierrs(1)) + if (size_type(i_int) > 0) then + allocate(hdr%inttags(size_type(i_int)),hdr%intvals(size_type(i_int)),stat=ierrs(1)) if (ierrs(1)==0) hdr%inttags(:) = '' endif - if (size(i_int1) > 0) then - allocate(hdr%int1tags(size(i_int1)),hdr%int1vals(size(i_int1)),stat=ierrs(2)) + if (size_type(i_int1) > 0) then + allocate(hdr%int1tags(size_type(i_int1)),hdr%int1vals(size_type(i_int1)),stat=ierrs(2)) if (ierrs(2)==0) hdr%int1tags(:) = '' endif - if (size(i_int2) > 0) then - allocate(hdr%int2tags(size(i_int2)),hdr%int2vals(size(i_int2)),stat=ierrs(3)) + if (size_type(i_int2) > 0) then + allocate(hdr%int2tags(size_type(i_int2)),hdr%int2vals(size_type(i_int2)),stat=ierrs(3)) if (ierrs(3)==0) hdr%int2tags(:) = '' endif - if (size(i_int4) > 0) then - allocate(hdr%int4tags(size(i_int4)),hdr%int4vals(size(i_int4)),stat=ierrs(4)) + if (size_type(i_int4) > 0) then + allocate(hdr%int4tags(size_type(i_int4)),hdr%int4vals(size_type(i_int4)),stat=ierrs(4)) if (ierrs(4)==0) hdr%int4tags(:) = '' endif - if (size(i_int8) > 0) then - allocate(hdr%int8tags(size(i_int8)),hdr%int8vals(size(i_int8)),stat=ierrs(5)) + if (size_type(i_int8) > 0) then + allocate(hdr%int8tags(size_type(i_int8)),hdr%int8vals(size_type(i_int8)),stat=ierrs(5)) if (ierrs(5)==0) hdr%int8tags(:) = '' endif - if (size(i_real) > 0) then - allocate(hdr%realtags(size(i_real)),hdr%realvals(size(i_real)),stat=ierrs(6)) + if (size_type(i_real) > 0) then + allocate(hdr%realtags(size_type(i_real)),hdr%realvals(size_type(i_real)),stat=ierrs(6)) if (ierrs(6)==0) hdr%realtags(:) = '' endif - if (size(i_real4) > 0) then - allocate(hdr%real4tags(size(i_real4)),hdr%real4vals(size(i_real4)),stat=ierrs(7)) + if (size_type(i_real4) > 0) then + allocate(hdr%real4tags(size_type(i_real4)),hdr%real4vals(size_type(i_real4)),stat=ierrs(7)) if (ierrs(7)==0) hdr%real4tags(:) = '' endif - if (size(i_real8) > 0) then - allocate(hdr%real8tags(size(i_real8)),hdr%real8vals(size(i_real8)),stat=ierrs(8)) + if (size_type(i_real8) > 0) then + allocate(hdr%real8tags(size_type(i_real8)),hdr%real8vals(size_type(i_real8)),stat=ierrs(8)) if (ierrs(8)==0) hdr%real8tags(:) = '' endif @@ -2412,17 +2412,19 @@ end subroutine open_dumpfile_rh ! in the file !+ !----------------------------------------------------- -subroutine read_array_from_file_r8(iunit,filename,tag,array,ierr,use_block) +subroutine read_array_from_file_r8(iunit,filename,tag,array,ierr,use_block,iprint_in) integer, intent(in) :: iunit character(len=*), intent(in) :: filename character(len=*), intent(in) :: tag real(kind=8), intent(out) :: array(:) integer, intent(out) :: ierr integer, intent(in), optional :: use_block + logical, intent(in), optional :: iprint_in integer, parameter :: maxarraylengths = 12 integer(kind=8) :: number8(maxarraylengths) integer :: i,j,k,iblock,nums(ndatatypes,maxarraylengths) integer :: nblocks,narraylengths,my_block + logical :: iprint character(len=lentag) :: mytag @@ -2431,6 +2433,14 @@ subroutine read_array_from_file_r8(iunit,filename,tag,array,ierr,use_block) else my_block = 1 ! match from block 1 by default endif + + ! if printing the tags + if (present(iprint_in)) then + iprint = iprint_in + else + iprint = .true. + endif + array = 0. ! open file for read and get minimal information from header @@ -2448,9 +2458,9 @@ subroutine read_array_from_file_r8(iunit,filename,tag,array,ierr,use_block) read(iunit,iostat=ierr) mytag if (trim(mytag)==trim(tag)) then read(iunit,iostat=ierr) array(1:min(int(number8(j)),size(array))) - print*,'->',mytag + if (iprint) print*,'->',mytag else - print*,' ',mytag + if (iprint) print*,' ',mytag read(iunit,iostat=ierr) endif else @@ -2474,24 +2484,34 @@ end subroutine read_array_from_file_r8 ! in the file !+ !----------------------------------------------------- -subroutine read_array_from_file_r4(iunit,filename,tag,array,ierr,use_block) +subroutine read_array_from_file_r4(iunit,filename,tag,array,ierr,use_block,iprint_in) integer, intent(in) :: iunit character(len=*), intent(in) :: filename character(len=*), intent(in) :: tag real(kind=4), intent(out) :: array(:) integer, intent(out) :: ierr integer, intent(in), optional :: use_block + logical, intent(in), optional :: iprint_in integer, parameter :: maxarraylengths = 12 integer(kind=8) :: number8(maxarraylengths) integer :: i,j,k,iblock,nums(ndatatypes,maxarraylengths) integer :: nblocks,narraylengths,my_block character(len=lentag) :: mytag + logical :: iprint if (present(use_block)) then my_block = use_block else my_block = 1 ! match from block 1 by default endif + + ! if printing the tags + if (present(iprint_in)) then + iprint = iprint_in + else + iprint = .true. + endif + array = 0. ! open file for read @@ -2509,9 +2529,9 @@ subroutine read_array_from_file_r4(iunit,filename,tag,array,ierr,use_block) read(iunit,iostat=ierr) mytag if (trim(mytag)==trim(tag)) then read(iunit,iostat=ierr) array(1:min(int(number8(j)),size(array))) - print*,'->',mytag + if (iprint) print*,'->',mytag else - print*,' ',mytag + if (iprint) print*,' ',mytag read(iunit,iostat=ierr) endif else diff --git a/src/main/utils_infiles.f90 b/src/main/utils_infiles.f90 index c40332b25..1a5259b6c 100644 --- a/src/main/utils_infiles.f90 +++ b/src/main/utils_infiles.f90 @@ -443,11 +443,17 @@ subroutine read_inopt_int(ival,tag,db,err,errcount,min,max) if (ierr==0) then if (present(min)) then write(chmin,"(g10.0)") min - if (ival < min) ierr = ierr_rangemin + if (ival < min) then + ierr = ierr_rangemin + ival = min + endif endif if (present(max)) then write(chmax,"(g10.0)") max - if (ival > max) ierr = ierr_rangemax + if (ival > max) then + ierr = ierr_rangemax + ival = max + endif endif endif @@ -493,11 +499,17 @@ subroutine read_inopt_real(val,tag,db,err,errcount,min,max) if (ierr==0) then if (present(min)) then write(chmin,"(g13.4)") min - if (val < min) ierr = ierr_rangemin + if (val < min) then + ierr = ierr_rangemin + val = min + endif endif if (present(max)) then write(chmax,"(g13.4)") max - if (val > max) ierr = ierr_rangemax + if (val > max) then + ierr = ierr_rangemax + val = max + endif endif endif if (present(err)) then diff --git a/src/main/utils_kepler.f90 b/src/main/utils_kepler.f90 new file mode 100644 index 000000000..deb5de94b --- /dev/null +++ b/src/main/utils_kepler.f90 @@ -0,0 +1,139 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module utils_kepler +! +! utils_kepler +! +! :References: None +! +! :Owner: Yrisch +! +! :Runtime parameters: None +! +! :Dependencies: physcon +! + use physcon,only: pi + implicit none + +contains +subroutine Espec(v2,r,mu,B) + real, intent(in) :: v2,r,mu + real, intent(out) :: B + + B = 0.5*v2 - mu/r + +end subroutine Espec + +subroutine extract_a(r,mu,v2,aij) + real, intent(in) :: r,mu,v2 + real, intent(out):: aij + aij = (r*mu)/(2.*mu-r*v2) + +end subroutine extract_a + +subroutine extract_a_dot(r2,r,mu,v2,v,acc,adot) + real, intent(in) :: r2,r,mu,v2,v,acc + real, intent(out) :: adot + real :: mu2 + mu2 = mu**2 + adot = 2.*(mu2*v+r2*v*acc)/((2.*mu-r*v2)**2) +end subroutine extract_a_dot + +subroutine extract_e(x,y,z,vx,vy,vz,mu,r,eij) + real, intent(in) :: x,y,z,vx,vy,vz,mu,r + real, intent(out):: eij + real :: eijx,eijy,eijz + real :: hx,hy,hz + + hx = y*vz-z*vy + hy = z*vx-x*vz + hz = x*vy-y*vx + + eijx = (vy*hz-vz*hy)/mu - x/r + eijy = (vz*hx-vx*hz)/mu - y/r + eijz = (vx*hy-hx*vy)/mu - z/r + + eij = sqrt(eijx**2+eijy**2+eijz**2) + +end subroutine extract_e + +subroutine extract_ea(x,y,z,vx,vy,vz,mu,aij,eij) + real, intent(in) :: x,y,z,vx,vy,vz,mu,aij + real, intent(out):: eij + real :: hx,hy,hz,h2,neg_e + + hx = y*vz-z*vy + hy = z*vx-x*vz + hz = x*vy-y*vx + + h2 = hx**2+hy**2+hz**2 + + neg_e = h2/(mu*aij) + print*,neg_e + if (neg_e>=1) then + eij = 0. + else + eij = sqrt(1-neg_e) + endif + +end subroutine extract_ea + +subroutine extract_kep_elmt(x,y,z,vx,vy,vz,mu,r,a,e,i,argp,longi,M) + real, intent(in) :: x,y,z,vx,vy,vz,mu,r + real, intent(out):: a,e,i,argp,longi,M + real :: hx,hy,hz,ex,ey,ez,v2,h,anoE,nu + real :: rdote,n,ndote + + v2 = vx**2+vy**2+vz**2 + + a = (r*mu)/(2*mu-r*v2) + + hx = y*vz-z*vy + hy = z*vx-x*vz + hz = x*vy-y*vx + + h = sqrt(hx*2+hy**2+hz**2) + i = acos(hz/h) + + ex = (vy*hz-vz*hy)/mu - x/r + ey = (vz*hx-vx*hz)/mu - y/r + ez = (vx*hy-hx*vy)/mu - z/r + + e = sqrt(ex**2+ey**2+ez**2) + + rdote = x*ex+y*ey+z*ez + + if (x*vx+y*vy+z*vz>=0) then + nu = acos(rdote/(e*r)) + else + nu = 2*pi - acos(rdote/(e*r)) + endif + anoE = tan(nu*0.5)/sqrt((1+e)/(1-e)) + anoE = 2*atan(anoE) + + M = E-e*sin(E) + + n = sqrt(hy**2+hx**2) + if (hx>=0) then + longi = acos(-hy/n) + else + longi = 2*pi - acos(-hy/n) + endif + + ndote = -hy*ex + hx*ey + if (ez>=0) then + argp = acos(ndote/(n*e)) + else + argp = 2*pi - acos(ndote/(n*e)) + endif + +end subroutine extract_kep_elmt + + + + +end module utils_kepler diff --git a/src/main/utils_subgroup.f90 b/src/main/utils_subgroup.f90 new file mode 100644 index 000000000..913a57606 --- /dev/null +++ b/src/main/utils_subgroup.f90 @@ -0,0 +1,35 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module utils_subgroup +! +! utils_subgroup +! +! :References: None +! +! :Owner: Yrisch +! +! :Runtime parameters: None +! +! :Dependencies: None +! + implicit none + integer, parameter :: ck_size = 8 + real,dimension(8),parameter :: cks=(/0.3922568052387800,0.5100434119184585,-0.4710533854097566,& + 0.0687531682525181,0.0687531682525181,-0.4710533854097566,& + 0.5100434119184585,0.3922568052387800/) + real,dimension(8),parameter :: cck_sorted=(/0.0976997828427615,0.3922568052387800,0.4312468317474820,& + 0.5000000000000000,0.5687531682525181,0.6077431947612200,& + 0.9023002171572385,1.0000000000000000/) + real,dimension(8),parameter :: dks=(/0.7845136104775600,0.2355732133593570,-1.1776799841788701,& + 1.3151863206839063,-1.1776799841788701,0.2355732133593570,& + 0.7845136104775600,0.0000000000000000/) + integer,dimension(8),parameter :: cck_sorted_id=(/6,1,3,4,5,7,2,8/) + + +contains + +end module utils_subgroup diff --git a/src/main/wind.F90 b/src/main/wind.F90 index 259e21e5c..3bb364228 100644 --- a/src/main/wind.F90 +++ b/src/main/wind.F90 @@ -207,8 +207,7 @@ subroutine wind_step(state) use cooling_solver, only:calc_cooling_rate use options, only:icooling use units, only:unit_ergg,unit_density - use dim, only:itau_alloc - use eos, only:ieos + use dim, only:itau_alloc,update_muGamma type(wind_state), intent(inout) :: state real :: rvT(3), dt_next, v_old, dlnQ_dlnT, Q_code, pH, pH_tot @@ -241,9 +240,9 @@ subroutine wind_step(state) state%gamma = state%JKmuS(idgamma) state%kappa = calc_kappa_dust(state%JKmuS(idK3), state%Tdust, state%rho) state%JKmuS(idalpha) = state%alpha_Edd+alpha_rad - elseif (idust_opacity == 1) then - state%kappa = calc_kappa_bowen(state%Tdust) - if (ieos == 5) call calc_muGamma(state%rho, state%Tg,state%mu, state%gamma, pH, pH_tot) + else + if (idust_opacity == 1) state%kappa = calc_kappa_bowen(state%Tdust) + if (update_muGamma) call calc_muGamma(state%rho, state%Tg,state%mu, state%gamma, pH, pH_tot) endif if (itau_alloc == 1) then @@ -345,13 +344,12 @@ subroutine wind_step(state) use ptmass_radiation, only:alpha_rad,iget_tdust,tdust_exp, isink_radiation use physcon, only:pi,Rg use dust_formation, only:evolve_chem,calc_kappa_dust,calc_kappa_bowen,& - calc_Eddington_factor,idust_opacity, calc_mugamma + calc_Eddington_factor,idust_opacity, calc_muGamma use part, only:idK3,idmu,idgamma,idsat,idkappa use cooling_solver, only:calc_cooling_rate use options, only:icooling use units, only:unit_ergg,unit_density - use dim, only:itau_alloc - use eos, only:ieos + use dim, only:itau_alloc,update_muGamma type(wind_state), intent(inout) :: state real :: rvT(3), dt_next, v_old, dlnQ_dlnT, Q_code, pH,pH_tot @@ -365,9 +363,9 @@ subroutine wind_step(state) state%mu = state%JKmuS(idmu) state%gamma = state%JKmuS(idgamma) state%kappa = calc_kappa_dust(state%JKmuS(idK3), state%Tdust, state%rho) - elseif (idust_opacity == 1) then - state%kappa = calc_kappa_bowen(state%Tdust) - if (ieos == 5 ) call calc_muGamma(state%rho, state%Tg,state%mu, state%gamma, pH, pH_tot) + else + if (idust_opacity == 1) state%kappa = calc_kappa_bowen(state%Tdust) + if (update_muGamma) call calc_muGamma(state%rho, state%Tg,state%mu, state%gamma, pH, pH_tot) endif if (itau_alloc == 1) then diff --git a/src/main/wind_equations.f90 b/src/main/wind_equations.f90 index ac0a78922..db79e9431 100644 --- a/src/main/wind_equations.f90 +++ b/src/main/wind_equations.f90 @@ -14,7 +14,7 @@ module wind_equations ! ! :Runtime parameters: None ! -! :Dependencies: dust_formation, eos, options, physcon +! :Dependencies: dim, dust_formation, eos, options, physcon ! implicit none @@ -290,6 +290,7 @@ end subroutine RK4_step_dr subroutine calc_dvT_dr(r, v, T0, Rstar_cgs, Mdot_cgs, mu0, gamma0, alpha, dalpha_dr, Q, dQ_dr, dv_dr, dT_dr, numerator, denominator) !all quantities in cgs use physcon, only:Gg,Rg,pi + use dim, only:update_muGamma use options, only:icooling,ieos use dust_formation, only:calc_muGamma,idust_opacity real, intent(in) :: r, v, T0, mu0, gamma0, alpha, dalpha_dr, Q, dQ_dr, Rstar_cgs, Mdot_cgs @@ -302,7 +303,7 @@ subroutine calc_dvT_dr(r, v, T0, Rstar_cgs, Mdot_cgs, mu0, gamma0, alpha, dalpha T = T0 mu = mu0 gamma = gamma0 - if (idust_opacity == 2) then + if (update_muGamma .or. idust_opacity == 2) then rho_cgs = Mdot_cgs/(4.*pi*r**2*v) call calc_muGamma(rho_cgs, T, mu, gamma, pH, pH_tot) endif diff --git a/src/setup/set_orbit.f90 b/src/setup/set_orbit.f90 new file mode 100644 index 000000000..6940ad2aa --- /dev/null +++ b/src/setup/set_orbit.f90 @@ -0,0 +1,285 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module setorbit +! +! Generic procedure for setting up two body orbits with +! different parameter sets for the orbital elements +! +! The current options are: +! 0) Campbell elements for bound or unbound orbit (aeiOwf) +! 1) Flyby parameters (periapsis, initial separation, argument of periapsis, inclination) +! 2) position and velocity for both bodies + +! While Campbell elements can be used for unbound orbits, they require +! specifying the true anomaly at the start of the simulation. This is +! not always easy to determine, so the flyby option is provided as an +! alternative. There one specifies the initial separation instead, however +! the choice of angles is more restricted +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: infile_utils, physcon, setbinary, setflyby, units +! + +! While Campbell elements can be used for unbound orbits, they require +! specifying the true anomaly at the start of the simulation. This is +! not always easy to determine, so the flyby option is provided as an +! alternative. There one specifies the initial separation instead, however +! the choice of angles is more restricted +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: physcon +! + implicit none + public :: set_orbit + public :: set_defaults_orbit,write_options_orbit,read_options_orbit + public :: orbit_t +! + ! define data types with options needed + ! to setup an orbit + ! + type campbell_elems + character(len=20) :: semi_major_axis ! string because can specific units + real :: e ! eccentricity + real :: i ! inclination + real :: O ! position angle of the ascending node + real :: w ! argument of periapsis + real :: f ! initial true anomaly + end type campbell_elems + + type posvel_elems + real :: x1(3) ! position of body 1 + real :: v1(3) ! velocity of body 1 + real :: x2(3) ! position of body 2 + real :: v2(3) ! velocity of body 2 + end type posvel_elems + + type flyby_elems + character(len=20) :: rp ! pericentre distance in arbitrary units + real :: d ! initial separation + real :: O ! position angle of the ascending node + real :: i ! inclination + end type flyby_elems + + ! + ! generic type handling all options + ! + type orbit_t + integer :: itype + type(campbell_elems) :: elems + type(flyby_elems) :: flyby + type(posvel_elems) :: posvel + end type orbit_t + + private + +contains + +!---------------------------------------------------------------- +!+ +! default parameters for orbit type +!+ +!---------------------------------------------------------------- +subroutine set_defaults_orbit(orbit) + type(orbit_t), intent(out) :: orbit + + orbit%itype = 0 + orbit%elems%semi_major_axis = '10.' + orbit%elems%e = 0.0 + orbit%elems%i = 0.0 + orbit%elems%O = 0.0 + orbit%elems%w = 270. ! argument of periapsis + orbit%elems%f = 180. ! start orbit at apocentre + + orbit%flyby%rp = '10.' + orbit%flyby%d = 100.0 + orbit%flyby%O = 0.0 + orbit%flyby%i = 0.0 + + orbit%posvel%x1 = 0.0 + orbit%posvel%v1 = 0.0 + orbit%posvel%x2 = 0.0 + orbit%posvel%v2 = 0.0 + orbit%posvel%x1(1) = 10.0 + orbit%posvel%x2(1) = -10.0 + orbit%posvel%v1(2) = 1.0 + orbit%posvel%v2(2) = -1.0 + +end subroutine set_defaults_orbit + +!---------------------------------------------------------------- +!+ +! setup for two body orbit +!+ +!---------------------------------------------------------------- +subroutine set_orbit(orbit,m1,m2,hacc1,hacc2,xyzmh_ptmass,vxyz_ptmass,nptmass,verbose,ierr,omega_corotate) + use physcon, only:days + use units, only:in_code_units,is_time_unit,utime + use setbinary, only:set_binary,get_a_from_period + use setflyby, only:set_flyby + type(orbit_t), intent(in) :: orbit + real, intent(in) :: m1,m2,hacc1,hacc2 + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + integer, intent(inout) :: nptmass + logical, intent(in) :: verbose + integer, intent(out) :: ierr + real, intent(out), optional :: omega_corotate + real :: rp,a + + ierr = 0 + select case(orbit%itype) + case(2) + ! body 1 + xyzmh_ptmass(1:3,nptmass+1) = orbit%posvel%x1(1:3) + xyzmh_ptmass(4,nptmass+1) = m1 + xyzmh_ptmass(5,nptmass+1) = hacc1 + vxyz_ptmass(1:3,nptmass+1) = orbit%posvel%v1(1:3) + ! body 2 + xyzmh_ptmass(1:3,nptmass+2) = orbit%posvel%x2(1:3) + xyzmh_ptmass(4,nptmass+2) = m2 + xyzmh_ptmass(5,nptmass+2) = hacc2 + vxyz_ptmass(1:3,nptmass+2) = orbit%posvel%v2(1:3) + case(1) + rp = in_code_units(orbit%flyby%rp,ierr) + + call set_flyby(m1,m2,rp,orbit%flyby%d,hacc1,hacc2,xyzmh_ptmass, & + vxyz_ptmass,nptmass,ierr,orbit%flyby%O,orbit%flyby%i,verbose=verbose) + case default + ! + !--if a is negative or is given time units, interpret this as a period + ! + a = in_code_units(orbit%elems%semi_major_axis,ierr) + if (is_time_unit(orbit%elems%semi_major_axis) .and. ierr == 0) then + a = -abs(a) + print "(a,g0,a,g0,a)",' Using PERIOD = ',abs(a),' = ',abs(a)*utime/days,' days' + endif + if (a < 0.) a = get_a_from_period(m1,m2,abs(a)) + ! + !--now setup orbit using sink particles + ! + if (present(omega_corotate)) then + call set_binary(m1,m2,a,orbit%elems%e,hacc1,hacc2,& + xyzmh_ptmass,vxyz_ptmass,nptmass,ierr,omega_corotate,& + posang_ascnode=orbit%elems%O,arg_peri=orbit%elems%w,& + incl=orbit%elems%i,f=orbit%elems%f,verbose=verbose) + else + call set_binary(m1,m2,a,orbit%elems%e,hacc1,hacc2,& + xyzmh_ptmass,vxyz_ptmass,nptmass,ierr,& + posang_ascnode=orbit%elems%O,arg_peri=orbit%elems%w,& + incl=orbit%elems%i,f=orbit%elems%f,verbose=verbose) + endif + end select + +end subroutine set_orbit + +!---------------------------------------------------------------- +!+ +! write options to .setup file +!+ +!---------------------------------------------------------------- +subroutine write_options_orbit(orbit,iunit,label) + use infile_utils, only:write_inopt + type(orbit_t), intent(in) :: orbit + integer, intent(in) :: iunit + character(len=*), intent(in), optional :: label + character(len=10) :: c + + ! append optional label e.g. '1', '2' + c = '' + if (present(label)) c = trim(adjustl(label)) + + write(iunit,"(/,a)") '# orbit '//trim(c) + call write_inopt(orbit%itype,'itype'//trim(c),'type of orbital elements (0=aeiOwf,1=flyby,2=posvel)',iunit) + select case(orbit%itype) + case(2) + call write_inopt(orbit%posvel%x1(1),'x1'//trim(c),'x position body 1',iunit) + call write_inopt(orbit%posvel%x1(2),'y1'//trim(c),'y position body 1',iunit) + call write_inopt(orbit%posvel%x1(3),'z1'//trim(c),'z position body 1',iunit) + call write_inopt(orbit%posvel%v1(1),'vx1'//trim(c),'x velocity body 1',iunit) + call write_inopt(orbit%posvel%v1(2),'vy1'//trim(c),'y velocity body 1',iunit) + call write_inopt(orbit%posvel%v1(3),'vz1'//trim(c),'z velocity body 1',iunit) + call write_inopt(orbit%posvel%x2(1),'x2'//trim(c),'x position body 2',iunit) + call write_inopt(orbit%posvel%x2(2),'y2'//trim(c),'y position body 2',iunit) + call write_inopt(orbit%posvel%x2(3),'z2'//trim(c),'z position body 2',iunit) + call write_inopt(orbit%posvel%v2(1),'vx2'//trim(c),'x velocity body 2',iunit) + call write_inopt(orbit%posvel%v2(2),'vy2'//trim(c),'y velocity body 2',iunit) + call write_inopt(orbit%posvel%v2(3),'vz2'//trim(c),'z velocity body 2',iunit) + case(1) + call write_inopt(orbit%flyby%rp,'rp'//trim(c),'pericentre distance',iunit) + call write_inopt(orbit%flyby%d,'d'//trim(c),'initial separation [same units as rp]',iunit) + call write_inopt(orbit%flyby%O,'O'//trim(c),'position angle of the ascending node',iunit) + call write_inopt(orbit%flyby%i,'i'//trim(c),'inclination',iunit) + case default + call write_inopt(orbit%elems%semi_major_axis,'a'//trim(c),& + 'semi-major axis (e.g. 1 au), period (e.g. 10*days) or rp if e=1',iunit) + call write_inopt(orbit%elems%e,'ecc'//trim(c),'eccentricity',iunit) + call write_inopt(orbit%elems%i,'inc'//trim(c),'inclination (deg)',iunit) + call write_inopt(orbit%elems%O,'O'//trim(c),'position angle of ascending node (deg)',iunit) + call write_inopt(orbit%elems%w,'w'//trim(c),'argument of periapsis (deg)',iunit) + call write_inopt(orbit%elems%f,'f'//trim(c),'initial true anomaly (180=apoastron)',iunit) + end select + +end subroutine write_options_orbit + +!---------------------------------------------------------------- +!+ +! read options from .setup file +!+ +!---------------------------------------------------------------- +subroutine read_options_orbit(orbit,db,nerr,label) + use infile_utils, only:inopts,read_inopt + type(orbit_t), intent(out) :: orbit + type(inopts), allocatable, intent(inout) :: db(:) + integer, intent(inout) :: nerr + character(len=*), intent(in), optional :: label + character(len=10) :: c + + ! append optional label e.g. '1', '2' + c = '' + if (present(label)) c = trim(adjustl(label)) + + call read_inopt(orbit%itype,'itype'//trim(c),db,errcount=nerr,min=0,max=2) + select case(orbit%itype) + case(2) + call read_inopt(orbit%posvel%x1(1),'x1'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%x1(2),'y1'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%x1(3),'z1'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%v1(1),'vx1'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%v1(2),'vy1'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%v1(3),'vz1'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%x2(1),'x2'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%x2(2),'y2'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%x2(3),'z2'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%v2(1),'vx2'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%v2(2),'vy2'//trim(c),db,errcount=nerr) + call read_inopt(orbit%posvel%v2(3),'vz2'//trim(c),db,errcount=nerr) + case(1) + call read_inopt(orbit%flyby%rp,'rp'//trim(c),db,errcount=nerr) + call read_inopt(orbit%flyby%d,'d'//trim(c),db,errcount=nerr) + call read_inopt(orbit%flyby%O,'O'//trim(c),db,errcount=nerr) + call read_inopt(orbit%flyby%i,'i'//trim(c),db,errcount=nerr) + case default + call read_inopt(orbit%elems%semi_major_axis,'a'//trim(c),db,errcount=nerr) + call read_inopt(orbit%elems%e,'ecc'//trim(c),db,min=0.,errcount=nerr) + call read_inopt(orbit%elems%i,'inc'//trim(c),db,errcount=nerr) + call read_inopt(orbit%elems%O,'O'//trim(c),db,errcount=nerr) + call read_inopt(orbit%elems%w,'w'//trim(c),db,errcount=nerr) + call read_inopt(orbit%elems%f,'f'//trim(c),db,errcount=nerr) + end select + +end subroutine read_options_orbit + +end module setorbit From e9e5bba8a8c23258677f5bdf9dad1c6c0cd4afda Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 24 Jun 2024 15:35:23 +0100 Subject: [PATCH 121/182] Merged Phantom upstream updates --- src/main/cooling_radapprox.f90 | 1 - src/main/deriv.F90 | 1 - src/main/energies.F90 | 451 +++++++++++++++++++-------------- src/main/ptmass_radiation.f90 | 102 ++++---- src/main/step_leapfrog.F90 | 6 +- 5 files changed, 311 insertions(+), 250 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index b7ea939e4..95217989d 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -84,7 +84,6 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) write (filename, 11) dt 11 format("coolrate_", E7.2,".dat") - print *, "In cooling" ratefile = 34 open(unit=ratefile,file=filename,status="replace",form="formatted") !$omp parallel do default(none) schedule(runtime) & diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index c66d27e5c..0294d04f8 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -185,7 +185,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& ! ! update energy if using radiative cooling approx (icooling=9) ! - print *, "min,max energy", minval(vxyzu(4,1:npart)), maxval(vxyzu(4,1:npart)) if (icooling == 9 .and. dt > 0.0 .and. icall==1) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) ! diff --git a/src/main/energies.F90 b/src/main/energies.F90 index d71e70db1..eec6576a3 100644 --- a/src/main/energies.F90 +++ b/src/main/energies.F90 @@ -18,19 +18,20 @@ module energies ! ! :Dependencies: boundary_dyn, centreofmass, dim, dust, eos, eos_piecewise, ! externalforces, gravwaveutils, io, kernel, metric_tools, mpiutils, -! nicil, options, part, ptmass, timestep, units, utils_gr, vectorutils, -! viscosity +! nicil, options, part, ptmass, subgroup, timestep, units, utils_gr, +! vectorutils, viscosity ! use dim, only:maxdusttypes,maxdustsmall use units, only:utime implicit none logical, public :: gas_only,track_mass,track_lum - real, public :: ekin,etherm,emag,epot,etot,totmom,angtot,mtot,xyzcom(3) + real, public :: ekin,etherm,emag,epot,etot,eacc,totmom,angtot,mtot,xyzcom(3) + real, public :: ekinacc,ethermacc,emagacc,epotacc,eradacc,etotall real, public :: hdivBonB_ave,hdivBonB_max real, public :: vrms,rmsmach,accretedmass,mdust(maxdusttypes),mgas - real, public :: xmom,ymom,zmom - real, public :: totlum + real, public :: xcom,ycom,zcom,xmom,ymom,zmom,angx,angy,angz + real, public :: totlum,angxall,angyall,angzall,angall real, public :: hx(4),hp(4),ddq_xy(3,3) integer, public :: iquantities integer(kind=8), public :: ndead,npartall,np_cs_eq_0,np_e_eq_0 @@ -71,7 +72,7 @@ subroutine compute_energies(t) isdead_or_accreted,epot_sinksink,imacc,ispinx,ispiny,& ispinz,mhd,gravity,poten,dustfrac,eos_vars,itemp,igasP,ics,& nden_nimhd,eta_nimhd,iion,ndustsmall,graindens,grainsize,& - iamdust,ndusttypes,rad,iradxi + iamdust,ndusttypes,rad,iradxi,gtgrad,group_info,n_group use part, only:pxyzu,fxyzu,fext use gravwaveutils, only:calculate_strain,calc_gravitwaves use centreofmass, only:get_centreofmass_accel @@ -81,7 +82,8 @@ subroutine compute_energies(t) use externalforces, only:externalforce,externalforce_vdependent,was_accreted,accradius1 use options, only:iexternalforce,calc_erot,alpha,ieos,use_dustfrac use mpiutils, only:reduceall_mpi - use ptmass, only:get_accel_sink_gas + use ptmass, only:get_accel_sink_gas,use_regnbody + use subgroup, only:get_pot_subsys use viscosity, only:irealvisc,shearfunc use nicil, only:nicil_update_nimhd,nicil_get_halldrift,nicil_get_ambidrift, & use_ohm,use_hall,use_ambi,n_data_out,n_warn,eta_constant @@ -97,10 +99,10 @@ subroutine compute_energies(t) real, intent(in) :: t integer :: iregime,idusttype,ierr real :: ev_data_thread(4,0:inumev) - real :: xi,yi,zi,hi,vxi,vyi,vzi,v2i,Bxi,Byi,Bzi,Bi,B2i,rhoi,angx,angy,angz - real :: xmomacc,ymomacc,zmomacc,angaccx,angaccy,angaccz,xcom,ycom,zcom,dm + real :: xi,yi,zi,hi,vxi,vyi,vzi,v2i,Bxi,Byi,Bzi,Bi,B2i,rhoi + real :: xmomacc,ymomacc,zmomacc,angaccx,angaccy,angaccz,dm real :: epoti,pmassi,dnptot,dnpgas,tsi - real :: xmomall,ymomall,zmomall,angxall,angyall,angzall,rho1i,vsigi + real :: xmomall,ymomall,zmomall,rho1i,vsigi real :: ponrhoi,spsoundi,dumx,dumy,dumz,gammai real :: divBi,hdivBonBi,alphai,valfven2i,betai real :: n_total,n_total1,n_ion,shearparam_art,shearparam_phys,ratio_phys_to_av @@ -108,13 +110,13 @@ subroutine compute_energies(t) real :: etaohm,etahall,etaambi,vhall,vion real :: curlBi(3),vhalli(3),vioni(3),data_out(n_data_out) real :: erotxi,erotyi,erotzi,fdum(3),x0(3),v0(3),a0(3),xyz_x_all(3),xyz_n_all(3) - real :: ethermi + real :: ekini,ethermi,epottmpi,eradi,emagi real :: pdotv,bigvi(1:3),alpha_gr,beta_gr_UP(1:3),lorentzi,pxi,pyi,pzi real :: gammaijdown(1:3,1:3),angi(1:3),fourvel_space(3) integer :: i,j,itype,iu integer :: ierrlist(n_warn) integer(kind=8) :: np,npgas,nptot,np_rho(maxtypes),np_rho_thread(maxtypes) - !real, allocatable :: axyz(:,:) + logical :: was_not_accreted ! initialise values itype = igas @@ -148,6 +150,11 @@ subroutine compute_energies(t) angaccx = 0. angaccy = 0. angaccz = 0. + ekinacc = 0. + ethermacc = 0. + emagacc = 0. + epotacc = 0. + eradacc = 0. mgas = 0. mdust = 0. mgas = 0. @@ -177,20 +184,22 @@ subroutine compute_energies(t) !$omp shared(iev_dtg,iev_ts,iev_macc,iev_totlum,iev_erot,iev_viscrat) & !$omp shared(eos_vars,grainsize,graindens,ndustsmall,metrics) & !$omp private(i,j,xi,yi,zi,hi,rhoi,vxi,vyi,vzi,Bxi,Byi,Bzi,Bi,B2i,epoti,vsigi,v2i) & -!$omp private(ponrhoi,spsoundi,gammai,ethermi,dumx,dumy,dumz,valfven2i,divBi,hdivBonBi,curlBi) & +!$omp private(ponrhoi,spsoundi,gammai,dumx,dumy,dumz,valfven2i,divBi,hdivBonBi,curlBi) & !$omp private(rho1i,shearparam_art,shearparam_phys,ratio_phys_to_av,betai) & !$omp private(gasfrac,rhogasi,dustfracisum,dustfraci,dust_to_gas,n_total,n_total1,n_ion) & !$omp private(etaohm,etahall,etaambi,vhalli,vhall,vioni,vion,data_out) & +!$omp private(ekini,ethermi,emagi,eradi,epottmpi) & !$omp private(erotxi,erotyi,erotzi,fdum) & !$omp private(ev_data_thread,np_rho_thread) & !$omp firstprivate(alphai,itype,pmassi) & !$omp private(pxi,pyi,pzi,gammaijdown,alpha_gr,beta_gr_UP,bigvi,lorentzi,pdotv,angi,fourvel_space) & !$omp shared(idrag) & -!$omp private(tsi,iregime,idusttype) & +!$omp private(tsi,iregime,idusttype,was_not_accreted) & !$omp shared(luminosity,track_lum) & !$omp reduction(+:np,npgas,np_cs_eq_0,np_e_eq_0) & !$omp reduction(+:xcom,ycom,zcom,mtot,xmom,ymom,zmom,angx,angy,angz,mdust,mgas) & !$omp reduction(+:xmomacc,ymomacc,zmomacc,angaccx,angaccy,angaccz) & +!$omp reduction(+:ekinacc,ethermacc,emagacc,epotacc,eradacc) & !$omp reduction(+:ekin,etherm,emag,epot,erad,vrms,rmsmach,ierrlist) call initialise_ev_data(ev_data_thread) np_rho_thread = 0 @@ -200,7 +209,8 @@ subroutine compute_energies(t) yi = xyzh(2,i) zi = xyzh(3,i) hi = xyzh(4,i) - if (.not.isdead_or_accreted(hi)) then + was_not_accreted = .not.was_accreted(iexternalforce,hi) + if (.not.isdead_or_accreted(hi) .or. .not. was_not_accreted) then if (maxphase==maxp) then itype = iamtype(iphase(i)) if (itype <= 0) call fatal('energies','particle type <= 0') @@ -208,32 +218,33 @@ subroutine compute_energies(t) endif rhoi = rhoh(hi,pmassi) - call ev_data_update(ev_data_thread,iev_rho,rhoi) - if (.not.gas_only) then - select case(itype) - case(igas) - call ev_data_update(ev_data_thread,iev_rhop(1), rhoi) - np_rho_thread(igas) = np_rho_thread(igas) + 1 - case(idust) - call ev_data_update(ev_data_thread,iev_rhop(2),rhoi) - np_rho_thread(idust) = np_rho_thread(idust) + 1 - case(iboundary) - call ev_data_update(ev_data_thread,iev_rhop(3), rhoi) - np_rho_thread(iboundary) = np_rho_thread(iboundary) + 1 - case(istar) - call ev_data_update(ev_data_thread,iev_rhop(4),rhoi) - np_rho_thread(istar) = np_rho_thread(istar) + 1 - case(idarkmatter) - call ev_data_update(ev_data_thread,iev_rhop(5), rhoi) - np_rho_thread(idarkmatter) = np_rho_thread(idarkmatter) + 1 - case(ibulge) - call ev_data_update(ev_data_thread,iev_rhop(6), rhoi) - np_rho_thread(ibulge) = np_rho_thread(ibulge) + 1 - end select + if (was_not_accreted) then + call ev_data_update(ev_data_thread,iev_rho,rhoi) + if (.not.gas_only) then + select case(itype) + case(igas) + call ev_data_update(ev_data_thread,iev_rhop(1), rhoi) + np_rho_thread(igas) = np_rho_thread(igas) + 1 + case(idust) + call ev_data_update(ev_data_thread,iev_rhop(2),rhoi) + np_rho_thread(idust) = np_rho_thread(idust) + 1 + case(iboundary) + call ev_data_update(ev_data_thread,iev_rhop(3), rhoi) + np_rho_thread(iboundary) = np_rho_thread(iboundary) + 1 + case(istar) + call ev_data_update(ev_data_thread,iev_rhop(4),rhoi) + np_rho_thread(istar) = np_rho_thread(istar) + 1 + case(idarkmatter) + call ev_data_update(ev_data_thread,iev_rhop(5), rhoi) + np_rho_thread(idarkmatter) = np_rho_thread(idarkmatter) + 1 + case(ibulge) + call ev_data_update(ev_data_thread,iev_rhop(6), rhoi) + np_rho_thread(ibulge) = np_rho_thread(ibulge) + 1 + end select + endif + np = np + 1 endif - np = np + 1 - vxi = vxyzu(1,i) vyi = vxyzu(2,i) vzi = vxyzu(3,i) @@ -243,11 +254,6 @@ subroutine compute_energies(t) pyi = pxyzu(2,i) pzi = pxyzu(3,i) - ! linear momentum - xmom = xmom + pmassi*pxi - ymom = ymom + pmassi*pyi - zmom = zmom + pmassi*pzi - call unpack_metric(metrics(:,:,:,i),betaUP=beta_gr_UP,alpha=alpha_gr,gammaijdown=gammaijdown) bigvi = (vxyzu(1:3,i)+beta_gr_UP)/alpha_gr v2i = dot_product_gr(bigvi,bigvi,gammaijdown) @@ -257,99 +263,142 @@ subroutine compute_energies(t) ! angular momentum fourvel_space = (lorentzi/alpha_gr)*vxyzu(1:3,i) call cross_product3D(xyzh(1:3,i),fourvel_space,angi) ! position cross with four-velocity - angx = angx + pmassi*angi(1) - angy = angy + pmassi*angi(2) - angz = angz + pmassi*angi(3) ! kinetic energy - ekin = ekin + pmassi*(pdotv + alpha_gr/lorentzi - 1.) ! The 'kinetic term' in total specific energy, minus rest mass - mtot = mtot + pmassi + ekini = pmassi*(pdotv + alpha_gr/lorentzi - 1.) ! The 'kinetic term' in total specific energy, minus rest mass else + pxi = vxi + pyi = vyi + pzi = vzi + ! centre of mass xcom = xcom + pmassi*xi ycom = ycom + pmassi*yi zcom = zcom + pmassi*zi + + ! angular momentum + angi(1) = (yi*vzi - zi*vyi) + angi(2) = (zi*vxi - xi*vzi) + angi(3) = (xi*vyi - yi*vxi) + + ! kinetic energy and rms velocity + v2i = vxi*vxi + vyi*vyi + vzi*vzi + ekini = pmassi*v2i + endif + + if (was_not_accreted) then + ! total mass mtot = mtot + pmassi ! linear momentum - xmom = xmom + pmassi*vxi - ymom = ymom + pmassi*vyi - zmom = zmom + pmassi*vzi + xmom = xmom + pmassi*pxi + ymom = ymom + pmassi*pyi + zmom = zmom + pmassi*pzi ! angular momentum - angx = angx + pmassi*(yi*vzi - zi*vyi) - angy = angy + pmassi*(zi*vxi - xi*vzi) - angz = angz + pmassi*(xi*vyi - yi*vxi) + angx = angx + pmassi*angi(1) + angy = angy + pmassi*angi(2) + angz = angz + pmassi*angi(3) ! kinetic energy & rms velocity - v2i = vxi*vxi + vyi*vyi + vzi*vzi - ekin = ekin + pmassi*v2i - endif + ekin = ekin + ekini + vrms = vrms + v2i + else + call ev_data_update(ev_data_thread,iev_macc,pmassi) - vrms = vrms + v2i + ! linear momentum (accreted particles) + xmomacc = xmomacc + pmassi*pxi + ymomacc = ymomacc + pmassi*pyi + zmomacc = zmomacc + pmassi*pzi + + ! angular momentum (accreted particles) + angaccx = angaccx + pmassi*angi(1) + angaccy = angaccy + pmassi*angi(2) + angaccz = angaccz + pmassi*angi(3) + + ! kinetic energy (accreted particles + ekinacc = ekinacc + ekini + endif ! rotational energy around each axis through the Centre of mass ! note: for efficiency, centre of mass is from the previous time energies was called - if (calc_erot) then + if (calc_erot .and. was_not_accreted) then call get_erot(xi,yi,zi,vxi,vyi,vzi,xyzcom,pmassi,erotxi,erotyi,erotzi) call ev_data_update(ev_data_thread,iev_erot(1),erotxi) call ev_data_update(ev_data_thread,iev_erot(2),erotyi) call ev_data_update(ev_data_thread,iev_erot(3),erotzi) endif - if (iexternalforce > 0) then + ! potential energy + epoti = 0. + if (iexternalforce > 0 .and. .not.gr) then dumx = 0. dumy = 0. dumz = 0. -#ifdef GR - epoti = 0. -#else - call externalforce(iexternalforce,xi,yi,zi,hi,t,dumx,dumy,dumz,epoti,ii=i) - call externalforce_vdependent(iexternalforce,xyzh(1:3,i),vxyzu(1:3,i),fdum,epoti) -#endif - epot = epot + pmassi*epoti + epottmpi = 0. + call externalforce(iexternalforce,xi,yi,zi,hi,t,dumx,dumy,dumz,epottmpi,ii=i) + call externalforce_vdependent(iexternalforce,xyzh(1:3,i),vxyzu(1:3,i),fdum,epottmpi) + epoti = pmassi*epottmpi endif if (nptmass > 0) then dumx = 0. dumy = 0. dumz = 0. - call get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,dumx,dumy,dumz,epoti) - epot = epot + pmassi*epoti + epottmpi = 0. + call get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,dumx,dumy,dumz,epottmpi) + epoti = epoti + pmassi*epottmpi + endif + if (gravity) epoti = epoti + poten(i) + if (was_not_accreted) then + epot = epot + epoti + else + epotacc = epotacc + epoti endif - if (gravity) epot = epot + poten(i) ! ! total dust mass for each species ! - if (use_dust) then + if (use_dust .and. was_not_accreted) then if (iamdust(iphase(i))) then idusttype = ndustsmall + itype - idust + 1 mdust(idusttype) = mdust(idusttype) + pmassi endif endif - if (do_radiation) erad = erad + pmassi*rad(iradxi,i) + if (do_radiation) then + eradi = pmassi*rad(iradxi,i) + if (was_not_accreted) then + erad = erad + eradi + else + eradacc = eradacc + eradi + endif + endif + ! ! the following apply ONLY to gas particles ! isgas: if (itype==igas) then - npgas = npgas + 1 if (use_dustfrac) then dustfraci = dustfrac(:,i) dustfracisum = sum(dustfraci) gasfrac = 1. - dustfracisum dust_to_gas = dustfraci(:)/gasfrac - do j=1,ndustsmall - call ev_data_update(ev_data_thread,iev_dtg,dust_to_gas(j)) - enddo - mdust(1:ndustsmall) = mdust(1:ndustsmall) + pmassi*dustfraci(1:ndustsmall) + if (was_not_accreted) then + do j=1,ndustsmall + call ev_data_update(ev_data_thread,iev_dtg,dust_to_gas(j)) + enddo + mdust(1:ndustsmall) = mdust(1:ndustsmall) + pmassi*dustfraci(1:ndustsmall) + endif else dustfraci = 0. dustfracisum = 0. gasfrac = 1. endif - mgas = mgas + pmassi*gasfrac + if (was_not_accreted) then + npgas = npgas + 1 + mgas = mgas + pmassi*gasfrac + endif ! thermal energy ponrhoi = eos_vars(igasP,i)/rhoi @@ -359,60 +408,70 @@ subroutine compute_energies(t) ethermi = pmassi*vxyzu(4,i)*gasfrac if (gr) ethermi = (alpha_gr/lorentzi)*ethermi - etherm = etherm + ethermi - - if (vxyzu(iu,i) < tiny(vxyzu(iu,i))) np_e_eq_0 = np_e_eq_0 + 1 - if (spsoundi < tiny(spsoundi) .and. vxyzu(iu,i) > 0. ) np_cs_eq_0 = np_cs_eq_0 + 1 + if (was_not_accreted) then + if (vxyzu(iu,i) < tiny(vxyzu(iu,i))) np_e_eq_0 = np_e_eq_0 + 1 + if (spsoundi < tiny(spsoundi) .and. vxyzu(iu,i) > 0. ) np_cs_eq_0 = np_cs_eq_0 + 1 + endif else - if ((ieos==2 .or. ieos == 5) .and. gammai > 1.001) then + if ((ieos==2 .or. ieos == 5 .or. ieos == 17) .and. gammai > 1.001) then !--thermal energy using polytropic equation of state - etherm = etherm + pmassi*ponrhoi/(gammai-1.)*gasfrac + ethermi = pmassi*ponrhoi/(gammai-1.)*gasfrac elseif (ieos==9) then !--thermal energy using piecewise polytropic equation of state - etherm = etherm + pmassi*ponrhoi/(gamma_pwp(rhoi)-1.)*gasfrac + ethermi = pmassi*ponrhoi/(gamma_pwp(rhoi)-1.)*gasfrac + else + ethermi = 0. endif - if (spsoundi < tiny(spsoundi)) np_cs_eq_0 = np_cs_eq_0 + 1 + if (spsoundi < tiny(spsoundi) .and. was_not_accreted) np_cs_eq_0 = np_cs_eq_0 + 1 endif vsigi = spsoundi - ! entropy - call ev_data_update(ev_data_thread,iev_entrop,pmassi*ponrhoi*rhoi**(1.-gammai)) - - ! gas temperature - if (eos_is_non_ideal(ieos) .or. eos_outputs_gasP(ieos)) then - call ev_data_update(ev_data_thread,iev_temp,eos_vars(itemp,i)) + if (was_not_accreted) then + etherm = etherm + ethermi + else + ethermacc = ethermacc + ethermi endif - ! min and mean stopping time - if (use_dustfrac) then - rhogasi = rhoi*gasfrac - do j=1,ndustsmall - call get_ts(idrag,j,grainsize(j),graindens(j),rhogasi,rhoi*dustfracisum,spsoundi,0.,tsi,iregime) - call ev_data_update(ev_data_thread,iev_ts,tsi) - enddo - endif + if (was_not_accreted) then + ! entropy + call ev_data_update(ev_data_thread,iev_entrop,pmassi*ponrhoi*rhoi**(1.-gammai)) - if (track_lum .and. lightcurve) call ev_data_update(ev_data_thread,iev_totlum,real(luminosity(i))) + ! gas temperature + if (eos_is_non_ideal(ieos) .or. eos_outputs_gasP(ieos)) then + call ev_data_update(ev_data_thread,iev_temp,eos_vars(itemp,i)) + endif - ! rms mach number - if (spsoundi > 0.) rmsmach = rmsmach + v2i/spsoundi**2 + ! min and mean stopping time + if (use_dustfrac) then + rhogasi = rhoi*gasfrac + do j=1,ndustsmall + call get_ts(idrag,j,grainsize(j),graindens(j),rhogasi,rhoi*dustfracisum,spsoundi,0.,tsi,iregime) + call ev_data_update(ev_data_thread,iev_ts,tsi) + enddo + endif - ! max of dissipation parameters - if (maxalpha==maxp) then - alphai = alphaind(1,i) - call ev_data_update(ev_data_thread,iev_alpha,alphai) - endif + if (track_lum .and. lightcurve) call ev_data_update(ev_data_thread,iev_totlum,real(luminosity(i))) - ! physical viscosity - if (irealvisc /= 0) then - shearparam_art = 0.1*alphai*hi*vsigi - shearparam_phys = shearfunc(xi,yi,zi,spsoundi) - if (shearparam_art > 0.) then - ratio_phys_to_av = shearparam_phys/shearparam_art - else - ratio_phys_to_av = 0. + ! rms mach number + if (spsoundi > 0.) rmsmach = rmsmach + v2i/spsoundi**2 + + ! max of dissipation parameters + if (maxalpha==maxp) then + alphai = alphaind(1,i) + call ev_data_update(ev_data_thread,iev_alpha,alphai) + endif + + ! physical viscosity + if (irealvisc /= 0) then + shearparam_art = 0.1*alphai*hi*vsigi + shearparam_phys = shearfunc(xi,yi,zi,spsoundi) + if (shearparam_art > 0.) then + ratio_phys_to_av = shearparam_phys/shearparam_art + else + ratio_phys_to_av = 0. + endif + call ev_data_update(ev_data_thread,iev_viscrat,ratio_phys_to_av) endif - call ev_data_update(ev_data_thread,iev_viscrat,ratio_phys_to_av) endif ! mhd parameters @@ -425,88 +484,70 @@ subroutine compute_energies(t) rho1i = 1./rhoi valfven2i = B2i*rho1i vsigi = sqrt(valfven2i + spsoundi*spsoundi) - emag = emag + pmassi*B2i*rho1i - - divBi = abs(divcurlB(1,i)) - if (B2i > 0.) then - hdivBonBi = hi*divBi/Bi - betai = 2.0*ponrhoi*rhoi/B2i ! plasma beta - else - hdivBonBi = 0. - betai = 0. - endif - call ev_data_update(ev_data_thread,iev_B, Bi ) - call ev_data_update(ev_data_thread,iev_divB, divBi ) - call ev_data_update(ev_data_thread,iev_hdivB,hdivBonBi) - call ev_data_update(ev_data_thread,iev_beta, betai ) + emagi = pmassi*B2i*rho1i + + if (was_not_accreted) then + emag = emag + emagi + divBi = abs(divcurlB(1,i)) + if (B2i > 0.) then + hdivBonBi = hi*divBi/Bi + betai = 2.0*ponrhoi*rhoi/B2i ! plasma beta + else + hdivBonBi = 0. + betai = 0. + endif + call ev_data_update(ev_data_thread,iev_B, Bi ) + call ev_data_update(ev_data_thread,iev_divB, divBi ) + call ev_data_update(ev_data_thread,iev_hdivB,hdivBonBi) + call ev_data_update(ev_data_thread,iev_beta, betai ) - if ( mhd_nonideal ) then - call nicil_update_nimhd(0,etaohm,etahall,etaambi,Bi,rhoi, & + if ( mhd_nonideal ) then + call nicil_update_nimhd(0,etaohm,etahall,etaambi,Bi,rhoi, & eos_vars(itemp,i),nden_nimhd(:,i),ierrlist,data_out) - curlBi = divcurlB(2:4,i) - if (use_ohm) then - call ev_data_update(ev_data_thread,iev_etao, etaohm ) - endif - if (use_hall) then - call nicil_get_halldrift(etahall,Bxi,Byi,Bzi,curlBi,vhalli) - vhall = sqrt( dot_product(vhalli,vhalli) ) - call ev_data_update(ev_data_thread,iev_etah(1),etahall ) - call ev_data_update(ev_data_thread,iev_etah(2),abs(etahall)) - call ev_data_update(ev_data_thread,iev_vhall ,vhall ) - endif - if (use_ambi) then - call nicil_get_ambidrift(etaambi,Bxi,Byi,Bzi,curlBi,vioni) - vion = sqrt( dot_product(vioni, vioni ) ) - call ev_data_update(ev_data_thread,iev_etaa, etaambi ) - call ev_data_update(ev_data_thread,iev_vel, sqrt(v2i) ) - call ev_data_update(ev_data_thread,iev_vion, vion ) - endif - if (.not.eta_constant) then - n_ion = 0 - do j = 9,21 - n_ion = n_ion + data_out(j) - enddo - n_total = data_out(5) - if (n_total > 0.) then - n_total1 = 1.0/n_total - else - n_total1 = 0.0 ! only possible if eta_constant = .true. + curlBi = divcurlB(2:4,i) + if (use_ohm) then + call ev_data_update(ev_data_thread,iev_etao, etaohm ) + endif + if (use_hall) then + call nicil_get_halldrift(etahall,Bxi,Byi,Bzi,curlBi,vhalli) + vhall = sqrt( dot_product(vhalli,vhalli) ) + call ev_data_update(ev_data_thread,iev_etah(1),etahall ) + call ev_data_update(ev_data_thread,iev_etah(2),abs(etahall)) + call ev_data_update(ev_data_thread,iev_vhall ,vhall ) + endif + if (use_ambi) then + call nicil_get_ambidrift(etaambi,Bxi,Byi,Bzi,curlBi,vioni) + vion = sqrt( dot_product(vioni, vioni ) ) + call ev_data_update(ev_data_thread,iev_etaa, etaambi ) + call ev_data_update(ev_data_thread,iev_vel, sqrt(v2i) ) + call ev_data_update(ev_data_thread,iev_vion, vion ) + endif + if (.not.eta_constant) then + n_ion = 0 + do j = 9,21 + n_ion = n_ion + data_out(j) + enddo + n_total = data_out(5) + if (n_total > 0.) then + n_total1 = 1.0/n_total + else + n_total1 = 0.0 ! only possible if eta_constant = .true. + endif + eta_nimhd(iion,i) = n_ion*n_total1 ! Save ionisation fraction for the dump file + call ev_data_update(ev_data_thread,iev_n(1),n_ion*n_total1) + call ev_data_update(ev_data_thread,iev_n(2),data_out( 8)*n_total1) + call ev_data_update(ev_data_thread,iev_n(3),data_out( 8)) + call ev_data_update(ev_data_thread,iev_n(4),n_total-n_ion) + call ev_data_update(ev_data_thread,iev_n(5),data_out(24)) + call ev_data_update(ev_data_thread,iev_n(6),data_out(23)) + call ev_data_update(ev_data_thread,iev_n(7),data_out(22)) endif - eta_nimhd(iion,i) = n_ion*n_total1 ! Save ionisation fraction for the dump file - call ev_data_update(ev_data_thread,iev_n(1),n_ion*n_total1) - call ev_data_update(ev_data_thread,iev_n(2),data_out( 8)*n_total1) - call ev_data_update(ev_data_thread,iev_n(3),data_out( 8)) - call ev_data_update(ev_data_thread,iev_n(4),n_total-n_ion) - call ev_data_update(ev_data_thread,iev_n(5),data_out(24)) - call ev_data_update(ev_data_thread,iev_n(6),data_out(23)) - call ev_data_update(ev_data_thread,iev_n(7),data_out(22)) endif + else + emagacc = emagacc + emagi endif endif endif isgas - - elseif (was_accreted(iexternalforce,hi)) then -! -!--count accretion onto fixed potentials (external forces) separately -! - vxi = vxyzu(1,i) - vyi = vxyzu(2,i) - vzi = vxyzu(3,i) - if (maxphase==maxp) then - pmassi = massoftype(iamtype(iphase(i))) - else - pmassi = massoftype(igas) - endif - xmomacc = xmomacc + pmassi*vxi - ymomacc = ymomacc + pmassi*vyi - zmomacc = zmomacc + pmassi*vzi - - angaccx = angaccx + pmassi*(yi*vzi - zi*vyi) - angaccy = angaccy + pmassi*(zi*vxi - xi*vzi) - angaccz = angaccz + pmassi*(xi*vyi - yi*vxi) - - call ev_data_update(ev_data_thread,iev_macc,pmassi) - endif enddo !$omp enddo @@ -601,9 +642,15 @@ subroutine compute_energies(t) emag = reduceall_mpi('+',emag) epot = reduceall_mpi('+',epot) erad = reduceall_mpi('+',erad) - if (nptmass > 1) epot = epot + epot_sinksink + if (nptmass > 1) then + if (use_regnbody) then + call get_pot_subsys(n_group,group_info,xyzmh_ptmass,fxyz_ptmass,gtgrad,epot_sinksink) + endif + epot = epot + epot_sinksink + endif etot = ekin + etherm + emag + epot + erad + etotall = etot xcom = reduceall_mpi('+',xcom) ycom = reduceall_mpi('+',ycom) @@ -694,12 +741,24 @@ subroutine compute_energies(t) angxall = angx + angaccx angyall = angy + angaccy angzall = angz + angaccz - ev_data(iev_sum,iev_angall) = sqrt(angxall*angxall + angyall*angyall + angzall*angzall) + angall = sqrt(angxall*angxall + angyall*angyall + angzall*angzall) + ev_data(iev_sum,iev_angall) = angall + + ekinacc = reduceall_mpi('+',ekinacc) + epotacc = reduceall_mpi('+',epotacc) + ethermacc = reduceall_mpi('+',ethermacc) + emagacc = reduceall_mpi('+',emagacc) + eradacc = reduceall_mpi('+',eradacc) + eacc = ekinacc + ethermacc + emagacc + epotacc + eradacc + etotall = etotall + eacc endif if (track_mass) then accretedmass = ev_data(iev_sum,iev_macc) - if (accradius1 > 0.) ev_data(iev_sum,iev_eacc) = accretedmass/accradius1 ! total accretion energy + if (accradius1 > 0.) then + !eacc = accretedmass/accradius1 + ev_data(iev_sum,iev_eacc) = eacc ! total accretion energy + endif endif if (track_lum) totlum = ev_data(iev_sum,iev_totlum) diff --git a/src/main/ptmass_radiation.f90 b/src/main/ptmass_radiation.f90 index 18954ec84..dc175ff8d 100644 --- a/src/main/ptmass_radiation.f90 +++ b/src/main/ptmass_radiation.f90 @@ -58,16 +58,25 @@ end subroutine init_radiation_ptmass ! compute radiative acceleration from ALL sink particles !+ !----------------------------------------------------------------------- -subroutine get_rad_accel_from_ptmass (nptmass,npart,xyzh,xyzmh_ptmass,fext,tau) +subroutine get_rad_accel_from_ptmass (nptmass,npart,i,xi,yi,zi,xyzmh_ptmass,fextx,fexty,fextz,tau,fsink_old,extrapfac) use part, only:ilum use units, only:umass,unit_luminosity - integer, intent(in) :: nptmass,npart - real, intent(in) :: xyzh(:,:) - real, intent(in) :: xyzmh_ptmass(:,:) - real, intent(in), optional :: tau(:) - real, intent(inout) :: fext(:,:) - real :: xa,ya,za,Mstar_cgs,Lstar_cgs + integer, intent(in) :: nptmass,npart,i + real, intent(in) :: xi,yi,zi + real, intent(in) :: xyzmh_ptmass(:,:) + real, optional, intent(in) :: tau(:) + real, intent(inout) :: fextx,fexty,fextz + real, optional, intent(in) :: fsink_old(:,:) + real, optional, intent(in) :: extrapfac + real :: dx,dy,dz,Mstar_cgs,Lstar_cgs integer :: j + logical :: extrap + + if (present(fsink_old)) then + extrap = .true. + else + extrap = .false. + endif do j=1,nptmass if (xyzmh_ptmass(4,j) < 0.) cycle @@ -75,10 +84,16 @@ subroutine get_rad_accel_from_ptmass (nptmass,npart,xyzh,xyzmh_ptmass,fext,tau) Lstar_cgs = xyzmh_ptmass(ilum,j)*unit_luminosity !compute radiative acceleration if sink particle is assigned a non-zero luminosity if (Lstar_cgs > 0.d0) then - xa = xyzmh_ptmass(1,j) - ya = xyzmh_ptmass(2,j) - za = xyzmh_ptmass(3,j) - call calc_rad_accel_from_ptmass(npart,xa,ya,za,Lstar_cgs,Mstar_cgs,xyzh,fext,tau) + if (extrap) then + dx = xi - xyzmh_ptmass(1,j) + extrapfac*fsink_old(1,j) + dy = yi - xyzmh_ptmass(2,j) + extrapfac*fsink_old(2,j) + dz = zi - xyzmh_ptmass(3,j) + extrapfac*fsink_old(3,j) + else + dx = xi - xyzmh_ptmass(1,j) + dy = yi - xyzmh_ptmass(2,j) + dz = zi - xyzmh_ptmass(3,j) + endif + call calc_rad_accel_from_ptmass(npart,i,dx,dy,dz,Lstar_cgs,Mstar_cgs,fextx,fexty,fextz,tau) endif enddo @@ -89,53 +104,40 @@ end subroutine get_rad_accel_from_ptmass ! compute radiative acceleration on all particles !+ !----------------------------------------------------------------------- -subroutine calc_rad_accel_from_ptmass(npart,xa,ya,za,Lstar_cgs,Mstar_cgs,xyzh,fext,tau) +subroutine calc_rad_accel_from_ptmass(npart,i,dx,dy,dz,Lstar_cgs,Mstar_cgs,fextx,fexty,fextz,tau) use part, only:isdead_or_accreted,dust_temp,nucleation,idkappa,idalpha use dim, only:do_nucleation,itau_alloc use dust_formation, only:calc_kappa_bowen - integer, intent(in) :: npart - real, intent(in) :: xyzh(:,:) - real, intent(in), optional :: tau(:) - real, intent(in) :: xa,ya,za,Lstar_cgs,Mstar_cgs - real, intent(inout) :: fext(:,:) - real :: dx,dy,dz,r,ax,ay,az,alpha,kappa - integer :: i - - !$omp parallel do default(none) & - !$omp shared(nucleation,do_nucleation,itau_alloc)& - !$omp shared(dust_temp) & - !$omp shared(npart,xa,ya,za,Mstar_cgs,Lstar_cgs,xyzh,fext,tau) & - !$omp private(i,dx,dy,dz,ax,ay,az,r,alpha,kappa) - do i=1,npart - if (.not.isdead_or_accreted(xyzh(4,i))) then - dx = xyzh(1,i) - xa - dy = xyzh(2,i) - ya - dz = xyzh(3,i) - za - r = sqrt(dx**2 + dy**2 + dz**2) - if (do_nucleation) then - if (itau_alloc == 1) then - call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& + integer, intent(in) :: npart,i + real, optional, intent(in) :: tau(:) + real, intent(in) :: dx,dy,dz,Lstar_cgs,Mstar_cgs + real, intent(inout) :: fextx,fexty,fextz + real :: r,ax,ay,az,alpha,kappa + + + r = sqrt(dx**2 + dy**2 + dz**2) + if (do_nucleation) then + if (itau_alloc == 1) then + call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& nucleation(idkappa,i),ax,ay,az,nucleation(idalpha,i),tau(i)) - else - call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& + else + call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& nucleation(idkappa,i),ax,ay,az,nucleation(idalpha,i)) - endif - else - kappa = calc_kappa_bowen(dust_temp(i)) - if (itau_alloc == 1) then - call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& + endif + else + kappa = calc_kappa_bowen(dust_temp(i)) + if (itau_alloc == 1) then + call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& kappa,ax,ay,az,alpha,tau(i)) - else - call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& + else + call get_radiative_acceleration_from_star(r,dx,dy,dz,Mstar_cgs,Lstar_cgs,& kappa,ax,ay,az,alpha) - endif - endif - fext(1,i) = fext(1,i) + ax - fext(2,i) = fext(2,i) + ay - fext(3,i) = fext(3,i) + az endif - enddo - !$omp end parallel do + endif + fextx = fextx + ax + fexty = fexty + ay + fextz = fextz + az + end subroutine calc_rad_accel_from_ptmass diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 3e78ba2c3..56ec50dc3 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -105,6 +105,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use mpiutils, only:reduceall_mpi use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass, & dsdt_ptmass,fsink_old,ibin_wake,dptmass + use part, only:n_group,n_ingroup,n_sing,gtgrad,group_info,nmatrix use io_summary, only:summary_printout,summary_variable,iosumtvi,iowake, & iosumflrp,iosumflrps,iosumflrc use boundary_dyn, only:dynamic_bdy,update_xyzminmax @@ -250,8 +251,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) 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,fsink_old,nbinmax,ibin_wake) + fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,& + dptmass,fsink_old,nbinmax,ibin_wake,gtgrad,group_info, & + nmatrix,n_group,n_ingroup,n_sing) else call substep_sph(dtsph,npart,xyzh,vxyzu) endif From be3c68555c2707f6ba394a47b0c1c1142456898d Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 25 Jun 2024 17:29:33 +0100 Subject: [PATCH 122/182] fixed bug in cooling_radapprox.f90 (does not skip inactive particles now) --- src/main/cooling_radapprox.f90 | 2 +- src/main/eos.f90 | 28 +- src/main/eos_stamatellos.f90 | 13 +- src/setup/setup_sphere.f90 | 848 +++++++++++++++++++++++++++++++++ 4 files changed, 869 insertions(+), 22 deletions(-) create mode 100644 src/setup/setup_sphere.f90 diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 95217989d..8582e570b 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -94,7 +94,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb) overpart: do i=1,npart - if (.not. iactive(iphase(i)) .or. isdead_or_accreted(xyzh(4,i))) cycle +! if (.not. iactive(iphase(i)) .or. isdead_or_accreted(xyzh(4,i))) cycle poti = Gpot_cool(i) du_FLDi = duFLD(i) ui = energ(i) diff --git a/src/main/eos.f90 b/src/main/eos.f90 index f23945122..a698fe23d 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -12,7 +12,7 @@ module eos ! 2 = adiabatic/polytropic eos ! 3 = eos for a locally isothermal disc as in Lodato & Pringle (2007) ! 4 = GR isothermal -! 5 = polytropic EOS with vary mu and gamma depending on H2 formation +! 5 = polytropic EOS with varying mu and gamma depending on H2 formation ! 6 = eos for a locally isothermal disc as in Lodato & Pringle (2007), ! centered on a sink particle ! 7 = z-dependent locally isothermal eos @@ -25,6 +25,7 @@ module eos ! 14 = locally isothermal prescription from Farris et al. (2014) for binary system ! 15 = Helmholtz free energy eos ! 16 = Shen eos +! 17 = polytropic EOS with varying mu (depending on H2 formation) ! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) ! 21 = read tabulated eos (for use with icooling == 8) ! @@ -162,7 +163,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam spsoundi = sqrt(ponrhoi) tempi = temperature_coef*mui*ponrhoi - case(2,5) + case(2,5,17) ! !--Adiabatic equation of state (code default) ! @@ -440,7 +441,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam ponrhoi = presi/rhoi gammai = 1.d0 + presi/(eni*rhoi) spsoundi = sqrt(gammai*ponrhoi) - + case default spsoundi = 0. ! avoids compiler warnings ponrhoi = 0. @@ -565,9 +566,8 @@ end subroutine init_eos !+ !----------------------------------------------------------------------- subroutine finish_eos(eos_type,ierr) - use eos_mesa, only: finish_eos_mesa - use eos_stamatellos, only: finish_S07cool - + use eos_mesa, only: finish_eos_mesa + use eos_stamatellos, only: finish_S07cool integer, intent(in) :: eos_type integer, intent(out) :: ierr @@ -846,7 +846,7 @@ end subroutine calc_rec_ene ! pressure and density. Inputs and outputs are in cgs units. ! ! Note on composition: -! For ieos=2, 5 and 12, mu_local is an input, X & Z are not used +! For ieos=2, 5, 12 and 17, mu_local is an input, X & Z are not used ! For ieos=10, mu_local is not used ! For ieos=20, mu_local is not used but available as an output !+ @@ -872,7 +872,7 @@ subroutine calc_temp_and_ene(eos_type,rho,pres,ene,temp,ierr,guesseint,mu_local, if (present(X_local)) X = X_local if (present(Z_local)) Z = Z_local select case(eos_type) - case(2,5) ! Ideal gas + case(2,5,17) ! Ideal gas temp = pres / (rho * kb_on_mh) * mu ene = pres / ( (gamma-1.) * rho) case(12) ! Ideal gas + radiation @@ -895,7 +895,7 @@ end subroutine calc_temp_and_ene ! are in cgs units. ! ! Note on composition: -! For ieos=2 and 12, mu_local is an input, X & Z are not used +! For ieos=2, 5, 12 and 17, mu_local is an input, X & Z are not used ! For ieos=10, mu_local is not used ! For ieos=20, mu_local is not used but available as an output !+ @@ -1070,7 +1070,7 @@ subroutine get_p_from_rho_s(ieos,S,rho,mu,P,temp) niter = 0 select case (ieos) - case (2,5) + case (2,5,17) temp = (cgsrho * exp(mu*cgss*mass_proton_cgs))**(2./3.) cgsP = cgsrho*kb_on_mh*temp / mu case (12) @@ -1175,7 +1175,7 @@ subroutine setpolyk(eos_type,iprint,utherm,xyzhi,npart) write(iprint,*) 'WARNING! different utherms but run is isothermal' endif - case(2,5) + case(2,5,17) ! !--adiabatic/polytropic eos ! this routine is ONLY called if utherm is NOT stored, so polyk matters @@ -1332,11 +1332,11 @@ subroutine eosinfo(eos_type,iprint) endif case(3) write(iprint,"(/,a,f10.6,a,f10.6)") ' Locally isothermal eq of state (R_sph): cs^2_0 = ',polyk,' qfac = ',qfacdisc - case(5) + case(5,17) if (maxvxyzu >= 4) then write(iprint,"(' Adiabatic equation of state: P = (gamma-1)*rho*u, where gamma & mu depend on the formation of H2')") else - stop '[stop eos] eos = 5 cannot assume isothermal conditions' + stop '[stop eos] eos = 5,17 cannot assume isothermal conditions' endif case(6) write(iprint,"(/,a,i2,a,f10.6,a,f10.6)") ' Locally (on sink ',isink, & @@ -1528,7 +1528,7 @@ subroutine read_options_eos(name,valstring,imatch,igotall,ierr) read(valstring,*,iostat=ierr) ieos ngot = ngot + 1 if (ieos <= 0 .or. ieos > maxeos) call fatal(label,'equation of state choice out of range') - if (ieos == 5) then + if (ieos == 5 .or. ieos == 17) then store_dust_temperature = .true. update_muGamma = .true. endif diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 9611f9685..5b60a7a86 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -93,14 +93,13 @@ subroutine read_optab(eos_file,ierr) OPTABLE(i,j,4),OPTABLE(i,j,5),OPTABLE(i,j,6) enddo enddo -! print *, 'nx,ny=', nx, ny end subroutine read_optab ! ! Main subroutine for interpolating tables to get EOS values ! subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) - use io, only:fatal + use io, only:warning real, intent(in) :: ui,rhoi real, intent(out) :: kappaBar,kappaPart,Ti,gmwi @@ -118,9 +117,9 @@ 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 - call fatal('getopac_opdep','rhoi out of range',var='rhoi',val=rhoi) + call warning('getopac_opdep','rhoi out of range',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) + call warning('getopac_opdep','ui out of range',var='ui',val=ui) endif if (rhoi < rhomin) then @@ -212,7 +211,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) - use io, only:fatal + use io, only:warning real, intent(out) :: ueqi real, intent(in) :: Teqi,rhoi @@ -222,9 +221,9 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) real rhoi_ if (rhoi > OPTABLE(nx,1,1) .or. rhoi < OPTABLE(1,1,1)) then - call fatal('getintenerg_opdep','rhoi out of range',var='rhoi',val=rhoi) + call warning('getintenerg_opdep','rhoi out of range',var='rhoi',val=rhoi) elseif (Teqi > OPTABLE(1,ny,2) .or. Teqi < OPTABLE(1,1,2)) then - call fatal('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) + call warning('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) endif diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 new file mode 100644 index 000000000..c297a13b5 --- /dev/null +++ b/src/setup/setup_sphere.f90 @@ -0,0 +1,848 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.bitbucket.io/ ! +!--------------------------------------------------------------------------! +module setup +! +! This module sets up a sphere-in-a-box: a cold, dense sphere placed in +! a warm medium; the two media are in pressure-equilibrium. +! This currently works for gas-only and two-fluid dust. +! +! :References: None +! +! :Owner: Alison Young +! +! :Runtime parameters: +! - BEfac : *over-density factor of the BE sphere [code units]* +! - BEmass : *mass radius of the BE sphere [code units]* +! - BErad_norm : *normalised radius of the BE sphere* +! - BErad_phys : *physical radius of the BE sphere [code units]* +! - BErho_cen : *central density of the BE sphere [code units]* +! - Bzero : *Magnetic field strength in Gauss* +! - T_sphere : *temperature in sphere* +! - ang_Bomega : *Angle (degrees) between B and rotation axis* +! - angvel : *angular velocity in rad/s* +! - beta_r : *rotational-to-gravitational energy ratio* +! - density_contrast : *density contrast in code units* +! - dist_unit : *distance unit (e.g. au)* +! - dust_to_gas_ratio : *dust-to-gas ratio* +! - form_binary : *the intent is to form a central binary* +! - graindenscgs : *grain density [g/cm^3]* +! - grainsizecgs : *grain size in [cm]* +! - h_acc : *accretion radius (code units)* +! - h_soft_sinksink : *sink-sink softening radius (code units)* +! - iBE_options : *The set of parameters to define the BE sphere* +! - icreate_sinks : *1: create sinks. 0: do not create sinks* +! - lattice : *particle lattice (random,cubic,closepacked,hcp,hexagonal)* +! - lbox : *length of a box side in terms of spherical radii* +! - mass_unit : *mass unit (e.g. solarm)* +! - masstoflux : *mass-to-magnetic flux ratio in units of critical value* +! - ndusttypes : *number of grain sizes* +! - np : *requested number of particles in sphere* +! - r_crit : *critical radius (code units)* +! - r_sphere : *radius of sphere in code units* +! - rho_final : *final maximum density (<=0 to ignore) (cgs units)* +! - rho_pert_amp : *amplitude of density perturbation* +! - rms_mach : *turbulent rms mach number* +! - shuffle_parts : *relax particles by shuffling* +! - sindex : *power-law index, e.g. MRN* +! - smaxcgs : *maximum grain size [cm]* +! - smincgs : *minimum grain size [cm]* +! - totmass_sphere : *mass of sphere in code units* +! - use_BE_sphere : *centrally condense as a BE sphere* +! +! :Dependencies: boundary, centreofmass, datafiles, dim, dust, eos, +! eos_stamatellos, infile_utils, io, kernel, mpidomain, options, part, +! physcon, prompting, ptmass, set_dust, set_dust_options, setup_params, +! spherical, timestep, unifdis, units, utils_shuffleparticles, velfield +! + use part, only:mhd,graindens,grainsize,ndusttypes,ndustsmall + use dim, only:use_dust,maxvxyzu,periodic,maxdustsmall + use options, only:calc_erot + use dust, only:grainsizecgs,graindenscgs + use set_dust_options, only:grainsizeinp,graindensinp,igrainsize,igraindens,& + smincgs,smaxcgs,sindex,dustbinfrac + implicit none + + public :: setpart + + private + !--private module variables + real :: xmini(3), xmaxi(3) + real :: density_contrast,totmass_sphere,r_sphere,T_sphere,cs_sphere + real :: angvel,beta_r,Bzero_G,masstoflux,dtg,ang_Bomega,rms_mach + real :: rho_pert_amp,lbox + real :: BErho_cen,BErad_phys,BErad_norm,BEmass,BEfac + real :: r_crit_setup,h_acc_setup,h_soft_sinksink_setup,rhofinal_setup + real(kind=8) :: udist,umass + integer :: np,iBEparam,icreate_sinks_setup + logical :: BEsphere,binary,mu_not_B,cs_in_code,angvel_not_betar,shuffle_parts + logical :: is_cube = .true. ! if false, then can set a rectangle if BEsphere=false; for backwards compatibility + character(len=20) :: dist_unit,mass_unit,lattice + character(len= 1), parameter :: labelx(3) = (/'x','y','z'/) + +contains + +!---------------------------------------------------------------- +!+ +! setup for a sphere-in-a-box +!+ +!---------------------------------------------------------------- +subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_out,time,fileprefix) + use physcon, only:pi,solarm,hours,years,au,kboltz,kb_on_mh + use dim, only:maxdusttypes,use_dustgrowth,maxdustlarge + use setup_params, only:rhozero,npart_total,rmax,ihavesetupB + use io, only:master,fatal,iprint + use unifdis, only:set_unifdis + use spherical, only:set_sphere + use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound + use prompting, only:prompt + use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity,unit_ergg + use eos, only:polyk2,ieos,gmw + use eos_stamatellos, only:read_optab,getopac_opdep,optable,getintenerg_opdep,eos_file + use part, only:Bxyz,Bextx,Bexty,Bextz,igas,idust,set_particle_type,hfact,dustfrac + use set_dust_options, only:dustbinfrac,set_dust_default_options,set_dust_interactively,dust_method + use dust, only:ilimitdustflux + use timestep, only:dtmax,tmax,dtmax_dratio,dtmax_min + use centreofmass, only:reset_centreofmass + use options, only:nfulldump,rhofinal_cgs,hdivbbmax_max,use_dustfrac + use kernel, only:hfact_default + use mpidomain, only:i_belong + use ptmass, only:icreate_sinks,r_crit,h_acc,h_soft_sinksink + use velfield, only:set_velfield_from_cubes + use datafiles, only:find_phantom_datafile + use set_dust, only:set_dustfrac,set_dustbinfrac + use utils_shuffleparticles, only:shuffleparticles + integer, intent(in) :: id + integer, intent(inout) :: npart + integer, intent(out) :: npartoftype(:) + real, intent(out) :: xyzh(:,:) + real, intent(out) :: vxyzu(:,:) + real, intent(out) :: massoftype(:) + real, intent(out) :: polyk,gamma,hfact_out + real, intent(inout) :: time + character(len=20), intent(in) :: fileprefix + character(len=20), parameter :: filevx = 'cube_v1.dat' + character(len=20), parameter :: filevy = 'cube_v2.dat' + character(len=20), parameter :: filevz = 'cube_v3.dat' + real(kind=8) :: h_acc_in + integer :: i,np_in,npartsphere,npmax,iBElast,ierr + integer :: iBE,ilattice + real :: totmass,vol_box,psep,psep_box,pmass_dusttogas + real :: vol_sphere,dens_sphere,dens_medium,cs_medium,angvel_code,przero + real :: u_sphere,kappaBar,kappaPart,gmwi,gammai,cs_sphere_cgs + real :: t_ff,r2,area,Bzero,rmasstoflux_crit + real :: rxy2,rxyz2,phi,dphi,central_density,edge_density,rmsmach,v2i,turbfac,rhocritTcgs,ui + real, allocatable :: rtab(:),rhotab(:) + logical :: iexist + logical :: make_sinks = .true. ! the default prompt is to ask to make sinks + character(len=120) :: filex,filey,filez + character(len=100) :: filename,cwd + character(len=40) :: fmt + character(len=10) :: h_acc_char + logical :: usebox = .false. + !--Initialise dust distribution, if using dust + if (use_dust) call set_dust_default_options() + + filename = trim(fileprefix)//'.setup' + print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)",& + ' Sphere setup' + + inquire(file=filename,exist=iexist) + if (iexist) then + call read_setupfile(filename,ierr) + np_in = np + if (ierr /= 0) then + if (id==master) call write_setupfile(filename) + stop + endif + elseif (id==master) then + print "(a,/)",trim(filename)//' not found: using interactive setup' + dist_unit = '1.0d16cm' + mass_unit = 'solarm' + ierr = 1 + do while (ierr /= 0) + call prompt('Enter mass unit (e.g. solarm,jupiterm,earthm)',mass_unit) + call select_unit(mass_unit,umass,ierr) + if (ierr /= 0) print "(a)",' ERROR: mass unit not recognised' + enddo + ierr = 1 + do while (ierr /= 0) + call prompt('Enter distance unit (e.g. au,pc,kpc,0.1pc)',dist_unit) + call select_unit(dist_unit,udist,ierr) + if (ierr /= 0) print "(a)",' ERROR: length unit not recognised' + enddo + ! + ! units + ! + call set_units(dist=udist,mass=umass,G=1.d0) + ! + ! prompt user for settings + ! + npmax = int(2.0/3.0*size(xyzh(1,:))) ! approx max number allowed in sphere given size(xyzh(1,:)) + if (npmax < 300000) then + np = npmax + elseif (npmax < 1000000) then + np = 300000 + else + np = 1000000 + endif + call prompt('Enter the approximate number of particles in the sphere',np,0,npmax) + np_in = np + + lattice = 'closepacked' + ilattice = 3 + call prompt('Enter the type of particle lattice (1=random,2=cubic,3=closepacked,4=hexagonal)',ilattice,0,4) + if (ilattice==1) then + lattice = 'random' + shuffle_parts = .false. + elseif (ilattice==2) then + lattice = 'cubic' + elseif (ilattice==4) then + lattice = 'hexagonal' + endif + + shuffle_parts = .false. + if (ilattice==1) shuffle_parts = .true. + call prompt('Relax particles by shuffling?',shuffle_parts) + + BEsphere = .false. + call prompt('Centrally condense the sphere as a BE sphere?',BEsphere) + + if (.not. BEsphere) then + r_sphere = 4. + call prompt('Enter radius of sphere in units of '//dist_unit,r_sphere,0.) + lbox = 4. + call prompt('Enter the box size in units of spherical radii: ',lbox,1.) + if (.not. is_cube) then + do i=1,3 + xmini(i) = -0.5*(lbox*r_sphere) + xmaxi(i) = -xmini(i) + enddo + endif + + totmass_sphere = 1.0 + call prompt('Enter total mass in sphere in units of '//mass_unit,totmass_sphere,0.) + else + print *, 'deleted' + endif + + call prompt('Enter temperature in sphere',T_sphere,1.,100.) + + call prompt('Enter EOS filename',eos_file) + + if (binary) then + angvel = 1.006d-12 + else + angvel = 1.77d-13 + endif + angvel_not_betar = .true. + beta_r = 0.02 + call prompt('Input angular velocity (true); else input ratio of rotational-to-potential energy ',angvel_not_betar) + if (angvel_not_betar) then + call prompt('Enter angular rotation speed in rad/s ',angvel,0.) + else + call prompt('Enter ratio of rotational-to-potential energy ',beta_r,0.) + endif + + rms_mach = 0. + call prompt('Enter the Mach number of the cloud turbulence',rms_mach,0.) + + if (mhd) then + Bzero_G = 1.0d-4 ! G + masstoflux = 5.0 + ang_Bomega = 180.0 + mu_not_B = .true. + call prompt('Input the mass-to-flux ratio (true); else input the magnetic field strength ',mu_not_B) + if (mu_not_B) then + call prompt('Enter mass-to-flux ratio in units of critical value ',masstoflux,0.) + else + call prompt('Enter magnetic field strength in Gauss ',Bzero_G,0.) + endif + call prompt('Enter the angle (degrees) between B and the rotation axis? ',ang_Bomega) + endif + + if (use_dust) then + !--currently assume one fluid dust + dtg = 0.01 + grainsize = 0. + graindens = 0. + grainsizecgs = 0.1 + graindenscgs = 3. + ndustsmall = 1 + smincgs = 1.e-5 + smaxcgs = 1. + sindex = 3.5 + call prompt('Enter total dust to gas ratio',dtg,0.) + call prompt('How many grain sizes do you want?',ndustsmall,1,maxdustsmall) + ndusttypes = ndustsmall + if (ndusttypes > 1) then + !--grainsizes + call prompt('Enter minimum grain size in cm',smincgs,0.) + call prompt('Enter maximum grain size in cm',smaxcgs,0.) + !--mass distribution + call prompt('Enter power-law index, e.g. MRN',sindex) + !--grain density + call prompt('Enter grain density in g/cm^3',graindenscgs,0.) + else + call prompt('Enter grain size in cm',grainsizecgs,0.) + call prompt('Enter grain density in g/cm^3',graindenscgs,0.) + endif + endif + + if (binary) then + rho_pert_amp = 0.1 + call prompt('Enter the amplitute of the density perturbation ',rho_pert_amp,0.0,0.4) + endif + + ! ask about sink particle details; these will not be saved to the .setup file since they exist in the .in file + ! + call prompt('Do you wish to dynamically create sink particles? ',make_sinks) + if (make_sinks) then + if (binary) then + h_acc_char = '3.35au' + else + h_acc_char = '1.0d-2' + endif + call prompt('Enter the accretion radius of the sink (with units; e.g. au,pc,kpc,0.1pc) ',h_acc_char) + call select_unit(h_acc_char,h_acc_in,ierr) + h_acc_setup = h_acc_in + if (ierr==0 ) h_acc_setup = h_acc_setup/udist + r_crit_setup = 5.0*h_acc_setup + icreate_sinks_setup = 1 + if (binary) h_soft_sinksink_setup = 0.4*h_acc_setup + else + icreate_sinks_setup = 0 + rhofinal_setup = 0.15 + call prompt('Enter final maximum density in g/cm^3 (ignored for <= 0) ',rhofinal_setup) + endif + if (id==master) call write_setupfile(filename) + stop 'please edit .setup file and rerun phantomsetup' + else + stop ! MPI, stop on other threads, interactive on master + endif + ! + ! units + ! + call set_units(dist=udist,mass=umass,G=1.d0) + ! + ! set dust properties + ! + if (use_dust) then + use_dustfrac = .true. + ndustsmall = ndusttypes + if (ndusttypes > 1) then + call set_dustbinfrac(smincgs,smaxcgs,sindex,dustbinfrac(1:ndusttypes),grainsize(1:ndusttypes)) + grainsize(1:ndusttypes) = grainsize(1:ndusttypes)/udist + graindens(1:ndusttypes) = graindenscgs/umass*udist**3 + else + grainsize(1) = grainsizecgs/udist + graindens(1) = graindenscgs/umass*udist**3 + endif + endif + + + + ! general parameters + ! + + vol_sphere = 4./3.*pi*r_sphere**3 + rhozero = totmass_sphere / vol_sphere + dens_sphere = rhozero + + ! call EOS + ieos = 21 + ierr = 0 + call read_optab(eos_file,ierr) + call getintenerg_opdep(T_sphere, dens_sphere*unit_density, u_sphere) + call getopac_opdep(u_sphere,dens_sphere,kappaBar,kappaPart,T_sphere,gmwi) + u_sphere = u_sphere/unit_ergg + time = 0. + if (use_dust) dust_method = 1 + hfact = hfact_default + hfact_out = hfact_default + print *, 'gamma =', gamma, 'u_sphere = ',u_sphere,T_sphere + + rmax = r_sphere + if (angvel_not_betar) then + angvel_code = angvel*utime + else + angvel_code = sqrt(3.0*totmass_sphere*beta_r/r_sphere**3) + angvel = angvel_code/utime + endif + + + totmass = totmass_sphere + t_ff = sqrt(3.*pi/(32.*dens_sphere)) + + przero = dens_sphere * kb_on_mh * T_sphere/gmwi ! code units + gammai = 1.d0 + (przero/u_sphere/dens_sphere) + cs_sphere = sqrt(gammai * przero/dens_sphere) + cs_sphere_cgs = cs_sphere * unit_velocity + polyk = cs_sphere**2 + gamma = 5./3. ! not used but set to keep Phantom happy. + ! + ! setup particles in the sphere; use this routine to get N_sphere as close to np as possible + ! + if (BEsphere) then + call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh, & + rhotab=rhotab(1:iBElast),rtab=rtab(1:iBElast),nptot=npart_total,& + exactN=.true.,np_requested=np,mask=i_belong) + else + call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& + exactN=.true.,np_requested=np,mask=i_belong) + if (trim(lattice)/='random') print "(a,es10.3)",' Particle separation in sphere = ',psep + endif + print "(a)",' Initialised sphere' + npartsphere = npart_total + + ! + ! set particle properties + ! + npartoftype(:) = 0 + npartoftype(igas) = npart + dustfrac = 0. + if (massoftype(igas) < epsilon(massoftype(igas))) massoftype(igas) = totmass/npart_total + do i = 1,npartoftype(igas) + call set_particle_type(i,igas) + if (use_dust .and. dust_method==1) then + if (ndusttypes > 1) then + dustfrac(1:ndusttypes,i) = dustbinfrac(1:ndusttypes)*dtg + else + dustfrac(1,i) = dtg/(1.+dtg) ! call set_dustfrac(dtg,dustfrac(:,i)) + endif + endif + enddo + ! + ! Set two-fluid dust + ! (currently deactivated; will need to re-test before use to ensure it is fully compatible with the current dust algorithms) + ! + if (use_dust .and. dust_method==2) then + ! particle separation in dust sphere & sdjust for close-packed lattice + pmass_dusttogas = 10.*dtg*massoftype(igas) + psep = (vol_sphere/pmass_dusttogas/real(np))**(1./3.) + psep = psep*sqrt(2.)**(1./3.) + call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& + exactN=.true.,np_requested=np/10,mask=i_belong) + npartoftype(idust) = int(npart_total) - npartoftype(igas) + massoftype(idust) = totmass_sphere*dtg/npartoftype(idust) + + do i = npartoftype(igas)+1,npart + call set_particle_type(i,idust) + enddo + + print "(a,4(i10,1x))", ' particle numbers: (gas_total, gas_sphere, dust, total): ' & + , npartoftype(igas),npartsphere,npartoftype(idust),npart + print "(a,2es10.3)" , ' particle masses: (gas,dust): ',massoftype(igas),massoftype(idust) + else + print "(a,3(i10,1x))", ' particle numbers: (sphere, low-density medium, total): ' & + , npartsphere, npart-npartsphere,npart + print "(a,es10.3)",' particle mass = ',massoftype(igas) + endif + ! + ! shuffle particles + ! + if (shuffle_parts) then + print*, "lets shuffle!" + if (BEsphere) then + call shuffleparticles(iprint,npart,xyzh,massoftype(igas),dmedium=dens_medium,ntab=iBElast, & + rtab=rtab,dtab=rhotab,dcontrast=density_contrast,is_setup=.true.,prefix=trim(fileprefix)) + else + call shuffleparticles(iprint,npart,xyzh,massoftype(igas), & + rsphere=rmax,dsphere=dens_sphere,dmedium=dens_medium,is_setup=.true.,prefix=trim(fileprefix)) + endif + endif + if (BEsphere) deallocate(rtab,rhotab) + ! + ! reset to centre of mass + ! (if random or shuffling, recentering may shift particles outside of the defined range) + ! + if (trim(lattice)/='random' .and. .not.shuffle_parts) call reset_centreofmass(npart,xyzh,vxyzu) + + ! + !--Stretching the spatial distribution to perturb the density profile, if requested + ! + if (binary) then + do i = 1,npart + rxy2 = xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) + rxyz2 = rxy2 + xyzh(3,i)*xyzh(3,i) + if (rxyz2 <= r_sphere**2) then + phi = atan(xyzh(2,i)/xyzh(1,i)) + if (xyzh(1,i) < 0.0) phi = phi + pi + dphi = 0.5*rho_pert_amp*sin(2.0*phi) + phi = phi - dphi + xyzh(1,i) = sqrt(rxy2)*cos(phi) + xyzh(2,i) = sqrt(rxy2)*sin(phi) + endif + enddo + endif + ! + ! Velocity: Turbulent velocity field + ! + vxyzu = 0. + if (rms_mach > 0.) then + call getcwd(cwd) + ! personal hack for J. Wurster since different computer clusters required different velocity fields + if (index(cwd,'gpfs1/scratch/astro/jhw5') > 0 .or. index(cwd,'data/dp187/dc-wurs1') > 0 ) then + ! Kennedy or Dial + filex = find_phantom_datafile(filevx,'velfield_sphng') + filey = find_phantom_datafile(filevy,'velfield_sphng') + filez = find_phantom_datafile(filevz,'velfield_sphng') + else + filex = find_phantom_datafile(filevx,'velfield') + filey = find_phantom_datafile(filevy,'velfield') + filez = find_phantom_datafile(filevz,'velfield') + endif + + call set_velfield_from_cubes(xyzh(:,1:npartsphere),vxyzu(:,:npartsphere),npartsphere, & + filex,filey,filez,1.,r_sphere,.false.,ierr) + if (ierr /= 0) call fatal('setup','error setting up velocity field on clouds') + + rmsmach = 0.0 + print*, 'Turbulence being set by user' + do i = 1,npartsphere + v2i = dot_product(vxyzu(1:3,i),vxyzu(1:3,i)) + rmsmach = rmsmach + v2i/cs_sphere**2 + enddo + rmsmach = sqrt(rmsmach/npartsphere) + if (rmsmach > 0.) then + turbfac = rms_mach/rmsmach ! normalise the energy to the desired mach number + else + turbfac = 0. + endif + do i = 1,npartsphere + vxyzu(1:3,i) = turbfac*vxyzu(1:3,i) + enddo + endif + ! + ! Velocity: uniform rotation (thermal energy & magnetic field too) + ! + do i=1,npart + r2 = dot_product(xyzh(1:3,i),xyzh(1:3,i)) + if (r2 < r_sphere**2) then + vxyzu(1,i) = vxyzu(1,i) - angvel_code*xyzh(2,i) + vxyzu(2,i) = vxyzu(2,i) + angvel_code*xyzh(1,i) + ui = u_sphere + if (maxvxyzu >= 4) vxyzu(4,i) = ui + else + if (maxvxyzu >= 4) vxyzu(4,i) = 1.5*polyk2 + endif + enddo + ! + ! set default runtime parameters if .in file does not exist + ! + filename=trim(fileprefix)//'.in' + inquire(file=filename,exist=iexist) + dtmax = t_ff/100. ! Since this variable can change, always reset it if running phantomsetup + if (.not. iexist) then + if (binary) then + tmax = 1.50*t_ff ! = 13.33 for default settings (Wurster, Price & Bate 2017) + else + tmax = 1.21*t_ff ! = 10.75 for default settings (Wurster, Price & Bate 2016) + endif + ieos = 21 + nfulldump = 1 + calc_erot = .true. + dtmax_dratio = 1.258 + icreate_sinks = icreate_sinks_setup + r_crit = r_crit_setup + h_acc = h_acc_setup + if (binary) h_soft_sinksink = h_soft_sinksink_setup + hdivbbmax_max = 1.0 ! 512. + if (icreate_sinks==1) then + dtmax_min = dtmax/8.0 + else + dtmax_min = 0.0 + rhofinal_cgs = rhofinal_setup + endif + ilimitdustflux = .true. + endif + ! + !--Summarise the sphere + ! + print "(a,i10)",' Input npart_sphere = ',np + print "(1x,50('-'))" + print "(a)",' Quantity (code units) (physical units)' + print "(1x,50('-'))" + fmt = "((a,1pg10.3,3x,1pg10.3),a)" + print fmt,' Total mass : ',totmass,totmass*umass,' g' + print fmt,' Mass in sphere : ',totmass_sphere,totmass_sphere*umass,' g' + print fmt,' Radius of sphere : ',r_sphere,r_sphere*udist,' cm' + if (BEsphere) then + print fmt,' Mean rho sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' + print fmt,' central density : ',central_density,central_density*unit_density,' g/cm^3' + print fmt,' edge density : ',edge_density,edge_density*unit_density,' g/cm^3' + print fmt,' Mean rho medium : ',dens_medium,dens_medium*unit_density,' g/cm^3' + else + print fmt,' Density sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' + endif + print fmt,' cs in sphere : ',cs_sphere,cs_sphere_cgs,' cm/s' + print fmt,' Free fall time : ',t_ff,t_ff*utime/years,' yrs' + print fmt,' Angular velocity : ',angvel_code,angvel,' rad/s' + print fmt,' Turbulent Mach no: ',rms_mach + print fmt,' Omega*t_ff : ',angvel_code*t_ff + + if (use_dust) then + print fmt,' dust-to-gas ratio: ',dtg,dtg,' ' + endif + print "(1x,50('-'))" + +end subroutine setpart + +!---------------------------------------------------------------- +!+ +! write parameters to setup file +!+ +!---------------------------------------------------------------- +subroutine write_setupfile(filename) + use infile_utils, only: write_inopt + character(len=*), intent(in) :: filename + integer, parameter :: iunit = 20 + integer :: i + + print "(a)",' writing setup options file '//trim(filename) + open(unit=iunit,file=filename,status='replace',form='formatted') + write(iunit,"(a)") '# input file for sphere-in-box setup routines' + write(iunit,"(/,a)") '# units' + call write_inopt(dist_unit,'dist_unit','distance unit (e.g. au)',iunit) + call write_inopt(mass_unit,'mass_unit','mass unit (e.g. solarm)',iunit) + + write(iunit,"(/,a)") '# particle resolution & placement' + call write_inopt(np,'np','requested number of particles in sphere',iunit) + call write_inopt(lattice,'lattice','particle lattice (random,cubic,closepacked,hcp,hexagonal)',iunit) + call write_inopt(shuffle_parts,'shuffle_parts','relax particles by shuffling',iunit) + + write(iunit,"(/,a)") '# options for box' + if (.not.BEsphere .and. .not.is_cube) then + ! left here for backwards compatibility and for simplicity if the user requires a rectangle in the future + do i=1,3 + call write_inopt(xmini(i),labelx(i)//'min',labelx(i)//' min',iunit) + call write_inopt(xmaxi(i),labelx(i)//'max',labelx(i)//' max',iunit) + enddo + else + call write_inopt(lbox,'lbox','length of a box side in terms of spherical radii',iunit) + endif + + write(iunit,"(/,a)") '# intended result' + call write_inopt(binary,'form_binary','the intent is to form a central binary',iunit) + + write(iunit,"(/,a)") '# options for sphere' + call write_inopt(BEsphere,'use_BE_sphere','centrally condense as a BE sphere',iunit) + if (.not. BEsphere) then + call write_inopt(r_sphere,'r_sphere','radius of sphere in code units',iunit) + call write_inopt(totmass_sphere,'totmass_sphere','mass of sphere in code units',iunit) + else + call write_inopt(iBEparam,'iBE_options','The set of parameters to define the BE sphere',iunit) + if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) & + call write_inopt(BErho_cen,'BErho_cen','central density of the BE sphere [code units]',iunit) + if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) & + call write_inopt(BErad_phys,'BErad_phys','physical radius of the BE sphere [code units]',iunit) + if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) & + call write_inopt(BErad_norm,'BErad_norm','normalised radius of the BE sphere',iunit) + if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) & + call write_inopt(BEmass,'BEmass','mass radius of the BE sphere [code units]',iunit) + if (iBEparam==4 .or. iBEparam==5) & + call write_inopt(BEfac,'BEfac','over-density factor of the BE sphere [code units]',iunit) + endif + call write_inopt(density_contrast,'density_contrast','density contrast in code units',iunit) + call write_inopt(T_sphere,'T_sphere','temperature in sphere',iunit) + if (angvel_not_betar) then + call write_inopt(angvel,'angvel','angular velocity in rad/s',iunit) + else + call write_inopt(beta_r,'beta_r','rotational-to-gravitational energy ratio',iunit) + endif + call write_inopt(rms_mach,'rms_mach','turbulent rms mach number',iunit) + if (mhd) then + if (mu_not_B) then + call write_inopt(masstoflux,'masstoflux','mass-to-magnetic flux ratio in units of critical value',iunit) + else + call write_inopt(Bzero_G,'Bzero','Magnetic field strength in Gauss',iunit) + endif + call write_inopt(ang_Bomega,'ang_Bomega','Angle (degrees) between B and rotation axis',iunit) + endif + if (use_dust) then + write(iunit,"(/,a)") '# Dust properties' + call write_inopt(dtg,'dust_to_gas_ratio','dust-to-gas ratio',iunit) + call write_inopt(ndusttypes,'ndusttypes','number of grain sizes',iunit) + if (ndusttypes > 1) then + call write_inopt(smincgs,'smincgs','minimum grain size [cm]',iunit) + call write_inopt(smaxcgs,'smaxcgs','maximum grain size [cm]',iunit) + call write_inopt(sindex, 'sindex', 'power-law index, e.g. MRN',iunit) + call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) + else + call write_inopt(grainsizecgs,'grainsizecgs','grain size in [cm]',iunit) + call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) + endif + endif + if (binary) then + call write_inopt(rho_pert_amp,'rho_pert_amp','amplitude of density perturbation',iunit) + endif + write(iunit,"(/,a)") '# Sink properties (values in .in file, if present, will take precedence)' + call write_inopt(icreate_sinks_setup,'icreate_sinks','1: create sinks. 0: do not create sinks',iunit) + if (icreate_sinks_setup==1) then + call write_inopt(h_acc_setup,'h_acc','accretion radius (code units)',iunit) + call write_inopt(r_crit_setup,'r_crit','critical radius (code units)',iunit) + if (binary) then + call write_inopt(h_soft_sinksink_setup,'h_soft_sinksink','sink-sink softening radius (code units)',iunit) + endif + else + call write_inopt(rhofinal_setup,'rho_final','final maximum density (<=0 to ignore) (cgs units)',iunit) + endif + close(iunit) + +end subroutine write_setupfile + +!---------------------------------------------------------------- +!+ +! Read parameters from setup file +!+ +!---------------------------------------------------------------- +subroutine read_setupfile(filename,ierr) + use infile_utils, only: open_db_from_file,inopts,read_inopt,close_db + use unifdis, only: is_valid_lattice + use io, only: error + use units, only: select_unit + character(len=*), intent(in) :: filename + integer, intent(out) :: ierr + integer, parameter :: iunit = 21 + integer :: i,nerr,kerr,jerr + type(inopts), allocatable :: db(:) + + !--Read values + print "(a)",' reading setup options from '//trim(filename) + call open_db_from_file(db,filename,iunit,ierr) + call read_inopt(mass_unit,'mass_unit',db,ierr) + call read_inopt(dist_unit,'dist_unit',db,ierr) + call read_inopt(BEsphere,'use_BE_sphere',db,ierr) + call read_inopt(binary,'form_binary',db,ierr) + call read_inopt(np,'np',db,ierr) + call read_inopt(lattice,'lattice',db,ierr) + if (ierr/=0 .or. .not. is_valid_lattice(trim(lattice))) then + print*, ' invalid lattice. Setting to closepacked' + lattice = 'closepacked' + endif + call read_inopt(shuffle_parts,'shuffle_parts',db,ierr) + + call read_inopt(lbox,'lbox',db,jerr) ! for backwards compatibility + if (jerr /= 0) then + do i=1,3 + call read_inopt(xmini(i),labelx(i)//'min',db,ierr) + call read_inopt(xmaxi(i),labelx(i)//'max',db,ierr) + enddo + lbox = -2.0*xmini(1)/r_sphere + endif + + if (.not. BEsphere) then + call read_inopt(r_sphere,'r_sphere',db,ierr) + call read_inopt(totmass_sphere,'totmass_sphere',db,ierr) + else + call read_inopt(iBEparam,'iBE_options',db,ierr) + if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) call read_inopt(BErho_cen,'BErho_cen',db,ierr) + if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) call read_inopt(BErad_phys,'BErad_phys',db,ierr) + if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) call read_inopt(BErad_norm,'BErad_norm',db,ierr) + if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) call read_inopt(BEmass,'BEmass',db,ierr) + if (iBEparam==4 .or. iBEparam==5) call read_inopt(BEfac,'BEfac',db,ierr) + endif + + call read_inopt(T_sphere,'T_sphere',db,jerr) + cs_in_code = .false. ! for backwards compatibility + if (jerr /= 0 .and. kerr == 0) then + cs_in_code = .false. + elseif (jerr == 0 .and. kerr /= 0) then + cs_in_code = .true. + else + ierr = ierr + 1 + endif + call read_inopt(angvel,'angvel',db,jerr) + call read_inopt(beta_r,'beta_r',db,kerr) + angvel_not_betar = .true. + if (jerr /= 0 .and. kerr == 0) then + angvel_not_betar = .false. + elseif (jerr == 0 .and. kerr /= 0) then + angvel_not_betar = .true. + else + ierr = ierr + 1 + endif + call read_inopt(rms_mach,'rms_mach',db,ierr) + mu_not_B = .true. + if (mhd) then + call read_inopt(masstoflux,'masstoflux',db,jerr) + call read_inopt(Bzero_G, 'Bzero', db,kerr) + call read_inopt(ang_Bomega,'ang_Bomega',db,ierr) + if (jerr /= 0 .and. kerr == 0) then + mu_not_B = .false. + elseif (jerr == 0 .and. kerr /= 0) then + mu_not_B = .true. + else + ierr = ierr + 1 + endif + endif + if (use_dust) then + call read_inopt(dtg,'dust_to_gas_ratio',db,ierr) + call read_inopt(ndusttypes,'ndusttypes',db,ierr) + if (ndusttypes > 1) then + call read_inopt(smincgs,'smincgs',db,ierr) + call read_inopt(smaxcgs,'smaxcgs',db,ierr) + call read_inopt(sindex,'cs_sphere',db,ierr) + call read_inopt(graindenscgs,'graindenscgs',db,ierr) + else + call read_inopt(grainsizecgs,'grainsizecgs',db,ierr) + call read_inopt(graindenscgs,'graindenscgs',db,ierr) + endif + endif + if (binary) then + call read_inopt(rho_pert_amp,'rho_pert_amp',db,ierr) + endif + call read_inopt(icreate_sinks_setup,'icreate_sinks',db,ierr) + if (icreate_sinks_setup==1) then + call read_inopt(h_acc_setup,'h_acc',db,ierr) + call read_inopt(r_crit_setup,'r_crit',db,ierr) + if (binary) then + call read_inopt(h_soft_sinksink_setup,'h_soft_sinksink',db,ierr) + endif + else + call read_inopt(rhofinal_setup,'rho_final',db,ierr) + endif + call close_db(db) + ! + ! parse units + ! + call select_unit(mass_unit,umass,nerr) + if (nerr /= 0) then + call error('setup_sphereinbox','mass unit not recognised') + ierr = ierr + 1 + endif + call select_unit(dist_unit,udist,nerr) + if (nerr /= 0) then + call error('setup_sphereinbox','length unit not recognised') + ierr = ierr + 1 + endif + + if (ierr > 0) then + print "(1x,a,i2,a)",'Setup_sphereinbox: ',nerr,' error(s) during read of setup file. Re-writing.' + endif + +end subroutine read_setupfile +!---------------------------------------------------------------- + !--Magnetic flux justification + ! This shows how the critical mass-to-flux values translates from CGS to code units. + ! + ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) ! cgs units of g G^-1 cm^-2 + ! convert base units from cgs to code: + ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *unit_Bfield*udist**2/umass + ! where + ! unit_Bfield = umass/(utime*sqrt(umass*udist/4*pi)) = sqrt(4.*pi*umass)/(utime*sqrt(udist)) + ! therefore + ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *sqrt(4.*pi*umass)*udist**2/(utime*sqrt(udist)*umass) + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*sqrt(umass)*udist**2/(utime*sqrt(udist)*umass) + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*udist**1.5/ (sqrt(umass)*utime) + ! where + ! G [cgs] = 1 * udist**3/(umass*utime**2) + ! therefore + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) *udist**1.5/ (sqrt(umass)*utime) / sqrt(udist**3/(umass*utime**2)) + ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) ! code units + +!---------------------------------------------------------------- +end module setup From 5d4e5215b45fc79fd49a2d9fc55b23f3cd85260c Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 26 Jun 2024 11:10:38 +0100 Subject: [PATCH 123/182] Updated test suite from upstream --- src/tests/test_ptmass.f90 | 4 +- src/tests/test_wind.f90 | 262 +++++++++++++++++++++++++++++--------- src/tests/testsuite.F90 | 2 + 3 files changed, 207 insertions(+), 61 deletions(-) diff --git a/src/tests/test_ptmass.f90 b/src/tests/test_ptmass.f90 index 7272f1276..966a77727 100644 --- a/src/tests/test_ptmass.f90 +++ b/src/tests/test_ptmass.f90 @@ -766,7 +766,7 @@ subroutine test_createsink(ntests,npass) use part, only:init_part,npart,npartoftype,igas,xyzh,massoftype,hfact,rhoh,& iphase,isetphase,fext,divcurlv,vxyzu,fxyzu,poten, & nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,ndptmass, & - dptmass + dptmass,fxyz_ptmass_sinksink use ptmass, only:ptmass_accrete,update_ptmass,icreate_sinks,& ptmass_create,finish_ptmass,ipart_rhomax,h_acc,rho_crit,rho_crit_cgs use energies, only:compute_energies,angtot,etot,totmom @@ -886,7 +886,7 @@ subroutine test_createsink(ntests,npass) call reduceloc_mpi('max',ipart_rhomax_global,id_rhomax) endif call ptmass_create(nptmass,npart,itestp,xyzh,vxyzu,fxyzu,fext,divcurlv,poten,& - massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,0.) + massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,dptmass,0.) ! ! check that creation succeeded ! diff --git a/src/tests/test_wind.f90 b/src/tests/test_wind.f90 index ffd72aea9..65de7fb84 100644 --- a/src/tests/test_wind.f90 +++ b/src/tests/test_wind.f90 @@ -14,15 +14,18 @@ module testwind ! ! :Runtime parameters: None ! -! :Dependencies: boundary, checksetup, dim, eos, inject, io, options, part, -! partinject, physcon, step_lf_global, testutils, timestep, timestep_ind, -! units, wind +! :Dependencies: allocutils, boundary, checksetup, dim, dust_formation, +! eos, inject, io, options, part, partinject, physcon, ptmass, +! ptmass_radiation, readwrite_infile, step_lf_global, testutils, +! timestep, timestep_ind, units, wind ! implicit none public :: test_wind private + logical :: vb = .false. + contains !---------------------------------------------------------- !+ @@ -30,29 +33,24 @@ module testwind !+ !---------------------------------------------------------- subroutine test_wind(ntests,npass) - use io, only:iprint,id,master,iverbose!,iwritein - use boundary, only:set_boundary - use options, only:ieos!,icooling - use physcon, only:au,solarm,solarl - use units, only:umass,set_units,utime,unit_energ,udist - use inject, only:init_inject,inject_particles,set_default_options_inject,inject_type - use eos, only:gmw,ieos,init_eos,gamma,polyk - use part, only:npart,init_part,nptmass,xyzmh_ptmass,vxyz_ptmass,xyzh,vxyzu,& - nptmass,npartoftype,igas,iTeff,iLum,iReff,massoftype,ntot - use timestep, only:time,tmax,dt,dtmax,nsteps,dtrad,dtforce,dtcourant,dterr,print_dtlog - use step_lf_global, only:step,init_step - use testutils, only:checkval,update_test_scores - use dim, only:isothermal,inject_parts,mpi - use partinject, only:update_injected_particles - use timestep_ind, only:nbinmax - use wind, only:trvurho_1D - use checksetup, only:check_setup - !use readwrite_infile, only:read_infile,write_infile + use io, only:id,master,iprint,iwritein + use inject, only:inject_type + use boundary, only:set_boundary + use physcon, only:au,solarm,solarl + use units, only:set_units + use part, only:npart,xyzmh_ptmass,vxyzu,dust_temp + use testutils, only:checkval,update_test_scores + use dim, only:mpi,maxTdust,maxp,sink_radiation,nucleation,ind_timesteps + use allocutils, only:allocate_array + use options, only:alphamax + use readwrite_infile, only:read_infile,write_infile integer, intent(inout) :: ntests,npass - integer :: i,ierr,nerror,istepfrac,npart_old,nfailed(9),nwarn - real :: dtinject,dtlast,t,default_particle_mass,dtext,dtnew,dtprint,dtmaxold,tprint + real, parameter :: eps_sum = 1e-14 + integer :: npart_old,nfailed(5),istepfrac + real :: dtinject,eint,ekin + logical :: testkd,testcyl,test2 if (mpi) then if (id==master) write(*,"(/,a,/)") '--> SKIPPING WIND TEST (currently not working with MPI)' @@ -67,13 +65,116 @@ subroutine test_wind(ntests,npass) call set_units(dist=au,mass=solarm,G=1.d0) call set_boundary(-50.,50.,-50.,50.,-50.,50.) + testkd = sink_radiation .and. nucleation .and. alphamax == 1. .and. ind_timesteps + test2 = .not.sink_radiation .and. .not.nucleation .and. alphamax == 1. .and. .not.ind_timesteps + testcyl = .not.sink_radiation .and. .not.nucleation .and. alphamax == 1. .and. ind_timesteps + +! test trans-sonic wind - no radiation, no dust + + call init_testwind(1,ntests,npass,npart_old,istepfrac,dtinject) + if (id==master) call write_infile('w.in','w.log','w.ev','w_00000',iwritein,iprint) + call integrate_wind(npart_old,istepfrac,dtinject) + nfailed(:) = 0 + eint = sum(vxyzu(4,1:npart)) + ekin = sqrt(sum(vxyzu(1,1:npart)**2+vxyzu(2,1:npart)**2+vxyzu(3,1:npart)**2)) + if (vb) print '(5(1x,es22.15),i8)',xyzmh_ptmass(4,1),xyzmh_ptmass(7,1),xyzmh_ptmass(15,1),eint,ekin,npart + call checkval(xyzmh_ptmass(4,1),1.199987894518367E+00,epsilon(0.),nfailed(1),'sink particle mass') + call checkval(xyzmh_ptmass(7,1),0.,epsilon(0.),nfailed(2),'mass accreted') + call checkval(npart,12180,0,nfailed(3),'number of ejected particles') + if (testcyl) then + call checkval(eint,3.360686893182378E+03,eps_sum,nfailed(4),'total internal energy') + call checkval(ekin,5.605632523862468E+01,eps_sum,nfailed(5),'total kinetic energy') + elseif (testkd) then + call checkval(eint,3.164153170427767E+03,eps_sum,nfailed(4),'total internal energy') + call checkval(ekin,6.101010545772693E+01,eps_sum,nfailed(5),'total kinetic energy') + elseif (test2) then + call checkval(eint,3.367417540822784E+03,eps_sum,nfailed(4),'total internal energy') + call checkval(ekin,5.524867074648306E+01,eps_sum,nfailed(5),'total kinetic energy') + else + call checkval(eint,3.179016341424608E+03,eps_sum,nfailed(4),'total internal energy') + call checkval(ekin,6.005124961952793E+01,eps_sum,nfailed(5),'total kinetic energy') + endif + call update_test_scores(ntests,nfailed,npass) + + + if (sink_radiation) then + +! test wind with bowen dust + radiative acceleration + + maxTdust = maxp + if (allocated(dust_temp)) deallocate(dust_temp) + call allocate_array('dust_temp',dust_temp,maxTdust) + + call init_testwind(2,ntests,npass,npart_old,istepfrac,dtinject) + !if (id==master) call write_infile('w2.in','w2.log','w2.ev','w2_00000',iwritein,iprint) + call integrate_wind(npart_old,istepfrac,dtinject) + nfailed(:) = 0 + eint = sum(vxyzu(4,1:npart)) + ekin = sqrt(sum(vxyzu(1,1:npart)**2+vxyzu(2,1:npart)**2+vxyzu(3,1:npart)**2)) + if (vb) print '(5(1x,es22.15),i8)',xyzmh_ptmass(4,1),xyzmh_ptmass(7,1),xyzmh_ptmass(15,1),eint,ekin,npart + call checkval(xyzmh_ptmass(4,1),1.199987815414834E+00,epsilon(0.),nfailed(1),'sink particle mass') + call checkval(xyzmh_ptmass(7,1),0.,epsilon(0.),nfailed(2),'mass accreted') + call checkval(npart,21924,0,nfailed(3),'number of ejected particles') + if (testkd) then + call checkval(eint,2.187465510809545E+02,eps_sum,nfailed(4),'total internal energy') + call checkval(ekin,1.709063901093157E+02,eps_sum,nfailed(5),'total kinetic energy') + else + call checkval(eint,2.218461223513102E+02,eps_sum,nfailed(4),'total internal energy') + call checkval(ekin,1.709669096834302E+02,eps_sum,nfailed(5),'total kinetic energy') + endif + else + if (id==master) write(*,"(/,a,/)") ' SKIPPING SINK RADIATION TEST' + endif + call update_test_scores(ntests,nfailed,npass) + + if (id==master) write(*,"(/,a)") '<-- WIND TEST COMPLETE' + +end subroutine test_wind + +!----------------------------------------------------------------------- +! +subroutine init_testwind(icase,ntests,npass,npart_old,istepfrac,dtinject) +! +!----------------------------------------------------------------------- + + use io, only:iverbose + use inject, only:init_inject,inject_particles,set_default_options_inject + use units, only:umass,utime,unit_energ,udist + use physcon, only:au,solarm,solarl + use eos, only:gmw,ieos,init_eos,gamma,polyk + use part, only:npart,init_part,nptmass,xyzmh_ptmass,vxyz_ptmass,xyzh,vxyzu,& + npartoftype,igas,iTeff,iLum,iReff,massoftype + use timestep, only:tmax,dt,dtmax,dtrad + use wind, only:trvurho_1D + use timestep_ind, only:nbinmax + use dim, only:isothermal + use checksetup, only:check_setup + use partinject, only:update_injected_particles + use testutils, only:checkval,update_test_scores + use ptmass, only:set_integration_precision + use ptmass_radiation, only:alpha_rad,isink_radiation + use dust_formation, only:idust_opacity + + integer, intent(in) :: icase + integer, intent(inout) :: ntests,npass + integer, intent(out) :: npart_old,istepfrac + real, intent(out) :: dtinject + + integer :: i,ierr,nerror,nwarn,nfailed(5) + real :: t,default_particle_mass,dtnew + call init_part() + call set_integration_precision() ! set properties of mass-losing sink particle nptmass = 1 - xyzmh_ptmass(4,1) = 1.2*solarm/umass - xyzmh_ptmass(5,1) = au/udist - xyzmh_ptmass(iTeff,1) = 50000. + xyzmh_ptmass(4,1) = 1.2*solarm/umass + xyzmh_ptmass(5,1) = au/udist + if (icase == 1) then + xyzmh_ptmass(iTeff,1) = 50000. + elseif (icase == 2) then + xyzmh_ptmass(iTeff,1) = 3000. + endif xyzmh_ptmass(iReff,1) = au/udist xyzmh_ptmass(iLum,1) = 2e4 *solarl * utime / unit_energ @@ -97,10 +198,20 @@ subroutine test_wind(ntests,npass) call init_eos(ieos,ierr) iverbose = 0 - !icooling = 0 - dtmax = 1. - tmax = 8. - tprint = tmax + dtmax = 1. + tmax = 8. + !wind + bowen dust + radiation force + if (icase == 1) then + alpha_rad = 0. + isink_radiation = 0 !radiation + alpha_rad + idust_opacity = 0 !bowen opacity + elseif (icase == 2) then + alpha_rad = 1. + isink_radiation = 3 !radiation + alpha_rad + idust_opacity = 1 !bowen opacity + else + stop '[test wind] unknown test ' + endif dt = 0. dtinject = huge(dtinject) dtrad = huge(dtrad) @@ -108,34 +219,76 @@ subroutine test_wind(ntests,npass) dtnew = 0. ! trans-sonic wind - call set_default_options_inject(1) + call set_default_options_inject(icase) call check_setup(nerror,nwarn) - istepfrac = 0 nfailed(:) = 0 + istepfrac = 0 call init_inject(nerror) + npart_old = npart - !debug if (id==master) call write_infile('w.in','w.log','w.ev','w_00000',iwritein,iprint) +!trans-sonic wind - no radiation + if (icase == 1) then + ! check particle's mass + call inject_particles(t,0.,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& + npart,npart_old,npartoftype,dtinject) + call update_injected_particles(npart_old,npart,istepfrac,nbinmax,t,dtmax,dt,dtinject) - ! check particle's mass - call checkval(massoftype(igas),1.490822861042279E-09,epsilon(0.),& - nfailed(1),'no errors in setting particle mass') - npart_old = npart - call inject_particles(t,0.,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& - npart,npart_old,npartoftype,dtinject) - call update_injected_particles(npart_old,npart,istepfrac,nbinmax,t,dtmax,dt,dtinject) - - ! check 1D wind profile - i = size(trvurho_1D(1,:)) - !print '((5(1x,es22.15)))',trvurho_1D(:,i),massoftype(igas) - call checkval(trvurho_1D(2,i),7.058624412798283E+13,epsilon(0.),nfailed(2),'outer wind radius') - call checkval(trvurho_1D(3,i),1.112160584479353E+06,epsilon(0.),nfailed(3),'outer wind velocity') - call checkval(trvurho_1D(4,i),2.031820842001706E+12,epsilon(0.),nfailed(4),'outer wind internal energy') - call checkval(trvurho_1D(5,i),8.878887149408118E-15,epsilon(0.),nfailed(5),'outer wind density') + ! check 1D wind profile + i = size(trvurho_1D(1,:)) + if (vb) print '((6(1x,es22.15)))',trvurho_1D(:,i),massoftype(igas) + call checkval(massoftype(igas),1.490822861042279E-9,epsilon(0.),nfailed(1),'setting particle mass') + call checkval(trvurho_1D(2,i),7.058624412798283E+13,epsilon(0.),nfailed(2),'1D wind terminal radius') + call checkval(trvurho_1D(3,i),1.112160584479353E+06,epsilon(0.),nfailed(3),'1D wind terminal velocity') + call checkval(trvurho_1D(4,i),2.031820842001706E+12,epsilon(0.),nfailed(4),'1D wind internal energy') + call checkval(trvurho_1D(5,i),8.878887149408118E-15,epsilon(0.),nfailed(5),'1D wind terminal density') + call update_test_scores(ntests,nfailed,npass) + endif + + !wind + radiation + if (icase == 2) then + ! check particle's mass + call inject_particles(t,0.,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,npart,npart_old,npartoftype,dtinject) + call update_injected_particles(npart_old,npart,istepfrac,nbinmax,t,dtmax,dt,dtinject) + + ! check 1D wind profile + i = size(trvurho_1D(1,:)) + if (vb) print '((6(1x,es22.15)))',trvurho_1D(:,i),massoftype(igas) + call checkval(massoftype(igas),6.820748526700016E-10,epsilon(0.),nfailed(1),'setting particle mass') + call checkval(trvurho_1D(2,i), 1.546371444697654E+14,epsilon(0.),nfailed(2),'1D wind terminal radius') + call checkval(trvurho_1D(3,i), 4.298693548460183E+06,epsilon(0.),nfailed(3),'1D wind terminal velocity') + call checkval(trvurho_1D(4,i), 4.318674031561777E+10,epsilon(0.),nfailed(4),'1D wind internal energy') + call checkval(trvurho_1D(5,i), 4.879641694552266E-16,epsilon(0.),nfailed(5),'1D wind terminal density') + call update_test_scores(ntests,nfailed,npass) + endif + +end subroutine init_testwind + + +!----------------------------------------------------------------------- +! +subroutine integrate_wind(npart_old,istepfrac,dtinject) +! +!----------------------------------------------------------------------- + + use io, only:id,iprint,master + use timestep, only:time,tmax,dt,dtmax,nsteps,dtrad,dtforce,dtcourant,dterr,print_dtlog + use part, only:npart,init_part,xyzmh_ptmass,vxyz_ptmass,xyzh,vxyzu,npartoftype,ntot + use timestep_ind, only:nbinmax + use step_lf_global, only:step,init_step + use partinject, only:update_injected_particles + use inject, only:inject_particles + + integer, intent(inout) :: istepfrac,npart_old + real, intent(inout) :: dtinject + + real :: dtlast,t,dtext,dtnew,dtprint,dtmaxold,tprint dt = dtinject dtlast = 0. time = 0. + tprint = tmax + t = 0. call init_step(npart_old,time,dtmax) @@ -145,7 +298,7 @@ subroutine test_wind(ntests,npass) ! ! injection of new particles into simulation ! - npart_old=npart + npart_old = npart call inject_particles(t,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,npart,npart_old,npartoftype,dtinject) call update_injected_particles(npart_old,npart,istepfrac,nbinmax,t,dtmax,dt,dtinject) dtmaxold = dtmax @@ -164,15 +317,6 @@ subroutine test_wind(ntests,npass) enddo - !print '((3(1x,es22.15),i8))',xyzmh_ptmass(4,1),xyzmh_ptmass(7,1),xyzmh_ptmass(15,1),npart - call checkval(xyzmh_ptmass(4,1),1.199987894518367E+00,epsilon(0.),nfailed(6),'sink particle mass') - call checkval(xyzmh_ptmass(7,1),0.,epsilon(0.),nfailed(7),'mass accreted') - call checkval(npart,12180,0,nfailed(8),'number of ejected particles') - call checkval(xyzmh_ptmass(15,1),1.591640703559762E-06,epsilon(0.),nfailed(9),'wind mass loss rate') - call update_test_scores(ntests,nfailed,npass) - - if (id==master) write(*,"(/,a)") '<-- WIND TEST COMPLETE' - -end subroutine test_wind +end subroutine integrate_wind end module testwind diff --git a/src/tests/testsuite.F90 b/src/tests/testsuite.F90 index d3bf32d13..a5c129f0d 100644 --- a/src/tests/testsuite.F90 +++ b/src/tests/testsuite.F90 @@ -97,6 +97,8 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) write(*,"(14x,a,/)") '-- Richard West (former UKAFF manager)' write(*,"(2x,a)") '"Trace, test and treat"' write(*,"(14x,a,/)") '-- South Korea' + write(*,"(2x,a)") '"Testing a program demonstrates that it contains errors, never that it is correct"' + write(*,"(14x,a,/)") '-- E. W. Dijkstra' endif ntests = 0 npass = 0 From 12367c0b8866ad34ab8c5b0ab44dfaaba1437a49 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 1 Jul 2024 11:45:31 +0100 Subject: [PATCH 124/182] Improve error handling in radapprox cooling --- src/main/cooling_radapprox.f90 | 16 ++++++++-------- src/main/eos_stamatellos.f90 | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 8582e570b..4b14a0641 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -94,7 +94,8 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb) overpart: do i=1,npart -! if (.not. iactive(iphase(i)) .or. isdead_or_accreted(xyzh(4,i))) cycle +! if (.not. iactive(iphase(i)) ) cycle + if (isdead_or_accreted(xyzh(4,i)) ) cycle poti = Gpot_cool(i) du_FLDi = duFLD(i) ui = energ(i) @@ -106,7 +107,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) + (xyzh(2,i)-xyzmh_ptmass(2,isink_star))**2d0 & + (xyzh(3,i)-xyzmh_ptmass(3,isink_star))**2d0 endif - if (rhoi*unit_density > 1d0) print *, "rhoi > 1.", rhoi,i,sqrt(ri2) + ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& Ti,gmwi) @@ -162,7 +163,6 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) opac_store(i) = opaci dudti_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opaci/unit_ergg*utime! code units -! if (mod(i,100) == 0) print *, "dudt_sph", dudt_sph(i) if (doFLD) then Teqi = (du_FLDi + dudt_sph(i)) *opaci*unit_ergg/utime ! physical units du_tot = dudt_sph(i) + dudti_rad + du_FLDi @@ -180,11 +180,11 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) endif teqi_store(i) = Teqi - if (Teqi > 1e6) 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 * dt=", dudt_sph(i)*dt - endif +! if (Teqi > 1e6) 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 * dt=", dudt_sph(i)*dt +! endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 5b60a7a86..59c9449a9 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -99,7 +99,7 @@ end subroutine read_optab ! Main subroutine for interpolating tables to get EOS values ! subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) - use io, only:warning + use io, only:fatal real, intent(in) :: ui,rhoi real, intent(out) :: kappaBar,kappaPart,Ti,gmwi @@ -117,9 +117,9 @@ 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 - call warning('getopac_opdep','rhoi out of range',var='rhoi',val=rhoi) + 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 warning('getopac_opdep','ui out of range',var='ui',val=ui) + call fatal('getopac_opdep','ui out of range',var='ui',val=ui) endif if (rhoi < rhomin) then @@ -211,7 +211,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) - use io, only:warning + use io, only:fatal real, intent(out) :: ueqi real, intent(in) :: Teqi,rhoi @@ -221,9 +221,9 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) real rhoi_ if (rhoi > OPTABLE(nx,1,1) .or. rhoi < OPTABLE(1,1,1)) then - call warning('getintenerg_opdep','rhoi out of range',var='rhoi',val=rhoi) + call fatal('getintenerg_opdep','rhoi out of range',var='rhoi',val=rhoi) elseif (Teqi > OPTABLE(1,ny,2) .or. Teqi < OPTABLE(1,1,2)) then - call warning('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) + call fatal('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) endif From 11ca2bdf58495a91492bfa28af39e5c298470b80 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 8 Jul 2024 09:43:18 +0100 Subject: [PATCH 125/182] Adds dradcool/dU_hydro check to icooling=9 --- src/main/cooling_radapprox.f90 | 44 ++++++++++++++++++---------------- src/main/step_leapfrog.F90 | 17 ++++++------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 4b14a0641..fea45fdfd 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -21,6 +21,7 @@ module cooling_radapprox implicit none real :: Lstar = 0d0 ! in units of L_sun + real,parameter :: dtcool_crit = 0.001 ! critical dt_rad/dt_hydro for not applying cooling 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 @@ -77,15 +78,10 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot real :: cs2,Om2,Hmod2 real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi - integer :: i,ratefile - character(len=20) :: filename + integer :: i,ratefile,n_uevo ! write (temp,'(E5.2)') dt - write (filename, 11) dt -11 format("coolrate_", E7.2,".dat") - ratefile = 34 - open(unit=ratefile,file=filename,status="replace",form="formatted") !$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) & @@ -94,7 +90,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb) overpart: do i=1,npart -! if (.not. iactive(iphase(i)) ) cycle + if (.not. iactive(iphase(i)) ) cycle if (isdead_or_accreted(xyzh(4,i)) ) cycle poti = Gpot_cool(i) du_FLDi = duFLD(i) @@ -114,12 +110,6 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) presi = kb_on_mh*rhoi*unit_density*Ti/gmwi ! cgs presi = presi/unit_pressure !code units - if (isnan(kappaBari)) then - print *, "kappaBari is NaN\n", " ui(erg) = ", ui*unit_ergg, "rhoi=", rhoi*unit_density, "Ti=", Ti, & - "i=", i - stop - endif - select case (od_method) case (1) ! Stamatellos+ 2007 method @@ -163,6 +153,15 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) opac_store(i) = opaci dudti_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opaci/unit_ergg*utime! code units + ! If radiative cooling is negligible compared to hydrodynamical heating + ! don't use this method to update energy, just use hydro du/dt (don't zero + ! fxyzu(4,i) ). + if (abs(dudti_rad/dudt_sph(i)) < dtcool_crit) then +! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& +! dudt_sph(i) + cycle + endif + if (doFLD) then Teqi = (du_FLDi + dudt_sph(i)) *opaci*unit_ergg/utime ! physical units du_tot = dudt_sph(i) + dudti_rad + du_FLDi @@ -209,7 +208,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) else energ(i) = ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/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 @@ -221,14 +220,19 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) stop endif - if (abs(dudt_sph(i)) >1.) then - !$omp critical - write (ratefile,'(I6,1X,E15.4)') i, (ui - energ(i))/dt - !$omp end critical - endif + ! zero fxyzu(4,i) because we already updated the energy + dudt_sph(i) = 0d0 enddo overpart !$omp end parallel do - close(ratefile) + + n_uevo = 0 + !$omp parallel do default(none) & + !$omp shared(dudt_sph,npart) private(i) reduction(+:n_uevo) + do i=1, npart + if (dudt_sph(i) /= 0d0) n_uevo = n_uevo + 1 + enddo + !$omp end parallel do + print *, "energy not evolved with cooling for", n_uevo, "particles" ! print *, "min/max dudt_sph():", minval(dudt_sph), maxval(dudt_sph) end subroutine radcool_update_energ diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 56ec50dc3..a1dd9939b 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -200,7 +200,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !Alison - if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L202", fxyzu(4,i) + !if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L202", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0. .and. icooling /= 9) then @@ -323,7 +323,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !Alison - if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) + !if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0. .and. icooling /= 9) then @@ -393,7 +393,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) dustpred,ddustevol,filfacpred,dustfrac,eos_vars,timei,dtsph,dtnew,& ppred,dens,metrics) - if (do_radiation .and. implicit_radiation .or. icooling == 9) then + if (do_radiation .and. implicit_radiation) then! .or. icooling == 9) then rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif @@ -484,7 +484,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif !Alison - if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) + ! if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then @@ -508,7 +508,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !Alison - if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L509", fxyzu(4,i) +! if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L509", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0. .and. icooling /= 9) then @@ -567,7 +567,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vzi = vxyzu(3,i) + hdtsph*fxyzu(3,i) if (maxvxyzu >= 4) eni = vxyzu(4,i) + hdtsph*fxyzu(4,i) !Alison - if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L568", fxyzu(4,i) + ! if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L568", fxyzu(4,i) erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 errmax = max(errmax,erri) @@ -660,8 +660,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vxyzu(:,i) = vxyzu(:,i) - hdtsph*fxyzu(:,i) endif - !Alison - if (icooling ==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L662", fxyzu(4,i) if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) - hdtsph*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) - hdtsph*dBevol(:,i) @@ -693,6 +691,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif + if (icooling == 9) then + vxyzu(4,1:npart) = vpred(4,1:npart) + endif endif enddo iterations From 7ae4d40adf3b0ee15475bcb318db5331a0630297 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 8 Jul 2024 09:54:47 +0100 Subject: [PATCH 126/182] Merging upstream changes --- AUTHORS | 4 ++-- build/MakeKrome | 4 ++++ build/Makefile_defaults_ifx | 17 +++++++++++++++++ src/main/extern_spiral.f90 | 14 +++++++------- 4 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 build/Makefile_defaults_ifx diff --git a/AUTHORS b/AUTHORS index f236e7dc4..9f44811cf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -18,18 +18,18 @@ Arnaud Vericel Mark Hutchison Mats Esseldeurs Rebecca Nealon +Yrisch Elisabeth Borchert Ward Homan Christophe Pinte -Yrisch Terrence Tricco Stephane Michoulier Simone Ceppi Spencer Magnall Enrico Ragusa Caitlyn Hardiman -Sergei Biriukov Cristiano Longarini +Sergei Biriukov Giovanni Dipierro Roberto Iaconi Hauke Worpel diff --git a/build/MakeKrome b/build/MakeKrome index 0171e2408..7de5d0c75 100644 --- a/build/MakeKrome +++ b/build/MakeKrome @@ -6,9 +6,13 @@ KROME_BUILD_DIR = ${KROMEPATH}/build KFLAGS=$(filter-out -std=f2008, $(FFLAGS)) ifeq ($(SYSTEM), ifort) KFLAGS += -O3 -ipo -ip -unroll -xHost -g -fp-model precise +else +ifeq ($(SYSTEM), ifx) + KFLAGS += -O3 -ipo -ip -unroll -xHost -g -fp-model precise else KFLAGS += -ffree-line-length-none -w -fallow-argument-mismatch endif +endif FFLAGS+= -I$(KROME_BUILD_DIR) PASSED=0 diff --git a/build/Makefile_defaults_ifx b/build/Makefile_defaults_ifx new file mode 100644 index 000000000..1e00e3918 --- /dev/null +++ b/build/Makefile_defaults_ifx @@ -0,0 +1,17 @@ +# default settings for ifx compiler +# override these in the Makefile +FC= ifx +#FFLAGS= -O3 -inline-factor=500 -shared-intel -warn uninitialized -warn unused -warn truncated_source -no-wrap-margin +FFLAGS= -O3 -shared-intel -warn uninitialized -warn unused -warn truncated_source -no-wrap-margin +DBLFLAG= -r8 +DEBUGFLAG= -check all -WB -traceback -g -debug all # -fpe0 -fp-stack-check -debug all -noarg_temp_created +#DEBUGFLAG= -g -traceback -check all -check bounds -check uninit -ftrapuv -debug all -warn all,nodec,interfaces,nousage -fpe0 -fp-stack-check -WB -no-diag-error-limit -no-wrap-margin -O0 -noarg_temp_created +ENDIANFLAGBIG= -convert big_endian +ENDIANFLAGLITTLE= -convert little_endian +# or use setenv F_UFMTENDIAN=big:45 at runtime (e.g. for unit 45 only) +CC = icc +CCFLAGS = -O3 +LIBCXX = -cxxlib +KNOWN_SYSTEM=yes + +OMPFLAGS= -qopenmp diff --git a/src/main/extern_spiral.f90 b/src/main/extern_spiral.f90 index ddeb68966..f27a06d9f 100644 --- a/src/main/extern_spiral.f90 +++ b/src/main/extern_spiral.f90 @@ -377,20 +377,20 @@ subroutine initialise_spiral(ierr) spiralsum(jj)=0.0d0 !-Loop over spheroids do j=1,Nt - Rspheroids(jj,j) = Ri+(DBLE(j)-1.d0)*d_0 + Rspheroids(jj,j) = Ri+(dble(j)-1.d0)*d_0 shapefn(jj,j) = (cotalpha/Nshape) * & - log(1.d0+(Rspheroids(jj,j)/Rsarms)**Nshape) + jj*2.0d0*pi/DBLE(NNi) + log(1.d0+(Rspheroids(jj,j)/Rsarms)**Nshape) + jj*2.0d0*pi/dble(NNi) !print*,jj,j,Rspheroids(jj,j),shapefn(jj,j) select case(iarms) case(2,4) !--For a linear density drop off from galactic centre: den0(jj,j) = (Rf-Rspheroids(jj,j))*3.d0*Mspiral & - / (DBLE(NNi)*pi*a_0*a_0*c_0) + / (dble(NNi)*pi*a_0*a_0*c_0) spiralsum(jj) = spiralsum(jj) + (Rf-Rspheroids(jj,j)) case(3) !--For a log density drop off from galactic centre: den0(jj,j) = exp((Ri-Rspheroids(jj,j))/Rl)*3.d0*Mspiral & - / (DBLE(NNi)*pi*a_0*a_0*c_0) + / (dble(NNi)*pi*a_0*a_0*c_0) spiralsum(jj) = spiralsum(jj) + exp((Ri-Rspheroids(jj,j))/Rl) end select enddo @@ -420,9 +420,9 @@ subroutine initialise_spiral(ierr) case(1) potfilename = 'pot3D.bin' if (id==master) print*,'Reading in potential from an external file (BINARY): ',potfilename - open (unit =1, file = TRIM(potfilename), status='old', form='UNFORMATTED', access='SEQUENTIAL', iostat=ios) + open(unit=1,file=trim(potfilename),status='old',form='UNFORMATTED',access='SEQUENTIAL',iostat=ios) if (ios /= 0 .and. id==master) then - print*, 'Error opening file:', TRIM(potfilename) + print*, 'Error opening file:', trim(potfilename) endif !Read in the grid lengths if they exist in the header. read(1) potlenz,potlenx,potleny @@ -1281,7 +1281,7 @@ subroutine Wang_bar(ri,phii,thetai,pot) allocate(PlmA(l+1)) call legendre_associated(l,m,cos(thetai),PlmA) Plm=PlmA(l+1) - thisphi = Anlm(i) * (s**REAL(l))/((1.+s)**(2.*REAL(l)+1.)) * Gnl * Plm * cos(REAL(m)*(phii)) + thisphi = Anlm(i) * (s**real(l))/((1.+s)**(2.*real(l)+1.)) * Gnl * Plm * cos(real(m)*(phii)) AlmnSum = AlmnSum + thisphi deallocate(GnlA,PlmA) From 32de3d177341ba43c97b978b9a183426d1638252 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 8 Jul 2024 10:02:37 +0100 Subject: [PATCH 127/182] Adds upstream changes --- src/main/extern_binary.f90 | 8 ++ src/main/extern_densprofile.f90 | 6 +- src/utils/moddump_radiotde.f90 | 156 +++++++++++++++++++++++++++----- src/utils/phantomanalysis.f90 | 7 +- 4 files changed, 148 insertions(+), 29 deletions(-) diff --git a/src/main/extern_binary.f90 b/src/main/extern_binary.f90 index d22725666..1602453fc 100644 --- a/src/main/extern_binary.f90 +++ b/src/main/extern_binary.f90 @@ -19,6 +19,7 @@ module extern_binary ! - accradius2 : *accretion radius of secondary (if iexternalforce=binary)* ! - eps_soft1 : *Plummer softening of primary* ! - eps_soft2 : *Plummer softening of secondary* +! - mass1 : *m1 of central binary system (if iexternalforce=binary)* ! - mass2 : *m2 of central binary system (if iexternalforce=binary)* ! - ramp : *ramp up mass of secondary over first 5 orbits?* ! @@ -234,6 +235,7 @@ subroutine write_options_externbinary(iunit) use infile_utils, only:write_inopt integer, intent(in) :: iunit + call write_inopt(mass1,'mass1','m1 of central binary system (if iexternalforce=binary)',iunit) call write_inopt(mass2,'mass2','m2 of central binary system (if iexternalforce=binary)',iunit) call write_inopt(accradius1,'accradius1','accretion radius of primary',iunit) call write_inopt(accradius2,'accradius2','accretion radius of secondary (if iexternalforce=binary)',iunit) @@ -259,6 +261,12 @@ subroutine read_options_externbinary(name,valstring,imatch,igotall,ierr) imatch = .true. igotall = .false. select case(trim(name)) + case('mass1') + read(valstring,*,iostat=ierr) mass1 + ngot = ngot + 1 + if (mass1 < 0.) then + call fatal(where,'invalid setting for m1 (<0)') + endif case('mass2') read(valstring,*,iostat=ierr) mass2 ngot = ngot + 1 diff --git a/src/main/extern_densprofile.f90 b/src/main/extern_densprofile.f90 index 407e50fae..d8fc59c21 100644 --- a/src/main/extern_densprofile.f90 +++ b/src/main/extern_densprofile.f90 @@ -137,13 +137,13 @@ subroutine read_rhotab(filename, rsize, rtab, rhotab, nread, polyk, gamma, rhoc, endif ! First line: # K gamma rhoc - read(iunit, *, iostat=ierr) hash,polyk, gamma, rhoc + read(iunit, *,iostat=ierr) hash,polyk, gamma, rhoc if (ierr /= 0) then call error('extern_densityprofile','Error reading first line of header from '//trim(filename)) return endif ! Second line: # nentries (number of r density entries in file) - read(iunit,*, iostat=ierr) hash,nread + read(iunit,*,iostat=ierr) hash,nread if (ierr /= 0) then call error('extern_densityprofile','Error reading second line of header from '//trim(filename)) return @@ -155,7 +155,7 @@ subroutine read_rhotab(filename, rsize, rtab, rhotab, nread, polyk, gamma, rhoc, endif ! Loop over 'n' lines: r and density separated by space do i = 1,nread - read(iunit,*, iostat=ierr) rtab(i), rhotab(i) + read(iunit,*,iostat=ierr) rtab(i), rhotab(i) if (ierr /= 0) then call error('extern_densityprofile','Error reading data from '//trim(filename)) return diff --git a/src/utils/moddump_radiotde.f90 b/src/utils/moddump_radiotde.f90 index ab4ab6bfe..28af40a44 100644 --- a/src/utils/moddump_radiotde.f90 +++ b/src/utils/moddump_radiotde.f90 @@ -14,7 +14,9 @@ module moddump ! ! :Runtime parameters: ! - ieos : *equation of state used* -! - ignore_radius : *tde particle inside this radius will be ignored* +! - ignore_radius : *ignore tde particle inside this radius (-ve = ignore all for injection)* +! - m_target : *target mass in circumnuclear gas cloud (in Msun) (-ve = ignore and use rho0)* +! - m_threshold : *threshold in solving rho0 for m_target (in Msun)* ! - mu : *mean molecular density of the cloud* ! - nbreak : *number of broken power laws* ! - nprof : *number of data points in the cloud profile* @@ -23,7 +25,7 @@ module moddump ! - rad_min : *inner radius of the circumnuclear gas cloud* ! - remove_overlap : *remove outflow particles overlap with circum particles* ! - rhof_n_1 : *power law index of the section* -! - rhof_rho0 : *density at rad_min (in g/cm^3)* +! - rhof_rho0 : *density at rad_min (in g/cm^3) (-ve = ignore and calc for m_target)* ! - temperature : *temperature of the gas cloud (-ve = read from file)* ! - use_func : *if use broken power law for density profile* ! @@ -32,7 +34,7 @@ module moddump ! implicit none public :: modify_dump - private :: rho,rho_tab,get_temp_r,uerg,calc_rhobreak,write_setupfile,read_setupfile + private :: rho,rho_tab,get_temp_r,uerg,calc_rhobreak,calc_rho0,write_setupfile,read_setupfile private integer :: ieos_in,nprof,nbreak,nbreak_old @@ -42,7 +44,7 @@ module moddump real, allocatable :: rhof_n(:),rhof_rbreak(:),rhof_rhobreak(:) real, allocatable :: rhof_n_in(:),rhof_rbreak_in(:) real, allocatable :: rad_prof(:),dens_prof(:) - real :: rhof_rho0 + real :: rhof_rho0,m_target,m_threshold logical :: use_func,use_func_old,remove_overlap contains @@ -53,9 +55,11 @@ module moddump ! !---------------------------------------------------------------- subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) - use physcon, only:solarm,years,mass_proton_cgs + use physcon, only:solarm,years,mass_proton_cgs,kb_on_mh,kboltz,radconst use setup_params, only:npart_total - use part, only:igas,set_particle_type,delete_particles_inside_radius,delete_particles_outside_sphere + use part, only:igas,set_particle_type,pxyzu,delete_particles_inside_radius, & + delete_particles_outside_sphere,kill_particle,shuffle_part, & + eos_vars,itemp,igamma,igasP use io, only:fatal,master,id use units, only:umass,udist,utime,set_units,unit_density use timestep, only:dtmax,tmax @@ -71,7 +75,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) real, intent(inout) :: massoftype(:) integer :: i,ierr,iunit=12,iprof integer :: np_sphere,npart_old - real :: totmass,delta,r + real :: totmass,delta,r,rhofr,presi character(len=120) :: fileset,fileprefix='radio' logical :: read_temp,setexists real, allocatable :: masstab(:),temp_prof(:) @@ -88,7 +92,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) !--Set default values temperature = 10. ! Temperature in Kelvin - mu = 2. ! mean molecular weight + mu = 1. ! mean molecular weight ieos_in = 2 ignore_radius = 1.e14 ! in cm use_func = .true. @@ -103,6 +107,9 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) allocate(rhof_n(nbreak),rhof_rbreak(nbreak)) rhof_n = -1.7 rhof_rbreak = rad_min + m_target = dot_product(npartoftype,massoftype)*umass/solarm + m_threshold = 1.e-3 + !--Profile default setups read_temp = .false. profile_filename = default_name @@ -138,7 +145,6 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) allocate(rhof_n(nbreak),rhof_rbreak(nbreak),rhof_rhobreak(nbreak)) rhof_n(:) = rhof_n_in(1:nbreak) rhof_rbreak(:) = rhof_rbreak_in(1:nbreak) - call calc_rhobreak() else if (temperature <= 0) read_temp = .true. rhof => rho_tab @@ -166,6 +172,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) endif ieos = ieos_in gmw = mu + write(*,'(a,1x,i2)') ' Using eos =', ieos !--Everything to code unit ignore_radius = ignore_radius/udist @@ -174,6 +181,8 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) rad_max = rad_max/udist rhof_rbreak = rhof_rbreak/udist rhof_rhobreak = rhof_rhobreak/unit_density + m_target = m_target*solarm/umass + m_threshold = m_threshold*solarm/umass else rad_prof = rad_prof/udist dens_prof = dens_prof/unit_density @@ -181,14 +190,34 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) rad_max = rad_prof(nprof) endif + !--Calc rho0 and rhobreak + if (use_func) then + if (rhof_rho0 < 0.) then + call calc_rho0(rhof) + elseif (m_target < 0.) then + call calc_rhobreak() + else + call fatal('moddump','Must give rho0 or m_target') + endif + endif + !--remove unwanted particles - npart_old = npart - call delete_particles_inside_radius((/0.,0.,0./),ignore_radius,npart,npartoftype) - write(*,'(I10,1X,A23,1X,E8.2,1X,A14)') npart_old - npart, 'particles inside radius', ignore_radius*udist, 'cm are deleted' - npart_old = npart - if (remove_overlap) then - call delete_particles_outside_sphere((/0.,0.,0./),rad_min,npart) - write(*,'(I10,1X,A24,1X,E8.2,1X,A14)') npart_old - npart, 'particles outside radius', rad_min*udist, 'cm are deleted' + if (ignore_radius > 0) then + npart_old = npart + call delete_particles_inside_radius((/0.,0.,0./),ignore_radius,npart,npartoftype) + write(*,'(I10,1X,A23,1X,E8.2,1X,A14)') npart_old - npart, 'particles inside radius', ignore_radius*udist, 'cm are deleted' + npart_old = npart + if (remove_overlap) then + call delete_particles_outside_sphere((/0.,0.,0./),rad_min,npart) + write(*,'(I10,1X,A24,1X,E8.2,1X,A14)') npart_old - npart, 'particles outside radius', rad_min*udist, 'cm are deleted' + npart_old = npart + endif + else + write(*,'(a)') ' Ignore all TDE particles' + do i = 1,npart + call kill_particle(i,npartoftype) + enddo + call shuffle_part(npart) npart_old = npart endif @@ -204,14 +233,21 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) !--Set particle properties do i = npart_old+1,npart call set_particle_type(i,igas) - r = dot_product(xyzh(1:3,i),xyzh(1:3,i)) + r = sqrt(dot_product(xyzh(1:3,i),xyzh(1:3,i))) + rhofr = rhof(r) if (read_temp) temperature = get_temp_r(r,rad_prof,temp_prof) - vxyzu(4,i) = uerg(rhof(r),temperature) + vxyzu(4,i) = uerg(rhofr,temperature,ieos) vxyzu(1:3,i) = 0. ! stationary for now + pxyzu(4,i) = entropy(rhofr,temperature,ieos) + pxyzu(1:3,i) = 0. + eos_vars(itemp,i) = temperature + presi = pressure(rhofr,temperature,ieos) + eos_vars(igamma,i) = 1. + presi/(rhofr*vxyzu(4,i)) enddo + if (ieos == 12) write(*,'(a,1x,f10.4)') ' Mean gamma =', sum(eos_vars(igamma,npart_old+1:npart))/(npart - npart_old) !--Set timesteps - tmax = 10.*years/utime + tmax = 3.*years/utime dtmax = tmax/1000. end subroutine modify_dump @@ -282,19 +318,60 @@ real function get_temp_r(r,rad_prof,temp_prof) end function get_temp_r -real function uerg(rho,T) +real function uerg(rho,T,ieos) use physcon, only:kb_on_mh,radconst use units, only:unit_density,unit_ergg real, intent(in) :: rho,T + integer, intent(in) :: ieos real :: ucgs_gas,ucgs_rad,rhocgs rhocgs = rho*unit_density ucgs_gas = 1.5*kb_on_mh*T/mu - ucgs_rad = 0. !radconst*T**4/rhocgs + if (ieos == 12) then + ucgs_rad = radconst*T**4/rhocgs + else + ucgs_rad = 0. !radconst*T**4/rhocgs + endif uerg = (ucgs_gas+ucgs_rad)/unit_ergg end function uerg +real function entropy(rho,T,ieos) + use physcon, only:kb_on_mh,radconst,kboltz + use units, only:unit_density,unit_ergg + real, intent(in) :: rho,T + integer, intent(in) :: ieos + real :: ent_gas,ent_rad,rhocgs + + rhocgs = rho*unit_density + ent_gas = kb_on_mh/mu*log(T**1.5/rhocgs) + if (ieos == 12) then + ent_rad = 4.*radconst*T**3/(3.*rhocgs) + else + ent_rad = 0. + endif + entropy = (ent_gas+ent_rad)/kboltz/ unit_ergg + +end function entropy + +real function pressure(rho,T,ieos) + use physcon, only:kb_on_mh,radconst + use units, only:unit_density,unit_pressure + real, intent(in) :: rho,T + integer, intent(in) :: ieos + real :: p_gas,p_rad,rhocgs + + rhocgs = rho*unit_density + p_gas = rhocgs*kb_on_mh*T/mu + if (ieos == 12) then + p_rad = radconst*T**4/3. + else + p_rad = 0. + endif + pressure = (p_gas+p_rad)/ unit_pressure + +end function pressure + subroutine calc_rhobreak() integer :: i @@ -307,6 +384,33 @@ subroutine calc_rhobreak() end subroutine calc_rhobreak +subroutine calc_rho0(rhof) + use units, only:unit_density + use stretchmap, only:get_mass_r + procedure(rho), pointer, intent(in) :: rhof + real :: rho0_min,rho0_max,totmass + integer :: iter + + rho0_min = 0. + rho0_max = 1. + totmass = -1. + iter = 0 + + do while (abs(totmass - m_target) > m_threshold) + rhof_rho0 = 0.5*(rho0_min + rho0_max) + call calc_rhobreak() + totmass = get_mass_r(rhof,rad_max,rad_min) + if (totmass > m_target) then + rho0_max = rhof_rho0 + else + rho0_min = rhof_rho0 + endif + iter = iter + 1 + enddo + write(*,'(a11,1x,es10.2,1x,a12,1x,i3,1x,a10)') ' Get rho0 =', rhof_rho0*unit_density, 'g/cm^-3 with', iter, 'iterations' + +end subroutine + !---------------------------------------------------------------- !+ ! write parameters to setup file @@ -324,14 +428,16 @@ subroutine write_setupfile(filename) write(iunit,"(a)") '# input file for setting up a circumnuclear gas cloud' write(iunit,"(/,a)") '# geometry' - call write_inopt(ignore_radius,'ignore_radius','tde particle inside this radius will be ignored',iunit) + call write_inopt(ignore_radius,'ignore_radius','ignore tde particle inside this radius (-ve = ignore all for injection)',iunit) call write_inopt(remove_overlap,'remove_overlap','remove outflow particles overlap with circum particles',iunit) call write_inopt(use_func,'use_func','if use broken power law for density profile',iunit) if (use_func) then call write_inopt(rad_min,'rad_min','inner radius of the circumnuclear gas cloud',iunit) call write_inopt(rad_max,'rad_max','outer radius of the circumnuclear gas cloud',iunit) write(iunit,"(/,a)") '# density broken power law' - call write_inopt(rhof_rho0,'rhof_rho0','density at rad_min (in g/cm^3)',iunit) + call write_inopt(rhof_rho0,'rhof_rho0','density at rad_min (in g/cm^3) (-ve = ignore and calc for m_target)',iunit) + call write_inopt(m_target,'m_target','target mass in circumnuclear gas cloud (in Msun) (-ve = ignore and use rho0)',iunit) + call write_inopt(m_threshold,'m_threshold','threshold in solving rho0 for m_target (in Msun)',iunit) call write_inopt(nbreak,'nbreak','number of broken power laws',iunit) write(iunit,"(/,a)") '# section 1 (from rad_min)' call write_inopt(rhof_n(1),'rhof_n_1','power law index of the section',iunit) @@ -386,7 +492,9 @@ subroutine read_setupfile(filename,ierr) if (use_func) then call read_inopt(rad_min,'rad_min',db,min=ignore_radius,err=ierr) call read_inopt(rad_max,'rad_max',db,min=rad_min,err=ierr) - call read_inopt(rhof_rho0,'rhof_rho0',db,min=0.,err=ierr) + call read_inopt(rhof_rho0,'rhof_rho0',db,err=ierr) + call read_inopt(m_target,'m_target',db,err=ierr) + call read_inopt(m_threshold,'m_threshold',db,err=ierr) call read_inopt(nbreak,'nbreak',db,min=1,err=ierr) allocate(rhof_rbreak_in(in_num),rhof_n_in(in_num)) call read_inopt(rhof_n_in(1),'rhof_n_1',db,err=ierr) diff --git a/src/utils/phantomanalysis.f90 b/src/utils/phantomanalysis.f90 index a0b88c2d2..94ccc3695 100644 --- a/src/utils/phantomanalysis.f90 +++ b/src/utils/phantomanalysis.f90 @@ -14,8 +14,8 @@ program phantomanalysis ! ! :Usage: phantomanalysis dumpfile(s) ! -! :Dependencies: analysis, dim, eos, fileutils, infile_utils, io, kernel, -! part, readwrite_dumps +! :Dependencies: analysis, dim, eos, externalforces, fileutils, +! infile_utils, io, kernel, part, readwrite_dumps ! use dim, only:tagline,do_nucleation,inucleation use part, only:xyzh,hfact,massoftype,vxyzu,npart !,npartoftype @@ -26,6 +26,7 @@ program phantomanalysis use analysis, only:do_analysis,analysistype use eos, only:ieos use kernel, only:hfact_default + use externalforces, only:mass1,accradius1 implicit none integer :: nargs,iloc,ierr,iarg,i,idust_opacity real :: time @@ -76,6 +77,8 @@ program phantomanalysis do_nucleation = .true. inucleation = 1 endif + call read_inopt(mass1,'mass1',db,ierr) + call read_inopt(accradius1,'accradius1',db,ierr) call close_db(db) close(ianalysis) endif From cc61452d00a529f3c9f840bbeab7278f3952c22f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 8 Jul 2024 10:10:04 +0100 Subject: [PATCH 128/182] Adds upstream changes --- build/Makefile_systems | 5 + src/main/eos_mesa_microphysics.f90 | 8 +- src/main/extern_gr.f90 | 2 +- src/main/externalforces_gr.f90 | 6 +- src/utils/analysis_tdeoutflow.f90 | 290 +++++++++++++++++++++++++++ src/utils/analysis_velocityshear.f90 | 16 +- src/utils/analysis_write_kdtree.F90 | 12 +- 7 files changed, 317 insertions(+), 22 deletions(-) create mode 100644 src/utils/analysis_tdeoutflow.f90 diff --git a/build/Makefile_systems b/build/Makefile_systems index d38bd096e..4a3c950f3 100644 --- a/build/Makefile_systems +++ b/build/Makefile_systems @@ -179,6 +179,11 @@ ifeq ($(SYSTEM), ifort) include Makefile_defaults_ifort endif +ifeq ($(SYSTEM), ifx) +# default settings for the new Intel Fortran Compiler + include Makefile_defaults_ifx +endif + ifeq ($(SYSTEM), ifortmac) # default settings for the Intel Fortran Compiler on Mac OS include Makefile_defaults_ifort diff --git a/src/main/eos_mesa_microphysics.f90 b/src/main/eos_mesa_microphysics.f90 index aa9268c13..903fef912 100644 --- a/src/main/eos_mesa_microphysics.f90 +++ b/src/main/eos_mesa_microphysics.f90 @@ -69,7 +69,7 @@ subroutine get_opacity_constants_mesa opacs_file = find_phantom_datafile(filename,'eos/mesa') ! Read the constants from the header of the opacity file - open(newunit=fnum, file=trim(opacs_file), status='old', action='read', form='unformatted') + open(newunit=fnum,file=trim(opacs_file),status='old',action='read',form='unformatted') read(fnum) mesa_opacs_nz,mesa_opacs_nx,mesa_opacs_nr,mesa_opacs_nt close(fnum) @@ -102,7 +102,7 @@ subroutine read_opacity_mesa(x,z) filename = trim(mesa_opacs_dir)//'opacs'//trim(mesa_opacs_suffix)//'.bindata' ! filename = trim(mesa_opacs_dir)//'/'//'opacs'//trim(mesa_opacs_suffix)//'.bindata' opacs_file = find_phantom_datafile(filename,'eos/mesa') - open(unit=fnum, file=trim(opacs_file), status='old', action='read', form='unformatted') + open(unit=fnum,file=trim(opacs_file),status='old',action='read',form='unformatted') read(fnum) mesa_opacs_nz,mesa_opacs_nx,mesa_opacs_nr,mesa_opacs_nt ! Read in the size of the table and the data @@ -308,7 +308,7 @@ subroutine get_eos_constants_mesa(ierr) filename = find_phantom_datafile(filename,'eos/mesa') ! Read constants from the header of first EoS tables - open(unit=fnum, file=trim(filename), status='old', action='read', form='unformatted',iostat=ierr) + open(unit=fnum,file=trim(filename),status='old',action='read',form='unformatted',iostat=ierr) if (ierr /= 0) return read(fnum) mesa_eos_ne, mesa_eos_nv, mesa_eos_nvar2 close(fnum) @@ -364,7 +364,7 @@ subroutine read_eos_mesa(x,z,ierr) ! Read in the size of the tables and the data ! i and j hold the Z and X values respectively ! k, l and m hold the values of V, Eint and the data respectively - open(unit=fnum, file=trim(filename), status='old', action='read', form='unformatted') + open(unit=fnum,file=trim(filename),status='old',action='read',form='unformatted') read(fnum) mesa_eos_ne, mesa_eos_nv, mesa_eos_nvar2 read(fnum)(mesa_eos_logVs(k),k=1,mesa_eos_nv) read(fnum)(mesa_eos_logEs(l),l=1,mesa_eos_ne) diff --git a/src/main/extern_gr.f90 b/src/main/extern_gr.f90 index 3d3aacdb2..7043299e2 100644 --- a/src/main/extern_gr.f90 +++ b/src/main/extern_gr.f90 @@ -13,7 +13,7 @@ module extern_gr ! Liptai & Price (2019), MNRAS 485, 819 ! Magnall, Price, Lasky & Macpherson (2023), Phys. Rev D. 108, 103534 ! -! :Owner: Spencer Magnall +! :Owner: David Liptai ! ! :Runtime parameters: None ! diff --git a/src/main/externalforces_gr.f90 b/src/main/externalforces_gr.f90 index 562660310..4219f96ae 100644 --- a/src/main/externalforces_gr.f90 +++ b/src/main/externalforces_gr.f90 @@ -27,7 +27,7 @@ module externalforces public :: accrete_particles,was_accreted public :: write_options_externalforces,read_options_externalforces public :: initialise_externalforces,is_velocity_dependent - public :: update_vdependent_extforce_leapfrog + public :: update_vdependent_extforce public :: update_externalforce public :: write_headeropts_extern,read_headeropts_extern @@ -124,7 +124,7 @@ end subroutine externalforce_vdependent ! necessary for using v-dependent forces in leapfrog !+ !----------------------------------------------------------------------- -subroutine update_vdependent_extforce_leapfrog(iexternalforce, & +subroutine update_vdependent_extforce(iexternalforce, & vhalfx,vhalfy,vhalfz,fxi,fyi,fzi,fexti,dt,xi,yi,zi,densi,ui) integer, intent(in) :: iexternalforce real, intent(in) :: dt,xi,yi,zi @@ -136,7 +136,7 @@ subroutine update_vdependent_extforce_leapfrog(iexternalforce, & ! ! This doesn't doesn't actually get used in gr... ! -end subroutine update_vdependent_extforce_leapfrog +end subroutine update_vdependent_extforce !----------------------------------------------------------------------- !+ diff --git a/src/utils/analysis_tdeoutflow.f90 b/src/utils/analysis_tdeoutflow.f90 new file mode 100644 index 000000000..3012ee514 --- /dev/null +++ b/src/utils/analysis_tdeoutflow.f90 @@ -0,0 +1,290 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module analysis +! +! Computes the outflow profile in a TDE simulation +! +! :References: None +! +! :Owner: Fitz) Hu +! +! :Runtime parameters: +! - phi_max : *max phi (in deg) (-ve = ignore)* +! - phi_min : *min phi (in deg) (-ve = ignore)* +! - r_in : *radius to count outflow (in cm)* +! - theta_max : *max theta (in deg) (-ve = ignore)* +! - theta_min : *min theta (in deg) (-ve = ignore)* +! +! :Dependencies: infile_utils, io, part, physcon, readwrite_dumps, units +! + implicit none + character(len=10), parameter, public :: analysistype = 'tdeoutflow' + public :: do_analysis + + private + + character(len=7) :: ana + real, dimension(:), allocatable :: rad_all,vr_all,v_all + real, dimension(:), allocatable :: theta,plot_theta,phi,vr,vtheta,vphi + logical, dimension(:), allocatable :: cap + real :: m_accum, m_cap + real :: vr_accum_mean, vr_accum_max, vr_cap_mean, vr_cap_max + real :: r_accum_maxv, r_cap_maxv + real :: v_accum_mean, v_cap_mean + real :: e_accum, e_cap + integer :: n_accum, n_cap + real :: shock_v, rad_min, rad_max, shock_e, shock_m!, shock_rho + real :: shock_v_tde, rad_min_tde, rad_max_tde, shock_e_tde, shock_m_tde!, shock_rho + real :: shock_v_cnm, rad_min_cnm, rad_max_cnm, shock_e_cnm, shock_m_cnm!, shock_rho + + !---- These can be changed in the params file + real :: rad_cap = 1.e16 ! radius where the outflow in captured (in cm) + real :: drad_cap = 4.7267e14 ! thickness of the shell to capture outflow (in cm) + real :: v_min = 0. + real :: v_max = 1. + real :: theta_min = -180. + real :: theta_max = 180. + real :: phi_min = -90. + real :: phi_max = 90. + + !--- shock detection global var + integer :: npart_cnm = -1, npart_tde, npart_tde_reserve=-1 + real, allocatable :: ent_bg(:) + logical, allocatable :: counted(:),accreted(:) + real :: told,r_in=1.e14 + logical :: first = .true. + +contains + +subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) + use readwrite_dumps, only: opened_full_dump + use units, only: udist,utime,unit_energ,umass!,unit_density + use physcon, only: solarm,days,c + use part, only: pxyzu + character(len=*), intent(in) :: dumpfile + integer, intent(in) :: numfile,npart,iunit + real, intent(in) :: xyzh(:,:),vxyzu(:,:) + real, intent(in) :: pmass,time + character(len=120) :: output + character(len=30) :: filename,outfile + integer :: i,ierr,npart_new,npart_tde_old + logical :: iexist + real :: toMsun,todays,dt + real :: mout,vrout,vout,macc + + toMsun = umass/solarm + todays = utime/days + + if (.not.opened_full_dump) then + write(*,'("SKIPPING FILE -- (Not a full dump)")') + return + endif + +! Print the analysis being done + write(*,'(" Performing analysis type ",A)') analysistype + write(*,'(" Input file name is ",A)') dumpfile + + ! Read black hole mass from params file + filename = 'analysis_'//trim(analysistype)//'.params' + inquire(file=filename,exist=iexist) + if (iexist) call read_tdeparams(filename,ierr) + if (.not.iexist.or.ierr/=0) then + call write_tdeparams(filename) + print*,' Edit '//trim(filename)//' and rerun phantomanalysis' + stop + endif + + ! input to code unit + r_in = r_in / udist + + ! allocate memory + if (allocated(rad_all)) deallocate(rad_all(npart),vr_all(npart),v_all(npart)) + allocate(rad_all(npart),vr_all(npart),v_all(npart)) + call to_rad(npart,xyzh,vxyzu,rad_all,vr_all,v_all) + + write(*,'(a)') ' Analysing the outflow ...' + + print*, 'Counting outflow from', r_in + + if (first) then + allocate(counted(npart),accreted(npart)) + counted = .false. + accreted = .false. + mout = 0. + vrout = 0. + vout = 0. + macc = 0. + dt = 1. + else + call outflow_analysis(npart,pmass,xyzh,vxyzu,rad_all,vr_all,v_all,mout,vrout,vout,macc) + dt = time - told + endif + told = time + + outfile='outflow' + inquire(file=outfile,exist=iexist) + if (iexist .and. .not. first) then + open(iunit,file=outfile,status='old',access='append') + elseif (iexist) then + open(iunit,file=outfile,status='replace') + else + open(iunit,file=outfile,status='new') + endif + + if (first) then + write(iunit,"('#',5(1x,'[',i2.2,1x,a11,']',2x))") & + 1,'time [s]', & + 2,'mout [g/s]', & + 3,'vrout [cm/s]', & + 4,'vout [cm/s]', & + 5,'macc [g/s]' + endif + + write(iunit,'(5(es18.10,1X))') & + time*utime, & + mout/dt*umass/utime, & + vrout, & + vout, & + macc/dt*umass/utime + close(iunit) + first = .false. + +end subroutine do_analysis + +subroutine to_rad(npart,xyzh,vxyzu,rad,vr,v) + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:),vxyzu(:,:) + real, intent(out) :: rad(:),vr(:),v(:) + integer :: i + real :: xyz(1:3),vxyz(1:3) + + do i = 1,npart + xyz = xyzh(1:3,i) + vxyz = vxyzu(1:3,i) + rad(i) = sqrt(dot_product(xyz,xyz)) + vr(i) = dot_product(xyz,vxyz)/rad(i) + v(i) = sqrt(dot_product(vxyz,vxyz)) + enddo + +end subroutine to_rad +!-------------------------------------------------------------------------------------------------------------------- +! +!-- Actual subroutine where the analysis is done! +! +!-------------------------------------------------------------------------------------------------------------------- +subroutine outflow_analysis(npart,pmass,xyzh,vxyzu,rad_all,vr_all,v_all,mout,vrout,vout,macc) + use io, only: fatal + use part, only:isdead_or_accreted + integer, intent(in) :: npart + real, intent(in) :: pmass,xyzh(:,:),vxyzu(:,:),rad_all(:),vr_all(:),v_all(:) + real, intent(out) :: mout,vrout,vout,macc + integer :: i,nout,nacc + real :: ri,vi,x,y,z + real :: thetai,phii,vri + real :: vrsum,vsum + + nout = 0 + nacc = 0 + vrsum = 0. + vsum = 0. + + do i = 1,npart + ri = rad_all(i) + vi = v_all(i) + vri = vr_all(i) + if (isdead_or_accreted(xyzh(4,i))) then + nacc = nacc + 1 + accreted(i) = .true. + elseif (ri > r_in) then + if (.not. counted(i)) then + if (theta_min < -180. .or. theta_min > 180.) theta_min = -180. + if (theta_max < theta_min .or. theta_max > 180.) theta_max = 180. + if (phi_min < -90. .or. phi_min > 90.) phi_min = -90. + if (phi_max < phi_min .or. phi_max > 90.) phi_max = 90. + + x = xyzh(1,i) + y = xyzh(2,i) + z = xyzh(3,i) + thetai = atan2d(y,x) + phii = atan2d(z,sqrt(x**2+y**2)) + + if ((thetai >= theta_min .and. thetai <= theta_max) .and. (phii >= phi_min .and. phii <= phi_max)) then + nout = nout + 1 + vrsum = vrsum + vri + vsum = vsum + vi + endif + counted(i) = .true. + endif + else + counted(i) = .false. + endif + enddo + mout = nout * pmass + vrout = vrsum / nout + vout = vsum / nout + macc = nacc * pmass + +end subroutine outflow_analysis + +!---------------------------------------------------------------- +!+ +! Read/write tde information from/to params file +!+ +!---------------------------------------------------------------- +subroutine write_tdeparams(filename) + use infile_utils, only:write_inopt + character(len=*), intent(in) :: filename + integer, parameter :: iunit = 20 + + print "(a)",' writing analysis options file '//trim(filename) + open(unit=iunit,file=filename,status='replace',form='formatted') + write(iunit,"(a,/)") '# options when performing TDE outflow analysis' + + call write_inopt(r_in,'r_in','radius to count outflow (in cm)',iunit) + + call write_inopt(theta_min,'theta_min','min theta (in deg) (-ve = ignore)',iunit) + call write_inopt(theta_max,'theta_max','max theta (in deg) (-ve = ignore)',iunit) + + call write_inopt(phi_min,'phi_min','min phi (in deg) (-ve = ignore)',iunit) + call write_inopt(phi_max,'phi_max','max phi (in deg) (-ve = ignore)',iunit) + + close(iunit) + +end subroutine write_tdeparams + +subroutine read_tdeparams(filename,ierr) + use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db + use io, only:error + character(len=*), intent(in) :: filename + integer, intent(out) :: ierr + integer, parameter :: iunit = 21 + integer :: nerr + type(inopts), allocatable :: db(:) + + print "(a)",' reading analysis options from '//trim(filename) + nerr = 0 + ierr = 0 + call open_db_from_file(db,filename,iunit,ierr) + + call read_inopt(r_in,'r_in',db,min=0.,errcount=nerr) + + call read_inopt(theta_min,'theta_min',db,max=360.,errcount=nerr) + call read_inopt(theta_max,'theta_max',db,max=360.,errcount=nerr) + + call read_inopt(phi_min,'phi_min',db,max=180.,errcount=nerr) + call read_inopt(phi_max,'phi_max',db,max=180.,errcount=nerr) + + call close_db(db) + if (nerr > 0) then + print "(1x,i2,a)",nerr,' error(s) during read of params file: re-writing...' + ierr = nerr + endif + +end subroutine read_tdeparams + +end module analysis + diff --git a/src/utils/analysis_velocityshear.f90 b/src/utils/analysis_velocityshear.f90 index 16637d2d6..da5209758 100644 --- a/src/utils/analysis_velocityshear.f90 +++ b/src/utils/analysis_velocityshear.f90 @@ -70,11 +70,11 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! Check if a neighbour file is present - neighbourfile = 'neigh_'//TRIM(dumpfile) + neighbourfile = 'neigh_'//trim(dumpfile) inquire(file=neighbourfile,exist = existneigh) if (existneigh.eqv..true.) then - print*, 'Neighbour file ', TRIM(neighbourfile), ' found' + print*, 'Neighbour file ', trim(neighbourfile), ' found' call read_neighbours(neighbourfile,npart) else @@ -158,8 +158,8 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) write(fmtstring, "('(I',I1,')')") ndigits write(numstring, fmtstring) num - valuefile = 'eig0'//TRIM(numstring) - vectorfile = 'evc0'//TRIM(numstring) + valuefile = 'eig0'//trim(numstring) + vectorfile = 'evc0'//trim(numstring) call write_eigenfiles(valuefile,vectorfile, iwrite) @@ -516,8 +516,8 @@ subroutine write_eigenfiles(valuefile,vectorfile, ngas) ! Write eigenvalues to file - print*, 'Writing eigenvalues to file ', TRIM(valuefile) - open(27,file=TRIM(valuefile), status='unknown',form='unformatted') + print*, 'Writing eigenvalues to file ', trim(valuefile) + open(27,file=trim(valuefile),status='unknown',form='unformatted') write(27) ngas write(27) (eigenpart(i),i=1,ngas) write(27) (xbin(i), i=1,ngas) @@ -529,8 +529,8 @@ subroutine write_eigenfiles(valuefile,vectorfile, ngas) close(27) ! Now write the eigenvectors to file - print*, 'Writing eigenvectors to file ', TRIM(vectorfile) - open(27,file=TRIM(vectorfile),status='unknown', form='unformatted') + print*, 'Writing eigenvectors to file ', trim(vectorfile) + open(27,file=trim(vectorfile),status='unknown',form='unformatted') write(27) ngas write(27) (eigenpart(i),i=1,ngas) write(27) (eigenvectors(1,1:3,i),i=1,ngas) diff --git a/src/utils/analysis_write_kdtree.F90 b/src/utils/analysis_write_kdtree.F90 index a185c915d..f27f4d623 100644 --- a/src/utils/analysis_write_kdtree.F90 +++ b/src/utils/analysis_write_kdtree.F90 @@ -78,8 +78,8 @@ subroutine write_kdtree_file(dumpfile) character(100) :: treefile integer :: icell - treefile = 'kdtree_'//TRIM(dumpfile) - print'(a,a)', 'Writing kdtree to binary file ', TRIM(treefile) + treefile = 'kdtree_'//trim(dumpfile) + print'(a,a)', 'Writing kdtree to binary file ', trim(treefile) ! Write tag indicating if this is from a run with or without gravity #ifdef GRAVITY @@ -90,7 +90,7 @@ subroutine write_kdtree_file(dumpfile) print '(a,a,I7)', 'This file does not contains masses: ', filetag, ncells #endif - open(10,file=treefile, form='unformatted') + open(10,file=treefile,form='unformatted') ! Write header data write(10) filetag, ncells @@ -131,10 +131,10 @@ subroutine read_kdtree_file(dumpfile) character(7) :: filetag character(100) :: treefile - treefile = 'kdtree_'//TRIM(dumpfile) - print'(a,a)', 'Reading kdtree from binary file ', TRIM(treefile) + treefile = 'kdtree_'//trim(dumpfile) + print'(a,a)', 'Reading kdtree from binary file ', trim(treefile) - open(10,file=treefile, form='unformatted') + open(10,file=treefile,form='unformatted') ! Read header read(10) filetag, ncells From 6913b19b5c37833351ac24b0460e1ac1c0e1da93 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 8 Jul 2024 10:15:09 +0100 Subject: [PATCH 129/182] Adds upstream changes --- src/main/forcing.F90 | 4 +- src/main/initial.F90 | 23 +- src/main/inject_BHL.f90 | 7 +- .../analysis_collidingcloudhistograms.f90 | 12 +- src/utils/analysis_dustywind.f90 | 348 ++++++++++++++++ src/utils/analysis_energies.f90 | 63 +++ src/utils/analysis_polytropes.f90 | 6 +- src/utils/analysis_prdrag.f90 | 6 +- src/utils/analysis_radiotde.f90 | 379 +++++++++++++----- 9 files changed, 734 insertions(+), 114 deletions(-) create mode 100644 src/utils/analysis_dustywind.f90 create mode 100644 src/utils/analysis_energies.f90 diff --git a/src/main/forcing.F90 b/src/main/forcing.F90 index 878e88f86..a0db37a7a 100644 --- a/src/main/forcing.F90 +++ b/src/main/forcing.F90 @@ -1076,8 +1076,8 @@ subroutine read_stirring_data_from_file(infile, time, timeinfile) my_file = find_phantom_datafile(infile,'forcing') - open (unit=42, file=my_file, iostat=ierr, status='old', action='read', & - access='sequential', form='unformatted') + open(unit=42,file=my_file,iostat=ierr,status='old',action='read', & + access='sequential',form='unformatted') ! header contains number of times and number of modes, end time, autocorrelation time, ... if (ierr==0) then if (Debug) write (*,'(A)') 'reading header...' diff --git a/src/main/initial.F90 b/src/main/initial.F90 index 314b72644..4c9a97aa2 100644 --- a/src/main/initial.F90 +++ b/src/main/initial.F90 @@ -22,7 +22,7 @@ module initial ! krome_interface, linklist, metric_tools, mf_write, mpibalance, ! mpidomain, mpimemory, mpitree, mpiutils, nicil, nicil_sup, omputils, ! options, part, partinject, porosity, ptmass, radiation_utils, -! readwrite_dumps, readwrite_infile, timestep, timestep_ind, +! readwrite_dumps, readwrite_infile, subgroup, timestep, timestep_ind, ! timestep_sts, timing, tmunu2grid, units, writeheader ! @@ -127,10 +127,11 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) use part, only:npart,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,Bevol,dBevol,tau, tau_lucy, & npartoftype,maxtypes,ndusttypes,alphaind,ntot,ndim,update_npartoftypetot,& maxphase,iphase,isetphase,iamtype,igas,idust,imu,igamma,massoftype, & - nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,& + nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,fxyz_ptmass_sinksink,& epot_sinksink,get_ntypes,isdead_or_accreted,dustfrac,ddustevol,& nden_nimhd,dustevol,rhoh,gradh, & - Bevol,Bxyz,dustprop,filfac,ddustprop,ndustsmall,iboundary,eos_vars,dvdx + Bevol,Bxyz,dustprop,filfac,ddustprop,ndustsmall,iboundary,eos_vars,dvdx, & + n_group,n_ingroup,n_sing,nmatrix,group_info use part, only:pxyzu,dens,metrics,rad,radprop,drad,ithick use densityforce, only:densityiterate use linklist, only:set_linklist @@ -150,7 +151,8 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) use nicil_sup, only:use_consistent_gmw use ptmass, only:init_ptmass,get_accel_sink_gas,get_accel_sink_sink, & h_acc,r_crit,r_crit2,rho_crit,rho_crit_cgs,icreate_sinks, & - r_merge_uncond,r_merge_cond,r_merge_uncond2,r_merge_cond2,r_merge2 + r_merge_uncond,r_merge_cond,r_merge_uncond2,r_merge_cond2,r_merge2, & + use_regnbody use timestep, only:time,dt,dtextforce,C_force,dtmax,dtmax_user,idtmax_n use timing, only:get_timings use timestep_ind, only:ibinnow,maxbins,init_ibin,istepfrac @@ -210,6 +212,7 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) use checkconserved, only:get_conserv,etot_in,angtot_in,totmom_in,mdust_in use fileutils, only:make_tags_unique use damping, only:idamp + use subgroup, only:group_identify character(len=*), intent(in) :: infile character(len=*), intent(out) :: logfile,evfile,dumpfile logical, intent(in), optional :: noread @@ -495,10 +498,15 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) endif if (nptmass > 0) then if (id==master) write(iprint,"(a,i12)") ' nptmass = ',nptmass - ! compute initial sink-sink forces and get timestep - call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,dtsinksink,& + if (use_regnbody) then + call group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix) + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,dtsinksink,& + iexternalforce,time,merge_ij,merge_n,dsdt_ptmass,group_info=group_info) + else + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,dtsinksink,& iexternalforce,time,merge_ij,merge_n,dsdt_ptmass) + endif dtsinksink = C_force*dtsinksink if (id==master) write(iprint,*) 'dt(sink-sink) = ',dtsinksink dtextforce = min(dtextforce,dtsinksink) @@ -538,6 +546,9 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) if (r_merge_uncond < 2.0*h_acc) then write(iprint,*) ' WARNING! Sink creation is on, but but merging is off! Suggest setting r_merge_uncond >= 2.0*h_acc' endif + dsdt_ptmass = 0. ! could introduce NaN in ptmass spins if not initialised (no get_accel done before creating sink) + fxyz_ptmass = 0. + fxyz_ptmass_sinksink = 0. endif if (abs(time) <= tiny(0.)) then !initialize nucleation array at the start of the run only diff --git a/src/main/inject_BHL.f90 b/src/main/inject_BHL.f90 index 860dcf058..a23162cc0 100644 --- a/src/main/inject_BHL.f90 +++ b/src/main/inject_BHL.f90 @@ -30,7 +30,7 @@ module inject character(len=*), parameter, public :: inject_type = 'BHL' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par ! !--runtime settings for this module ! @@ -261,6 +261,11 @@ subroutine inject_or_update_particles(ifirst, n, position, velocity, h, u, bound end subroutine inject_or_update_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Writes input options to the input file diff --git a/src/utils/analysis_collidingcloudhistograms.f90 b/src/utils/analysis_collidingcloudhistograms.f90 index c17daaddb..11345d4ce 100644 --- a/src/utils/analysis_collidingcloudhistograms.f90 +++ b/src/utils/analysis_collidingcloudhistograms.f90 @@ -63,8 +63,8 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! ! Initialise values & Open file ! - fileoutSV = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_SinkVel.dat' - fileoutSA = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_SinkAverages.dat' + fileoutSV = trim(dumpfile(1:index(dumpfile,'_')-1))//'_SinkVel.dat' + fileoutSA = trim(dumpfile(1:index(dumpfile,'_')-1))//'_SinkAverages.dat' inquire(file=fileoutSV,exist=iexist) if ( .not.iexist .or. firstcall ) then firstcall = .false. @@ -117,7 +117,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) 7,'vy', & 8,'vz' do k = 1,nres - write(fileoutSH,'(2a,I3.3,a)') trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_SinkHisto',nbins(k),'.dat' + write(fileoutSH,'(2a,I3.3,a)') trim(dumpfile(1:index(dumpfile,'_')-1)),'_SinkHisto',nbins(k),'.dat' open(iunit+(2*k+1),file=fileoutSH,status='replace') write(iunit+(2*k+1),"('#',10(1x,'[',i2.2,1x,a11,']',2x))") & 1,'idump', & @@ -130,7 +130,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) 8,'N velx', & 9,'N vely', & 10,'N velz' - write(fileoutGH,'(2a,I3.3,a)') trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_GasHisto',nbins(k),'.dat' + write(fileoutGH,'(2a,I3.3,a)') trim(dumpfile(1:index(dumpfile,'_')-1)),'_GasHisto',nbins(k),'.dat' open(iunit+(2*k+2),file=fileoutGH,status='replace') write(iunit+(2*k+2),"('#',10(1x,'[',i2.2,1x,a11,']',2x))") & 1,'idump', & @@ -162,8 +162,8 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) open(iunit ,file=fileoutSV,position='append') open(iunit+20,file=fileoutSA,position='append') do k = 1,nres - write(fileoutSH,'(2a,I3.3,a)') trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_SinkHisto',nbins(k),'.dat' - write(fileoutGH,'(2a,I3.3,a)') trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_GasHisto',nbins(k),'.dat' + write(fileoutSH,'(2a,I3.3,a)') trim(dumpfile(1:index(dumpfile,'_')-1)),'_SinkHisto',nbins(k),'.dat' + write(fileoutGH,'(2a,I3.3,a)') trim(dumpfile(1:index(dumpfile,'_')-1)),'_GasHisto',nbins(k),'.dat' open(iunit+(2*k+1),file=fileoutSH,position='append') open(iunit+(2*k+2),file=fileoutGH,position='append') enddo diff --git a/src/utils/analysis_dustywind.f90 b/src/utils/analysis_dustywind.f90 new file mode 100644 index 000000000..74f071edb --- /dev/null +++ b/src/utils/analysis_dustywind.f90 @@ -0,0 +1,348 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module analysis +! +! Analysis routine for dusty wind testing +! +! :References: None +! +! :Owner: Lionel Siess +! +! :Runtime parameters: None +! +! :Dependencies: dim, dust_formation, kernel, part, units +! + + implicit none + character(len=20), parameter, public :: analysistype = 'dustywind' + + public :: do_analysis + + private + integer, parameter :: N = 1024 !32 + real, parameter :: theta = 0., phi = 0. + real, parameter :: u(3) = (/ sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta) /) + +contains + +subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) + + use part, only: nptmass,xyzmh_ptmass,vxyz_ptmass,iLum,iTeff,iReff + use part, only: dust_temp,isdead_or_accreted,nucleation + use dust_formation, only: set_abundances + + !general variables + character(len=*), intent(in) :: dumpfile + integer, intent(in) :: num,npart,iunit + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + real, intent(in) :: particlemass,time + + real :: L_star,T_star,R_star,xa,ya,za + integer :: j + + call set_abundances + !property of the sink particle + j = 1 + T_star = xyzmh_ptmass(iTeff,j) + L_star = xyzmh_ptmass(iLum,j) + R_star = xyzmh_ptmass(iReff,j) !sqrt(L_star/(4.*pi*steboltz*utime**3/umass*R_star**4)) + xa = xyzmh_ptmass(1,j) + ya = xyzmh_ptmass(2,j) + za = xyzmh_ptmass(3,j) + call get_Teq_from_Lucy(npart,xyzh,xa,ya,za,R_star,T_star,dust_temp) + + +end subroutine do_analysis + +!------------------------------------------------------------------------------- +!+ +! Calculates the radiative equilibrium temperature using the Lucy approximation +! Performs ray-tracing along 1 direction (could be generalized to include other directions) +!+ +!------------------------------------------------------------------------------- +subroutine get_Teq_from_Lucy(npart,xyzh,xa,ya,za,R_star,T_star,dust_temp) + use part, only:isdead_or_accreted,nucleation,idK3 + use dim, only:do_nucleation + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:),xa,ya,za,R_star,T_star + real, intent(out) :: dust_temp(:) + real :: r(3),r0(3),d,dmin,dmax,d2_axis,OR(N),Teq(N),K3(N),rho_over_r2(2*N+1),rho(N) + integer :: i,idx_axis(npart),naxis + + !.. find particles that lie within 2 smoothing lengths of the ray axis + r0(1:3) = (/xa, ya, za/) + dmin = 1.d99 + dmax = 0 + naxis = 0 +!$omp parallel do default(none) & +!$omp shared(npart,xyzh,r0,naxis,idx_axis) & +!$omp private(i,r,d,d2_axis) & +!$omp reduction(min:dmin) & +!$omp reduction(max:dmax) + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + r = xyzh(1:3,i)-r0 + !d = r(1)**2+r(2)**2+r(3)**2 + d = dot_product(r,r) + dmin = min(d,dmin) + dmax = max(d,dmax) + !distance to the axis + !d2_axis = sq_distance_to_z(r) + d2_axis = sq_distance_to_line(r,u) + if (d2_axis < 4.*xyzh(4,i)*xyzh(4,i)) then + !$omp critical (crit_naxis_add) + naxis = naxis+1 + idx_axis(naxis) = i + !$omp end critical (crit_naxis_add) + endif + endif + enddo +!$omp end parallel do + dmin = sqrt(dmin) + dmax = sqrt(dmax) + + + if (do_nucleation) then + call density_along_line(npart, xyzh, r0, naxis, idx_axis, -dmax, dmax, R_star, N, rho, & + rho_over_r2, dust_temp, Teq, nucleation(idK3,:), K3) + call calculate_Teq(N, dmax, R_star, T_star, rho, rho_over_r2, OR, Teq, K3) + else + call density_along_line(npart, xyzh, r0, naxis, idx_axis, -dmax, dmax, R_star, N, rho, & + rho_over_r2, dust_temp, Teq) + call calculate_Teq(N, dmax, R_star, T_star, rho, rho_over_r2, OR, Teq) + endif + call interpolate_on_particles(npart, N, dmax, r0, Teq, dust_temp, xyzh) + +end subroutine get_Teq_from_Lucy + +!-------------------------------------------------------------------------- +!+ +! Calculates the radiative equilibrium temperature along the ray direction +!+ +!-------------------------------------------------------------------------- +subroutine calculate_Teq(N, dmax, R_star, T_star, rho, rho_over_r2, OR, Teq, K3) + use dust_formation, only : calc_kappa_dust,calc_kappa_bowen,idust_opacity + integer, intent(in) :: N + real, intent(in) :: dmax, R_star, T_star, rho(N), rho_over_r2(2*N+1) + real, optional, intent(in) :: K3(N) + real, intent(out) :: Teq(N) + + real :: OR(N),tau_prime(N),vTeq(N),kappa(N),dTeq,pTeq(N) + real :: dr, fact, rho_on_r2(N) + real, parameter :: tol = 1.d-2, kap_gas = 2.d-4 + integer :: i,istart,iter + + + tau_prime = 0. + iter = 0 + vTeq = 0. + dTeq = 1. + dr = dmax/N + forall(i=1:N) OR(i) = i*dr + OR(N) = dmax + fact = dr/2. * R_star**2 + do i = 1,N + if (OR(i) > R_star) exit + enddo + istart = i-1 + if (istart > 0) Teq(1:istart) = T_star + Teq(istart+1:N) = T_star*(0.5*(1.-sqrt(1.-(R_star/OR(istart+1:N))**2))) + vTeq = Teq + pTeq= Teq + rho_on_r2 = 0. + kappa = 0. + + do while (dTeq > tol .and. iter < 20) + if (iter == 0) dTeq = 0. + iter = iter+1 + do i=N-1,istart+1,-1 + if (idust_opacity == 2) then + if (rho(i) > 0.) then + kappa(i) = calc_kappa_dust(K3(i),Teq(i),rho(i)) + else + kappa(i) = 0.d0 + endif + elseif (idust_opacity == 1) then + kappa(i) = calc_kappa_bowen(Teq(i)) + endif + rho_on_r2(i) = rho_over_r2(N-i)+rho_over_r2(N-i+1)+rho_over_r2(N+i+1)+rho_over_r2(N+i+2) + !if (iter >= 1) print *,'teq loop',i,K3(i),Teq(i),kappa(i),rho_on_r2(i) + tau_prime(i) = tau_prime(i+1) + fact*(kappa(i)+kap_gas) *rho_on_r2(i) + + Teq(i) = T_star*(0.5*(1.-sqrt(1.-(R_star/OR(i))**2)) + 0.75*tau_prime(i))**(1./4.) + dTeq = max(dTeq,abs(1.-Teq(i)/(1.d-5+vTeq(i)))) + vTeq(i) = Teq(i) + enddo + print *,iter,dTeq + enddo + print *,iter + open(unit=220,file='Teq.dat') + write(220,*) '# ng z vTeq Teq tau kappa rho_on_r2' + do i = 1,N + write(220,*) i,OR(i),pTeq(i),Teq(i),tau_prime(i),kappa(i),rho_on_r2(i) + enddo + close(220) + +end subroutine calculate_Teq + +!----------------------------------------------------------------------- +!+ +! compute the mean properties along the ray +!+ +!----------------------------------------------------------------------- +subroutine density_along_line(npart, xyzh, r0, npart_axis, idx_axis, rmin, rmax, r_star, N, & + rho_cgs, rho_over_r2, T, Teq, K3, K3i) + use kernel, only:cnormk,wkern + use part, only:massoftype,igas,rhoh + use units, only:unit_density + integer, intent(in) :: npart,N + real, intent(in) :: xyzh(:,:), T(:), r0(3) + real, optional, intent(in) :: K3(:) + integer, intent(in) :: npart_axis, idx_axis(npart) + real, intent(in) :: rmin, rmax, R_star + real, intent(out) :: rho_over_r2(2*N+1), Teq(N), rho_cgs(N) + real, optional, intent(out) :: K3i(N) + real :: rhoi(2*N+1), OR(2*N+1), Ti(2*N+1), Ki(2*N+1), xnorm(2*N+1) + real :: OH, d2_axis, HR, q2, q, fact0, fact, h, h2, part_mass + real :: delta_r, rmin_o, rmin_p, rmax_p, dr, r(3), xfact, rhoinv + integer :: i, np, j, j_min, j_max, Nr + +! Discretization of the line of sight in N segments + Nr = 2*N+1 + dr = (rmax-rmin)/(Nr-1) + rmin_o = rmin - dr + do i=1,Nr + OR(i) = dr*i+rmin_o + print *,i,OR(i),R_star + enddo + print *,'*******',rmax,rmin,r_star + + open(unit=220,file='allpart.dat') + write(220,*) '# ng x y z rho T K' + do i = 1, npart + write (220,*) np,xyzh(1:3,i)-r0(3),rhoh(xyzh(4,i),part_mass),T(i),K3(i) + enddo + close(220) + rhoi(:) = 0. + Teq(:) = 0. + K3i(:) = 0. + Ki(:) = 0. + Ti(:) = 0. + xnorm(:) = 0. + part_mass = massoftype(igas) + fact0 = part_mass*cnormk + open(unit=221,file='part_axis.dat') + write(221,*) '# ng x y z rho T K' + do i = 1, npart_axis + np = idx_axis(i) + r = xyzh(1:3,np)-r0(3) + !distance to z-axis + !OH = r(3) + !d2_axis = sq_distance_to_z(r) + OH = dot_product(r,u) + d2_axis = sq_distance_to_line(r,u) + h = xyzh(4,np) + h2 = h*h + delta_r = sqrt(4.*h2 - d2_axis) + ! rmin_p and rmax_p are the positions on the line of the two intersections between the line and the interaction sphere + rmin_p = OH-delta_r + rmax_p = OH+delta_r + j_min = ceiling((rmin_p-rmin_o)/dr) + j_max = floor((rmax_p-rmin_o)/dr) + j_min = max(1, j_min) + j_max = min(Nr, j_max) + ! Adds the contribution of particle np to density at all the discretized locations in the interaction sphere + fact = fact0/h**3 + rhoinv = 1./rhoh(h,part_mass) + write (221,*) np,r,rhoh(h,part_mass),T(np),K3(np) + do j=j_min, j_max + HR = OR(j) - OH + q2 = (d2_axis+HR**2)/h2 + q = sqrt(q2) + xfact = fact*wkern(q2,q) + rhoi(j) = rhoi(j) + xfact + xnorm(j) = xnorm(j)+xfact*rhoinv + Ti(j) = Ti(j) + xfact*rhoinv*T(np) + if (present(K3)) Ki(j) = Ki(j) + xfact*rhoinv*K3(np) + !print *,j,Ti(j),T(np),part_mass/(rhoh(h,part_mass)*h**3)!rhoh(h,part_mass),part_mass,q,fact,wkern(q2,q) + enddo + enddo + close (221) +! rho_over_r2 = 0 inside the star so that we do not divide by zero! + open(unit=222,file='ray.dat') + write(222,*) '# ng z rho T K xnorm rho_over_r2' + do j=1,Nr + if (xnorm(j) > 0.) then + Ti(j) = Ti(j)/xnorm(j) + if (present(K3)) Ki(j) = Ki(j) /xnorm(j) + endif + if (abs(OR(j)) < r_star) then + rho_over_r2(j) = 0. + else + rho_over_r2(j) = rhoi(j)/OR(j)**2 + endif + print *,j,rho_over_r2(j) + write (222,*) j,OR(j),rhoi(j),Ti(j),Ki(j),xnorm(j),rho_over_r2(j) + enddo + close(222) + do j=1,N + rho_cgs(N+1-j) = (rhoi(j)+rhoi(2*N-j+2))*unit_density/2. + Teq(N+1-j) = (Ti(j)+Ti(2*N-j+2))/2. + if (present(K3)) K3i(N+1-j) = (Ki(j)+Ki(2*N-j+2))/2. +! print *,'k3i',j,k3i(j) + enddo + +end subroutine density_along_line + +!----------------------------------------------------------------------- +!+ +! Interpolates a quantity computed on the discretized line of sight for all SPH particles +! (spherical symmetry assumed) +!+ +!----------------------------------------------------------------------- +subroutine interpolate_on_particles(npart, N, dmax, r0, Teq, dust_temp, xyzh) + use part, only:isdead_or_accreted + integer, intent(in) :: npart, N + real, intent(in) :: dmax, r0(3), Teq(N), xyzh(:,:) + real, intent(out) :: dust_temp(:) + + real :: r(3), d, dr, d2 + integer :: i, j + + dr = dmax / N + !should start at nwall + do i=1,npart + if (.not.isdead_or_accreted(xyzh(4,i))) then + r = xyzh(1:3,i) - r0 + d2 = dot_product(r,r) + d = sqrt(d2) + j = min(int(d/dr),N-1) + dust_temp(i) = (d-dr*j)*(Teq(j+1)-Teq(j))/dr + Teq(j) + endif + enddo + open(unit=220,file='all_final.dat') + write(220,*) '# ng x y z T' + do i = 1, npart + write (220,*) i,xyzh(1:3,i)-r0(3),dust_temp(i) + enddo + close(220) +end subroutine interpolate_on_particles + +real function sq_distance_to_z(r) + real, intent(in) :: r(3) + sq_distance_to_z = r(1)*r(1)+r(2)*r(2) +end function sq_distance_to_z + +real function sq_distance_to_line(r,u) + real, intent(in) :: r(3),u(3) + real :: p,d(3) + p = dot_product(r,u) + d = r-p*u + sq_distance_to_line = dot_product(d,d) +end function sq_distance_to_line + +end module analysis diff --git a/src/utils/analysis_energies.f90 b/src/utils/analysis_energies.f90 new file mode 100644 index 000000000..4d4288b74 --- /dev/null +++ b/src/utils/analysis_energies.f90 @@ -0,0 +1,63 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module analysis +! +! Analysis routine computing the energy accounting for accreted +! particles +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: energies, evwrite, metric_tools, options, part +! + implicit none + character(len=20), parameter, public :: analysistype = 'energies' + public :: do_analysis + + logical, private :: first = .true. + private + +contains + +subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) + use energies, only:compute_energies,track_mass,ekin,emag,etherm,epot,etot,& + eacc,etotall,totmom,angtot,angall + use metric_tools, only:init_metric + use part, only:metrics,metricderivs,gr + use evwrite, only:init_evfile + use options, only:iexternalforce + character(len=*), intent(in) :: dumpfile + integer, intent(in) :: num,npart,iunit + real, intent(in) :: xyzh(:,:),vxyzu(:,:) + real, intent(in) :: particlemass,time + + if (gr) then + call init_metric(npart,xyzh,metrics,metricderivs) + iexternalforce = 1 + endif + if (first) then + call init_evfile(1,'crap.ev',open_file=.false.) + endif + track_mass = .true. + call compute_energies(time) + + if (first) then + open(unit=1,file='energies.ev',status='new',action='write') + write(1,"(a)") '# time,ekin,etherm,emag,epot,etot,eacc,etot+eacc,totmom,angtot,etotall,angall' + first = .false. + endif + write(1,*) time,ekin,etherm,emag,epot,etot,eacc,etot+eacc,totmom,angtot,etotall,angall + + print*,' TOTAL ENERGY IS: ',etot + print*,' TOTAL ENERGY INCLUDING ACCRETION: ',etotall + +end subroutine do_analysis + +end module analysis diff --git a/src/utils/analysis_polytropes.f90 b/src/utils/analysis_polytropes.f90 index bd0c57df8..c112085a3 100644 --- a/src/utils/analysis_polytropes.f90 +++ b/src/utils/analysis_polytropes.f90 @@ -61,7 +61,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) character(len=200) :: fileout ! !--from .setup, determine if binary or not - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'.setup' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'.setup' inquire(file=fileout,exist=iexist) if ( iexist ) then write(*,'(2a)') "reading setup file: ",trim(fileout) @@ -78,7 +78,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) if ( binary ) then ! !--Open file (appendif exists) - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_centres.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_centres.dat' inquire(file=fileout,exist=iexist) if ( .not.iexist .or. firstcall ) then open(iunit,file=fileout,status='replace') @@ -252,7 +252,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! !--print period tracking to file (overwriting anything in existance) if ( binary ) then - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_period.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_period.dat' fileout=trim(fileout) open(iunit,file=fileout) write(iunit,"('#',4(1x,'[',i2.2,1x,a11,']',2x))") & diff --git a/src/utils/analysis_prdrag.f90 b/src/utils/analysis_prdrag.f90 index 14160df8a..8372c5c23 100644 --- a/src/utils/analysis_prdrag.f90 +++ b/src/utils/analysis_prdrag.f90 @@ -48,7 +48,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) real :: r1, r2 print*,' Hello Hauke, time in file = ',time - open( unit=106, file='radial.out', status='replace', iostat=ierr) + open( unit=106,file='radial.out',status='replace', iostat=ierr) if ( ierr /= 0 ) stop 'error opening radial.out' call make_beta_grids( xyzh, particlemass, npart ) @@ -67,7 +67,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) enddo close( 106 ) - open( unit=106, file='radialinterp.out', status='replace', iostat=ierr) + open( unit=106,file='radialinterp.out',status='replace', iostat=ierr) if ( ierr /= 0 ) stop 'error opening radialinterp.out' write(106,*), "#r_rad rbin theta thetabin r_cyl z rho tau beta" @@ -93,7 +93,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) close(106) - open( unit=106, file='applied.out', status='replace', iostat=ierr) + open( unit=106,file='applied.out',status='replace', iostat=ierr) if ( ierr /= 0 ) stop 'error opening applied.out' write(106,*), "#x y z r_cyl beta r_bin th_bin" diff --git a/src/utils/analysis_radiotde.f90 b/src/utils/analysis_radiotde.f90 index bef969001..918e8473b 100644 --- a/src/utils/analysis_radiotde.f90 +++ b/src/utils/analysis_radiotde.f90 @@ -14,6 +14,7 @@ module analysis ! ! :Runtime parameters: ! - drad_cap : *capture thickness (in cm) (-ve for all particles at outer radius)* +! - npart_tde : *npart in tde sims (-ve=10*npart of cnm)* ! - phi_max : *max phi (in deg)* ! - phi_min : *min phi (in deg)* ! - rad_cap : *capture inner radius (in cm)* @@ -22,7 +23,7 @@ module analysis ! - v_max : *max velocity (in c)* ! - v_min : *min velocity (in c)* ! -! :Dependencies: infile_utils, io, physcon, readwrite_dumps, units +! :Dependencies: infile_utils, io, part, physcon, readwrite_dumps, units ! implicit none character(len=8), parameter, public :: analysistype = 'radiotde' @@ -30,8 +31,19 @@ module analysis private + character(len=7) :: ana + real, dimension(:), allocatable :: rad_all,vr_all,v_all real, dimension(:), allocatable :: theta,plot_theta,phi,vr,vtheta,vphi logical, dimension(:), allocatable :: cap + real :: m_accum, m_cap + real :: vr_accum_mean, vr_accum_max, vr_cap_mean, vr_cap_max + real :: r_accum_maxv, r_cap_maxv + real :: v_accum_mean, v_cap_mean + real :: e_accum, e_cap + integer :: n_accum, n_cap + real :: shock_v, rad_min, rad_max, shock_e, shock_m!, shock_rho + real :: shock_v_tde, rad_min_tde, rad_max_tde, shock_e_tde, shock_m_tde!, shock_rho + real :: shock_v_cnm, rad_min_cnm, rad_max_cnm, shock_e_cnm, shock_m_cnm!, shock_rho !---- These can be changed in the params file real :: rad_cap = 1.e16 ! radius where the outflow in captured (in cm) @@ -42,22 +54,25 @@ module analysis real :: theta_max = 180. real :: phi_min = -90. real :: phi_max = 90. - real :: m_accum, m_cap, vr_accum_mean, vr_cap_mean, v_accum_mean, v_cap_mean, e_accum, e_cap - integer :: n_accum, n_cap + + !--- shock detection global var + integer :: npart_cnm = -1, npart_tde, npart_tde_reserve=-1 + real, allocatable :: ent_bg(:) contains subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) use readwrite_dumps, only: opened_full_dump - use units, only: utime,udist,unit_energ,umass + use units, only: utime,udist,unit_energ,umass!,unit_density use physcon, only: solarm,days + use part, only: pxyzu character(len=*), intent(in) :: dumpfile integer, intent(in) :: numfile,npart,iunit real, intent(in) :: xyzh(:,:),vxyzu(:,:) real, intent(in) :: pmass,time character(len=120) :: output character(len=30) :: filename - integer :: i,ierr + integer :: i,ierr,npart_new,npart_tde_old logical :: iexist real :: toMsun,todays @@ -67,6 +82,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) n_cap = 0 e_accum = 0. e_cap = 0. + ana = 'shock' toMsun = umass/solarm todays = utime/days @@ -77,11 +93,8 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) endif ! Print the analysis being done - write(*,'("Performing analysis type ",A)') analysistype - write(*,'("Input file name is ",A)') dumpfile - - write(output,"(a8,i5.5)") 'outflow_',numfile - write(*,'("Output file name is ",A)') output + write(*,'(" Performing analysis type ",A)') analysistype + write(*,'(" Input file name is ",A)') dumpfile ! Read black hole mass from params file filename = 'analysis_'//trim(analysistype)//'.params' @@ -93,81 +106,157 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) stop endif - rad_cap = rad_cap/udist - if (drad_cap < 0.) then - drad_cap = huge(0.) - else - drad_cap = drad_cap/udist + ! read background entropy + if (npart_cnm < 0) then + if (npart_tde_reserve < 0) npart_tde_reserve = 10*npart + allocate(ent_bg(npart_tde_reserve+npart)) ! save more memory for later injection + npart_cnm = npart + call record_background(pxyzu(4,:),0,npart,ent_bg) + write(*,'(I9,1x,a16)') npart_cnm, 'particles in CNM' endif - print*, 'Capture particles from', rad_cap, 'to', rad_cap+drad_cap - - allocate(theta(npart),plot_theta(npart),phi(npart),vr(npart),vtheta(npart),vphi(npart),cap(npart)) - cap = .false. - - call tde_analysis(npart,pmass,xyzh,vxyzu) - - if (n_cap > 0) then - open(iunit,file=output) - write(iunit,'("# ",es20.12," # TIME")') time - write(iunit,"('#',6(1x,'[',i2.2,1x,a11,']',2x))") & - 1,'theta', & - 2,'thetap', & - 3,'phi', & - 4,'vr', & - 5,'vtheta', & - 6,'vphi' - - do i = 1,npart - if (cap(i)) then - write(iunit,'(6(es18.10,1X))') & - theta(i), & - plot_theta(i), & - phi(i), & - vr(i), & - vtheta(i), & - vphi(i) - endif - enddo +! not meaningful and will not do anything if cut-and-put + npart_tde_old = npart_tde + npart_tde = npart - npart_cnm + npart_new = npart_tde - npart_tde_old + if (npart_new > 0) call record_background(pxyzu(4,:),npart_tde_old+npart_cnm,npart_new,ent_bg) + + ! allocate memory + allocate(rad_all(npart),vr_all(npart),v_all(npart)) + call to_rad(npart,xyzh,vxyzu,rad_all,vr_all,v_all) + + select case (trim(ana)) + case ('outflow') + write(*,'(a)') ' Analysing the outflow ...' + write(output,"(a8,i5.5)") 'outflow_',numfile + write(*,'(" Output file name is ",A)') output + + rad_cap = rad_cap/udist + if (drad_cap < 0.) then + drad_cap = huge(0.) + else + drad_cap = drad_cap/udist + endif + print*, 'Capture particles from', rad_cap, 'to', rad_cap+drad_cap + + allocate(theta(npart),plot_theta(npart),phi(npart),vr(npart),vtheta(npart), & + vphi(npart),cap(npart)) + cap = .false. + + call outflow_analysis(npart,pmass,xyzh,vxyzu,rad_all,vr_all,v_all) + + if (n_cap > 0) then + open(iunit,file=output) + write(iunit,'("# ",es20.12," # TIME")') time + write(iunit,"('#',6(1x,'[',i2.2,1x,a11,']',2x))") & + 1,'theta', & + 2,'thetap', & + 3,'phi', & + 4,'vr', & + 5,'vtheta', & + 6,'vphi' + + do i = 1,npart + if (cap(i)) then + write(iunit,'(6(es18.10,1X))') & + theta(i), & + plot_theta(i), & + phi(i), & + vr(i), & + vtheta(i), & + vphi(i) + endif + enddo + close(iunit) + endif + + deallocate(theta,plot_theta,phi,vr,vtheta,vphi,cap,rad_all,vr_all,v_all) + + inquire(file='outflows',exist=iexist) + if (iexist) then + open(iunit,file='outflows',status='old',position='append') + else + open(iunit,file='outflows',status='new') + write(iunit,'(14(A,1X))') '#', 'time', 'm_cap[msun]', 'm_accum[msun]', 'vr_accum_mean[c]', 'vr_accum_max[c]', & + 'r_accum_maxv[cm]', 'vr_cap_mean[c]', 'vr_cap_max[c]', 'r_cap_maxv[cm]', & + 'v_accum_mean[c]', 'v_cap_mean[c]', 'e_accum[erg]', 'e_cap[erg]' + endif + write(iunit,'(13(es18.10,1x))') & + time*todays, & + m_cap*toMsun, & + m_accum*toMsun, & + vr_accum_mean, & + vr_accum_max, & + r_accum_maxv*udist, & + vr_cap_mean, & + vr_cap_max, & + r_cap_maxv*udist, & + v_accum_mean, & + v_cap_mean, & + e_accum*unit_energ, & + e_cap*unit_energ close(iunit) - endif - deallocate(theta,plot_theta,phi,vr,vtheta,vphi,cap) + write(*,'(I8,1X,A2,1X,I8,1X,A34)') n_cap, 'of', npart, 'particles are in the capture shell' + write(*,'(I8,1X,A2,1X,I8,1X,A40)') n_accum, 'of', npart, 'particles are outside the capture radius' - inquire(file='outflows',exist=iexist) - if (iexist) then - open(iunit,file='outflows',status='old',position='append') - else - open(iunit,file='outflows',status='new') - write(iunit,'(9(A15,1X))') '# time', 'm_cap[msun]', 'm_accum[msun]', 'vr_accum_mean[c]', 'vr_cap_mean[c]', & - 'v_accum_mean[c]', 'v_cap_mean[c]', 'e_accum[erg]', 'e_cap[erg]' - endif - write(iunit,'(9(es18.10,1x))') & - time*todays, & - m_cap*toMsun, & - m_accum*toMsun, & - vr_accum_mean, & - vr_cap_mean, & - v_accum_mean, & - v_cap_mean, & - e_accum*unit_energ, & - e_cap*unit_energ - close(iunit) + case ('shock') + write(*,'(a)') ' Analysing the shock ...' - write(*,'(I8,1X,A2,1X,I8,1X,A34)') n_cap, 'of', npart, 'particles are in the capture shell' - write(*,'(I8,1X,A2,1X,I8,1X,A40)') n_accum, 'of', npart, 'particles are outside the capture radius' + call shock_analysis(npart,pmass,rad_all,vr_all,pxyzu(4,:)) + + deallocate(rad_all,vr_all,v_all) + + inquire(file='shock',exist=iexist) + if (iexist) then + open(iunit,file='shock',status='old',position='append') + else + open(iunit,file='shock',status='new') + write(iunit,'(17(A,1x))') '#', 'time', 'rad_min[cm]', 'rad_max[cm]', 'velocity[c]', 'mass[Msun]', 'energy[erg]', & !'density[g/cm-3]' + 'rad_min_tde[cm]', 'rad_max_tde[cm]', 'vel_tde[c]', 'mass_tde[Msun]', 'ene_tde[erg]', & + 'rad_min_cnm[cm]', 'rad_max_cnm[cm]', 'vel_cnm[c]', 'mass_cnm[Msun]', 'ene_cnm[erg]' + endif + if (rad_max > 0.) then + write(iunit,'(16(es18.10,1x))') & + time*todays, & + rad_min*udist, rad_max*udist, shock_v, shock_m*umass/solarm, shock_e*unit_energ, & + rad_min_tde*udist, rad_max_tde*udist, shock_v_tde, shock_m_tde*umass/solarm, shock_e_tde*unit_energ, & + rad_min_cnm*udist, rad_max_cnm*udist, shock_v_cnm, shock_m_cnm*umass/solarm, shock_e_cnm*unit_energ !shock_rho*unit_density + endif + close(iunit) + + case default + write(*,'(a)') " Unknown analysis type. Do 'outflow' or 'shock'" + stop + end select end subroutine do_analysis +subroutine to_rad(npart,xyzh,vxyzu,rad,vr,v) + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:),vxyzu(:,:) + real, intent(out) :: rad(:),vr(:),v(:) + integer :: i + real :: xyz(1:3),vxyz(1:3) + + do i = 1,npart + xyz = xyzh(1:3,i) + vxyz = vxyzu(1:3,i) + rad(i) = sqrt(dot_product(xyz,xyz)) + vr(i) = dot_product(xyz,vxyz)/rad(i) + v(i) = sqrt(dot_product(vxyz,vxyz)) + enddo + +end subroutine to_rad !-------------------------------------------------------------------------------------------------------------------- ! !-- Actual subroutine where the analysis is done! ! !-------------------------------------------------------------------------------------------------------------------- -subroutine tde_analysis(npart,pmass,xyzh,vxyzu) +subroutine outflow_analysis(npart,pmass,xyzh,vxyzu,rad_all,vr_all,v_all) integer, intent(in) :: npart - real, intent(in) :: pmass,xyzh(:,:),vxyzu(:,:) + real, intent(in) :: pmass,xyzh(:,:),vxyzu(:,:),rad_all(:),vr_all(:),v_all(:) integer :: i - real :: r,v,x,y,z,xyz(1:3),vx,vy,vz,vxyz(1:3) + real :: r,v,x,y,z,vx,vy,vz real :: thetai,phii,vri real :: vr_accum_add,vr_cap_add,v_accum_add,v_cap_add @@ -175,25 +264,29 @@ subroutine tde_analysis(npart,pmass,xyzh,vxyzu) vr_cap_add = 0. v_accum_add = 0. v_cap_add = 0. + vr_accum_max = 0. + vr_cap_max = 0. do i = 1,npart x = xyzh(1,i) y = xyzh(2,i) z = xyzh(3,i) - xyz = (/x,y,z/) vx = vxyzu(1,i) vy = vxyzu(2,i) vz = vxyzu(3,i) - vxyz = (/vx,vy,vz/) - r = sqrt(dot_product(xyz,xyz)) - v = sqrt(dot_product(vxyz,vxyz)) + r = rad_all(i) + v = v_all(i) if (r > rad_cap) then m_accum = m_accum + pmass n_accum = n_accum + 1 e_accum = e_accum + 0.5*pmass*v**2 - vri = dot_product(vxyz,xyz)/r + vri = vr_all(i) vr_accum_add = vr_accum_add + vri v_accum_add = v_accum_add + v + if (vri > vr_accum_max) then + vr_accum_max = vri + r_accum_maxv = r + endif if (r-rad_cap < drad_cap .and. (v >= v_min .and. v <= v_max)) then thetai = atan2d(y,x) phii = atan2d(z,sqrt(x**2+y**2)) @@ -210,6 +303,10 @@ subroutine tde_analysis(npart,pmass,xyzh,vxyzu) e_cap = e_cap + 0.5*pmass*v**2 vr_cap_add = vr_cap_add + vri v_cap_add = v_cap_add + v + if (vri > vr_cap_max) then + vr_cap_max = vri + r_cap_maxv = r + endif endif endif endif @@ -219,7 +316,88 @@ subroutine tde_analysis(npart,pmass,xyzh,vxyzu) vr_cap_mean = vr_cap_add/n_cap v_cap_mean = v_cap_add/n_cap -end subroutine tde_analysis +end subroutine outflow_analysis + +subroutine record_background(ent,npart_old,npart_new,ent_bg) + real, intent(in) :: ent(:) + integer, intent(in) :: npart_old,npart_new + real, intent(inout) :: ent_bg(:) + integer, parameter :: iunit=235 + integer :: i + + print*, 'Record background entropy of ', npart_new, ' particles' + + do i=1,npart_new + ent_bg(npart_old+i) = ent(npart_old+i)*1.1 ! give some range for self evolution + !(is there a reasonable choice instead of arbitrary?) + enddo + +end subroutine record_background + +subroutine shock_analysis(npart,pmass,rad_all,vr_all,ent) + use units, only: udist + use physcon, only: au,pi + integer, intent(in) :: npart + real, intent(in) :: pmass,rad_all(:),vr_all(:),ent(:) + integer :: i,n,n_cnm,n_tde + real :: ri,half_m,ei,vi + ! + !------Determine the shock + ! + n = 0 + n_cnm = 0. + n_tde = 0. + shock_e = 0. + shock_e_cnm = 0. + shock_e_tde = 0. + shock_v = 0. ! take max vel + shock_v_cnm = 0. + shock_v_tde = 0. + rad_max = 0. + rad_max_cnm = 0. + rad_max_tde = 0. + rad_min = huge(0.) + rad_min_cnm = huge(0.) + rad_min_tde = huge(0.) + half_m = pmass*0.5 + + do i = 1,npart + if (ent(i) > ent_bg(i)) then + ri = rad_all(i) + vi = vr_all(i) + ei = half_m*vi**2 + n = n + 1 + if (vi > shock_v) shock_v = vi + if (ri < rad_min) rad_min = ri + if (ri > rad_max) rad_max = ri + shock_e = shock_e + ei + + if (i > npart_cnm) then + ! tde outflow + n_tde = n_tde + 1 + if (vi > shock_v_tde) shock_v_tde = vi + if (ri < rad_min_tde) rad_min_tde = ri + if (ri > rad_max_tde) rad_max_tde = ri + shock_e_tde = shock_e_tde + ei + else + ! cnm + n_cnm = n_cnm + 1 + if (vi > shock_v_cnm) shock_v_cnm = vi + if (ri < rad_min_cnm) rad_min_cnm = ri + if (ri > rad_max_cnm) rad_max_cnm = ri + shock_e_cnm = shock_e_cnm + ei + endif + endif + enddo + + write(*,'(a14,1x,es8.1,1x,a5,1x,es8.1,1x,a2)') ' Shock is from', rad_min*udist/au, 'au to', rad_max*udist/au, 'au' + + shock_m = shock_e*2./shock_v**2 !pmass*n + shock_m_cnm = shock_e_cnm*2./shock_v_cnm**2 !pmass*n_cnm + shock_m_tde = shock_e_tde*2./shock_v_tde**2 !pmass*n_tde + !shock_rho = shock_m*4./3.*pi*(rad_max**3-rad_min**3) + +end subroutine shock_analysis !---------------------------------------------------------------- !+ @@ -234,18 +412,25 @@ subroutine write_tdeparams(filename) print "(a)",' writing analysis options file '//trim(filename) open(unit=iunit,file=filename,status='replace',form='formatted') write(iunit,"(a,/)") '# options when performing radio TDE analysis' + call write_inopt(ana,'analysis',"analysis type: 'outflow' or 'shock'",iunit) - call write_inopt(rad_cap,'rad_cap','capture inner radius (in cm)',iunit) - call write_inopt(drad_cap,'drad_cap','capture thickness (in cm) (-ve for all particles at outer radius)',iunit) + select case (trim(ana)) + case ('outflow') + call write_inopt(rad_cap,'rad_cap','capture inner radius (in cm)',iunit) + call write_inopt(drad_cap,'drad_cap','capture thickness (in cm) (-ve for all particles at outer radius)',iunit) - call write_inopt(v_min,'v_min','min velocity (in c)',iunit) - call write_inopt(v_max,'v_max','max velocity (in c)',iunit) + call write_inopt(v_min,'v_min','min velocity (in c)',iunit) + call write_inopt(v_max,'v_max','max velocity (in c)',iunit) - call write_inopt(theta_min,'theta_min','min theta (in deg)',iunit) - call write_inopt(theta_max,'theta_max','max theta (in deg)',iunit) + call write_inopt(theta_min,'theta_min','min theta (in deg)',iunit) + call write_inopt(theta_max,'theta_max','max theta (in deg)',iunit) - call write_inopt(phi_min,'phi_min','min phi (in deg)',iunit) - call write_inopt(phi_max,'phi_max','max phi (in deg)',iunit) + call write_inopt(phi_min,'phi_min','min phi (in deg)',iunit) + call write_inopt(phi_max,'phi_max','max phi (in deg)',iunit) + case ('shock') + call write_inopt(npart_tde_reserve,'npart_tde','npart in tde sims (-ve=10*npart of cnm)',iunit) + case default + end select close(iunit) @@ -260,22 +445,30 @@ subroutine read_tdeparams(filename,ierr) integer :: nerr type(inopts), allocatable :: db(:) - print "(a)",'reading analysis options from '//trim(filename) + print "(a)",' reading analysis options from '//trim(filename) nerr = 0 ierr = 0 call open_db_from_file(db,filename,iunit,ierr) - call read_inopt(rad_cap,'rad_cap',db,min=0.,errcount=nerr) - call read_inopt(drad_cap,'drad_cap',db,errcount=nerr) + call read_inopt(ana,'analysis',db,errcount=nerr) + + select case (trim(ana)) + case ('outflow') + call read_inopt(rad_cap,'rad_cap',db,min=0.,errcount=nerr) + call read_inopt(drad_cap,'drad_cap',db,errcount=nerr) - call read_inopt(v_min,'v_min',db,min=0.,max=1.,errcount=nerr) - call read_inopt(v_max,'v_max',db,min=0.,max=1.,errcount=nerr) + call read_inopt(v_min,'v_min',db,min=0.,max=1.,errcount=nerr) + call read_inopt(v_max,'v_max',db,min=0.,max=1.,errcount=nerr) - call read_inopt(theta_min,'theta_min',db,min=-180.,max=180.,errcount=nerr) - call read_inopt(theta_max,'theta_max',db,min=-180.,max=180.,errcount=nerr) + call read_inopt(theta_min,'theta_min',db,min=-180.,max=180.,errcount=nerr) + call read_inopt(theta_max,'theta_max',db,min=-180.,max=180.,errcount=nerr) - call read_inopt(phi_min,'phi_min',db,min=-90.,max=90.,errcount=nerr) - call read_inopt(phi_max,'phi_max',db,min=-90.,max=90.,errcount=nerr) + call read_inopt(phi_min,'phi_min',db,min=-90.,max=90.,errcount=nerr) + call read_inopt(phi_max,'phi_max',db,min=-90.,max=90.,errcount=nerr) + case ('shock') + call read_inopt(npart_tde_reserve,'npart_tde',db,errcount=nerr) + case default + end select call close_db(db) if (nerr > 0) then From 03403c8b22f59958c1bb6c85ad92e9f7fdd27bd3 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 10 Jul 2024 17:23:25 +0100 Subject: [PATCH 130/182] Calling cooling_radapprox from evolve.f90 --- src/main/cooling_radapprox.f90 | 41 ++++++++++++++------------- src/main/deriv.F90 | 27 ++++-------------- src/main/evolve.F90 | 31 +++++++++++++++++++-- src/main/step_leapfrog.F90 | 51 +++++++++++++++++----------------- 4 files changed, 81 insertions(+), 69 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index fea45fdfd..774c237d7 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -62,7 +62,7 @@ end subroutine init_star ! ! Do cooling calculation ! -! update energy to return evolved energy array. +! update energy to return evolved energy array. Called from evolve.F90 subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) use io, only:warning use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh,piontwo,rpiontwo @@ -90,8 +90,9 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb) overpart: do i=1,npart - if (.not. iactive(iphase(i)) ) cycle - if (isdead_or_accreted(xyzh(4,i)) ) cycle + if (.not. iactive(iphase(i)) .or. isdead_or_accreted(xyzh(4,i)) ) then + dudt_sph(i) = 0d0 + endif poti = Gpot_cool(i) du_FLDi = duFLD(i) ui = energ(i) @@ -154,11 +155,12 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) dudti_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opaci/unit_ergg*utime! code units ! If radiative cooling is negligible compared to hydrodynamical heating - ! don't use this method to update energy, just use hydro du/dt (don't zero - ! fxyzu(4,i) ). + ! don't use this method to update energy, just use hydro du/dt if (abs(dudti_rad/dudt_sph(i)) < dtcool_crit) then ! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& -! dudt_sph(i) + ! dudt_sph(i) + energ(i) = ui + dudt_sph(i)*dt + dudt_sph(i) = 0d0 cycle endif @@ -179,11 +181,11 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) endif teqi_store(i) = Teqi -! if (Teqi > 1e6) 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 * dt=", dudt_sph(i)*dt -! endif + 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 * dt=", dudt_sph(i)*dt + endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg @@ -225,14 +227,15 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) enddo overpart !$omp end parallel do - n_uevo = 0 - !$omp parallel do default(none) & - !$omp shared(dudt_sph,npart) private(i) reduction(+:n_uevo) - do i=1, npart - if (dudt_sph(i) /= 0d0) n_uevo = n_uevo + 1 - enddo - !$omp end parallel do - print *, "energy not evolved with cooling for", n_uevo, "particles" + !n_uevo = 0 + !!$omp parallel do default(none) & + !!$omp shared(dudt_sph,npart) private(i) reduction(+:n_uevo) + !do i=1, npart + ! if (dudt_sph(i) /= 0d0) n_uevo = n_uevo + 1 + ! dudt_sph(i) = 0d0 + !enddo + !!$omp end parallel do +! print *, "energy not evolved with cooling for", n_uevo, "particles" ! print *, "min/max dudt_sph():", minval(dudt_sph), maxval(dudt_sph) end subroutine radcool_update_energ diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 0294d04f8..4bbab4bdf 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -14,10 +14,10 @@ module deriv ! ! :Runtime parameters: None ! -! :Dependencies: cons2prim, densityforce, derivutils, dim, dust_formation, -! externalforces, forces, forcing, growth, io, linklist, metric_tools, -! options, part, porosity, ptmass, ptmass_radiation, radiation_implicit, -! timestep, timestep_ind, timing +! :Dependencies: cons2prim, densityforce, derivutils, dim, externalforces, +! forces, forcing, growth, io, linklist, metric_tools, options, part, +! porosity, ptmass, ptmass_radiation, radiation_implicit, timestep, +! timestep_ind, timing ! implicit none @@ -61,9 +61,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& use cons2prim, only:cons2primall,cons2prim_everything use metric_tools, only:init_metric use radiation_implicit, only:do_radiation_implicit,ierr_failed_to_converge - use options, only:implicit_radiation,implicit_radiation_store_drad,use_porosity,icooling - use cooling_radapprox, only:radcool_update_energ - use cooling, only:Tfloor + use options, only:implicit_radiation,implicit_radiation_store_drad,use_porosity integer, intent(in) :: icall integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -182,11 +180,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& if (use_porosity) call get_probastick(npart,xyzh,ddustprop(1,:),dustprop,dustgasprop,filfac) endif -! -! update energy if using radiative cooling approx (icooling=9) -! - if (icooling == 9 .and. dt > 0.0 .and. icall==1) call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) - ! ! compute dust temperature ! @@ -202,16 +195,6 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& enddo !$omp end parallel do endif - -! Set dudt to zero because we evolved energy already for icooling=9 - if (icooling == 9 .and. icall==1) then - !$omp parallel do shared(fxyzu,npart) private(i) - do i=1,npart - fxyzu(4,i) = 0. - enddo - !$omp end parallel do - endif - ! ! set new timestep from Courant/forces condition ! diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index 92c22f776..a823bd1bc 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -77,10 +77,12 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use partinject, only:update_injected_particles #endif use dim, only:do_radiation - use options, only:exchange_radiation_energy,implicit_radiation + use options, only:exchange_radiation_energy,implicit_radiation,icooling use part, only:rad,radprop use radiation_utils, only:update_radenergy use timestep, only:dtrad + use cooling, only:Tfloor + use cooling_radapprox,only:radcool_update_energ #ifdef LIVE_ANALYSIS use analysis, only:do_analysis use part, only:igas @@ -89,7 +91,8 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) #endif use part, only:npart,nptmass,xyzh,vxyzu,fxyzu,fext,divcurlv,massoftype, & xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,gravity,iboundary, & - fxyz_ptmass_sinksink,ntot,poten,ndustsmall,accrete_particles_outside_sphere + fxyz_ptmass_sinksink,ntot,poten,ndustsmall,accrete_particles_outside_sphere, & + iphase,iactive use quitdump, only:quit use ptmass, only:icreate_sinks,ptmass_create,ipart_rhomax,pt_write_sinkev,calculate_mdot, & set_integration_precision @@ -137,7 +140,9 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) logical :: use_global_dt integer :: j,nskip,nskipped,nevwrite_threshold,nskipped_sink,nsinkwrite_threshold character(len=120) :: dumpfile_orig - + integer :: imax + real :: umax + tprint = 0. nsteps = 0 nsteplast = 0 @@ -284,6 +289,20 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) if (do_radiation .and. exchange_radiation_energy .and. .not.implicit_radiation) then call update_radenergy(npart,xyzh,fxyzu,vxyzu,rad,radprop,0.5*dt) endif + + if (icooling == 9) then + write (*,*) "Before step", maxval(vxyzu(4,:)),minval(vxyzu(4,:)) + umax = 0d0 + do i=1, npart + if (vxyzu(4,i) > umax) then + umax = vxyzu(4,i) + imax = i + endif + enddo + print *, "max i=", imax, iactive(iphase(i)), fxyzu(4,i) + call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) + write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)), fxyzu(4,i) + endif nsteps = nsteps + 1 ! !--evolve data for one timestep @@ -302,6 +321,12 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) call update_radenergy(npart,xyzh,fxyzu,vxyzu,rad,radprop,0.5*dt) endif +! if (icooling == 9) then + ! write (*,*) "after step",maxval(vxyzu(4,:)),minval(vxyzu(4,:)) +! call radcool_update_energ(0.5*dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) + ! write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)) + ! endif + dtlast = dt !--timings for step call diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index a1dd9939b..a5eccbc54 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -127,7 +127,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use eos, only:equationofstate use substepping, only:substep,substep_gr, & substep_sph_gr,substep_sph - + integer, intent(inout) :: npart integer, intent(in) :: nactive real, intent(in) :: t,dtsph @@ -172,7 +172,7 @@ 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) & !$omp shared(mprev,filfacprev,filfac,use_porosity) & !$omp shared(ibin,ibin_old,twas,timei) & !$omp firstprivate(itype) & @@ -199,11 +199,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - !Alison - !if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L202", fxyzu(4,i) !--floor the thermal energy if requested and required - if (ufloor > 0. .and. icooling /= 9) then + if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then vxyzu(4,i) = ufloor nvfloorp = nvfloorp + 1 @@ -233,7 +231,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif call check_dustprop(npart,dustprop,filfac,mprev,filfacprev) endif - +! print *, "line 234", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) !---------------------------------------------------------------------- ! substepping with external and sink particle forces, using dtextforce @@ -251,7 +249,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) 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,& + fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,& dptmass,fsink_old,nbinmax,ibin_wake,gtgrad,group_info, & nmatrix,n_group,n_ingroup,n_sing) else @@ -275,7 +273,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) & !$omp shared(twas,timei) & !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & @@ -326,7 +324,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) !--floor the thermal energy if requested and required - if (ufloor > 0. .and. icooling /= 9) then + if (ufloor > 0.) then if (vpred(4,i) < ufloor) then vpred(4,i) = ufloor nvfloorps = nvfloorps + 1 @@ -387,13 +385,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (npart > 0) then if (gr) vpred = vxyzu ! Need primitive utherm as a guess in cons2prim 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) - if (do_radiation .and. implicit_radiation) then! .or. icooling == 9) then + if (do_radiation .and. implicit_radiation) then rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif @@ -407,6 +404,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) call fatal('step','step too small: bin would exceed maximum') endif endif +! print *, "line 407", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) ! ! if using super-timestepping, determine what dt will be used on the next loop ! @@ -422,6 +420,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! any extra iterations, but to be reversible for velocity-dependent ! forces we must iterate until velocities agree. !------------------------------------------------------------------------- + +! print *, "line 423", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) its = 0 converged = .false. errmaxmean = 0.0 @@ -483,9 +483,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif - !Alison - ! if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L488", fxyzu(4,i) - + if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + dti*dBevol(:,i) @@ -507,11 +505,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - !Alison -! if (fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L509", fxyzu(4,i) - + !--floor the thermal energy if requested and required - if (ufloor > 0. .and. icooling /= 9) then + if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then vxyzu(4,i) = ufloor nvfloorc = nvfloorc + 1 @@ -566,8 +562,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) 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) - !Alison - ! if (icooling==9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L568", fxyzu(4,i) erri = (vxi - vpred(1,i))**2 + (vyi - vpred(2,i))**2 + (vzi - vpred(3,i))**2 errmax = max(errmax,erri) @@ -579,7 +573,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(2,i) = vyi vxyzu(3,i) = vzi !--this is the energy equation if non-isothermal - if (maxvxyzu >= 4 .and. icooling /= 9) vxyzu(4,i) = eni + if (maxvxyzu >= 4) vxyzu(4,i) = eni endif if (itype==idust .and. use_dustgrowth) dustprop(:,i) = dustprop(:,i) + hdtsph*ddustprop(:,i) @@ -619,8 +613,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(store_itype,vxyzu,fxyzu,vpred,iphase) & !$omp shared(Bevol,dBevol,Bpred,pxyzu,ppred) & !$omp shared(dustprop,ddustprop,dustproppred,use_dustfrac,dustevol,dustpred,ddustevol) & -!$omp shared(filfac,filfacpred,use_porosity,icooling) & -!$omp shared(rad,drad,radpred) & +!$omp shared(filfac,filfacpred,use_porosity) & +!$omp shared(rad,drad,radpred,icooling) & !$omp firstprivate(itype) & !$omp schedule(static) until_converged: do i=1,npart @@ -628,11 +622,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (iamboundary(itype)) cycle until_converged if (ind_timesteps) then + if (icooling == 9) vxyzu(4,i) = vpred(4,i) !keep original value of u if (iactive(iphase(i))) then - if (gr) then ppred(:,i) = pxyzu(:,i) else +! if (icooling == 9) vxyzu(4,i) = vpred(4,i) !keep original value of u vpred(:,i) = vxyzu(:,i) endif if (use_dustgrowth) dustproppred(:,i) = dustprop(:,i) @@ -683,6 +678,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! get new force using updated velocity: no need to recalculate density etc. ! if (gr) vpred = vxyzu ! Need primitive utherm as a guess in cons2prim +! print *, "before 2nd derivs", maxval(vpred(4,:)), minval(vpred(4,:)),maxval(fxyzu(4,:)) call derivs(2,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) @@ -692,11 +688,16 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(4,1:npart) = vpred(4,1:npart) endif if (icooling == 9) then +! print *, "after 2nd derivs:vpred", maxval(vpred(4,:)), minval(vpred(4,:)) vxyzu(4,1:npart) = vpred(4,1:npart) endif endif + if (icooling == 9) then +! print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) + vxyzu(4,1:npart) = vpred(4,1:npart) + endif enddo iterations - + print *, "line 695", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) ! MPI reduce summary variables nwake = int(reduceall_mpi('+', nwake)) nvfloorp = int(reduceall_mpi('+', nvfloorp)) From d317ef772f7637805794d730bc80f7848c85276f Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 11 Jul 2024 16:24:42 +0100 Subject: [PATCH 131/182] radapprox bugfix and upstream updates --- docs/images/vscode-findent.png | Bin 43037 -> 0 bytes src/main/cooling_radapprox.f90 | 1 + src/main/force.F90 | 3 +- src/main/inject_asteroidwind.f90 | 7 ++++- src/main/inject_bondi.f90 | 7 ++++- src/main/inject_firehose.f90 | 6 +++- src/main/inject_galcen_winds.f90 | 7 ++++- src/main/inject_keplerian.f90 | 30 ++++++++++---------- src/main/inject_keplerianshear.f90 | 7 ++++- src/main/inject_rochelobe.f90 | 6 +++- src/main/inject_sne.f90 | 7 ++++- src/main/inject_steadydisc.f90 | 7 ++++- src/main/inject_unifwind.f90 | 7 ++++- src/main/inject_wind.f90 | 43 +++++++++++++++++++++++------ src/main/inject_windtunnel.f90 | 6 +++- 15 files changed, 110 insertions(+), 34 deletions(-) delete mode 100644 docs/images/vscode-findent.png diff --git a/docs/images/vscode-findent.png b/docs/images/vscode-findent.png deleted file mode 100644 index a26de6b40d39e56731c69058271a95d5407e3e3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43037 zcmb5Vb9^4#`Ue^(jcuEaZ8UCd+qP|^N#itZ!^XCqG`4LuYH+7#pYz*2``r7-P2YSn zeP`CJHA~MI&qON7Ng%-D!h(Q+AV^7yDS?1Mh=72AqQZay-?(8O_(p8s!QDF&=ujjnuW}Vl5BK?=Y`T6tBmNnwI~6OCAN@J#hcYDG~?A$~{tyh8p} z?j~GHF2{(?bA*aED3pl+gfG1}u@FqCLFDw-#*P*>oKG{jB7zE?BrCd#O1*1~#0S-| zY;3G3nJ=aaXPXf!Ajk!pDd`QB^{4$+^4=A9mI}B00y~9=ex6EJx8|dN!@j?aS(wc} zJet@rn3O@EiG1Sgnv^~+y}6>3#UebM=ZtTzNgzFwS6H)>S`YjUS4a1CJ5C-6YZmFP z`RI;Gb%9wLu^`-}#lFK6{1QJg(CVt9)s5o3MHHL2>3NW|Paoi@!MGJV9f) z$1;B$nnX1Z8GU)g0d;C+<5lY5gnQ&NzYiPrP8)a!n`_twCPED6lkko!01+&Z5k&JD zLo+$FDm6-7I;13so(HYj)`v&Cuf95eWo3B>5VkYT%pc~vuo$3IZYgxhCh{v&$w=_TU?0A~vIV?nf-vjCT?9AZL~IKr zf&numhV2XP4}gP^Tt}_K-wpanOoSd}Yk)-!p7I3>A0oV4aSBW>sCJXI3AUx1!GY*D znB)>aCdl0YKZqD#Ebvl(z;+%vH3q6M3pLg<42DR*0*(sg zoUot>)tA~S({Io%a0o(VQ`U!QF+syswB_KLUCxG3VP}i3)6=1V(WCg{l<{zd@+LN(X5L(+Z`0DOHU9#-T!W3{^_> z6YM8S><8r^E_Lk71OyRr;?6%tr>v*6r%Vrn56x~pZxL=mywG1TM7u4F>6z`YIVcg6 zqcr1&2R|8DF%L3hF*P!Yrnzg-r-rfjw-|s|UoEno(w<_T>e-+*5Ud0f^u=vCa3N$- zOn_sB?QGUKJT~z+i8iq|>8&E4gXe@S^sel@T)p!^@dNLG(2p04z33P0k4O6iGXTLU zf*mNKAw^AkN>ztai53R4BW9XU^CKAhgDhDkRVpf8Bvu4cguNtr66kPBT>v?G1zAc` zT*CWAC`qDWS`#>y=q$<9#Kt6~gq30UVS8%ysCWIDNkYTz&Q<=q|Gn!TVmQt3jbn-RNf|8AcAy`d}SGx7%FE$BtL}x_*iGA)^XRm`c z^#!GSwSzLOZ=59?N^gb23zsvJ3yYOM@~;%oDlGGwg`AuB1;*hr80%E(SL>U!Ahjgw z&nO>Xg(!#bZ}JgwEPtK#PUM>^8UpUTshbx7y;@d6cR#Y74q6P(0NBpjK=#1JN7;`?A34(N(%>^oGiyFN%i_rrr74cJjisimX0EXfX0VRU zjNfOtYj!Vy|7Ee|OS1XrH7GAc5PK-{H4z11;c4>^m0OkONdQ4gTiPl1LCDB^e zTFq))%gdJCSg+i+R$)ea?&ClOFzetM7yBVe5Ps zS{Gksoy~A>kZ+3OE8_bOnkKzd@vPa)*0A>QHnlfb_P%aoovH8N4{dY_&UJSCvvtuJ zs0w)#Q!;TmcpDIDhmV^sR7(Ww1gSx1BT+(2Kz)W3M68BM45=FrKY$+JV15(+=J<`e zjsiZUy4Nj)AD$CIAM^DF>@?^Sat|&?Z1KacxQn_*VQ?XaSuZuYq0kulzAM6HhCL8x^UsB*{C;Y_KYmLbw)q- z`ZJ|%@n?h=LHBc#OI7$SLSgB%^$8luLsMN{hoitb1RuA~>*X7n>HiGrX{4=%_ zm9ki}juTtRT*Wpis8QOGYeGzW)GY%oQ!FoLdZ&>JMzfyTIwZatJ%a$B)+#ny6Lz32(pJb{k9PHxBR zXM_g4D9*Mu?AB@qc`AF|^-WID4YpmnU771&9L@Hn&zLV2mn)Uyh?(~`uUcJnO-dHp z8cGkIaPFfi7pEO`FLp-OBlDG{2l>7$RV!jEcJ}wnepMRHTwgsL2A>JWd5?JE+&b3k zO&0c02a`tD`qpaJUW!PHD!gOvY*ucXWfk1YR=>8Dh_o6x_y1~dYj6M6cF(SMtb(cL z_oVmml3f~5x^Ip2C)Zm{aId1wz+{I`kF;lbCP z1033#x)>6B*xJ}R^LX%+{_6@J;Q05~jHJZ>y2QnrpH$8C5pC|uW@LyGG{9Pq86F1YJb^dYckD|Yy zfk)oS5~$AbcP9!k^D+LVJI#>qLe4&sDoYE*W zBO^0CooYLQPQ5aV+nHkfGW)aF&*O#WTH~v2wQDb2HjC*7TW_D;bSFG3+x{rmP&h1< z^o=$+PtD~{LC`}D_IilU$4>vZCDA{+B@hDIIak0}NmR_=rBtAB_Vs&YxRP60l6aoI$*vN>8uj%0U7!?oi z>ecgRKaM^}Q3gT;Xu7FS4eweu}^SGm<~t-|{udmPLe6>O@+e^1)5qR7V+ZDtr0{rDXZhwD$=bNCG z79LPgMl41>hx>Da5)s2qaac_H@`8fkprPU1P7rd~7TQX)(Ny1C3w2{-G>e9X@4*8x zjw8u~Cc8sFns}TFM{CXXdczQcvf0bJulKCQHq0h-{9c|^75Q|t@6UKMxSh@Bv<2MH zW1>f4=ALtNmA_7OwzRa!=L&QmwV-1M}YBhJ^nyz_ky@3+_X2TPqM3_7(o z?MA%>(r=f`^>he$9CowchEwQ1vzU!VY*G5qsy%BfE7yw0YE@NR9Q-_4V4BJ*GL3xs zYV|9DN&)M7ak28=2UCo601&R{%)78}tMG_I_k|5Nqc>~^QR?2o9o9{I_BwjsY4 zsI6%7dK)XNFnk}Y`Emvp^$IPh#Ndm?*B5VcPTW5ij%Bn^&=2g@u+N{>tBurPd}9bs zbXr_AWoxx+&GzanYx@Xzc-#UK*{#(C1vkvbwa{sdNUkYxh?ACT_R^S*&w-YR$Ku9i zO&5&{#m3-;3x#tg6&Dxpji?3$Zu~%Ta&#j^%yu}MhP0rH;k`d!BOoNan-om3Uu#L^ z_eLZl${k55GrCQuioa^G%~XJeRvAfUz%xXrRcZ42nc?WEpN;I^?6_kUi#v}@rKP2n zz(1v{S~ia?r(7Hp9{A|ARBP^kL%G;TPGlq;PslG;{PiFii!ld|Q-1@?dZ9AJ*2rkO zP|BIUGGUv$hvX$II9NX(k5k&O^Yt}~T0)CkL{#+G{YAQ(*Qj3-$h(C9eEMXFnQ?-_ z!jUel=SDCKe6&~GgoTCI*K?E@_`Pn0Z6F*m;18L}=tRRN1&3t<5x3Gg?e(xl>bj_P zny9zAl~9$0hp@$Lm^wbyfr<|#P+WGpU*v>-s6L*n$a_yLh)>{cu*Z)J+^XsuQ9CMB zRG+J8VF%B5-BzoKEXYL+2LIRRrYh4>N~r;%b(gbcQEhF!b`eLK`CHXTc$}c%;17s} zpQej$Q)8l{l8S9;)_BdH>Mdswr&UBn(K0Ug$MF;*fBg92&rfH}T#vr6@OLo_xEf4HrjY(i$R?l1?Qe=?Pq#-K-xQVmwwW*-7AkEWFl`O}xm7~5 zN!Zv~{T?nsd7S$qgki?(ZI+5{{Z^kCvlgKVZmS)HCHFe-s3JW;d=yVH3eSIP*fppfB zP1F{MR*}%CkC_cZ+C##&Fil(5l&~$WjK2HNGalNrVR4&oUFRU7T z%K2i$Z?C`J20*08DL$=M8`I4<8eq4WjY~Hp*@5;d<3CX7EgN!kX`pNc-u8S`KbOUW zK>qYi{d>o4pqDUZ&RPV@dnRP>bS_7mg-QYv-o%j7qZxA$c*g)%!tJM@Wn0bn;dOV z=0A>S)c4`D?&`O=IPQq|BV#tiPr|`dRBwPJ0rS*qx^M|-w!w~&cFjI|d+ddR3;c%` zmm^F}%>AQBbg7cnf!LGf#tSb0*QCS4H1+R#hJ&m+{RD;=?6(jtW$KLm4WQfa4K9Z= zRQ(?=zt0cgb34JH-4QE-m~V-2p0Yp}=ywu&-xCH7D0qz`dl*sXp$>$?9c1%+up8nS(>zELUJ{7m`ZOh2LQl+etc=K2~7Uo3sNyF%hLI zlnT@C9rz4bk*p_0&j1!SE)++fY>{*d$plKBaE;B`V<+v$Jc z)J=61NreG}(zHV~D1Q!)k43LiE7bB?T!<@ihBXL&-%=~Lq3wsmNE$!`0!vJ%i*61k zw}Tt?^1qPBZU*PBUv-<1dxj1H@QG+*Tcg$tQb1n`r;sPH)_9P^r%74HGfTd6Wc3$d=N zV<|1Oj*!j!5|UkW1B^vckOmVt4F#>lTOwm_UxZ-zw{McRXR=9x2!G>4;=o*aVqu)* zPn8B-c=*q6u9Q+Vq>m7gkkSpS3e!y2GJ->4UfpI>r76ac%~q7omvt5lk`+1XvIlVGnB%*JtNzw65o zMkjNE%6lp;F0RS3-(+$Fa4rl8 z5s`yLaBN~=07AlS(4|n$BwVa<^7e9{LX+G8a~cwAc&0>6i_h=Xrc}?&{9~xQ(#yyc z&SvXffpm%$O#%@xhNvH7@Hj2cS3hWorr7EG(Q;kN{>>gb-vNwgV^_HF%ua~GfRSqz zoI`oN!*}CH!Pjau@Fb0spqD|Vy>+HgS^Ap6o|N8jc|vX{TwZzVIiH;Y*Ifg;Jp$f4 z;EA9))+y0(alr~CQKA7<-(WQ-ULv_YOsD?dP@nxlNH~T1O8sg(HEk@60Rok=zwA#G zCYS+YIu=j)d@#${U@c=oFxuu>Tdgm$n&XO7wNGf5_A=M(%zH&kSgjc}9cI7i^()h* z16{@A?qosP0`LU68R^v&AK`ZeLofa%ZbrqkLNUd)>~uGcE4RtyEnlHQn*! zG*048vpsd(*-y9g)v!iSBi42RD@3+RN*{Ep488q{fC^ba*~!QXR4S9^itNEWmJr?i zdexQ%VZhyd1~}Y3;;lr2U=z{WmX%&9m2V+fN2-+czm*rdmje(HAa-GItIe!Ae2V4C z-P=Sc2TP6ilVj=1NqQLke{PdXi6Ex3v^^%O{)`Ue^0(bNHAQFD;cdrs$Y^|odF;XXfOx}A0VK*@x{`suAy=F0ZjV- zJ(=A`$4@w(KFU99+=gMo?PUae=MxN~7xJ{AUqnwIWf(g?SEj!08+^c7x@r370#l(7 z!bvXW(!}|@?%xQpE1s$=d&G~=xZ%%P3mhkuLZIs4%>Zku3qijV z(d+&^o9_*J$%9$)WZsQJCUw9hNBujP()>v08wWO@huF_!_Bed*-Sdv;JsJPi+0|ya ztE4_)EBIP2mrD8vsR6kCLny!uty%%H>yaLott)f-gZ%OKbZK&W8rWLa0>OV3ju9Ce zOzODbn`)@Ux+54Vx@PnItfDkLo_$ASQRaML7Z~^*5q~khhTCbkORr0+#AKcC9*AXj zOEt_i6SpM)s4g7>^%L_H(-hLjjJm~Yrryqt@Z(sifm@|grJTcJD)J-0pD7!@KO7zhfQ-BbLPRBzp>Ur8 zp7}c-?h28qR_b7oGVndG0hs!|4p*by8m3K^cDvVj=Ub(T{f0R0hu}W~761-5-H8(x zQQrXWiid4Nr&Rdu@LRpBZW|rAB5tCKYj&2Pf1YX?pIW6(hM<3UwJ{Yb5#xNwaP&R3h;0o(>4#pjDoUZ6puiLrPK6X~on zdfNMAE!&~o01}P35n?2{Mnk{lCK5pD9v-d=BGS8NdU|Sr)6(}g+Px3f+j$e;_CHqD-eA+u z4_1Opo-bDaygfo=Dpe`b$`k1asuGeWdE6aFv$vPWE|sXaV$TuuZ?H%dIn(L%t9RTf zM%Dsq`E^UfK}`)4W`(ls$$xTWP*Vg3*_U^jlw^&v9Sqi zAQWh0bUI&ag)8uIEMqm7>*>NYA$=RqOaOE!Sl%mEH)Avf|6LyennroJYqn-_aj{g@+F%6p{oMBr zNiLsS8;8r2!$a(`pFAE4)$M6q#d6u9bMzTq=z2DlsvEuOa#*=i(;QrY`2EVC-M!o;9I|S;e!^1<-@K;9KFY;hu zU^X_VK0ZE|l&P;T;k#q$z1?~3O7`+Oe1^8VaEzAS_za?=#*XYXrtTN(^Z6f6P{?#R zY_-Cb)>?kjDty^ot}ojj>9F~cpVD|gQ&n{-92~Zj!U8b*z97t^;^eeGKk%Q&bAz!u zZ61{}pU)SgD$FM<6PP2$G_+EMHirfeoY`n1F{WexvE(GsBy|S*@*jZ>-oS9INCu0T zM9jXA*5CXf4^Wl}1y*s=6%`eo_s0SPWwuK%b?S!B`r$65Q%c1?_-ZuR0NYMwev-#% z6zO)GVQ-7gk`r-~a)S-`E-_cF&tnp=yIuEh#$daAYS@c@W@OKdh1IWTlCP*aliM0d zFkM*2WO8>93(Lp1TK!JAOszt@v7x`lkN))?ENsZiR`0J&&c<|hYrT{C@$Hc-vA-e7 zZ)kAYimbrO!t#{UVXzbv7boZ7;Lw%=PjHNmgTrjUZlm)-4AQ>(bbU?ONv^H@8}iJ+ zmqZm&QZ23J+jhqbPc00Kpv0P{y!@RfOYz>FpK{k&4>ec zQNF}T5i)xHNr8Vi-U;jzbLTTk75JaP3^*Pp15f~;-Yw;S-{@fvg4)>ck<8$qs(6xw z5G%=j7(!;77ly;$2t{)+fCBbL<|cFaLuIa?Lu{a-C5(-eBhdyacN12BE8ff;6LgIA z-uHKDY1p2Kw*TlV!OVY4+rTK))LPSEz2o=3tF5bxitupX?CL0VU}k3@&Ag|ZOZ=o1 z`A}!S@neWu-sSeqb@WF8bZ<`&Dh;V_seY&8%|1h`t8;>r#Xr_`;Rmn`V1EbLTZPp^ zp5g55YzCWUwecXPBRe2yPcfC|2yzb&4w?g^4UGkx`GgLjrYb2UeE5eM;713R0q7j* z0=`LBxx~f^OJ9UVr3QeVX=JUgu5KVU)51Fkxw*bd3jg2 zM>{milznv7yKBg9lR3V0s-;2Vq9P*dk?Nnx`{REm{`v(23wA3%T3$;nAmp&ZFiBINfHwdnf_e~+O_@j2z_BCtN;R#+ud|Vvj`@9dYX{Pt5O1CDOnH7?1QWzhB*ib z_{@a-j3SlwL;e;Y>UJ)XES$uq#&pyV;Bx4L2(XQgJ32u@U_gI08TK{+9+9Y#RR2uM zk8g^smx&wK_8rYV_KSwjH(=@I^HM4MKI{O5>^04>)c@MST>PR2Cy@dreTg(tJbJOY6 z?G`^oX$WBpwMY1T3dMcgzLCb>K0P>~i{Z2vaoQiF=_Ef52ncwGHUPs*N(vSh7#KK< zHul<6&J=?c+WXs0K)KMgz}68NG6f8oken~|Q=HALZ171<1xQ2!fHtY=N29w$z~iDs zntVHs0b=zd-;_(#`IXILV`&TherDLRF7(3{&_gf`B=Ue`w~6=b`SAu_y;2J~Sp?8| zo+G6O2jhQiLxa&ANMPG8*VQ+=YqWcXTFB5ml4+S_|GkkCQ(Yq91UG9iXfL}R&tfE| zV$kswCL!ZtUx_kA5TwIl(uc^z6A99*jZH5uYB-H1?$jb)U3jm;PI*Nk}a``O2*?T zPhop(cK)iYBR>tdKVcg|lbsZ#Bu&{)==FEJ6B>c>5gia>UG4BKP^;icqYX>BQo@Un zGl)}*#;j;-&kYL=MZ#sn?}oJq0G6d%`NRF?)&u~+DuJE&?vz_Z1pNwG*5&aacLd-( zD@~3SDXLO!@@6;tu7hy|iL}pzJAkB_Ha6eZ46xJBfRGo*&Os$lTU&0FuPb^lV#&9oBf93@g5u+u{%cK0RkGD zYYUH6#WgjPrTbp=tFU(~D^_)uV23_G$3(VHTjP zMMU1?eoSLJJ73dAw!hv595CmD_aVy?2=CSi&S(4kF*xJ0S(#E${OO4V#SK3@u!VQx ziglf@x8KZt9H0OwZ5c$KaIm;;>zxp^5Ih=9I09Zo=TbWBn)IiKlkI-E2jkl-&+}~- zr^jn{0GbX^`aQJyzu8^yUcLN63X4?&6#BthWo2b|C#Mp%3d&;iZT;ZhaHNSWZb*Sx zJWkP3K!Pn-?8P0O-W^t}$S`<|U#dO8danc6F5tIWSz!X+`?luh7n@Ui0G~Mw4hu5_ zBAKdv2>0JBAwdi*S3Q7yvmy;I%#(}@5OYC$iMPVI;Njsv5-WxwI1>u`)fAhFV|_;H zIRmKN;x$}w+VPyV5d>M3kfqH=M>Bw|fL?KOIlbEKZr5#fi}32hv6CKdg8v}8!B?fX zH<7K~&|qsmo)O*-0kFxt-C?p%BBA+mir^}M$;hQO=%A1jUpAV`@L^)Mq;?=K`|`Rd z_fq{@xL8bxtFV!^4=N=5A)@Fwo7X)!00J6fkI4X7+T4BQNe|hCc@58xaNEKjUIN{p zp_v@J5QbxL>VcREhfW=F19TPh9IO|}oRNDI5Wn|^62YZZk|?4D@M+a6?>4)A$1v(@ zXcZgJJDv8iRRJ@QNYpt3$FswPs=YU#!RF?2yPwtO;LF#~kRLzOse``6$HeqO3Hvkj2xsD}T(*LA{_J-DC`wwWP*4vjKcLApIr_eo zTOg|BsVG9&@%@dWi2ET>V+QIhXLMAKcW!zHic4mNPUfTZ4IK?UW^2vWV?yfc>v!?! zygizL=masURRvdjiGBb8gsosrYHU_R5L&B*g&67GVa0;5(P+3<`wha<^dU!Af>>d4 zzvV#~DJO-Du3&M%&NmE+4Wxk>&f$+5f7cgS#D2ECv?+1eXfJxjTQ?LEyeeTSzWO=; z=&%zz(#V6>4qGPd@|Kxc+-d4dha~2E9h2$8BbYWxUY8w15+cNiei9>aaJ=p<8#A*w zR#I#ra{$hi%RtB;ew73YnIF(0wC+yd^wH{lnt9#yzv;Hx0TwrjK+uV868s+I3ZywhzFu#%k<~09(!$4NK4+}NQXm7-|*=et5 z4u`dPbM$RX6upB3hLM;sH1ab*p~2A5l6@ki`F)=t?5+zVBd^O0R4)*(h(7h4ZD!Ip zKnS5iH_Qa63Af3Rr%XJ|3GE75&X%e|3Zs%=nMV+#*3ESIN+6qkiZWo0`Iw2`YK>0) zB@GT2|GCB69s2nZ5SgKHi)~lbhE`kenN&VzRl_M314_VD`k_#XlIf*!-}9q0U~{as zdD0D$FFGVs)z`CiyM8RXUC@H>}^ zP6LZ7uCg>fs3Yp7B#=^Uval%K)9J3kkeQrh;V-7;zMj5E{XP z$_TLPfnbst)I+0+Q*Fs8M=YQ>^18+a0|!s&%aS^JKF{t^i(UZ-%Ye0lCKaY7{i#3l zSe)nO{-6qS*vE;(YXwsB4MIjg1SY0&A{hE!IB+K^0`grR^?ZeJdw7UJV~mdHHFk6j zOza3}5(t zv>ua3w@1nR{JE8YapcGDi03V1K-GSE>0WD2x6LO#=jXWPBTY`zS!fa-9&X5jT^uNEGh1?FFEaH>xP~xjn_e_jupKd}Q=9BSm;2UT+w;aBsPOCoXT^%8I+)bYXfMeO;6lYBES-OK$|uec0KgO#0wPT?sX(& zLTSX~D#3Z5WWUkU_z%X}R!PLU0JINn-cjl?ZKVOo9-#k`=!D7)MA7gv zjmqGk45OdFi=)Fu8w&VFeJqsh`Ha4e*7&YD!WNvIlaWy#z*P$;i`8)Oo~Rj^iYzvS z5lo2NHr{vmd@hHDDRcTtnt$Y(T)qHgxg*!mt3)_slYEVdqqfES9?|dgyM8ALCV?Sy zq{oRxR*;bm!AxpZ8y*q1!vl*p?92dR9_moqe8pLf`DB=;Rem0$`3KW{NuByP zLBmRwc*1O6SF6ucvi*hb8ta(2$iBU7WpA9RTW<|bEv_fxpF~{1WY&M6mCP1@#A70Z z>w&u15G&@R2?@!_$fxy;zHaSxDhF&#Lrzu*c|c~}O1hk#8HJrA&t0WBSvgoP%mTP- zxo#`0l*{DoEPh~yfNx8`?u-A7WYlZKQ&CM%0?WZfcBByO9emde3a?v)3?OuOhe3NB zy1AVxiqR}pXj4(+$fAb~b+4o%k9FHw>VGSi{Yc}QAoU-XA9yPV@;&eQc_8IhF6cg2 z2@G3rr=DcG(j`(QxC$if;flwgxvjFY^7cB}!&ixp^@u>O?Za$AOG+qp5IZXjn$(jR zO}b?LqWAdpwAIZ%0$^j?tSvW~j&f*(u{nG(;=$zb@11QG8!6QrNv1;T5mpE*{hX8% zd=Q-tqH+QXim%k6glhd#O%UYMpk0Go^heGGxkvyDB??!Y7?@xt$oe6RK^O8N=ntmU zU-H>JTl?cDf~`b0@qa6Be)hi=l=~aQi)kXzQveY&X=raB9eG}DH}8rYOcOD!Gyg~I z5%MAjL>0nZo{K+ST_B^74fOq${7ig&_MZfkIPg{yXbHc7>-rz917wUsOQ1%}r>p9l zzX8^7ABONF4_kv0SZUUw$C${*Xbl21xk1nh+!Wuj_@tjuHaQV9!0z zS3^BoiS(kr78k2kXd$#=+3yZ@8yXtYe4~Z@08GF{25q+??6%Kjko}q=e?R!|7*1S) zCh5jzHk6P!#q>KTW~Ct|TXz(gT7aVf2=n|E!3J;tP^hM115G510XX6S2!H@>iRR^V z-1fNIrnoGIOFaEi;GRM|cU5x-Kp#MJKktt|0P-LS3Cn;iA*Etj%@Bng0bf4T5r`{V zc+~?Q*H>4E!zVzvmKj9_2tJTgayOMHXFBp}W_H%&?e(`q^IfMoOKqqo_aDzL7$J0> z&pa?NfQx$!Oy;C}v+khgoq<@9xY$@-AhibIWjy8+@E<>pOC=YRp}iuL04}|oyMC4P z!5xrq!e+b7LUJ&c&T2lEhQj!&U1PF!ccy(jTcX|J6AI+bOk}V#(9+iUzmZ(KS^h(F zE0hNtjvfG<0ra#SK2K5uz&V5u#9Aa05CdpDMkyIFvBAZv;JeWSCdJd0^O|3$!m|Df(l7M%(B|uC;^dF~jGZP|- z$~cGrMkE$+tBe}3V}SGnD{Je|^qREpcB14Y91egj!91}|tx=Vb!0hJ-%N)G(mm$y- zvA{h6DFBNQ42}>>cxGjga0d8ti*iCH*UvIAY!*`*+PulLE*2I;fZbKNJIQ%D2c*a< z%$IAnx?g}{yxj066l?dn`M*3N^vNUnuM6O4;jkCS+hmbtPM}>7XOC$;-k4&+7RD4w zrCdXDTy$3Ol*&CTHrQ%CtzvxtG@NGF;Gf%^(Nhz7JJQ{a0*4MH^^_gYG%BainvV15 zLJ#^qnP|>ZW0=ZTp0?QHrfRj{EU#2adbSot<9((#Yjavr^`x{(UVTa#$=L9|J|0?< zxR!axPuz_3A5~KlHgI|h8bABsXCbzMe$$XPLwL45 zso}VVW~t=;B=8u$_9r9D*xH*afK@bD{8*l-%zmal%a!_KJUF3{Bo)w(rnp7 zAlHH={NLLKDpdj>4jLXFfYQ$?KW4;YZ`HV+NrxEO*sg53caLXsen~%B_-?q4RX7B! zeC>LxVD%Ar+*w{e9Z&JVLxr{pXgmtJ5Qv1UfbyP%&Xz$H z9~mdNkB%-|C^=vLq+Y4BTxFa)i7S+g_H%XK-E9dO+)!~oy^Ie( z`qwr*d)8vmrO{E|CHtkyKD5O@AS0v4NvY}D(tSDox(L6P-6);nVypavDSSN#?Veyo zMeKI}$-jd&H49x`alS$7=$hi%%F@!x{P~TpwDi-c{mka~Rqon0zZ<{OU)5NzfR|{J zu{CQkan0&lhEAi;qA#{Ph$ACs2w|V5j8skRS`QCnL`)iDB`QL;-WHpnCGScmUrFB& zN0+~?NRT-d={@w-_6bn&_MaLk1J` zEGN@Y3=vl!Kk3E_l?G?+9sTElD#tMmuj54XFIA3l_n_m1bGM22Wgn~=VH)XMv}(oK zHCwK(_q3zZ1d;w7)g^&F)db#37y>F<_4TDu7)X{)=yUl_CV^hLS+xp9=d;*Y& z3)+3DU~&Kw|M2)|I-K;OX$#-|ONf!3SKGw)wD}-BPAY?Tl$0spRf%*oHk!XaLl()f z`9Xte;IP}RiUA4P$H!LR_1Z<+_U6h!Vy>$>*VbAaE6QJC-@QXb@;5g#3tP8atRg^+ z#bxi-=?18})9w(n=d}lb-}sEE4P!#|IuUVM2j2aJ$J_tJX)mz5d4f(z7&cCLcfQ8Z zxq*P!V2Bh6*kLN=4@hn=;-PYK1H()KMGn(0n)%lUaClt6o#9f z%`q7=!po%3^g1i~mY@Wbgv)0e$r(B4mgTXoWmpw~}q+Qa1PQK#mJCZJ6bJb zcf%X}?NTnh{ShNYVoo!?$4)QrlMX>KI7;E{&iz=%+LJD?DOxHXr)AbN?(g{UmcG zpX*vA^3c`fa?@XK`c+JI+s0Hi-~TNS3hD{QX?tErSNF2r)m=X>vgsjndT#C=j7Ma} z*~NN0xWCvmav~I6U-gc!)WYGbYwZc0AN`@RK8|@gNX<#38kMrR%VddrMY&hHouG&2 zz_f=)JZ>BrhSqy^xpp5C`@5r?WzTiHScRCe8V*=RWc6ZqL`MY{4 zo_4Ash5!_h-5p3u^fp*uZAr^*U_!Q3IsuGupM+D_#3&$+d}#o*5oRUy$3;k;*RzB}*a_Q;vXtq#q5MpH}6FfDp1;1XY8 zmD^bS44CPgD`1+@%vWbCjq?@SkC$7)9lp>;h8S+u!Ce8B*h~fy$umq3KlZnTf(?vOZ`^{(Yo&Cjkt zQBFIZaH8hC^AN%P(a3rO>H4krySF;JRGFDr8ucUKxCP2ogFrHi5mfQwIg*t*ux#ea zw1L+V2>g{7$)~!AdEFL3c<5Dvd(aU;hXmhL8fs_*t6A?z98x9 zN{C(q830Hkh^;VYBcE^-X|}+(0vVxfe!LH%Ffjxq^_4nHxWMCW7M468K1~SwE3%=p z70#^~iFod^v~n24cfOvu>{ePpZgtFQUj5TO(Q4zx7f^67Dc#t}$JueqGToi&IawY2ljCUaD^yGII zlL1Fnx9Y$Bx^8^GiH1_d_X`CVN|_Wu(MnYYhI~t@47Lq6ONC`+(P#Tty$Ti<7U779 z9_6B8w{(j6l2e{9kUA3J z7Ec}$L_i`OsexM|7?SptI7o@=B9vK(kMk+qlKW2(gkMCx^C&Z0oG-Hi z{kVNtH&>HDGQ0fXDdDRhmVdh9o@kL5e$y}?E2B!6OZ1Zr4bF*_6k`mOPaTne2zzll zaSB|k^8l*2Y>9)m-lO*e*FuRB_ROUi|KCEu7inS&7N~lmd_Fk?PmuS9d|#K9+PI}0 z!$_kV=~?|*0s#|aiww74+joC5*Vru8A4r;8M8QjcNL*aI63p}=lNk^+a*lLhBlwfAz)8S+eH%q@;X?}WaH?55za+9HZ+B>4y@)1 z^yiac1FxnCDOmJHbQ`U_g8^@Amh>3G6N!WA=?Vac3c}v&74W>~0uy7ZqRKgL@R-c; z9OXq)g_4(_q_QZJO?NuHtFuhLOy=Iz42AVy_-2TJ0}fr}mPjV}JG*%)EuzlD)033w z3PK8XXpLOEgu}B&A+KjJo~YgJBg$oURaLo))D>$R*FdauH_^o2XhP7+@mv{FUWDIv z(k*((3Xq4TU|1kNE`-XPCm|t`%j2q~gKAEV`OE~oE)(Z`AeYO1Ge^;!X#!-ay;CKz zG)lV9^%r<^iZ8ShxJ_wn`#Lk*yu>7w==X`z!hkIGHY0Mc9yY6W<#iZq!>N!JjbS_F!5BouNaS#5iNBn_Qb7dQN zUktxUM`s|?OX1yZKvl{zM*6g-i-rZZiC()GjyWr<^RV!+Lg`0oqd0s%=3A^~rPWaE zLo)pc{}?Y6wqSI{Qstb!@>=N>bT9D#hqbqis&eh#cq!@bl#uT34ke`(L^?#IySoJm zX_4-bP!MTp1OZVI5NV|wl@iY6-Fv&^{6CxzXN-63ca1&Ru-1B>=f3B>=5_t5xIXymB&*0_W%O%hjg}QWVe4k`h;MQVtqVyADw|BF zAR5N6$HxULkKF5pbjLP)m284TeBqK}425ZAg?%}kgee3t{MwRA5l(V=G|pNO6X!?yT_SK;7ED}Cx5KAN{O+KzG3VRdVtweJbr>( zUB`=W??p>sO5z?zy9}P|ta$e69hj&1Xe}gX8aW#iGdp!-%D;lDB!Xv zIQ&4>*Ki?5%#3{9+$Jj;F)J&}k~N0U#dSmFq|w{LYK??UO->yG_{kqhihqxZcQnxB87;%As$7uv=5joX$5+VavWgLC!P$l<2HPT~&_ z>pO3;hu(xb8pjSaa^4oF)v+WPkjb}9)d$RS$r9cypzCtcTuS?Cra^EuoN-IGXV;Wy<+!-jeT?mBX?z271(qc`GRU-JbiQ@p=Pq{lgHaEjlJd=b;a@J zAj*ty>CtWs>6{PABU=M_i0`yIzPx%QQqS$Vku&!+>f%C;EN5YdBtOUgL_DL2h3Axe z5gA|Zi~li(d>~)>56hjr^bm6cm++&}h4+J}B8=q@V}D42^9k2>k1xi8W&-vi14R+B z-|;qsuR#BJpQKjQ3X-fx3#RHVI(AgZzrapsW|0vYX~F*JtTU0=(wCZ?35KbPfow59 zz~)m}XjzMW=~D&W`g!BCYqO3iJ&VatR*hb~Y4qM7K||vRWUev#Y063bnvx3pJ&Ss0 zSERf_bFlu7WuJPY9T94Cc!P*4a=`GCd=$a)>tDAj^scm^Pfj&N-RWF?1tG%32ncSz zZb`*|s#BrCM$s?R+1H2rejPtkPHHtQIYE+woE%}qV3kK+f1C+jSy2WWoA77&n2OCP z$PdrI%#fNdzHfMtPS7jAin&@f0 zFYUDIy`tV^tTBG{pZ}n+i8@iIBo@wD>vsEML?0_7u;E_tG8={5>mBx#H|bmtY$_S9 zvGSt4GtG) zN`*a*jq2t03Kiu0+ivjiVL6(8vfJ%Ee)%p;Jh`=D~H;cv`Nz;$B^%ue>4>9CkY)q~M=TzXi{W;x~y(z1klc#|+ z$S}Vw=sx{o3Z^B6#GZ^qHP~Iw)G98d4O^3S#ojI)ar+=RMfo2yRfTp=c#?BiS|#iW zdfp?nX3FJJ_&6#Mq!{5!i(Lgj^pK{FSu^L6&iQ%Z(QA`!x>(jbzxLhs(#1(`?+(2f z(6lv@^jWFJi(tQ zyhUV=l(GBTFfjU5%5zisiSSmf65{gvrxLlJ*f3r~!*6lrc@O?pm|g zI*fHy{;!clv*rOF@dpb)gd8+uYH9xzur|BnAvWKAgk}Ta@6Q}`J5bUd4V!p2YxckC+L$j#v*|-Mcs-X_a)liO9rI!IQE-js zU5(iBim3jQp=*AIEt>W*YIst}bu*^>AEE}F*n)Y&Q2I5Ww*~Dx*@78Mz;8_HI>Y=|_r2OVZ z)3NKLD{)qAFXoJ9kfx!p*qJB(Y(_hr$Vq0m{|)KsH|t%*w5Xh#<a!aWJne8_&H z8u;kfvS?&QX5RUA@?Gx@nF=xR6$tlmlENa#5cwpyXBqZvkT{VzU%!66XQKZmoQ2tU zFalhKeGdII#Sa7I@d)0rY>t;49?{9y4k4vAL^JPpv2MO_w0uvjQC42ACQJB+tk`+T zfbp^SO6pNzp#54TYy5b1u_K}Om5bZ?s{CjgW}nR7OQMdR$rEN~G3{V<#pBCNddqGi z(siIv1xZZKBOb7)?k{Qd1xUHdZ}s~L&8jQP=gstuNQGvaS==&cb*#wr{(_^IJ^?Zr|9BFy z`HyY3NDL{iujti{AD=zQkzI}rBxldfXQ~9z(`KA82r$?(Es$mImo`=D@y>qVPe+xV-@5t+mY*`8-^;FxG^-Y>l!pUvrR0UC0&=NL~Sr968k7l zv|eFHRAAqF-1N0a2>T8DUP2|y)Pr2T(_HUIrok42E$bm%h^_w8H5s?tDzcCp9!JZZ zJBNmm92_RQ_5?^J=bIOaU%Mv5sMeilW>#xam$r_W8tTDWajYez+I9US%Ph4zBZuKI zxtgQ+3)Y8axI*f!DH$sNb3)_ufKAxDj`uN&P6$Hd+csaJx?=S5u|BWcE(=|+pq&V~ zXvyF<7EefDDDz~=_t)3_RwRySUqwxQBF(UV(C%Mua`E$aG>H(h_-!mdvY6Cg8(wo~ z=a`0n7@K8J=sQ)c*H#P18W4^!n;_eQzBxoAu@bI{)dd7-Z#*cD*kpKo-|r)pG&xo+jBT_&CE^uL`gez3^TaD36-%roNylEk57iIV9S=7&lFR$DlKwsA8`@Nf!Uoev=m+f0} z!-IPesIqJorRKNUoe$h2ef?Ps{6_bNojFWey(6*hK%6VnuYAK9-0p6qUV8TUhs;I2QYB6a;U05)O@f?h^?$0#6f;8>keoID%t&9w9 zt0~fmvjFcvnijz_3_CY!I#lg!Z5QLe7eye?gg?LQ`2?2TLMwIo z`EY)f)e4<<1LQC!!GWC*8Yttuupn!HQU+Qsj$iC(#pwdYT^y$)|z)Glx2H>C-RIAsjjXL z*1?5^1(~wITWWt^fR032OzSv^>Nz5RMdxj><$K2oA$6q|R$*^!}sj%dsyeA{SRR z1eCSvZ4Qw$%rA{-F4{ zxVBcw(QGkDljT-XuKp+Au)9KVRBesze0q9XeW&4UbZJE5KdC=uKE!RQR10^`|J>fY z43*Fg)q1mr?u4x5;#7eu}-v+1d>p|K~O>2qMS)Lx?T`D;j#T`G* z9dY{d(t2oO`Rx-tW02xjLF=!oen7^mRi;LE3h4<*H2z%wI23eY%qA{=GMxEXx0Idu zQH}}euq@zNh@Ei6U6=FRohSrsviZ7kc+llXfOUh0w|%;|bSXGOTUTCQ{&mojnv}HB zygLi@)}|JoAuzJry1-EXrPEw8JA`3^BoV2oJ{z|*R<=h7Lk|L}2w3@*pe|^oa zNZESKrE(G!D9jp^D=RCfVC}rOVh&H{a57V6PR`XgFm;s8%*f1C_zX7MkJHUJ^W`Iw z@Ng_GlD*b+ejXpJe5g9U@X7!eDIV_j_Q75VU%<&-(L!NS%k-_m$NhlWfk>0%KsIPS zva+(u(FMJ*rZGgJVH6P|q057-u(#VXJ}oWnEG^$WjmPw%T2|JXhAM949~r#PT+Lwq zZ=*qdGOM_d5ZOQfbqZ!OgvpKl{KBh&tADe7g4=ol6?L0j^#5~rIAchS54;ZCR4{fkf#>Somle*|v zgrH)a?V;?x-T64g2Qs-UQ&=^BVtCiuL^TmZZjdC(EZv`X*#O2anxq)cbouppm`{C( zIJN{;?&$U8usWZ@=4{)AA~Jl9_>tx1VsXCTDL+&j(W3f0gJFPUWM?)Y?K)&5l-Ji? zRj_$?l{-*!WPSpS;-Eljh|aj#vjHvIdg#{DPS?A-!Xr1e4qNY)KeoKJWZ8Oa^)S@< zJ)*oGc0s}AqrGc7`z%zTWkb-cGZ---(6z;$`xT16zeyhY)d_HVn-jC?=zV}d2K7P~ zgajb)A^pl@JQro03h|7_V`sb8dk>S9!ox#IeF^+Y3R+rbzDu2_fAO^Nl^f&MChG(O z`4eJdNR9$S<6f_S{Pxz!bK@J`9coE$QD*Hp2%4(I1=o%8B+TU^*tE{0SwaS2GD{3x z`*_-i6bo7DJioTKBo@+bWMpJmSkfUI2vJ(be2K0ua`l_tD9Te=MeF|;ktY1I+1 z#(5)#zXbT$+pA|sVw{9IrMsR)kK6XJ{aAcBk8nExz zEn1H=erjqt3VK`6ROZkTspPr z^K7iFijp%8`bsn;phd`Iw5;_RX>uWY`xeV0ryI~1`0TGWcm6Q7z+}n6`ulBV<=sSj zWXYKW=gXfIC*)DT>Y1VojAVe0B!P+3Tbbb%Di*SaxxMxN5t z*&*%a0@*?#>W9&tG+q&r8yAU+956Bv5gDE92&(zRArqTA2ZH$xsj`{34x}@+Z=isR zt*hg^KAdrO>$%MqM1h=-o=hS?+M&#Vt)b70Y03u*1~8=1(-rCwZrtM?l3`u_EW>5_ z5<#@mkv&h3{xRHkbY>P7i(6Y7#D7*@u$n6m-n7o-x9&32^Y7WtC1SbxHn#&fE|p)t zkgaZPXy!hfjKaKgh3CP`7caWhWWIsG%4FE}*5TXn!96I(T)}r^wxof68P>#fvdvgs zO#m@_s?84#v(f(kb8z0kL>^5J|Tu%WN8BR{0gRC&j{tLPj_ z$&4fA;+gul!6^_WBt@OQTTNz{piRu}8?gzp#UJWC~FL4a#y#4?Y;q~q3EeY?w& z_y8Wc#VK3Wa=Y`w477(}{`NiEm0P9o2R#In37PgrKW-P%LB|uJ2iir^y=h!ekdRCm zh_q=g=}a9#wE2YxVlmXme2&>zw^}UbW?>3Vul3x1icmqJ8;lVaQKn51k&(Dm-xzN2hwqR2I7Co`j_L6mI+@y*l%x48(b3tmkE5M24Tw1n&{z5s9{)=AP`t_e zcJu65fJR~(cukW0`+jpya62HY=r-8l?1h7uhY>sHzh$LhNQ$CmiX*uW;z9eJ7q(xw zehG4N`h%2)9x3U2s5Q)>>w1$hMx0`P18!&os5u+U(}QJ!0?bYqkrDc{vW3aIYta|r zvWL*BqHF&nF3|)E0Ys`DRi60c<~vHM__sxQ?koc#quy($YpxX|Q}BLvO3m*4KkI}` zAD=K(?%iJ%9d*^zjEsypI5{~9a-B@%nY@LB()Kxg)>l`}vNG{mq9^HYg$=|dC)l~J zYLyNQL|+ymIxih3(_dYk4T+D>(U;16jE)Gw4o*AyL@oka6R53@zMz}23_=kp39v1% z4f0ckKX0WuO*#_hRF$Wlr?R_A$!r2z3eL`wsRK$_J#mtm$_lfyCe=otFU3S@s4=2{ zXmvA&a^$N401E$ur9AF17#ELlFy?br&maDzk|y(v`QKwir;lD_Bgm{Tp0b{5wiB}d zmBY@iVy@Na8r#r)oi^mE#J?Z5|G5c0FwTzonLT{!g#UAoncfV3AO3&GPQfDS)4KYf zCt`O9YP_@k8=bhntJ6PTFeU(eW8eGTlYjr^`Si>3>}x_W&A<9mL_+1O&?qnO6^Q(+ zf=uk>VUeXc7@|d#fD87||0PO-H*;`F$?5;~0b~_4HF*r5+K%P9xVyW<-DQ<}5|FKy z!a7x;R0$8?#>R%9uk^3Owf8&kMSlF(XUT^00d$z;MV4dx=@(0okb#vj$#p#OUEz(L zI}PjCuV06h7`<9r)$7+ar-y6jP!0;ZV{Nkk`)$jLXX%wZdu9S_J~-zlKfhd?nF{4jGTjx^K#c!%uj8bMZ}rxmrRv8(yq%JKwZErF+S_^b<3}c8;fXH+uR1zv04rf^ z{1ozqAms&z%en~*J3x>&iA}de#3?i>7nmQ2$R{ss-!+3<3y@Q>=T!!E+YpL*B3zyD z@>`YR^XBH808M%n|H~ch{LznLFS^_2D`wdjx74S>sg=je{-?{ur>M8H6G0XA3y}uI z;RC?}0K23D|7@t1C@!ust#qr?eM2OeE#AKS((&VLTgyTMX^Y3k$Cj6t29rh~Nxxo! zE<^|-P=k;>)iJPH8y@$MZh%%SVSq7A(|45G)xjE#-aga6#6uG4+d^HL z-N*H;EJ}PO){S*>v7mGL%3D5FcV7txori++CWSqmfSQ_`kZ`=-dV|lBS@u2<2C}6C zx`u`X@edUTlK!p?EQ|7jhIP%lLU z2nm#H7m}i2d`pHd#(E$)VG$h@lQ6QQBj|2mBvgm(eq`MIF1Wb3Z&Ep4rsxUjJph&} zzGHhkPxy26($0}5BD5okDnbt?Lg}-*;~M@)rV!XH*JbJCN4LE32tt)lo7kMKjN4LH3$1t>RX-3xu@2 z2IKS;6yLzs&FbYq6n=LD6BbR88l8 zm|%-QfU#-n|0gu=0DRTxPp~P7cT#$sY5UUydoYpZGR(VC8*R;zal$?_E5#BEfq6|0 zNf$ zs}Lowbp3jCd|ch03($(1y}UZFTNMy@$(7wueN#y&Jn_QnZAHQn9_i1an!x9IGlq_( zO?j=!xlRI<2M3wYmHx5ITwZ-Ue&(3A*JF@9NcHt?Mt@*-NJ~Q_WfMm?b^hKExmj0H6>vMj|Lz}LwjR#?sqS;*??pH9COYGf z^+EU0;Fo`>(Z4s)#70ncimF$7XaCL||4*{9%8Oe_|4YOB^S+^rzeHMC;>CUWt0(>Q zQ^3!9{eS=2W8@BGh^^q!h{q(fwRO{a`?WIt^XqWeloj|wbmWF0_+X+Q=4QGj>fm4> z%iz1&#J9YY2;9nV)mBy4pcP^h~!09c)v3!Me*nL4!ILi59@B@v26}U35!%ow=jrA(@){>cqS_7zJBO%z~dA#3y zZ?yH`n~+joBw{8lip<(afE7eUMX`L5>CG{GzW#7WHuiy;+~1%6=qUyxtL4~z4UPDB zg)G<<<2zpMh(9#&4O+eFk$6C_Y4SNhm1b}oN{hdw5dkpb)yUJWjwt;wR1JQcv-QtV z=|0QI$k-`Ah)Vl~BViBy(|FPSz(8q*C|vbwKQQsyKp=U4`ev@Q;s5x|67b*!yesel z|NIodh!{*>TJ(+s$(3dKas8S7R6RI2koUfQ6XviMswMvWA?#6`uM8;%28nDiWbCff zgV>W~N+~=%*u%I3S$#nB0vHwoA|@{eaBv4;6q;L7Vgv4=YYYse-0mAQQ+!5^o3zsY z&R)4_B0fwnbdwO$_Koh`SwK4iA27oYi~EKJrZU(mA4xegfTjEv0A2n^yLCn{bHI@_ zRcr3>X4>KNgo(yhWdQ`)Z~B^<&q{g`Z-0K-e_Q`-pvTKowAYwQc=(mAHWoyj0|VR3 z6mzg~aAM-({P((8dQ&S&;d7&%&nzDwJwDvqi;0z282x%2GYNH_7R+Xs)q7a-)hQVpenuVkgD698D1vS-G&{Xa4SuK6!`1n`_2ly30 z3|j`Y)N>mRV57bPuoFO>K#oE_J~BV*iLr#`bL;)R&iRW5FH$pY>mAzCBz$~ie5D?w zUPpD_36s=@x)!60*ocrC83TCY{zGeUg9Myl7sMqY*!Un31e=)X);7s7Fi@xBk@NQS z-viL2jI-HJwUG$m86dY0MyAdc>Cxf$JAc?^`a_v5+e4vvm{_Y12UkCJhN zJWYYdoyhVPUx+ma93oq%O458DZPP7Y=}q5xJ88dE-hLezc<%$nJqPI=T`MhfSZ8}a z0{!Fst@j6P-(qP@nRZd zV=5Z4eIo2|B2)~5ffrVT@!nGKYsjvJ)H$I%NpwHhlhvn`DG47 z^uR;fpMu#R__h}MnmcV;oLU3m0?`5GJ5fCdluup+`tI}S&LPCSS)ncb!7s2POc-V%*#wH{!^{>2L*F0Ss* z%YqwJ1f$Ok8xzOUfoJ3e#aj9DFnxI)@Qyi|w?Q)$hNL}si?NnD) z!HSRb)6&3z{M*+sG`t%e*KRy|jgQ~u^?jX0p<8klBfK9*oB$F^s04ws!(}OJoULT3 zjMU+^?3YzYGbAKg*g}Xqq=cW3uP<$?*6GU$uwm}{{!E*jJ4AC-4MDoH7l!f-Nm{Qm zGqaWcgPEfvt|1bQt(jT0FTNzIfaWO0SiEK~s^X0s?Ax+Uu3yD(+$d$yJj-Y0byh?! zct0jwhQEjzGz378-nU)e+G6&3nJ#C?D-rO%Sv{~_0tUnaPVSA#y6ox8;hu!)&KQoh z0J7r+rg$(tkX1F%sXEcDGR%E60ZSPc76uIE_zPP6;nf5kBFW!1#y|s#^g=u$*{~ds z@kyo1xG*=#Lpd! zeu5kR`t>(2c}_Qxb)D7il=i@75BL1t7Ej~sn;E>6r64qCiM?+zR}iVzqbzdW0{WUj*jv9V`JF` z66iweS%QvxizFFIme(-tg`eJH{qAKW(dzfJ5zau!tIY^faF^@8#%VW@NMMk@^Ytr+ z(!$bnj571*?rRJI0bzKwgn5|rFG6H6E51R~-teG>7(fU>O4rO8Fs6-I?oSr6)kebneeoTwFy(+3)t+oU)LD13Us}?{p4?v;B zE0`P~|2Fgr7%y5Fpa1jlU&1eeBYyL<(Si!EX&7V+~4=I z2>cO(31nvWSTxi(pK6xsd@L-I$Jm|kcFu+7T{B0xh#9#3>8|Z6Rld2|{KC7!>+#dm z_qipSgo?y5s$0S;O3a1b0@HPmPkQE z6Q(IjzsJ^$p>d@FSu;XU(dg9jW$|zv(b^3(dPMgzUe=>cLxjXwWHr+?o(pYbhspe# z_HnpQD!x>#h_>X*-9M2uEFj-wZ5{Fc^UDjMDG12-rEqP;QDbAem@X1ZKYhx9PI1|R zC1GqPLR!{UB&iv>{o0YUv&WZajm43!`=~dviAketDp|3vL|=_{8d~Z_Ph9Cz!kn@9bAGI6-7#8Olvr>imHC(CXW$Dd$_>*|vv$ zmCCzx)M6QD4s-1kHp)whWXfy|gluaG$2!bJhHCR&5px7e6CD?Hw?Fk6>>{9{BO&db zQJDws7AnVB)Qz$)0s?rj#g z78d9#=;-Ld_hbj@!gSH12)90aMaRS#H>&p%UtmdO%e6GYd=77b>nNSKEl14l>RqDP zAI>yZ&K2G&Y&1kf@rf0XWS(hqY11w&x&P+opz1Mkg}#eJ-2PYhl`(+>sy<%N2=pua;K*XpBUP{MP3?Snrq;)|t6o30vkCo6#H9N~sKsF^?qOGo&O|q_ z0-S?l>S23S?A7>rT6MXi{>oUqQxa36I;T1AGiB?{BT5uF1R%0pAWilVIPvRxJe-!w zF@4AIFx8lMU#F4qG*Et9?h86WEHz)}iUlGs|6lWj;kWhRJ!4Lb76%pr$P zpcmO-1(Uko67$$nc}doZMCpL#0eVp%faQe?iR}(6qk61==+4R>O1~i9cv^Hes+KKt zA(574ri3{$p-^Ton@3lO~nINZf?>I|9Rdi2ul~< zC?B$PCK^ifi1c;wa$5r7ug^;gMD`%>000q;yxqZK!w}fOq7*m3rm3iZLhD2HN~} z9HOtuGZ_Q`d;3Ne&5e|-rj#FSHFB=lCAZS|IT#o$j&?&59oBC5q6?H`l&3V~ax^kg z3|ZYLFm~3=~^S+b;TW&(ct>M}jrlo`~P`wIz3U8v8Hi{HOEA9zb_q(@C-A{+Cz zo*+LeVD?sx395h#2{&aKvw#3rxnC@X_LG#t$%7R2@`G{=lo(*nQ*R{Ia%DW$6`MgS z-yF;Tm2WjqwYR$(QBC<{b1K9ssmwH=q+Grlda`S@cBGZTMXGdnYJZ?s9x(kn7~;8S z7C9#5ugUA%YZ5|E?SgLKZ9{*s0;@t#Vp2?wSt);+>E`vz)fqsKOVlNz95ov-O!g232@G=+AY z`!ou30MJxMtWC}~qnK=@vL+a2hlWdi3;I#;qFmlSi}llu9#L3GMs#`T3^hGS8Q8J+ zeh@ZtbQTb=q85ibqbwwU3$Z)mUf_bDudO#Gk4A57DrCS=%8|EF?h%{JOmzflYE$1N zKU6%p?PE8|`u2Bg?kXNKn#3m-Fud78m#EJlDfv7R!IQf0+lX^(w0M35WITV4%7{F# zjoG}V4_Ita)|hc9_@V@CyvO&Fzc>>89>Gk-!)(H{<=WgcnH0XcM;hne!p!syKg~2@fY|o^^E>ahP{{C zB>i8F;pMRIExP|Z!l1WVc_e@JJpU6{K(er6f-y%`(O~oMPxZ%(c0~C1P6(MA|CBZU z|NVI>4~N4w0fe1VTue+=Rn@bV+zv2wFmUeqws%E5q@{0BIK77&GsG_bu{_fr7=^unZtvmaETZUZ3VY&(y z_kkpXRzI?8R!g(_&AYSj-eI8n`uYwIUV}p@{LjyJk^^jr2KTQ$kFeGJ&p-&OsZ>7x z%*_wwkD;XTRQ%H`50)NI250#z=WUKlj&1y0TC4soci2-r#)IYv1T(n|h(@ zAt@IcpNFZj$Cb?A*E7)p!~afS-Ucv3#t5P7T#F*0p`pRw?U`sSb03_Ukv{`Blu9N$ z5tOe33DMD=FR;HG85*7*Rl&?`ZaC8oCStuP8xvRNCqh7Uyv42t67(H|nPlsBCZuI*R9UTEDveMyb({CF4OT9 zi1@Vynol*-mJ_JOaM|xv*g-3@y-ic3%lvzxsZR`^&f}+{xs(R3y}%}V3I$ccAbhTJ zd-5S0)im{|Bx~#I_LH?r8Riz#b(TiO47{r!D{0wzZjXST)&eQR?$K-Zl2R=4m2~mb zXJ;dTQX{#4qu&*@ghbJR6KGeY=*j>kuT^ER*Bx~sq}j!Z|F+tojyNq^(CC#bO|}5! zgLkH$d&N^W>@V|$524?Hvs@g%G{;Ei2^;JW5F?h!xfD_f!JK_8L_L+H&uKOsn|ks_ z5v1tN9CO&c15e-L$>eG;1eHWH#B1VW`q|I(Si|W%xi8e6%&e>!9v!9&jt*Lu-81H` zsZO10X~Of2;L_sdWZ+&m_W$Xb`ar+2d+qVcf{f#lafS29^%v^z-#zfo z{7;Wwoi5rvt?12~;4uEsM;(-!+!oTly_>`RRn?Gw<)s>;5w3|sflYCN)aTpZ&-Ol) z&3bG-T*kt9nAyJUZa))c5y53&J#4Pk(}xsF5%Vekoy%T~vT{^r<}vi^aQ(Ty`WJ`C z$Hyln)#>>_;uMQGF(DM~uT4TWjR>mCvE=gmCW@!F_Xkbd{p;?Hj(`iM!v5-`M}Rhm z`$P&tA4%ivTe|BXViOWhw_dsdq9)NkJd#aEaeLCm?ZM{yG&;s6cd(|nF^m!+K=BjY zV!eHR3;R6&|85tuPd_#RD%C7aBKj(r{*R?b8=wG-jHNp{f z@;$WgN z{h z4BVPWc)>CSK$JZ?eo7(~JsNvcxZAfW`ml;`A7SKukmSsd_wg;~^eQTY9+gv{?|jvN z@sizax+;)Om#DjA=ZX>8z~@&Uy>3BLkx1q1_7Y`A)wk*2^`C9u<~Evax2>ppDmeM^ z^~nA(Z9)}hmhdy9@e7~Th{{pU;kf-QN_m2{b=!+Twmfr(s9703qlT@~sik%z2b`@O zN{f}}8{@RMb5v<2>#aqWHNZy(MCFJb^6T&os)H)liDfM1waq#6z{PYoz|GaQ-FxpR z8s61;VKCpr@nNd`hU1{u>^h;C+}&fkbV#vlUc}3za9({oPw0qKp`^tzU46So4rIfV z!#(BupRl&A$x%>H0Lw?BX_Yc<+;*~bp-_II{<};nW6ZnNXSU6nc2vp9Y(4#1qEp26 zr{j9p-A$^&F zvk>XE*|x_P%;PT|e{F5vy*hdWhCRe2Bx1gYD8p=Unp3G&pRNYFpyL@x-8Ffnyc-Um zwxc{YmNy>dnO9X~DaiEn_j~Tls#V-DZh!WSTdyD3#`uA^8tmdP9Ya{U!2D7_(jwJu zGkpHdlFD(_2t@)8L!+RFquYiDo_zW+JuUt<tm8f?ZCw9A9}$3tsc(C zsl8#E#GnNK1Y4`|-F3NKj(4)dS8YatlkN9Q+3L|Q{a%C}upvgjZ=@?pUk^dJ z8IIKW;1eRp`_|SH1`8Y{0F#|U{_eqSt4FRhGBQ%m{Edp0_3HHQd(=7nFW#Mo_e5+2 zDFmu#OB!rUSIeGt>WB8SC)X*O3FSU&95-Vc+>8dE$M zQ@Z4UfKOjKg76rCX833o;7Z*Xn+xwaL`9GKX;&^eh!>%krz7#$o$Op~e_`2wp4;C3 z`c10Z?hG89VyIg(+!S=N4d&^0+knsA+}e8S@Hs9|byFfi?R}{qdjp5~u;%YpLjxU3 zUJ7DiVPO~wV&>=rhv{Q)F?T`Nttx};kbn|yIqBE>&5b4~zbLlH4=`HeFDdf(!*6d(h4-jm$51go8VhI7$RPoC_gRS64ny zPcLdW>$v2Ah*#o%1&g%H^8O6n@Bw}W8b#R3)NXgSs0)fr8DcmZZiAHuCi+$K{E9T4ZZn0G11%{;~DhV>6@m!1-u?O_X_0*|g2~$_QyMFN;-)3><&r zw!iGM49{%<*bI`c?aTJVl8j7DxXZd|-my!0eDaJ|$nNgi_@e^CXlndm_HIkR=x)HD zu#fW!356Mg9?ori@?aqGyde4z1BaHDHcA`I9Wv2=V15O0lQ;Mt96M{g>v>h0Gq*-f z;qe=J+E{(_F_}S{sFbLv+B?gX$maJWFf$lBH}~JBtNN8lq$k}l|M<+#v|65k(aiFG z5*mh!cg=oSq@1`gH@%aIk96o1L*dte=-5ZPQxyK1yR-;uYl#RV5)yuER9JYt?P|Nj z(Qg*6ci+Bpe}LRyUZ(pc>VmlY>Hst|!TtsYqQdBG+65>kfvM+ISK`L{SXmu$mN}X! zDNk-mipa4Y<$~J)H;msp+ipVL3RzN7NKyTwRhKRn z_)6+L{I&*95t%7sizTJ{f#r|#9?Pmd=pt}!TxpTr2EmpfA#=2}&F(t8*RPY0Uh{hj>WPc$V}lgpEQ+@V@uF=cEGW;2KW)7T08}!He1S_-I2#% zQ`k&)(F(ZsNX945o7&~;s=C@Rn$H5@gag7KyL^jJ*v7|PcSq@P z$nd4}5f!DSX{f0cDJfAg(B=KP-iZv#G6K33JPDb?4l@L!sAP+gI2(DIDfUIW0s;@A zs(7fYSRO*yTDYi3nPpYQ4^A`2{dXME`bBWG0{Bq4zEgYG{fc~3pLMT2kcunrH73S~ zomDOTn4zGd@9ell*M7YSpZOW#Zyw{W_(pnUalLZvgI@}x+Qj*%4jiB2F6J;zswZ8w zp`#j;ve66+%X+u6F>$VuL`BL`o>1g=36YVJJ$BWX2y;r&yUS<(fFs>%_sPeao!IbI zwj2};s$x$PEdJl#&AdmK{du{rM5=Wp9&HgnZKkwzG({cwDvvW_(75&nvu*|3OLT7v*pI96F9q+fXYtDXf{U+8nIP(gHVgd7jzqV(=h>BGW~Ma$)w22ZOvg6qG`s z%)Rcv_mMW}3^xkF?`%N+z1XmpB&aSy(oznfYiLqM`{>x$~!7rFP`)9%uGHIhA48?c)p6S>w6CA5U1kn`OqR z*aFcNt+N~H?RWk@&%^d6UEx&Rw+4S4HObjq44q=T zxkj|Ann$J&_II_`|}31&|+1y*n=_z5|#_gIju0;$F&n)oIVP9v}2X`xTHatI6K z-mXj1%hIT*J1QRMug>}4o8Q8$c{SlHt3g3LSzL5oo~U~l$V2#5=n+fvS`60i4Bi-5 z-k+pUeqeUuVsh2Vfpw0uhtp$wCSWi*)gUi|M07E!bw+tXx$curQAjlsA>ks-?;Fg! zCql1OPgI|hr!l{IpZvKN0fCZRMNv-Ae3KBj>X%~$BfQ=0ZG31O@WKKu?(1}Mh64^FY@0{$}ggq1swcEZD8UX=;ZhpM`0nvI-n*9e6J3mwc>+MCnu+;YV_u-rTOMLqXyjw zbx}gX`T0)c3EJg;qWVQ4(z04HOcZNesjg#~UF%&sKU8lu7wr@Cxei<~nr!L^(+7>K zTN6>*P=0+UA~>f1N|5&RQ**u`1I6{MGR<4jZxJ>zpG1ZCv2N*=)aQkS#rHF1$d%#0~jtycLX6F9SOCW>7-=Ej%{Ml!3)Mv03u4 zfGbGIrgz)VK9NaR+^)zj{ioV%c!^HNGXGXv!D{I`iDT*YTl)mzX&l`-CWsQ_{BIoj zr8-VHKo4Xc*MWEok$?X1|9&1^iAnSS_4HF;f}*2lSUn&A{YEckExJn`|Ns2;habK_ z*UUxqrZCmg($djcl({$q!#|NZ5Xl`fIoE)0p(DpqS}!cz2#%#)e$iH+Ur?!ge>d{? zzl;mni(STQ z36k^5=3PYo5(BjTDv-9Q1HM1vH$=6A~-{UpNq}~M}~pbo;?e?BRd?Cdwa{r#5t9quuIrJ#Q&L5^IJ?5wdXB0m+&A&YQv zO@Uqxqc9&xR=t~r*FfiGZ;)~+U`abtD+Muy)39Ff)-f2#u{KT#;+c&teh<0+GNra> zL!E;xGYrObu!Zw~?n_}KqLuQ^n9_OiF97)EU5SI??;Fz*N%Ai4-!~b!{Bc66Quz1{ z_g}6F8vW;F(Sf%pFRH7n-42f24kmH1v0V>##XNuaXK)f-wi+Er8=qJ@lHbk$%qzms z%ZwLu!}>a(1v((vJaRbrbhYq7%FY9kl_T8OANQ&3~`A419AhY{#ceQf)~c^$G=#_3OvA^uIl!v}<7F5m?v|Pc_?1`THAp<$(2P z#&@OTyy^7Sz`8i&OI8lusg#^YX%R_j5q0}YsmGphGUBZ?!zY76qXVca7oQkaUXhRf zb0Kjhy8IpPFFO_tzPmT5k|tK-e$uJ19=`XpcUpZ&yrv#+<@p0kxqp6P*~+pSJqc;I zKyrY&bZBU3ax&q?@yZU&VQi&a8y*CR*cnCUvWK?ZEj@L51U*2TT(tKv#=*>7HQRuhR;Mp-xJd9&>Bx|2(W7U}s>UHihLJ)kE{m_PI|O!qVH{fXS-ksbotU+Wu`!{)zkgr= z)_MZ4>oiN5b~tqGSZVMQS4c<*C_UI7FH$~0LhW1JuAD}?VKO!t z%u_H@e?7%AuJFxY%fgmd1FAZ$#c-QCFS7-8O%~VjWW}&4uII*A=A=Ar^#i9z4fcuk zzuUXx_|Rk#c^IgUNbNAmQyqOA_d3d;4Nz@P>B}G;Q4XL1=TQh9RFsoDcd>E9R!SrWv@Dp(UTW8df4hjP*79 z4vi6`E)oS9Y`N}R%q4k(&?jjpp*T9*IEKo|bH}O6cu!_Tp~BSqNB!*(rbXwZFrBek zJ9+X+sr1FmttTT+{(F6Q7EZ;^3>l2F_XQzLH^Af?eq;m>p>)s(C|xk^Z%eVaw`6Ox z=NrLnAPH+-9T{aHLqii$Uj8ywJb{UcNk{yht?l#|fPO_p{QAT(5RH4}0Q;r4Z^Kts z#EgyO0S~RdGV&DqvBMaH_hLQR+qN%H$Q<*WmS{%ZeC3TtAtf&`9pc?m_It_9GR2nM z80jXt)Y2cXVfrfFVsU&$DECgw5`xa4(~~7GIZWF?YoIO!W4+&GGIy8sF{zmWewW0( zF33W&x7ScrRYjpts;Xr`vBUQRZUV)?w)Sf8;2<3mW*F-Vr;-|TY|c{AsTtT{xH=|# zgUeVu(5R!J7-?*-&H=8~5W=nKL8vLvn@jR`ax%l({({UGSS3l@t9L9J`zoF<^985NTT?%(!xk@uKPOdE?ctbS^!=J@pqrDfnsd1{Z}t1o)3#d` zr?nsLC|VnI+y4ltwg{z`Liw&>S^)IXmNUS^yz@cf;>}25tqm(%+p-9q4*2-iwl z)jb(`s^7yPBjOe$+Lb`lbHwg>QCxNPaSq@f2Ce-lN&MhZ2nbV^Kjmg|_Hmm~U)aa` zjJ+8-d0*=MQ!N@x(IB!dHT_KIqbHO8T9ltvdK+%RDaW`BBN1e;_>E;5D(~tsgvWj# z!+?B;xAmQ&0eeLzsu>@2jr_%`UFA(XeL~`>=XsOBUs*~PB!X|!Db+Imr92kyfQ8Ke zEj%@;x7ew9gPn~}Eh$|hSwOG>EW3k3KGcD2B<+paA@)lTES?chco2BdTQJH!N!dG& z*S!g(HnloNU36DdlZfoX-FCbM71*S#tgyH%<%ET{MTfg#cWd@)Bb}DNBb6aVaZW~SL#vQ!}D?rwTdID}t zR{V=#s0_VAD%Pz`6V&5nWo38eY}NGjTT`AUdpL}1XzqD^=vczIZ?RHSz3vy1+V$Y2 zOE*pun%rDJQhCRBLTAo@46W#3dI~3a-Dg#k{qur)Lhg?$#!S(u*7j=$8^a-jNX~@a zTl~W*nI>HmJ6p)`90StC5&!P>n~*UIY^GRl8Q+anQ&UMP<9QQzVihmf%i>ZB zg7WyKn0IfKVNO8t<>V$9FkMNRUv}`A!glnHl@I zyk34UgJ`T%ks04-7c0>tEA|$(_&#srJwMUSTxgb#dK-szoHXvRSoY4+9jZW`wbEMU zN!bLdcy)CEgguuM&~=XbM-jh|rvH7Wxv;HiXT8~Okh&RMtXp9hBcQgHiW!p$3XlKN z-6IbX$gxa=ik%scq85U4+Zr`+!suO}bdDOL#EY^#z@mc$CtC|1zs-<%ewfP6Zt{2w zA;64FD6g%y^4^5XqvqY0mWv9gL~~!; zSY2DQvdX+RGk_imf};Tx9T4jr1iO#`r7;zu@vi>rZ8!7UYu^Y@PX81N%kg&4YA{T7 z8>`{(35S9N7gD&|rtqX`qiTQ=)=~eSK&4wZ<5!M9r?+gjGcyUvjLsrAA&(Jj7jj?1 zlp_mAj`k+&Vknf}Wn9z7zQ-3!Hb(oMDs1e+AE)x!Kv2loTMF0+mj@w|G?*)IC4GK8HPJ zFl0oNA+}jdcw2qC%tHd#BhI<3KS%ORP5n`xlEP-3ZHPa37kMBW_jxxzDL&#(@P&$=gwgThCw;zu$H0CuZI~?vTO7j3V zI~WyTm*&WT9!`)j8)zA{RnoJDK#&w8?8zSki)KH6ZAmHB$~ZmH4x*zq`;ypvnj8{3 zzcpZ(=z|KdB=Bcv;;giW)V{T4&*M^ya3iuTgRRpbkqE}WlZ%rY!1@VWnGFUuKk=3S zvCB|JuLpM@@Z#m=1<5B2i3@P@D0vYJC?&Zkf9=cX;O34BO+Nq3Iw6Yno6Z7>(B6(G z5X^fs-FGzDaNvcX=4fx{?<+PV9+^i=;^Ps1PaJ=_+M1Km?uS<>LBOtusQ@U&pG*2Gb=-Acbcb_mx znr_<~Gq75sqA)a7gxsS% zz_Css7QR-?Mf0xzqD-{Ja_Wd?8jFYgUJHm~u`6$+$;$!>7$l_Hl~jO;U0kfgEIs+Y z?p|)@a@3^4)iQokfw3TE7Y1U#Bl?Rq5giLGO;Tp{ti>Ee+k*7kF&C%la?5T5&r zJmj62rP6!gxfee_M17NAU+!>O95jm6l(KrCr9e|krgX2fhlJIKValCaIDF5=5TyjV4a&0PoIdKeXpu(YOoF;-*a6VDl`+#%KZ`}a?TN>|S^%3BV> zfPKAp($bbY)6|2gSaJ{rhpt*pEBJwlFB=yZluO;{D%D_SZmA@4)<+w~vmw#}v@u|t zm@lakivQx~o?*tMt@3H;pvkAWPt;Ddi>$Pus%VU)b5Gy+-`4EEt(XzCV#GBC2Zy7o zx4X;vt!Q1l-@PNH$HWBxysKp9J4<5b-Ght1AAv{Mge%D^D74K}JNe6&Twc5F(+*xe zY&Hc)6%TW=GsFw3r!tT3ed>byTmk`nQ~CEb!_Fv8yuW1i%19wz+f{wH0i^JQ1FOco zsoe%G^X`C$>K`zw+KENANA5krDA^VH+wD(hOuyp*huDV9AbocISM4R+AnbImbHlFN z5fly&<2$Nf=F#jz$ij1s0E2xpid@-k=<9pr-s%92yu12~k5LkrEPT$j z3oJ@Y>#qxrtFNyI;lb*swCLN#;7dLUy3gcf)1o4AP+tKlR|OJFvC=j#YJD7sfzEfh zuf2V0aT3kMef@}#vueO}Ar6;F_yO?>_6;m~@~#E diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 774c237d7..d154b90b0 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -92,6 +92,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) overpart: do i=1,npart if (.not. iactive(iphase(i)) .or. isdead_or_accreted(xyzh(4,i)) ) then dudt_sph(i) = 0d0 + cycle endif poti = Gpot_cool(i) du_FLDi = duFLD(i) diff --git a/src/main/force.F90 b/src/main/force.F90 index 491b961a8..82a63baf4 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2827,7 +2827,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi - if ((icooling==9) .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes + if ((icooling==9) .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif @@ -3065,6 +3065,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv ! cooling timestep dt < fac*u/(du/dt) if (maxvxyzu >= 4 .and. .not. gr) then ! not with gr which uses entropy if (eni + dtc*fxyzu(4,i) < epsilon(0.) .and. eni > epsilon(0.)) dtcool = C_cool*abs(eni/fxyzu(4,i)) + if (dtcool < epsilon(0.) .or. isnan(dtcool)) print *, "dtcool=zero or NaN in force.F90", dtcool endif ! s entropy timestep to avoid too large s entropy leads to infinite temperature diff --git a/src/main/inject_asteroidwind.f90 b/src/main/inject_asteroidwind.f90 index 0df65a857..37072a760 100644 --- a/src/main/inject_asteroidwind.f90 +++ b/src/main/inject_asteroidwind.f90 @@ -29,7 +29,7 @@ module inject real, public :: mdot = 5.e8 ! mass injection rate in grams/second public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par private @@ -149,6 +149,11 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Returns dndt(t) depending on which function is chosen diff --git a/src/main/inject_bondi.f90 b/src/main/inject_bondi.f90 index 8eb40aec7..9af9af121 100644 --- a/src/main/inject_bondi.f90 +++ b/src/main/inject_bondi.f90 @@ -31,7 +31,8 @@ module inject inject_particles, & write_options_inject, & read_options_inject, & - set_default_options_inject + set_default_options_inject, & + update_injected_par !-- Runtime variables read from input file real, public :: rin = 18.1 @@ -216,6 +217,10 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_firehose.f90 b/src/main/inject_firehose.f90 index 92bf578c0..7db1c2759 100644 --- a/src/main/inject_firehose.f90 +++ b/src/main/inject_firehose.f90 @@ -26,7 +26,7 @@ module inject character(len=*), parameter, public :: inject_type = 'firehose' public :: inject_particles, write_options_inject, read_options_inject - public :: init_inject, set_default_options_inject + public :: init_inject, set_default_options_inject, update_injected_par real, private :: Mdot = 0. real, private :: Mdotcode = 0. @@ -210,6 +210,10 @@ end function Mdotfunc end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_galcen_winds.f90 b/src/main/inject_galcen_winds.f90 index 231367852..5422ba9ff 100644 --- a/src/main/inject_galcen_winds.f90 +++ b/src/main/inject_galcen_winds.f90 @@ -26,7 +26,7 @@ module inject character(len=*), parameter, public :: inject_type = 'galcen_winds' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par real :: outer_boundary = 20. character(len=120) :: datafile = 'winddata.txt' @@ -223,6 +223,11 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Writes input options to the input file. diff --git a/src/main/inject_keplerian.f90 b/src/main/inject_keplerian.f90 index 7ade9b7b0..7e4f8e221 100644 --- a/src/main/inject_keplerian.f90 +++ b/src/main/inject_keplerian.f90 @@ -8,16 +8,18 @@ module inject ! ! Injection of material at keplerian speed in an accretion disc ! -! :References: +! :References: ! -! :Owner: Daniel Price +! :Owner: Cristiano Longarini ! ! :Runtime parameters: -! - datafile : *name of data file for wind injection* -! - outer_boundary : *kill gas particles outside this radius* +! - HonR_inj : *aspect ratio to give temperature at rinj* +! - follow_sink : *injection radius is relative to sink particle 1* +! - mdot : *mass injection rate [msun/yr]* +! - rinj : *injection radius* ! -! :Dependencies: dim, eos, infile_utils, io, part, partinject, physcon, -! random, units +! :Dependencies: eos, externalforces, infile_utils, io, options, part, +! partinject, physcon, random, units ! implicit none character(len=*), parameter, public :: inject_type = 'keplerian' @@ -114,7 +116,7 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& r2min = huge(r2min) do i=1,npart if (.not.isdead_or_accreted(xyzh(4,i))) then - r2 = (xyzh(1,i)-x0(1))**2 + (xyzh(2,i)-x0(2))**2 + r2 = (xyzh(1,i)-x0(1))**2 + (xyzh(2,i)-x0(2))**2 dr2 = abs(r2 - rinj*rinj) if (dr2 < r2min) then hguess = xyzh(4,i) @@ -174,8 +176,8 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& vphi = vkep*(1. - (zi/rinj)**2)**(-0.75) ! see Martire et al. (2024) - xyzi = (/rinj*cosphi,rinj*sinphi,zi/) - vxyz = (/-vphi*sinphi, vphi*cosphi, 0./) + xyzi = (/rinj*cosphi,rinj*sinphi,zi/) + vxyz = (/-vphi*sinphi, vphi*cosphi, 0./) u = 1.5*cs**2 @@ -214,11 +216,11 @@ subroutine write_options_inject(iunit) call write_inopt(mdot,'mdot','mass injection rate [msun/yr]',iunit) call write_inopt(rinj,'rinj','injection radius',iunit) if (maxvxyzu >= 4) then - call write_inopt(HonR_inj,'HonR_inj','aspect ratio to give temperature at rinj',iunit) -endif -if (nptmass >= 1) then - call write_inopt(follow_sink,'follow_sink','injection radius is relative to sink particle 1',iunit) -endif + call write_inopt(HonR_inj,'HonR_inj','aspect ratio to give temperature at rinj',iunit) + endif + if (nptmass >= 1) then + call write_inopt(follow_sink,'follow_sink','injection radius is relative to sink particle 1',iunit) + endif end subroutine write_options_inject diff --git a/src/main/inject_keplerianshear.f90 b/src/main/inject_keplerianshear.f90 index ac93e0858..cea2359ae 100644 --- a/src/main/inject_keplerianshear.f90 +++ b/src/main/inject_keplerianshear.f90 @@ -50,7 +50,7 @@ module inject character(len=*), parameter, public :: inject_type = 'keplerianshear' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par public :: set_injection_parameters type injectparams @@ -186,6 +186,11 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Writes input options to the input file diff --git a/src/main/inject_rochelobe.f90 b/src/main/inject_rochelobe.f90 index ffe84d4dd..054a264b1 100644 --- a/src/main/inject_rochelobe.f90 +++ b/src/main/inject_rochelobe.f90 @@ -25,7 +25,7 @@ module inject character(len=*), parameter, public :: inject_type = 'rochelobe' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par real, private :: Mdot = 1.0e-9 real, private :: Mdotcode = 0. @@ -278,6 +278,10 @@ subroutine phi_derivs(phinns,phizzs,xyzL1,xx1,xx2,theta_s,m1,m2,mu,r12,Porb) end subroutine phi_derivs +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_sne.f90 b/src/main/inject_sne.f90 index 24d3bc2ab..2152ef1eb 100644 --- a/src/main/inject_sne.f90 +++ b/src/main/inject_sne.f90 @@ -20,7 +20,7 @@ module inject character(len=*), parameter, public :: inject_type = 'supernovae' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par integer, parameter :: maxsn = 30 real, parameter :: xyz_sn(3,maxsn) = & @@ -135,6 +135,11 @@ subroutine inject_particles(time,dtlast_u,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Writes input options to the input file diff --git a/src/main/inject_steadydisc.f90 b/src/main/inject_steadydisc.f90 index c8ec71e01..eb6d6c128 100644 --- a/src/main/inject_steadydisc.f90 +++ b/src/main/inject_steadydisc.f90 @@ -26,7 +26,7 @@ module inject character(len=*), parameter, public :: inject_type = 'steadydisc' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par real, private :: R_ref,sig_ref real, private :: p_index,q_index,HoverR,M_star @@ -203,6 +203,11 @@ subroutine inject_particles_in_annulus(r1,r2,ninject,injected,list) end subroutine inject_particles_in_annulus +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Writes input options to the input file diff --git a/src/main/inject_unifwind.f90 b/src/main/inject_unifwind.f90 index d1a456ff6..d2205b97b 100644 --- a/src/main/inject_unifwind.f90 +++ b/src/main/inject_unifwind.f90 @@ -23,7 +23,7 @@ module inject character(len=*), parameter, public :: inject_type = 'unifwind' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par real, public :: wind_density = 7.2d-16 real, public :: wind_velocity = 29. @@ -125,6 +125,11 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Writes input options to the input file diff --git a/src/main/inject_wind.f90 b/src/main/inject_wind.f90 index cca46c932..43de42245 100644 --- a/src/main/inject_wind.f90 +++ b/src/main/inject_wind.f90 @@ -34,7 +34,7 @@ module inject character(len=*), parameter, public :: inject_type = 'wind' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - wind_injection_radius,set_default_options_inject + wind_injection_radius,set_default_options_inject,update_injected_par private ! !--runtime settings for this module @@ -78,7 +78,7 @@ subroutine init_inject(ierr) use options, only:icooling,ieos use io, only:fatal,iverbose use setbinary, only:get_eccentricity_vector - use timestep, only:tmax,dtmax + use timestep, only:tmax use wind_equations, only:init_wind_equations use wind, only:setup_wind,save_windprofile use physcon, only:mass_proton_cgs, kboltz, Rg, days, km, au, years, solarm, pi, Gg @@ -88,12 +88,11 @@ subroutine init_inject(ierr) use part, only:xyzmh_ptmass,vxyz_ptmass,massoftype,igas,iboundary,imloss,ilum,iTeff,iReff,nptmass use injectutils, only:get_sphere_resolution,get_parts_per_sphere,get_neighb_distance use cooling_molecular, only:do_molecular_cooling,fit_rho_power,fit_rho_inner,fit_vel,r_compOrb - use ptmass_radiation, only:alpha_rad integer, intent(out) :: ierr - integer :: ires_min,nzones_per_sonic_point,new_nfill + integer :: nzones_per_sonic_point,new_nfill real :: mV_on_MdotR,initial_wind_velocity_cgs,dist_to_sonic_point,semimajoraxis_cgs - real :: dr,dp,mass_of_particles1,tcross,tend,vesc,rsonic,tsonic,initial_Rinject,tboundary + real :: dr,dp,mass_of_particles1,tcross,tend,rsonic,tsonic,initial_Rinject,tboundary real :: separation_cgs,wind_mass_rate_cgs,wind_velocity_cgs,ecc(3),eccentricity,Tstar if (icooling > 0) nwrite = nwrite+1 @@ -232,6 +231,7 @@ subroutine init_inject(ierr) time_between_spheres = mass_of_spheres / wind_mass_rate massoftype(iboundary) = mass_of_particles if (time_between_spheres > tmax) then + call logging(initial_wind_velocity_cgs,rsonic,Tsonic,Tboundary) print *,'time_between_spheres = ',time_between_spheres,' < tmax = ',tmax call fatal(label,'no shell ejection : tmax < time_between_spheres') endif @@ -268,8 +268,29 @@ subroutine init_inject(ierr) print*,'got dr/dp = ',dr/dp,' compared to desired dr on dp = ',wind_shell_spacing endif + xyzmh_ptmass(imloss,wind_emitting_sink) = wind_mass_rate !logging + call logging(initial_wind_velocity_cgs,rsonic,Tsonic,Tboundary) + +end subroutine init_inject + + +!----------------------------------------------------------------------- + +subroutine logging(initial_wind_velocity_cgs,rsonic,Tsonic,Tboundary) + +!----------------------------------------------------------------------- + + use physcon, only:pi,gg + use units, only:utime,udist + use timestep, only:dtmax + use ptmass_radiation, only:alpha_rad + + real, intent(in) :: initial_wind_velocity_cgs,rsonic,Tsonic,Tboundary + integer :: ires_min + real :: vesc + vesc = sqrt(2.*Gg*Mstar_cgs*(1.-alpha_rad)/Rstar_cgs) print*,'mass_of_particles = ',mass_of_particles print*,'particles per sphere = ',particles_per_sphere @@ -309,9 +330,8 @@ subroutine init_inject(ierr) if (iwind_resolution < ires_min) print *,'WARNING! resolution too low to pass sonic point : iwind_resolution < ',ires_min endif - xyzmh_ptmass(imloss,wind_emitting_sink) = wind_mass_rate +end subroutine logging -end subroutine init_inject !----------------------------------------------------------------------- !+ @@ -482,6 +502,11 @@ subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& end subroutine inject_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine + !----------------------------------------------------------------------- !+ ! Oscillating inner boundary @@ -635,15 +660,15 @@ subroutine set_default_options_inject(flag) wind_mass_rate_Msun_yr = 8.2d-8 wind_injection_radius_au = 0. else - !trans-sonic wind if (icase == 1) then + !trans-sonic wind sonic_type = 1 wind_velocity_km_s = 0. wind_mass_rate_Msun_yr = 1.d-5 wind_injection_radius_au = 2. wind_temperature = 50000. - !super sonic-wind else + !super sonic-wind sonic_type = 0 wind_velocity_km_s = 20. wind_mass_rate_Msun_yr = 1.d-5 diff --git a/src/main/inject_windtunnel.f90 b/src/main/inject_windtunnel.f90 index 7ef2cdc25..79ee0aac0 100644 --- a/src/main/inject_windtunnel.f90 +++ b/src/main/inject_windtunnel.f90 @@ -32,7 +32,7 @@ module inject character(len=*), parameter, public :: inject_type = 'windtunnel' public :: init_inject,inject_particles,write_options_inject,read_options_inject,& - set_default_options_inject + set_default_options_inject,update_injected_par ! !--runtime settings for this module ! @@ -255,6 +255,10 @@ subroutine inject_or_update_particles(ifirst, n, position, velocity, h, u, bound end subroutine inject_or_update_particles +subroutine update_injected_par + ! -- placeholder function + ! -- does not do anything and will never be used +end subroutine !----------------------------------------------------------------------- !+ From a6499e0af1f9ac4f94e96e01405bd692f710e2a8 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 23 Jul 2024 14:35:15 +0100 Subject: [PATCH 132/182] Edits for radapprox cooling --- src/main/cooling_radapprox.f90 | 60 ++++++++++++++++++++-------------- src/main/evolve.F90 | 26 ++++++++++----- src/main/step_leapfrog.F90 | 24 ++++++++------ 3 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index d154b90b0..64742de0d 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -21,7 +21,7 @@ module cooling_radapprox implicit none real :: Lstar = 0d0 ! in units of L_sun - real,parameter :: dtcool_crit = 0.001 ! critical dt_rad/dt_hydro for not applying cooling + real,parameter :: dtcool_crit = 0.0001 ! critical dt_rad/dt_hydro for not applying cooling 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 @@ -63,37 +63,47 @@ end subroutine init_star ! Do cooling calculation ! ! update energy to return evolved energy array. Called from evolve.F90 -subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) +subroutine radcool_update_energ(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 + use part, only:iphase,maxphase,maxp,iamtype,ibin + use timestep_ind, only:get_dt integer,intent(in) :: npart - real,intent(in) :: xyzh(:,:),dt,Tfloor + real,intent(in) :: xyzh(:,:),dtsph,Tfloor real,intent(inout) :: energ(:),dudt_sph(:) - real :: ui,rhoi,coldensi,kappaBari,kappaParti,ri2 + real :: ui,rhoi,coldensi,kappaBari,kappaParti,ri2,dti real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot real :: cs2,Om2,Hmod2 real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi integer :: i,ratefile,n_uevo ! write (temp,'(E5.2)') dt - + 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,dt,dudt_sph,utime,udist,umass,unit_ergg,gradP_cool,Lstar) & + !$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) & - !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb) + !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,dti) & + !$omp shared(maxp,maxphase,ibin) reduction(+:n_uevo) + overpart: do i=1,npart - if (.not. iactive(iphase(i)) .or. isdead_or_accreted(xyzh(4,i)) ) then - dudt_sph(i) = 0d0 - cycle + if (maxphase==maxp) then + if (iamtype(iphase(i)) /= igas) cycle + if (isdead_or_accreted(xyzh(4,i))) cycle + if (.not. iactive(iphase(i)) ) then +! dudt_sph(i) = 0d0 + 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) @@ -104,6 +114,8 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) 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 @@ -157,13 +169,13 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) ! 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/dudt_sph(i)) < dtcool_crit) then -! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& - ! dudt_sph(i) - energ(i) = ui + dudt_sph(i)*dt - dudt_sph(i) = 0d0 - cycle - endif +! if (abs(dudti_rad/dudt_sph(i)) < dtcool_crit) then + ! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& + ! dudt_sph(i) + ! energ(i) = ui + dudt_sph(i)*dti + ! dudt_sph(i) = 0d0 + ! cycle + !endif if (doFLD) then Teqi = (du_FLDi + dudt_sph(i)) *opaci*unit_ergg/utime ! physical units @@ -185,7 +197,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) 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 * dt=", dudt_sph(i)*dt + "dudt_sph * dti=", dudt_sph(i)*dti endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) @@ -206,10 +218,10 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) ! evolve energy if (tthermi == 0d0) then energ(i) = ui ! condition if denominator above is zero - elseif ( (dt/tthermi) < TINY(ui) ) then + elseif ( (dti/tthermi) < TINY(ui) ) then energ(i) = ui else - energ(i) = ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) !code units + 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 @@ -217,7 +229,7 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) 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=",dt,"tthermi=", tthermi,"umini=", umini + 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 @@ -228,7 +240,6 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) enddo overpart !$omp end parallel do - !n_uevo = 0 !!$omp parallel do default(none) & !!$omp shared(dudt_sph,npart) private(i) reduction(+:n_uevo) !do i=1, npart @@ -237,7 +248,8 @@ subroutine radcool_update_energ(dt,npart,xyzh,energ,dudt_sph,Tfloor) !enddo !!$omp end parallel do ! print *, "energy not evolved with cooling for", n_uevo, "particles" -! print *, "min/max dudt_sph():", minval(dudt_sph), maxval(dudt_sph) +! print *, "min/max dudt_sph():", minval(dudt_sph), maxval(dudt_sph) + print *, "radcool min/max u():", minval(energ), maxval(energ) end subroutine radcool_update_energ diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index a823bd1bc..3385e8fff 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -291,17 +291,20 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) endif if (icooling == 9) then - write (*,*) "Before step", maxval(vxyzu(4,:)),minval(vxyzu(4,:)) umax = 0d0 + imax = 0. do i=1, npart if (vxyzu(4,i) > umax) then umax = vxyzu(4,i) imax = i endif enddo - print *, "max i=", imax, iactive(iphase(i)), fxyzu(4,i) - call radcool_update_energ(dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) - write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)), fxyzu(4,i) + print *, "max i=", imax, vxyzu(4,imax),iactive(iphase(imax)), fxyzu(4,imax) + print *, "minmax fxyzu(4,:)=", minval(fxyzu(4,1:npart)),maxval(fxyzu(4,1:npart)) + call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) + ! write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)), fxyzu(4,i) + write (*,*) "Before step", maxval(vxyzu(4,:)),minval(vxyzu(4,:)) + write (*,*) "fxyzu(4:)=", maxval(fxyzu(4,1:npart)),minval(fxyzu(4,1:npart)) endif nsteps = nsteps + 1 ! @@ -321,11 +324,16 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) call update_radenergy(npart,xyzh,fxyzu,vxyzu,rad,radprop,0.5*dt) endif -! if (icooling == 9) then - ! write (*,*) "after step",maxval(vxyzu(4,:)),minval(vxyzu(4,:)) -! call radcool_update_energ(0.5*dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) - ! write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)) - ! endif + if (icooling == 9) then + imax = 0 + write (*,*) "after step",maxval(vxyzu(4,1:npart)),minval(vxyzu(4,1:npart)) + do i=1,npart + if (abs(fxyzu(4,i)) > epsilon(fxyzu(4,i))) imax = imax + 1 + end do + print *, "n dudt > 0 =", imax + ! call radcool_update_energ(0.5*dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) + ! write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)) + endif dtlast = dt diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index a5eccbc54..2838c5a68 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -167,12 +167,12 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) store_itype = (maxphase==maxp .and. ntypes > 1) ialphaloc = 2 nvfloorp = 0 - + print *, "L197 predictor, maxmin abs fxyzu=", maxval(abs(fxyzu(4,1:npart))),minval(abs(fxyzu(4,1:npart))) !$omp parallel do default(none) & !$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) & + !$omp shared(dustprop,ddustprop,dustproppred,ufloor,icooling) & !$omp shared(mprev,filfacprev,filfac,use_porosity) & !$omp shared(ibin,ibin_old,twas,timei) & !$omp firstprivate(itype) & @@ -231,7 +231,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif call check_dustprop(npart,dustprop,filfac,mprev,filfacprev) endif -! print *, "line 234", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) + !Alison icooling, vpred is right value here for u, but shouldn't be ...? + print *, "line 234", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)),"nactive =", nactive !---------------------------------------------------------------------- ! substepping with external and sink particle forces, using dtextforce @@ -273,7 +274,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) & +!$omp shared(eos_vars,ufloor,icooling) & !$omp shared(twas,timei) & !$omp shared(rad,drad,radpred)& !$omp private(hi,rhoi,tdecay1,source,ddenom,hdti) & @@ -321,7 +322,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif !Alison - !if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) + if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) !--floor the thermal energy if requested and required if (ufloor > 0.) then @@ -394,6 +395,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif + if (icooling == 0) vxyzu(4,1:npart) = vpred(4,1:npart) if (gr) vxyzu = vpred ! May need primitive variables elsewhere? if (dt_too_small) then @@ -404,7 +406,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) call fatal('step','step too small: bin would exceed maximum') endif endif -! print *, "line 407", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) + print *, "line 407", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)), "nactive=", nactive ! ! if using super-timestepping, determine what dt will be used on the next loop ! @@ -421,7 +423,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! forces we must iterate until velocities agree. !------------------------------------------------------------------------- -! print *, "line 423", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) + print *, "line 423", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) its = 0 converged = .false. errmaxmean = 0.0 @@ -688,16 +690,18 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(4,1:npart) = vpred(4,1:npart) endif if (icooling == 9) then -! print *, "after 2nd derivs:vpred", maxval(vpred(4,:)), minval(vpred(4,:)) + print *, "after 2nd derivs:vpred", maxval(vpred(4,:)), minval(vpred(4,:)) vxyzu(4,1:npart) = vpred(4,1:npart) endif endif if (icooling == 9) then -! print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) + ! print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) + print *, "end of iteration, dudt", maxval(fxyzu(4,1:npart)), minval(fxyzu(4,1:npart)) + print *, "End of iteration, nactive=", nactive vxyzu(4,1:npart) = vpred(4,1:npart) endif enddo iterations - print *, "line 695", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) +! print *, "line 695", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) ! MPI reduce summary variables nwake = int(reduceall_mpi('+', nwake)) nvfloorp = int(reduceall_mpi('+', nvfloorp)) From ec1a5848228b846fb4dff9abeaafd09088f445e4 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 24 Jul 2024 17:12:08 +0100 Subject: [PATCH 133/182] Fixes for cooling_radapprox --- src/main/cooling_radapprox.f90 | 214 ++++++++++++++++++++++++++++----- src/main/eos_stamatellos.f90 | 3 + src/main/evolve.F90 | 23 +--- src/main/step_leapfrog.F90 | 31 +++-- 4 files changed, 207 insertions(+), 64 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 64742de0d..e73edcdf1 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -26,14 +26,14 @@ module cooling_radapprox 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 + public :: init_star,radcool_update_energ_loop contains subroutine init_star() use part, only:nptmass,xyzmh_ptmass use io, only:fatal - integer :: i,imin + integer :: i,imin=0 real :: rsink2,rsink2min rsink2min = 0d0 @@ -59,11 +59,168 @@ subroutine init_star() "at (xyz)",xyzmh_ptmass(1:3,isink_star)!"as illuminating star." end subroutine init_star + +! +! Do cooling calculation +! +! update energy to return evolved energy array. Called from step corrector +subroutine radcool_update_energ(i,dti,npart,xyzhi,ui,dudti_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 + use part, only:iphase,maxphase,maxp,iamtype,ibin + use timestep_ind, only:get_dt + integer,intent(in) :: i,npart + real,intent(in) :: xyzhi(:),dti,Tfloor,dudti_sph + real,intent(inout) :: ui + real :: rhoi,coldensi,kappaBari,kappaParti,ri2 + real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot + real :: cs2,Om2,Hmod2 + real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi + integer :: ratefile,n_uevo + +! write (temp,'(E5.2)') dt + coldensi = huge(coldensi) + poti = Gpot_cool(i) + du_FLDi = duFLD(i) + if (abs(ui) < epsilon(ui)) print *, "ui zero", i + rhoi = rhoh(xyzhi(4),massoftype(igas)) + + if (isink_star > 0) then + ri2 = (xyzhi(1)-xyzmh_ptmass(1,isink_star))**2d0 & + + (xyzhi(2)-xyzmh_ptmass(2,isink_star))**2d0 & + + (xyzhi(3)-xyzmh_ptmass(3,isink_star))**2d0 + else + ri2 = xyzhi(1)**2d0 + xyzhi(2)**2d0 + xyzhi(3)**2d0 + endif + + ! get opacities & Ti for ui + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,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 + 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 = dudti_sph + du_FLDi + else + du_tot = dudti_sph + 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) + ui = ui + du_tot*dti + return + 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)=", dudti_sph, "duradi=", dudti_rad, "Ti=", Ti, & + "Tmini=", Tmini4**(1.0/4.0),du_tot,Hcomb, "r=",sqrt(ri2), "ui=", ui, & + "dudt_sph * dti=", dudti_sph*dti + endif + + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/unit_ergg + + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,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 + ui = ui ! condition if denominator above is zero + elseif ( (dti/tthermi) < TINY(ui) ) then + ui = ui + else + ui = ui*exp(-dti/tthermi) + ueqi*(1.d0-exp(-dti/tthermi)) !code units + endif + + if (isnan(ui) .or. ui < 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",dudti_sph + 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 + +end subroutine radcool_update_energ + + ! ! Do cooling calculation ! ! update energy to return evolved energy array. Called from evolve.F90 -subroutine radcool_update_energ(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) +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 @@ -81,7 +238,10 @@ subroutine radcool_update_energ(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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) & @@ -97,7 +257,6 @@ subroutine radcool_update_energ(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) if (iamtype(iphase(i)) /= igas) cycle if (isdead_or_accreted(xyzh(4,i))) cycle if (.not. iactive(iphase(i)) ) then -! dudt_sph(i) = 0d0 n_uevo = n_uevo + 1 cycle endif @@ -153,6 +312,9 @@ subroutine radcool_update_energ(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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 @@ -166,25 +328,23 @@ subroutine radcool_update_energ(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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 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/dudt_sph(i)) < dtcool_crit) then - ! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& - ! dudt_sph(i) - ! energ(i) = ui + dudt_sph(i)*dti - ! dudt_sph(i) = 0d0 - ! cycle - !endif if (doFLD) then - Teqi = (du_FLDi + dudt_sph(i)) *opaci*unit_ergg/utime ! physical units - du_tot = dudt_sph(i) + dudti_rad + du_FLDi + du_tot = dudt_sph(i) + du_FLDi else - Teqi = dudt_sph(i)*opaci*unit_ergg/utime - du_tot = dudt_sph(i) + dudti_rad + 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 @@ -235,22 +395,12 @@ subroutine radcool_update_energ(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) stop endif - ! zero fxyzu(4,i) because we already updated the energy - dudt_sph(i) = 0d0 enddo overpart !$omp end parallel do - !!$omp parallel do default(none) & - !!$omp shared(dudt_sph,npart) private(i) reduction(+:n_uevo) - !do i=1, npart - ! if (dudt_sph(i) /= 0d0) n_uevo = n_uevo + 1 - ! dudt_sph(i) = 0d0 - !enddo - !!$omp end parallel do -! print *, "energy not evolved with cooling for", n_uevo, "particles" -! print *, "min/max dudt_sph():", minval(dudt_sph), maxval(dudt_sph) - print *, "radcool min/max u():", minval(energ), maxval(energ) -end subroutine radcool_update_energ + 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 subroutine write_options_cooling_radapprox(iunit) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 59c9449a9..5b784bb82 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -42,7 +42,10 @@ subroutine init_S07cool() allocate(ttherm_store(npart)) allocate(teqi_store(npart)) allocate(opac_store(npart)) + Gpot_cool(:) = 0d0 + gradP_cool(:) = 0d0 urad_FLD(:) = 0d0 + duFLD(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') if (doFLD) then print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index 3385e8fff..9c81bbf1d 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -82,7 +82,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use radiation_utils, only:update_radenergy use timestep, only:dtrad use cooling, only:Tfloor - use cooling_radapprox,only:radcool_update_energ + use cooling_radapprox,only:radcool_update_energ_loop #ifdef LIVE_ANALYSIS use analysis, only:do_analysis use part, only:igas @@ -291,20 +291,10 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) endif if (icooling == 9) then - umax = 0d0 - imax = 0. - do i=1, npart - if (vxyzu(4,i) > umax) then - umax = vxyzu(4,i) - imax = i - endif - enddo - print *, "max i=", imax, vxyzu(4,imax),iactive(iphase(imax)), fxyzu(4,imax) - print *, "minmax fxyzu(4,:)=", minval(fxyzu(4,1:npart)),maxval(fxyzu(4,1:npart)) - call radcool_update_energ(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) + call radcool_update_energ_loop(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) ! write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)), fxyzu(4,i) write (*,*) "Before step", maxval(vxyzu(4,:)),minval(vxyzu(4,:)) - write (*,*) "fxyzu(4:)=", maxval(fxyzu(4,1:npart)),minval(fxyzu(4,1:npart)) + ! write (*,*) "fxyzu(4:)=", maxval(fxyzu(4,1:npart)),minval(fxyzu(4,1:npart)) endif nsteps = nsteps + 1 ! @@ -325,14 +315,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) endif if (icooling == 9) then - imax = 0 write (*,*) "after step",maxval(vxyzu(4,1:npart)),minval(vxyzu(4,1:npart)) - do i=1,npart - if (abs(fxyzu(4,i)) > epsilon(fxyzu(4,i))) imax = imax + 1 - end do - print *, "n dudt > 0 =", imax - ! call radcool_update_energ(0.5*dt,npart,xyzh,vxyzu(4,:),fxyzu(4,:),Tfloor) - ! write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)) endif dtlast = dt diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 2838c5a68..6820ba598 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -197,7 +197,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + if (icooling == 9) then + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + else + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + endif endif !--floor the thermal energy if requested and required @@ -321,9 +325,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - !Alison - if (icooling == 9 .and. fxyzu(4,i) > epsilon(fxyzu(4,i))) print *, "!warning! step L324", fxyzu(4,i) - + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vpred(4,i) < ufloor) then @@ -385,6 +387,7 @@ 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,1:npart) = vxyzu(4,1:npart) dt_too_small = .false. call derivs(1,npart,nactive,xyzh,vpred,fxyzu,fext,divcurlv,& divcurlB,Bpred,dBevol,radpred,drad,radprop,dustproppred,ddustprop,& @@ -483,7 +486,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + dti*fxyzu(:,i) else - vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) + if (icooling == 9) then + vxyzu(1:3,i) = vxyzu(1:3,i) + dti*fxyzu(1:3,i) + else + vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) + endif endif if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) @@ -505,7 +512,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (gr) then pxyzu(:,i) = pxyzu(:,i) + hdti*fxyzu(:,i) else - vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + if (icooling == 9) then + vxyzu(1:3,i) = vxyzu(1:3,i) + hdti*fxyzu(1:3,i) + else + vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) + endif endif !--floor the thermal energy if requested and required @@ -624,12 +635,10 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) if (iamboundary(itype)) cycle until_converged if (ind_timesteps) then - if (icooling == 9) vxyzu(4,i) = vpred(4,i) !keep original value of u if (iactive(iphase(i))) then if (gr) then ppred(:,i) = pxyzu(:,i) else -! if (icooling == 9) vxyzu(4,i) = vpred(4,i) !keep original value of u vpred(:,i) = vxyzu(:,i) endif if (use_dustgrowth) dustproppred(:,i) = dustprop(:,i) @@ -680,7 +689,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! get new force using updated velocity: no need to recalculate density etc. ! if (gr) vpred = vxyzu ! Need primitive utherm as a guess in cons2prim -! print *, "before 2nd derivs", maxval(vpred(4,:)), minval(vpred(4,:)),maxval(fxyzu(4,:)) call derivs(2,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) @@ -691,17 +699,16 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif if (icooling == 9) then print *, "after 2nd derivs:vpred", maxval(vpred(4,:)), minval(vpred(4,:)) - vxyzu(4,1:npart) = vpred(4,1:npart) endif endif if (icooling == 9) then - ! print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) + print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) print *, "end of iteration, dudt", maxval(fxyzu(4,1:npart)), minval(fxyzu(4,1:npart)) print *, "End of iteration, nactive=", nactive vxyzu(4,1:npart) = vpred(4,1:npart) endif enddo iterations -! print *, "line 695", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) + ! MPI reduce summary variables nwake = int(reduceall_mpi('+', nwake)) nvfloorp = int(reduceall_mpi('+', nvfloorp)) From 1ee547f635dbf716669dddeb127ba8ddc9256156 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 25 Jul 2024 12:07:35 +0100 Subject: [PATCH 134/182] minor changes to cooling_radapprox.f90 --- src/main/cooling_radapprox.f90 | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index e73edcdf1..b2a1e991f 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -175,7 +175,10 @@ subroutine radcool_update_energ(i,dti,npart,xyzhi,ui,dudti_sph,Tfloor) if (Teqi > 9e5) then print *,"i=",i, "dudt_sph(i)=", dudti_sph, "duradi=", dudti_rad, "Ti=", Ti, & "Tmini=", Tmini4**(1.0/4.0),du_tot,Hcomb, "r=",sqrt(ri2), "ui=", ui, & - "dudt_sph * dti=", dudti_sph*dti + "dudt_sph * dti=", dudti_sph*dti + elseif (Teqi < epsilon(Teqi)) then + print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& + "Ti=", Ti, "poti=",poti, "rhoi=", rhoi endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) @@ -334,14 +337,14 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) else du_tot = dudt_sph(i) endif - ! If radiative cooling is negligible compared to hydrodynamical heating + !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 + 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 + energ(i) = ui + du_tot*dti + cycle + endif Teqi = du_tot * opaci*unit_ergg/utime ! physical units du_tot = du_tot + dudti_rad From 0f1469ef7ea899229f9269d24d1e4695e11d128b Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 26 Jul 2024 09:55:06 +0100 Subject: [PATCH 135/182] Edits to icooling = 9 --- src/main/cooling_radapprox.f90 | 60 ++++++++++++++++++++-------------- src/main/eos_stamatellos.f90 | 9 +++-- src/main/evolve.F90 | 5 --- src/main/step_leapfrog.F90 | 20 +++++++----- 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index b2a1e991f..dd62d3f50 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -26,7 +26,7 @@ module cooling_radapprox 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 :: init_star, radcool_update_energ_loop contains @@ -64,38 +64,39 @@ end subroutine init_star ! Do cooling calculation ! ! update energy to return evolved energy array. Called from step corrector -subroutine radcool_update_energ(i,dti,npart,xyzhi,ui,dudti_sph,Tfloor) +subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,dudti_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 - use part, only:iphase,maxphase,maxp,iamtype,ibin use timestep_ind, only:get_dt - integer,intent(in) :: i,npart - real,intent(in) :: xyzhi(:),dti,Tfloor,dudti_sph + integer,intent(in) :: i + integer(kind=1),intent(in) :: ibini + real,intent(in) :: xyzhi(:),dtsph,dudti_sph,Tfloor real,intent(inout) :: ui - real :: rhoi,coldensi,kappaBari,kappaParti,ri2 + real :: dti,rhoi,coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot real :: cs2,Om2,Hmod2 real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi - integer :: ratefile,n_uevo -! write (temp,'(E5.2)') dt - coldensi = huge(coldensi) - poti = Gpot_cool(i) - du_FLDi = duFLD(i) - if (abs(ui) < epsilon(ui)) print *, "ui zero", i - rhoi = rhoh(xyzhi(4),massoftype(igas)) - - if (isink_star > 0) then - ri2 = (xyzhi(1)-xyzmh_ptmass(1,isink_star))**2d0 & - + (xyzhi(2)-xyzmh_ptmass(2,isink_star))**2d0 & - + (xyzhi(3)-xyzmh_ptmass(3,isink_star))**2d0 - else - ri2 = xyzhi(1)**2d0 + xyzhi(2)**2d0 + xyzhi(3)**2d0 - endif + dti = get_dt(dtsph,ibini) + coldensi = huge(coldensi) + poti = Gpot_cool(i) + du_FLDi = duFLD(i) + kappaBari = 0d0 + kappaParti = 0d0 + if (abs(ui) < epsilon(ui)) print *, "ui zero", i + rhoi = rhoh(xyzhi(4),massoftype(igas)) + + if (isink_star > 0) then + ri2 = (xyzhi(1)-xyzmh_ptmass(1,isink_star))**2d0 & + + (xyzhi(2)-xyzmh_ptmass(2,isink_star))**2d0 & + + (xyzhi(3)-xyzmh_ptmass(3,isink_star))**2d0 + else + ri2 = xyzhi(1)**2d0 + xyzhi(2)**2d0 + xyzhi(3)**2d0 + endif ! get opacities & Ti for ui call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& @@ -132,6 +133,9 @@ subroutine radcool_update_energ(i,dti,npart,xyzhi,ui,dudti_sph,Tfloor) 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 + call warning("In radapprox cooling","cooling method not recognised",ival=od_method) + return end select ! Tfloor is from input parameters and is background heating @@ -151,8 +155,9 @@ subroutine radcool_update_energ(i,dti,npart,xyzhi,ui,dudti_sph,Tfloor) else du_tot = dudti_sph endif + ! If radiative cooling is negligible compared to hydrodynamical heating - ! don't use this method to update energy, just use hydro du/dt + ! don't use this method to update energy, just use hydro du/dt. Does it conserve u alright? if (abs(dudti_rad/du_tot) < dtcool_crit) then ! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& ! dudt_sph(i) @@ -161,10 +166,9 @@ subroutine radcool_update_energ(i,dti,npart,xyzhi,ui,dudti_sph,Tfloor) endif Teqi = du_tot * opaci*unit_ergg/utime ! physical units - du_tot = du_tot + dudti_rad - Teqi = Teqi/4.d0/steboltz Teqi = Teqi + Tmini4 + du_tot = du_tot + dudti_rad if (Teqi < Tmini4) then Teqi = Tmini4**(1.0/4.0) else @@ -179,6 +183,9 @@ subroutine radcool_update_energ(i,dti,npart,xyzhi,ui,dudti_sph,Tfloor) elseif (Teqi < epsilon(Teqi)) then print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& "Ti=", Ti, "poti=",poti, "rhoi=", rhoi + elseif (Teqi < Tfloor) then + print *, "Teqi=",Teqi, "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& + "Ti=", Ti, "poti=",poti, "rhoi=", rhoi endif call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) @@ -360,7 +367,10 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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 + "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 call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 5b784bb82..a6d485982 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -46,6 +46,9 @@ subroutine init_S07cool() gradP_cool(:) = 0d0 urad_FLD(:) = 0d0 duFLD(:) = 0d0 + teqi_store(:) = 0d0 + ttherm_store(:) = 0d0 + opac_store(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') if (doFLD) then print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" @@ -214,7 +217,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) end subroutine getopac_opdep subroutine getintenerg_opdep(Teqi, rhoi, ueqi) - use io, only:fatal + use io, only:warning real, intent(out) :: ueqi real, intent(in) :: Teqi,rhoi @@ -224,9 +227,9 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) real rhoi_ if (rhoi > OPTABLE(nx,1,1) .or. rhoi < OPTABLE(1,1,1)) then - call fatal('getintenerg_opdep','rhoi out of range',var='rhoi',val=rhoi) + call warning('getintenerg_opdep','rhoi out of range',var='rhoi',val=rhoi) elseif (Teqi > OPTABLE(1,ny,2) .or. Teqi < OPTABLE(1,1,2)) then - call fatal('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) + call warning('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) endif diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index 9c81bbf1d..cd41228a4 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -81,8 +81,6 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use part, only:rad,radprop use radiation_utils, only:update_radenergy use timestep, only:dtrad - use cooling, only:Tfloor - use cooling_radapprox,only:radcool_update_energ_loop #ifdef LIVE_ANALYSIS use analysis, only:do_analysis use part, only:igas @@ -291,10 +289,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) endif if (icooling == 9) then - call radcool_update_energ_loop(dt,npart,xyzh,vxyzu(4,1:npart),fxyzu(4,1:npart),Tfloor) - ! write (*,*) " ",maxval(vxyzu(4,:)),minval(vxyzu(4,:)), fxyzu(4,i) write (*,*) "Before step", maxval(vxyzu(4,:)),minval(vxyzu(4,:)) - ! write (*,*) "fxyzu(4:)=", maxval(fxyzu(4,1:npart)),minval(fxyzu(4,1:npart)) endif nsteps = nsteps + 1 ! diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 6820ba598..ae4ef96ff 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -117,7 +117,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use metric_tools, only:imet_minkowski,imetric use cons2prim, only:cons2primall use extern_gr, only:get_grforce_all - use cooling, only:ufloor,cooling_in_step + use cooling, only:ufloor,cooling_in_step,Tfloor use timing, only:increment_timer,get_timings,itimer_extf use growth, only:check_dustprop use options, only:use_porosity,icooling @@ -127,7 +127,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use eos, only:equationofstate use substepping, only:substep,substep_gr, & substep_sph_gr,substep_sph - + use cooling_radapprox, only:radcool_update_energ + integer, intent(inout) :: npart integer, intent(in) :: nactive real, intent(in) :: t,dtsph @@ -167,7 +168,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) store_itype = (maxphase==maxp .and. ntypes > 1) ialphaloc = 2 nvfloorp = 0 - print *, "L197 predictor, maxmin abs fxyzu=", maxval(abs(fxyzu(4,1:npart))),minval(abs(fxyzu(4,1:npart))) +! print *, "L197 predictor, maxmin abs fxyzu=", maxval(abs(fxyzu(4,1:npart))),minval(abs(fxyzu(4,1:npart))) !$omp parallel do default(none) & !$omp shared(npart,xyzh,vxyzu,fxyzu,iphase,hdtsph,store_itype) & !$omp shared(rad,drad,pxyzu) & @@ -236,7 +237,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) call check_dustprop(npart,dustprop,filfac,mprev,filfacprev) endif !Alison icooling, vpred is right value here for u, but shouldn't be ...? - print *, "line 234", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)),"nactive =", nactive +! print *, "line 234", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)),"nactive =", nactive !---------------------------------------------------------------------- ! substepping with external and sink particle forces, using dtextforce @@ -398,7 +399,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif - if (icooling == 0) vxyzu(4,1:npart) = vpred(4,1:npart) + if (icooling == 9) vxyzu(4,1:npart) = vpred(4,1:npart) if (gr) vxyzu = vpred ! May need primitive variables elsewhere? if (dt_too_small) then @@ -409,7 +410,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) call fatal('step','step too small: bin would exceed maximum') endif endif - print *, "line 407", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)), "nactive=", nactive +! print *, "line 407", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)), "nactive=", nactive ! ! if using super-timestepping, determine what dt will be used on the next loop ! @@ -426,7 +427,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! forces we must iterate until velocities agree. !------------------------------------------------------------------------- - print *, "line 423", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) +! print *, "line 423", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) its = 0 converged = .false. errmaxmean = 0.0 @@ -453,7 +454,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(ibin,ibin_old,ibin_sts,twas,timei,use_sts,dtsph_next,ibin_wake,sts_it_n) & !$omp shared(ibin_dts,nbinmax) & !$omp private(dti,hdti) & -!$omp shared(rad,radpred,drad)& +!$omp shared(rad,radpred,drad,Tfloor)& !$omp private(i,vxi,vyi,vzi) & !$omp private(pxi,pyi,pzi,p2i) & !$omp private(erri,v2i,eni) & @@ -488,6 +489,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) + if (its == 1) call radcool_update_energ(i,ibin(i),dtsph,xyzh(:,i),vxyzu(4,i),fxyzu(4,i),Tfloor) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif @@ -703,9 +705,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif if (icooling == 9) then print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) + print *, "end of iteration", maxval(vxyzu(4,:)), minval(vxyzu(4,:)) print *, "end of iteration, dudt", maxval(fxyzu(4,1:npart)), minval(fxyzu(4,1:npart)) print *, "End of iteration, nactive=", nactive - vxyzu(4,1:npart) = vpred(4,1:npart) endif enddo iterations From 018c251156f0b4cd07d1385d185a913e2ba84613 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 29 Jul 2024 13:47:29 +0100 Subject: [PATCH 136/182] Upstream changes added --- src/main/evolve.F90 | 17 +- src/main/inject_sim.f90 | 370 ++ src/main/ionization.f90 | 10 +- src/main/kdtree.F90 | 18 +- src/main/kernel_WendlandC2.f90 | 18 +- src/main/kernel_WendlandC4.f90 | 37 +- src/main/kernel_WendlandC6.f90 | 21 + src/main/kernel_cubic.f90 | 20 + src/main/kernel_quartic.f90 | 25 + src/main/kernel_quintic.f90 | 29 + src/main/metric_minkowski.f90 | 5 +- src/main/mpi_dens.F90 | 3 + src/main/mpi_derivs.F90 | 17 + src/main/mpi_memory.f90 | 317 -- src/main/mpi_tree.F90 | 3 + src/main/mpi_utils.F90 | 59 + src/main/nicil_supplement.F90 | 236 - src/main/options.f90 | 11 +- src/main/partinject.F90 | 4 +- src/main/porosity.f90 | 2 +- src/main/ptmass.F90 | 47 +- src/setup/readwrite_kepler.f90 | 6 +- src/setup/readwrite_mesa.f90 | 2 +- src/setup/set_binary.f90 | 13 +- src/setup/set_hierarchical.f90 | 327 +- src/setup/set_hierarchical_utils.f90 | 10 +- src/setup/set_orbit.f90 | 15 + src/setup/set_star.f90 | 218 +- src/setup/set_unifdis.f90 | 1 - src/setup/setup_binary.f90 | 144 +- src/setup/setup_chinchen.f90 | 5 +- src/setup/setup_cluster.f90 | 6 +- src/setup/setup_galdisc.f90 | 20 +- src/setup/setup_grdisc.F90 | 107 +- src/setup/setup_grtde.f90 | 18 +- src/utils/analysis_CoM.f90 | 2 +- src/utils/analysis_angmom.f90 | 4 +- src/utils/analysis_angmomvec.f90 | 4 +- src/utils/analysis_average_orb_en.f90 | 4 +- src/utils/analysis_bzrms.f90 | 6 +- src/utils/analysis_clumpfind.F90 | 22 +- src/utils/analysis_clumpfindWB23.F90 | 2 +- .../analysis_collidingcloudevolution.f90 | 2 +- src/utils/analysis_common_envelope.f90 | 4494 +++++++++++++++++ 44 files changed, 5725 insertions(+), 976 deletions(-) create mode 100644 src/main/inject_sim.f90 delete mode 100644 src/main/mpi_memory.f90 delete mode 100644 src/main/nicil_supplement.F90 create mode 100644 src/utils/analysis_common_envelope.f90 diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index cd41228a4..92c22f776 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -77,7 +77,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use partinject, only:update_injected_particles #endif use dim, only:do_radiation - use options, only:exchange_radiation_energy,implicit_radiation,icooling + use options, only:exchange_radiation_energy,implicit_radiation use part, only:rad,radprop use radiation_utils, only:update_radenergy use timestep, only:dtrad @@ -89,8 +89,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) #endif use part, only:npart,nptmass,xyzh,vxyzu,fxyzu,fext,divcurlv,massoftype, & xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,gravity,iboundary, & - fxyz_ptmass_sinksink,ntot,poten,ndustsmall,accrete_particles_outside_sphere, & - iphase,iactive + fxyz_ptmass_sinksink,ntot,poten,ndustsmall,accrete_particles_outside_sphere use quitdump, only:quit use ptmass, only:icreate_sinks,ptmass_create,ipart_rhomax,pt_write_sinkev,calculate_mdot, & set_integration_precision @@ -138,9 +137,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) logical :: use_global_dt integer :: j,nskip,nskipped,nevwrite_threshold,nskipped_sink,nsinkwrite_threshold character(len=120) :: dumpfile_orig - integer :: imax - real :: umax - + tprint = 0. nsteps = 0 nsteplast = 0 @@ -287,10 +284,6 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) if (do_radiation .and. exchange_radiation_energy .and. .not.implicit_radiation) then call update_radenergy(npart,xyzh,fxyzu,vxyzu,rad,radprop,0.5*dt) endif - - if (icooling == 9) then - write (*,*) "Before step", maxval(vxyzu(4,:)),minval(vxyzu(4,:)) - endif nsteps = nsteps + 1 ! !--evolve data for one timestep @@ -309,10 +302,6 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) call update_radenergy(npart,xyzh,fxyzu,vxyzu,rad,radprop,0.5*dt) endif - if (icooling == 9) then - write (*,*) "after step",maxval(vxyzu(4,1:npart)),minval(vxyzu(4,1:npart)) - endif - dtlast = dt !--timings for step call diff --git a/src/main/inject_sim.f90 b/src/main/inject_sim.f90 new file mode 100644 index 000000000..a305b8dc8 --- /dev/null +++ b/src/main/inject_sim.f90 @@ -0,0 +1,370 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module inject +! +! Handles particle injections from another simulations (for TDE outflow only currently) +! +! :References: None +! +! :Owner: Fitz) Hu +! +! :Runtime parameters: +! - r_inject : *radius to inject tde outflow (in cm)* +! +! :Dependencies: dump_utils, fileutils, infile_utils, io, part, partinject, +! readwrite_dumps_common, readwrite_dumps_fortran, timestep, units +! + use fileutils, only:getnextfilename + + implicit none + character(len=*), parameter, public :: inject_type = 'sim' + + public :: init_inject,inject_particles,write_options_inject,read_options_inject, & + set_default_options_inject,update_injected_par + private :: read_injected_par +! +!--runtime settings for this module +! + +! global variables + + character(len=120) :: start_dump,final_dump,pre_dump,next_dump + integer :: npart_sim + real :: r_inject,r_inject_cgs=-1,next_time!,e_inject + real, allocatable :: xyzh_pre(:,:),xyzh_next(:,:),vxyzu_next(:,:),pxyzu_next(:,:) + logical, allocatable :: injected(:) + + character(len=*), parameter :: label = 'inject_tdeoutflow' + character(len=*), parameter :: injected_filename = 'injected_par' + +contains + +!----------------------------------------------------------------------- +!+ +! Initialize -- find the start dump to inject +!+ +!----------------------------------------------------------------------- +subroutine init_inject(ierr) + use io, only:error + use timestep, only:time + use units, only:udist + + integer, intent(out) :: ierr + integer, parameter :: max_niter=5000, idisk=23 + integer :: niter + + ! + !--find the tde dump at the right time + ! + next_time = -1. + next_dump = getnextfilename(start_dump) + call get_dump_time_npart(trim(next_dump),next_time,ierr,npart_out=npart_sim) + ierr = 0 + niter = 0 + + do while (next_time < time .and. niter < max_niter) + niter = niter + 1 + pre_dump = next_dump + next_dump = getnextfilename(next_dump) + call get_dump_time_npart(trim(next_dump),next_time,ierr) + if (ierr /= 0) then + ierr = 0 + call error('inject','error reading time and npart from '//trim(next_dump)) + cycle + endif + enddo + start_dump = next_dump + + write(*,'(a,1x,es10.2)') ' Start read sims and inject particle from '//trim(next_dump)//' at t =',next_time + + r_inject = r_inject_cgs/udist ! to code unit + allocate(xyzh_pre(4,npart_sim),xyzh_next(4,npart_sim),vxyzu_next(4,npart_sim),pxyzu_next(4,npart_sim),injected(npart_sim)) + xyzh_pre = 0. + injected = .false. + call read_injected_par() + !e_inject = -1./r_inject + +end subroutine init_inject + +!----------------------------------------------------------------------- +!+ +! Main routine handling wind injection. +!+ +!----------------------------------------------------------------------- +subroutine inject_particles(time,dtlast,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& + npart,npart_old,npartoftype,dtinject) + real, intent(in) :: time, dtlast + real, intent(inout) :: xyzh(:,:), vxyzu(:,:), xyzmh_ptmass(:,:), vxyz_ptmass(:,:) + integer, intent(inout) :: npart,npart_old + integer, intent(inout) :: npartoftype(:) + real, intent(out) :: dtinject + integer :: ierr + real :: tfac + + ! + !--inject particles only if time has reached + ! + tfac = 1. + if (time >= next_time) then + ! read next dump + call read_dump(next_dump,xyzh_next,ierr,vxyzu_dump=vxyzu_next,pxyzu_dump=pxyzu_next) + + npart_old = npart + call inject_required_part_tde(npart,npartoftype,xyzh,vxyzu,xyzh_pre,xyzh_next,vxyzu_next,pxyzu_next) + + ! copy to pre for next injection use + pre_dump = next_dump + xyzh_pre = xyzh_next + + call find_next_dump(next_dump,next_time,ierr) + start_dump = next_dump + + write(*,'(i10,1x,a27,1x,a)') npart-npart_old, 'particles are injected from', trim(pre_dump) + + if (pre_dump == final_dump) then + write(*,'(a)') ' Reach the final dumpfile. Stop injecting ...' + next_time = huge(0.) + endif + + tfac = 1.d-40 ! set a tiny timestep so the code has time to adjust for timestep + endif + + ! update time to next inject + dtinject = tfac*(next_time - time) +end subroutine inject_particles + +subroutine read_dump(filename,xyzh_dump,ierr,vxyzu_dump,pxyzu_dump) + use dump_utils, only: read_array_from_file + character(len=*), intent(in) :: filename + real, intent(out) :: xyzh_dump(:,:) + integer, intent(out) :: ierr + real, intent(out), optional :: vxyzu_dump(:,:),pxyzu_dump(:,:) + integer, parameter :: iunit = 578 + real(kind=4) :: h(npart_sim) + + ! + !--read xyzh + ! + call read_array_from_file(iunit,filename,'x',xyzh_dump(1,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'y',xyzh_dump(2,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'z',xyzh_dump(3,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'h',h,ierr,iprint_in=.false.) + xyzh_dump(4,:) = h + + ! + !--read vxyzu + ! + if (present(vxyzu_dump)) then + call read_array_from_file(iunit,filename,'vx',vxyzu_dump(1,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'vy',vxyzu_dump(2,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'vz',vxyzu_dump(3,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'u',vxyzu_dump(4,:),ierr,iprint_in=.false.) + endif + + ! + !--read vxyzu + ! + if (present(pxyzu_dump)) then + call read_array_from_file(iunit,filename,'px',pxyzu_dump(1,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'py',pxyzu_dump(2,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'pz',pxyzu_dump(3,:),ierr,iprint_in=.false.) + call read_array_from_file(iunit,filename,'entropy',pxyzu_dump(4,:),ierr,iprint_in=.false.) + endif + +end subroutine read_dump + +subroutine get_dump_time_npart(filename,time,ierr,npart_out) + use io, only:iprint,id,nprocs + use dump_utils, only:dump_h,open_dumpfile_r,read_header,free_header + use part, only:maxtypes + use readwrite_dumps_fortran, only:unfill_header + use readwrite_dumps_common, only:get_options_from_fileid + + character(len=*), intent(in) :: filename + real, intent(out) :: time + integer, intent(out) :: ierr + integer, intent(out), optional :: npart_out + integer, parameter :: idisk=389 + character(len=120) :: fileid + logical :: tagged,phantomdump,smalldump,use_dustfrac + type(dump_h) :: hdr + integer(kind=8) :: nparttot + integer :: nblocks,npartoftype(maxtypes),npart + real :: hfactfile,alphafile + + call open_dumpfile_r(idisk,filename,fileid,ierr) + call get_options_from_fileid(fileid,tagged,phantomdump,smalldump,use_dustfrac,ierr) + call read_header(idisk,hdr,ierr,tagged=tagged) + call unfill_header(hdr,phantomdump,tagged,nparttot, & + nblocks,npart,npartoftype, & + time,hfactfile,alphafile,iprint,id,nprocs,ierr) + call free_header(hdr,ierr) + close(idisk) + + if (present(npart_out)) npart_out = npart + +end subroutine get_dump_time_npart + +subroutine find_next_dump(next_dump,next_time,ierr) + character(len=*), intent(inout) :: next_dump + real, intent(out) :: next_time + integer, intent(out) :: ierr + + next_dump = getnextfilename(next_dump) + call get_dump_time_npart(next_dump,next_time,ierr) + +end subroutine find_next_dump + +subroutine inject_required_part_tde(npart,npartoftype,xyzh,vxyzu,xyzh_pre,xyzh_next,vxyzu_next,pxyzu_next) + use part, only:igas,pxyzu,isdead_or_accreted + use partinject, only:add_or_update_particle + integer, intent(inout) :: npart, npartoftype(:) + real, intent(inout) :: xyzh(:,:), vxyzu(:,:) + real, intent(in) :: xyzh_pre(:,:), xyzh_next(:,:), vxyzu_next(:,:), pxyzu_next(:,:) + integer :: i,partid + real :: r_next,r_pre,vr_next!,e_next + + ! + !--check all the particles + ! + do i=1,npart_sim + if (.not. isdead_or_accreted(xyzh_next(4,i)) .and. .not. injected(i)) then + r_next = sqrt(dot_product(xyzh_next(1:3,i),xyzh_next(1:3,i))) + r_pre = sqrt(dot_product(xyzh_pre(1:3,i),xyzh_pre(1:3,i))) + vr_next = (dot_product(xyzh_next(1:3,i),vxyzu_next(1:3,i)))/r_next + !e_next = 0.5*vr_next**2 - 1./r_next + + if (r_next > r_inject .and. r_pre < r_inject .and. vr_next > 0.) then! .and. e_next > e_inject) then + ! inject particle by copy the data into position + partid = npart+1 + call add_or_update_particle(igas,xyzh_next(1:3,i),vxyzu_next(1:3,i),xyzh_next(4,i), & + vxyzu_next(4,i),partid,npart,npartoftype,xyzh,vxyzu) + pxyzu(:,partid) = pxyzu_next(:,i) + injected(i) = .true. + endif + endif + enddo + +end subroutine inject_required_part_tde + +subroutine read_injected_par() + use io, only:fatal,warning + integer, parameter :: iunit=242 + logical :: iexist + integer :: nread,i + + inquire(file=trim(injected_filename),exist=iexist) + + if (iexist) then + open(iunit,file=trim(injected_filename),status='old') + read(iunit,*) nread + + ! check if npart in file is the same as npart_sim + if (nread /= npart_sim) call fatal('inject_sim','npart in '//trim(injected_filename)// & + ' does not match npart_sim') + + do i=1,nread + read(iunit,*) injected(i) + enddo + close(iunit) + else + call warning('inject_sim',trim(injected_filename)//' not found, assume no particles are injected') + injected = .false. + endif + +end subroutine + +subroutine update_injected_par() + use io, only:error + integer, parameter :: iunit=284 + logical :: iexist + integer :: i + + if (allocated(injected)) then + inquire(file=trim(injected_filename),exist=iexist) + if (iexist) then + open(iunit,file=trim(injected_filename),status='replace') + else + open(iunit,file=trim(injected_filename),status='new') + endif + + write(iunit,*) npart_sim + do i=1,npart_sim + write(iunit,*) injected(i) + enddo + close(iunit) + endif +end subroutine + +!----------------------------------------------------------------------- +!+ +! Writes input options to the input file +!+ +!----------------------------------------------------------------------- +subroutine write_options_inject(iunit) + use infile_utils, only: write_inopt + integer, intent(in) :: iunit + character(len=10), parameter :: start_dump_default = 'dump_00000', & + final_dump_default = 'dump_02000' + real, parameter :: r_inject_default = 5.e14 + + ! write something meaningful in infile + if (r_inject_cgs <= 0.) then + start_dump = start_dump_default + r_inject_cgs = r_inject_default + final_dump = final_dump_default + endif + + write(iunit,"(/,a)") '# options controlling particle injection' + call write_inopt("'"//trim(start_dump)//"'",'start_dump', & + 'dumpfile to start for injection (with relative path if in other direc)',iunit) + call write_inopt(r_inject_cgs,'r_inject','radius to inject tde outflow (in cm)',iunit) + call write_inopt("'"//trim(final_dump)//"'",'final_dump', & + 'stop injection after this dump (with relative path if in other direc)',iunit) + +end subroutine write_options_inject + +!----------------------------------------------------------------------- +!+ +! Reads input options from the input file. +!+ +!----------------------------------------------------------------------- +subroutine read_options_inject(name,valstring,imatch,igotall,ierr) + use io, only:fatal + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotall + integer,intent(out) :: ierr + character(len=30), parameter :: label = 'read_options_inject' + integer, save :: ngot + + imatch = .true. + igotall = .false. + select case(trim(name)) + case('start_dump') + read(valstring,*,iostat=ierr) start_dump + ngot = ngot + 1 + case('r_inject') + read(valstring,*,iostat=ierr) r_inject_cgs + ngot = ngot + 1 + if (r_inject_cgs < 0.) call fatal(label,'invalid setting for r_inject (<0)') + case('final_dump') + read(valstring,*,iostat=ierr) final_dump + ngot = ngot + 1 + case default + imatch = .false. + end select + + igotall = (ngot >= 3) + +end subroutine read_options_inject + +subroutine set_default_options_inject(flag) + integer, optional, intent(in) :: flag + +end subroutine set_default_options_inject + +end module inject diff --git a/src/main/ionization.f90 b/src/main/ionization.f90 index 032bc9ad6..02691af62 100644 --- a/src/main/ionization.f90 +++ b/src/main/ionization.f90 @@ -14,7 +14,8 @@ module ionization_mod ! ! :Runtime parameters: None ! -! :Dependencies: eos_idealplusrad, io, part, physcon, units, vectorutils +! :Dependencies: dim, eos_idealplusrad, io, part, physcon, units, +! vectorutils ! implicit none @@ -338,13 +339,15 @@ end subroutine get_erec_components ! gas particle. Inputs and outputs in code units !+ !---------------------------------------------------------------- -subroutine calc_thermal_energy(particlemass,ieos,xyzh,vxyzu,presi,tempi,ethi) - use part, only:rhoh +subroutine calc_thermal_energy(particlemass,ieos,xyzh,vxyzu,presi,tempi,ethi,radprop) + use dim, only:do_radiation + use part, only:rhoh,iradxi use eos_idealplusrad, only:get_idealgasplusrad_tempfrompres,get_idealplusrad_enfromtemp use physcon, only:radconst,Rg 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(out) :: ethi real :: hi,densi_cgs,mui @@ -357,6 +360,7 @@ subroutine calc_thermal_energy(particlemass,ieos,xyzh,vxyzu,presi,tempi,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) end select end subroutine calc_thermal_energy diff --git a/src/main/kdtree.F90 b/src/main/kdtree.F90 index 9b70a7f1f..e9a0c9e9f 100644 --- a/src/main/kdtree.F90 +++ b/src/main/kdtree.F90 @@ -30,8 +30,6 @@ module kdtree integer, public, allocatable :: inoderange(:,:) integer, public, allocatable :: inodeparts(:) type(kdnode), allocatable :: refinementnode(:) - integer, allocatable :: list(:) - !$omp threadprivate(list) ! !--tree parameters @@ -81,9 +79,6 @@ subroutine allocate_kdtree call allocate_array('inoderange', inoderange, 2, ncellsmax+1) call allocate_array('inodeparts', inodeparts, maxp) if (mpi) call allocate_array('refinementnode', refinementnode, ncellsmax+1) - !$omp parallel - call allocate_array('list', list, maxp) - !$omp end parallel end subroutine allocate_kdtree @@ -93,10 +88,6 @@ subroutine deallocate_kdtree if (allocated(inodeparts)) deallocate(inodeparts) if (mpi .and. allocated(refinementnode)) deallocate(refinementnode) - !$omp parallel - if (allocated(list)) deallocate(list) - !$omp end parallel - end subroutine deallocate_kdtree @@ -206,7 +197,7 @@ subroutine maketree(node, xyzh, np, ndim, ifirstincell, ncells, refinelevels) ! construct node call construct_node(node(nnode), nnode, mymum, level, xmini, xmaxi, npnode, .true., & ! construct in parallel il, ir, nl, nr, xminl, xmaxl, xminr, xmaxr, & - ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, list, .false.) + ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, .false.) if (wassplit) then ! add children to back of queue if (istack+2 > istacksize) call fatal('maketree',& @@ -256,7 +247,7 @@ subroutine maketree(node, xyzh, np, ndim, ifirstincell, ncells, refinelevels) ! construct node call construct_node(node(nnode), nnode, mymum, level, xmini, xmaxi, npnode, .false., & ! don't construct in parallel il, ir, nl, nr, xminl, xmaxl, xminr, xmaxr, & - ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, list, .false.) + ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, .false.) if (wassplit) then ! add children to top of stack if (istack+2 > istacksize) call fatal('maketree',& @@ -465,7 +456,7 @@ end subroutine pop_off_stack !-------------------------------------------------------------------- subroutine construct_node(nodeentry, nnode, mymum, level, xmini, xmaxi, npnode, doparallel,& il, ir, nl, nr, xminl, xmaxl, xminr, xmaxr, & - ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, list, & + ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, & global_build) use dim, only:maxtypes,mpi use part, only:massoftype,igas,iamtype,maxphase,maxp,npartoftype @@ -484,7 +475,6 @@ subroutine construct_node(nodeentry, nnode, mymum, level, xmini, xmaxi, npnode, integer, intent(inout) :: maxlevel, minlevel real, intent(in) :: xyzh(:,:) logical, intent(out) :: wassplit - integer, intent(out) :: list(:) ! not actually sent out, but to avoid repeated memory allocation/deallocation logical, intent(in) :: global_build real :: xyzcofm(ndim) @@ -1552,7 +1542,7 @@ subroutine maketreeglobal(nodeglobal,node,nodemap,globallevel,refinelevels,xyzh, call construct_node(mynode(1), iself, parent, level, xmini, xmaxi, npcounter, .false., & il, ir, nl, nr, xminl, xmaxl, xminr, xmaxr, & - ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, list, & + ncells, ifirstincell, minlevel, maxlevel, ndim, xyzh, wassplit, & .true.) if (.not.wassplit) then diff --git a/src/main/kernel_WendlandC2.f90 b/src/main/kernel_WendlandC2.f90 index 882b2d4a4..4dd74aa6f 100644 --- a/src/main/kernel_WendlandC2.f90 +++ b/src/main/kernel_WendlandC2.f90 @@ -90,7 +90,7 @@ end subroutine get_kernel_grav1 pure subroutine kernel_softening(q2,q,potensoft,fsoft) real, intent(in) :: q2,q real, intent(out) :: potensoft,fsoft - real :: q4, q6 + real :: q4 if (q < 2.) then q4 = q2*q2 @@ -104,6 +104,22 @@ pure subroutine kernel_softening(q2,q,potensoft,fsoft) end subroutine kernel_softening +!------------------------------------------ +! gradient acceleration kernel needed for +! use in Forward symplectic integrator +!------------------------------------------ +pure subroutine kernel_grad_soft(q2,q,gsoft) + real, intent(in) :: q2,q + real, intent(out) :: gsoft + + if (q < 2.) then + gsoft = 3.*q2*q*(35.*q2*q - 240.*q2 + 560.*q - 448.)/256. + else + gsoft = -3./q2 + endif + +end subroutine kernel_grad_soft + !------------------------------------------ ! double-humped version of the kernel for ! use in drag force calculations diff --git a/src/main/kernel_WendlandC4.f90 b/src/main/kernel_WendlandC4.f90 index ea1202d65..6a0ded877 100644 --- a/src/main/kernel_WendlandC4.f90 +++ b/src/main/kernel_WendlandC4.f90 @@ -37,8 +37,9 @@ pure subroutine get_kernel(q2,q,wkern,grkern) !--Wendland 2/3D C^4 if (q < 2.) then - wkern = (-q/2. + 1.)**6*(35.*q2/12. + 3.*q + 1.) - grkern = 11.6666666666667*q2*(0.5*q - 1.)**5 + 4.66666666666667*q*(0.5*q - 1.)**5 + wkern = (1 - q/2.)**6*(35.*q2/12. + 3.*q + 1.) + grkern = (1 - q/2.)**6*(35.*q/6. + 3.) - 3.*(1. - q/2.)**5*(35.*q2/12. + 3.*q + & + 1.) else wkern = 0. grkern = 0. @@ -50,7 +51,7 @@ pure elemental real function wkern(q2,q) real, intent(in) :: q2,q if (q < 2.) then - wkern = (-q/2. + 1.)**6*(35.*q2/12. + 3.*q + 1.) + wkern = (1 - q/2.)**6*(35.*q2/12. + 3.*q + 1.) else wkern = 0. endif @@ -61,7 +62,8 @@ pure elemental real function grkern(q2,q) real, intent(in) :: q2,q if (q < 2.) then - grkern = 11.6666666666667*q2*(0.5*q - 1.)**5 + 4.66666666666667*q*(0.5*q - 1.)**5 + grkern = (1 - q/2.)**6*(35.*q/6. + 3.) - 3.*(1. - q/2.)**5*(35.*q2/12. + 3.*q + & + 1.) else grkern = 0. endif @@ -77,8 +79,9 @@ pure subroutine get_kernel_grav1(q2,q,wkern,grkern,dphidh) q4 = q2*q2 q6 = q4*q2 q8 = q6*q2 - wkern = (-q/2. + 1.)**6*(35.*q2/12. + 3.*q + 1.) - grkern = 11.6666666666667*q2*(0.5*q - 1.)**5 + 4.66666666666667*q*(0.5*q - 1.)**5 + wkern = (1 - q/2.)**6*(35.*q2/12. + 3.*q + 1.) + grkern = (1 - q/2.)**6*(35.*q/6. + 3.) - 3.*(1. - q/2.)**5*(35.*q2/12. + 3.*q + & + 1.) dphidh = -1155.*q6*q4/32768. + 55.*q8*q/128. - 17325.*q8/8192. + 165.*q6*q/32. - & 5775.*q6/1024. + 1155.*q4/256. - 495.*q2/128. + 55./32. else @@ -109,6 +112,26 @@ pure subroutine kernel_softening(q2,q,potensoft,fsoft) end subroutine kernel_softening +!------------------------------------------ +! gradient acceleration kernel needed for +! use in Forward symplectic integrator +!------------------------------------------ +pure subroutine kernel_grad_soft(q2,q,gsoft) + real, intent(in) :: q2,q + real, intent(out) :: gsoft + real :: q4, q6 + + if (q < 2.) then + q4 = q2*q2 + q6 = q4*q2 + gsoft = 3.*q2*q*(175.*q6 - 1848.*q4*q + 7700.*q4 - 15400.*q2*q + 13200.*q2 - & + 4928.)/2048. + else + gsoft = -3./q2 + endif + +end subroutine kernel_grad_soft + !------------------------------------------ ! double-humped version of the kernel for ! use in drag force calculations @@ -118,7 +141,7 @@ pure elemental real function wkern_drag(q2,q) !--double hump Wendland 2/3D C^4 kernel if (q < 2.) then - wkern_drag = q2*(-q/2. + 1.)**6*(35.*q2/12. + 3.*q + 1.) + wkern_drag = q2*(1. - q/2.)**6*(35.*q2/12. + 3.*q + 1.) else wkern_drag = 0. endif diff --git a/src/main/kernel_WendlandC6.f90 b/src/main/kernel_WendlandC6.f90 index b7b690789..c6e54af66 100644 --- a/src/main/kernel_WendlandC6.f90 +++ b/src/main/kernel_WendlandC6.f90 @@ -112,6 +112,27 @@ pure subroutine kernel_softening(q2,q,potensoft,fsoft) end subroutine kernel_softening +!------------------------------------------ +! gradient acceleration kernel needed for +! use in Forward symplectic integrator +!------------------------------------------ +pure subroutine kernel_grad_soft(q2,q,gsoft) + real, intent(in) :: q2,q + real, intent(out) :: gsoft + real :: q4, q6, q8 + + if (q < 2.) then + q4 = q2*q2 + q6 = q4*q2 + q8 = q6*q2 + gsoft = 3.*q2*q*(2860.*q8*q - 40425.*q8 + 240240.*q6*q - 764400.*q6 + & + 1345344.*q4*q - 1121120.*q4 + 549120.*q2 - 256256.)/65536. + else + gsoft = -3./q2 + endif + +end subroutine kernel_grad_soft + !------------------------------------------ ! double-humped version of the kernel for ! use in drag force calculations diff --git a/src/main/kernel_cubic.f90 b/src/main/kernel_cubic.f90 index bf16cead5..6ec8230a9 100644 --- a/src/main/kernel_cubic.f90 +++ b/src/main/kernel_cubic.f90 @@ -119,6 +119,26 @@ pure subroutine kernel_softening(q2,q,potensoft,fsoft) end subroutine kernel_softening +!------------------------------------------ +! gradient acceleration kernel needed for +! use in Forward symplectic integrator +!------------------------------------------ +pure subroutine kernel_grad_soft(q2,q,gsoft) + real, intent(in) :: q2,q + real, intent(out) :: gsoft + real :: q4 + + if (q < 1.) then + gsoft = q2*q*(1.5*q - 2.4) + elseif (q < 2.) then + q4 = q2*q2 + gsoft = (q4*(-0.5*q2 + 2.4*q - 3.) + 0.2)/q2 + else + gsoft = -3./q2 + endif + +end subroutine kernel_grad_soft + !------------------------------------------ ! double-humped version of the kernel for ! use in drag force calculations diff --git a/src/main/kernel_quartic.f90 b/src/main/kernel_quartic.f90 index a698e32b6..de96a3432 100644 --- a/src/main/kernel_quartic.f90 +++ b/src/main/kernel_quartic.f90 @@ -148,6 +148,31 @@ pure subroutine kernel_softening(q2,q,potensoft,fsoft) end subroutine kernel_softening +!------------------------------------------ +! gradient acceleration kernel needed for +! use in Forward symplectic integrator +!------------------------------------------ +pure subroutine kernel_grad_soft(q2,q,gsoft) + real, intent(in) :: q2,q + real, intent(out) :: gsoft + real :: q4, q6 + + if (q < 0.5) then + gsoft = 6.*q2*q*(4.*q2 - 7.)/35. + elseif (q < 1.5) then + q4 = q2*q2 + q6 = q4*q2 + gsoft = (-1024.*q6*q + 4480.*q6 - 5376.*q4*q + 560.*q4 - 1.)/(2240.*q2) + elseif (q < 2.5) then + q4 = q2*q2 + q6 = q4*q2 + gsoft = (512.*q6*q - 4480.*q6 + 13440.*q4*q - 14000.*q4 + 2185.)/(4480.*q2) + else + gsoft = -3./q2 + endif + +end subroutine kernel_grad_soft + !------------------------------------------ ! double-humped version of the kernel for ! use in drag force calculations diff --git a/src/main/kernel_quintic.f90 b/src/main/kernel_quintic.f90 index 64482f474..82e735192 100644 --- a/src/main/kernel_quintic.f90 +++ b/src/main/kernel_quintic.f90 @@ -152,6 +152,35 @@ pure subroutine kernel_softening(q2,q,potensoft,fsoft) end subroutine kernel_softening +!------------------------------------------ +! gradient acceleration kernel needed for +! use in Forward symplectic integrator +!------------------------------------------ +pure subroutine kernel_grad_soft(q2,q,gsoft) + real, intent(in) :: q2,q + real, intent(out) :: gsoft + real :: q4, q6, q8 + + if (q < 1.) then + gsoft = q2*q*(-175.*q2*q + 480.*q2 - 672.)/840. + elseif (q < 2.) then + q4 = q2*q2 + q6 = q4*q2 + q8 = q6*q2 + gsoft = (175.*q8 - 1440.*q6*q + 4200.*q6 - 4704.*q4*q + 1050.*q4 - & + 15.)/(1680.*q2) + elseif (q < 3.) then + q4 = q2*q2 + q6 = q4*q2 + q8 = q6*q2 + gsoft = (-35.*q8 + 480.*q6*q - 2520.*q6 + 6048.*q4*q - 5670.*q4 + & + 1521.)/(1680.*q2) + else + gsoft = -3./q2 + endif + +end subroutine kernel_grad_soft + !------------------------------------------ ! double-humped version of the kernel for ! use in drag force calculations diff --git a/src/main/metric_minkowski.f90 b/src/main/metric_minkowski.f90 index 3562abad8..8164301c0 100644 --- a/src/main/metric_minkowski.f90 +++ b/src/main/metric_minkowski.f90 @@ -202,8 +202,9 @@ subroutine read_options_metric(name,valstring,imatch,igotall,ierr) logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr - ! imatch = .true. - ! igotall = .true. + imatch = .true. + igotall = .true. + ierr = 0 end subroutine read_options_metric diff --git a/src/main/mpi_dens.F90 b/src/main/mpi_dens.F90 index d578658e3..5948afce0 100644 --- a/src/main/mpi_dens.F90 +++ b/src/main/mpi_dens.F90 @@ -74,6 +74,7 @@ module mpidens integer :: maxlength = 0 integer :: n = 0 integer :: number + integer :: idum ! to avoid ifort warning end type stackdens contains @@ -227,6 +228,8 @@ subroutine free_mpitype_of_celldens(dtype) integer :: mpierr call MPI_Type_free(dtype,mpierr) +#else + dtype = 0 #endif end subroutine free_mpitype_of_celldens diff --git a/src/main/mpi_derivs.F90 b/src/main/mpi_derivs.F90 index a9b2b2641..1847cbd6c 100644 --- a/src/main/mpi_derivs.F90 +++ b/src/main/mpi_derivs.F90 @@ -137,7 +137,12 @@ subroutine init_celldens_exchange(xbufrecv,ireq,thread_complete,ncomplete_mpi,dt ncomplete_mpi = 0 !$omp end master thread_complete(omp_thread_num()+1) = .false. +#else + ncomplete_mpi = 0 + ireq = 0 + dtype = 0 #endif + end subroutine init_celldens_exchange subroutine init_cellforce_exchange(xbufrecv,ireq,thread_complete,ncomplete_mpi,dtype) @@ -177,6 +182,10 @@ subroutine init_cellforce_exchange(xbufrecv,ireq,thread_complete,ncomplete_mpi,d ncomplete_mpi = 0 !$omp end master thread_complete(omp_thread_num()+1) = .false. +#else + ncomplete_mpi = 0 + ireq = 0 + dtype = 0 #endif end subroutine init_cellforce_exchange @@ -209,6 +218,8 @@ subroutine send_celldens(cell,targets,irequestsend,xsendbuf,counters,dtype) counters(newproc+1,isent) = counters(newproc+1,isent) + 1 endif enddo +#else + xsendbuf = cell #endif end subroutine send_celldens @@ -237,6 +248,8 @@ subroutine send_cellforce(cell,targets,irequestsend,xsendbuf,counters,dtype) counters(newproc+1,isent) = counters(newproc+1,isent) + 1 endif enddo +#else + xsendbuf = cell #endif end subroutine send_cellforce @@ -260,6 +273,8 @@ subroutine check_send_finished(irequestsend,idone) enddo !--never test self; always set to true idone(id+1) = .true. +#else + idone = .true. #endif end subroutine check_send_finished @@ -619,6 +634,8 @@ subroutine check_complete(counters,ncomplete_mpi) endif endif enddo +#else + ncomplete_mpi = 1 #endif end subroutine check_complete diff --git a/src/main/mpi_memory.f90 b/src/main/mpi_memory.f90 deleted file mode 100644 index 5d635f2d4..000000000 --- a/src/main/mpi_memory.f90 +++ /dev/null @@ -1,317 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module mpimemory -! -! None -! -! :References: None -! -! :Owner: Conrad Chan -! -! :Runtime parameters: None -! -! :Dependencies: dim, io, mpidens, mpiforce -! - use io, only:fatal,iprint - use mpidens, only:celldens,stackdens - use mpiforce, only:cellforce,stackforce - - implicit none - - interface allocate_stack - module procedure allocate_stack_dens,allocate_stack_force - end interface allocate_stack - - interface swap_stacks ! force doesn't require a stack swap - module procedure swap_stacks_dens - end interface swap_stacks - - interface push_onto_stack - module procedure push_onto_stack_dens,push_onto_stack_force - end interface push_onto_stack - - interface get_cell - module procedure get_cell_dens,get_cell_force - end interface get_cell - - interface write_cell - module procedure write_cell_dens,write_cell_force - end interface write_cell - - interface reserve_stack - module procedure reserve_stack_dens,reserve_stack_force - end interface reserve_stack - - public :: allocate_mpi_memory - public :: deallocate_mpi_memory - public :: allocate_stack - public :: swap_stacks - public :: push_onto_stack - public :: get_cell - public :: write_cell - public :: reserve_stack - public :: reset_stacks - public :: increase_mpi_memory - - ! stacks to be referenced from density and force routines - type(stackdens), public :: dens_stack_1 - type(stackdens), public :: dens_stack_2 - type(stackdens), public :: dens_stack_3 - type(stackforce), public :: force_stack_1 - type(stackforce), public :: force_stack_2 - - integer, public :: stacksize - - private - - ! primary chunk of memory requested using alloc - type(celldens), allocatable, target :: dens_cells(:,:) - type(cellforce), allocatable, target :: force_cells(:,:) - -contains - -subroutine allocate_mpi_memory(npart, stacksize_in) - integer, optional, intent(in) :: npart - integer, optional, intent(in) :: stacksize_in - integer :: allocstat - - allocstat = 0 - - if (present(stacksize_in)) stacksize = stacksize_in - if (present(npart)) call calculate_stacksize(npart) - - if (allocated(dens_cells)) then - if (stacksize /= size(dens_cells,1)) then - call fatal('stack', 'dens_cells already allocated with a different size') - endif - endif - - if (allocated(force_cells)) then - if (stacksize /= size(force_cells,1)) then - call fatal('stack', 'force_cells already allocated with a different size') - endif - endif - - if (.not. allocated(dens_cells)) allocate(dens_cells(stacksize,3), stat=allocstat) - if (allocstat /= 0) call fatal('stack','fortran memory allocation error') - call allocate_stack(dens_stack_1, 1) - call allocate_stack(dens_stack_2, 2) - call allocate_stack(dens_stack_3, 3) - - if (.not. allocated(force_cells)) allocate(force_cells(stacksize,2), stat=allocstat) - if (allocstat /= 0) call fatal('stack','fortran memory allocation error') - call allocate_stack(force_stack_1, 1) - call allocate_stack(force_stack_2, 2) - -end subroutine allocate_mpi_memory - -subroutine increase_mpi_memory - use io, only:id - real, parameter :: factor = 1.5 - integer :: stacksize_new - integer :: allocstat - - ! temporary memory for increasing stack sizes - type(celldens), allocatable, target :: dens_cells_tmp(:,:) - type(cellforce), allocatable, target :: force_cells_tmp(:,:) - - stacksize_new = int(real(stacksize) * factor) - write(iprint, *) 'MPI dens stack exceeded on', id, 'increasing size to', stacksize_new - - ! Expand density - call move_alloc(dens_cells, dens_cells_tmp) - allocate(dens_cells(stacksize_new,3), stat=allocstat) - if (allocstat /= 0) call fatal('stack', 'error increasing dens stack size') - dens_cells(1:stacksize,:) = dens_cells_tmp(:,:) - deallocate(dens_cells_tmp) - - ! Expand force - call move_alloc(force_cells, force_cells_tmp) - allocate(force_cells(stacksize_new,2), stat=allocstat) - if (allocstat /= 0) call fatal('stack', 'error increasing force stack size') - force_cells(1:stacksize,:) = force_cells_tmp(:,:) - deallocate(force_cells_tmp) - - stacksize = stacksize_new - call allocate_stack(force_stack_1, 1) - call allocate_stack(force_stack_2, 2) - call allocate_stack(dens_stack_1, dens_stack_1%number) - call allocate_stack(dens_stack_2, dens_stack_2%number) - call allocate_stack(dens_stack_3, dens_stack_3%number) -end subroutine increase_mpi_memory - -subroutine calculate_stacksize(npart) - use dim, only:mpi,minpart - use io, only:nprocs,id,master - integer, intent(in) :: npart - integer, parameter :: safety = 8 - - ! size of the stack needed for communication, - ! should be at least the maximum number of cells that need - ! to be exported to other tasks. - ! - ! if it is not large enough, it will be automatically expanded - - ! number of particles per cell, divided by number of tasks - if (mpi .and. nprocs > 1) then - ! assume that every cell will be exported, with some safety factor - stacksize = (npart / minpart / nprocs) * safety - - if (id == master) then - write(iprint, *) 'MPI memory stack size = ', stacksize - write(iprint, *) ' (total number of cells that can be exported by a single task)' - endif - else - stacksize = 0 - endif - -end subroutine calculate_stacksize - -subroutine deallocate_mpi_memory - if (allocated(dens_cells )) deallocate(dens_cells ) - if (allocated(force_cells)) deallocate(force_cells) -end subroutine deallocate_mpi_memory - -subroutine allocate_stack_dens(stack, i) - type(stackdens), intent(inout) :: stack - integer, intent(in) :: i - - stack%number = i - stack%cells => dens_cells(1:stacksize,stack%number) - stack%maxlength = stacksize - -end subroutine allocate_stack_dens - -subroutine allocate_stack_force(stack, i) - type(stackforce), intent(inout) :: stack - integer, intent(in) :: i - - stack%number = i - stack%cells => force_cells(1:stacksize,stack%number) - stack%maxlength = stacksize - -end subroutine allocate_stack_force - -subroutine swap_stacks_dens(stack_a, stack_b) - type(stackdens), intent(inout) :: stack_a - type(stackdens), intent(inout) :: stack_b - - integer :: temp_n - integer :: temp_number - - if (stack_a%maxlength /= stack_b%maxlength) call fatal('stack', 'stack swap of unequal size') - - ! counters - temp_n = stack_a%n - stack_a%n = stack_b%n - stack_b%n = temp_n - - ! addresses - temp_number = stack_a%number - stack_a%number = stack_b%number - stack_b%number = temp_number - - ! change pointers - stack_a%cells => dens_cells(1:stacksize,stack_a%number) - stack_b%cells => dens_cells(1:stacksize,stack_b%number) - -end subroutine swap_stacks_dens - -subroutine push_onto_stack_dens(stack,cell) - type(stackdens), intent(inout) :: stack - type(celldens), intent(in) :: cell - - integer :: i - - call reserve_stack(stack,i) - - ! no other thread will write to the same position, so it is threadsafe to write without a critical section - stack%cells(i) = cell -end subroutine push_onto_stack_dens - -subroutine push_onto_stack_force(stack,cell) - type(stackforce), intent(inout) :: stack - type(cellforce), intent(in) :: cell - - integer :: i - - call reserve_stack(stack,i) - - ! no other thread will write to the same position, so it is threadsafe to write without a critical section - stack%cells(i) = cell -end subroutine push_onto_stack_force - -type(celldens) function get_cell_dens(stack,i) - type(stackdens), intent(in) :: stack - integer, intent(in) :: i - - if (stack%n < i) call fatal('dens','attempting to read invalid stack address') - get_cell_dens = stack%cells(i) -end function get_cell_dens - -type(cellforce) function get_cell_force(stack,i) - type(stackforce), intent(in) :: stack - integer, intent(in) :: i - - if (stack%n < i) call fatal('force','attempting to read invalid stack address') - get_cell_force = stack%cells(i) -end function get_cell_force - -subroutine write_cell_dens(stack,cell) - type(stackdens), intent(inout) :: stack - type(celldens), intent(inout) :: cell - - if (cell%waiting_index > stack%maxlength) call fatal('dens','attempting to write to invalid stack address') - stack%cells(cell%waiting_index) = cell - -end subroutine write_cell_dens - -subroutine write_cell_force(stack,cell) - type(stackforce), intent(inout) :: stack - type(cellforce), intent(inout) :: cell - - if (cell%waiting_index > stack%maxlength) call fatal('force','attempting to write to invalid stack address') - stack%cells(cell%waiting_index) = cell - -end subroutine write_cell_force - -subroutine reserve_stack_dens(stack,i) - type(stackdens), intent(inout) :: stack - integer, intent(out) :: i - - !$omp atomic capture - stack%n = stack%n + 1 - i = stack%n - !$omp end atomic - - if (i > stack%maxlength) call fatal('dens','MPI stack exceeded') - -end subroutine reserve_stack_dens - -subroutine reserve_stack_force(stack,i) - type(stackforce), intent(inout) :: stack - integer, intent(out) :: i - - !$omp atomic capture - stack%n = stack%n + 1 - i = stack%n - !$omp end atomic - - if (i > stack%maxlength) call fatal('force','MPI stack exceeded') - -end subroutine reserve_stack_force - -subroutine reset_stacks - dens_stack_1%n=0 - dens_stack_2%n=0 - dens_stack_3%n=0 - - force_stack_1%n=0 - force_stack_2%n=0 -end subroutine reset_stacks - -end module mpimemory diff --git a/src/main/mpi_tree.F90 b/src/main/mpi_tree.F90 index fe49e3c22..8b24ace8c 100644 --- a/src/main/mpi_tree.F90 +++ b/src/main/mpi_tree.F90 @@ -132,6 +132,9 @@ subroutine get_group_cofm(xyzcofm,totmass_node,level,cofmsum,totmassg) call MPI_ALLREDUCE(totmass_node,totmassg,1,MPI_REAL8,MPI_SUM,comm_cofm(level+1),mpierr) call MPI_ALLREDUCE(cofmpart,cofmsum,3,MPI_REAL8,MPI_SUM,comm_cofm(level+1),mpierr) cofmsum = cofmsum / totmassg +#else + cofmsum = xyzcofm*totmass_node + totmassg = totmass_node #endif end subroutine get_group_cofm diff --git a/src/main/mpi_utils.F90 b/src/main/mpi_utils.F90 index e725bc020..03816c05d 100644 --- a/src/main/mpi_utils.F90 +++ b/src/main/mpi_utils.F90 @@ -110,6 +110,7 @@ module mpiutils public :: fill_buffer, unfill_buf public :: reduceloc_mpi public :: waitmyturn,endmyturn + public :: start_threadwrite,end_threadwrite private @@ -227,6 +228,64 @@ subroutine endmyturn(myid) end subroutine endmyturn +!-------------------------------------------------------------------- +!+ +! utility for initialising each thread +!+ +!-------------------------------------------------------------------- +subroutine start_threadwrite(id,iunit,filename) +#ifdef MPI + use mpi +#endif + use io, only:error,iverbose + implicit none + integer, intent(in) :: id, iunit + character(len=*), intent(in) :: filename + integer :: nowgo,ierr + + if (iverbose >= 3) print *,id,' : starting write...' + nowgo = 0 + if (id > 0) then +#ifdef MPI + call MPI_RECV(nowgo,1,MPI_INTEGER,id-1,99,MPI_COMM_WORLD,status,mpierr) +#endif + open(unit=iunit,file=filename,status='old',form='unformatted',position='append',iostat=ierr) + if (ierr /= 0) then + call error('start_threadwrite','can''t append to dumpfile '//trim(filename)) + else + if (iverbose >= 3) print*,'thread ',id,': opened file '//trim(filename) + endif + endif + +end subroutine start_threadwrite + +!-------------------------------------------------------------------- +!+ +! utility for finalising each thread +!+ +!-------------------------------------------------------------------- +subroutine end_threadwrite(id) + use io, only:iverbose +#ifdef MPI + use mpi + use io, only:nprocs +#endif + implicit none + integer, intent(in) :: id +#ifdef MPI + integer :: nowgo +#endif + + if (iverbose >= 3) print *,' thread ',id,' : finished write.' +#ifdef MPI + if (id < nprocs-1) then + nowgo = 1 + call MPI_SEND(nowgo,1,MPI_INTEGER,id+1,99,MPI_COMM_WORLD,mpierr) + endif +#endif + +end subroutine end_threadwrite + !-------------------------------------------------------------------- !+ ! MPI barrier interface (no-op if called in non-mpi code) diff --git a/src/main/nicil_supplement.F90 b/src/main/nicil_supplement.F90 deleted file mode 100644 index 33533c07b..000000000 --- a/src/main/nicil_supplement.F90 +++ /dev/null @@ -1,236 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module nicil_sup -! -! Contains wrapper routines so that NICIL can be used in Phantom -! -! :References: Wurster (2016) -! Wurster (2021) -! -! :Owner: Daniel Price -! -! :Runtime parameters: -! - C_AD : *constant coefficient for ambipolar diffusion* -! - C_HE : *constant coefficient for the Hall effect (incl. sign)* -! - C_OR : *constant coefficient for ohmic resistivity* -! - Cdt_diff : *coefficient to control the Ohmic & ambipolar timesteps* -! - Cdt_hall : *coefficient to control the Hall timestep* -! - a0_grain : *grain radius (cm)* -! - alpha_AD : *power law exponent for ambipolar diffusion* -! - an_grain : *minimum grain radius (cm)* -! - ax_grain : *maximum grain radius (cm)* -! - eta_const_type : *Coefficient type: phys.cnst+B+rho (1), C_NI+B+rho (2), C_NI (3)* -! - eta_constant : *Use constant coefficients for all non-ideal MHD terms* -! - fdg : *dust-to-gas mass ratio* -! - gamma_AD : *ion-neutral coupling coefficient for ambipolar diffusion* -! - hall_lt_zero : *sign of the hall coefficient (<0 if T)* -! - n_e_cnst : *constant electron number density* -! - rho_bulk : *bulk grain density (g/cm^3)* -! - rho_i_cnst : *ionisation density for ambipolar diffusion* -! - rho_n_cnst : *neutral density for ambipolar diffusion* -! - use_ambi : *Calculate the coefficient for ambipolar diffusion* -! - use_hall : *Calculate the coefficient for the Hall effect* -! - use_ohm : *Calculate the coefficient for Ohmic resistivity* -! - zeta : *cosmic ray ionisation rate (s^-1)* -! -! :Dependencies: infile_utils, nicil, physcon -! - use nicil, only: use_ohm,use_hall,use_ambi,na, & - fdg,rho_bulk,a0_grain,an_grain,ax_grain,zeta_cgs,Cdt_diff,Cdt_hall, & - eta_constant,eta_const_type,icnstphys,icnstsemi,icnst,C_OR,C_HE,C_AD, & - n_e_cnst,hall_lt_zero,rho_i_cnst,rho_n_cnst,alpha_AD,gamma_AD - implicit none - ! - !--Subroutines - public :: use_consistent_gmw,write_options_nicil,read_options_nicil - - private - -contains - -!----------------------------------------------------------------------- -!+ -! Ensures a consistent meanmolecular mass is used -!+ -!----------------------------------------------------------------------- -subroutine use_consistent_gmw(ierr,gmw_eos,gmw_nicil) - use nicil, only:meanmolmass - integer, intent(out) :: ierr - real, intent(out) :: gmw_nicil - real, intent(inout) :: gmw_eos - - gmw_nicil = meanmolmass - if (abs(meanmolmass-gmw_eos) > epsilon(gmw_eos)) then - ierr = 1 - gmw_eos = meanmolmass - endif - -end subroutine use_consistent_gmw -!----------------------------------------------------------------------- -!+ -! writes input options to the input file -!+ -!----------------------------------------------------------------------- -subroutine write_options_nicil(iunit) - use infile_utils, only:write_inopt - integer, intent(in) :: iunit - - write(iunit,"(/,a)") '# options controlling non-ideal MHD' - call write_inopt(use_ohm , 'use_ohm' ,'Calculate the coefficient for Ohmic resistivity',iunit) - call write_inopt(use_hall, 'use_hall' ,'Calculate the coefficient for the Hall effect',iunit) - call write_inopt(use_ambi, 'use_ambi' ,'Calculate the coefficient for ambipolar diffusion',iunit) - call write_inopt(eta_constant,'eta_constant','Use constant coefficients for all non-ideal MHD terms',iunit) - if ( eta_constant ) then - call write_inopt(eta_const_type,'eta_const_type','Coefficient type: phys.cnst+B+rho (1), C_NI+B+rho (2), C_NI (3)',iunit) - if ( eta_const_type==1 ) then - if ( use_ohm .or. use_hall ) then - call write_inopt(n_e_cnst,'n_e_cnst' ,'constant electron number density',iunit) - if ( use_hall ) call write_inopt(hall_lt_zero, 'hall_lt_zero' ,'sign of the hall coefficient (<0 if T)',iunit) - endif - if ( use_ambi ) then - call write_inopt(gamma_AD, 'gamma_AD', 'ion-neutral coupling coefficient for ambipolar diffusion',iunit) - call write_inopt(rho_i_cnst, 'rho_i_cnst','ionisation density for ambipolar diffusion',iunit) - call write_inopt(rho_n_cnst, 'rho_n_cnst','neutral density for ambipolar diffusion',iunit) - call write_inopt(alpha_AD, 'alpha_AD', 'power law exponent for ambipolar diffusion',iunit) - endif - elseif ( eta_const_type==2 ) then - if ( use_ohm ) call write_inopt(C_OR,'C_OR', 'semi-constant coefficient for ohmic resistivity',iunit) - if ( use_hall ) call write_inopt(C_HE,'C_HE', 'semi-constant coefficient for the Hall effect (incl. sign)',iunit) - if ( use_ambi ) call write_inopt(C_AD,'C_AD', 'semi-constant coefficient for ambipolar diffusion',iunit) - elseif ( eta_const_type==3 ) then - if ( use_ohm ) call write_inopt(C_OR,'C_OR', 'constant coefficient for ohmic resistivity',iunit) - if ( use_hall ) call write_inopt(C_HE,'C_HE', 'constant coefficient for the Hall effect (incl. sign)',iunit) - if ( use_ambi ) call write_inopt(C_AD,'C_AD', 'constant coefficient for ambipolar diffusion',iunit) - endif - endif - call write_inopt(Cdt_diff, 'Cdt_diff', 'coefficient to control the Ohmic & ambipolar timesteps',iunit) - call write_inopt(Cdt_hall, 'Cdt_hall', 'coefficient to control the Hall timestep',iunit) - if ( .not. eta_constant ) then - write(iunit,"(/,a)") '# options controlling ionisation' - call write_inopt(fdg, 'fdg', 'dust-to-gas mass ratio',iunit) - call write_inopt(rho_bulk, 'rho_bulk', 'bulk grain density (g/cm^3)',iunit) - if ( na==1 ) then - call write_inopt(a0_grain, 'a0_grain', 'grain radius (cm)',iunit) - else - call write_inopt(an_grain, 'an_grain', 'minimum grain radius (cm)',iunit) - call write_inopt(ax_grain, 'ax_grain', 'maximum grain radius (cm)',iunit) - endif - call write_inopt(zeta_cgs, 'zeta', 'cosmic ray ionisation rate (s^-1)',iunit) - endif - -end subroutine write_options_nicil -!----------------------------------------------------------------------- -!+ -! reads input options from the input file -!+ -!----------------------------------------------------------------------- -subroutine read_options_nicil(name,valstring,imatch,igotall,ierr) - use physcon, only:fourpi - character(len=*), intent(in) :: name,valstring - logical, intent(out) :: imatch,igotall - integer, intent(out) :: ierr - integer :: ngotmax - integer, save :: ngot = 0 - - !--Initialise parameters - imatch = .true. - igotall = .false. - !--Number of input parameters - ngotmax = 6 - - !--Read input parameters - select case(trim(name)) - case('use_ohm') - read(valstring,*,iostat=ierr) use_ohm - ngot = ngot + 1 - case('use_hall') - read(valstring,*,iostat=ierr) use_hall - ngot = ngot + 1 - case('use_ambi') - read(valstring,*,iostat=ierr) use_ambi - ngot = ngot + 1 - case('eta_constant') - read(valstring,*,iostat=ierr) eta_constant - ngot = ngot + 1 - if (eta_constant) then - ngotmax = ngotmax + 1 - else - ngotmax = ngotmax + 4 - if (na==1) ngotmax = ngotmax + 1 - endif - case('eta_const_type') - read(valstring,*,iostat=ierr) eta_const_type - ngot = ngot + 1 - if (eta_const_type==1) then - if (use_ohm ) ngotmax = ngotmax + 1 - if (use_hall) ngotmax = ngotmax + 2 - if (use_ambi) ngotmax = ngotmax + 4 - elseif (eta_const_type==2 .or. eta_const_type==3) then - if (use_ohm ) ngotmax = ngotmax + 1 - if (use_hall) ngotmax = ngotmax + 1 - if (use_ambi) ngotmax = ngotmax + 1 - endif - case('C_OR') - read(valstring,*,iostat=ierr) C_OR - ngot = ngot + 1 - case('C_HE') - read(valstring,*,iostat=ierr) C_HE - ngot = ngot + 1 - case('C_AD') - read(valstring,*,iostat=ierr) C_AD - ngot = ngot + 1 - case('n_e_cnst') - read(valstring,*,iostat=ierr) n_e_cnst - ngot = ngot + 1 - case('hall_lt_zero') - read(valstring,*,iostat=ierr) hall_lt_zero - ngot = ngot + 1 - case('gamma_AD') - read(valstring,*,iostat=ierr) gamma_AD - ngot = ngot + 1 - case('rho_i_cnst') - read(valstring,*,iostat=ierr) rho_i_cnst - ngot = ngot + 1 - case('rho_n_cnst') - read(valstring,*,iostat=ierr) rho_n_cnst - ngot = ngot + 1 - case('alpha_AD') - read(valstring,*,iostat=ierr) alpha_AD - ngot = ngot + 1 - case('fdg') - read(valstring,*,iostat=ierr) fdg - ngot = ngot + 1 - case('rho_bulk') - read(valstring,*,iostat=ierr) rho_bulk - ngot = ngot + 1 - case('a0_grain') - read(valstring,*,iostat=ierr) a0_grain - ngot = ngot + 1 - case('an_grain') - read(valstring,*,iostat=ierr) an_grain - ngot = ngot + 1 - case('ax_grain') - read(valstring,*,iostat=ierr) ax_grain - ngot = ngot + 1 - case('zeta') - read(valstring,*,iostat=ierr) zeta_cgs - ngot = ngot + 1 - case('Cdt_diff') - read(valstring,*,iostat=ierr) Cdt_diff - ngot = ngot + 1 - case('Cdt_hall') - read(valstring,*,iostat=ierr) Cdt_hall - ngot = ngot + 1 - case default - imatch = .false. - end select - if ( ngot >= ngotmax ) igotall = .true. - -end subroutine read_options_nicil - -!----------------------------------------------------------------------- -end module nicil_sup diff --git a/src/main/options.f90 b/src/main/options.f90 index 36bc7e5eb..f49271fca 100644 --- a/src/main/options.f90 +++ b/src/main/options.f90 @@ -29,13 +29,14 @@ module options real, public :: avdecayconst integer, public :: nfulldump,nmaxdumps,iexternalforce real, public :: tolh,damp,rkill - real(kind=4), public :: twallmax + integer, parameter :: sp = 4 ! single precision + real(kind=sp), public :: twallmax ! artificial viscosity, thermal conductivity, resistivity real, public :: alpha,alphau,beta real, public :: alphamax - real, public :: alphaB, psidecayfac, overcleanfac, hdivbbmax_max + real, public :: alphaB, psidecayfac, overcleanfac integer, public :: ishock_heating,ipdv_heating,icooling,iresistive_heating integer, public :: ireconav @@ -51,7 +52,7 @@ module options logical, public :: use_mcfost, use_Voronoi_limits_file, use_mcfost_stellar_parameters, mcfost_computes_Lacc logical, public :: mcfost_uses_PdV, mcfost_dust_subl integer, public :: ISM - real(kind=4), public :: mcfost_keep_part + real(kind=sp), public :: mcfost_keep_part character(len=80), public :: Voronoi_limits_file ! radiation @@ -133,8 +134,6 @@ subroutine set_default_options alphaB = 1.0 psidecayfac = 1.0 ! psi decay factor (MHD only) overcleanfac = 1.0 ! factor to increase signal velocity for (only) time steps and psi cleaning - hdivbbmax_max = 1.0 ! if > overcleanfac, then use B/(h*|div B|) as a coefficient for dtclean; - ! ! this is the max value allowed; test suggest =512 for magnetised colliding flows beta = 2.0 ! beta viscosity term avdecayconst = 0.1 ! decay time constant for viscosity switches @@ -150,7 +149,7 @@ subroutine set_default_options mcfost_computes_Lacc = .false. mcfost_dust_subl = .false. mcfost_uses_PdV = .true. - mcfost_keep_part = real(0.999,kind=4) + mcfost_keep_part = 0.999_sp ISM = 0 ! radiation diff --git a/src/main/partinject.F90 b/src/main/partinject.F90 index dadfffb35..8f621fbb3 100644 --- a/src/main/partinject.F90 +++ b/src/main/partinject.F90 @@ -43,7 +43,7 @@ module partinject subroutine add_or_update_particle(itype,position,velocity,h,u,particle_number,npart,npartoftype,xyzh,vxyzu,JKmuS) use part, only:maxp,iamtype,iphase,maxvxyzu,iboundary,nucleation,eos_vars,abundance use part, only:maxalpha,alphaind,maxgradh,gradh,fxyzu,fext,set_particle_type - use part, only:mhd,Bevol,dBevol,Bxyz,divBsymm!,dust_temp + use part, only:mhd,Bevol,dBevol,Bxyz,divBsymm,gr,pxyzu!,dust_temp use part, only:divcurlv,divcurlB,ndivcurlv,ndivcurlB,ntot,ibin,imu,igamma use part, only:iorig,norig use io, only:fatal @@ -105,6 +105,8 @@ subroutine add_or_update_particle(itype,position,velocity,h,u,particle_number,np divBsymm(particle_number) = 0. endif + if (gr) pxyzu(:,particle_number) = 0. + if (ndivcurlv > 0) divcurlv(:,particle_number) = 0. if (ndivcurlB > 0) divcurlB(:,particle_number) = 0. if (maxalpha==maxp) alphaind(:,particle_number) = 0. diff --git a/src/main/porosity.f90 b/src/main/porosity.f90 index 547584f34..7b5071b17 100755 --- a/src/main/porosity.f90 +++ b/src/main/porosity.f90 @@ -6,7 +6,7 @@ !--------------------------------------------------------------------------! module porosity ! -! Contains routine for porosity evolution (growth, bouncing, +! Contains routine for porosity evolution (growth, bouncing, ! fragmentation, compaction, disruption) ! ! :References: diff --git a/src/main/ptmass.F90 b/src/main/ptmass.F90 index 65dab95a1..e75d1c29d 100644 --- a/src/main/ptmass.F90 +++ b/src/main/ptmass.F90 @@ -59,6 +59,7 @@ module ptmass ! settings affecting routines in module (read from/written to input file) integer, public :: icreate_sinks = 0 + integer, public :: isink_potential = 0 real, public :: rho_crit_cgs = 1.e-10 real, public :: r_crit = 5.e-3 real, public :: h_acc = 1.e-3 @@ -69,7 +70,6 @@ module ptmass real, public :: r_merge_cond = 0.0 ! sinks will merge if bound within this radius real, public :: f_crit_override = 0.0 ! 1000. - logical, public :: use_regnbody = .false. ! subsystems switch logical, public :: use_fourthorder = .true. integer, public :: n_force_order = 3 @@ -160,7 +160,7 @@ subroutine get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,fxi,fyi,fzi,phi, real :: ftmpxi,ftmpyi,ftmpzi real :: dx,dy,dz,rr2,ddr,dr3,f1,f2,pmassj,J2,shat(3),Rsink real :: hsoft,hsoft1,hsoft21,q2i,qi,psoft,fsoft - real :: fxj,fyj,fzj,dsx,dsy,dsz + real :: fxj,fyj,fzj,dsx,dsy,dsz,fac,r integer :: j logical :: tofrom,extrap ! @@ -241,14 +241,30 @@ subroutine get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,fxi,fyi,fzi,phi, ! acceleration of gas due to point mass particle f1 = pmassj*dr3 + + ! acceleration of sink from gas + if (tofrom) f2 = pmassi*dr3 + + ! modified potential + select case (isink_potential) + case(1) + ! Ayliffe & Bate (2010) equation 2 (prevent accretion on to sink) + Rsink = xyzmh_ptmass(iReff,j) + r=1./ddr + if (Rsink > 0. .and. r < 2*Rsink) then + fac = (1. - (2. - r/Rsink)**4) + f1 = f1*fac + f2 = f2*fac + phi = phi - pmassj*(r**3/3.-4.*r**2*Rsink+24.*r*Rsink**2 & + -16.*Rsink**4/r-32.*Rsink**3*log(r))/Rsink**4 + endif + end select + ftmpxi = ftmpxi - dx*f1 ftmpyi = ftmpyi - dy*f1 ftmpzi = ftmpzi - dz*f1 phi = phi - pmassj*ddr ! potential (GM/r) - ! acceleration of sink from gas - if (tofrom) f2 = pmassi*dr3 - ! additional accelerations due to oblateness if (abs(J2) > 0.) then shat = unitvec(xyzmh_ptmass(ispinx:ispinz,j)) @@ -658,25 +674,28 @@ subroutine ptmass_vdependent_correction(nptmass,dkdt,vxyz_ptmass,fxyz_ptmass,xyz real, intent(inout) :: vxyz_ptmass(3,nptmass), xyzmh_ptmass(nsinkproperties,nptmass) real, intent(inout) :: fxyz_ptmass(4,nptmass) integer, intent(in) :: iexternalforce - real :: fxi,fyi,fzi,fextv(3) + real :: fxi,fyi,fzi,vxhalfi,vyhalfi,vzhalfi,fextv(3) integer :: i !$omp parallel do schedule(static) default(none) & !$omp shared(vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dkdt,nptmass,iexternalforce) & - !$omp private(fxi,fyi,fzi,fextv) & + !$omp private(vxhalfi,vyhalfi,vzhalfi,fxi,fyi,fzi,fextv) & !$omp private(i) do i=1,nptmass if (xyzmh_ptmass(4,i) > 0.) then + vxhalfi = vxyz_ptmass(1,i) + vyhalfi = vxyz_ptmass(2,i) + vzhalfi = vxyz_ptmass(3,i) fxi = fxyz_ptmass(1,i) fyi = fxyz_ptmass(2,i) fzi = fxyz_ptmass(3,i) call update_vdependent_extforce(iexternalforce,& - vxyz_ptmass(1,i),vxyz_ptmass(2,i),vxyz_ptmass(3,i), & - fxi,fyi,fzi,fextv,dkdt,xyzmh_ptmass(1,i),xyzmh_ptmass(2,i), & + vxhalfi,vyhalfi,vzhalfi,fxi,fyi,fzi,fextv,dkdt, & + xyzmh_ptmass(1,i),xyzmh_ptmass(2,i), & xyzmh_ptmass(3,i)) - fxyz_ptmass(1,i) = fxi + fextv(1) - fxyz_ptmass(2,i) = fyi + fextv(2) - fxyz_ptmass(3,i) = fzi + fextv(3) + fxyz_ptmass(1,i) = fxi + fxyz_ptmass(2,i) = fyi + fxyz_ptmass(3,i) = fzi endif enddo !$omp end parallel do @@ -1931,6 +1950,7 @@ subroutine write_options_ptmass(iunit) integer, intent(in) :: iunit write(iunit,"(/,a)") '# options controlling sink particles' + call write_inopt(isink_potential,'isink_potential','sink potential(0=1/r,1=surf)',iunit) if (gravity) then call write_inopt(icreate_sinks,'icreate_sinks','allow automatic sink particle creation',iunit) if (icreate_sinks > 0) then @@ -1977,6 +1997,9 @@ subroutine read_options_ptmass(name,valstring,imatch,igotall,ierr) read(valstring,*,iostat=ierr) icreate_sinks ngot = ngot + 1 if (icreate_sinks < 0) call fatal(label,'sink creation option out of range') + case('isink_potential') + read(valstring,*,iostat=ierr) isink_potential + ngot = ngot + 1 case('rho_crit_cgs') read(valstring,*,iostat=ierr) rho_crit_cgs if (rho_crit_cgs < 0.) call fatal(label,'rho_crit < 0') diff --git a/src/setup/readwrite_kepler.f90 b/src/setup/readwrite_kepler.f90 index 21d138b8b..41f73b86f 100644 --- a/src/setup/readwrite_kepler.f90 +++ b/src/setup/readwrite_kepler.f90 @@ -100,11 +100,11 @@ subroutine read_kepler_file(filepath,ng_max,n_rows,rtab,rhotab,ptab,temperature, !--This is used as a test for saving composition. ! ierr = 0 - open(newunit=iu, file=trim(fullfilepath)) + open(newunit=iu,file=trim(fullfilepath)) !The row with the information about column headings is at nheaderlines-1. !we skip the first nheaderlines-2 rows and then read the nheaderlines-1 to find the substrings call skip_header(iu,nheaderlines-2,ierr) - read(iu, '(a)', iostat=ierr) line + read(iu, '(a)',iostat=ierr) line !read the column labels and store them in an array. allocate(all_label(n_cols)) @@ -125,7 +125,7 @@ subroutine read_kepler_file(filepath,ng_max,n_rows,rtab,rhotab,ptab,temperature, ! !--Read the file again and save the data in stardata tensor. ! - open(newunit=iu, file=trim(fullfilepath)) + open(newunit=iu,file=trim(fullfilepath)) call skip_header(iu,nheaderlines,ierr) do k=1,n_rows read(iu,*,iostat=ierr) stardata(k,:) diff --git a/src/setup/readwrite_mesa.f90 b/src/setup/readwrite_mesa.f90 index a053eb985..d69a8ff72 100644 --- a/src/setup/readwrite_mesa.f90 +++ b/src/setup/readwrite_mesa.f90 @@ -230,7 +230,7 @@ subroutine write_mesa(outputpath,m,pres,temp,r,rho,ene,Xfrac,Yfrac,csound,mu) optionalcols(:,noptionalcols) = csound endif - open(newunit=iu, file = outputpath, status = 'replace') + open(newunit=iu,file=outputpath,status='replace') do i = 1,noptionalcols+ncols-1 write(iu,'(a24,2x)',advance="no") trim(headers(i)) enddo diff --git a/src/setup/set_binary.f90 b/src/setup/set_binary.f90 index e1208a837..3027f47d7 100644 --- a/src/setup/set_binary.f90 +++ b/src/setup/set_binary.f90 @@ -34,6 +34,7 @@ module setbinary end interface get_eccentricity_vector real, parameter :: pi = 4.*atan(1.) + real, parameter :: deg_to_rad = pi/180. integer, parameter :: & ierr_m1 = 1, & ierr_m2 = 2, & @@ -186,19 +187,19 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & if (present(posang_ascnode) .and. present(arg_peri) .and. present(incl)) then ! Campbell elements ecc = eccentricity - omega = arg_peri*pi/180. + omega = arg_peri*deg_to_rad ! our conventions here are Omega is measured East of North - big_omega = posang_ascnode*pi/180. + 0.5*pi - inc = incl*pi/180. + big_omega = posang_ascnode*deg_to_rad + 0.5*pi + inc = incl*deg_to_rad if (present(f)) then ! get eccentric, parabolic or hyperbolic anomaly from true anomaly ! (https://en.wikipedia.org/wiki/Eccentric_anomaly#From_the_true_anomaly) - theta = f*pi/180. + theta = f*deg_to_rad E = get_E_from_true_anomaly(theta,ecc) elseif (present(mean_anomaly)) then ! get eccentric anomaly from mean anomaly by solving Kepler equation - bigM = mean_anomaly*pi/180. + bigM = mean_anomaly*deg_to_rad E = get_E_from_mean_anomaly(bigM,ecc) else ! set binary at apastron @@ -324,7 +325,7 @@ subroutine set_binary(m1,m2,semimajoraxis,eccentricity, & ! rotate if inclination is non-zero ! if (present(incl) .and. .not.(present(arg_peri) .and. present(posang_ascnode))) then - xangle = incl*pi/180. + xangle = incl*deg_to_rad cosi = cos(xangle) sini = sin(xangle) do i=i1,i2 diff --git a/src/setup/set_hierarchical.f90 b/src/setup/set_hierarchical.f90 index 22dad2a68..c52aeabd6 100644 --- a/src/setup/set_hierarchical.f90 +++ b/src/setup/set_hierarchical.f90 @@ -493,31 +493,33 @@ subroutine set_multiple(m1,m2,semimajoraxis,eccentricity, & !--- Load/Create HIERARCHY file: xyzmh_ptmass index | hierarchical index | star mass | companion star mass | semi-major axis | eccentricity | period | inclination | argument of pericenter | ascending node longitude inquire(file=trim(filename), exist=iexist) - if (present(subst) .and. subst>10) then - if (iexist) then - open(1, file = trim(filename), status = 'old') - lines=0 - do - read(1, *, iostat=io) data(lines+1,:) - if (io/=0) exit - lines = lines + 1 - enddo - close(1) - else - print "(1x,a)",'ERROR: set_multiple: there is no HIERARCHY file, cannot perform subtitution.' - ierr = ierr_HIER2 + if (present(subst)) then + if (subst>10) then + if (iexist) then + open(1,file=trim(filename),status='old') + lines=0 + do + read(1, *,iostat=io) data(lines+1,:) + if (io/=0) exit + lines = lines + 1 + enddo + close(1) + else + print "(1x,a)",'ERROR: set_multiple: there is no HIERARCHY file, cannot perform subtitution.' + ierr = ierr_HIER2 + endif endif else if (iexist) then print "(1x,a)",'WARNING: set_multiple: deleting an existing HIERARCHY file.' - open(1, file=trim(filename), status='old') - close(1, status='delete') + open(1,file=trim(filename),status='old') + close(1,status='delete') endif mtot = m1 + m2 period = sqrt(4.*pi**2*semimajoraxis**3/mtot) - open(1, file = trim(filename), status = 'new') + open(1,file=trim(filename),status='new') if (present(incl)) then if (present(posang_ascnode) .and. present(arg_peri)) then write(1,*) 1, 11, m1, m2, semimajoraxis, eccentricity, period, incl, arg_peri, posang_ascnode @@ -535,75 +537,78 @@ subroutine set_multiple(m1,m2,semimajoraxis,eccentricity, & subst_index = 0 !--- Checks to avoid bad substitutions - if (present(subst) .and. subst>10) then - write(hier_prefix, *) subst - io=0 - mtot = 0. - do i=1,lines - if (data(i,2)==abs(subst)) then ! Check that star to be substituted exists in HIERARCHY file - if (data(i,1)==0) then ! Check that star to be substituted has not already been substituted - print "(1x,a)",'ERROR: set_multiple: star '//trim(hier_prefix)//' substituted yet.' - ierr = ierr_subststar - endif - subst_index = int(data(i,1)) - data(i,1) = 0 - - if (subst>0) then - rel_posang_ascnode = data(i, 10) - - if (rel_posang_ascnode /= 0) then - print "(1x,a)",'ERROR: set_multiple: at the moment phantom can subst only Omega=0 binaries.' - ierr = ierr_Omegasubst + if (present(subst)) then + if (subst>10) then + write(hier_prefix, *) subst + io=0 + mtot = 0. + do i=1,lines + if (data(i,2)==abs(subst)) then ! Check that star to be substituted exists in HIERARCHY file + if (data(i,1)==0) then ! Check that star to be substituted has not already been substituted + print "(1x,a)",'ERROR: set_multiple: star '//trim(hier_prefix)//' substituted yet.' + ierr = ierr_subststar + endif + subst_index = int(data(i,1)) + data(i,1) = 0 + + if (subst>0) then + rel_posang_ascnode = data(i, 10) + + if (rel_posang_ascnode /= 0) then + print "(1x,a)",'ERROR: set_multiple: at the moment phantom can subst only Omega=0 binaries.' + ierr = ierr_Omegasubst + endif + + rel_arg_peri= data(i, 9) + rel_incl = data(i, 8) + else + rel_posang_ascnode = posang_ascnode + rel_arg_peri = arg_peri + rel_incl = incl endif - rel_arg_peri= data(i, 9) - rel_incl = data(i, 8) - else - rel_posang_ascnode = posang_ascnode - rel_arg_peri = arg_peri - rel_incl = incl - endif + mtot = data(i, 3) + m_comp = data(i, 4) + a_comp = data(i, 5) + e_comp = data(i, 6) - mtot = data(i, 3) - m_comp = data(i, 4) - a_comp = data(i, 5) - e_comp = data(i, 6) + q_comp = mtot/m_comp + if (q_comp>1) q_comp=q_comp**(-1) - q_comp = mtot/m_comp - if (q_comp>1) q_comp=q_comp**(-1) + ! Mardling & Aarseth (2001) criterion check + period_ratio = sqrt((a_comp*a_comp*a_comp)/(m_comp+mtot)/& + (semimajoraxis*semimajoraxis*semimajoraxis)*(mtot)) ! Po/Pi + criterion = 4.7*(1-e_comp)**(-1.8)*(1+e_comp)**(0.6)*(1+q_comp)**(0.1) - ! Mardling&Aarseth (2001) criterion check + if (criterion > period_ratio) then + print "(1x,a)",'WARNING: set_multiple: orbital parameters do not satisfy '//& + 'Mardling & Aarseth stability criterion.' + endif - period_ratio = sqrt((a_comp*a_comp*a_comp)/(m_comp+mtot)/(semimajoraxis*semimajoraxis*semimajoraxis)*(mtot)) ! Po/Pi - criterion = 4.7*(1-e_comp)**(-1.8)*(1+e_comp)**(0.6)*(1+q_comp)**(0.1) + q2=m2/m1 + mprimary = mtot/(1+q2) + msecondary = mtot*q2/(1+q2) - if (criterion > period_ratio) then - print "(1x,a)",'WARNING: set_multiple: orbital parameters does not satisfy Mardling and Aarseth stability criterion.' + io=1 + exit endif + enddo - q2=m2/m1 - mprimary = mtot/(1+q2) - msecondary = mtot*q2/(1+q2) + if (io == 0) then + print "(1x,a)",'ERROR: set_multiple: star '//trim(hier_prefix)//' not present in HIERARCHY file.' + ierr = ierr_missstar + endif - io=1 - exit + if (subst_index > 0 .and. subst_index <= size(xyzmh_ptmass(1,:))) then ! check for seg fault + x_subst(:)=xyzmh_ptmass(1:3,subst_index) + v_subst(:)=vxyz_ptmass(:,subst_index) endif - enddo + !i1 = subst_index + !i2 = nptmass + 1 + !nptmass = nptmass + 1 - if (io == 0) then - print "(1x,a)",'ERROR: set_multiple: star '//trim(hier_prefix)//' not present in HIERARCHY file.' - ierr = ierr_missstar + period = sqrt(4.*pi**2*semimajoraxis**3/mtot) endif - - if (subst_index > 0 .and. subst_index <= size(xyzmh_ptmass(1,:))) then ! check for seg fault - x_subst(:)=xyzmh_ptmass(1:3,subst_index) - v_subst(:)=vxyz_ptmass(:,subst_index) - endif - !i1 = subst_index - !i2 = nptmass + 1 - !nptmass = nptmass + 1 - - period = sqrt(4.*pi**2*semimajoraxis**3/mtot) else mprimary = m1 msecondary = m2 @@ -620,111 +625,113 @@ subroutine set_multiple(m1,m2,semimajoraxis,eccentricity, & f=f,accretion_radius1=accretion_radius1,accretion_radius2=accretion_radius2, & xyzmh_ptmass=xyzmh_ptmass,vxyz_ptmass=vxyz_ptmass,nptmass=nptmass, ierr=ierr) - if (present(subst) .and. subst>10) then - !--- lower nptmass, copy one of the new sinks to the subst star - nptmass = nptmass-1 - i1 = subst_index - i2 = nptmass + if (present(subst)) then + if (subst>10) then + !--- lower nptmass, copy one of the new sinks to the subst star + nptmass = nptmass-1 + i1 = subst_index + i2 = nptmass - ! positions and accretion radii - xyzmh_ptmass(1:6,i1) = xyzmh_ptmass(1:6,nptmass+1) + ! positions and accretion radii + xyzmh_ptmass(1:6,i1) = xyzmh_ptmass(1:6,nptmass+1) - ! test Jolien + ! test Jolien ! print "(5(2x,a,g12.3,/),2x,a,g12.3)", & ! 'i1 :',i1, & ! 'mass i1:',xyzmh_ptmass(4,i1), & ! 'i2 :',i2, & ! 'mass i2:',xyzmh_ptmass(4,i2) - ! velocities - vxyz_ptmass(:,i1) = vxyz_ptmass(:,nptmass+1) - - !--- - ! Rotate the substituting binary with orientational parameters - ! referring to the substituted star's orbital plane - if (subst>0) then - - omega = rel_arg_peri*pi/180. - !big_omega = rel_posang_ascnode*pi/180.! + 0.5*pi - inc = rel_incl*pi/180. - - ! Retrieve eulerian angles of the substituted star orbit's semi-major axis (y axis) - if (omega <= pi/2) then - beta_y = omega - sign_alpha=-1 - if (inc <= pi) then - sign_gamma=1 + ! velocities + vxyz_ptmass(:,i1) = vxyz_ptmass(:,nptmass+1) + + !--- + ! Rotate the substituting binary with orientational parameters + ! referring to the substituted star's orbital plane + if (subst>0) then + + omega = rel_arg_peri*pi/180. + !big_omega = rel_posang_ascnode*pi/180.! + 0.5*pi + inc = rel_incl*pi/180. + + ! Retrieve eulerian angles of the substituted star orbit's semi-major axis (y axis) + if (omega <= pi/2) then + beta_y = omega + sign_alpha=-1 + if (inc <= pi) then + sign_gamma=1 + else + sign_gamma=-1 + endif else - sign_gamma=-1 + beta_y = 2*pi-omega + sign_alpha=1 + if (inc <= pi) then + sign_gamma=-1 + else + sign_gamma=1 + endif endif - else - beta_y = 2*pi-omega - sign_alpha=1 + gamma_y=acos(sign_gamma*sin(beta_y)*sin(inc)) + alpha_y=acos(sign_alpha*sqrt(abs(sin(beta_y)**2-cos(gamma_y)**2))) ! Needs abs cause float approx for cos + + ! Retrieve eulerian angles of the axis perpendicular to the substituted star orbital plane (z axis) + beta_z = pi/2. + gamma_z = inc + alpha_z = pi/2. - inc if (inc <= pi) then - sign_gamma=-1 - else - sign_gamma=1 + gamma_z=inc + if (inc <= pi/2.) then + alpha_z = pi/2.-inc + elseif (inc > pi/2.) then + alpha_z = inc-pi/2. + endif + elseif (inc < 2.*pi .and. inc > pi) then + gamma_z = 2.*pi-inc + if (inc <= 3.*pi/2.) then + alpha_z = inc-pi/2 + elseif (inc > 3.*pi/2.) then + alpha_z = 5.*pi/2.-inc + endif endif - endif - gamma_y=acos(sign_gamma*sin(beta_y)*sin(inc)) - alpha_y=acos(sign_alpha*sqrt(abs(sin(beta_y)**2-cos(gamma_y)**2))) ! Needs abs cause float approx for cos - ! Retrieve eulerian angles of the axis perpendicular to the substituted star orbital plane (z axis) - beta_z = pi/2. - gamma_z = inc - alpha_z = pi/2. - inc - if (inc <= pi) then - gamma_z=inc - if (inc <= pi/2.) then - alpha_z = pi/2.-inc - elseif (inc > pi/2.) then - alpha_z = inc-pi/2. - endif - elseif (inc < 2.*pi .and. inc > pi) then - gamma_z = 2.*pi-inc - if (inc <= 3.*pi/2.) then - alpha_z = inc-pi/2 - elseif (inc > 3.*pi/2.) then - alpha_z = 5.*pi/2.-inc - endif + ! Rotate substituting sinks by argument of pericenter around the z axis + call gen_rotate(xyzmh_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, arg_peri*pi/180) + call gen_rotate(vxyz_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, arg_peri*pi/180) + call gen_rotate(xyzmh_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, arg_peri*pi/180) + call gen_rotate(vxyz_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, arg_peri*pi/180) + + ! Rotate substituting sinks by inclination around the y axis + call gen_rotate(xyzmh_ptmass(1:3,i1),alpha_y,beta_y,gamma_y, incl*pi/180) + call gen_rotate(vxyz_ptmass(1:3,i1),alpha_y,beta_y,gamma_y, incl*pi/180) + call gen_rotate(xyzmh_ptmass(1:3,i2),alpha_y,beta_y,gamma_y, incl*pi/180) + call gen_rotate(vxyz_ptmass(1:3,i2),alpha_y,beta_y,gamma_y, incl*pi/180) + + ! Rotate substituting sinks by ascending node longitude around the z axis + call gen_rotate(xyzmh_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) + call gen_rotate(vxyz_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) + call gen_rotate(xyzmh_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) + call gen_rotate(vxyz_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) endif - ! Rotate substituting sinks by argument of pericenter around the z axis - call gen_rotate(xyzmh_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, arg_peri*pi/180) - call gen_rotate(vxyz_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, arg_peri*pi/180) - call gen_rotate(xyzmh_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, arg_peri*pi/180) - call gen_rotate(vxyz_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, arg_peri*pi/180) - - ! Rotate substituting sinks by inclination around the y axis - call gen_rotate(xyzmh_ptmass(1:3,i1),alpha_y,beta_y,gamma_y, incl*pi/180) - call gen_rotate(vxyz_ptmass(1:3,i1),alpha_y,beta_y,gamma_y, incl*pi/180) - call gen_rotate(xyzmh_ptmass(1:3,i2),alpha_y,beta_y,gamma_y, incl*pi/180) - call gen_rotate(vxyz_ptmass(1:3,i2),alpha_y,beta_y,gamma_y, incl*pi/180) - - ! Rotate substituting sinks by ascending node longitude around the z axis - call gen_rotate(xyzmh_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) - call gen_rotate(vxyz_ptmass(1:3,i1),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) - call gen_rotate(xyzmh_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) - call gen_rotate(vxyz_ptmass(1:3,i2),alpha_z,beta_z,gamma_z, posang_ascnode*pi/180) - endif - - ! Move the substituting binary's center of mass in the substituted star position - xyzmh_ptmass(1:3,i1) = xyzmh_ptmass(1:3,i1)+x_subst - xyzmh_ptmass(1:3,i2) = xyzmh_ptmass(1:3,i2)+x_subst - ! Set the substituting binary's center of mass velocity - vxyz_ptmass(:,i1) = vxyz_ptmass(:,i1)+v_subst - vxyz_ptmass(:,i2) = vxyz_ptmass(:,i2)+v_subst - - ! Write updated HIERARCHY file with the two new stars and the substituted one - open(1, file = trim(filename), status = 'old') - do i=1,lines - write(1,*) int(data(i,1)), int(data(i,2)), data(i,3:) - enddo - write(1,*) i1, trim(hier_prefix)//"1", mprimary, msecondary, semimajoraxis, eccentricity, & + ! Move the substituting binary's center of mass in the substituted star position + xyzmh_ptmass(1:3,i1) = xyzmh_ptmass(1:3,i1)+x_subst + xyzmh_ptmass(1:3,i2) = xyzmh_ptmass(1:3,i2)+x_subst + ! Set the substituting binary's center of mass velocity + vxyz_ptmass(:,i1) = vxyz_ptmass(:,i1)+v_subst + vxyz_ptmass(:,i2) = vxyz_ptmass(:,i2)+v_subst + + ! Write updated HIERARCHY file with the two new stars and the substituted one + open(1,file=trim(filename),status='old') + do i=1,lines + write(1,*) int(data(i,1)), int(data(i,2)), data(i,3:) + enddo + write(1,*) i1, trim(hier_prefix)//"1", mprimary, msecondary, semimajoraxis, eccentricity, & period, incl, arg_peri, posang_ascnode - write(1,*) i2, trim(hier_prefix)//"2", msecondary, mprimary, semimajoraxis, eccentricity, & + write(1,*) i2, trim(hier_prefix)//"2", msecondary, mprimary, semimajoraxis, eccentricity, & period, incl, arg_peri, posang_ascnode - close(1) + close(1) + endif endif end subroutine set_multiple diff --git a/src/setup/set_hierarchical_utils.f90 b/src/setup/set_hierarchical_utils.f90 index 50aa1866e..6921d5daa 100644 --- a/src/setup/set_hierarchical_utils.f90 +++ b/src/setup/set_hierarchical_utils.f90 @@ -247,10 +247,10 @@ subroutine load_hierarchy_file(prefix, data, lines, ierr) inquire(file=trim(filename), exist=iexist) if (iexist) then - open(2, file = trim(filename), status = 'old') + open(2,file=trim(filename),status='old') lines=0 do - read(2, *, iostat=io) data(lines+1,:) + read(2, *,iostat=io) data(lines+1,:) if (io/=0) exit lines = lines + 1 enddo @@ -301,7 +301,7 @@ subroutine update_hierarchy_file(prefix, hs, data, lines, hier_prefix, i1, i2, i endif if (lines > 0) then - open(newunit=iu, file = trim(filename), status = 'old') + open(newunit=iu,file=trim(filename),status='old') do i=1,lines write(iu,*) int(data(i,1)), int(data(i,2)), data(i,3:) enddo @@ -309,7 +309,7 @@ subroutine update_hierarchy_file(prefix, hs, data, lines, hier_prefix, i1, i2, i inquire(file=trim(filename), exist=iexist) if (iexist) print "(1x,a)",'WARNING: set_multiple: deleting an existing HIERARCHY file.' - open(newunit=iu, file = trim(filename), status = 'replace') + open(newunit=iu,file=trim(filename),status='replace') endif write(iu,*) i1, trim(hier_prefix)//"1", mprimary, msecondary, semimajoraxis, eccentricity, & period, incl, arg_peri, posang_ascnode @@ -462,7 +462,7 @@ subroutine find_hierarchy_index(level, int_sinks, inner_sinks_num, prefix) character(len=10) :: label = ' ' - read(level, *, iostat=io) h_index + read(level, *,iostat=io) h_index call load_hierarchy_file(prefix, data, lines, ierr) diff --git a/src/setup/set_orbit.f90 b/src/setup/set_orbit.f90 index 6940ad2aa..23a25885d 100644 --- a/src/setup/set_orbit.f90 +++ b/src/setup/set_orbit.f90 @@ -29,6 +29,21 @@ module setorbit ! :Dependencies: infile_utils, physcon, setbinary, setflyby, units ! +! While Campbell elements can be used for unbound orbits, they require +! specifying the true anomaly at the start of the simulation. This is +! not always easy to determine, so the flyby option is provided as an +! alternative. There one specifies the initial separation instead, however +! the choice of angles is more restricted +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: infile_utils, physcon, setbinary, setflyby, units +! + ! While Campbell elements can be used for unbound orbits, they require ! specifying the true anomaly at the start of the simulation. This is ! not always easy to determine, so the flyby option is provided as an diff --git a/src/setup/set_star.f90 b/src/setup/set_star.f90 index fa316c63f..cea8982c8 100644 --- a/src/setup/set_star.f90 +++ b/src/setup/set_star.f90 @@ -15,7 +15,9 @@ module setstar ! ! :Owner: Daniel Price ! -! :Runtime parameters: None +! :Runtime parameters: +! - nstars : *number of stars to add (0-'//achar(size(star)+48)//')* +! - relax : *relax stars into equilibrium* ! ! :Dependencies: centreofmass, dim, eos, extern_densprofile, infile_utils, ! io, mpiutils, part, physcon, prompting, radiation_utils, relaxstar, @@ -50,11 +52,18 @@ module setstar end type star_t public :: star_t - public :: set_star,set_defaults_star,shift_star - public :: write_options_star,read_options_star,set_star_interactive + public :: set_star,set_stars + public :: set_defaults_star,set_defaults_stars + public :: shift_star,shift_stars + public :: write_options_star,write_options_stars + public :: read_options_star,read_options_stars + public :: set_star_interactive public :: ikepler,imesa,ibpwpoly,ipoly,iuniform,ifromfile,ievrard public :: need_polyk + integer, parameter :: istar_offset = 3 ! offset for particle type to distinguish particles + ! placed in stars from other particles in the simulation + private contains @@ -91,6 +100,21 @@ subroutine set_defaults_star(star) end subroutine set_defaults_star +!-------------------------------------------------------------------------- +!+ +! same as above but does it for multiple stars +!+ +!-------------------------------------------------------------------------- +subroutine set_defaults_stars(stars) + type(star_t), intent(out) :: stars(:) + integer :: i + + do i=1,size(stars) + call set_defaults_star(stars(i)) + enddo + +end subroutine set_defaults_stars + !-------------------------------------------------------------------------- !+ ! Master routine to setup a star from a specified file or density profile @@ -132,7 +156,7 @@ subroutine set_star(id,master,star,xyzh,vxyzu,eos_vars,rad,& integer, intent(out) :: ierr real, intent(in), optional :: x0(3),v0(3) integer, intent(in), optional :: itype - procedure(mask_prototype) :: mask + procedure(mask_prototype) :: mask integer :: npts,ierr_relax integer :: ncols_compo,npart_old,i real, allocatable :: r(:),den(:),pres(:),temp(:),en(:),mtab(:),Xfrac(:),Yfrac(:),mu(:) @@ -278,7 +302,7 @@ subroutine set_star(id,master,star,xyzh,vxyzu,eos_vars,rad,& ! if (present(itype)) then do i=npart_old+1,npart - call set_particle_type(i,itype) + call set_particle_type(i,itype+istar_offset) enddo endif ! @@ -318,6 +342,46 @@ subroutine set_star(id,master,star,xyzh,vxyzu,eos_vars,rad,& end subroutine set_star +!-------------------------------------------------------------------------- +!+ +! As above but loops over all stars +!+ +!-------------------------------------------------------------------------- +subroutine set_stars(id,master,nstars,star,xyzh,vxyzu,eos_vars,rad,& + npart,npartoftype,massoftype,hfact,& + xyzmh_ptmass,vxyz_ptmass,nptmass,ieos,polyk,gamma,X_in,Z_in,& + relax,use_var_comp,write_rho_to_file,& + rhozero,npart_total,mask,ierr) + use unifdis, only:mask_prototype + type(star_t), intent(inout) :: star(:) + integer, intent(in) :: id,master,nstars + integer, intent(inout) :: npart,npartoftype(:),nptmass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:),eos_vars(:,:),rad(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + real, intent(inout) :: massoftype(:) + real, intent(in) :: hfact + logical, intent(in) :: relax,use_var_comp,write_rho_to_file + integer, intent(in) :: ieos + real, intent(inout) :: polyk,gamma + real, intent(in) :: X_in,Z_in + real, intent(out) :: rhozero + integer(kind=8), intent(out) :: npart_total + integer, intent(out) :: ierr + procedure(mask_prototype) :: mask + integer :: i + + do i=1,min(nstars,size(star)) + if (star(i)%iprofile > 0) then + print "(/,a,i0,a)",' --- STAR ',i,' ---' + call set_star(id,master,star(i),xyzh,vxyzu,eos_vars,rad,npart,npartoftype,& + massoftype,hfact,xyzmh_ptmass,vxyz_ptmass,nptmass,ieos,polyk,gamma,& + X_in,Z_in,relax,use_var_comp,write_rho_to_file,& + rhozero,npart_total,mask,ierr,itype=i) + endif + enddo + +end subroutine set_stars + !----------------------------------------------------------------------- !+ ! shift star to the desired position and velocity @@ -347,13 +411,14 @@ subroutine shift_star(npart,xyz,vxyz,x0,v0,itype,corotate) omega = L/dot_product(rcyl,rcyl) print*,'Adding spin to star: omega = ',omega endif + if (present(itype)) print "(a,i0,a,2(es10.3,','),es10.3,a)",' MOVING STAR ',itype,' to (x,y,z) = (',x0(1:3),')' over_parts: do i=1,npart if (present(itype)) then ! get type of current particle call get_particle_type(i,mytype) ! skip particles that do not match the specified type - if (mytype /= itype) cycle over_parts + if (mytype /= itype+istar_offset) cycle over_parts ! reset type back to gas call set_particle_type(i,igas) endif @@ -367,6 +432,39 @@ subroutine shift_star(npart,xyz,vxyz,x0,v0,itype,corotate) end subroutine shift_star +!----------------------------------------------------------------------- +!+ +! As above but shifts all stars to desired positions and velocities +!+ +!----------------------------------------------------------------------- +subroutine shift_stars(nstar,star,xyzmh_ptmass_in,vxyz_ptmass_in,& + xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,npart,nptmass,corotate) + integer, intent(in) :: nstar,npart + type(star_t), intent(in) :: star(nstar) + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + real, intent(in) :: xyzmh_ptmass_in(:,:),vxyz_ptmass_in(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + integer, intent(inout) :: nptmass + logical, intent(in), optional :: corotate + integer :: i + logical :: do_corotate + + do_corotate = .false. + if (present(corotate)) do_corotate = corotate + + do i=1,min(nstar,size(xyzmh_ptmass_in(1,:))) + if (star(i)%iprofile > 0) then + call shift_star(npart,xyzh,vxyzu,x0=xyzmh_ptmass_in(1:3,i),& + v0=vxyz_ptmass_in(1:3,i),itype=i,corotate=do_corotate) + else + nptmass = nptmass + 1 + xyzmh_ptmass(:,nptmass) = xyzmh_ptmass_in(:,i) + vxyz_ptmass(:,nptmass) = vxyz_ptmass_in(:,i) + endif + enddo + +end subroutine shift_stars + !----------------------------------------------------------------------- !+ ! print a distance in both code units and physical units @@ -674,6 +772,7 @@ subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) character(len=*), intent(in), optional :: label character(len=10) :: c real :: mcore_msun,rcore_rsun,lcore_lsun,mstar_msun,rstar_rsun,hsoft_rsun + integer :: ierr ! set defaults call set_defaults_star(star) @@ -703,18 +802,18 @@ subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) call read_inopt(star%isinkcore,'isinkcore'//trim(c),db,errcount=nerr) if (star%isinkcore) then - call read_inopt(lcore_lsun,'lcore'//trim(c),db,errcount=nerr,min=0.) - star%lcore = lcore_lsun*real(solarl/unit_luminosity) + call read_inopt(lcore_lsun,'lcore'//trim(c),db,errcount=nerr,min=0.,err=ierr) + if (ierr==0) star%lcore = lcore_lsun*real(solarl/unit_luminosity) endif call read_inopt(star%isoftcore,'isoftcore'//trim(c),db,errcount=nerr,min=0) if (star%isoftcore <= 0) then ! sink particle core without softening if (star%isinkcore) then - call read_inopt(mcore_msun,'mcore'//trim(c),db,errcount=nerr,min=0.) - star%mcore = mcore_msun*real(solarm/umass) - call read_inopt(hsoft_rsun,'hsoft'//trim(c),db,errcount=nerr,min=0.) - star%hsoft = hsoft_rsun*real(solarr/udist) + call read_inopt(mcore_msun,'mcore'//trim(c),db,errcount=nerr,min=0.,err=ierr) + if (ierr==0) star%mcore = mcore_msun*real(solarm/umass) + call read_inopt(hsoft_rsun,'hsoft'//trim(c),db,errcount=nerr,min=0.,err=ierr) + if (ierr==0) star%hsoft = hsoft_rsun*real(solarr/udist) endif else call read_inopt(star%outputfilename,'outputfilename'//trim(c),db,errcount=nerr) @@ -725,13 +824,13 @@ subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) endif if ((star%isofteningopt==1) .or. (star%isofteningopt==3)) then - call read_inopt(rcore_rsun,'rcore'//trim(c),db,errcount=nerr,min=0.) - star%rcore = rcore_rsun*real(solarr/udist) + call read_inopt(rcore_rsun,'rcore'//trim(c),db,errcount=nerr,min=0.,err=ierr) + if (ierr==0) star%rcore = rcore_rsun*real(solarr/udist) endif if ((star%isofteningopt==2) .or. (star%isofteningopt==3) & .or. (star%isoftcore==2)) then - call read_inopt(mcore_msun,'mcore'//trim(c),db,errcount=nerr,min=0.) - star%mcore = mcore_msun*real(solarm/umass) + call read_inopt(mcore_msun,'mcore'//trim(c),db,errcount=nerr,min=0.,err=ierr) + if (ierr==0) star%mcore = mcore_msun*real(solarm/umass) endif endif case(ievrard) @@ -745,15 +844,94 @@ subroutine read_options_star(star,need_iso,ieos,polyk,db,nerr,label) if (need_inputprofile(star%iprofile)) then call read_inopt(star%input_profile,'input_profile'//trim(c),db,errcount=nerr) else - call read_inopt(mstar_msun,'Mstar'//trim(c),db,errcount=nerr,min=0.) - star%mstar = mstar_msun*real(solarm/umass) + call read_inopt(mstar_msun,'Mstar'//trim(c),db,errcount=nerr,min=0.,err=ierr) + if (ierr==0) star%mstar = mstar_msun*real(solarm/umass) if (need_rstar(star%iprofile)) then - call read_inopt(rstar_rsun,'Rstar'//trim(c),db,errcount=nerr,min=0.) - star%rstar = rstar_rsun*real(solarr/udist) + call read_inopt(rstar_rsun,'Rstar'//trim(c),db,errcount=nerr,min=0.,err=ierr) + if (ierr==0) star%rstar = rstar_rsun*real(solarr/udist) endif endif endif end subroutine read_options_star +!----------------------------------------------------------------------- +!+ +! write_options routine that writes options for multiple stars +!+ +!----------------------------------------------------------------------- +subroutine write_options_stars(star,relax,iunit,nstar) + use relaxstar, only:write_options_relax + use infile_utils, only:write_inopt + type(star_t), intent(in) :: star(:) + integer, intent(in) :: iunit + logical, intent(in) :: relax + integer, intent(in), optional :: nstar + integer :: i,nstars + + ! optionally ask for number of stars, otherwise fix nstars to the input array size + if (present(nstar)) then + call write_inopt(nstar,'nstars','number of stars to add (0-'//achar(size(star)+48)//')',iunit) + nstars = nstar + else + nstars = size(star) + endif + + ! write options for each star + do i=1,nstars + call write_options_star(star(i),iunit,label=achar(i+48)) + enddo + + ! write relaxation options if any stars are made of gas + if (nstars > 0) then + if (any(star(1:nstars)%iprofile > 0)) then + write(iunit,"(/,a)") '# relaxation options' + call write_inopt(relax,'relax','relax stars into equilibrium',iunit) + call write_options_relax(iunit) + endif + endif + +end subroutine write_options_stars + +!----------------------------------------------------------------------- +!+ +! read_options routine that reads options for multiple stars +!+ +!----------------------------------------------------------------------- +subroutine read_options_stars(star,need_iso,ieos,polyk,relax,db,nerr,nstar) + use relaxstar, only:read_options_relax + use infile_utils, only:inopts,read_inopt + type(star_t), intent(out) :: star(:) + type(inopts), allocatable, intent(inout) :: db(:) + integer, intent(out) :: need_iso + integer, intent(inout) :: ieos + real, intent(inout) :: polyk + logical, intent(out) :: relax + integer, intent(inout) :: nerr + integer, intent(out), optional :: nstar + integer :: i,nstars + + ! optionally ask for number of stars + if (present(nstar)) then + call read_inopt(nstar,'nstars',db,nerr,min=0,max=size(star)) + nstars = nstar + else + nstars = size(star) + endif + + ! read options for each star + do i=1,nstars + call read_options_star(star(i),need_iso,ieos,polyk,db,nerr,label=achar(i+48)) + enddo + + ! read relaxation options if any stars are made of gas + if (nstars > 0) then + if (any(star(1:nstars)%iprofile > 0)) then + call read_inopt(relax,'relax',db,errcount=nerr) + call read_options_relax(db,nerr) + endif + endif + +end subroutine read_options_stars + end module setstar diff --git a/src/setup/set_unifdis.f90 b/src/setup/set_unifdis.f90 index b4dece1de..782d6c3af 100644 --- a/src/setup/set_unifdis.f90 +++ b/src/setup/set_unifdis.f90 @@ -56,7 +56,6 @@ subroutine set_unifdis(lattice,id,master,xmin,xmax,ymin,ymax, & nptot,npy,npz,npnew_in,rhofunc,massfunc,inputiseed,verbose,centre,dir,geom,mask,err) use random, only:ran2 use stretchmap, only:set_density_profile - !use mpidomain, only:i_belong character(len=*), intent(in) :: lattice integer, intent(in) :: id,master integer, intent(inout) :: np diff --git a/src/setup/setup_binary.f90 b/src/setup/setup_binary.f90 index 28a0efac9..0b6c87bd5 100644 --- a/src/setup/setup_binary.f90 +++ b/src/setup/setup_binary.f90 @@ -13,28 +13,21 @@ module setup ! :Owner: Daniel Price ! ! :Runtime parameters: -! - O : *position angle of ascending node (deg)* -! - a : *semi-major axis (e.g. 1 au), period (e.g. 10*days) or rp if e=1* -! - corotate : *set stars in corotation* -! - eccentricity : *eccentricity* -! - f : *initial true anomaly (180=apoastron)* -! - inc : *inclination (deg)* -! - relax : *relax stars into equilibrium* -! - w : *argument of periapsis (deg)* +! - corotate : *set stars in corotation* ! ! :Dependencies: centreofmass, dim, eos, externalforces, infile_utils, io, -! mpidomain, options, part, physcon, relaxstar, setbinary, setstar, -! setunits, setup_params, units +! kernel, mpidomain, options, part, physcon, setorbit, setstar, setunits, +! setup_params ! - use setstar, only:star_t + use setstar, only:star_t + use setorbit, only:orbit_t use dim, only:gr implicit none public :: setpart - real :: a,ecc,inc,O,w,f logical :: relax,corotate - type(star_t) :: star(2) - character(len=20) :: semi_major_axis + type(star_t) :: star(2) + type(orbit_t) :: orbit private @@ -49,19 +42,18 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& polyk,gamma,hfact,time,fileprefix) use part, only:gr,nptmass,xyzmh_ptmass,vxyz_ptmass,& ihacc,ihsoft,eos_vars,rad,nsinkproperties,iJ2,iReff,ispinx,ispinz - use setbinary, only:set_binary,get_a_from_period - use units, only:is_time_unit,in_code_units,utime - use physcon, only:solarm,au,pi,solarr,days + use setorbit, only:set_defaults_orbit,set_orbit use options, only:iexternalforce use externalforces, only:iext_corotate,iext_geopot,iext_star,omega_corotate,mass1,accradius1 use io, only:master,fatal - use setstar, only:set_star,set_defaults_star,shift_star + use setstar, only:set_defaults_stars,set_stars,shift_stars use eos, only:X_in,Z_in,ieos use setup_params, only:rhozero,npart_total use mpidomain, only:i_belong use centreofmass, only:reset_centreofmass use setunits, only:mass_unit,dist_unit use physcon, only:deg_to_rad + use kernel, only:hfact_default integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -72,9 +64,10 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& character(len=20), intent(in) :: fileprefix real, intent(out) :: vxyzu(:,:) character(len=120) :: filename - integer :: ierr,i,nstar,nptmass_in,iextern_prev + integer :: ierr,nstar,nptmass_in,iextern_prev logical :: iexist,write_profile,use_var_comp,add_spin real :: xyzmh_ptmass_in(nsinkproperties,2),vxyz_ptmass_in(3,2),angle + logical, parameter :: set_oblateness = .false. ! !--general parameters ! @@ -83,6 +76,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& time = 0. polyk = 0. gamma = 1. + hfact = hfact_default ! !--space available for injected gas particles ! in case only sink particles are used @@ -95,18 +89,10 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& vxyzu(:,:) = 0. nptmass = 0 nstar = 2 - do i=1,nstar - call set_defaults_star(star(i)) - enddo + call set_defaults_stars(star) + call set_defaults_orbit(orbit) relax = .true. corotate = .false. - semi_major_axis = '10.' - a = 10. - ecc = 0. - inc = 0. - O = 0. - w = 270. - f = 180. ieos = 2 if (id==master) print "(/,65('-'),1(/,a),/,65('-'),/)",& @@ -130,54 +116,27 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& iextern_prev = iexternalforce iexternalforce = 0 gamma = 5./3. - do i=1,nstar - if (star(i)%iprofile > 0) then - print "(/,a,i0,a)",' --- STAR ',i,' ---' - call set_star(id,master,star(i),xyzh,vxyzu,eos_vars,rad,npart,npartoftype,& - massoftype,hfact,xyzmh_ptmass,vxyz_ptmass,nptmass,ieos,polyk,gamma,& - X_in,Z_in,relax,use_var_comp,write_profile,& - rhozero,npart_total,i_belong,ierr,itype=i) - endif - enddo + call set_stars(id,master,nstar,star,xyzh,vxyzu,eos_vars,rad,npart,npartoftype,& + massoftype,hfact,xyzmh_ptmass,vxyz_ptmass,nptmass,ieos,polyk,gamma,& + X_in,Z_in,relax,use_var_comp,write_profile,& + rhozero,npart_total,i_belong,ierr) - ! - !--if a is negative or is given time units, interpret this as a period - ! - a = in_code_units(semi_major_axis,ierr) - if (is_time_unit(semi_major_axis) .and. ierr == 0) then - a = -abs(a) - print "(a,g0,a,g0,a)",' Using PERIOD = ',abs(a),' = ',abs(a)*utime/days,' days' - endif - if (a < 0.) a = get_a_from_period(star(1)%mstar,star(2)%mstar,abs(a)) - ! - !--now setup orbit using fake sink particles - ! nptmass_in = 0 - if (iexternalforce==iext_corotate) then - call set_binary(star(1)%mstar,star(2)%mstar,a,ecc,star(1)%hacc,star(2)%hacc,& - xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,ierr,omega_corotate,& - posang_ascnode=O,arg_peri=w,incl=inc,f=f,verbose=(id==master)) - add_spin = .false. ! already in corotating frame + if (iextern_prev==iext_corotate) then + call set_orbit(orbit,star(1)%mstar,star(2)%mstar,star(1)%hacc,star(2)%hacc,& + xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,(id==master),ierr,omega_corotate) + add_spin = .false. else - call set_binary(star(1)%mstar,star(2)%mstar,a,ecc,star(1)%hacc,star(2)%hacc,& - xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,ierr,& - posang_ascnode=O,arg_peri=w,incl=inc,f=f,verbose=(id==master)) + call set_orbit(orbit,star(1)%mstar,star(2)%mstar,star(1)%hacc,star(2)%hacc,& + xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,(id==master),ierr) add_spin = corotate endif - if (ierr /= 0) call fatal ('setup_binary','error in call to set_binary') + if (ierr /= 0) call fatal ('setup_binary','error in call to set_orbit') ! !--place stars into orbit, or add real sink particles if iprofile=0 ! - do i=1,nstar - if (star(i)%iprofile > 0) then - call shift_star(npart,xyzh,vxyzu,x0=xyzmh_ptmass_in(1:3,i),& - v0=vxyz_ptmass_in(1:3,i),itype=i,corotate=add_spin) - else - nptmass = nptmass + 1 - xyzmh_ptmass(:,nptmass) = xyzmh_ptmass_in(:,i) - vxyz_ptmass(:,nptmass) = vxyz_ptmass_in(:,i) - endif - enddo + call shift_stars(nstar,star,xyzmh_ptmass_in,vxyz_ptmass_in,xyzh,vxyzu,& + xyzmh_ptmass,vxyz_ptmass,npart,nptmass,corotate=add_spin) ! !--restore options ! @@ -192,7 +151,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,& accradius1 = xyzmh_ptmass(ihacc,nptmass+1) xyzmh_ptmass(:,nptmass) = xyzmh_ptmass(:,nptmass+1) vxyz_ptmass(:,nptmass) = vxyz_ptmass(:,nptmass+1) - else + elseif (set_oblateness) then ! set J2 for sink particle 1 to be equal to oblateness of Saturn xyzmh_ptmass(iJ2,1) = 0.01629 angle = 30.*deg_to_rad @@ -210,8 +169,8 @@ end subroutine setpart !---------------------------------------------------------------- subroutine write_setupfile(filename) use infile_utils, only:write_inopt - use setstar, only:write_options_star - use relaxstar, only:write_options_relax + use setstar, only:write_options_stars + use setorbit, only:write_options_orbit use setunits, only:write_options_units character(len=*), intent(in) :: filename integer :: iunit @@ -221,23 +180,9 @@ subroutine write_setupfile(filename) write(iunit,"(a)") '# input file for binary setup routines' call write_options_units(iunit,gr) - call write_options_star(star(1),iunit,label='1') - call write_options_star(star(2),iunit,label='2') - - write(iunit,"(/,a)") '# orbit settings' - call write_inopt(semi_major_axis,'a','semi-major axis (e.g. 1 au), period (e.g. 10*days) or rp if e=1',iunit) - call write_inopt(ecc,'ecc','eccentricity',iunit) - call write_inopt(inc,'inc','inclination (deg)',iunit) - call write_inopt(O,'O','position angle of ascending node (deg)',iunit) - call write_inopt(w,'w','argument of periapsis (deg)',iunit) - call write_inopt(f,'f','initial true anomaly (180=apoastron)',iunit) + call write_options_stars(star,relax,iunit) call write_inopt(corotate,'corotate','set stars in corotation',iunit) - - if (any(star(:)%iprofile > 0)) then - write(iunit,"(/,a)") '# relaxation options' - call write_inopt(relax,'relax','relax stars into equilibrium',iunit) - call write_options_relax(iunit) - endif + call write_options_orbit(orbit,iunit) close(iunit) end subroutine write_setupfile @@ -250,8 +195,8 @@ end subroutine write_setupfile subroutine read_setupfile(filename,ieos,polyk,ierr) use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db use io, only:error,fatal - use setstar, only:read_options_star - use relaxstar, only:read_options_relax + use setstar, only:read_options_stars + use setorbit, only:read_options_orbit use setunits, only:read_options_and_set_units character(len=*), intent(in) :: filename integer, intent(inout) :: ieos @@ -265,25 +210,12 @@ subroutine read_setupfile(filename,ieos,polyk,ierr) ierr = 0 call open_db_from_file(db,filename,iunit,ierr) call read_options_and_set_units(db,nerr,gr) - call read_options_star(star(1),need_iso,ieos,polyk,db,nerr,label='1') - call read_options_star(star(2),need_iso,ieos,polyk,db,nerr,label='2') + call read_options_stars(star,need_iso,ieos,polyk,relax,db,nerr) if (need_iso==1) call fatal('setup_binary','incompatible setup for eos') - - call read_inopt(semi_major_axis,'a',db,errcount=nerr) - call read_inopt(ecc,'ecc',db,min=0.,errcount=nerr) - call read_inopt(inc,'inc',db,errcount=nerr) - call read_inopt(O,'O',db,errcount=nerr) - call read_inopt(w,'w',db,errcount=nerr) - call read_inopt(f,'f',db,errcount=nerr) - call read_inopt(corotate,'corotate',db,errcount=nerr) - - if (any(star(:)%iprofile > 0)) then - call read_inopt(relax,'relax',db,errcount=nerr) - call read_options_relax(db,nerr) - endif - + call read_options_orbit(orbit,db,nerr) call close_db(db) + if (nerr > 0) then print "(1x,i2,a)",nerr,' error(s) during read of setup file: re-writing...' ierr = nerr diff --git a/src/setup/setup_chinchen.f90 b/src/setup/setup_chinchen.f90 index 708700567..66c97168a 100644 --- a/src/setup/setup_chinchen.f90 +++ b/src/setup/setup_chinchen.f90 @@ -34,7 +34,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use physcon, only:solarm,au,pi use options, only:iexternalforce use externalforces, only:iext_binary - use extern_binary, only:mass2 + use extern_binary, only:mass2,mass1 use io, only:master use timestep, only:dtmax integer, intent(in) :: id @@ -79,7 +79,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, vxyz_ptmass(1,1) = 0.489765446 iexternalforce = iext_binary - mass2 = m1 + mass1 = 0.5 + mass2 = mass1 dtmax = 0.1*(9.*pi) end subroutine setpart diff --git a/src/setup/setup_cluster.f90 b/src/setup/setup_cluster.f90 index cd3e60944..36b0d137d 100644 --- a/src/setup/setup_cluster.f90 +++ b/src/setup/setup_cluster.f90 @@ -112,9 +112,6 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, dist_fac = 1.0 ! distance code unit: dist_fac * pc endif - !--Set units - call set_units(dist=dist_fac*pc,mass=mass_fac*solarm,G=1.) - if (maxvxyzu >= 4) ieos_in = 2 ! Adiabatic equation of state !--Read values from .setup @@ -131,6 +128,9 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call write_setupfile(fileset) endif + !--Set units + call set_units(dist=dist_fac*pc,mass=mass_fac*solarm,G=1.) + !--Define remaining variables using the inputs polyk = kboltz*Temperature/(mu*mass_proton_cgs)*(utime/udist)**2 rmax = Rcloud_pc*(pc/udist) diff --git a/src/setup/setup_galdisc.f90 b/src/setup/setup_galdisc.f90 index e6dbcd55b..37e1ac6c2 100644 --- a/src/setup/setup_galdisc.f90 +++ b/src/setup/setup_galdisc.f90 @@ -175,7 +175,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, totvolH = 4./3.*pi*(5.0*rcyl)**3 !halo galsetupic = 'galsetic.txt' - OPEN(21,file=galsetupic,form='formatted') + open(21,file=galsetupic,form='formatted') do i=1,5 if (i==1) then read(21,*)sometext,npartoftype(igas) @@ -208,7 +208,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--Gas loop totmassG=0. if (yn_gas==1) then - OPEN(24,file='asciifile_G',form='formatted') + open(24,file='asciifile_G',form='formatted') i=1 over_npartG: do while(i <= npartoftype(igas)) read(24,*)xis,yis,zis,mis,vxis,vyis,vzis,phaseis @@ -227,7 +227,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, endif i=i+1 enddo over_npartG - CLOSE(24) + close(24) massoftype(igas) = totmassG/real( npartoftype(igas)) rhozero3 = totmassG/totvol h3 = hfact*(massoftype(igas) /rhozero3)**(1./3.) @@ -245,7 +245,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--Disc loop totmassD=0. if (yn_star==1) then - OPEN(22,file='asciifile_D',form='formatted') + open(22,file='asciifile_D',form='formatted') i= npartoftype(igas) + 1 over_npartS: do while(i <= npartoftype(igas) + npartoftype(istar)) read(22,*)xis,yis,zis,mis,vxis,vyis,vzis,phaseis @@ -264,7 +264,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, endif i=i+1 enddo over_npartS - CLOSE(22) + close(22) massoftype(istar) = totmassD/real( npartoftype(istar)) rhozero1 = totmassD/totvol h1 = hfact*(massoftype(istar)/rhozero1)**(1./3.) @@ -282,7 +282,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--Bulge loop totmassB=0. if (yn_bulge==1) then - OPEN(23,file='asciifile_B',form='formatted') + open(23,file='asciifile_B',form='formatted') i=npartoftype(istar)+npartoftype(igas) + 1 over_npartB: do while(i <=npartoftype(igas)+npartoftype(istar)+npartoftype(ibulge)) read(23,*)xis,yis,zis,mis,vxis,vyis,vzis,phaseis @@ -301,7 +301,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, endif i=i+1 enddo over_npartB - CLOSE(23) + close(23) massoftype(ibulge) = totmassB/real( npartoftype(ibulge)) rhozero2 = totmassB/totvolB h2 = hfact*(massoftype(ibulge)/rhozero2)**(1./3.) @@ -319,7 +319,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, !--Halo loop totmassH=0. if (yn_halo==1) then - OPEN(23,file='asciifile_H',form='formatted') + open(23,file='asciifile_H',form='formatted') i=npartoftype(ibulge)+npartoftype(istar)+npartoftype(igas) + 1 over_npartH: do while(i <=npartoftype(igas)+npartoftype(istar)+npartoftype(ibulge)+npartoftype(idarkmatter)) read(23,*)xis,yis,zis,mis,vxis,vyis,vzis,phaseis @@ -338,7 +338,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, endif i=i+1 enddo over_npartH - CLOSE(23) + close(23) massoftype(idarkmatter) = totmassH/real( npartoftype(idarkmatter)) rhozero4 = totmassH/totvolH h4 = hfact*(massoftype(idarkmatter)/rhozero4)**(1./3.) @@ -422,7 +422,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, h1 = hfact*(massoftype(1)/rhozero)**(1./3.) - if (TRIM(partdist)=='o') then + if (trim(partdist)=='o') then !--Loop for pseudo-random placement (from observed distribution) print "(a)",' Realistic gas distribution requires location of CDF(r) files:' itot=0 diff --git a/src/setup/setup_grdisc.F90 b/src/setup/setup_grdisc.F90 index e6fa50dc4..ed22b212c 100644 --- a/src/setup/setup_grdisc.F90 +++ b/src/setup/setup_grdisc.F90 @@ -29,17 +29,23 @@ module setup ! - spin : *spin parameter of black hole |a|<1* ! - theta : *inclination of disc (degrees)* ! -! :Dependencies: eos, extern_lensethirring, externalforces, infile_utils, -! io, kernel, metric, options, part, physcon, prompting, setdisc, +! :Dependencies: dim, eos, extern_lensethirring, externalforces, +! infile_utils, io, kernel, metric, mpidomain, options, part, physcon, +! prompting, setdisc, setorbit, setstar, setunits, setup_params, ! timestep, units ! - use options, only:alpha + use options, only:alpha + use setstar, only:star_t + use setorbit, only:orbit_t implicit none public :: setpart real, private :: mhole,mdisc,r_in,r_out,r_ref,spin,honr,theta,p_index,q_index,accrad,gamma_ad - integer, private :: np - logical, private :: ismooth + integer, private :: np,nstars + logical, private :: ismooth,relax + integer, parameter :: max_stars = 10 + type(star_t), private :: star(max_stars) + type(orbit_t),private :: orbit(max_stars) private @@ -52,10 +58,10 @@ module setup !---------------------------------------------------------------- subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) use setdisc, only:set_disc - use part, only:igas + use part, only:igas,nsinkproperties,eos_vars,rad,xyzmh_ptmass,vxyz_ptmass,nptmass use io, only:master use externalforces, only:accradius1,accradius1_hard - use options, only:iexternalforce,alphau,iexternalforce + use options, only:iexternalforce,alphau,iexternalforce,ipdv_heating,ishock_heating use units, only:set_units,umass use physcon, only:solarm,pi #ifdef GR @@ -66,8 +72,13 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, #endif use prompting, only:prompt use timestep, only:tmax,dtmax - use eos, only:ieos + use eos, only:ieos,use_var_comp,X_in,Z_in use kernel, only:hfact_default + use setstar, only:shift_star,set_stars + use setorbit, only:set_defaults_orbit,set_orbit + use setunits, only:mass_unit + use mpidomain, only:i_belong + use setup_params, only:rhozero integer, intent(in) :: id integer, intent(out) :: npart integer, intent(out) :: npartoftype(:) @@ -78,13 +89,16 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, real, intent(inout) :: time character(len=20), intent(in) :: fileprefix character(len=120) :: filename - integer :: ierr - logical :: iexist + integer :: ierr,nptmass_in,i + integer(kind=8) :: npart_total + logical :: iexist,write_profile real :: cs2 + real :: xyzmh_ptmass_in(nsinkproperties,2),vxyz_ptmass_in(3,2) time = 0. alphau = 0.0 npartoftype(:) = 0 + nptmass = 0 iexternalforce = 1 hfact = hfact_default @@ -99,7 +113,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ! ! Set default problem parameters ! - + mass_unit = '1e6*solarm' mhole = 1.e6 ! (solarm) mdisc = 10. ! (solarm) r_in = 4. ! (GM/c^2) @@ -112,14 +126,25 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, theta = 3. ! inclination angle (degrees) p_index= 1.5 q_index= 0.75 - gamma_ad= 1.001 + gamma_ad= 5./3. np = 1e6 accrad = 4. ! (GM/c^2) + accradius1 = accrad + gamma = gamma_ad + ! default units + call set_units(G=1.,c=1.,mass=mhole*solarm) ! Set central mass to M=1 in code units + + ! stars + nstars = 0 + do i=1,size(orbit) + call set_defaults_orbit(orbit(i)) + enddo + relax = .true. ! !-- Read runtime parameters from setup file ! - if (id==master) print "(/,65('-'),1(/,a),/,65('-'),/)",'Disc setup' + if (id==master) print "(/,65('-'),(/,1x,a),/,65('-'),/)",'General relativistic disc setup' filename = trim(fileprefix)//'.setup' inquire(file=filename,exist=iexist) if (iexist) call read_setupfile(filename,ierr) @@ -186,7 +211,36 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, npartoftype(1) = npart - return + ! + ! add stars on desired orbits around the black hole, these could be + ! either sink particles or balls of gas + ! + if (nstars > 0) then + write_profile = .false. + call set_stars(id,master,nstars,star,xyzh,vxyzu,eos_vars,rad,npart,npartoftype,& + massoftype,hfact,xyzmh_ptmass,vxyz_ptmass,nptmass,ieos,polyk,gamma,& + X_in,Z_in,relax,use_var_comp,write_profile,& + rhozero,npart_total,i_belong,ierr) + do i=1,nstars + nptmass_in = 0 + call set_orbit(orbit(i),mhole/umass,star(i)%mstar,r_in,star(i)%rstar, & + xyzmh_ptmass_in,vxyz_ptmass_in,nptmass_in,(id==master),ierr) + + ! shift the star to the position of the second body + if (star(i)%iprofile > 0) then + call shift_star(npart,xyzh,vxyzu,x0=xyzmh_ptmass_in(:,2),v0=vxyz_ptmass_in(:,2),itype=i) + else + nptmass = nptmass + 1 + xyzmh_ptmass(:,nptmass) = xyzmh_ptmass_in(:,2) + vxyz_ptmass(:,nptmass) = vxyz_ptmass_in(:,2) + endif + enddo + endif + + ipdv_heating = 0 + ishock_heating = 0 + if (id==master) print "(/,a,/)",' ** SETTING ipdv_heating=0 and ishock_heating=0 for grdisc setup **' + end subroutine setpart @@ -195,12 +249,18 @@ end subroutine setpart ! subroutine write_setupfile(filename) use infile_utils, only:write_inopt + use setstar, only:write_options_stars + use setorbit, only:write_options_orbit + use setunits, only:write_options_units character(len=*), intent(in) :: filename integer, parameter :: iunit = 20 + integer :: i print "(a)",' writing setup options file '//trim(filename) open(unit=iunit,file=filename,status='replace',form='formatted') - write(iunit,"(a)") '# input file for grdisc setup' + call write_options_units(iunit,gr=.true.) + + write(iunit,"(/,a)") '# disc parameters' call write_inopt(mhole ,'mhole' ,'mass of black hole (solar mass)' , iunit) call write_inopt(mdisc ,'mdisc' ,'mass of disc (solar mass)' , iunit) call write_inopt(r_in ,'r_in' ,'inner edge of disc (GM/c^2, code units)' , iunit) @@ -216,6 +276,12 @@ subroutine write_setupfile(filename) call write_inopt(gamma_ad,'gamma' ,'adiabatic gamma' , iunit) call write_inopt(accrad ,'accrad' ,'accretion radius (GM/c^2, code units)' , iunit) call write_inopt(np ,'np' ,'number of particles in disc' , iunit) + + write(iunit,"(/,a)") '# stars' + call write_options_stars(star,relax,iunit,nstar=nstars) + do i=1,nstars + call write_options_orbit(orbit(i),iunit,label=achar(i+48)) + enddo close(iunit) end subroutine write_setupfile @@ -223,16 +289,21 @@ end subroutine write_setupfile subroutine read_setupfile(filename,ierr) use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db use io, only:error + use setstar, only:read_options_stars + use setorbit, only:read_options_orbit + use eos, only:ieos,polyk + use setunits, only:read_options_and_set_units character(len=*), intent(in) :: filename integer, intent(out) :: ierr integer, parameter :: iunit = 21 - integer :: nerr + integer :: nerr,need_iso,i type(inopts), allocatable :: db(:) print "(a)",'reading setup options from '//trim(filename) nerr = 0 ierr = 0 call open_db_from_file(db,filename,iunit,ierr) + call read_options_and_set_units(db,nerr,gr=.true.) call read_inopt(mhole ,'mhole' ,db,min=0.,errcount=nerr) call read_inopt(mdisc ,'mdisc' ,db,min=0.,errcount=nerr) call read_inopt(r_in ,'r_in' ,db,min=0.,errcount=nerr) @@ -248,6 +319,10 @@ subroutine read_setupfile(filename,ierr) call read_inopt(gamma_ad,'gamma' ,db,min=1.,errcount=nerr) call read_inopt(accrad ,'accrad' ,db,min=0.,errcount=nerr) call read_inopt(np ,'np ' ,db,min=0 ,errcount=nerr) + call read_options_stars(star,need_iso,ieos,polyk,relax,db,nerr,nstars) + do i=1,nstars + call read_options_orbit(orbit(i),db,nerr,label=achar(i+48)) + enddo call close_db(db) if (nerr > 0) then print "(1x,i2,a)",nerr,' error(s) during read of setup file: re-writing...' diff --git a/src/setup/setup_grtde.f90 b/src/setup/setup_grtde.f90 index a6d04d9ef..65df28533 100644 --- a/src/setup/setup_grtde.f90 +++ b/src/setup/setup_grtde.f90 @@ -22,8 +22,9 @@ module setup ! - theta : *inclination of orbit (degrees)* ! ! :Dependencies: eos, externalforces, gravwaveutils, infile_utils, io, -! kernel, metric, mpidomain, part, physcon, relaxstar, setbinary, -! setstar, setup_params, timestep, units, vectorutils +! kernel, metric, mpidomain, options, part, physcon, relaxstar, +! setbinary, setstar, setup_params, systemutils, timestep, units, +! vectorutils ! use setstar, only:star_t implicit none @@ -45,7 +46,7 @@ module setup !---------------------------------------------------------------- subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,ihacc,ihsoft,igas,& - gravity,eos_vars,rad + gravity,eos_vars,rad,gr use setbinary, only:set_binary use setstar, only:set_star,shift_star use units, only:set_units,umass,udist @@ -60,6 +61,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, use vectorutils, only:rotatevec use gravwaveutils, only:theta_gw,calc_gravitwaves use setup_params, only:rhozero,npart_total + use systemutils, only:get_command_option + use options, only:iexternalforce integer, intent(in) :: id integer, intent(inout) :: npart integer, intent(out) :: npartoftype(:) @@ -70,7 +73,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, character(len=20), intent(in) :: fileprefix real, intent(out) :: vxyzu(:,:) character(len=120) :: filename - integer :: ierr + integer :: ierr,np_default logical :: iexist,write_profile,use_var_comp real :: rtidal,rp,semia,period,hacc1,hacc2 real :: vxyzstar(3),xyzstar(3) @@ -100,7 +103,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call set_units(mass=mhole*solarm,c=1.d0,G=1.d0) !--Set central mass to M=1 in code units star%mstar = 1.*solarm/umass star%rstar = 1.*solarr/udist - star%np = 1e6 + np_default = 1e6 + star%np = int(get_command_option('np',default=np_default)) ! can set default value with --np=1e5 flag (mainly for testsuite) star%iprofile = 2 beta = 5. ecc = 0.8 @@ -109,7 +113,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, theta = 0. write_profile = .false. use_var_comp = .false. - relax = .false. + relax = .true. ! !-- Read runtime parameters from setup file ! @@ -226,6 +230,8 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, theta_gw = -theta*180./pi endif + if (.not.gr) iexternalforce = 1 + if (npart == 0) call fatal('setup','no particles setup') if (ierr /= 0) call fatal('setup','ERROR during setup') diff --git a/src/utils/analysis_CoM.f90 b/src/utils/analysis_CoM.f90 index 199caa247..b50fa4f5c 100644 --- a/src/utils/analysis_CoM.f90 +++ b/src/utils/analysis_CoM.f90 @@ -40,7 +40,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! ! Open file (appendif exists) ! - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_com.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_com.dat' inquire(file=fileout,exist=iexist) if ( .not.iexist .or. firstcall ) then firstcall = .false. diff --git a/src/utils/analysis_angmom.f90 b/src/utils/analysis_angmom.f90 index f27a87c2c..ce25dbc04 100644 --- a/src/utils/analysis_angmom.f90 +++ b/src/utils/analysis_angmom.f90 @@ -88,7 +88,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) ! Write angular momentum information if (first) then first = .false. - open(newunit=iu, file='angmom.ev',status='replace') + open(newunit=iu,file='angmom.ev',status='replace') write(iu,"('#',5(1x,'[',i2.2,1x,a11,']',2x))") & 1,'time',& 2,'L_{gas}', & @@ -96,7 +96,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) 4,'L_{spin}', & 5,'L_{total}' else - open(newunit=iu, file='angmom.ev',position='append') + open(newunit=iu,file='angmom.ev',position='append') endif write(iu,'(6(es18.10,1X))') time*utime/years,Ltot_mag*unit_angmom,Lsink_mag*unit_angmom,& Lspin_mag*unit_angmom,L_total_mag*unit_angmom diff --git a/src/utils/analysis_angmomvec.f90 b/src/utils/analysis_angmomvec.f90 index 31c6d6c3d..eac98cd34 100644 --- a/src/utils/analysis_angmomvec.f90 +++ b/src/utils/analysis_angmomvec.f90 @@ -42,7 +42,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) ! Write angular momentum vector information if (first) then first = .false. - open(unit=iu, file='angmomvec.ev',status='replace') + open(unit=iu,file='angmomvec.ev',status='replace') write(iu,"('#',6(1x,'[',i2.2,1x,a11,']',2x))") & 1,'time',& 2,'Lx', & @@ -51,7 +51,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) 5,'inc', & 6,'rot' else - open(unit=iu, file='angmomvec.ev',position='append') + open(unit=iu,file='angmomvec.ev',position='append') endif write(iu,'(6(es18.10,1X))') time,Lhat,inc,rot close(iu) diff --git a/src/utils/analysis_average_orb_en.f90 b/src/utils/analysis_average_orb_en.f90 index f9c99a3af..c1c99003e 100644 --- a/src/utils/analysis_average_orb_en.f90 +++ b/src/utils/analysis_average_orb_en.f90 @@ -41,14 +41,14 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) if (first) then first = .false. - open(unit=iu, file='orbitalenergy.ev',status='replace') + open(unit=iu,file='orbitalenergy.ev',status='replace') write(iu,"('#',4(1x,'[',i2.2,1x,a11,']',2x))") & 1,'time',& 2,'ekin',& 3,'epot',& 4,'etot' else - open(unit=iu, file='orbitalenergy.ev',position='append') + open(unit=iu,file='orbitalenergy.ev',position='append') endif write(iu,'(4(es18.10,1X))') time,ekin_av,epot_av,e_av close(iu) diff --git a/src/utils/analysis_bzrms.f90 b/src/utils/analysis_bzrms.f90 index e5b6443e2..d8425a483 100644 --- a/src/utils/analysis_bzrms.f90 +++ b/src/utils/analysis_bzrms.f90 @@ -51,7 +51,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) logical :: iexist ! !--Open file (appendif exists) - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_bzrms.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_bzrms.dat' inquire(file=fileout,exist=iexist) if ( .not.iexist .or. firstcall ) then firstcall = .false. @@ -83,7 +83,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif ! !--Read the setup file to get the values of interest - filename=trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'.setup' + filename=trim(dumpfile(1:index(dumpfile,'_')-1))//'.setup' inquire(file=filename,exist=iexist) if (iexist) then call read_setupfile(filename,mhd) @@ -95,7 +95,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) endif ! !--Get coefficient values from the .in file - filename=trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'.in' + filename=trim(dumpfile(1:index(dumpfile,'_')-1))//'.in' inquire(file=filename,exist=iexist) C_AD = 0.0 C_HE = 0.0 diff --git a/src/utils/analysis_clumpfind.F90 b/src/utils/analysis_clumpfind.F90 index 697a4e1c1..809036724 100644 --- a/src/utils/analysis_clumpfind.F90 +++ b/src/utils/analysis_clumpfind.F90 @@ -121,11 +121,11 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! Check if a neighbour file is present - neighbourfile = 'neigh_'//TRIM(dumpfile) + neighbourfile = 'neigh_'//trim(dumpfile) inquire(file=neighbourfile,exist = existneigh) if (existneigh) then - print*, 'Neighbour file ', TRIM(neighbourfile), ' found' + print*, 'Neighbour file ', trim(neighbourfile), ' found' call read_neighbours(neighbourfile,npart) else ! If there is no neighbour file, generate the list @@ -146,7 +146,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) allocate(dpoten(npart)) ! Holding array for potential (real*8) - dpoten = DBLE(poten) + dpoten = dble(poten) ! Add potential contribution from all sinks first @@ -219,7 +219,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) over_parts: do l = 1,npart - percent = 100.0*REAL(l)/REAL(npart) + percent = 100.0*real(l)/real(npart) if (percent > percentcount) then write(*,'(I3," % complete")') int(percentcount) @@ -377,7 +377,7 @@ subroutine read_analysis_options(dumpfile) if (inputexist) then print '(a,a,a)', "File ",inputfile, " found: reading analysis options" - open(10,file=inputfile, form='formatted') + open(10,file=inputfile,form='formatted') read(10,*) boundchoice read(10,*) sinkchoice read(10,*) skipchoice @@ -413,7 +413,7 @@ subroutine read_analysis_options(dumpfile) if (skipsmalldumps) skipchoice = 'y' ! Write choices to new inputfile - open(10,file=inputfile, status='new', form='formatted') + open(10,file=inputfile,status='new',form='formatted') write(10,*) boundchoice, " Test clumps for gravitational boundness?" write(10,*) sinkchoice, " Include sinks' contribution to potential?" write(10,*) skipchoice, " Skip small dumps (velocity data missing)?" @@ -465,7 +465,7 @@ subroutine amend_options_file(dumpfile) character(len=*),intent(in) :: dumpfile ! Open the options file, and wind forward to the line of interest - open(10,file='clumpfind.options', form='formatted') + open(10,file='clumpfind.options',form='formatted') read(10,*) read(10,*) read(10,*) @@ -979,7 +979,7 @@ subroutine write_clump_data(nclump,deletedclumps,npart,time,dumpfile,tag) clumpfile = trim(tag)//"_clumpcat_"//trim(dumpfile) - open(10,file=clumpfile, status='unknown') + open(10,file=clumpfile,status='unknown') write(10,*) nclump-deletedclumps, time do iclump=1,nclump @@ -1006,7 +1006,7 @@ subroutine write_clump_data(nclump,deletedclumps,npart,time,dumpfile,tag) if (member(i) > 0) member(i) = clump(member(i))%ID enddo - open(10,file=clumpfile, form='unformatted') + open(10,file=clumpfile,form='unformatted') write(10) (member(i), i=1,npart) close(10) @@ -1033,7 +1033,7 @@ subroutine read_oldclump_data(noldclump,npart,oldtime,olddumpfile,tag) clumpfile = trim(tag)//"_clumpcat_"//trim(olddumpfile) - open(10,file=clumpfile, status='unknown') + open(10,file=clumpfile,status='unknown') read(10,*) noldclump, oldtime allocate(oldclump(noldclump)) @@ -1054,7 +1054,7 @@ subroutine read_oldclump_data(noldclump,npart,oldtime,olddumpfile,tag) allocate(oldmember(npart)) - open(10,file=clumpfile, form='unformatted') + open(10,file=clumpfile,form='unformatted') read(10) (oldmember(i), i=1,npart) close(10) diff --git a/src/utils/analysis_clumpfindWB23.F90 b/src/utils/analysis_clumpfindWB23.F90 index da430b9ff..00e59de56 100644 --- a/src/utils/analysis_clumpfindWB23.F90 +++ b/src/utils/analysis_clumpfindWB23.F90 @@ -687,7 +687,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) !--Write results to file (both all the clumps at the current time, and to the file for each clump) write(filename,'(2a)') trim(dumpfile),'clumps' - open (unit=iunit,file=trim(filename)) + open(unit=iunit,file=trim(filename)) write(iunit,'(a,I6,a,Es18.6)') '#Nclumps = ',nclump,'; Time = ',time write(iunit,"('#',24(1x,'[',i2.2,1x,a11,']',2x))") & 1,'clump ID', & diff --git a/src/utils/analysis_collidingcloudevolution.f90 b/src/utils/analysis_collidingcloudevolution.f90 index 52cfdec52..110cd4842 100644 --- a/src/utils/analysis_collidingcloudevolution.f90 +++ b/src/utils/analysis_collidingcloudevolution.f90 @@ -44,7 +44,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) ! ! Initialise values & Open file ! - write(fileout,'(2a)') trim(dumpfile(1:INDEX(dumpfile,'_')-1)),'_MassEvolution.dat' + write(fileout,'(2a)') trim(dumpfile(1:index(dumpfile,'_')-1)),'_MassEvolution.dat' if ( firstcall ) then firstcall = .false. dthresh_cgs(1) = 1.0d-23 diff --git a/src/utils/analysis_common_envelope.f90 b/src/utils/analysis_common_envelope.f90 new file mode 100644 index 000000000..a527f4b41 --- /dev/null +++ b/src/utils/analysis_common_envelope.f90 @@ -0,0 +1,4494 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module analysis +! +! Analysis routine for common envelope simulations +! +! :References: None +! +! :Owner: Mike Lau +! +! :Runtime parameters: None +! +! :Dependencies: centreofmass, dim, dust_formation, energies, eos, +! eos_gasradrec, eos_mesa, extern_corotate, io, ionization_mod, kernel, +! mesa_microphysics, part, physcon, prompting, ptmass, setbinary, +! sortutils, table_utils, units, vectorutils +! + + use part, only:xyzmh_ptmass,vxyz_ptmass,nptmass,poten,ihsoft,ihacc,& + rhoh,nsinkproperties,maxvxyzu,maxptmass,isdead_or_accreted,& + 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 + use physcon, only:gg,pi,c,Rg + use io, only:fatal + use prompting, only:prompt + use centreofmass, only:get_centreofmass, reset_centreofmass + use energies, only:compute_energies,ekin,etherm,epot,etot + use ptmass, only:get_accel_sink_gas,get_accel_sink_sink + use kernel, only:kernel_softening,radkern,wkern,cnormk + use ionization_mod,only:calc_thermal_energy + use eos, only:equationofstate,ieos,init_eos,X_in,Z_in,gmw,get_spsound,done_init_eos + use eos_gasradrec, only:irecomb + use eos_mesa, only:get_eos_kappa_mesa,get_eos_pressure_temp_mesa,& + get_eos_various_mesa,get_eos_pressure_temp_gamma1_mesa + use setbinary, only:Rochelobe_estimate,L1_point + use sortutils, only:set_r2func_origin,r2func_origin,indexxfunc + use table_utils, only:logspace + implicit none + character(len=20), parameter, public :: analysistype = 'common_envelope' + integer :: analysis_to_perform + integer :: dump_number = 0 + real :: omega_corotate=0,init_radius,rho_surface,gamma + logical, dimension(5) :: switch = .false. + public :: do_analysis + public :: tconv_profile,get_interior_mass ! public = no unused fn warning + public :: planet_destruction,total_dust_mass ! make public to avoid compiler warning + private + +contains + +subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) + character(len=*), intent(in) :: dumpfile + integer, intent(in) :: num,npart,iunit + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + real, intent(in) :: particlemass,time + logical :: requires_eos_opts + + !chose analysis type + if (dump_number==0) then + print "(40(a,/))", & + ' 1) Sink separation', & + ' 2) Bound and unbound quantities', & + ' 3) Energies', & + ' 4) Profile from centre of mass', & + ' 5) Roche-lobe utils', & + ' 6) Star stabilisation suite', & + ' 7) Simulation units and particle properties', & + ' 8) Output .divv', & + ' 9) EoS testing', & + '10) Profile of newly unbound particles', & + '11) Sink properties', & + '12) MESA EoS compute total entropy and other average td quantities', & + '13) Gravitational drag on sinks', & + '14) CoM of gas around primary core', & + '15) J-E plane', & + '16) Rotation profile', & + '17) Energy profile', & + '18) Recombination statistics', & + '19) Optical depth profile', & + '20) Particle tracker', & + '21) Unbound ion fraction', & + '22) Optical depth at recombination', & + '23) Envelope binding energy', & + '24) Print dumps number matching separation', & + '25) Companion mass coordinate vs. time', & + '26) Energy histogram',& + '27) Analyse disk',& + '28) Recombination energy vs time',& + '29) Binding energy profile',& + '30) planet_rvm',& + '31) Velocity histogram',& + '32) Unbound temperature',& + '33) Planet mass distribution',& + '34) Planet profile',& + '35) Velocity profile',& + '36) Angular momentum profile',& + '37) Keplerian velocity profile',& + '38) Total dust mass' + analysis_to_perform = 1 + 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) + + ! List of analysis options that require specifying EOS options + requires_eos_opts = any((/2,3,4,5,6,8,9,10,13,17,18,19,20,21,22,23,26,27,28,29,30,32,38/) == analysis_to_perform) + if (dump_number == 0 .and. requires_eos_opts) call set_eos_options(analysis_to_perform) + + select case(analysis_to_perform) + case(1) !sink separation + call separation_vs_time(time) + case(2) !bound and unbound quantities + call bound_mass(time,npart,particlemass,xyzh,vxyzu) + case(3) !Energies and bound mass + call calculate_energies(time,npart,particlemass,xyzh,vxyzu) + case(4) !Profile from COM (can be used for stellar profile) + call create_profile(time, num, npart, particlemass, xyzh, vxyzu) + case(5) !Mass within roche lobes + call roche_lobe_values(time,npart,particlemass,xyzh,vxyzu) + case(6) !Star stabilisation suite + 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(9) !EoS testing + call eos_surfaces + case(10) !New unbound particle profiles in time + call unbound_profiles(time,num,npart,particlemass,xyzh,vxyzu) + case(11) !sink properties + call sink_properties(time,npart,particlemass,xyzh,vxyzu) + case(12) !MESA EoS compute total entropy and other average thermodynamical quantities + call bound_unbound_thermo(time,npart,particlemass,xyzh,vxyzu) + case(13) !Gravitational drag on sinks + call gravitational_drag(time,npart,particlemass,xyzh,vxyzu) + case(14) + call get_core_gas_com(time,npart,xyzh,vxyzu) + case(15) + call J_E_plane(num,npart,particlemass,xyzh,vxyzu) + case(16) ! Rotation profile + call rotation_profile(time,num,npart,xyzh,vxyzu) + case(17) ! Energy profile + call energy_profile(time,npart,particlemass,xyzh,vxyzu) + case(18) ! Recombination statistics + call recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) + case(19) ! Optical depth profile + call tau_profile(time,num,npart,particlemass,xyzh) + case(20) ! Particle tracker + call track_particle(time,particlemass,xyzh,vxyzu) + case(21) ! Unbound ion fractions + call unbound_ionfrac(time,npart,particlemass,xyzh,vxyzu) + case(22) ! Optical depth at recombination + call recombination_tau(time,npart,particlemass,xyzh,vxyzu) + case(23) ! Calculate binding energy outside core + call env_binding_ene(npart,particlemass,xyzh,vxyzu) + case(24) ! Print dump number corresponding to given set of sink-sink separations + call print_dump_numbers(dumpfile) + case(25) ! Companion mass coordinate (spherical mass shells) vs. time + call m_vs_t(time,npart,particlemass,xyzh) + case(26) ! Energy histogram + call energy_hist(time,npart,particlemass,xyzh,vxyzu) + case(27) ! Analyse disk around companion + call analyse_disk(num,npart,particlemass,xyzh,vxyzu) + case(28) ! Recombination energy vs. time + call erec_vs_t(time,npart,particlemass,xyzh) + case(29) ! Binding energy profile + call create_bindingEnergy_profile(time,num,npart,particlemass,xyzh,vxyzu) + case(30) ! Planet coordinates and mass + call planet_rvm(time,particlemass,xyzh,vxyzu) + case(31) ! Velocity histogram + call velocity_histogram(time,num,npart,particlemass,xyzh,vxyzu) + case(32) ! Unbound temperatures + call unbound_temp(time,npart,particlemass,xyzh,vxyzu) + case(33) ! Planet mass distribution + call planet_mass_distribution(time,num,npart,xyzh) + case(34) ! Calculate planet profile + call planet_profile(num,dumpfile,particlemass,xyzh,vxyzu) + case(35) ! Velocity profile + call velocity_profile(time,num,npart,particlemass,xyzh,vxyzu) + case(36) ! Angular momentum profile + call angular_momentum_profile(time,num,npart,particlemass,xyzh,vxyzu) + case(37) ! Keplerian velocity profile + call vkep_profile(time,num,npart,particlemass,xyzh,vxyzu) + case(38) !Total dust mass + call total_dust_mass(time,npart,particlemass,xyzh) + end select + !increase dump number counter + dump_number = dump_number + 1 + +end subroutine do_analysis + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!! Analysis routines !!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + +subroutine total_dust_mass(time,npart,particlemass,xyzh) + use part, only:nucleation,idK3,idK0,idK1, idJstar + use dust_formation, only:set_abundances, mass_per_H + use physcon, only:atomic_mass_unit + real, intent(in) :: time,particlemass,xyzh(:,:) + integer, intent(in) :: npart + integer :: i,ncols,j + real, dimension(2) :: dust_mass + character(len=17), allocatable :: columns(:) + real, allocatable :: temp(:) !npart + real :: median,mass_factor,grain_size + real, parameter :: a0 = 1.28e-4 !radius of a carbon atom in micron + + call set_abundances !initialize mass_per_H + dust_mass = 0. + ncols = 2 + print *,'size(nucleation,1) = ',size(nucleation,1) + print *,'size(nucleation,2) = ',size(nucleation,2) + allocate(columns(ncols),temp(npart)) + columns = (/'Dust mass [Msun]', & + 'median size [um]'/) + j=0 + mass_factor = 12.*atomic_mass_unit*particlemass/mass_per_H + do i = 1,npart + if (.not. isdead_or_accreted(xyzh(4,i))) then + dust_mass(1) = dust_mass(1) + nucleation(idK3,i) *mass_factor + grain_size = a0*nucleation(idK1,i)/(nucleation(idK0,i)+1.0E-99) !in micron + if (grain_size > a0) then + j = j+1 + temp(j) = grain_size + endif + endif + enddo + + call sort(temp,j) + if (mod(j,2)==0) then !npart + median = (temp(j/2)+temp(j/2+1))/2.0 !(temp(npart/2)+temp(npart/2+1))/2.0 + else + median = (temp(j/2)+temp(j/2+1))/2.0 !temp(npart/2+1) + endif + + dust_mass(2) = median + + call write_time_file('total_dust_mass_vs_time', columns, time, dust_mass, ncols, dump_number) + !after execution of the analysis routine, a file named "total_dust_mass_vs_time.ev" appears + deallocate(columns,temp) + +end subroutine total_dust_mass + +! -------------------------------------------------------------------- +! integer function FindMinimum(): +! This function returns the location of the minimum in the section +! between Start and End. +! -------------------------------------------------------------------- + +integer function FindMinimum(x, Start, Fin) + implicit none + integer, intent(in) :: start, fin + real, dimension(Fin), intent(in) :: x + real :: minimum + integer :: location + integer :: i + + minimum = x(start) ! assume the first is the min + location = start ! record its position + do i = start+1, fin ! start with next elements + if (x(i) < minimum) then ! if x(i) less than the min? + minimum = x(i) ! yes, a new minimum found + location = i ! record its position + endif + enddo + findminimum = location ! return the position +end function FindMinimum + +! -------------------------------------------------------------------- +! subroutine Sort(): +! This subroutine receives an array x() and sorts it into ascending +! order. +! -------------------------------------------------------------------- + +subroutine Sort(x, longitud) + implicit none + integer, intent(in) :: longitud + real, dimension(longitud), intent(inout) :: x + integer :: i + integer :: location + + do i = 1, longitud-1 ! except for the last + location = findminimum(x, i, longitud) ! find min from this to last + call swap(x(i), x(location)) ! swap this and the minimum + enddo +end subroutine Sort + + +!---------------------------------------------------------------- +!+ +! Separation vs. time +!+ +!---------------------------------------------------------------- +subroutine separation_vs_time(time) + real, intent(in) :: time + character(len=17), allocatable :: columns(:) + real :: sink_separation(4,nptmass-1) + integer :: i,ncols + ncols = 4*(nptmass-1) + allocate(columns(ncols)) + + do i=1,(nptmass-1) + call separation_vector(xyzmh_ptmass(1:3,1),xyzmh_ptmass(1:3,i+1),sink_separation(1:4,i)) + + write(columns((i*4)-3), '(A11,I1)') ' x sep. ', i + write(columns((i*4)-2), '(A11,I1)') ' y sep. ', i + write(columns((i*4)-1), '(A11,I1)') ' z sep. ', i + write(columns((i*4)), '(A11,I1)') ' sep. ', i + enddo + + call write_time_file('separation_vs_time', columns, time, sink_separation, ncols, dump_number) + deallocate(columns) +end subroutine separation_vs_time + + +!---------------------------------------------------------------- +!+ +! Output planet position (x,y,z,r) and velocity (vx,vy,vz,|v|) +! relative to core, instantaneous mass according to different +! criteria (m1,m2,m3,m4,m5), max. density, and min. entropy +! +! For small dumps, only (x,y,z,r) and rhomax may be determined. +! All other quantities will be outputted as zero. +!+ +!---------------------------------------------------------------- +subroutine planet_rvm(time,particlemass,xyzh,vxyzu) + use eos, only:entropy + 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, allocatable :: data_cols(:),mass(:),vthreshold(:) + integer :: i,j,ncols,maxrho_ID,ientropy,Nmasks + integer, save :: nplanet + integer, allocatable, save :: planetIDs(:) + logical :: isfulldump + + if (.not. done_init_eos) call fatal("planet_rvm","EOS has not been initialised.") + + ncols = 15 + allocate(data_cols(ncols),columns(ncols)) + columns = (/' x sep', & + ' y sep', & + ' z sep', & + ' sep', & + ' vx', & + ' vy', & + ' vz', & + ' v', & + ' m1', & + ' m2', & + ' m3', & + ' m4', & + ' m5', & + ' rhomax', & + ' smin'/) + + if (dump_number == 0) call get_planetIDs(nplanet,planetIDs) + isfulldump = (vxyzu(4,1) > 0.) + + ! Find highest density and lowest entropy in planet + rhoprev = 0. + maxrho_ID = 1 + smin = huge(0.) + ientropy = 1 + ieos = 2 + gamma = 5./3. + do i = 1,nplanet + rhoi = rhoh(xyzh(4,planetIDs(i)), particlemass) + if (rhoi > rhoprev) then + maxrho_ID = planetIDs(i) + rhoprev = rhoi + endif + + if (isfulldump) then + presi = (gamma-1.)*vxyzu(4,i) + si = entropy(rhoi*unit_density,presi*unit_pressure,gmw,ientropy) + smin = min(smin,si) + endif + enddo + + planet_com = xyzh(1:3,maxrho_ID) + sep = planet_com - xyzmh_ptmass(1:3,1) + + if (isfulldump) then + planet_vel = vxyzu(1:3,maxrho_ID) + vel = planet_vel - vxyz_ptmass(1:3,1) + else + vel = 0. + smin = 0. + endif + + ! Sum planet mass according to criterion + Nmasks = 5 ! Number of velocity thresholds for calculating planet mass + allocate(mass(Nmasks),vthreshold(Nmasks)) + mass = 0. + if (isfulldump) then + Rthreshold = 0.21 ! Radius criterion to be considered part of planet + vthreshold = (/0.1,0.3,0.5,0.7,0.9/) ! Allowed fractional deviation in particle velocity from velocity of densest planet particle + do i = 1,nplanet + sepi = separation(xyzh(1:3,planetIDs(i)), planet_com) + do j = 1,Nmasks + if ( (sepi < Rthreshold) .and. (abs(1. - dot_product(vxyzu(1:3,planetIDs(i)),planet_vel)/& + dot_product(planet_vel,planet_vel)) < vthreshold(j)) ) then ! vi dot vp / vp^2 > threshold + mass(j:Nmasks) = mass(j:Nmasks) + 1. + exit + endif + enddo + enddo + mass = mass * particlemass + endif + + data_cols = (/ sep(1), sep(2), sep(3), distance(planet_com),& + vel(1), vel(2), vel(3), distance(vel),& + mass(1), mass(2), mass(3), mass(4), mass(5), rhoprev, smin /) + call write_time_file('planet_rvm', columns, time, data_cols, ncols, dump_number) + + deallocate(data_cols,columns,mass,vthreshold) + +end subroutine planet_rvm + + +!---------------------------------------------------------------- +!+ +! Output radial distribution of planetary material +!+ +!---------------------------------------------------------------- +subroutine planet_mass_distribution(time,num,npart,xyzh) + integer, intent(in) :: npart,num + real, intent(in) :: time + real, intent(inout) :: xyzh(:,:) + real, allocatable :: rad_part(:),dist_part(:),hist_var(:) + real :: mina,maxa,xyz_origin(3) + character(len=17) :: filename + character(len=100) :: data_formatter,headerline + integer :: i,iu,nbins + integer, save :: nplanet + integer, allocatable, save :: planetIDs(:) + + if (dump_number == 0) call get_planetIDs(nplanet,planetIDs) + + nbins = 1000 ! Radial bins + mina = 0. + maxa = 4.2 + + allocate(rad_part(nplanet),dist_part(nplanet),hist_var(nbins)) + filename = ' planet_m_dist.ev' + xyz_origin = xyzmh_ptmass(1:3,1) + + dist_part = 0. + rad_part = 0. + do i = 1,nplanet + rad_part(i) = separation(xyzh(1:3,planetIDs(i)),xyz_origin) + dist_part(i) = 1. + enddo + + call histogram_setup(rad_part,dist_part,hist_var,nplanet,maxa,mina,nbins,.false.,.false.) + + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + if (num == 0) then + open(newunit=iu,file=trim(adjustl(filename)),status='replace') + write(headerline, "(a,i5,a,f5.2,a,f5.2)") "# Planet mass distribution, nbins = ", nbins,", min a = ", mina, ", max a = ", maxa + write(iu, "(a)") headerline + close(unit=iu) + endif + open(newunit=iu,file=trim(adjustl(filename)), position='append') + write(iu,data_formatter) time,hist_var(:) + close(unit=iu) + + deallocate(rad_part,dist_part,hist_var) + +end subroutine planet_mass_distribution + + +!---------------------------------------------------------------- +!+ +! Companion mass coordinate (spherical mass shells) vs. time +!+ +!---------------------------------------------------------------- +subroutine m_vs_t(time,npart,particlemass,xyzh) + integer, intent(in) :: npart + real, intent(in) :: time,particlemass,xyzh(:,:) + character(len=17) :: colname + real :: sinksinksep,mass(1) + integer :: i,k + integer, allocatable :: iorder(:) + + allocate(iorder(npart)) + + call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) ! Order particles by distance from core + call indexxfunc(npart,r2func_origin,xyzh,iorder) + + sinksinksep = separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) + do i=1,npart + k = iorder(i) + if (separation(xyzh(1:3,k), xyzmh_ptmass(1:3,1)) > sinksinksep) exit + enddo + + mass = i*particlemass + xyzmh_ptmass(4,1) + write(colname, '(A11)') ' mass coord' + call write_time_file(' m_vs_t',colname,time,mass,1,dump_number) + + deallocate(iorder) + +end subroutine m_vs_t + + +!---------------------------------------------------------------- +!+ +! Bound mass +!+ +!---------------------------------------------------------------- +subroutine bound_mass(time,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp,radprop + 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 :: E_H2,E_HI,E_HeI,E_HeII + real, save :: Xfrac,Yfrac,Zfrac + real :: rhopart,ponrhoi,spsoundi,tempi,dum1,dum2,dum3 + real, dimension(3) :: rcrossmv + real, dimension(28) :: bound + integer :: i,bound_i,ncols + integer, parameter :: ib=1,ibt=9,ibe=17 + character(len=17), allocatable :: columns(:) + + if (.not. done_init_eos) call fatal("bound_mass","EOS has not been initialised.") + + ncols = 28 + bound = 0. + allocate(columns(ncols)) + columns = (/' b num part', & ! Total bound number of particles + ' b mass', & ! Total bound gas mass + ' b ang mom', & ! Total bound gas angular momentum wrt CoM of entire system + ' b tot en', & ! Total bound energy of gas + ' ub num part', & + ' ub mass', & + ' ub ang mom', & + ' ub tot en', & + ' bt num part', & ! As in comments above, but including thermal energy in criterion + ' bt mass', & + ' bt ang mom', & + ' bt tot en', & + 'ubt num part', & + ' ubt mass', & + ' ubt ang mom', & + ' ubt tot en', & + ' be num part', & + ' be mass', & + ' be ang mom', & + ' be tot en', & + 'ube num part', & + ' ube mass', & + ' ube ang mom', & + ' ube tot en', & + ' HeII bm', & ! Bound mass including recombination energy of HeII + ' HeII+HeI bm', & ! Bound mass including recombination energy of HeII, HeI + ' He+HI bm', & ! Bound mass including recombination energy of HeII, HeI, HI + ' He+HI+H2 bm'/) ! Bound mass including recombination energy of HeII, HeI, HI, H2 + + Zfrac = 0. + if (dump_number == 0) then + if (ieos /= 10 .and. ieos /= 20) then ! For MESA EoS, just use X_in and Z_in from eos module + Xfrac = 0.69843 + Zfrac = 0.01426 + call prompt('Enter hydrogen mass fraction to assume for recombination:',Xfrac,0.,1.) + call prompt('Enter metallicity to assume for recombination:',Zfrac,0.,1.) + else + Xfrac = X_in + Zfrac = Z_in + endif + Yfrac = 1. - Xfrac - Zfrac + endif + + ! Ionisation energies per particle (in code units) + E_H2 = 0.5*Xfrac*0.0022866 * particlemass + E_HI = Xfrac*0.0068808 * particlemass + E_HeI = 0.25*Yfrac*0.012442 * particlemass + E_HeII = 0.25*Yfrac*0.027536 * particlemass + + 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 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)) + 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. + rcrossmv = (/ 0., 0., 0. /) + endif + + ! Bound criterion + if ((epoti + ekini < 0.) .or. isdead_or_accreted(xyzh(4,i))) then + bound_i = ib + else + bound_i = ib + 4 ! Unbound + endif + + bound(bound_i) = bound(bound_i) + 1 + bound(bound_i + 1) = bound(bound_i + 1) + particlemass + bound(bound_i + 2) = bound(bound_i + 2) + distance(rcrossmv) + bound(bound_i + 3) = bound(bound_i + 3) + etoti + + ! Bound criterion INCLUDING thermal energy + if ((epoti + ekini + ethi < 0.) .or. isdead_or_accreted(xyzh(4,i))) then + bound_i = ibt + else + bound_i = ibt + 4 + endif + + bound(bound_i) = bound(bound_i) + 1 + bound(bound_i + 1) = bound(bound_i + 1) + particlemass + bound(bound_i + 2) = bound(bound_i + 2) + distance(rcrossmv) + bound(bound_i + 3) = bound(bound_i + 3) + etoti + + ! Bound criterion using enthalpy + if ((epoti + ekini + ethi + ponrhoi*particlemass < 0.) .or. isdead_or_accreted(xyzh(4,i))) then + bound_i = ibe + else + bound_i = ibe + 4 + endif + + bound(bound_i) = bound(bound_i) + 1 + bound(bound_i + 1) = bound(bound_i + 1) + particlemass + bound(bound_i + 2) = bound(bound_i + 2) + distance(rcrossmv) + bound(bound_i + 3) = bound(bound_i + 3) + etoti + + ! Bound criterion including HeI + HeII ionisation energy + if ((epoti + ekini + ethi + E_HeII < 0.) .or. isdead_or_accreted(xyzh(4,i))) then + bound(25) = bound(25) + particlemass + endif + + ! Bound criterion including HeI + HeII ionisation energy + if ((epoti + ekini + ethi + E_HeII + E_HeI < 0.) .or. isdead_or_accreted(xyzh(4,i))) then + bound(26) = bound(26) + particlemass + endif + + ! Bound criterion including HeI + HeII + HI ionisation energy + if ((epoti + ekini + ethi + E_HeII + E_HeI + E_HI < 0.) .or. isdead_or_accreted(xyzh(4,i))) then + bound(27) = bound(27) + particlemass + endif + + ! Bound criterion including HeI + HeII + HI + H2 ionisation energy + if ((epoti + ekini + ethi + E_HeII + E_HeI + E_HI + E_H2 < 0.) .or. isdead_or_accreted(xyzh(4,i))) then + bound(28) = bound(28) + particlemass + endif + enddo + + call write_time_file('boundunbound_vs_time', columns, time, bound, ncols, dump_number) + deallocate(columns) + +end subroutine bound_mass + + +!---------------------------------------------------------------- +!+ +! Calculate energies +!+ +!---------------------------------------------------------------- +subroutine calculate_energies(time,npart,particlemass,xyzh,vxyzu) + use vectorutils, only:cross_product3D + 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 :: rhopart,ponrhoi,spsoundi,tempi,r_ij,radvel + real, dimension(3) :: rcrossmv + character(len=17), allocatable :: columns(:) + integer :: i,j,ncols + logical :: inearsink + integer, parameter :: ie_tot = 1 + integer, parameter :: ie_pot = ie_tot + 1 + integer, parameter :: ie_kin = ie_pot + 1 + integer, parameter :: ie_therm = ie_kin + 1 + integer, parameter :: ipot_sink = ie_therm + 1 + integer, parameter :: ikin_sink = ipot_sink + 1 + integer, parameter :: iorb_sink = ikin_sink + 1 + integer, parameter :: iorb_comp = iorb_sink + 1 + integer, parameter :: ipot_env = iorb_comp + 1 + integer, parameter :: ie_env = ipot_env + 1 + integer, parameter :: ikin_bound = ie_env + 1 + integer, parameter :: ikin_unbound = ikin_bound + 1 + integer, parameter :: imass_bound = ikin_unbound + 1 + integer, parameter :: imass_unbound = imass_bound + 1 + integer, parameter :: ipot_pp = imass_unbound + 1 + integer, parameter :: ipot_ps = ipot_pp + 1 + integer, parameter :: ijz_tot = ipot_ps + 1 + integer, parameter :: ijz_bound = ijz_tot + 1 + integer, parameter :: ijz_unbound = ijz_bound + 1 + integer, parameter :: ijz_orb = ijz_unbound + 1 + integer, parameter :: ie_gas = ijz_orb + 1 + integer, parameter :: fallbackmass = ie_gas + 1 + integer, parameter :: fallbackmom = fallbackmass + 1 + real, dimension(fallbackmom) :: encomp + + ncols = 23 + allocate(columns(ncols)) + columns = (/'total energy',& + ' pot energy',& + ' kin energy',& + 'therm energy',& + ' sink pot',& ! does not include sink-gas potential energy + ' sink kin',& + ' sink orb',& ! sink kin + sink pot + ' comp orb',& + ' env pot',& + ' env energy',& + ' bound kin',& + ' unbound kin',& + ' bound mass',& + 'unbound mass',& + ' p-p pot',& + ' p-s pot',& + ' tot ang mom',& + ' b ang mom',& + ' ub ang mom',& + ' orb ang mom',& + ' gas energy',& + ' fallback',& + 'fallback mom'/) + + encomp(5:) = 0. + call compute_energies(time) + ekin = 0. + + do i=1,npart + encomp(ipot_pp) = encomp(ipot_pp) + poten(i) ! poten already includes factor of 1/2 to correct for double counting + encomp(ipot_env) = encomp(ipot_env) + poten(i) + + call cross_product3D(xyzh(1:3,i), particlemass * vxyzu(1:3,i), rcrossmv) + 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) + + encomp(ipot_ps) = encomp(ipot_ps) + particlemass * phii + + phii1 = 0. + call get_accel_sink_gas(1,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass,fxi,fyi,fzi,phii1) + encomp(ipot_env) = encomp(ipot_env) + phii1 * particlemass + + do j=1,nptmass + if (xyzmh_ptmass(4,j) > 0.) then + r_ij = separation(xyzmh_ptmass(1:3,j),xyzh(1:3,i)) + if (r_ij < 80.) then + inearsink = .true. + endif + endif + enddo + + 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 (etoti < 0) then + encomp(ikin_bound) = encomp(ikin_bound) + ekini + encomp(imass_bound) = encomp(imass_bound) + particlemass + encomp(ijz_bound) = encomp(ijz_bound) + jz + radvel = dot_product(vxyzu(1:3,i),xyzh(1:3,i)) / distance(xyzh(1:3,i)) + + if (inearsink .eqv. .false.) then + if (radvel < 0.) then + encomp(fallbackmass) = encomp(fallbackmass) + particlemass + encomp(fallbackmom) = encomp(fallbackmom) + particlemass * radvel + endif + endif + + else + encomp(ikin_unbound) = encomp(ikin_unbound) + ekini + encomp(imass_unbound) = encomp(imass_unbound) + particlemass + encomp(ijz_unbound) = encomp(ijz_unbound) + jz + endif + enddo + + do i=1,nptmass + if (xyzmh_ptmass(4,i) > 0.) then + call cross_product3D(xyzmh_ptmass(1:3,i), xyzmh_ptmass(4,i)*vxyz_ptmass(1:3,i), rcrossmv) + jz = rcrossmv(3) + encomp(ijz_tot) = jz + encomp(ijz_tot) + encomp(ijz_orb) = jz + encomp(ijz_orb) + encomp(ikin_sink) = encomp(ikin_sink) + 0.5 * xyzmh_ptmass(4,i) * distance(vxyz_ptmass(1:3,i))**2 + if (i==2) encomp(iorb_comp) = encomp(iorb_comp) + 0.5 * xyzmh_ptmass(4,i) * distance(vxyz_ptmass(1:3,i))**2 + endif + enddo + + do i=1,nptmass-1 + if (xyzmh_ptmass(4,i) > 0.) then + do j=i+1,nptmass + if (xyzmh_ptmass(4,j) > 0.) then + r_ij = separation(xyzmh_ptmass(1:3,i),xyzmh_ptmass(1:3,j)) + encomp(ipot_sink) = encomp(ipot_sink) - xyzmh_ptmass(4,i) * xyzmh_ptmass(4,j) / r_ij ! Newtonian expression is fine as long as rij > hsofti + hsoftj + if (i==1 .and. j==2) encomp(iorb_comp) = encomp(iorb_comp) - xyzmh_ptmass(4,i) * xyzmh_ptmass(4,j) / r_ij + endif + enddo + endif + enddo + + ekin = encomp(ikin_bound) + encomp(ikin_unbound) + encomp(ikin_sink) + encomp(iorb_sink) = encomp(ipot_sink) + encomp(ikin_sink) + encomp(ie_env) = encomp(ipot_env) + etherm + encomp(ikin_bound) + epot = encomp(ipot_pp) + encomp(ipot_ps) + encomp(ipot_sink) + etot = epot + ekin + etherm + encomp(ie_gas) = encomp(ikin_bound) + encomp(ikin_unbound) + encomp(ipot_ps) + + encomp(ie_tot) = etot + encomp(ie_pot) = epot + encomp(ie_kin) = ekin + encomp(ie_therm) = etherm + + call write_time_file('energy', columns, time, encomp, ncols, dump_number) + deallocate(columns) + +end subroutine calculate_energies + + +!!!!! Create profile !!!!! +subroutine create_profile(time, num, npart, particlemass, xyzh, vxyzu) + integer, intent(in) :: npart, num + real, intent(in) :: time, particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + real, save :: profile_vector(3) + integer :: ncols + character(len=15) :: name_in + real, allocatable :: profile(:,:) + + if (dump_number == 0) then + profile_vector=(/1.,0.,0./) + call prompt('Would you like simple profiles?', switch(1), .true.) + call prompt('Choose profile vector x-component ',profile_vector(1)) + call prompt('Choose profile vector y-component ',profile_vector(2)) + call prompt('Choose profile vector z-component ',profile_vector(3)) + endif + + if (switch(1)) then + ncols = 8 + else + ncols = 18 + endif + + if (all(profile_vector <= tiny(profile_vector))) then + write(*,*)'Using all particles!' + call stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,switch(1)) + write(name_in, "(a)") 'part_profile' + else + write(*,*)'Profile_vector is:',profile_vector + call stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,switch(1),profile_vector) + write(name_in, "(a,i1,i1,i1)") 'ray_profile_',int(profile_vector(1:3)) + endif + + allocate(columns(18)) + columns = (/' radius',& + ' mass coord',& + ' azimuth',& + ' density',& + ' velocity',& + ' rad. vel.',& + ' vxy tan.',& + ' omega',& !Simple creates up to here + ' int. energy',& + ' pressure',& + ' sound speed',& + ' temp',& + ' kappa',& + ' mfp',& + ' energy',& + ' HII frac',& + ' HeII frac',& + ' HeIII frac'/) + + call write_file(name_in, 'profile', columns, profile, size(profile(1,:)), ncols, num) + + deallocate(profile,columns) +end subroutine create_profile + + +!!!!! Roche lobe values !!!!! +subroutine roche_lobe_values(time,npart,particlemass,xyzh,vxyzu) + use vectorutils, only:cross_product3D + integer, intent(in) :: npart + real, intent(in) :: time, particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + integer :: i, j, nFB, nR1T, ncols + integer, parameter :: iRL1 = 1 + integer, parameter :: iMRL1 = 2 + integer, parameter :: iBMRL1 = 3 + integer, parameter :: ijzRL1 = 4 + integer, parameter :: iRL2 = 5 + integer, parameter :: iMRL2 = 6 + integer, parameter :: iBMRL2 = 7 + integer, parameter :: ijzRL2 = 8 + integer, parameter :: iR1 = 9 + integer, parameter :: iR1T = 10 + integer, parameter :: iRej = 11 + integer, parameter :: iMej = 12 + integer, parameter :: iBMej = 13 + integer, parameter :: ijzej = 14 + integer, parameter :: iBjzej = 15 + integer, parameter :: iMF = 16 + integer, parameter :: ijzMF = 17 + integer, parameter :: iDR = 18 + integer, parameter :: iFB = 19 + integer, parameter :: iFBV = 20 + integer, parameter :: iFBJz = 21 + real, dimension(iFBJz) :: MRL + real :: etoti, ekini, einti, epoti, phii, jz + logical, dimension(:), allocatable, save:: transferred + real, save :: m1, m2 + real :: sep, sep1, sep2 + real :: rhovol, rhomass, rhopart, R1, rad_vel, sepCoO + real :: temp_const, ponrhoi, spsoundi, tempi + real, dimension(3) :: rcrossmv, CoO, com_xyz, com_vxyz + real, allocatable :: xyz_a(:,:) + integer :: npart_a, mean_rad_num + integer, allocatable :: iorder(:) + + allocate(iorder(npart),xyz_a(3,npart)) + + MRL = 0. + rhovol = 0. + rhomass = 0. + nFB = 0 + nR1T = 0 + temp_const = (unit_pressure / unit_density) * 1.34 / Rg + + if (dump_number == 0) then + m1 = npart * particlemass + xyzmh_ptmass(4,1) + m2 = xyzmh_ptmass(4,2) + allocate(transferred(npart)) + transferred(1:npart) = .false. + + rho_surface = rhoh(xyzh(4,1), particlemass) + do i=1,npart + rhopart = rhoh(xyzh(4,i), particlemass) + if (rhopart < rho_surface) then + rho_surface = rhopart + endif + enddo + endif + + mean_rad_num = npart / 200 + npart_a = 0 + + do i=1,npart + rhopart = rhoh(xyzh(4,i), particlemass) + if (rhopart > rho_surface) then + if (separation(xyzh(1:3,i), xyzmh_ptmass(1:3,1)) < & + separation(xyzh(1:3,i), xyzmh_ptmass(1:3,2))) then + rhomass = rhomass + particlemass + rhovol = rhovol + particlemass / rhopart + npart_a = npart_a + 1 + xyz_a(1:3,npart_a) = xyzh(1:3,i) + endif + endif + enddo + + call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) + call indexxfunc(npart_a,r2func_origin,xyz_a,iorder) + + R1 = 0 + do i=npart_a-mean_rad_num,npart_a + j = iorder(i) + R1 = R1 + separation(xyz_a(1:3,j),xyzmh_ptmass(1:3,1)) + enddo + + R1 = R1 / real(mean_rad_num) + + sep = separation(xyzmh_ptmass(1:3,1),xyzmh_ptmass(1:3,2)) + MRL(iRL1) = Rochelobe_estimate(m2,m1,sep) + MRL(iRL2) = Rochelobe_estimate(m1,m2,sep) + + !R1 = (3. * rhovol/(4. * pi))**(1./3.) + CoO(1:3) = (xyzmh_ptmass(1:3,1) + xyzmh_ptmass(1:3,2)) / 2. + MRL(iR1) = R1 + MRL(iRej) = separation(CoO(1:3),xyzmh_ptmass(1:3,1)) + R1 + + 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) + + sep1 = separation(xyzmh_ptmass(1:3,1),xyzh(1:3,i)) + sep2 = separation(xyzmh_ptmass(1:3,2),xyzh(1:3,i)) + sepCoO = separation(CoO(1:3),xyzh(1:3,i)) + + call cross_product3D(xyzh(1:3,i)-com_xyz(1:3), particlemass * vxyzu(1:3,i), rcrossmv) + jz = rcrossmv(3) + + if (sep1 < MRL(iRL1)) then + MRL(iMRL1) = MRL(iMRL1) + particlemass + MRL(ijzRL1) = MRL(ijzRL1) + jz + if (etoti < 0) then + MRL(iBMRL1) = MRL(iBMRL1) + particlemass + endif + endif + + if (sep2 < MRL(iRL2)) then + MRL(iMRL2) = MRL(iMRL2) + particlemass + MRL(ijzRL2) = MRL(ijzRL2) + jz + + if (transferred(i) .eqv. .false.) then + MRL(iMF) = MRL(iMF) + particlemass + MRL(ijzMF) = MRL(ijzMF) + jz + transferred(i) = .true. + endif + + if (etoti < 0) then + MRL(iBMRL2) = MRL(iBMRL2) + particlemass + endif + endif + + if ((sep1 - xyzh(4,i) < R1) .and. (sep1 + xyzh(4,i) > R1)) then !!!!FIX THIS + call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) + MRL(iR1T) = MRL(iR1T) + ponrhoi * temp_const + nR1T = nR1T + 1 + endif + + if (sepCoO > MRL(iRej)) then + rad_vel = dot_product(vxyzu(1:3,i),xyzh(1:3,i)) / distance(xyzh(1:3,i)) + + MRL(iMej) = MRL(iMej) + particlemass + MRL(ijzej) = MRL(ijzej) + jz + + if (etoti < 0) then + MRL(iBMej) = MRL(iBMej) + particlemass + MRL(iBjzej) = MRL(iBjzej) + jz + endif + + if (rad_vel < 0) then + MRL(iFB) = MRL(iFB) + particlemass + MRL(iFBV) = MRL(iFBV) + rad_vel + MRL(iFBJz) = MRL(iFBJz) + jz + nFB = nFB + 1 + endif + endif + enddo + + if (nR1T == 0) then + MRL(iR1T) = 0 + else + MRL(iR1T) = MRL(iR1T) / real(nR1T) + endif + + if (nFB == 0) then + MRL(iFBV) = 0 + else + MRL(iFBV) = MRL(iFBV) / real(nFB) + endif + + + + MRL(iMRL1) = MRL(iMRL1) + xyzmh_ptmass(4,1) + MRL(iMRL2) = MRL(iMRL2) + xyzmh_ptmass(4,2) + + MRL(iDR) = (R1 - MRL(iRL1)) / R1 + + call cross_product3D(xyzmh_ptmass(1:3,1) - com_xyz(1:3),xyzmh_ptmass(4,1) * vxyz_ptmass(1:3,1),rcrossmv) + MRL(ijzRL1) = MRL(ijzRL1) + rcrossmv(3) + + call cross_product3D(xyzmh_ptmass(1:3,2) - com_xyz(1:3),xyzmh_ptmass(4,2) * vxyz_ptmass(1:3,2),rcrossmv) + MRL(ijzRL2) = MRL(ijzRL2) + rcrossmv(3) + + m1 = rhomass + xyzmh_ptmass(4,1) + m2 = MRL(iMRL2) + + ncols = 21 + allocate(columns(ncols)) + columns = (/' RL1',& + ' Mass in RL1',& + ' B Mass RL1',& + ' jz in RL1',& + ' RL2',& + ' Mass in RL2',& + ' B Mass RL2',& + ' jz in RL2',& + ' R1',& + ' R1 temp',& + ' R_ejecta',& + 'Mass ejected',& + 'B Mass eject',& + ' jz ejected',& + ' B jz eject',& + ' Mass flow',& + 'Mass flow jz',& + ' R1-RL1/R1',& + ' Fallback',& + 'Fallback vel',& + ' Fallback Jz'/) + + call write_time_file('roche_lobes', columns, time, MRL, ncols, dump_number) + deallocate(columns,iorder) + +end subroutine roche_lobe_values + +!---------------------------------------------------------------- +!+ +! Star stabilisation +!+ +!---------------------------------------------------------------- +subroutine star_stabilisation_suite(time,npart,particlemass,xyzh,vxyzu) + use part, only:fxyzu + use eos, only:equationofstate + integer, intent(in) :: npart + real, intent(in) :: time, particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + integer :: i,j,k,ncols,mean_rad_num,npart_a + 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 + integer, parameter :: ivoleqrad = 1 + integer, parameter :: idensrad = 2 + integer, parameter :: imassout = 3 + integer, parameter :: imassfracout = 4 + integer, parameter :: ipartrad = 5 + integer, parameter :: ipart2hrad = 6 + integer, parameter :: ipdensrad = 7 + integer, parameter :: ip2hdensrad = 8 + integer, parameter :: ivirialpart = 9 + integer, parameter :: ivirialfluid = 10 + + ncols = 10 + allocate(columns(ncols),star_stability(ncols),iorder(npart),iorder_a(npart)) + columns = (/'vol. eq. rad',& + ' density rad',& + 'mass outside',& + 'frac outside',& + ' part rad',& + ' part 2h rad',& + ' p dens rad',& + 'p2h dens rad',& + 'part. virial',& ! Residual of virial theorem for self-gravitating particles + 'fluid virial'/) ! Residual of virial theorem for fluid + + ! Get order of particles by distance from sink particle core + call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) + call indexxfunc(npart,r2func_origin,xyzh,iorder) + + ! Get density of outermost particle in initial star dump + if (dump_number == 0) then + rho_surface = rhoh(xyzh(4,iorder(npart)), particlemass) + endif + + npart_a = 0 + totvol = 0. + rhovol = 0. + virialpart = 0. + totekin = 0. + totepot = 0. + virialintegral= 0. + do i = 1,npart + 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) + totekin = totekin + ekini + totepot = totepot + 0.5*epoti ! Factor of 1/2 to correct for double counting + if (rhopart > rho_surface) then + ! Sum "volume" of particles within "surface" of initial star dump + rhovol = rhovol + particlemass / rhopart + npart_a = npart_a + 1 ! Count number of particles within "surface" of initial star dump + endif + ! Calculate residual of Virial theorem for fluid + if (ieos == 2) then + call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,gamma_local=gamma) + else + call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) + endif + virialintegral = virialintegral + 3. * ponrhoi * particlemass + enddo + virialpart = virialpart / (abs(totepot) + 2.*abs(totekin)) ! Normalisation for the virial + virialfluid = (virialintegral + totepot) / (abs(virialintegral) + abs(totepot)) + + ! Sort particles within "surface" by radius + call indexxfunc(npart_a,r2func_origin,xyzh,iorder_a) + + mean_rad_num = npart / 200 ! 0.5 percent of particles + star_stability = 0. + ! Loop over the outermost npart/200 particles that are within the "surface" + do i = npart_a - mean_rad_num,npart_a + j = iorder(i) + k = iorder_a(i) + star_stability(ipartrad) = star_stability(ipartrad) + separation(xyzh(1:3,j),xyzmh_ptmass(1:3,1)) + star_stability(ipart2hrad) = star_stability(ipart2hrad) + separation(xyzh(1:3,j),xyzmh_ptmass(1:3,1)) + xyzh(4,j) + star_stability(ipdensrad) = star_stability(ipdensrad) + separation(xyzh(1:3,k),xyzmh_ptmass(1:3,1)) + star_stability(ip2hdensrad) = star_stability(ip2hdensrad) + separation(xyzh(1:3,k),xyzmh_ptmass(1:3,1)) + xyzh(4,j) + enddo + + star_stability(ipartrad) = star_stability(ipartrad) / real(mean_rad_num) + star_stability(ipart2hrad) = star_stability(ipart2hrad) / real(mean_rad_num) + star_stability(ipdensrad) = star_stability(ipdensrad) / real(mean_rad_num) + star_stability(ip2hdensrad) = star_stability(ip2hdensrad) / real(mean_rad_num) + star_stability(ivoleqrad) = (3. * totvol/(4. * pi))**(1./3.) + star_stability(idensrad) = (3. * rhovol/(4. * pi))**(1./3.) + star_stability(ivirialpart) = virialpart + star_stability(ivirialfluid)= virialfluid + + if (dump_number == 0) then + init_radius = star_stability(ivoleqrad) + endif + + star_stability(imassout) = 0. + total_mass = xyzmh_ptmass(4,1) + do i = 1,npart + if (separation(xyzmh_ptmass(1:3,1),xyzh(1:3,i)) > init_radius) then + star_stability(imassout) = star_stability(imassout) + particlemass + endif + total_mass = total_mass + particlemass + enddo + + star_stability(imassfracout) = star_stability(imassout) / total_mass + call write_time_file('star_stability', columns, time, star_stability, ncols, dump_number) + deallocate(columns,star_stability,iorder,iorder_a) + +end subroutine star_stabilisation_suite + + +!---------------------------------------------------------------- +!+ +! Print simulation parameters +!+ +!---------------------------------------------------------------- +subroutine print_simulation_parameters(npart,particlemass) + integer, intent(in) :: npart + real, intent(in) :: particlemass + integer :: i + + write(*,"(/,3(a,es10.3,1x),a)") ' Mass: ',umass, 'g Length: ',udist, 'cm Time: ',utime,'s' + write(*,"(3(a,es10.3,1x),a)") ' Density: ',unit_density, 'g/cm^3 Energy: ',unit_energ,'erg En/m: ',unit_ergg,'erg/g' + write(*,"(3(a,es10.3,1x),a)") ' Velocity: ',unit_velocity,'cm/s Bfield: ',unit_Bfield,'G Pressure: ',& + unit_pressure,'g/cm s^2' + write(*,"(2(a,es10.3,1x),/)") ' G: ', gg*umass*utime**2/udist**3,' c: ',c*utime/udist + + do i=1,nptmass + if (xyzmh_ptmass(4,i) > 0.) then + write(*,'(A,I2,A,ES10.3,A,ES10.3)') 'Point mass ',i,': M = ',xyzmh_ptmass(4,i),' and h_soft = ',xyzmh_ptmass(ihsoft,i) + endif + enddo + write(*,"(A,ES10.3)") 'Sink-sink separation: ', separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) + + write(*,'(A,I7,A,ES10.3)') 'Gas particles : ',npart,' particles, each of mass ',particlemass + +end subroutine print_simulation_parameters + + +!---------------------------------------------------------------- +!+ +! Write quantities (up to four) to divv file +!+ +!---------------------------------------------------------------- +subroutine output_divv_files(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 + 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,& + dum1,dum2,dum3,dum4,dum5 + 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, parameter :: Scrit = 2. ! Critical saturation ratio + logical :: verbose = .false. + + allocate(quant(4,npart)) + Nquantities = 14 + if (dump_number == 0) then + print "(14(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) + endif + + ! 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 + + !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)) + 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 + epsC = eps(3) - nucleation(idK3,i) + if (epsC < 0.) then + print *,'eps(C) =',eps(3),', K3=',nucleation(idK3,i),', epsC=',epsC,', T=',tempi,' rho=',rho_cgs + print *,'JKmuS=',nucleation(:,i) + stop '[S-dust_formation] epsC < 0!' + endif + if (tempi > 450.) then + !call chemical_equilibrium_light to obtain pC, and pC2H2 + call chemical_equilibrium_light(rho_cgs, tempi, epsC, pC, pC2, pC2H, pC2H2, nucleation(idmu,i), nucleation(idgamma,i)) + S = pC/psat_C(tempi) + if (S > Scrit) then + !call nucleation_function to obtain JstarS + call calc_nucleation(tempi, pC, 0., 0., 0., pC2H2, S, JstarS, taustar, taugr) + JstarS = JstarS/ nH_tot + endif + endif + !Check if the variables have meaningful values close to condensation temperatures + if (tempi >= 1400. .and. tempi <= 1500. .and. verbose ) then + print *,'size(nucleation,1) = ',size(nucleation,1) + print *,'size(nucleation,2) = ',size(nucleation,2) + print *,'nucleation(idK3,i) = ',nucleation(idK3,i) + 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 + case default + print*,"Error: Requested quantity is invalid." + stop + 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) + enddo + close(iu) + deallocate(quant) + +end subroutine output_divv_files + + + +!!!!! EoS surfaces !!!!! +subroutine eos_surfaces + integer :: i, j, ierr + real :: rho_array(1000) = (/ (10**(i/10000.), i=-180000,-30150,150) /) + real :: eni_array(1000) = (/ (10**(i/10000.), i=120000,149970,30) /) + real :: temp_array(400) = (/ (10**(i/1000.), i=3000,6990,10) /) + real :: kappa_array(1000,400) + real :: gam1_array(1000,1000) + real :: pres_array(1000,1000) + real :: dum(1000,1000) + real :: kappat, kappar + + + do i=1,size(rho_array) + do j=1,size(eni_array) + if (j < size(temp_array) + 1) then + call get_eos_kappa_mesa(rho_array(i),temp_array(j),kappa_array(i,j),kappat,kappar) + endif + call get_eos_pressure_temp_gamma1_mesa(rho_array(i),eni_array(j),pres_array(i,j),dum(i,j),gam1_array(i,j),ierr) + !call get_eos_pressure_temp_mesa(rho_array(i),eni_array(j),pres_array(i,j),temp) + !pres_array(i,j) = eni_array(j)*rho_array(i)*0.66667 / pres_array(i,j) + enddo + enddo + + open(unit=1000,file='mesa_eos_pressure.out',status='replace') + + !Write data to file + do i=1,1000 + write(1000,"(1000(3x,es18.11e2,1x))") pres_array(i,:) + enddo + + close(unit=1000) + + open(unit=1002,file='mesa_eos_gamma.out',status='replace') + + !Write data to file + do i=1,1000 + write(1002,"(1000(3x,es18.11e2,1x))") gam1_array(i,:) + enddo + + close(unit=1002) + + open(unit=1001,file='mesa_eos_kappa.out',status='replace') + + !Write data to file + do i=1,1000 + write(1001,"(400(3x,es18.11e2,1x))") kappa_array(i,:) + enddo + + close(unit=1001) + +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 + use mesa_microphysics, only:getvalue_mesa + use ionization_mod, only:ionisation_fraction + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + integer, parameter :: nparttotrack=10,ncols=17 + real :: r,v,rhopart,ponrhoi,Si,spsoundi,tempi,machi,xh0,xh1,xhe0,xhe1,xhe2,& + ekini,einti,epoti,ethi,etoti,dum,phii,pgas,mu + 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 /) + columns = (/ ' r',& + ' v',& + ' rho',& + ' temp',& + 'entropy',& + 'spsound',& + ' mach',& + ' ekin',& + ' epot',& + ' eth',& + ' eint',& + ' etot',& + ' xHI',& + ' xHII',& + ' xHeI',& + ' xHeII',& + ' xHeIII' /) + + call compute_energies(time) + + do i=1,nparttotrack + write (filenames(i),"(a1,i7.7)") "p", partID(i) + enddo + + do k=1,nparttotrack + i = partID(k) + 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) + 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 + 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 + 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) + 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) + + ! Write file + datatable = (/ r,v,rhopart,eos_vars(itemp,i),Si,spsoundi,machi,ekini,epoti,ethi,einti,etoti,xh0,xh1,xhe0,xhe1,xhe2 /) + call write_time_file(trim(adjustl(filenames(k))),columns,time,datatable,ncols,dump_number) + enddo + +end subroutine track_particle + + +!---------------------------------------------------------------- +!+ +! Optical depth profile +!+ +!---------------------------------------------------------------- +subroutine tau_profile(time,num,npart,particlemass,xyzh) + use part, only:eos_vars,itemp + integer, intent(in) :: npart,num + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:) + integer :: nbins + real, allocatable :: rad_part(:),kappa_part(:),rho_part(:) + real, allocatable :: kappa_hist(:),rho_hist(:),tau_r(:),sepbins(:) + real :: maxloga,minloga,kappa,kappat,kappar + character(len=17) :: filename + character(len=40) :: data_formatter + integer :: i,unitnum + + call compute_energies(time) + nbins = 500 + + allocate(rad_part(npart),kappa_part(npart),rho_part(npart)) + rad_part = 0. + kappa_part = 0. + rho_part = 0. + minloga = 0.5 + maxloga = 4.3 + + allocate(rho_hist(nbins),kappa_hist(nbins),sepbins(nbins),tau_r(nbins)) + filename = ' grid_tau.ev' + + do i=1,npart + rho_part(i) = rhoh(xyzh(4,i), particlemass) + rad_part(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) + call get_eos_kappa_mesa(rho_part(i)*unit_density,eos_vars(itemp,i),kappa,kappat,kappar) + kappa_part(i) = kappa ! In cgs units? + enddo + + call histogram_setup(rad_part(1:npart),kappa_part,kappa_hist,npart,maxloga,minloga,nbins,.true.,.true.) + call histogram_setup(rad_part(1:npart),rho_part,rho_hist,npart,maxloga,minloga,nbins,.true.,.true.) + + + ! Integrate optical depth inwards + sepbins = (/ (10**(minloga + (i-1) * (maxloga-minloga)/real(nbins)), i=1,nbins) /) ! Create log-uniform bins + ! Convert to cgs units (kappa has already been outputted in cgs) + rho_hist = rho_hist * unit_density + sepbins = sepbins * udist ! udist should be Rsun in cm + + tau_r(nbins) = 0. + do i=nbins,2,-1 + tau_r(i-1) = tau_r(i) + kappa_hist(i) * rho_hist(i) * (sepbins(i+1) - sepbins(i)) + enddo + + ! Write data row + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + if (num == 0) then + unitnum = 1000 + open(unit=unitnum,file=trim(adjustl(filename)),status='replace') + write(unitnum, "(a)") '# Optical depth profile' + close(unit=unitnum) + endif + unitnum=1002 + open(unit=unitnum,file=trim(adjustl(filename)), position='append') + write(unitnum,data_formatter) time,tau_r + close(unit=unitnum) + deallocate(rad_part,kappa_part,rho_part) + deallocate(rho_hist,kappa_hist,sepbins,tau_r) + +end subroutine tau_profile + +!---------------------------------------------------------------- +!+ +! Sound crossing time profile +!+ +!---------------------------------------------------------------- +subroutine tconv_profile(time,num,npart,particlemass,xyzh,vxyzu) + use part, only:itemp + use eos, only:get_spsound + use units, only:unit_velocity + integer, intent(in) :: npart,num + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + integer :: nbins + real, allocatable :: rad_part(:),cs_part(:) + real, allocatable :: cs_hist(:),tconv(:),sepbins(:) + real :: maxloga,minloga,rhoi + character(len=17) :: filename + character(len=40) :: data_formatter + integer :: i,unitnum + + call compute_energies(time) + nbins = 500 + allocate(rad_part(npart),cs_part(npart)) + rad_part = 0. + cs_part = 0. + minloga = 0.5 + maxloga = 4.3 + + allocate(cs_hist(nbins),sepbins(nbins),tconv(nbins)) + filename = ' grid_tconv.ev' + + do i=1,npart + rhoi = rhoh(xyzh(4,i), particlemass) + rad_part(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) + cs_part(i) = get_spsound(eos_type=ieos,xyzi=xyzh(:,i),rhoi=rhoi,vxyzui=vxyzu(:,i),gammai=gamma,mui=gmw,Xi=X_in,Zi=Z_in) + enddo + + call histogram_setup(rad_part(1:npart),cs_part,cs_hist,npart,maxloga,minloga,nbins,.true.,.true.) + + ! Integrate sound-crossing time from surface inwards + sepbins = (/ (10**(minloga + (i-1) * (maxloga-minloga)/real(nbins)), i=1,nbins) /) ! Create log-uniform bins + ! Convert to cgs units + cs_hist = cs_hist * unit_velocity + sepbins = sepbins * udist ! udist should be Rsun in cm + + tconv(nbins) = 0. + do i=nbins,2,-1 + if (cs_hist(i) < tiny(1.)) then + tconv(i-1) = tconv(i) + else + tconv(i-1) = tconv(i) + (sepbins(i+1) - sepbins(i)) / cs_hist(i) + endif + enddo + + ! Write data row + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + if (num == 0) then + unitnum = 1000 + open(unit=unitnum,file=trim(adjustl(filename)),status='replace') + write(unitnum, "(a)") '# Sound crossing time profile' + close(unit=unitnum) + endif + unitnum=1002 + open(unit=unitnum,file=trim(adjustl(filename)), position='append') + write(unitnum,data_formatter) time,tconv + close(unit=unitnum) + + deallocate(rad_part,cs_part) + +end subroutine tconv_profile + + +!---------------------------------------------------------------- +!+ +! Histogram of optical depth at hydrogen recombination +!+ +!---------------------------------------------------------------- +subroutine recombination_tau(time,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + use ionization_mod, only:ionisation_fraction + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + integer :: nbins + integer, allocatable :: recombined_pid(:) + real, allocatable :: rad_part(:),kappa_part(:),rho_part(:) + real, allocatable, save:: tau_recombined(:) + 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 + real, parameter :: recomb_th=0.9 + integer :: i,j,nrecombined,bin_ind + + call compute_energies(time) + allocate(rad_part(npart),kappa_part(npart),rho_part(npart),recombined_pid(npart)) + rad_part = 0. + kappa_part = 0. + rho_part = 0. + nbins = 300 ! Number of radial bins + minloga = 0.5 + maxloga = 4.3 + allocate(rho_hist(nbins),kappa_hist(nbins),sepbins(nbins),sepbins_cm(nbins),tau_r(nbins)) + if (dump_number == 0) then + allocate(tau_recombined(npart),prev_recombined(npart)) + tau_recombined = -1. ! Store tau of newly-recombined particles. -ve data means particle never recombined] + prev_recombined = .false. ! All hydrogen is ionised at the start + endif + + j=0 + do i=1,npart + rho_part(i) = rhoh(xyzh(4,i), particlemass) + rad_part(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) + call equationofstate(ieos,ponrhoi,spsoundi,rho_part(i),xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) + 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_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 + j=j+1 + recombined_pid(j) = i + prev_recombined(i) = .true. + else + prev_recombined(i) = .false. + endif + enddo + nrecombined = j + + call histogram_setup(rad_part(1:npart),kappa_part,kappa_hist,npart,maxloga,minloga,nbins,.true.,.true.) + call histogram_setup(rad_part(1:npart),rho_part,rho_hist,npart,maxloga,minloga,nbins,.true.,.true.) + + ! Integrate optical depth inwards + sepbins = (/ (10.**(minloga + (i-1) * (maxloga-minloga)/real(nbins)), i=1,nbins) /) ! Create log-uniform bins + + ! Convert to cgs units (kappa has already been outputted in cgs) + rho_hist = rho_hist * unit_density + sepbins_cm = sepbins * udist ! udist should be Rsun in g + + ! Integrate bins in tau(r) + tau_r(nbins) = 0. + do i=nbins,2,-1 + tau_r(i-1) = tau_r(i) + kappa_hist(i) * rho_hist(i) * (sepbins_cm(i+1) - sepbins_cm(i)) + enddo + + ! Integrate optical depth for each newly recombined particle + do j=1,nrecombined + i = recombined_pid(j) + bin_ind = 1 + nint( nbins * ( log10(rad_part(i))-minloga ) / (maxloga-minloga) ) ! Find radial bin of recombined particle + tau_recombined(i) = tau_r(bin_ind) + enddo + ! Trick write_time_file into writing my data table + if (dump_number == 320) then + do i=1,npart + call write_time_file("recombination_tau",(/' tau'/),-1.,tau_recombined(i),1,i-1) ! Set num = i-1 so that header will be written for particle 1 and particle 1 only + enddo + endif + deallocate(recombined_pid,rad_part,kappa_part,rho_part) + +end subroutine recombination_tau + + +!---------------------------------------------------------------- +!+ +! Energy histogram +!+ +!---------------------------------------------------------------- +subroutine energy_hist(time,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: filename(:) + 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, allocatable :: quant(:) + logical :: ilogbins + + nhists = 3 + nbins = 500 + allocate(filename(nhists),coord(npart,nhists),hist(nbins),Emin(nhists),Emax(nhists)) + Emin = (/ -0.0446, 0., 0. /) + Emax = (/ 0.0315, 0.0105, 0.0105 /) + ilogbins = .false. + filename = (/ ' hist_kp.ev', & + ' hist_erec.ev', & + ' hist_eth.ev' /) + + allocate(quant(npart)) + quant = (/ (1., i=1,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) + 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 + endif + coord(i,1) = (ekini + epoti)/particlemass + coord(i,2) = vxyzu(4,i) - ethi/particlemass + coord(i,3) = ethi/particlemass + enddo + + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + do i=1,nhists + call histogram_setup(coord(:,i),quant,hist,npart,Emax(i),Emin(i),nbins,.false.,ilogbins) + if (dump_number == 0) then + unitnum = 1000 + open(unit=unitnum,file=trim(adjustl(filename(i))),status='replace') + close(unit=unitnum) + endif + unitnum=1001+i + open(unit=unitnum,file=trim(adjustl(filename(i))),status='old', position='append') + write(unitnum,data_formatter) time,hist + close(unit=unitnum) + enddo + deallocate(filename,coord,hist,Emin,Emax,quant) + +end subroutine energy_hist + + +!---------------------------------------------------------------- +!+ +! Energy profile +!+ +!---------------------------------------------------------------- +subroutine energy_profile(time,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + use eos, only:entropy + use mesa_microphysics, only:getvalue_mesa + use ionization_mod, only:ionisation_fraction + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + integer :: nbins + real, allocatable :: coord(:) + real, allocatable :: hist(:),quant(:,:) + real :: ekini,einti,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 + integer :: i,k,unitnum,ierr,ientropy,nvars + integer, allocatable :: iorder(:) + integer, save :: iquantity + logical :: ilogbins + logical, save :: use_mass_coord + + if (dump_number==0) then + iquantity = 1 + use_mass_coord = .false. + print "(5(/,a))",'1. Energy',& + '2. Entropy',& + '3. Bernoulli energy',& + '4. Ion fractions',& + '5. Sound speed' + call prompt("Select quantity to calculate",iquantity,1,5) + call prompt("Bin in mass coordinates instead of radius?",use_mass_coord) + endif + + nbins = 500 + allocate(hist(nbins)) + if (use_mass_coord) then + mincoord = 3.8405 ! Min. mass coordinate + maxcoord = 12.0 ! Max. mass coordinate + ilogbins = .false. + else + mincoord = 0.5 ! Min. log(r) + maxcoord = 4.3 ! Max. log(r) + ilogbins = .true. + endif + + call compute_energies(time) + + ! Allocate arrays for single variable outputs + if (iquantity==1 .or. iquantity==2 .or. iquantity==3 .or. iquantity==5) then + nvars = 1 + else + nvars = 5 + endif + allocate(filename(nvars),headerline(nvars),quant(npart,nvars),coord(npart)) + + coord = 0. + quant = 0. + select case (iquantity) + case(1) ! Energy + filename = ' grid_Etot.ev' + headerline = '# Energy profile ' + case(2) ! Entropy + filename = ' grid_entropy.ev' + headerline = '# Entropy profile' + select case(ieos) + case(2) + ientropy = 1 + case(12) + ientropy = 2 + case(10,20) + ientropy = 3 + case default + ientropy = -1 + end select + case(3) ! Bernoulli energy (per unit mass) + filename = 'grid_bernoulli.ev' + headerline = '# Bernoulli prof.' + case(4) ! Ion fraction profiles + filename = (/ ' grid_HI.ev', & + ' grid_HII.ev', & + ' grid_HeI.ev', & + ' grid_HeII.ev', & + ' grid_HeIII.ev' /) + headerline = (/ ' # HI', & + ' # HII', & + ' # HeI', & + ' # HeII', & + ' # HeIII' /) + case(5) ! Sound speed + filename = ' grid_cs.ev' + headerline = '# cs profile ' + end select + + allocate(iorder(npart)) + if (use_mass_coord) then + call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) ! Order particles by distance from core + call indexxfunc(npart,r2func_origin,xyzh,iorder) + else + iorder = (/(i, i=1,npart, 1)/) ! Have iorder(k) be same as k + endif + + do k=1,npart + i = iorder(k) ! Loop from innermost to outermost particle + if (use_mass_coord) then + coord(i) = real(k-1) ! Number of particles interior to particle k + else + coord(i) = separation(xyzh(1:3,i),xyzmh_ptmass(1:3,1)) + endif + + 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)) + 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_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) + quant(i,1) = ekini + epoti + ethi + case(2) ! Entropy + if ((ieos==10) .and. (ientropy==2)) 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 + else + mu = gmw + endif + if ((ieos==10) .and. (ientropy==3)) then + quant(i,1) = entropy(rhopart*unit_density,ponrhoi*rhopart*unit_pressure,mu,ientropy,vxyzu(4,i)*unit_ergg,ierr) + else + 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) + 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) + quant(i,1) = xh0 + quant(i,2) = xh1 + quant(i,3) = xhe0 + quant(i,4) = xhe1 + quant(i,5) = xhe2 + case(5) ! Sound speed + quant(i,1) = spsoundi + end select + enddo + + if (use_mass_coord) coord = coord * particlemass + xyzmh_ptmass(4,1) + + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + do i=1,nvars + call histogram_setup(coord,quant(:,i),hist,npart,maxcoord,mincoord,nbins,.true.,ilogbins) + if (dump_number == 0) then + unitnum = 1000 + open(unit=unitnum,file=trim(adjustl(filename(i))),status='replace') + write(unitnum, "(a)") trim(headerline(i)) + close(unit=unitnum) + endif + unitnum=1001+i + open(unit=unitnum,file=trim(adjustl(filename(i))),status='old', position='append') + write(unitnum,data_formatter) time,hist + close(unit=unitnum) + enddo + deallocate(iorder,coord,headerline,filename,quant,hist) + +end subroutine energy_profile + + +!---------------------------------------------------------------- +!+ +! Rotation profiles +!+ +!---------------------------------------------------------------- +subroutine rotation_profile(time,num,npart,xyzh,vxyzu) + use vectorutils, only:cross_product3D + integer, intent(in) :: npart,num + real, intent(in) :: time + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + integer :: nbins + real, allocatable :: rad_part(:) + real, allocatable :: hist_var(:),dist_part(:,:) + real :: minloga,maxloga,sep_vector(3),vel_vector(3),J_vector(3),xyz_origin(3),vxyz_origin(3),omega,vphi + character(len=17), allocatable :: grid_file(:) + character(len=40) :: data_formatter + integer :: i,unitnum,nfiles,iradius + + nbins = 500 + minloga = 0.5 + maxloga = 4.3 + iradius = 1 ! 1: Bin by cylindrical radius; 2: Bin by spherical radius; 3: Bin by cylindrical radius from CM + + nfiles = 2 + allocate(hist_var(nbins),grid_file(nfiles),dist_part(nfiles,npart),rad_part(npart)) + rad_part = 0. + dist_part = 0. + grid_file = (/ ' grid_omega.ev', & + ' grid_Jz.ev' /) + + select case (iradius) + case(1,2) ! Take donor core as origin + xyz_origin = xyzmh_ptmass(1:3,1) + vxyz_origin = vxyz_ptmass(1:3,1) + case(3) ! Take sink CM as origin + xyz_origin = (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)) + vxyz_origin = (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)) + end select + + do i=1,npart + select case (iradius) + case(1,3) ! Bin by cylindrical radius + rad_part(i) = sqrt( dot_product(xyzh(1:2,i) - xyz_origin(1:2), xyzh(1:2,i) - xyz_origin(1:2)) ) + case(2) ! Bin by spherical radius + rad_part(i) = separation(xyzh(1:3,i),xyz_origin) + end select + + call get_gas_omega(xyz_origin,vxyz_origin,xyzh(1:3,i),vxyzu(1:3,i),vphi,omega) + dist_part(1,i) = vphi + + sep_vector = xyzh(1:3,i) - xyz_origin(1:3) + vel_vector = vxyzu(1:3,i) - vxyz_origin(1:3) + call cross_product3D(vel_vector, sep_vector, J_vector) + dist_part(2,i) = dot_product(J_vector, (/0.,0.,1./)) + enddo + + do i=1,nfiles + call histogram_setup(rad_part(1:npart),dist_part(i,1:npart),hist_var,npart,maxloga,minloga,nbins,.true.,.true.) + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + if (num == 0) then + unitnum = 1000 + open(unit=unitnum,file=trim(adjustl(grid_file(i))),status='replace') + write(unitnum, "(a)") '# z-component of angular velocity' + close(unit=unitnum) + endif + unitnum=1001+i + open(unit=unitnum,file=trim(adjustl(grid_file(i))), position='append') + write(unitnum,data_formatter) time,hist_var(:) + close(unit=unitnum) + enddo + deallocate(hist_var,grid_file,dist_part,rad_part) + +end subroutine rotation_profile + + +!---------------------------------------------------------------- +!+ +! Velocity distribution +!+ +!---------------------------------------------------------------- +subroutine velocity_histogram(time,num,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + real, intent(in) :: time,particlemass + integer, intent(in) :: npart,num + real, intent(inout) :: 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, 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_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))) + + if (ekini+epoti > 0.) then + vbound(i) = -1.e15 + vunbound(i) = vr(i) + else + vbound(i) = vr(i) + vunbound(i) = -1.e15 + endif + enddo + + ncols = npart + write(data_formatter, "(a,I6.6,a)") "(", ncols+1, "(2x,es18.11e2))" + file_name1 = "vel_bound.ev" + file_name2 = "vel_unbound.ev" + + if (dump_number == 0) then + open(newunit=iu1,file=file_name1,status='replace') + open(newunit=iu2,file=file_name2,status='replace') + else + open(newunit=iu1,file=file_name1, position='append') + open(newunit=iu2,file=file_name2, position='append') + endif + + write(iu1,data_formatter) time,vbound + write(iu2,data_formatter) time,vunbound + close(unit=iu1) + close(unit=iu2) + + deallocate(vbound,vunbound,vr) + +end subroutine velocity_histogram + + +!---------------------------------------------------------------- +!+ +! Velocity profile +!+ +!---------------------------------------------------------------- +subroutine velocity_profile(time,num,npart,particlemass,xyzh,vxyzu) + real, intent(in) :: time,particlemass + integer, intent(in) :: npart,num + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=40) :: data_formatter + character(len=40) :: file_name + integer :: i,nbins,iu,count + real :: rmin,rmax,xyz_origin(3),vxyz_origin(3),vphi,omega,& + theta1,theta2,tantheta1,tantheta2,tantheta + real, allocatable, dimension(:) :: rad_part,dist_part,hist + + nbins = 500 + rmin = 0. + rmax = 5. + + allocate(hist(nbins),dist_part(npart),rad_part(npart)) + dist_part = 0. + file_name = ' vphi_profile.ev' + + ! Select origin + xyz_origin = xyzmh_ptmass(1:3,1) + vxyz_origin = vxyz_ptmass(1:3,1) + + ! Masking in polar angle + theta1 = 75. ! Polar angle in deg + theta2 = 105. + tantheta1 = tan(theta1*3.14159/180.) + tantheta2 = tan(theta2*3.14159/180.) + + count = 0 + do i = 1,npart + rad_part(i) = sqrt( dot_product(xyzh(1:2,i) - xyz_origin(1:2), xyzh(1:2,i) - xyz_origin(1:2)) ) ! Cylindrical radius + + ! Masking in polar angle + tantheta = rad_part(i)/(xyzh(3,i) - xyzmh_ptmass(3,1)) + if ( (tantheta>0. .and. tanthetatantheta2) ) cycle + + call get_gas_omega(xyz_origin,vxyz_origin,xyzh(1:3,i),vxyzu(1:3,i),vphi,omega) + dist_part(i) = vphi + count = count + 1 + enddo + + call histogram_setup(rad_part,dist_part,hist,count,rmax,rmin,nbins,.true.,.false.) + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + if (num == 0) then + open(newunit=iu,file=trim(adjustl(file_name)),status='replace') + write(iu, "(a)") '# Azimuthal velocity profile' + close(unit=iu) + endif + open(newunit=iu,file=trim(adjustl(file_name)), position='append') + write(iu,data_formatter) time,hist + close(unit=iu) + deallocate(hist,dist_part,rad_part) + +end subroutine velocity_profile + + +!---------------------------------------------------------------- +!+ +! Specific z-angular momentum profile +!+ +!---------------------------------------------------------------- +subroutine angular_momentum_profile(time,num,npart,particlemass,xyzh,vxyzu) + real, intent(in) :: time,particlemass + integer, intent(in) :: npart,num + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=40) :: data_formatter + character(len=40) :: file_name + integer :: i,nbins,iu,count + real :: rmin,rmax,xyz_origin(3),vxyz_origin(3),& + theta1,theta2,tantheta1,tantheta2,tantheta + real, allocatable, dimension(:) :: rad_part,dist_part,hist + + nbins = 500 + rmin = 0. + rmax = 5. + + allocate(hist(nbins),dist_part(npart),rad_part(npart)) + dist_part = 0. + file_name = ' jz_profile.ev' + + ! Select origin + xyz_origin = xyzmh_ptmass(1:3,1) + vxyz_origin = vxyz_ptmass(1:3,1) + + ! Masking in polar angle + theta1 = 75. ! Polar angle in deg + theta2 = 105. + tantheta1 = tan(theta1*3.14159/180.) + tantheta2 = tan(theta2*3.14159/180.) + + count = 0 + do i = 1,npart + rad_part(i) = sqrt( dot_product(xyzh(1:2,i) - xyz_origin(1:2), xyzh(1:2,i) - xyz_origin(1:2)) ) ! Cylindrical radius + + ! Masking in polar angle + tantheta = rad_part(i)/(xyzh(3,i) - xyzmh_ptmass(3,1)) + if ( (tantheta>0. .and. tanthetatantheta2) ) cycle + + dist_part(i) = ( (xyzh(1,i)-xyz_origin(1))*(vxyzu(2,i)-vxyz_origin(2)) - & + (xyzh(2,i)-xyz_origin(2))*(vxyzu(1,i)-vxyz_origin(1)) ) + count = count + 1 + enddo + + call histogram_setup(rad_part,dist_part,hist,count,rmax,rmin,nbins,.true.,.false.) + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + if (num == 0) then + open(newunit=iu,file=trim(adjustl(file_name)),status='replace') + write(iu, "(a)") '# z-angular momentum profile' + close(unit=iu) + endif + open(newunit=iu,file=trim(adjustl(file_name)), position='append') + write(iu,data_formatter) time,hist + close(unit=iu) + +end subroutine angular_momentum_profile + + +!---------------------------------------------------------------- +!+ +! Keplerian velocity profile +!+ +!---------------------------------------------------------------- +subroutine vkep_profile(time,num,npart,particlemass,xyzh,vxyzu) + use sortutils, only:set_r2func_origin,r2func_origin,find_rank + use part, only:iorder=>ll + real, intent(in) :: time,particlemass + integer, intent(in) :: npart,num + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=40) :: data_formatter,file_name + integer :: i,nbins,iu + real :: rmin,rmax,massi,Mtot + real, allocatable :: hist(:),rad_part(:),dist_part(:) + + nbins = 500 + rmin = 0. + rmax = 5. + + allocate(hist(nbins),rad_part(npart),dist_part(npart)) + dist_part = 0. + file_name = ' vkep_profile.ev' + + call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) + call find_rank(npart,r2func_origin,xyzh(1:3,:),iorder) + + Mtot = npart*particlemass + do i = 1,npart + massi = Mtot * real(iorder(i)-1) / real(npart) + xyzmh_ptmass(4,1) + rad_part(i) = separation( xyzh(1:3,i), xyzmh_ptmass(1:3,1) ) + dist_part(i) = sqrt(massi/rad_part(i)) + enddo + + call histogram_setup(rad_part,dist_part,hist,npart,rmax,rmin,nbins,.true.,.false.) + write(data_formatter, "(a,I5,a)") "(", nbins+1, "(3x,es18.10e3,1x))" + if (num == 0) then + open(newunit=iu,file=trim(adjustl(file_name)),status='replace') + write(iu, "(a)") '# Keplerian velocity profile' + close(unit=iu) + endif + open(newunit=iu,file=trim(adjustl(file_name)), position='append') + write(iu,data_formatter) time,hist + close(unit=iu) + deallocate(hist,dist_part,rad_part) + +end subroutine vkep_profile + + +!---------------------------------------------------------------- +!+ +! Planet profile +!+ +!---------------------------------------------------------------- +subroutine planet_profile(num,dumpfile,particlemass,xyzh,vxyzu) + character(len=*), intent(in) :: dumpfile + integer, intent(in) :: num + real, intent(in) :: particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=40) :: file_name + integer :: i,maxrho_ID,iu + integer, save :: nplanet + integer, allocatable, save :: planetIDs(:) + real :: rhoprev + real, dimension(3) :: planet_com,planet_vcom,vnorm,ri,Rvec + real, allocatable :: R(:),z(:),rho(:) + + if (dump_number ==0 ) call get_planetIDs(nplanet,planetIDs) + allocate(R(nplanet),z(nplanet),rho(nplanet)) + + ! Find highest density in planet + rhoprev = 0. + maxrho_ID = planetIDs(1) + do i = 1,nplanet + rho(i) = rhoh(xyzh(4,planetIDs(i)), particlemass) + if (rho(i) > rhoprev) then + maxrho_ID = planetIDs(i) + rhoprev = rho(i) + endif + enddo + planet_com = xyzh(1:3,maxrho_ID) + planet_vcom = vxyzu(1:3,maxrho_ID) + vnorm = planet_vcom / sqrt(dot_product(planet_vcom,planet_vcom)) + + ! Write to file + file_name = trim(dumpfile)//".planetpart" + open(newunit=iu,file=file_name,status='replace') + + ! Record R and z cylindrical coordinates w.r.t. planet_com + do i = 1,nplanet + ri = xyzh(1:3,planetIDs(i)) - planet_com ! Particle position w.r.t. planet_com + z(i) = dot_product(ri, vnorm) + Rvec = ri - z(i)*vnorm + R(i) = sqrt(dot_product(Rvec,Rvec)) + ! write(iu,"(es13.6,2x,es13.6,2x,es13.6)") R(i),z(i),rho(i) + write(iu,"(es13.6,2x,es13.6,2x,es13.6,2x,es13.6,2x,es13.6)") xyzh(1,i),xyzh(2,i),xyzh(3,i),rho(i),vxyzu(4,i) + enddo + + close(unit=iu) + deallocate(R,z,rho) + +end subroutine planet_profile + + +!---------------------------------------------------------------- +!+ +! Unbound profiles +!+ +!---------------------------------------------------------------- +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 + + call compute_energies(time) + npart_hist = 0 ! Stores number of particles fulfilling each of the four bound/unbound criterion + nbins = 500 + rad_part = 0. ! (4,npart_hist)-array storing separations of particles + dist_part = 0. + 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' /) + + if (dump_number == 0) then + allocate(prev_bound(2,npart)) + allocate(prev_unbound(2,npart)) + prev_bound = .false. + prev_unbound = .false. + 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 + endif + 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,& + .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') + 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') + + write(unitnum,"()") + write(unitnum,data_formatter) time,hist_var(:) + + close(unit=unitnum) + enddo + deallocate(hist_var) + +end subroutine unbound_profiles + + +!---------------------------------------------------------------- +!+ +! Unbound ion fractions: Look at distribution of ion fraction when given particle is unbound +!+ +!---------------------------------------------------------------- +subroutine unbound_ionfrac(time,npart,particlemass,xyzh,vxyzu) + use ionization_mod, only:get_xion,ionisation_fraction + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17) :: columns(5) + integer :: i + real :: etoti,ekini,einti,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(:,:) + + columns = (/' xion1', & + ' xion2', & + ' xion3', & + ' xion4', & + ' 1-xion3' /) + + if (dump_number == 0) then + allocate(prev_unbound(npart),prev_bound(npart)) + prev_bound = .false. + prev_unbound = .false. + allocate(ionfrac(npart,5)) + ionfrac = -1. ! Initialise ion states to -1 + endif + + call compute_energies(time) + 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_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,tempi,ethi) + etoti = ekini + epoti + ethi + + if ((etoti > 0.) .and. (.not. prev_unbound(i))) then + if (ieos == 10) then ! MESA EoS + call ionisation_fraction(rhopart*unit_density,tempi,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) + elseif (ieos == 20) then ! Gas + radiation + recombination EoS + call get_xion(log10(rhopart*unit_density),tempi,X_in,1.-X_in-Z_in,xion) + xh0 = xion(1) ! H2 ionisation fraction + xh1 = xion(2) ! H ionisation fraction + xhe1 = xion(3) ! He ionisation to He+ fraction + xhe2 = xion(4) ! He+ ionisation to He++ fraction + xhe0 = 1.-xion(3) + else ! Not supported + print*,"Error, not sensible to use unbound_ionfrac when not using MESA EoS (ieos=10) or gas+rad+rec EoS (ieos=20)" + stop + endif + ionfrac(i,1) = xh0 + ionfrac(i,2) = xh1 + ionfrac(i,3) = xhe1 + ionfrac(i,4) = xhe2 + ionfrac(i,5) = xhe0 + prev_unbound(i) = .true. + elseif (etoti < 0.) then + prev_unbound(i) = .false. + endif + enddo + + ! Trick write_time_file into writing my data table + print*,'Dump number is ',dump_number + if (dump_number == 258) then + do i=1,npart + call write_time_file("unbound_ionfrac",columns,-1.,ionfrac(i,1:5),5,i-1) ! Set num = i-1 so that header will be written for particle 1 and particle 1 only + enddo + endif + +end subroutine unbound_ionfrac + + +!---------------------------------------------------------------- +!+ +! Unbound temperature +!+ +!---------------------------------------------------------------- +subroutine unbound_temp(time,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + use ionization_mod, only:get_xion + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17) :: columns(1) + integer :: i,final_count(7) + real :: etoti,ekini,einti,epoti,ethi,phii,dum,rhopart,& + ponrhoi,spsoundi,temp_bins(7) + logical, allocatable, save :: prev_unbound(:),prev_bound(:) + real, allocatable, save :: temp_unbound(:) + + columns = (/' temp'/) + + if (dump_number == 0) then + allocate(prev_unbound(npart),prev_bound(npart),temp_unbound(npart)) + prev_bound = .false. + prev_unbound = .false. + temp_unbound = 0. ! Initialise temperatures to 0. + endif + + 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_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhopart,eos_vars(itemp,i),ethi) + etoti = ekini + epoti + ethi + + if ((etoti > 0.) .and. (.not. prev_unbound(i))) then + temp_unbound(i) = eos_vars(itemp,i) + prev_unbound(i) = .true. + elseif (etoti < 0.) then + prev_unbound(i) = .false. + endif + enddo + + print*,'dump_number=',dump_number + ! Trick write_time_file into writing my data table + if (dump_number == 167) then + temp_bins = (/ 2.e3, 5.5e3, 8.e3, 1.5e4, 2.e4, 4.e4, 1.e15 /) + final_count = 0 + do i=1,npart + if (temp_unbound(i) > 1.e-15) then + if (temp_unbound(i) < temp_bins(1)) then + final_count(1:7) = final_count(1:7) + 1 + elseif (temp_unbound(i) < temp_bins(2)) then + final_count(2:7) = final_count(2:7) + 1 + elseif (temp_unbound(i) < temp_bins(3)) then + final_count(3:7) = final_count(3:7) + 1 + elseif (temp_unbound(i) < temp_bins(4)) then + final_count(4:7) = final_count(4:7) + 1 + elseif (temp_unbound(i) < temp_bins(5)) then + final_count(5:7) = final_count(5:7) + 1 + elseif (temp_unbound(i) < temp_bins(6)) then + final_count(6:7) = final_count(6:7) + 1 + elseif (temp_unbound(i) < temp_bins(7)) then + final_count(7) = final_count(7) + 1 + endif + endif + call write_time_file("unbound_temp",columns,-1.,temp_unbound(i),1,i-1) ! Set num = i-1 so that header will be written for particle 1 and particle 1 only + enddo + + print*,final_count + endif + +end subroutine unbound_temp + + +!---------------------------------------------------------------- +!+ +! Recombination statistics +!+ +!---------------------------------------------------------------- +subroutine recombination_stats(time,num,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + use ionization_mod, only:ionisation_fraction + 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 + character(len=40) :: data_formatter,logical_format + logical, allocatable :: isbound(:) + integer, allocatable :: H_state(:),He_state(:) + integer :: i + real, parameter :: recomb_th=0.05 + + call compute_energies(time) + + allocate(isbound(npart),H_state(npart),He_state(npart)) + do i=1,npart + ! 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 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) + + ! Is unbound? + if (etoti > 0.) then + isbound(i) = .false. + else + isbound(i) = .true. + endif + + ! H ionisation state + if (xh0 > recomb_th) then + H_state(i) = 1 + elseif (xh1 > recomb_th) then + H_state(i) = 2 + else + H_state(i) = 0 ! This should not happen + endif + + ! H ionisation state + if (xhe0 > recomb_th) then + He_state(i) = 1 + elseif (xhe1 > recomb_th) then + He_state(i) = 2 + elseif (xhe2 > recomb_th) then + He_state(i) = 3 + else + He_state(i) = 0 ! This should not happen + 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 + + if (num == 0) then ! Write header line + open(unit=1000,file="H_state.ev",status='replace') + write(1000, "(a)") '# Ion fraction statistics' + close(unit=1000) + open(unit=1001,file="He_state.ev",status='replace') + write(1001, "(a)") '# Ion fraction statistics' + close(unit=1001) + open(unit=1002,file="isbound.ev",status='replace') + write(1002, "(a)") '# Ion fraction statistics' + close(unit=1002) + endif + + open(unit=1000,file="H_state.ev", position='append') + 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=1000,file="isbound.ev", position='append') + write(1000,logical_format) time,isbound(:) + close(unit=1000) + + deallocate(isbound,H_state,He_state) + +end subroutine recombination_stats + + +!---------------------------------------------------------------- +!+ +! Sink properties +!+ +!---------------------------------------------------------------- +subroutine sink_properties(time,npart,particlemass,xyzh,vxyzu) + use vectorutils, only:cross_product3D + integer, intent(in) :: npart + real, intent(in) :: time, particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + character(len=17) :: filename + real :: sinkcomp(35) + real :: ang_mom(3) + real :: phitot, dtsinksink, fonrmax + real :: fxi, fyi, fzi, phii + real, dimension(4,maxptmass) :: fssxyz_ptmass + real, dimension(4,maxptmass) :: fxyz_ptmass + real, dimension(3,maxptmass) :: dsdt_ptmass + real, dimension(3) :: com_xyz,com_vxyz + integer :: i,ncols,merge_n,merge_ij(nptmass) + + ncols = 31 + allocate(columns(ncols)) + columns = (/' x', & + ' y', & + ' z', & + ' r', & + ' vx', & + ' vy', & + ' vz', & + ' |v|', & + ' px', & + ' py', & + ' pz', & + ' |p|', & + ' fssx', & + ' fssy', & + ' fssz', & + ' |fss|', & + ' fsx', & + ' fsy', & + ' fsz', & + ' |fs|', & + ' ang mom x', & + ' ang mom y', & + ' ang mom z', & + ' |ang mom|', & + ' kin en', & + ' CoM x ', & + ' CoM y ', & + ' CoM z ', & + ' CoM vx', & + ' CoM vy', & + ' CoM vz' /) + + fxyz_ptmass = 0. + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) + fssxyz_ptmass = fxyz_ptmass + do i=1,npart + call get_accel_sink_gas(nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass,& + fxi,fyi,fzi,phii,particlemass,fxyz_ptmass,dsdt_ptmass,fonrmax) + enddo + + ! Determine position and velocity of the CoM + call orbit_com(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,com_xyz,com_vxyz) + + do i=1,nptmass + sinkcomp = 0. + write (filename, "(A16,I0)") "sink_properties_", i + + ! position xyz + sinkcomp(1:3) = xyzmh_ptmass(1:3,i) + ! position modulus + sinkcomp(4) = distance(xyzmh_ptmass(1:3,i)) + ! velocity xyz + sinkcomp(5:7) = vxyz_ptmass(1:3,i) + ! velocity modulus + sinkcomp(8) = distance(vxyz_ptmass(1:3,i)) + ! momentum xyz + sinkcomp(9:11) = xyzmh_ptmass(4,i)*vxyz_ptmass(1:3,i) + ! momentum modulus + sinkcomp(12) = xyzmh_ptmass(4,i)*sinkcomp(8) + ! force xyz + sinkcomp(13:15) = fssxyz_ptmass(1:3,i) + ! force modulus + sinkcomp(16) = distance(fssxyz_ptmass(1:3,i)) + ! tot force xyz + sinkcomp(17:19) = fxyz_ptmass(1:3,i) + ! tot force modulus + sinkcomp(20) = distance(fxyz_ptmass(1:3,i)) + ! angular momentum xyz + call cross_product3D(xyzmh_ptmass(1:3,i), xyzmh_ptmass(4,i)*vxyz_ptmass(1:3,i), ang_mom) + sinkcomp(21:23) = ang_mom + ! angular momentum modulus + sinkcomp(24) = distance(ang_mom(1:3)) + ! kinetic energy + sinkcomp(25) = 0.5*xyzmh_ptmass(4,i)*sinkcomp(8)**2 + ! CoM position + sinkcomp(26:28) = com_xyz(1:3) + ! CoM velocity + sinkcomp(29:31) = com_vxyz(1:3) + + call write_time_file(filename, columns, time, sinkcomp, ncols, dump_number) + enddo + deallocate(columns) + +end subroutine sink_properties + + + +subroutine env_binding_ene(npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + integer, intent(in) :: npart + real, intent(in) :: particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + integer :: i + real :: ethi,phii,rhoi,ponrhoi,spsoundi,tempi,dum1,dum2,dum3 + real :: bind_g,bind_th,bind_int,eth_tot,eint_tot + + bind_g = 0. + bind_th = 0. + bind_int = 0. + eint_tot = 0. + eth_tot = 0. + do i=1,npart + ! Gas-gas potential + bind_g = bind_g + poten(i) ! Double counting factor of 1/2 already included in poten + + ! Sink-sink potential + phii = 0. + call get_accel_sink_gas(1,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),xyzmh_ptmass(:,1),dum1,dum2,dum3,phii) ! Include only core particle; no companion + bind_g = bind_g + particlemass * phii + + rhoi = rhoh(xyzh(4,i), particlemass) + call equationofstate(ieos,ponrhoi,spsoundi,rhoi,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) + call calc_thermal_energy(particlemass,ieos,xyzh(:,i),vxyzu(:,i),ponrhoi*rhoi,eos_vars(itemp,i),ethi) + + eth_tot = eth_tot + ethi + eint_tot = eint_tot + particlemass * vxyzu(4,i) + enddo + bind_th = bind_g + eth_tot + bind_int = bind_g + eint_tot + + print*,bind_g*unit_energ, bind_th*unit_energ, bind_int*unit_energ + +end subroutine env_binding_ene + + +subroutine bound_unbound_thermo(time,npart,particlemass,xyzh,vxyzu) + integer, intent(in) :: npart + real, intent(in) :: time, particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + integer :: i, ncols + real, dimension(8) :: entropy_array + real :: etoti, ekini, einti, epoti, phii, rhopart + 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 + integer, parameter :: ient_ub = 2 + integer, parameter :: itemp_b = 3 + integer, parameter :: itemp_ub = 4 + integer, parameter :: ipres_b = 5 + integer, parameter :: ipres_ub = 6 + integer, parameter :: idens_b = 7 + integer, parameter :: idens_ub = 8 + + !zeroes the entropy variable and others + entropy_array = 0. + + !setup + if (dump_number == 0) then + call prompt('Would you like to use thermal energy in the computation of the bound/unbound status?', switch(1),.false.) + endif + + 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) + + rhopart = rhoh(xyzh(4,i), particlemass) + + !gets entropy for the current particle + call get_eos_various_mesa(rhopart*unit_density,vxyzu(4,i) * unit_ergg, & + pres_1,proint_1,peint_1,temp_1,troint_1, & + teint_1,entrop_1,abad_1,gamma1_1,gam_1) + + !sums entropy and other quantities for bound particles and unbound particles + + if (.not. switch(1)) then + etoti = etoti - einti + endif + + if (etoti < 0.0) then !bound + entropy_array(ient_b) = entropy_array(ient_b) + entrop_1 + entropy_array(itemp_b) = entropy_array(itemp_b) + temp_1 + entropy_array(ipres_b) = entropy_array(ipres_b) + pres_1 + entropy_array(idens_b) = entropy_array(idens_b) + rhopart*unit_density + + else !unbound + entropy_array(ient_ub) = entropy_array(ient_ub) + entrop_1 + entropy_array(itemp_ub) = entropy_array(itemp_ub) + temp_1 + entropy_array(ipres_ub) = entropy_array(ipres_ub) + pres_1 + entropy_array(idens_ub) = entropy_array(idens_ub) + rhopart*unit_density + + endif + + enddo + + !average + entropy_array(itemp_b) = entropy_array(itemp_b) / npart + entropy_array(itemp_ub) = entropy_array(itemp_ub) / npart + entropy_array(ipres_b) = entropy_array(ipres_b) / npart + entropy_array(ipres_ub) = entropy_array(ipres_ub) / npart + entropy_array(idens_b) = entropy_array(idens_b) / npart + entropy_array(idens_ub) = entropy_array(idens_ub) / npart + + !writes on file + ncols = 8 + allocate(columns(ncols)) + columns = (/' b entr',& + ' unb entr',& + ' avg b temp',& + ' avg unb temp',& + ' avg b pres',& + ' avg unb pres',& + ' avg b dens',& + ' avg unb dens'/) + call write_time_file('entropy_vs_time', columns, time, entropy_array, ncols, dump_number) + deallocate(columns) +end subroutine bound_unbound_thermo + + +!---------------------------------------------------------------- +!+ +! Gravitational drag +!+ +!---------------------------------------------------------------- +subroutine gravitational_drag(time,npart,particlemass,xyzh,vxyzu) + use prompting, only:prompt + use vectorutils, only:cross_product3D + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + character(len=17) :: filename + integer :: i,j,k,ncols,sizeRcut,vol_npart,merge_ij(nptmass),merge_n + integer, allocatable :: iorder(:) + real, dimension(:), allocatable, save :: ang_mom_old,time_old + real, dimension(:,:), allocatable :: drag_force + real, dimension(4,maxptmass) :: fxyz_ptmass,fxyz_ptmass_sinksink + real, dimension(3,maxptmass) :: dsdt_ptmass + real, dimension(3) :: avg_vel,avg_vel_par,avg_vel_perp,& + com_xyz,com_vxyz,unit_vel,unit_vel_perp,& + pos_wrt_CM,vel_wrt_CM,ang_mom,com_vec,& + unit_sep,unit_sep_perp,vel_contrast_vec,Fgrav + real :: drag_perp,drag_par,drag_perp_proj,& + vel_contrast,mdot,sep,Jdot,R2,& + rho_avg,cs,racc,fonrmax,fxi,fyi,fzi,& + phii,phitot,dtsinksink,interior_mass,sinksinksep,& + volume,vol_mass,vKep,omega,maxsep,cos_psi,mass_coregas,& + com_sink_sep,Fgrav_mag + real, dimension(:), allocatable :: Rcut + real, dimension(:,:,:), allocatable :: force_cut_vec + logical, save :: iacc,icentreonCM + integer, save :: iavgopt + + ! OPTIONS + if (dump_number == 0) then + print*,'Options for averaging gas properties:' + print "(6(/,a))",'1. Average over sphere centred on the companion (not recommended)',& + '2. Average over sphere centred on opposite side of orbit',& + '3. Average over annulus',& + '4. Average over annulus but excluding sphere centred on the companion',& + '5. Average over sphere twice as far on the opposite side of the orbit',& + '6. Average over sphere half as far on the opposite side of the orbit' + iavgopt = 2 + call prompt('Select option above : ',iavgopt,1,6) + icentreonCM = .false. + select case (iavgopt) + case(2,5,6) + call prompt('Centre averaging sphere on the CM (otherwise, centre on primary core)?: ',icentreonCM) + case(3,4) + call prompt('Centre annulus on the CM (otherwise, centre on primary core)?: ',icentreonCM) + end select + + write(*,"(a,i2)") 'Using ieos = ',ieos + if ( xyzmh_ptmass(ihacc,2) > 0 ) then + write(*,"(a,f13.7,a)") 'Companion has accretion radius = ', xyzmh_ptmass(ihacc,2), '(code units)' + write(*,"(a)") 'Will analyse accretion' + iacc = .true. + else + iacc = .false. + endif + endif + + ncols = 31 + allocate(columns(ncols),iorder(npart),force_cut_vec(4,maxptmass,5)) + allocate(drag_force(ncols,nptmass)) + columns = (/' drag_perp', & ! 1 Component of net force (excluding sink-sink) perpendicular to sink separation (projection on (r2-r1) x z) + ' drag_par', & ! 2 Component of net force (excluding sink-sink) projected along sink separation, -(r2-r1) + 'drag_perp_pr', & ! 3 'drag_perp' projected along the -v direction + ' F_dot_v', & ! 4 Dot product of 'drag_perp_pr' and sink velocity (<0 means energy dissipation) + ' drag_torque', & ! 5 torque / r of sink + ' cos_psi', & ! 6 Cosine of angle between (r2-r1) x z and -v + ' Fgrav', & ! 7 Magnitude of gravitational force from core and gas around it inferred from net force minus drag + 'mass_coregas', & ! 8 Mass of core+gas inferred from net force minus drag + ' drag_BHL', & ! 9 Bondi-Hoyle-Lyttleton drag force + ' mdot_BHL', & ! 10 Bond-Hoyle-Lyttleton mass accretion rate + ' v_con', & ! 11 Magnitude of average background gas velocity minus sink velocity, positive when vsink dot vgas < 0 + ' v_con_par', & ! 12 Projection of velocity contrast on -vsink + ' v_Kep', & ! 13 Keplerian velocity of companion, sqrt(M( 0.) then + rho_avg = vol_mass / volume + avg_vel_par(1:3) = dot_product(avg_vel, unit_vel) * unit_vel + avg_vel_perp(1:3) = avg_vel(1:3) - avg_vel_par(1:3) + vel_contrast_vec = avg_vel - vxyz_ptmass(1:3,i) + vel_contrast = sign( distance(vel_contrast_vec), -dot_product(vxyz_ptmass(1:3,i), avg_vel) ) + racc = 2. * xyzmh_ptmass(4,i) / (vel_contrast**2 + cs**2) ! Accretion radius + mdot = 4.*pi * xyzmh_ptmass(4,i)**2 * rho_avg / (cs**2 + vel_contrast**2)**1.5 ! BHL mass accretion rate + endif + + + ! Sum acceleration (fxyz_ptmass) on companion due to gravity of gas particles + force_cut_vec = 0. + fxyz_ptmass = 0. + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) + + sizeRcut = 5 + if (i == 1) allocate(Rcut(sizeRcut)) + call logspace(Rcut,0.4,2.5) + !Rcut = Rcut * racc ! Bin by fraction of accretion radius + Rcut = Rcut * separation( xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2) ) ! Bin by fraction of sink-sink separation + + do j = 1,npart + if (.not. isdead_or_accreted(xyzh(4,j))) then + ! Get total gravitational force from gas + call get_accel_sink_gas(nptmass,xyzh(1,j),xyzh(2,j),xyzh(3,j),xyzh(4,j),xyzmh_ptmass,& + fxi,fyi,fzi,phii,particlemass,fxyz_ptmass,dsdt_ptmass,fonrmax) + ! Get force from gas within distance cutoff + do k = 1,sizeRcut + if ( separation(xyzh(1:3,j), xyzmh_ptmass(1:4,i)) < Rcut(k) ) then + call get_accel_sink_gas(nptmass,xyzh(1,j),xyzh(2,j),xyzh(3,j),xyzh(4,j),xyzmh_ptmass,& + fxi,fyi,fzi,phii,particlemass,force_cut_vec(1:4,:,k),dsdt_ptmass,fonrmax) + endif + enddo + endif + enddo + + ! Calculate angular momentum of companion wrt orbit CoM + pos_wrt_CM = xyzmh_ptmass(1:3,i) - com_xyz(1:3) + vel_wrt_CM = vxyz_ptmass(1:3,i) - com_vxyz(1:3) + call cross_product3D(pos_wrt_CM, xyzmh_ptmass(4,i) * vel_wrt_CM, ang_mom) + Jdot = (ang_mom(3) - ang_mom_old(i)) / (time - time_old(i)) ! Average change in angular momentum + R2 = distance(xyzmh_ptmass(1:3,i) - com_xyz(1:3)) + ang_mom_old(i) = ang_mom(3) ! Set ang_mom_old for next dump + time_old(i) = time + + ! Calculate mass interior to companion + call set_r2func_origin(xyzmh_ptmass(1,3-i),xyzmh_ptmass(2,3-i),xyzmh_ptmass(3,3-i)) ! Order particles by distance from donor core + call indexxfunc(npart,r2func_origin,xyzh,iorder) + sinksinksep = separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) + interior_mass = xyzmh_ptmass(4,3-i) ! Include mass of donor core + select case(iavgopt) + case(5) ! Calculate mass interior to R/2 + maxsep = 2.*sinksinksep + case(6) ! Calculate mass interior to 2*R + maxsep = 0.5*sinksinksep + case default ! Calculate mass interior to R + maxsep = sinksinksep + end select + do j = 1,npart + k = iorder(j) + sep = separation(xyzmh_ptmass(1:3,3-i), xyzh(1:3,k)) + if (sep > maxsep) exit + interior_mass = interior_mass + particlemass + enddo + vKep = sqrt(interior_mass / sinksinksep) + + ! Calculate perpendicular force projected along -v + cos_psi = cos_vector_angle(-unit_sep_perp, -vxyz_ptmass(1:3,i)) ! Theta is angle between (r2-r1) x z and -v + drag_par = - dot_product(fxyz_ptmass(1:3,i),unit_sep) * xyzmh_ptmass(4,i) ! Total force projected along -(r2-r1) + drag_perp = dot_product(fxyz_ptmass(1:3,i),-unit_sep_perp) * xyzmh_ptmass(4,i) ! Total force projected along -(r2-r1) x z + drag_perp_proj = drag_perp / cos_psi ! Perpendicular force projected along -v + + ! Calculate core + gas mass based on projected gravitational force + Fgrav = fxyz_ptmass(1:3,i) * xyzmh_ptmass(4,i) - drag_perp_proj * (-unit_vel) ! Ftot,gas + Fsinksink = Fdrag + Fgrav + call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass_sinksink,phitot,dtsinksink,0,0.,merge_ij,merge_n,dsdt_ptmass) + Fgrav = Fgrav + fxyz_ptmass_sinksink(1:3,i) * xyzmh_ptmass(4,i) + Fgrav_mag = distance(Fgrav) + mass_coregas = Fgrav_mag * sinksinksep**2 / xyzmh_ptmass(4,i) + + ! Calculate CoM inferred from core + gas mass + com_vec = (mass_coregas * xyzmh_ptmass(1:3,3-i) + xyzmh_ptmass(4,i) * xyzmh_ptmass(1:3,i)) / (mass_coregas + xyzmh_ptmass(4,i)) + com_sink_sep = separation(com_vec, xyzmh_ptmass(1:3,i)) + + drag_force(1,i) = drag_perp + drag_force(2,i) = drag_par + drag_force(3,i) = drag_perp_proj + drag_force(4,i) = drag_perp_proj * (-distance(vxyz_ptmass(1:3,i))) + drag_force(5,i) = Jdot / R2 + drag_force(6,i) = cos_psi + drag_force(7,i) = Fgrav_mag + drag_force(8,i) = mass_coregas + drag_force(9,i) = mdot * vel_contrast ! BHL drag force + drag_force(10,i) = mdot + drag_force(11,i) = vel_contrast + drag_force(12,i) = dot_product(vel_contrast_vec, -unit_vel) + drag_force(13,i) = vKep + drag_force(14,i) = interior_mass + drag_force(15,i) = omega + drag_force(16,i) = cs + drag_force(17,i) = rho_avg + drag_force(18,i) = racc + drag_force(19,i) = com_sink_sep + drag_force(20,i) = separation(com_xyz(1:3),xyzmh_ptmass(1:3,i)) + drag_force(21,i) = sinksinksep + drag_force(22,i) = - dot_product(force_cut_vec(1:3,i,1),unit_sep) * xyzmh_ptmass(4,i) + drag_force(23,i) = - dot_product(force_cut_vec(1:3,i,1),unit_sep_perp) * xyzmh_ptmass(4,i) + drag_force(24,i) = - dot_product(force_cut_vec(1:3,i,2),unit_sep) * xyzmh_ptmass(4,i) + drag_force(25,i) = - dot_product(force_cut_vec(1:3,i,2),unit_sep_perp) * xyzmh_ptmass(4,i) + drag_force(26,i) = - dot_product(force_cut_vec(1:3,i,3),unit_sep) * xyzmh_ptmass(4,i) + drag_force(27,i) = - dot_product(force_cut_vec(1:3,i,3),unit_sep_perp) * xyzmh_ptmass(4,i) + drag_force(28,i) = - dot_product(force_cut_vec(1:3,i,4),unit_sep) * xyzmh_ptmass(4,i) + drag_force(29,i) = - dot_product(force_cut_vec(1:3,i,4),unit_sep_perp) * xyzmh_ptmass(4,i) + drag_force(30,i) = - dot_product(force_cut_vec(1:3,i,5),unit_sep) * xyzmh_ptmass(4,i) + drag_force(31,i) = - dot_product(force_cut_vec(1:3,i,5),unit_sep_perp) * xyzmh_ptmass(4,i) + + ! Write to output + write (filename, "(A16,I0)") "sink_drag_", i + call write_time_file(trim(adjustl(filename)), columns, time, drag_force(:,i), ncols, dump_number) + enddo + deallocate(columns,drag_force,force_cut_vec,Rcut) + +end subroutine gravitational_drag + + +subroutine J_E_plane(num,npart,particlemass,xyzh,vxyzu) + use vectorutils, only:cross_product3D + integer, intent(in) :: npart,num + 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, allocatable :: data(:,:) + + ncols = 7 + allocate(columns(ncols),data(ncols,npart)) + columns = (/' E',& + ' Jxcom',& + ' Jycom',& + ' Jzcom',& + ' Jxcore',& + ' Jycore',& + ' Jzcore'/) + + 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) + 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 + call cross_product3D(xyzh(1:3,i)-com_xyz(1:3), vxyz_ptmass(1:3,i)-com_vxyz(1:3), angmom_com) + data(2:4,i) = angmom_com + enddo + + data(1,:) = data(1,:) / particlemass ! specific energy + + call write_file('JEplane','JEplane',columns,data,size(data(1,:)),ncols,num) + deallocate(columns,data) + +end subroutine J_E_plane + +!------------------------------------------------------------------- +!+ +! Planet destruction +!+ +!------------------------------------------------------------------- +subroutine planet_destruction(time,npart,particlemass,xyzh,vxyzu) + use kernel, only:wkern + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + character(len=18) :: filename + real, allocatable :: planetDestruction(:) + integer :: ncols,i,j + real, save :: time_old + real, allocatable, save :: particleRho(:) + character(len=50) :: planetRadiusPromptString + real, allocatable, save :: planetRadii(:) !In units of Rsun + + real, dimension(3) :: currentGasVel, currentVelContrast + real :: currentRho(1) !Is a one element array because sphInterpolation returns a 1 dimensional array. + real :: currentRhoScaled,currentVelContrastScaled,currentPlanetRhoScaled + real :: currentPlanetMassScaled,currentPlanetRadiusScaled + real, allocatable, save :: currentKhAblatedMass(:) + + ncols=5 + allocate(columns(ncols),planetDestruction(ncols)) + columns=(/" rhoGas", & + " kh_rhoCrit", & + " kh_lmax", & + " kh_mdot", & + " kh_ablatedM" /) + + !Kelvin-Helmholtz instability planet destruction as described in "On the survival of brown dwarfs + !and planets by their giant host star" (https://arxiv.org/abs/1210.0879). Description of columns: + !rhoGas: background gas density at sink. In units of g/cm^3. + !kh_rhoCrit: paper equation 5. In units of g/cm^3. + !kh_lmax: paper equation 6. In units of Jupiter radii. + !kh_mdot: paper equation 7. In units of Jupiter mass/year. + !kh_ablatedM: kh_mdot integrated over time. In units of Jupiter masses. + + currentRho = 0. + do i=1,nptmass + if (i==1) cycle !The first sink is assumed to be the core. + + if ((dump_number==0) .and. (i==2)) then !This is only done once. + allocate(planetRadii(nptmass)) + planetRadii=0.1 + do j=2,nptmass + write(planetRadiusPromptString,"(A13,I0,A32)") "Enter planet ",j-1," radius in units of solar radii" + call prompt(planetRadiusPromptString,planetRadii(i),0.0,1.0) + enddo + + allocate(particleRho(npart)) + allocate(currentKhAblatedMass(nptmass)) + + time_old=0.0 + particleRho=getParticleRho(xyzh(4,:),particlemass) + currentKhAblatedMass=0.0 + endif + + + currentRho=sphInterpolation(npart,particlemass,particleRho,xyzh,xyzmh_ptmass(1:3,i),reshape(particleRho,(/1,npart/))) + currentGasVel=sphInterpolation(npart,particlemass,particleRho,xyzh,xyzmh_ptmass(1:3,i),vxyzu(1:3,:)) + currentVelContrast=vxyz_ptmass(1:3,i)-currentGasVel + + currentPlanetRadiusScaled=planetRadii(i)/0.1 !In units of 0.1 Rsun. + currentPlanetMassScaled=xyzmh_ptmass(4,i)*104.74 !In units of 10 jupiter masses. + currentPlanetRhoScaled=(xyzmh_ptmass(4,i)/((4.0/3.0)*pi*(planetRadii(i)**3.0)))*0.44 !In units of 13.34 g/cm^3 + currentRhoScaled=currentRho(1)*59000.0 !In units of 10^-4 g/cm^3. + currentVelContrastScaled=distance(currentVelContrast)*4.37 !In units of 100 km/s. + + planetDestruction(1)=currentRho(1)*5.9 + planetDestruction(2)=3.82*(currentPlanetRhoScaled**(4.0/3.0))*(currentPlanetMassScaled**(2.0/3.0))& + *(currentVelContrastScaled**(-2.0)) + planetDestruction(3)=0.0000263*(currentVelContrastScaled**2.0)*currentRhoScaled*(currentPlanetRhoScaled**((-5.0)/3.0))& + *(currentPlanetMassScaled**((-1.0)/3.0)) + planetDestruction(4)=11.0*currentVelContrastScaled*currentRhoScaled*(currentPlanetRadiusScaled**2.0)& + *(planetDestruction(3)/(currentPlanetRadiusScaled*0.973)) + + currentKhAblatedMass(i)=currentKhAblatedMass(i)+((time-time_old)*planetDestruction(4)*0.0000505) + planetDestruction(5)=currentKhAblatedMass(i) + + + write(filename, "(A17,I0)") "sink_destruction_",i + call write_time_file(filename, columns, time, planetDestruction, ncols, dump_number) + enddo + + time_old=time + + deallocate(columns,planetDestruction) +end subroutine planet_destruction + +!----------------------------------------------------------------------------------------- +!+ +!Binding energy profile +!+ +!----------------------------------------------------------------------------------------- +subroutine create_bindingEnergy_profile(time,num,npart,particlemass,xyzh,vxyzu) + real, intent(in) :: time,particlemass + integer, intent(in) :: num,npart + real, intent(in) :: xyzh(4,npart),vxyzu(4,npart) + + character(len=17), allocatable :: columns(:) + real, allocatable :: profile(:,:) + integer :: ncols,i,j + integer, allocatable :: iorder(:) + real :: currentInteriorMass,currentParticleGPE,currentCoreParticleSeparation + real :: previousBindingEnergy,previousBindingEnergyU + + ncols=3 + allocate(columns(ncols),iorder(npart)) + allocate(profile(ncols,npart)) + columns=(/" radius",& + " bEnergy",& !Binding energy without internal energy. + " bEnergy (u)"/) !Binding energy with internal energy. + + + call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) + call indexxfunc(npart,r2func_origin,xyzh,iorder) + currentInteriorMass=xyzmh_ptmass(4,1)+(npart*particlemass) !Initally set to the entire mass of the star. + + do i=npart,1,-1 !Loops over all particles from outer to inner. + j=iorder(i) + currentInteriorMass=currentInteriorMass-particlemass + currentCoreParticleSeparation=separation(xyzmh_ptmass(1:3,1),xyzh(1:3,j)) + currentParticleGPE=(currentInteriorMass*particlemass)/currentCoreParticleSeparation + + !The binding energy at a particular radius is the sum of the gravitational potential energies + !(and internal energies in the case of the third column) of all particles beyond that radius. + if (i==npart) then + previousBindingEnergy=0.0 + previousBindingEnergyU=0.0 + else + previousBindingEnergy=profile(2,i+1) + previousBindingEnergyU=profile(3,i+1) + endif + + profile(1,i)=currentCoreParticleSeparation + profile(2,i)=previousBindingEnergy+currentParticleGPE + profile(3,i)=previousBindingEnergyU+currentParticleGPE-(vxyzu(4,j)*particlemass) + enddo + + call write_file('bEnergyProfile','bEnergyProfiles',columns,profile,npart,ncols,num) + deallocate(columns,iorder,profile) + +end subroutine create_bindingEnergy_profile + + +subroutine get_core_gas_com(time,npart,xyzh,vxyzu) + use sortutils, only:set_r2func_origin,r2func_origin,indexxfunc + integer, intent(in) :: npart + real, intent(in) :: time + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + real :: sep,maxsep,core_gas_com(3),core_gas_vcom(3),xyz_gas(4,npart),vxyz_gas(3,npart) + real, allocatable :: mytable(:) + character(len=17), allocatable :: columns(:) + character(len=17) :: filename + integer, save :: ngas + integer, allocatable, save :: iorder(:) + integer :: ncols,j,k + + ncols = 12 + allocate(columns(ncols)) + allocate(mytable(ncols)) + mytable = 0. + columns = (/' gas_com_x', & + ' gas_com_y', & + ' gas_com_z', & + ' gas_com_vx', & + ' gas_com_vy', & + ' gas_com_vz', & + ' core_x', & + ' core_y', & + ' core_z', & + ' core_vx', & + ' core_vy', & + ' core_vz' /) + + + ! Record particles that are closest to primary core + if (dump_number == 0) then + allocate(iorder(npart)) + maxsep = 10. ! 10 Rsun + ngas = 0 + call set_r2func_origin(xyzmh_ptmass(1,1),xyzmh_ptmass(2,1),xyzmh_ptmass(3,1)) ! Order particles by distance from donor core + call indexxfunc(npart,r2func_origin,xyzh,iorder) + + do j=1,npart + k = iorder(j) + if (j < 10) print*,k + sep = separation(xyzmh_ptmass(1:3,1), xyzh(1:3,k)) + if (sep > maxsep) exit + ngas = ngas + 1 + enddo + endif + + print*,'ngas=',ngas + + do j=1,ngas + k = iorder(j) + xyz_gas(1:4,j) = xyzh(1:4,k) + vxyz_gas(1:3,j) = vxyzu(1:3,k) + enddo + + call get_centreofmass(core_gas_com,core_gas_vcom,ngas,xyz_gas,vxyz_gas) ! Do not include sinks + + mytable(1:3) = core_gas_com(1:3) + mytable(4:6) = core_gas_vcom(1:3) + mytable(7:9) = xyzmh_ptmass(1:3,1) + mytable(10:12) = vxyz_ptmass(1:3,1) + + write (filename, "(A16,I0)") "core_gas_com" + call write_time_file(trim(adjustl(filename)),columns,time,mytable,ncols,dump_number) +end subroutine get_core_gas_com + + +!---------------------------------------------------------------- +!+ +! Print dump numbers corresponding to given sink-sink separations +!+ +!---------------------------------------------------------------- +subroutine print_dump_numbers(dumpfile) + character(len=*), intent(in) :: dumpfile + character(len=50), allocatable, save :: dumpfiles(:) + integer :: nseps + integer, save :: i + real, allocatable :: sinksinksep(:) + real :: sep + + nseps = 2 + allocate(sinksinksep(nseps)) + if (dump_number == 0) then + allocate(dumpfiles(nseps)) + i=1 + endif + sinksinksep = (/ 938., 67. /) + + sep = separation(xyzmh_ptmass(1:3,1),xyzmh_ptmass(1:3,2)) + if ( sep < sinksinksep(i) ) then + dumpfiles(i) = trim(dumpfile) + i=i+1 + endif + if (i==nseps+1) then + print "(5(a,/))",'../',dumpfiles + return + endif + +end subroutine print_dump_numbers + + +!---------------------------------------------------------------- +!+ +! Analyse disk +!+ +!---------------------------------------------------------------- +subroutine analyse_disk(num,npart,particlemass,xyzh,vxyzu) + use part, only:eos_vars,itemp + use extern_corotate, only:get_companion_force + use vectorutils, only:cross_product3D + integer, intent(in) :: num,npart + real, intent(in) :: particlemass + real, intent(inout) :: xyzh(:,:),vxyzu(:,:) + character(len=17), allocatable :: columns(:) + real, allocatable :: data(:,:) + real :: diskz,diskR2,diskR1,R,omegai,phii,rhopart,ponrhoi,spsoundi,tempi,& + epoti,ekini,ethi,Ji(3),vrel2,fxi,fyi,fzi,vphi + integer :: ncols,i + + ncols = 9 + allocate(columns(ncols),data(ncols,npart)) + data = -1. + columns = (/' R',& ! cylindrical radius w.r.t companion + ' E',& ! specific energy (kin+pot only) w.r.t. companion + ' Omega',& ! angular momentum w.r.t. companion + ' Jx',& ! specific angular momentum components + ' Jy',& + ' Jz',& + ' ekin',& + ' epot',& ! gravitational potential energy due to companion only + ' etherm'/) + + ! Set disk dimensions + diskz = 50. ! disk half-thickness + diskR1 = 5. ! disk inner radius + diskR2 = 150. ! disk outer radius + + do i=1,npart + ! Skip if particle is not within the defined disk + if (abs(xyzh(3,i) - xyzmh_ptmass(3,2)) > diskz) cycle + R = sqrt( (xyzh(1,i) - xyzmh_ptmass(1,2))**2 + (xyzh(2,i) - xyzmh_ptmass(2,2))**2 ) + if ( (R > diskR2) .or. (R < diskR1) ) cycle + + vrel2 = (vxyzu(1,i) - vxyz_ptmass(1,2))**2 + (vxyzu(2,i) - vxyz_ptmass(2,2))**2 + (vxyzu(3,i) - vxyz_ptmass(3,2))**2 + ekini = 0.5*particlemass*vrel2 + + ! Calculate gravitational potential due to companion only + phii = 0. + call get_companion_force(xyzh(1:3,i),fxi,fyi,fzi,phii) + epoti = phii*particlemass + + ! Calculate thermal 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) + + call get_gas_omega(xyzmh_ptmass(1:3,2),vxyz_ptmass(1:3,2),xyzh(1:3,i),vxyzu(1:3,i),vphi,omegai) + call cross_product3D(xyzh(1:3,i)-xyzmh_ptmass(1:3,2), vxyzu(1:3,i)-vxyz_ptmass(1:3,2), Ji) + + data(1,i) = R + data(2,i) = (ekini+epoti) / particlemass + data(3,i) = omegai + data(4:6,i) = Ji + data(7,i) = ekini + data(8,i) = epoti + data(9,i) = ethi + enddo + call write_file('companion_disk','companion_disk',columns,data,npart,ncols,num) + deallocate(columns) + +end subroutine analyse_disk + + +!---------------------------------------------------------------- +!+ +! Recombination energy vs. time +!+ +!---------------------------------------------------------------- +subroutine erec_vs_t(time,npart,particlemass,xyzh) + use ionization_mod, only:get_erec_components + integer, intent(in) :: npart + real, intent(in) :: time,particlemass + real, intent(inout) :: xyzh(:,:) + character(len=17) :: filename,columns(4) + integer :: i + real :: ereci(4),erec(4),tempi,rhoi + + columns = (/' H2', & + ' HI', & + ' HeI', & + ' HeII'/) + + erec = 0. + do i = 1,npart + rhoi = rhoh(xyzh(4,i), particlemass) + call get_erec_components( log10(rhoi*unit_density), tempi, X_in, 1.-X_in-Z_in, ereci) + erec = erec + ereci + enddo + + write (filename, "(A16,I0)") "erec_vs_t" + call write_time_file(trim(adjustl(filename)),columns,time,erec,4,dump_number) + +end subroutine erec_vs_t + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!! Routines used in analysis routines !!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +!---------------------------------------------------------------- +!+ +! Calculate the angular velocity of an envelope gas particle +! relative to a reference point +!+ +!---------------------------------------------------------------- +subroutine get_gas_omega(xyz_centre,vxyz_centre,xyzi,vxyzi,vphi,omega) + use vectorutils, only:cross_product3D + real, intent(in) :: xyz_centre(3),vxyz_centre(3),xyzi(3),vxyzi(3) + real, intent(out) :: vphi,omega + real :: Rmag,R(3),phi_unitvec(3),R_unitvec(3) + + ! xyz_centre: Position vector of reference point + ! vxyz_centre: Velocity vector of reference point + ! R: Cylindrical radius vector + R(1:2) = xyzi(1:2) - xyz_centre(1:2) ! Separation in x-y plane + R(3) = 0. + Rmag = sqrt(dot_product(R,R)) + R_unitvec = R / Rmag + call cross_product3D((/0.,0.,1./), R_unitvec, phi_unitvec) ! phi = z x R + vphi = dot_product(vxyzi - vxyz_centre, phi_unitvec) + omega = vphi / Rmag +end subroutine get_gas_omega + + +!---------------------------------------------------------------- +!+ +! Calculate kinetic, gravitational potential (gas-gas and sink-gas), +! and internal energy of a gas particle. +!+ +!---------------------------------------------------------------- +subroutine calc_gas_energies(particlemass,poten,xyzh,vxyzu,radprop,xyzmh_ptmass,phii,epoti,ekini,einti,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 + real, intent(in) :: particlemass + real(4), intent(in) :: poten + real, intent(in) :: xyzh(:),vxyzu(:),radprop(:) + real, dimension(5,nptmass), intent(in) :: xyzmh_ptmass + real, intent(out) :: phii,epoti,ekini,einti,etoti + real :: fxi,fyi,fzi + + phii = 0.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 + +end subroutine calc_gas_energies + + +subroutine adjust_corotating_velocities(npart,particlemass,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,omega_c,dump_number) + use vectorutils, only:cross_product3D + real, dimension(:,:), intent(in) :: xyzmh_ptmass,xyzh + real, dimension(:,:), intent(inout) :: vxyzu,vxyz_ptmass + real, intent(inout) :: omega_c + real, intent(in) :: particlemass + integer, intent(in) :: npart, dump_number + + logical :: switch + real :: sep, mtot + real, dimension(3) :: omega_vec, omegacrossr + integer :: i + + if (dump_number == 0) then + call prompt('Was this in a corotating frame?',switch,.false.) + + if (switch) then + sep = separation(xyzmh_ptmass(1:3,1), xyzmh_ptmass(1:3,2)) + mtot = sum(xyzmh_ptmass(4,:)) + npart*particlemass + omega_c = sqrt(mtot / sep**3) + else + omega_c = -1 + endif + endif + + if (omega_c > 0.) then + omega_vec = (/ 0.,0.,omega_c /) + + do i=1,npart + call cross_product3D(omega_vec,xyzh(1:3,i),omegacrossr) + vxyzu(1:3,i) = vxyzu(1:3,i) + omegacrossr(1:3) + enddo + + do i=1,nptmass + call cross_product3D(omega_vec,xyzmh_ptmass(1:3,i),omegacrossr) + vxyz_ptmass(1:3,i) = vxyz_ptmass(1:3,i) + omegacrossr(1:3) + enddo + endif +end subroutine adjust_corotating_velocities + + +! returns a profile from the centre of mass +! profile can either use all particles or can find particles within 2h of a given ray +! if simple flag is set to true, it will only produce a limited subset +subroutine stellar_profile(time,ncols,particlemass,npart,xyzh,vxyzu,profile,simple,ray) + use eos, only:ieos,equationofstate,X_in, Z_in + use eos_mesa, only:get_eos_kappa_mesa,get_eos_pressure_temp_mesa + use physcon, only:kboltz,mass_proton_cgs + use centreofmass, only:get_centreofmass + use energies, only:compute_energies + use part, only:xyzmh_ptmass,rhoh,ihsoft,poten + use units, only:udist,unit_ergg,unit_density,unit_pressure,unit_velocity,unit_energ + use kernel, only:kernel_softening,radkern + use ptmass, only:get_accel_sink_gas + use ionization_mod, only:ionisation_fraction + + real, intent(in) :: time + integer, intent(in) :: ncols + real, intent(in) :: particlemass + integer, intent(in) :: npart + real, intent(in) :: xyzh(:,:) + real, intent(inout) :: vxyzu(:,:) + real, intent(out), allocatable :: profile(:,:) + logical, intent(in) :: simple + real, intent(in), optional :: ray(3) + integer :: i,iprofile + 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 :: xh0, xh1, xhe0, xhe1, xhe2 + real :: temp_profile(ncols,npart) + logical :: criteria + + call compute_energies(time) + + iprofile = 0 + + do i=1,npart + if (xyzh(4,i) >= 0) then + + if (present(ray)) then + proj_mag = dot_product(xyzh(1:3,i),ray(1:3)) + proj = proj_mag * ray + orth(1:3) = xyzh(1:3,i) - proj(1:3) + orth_dist = separation(orth,(/0.,0.,0./)) + orth_ratio = orth_dist / xyzh(4,i) + if (orth_ratio < radkern .and. proj_mag > 0.) then + criteria = .true. + else + criteria = .false. + endif + else + criteria = .true. + endif + + if (criteria) then + + iprofile = iprofile + 1 + + rhopart = rhoh(xyzh(4,i), particlemass) + + temp_profile(1,iprofile) = distance(xyzh(1:3,i)) * udist + temp_profile(3,iprofile) = atan2(xyzh(2,i),xyzh(1,i)) + temp_profile(4,iprofile) = rhopart * unit_density + temp_profile(5,iprofile) = distance(vxyzu(1:3,i)) * unit_velocity + temp_profile(6,iprofile) = dot_product(vxyzu(1:3,i),xyzh(1:3,i)) / distance(xyzh(1:3,i)) * unit_velocity + temp_profile(7,iprofile) = sqrt(distance(vxyzu(1:2,i))**2 - (dot_product(vxyzu(1:2,i),xyzh(1:2,i)) & + / distance(xyzh(1:2,i)))**2) * unit_velocity + temp_profile(8,iprofile) = temp_profile(7,iprofile) / (distance(xyzh(1:2,i)) * udist) + if (simple .eqv. .false.) then + call equationofstate(ieos,ponrhoi,spsoundi,rhopart,xyzh(1,i),xyzh(2,i),xyzh(3,i),tempi,vxyzu(4,i)) + + if (ieos == 10) then + call get_eos_pressure_temp_mesa(rhopart*unit_density,vxyzu(4,i) * unit_ergg,pres,temp) + call get_eos_kappa_mesa(rhopart*unit_density,temp,kappa,kappat,kappar) + else + temp = (ponrhoi * (unit_pressure/unit_density) * 2.381 * mass_proton_cgs) / kboltz + kappa = 1. + endif + + call calc_gas_energies(particlemass,poten(i),xyzh(:,i),vxyzu(:,i),radprop(:,i),& + xyzmh_ptmass,phii,epoti,ekini,einti,etoti) + + call ionisation_fraction(rhopart*unit_density,temp,X_in,1.-X_in-Z_in,xh0,xh1,xhe0,xhe1,xhe2) + + temp_profile(9,iprofile) = vxyzu(4,i) * unit_ergg + temp_profile(10,iprofile) = ponrhoi * rhopart * unit_pressure + temp_profile(11,iprofile) = spsoundi * unit_velocity + temp_profile(12,iprofile) = temp + temp_profile(13,iprofile) = kappa + temp_profile(14,iprofile) = 1. / (kappa * rhopart * unit_density) + temp_profile(15,iprofile) = etoti * unit_energ + temp_profile(16,iprofile) = xh1 + temp_profile(17,iprofile) = xhe1 + temp_profile(18,iprofile) = xhe2 + endif + endif + endif + enddo + + allocate(profile(ncols,iprofile)) + profile(1:ncols,1:iprofile) = temp_profile(1:ncols,1:iprofile) + + call quicksort(profile, 1, iprofile, ncols, 1) + + do i=1,iprofile + if (i==1) profile(2,i) = particlemass + if (i > 1) profile(2,i) = profile(2,i-1) + particlemass + enddo + + deallocate(profile) + print*, "Profile completed" + +end subroutine stellar_profile + +!---------------------------------------------------------------- +!+ +! Calculate mass interior to companion +!+ +!---------------------------------------------------------------- +subroutine get_interior_mass(xyzh,vxyzu,donor_xyzm,companion_xyzm,particlemass,npart,iavgopt,interior_mass,com_xyz,com_vxyz) + real, intent(in) :: xyzh(:,:),vxyzu(:,:),donor_xyzm(4),companion_xyzm(4),particlemass + real, intent(out) :: interior_mass,com_xyz(3),com_vxyz(3) + integer, intent(in) :: npart,iavgopt + real :: sinksinksep,maxsep,sep,xyz_int(3,npart),vxyz_int(3,npart) + integer :: j,k,npart_int + integer, allocatable :: iorder(:) + + ! Calculate mass interior to companion + allocate(iorder(npart)) + call set_r2func_origin(donor_xyzm(1),donor_xyzm(2),donor_xyzm(3)) ! Order particles by distance from donor core + call indexxfunc(npart,r2func_origin,xyzh,iorder) + sinksinksep = separation(donor_xyzm(1:3), companion_xyzm(1:3)) + interior_mass = donor_xyzm(4) ! Include mass of donor core + select case(iavgopt) + case(5) ! Calculate mass interior to R/2 + maxsep = 2.*sinksinksep + case(6) ! Calculate mass interior to 2*R + maxsep = 0.5*sinksinksep + case default ! Calculate mass interior to R + maxsep = sinksinksep + end select + npart_int = 0 + do j = 1,npart + k = iorder(j) + sep = separation(donor_xyzm(1:3), xyzh(1:3,k)) + if (sep > maxsep) exit + npart_int = npart_int + 1 + xyz_int(1:3,npart_int) = xyzh(1:3,k) + vxyz_int(1:3,npart_int) = vxyzu(1:3,k) + enddo + interior_mass = npart_int * particlemass + + call get_centreofmass(com_xyz,com_vxyz,npart_int,xyz_int,vxyz_int,nptmass,xyzmh_ptmass,vxyz_ptmass) + deallocate(iorder) + +end subroutine get_interior_mass + +!---------------------------------------------------------------- +!+ +! Get CoM position and velocity of the two point masses plus +! gas particles radius = 2*sep from the donor, where sep is the +! distance between the donor and the CoM of just the point masses. +!+ +!---------------------------------------------------------------- +subroutine orbit_com(npart,xyzh,vxyzu,nptmass,xyzmh_ptmass,vxyz_ptmass,com_xyz,com_vxyz) + integer, intent(in) :: npart,nptmass + real, intent(in) :: xyzh(:,:),vxyzu(:,:),xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + real, intent(out), dimension(3) :: com_xyz,com_vxyz + real, allocatable :: xyz_a(:,:) + real, allocatable :: vxyz_a(:,:) + integer, allocatable :: iorder(:) + integer :: npart_a + real :: sep + integer :: i,j,k + + allocate(iorder(npart),xyz_a(4,npart),vxyz_a(3,npart)) + + ! Get order of particles by distance from CoM of point masses + com_xyz(1) = sum(xyzmh_ptmass(1,:)*xyzmh_ptmass(4,:))/nptmass + com_xyz(2) = sum(xyzmh_ptmass(2,:)*xyzmh_ptmass(4,:))/nptmass + com_xyz(3) = sum(xyzmh_ptmass(3,:)*xyzmh_ptmass(4,:))/nptmass + call set_r2func_origin(com_xyz(1),com_xyz(2),com_xyz(3)) + call indexxfunc(npart,r2func_origin,xyzh,iorder) + ! Displacement of donor core from the CoM of point masses + sep = separation(xyzmh_ptmass(1:3,1),com_xyz(1:3)) + + ! Calculate CoM of orbit, including only gas particles within radius = 2*sep from donor core + ! The point is that by including some gas particles around the donor core, we get a more accurate + ! position of the CoM about which the stellar cores orbit + i = 1 + k = 1 + do while (i < npart+1) + j = iorder(i) ! Loop from particles closest to farthest from CoM + if (isdead_or_accreted(xyzh(4,j))) then + i = i + 1 + else + if (separation(xyzh(1:3,j),com_xyz(1:3)) > 2.*sep) exit + xyz_a(1:4,k) = xyzh(1:4,j) + vxyz_a(1:3,k) = vxyzu(1:3,j) + i = i + 1 + k = k + 1 + endif + enddo + npart_a = k - 1 + call get_centreofmass(com_xyz,com_vxyz,npart_a,xyz_a,vxyz_a,nptmass,xyzmh_ptmass,vxyz_ptmass) + deallocate(iorder,xyz_a,vxyz_a) + +end subroutine orbit_com + +subroutine average_in_vol(xyzh,vxyzu,npart,particlemass,com_xyz,com_vxyz,isink,icentreonCM,iavgopt,vel,cs,omega,volume,vol_mass,& + vol_npart) + real, intent(in) :: xyzh(:,:),vxyzu(:,:),com_xyz(:),com_vxyz(:),particlemass + logical, intent(in) :: icentreonCM + real, intent(out) :: vel(:),cs,omega,volume,vol_mass + integer, intent(out) :: vol_npart + integer, intent(in) :: npart,isink,iavgopt + real :: orbit_centre(3),orbit_centre_vel(3),sphere_centre(3),Rarray(size(xyzh(1,:))),zarray(size(xyzh(1,:))),vxyzu_copy(4) + real :: Rsphere,sep,omega_out,Rsinksink,dR,dz,vphi + integer :: i,j,k,iorder(size(xyzh(1,:))) + + i = isink + if (icentreonCM) then ! Centre on orbit CoM + orbit_centre = com_xyz + orbit_centre_vel = com_vxyz + else ! Centre on primary core + orbit_centre = xyzmh_ptmass(1:3,3-i) + orbit_centre_vel = vxyz_ptmass(1:3,3-i) + endif + + Rsphere = 0.2 * separation(orbit_centre, xyzmh_ptmass(1:3,i)) + Rsinksink = separation(xyzmh_ptmass(1:2,i), xyzmh_ptmass(1:2,3-i)) ! [(x2-x1)^2 + (y2-y1)^2]^0.5 + dR = 0.2*Rsinksink + dz = 0.2*Rsinksink + vol_npart = 0 + vol_mass = 0. + omega = 0. + cs = 0. + + ! If averaging over a sphere, get order of particles from closest to farthest from sphere centre + dr = 0. + dz = 0. + Rsinksink = 0. + vol_npart = 0 + Rsphere = 0. + select case(iavgopt) + case(1,2,5,6) + select case (iavgopt) + case(1) ! Use companion position + sphere_centre = xyzmh_ptmass(1:3,i) + case(2) ! Use companion position on the opposite side of orbit + sphere_centre = 2.*orbit_centre - xyzmh_ptmass(1:3,i) ! Just r1 - (r2 - r1) + case(5) ! Averaging twice as far on opposite side of orbit + sphere_centre = 2.*(orbit_centre - xyzmh_ptmass(1:3,i)) ! Just r1 - 2(r2 - r1) + case(6) ! Averaging half as far on opposite side of orbit + sphere_centre = 1.5*orbit_centre - 0.5*xyzmh_ptmass(1:3,i) ! Just r1 - 0.5*(r2 - r1) + end select + call set_r2func_origin(sphere_centre(1),sphere_centre(2),sphere_centre(3)) + call indexxfunc(npart,r2func_origin,xyzh,iorder) + + ! Sum velocities, cs, and densities of all particles within averaging sphere + do j = 1,npart + k = iorder(j) ! Only use particles within the averaging sphere + if (.not. isdead_or_accreted(xyzh(4,k))) then + sep = separation(xyzh(1:3,k), sphere_centre) + if (sep > Rsphere) exit + vel(1:3) = vel(1:3) + vxyzu(1:3,k) + vxyzu_copy = vxyzu(:,k) + cs = cs + get_spsound(ieos,xyzh(1:3,k),rhoh(xyzh(4,k),particlemass),vxyzu_copy) + call get_gas_omega(orbit_centre,orbit_centre_vel,xyzh(1:3,k),vxyzu(1:3,k),vphi,omega_out) + omega = omega + omega_out + endif + enddo + vol_npart = j-1 ! Number of (unaccreted) particles in the sphere + vol_mass = vol_npart * particlemass + if ((iavgopt == 2) .or. (iavgopt == 5) .or. (iavgopt == 6)) vel = -vel ! To-do: get rid of this line + + ! Averaging in annulus + case(3,4) + Rarray = sqrt( (xyzh(1,:) - xyzmh_ptmass(1,3-i))**2 + (xyzh(2,:) - xyzmh_ptmass(2,3-i))**2) ! [(x-x1)^2 + (y-y1)^2]^0.5 + zarray = xyzh(3,:) - xyzmh_ptmass(3,3-i) + if (iavgopt == 4) Rsphere = 0.2*separation(xyzmh_ptmass(1:3,3-i),xyzmh_ptmass(1:3,i)) + do k = 1,npart + if ( (iavgopt == 4) .and. (separation(xyzh(1:3,k), xyzmh_ptmass(1:3,i)) < Rsphere) ) cycle + if ( (abs(Rarray(k) - Rsinksink) < 0.5*dR) .and.& + (abs(zarray(k) - xyzmh_ptmass(3,3-i)) < 0.5*dz) ) then + vel = vel + vxyzu(1:3,k) + vxyzu_copy = vxyzu(:,k) + cs = cs + get_spsound(ieos,xyzh(1:3,k),rhoh(xyzh(4,k),particlemass),vxyzu_copy) + call get_gas_omega(orbit_centre,orbit_centre_vel,xyzh(1:3,k),vxyzu(1:3,k),vphi,omega_out) + omega = omega + omega_out + vol_npart = vol_npart + 1 + endif + enddo + vol_mass = vol_npart * particlemass + end select + + ! Calculate averaging volume based on averaging option + select case (iavgopt) + case (1,2,5,6) ! Spheres + volume = 4./3.*pi*Rsphere**3 + case(3) ! Annulus + volume = 2.*pi * Rsinksink * dR * dz + case(4) ! Annulus with sphere subtracted + volume = 2.*pi * Rsinksink * dR * dz + volume = volume - 0.4*dR*dz*Rsinksink + case default + volume = 0. + print*,'Unknown averaging option' + return + end select + + ! Calculate volume averages + if (vol_npart > 0) then + vel(1:3) = vel(1:3) / float(vol_npart) + omega = omega / float(vol_npart) + cs = cs / float(vol_npart) + endif + +end subroutine average_in_vol + + +!---------------------------------------------------------------- +!+ +! Returns hist, the radial or mass-coordinate profile of a +! quantity. +! +! Inputs: +! coord: Array of radius or mass-coordinate of each particle +! quant: Array containing quantity for each particle to be binned +! bin_min: Lower bin edge for coord +! bin_max: Upper bin edge for coord +! nbins: Number of bins for coord +! logbins: If true, produce log-uniform bins +! normalise_by_bincount: If true, normalises histogram by bin +! count, thus averaging the quantity +!+ +!---------------------------------------------------------------- +subroutine histogram_setup(coord,quant,hist,npart,bin_max,bin_min,nbins,normalise_by_bincount,logbins) + integer, intent(in) :: npart,nbins + real, intent(in) :: coord(npart),quant(npart),bin_max, bin_min + logical, intent(in) :: normalise_by_bincount,logbins + real, intent(out) :: hist(nbins) + integer :: i,j,bincount(nbins) + real :: bins(nbins) + + if (logbins) then ! Create log-uniform bins + bins = (/ (10**(bin_min + (i-1) * (bin_max-bin_min)/real(nbins)), i=1,nbins) /) + else ! Create linear bins + bins = (/ (bin_min + (i-1) * (bin_max-bin_min)/real(nbins), i=1,nbins) /) + endif + + hist = 0. + bincount = 0 + + do j=1,npart + do i=1,nbins-1 + if (coord(j) >= bins(i) .and. coord(j) < bins(i+1)) then + bincount(i) = bincount(i) + 1 + hist(i) = hist(i) + quant(j) + exit ! Move onto next particle + endif + enddo + enddo + + if (normalise_by_bincount) then + do i=1,nbins + if (bincount(i) > 0) then + hist(i) = hist(i) / real(bincount(i)) + endif + enddo + endif + +end subroutine histogram_setup + +subroutine write_file(name_in, dir_in, cols, data_in, npart, ncols, num) + !outputs a file from a single dump + character(len=*), intent(in) :: name_in, dir_in + integer, intent(in) :: npart, ncols, num + character(len=*), dimension(ncols), intent(in) :: cols + character(len=20), dimension(ncols) :: columns + character(len=40) :: data_formatter, column_formatter + character(len(name_in)+9) :: file_name + + real, dimension(ncols,npart), intent(in) :: data_in + integer :: i, unitnum + + unitnum = 1000 + num + if (dump_number == 0) then + call system('mkdir ' // dir_in ) + endif + + write(file_name, "(2a,i5.5,a)") trim(name_in), "_", num, ".ev" + + open(unit=unitnum,file='./'//dir_in//'/'//file_name,status='replace') + + write(column_formatter, "(a,I2.2,a)") "('#',2x,", ncols, "('[',a15,']',3x))" + write(data_formatter, "(a,I2.2,a)") "(", ncols, "(2x,es19.11e3))" + + do i=1,ncols + write(columns(i), "(I2.2,a)") i, cols(i) + enddo + + !set column headings + write(unitnum, column_formatter) columns(:) + + !Write data to file + do i=1,npart + write(unitnum,data_formatter) data_in(:ncols,i) + enddo + + close(unit=unitnum) +end subroutine write_file + + +subroutine write_time_file(name_in, cols, time, data_in, ncols, num) + !outputs a file over a series of dumps + character(len=*), intent(in) :: name_in + integer, intent(in) :: ncols, num + character(len=*), dimension(ncols), intent(in) :: cols + character(len=20), dimension(ncols) :: columns + character(len=40) :: data_formatter, column_formatter + character(len(name_in)+9) :: file_name + real, intent(in) :: time + real, dimension(ncols), intent(in) :: data_in + integer :: i, unitnum + + write(column_formatter, "(a,I2.2,a)") "('#',2x,", ncols+1, "('[',a15,']',3x))" + write(data_formatter, "(a,I2.2,a)") "(", ncols+1, "(2x,es18.11e2))" + write(file_name,"(2a,i3.3,a)") name_in, '.ev' + + if (num == 0) then + unitnum = 1000 + + open(unit=unitnum,file=file_name,status='replace') + do i=1,ncols + write(columns(i), "(I2,a)") i+1, cols(i) + enddo + + !set column headings + write(unitnum, column_formatter) '1 time', columns(:) + close(unit=unitnum) + endif + + unitnum=1001+num + + open(unit=unitnum,file=file_name, position='append') + + write(unitnum,data_formatter) time, data_in(:ncols) + + close(unit=unitnum) + +end subroutine write_time_file + +real function distance(a) + ! Return norm of a vector of arbitrary dimension + real, intent(in), dimension(:) :: a + + distance = sqrt(dot_product(a,a)) +end function distance + +subroutine unit_vector(a,b) + real, intent(in), dimension(3) :: a + real, intent(out), dimension(3) :: b + + b(1:3) = a(1:3) / distance(a(1:3)) +end subroutine unit_vector + +real function cos_vector_angle(a,b) + real, intent(in), dimension(3) :: a,b + if (distance(a) == 0 .or. distance(b) == 0) then + cos_vector_angle = 1. + else + cos_vector_angle = dot_product(a,b) / (distance(a) * distance(b)) + endif +end function cos_vector_angle + +subroutine separation_vector(a,b,c) + !return difference between two vectors + real, intent(in), dimension(3) :: a,b + real, intent(out), dimension(4) :: c + + c(1) = a(1) - b(1) + c(2) = a(2) - b(2) + c(3) = a(3) - b(3) + c(4) = distance(c(1:3)) +end subroutine separation_vector + +real function separation(a,b) + !return the distance between two vectors + real, intent(in), dimension(:) :: a,b + + separation = distance(a - b) +end function separation + +!Creates an array of SPH particle densities for each value of h. +elemental real function getParticleRho(h,particlemass) + real, intent(in) :: h,particlemass + getParticleRho=rhoh(h,particlemass) +end function getParticleRho + +!Performs SPH interpolation on the SPH particle property toInterpolate at the location interpolateXyz. +!The smoothing length used is the smoothing length of the closest SPH particle to interpolateXyz. +function sphInterpolation(npart,particlemass,particleRho,particleXyzh,interpolateXyz,toInterpolate) result(interpolatedData) + use kernel, only:wkern + integer, intent(in) :: npart + real, intent(in) :: particlemass + real, intent(in) :: particleRho(npart) + real, intent(in) :: particleXyzh(4,npart) + real, intent(in) :: interpolateXyz(3) + real, intent(in) :: toInterpolate(:,:) + real :: interpolatedData(size(toInterpolate,1)) + + integer :: i,j + integer, allocatable :: iorder(:) + real :: currentR,currentQ,currentQ2 + real :: nearestSphH + real :: currentParticleRho,currentSphSummandFactor + + interpolatedData=0.0 + allocate(iorder(npart)) + call set_r2func_origin(interpolateXyz(1),interpolateXyz(2),interpolateXyz(3)) + call indexxfunc(npart,r2func_origin,particleXyzh,iorder) !Gets the order of SPH particles from the interpolation point. + nearestSphH=particleXyzh(4,iorder(1)) !The smoothing length of the nearest SPH particle to the ineterpolation point. + + do i=1,npart + j=iorder(i) + + currentR=separation(interpolateXyz,particleXyzh(1:3,j)) + currentQ=currentR/nearestSphH !currentR is scaled in units of nearestSphH + currentQ2=currentQ**2.0 + + !All SPH particles beyond 2 smoothing lengths are ignored. + if (currentQ>2) then + exit + endif + + !SPH interpolation is done below. + currentParticleRho=particleRho(j) + currentSphSummandFactor=(particlemass/currentParticleRho)*((1.0/((nearestSphH**3.0)*pi))*wkern(currentQ2,currentQ)) + interpolatedData=interpolatedData+(currentSphSummandFactor*toInterpolate(:,j)) + enddo + deallocate(iorder) + +end function sphInterpolation + +!Sorting routines +recursive subroutine quicksort(a, first, last, ncols, sortcol) + integer, intent(in) :: first, last, ncols, sortcol + real, dimension(ncols,last-first+1), intent(inout) :: a + real :: x + integer :: i, j, k + + x = a(sortcol, (first+last) / 2 ) + i = first + j = last + do + do while (a(sortcol, i) < x) + i=i+1 + enddo + + do while (x < a(sortcol, j)) + j=j-1 + enddo + + if (i >= j) exit + + do k=1,ncols + call swap(a(k,i),a(k,j)) + enddo + + i=i+1 + j=j-1 + enddo + if (first < i-1) call quicksort(a, first, i-1, ncols, sortcol) + if (j+1 < last) call quicksort(a, j+1, last, ncols, sortcol) +end subroutine quicksort + +subroutine swap(a,b) + real, intent(inout) :: a,b + real :: c + + c = a + a = b + b = c + +end subroutine swap + + +!---------------------------------------------------------------- +!+ +! Determine ID of planet particles based on distance from host star core +!+ +!---------------------------------------------------------------- +subroutine get_planetIDs(nplanet,planetIDs) + integer, allocatable, intent(out) :: planetIDs(:) + integer, intent(out) :: nplanet + integer :: i + + ! Determine planet particle IDs (the nplanet particles initially farthest from the donor star) + nplanet = 1262 + call prompt('Enter number of planet particles:',nplanet,0) + allocate(planetIDs(nplanet)) + do i = 1,nplanet + planetIDs(i) = i + enddo + +end subroutine get_planetIDs + + +!---------------------------------------------------------------- +!+ +! Set EOS options for analysis +!+ +!---------------------------------------------------------------- +subroutine set_eos_options(analysis_to_perform) + integer, intent(in) :: analysis_to_perform + integer :: ierr + + ieos = 2 + call prompt('Enter ieos:',ieos) + select case(ieos) + 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 + case(10,20) + gamma = 5./3. + X_in = 0.69843 + Z_in = 0.01426 + call prompt('Enter hydrogen mass fraction:',X_in,0.,1.) + call prompt('Enter metallicity:',Z_in,0.,1.) + irecomb = 0 + if (ieos==20) call prompt('Using gas+rad+rec EoS. Enter irecomb:',irecomb,0,2) + case default + call fatal('analysis_common_envelope',"EOS type not supported") + end select + call init_eos(ieos,ierr) + if (ierr /= 0) call fatal('analysis_common_envelope',"Failed to initialise EOS") + +end subroutine set_eos_options + + +!---------------------------------------------------------------- +!+ +! Calculates escape velocity for all SPH particles given the potential energy +! of the system at that time +!+ +!---------------------------------------------------------------- +subroutine calc_escape_velocities(particlemass,poten,xyzh,vxyzu,xyzmh_ptmass,phii,epoti,v_esc) + use ptmass, only:get_accel_sink_gas + use part, only:nptmass + real, intent(in) :: particlemass + real(4), intent(in) :: poten + real, dimension(4), intent(in) :: xyzh,vxyzu + real, dimension(5,nptmass), intent(in) :: xyzmh_ptmass + real :: phii,epoti + real :: fxi,fyi,fzi + real, intent(out) :: v_esc + + phii = 0.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 + v_esc = sqrt(2*abs(epoti/particlemass)) + +end subroutine calc_escape_velocities + +end module analysis From d16edd7879e77c16dbb2188ed5ab626613824c0b Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 29 Jul 2024 16:53:02 +0100 Subject: [PATCH 137/182] More upstream updates --- build/Makefile | 1 + build/Makefile_setups | 12 +- src/main/lumin_nsdisc.f90 | 1118 ----------------- src/main/mpi_force.F90 | 3 + src/main/phantom.F90 | 2 +- src/main/readwrite_dumps_common.f90 | 453 ++++++- ...ortran.F90 => readwrite_dumps_fortran.f90} | 836 ++---------- src/main/readwrite_infile.F90 | 10 +- src/utils/analysis_GalMerger.f90 | 2 +- src/utils/analysis_NSmerger.f90 | 6 +- 10 files changed, 591 insertions(+), 1852 deletions(-) delete mode 100644 src/main/lumin_nsdisc.f90 rename src/main/{readwrite_dumps_fortran.F90 => readwrite_dumps_fortran.f90} (64%) diff --git a/build/Makefile b/build/Makefile index 96454f9b3..1ad43de54 100644 --- a/build/Makefile +++ b/build/Makefile @@ -1287,6 +1287,7 @@ giza-fortran.o : $(SPLASH_DIR)/giza/interface/giza-fortran.F90 $(SPLASH_DIR)/giz compilers: @echo "I suggest one of the following, based on detected Fortran compilers..."; echo; + @if type -p ifx > /dev/null; then echo "make SYSTEM=ifx"; fi; @if type -p ifort > /dev/null; then echo "make SYSTEM=ifort"; fi; @if type -p pathf90 > /dev/null; then echo "make SYSTEM=pathf90"; fi; @if type -p pgf90 > /dev/null; then echo "make SYSTEM=pgf90"; fi; diff --git a/build/Makefile_setups b/build/Makefile_setups index d5f34b9a5..65cb620f4 100644 --- a/build/Makefile_setups +++ b/build/Makefile_setups @@ -206,7 +206,7 @@ ifeq ($(SETUP), grdisc) # accretion disc around a Kerr black hole SETUPFILE= setup_grdisc.f90 ANALYSIS= analysis_disc.f90 - GR=yes + GR=no METRIC=kerr KNOWN_SETUP=yes MULTIRUNFILE= multirun.f90 @@ -421,6 +421,16 @@ ifeq ($(SETUP), sphereinbox) KNOWN_SETUP=yes endif +ifeq ($(SETUP), sphere) +# sphere setup + ISOTHERMAL=no + PERIODIC=no + IND_TIMESTEPS=yes + GRAVITY=yes + SETUPFILE= velfield_fromcubes.f90 setup_sphere.f90 + KNOWN_SETUP=yes +endif + ifeq ($(SETUP), shock) # shock tube tests PERIODIC=yes diff --git a/src/main/lumin_nsdisc.f90 b/src/main/lumin_nsdisc.f90 deleted file mode 100644 index 90db88923..000000000 --- a/src/main/lumin_nsdisc.f90 +++ /dev/null @@ -1,1118 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! -!--------------------------------------------------------------------------! -module lumin_nsdisc -! -! This module contains routines for calculating beta, the -! ratio of radiation to gravitational force, for an accretion disc -! surrounding a neutron star. It contains associated functions -! for calculating opacity, accretion luminosity, etc. -! -! :References: None -! -! :Owner: Daniel Price -! -! :Runtime parameters: None -! -! :Dependencies: eos, infile_utils, io, physcon, units -! - - use physcon, only: pi - implicit none - - real :: LumAcc = 0.0 ! luminosity from accretion - integer, public :: BurstProfile = 0 ! Burst luminosity / profile - real, private :: Lstar = 0.0 ! total luminosity of star as a fraction of Eddington - real, private :: LEdd = 0.0 ! Eddington luminosity in code units - real, private :: frac_X = 0.7 ! Hydrogen fraction - integer, private :: rad_trans = 0 ! Radiation transport prescription - real :: AccLumEff = 1.0 ! Fraction of accretion luminosity that - ! participates in radiation force. This is - ! mostly only relevant for compact objects. - ! number of gridpoints for the rho, tau, beta grids - integer, parameter :: nr = 63, nth=16 , nph=24, nz=30 - real :: ringrid(0:nr), cyl_ringrid(0:nr), thmingrid(0:nth), phmingrid(0:nph), zmingrid(0:nz) - integer :: npgrid(0:nr-1,0:nth-1,0:nph-1), w92npart( 0:nr-1 ), cyl_npgrid(0:nr-1,0:nz,0:nph-1) - real :: densitygrid(0:nr-1,0:nth-1,0:nph-1), ldensitygrid(0:nr-1,0:nth-1,0:nph-1) - real :: tauradgrid(0:nr-1,0:nth-1,0:nph-1), ltauradgrid(0:nr-1,0:nth-1,0:nph-1) - real :: betagrid(0:nr-1,0:nth-1,0:nph-1), lbetagrid(0:nr-1,0:nth-1,0:nph-1) !the grids - - real :: cyl_densitygrid(0:nr-1,0:nz,0:nph-1), cyl_ldensitygrid(0:nr-1,0:nz,0:nph-1) - real :: cyl_tauradgrid(0:nr-1,0:nz,0:nph-1), cyl_ltauradgrid(0:nr-1,0:nz,0:nph-1) - real :: cyl_betagrid(0:nr-1,0:nz,0:nph-1), cyl_lbetagrid(0:nr-1,0:nz,0:nph-1) !cylindrical grids - - real :: w92betagrid( 0:nr-1 ), w92sumbeta( 0:nr-1 ) !cylindrical grid for comparison with W92 - real :: thetamin = 0.0, thetamax = pi, rmin = 1.0, rmax = 1001.0 - real :: zmin = -200, zmax=200 - real :: phimax = 2*pi, phimin=0 - real :: Lstar_burst - real, parameter :: eps = 1.e-6 - integer, private :: made_grid_points = 0 - - public :: beta, set_Lstar, calc_sigma, calc_scaleheight - public :: read_options_lumin_nsdisc, write_options_lumin_nsdisc - public :: LumAcc, Lstar_burst, AccLumEff, ringrid, thmingrid, thetamin, thetamax, rmin, rmax - public :: nr, nth, nph, densitygrid, tauradgrid, betagrid, lbetagrid, make_beta_grids - public :: get_grid_points, bilin_interp, get_grid_bins, sphere_segment, get_bracket_grid_points - public :: ldensitygrid, ltauradgrid, careful_log, phmingrid, phimin, phimax, w92betagrid - public :: cyl_ringrid, zmingrid, cyl_npgrid, cyl_densitygrid, cyl_ldensitygrid, cyl_tauradgrid - public :: cyl_ltauradgrid, cyl_betagrid, cyl_lbetagrid, zmin, zmax, nz - - private :: calc_kappa, eps - - private - -contains - -!---------------------------------------------------------------- -!+ -! Sets the location of the grid points -!+ -!---------------------------------------------------------------- - -subroutine make_grid_points() - use physcon, only:pi, twopi - integer :: rbin, thbin, phbin, zbin - real :: A, B, C, tempr - A = (rmax-rmin)/(nr*nr) - B = 2.*(thetamin-thetamax)/nth - C = 2.*(zmin-zmax)/nz - - do rbin=0, nr-1 - tempr = rmin + A*rbin**2 - ringrid(rbin) = tempr - w92betagrid(rbin) = tempr - cyl_ringrid(rbin) = tempr - enddo - - thmingrid(0)=thetamin - do thbin=1,nth/2-1 - thmingrid(thbin) = B*(1.0*thbin*thbin/nth-thbin)+thetamin - thmingrid(nth-thbin) = thetamax - thmingrid(thbin) - enddo - thmingrid(nth/2) = (thetamin+thetamax)/2; - - zmingrid(0)=zmin - do zbin=1,nz/2-1 - zmingrid(zbin) = C*(1.0*zbin*zbin/nz-zbin)+zmin - zmingrid(nz-zbin) = (zmax+zmin)/2. - zmingrid(zbin) - enddo - zmingrid(nz/2) = (zmin+zmax)/2. - - do phbin=0,nph-1 - phmingrid(phbin) = phbin * twopi/nph - enddo - - made_grid_points = 1 - -end subroutine make_grid_points - -!---------------------------------------------------------------- -!+ -! Given a set of coordinates r, theta, phi, finds the cell -! those coords are in -!+ -!---------------------------------------------------------------- - -subroutine get_grid_bins( r, zt, rbin, ztbin, phi, phibin ) - use physcon, only:pi, twopi - use io, only : fatal - real, intent(in) :: r, phi, zt - integer, intent(out) :: rbin, ztbin, phibin - real :: B, C, ztnew - - rbin = int( nr*sqrt( (r-rmin)/(rmax-rmin))) - - B = 2.*(thetamin-thetamax)/(nth) - C = 2.*(zmin-zmax)/nz - - select case(rad_trans) - case(2) - if ( zt < (zmin+zmax)/2. ) then - ztbin = int( (sqrt( (nz*C)**2 + 4*nz*C*(zt-zmin) ) + nz*C)/(2.*C) ) - else - ztnew = zmin + zmax - zt - ztbin = int( (sqrt( (nz*C)**2 + 4*nz*C*(ztnew-zmin) ) + nz*C)/(2.*C) ) - ztbin = nz-ztbin-1 - endif - if ( ztbin>nz ) ztbin = nz - if ( ztbin<0 ) ztbin = 0 - case default ! 0,1 - if ( zt < (thetamin+thetamax)/2. ) then - ztbin = int( (sqrt( (nth*B)**2 + 4*nth*B*(zt-thetamin) ) + nth*B)/(2.*B) ) - else - ztnew = thetamin + thetamax - zt - ztbin = int( (sqrt( (nth*B)**2 + 4*nth*B*(ztnew-thetamin) ) + nth*B)/(2.*B) ) - ztbin = nth-ztbin-1 - endif - if ( ztbin < 0 .or. ztbin>nth-1 ) then - call fatal( 'lumin_nsdisc', 'Array out of bounds error in get_grid_bins (theta)' ) - endif - end select - - phibin = int( phi*nph/twopi) - if ( rbin>nr-1 ) rbin=nr-1 ! Avoids segfaults for distant particles - if ( rbin<0 ) rbin = 0 ! Avoids segfaults for accreted particles - -end subroutine get_grid_bins - -!---------------------------------------------------------------- -!+ -! Given a bin in an array, finds the inner and outer edges, and the -! midpoint -!+ -!---------------------------------------------------------------- - -subroutine get_grid_points( array, ix, nx, maxx, xin, xout, xmid ) - use io, only : fatal - integer, intent(in) :: nx, ix - real, intent(in) :: array(0:nx-1), maxx - real, intent(out) :: xin, xout, xmid - if ( ix<0.or.ix>=nx ) then - call fatal( 'lumin_nsdisc', 'Array out of bounds error in get_grid_points' ) - endif - xin = array(ix) - - if ( ix==nx-1 ) then - xout = maxx - else - xout = array(ix+1) - endif - - xmid = ( xin + xout )/2. - -end subroutine get_grid_points - -!---------------------------------------------------------------- -!+ -! Given a bin in an array, finds the midpoints of that bin and the next -! one out. This is called in preparation for bilin_interp -!+ -!---------------------------------------------------------------- - -subroutine get_bracket_grid_points( array, ix, nx, maxx, x1, x2 ) - use io, only : fatal - integer, intent(in) :: nx, ix - real, intent(in) :: array(0:nx-1), maxx - real, intent(out) :: x1, x2 - real :: minimum, maximum, boundary - - if ( ix<0.or.ix>=nx-1 ) then - call fatal( 'lumin_nsdisc', 'Array out of bounds error in get_bracket_grid_points' ) - !this should never happen. Checks in the calling function should avoid passing bad ix values. - endif - - minimum = array(ix) - boundary = array(ix+1) - - if ( ix==nx-2 ) then - maximum = maxx - else - maximum = array(ix+2) - endif - - x1 = minimum + (boundary-minimum)/2. - x2 = boundary + (maximum-boundary)/2. - -end subroutine get_bracket_grid_points - -!---------------------------------------------------------------- -!+ -! Generates a set of grids containing rho, tau, and beta -! Calculates density by counting the number of particles in -! each spherical r,theta bin -! Calculates tau by integrating radially from NS surface -! Calculates beta = exp(-tau). You still need to multiply beta -! by L*/LEdd to get the true beta used to calculate PR drag -!+ -!---------------------------------------------------------------- - -subroutine make_beta_grids(xyzh,particlemass,npart) - use units, only: udist, umass - - integer, intent(in) :: npart - real, intent(in) :: xyzh(:,:) - real, intent(in) :: particlemass - real :: theta, r, phi, kappa, r_cyl - real :: dr, dz, cell_phin, cell_phout, cell_phmid - real :: cell_rin, cell_rout, cell_rmid, cell_thin, cell_thout, cell_thmid - real :: cell_zin, cell_zout, cell_zmid - real :: cell_volume, logzero, x, y, z - integer :: rbin, thbin, phbin, zbin, ipart, totpart - - kappa = real(calc_kappa( frac_X, 2. ) * (umass/(udist*udist))) !kappa in code units - - logzero = careful_log( 0.0 ) - - call make_grid_points() - do rbin=0, nr-1 !clear the density grid, since it is retained after every call - do phbin=0, nph-1 - do thbin=0, nth-1 - ldensitygrid( rbin, thbin, phbin ) = logzero - densitygrid( rbin, thbin, phbin ) = 0.0 - npgrid( rbin, thbin, phbin ) = 0 - enddo - do zbin=0, nz - cyl_ldensitygrid(rbin, zbin, phbin) = logzero - cyl_densitygrid(rbin, zbin, phbin) = 0.0 - cyl_npgrid(rbin, zbin, phbin) = 0 - enddo - enddo - enddo - - totpart = 0 - do ipart=1, npart !fills the density grid by counting particles and assigning - !each one to a cell - x = xyzh(1, ipart) - y = xyzh(2, ipart) - z = xyzh(3, ipart) - - if ( isnan(x).or.isnan(y).or.isnan(z) ) then - x=0. - y=0. - z=0. - endif - - r = sqrt( x**2 + y**2 + z**2 ) - r_cyl = sqrt(x**2 + y**2) - - if ( r>rmin.and.r thetamax ) theta = thetamax - if ( theta < thetamin ) theta = thetamin - - phi = pi + atan2( y, x ) - endif - if (phbin >= nph ) then !phi is cyclic - phbin = phbin - nph - endif - cell_phin = phmingrid( phbin ) - if ( phbin == nph-1 ) then - cell_phout = phimax - else - cell_phout = phmingrid( phbin+1 ) - endif - if ( r>rmin.and.r=0).and.(rbin=0).and.(thbin=0).and.(phbinzmax ) z=zmax-eps - if ( z=0).and.(rbin=0).and.(zbin=0).and.(phbin thetamax ) theta = thetamax - if ( theta < thetamin ) theta = thetamin - phi = pi + atan2( y, x ) - if ( r_cyl>= 0) then - call get_grid_bins( r_cyl, 0., rbin, thbin, 0., phbin ) - else - rbin=-1 - thbin=-1 - phbin=-1 - endif - if ( rbin>=0.and.rbin= taubig ) then - tau_to_beta = 0. - else - tau_to_beta = exp(-tau) - endif - -end function tau_to_beta - -!------------------------------------------------ -!+ -! Calculates the total luminosity of the star, -! including perhaps luminosity from accretion -!+ -!------------------------------------------------ - -subroutine set_Lstar( BurstProfile, time, dmdt, Mstar ) - use units, only:utime, umass, udist - use physcon, only:fourpi - real, intent(in) :: time, dmdt, Mstar - integer, intent(in) :: BurstProfile - real :: ptime, ptime2 - -!this assumes c=G=1. - LEdd = real(fourpi*Mstar/(calc_kappa( frac_X, 2. ) / ( udist*udist / umass ))) - ptime = real(time*utime) - ptime2 = ptime*ptime - - select case( BurstProfile ) - - case(-1) ! Test case. I will modify this one frequently. - if ( time < 9999.) then - Lstar_burst=0.0 - AccLumEff=0.0 - else - Lstar_burst=1.0 - AccLumEff=0.0 - endif - case(0) ! No luminosity, either from burning or from accretion feedback - Lstar_burst = 0.0 - AccLumEff = 0.0 - case(1) !Time-variable luminosity profile. - ! 00.00 - 00.25 = no luminosity at all to remove initial transient - ! 00.25 - 01.00 = no L*, linearly ramp up accretion feedback from 0 to 1 - ! 01.00 - 01.50 = Linear rise in L* from 0 to LEdd/2 - ! 01.50 - 10.00 = Quadratic decay back to zero - ! 10.00 - = L* = 0, AccLumEff = 1. - if ( ptime < 0.25 ) then - Lstar_burst = 0.0 - AccLumEff = 0.0 - elseif ( ptime < 1.0 ) then - Lstar_burst = 0.0 - AccLumEff = (ptime*4. - 1.)/3. - elseif ( ptime < 1.5 ) then - Lstar_burst = (ptime - 1.) - AccLumEff = 1. - elseif ( ptime < 10. ) then - Lstar_burst = (2*ptime2 - 40*ptime + 200)/289.0 - AccLumEff = 1. - else - Lstar_burst = 0.0 - AccLumEff = 1. - endif - case(2) ! No burning, but ramp up AccLumEff after initial transient - Lstar_burst = 0.0 - if ( ptime < 0.25 ) then - AccLumEff = 0.0 - elseif ( ptime < 1.0 ) then - AccLumEff = (ptime*4. - 1.)/3. - else - AccLumEff = 1.0 - endif - case(3) ! No burning, but ramp up AccLumEff half as fast as in case(2) - Lstar_burst = 0.0 - if ( ptime < 0.25 ) then - AccLumEff = 0.0 - elseif ( ptime < 1.75 ) then - AccLumEff = (ptime*4. - 1.)/6. - else - AccLumEff = 1.0 - endif - case(4) ! Remove initial transient; ramp up acclum over 3/4 second; allow to settle to 10s; - ! impose a half eddington burst at 10s - Lstar_burst = 0.0 - if ( ptime < 0.25 ) then !remove initial transient - AccLumEff = 0.0 - elseif ( ptime < 1.00 ) then !ramp up AccLum - AccLumEff = (ptime*4. - 1.)/3. - elseif ( ptime < 10.00 ) then !Settle disc - AccLumEff = 1.0 - elseif ( ptime < 10.5 ) then !Burst rise - AccLumEff = 1.0 - Lstar_burst = (ptime-10) - elseif ( ptime < 20.5 ) then !Burst decay - AccLumEff = 1.0 - Lstar_burst = (4*ptime2 - 164*ptime + 1681)/800. - else !Post burst - AccLumEff = 1.0 - Lstar_burst = 0.0 - endif - case(5) ! Eddington luminosity from beginning of simulation - Lstar_burst = 1.0 - AccLumEff = 1.0 - case(6) ! Remove initial transient; ramp up acclum over 3/4 second; allow to settle to 10s; - ! impose a half eddington burst at 10s - Lstar_burst = 0.0 - if ( ptime < 0.25 ) then !remove initial transient - AccLumEff = 0.0 - elseif ( ptime < 1.00 ) then !ramp up AccLum - AccLumEff = (ptime*4. - 1.)/3. - elseif ( ptime < 10.00 ) then !Settle disc - AccLumEff = 1.0 - elseif ( ptime < 10.5 ) then !Burst rise - AccLumEff = 1.0 - Lstar_burst = (ptime-10)*2 - elseif ( ptime < 20.5 ) then !Burst decay - AccLumEff = 1.0 - Lstar_burst = (4*ptime2 - 164*ptime + 1681)/400. - else !Post burst - AccLumEff = 1.0 - Lstar_burst = 0.0 - endif - case(7) !Fit to a type-1 nonPRE burst from 1636-536. Since I'll be starting from an already settled simulation, no need to adjust time - ptime2 = ptime-3 - Lstar_burst = 0.0 - AccLumEff = 0.0 - if ( ptime > 2. .and. ptime <3. ) then - Lstar_burst=0 - AccLumEff = ptime-2. - endif - if ( ptime>3 ) then - Lstar_burst = 9.4*ptime2**1.6*exp(-2.9*ptime2**0.4) - AccLumEff = 1. - endif - case(8) !0.1 L_Edd from beginning of simulation, used for prtest - Lstar_burst = 0.10 - AccLumEff = 0.00 - end select - - if ( AccLumEff > 1.e-16 ) then !If we are including luminosity feedback - LumAcc = AccLumEff * get_AccLum( dmdt, Mstar ) - else - LumAcc = 0.0 - endif - Lstar = Lstar_burst + LumAcc - -end subroutine set_Lstar - -!---------------------------------------------------- -!+ -! Converts accretion rate into luminosity -!+ -!---------------------------------------------------- - -real function get_AccLum( dmdt, Mstar ) !Luminosity from accretion - use units, only:get_G_code - real, intent(in) :: dmdt, Mstar - real :: ggcode, Rstar - - ggcode = get_G_code() - Rstar = 1. - - get_AccLum = (ggcode * Mstar * dmdt / Rstar) / LEdd - -end function get_AccLum - -!---------------------------------------------- -!+ -! function computing kappa opacity from hydrogen -! fraction X and temperature kT (in keV). -! Returns opacity in cm^2 g^{-1} -! -! See Lewin et al 1993, SSR, 62, 233 (p. 276 4.13b) -!+ -!---------------------------------------------- - -real function calc_kappa( X, kT ) - real, intent(in) :: X, kT - real :: k0, tempcorr - k0 = 0.2*(1.0 + X) - tempcorr = 1.0 + ( kT/39.2 )**0.86 - calc_kappa = k0/tempcorr -end function calc_kappa - -!---------------------------------------------- -!+ -! function computing the beta parameter -!+ -!---------------------------------------------- -real function beta(x,y,z) - use physcon, only:c, gg, fourpi, pi, roottwo, rpiontwo - use io, only:fatal - use units, only:umass,udist - real, intent(in) :: x,y,z - real :: r, theta, phi, rcyl, H, kappa, tau - integer :: rbin, thetabin, phibin, zbin - - beta = 0. - rcyl = sqrt( x*x + y*y ) - phi = pi + atan2(y,x) - r = sqrt(x**2 + y**2 + z**2) - theta=acos(z/r) - - select case( rad_trans ) - case( 0 ) - r = sqrt(x**2 + y**2 + z**2) - theta = acos( z/r ) - if ( theta > thetamax ) theta = thetamax - if ( theta < thetamin ) theta = thetamin - if ( r>rmin.and.rrmin.and.rcyl Lstar ) then - beta = Lstar !hopefully unnecessary sanity checks - endif - if ( beta < 0. ) beta = 0. - -end function beta - -!---------------------------------------------- -!+ -! Calculates a beta by calling bilin_interp -!+ -!--------------------------------------------- -real function beta_by_interp(r, theta, phi) - real, intent(in) :: r, theta, phi - real :: betain, betaout - integer :: rbin, thetabin, phibin - - beta_by_interp = 0 - rbin=0 - thetabin=0 - phibin=0 - call get_grid_bins( r, theta, rbin, thetabin, phi, phibin ) - - if ( rbin >= nr-1 ) rbin = nr-1 - - if ( r<=rmin ) then - betain = 0. - betaout = 0. - elseif ( frac_X < 0. ) then - betain = 1. - betaout = 1. - elseif ( rbin>=nr-1 ) then - betain = lbetagrid(nr-1, thetabin, phibin) - betain = min(exp(betain), 1.) - betaout = betain - else - betain = bilin_interp( lbetagrid, ringrid(rbin), theta, phi) - betain = exp(betain) - - betaout = bilin_interp( lbetagrid, ringrid(rbin+1), theta, phi ) - betaout = exp(betaout) - endif - - if ( npgrid( rbin, thetabin, phibin )==0) then - beta_by_interp = betain - else - beta_by_interp = (betaout + (betain-betaout)/npgrid( rbin, thetabin, phibin )) - - endif - -end function beta_by_interp - -!---------------------------------------------- -!+ -! Calculates a beta by calling bilin_interp on a cylindrical grid -!+ -!--------------------------------------------- -real function beta_by_interp_cyl(r, z, phi) - real, intent(in) :: r, z, phi - real :: betain, betaout - integer :: rbin, zbin, phibin - real :: znew - znew=z - if ( z > zmax ) znew = zmax - eps - if ( z < zmin ) znew = zmin + eps - rbin=0 - zbin=0 - phibin=0 - call get_grid_bins( r, z, rbin, zbin, phi, phibin ) - if ( r<=rmin ) then - betain = 0. - betaout = 0. - elseif ( frac_X < 0. ) then - betain = 1. - betaout = 1. - elseif ( rbin>=nr-1 ) then - betain = bilin_interp_cyl( cyl_lbetagrid, r, z, phi ) - betain = min(exp(betain), 1.) - betaout = betain - else - betain = bilin_interp_cyl( cyl_lbetagrid, r, z, phi ) - betain = exp(betain) - betaout = bilin_interp_cyl( cyl_lbetagrid, r, z, phi ) - betaout = exp(betaout) - endif - - if ( cyl_npgrid( rbin, zbin, phibin )==0) then - beta_by_interp_cyl = betain - else - beta_by_interp_cyl = (betaout + (betain-betaout)/cyl_npgrid( rbin, zbin, phibin )) - endif - -end function beta_by_interp_cyl - -!---------------------------------------------- -!+ -! Finds a value by bilinearly interpolating on a grid -!+ -!---------------------------------------------- - -real function bilin_interp( array, r, theta, phi ) - use physcon, only: twopi - real, intent(in) :: array(0:nr-1, 0:nth-1, 0:nph-1), phi, theta, r - real :: t1, t2, p1, p2, ft1p1, ft2p1,ft1p2, ft2p2, tmid, pmid - real :: ftp, dta, dtb, dpa, dpb, dummy - integer :: tbin1, tbin2, pbin1, pbin2, tbin0, pbin0, rbin0 - - bilin_interp = 0. - if ( r>rmin) then - call get_grid_bins( r, theta, rbin0, tbin0, phi, pbin0 ) - else - call get_grid_bins( rmin+eps, theta, rbin0, tbin0, phi, pbin0 ) - rbin0=0 - endif - call get_grid_points( thmingrid, tbin0, nth, thetamax, t1, t2, tmid ) - - if ( tbin0 == 0.and.thetatmid ) then - call get_bracket_grid_points( thmingrid, nth-2, nth, thetamax, t1, t2 ) - tbin1 = nth-2 - elseif ( theta > tmid ) then - call get_bracket_grid_points( thmingrid, tbin0, nth, thetamax, t1, t2 ) - tbin1 = tbin0 - else - call get_bracket_grid_points( thmingrid, tbin0-1, nth, thetamax, t1, t2 ) - tbin1 = tbin0-1 - endif - - call get_grid_points( phmingrid, pbin0, nph, phimax, p1, p2, pmid ) - - if ( pbin0 == 0.and.phipmid ) then - call get_bracket_grid_points( phmingrid, nph-2, nph, phimax, p1, dummy ) - call get_bracket_grid_points( phmingrid, 0, nph, phimax, dummy, p2 ) - p2 = p2 + twopi - pbin1 = nph-1 - pbin2 = 0 - elseif ( phi>pmid ) then - call get_bracket_grid_points( phmingrid, pbin0, nph, phimax, p1, p2 ) - pbin1 = pbin0 - pbin2 = pbin0+1 - else - call get_bracket_grid_points( phmingrid, pbin0-1, nph, phimax, p1, p2 ) - pbin1 = pbin0-1 - pbin2 = pbin0 - endif - - tbin2=tbin1+1 - - if ( pbin1<0 ) pbin1 = nph-1 - if ( pbin2>nph-1 ) pbin2 = 0 - - ft1p1 = array( rbin0, tbin1, pbin1 ) - ft1p2 = array( rbin0, tbin1, pbin2 ) - ft2p1 = array( rbin0, tbin2, pbin1 ) - ft2p2 = array( rbin0, tbin2, pbin2 ) - - dta = theta - t1 - dtb = t2 - theta - dpa = phi - p1 - dpb = p2 - phi - - ftp = ft1p1*dtb*dpb & - + ft2p1*dta*dpb & - + ft1p2*dtb*dpa & - + ft2p2*dta*dpa - - bilin_interp = ftp/( (t2-t1)*(p2-p1) ) - -end function bilin_interp - -!---------------------------------------------- -!+ -! Finds a value by bilinearly interpolating on a cylindrical grid -!+ -!---------------------------------------------- - -real function bilin_interp_cyl( array, r, z, phi ) - use physcon, only: twopi - real, intent(in) :: array(0:nr-1, 0:nz, 0:nph-1), phi, z, r - real :: r1, r2, p1, p2, fr1p1, fr2p1,fr1p2, fr2p2, rmid, pmid - real :: frp, dra, drb, dpa, dpb, dummy - integer :: rbin1, rbin2, pbin1, pbin2, zbin0, pbin0, rbin0 - real :: znew - znew=z - zbin0=0 - if ( z>zmax ) znew = zmax - eps - if ( zrmid ) then - call get_bracket_grid_points( cyl_ringrid, nr-2, nr, rmax, r1, r2 ) - rbin1 = nr-2 - elseif ( r > rmid ) then - call get_bracket_grid_points( cyl_ringrid, rbin0, nr, rmax, r1, r2 ) - rbin1 = rbin0 - else - call get_bracket_grid_points( cyl_ringrid, rbin0-1, nr, rmax, r1, r2 ) - rbin1 = rbin0-1 - endif - - call get_grid_points( phmingrid, pbin0, nph, phimax, p1, p2, pmid ) - - if ( pbin0 == 0.and.phipmid ) then - call get_bracket_grid_points( phmingrid, nph-2, nph, phimax, p1, dummy ) - call get_bracket_grid_points( phmingrid, 0, nph, phimax, dummy, p2 ) - p2 = p2 + twopi - pbin1 = nph-1 - pbin2 = 0 - elseif ( phi>pmid ) then - call get_bracket_grid_points( phmingrid, pbin0, nph, phimax, p1, p2 ) - pbin1 = pbin0 - pbin2 = pbin0+1 - else - call get_bracket_grid_points( phmingrid, pbin0-1, nph, phimax, p1, p2 ) - pbin1 = pbin0-1 - pbin2 = pbin0 - endif - - rbin2=rbin1+1 - - if ( pbin1<0 ) pbin1 = nph-1 - if ( pbin2>nph-1 ) pbin2 = 0 - - fr1p1 = array( rbin1, zbin0, pbin1 ) - fr1p2 = array( rbin1, zbin0, pbin2 ) - fr2p1 = array( rbin2, zbin0, pbin1 ) - fr2p2 = array( rbin2, zbin0, pbin2 ) - - dra = r - r1 - drb = r2 - r - dpa = phi - p1 - dpb = p2 - phi - - frp = fr1p1*drb*dpb & - + fr2p1*dra*dpb & - + fr1p2*drb*dpa & - + fr2p2*dra*dpa - - bilin_interp_cyl = frp/( (r2-r1)*(p2-p1) ) - -end function bilin_interp_cyl - -!---------------------------------------------- -!+ -! Returns the natural logarithm of a number, -! or a very large negative number if given a negative -!+ -!---------------------------------------------- - -real function careful_log( x ) - real, intent(in) :: x - real, parameter :: xbig = range(x)*log(10.) - if ( x <= 0. ) then - careful_log = -100. - else - careful_log = max(log(x), -xbig/2.) - endif -end function careful_log - -!---------------------------------------------- -!+ -! function computing the disc scale height -!+ -!---------------------------------------------- -real function calc_scaleheight( r ) - use eos, only:polyk, qfacdisc - real, intent(in) :: r - real :: omega, cs - if ( r > 0. ) then - omega = 1.0/r**(1.5) - cs = sqrt(polyk) * r**(-qfacdisc) - calc_scaleheight = (cs/omega) - else - calc_scaleheight = -1000. !sentinel value for star interior - endif -end function calc_scaleheight - -!---------------------------------------------- -!+ -! function computing the disc surface density -!+ -!---------------------------------------------- -real function calc_sigma( r ) - use units, only:umass - use physcon, only:solarm - real, intent(in) :: r - real :: R_in = 1., Mdisc - - Mdisc = real(1.4d0*solarm/umass*5.d-16) - - if ( r>r_In ) then - calc_sigma = sqrt(R_in) * Mdisc * r**(-3./2.)*(1-sqrt(R_in/r)) - else - calc_sigma = 0. - endif - -end function calc_sigma - -!----------------------------------------------------------------------- -!+ -! writes input options to the input file -!+ -!----------------------------------------------------------------------- -subroutine write_options_lumin_nsdisc(iunit) - use infile_utils, only:write_inopt - integer, intent(in) :: iunit - - write(iunit,"(/,a)") '# options relating to the neutron star disc' - call write_inopt(BurstProfile,'BurstProfile',& - 'Burst Profile',iunit) - ! Between 0 and 1 = constant luminosity - ! Any negative value = burst profile as described in set_Lstar - - call write_inopt(frac_X,'frac_X',& - 'Hydrogen fraction (-ve for zero opacity)',iunit) - - call write_inopt(rad_trans, 'rad_trans', & - 'Radiation transport prescription', iunit) - -end subroutine write_options_lumin_nsdisc - -!----------------------------------------------------------------------- -!+ -! reads input options from the input file -!+ -!----------------------------------------------------------------------- -subroutine read_options_lumin_nsdisc(name,valstring,imatch,igotall,ierr) - use io, only:fatal, warning - character(len=*), intent(in) :: name,valstring - logical, intent(out) :: imatch,igotall - integer, intent(out) :: ierr - integer, save :: ngot = 0 - character(len=30), parameter :: label = 'read_options_lumin_nsdisc' - - imatch = .true. - igotall = .false. - - select case(trim(name)) - case('BurstProfile') - read(valstring,*,iostat=ierr) BurstProfile - case('frac_X') - read(valstring,*,iostat=ierr) frac_X - case('rad_trans') - read(valstring,*,iostat=ierr) rad_trans - case default - imatch = .false. - end select - igotall = (ngot >= 1) - -end subroutine read_options_lumin_nsdisc - -end module lumin_nsdisc diff --git a/src/main/mpi_force.F90 b/src/main/mpi_force.F90 index 3dab68ded..2fe66c34f 100644 --- a/src/main/mpi_force.F90 +++ b/src/main/mpi_force.F90 @@ -76,6 +76,7 @@ module mpiforce integer :: maxlength = 0 integer :: n = 0 integer :: number + integer :: ibuffer ! to avoid ifort error end type stackforce contains @@ -236,6 +237,8 @@ subroutine free_mpitype_of_cellforce(dtype) integer :: mpierr call MPI_Type_free(dtype,mpierr) +#else + dtype = 0 #endif end subroutine free_mpitype_of_cellforce diff --git a/src/main/phantom.F90 b/src/main/phantom.F90 index 3046d69ba..798802b99 100644 --- a/src/main/phantom.F90 +++ b/src/main/phantom.F90 @@ -2,7 +2,7 @@ ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! ! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.github.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! program phantom ! diff --git a/src/main/readwrite_dumps_common.f90 b/src/main/readwrite_dumps_common.f90 index 5cf289f29..11df1d566 100644 --- a/src/main/readwrite_dumps_common.f90 +++ b/src/main/readwrite_dumps_common.f90 @@ -10,12 +10,13 @@ module readwrite_dumps_common ! ! :References: None ! -! :Owner: Daniel Mentiplay +! :Owner: Daniel Price ! ! :Runtime parameters: None ! -! :Dependencies: dim, dump_utils, dust_formation, eos, gitinfo, io, -! options, part, sphNGutils +! :Dependencies: boundary, boundary_dyn, checkconserved, dim, dump_utils, +! dust, dust_formation, eos, externalforces, fileutils, gitinfo, io, +! options, part, setup_params, sphNGutils, timestep, units ! use dump_utils, only:lenid implicit none @@ -110,6 +111,452 @@ subroutine get_options_from_fileid(fileid,tagged,phantomdump,smalldump,& end subroutine get_options_from_fileid +!-------------------------------------------------------------------- +!+ +! utility to extract header variables to phantom +!+ +!------------------------------------------------------------------- +subroutine unfill_header(hdr,phantomdump,got_tags,nparttot, & + nblocks,npart,npartoftype, & + tfile,hfactfile,alphafile,iprint,id,nprocs,ierr) + use dim, only:maxdustlarge,use_dust + use io, only:master ! check this + use eos, only:isink + use part, only:maxtypes,igas,idust,ndustsmall,ndustlarge,ndusttypes,& + npartoftypetot + use units, only:udist,umass,utime,set_units_extra,set_units + use dump_utils, only:extract,dump_h + use fileutils, only:make_tags_unique + type(dump_h), intent(in) :: hdr + logical, intent(in) :: phantomdump,got_tags + integer(kind=8), intent(out) :: nparttot + integer, intent(out) :: nblocks,npart,npartoftype(maxtypes) + real, intent(out) :: tfile,hfactfile,alphafile + integer, intent(in) :: iprint,id,nprocs + integer, intent(out) :: ierr + integer :: nparttoti,npartoftypetoti(maxtypes),ntypesinfile,nptinfile + integer :: ierr1,ierrs(3),i,counter + integer(kind=8) :: ntypesinfile8 + character(len=10) :: dust_label(maxdustlarge) + + ierr = 0 + nparttot = 0 + npartoftypetot(:) = 0 + npart = 0 + npartoftype(:) = 0 + isink = 0 + call extract('ntypes',ntypesinfile,hdr,ierr1) + if (ierr1 /= 0 .or. ntypesinfile < 1) then + if (phantomdump .and. got_tags) then + ierr = 4 + return + else + ntypesinfile = 5 + endif + endif + + ! extract quantities from integer header + call extract('nparttot',nparttoti,hdr,ierr1) + if (ierr1 /= 0) then + ierr = 5 + return + endif + if (ntypesinfile > maxtypes) then + write(*,*) 'WARNING: number of particle types in file exceeds array limits' + write(*,*) 'READING ONLY FIRST ',maxtypes,' OF ',ntypesinfile,' particle types' + ntypesinfile = maxtypes + endif + call extract('npartoftype',npartoftypetoti(1:ntypesinfile),hdr,ierr1) + if (ierr1 /= 0) then + npartoftype(1) = nparttoti ! assume only gas particles + endif + call extract('nblocks',nblocks,hdr,ierr1,default=1) + if (ierr1 /= 0) write(*,*) 'number of MPI blocks not read: assuming 1' + + nparttot = int(nparttoti,kind=8) + npartoftypetot = int(npartoftypetoti,kind=8) + if (nblocks==1) then + npartoftype(1:ntypesinfile) = int(npartoftypetot(1:ntypesinfile)) + if (npartoftype(idust) > 0) write(*,*) 'n(gas) = ',npartoftype(igas) + counter = 0 + do i=1,maxdustlarge + if (npartoftype(idust+i-1) > 0) then + counter = counter + 1 + endif + enddo + dust_label = 'dust' + call make_tags_unique(counter,dust_label) + do i=1,counter + write(*,*) 'n('//trim(dust_label(i))//') = ',npartoftype(idust+i-1) + enddo + endif + call extract('isink',isink,hdr,ierr1) + +!--non-MPI dumps + if (nprocs==1) then + if (nparttoti > huge(npart)) then + write (*,*) 'ERROR in readdump: number of particles exceeds 32 bit limit, must use int(kind=8)''s ',nparttoti + ierr = 4 + return + endif + endif + if (nblocks==1) then + npart = int(nparttoti) + nparttot = npart + if (id==master) write (iprint,*) 'npart = ',npart + endif + if (got_tags) then + call extract('ntypes',ntypesinfile8,hdr,ierr1) + ntypesinfile = int(ntypesinfile8) + endif + if (ntypesinfile > maxtypes) then + write(*,*) 'WARNING: number of particle types in file exceeds array limits' + write(*,*) 'READING ONLY FIRST ',maxtypes,' OF ',ntypesinfile,' particle types' + ntypesinfile = maxtypes + endif + call extract('nparttot',nparttot,hdr,ierr1) + if (nblocks > 1) then + call extract('npartoftype',npartoftype(1:ntypesinfile),hdr,ierr1) + endif + if (id==master) write(*,*) 'npart(total) = ',nparttot +! +!--number of dust species +! + if (use_dust) then + call extract('ndustsmall',ndustsmall,hdr,ierrs(1)) + call extract('ndustlarge',ndustlarge,hdr,ierrs(2)) + if (any(ierrs(1:2) /= 0)) then + call extract('ndustfluids',ndustsmall,hdr,ierrs(1)) ! for backwards compatibility + if (ierrs(1) /= 0) write(*,*) 'ERROR reading number of small/large grain types from file header' + endif + ndusttypes = ndustsmall + ndustlarge + endif +! +!--units +! + call extract('udist',udist,hdr,ierrs(1)) + call extract('umass',umass,hdr,ierrs(2)) + call extract('utime',utime,hdr,ierrs(3)) + if (all(ierrs(1:3)==0)) then + call set_units_extra() + else + write(iprint,*) 'ERROR reading units from dump file, assuming default' + call set_units() ! use default units + endif + ! get nptmass from header, needed to figure out if gwinspiral info is sensible + call extract('nptmass',nptinfile,hdr,ierrs(1)) +!--default real + call unfill_rheader(hdr,phantomdump,ntypesinfile,nptinfile,& + tfile,hfactfile,alphafile,iprint,ierr) + if (ierr /= 0) return + + if (id==master) write(iprint,*) 'time = ',tfile + +end subroutine unfill_header + +!-------------------------------------------------------------------- +!+ +! subroutine to fill the real header with various things +!+ +!------------------------------------------------------------------- +subroutine fill_header(sphNGdump,t,nparttot,npartoftypetot,nblocks,nptmass,hdr,ierr) + use eos, only:write_headeropts_eos,polyk2 + use options, only:tolh,alpha,alphau,alphaB,iexternalforce,ieos + use part, only:massoftype,hfact,Bextx,Bexty,Bextz,ndustsmall,ndustlarge,& + idust,grainsize,graindens,ndusttypes + use checkconserved, only:get_conserv,etot_in,angtot_in,totmom_in,mdust_in + use setup_params, only:rhozero + use timestep, only:dtmax_user,idtmax_n_next,idtmax_frac_next,C_cour,C_force + use externalforces, only:write_headeropts_extern + use boundary, only:xmin,xmax,ymin,ymax,zmin,zmax + use boundary_dyn, only:dynamic_bdy,dxyz,rho_bkg_ini,irho_bkg_ini + use dump_utils, only:reset_header,add_to_rheader,add_to_header,add_to_iheader,num_in_header,dump_h,maxphead + use dim, only:use_dust,maxtypes,use_dustgrowth,do_nucleation, & + phantom_version_major,phantom_version_minor,phantom_version_micro,periodic,idumpfile + use units, only:udist,umass,utime,unit_Bfield + use dust_formation, only:write_headeropts_dust_formation + + logical, intent(in) :: sphNGdump + real, intent(in) :: t + integer(kind=8), intent(in) :: nparttot,npartoftypetot(:) + integer, intent(in) :: nblocks,nptmass + type(dump_h), intent(inout) :: hdr + integer, intent(out) :: ierr + integer :: number + + ierr = 0 + ! default int + call add_to_iheader(int(nparttot),'nparttot',hdr,ierr) + call add_to_iheader(maxtypes,'ntypes',hdr,ierr) + call add_to_iheader(int(npartoftypetot(1:maxtypes)),'npartoftype',hdr,ierr) + call add_to_iheader(nblocks,'nblocks',hdr,ierr) + call add_to_iheader(nptmass,'nptmass',hdr,ierr) + call add_to_iheader(ndustlarge,'ndustlarge',hdr,ierr) + call add_to_iheader(ndustsmall,'ndustsmall',hdr,ierr) + call add_to_iheader(idust,'idust',hdr,ierr) + call add_to_iheader(idtmax_n_next,'idtmax_n',hdr,ierr) + call add_to_iheader(idtmax_frac_next,'idtmax_frac',hdr,ierr) + call add_to_iheader(idumpfile,'idumpfile',hdr,ierr) + call add_to_iheader(phantom_version_major,'majorv',hdr,ierr) + call add_to_iheader(phantom_version_minor,'minorv',hdr,ierr) + call add_to_iheader(phantom_version_micro,'microv',hdr,ierr) + + ! int*8 + call add_to_header(nparttot,'nparttot',hdr,ierr) + call add_to_header(int(maxtypes,kind=8),'ntypes',hdr,ierr) + call add_to_header(npartoftypetot(1:maxtypes),'npartoftype',hdr,ierr) + + ! int*4 + call add_to_header(iexternalforce,'iexternalforce',hdr,ierr) + call add_to_header(ieos,'ieos',hdr,ierr) + call write_headeropts_eos(ieos,hdr,ierr) + + ! default real variables + call add_to_rheader(t,'time',hdr,ierr) + call add_to_rheader(dtmax_user,'dtmax',hdr,ierr) + call add_to_rheader(rhozero,'rhozero',hdr,ierr) + if (sphNGdump) then ! number = 23 + call add_to_rheader(0.,'escaptot',hdr,ierr) + call add_to_rheader(0.,'tkin',hdr,ierr) + call add_to_rheader(0.,'tgrav',hdr,ierr) + call add_to_rheader(0.,'tterm',hdr,ierr) + call add_to_rheader(0.,'anglostx',hdr,ierr) + call add_to_rheader(0.,'anglosty',hdr,ierr) + call add_to_rheader(0.,'anglostz',hdr,ierr) + call add_to_rheader(0.,'specang',hdr,ierr) + call add_to_rheader(0.,'ptmassin',hdr,ierr) + call add_to_rheader(0.,'tmag',hdr,ierr) + call add_to_rheader(Bextx,'Bextx',hdr,ierr) + call add_to_rheader(Bexty,'Bexty',hdr,ierr) + call add_to_rheader(Bextz,'Bextz',hdr,ierr) + call add_to_rheader(0.,'hzero',hdr,ierr) + call add_to_rheader(1.5*polyk2,'uzero_n2',hdr,ierr) + call add_to_rheader(0.,'hmass',hdr,ierr) + call add_to_rheader(0.,'gapfac',hdr,ierr) + call add_to_rheader(0.,'pmassinitial',hdr,ierr) + else ! number = 49 + call add_to_rheader(hfact,'hfact',hdr,ierr) + call add_to_rheader(tolh,'tolh',hdr,ierr) + call add_to_rheader(C_cour,'C_cour',hdr,ierr) + call add_to_rheader(C_force,'C_force',hdr,ierr) + call add_to_rheader(alpha,'alpha',hdr,ierr) + call add_to_rheader(alphau,'alphau',hdr,ierr) + call add_to_rheader(alphaB,'alphaB',hdr,ierr) + call add_to_rheader(massoftype,'massoftype',hdr,ierr) ! array + if (do_nucleation) call write_headeropts_dust_formation(hdr,ierr) + call add_to_rheader(Bextx,'Bextx',hdr,ierr) + call add_to_rheader(Bexty,'Bexty',hdr,ierr) + call add_to_rheader(Bextz,'Bextz',hdr,ierr) + call add_to_rheader(0.,'dum',hdr,ierr) + if (iexternalforce /= 0) call write_headeropts_extern(iexternalforce,hdr,t,ierr) + if (periodic) then + call add_to_rheader(xmin,'xmin',hdr,ierr) + call add_to_rheader(xmax,'xmax',hdr,ierr) + call add_to_rheader(ymin,'ymin',hdr,ierr) + call add_to_rheader(ymax,'ymax',hdr,ierr) + call add_to_rheader(zmin,'zmin',hdr,ierr) + call add_to_rheader(zmax,'zmax',hdr,ierr) + endif + if (dynamic_bdy) then + call add_to_rheader(dxyz,'dxyz',hdr,ierr) + call add_to_iheader(irho_bkg_ini,'irho_bkg_ini',hdr,ierr) + call add_to_rheader(rho_bkg_ini,'rho_bkg_ini',hdr,ierr) + endif + call add_to_rheader(get_conserv,'get_conserv',hdr,ierr) + call add_to_rheader(etot_in,'etot_in',hdr,ierr) + call add_to_rheader(angtot_in,'angtot_in',hdr,ierr) + call add_to_rheader(totmom_in,'totmom_in',hdr,ierr) + call add_to_rheader(mdust_in(1:ndusttypes),'mdust_in',hdr,ierr) + if (use_dust) then + call add_to_rheader(grainsize(1:ndusttypes),'grainsize',hdr,ierr) + call add_to_rheader(graindens(1:ndusttypes),'graindens',hdr,ierr) + endif + endif + + ! real*8 + call add_to_header(udist,'udist',hdr,ierr) + call add_to_header(umass,'umass',hdr,ierr) + call add_to_header(utime,'utime',hdr,ierr) + call add_to_header(unit_Bfield,'umagfd',hdr,ierr) + + if (ierr /= 0) write(*,*) ' ERROR: arrays too small writing rheader' + + number = num_in_header(hdr%realtags) + if (number >= maxphead) then + write(*,*) 'error: header arrays too small for number of items in header: will be truncated' + endif + +end subroutine fill_header + +!-------------------------------------------------------------------- +!+ +! subroutine to set runtime parameters having read the real header +!+ +!------------------------------------------------------------------- +subroutine unfill_rheader(hdr,phantomdump,ntypesinfile,nptmass,& + tfile,hfactfile,alphafile,iprint,ierr) + use io, only:id,master + use dim, only:maxvxyzu,nElements,use_dust,use_dustgrowth,use_krome,do_nucleation,idumpfile + use eos, only:extract_eos_from_hdr, read_headeropts_eos + use options, only:ieos,iexternalforce + use part, only:massoftype,Bextx,Bexty,Bextz,mhd,periodic,& + maxtypes,grainsize,graindens,ndusttypes + use checkconserved, only:get_conserv,etot_in,angtot_in,totmom_in,mdust_in + use setup_params, only:rhozero + use externalforces, only:read_headeropts_extern,extract_iextern_from_hdr + use boundary, only:xmin,xmax,ymin,ymax,zmin,zmax,set_boundary + use boundary_dyn, only:dynamic_bdy,dxyz,irho_bkg_ini,rho_bkg_ini,rho_bkg_ini1 + use dump_utils, only:extract,dump_h + use dust, only:grainsizecgs,graindenscgs + use units, only:unit_density,udist + use timestep, only:idtmax_n,idtmax_frac + use dust_formation, only:read_headeropts_dust_formation + type(dump_h), intent(in) :: hdr + logical, intent(in) :: phantomdump + integer, intent(in) :: iprint,ntypesinfile,nptmass + real, intent(out) :: tfile,hfactfile,alphafile + integer, intent(out) :: ierr + + integer, parameter :: lu = 173 + integer :: ierrs(10),iextern_in_file + real :: xmini,xmaxi,ymini,ymaxi,zmini,zmaxi,dtmaxi + real :: alphaufile,alphaBfile,C_courfile,C_forcefile,tolhfile + logical :: iexist + + ierr = 0 + call extract('time',tfile,hdr,ierr) + if (ierr/=0) call extract('gt',tfile,hdr,ierr) ! this is sphNG's label for time + call extract('dtmax',dtmaxi,hdr,ierr) + call extract('rhozero',rhozero,hdr,ierr) + Bextx = 0. + Bexty = 0. + Bextz = 0. + if (phantomdump) then + call extract('hfact',hfactfile,hdr,ierr) + call extract('tolh',tolhfile,hdr,ierr) + call extract('C_cour',C_courfile,hdr,ierr) + call extract('C_force',C_forcefile,hdr,ierr) + call extract('alpha',alphafile,hdr,ierr) + if (maxvxyzu >= 4) then + call extract('alphau',alphaufile,hdr,ierr) + else + alphaufile = 0. + endif + if (mhd) then + call extract('alphaB',alphaBfile,hdr,ierr) + endif + + if (extract_eos_from_hdr) call extract('ieos',ieos,hdr,ierr) + + call extract('massoftype',massoftype(1:ntypesinfile),hdr,ierr) + if (ierr /= 0) then + write(*,*) '*** ERROR reading massoftype from dump header ***' + ierr = 4 + endif + if (do_nucleation) then + call read_headeropts_dust_formation(hdr,ierr) + if (ierr /= 0) ierr = 6 + endif + + call extract('iexternalforce',iextern_in_file,hdr,ierrs(1)) + if (extract_iextern_from_hdr) iexternalforce = iextern_in_file + if (iexternalforce /= 0) then + call read_headeropts_extern(iexternalforce,hdr,nptmass,ierrs(1)) + if (ierrs(1) /= 0) ierr = 5 + elseif (iextern_in_file /= 0) then + call read_headeropts_extern(iextern_in_file,hdr,nptmass,ierrs(1)) + if (ierrs(1) /= 0) ierr = 5 + endif + + call extract('idtmax_n',idtmax_n,hdr,ierr,default=1) + call extract('idtmax_frac',idtmax_frac,hdr,ierr) + call extract('idumpfile',idumpfile,hdr,ierr) + else + massoftype(1) = 0. + hfactfile = 0. + endif + + call read_headeropts_eos(ieos,hdr,ierr) + + if (periodic) then + call extract('xmin',xmini,hdr,ierrs(1)) + call extract('xmax',xmaxi,hdr,ierrs(2)) + call extract('ymin',ymini,hdr,ierrs(3)) + call extract('ymax',ymaxi,hdr,ierrs(4)) + call extract('zmin',zmini,hdr,ierrs(5)) + call extract('zmax',zmaxi,hdr,ierrs(6)) + if (any(ierrs(1:6) /= 0)) then + write(*,"(2(/,a))") ' ERROR: dump does not contain boundary positions', & + ' but we are using periodic boundaries' + inquire(file='bound.tmp',exist=iexist) + if (iexist) then + open(unit=lu,file='bound.tmp') + read(lu,*) xmini,xmaxi,ymini,ymaxi,zmini,zmaxi + close(lu) + call set_boundary(xmini,xmaxi,ymini,ymaxi,zmini,zmaxi) + write(*,"(a,6(es10.3,1x))") ' READ from bound.tmp ',xmin,xmax,ymin,ymax,zmin,zmax + else + write(*,"(3(/,a),/,/,a)") ' To silence this error and restart from an older dump file ', & + ' create an ascii file called "bound.tmp" in the current directory', & + ' with xmin,xmax,ymin,ymax,zmin & zmax in it, e.g.: ', & + ' 0. 1. 0. 1. 0. 1.' + ierr = 5 ! spit fatal error + endif + else + call set_boundary(xmini,xmaxi,ymini,ymaxi,zmini,zmaxi) + endif + endif + + if (dynamic_bdy) then + call extract('irho_bkg_ini',irho_bkg_ini,hdr,ierrs(1)) + call extract('rho_bkg_ini',rho_bkg_ini,hdr,ierrs(1)) + call extract('dxyz',dxyz,hdr,ierrs(2)) + if (rho_bkg_ini > 0.) then + rho_bkg_ini1 = 1.0/rho_bkg_ini + else + rho_bkg_ini1 = 0. + endif + endif + + if (mhd) then + call extract('Bextx',Bextx,hdr,ierrs(1)) + call extract('Bexty',Bexty,hdr,ierrs(2)) + call extract('Bextz',Bextz,hdr,ierrs(3)) + if (id==master) then + if (any(ierrs(1:3) /= 0)) then + write(*,*) 'ERROR reading external field (setting to zero)' + else + write(*,*) 'External field found, Bext = ',Bextx,Bexty,Bextz + endif + endif + endif + + ! values to track that conserved values remain conserved + call extract('get_conserv',get_conserv,hdr,ierrs(1)) + call extract('etot_in', etot_in, hdr,ierrs(2)) + call extract('angtot_in', angtot_in, hdr,ierrs(3)) + call extract('totmom_in', totmom_in, hdr,ierrs(4)) + call extract('mdust_in', mdust_in(1:ndusttypes), hdr,ierrs(5)) + if (any(ierrs(1:4) /= 0)) then + write(*,*) 'ERROR reading values to verify conservation laws. Resetting initial values.' + get_conserv = 1.0 + endif + + + !--pull grain size and density arrays if they are in the header + !-- i.e. if dustgrowth is not ON + if (use_dust .and. .not.use_dustgrowth) then + call extract('grainsize',grainsize(1:ndusttypes),hdr,ierrs(1)) + call extract('graindens',graindens(1:ndusttypes),hdr,ierrs(2)) + if (any(ierrs(1:2) /= 0)) then + write(*,*) 'ERROR reading grain size/density from file header' + grainsize(1) = real(grainsizecgs/udist) + graindens(1) = real(graindenscgs/unit_density) + endif + endif + +end subroutine unfill_rheader + !--------------------------------------------------------------- !+ ! make sure required arrays have been read from Phantom file diff --git a/src/main/readwrite_dumps_fortran.F90 b/src/main/readwrite_dumps_fortran.f90 similarity index 64% rename from src/main/readwrite_dumps_fortran.F90 rename to src/main/readwrite_dumps_fortran.f90 index 389bb7fef..6ecf0627c 100644 --- a/src/main/readwrite_dumps_fortran.F90 +++ b/src/main/readwrite_dumps_fortran.f90 @@ -18,17 +18,16 @@ module readwrite_dumps_fortran ! ! :Runtime parameters: None ! -! :Dependencies: boundary, boundary_dyn, checkconserved, dim, dump_utils, -! dust, dust_formation, eos, externalforces, fileutils, io, lumin_nsdisc, -! memory, metric_tools, mpi, mpiutils, options, part, -! readwrite_dumps_common, setup_params, sphNGutils, timestep, units +! :Dependencies: boundary_dyn, dim, dump_utils, eos, io, memory, +! metric_tools, mpiutils, options, part, readwrite_dumps_common, +! sphNGutils, timestep ! use dump_utils, only:lenid,ndatatypes,i_int,i_int1,i_int2,i_int4,i_int8,& i_real,i_real4,i_real8,int1,int2,int1o,int2o,dump_h,lentag - use readwrite_dumps_common, only:check_arrays,fileident,get_options_from_fileid + use readwrite_dumps_common, only:check_arrays,fileident,get_options_from_fileid,fill_header,unfill_header implicit none - public :: write_smalldump_fortran,write_fulldump_fortran,read_smalldump_fortran,read_dump_fortran + public :: write_smalldump_fortran,write_fulldump_fortran,read_smalldump_fortran,read_dump_fortran,unfill_header logical, target, public :: opened_full_dump_fortran ! for use in analysis files if user wishes to skip small dumps logical, target, public :: dt_read_in_fortran ! to determine if dt has been read in so that ibin & ibinold can be set on restarts @@ -39,161 +38,6 @@ module readwrite_dumps_fortran private contains -!-------------------------------------------------------------------- -!+ -! utility to determine whether to read a particular block -! in the dump file, in whole or in part. -! Allows limited changes to number of threads. -!+ -!-------------------------------------------------------------------- -subroutine get_blocklimits(npartblock,nblocks,nthreads,id,iblock,noffset,npartread) - use io, only:die,fatal - integer(kind=8), intent(in) :: npartblock - integer, intent(in) :: nblocks,nthreads,id,iblock - integer, intent(out) :: noffset,npartread - integer :: nblocksperthread,nthreadsperblock - character(len=15), parameter :: tag = 'get_blocklimits' -! -!--check for errors in input -! - if (npartblock < 0) call fatal(tag,'block in dump file has npartinblock < 0') - if (npartblock > huge(npartread)) call fatal(tag,'npart in block exceeds 32 bit limit') -! -!--usual situation: nblocks = nprocessors -! read whole block if id = iblock -! - if (nblocks==nthreads) then - if (id==iblock-1) then - !--read whole block - npartread = int(npartblock) - noffset = 0 - else - !--do not read block - npartread = 0 - noffset = 0 - endif - - elseif (nblocks > nthreads .and. mod(nblocks,nthreads)==0) then -! -!--if more blocks than processes and nblocks exactly divisible by nthreads, -! then just read more than one block per thread -! - nblocksperthread = nblocks/nthreads - if (id==(iblock-1)/nblocksperthread) then - npartread = int(npartblock) - noffset = 0 - else - npartread = 0 - noffset = 0 - endif - - elseif (nthreads > nblocks .and. mod(nthreads,nblocks)==0) then -! -!--if more threads than blocks, and exactly divisible, read fractions of blocks only -! - nthreadsperblock = nthreads/nblocks - if (id/nthreadsperblock==iblock-1) then - npartread = int((npartblock-1)/nthreadsperblock) + 1 - noffset = mod(id,nthreadsperblock)*npartread - - if (mod(id,nthreadsperblock)==nthreadsperblock-1) then - !--last thread has remainder for non-exactly divisible numbers of particles - npartread = int(npartblock) - (nthreadsperblock-1)*npartread - !--die if we would need to load balance between more than the last processor. - if (npartread < 0) then - print*,' npart to read from last block =',npartread - call fatal(tag,'error assigning npart to last thread') - endif - endif - else - npartread = 0 - noffset = 0 - endif - else - noffset = 0 - npartread = 0 - print*,' ERROR: rearrangement of ',nblocks,' blocks to ',nthreads,' threads not implemented' - call die - endif - -end subroutine get_blocklimits - -!-------------------------------------------------------------------- -!+ -! utility for initialising each thread -!+ -!-------------------------------------------------------------------- -subroutine start_threadwrite(id,iunit,filename) -#ifdef MPI - use mpi - use mpiutils, only:status,mpierr -#endif - use io, only:fatal,iverbose - implicit none - integer, intent(in) :: id, iunit - character(len=*), intent(in) :: filename - integer :: nowgo,ierr - - if (iverbose >= 3) print *,id,' : starting write...' - nowgo = 0 - if (id > 0) then -#ifdef MPI - call MPI_RECV(nowgo,1,MPI_INTEGER,id-1,99,MPI_COMM_WORLD,status,mpierr) -#endif - open(unit=iunit,file=filename,status='old',form='unformatted',position='append',iostat=ierr) - if (ierr /= 0) then - call fatal('start_threadwrite','can''t append to dumpfile '//trim(filename)) - else - if (iverbose >= 3) print*,'thread ',id,': opened file '//trim(filename) - endif - endif - -end subroutine start_threadwrite - -!-------------------------------------------------------------------- -!+ -! utility for finalising each thread -!+ -!-------------------------------------------------------------------- -subroutine end_threadwrite(id) - use io, only:iverbose -#ifdef MPI - use mpi - use mpiutils, only:mpierr - use io, only:nprocs -#endif - implicit none - integer, intent(in) :: id -#ifdef MPI - integer :: nowgo -#endif - - if (iverbose >= 3) print *,' thread ',id,' : finished write.' -#ifdef MPI - if (id < nprocs-1) then - nowgo = 1 - call MPI_SEND(nowgo,1,MPI_INTEGER,id+1,99,MPI_COMM_WORLD,mpierr) - endif -#endif - -end subroutine end_threadwrite - -!-------------------------------------------------------------------- -!+ -! extract dump size used in Phantom from the fileid string -!+ -!-------------------------------------------------------------------- -subroutine get_dump_size(fileid,smalldump) - character(len=lenid), intent(in) :: fileid - logical, intent(out) :: smalldump - ! - if (fileid(1:1)=='S') then - smalldump = .true. - else - smalldump = .false. - endif - -end subroutine get_dump_size !-------------------------------------------------------------------- !+ @@ -204,7 +48,7 @@ end subroutine get_dump_size subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use dim, only:maxp,maxvxyzu,maxalpha,ndivcurlv,ndivcurlB,maxgrav,gravity,use_dust,& lightcurve,use_dustgrowth,store_dust_temperature,gr,do_nucleation,& - ind_timesteps,mhd_nonideal,use_krome,h2chemistry,update_muGamma + ind_timesteps,mhd_nonideal,use_krome,h2chemistry,update_muGamma,mpi use eos, only:ieos,eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP use io, only:idump,iprint,real4,id,master,error,warning,nprocs use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,Bevol,Bevol_label,Bxyz,Bxyz_label,npart,maxtypes, & @@ -222,12 +66,9 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use options, only:use_dustfrac,use_porosity,use_var_comp,icooling use dump_utils, only:tag,open_dumpfile_w,allocate_header,& free_header,write_header,write_array,write_block_header - use mpiutils, only:reduce_mpi,reduceall_mpi + use mpiutils, only:reduce_mpi,reduceall_mpi,start_threadwrite,end_threadwrite use timestep, only:dtmax,idtmax_n,idtmax_frac use part, only:ibin,krome_nmols,T_gas_cool -#ifdef PRDRAG - use lumin_nsdisc, only:beta -#endif use metric_tools, only:imetric, imet_et use eos_stamatellos, only:gradP_cool,doFLD,urad_FLD,ttherm_store,teqi_store,opac_store real, intent(in) :: t @@ -240,7 +81,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) integer(kind=8) :: ilen(4) integer :: nums(ndatatypes,4) integer :: ipass,k,l,ioffset - integer :: ierr,ierrs(30) + integer :: ierr,nerr integer :: nblocks,nblockarrays,narraylengths integer(kind=8) :: nparttot logical :: sphNGdump,write_itype,use_gas @@ -252,21 +93,21 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) !--collect global information from MPI threads ! !--allow non-MPI calls to create MPI dump files -#ifdef MPI - nparttot = reduceall_mpi('+',npart) - call update_npartoftypetot -#else - if (present(ntotal)) then - nparttot = ntotal + if (mpi) then + nparttot = reduceall_mpi('+',npart) call update_npartoftypetot - if (all(npartoftypetot==0)) then - npartoftypetot(1) = ntotal - endif else - nparttot = npart - call update_npartoftypetot + if (present(ntotal)) then + nparttot = ntotal + call update_npartoftypetot + if (all(npartoftypetot==0)) then + npartoftypetot(1) = ntotal + endif + else + nparttot = npart + call update_npartoftypetot + endif endif -#endif nblocks = nprocs sphNGdump = .false. @@ -329,13 +170,13 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ! repeated nblocks times (once for each MPI process) ! nblockarrays = narraylengths*nblocks - write (idump, iostat=ierr) nblockarrays + write (idump,iostat=ierr) nblockarrays endif masterthread call start_threadwrite(id,idump,dumpfile) - ierrs = 0 + nerr = 0 nums = 0 ilen = 0_8 if (sphNGdump) then @@ -345,64 +186,65 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) endif do ipass=1,2 do k=1,ndatatypes + nerr = 0 ! ! Block 1 arrays (hydrodynamics) ! ilen(1) = int(npart,kind=8) - if (write_itype) call write_array(1,iphase,'itype',npart,k,ipass,idump,nums,ierrs(1),func=iamtype_int11) - call write_array(1,xyzh,xyzh_label,3,npart,k,ipass,idump,nums,ierrs(2)) + if (write_itype) call write_array(1,iphase,'itype',npart,k,ipass,idump,nums,nerr,func=iamtype_int11) + call write_array(1,xyzh,xyzh_label,3,npart,k,ipass,idump,nums,nerr) if (use_dustgrowth) then - call write_array(1,dustprop,dustprop_label,2,npart,k,ipass,idump,nums,ierrs(3)) - call write_array(1,VrelVf,VrelVf_label,npart,k,ipass,idump,nums,ierrs(3)) - call write_array(1,dustgasprop,dustgasprop_label,4,npart,k,ipass,idump,nums,ierrs(3)) - if (use_porosity) call write_array(1,filfac,filfac_label,npart,k,ipass,idump,nums,ierrs(3)) + call write_array(1,dustprop,dustprop_label,2,npart,k,ipass,idump,nums,nerr) + call write_array(1,VrelVf,VrelVf_label,npart,k,ipass,idump,nums,nerr) + call write_array(1,dustgasprop,dustgasprop_label,4,npart,k,ipass,idump,nums,nerr) + if (use_porosity) call write_array(1,filfac,filfac_label,npart,k,ipass,idump,nums,nerr) endif - if (h2chemistry) call write_array(1,abundance,abundance_label,nabundances,npart,k,ipass,idump,nums,ierrs(5)) - if (use_dust) call write_array(1,dustfrac,dustfrac_label,ndusttypes,npart,k,ipass,idump,nums,ierrs(7)) - if (use_dust) call write_array(1,tstop,tstop_label,ndustsmall,npart,k,ipass,idump,nums,ierrs(8)) + if (h2chemistry) call write_array(1,abundance,abundance_label,nabundances,npart,k,ipass,idump,nums,nerr) + if (use_dust) call write_array(1,dustfrac,dustfrac_label,ndusttypes,npart,k,ipass,idump,nums,nerr) + if (use_dust) call write_array(1,tstop,tstop_label,ndustsmall,npart,k,ipass,idump,nums,nerr) if (use_dustfrac) then do l=1,ndustsmall - call write_array(1,deltav(:,l,:),deltav_label,3,npart,k,ipass,idump,nums,ierrs(10)) + call write_array(1,deltav(:,l,:),deltav_label,3,npart,k,ipass,idump,nums,nerr) enddo endif if (gr) then - call write_array(1,pxyzu,pxyzu_label,maxvxyzu,npart,k,ipass,idump,nums,ierrs(8)) - call write_array(1,dens,'dens prim',npart,k,ipass,idump,nums,ierrs(8)) + call write_array(1,pxyzu,pxyzu_label,maxvxyzu,npart,k,ipass,idump,nums,nerr) + call write_array(1,dens,'dens prim',npart,k,ipass,idump,nums,nerr) if (imetric==imet_et) then ! Output metric if imetric=iet - call write_array(1,metrics(1,1,1,:), 'gtt (covariant)',npart,k,ipass,idump,nums,ierrs(8)) + call write_array(1,metrics(1,1,1,:), 'gtt (covariant)',npart,k,ipass,idump,nums,nerr) ! call write_array(1,metrics(1,2,1,:), 'gtx (covariant)',npart,k,ipass,idump,nums,ierrs(8)) ! call write_array(1,metrics(1,3,1,:), 'gty (covariant)',npart,k,ipass,idump,nums,ierrs(8)) ! call write_array(1,metrics(1,2,1,:), 'gtz (covariant)',npart,k,ipass,idump,nums,ierrs(8)) ! call write_array(1,metrics(1,2,1,:), 'gtx (covariant)',npart,k,ipass,idump,nums,ierrs(8)) - call write_array(1,metrics(2,2,1,:), 'gxx (covariant)',npart,k,ipass,idump,nums,ierrs(8)) - call write_array(1,metrics(3,3,1,:), 'gyy (covariant)',npart,k,ipass,idump,nums,ierrs(8)) - call write_array(1,metrics(4,4,1,:), 'gzz (covariant)',npart,k,ipass,idump,nums,ierrs(8)) + call write_array(1,metrics(2,2,1,:), 'gxx (covariant)',npart,k,ipass,idump,nums,nerr) + call write_array(1,metrics(3,3,1,:), 'gyy (covariant)',npart,k,ipass,idump,nums,nerr) + call write_array(1,metrics(4,4,1,:), 'gzz (covariant)',npart,k,ipass,idump,nums,nerr) - call write_array(1,metricderivs(1,1,1,:), 'dxgtt (covariant)',npart,k,ipass,idump,nums,ierrs(8)) - call write_array(1,metricderivs(2,2,1,:), 'dxgxx (covariant)',npart,k,ipass,idump,nums,ierrs(8)) - call write_array(1,metricderivs(3,3,1,:), 'dxgyy (covariant)',npart,k,ipass,idump,nums,ierrs(8)) - call write_array(1,metricderivs(4,4,1,:), 'dxgzz (covariant)',npart,k,ipass,idump,nums,ierrs(8)) + call write_array(1,metricderivs(1,1,1,:), 'dxgtt (covariant)',npart,k,ipass,idump,nums,nerr) + call write_array(1,metricderivs(2,2,1,:), 'dxgxx (covariant)',npart,k,ipass,idump,nums,nerr) + call write_array(1,metricderivs(3,3,1,:), 'dxgyy (covariant)',npart,k,ipass,idump,nums,nerr) + call write_array(1,metricderivs(4,4,1,:), 'dxgzz (covariant)',npart,k,ipass,idump,nums,nerr) - call write_array(1,tmunus(1,1,:), 'tmunutt (covariant)',npart,k,ipass,idump,nums,ierrs(8)) + call write_array(1,tmunus(1,1,:), 'tmunutt (covariant)',npart,k,ipass,idump,nums,nerr) endif endif if (eos_is_non_ideal(ieos) .or. (.not.store_dust_temperature .and. icooling > 0)) then - call write_array(1,eos_vars(itemp,:),eos_vars_label(itemp),npart,k,ipass,idump,nums,ierrs(12)) + call write_array(1,eos_vars(itemp,:),eos_vars_label(itemp),npart,k,ipass,idump,nums,nerr) endif - if (eos_is_non_ideal(ieos)) call write_array(1,eos_vars(igamma,:),eos_vars_label(igamma),npart,k,ipass,idump,nums,ierrs(12)) + if (eos_is_non_ideal(ieos)) call write_array(1,eos_vars(igamma,:),eos_vars_label(igamma),npart,k,ipass,idump,nums,nerr) - call write_array(1,vxyzu,vxyzu_label,maxvxyzu,npart,k,ipass,idump,nums,ierrs(4)) + call write_array(1,vxyzu,vxyzu_label,maxvxyzu,npart,k,ipass,idump,nums,nerr) ! write pressure to file if ((eos_outputs_gasP(ieos) .or. eos_is_non_ideal(ieos)) .and. k==i_real) then - call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,ierrs(13),index=igasP) + call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,nerr,index=igasP) endif ! write X, Z, mu to file if (eos_outputs_mu(ieos)) then - call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,ierrs(13),index=imu) + call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,nerr,index=imu) if (use_var_comp) then - call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,ierrs(13),index=iX) - call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,ierrs(13),index=iZ) + call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,nerr,index=iX) + call write_array(1,eos_vars,eos_vars_label,1,npart,k,ipass,idump,nums,nerr,index=iZ) endif endif ! write stamatellos cooling values @@ -413,73 +255,64 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) call write_array(1,opac_store,'opacity',npart,k,ipass,idump,nums,ierrs(13)) endif ! smoothing length written as real*4 to save disk space - call write_array(1,xyzh,xyzh_label,1,npart,k,ipass,idump,nums,ierrs(14),use_kind=4,index=4) - if (maxalpha==maxp) call write_array(1,alphaind,(/'alpha'/),1,npart,k,ipass,idump,nums,ierrs(15)) + call write_array(1,xyzh,xyzh_label,1,npart,k,ipass,idump,nums,nerr,use_kind=4,index=4) + if (maxalpha==maxp) call write_array(1,alphaind,(/'alpha'/),1,npart,k,ipass,idump,nums,nerr) !if (maxalpha==maxp) then ! (uncomment this to write alphaloc to the full dumps) ! call write_array(1,alphaind,(/'alpha ','alphaloc'/),2,npart,k,ipass,idump,nums,ierrs(10)) !endif - if (ndivcurlv >= 1) call write_array(1,divcurlv,divcurlv_label,ndivcurlv,npart,k,ipass,idump,nums,ierrs(16)) + if (ndivcurlv >= 1) call write_array(1,divcurlv,divcurlv_label,ndivcurlv,npart,k,ipass,idump,nums,nerr) !if (maxdvdx==maxp) call write_array(1,dvdx,dvdx_label,9,npart,k,ipass,idump,nums,ierrs(17)) if (gravity .and. maxgrav==maxp) then - call write_array(1,poten,'poten',npart,k,ipass,idump,nums,ierrs(17)) + call write_array(1,poten,'poten',npart,k,ipass,idump,nums,nerr) endif if (ind_timesteps) then if (.not.allocated(temparr)) allocate(temparr(npart)) temparr(1:npart) = dtmax/2.**ibin(1:npart) - call write_array(1,temparr,'dt',npart,k,ipass,idump,nums,ierrs(18),use_kind=4) + call write_array(1,temparr,'dt',npart,k,ipass,idump,nums,nerr,use_kind=4) endif - call write_array(1,iorig,'iorig',npart,k,ipass,idump,nums,ierrs(29)) + call write_array(1,iorig,'iorig',npart,k,ipass,idump,nums,nerr) -#ifdef PRDRAG - if (k==i_real) then - if (.not.allocated(temparr)) allocate(temparr(npart)) - do l=1,npart - temparr(l) = real4(beta(xyzh(1,l), xyzh(2,l), xyzh(3,l))) - enddo - call write_array(1,temparr,'beta_pr',npart,k,ipass,idump,nums,ierrs(19)) - endif -#endif if (lightcurve) then - call write_array(1,luminosity,'luminosity',npart,k,ipass,idump,nums,ierrs(20)) + call write_array(1,luminosity,'luminosity',npart,k,ipass,idump,nums,nerr) endif if (use_krome) then - call write_array(1,abundance,abundance_label,krome_nmols,npart,k,ipass,idump,nums,ierrs(21)) - call write_array(1,T_gas_cool,'temp',npart,k,ipass,idump,nums,ierrs(24)) + call write_array(1,abundance,abundance_label,krome_nmols,npart,k,ipass,idump,nums,nerr) + call write_array(1,T_gas_cool,'temp',npart,k,ipass,idump,nums,nerr) endif if (update_muGamma .or. use_krome) then - call write_array(1,eos_vars(imu,:),eos_vars_label(imu),npart,k,ipass,idump,nums,ierrs(12)) - call write_array(1,eos_vars(igamma,:),eos_vars_label(igamma),npart,k,ipass,idump,nums,ierrs(12)) + call write_array(1,eos_vars(imu,:),eos_vars_label(imu),npart,k,ipass,idump,nums,nerr) + call write_array(1,eos_vars(igamma,:),eos_vars_label(igamma),npart,k,ipass,idump,nums,nerr) endif - if (do_nucleation) then - call write_array(1,nucleation,nucleation_label,n_nucleation,npart,k,ipass,idump,nums,ierrs(25)) + call write_array(1,nucleation,nucleation_label,n_nucleation,npart,k,ipass,idump,nums,nerr) endif If (itau_alloc == 1) then - call write_array(1,tau,'tau',npart,k,ipass,idump,nums,ierrs(30)) + call write_array(1,tau,'tau',npart,k,ipass,idump,nums,nerr) endif If (itauL_alloc == 1) then - call write_array(1,tau_lucy,'tau_lucy',npart,k,ipass,idump,nums,ierrs(30)) + call write_array(1,tau_lucy,'tau_lucy',npart,k,ipass,idump,nums,nerr) endif if (store_dust_temperature) then - call write_array(1,dust_temp,'Tdust',npart,k,ipass,idump,nums,ierrs(26)) + call write_array(1,dust_temp,'Tdust',npart,k,ipass,idump,nums,nerr) endif if (do_radiation) then - call write_array(1,rad,rad_label,maxirad,npart,k,ipass,idump,nums,ierrs(27)) - call write_array(1,radprop,radprop_label,maxradprop,npart,k,ipass,idump,nums,ierrs(28)) + call write_array(1,rad,rad_label,maxirad,npart,k,ipass,idump,nums,nerr) + call write_array(1,radprop,radprop_label,maxradprop,npart,k,ipass,idump,nums,nerr) endif - if (any(ierrs(1:28) /= 0)) call error('write_dump','error writing hydro arrays') + if (nerr > 0) call error('write_dump','error writing hydro arrays') enddo + nerr = 0 do k=1,ndatatypes ! ! Block 2 arrays (sink particles) ! if (.not. sphNGdump .and. nptmass > 0 .and. nptmass <= maxptmass) then ilen(2) = int(nptmass,kind=8) - call write_array(2,xyzmh_ptmass,xyzmh_ptmass_label,nsinkproperties,nptmass,k,ipass,idump,nums,ierrs(1)) - call write_array(2,vxyz_ptmass,vxyz_ptmass_label,3,nptmass,k,ipass,idump,nums,ierrs(2)) - if (any(ierrs(1:2) /= 0)) call error('write_dump','error writing sink particle arrays') + call write_array(2,xyzmh_ptmass,xyzmh_ptmass_label,nsinkproperties,nptmass,k,ipass,idump,nums,nerr) + call write_array(2,vxyz_ptmass,vxyz_ptmass_label,3,nptmass,k,ipass,idump,nums,nerr) + if (nerr > 0) call error('write_dump','error writing sink particle arrays') endif enddo @@ -488,18 +321,20 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ! Block 4 arrays (MHD) ! if (mhd) then + nerr = 0 ilen(4) = int(npart,kind=8) - call write_array(4,Bxyz,Bxyz_label,3,npart,k,ipass,idump,nums,ierrs(1)) ! Bx,By,Bz - call write_array(4,Bevol,Bevol_label,1,npart,k,ipass,idump,nums,ierrs(1),index=4) ! psi + call write_array(4,Bxyz,Bxyz_label,3,npart,k,ipass,idump,nums,nerr) ! Bx,By,Bz + call write_array(4,Bevol,Bevol_label,1,npart,k,ipass,idump,nums,nerr,index=4) ! psi if (ndivcurlB >= 1) then - call write_array(4,divcurlB,divcurlB_label,ndivcurlB,npart,k,ipass,idump,nums,ierrs(2)) + call write_array(4,divcurlB,divcurlB_label,ndivcurlB,npart,k,ipass,idump,nums,nerr) else - call write_array(4,divBsymm,'divBsymm',npart,k,ipass,idump,nums,ierrs(2)) + call write_array(4,divBsymm,'divBsymm',npart,k,ipass,idump,nums,nerr) endif - if (any(ierrs(1:2) /= 0)) call error('write_dump','error writing MHD arrays') + if (nerr > 0) call error('write_dump','error writing MHD arrays') if (mhd_nonideal) then - call write_array(4,eta_nimhd,eta_nimhd_label,4,npart,k,ipass,idump,nums,ierrs(1)) - if (ierrs(1) /= 0) call error('write_dump','error writing non-ideal MHD arrays') + nerr = 0 + call write_array(4,eta_nimhd,eta_nimhd_label,4,npart,k,ipass,idump,nums,nerr) + if (nerr > 0) call error('write_dump','error writing non-ideal MHD arrays') endif endif enddo @@ -523,7 +358,6 @@ end subroutine write_fulldump_fortran ! (faked to look like the default real is real*4) !+ !------------------------------------------------------------------- - subroutine write_smalldump_fortran(t,dumpfile) use dim, only:maxp,maxtypes,use_dust,lightcurve,use_dustgrowth,h2chemistry use options, only:use_porosity @@ -538,7 +372,7 @@ subroutine write_smalldump_fortran(t,dumpfile) rad,rad_label,do_radiation,maxirad,luminosity use dump_utils, only:open_dumpfile_w,dump_h,allocate_header,free_header,& write_header,write_array,write_block_header - use mpiutils, only:reduceall_mpi + use mpiutils, only:reduceall_mpi,start_threadwrite,end_threadwrite real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer(kind=8) :: ilen(4) @@ -567,7 +401,7 @@ subroutine write_smalldump_fortran(t,dumpfile) call open_dumpfile_w(idump,dumpfile,fileident('ST'),ierr,singleprec=.true.) if (ierr /= 0) then - call error('write_smalldump','can''t create new dumpfile '//trim(dumpfile)) + call error('write_smalldump','could not write new dumpfile '//trim(dumpfile)) return endif ! @@ -587,7 +421,7 @@ subroutine write_smalldump_fortran(t,dumpfile) !--arrays: number of array lengths ! nblockarrays = narraylengths*nblocks - write (idump, iostat=ierr) nblockarrays + write (idump,iostat=ierr) nblockarrays if (ierr /= 0) call error('write_smalldump','error writing nblockarrays') endif masterthread @@ -595,6 +429,7 @@ subroutine write_smalldump_fortran(t,dumpfile) call start_threadwrite(id,idump,dumpfile) nums = 0 + ierr = 0 ilen = 0_8 write_itype = (maxphase==maxp .and. any(npartoftypetot(2:) > 0)) do ipass=1,2 @@ -651,7 +486,6 @@ end subroutine write_smalldump_fortran ! and also from standard sphNG dump files !+ !------------------------------------------------------------------- - subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ierr,headeronly,dustydisc) use memory, only:allocate_memory use dim, only:maxp,maxvxyzu,gravity,lightcurve,mhd,maxp_hard,inject_parts,mpi @@ -659,8 +493,9 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie use part, only:xyzh,vxyzu,massoftype,npart,npartoftype,maxtypes,iphase, & maxphase,isetphase,nptmass,nsinkproperties,maxptmass,get_pmass, & xyzmh_ptmass,vxyz_ptmass - use dump_utils, only:skipblock,skip_arrays,check_tag,lenid,ndatatypes,read_header, & - open_dumpfile_r,get_error_text,ierr_realsize,free_header,read_block_header + use dump_utils, only:get_dump_size,skipblock,skip_arrays,check_tag,lenid,ndatatypes,read_header, & + open_dumpfile_r,get_error_text,ierr_realsize,free_header,read_block_header,& + get_blocklimits use mpiutils, only:reduce_mpi,reduceall_mpi use sphNGutils, only:convert_sinks_sphNG,mass_sphng use options, only:use_dustfrac @@ -680,6 +515,7 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie logical :: tagged,phantomdump,smalldump real :: dumr,alphafile character(len=lenid) :: fileidentr + character(len=12) :: string type(dump_h) :: hdr integer :: i,ierrh @@ -812,7 +648,11 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie ! Also handles MPI -> non-MPI dump conversion and vice-versa. ! Can be used by non-MPI codes to read isolated blocks only. ! - call get_blocklimits(nhydrothisblock,nblocks,nprocs,id,iblock,noffset,npartread) + call get_blocklimits(nhydrothisblock,nblocks,nprocs,id,iblock,noffset,npartread,ierr) + if (ierr /= 0) then + call error('read_dump','could not map blocks in dump to number of threads') + return + endif i1 = i2 + 1 i2 = i1 + (npartread - 1) npart = npart + npartread @@ -825,13 +665,10 @@ subroutine read_dump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,nprocs,ie endif cycle overblocks elseif (npartread > 0) then -#ifdef MPI - write(*,"(a,i5,2(a,i10),a,i5,a,i10,'-',i10)") & - 'thread ',id,' reading particles ',noffset+1,':',noffset+npartread,', from block ',iblock,' lims=',i1,i2 -#else - write(*,"(2(a,i10),a,i5,a,i10,'-',i10)") & - ' reading particles ',noffset+1,':',noffset+npartread,', from block ',iblock,' lims=',i1,i2 -#endif + string = '' + if (nprocs > 1) write(string,'(a,i5)') 'thread',iblock + write(*,"(2(a,i10),a,i5,a,i10,'-',i10)") trim(string)//' reading particles ',noffset+1,& + ':',noffset+npartread,', from block ',iblock,' lims=',i1,i2 else write(*,"(a,i10,a)") ' WARNING! block contains no SPH particles, reading ',nptmass,' point mass particles only' endif @@ -923,7 +760,7 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro use part, only:npart,npartoftype,maxtypes,nptmass,nsinkproperties,maxptmass, & massoftype use dump_utils, only:skipblock,skip_arrays,check_tag,open_dumpfile_r,get_error_text,& - ierr_realsize,read_header,extract,free_header,read_block_header + ierr_realsize,read_header,extract,free_header,read_block_header,get_blocklimits use mpiutils, only:reduce_mpi,reduceall_mpi use options, only:use_dustfrac character(len=*), intent(in) :: dumpfile @@ -941,6 +778,7 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro logical :: tagged,phantomdump,smalldump real :: alphafile character(len=lenid) :: fileidentr + character(len=12) :: string type(dump_h) :: hdr integer :: i @@ -1057,17 +895,19 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro ! Also handles MPI -> non-MPI dump conversion and vice-versa. ! Can be used by non-MPI codes to read isolated blocks only. ! - call get_blocklimits(nhydrothisblock,nblocks,nprocs,id,iblock,noffset,npartread) + call get_blocklimits(nhydrothisblock,nblocks,nprocs,id,iblock,noffset,npartread,ierr) + if (ierr /= 0) then + call error('read_dump','could not map blocks in dump to number of threads') + return + endif i1 = i2 + 1 i2 = i1 + (npartread - 1) npart = npart + npartread -#ifdef MPI if (npart > maxp) then write(*,*) 'npart > maxp in readwrite_dumps' ierr = 1 return endif -#endif if (npartread <= 0 .and. nptmass <= 0) then call skipblock(idisk1,nums(:,1),nums(:,2),nums(:,3),nums(:,4),tagged,ierr) if (ierr /= 0) then @@ -1076,13 +916,10 @@ subroutine read_smalldump_fortran(dumpfile,tfile,hfactfile,idisk1,iprint,id,npro endif cycle overblocks elseif (npartread > 0) then -#ifdef MPI - write(*,"(a,i5,2(a,i10),a,i5,a,i10,'-',i10)") & - 'thread ',id,' reading particles ',noffset+1,':',noffset+npartread,', from block ',iblock,' lims=',i1,i2 -#else - write(*,"(2(a,i10),a,i5,a,i10,'-',i10)") & - ' reading particles ',noffset+1,':',noffset+npartread,', from block ',iblock,' lims=',i1,i2 -#endif + string = '' + if (nprocs > 1) write(string,'(a,i5)') 'thread',iblock + write(*,"(2(a,i10),a,i5,a,i10,'-',i10)") trim(string)//' reading particles ',noffset+1,& + ':',noffset+npartread,', from block ',iblock,' lims=',i1,i2 else write(*,"(a,i10,a)") ' WARNING! block contains no SPH particles, reading ',nptmass,' point mass particles only' endif @@ -1167,6 +1004,7 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto logical :: got_filfac,got_divcurlv(4),got_rad(maxirad),got_radprop(maxradprop),got_pxyzu(4),got_iorig character(len=lentag) :: tag,tagarr(64) integer :: k,i,iarr,ik,ndustfraci + real, allocatable :: tmparray(:) ! !--read array type 1 arrays @@ -1201,6 +1039,7 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto got_iorig = .false. ndustfraci = 0 + if (use_dust) allocate(tmparray(size(dustfrac,2))) over_arraylengths: do iarr=1,narraylengths do k=1,ndatatypes @@ -1234,8 +1073,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto if (use_dust) then if (any(tag == dustfrac_label)) then ndustfraci = ndustfraci + 1 - call read_array(dustfrac(ndustfraci,:),dustfrac_label(ndustfraci),got_dustfrac(ndustfraci), & + call read_array(tmparray,dustfrac_label(ndustfraci),got_dustfrac(ndustfraci), & ik,i1,i2,noffset,idisk1,tag,match,ierr) + dustfrac(ndustfraci,i1:i2) = tmparray(i1:i2) endif endif if (h2chemistry) then @@ -1297,6 +1137,7 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto enddo enddo over_arraylengths + if (allocated(tmparray)) deallocate(tmparray) ! ! check for errors ! @@ -1371,453 +1212,6 @@ subroutine check_block_header(narraylengths,nblocks,ilen,nums,nparttot,nhydrothi end subroutine check_block_header -!-------------------------------------------------------------------- -!+ -! utility to extract header variables to phantom -!+ -!------------------------------------------------------------------- -subroutine unfill_header(hdr,phantomdump,got_tags,nparttot, & - nblocks,npart,npartoftype, & - tfile,hfactfile,alphafile,iprint,id,nprocs,ierr) - use dim, only:maxdustlarge,use_dust - use io, only:master ! check this - use eos, only:isink - use part, only:maxtypes,igas,idust,ndustsmall,ndustlarge,ndusttypes,& - npartoftypetot - use units, only:udist,umass,utime,set_units_extra,set_units - use dump_utils, only:extract,dump_h - use fileutils, only:make_tags_unique - type(dump_h), intent(in) :: hdr - logical, intent(in) :: phantomdump,got_tags - integer(kind=8), intent(out) :: nparttot - integer, intent(out) :: nblocks,npart,npartoftype(maxtypes) - real, intent(out) :: tfile,hfactfile,alphafile - integer, intent(in) :: iprint,id,nprocs - integer, intent(out) :: ierr - integer :: nparttoti,npartoftypetoti(maxtypes),ntypesinfile,nptinfile - integer :: ierr1,ierrs(3),i,counter - integer(kind=8) :: ntypesinfile8 - character(len=10) :: dust_label(maxdustlarge) - - ierr = 0 - nparttot = 0 - npartoftypetot(:) = 0 - npart = 0 - npartoftype(:) = 0 - isink = 0 - call extract('ntypes',ntypesinfile,hdr,ierr1) - if (ierr1 /= 0 .or. ntypesinfile < 1) then - if (phantomdump .and. got_tags) then - ierr = 4 - return - else - ntypesinfile = 5 - endif - endif - - ! extract quantities from integer header - call extract('nparttot',nparttoti,hdr,ierr1) - if (ierr1 /= 0) then - ierr = 5 - return - endif - if (ntypesinfile > maxtypes) then - write(*,*) 'WARNING: number of particle types in file exceeds array limits' - write(*,*) 'READING ONLY FIRST ',maxtypes,' OF ',ntypesinfile,' particle types' - ntypesinfile = maxtypes - endif - call extract('npartoftype',npartoftypetoti(1:ntypesinfile),hdr,ierr1) - if (ierr1 /= 0) then - npartoftype(1) = nparttoti ! assume only gas particles - endif - call extract('nblocks',nblocks,hdr,ierr1,default=1) - if (ierr1 /= 0) write(*,*) 'number of MPI blocks not read: assuming 1' - - nparttot = int(nparttoti,kind=8) - npartoftypetot = int(npartoftypetoti,kind=8) - if (nblocks==1) then - npartoftype(1:ntypesinfile) = int(npartoftypetot(1:ntypesinfile)) - if (npartoftype(idust) > 0) write(*,*) 'n(gas) = ',npartoftype(igas) - counter = 0 - do i=1,maxdustlarge - if (npartoftype(idust+i-1) > 0) then - counter = counter + 1 - endif - enddo - dust_label = 'dust' - call make_tags_unique(counter,dust_label) - do i=1,counter - write(*,*) 'n('//trim(dust_label(i))//') = ',npartoftype(idust+i-1) - enddo - endif - call extract('isink',isink,hdr,ierr1) - -!--non-MPI dumps - if (nprocs==1) then - if (nparttoti > huge(npart)) then - write (*,*) 'ERROR in readdump: number of particles exceeds 32 bit limit, must use int(kind=8)''s ',nparttoti - ierr = 4 - return - endif - endif - if (nblocks==1) then - npart = int(nparttoti) - nparttot = npart - if (id==master) write (iprint,*) 'npart = ',npart - endif - if (got_tags) then - call extract('ntypes',ntypesinfile8,hdr,ierr1) - ntypesinfile = int(ntypesinfile8) - endif - if (ntypesinfile > maxtypes) then - write(*,*) 'WARNING: number of particle types in file exceeds array limits' - write(*,*) 'READING ONLY FIRST ',maxtypes,' OF ',ntypesinfile,' particle types' - ntypesinfile = maxtypes - endif - call extract('nparttot',nparttot,hdr,ierr1) - if (nblocks > 1) then - call extract('npartoftype',npartoftype(1:ntypesinfile),hdr,ierr1) - endif - if (id==master) write(*,*) 'npart(total) = ',nparttot -! -!--number of dust species -! - if (use_dust) then - call extract('ndustsmall',ndustsmall,hdr,ierrs(1)) - call extract('ndustlarge',ndustlarge,hdr,ierrs(2)) - if (any(ierrs(1:2) /= 0)) then - call extract('ndustfluids',ndustsmall,hdr,ierrs(1)) ! for backwards compatibility - if (ierrs(1) /= 0) write(*,*) 'ERROR reading number of small/large grain types from file header' - endif - ndusttypes = ndustsmall + ndustlarge - endif -! -!--units -! - call extract('udist',udist,hdr,ierrs(1)) - call extract('umass',umass,hdr,ierrs(2)) - call extract('utime',utime,hdr,ierrs(3)) - if (all(ierrs(1:3)==0)) then - call set_units_extra() - else - write(iprint,*) 'ERROR reading units from dump file, assuming default' - call set_units() ! use default units - endif - ! get nptmass from header, needed to figure out if gwinspiral info is sensible - call extract('nptmass',nptinfile,hdr,ierrs(1)) -!--default real - call unfill_rheader(hdr,phantomdump,ntypesinfile,nptinfile,& - tfile,hfactfile,alphafile,iprint,ierr) - if (ierr /= 0) return - - if (id==master) write(iprint,*) 'time = ',tfile - -end subroutine unfill_header - -!-------------------------------------------------------------------- -!+ -! subroutine to fill the real header with various things -!+ -!------------------------------------------------------------------- -subroutine fill_header(sphNGdump,t,nparttot,npartoftypetot,nblocks,nptmass,hdr,ierr) - use eos, only:write_headeropts_eos,polyk2 - use options, only:tolh,alpha,alphau,alphaB,iexternalforce,ieos - use part, only:massoftype,hfact,Bextx,Bexty,Bextz,ndustsmall,ndustlarge,& - idust,grainsize,graindens,ndusttypes - use checkconserved, only:get_conserv,etot_in,angtot_in,totmom_in,mdust_in - use setup_params, only:rhozero - use timestep, only:dtmax_user,idtmax_n_next,idtmax_frac_next,C_cour,C_force - use externalforces, only:write_headeropts_extern - use boundary, only:xmin,xmax,ymin,ymax,zmin,zmax - use boundary_dyn, only:dynamic_bdy,dxyz,rho_bkg_ini,irho_bkg_ini - use dump_utils, only:reset_header,add_to_rheader,add_to_header,add_to_iheader,num_in_header - use dim, only:use_dust,maxtypes,use_dustgrowth,do_nucleation, & - phantom_version_major,phantom_version_minor,phantom_version_micro,periodic,idumpfile - use units, only:udist,umass,utime,unit_Bfield - use dust_formation, only:write_headeropts_dust_formation - - logical, intent(in) :: sphNGdump - real, intent(in) :: t - integer(kind=8), intent(in) :: nparttot,npartoftypetot(:) - integer, intent(in) :: nblocks,nptmass - type(dump_h), intent(inout) :: hdr - integer, intent(out) :: ierr - integer :: number - - ierr = 0 - ! default int - call add_to_iheader(int(nparttot),'nparttot',hdr,ierr) - call add_to_iheader(maxtypes,'ntypes',hdr,ierr) - call add_to_iheader(int(npartoftypetot(1:maxtypes)),'npartoftype',hdr,ierr) - call add_to_iheader(nblocks,'nblocks',hdr,ierr) - call add_to_iheader(nptmass,'nptmass',hdr,ierr) - call add_to_iheader(ndustlarge,'ndustlarge',hdr,ierr) - call add_to_iheader(ndustsmall,'ndustsmall',hdr,ierr) - call add_to_iheader(idust,'idust',hdr,ierr) - call add_to_iheader(idtmax_n_next,'idtmax_n',hdr,ierr) - call add_to_iheader(idtmax_frac_next,'idtmax_frac',hdr,ierr) - call add_to_iheader(idumpfile,'idumpfile',hdr,ierr) - call add_to_iheader(phantom_version_major,'majorv',hdr,ierr) - call add_to_iheader(phantom_version_minor,'minorv',hdr,ierr) - call add_to_iheader(phantom_version_micro,'microv',hdr,ierr) - - ! int*8 - call add_to_header(nparttot,'nparttot',hdr,ierr) - call add_to_header(int(maxtypes,kind=8),'ntypes',hdr,ierr) - call add_to_header(npartoftypetot(1:maxtypes),'npartoftype',hdr,ierr) - - ! int*4 - call add_to_header(iexternalforce,'iexternalforce',hdr,ierr) - call add_to_header(ieos,'ieos',hdr,ierr) - call write_headeropts_eos(ieos,hdr,ierr) - - ! default real variables - call add_to_rheader(t,'time',hdr,ierr) - call add_to_rheader(dtmax_user,'dtmax',hdr,ierr) - call add_to_rheader(rhozero,'rhozero',hdr,ierr) - if (sphNGdump) then ! number = 23 - call add_to_rheader(0.,'escaptot',hdr,ierr) - call add_to_rheader(0.,'tkin',hdr,ierr) - call add_to_rheader(0.,'tgrav',hdr,ierr) - call add_to_rheader(0.,'tterm',hdr,ierr) - call add_to_rheader(0.,'anglostx',hdr,ierr) - call add_to_rheader(0.,'anglosty',hdr,ierr) - call add_to_rheader(0.,'anglostz',hdr,ierr) - call add_to_rheader(0.,'specang',hdr,ierr) - call add_to_rheader(0.,'ptmassin',hdr,ierr) - call add_to_rheader(0.,'tmag',hdr,ierr) - call add_to_rheader(Bextx,'Bextx',hdr,ierr) - call add_to_rheader(Bexty,'Bexty',hdr,ierr) - call add_to_rheader(Bextz,'Bextz',hdr,ierr) - call add_to_rheader(0.,'hzero',hdr,ierr) - call add_to_rheader(1.5*polyk2,'uzero_n2',hdr,ierr) - call add_to_rheader(0.,'hmass',hdr,ierr) - call add_to_rheader(0.,'gapfac',hdr,ierr) - call add_to_rheader(0.,'pmassinitial',hdr,ierr) - else ! number = 49 - call add_to_rheader(hfact,'hfact',hdr,ierr) - call add_to_rheader(tolh,'tolh',hdr,ierr) - call add_to_rheader(C_cour,'C_cour',hdr,ierr) - call add_to_rheader(C_force,'C_force',hdr,ierr) - call add_to_rheader(alpha,'alpha',hdr,ierr) - call add_to_rheader(alphau,'alphau',hdr,ierr) - call add_to_rheader(alphaB,'alphaB',hdr,ierr) - call add_to_rheader(massoftype,'massoftype',hdr,ierr) ! array - if (do_nucleation) call write_headeropts_dust_formation(hdr,ierr) - call add_to_rheader(Bextx,'Bextx',hdr,ierr) - call add_to_rheader(Bexty,'Bexty',hdr,ierr) - call add_to_rheader(Bextz,'Bextz',hdr,ierr) - call add_to_rheader(0.,'dum',hdr,ierr) - if (iexternalforce /= 0) call write_headeropts_extern(iexternalforce,hdr,t,ierr) - if (periodic) then - call add_to_rheader(xmin,'xmin',hdr,ierr) - call add_to_rheader(xmax,'xmax',hdr,ierr) - call add_to_rheader(ymin,'ymin',hdr,ierr) - call add_to_rheader(ymax,'ymax',hdr,ierr) - call add_to_rheader(zmin,'zmin',hdr,ierr) - call add_to_rheader(zmax,'zmax',hdr,ierr) - endif - if (dynamic_bdy) then - call add_to_rheader(dxyz,'dxyz',hdr,ierr) - call add_to_iheader(irho_bkg_ini,'irho_bkg_ini',hdr,ierr) - call add_to_rheader(rho_bkg_ini,'rho_bkg_ini',hdr,ierr) - endif - call add_to_rheader(get_conserv,'get_conserv',hdr,ierr) - call add_to_rheader(etot_in,'etot_in',hdr,ierr) - call add_to_rheader(angtot_in,'angtot_in',hdr,ierr) - call add_to_rheader(totmom_in,'totmom_in',hdr,ierr) - call add_to_rheader(mdust_in(1:ndusttypes),'mdust_in',hdr,ierr) - if (use_dust) then - call add_to_rheader(grainsize(1:ndusttypes),'grainsize',hdr,ierr) - call add_to_rheader(graindens(1:ndusttypes),'graindens',hdr,ierr) - endif - endif - - ! real*8 - call add_to_header(udist,'udist',hdr,ierr) - call add_to_header(umass,'umass',hdr,ierr) - call add_to_header(utime,'utime',hdr,ierr) - call add_to_header(unit_Bfield,'umagfd',hdr,ierr) - - if (ierr /= 0) write(*,*) ' ERROR: arrays too small writing rheader' - - number = num_in_header(hdr%realtags) - if (number >= maxphead) then - write(*,*) 'error: header arrays too small for number of items in header: will be truncated' - endif - -end subroutine fill_header - -!-------------------------------------------------------------------- -!+ -! subroutine to set runtime parameters having read the real header -!+ -!------------------------------------------------------------------- -subroutine unfill_rheader(hdr,phantomdump,ntypesinfile,nptmass,& - tfile,hfactfile,alphafile,iprint,ierr) - use io, only:id,master - use dim, only:maxvxyzu,nElements,use_dust,use_dustgrowth,use_krome,do_nucleation,idumpfile - use eos, only:extract_eos_from_hdr, read_headeropts_eos - use options, only:ieos,iexternalforce - use part, only:massoftype,Bextx,Bexty,Bextz,mhd,periodic,& - maxtypes,grainsize,graindens,ndusttypes - use checkconserved, only:get_conserv,etot_in,angtot_in,totmom_in,mdust_in - use setup_params, only:rhozero - use externalforces, only:read_headeropts_extern,extract_iextern_from_hdr - use boundary, only:xmin,xmax,ymin,ymax,zmin,zmax,set_boundary - use boundary_dyn, only:dynamic_bdy,dxyz,irho_bkg_ini,rho_bkg_ini,rho_bkg_ini1 - use dump_utils, only:extract - use dust, only:grainsizecgs,graindenscgs - use units, only:unit_density,udist - use timestep, only:idtmax_n,idtmax_frac - use dust_formation, only:read_headeropts_dust_formation - type(dump_h), intent(in) :: hdr - logical, intent(in) :: phantomdump - integer, intent(in) :: iprint,ntypesinfile,nptmass - real, intent(out) :: tfile,hfactfile,alphafile - integer, intent(out) :: ierr - - integer, parameter :: lu = 173 - integer :: ierrs(10),iextern_in_file - real :: xmini,xmaxi,ymini,ymaxi,zmini,zmaxi,dtmaxi - real :: alphaufile,alphaBfile,C_courfile,C_forcefile,tolhfile - logical :: iexist - - ierr = 0 - call extract('time',tfile,hdr,ierr) - if (ierr/=0) call extract('gt',tfile,hdr,ierr) ! this is sphNG's label for time - call extract('dtmax',dtmaxi,hdr,ierr) - call extract('rhozero',rhozero,hdr,ierr) - Bextx = 0. - Bexty = 0. - Bextz = 0. - if (phantomdump) then - call extract('hfact',hfactfile,hdr,ierr) - call extract('tolh',tolhfile,hdr,ierr) - call extract('C_cour',C_courfile,hdr,ierr) - call extract('C_force',C_forcefile,hdr,ierr) - call extract('alpha',alphafile,hdr,ierr) - if (maxvxyzu >= 4) then - call extract('alphau',alphaufile,hdr,ierr) - else - alphaufile = 0. - endif - if (mhd) then - call extract('alphaB',alphaBfile,hdr,ierr) - endif - - if (extract_eos_from_hdr) call extract('ieos',ieos,hdr,ierr) - - call extract('massoftype',massoftype(1:ntypesinfile),hdr,ierr) - if (ierr /= 0) then - write(*,*) '*** ERROR reading massoftype from dump header ***' - ierr = 4 - endif - if (do_nucleation) then - call read_headeropts_dust_formation(hdr,ierr) - if (ierr /= 0) ierr = 6 - endif - - call extract('iexternalforce',iextern_in_file,hdr,ierrs(1)) - if (extract_iextern_from_hdr) iexternalforce = iextern_in_file - if (iexternalforce /= 0) then - call read_headeropts_extern(iexternalforce,hdr,nptmass,ierrs(1)) - if (ierrs(1) /= 0) ierr = 5 - elseif (iextern_in_file /= 0) then - call read_headeropts_extern(iextern_in_file,hdr,nptmass,ierrs(1)) - if (ierrs(1) /= 0) ierr = 5 - endif - - call extract('idtmax_n',idtmax_n,hdr,ierr,default=1) - call extract('idtmax_frac',idtmax_frac,hdr,ierr) - call extract('idumpfile',idumpfile,hdr,ierr) - else - massoftype(1) = 0. - hfactfile = 0. - endif - - call read_headeropts_eos(ieos,hdr,ierr) - - if (periodic) then - call extract('xmin',xmini,hdr,ierrs(1)) - call extract('xmax',xmaxi,hdr,ierrs(2)) - call extract('ymin',ymini,hdr,ierrs(3)) - call extract('ymax',ymaxi,hdr,ierrs(4)) - call extract('zmin',zmini,hdr,ierrs(5)) - call extract('zmax',zmaxi,hdr,ierrs(6)) - if (any(ierrs(1:6) /= 0)) then - write(*,"(2(/,a))") ' ERROR: dump does not contain boundary positions', & - ' but we are using periodic boundaries' - inquire(file='bound.tmp',exist=iexist) - if (iexist) then - open(unit=lu,file='bound.tmp') - read(lu,*) xmini,xmaxi,ymini,ymaxi,zmini,zmaxi - close(lu) - call set_boundary(xmini,xmaxi,ymini,ymaxi,zmini,zmaxi) - write(*,"(a,6(es10.3,1x))") ' READ from bound.tmp ',xmin,xmax,ymin,ymax,zmin,zmax - else - write(*,"(3(/,a),/,/,a)") ' To silence this error and restart from an older dump file ', & - ' create an ascii file called "bound.tmp" in the current directory', & - ' with xmin,xmax,ymin,ymax,zmin & zmax in it, e.g.: ', & - ' 0. 1. 0. 1. 0. 1.' - ierr = 5 ! spit fatal error - endif - else - call set_boundary(xmini,xmaxi,ymini,ymaxi,zmini,zmaxi) - endif - endif - - if (dynamic_bdy) then - call extract('irho_bkg_ini',irho_bkg_ini,hdr,ierrs(1)) - call extract('rho_bkg_ini',rho_bkg_ini,hdr,ierrs(1)) - call extract('dxyz',dxyz,hdr,ierrs(2)) - if (rho_bkg_ini > 0.) then - rho_bkg_ini1 = 1.0/rho_bkg_ini - else - rho_bkg_ini1 = 0. - endif - endif - - if (mhd) then - call extract('Bextx',Bextx,hdr,ierrs(1)) - call extract('Bexty',Bexty,hdr,ierrs(2)) - call extract('Bextz',Bextz,hdr,ierrs(3)) - if (id==master) then - if (any(ierrs(1:3) /= 0)) then - write(*,*) 'ERROR reading external field (setting to zero)' - else - write(*,*) 'External field found, Bext = ',Bextx,Bexty,Bextz - endif - endif - endif - - ! values to track that conserved values remain conserved - call extract('get_conserv',get_conserv,hdr,ierrs(1)) - call extract('etot_in', etot_in, hdr,ierrs(2)) - call extract('angtot_in', angtot_in, hdr,ierrs(3)) - call extract('totmom_in', totmom_in, hdr,ierrs(4)) - call extract('mdust_in', mdust_in(1:ndusttypes), hdr,ierrs(5)) - if (any(ierrs(1:4) /= 0)) then - write(*,*) 'ERROR reading values to verify conservation laws. Resetting initial values.' - get_conserv = 1.0 - endif - - - !--pull grain size and density arrays if they are in the header - !-- i.e. if dustgrowth is not ON - if (use_dust .and. .not.use_dustgrowth) then - call extract('grainsize',grainsize(1:ndusttypes),hdr,ierrs(1)) - call extract('graindens',graindens(1:ndusttypes),hdr,ierrs(2)) - if (any(ierrs(1:2) /= 0)) then - write(*,*) 'ERROR reading grain size/density from file header' - grainsize(1) = real(grainsizecgs/udist) - graindens(1) = real(graindenscgs/unit_density) - endif - endif - -end subroutine unfill_rheader - - !----------------------------------------------------------------- !+ ! if tags not read, give expected order of variables in header diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index ec94e4cee..a116046ef 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -108,7 +108,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) use growth, only:write_options_growth use porosity, only:write_options_porosity #ifdef INJECT_PARTICLES - use inject, only:write_options_inject + use inject, only:write_options_inject,inject_type,update_injected_par #endif use dust_formation, only:write_options_dust_formation use nicil_sup, only:write_options_nicil @@ -215,7 +215,8 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) ! thermodynamics ! call write_options_eos(iwritein) - if (maxvxyzu >= 4 .and. (ieos==2 .or. ieos==5 .or. ieos==10 .or. ieos==15 .or. ieos==12 .or. ieos==16 .or. ieos==21) ) then + if (maxvxyzu >= 4 .and. (ieos==2 .or. ieos==5 .or. ieos==10 .or. ieos==15 .or. ieos==12 .or. ieos==16 & + .or. ieos==17 .or. ieos==21) ) then call write_inopt(ipdv_heating,'ipdv_heating','heating from PdV work (0=off, 1=on)',iwritein) call write_inopt(ishock_heating,'ishock_heating','shock heating (0=off, 1=on)',iwritein) if (mhd) then @@ -269,6 +270,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) write(iwritein,"(/,a)") '# options for injecting/removing particles' #ifdef INJECT_PARTICLES call write_options_inject(iwritein) + if (inject_type=='sim') call update_injected_par() #endif call write_inopt(rkill,'rkill','deactivate particles outside this radius (<0 is off)',iwritein) @@ -685,14 +687,14 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (beta > 4.) call warn(label,'very high beta viscosity set') #ifndef MCFOST if (maxvxyzu >= 4 .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /= 4 .and. ieos /= 10 .and. & - ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 20 .and. ieos/=21)) & + ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 17 .and. ieos /= 20 .and. ieos/=21)) & call fatal(label,'only ieos=2 makes sense if storing thermal energy') #endif if (irealvisc < 0 .or. irealvisc > 12) call fatal(label,'invalid setting for physical viscosity') if (shearparam < 0.) call fatal(label,'stupid value for shear parameter (< 0)') if (irealvisc==2 .and. shearparam > 1) call error(label,'alpha > 1 for shakura-sunyaev viscosity') if (iverbose > 99 .or. iverbose < -9) call fatal(label,'invalid verboseness setting (two digits only)') - if (icooling > 0 .and. .not.(ieos == 2 .or. ieos == 5 .or. ieos ==21)) & + if (icooling > 0 .and. .not.(ieos == 2 .or. ieos == 5 .or. ieos == 17 .or. ieos == 21)) & call fatal(label,'cooling requires adiabatic eos (ieos=2)') if (icooling > 0 .and. (ipdv_heating <= 0 .or. ishock_heating <= 0)) & call fatal(label,'cooling requires shock and work contributions') diff --git a/src/utils/analysis_GalMerger.f90 b/src/utils/analysis_GalMerger.f90 index 4dc4d3352..6f4e0c1fb 100644 --- a/src/utils/analysis_GalMerger.f90 +++ b/src/utils/analysis_GalMerger.f90 @@ -47,7 +47,7 @@ subroutine do_analysis(dumpfile,num,xyzh,vxyzu,particlemass,npart,time,iunit) character(len=200) :: fileout ! !--Open file (appendif exists) - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_stellarCoM.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_stellarCoM.dat' inquire(file=fileout,exist=iexist) if ( .not.iexist .or. firstcall ) then firstcall = .false. diff --git a/src/utils/analysis_NSmerger.f90 b/src/utils/analysis_NSmerger.f90 index 053402dff..c96e57d0d 100644 --- a/src/utils/analysis_NSmerger.f90 +++ b/src/utils/analysis_NSmerger.f90 @@ -127,7 +127,7 @@ subroutine trace_com(dumpfile,xyzh,vxyzu,time,npart,iunit) real :: rad ! !--Open file (appendif exists) - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_orbit.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_orbit.dat' inquire(file=fileout,exist=iexist) if ( firstcall .or. .not.iexist ) then open(iunit,file=fileout,status='replace') @@ -280,7 +280,7 @@ subroutine calculate_I(dumpfile,xyzh,time,npart,iunit,particlemass) real :: principle(3),evectors(3,3),ellipticity(2) ! !--Open file (appendif exists) - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_inertia.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_inertia.dat' inquire(file=fileout,exist=iexist) if ( firstcall .or. .not.iexist ) then open(iunit,file=fileout,status='replace') @@ -358,7 +358,7 @@ subroutine calculate_midplane_profile(dumpfile,xyzh,vxyzu,npart,iunit,particlema if (.not.opened_full_dump)return ! !--Open file - fileout = trim(dumpfile(1:INDEX(dumpfile,'_')-1))//'_rotataxesprofile'//trim(dumpfile(INDEX(dumpfile,'_'):))//'.dat' + fileout = trim(dumpfile(1:index(dumpfile,'_')-1))//'_rotataxesprofile'//trim(dumpfile(index(dumpfile,'_'):))//'.dat' open(iunit,file=fileout,status='replace') write(iunit,"('#',10(1x,'[',i2.2,1x,a11,']',2x))") & 1,'outer bin rad',& From 292fca23d004ed5f6a0200898329303bb2264d71 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 29 Jul 2024 18:11:10 +0100 Subject: [PATCH 138/182] Edits to make upstream changes work --- src/main/cooling_radapprox.f90 | 30 +++++++------ src/main/dens.F90 | 2 +- src/main/eos_stamatellos.f90 | 7 ++- src/main/force.F90 | 64 +++++++++++----------------- src/main/readwrite_dumps_fortran.f90 | 6 +-- src/main/step_leapfrog.F90 | 6 --- 6 files changed, 50 insertions(+), 65 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index dd62d3f50..b8b869f39 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -63,18 +63,18 @@ end subroutine init_star ! ! Do cooling calculation ! -! update energy to return evolved energy array. Called from step corrector -subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,dudti_sph,Tfloor) +! update energy to return evolved energy array. Called from substep +subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,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 + duFLD,doFLD,ttherm_store,teqi_store,opac_store,duSPH use part, only:xyzmh_ptmass,rhoh,massoftype,igas use timestep_ind, only:get_dt integer,intent(in) :: i integer(kind=1),intent(in) :: ibini - real,intent(in) :: xyzhi(:),dtsph,dudti_sph,Tfloor + real,intent(in) :: xyzhi(:),dtsph,Tfloor real,intent(inout) :: ui real :: dti,rhoi,coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot @@ -87,6 +87,9 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,dudti_sph,Tfloor) du_FLDi = duFLD(i) kappaBari = 0d0 kappaParti = 0d0 + Teqi = huge(Teqi) + tthermi = huge(tthermi) + opaci = epsilon(opaci) if (abs(ui) < epsilon(ui)) print *, "ui zero", i rhoi = rhoh(xyzhi(4),massoftype(igas)) @@ -146,22 +149,26 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,dudti_sph,Tfloor) Tmini4 = Tfloor**4d0 endif + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg + 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 = dudti_sph + du_FLDi + du_tot = duSPH(i) + du_FLDi else - du_tot = dudti_sph + 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(dudti_rad/du_tot) < dtcool_crit) then ! print *, "not cooling/heating for r=",sqrt(ri2),".", dudti_rad,& - ! dudt_sph(i) + ! dusph(i) ui = ui + du_tot*dti + if (ui < umini) ui = umini return endif @@ -177,9 +184,9 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,dudti_sph,Tfloor) teqi_store(i) = Teqi if (Teqi > 9e5) then - print *,"i=",i, "dudt_sph(i)=", dudti_sph, "duradi=", dudti_rad, "Ti=", Ti, & + 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=", dudti_sph*dti + "dudt_sph * dti=", dusph(i)*dti elseif (Teqi < epsilon(Teqi)) then print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& "Ti=", Ti, "poti=",poti, "rhoi=", rhoi @@ -191,9 +198,6 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,dudti_sph,Tfloor) call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg - ! calculate thermalization timescale if ((du_tot) == 0.d0) then tthermi = 0d0 @@ -216,7 +220,7 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,dudti_sph,Tfloor) ! 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",dudti_sph + print *, "opaci=",opaci,"coldensi=",coldensi,"dusph(i)",duSPH(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) diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 60d90ed93..81cd68031 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -101,7 +101,7 @@ module densityforce !real, parameter :: cnormk = 1./pi, wab0 = 1., gradh0 = -3.*wab0, radkern2 = 4F.0 integer, parameter :: isizecellcache = 1000 integer, parameter :: isizeneighcache = 0 - integer, parameter :: maxdensits = 50 + integer, parameter :: maxdensits = 100 !--statistics which can be queried later integer, private :: maxneighact,nrelink diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index a6d485982..ff3b7a404 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(:) + real,allocatable,public :: ttherm_store(:),teqi_store(:),opac_store(:),duSPH(:) character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file logical,public :: doFLD = .True., floor_energy = .False. integer,public :: iunitst=19 @@ -41,7 +41,8 @@ subroutine init_S07cool() allocate(urad_FLD(npart)) allocate(ttherm_store(npart)) allocate(teqi_store(npart)) - allocate(opac_store(npart)) + allocate(opac_store(npart)) + allocate(duSPH(npart)) Gpot_cool(:) = 0d0 gradP_cool(:) = 0d0 urad_FLD(:) = 0d0 @@ -49,6 +50,7 @@ subroutine init_S07cool() teqi_store(:) = 0d0 ttherm_store(:) = 0d0 opac_store(:) = 0d0 + duSPH(:) = 0d0 open (unit=iunitst,file='EOSinfo.dat',status='replace') if (doFLD) then print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" @@ -67,6 +69,7 @@ subroutine finish_S07cool() if (allocated(ttherm_store)) deallocate(ttherm_store) if (allocated(teqi_store)) deallocate(teqi_store) if (allocated(opac_store)) deallocate(opac_store) + if (allocated(duSPH)) deallocate(duSPH) close(iunitst) end subroutine finish_S07cool diff --git a/src/main/force.F90 b/src/main/force.F90 index 82a63baf4..aa5438914 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -150,27 +150,26 @@ module forces idBevolyi = 10, & idBevolzi = 11, & idivBdiffi = 12, & - ihdivBBmax = 13, & !--dust array indexing - ifdragxi = 14, & - ifdragyi = 15, & - ifdragzi = 16, & - iddustevoli = 17, & - iddustevoliend = 17 + (maxdustsmall-1), & - idudtdusti = 18 + (maxdustsmall-1), & - idudtdustiend = 18 + 2*(maxdustsmall-1), & - ideltavxi = 19 + 2*(maxdustsmall-1), & - ideltavxiend = 19 + 3*(maxdustsmall-1), & - ideltavyi = 20 + 3*(maxdustsmall-1), & - ideltavyiend = 20 + 4*(maxdustsmall-1), & - ideltavzi = 21 + 4*(maxdustsmall-1), & - ideltavziend = 21 + 5*(maxdustsmall-1), & - idvix = 22 + 5*(maxdustsmall-1), & - idviy = 23 + 5*(maxdustsmall-1), & - idviz = 24 + 5*(maxdustsmall-1), & - idensgasi = 25 + 5*(maxdustsmall-1), & - icsi = 26 + 5*(maxdustsmall-1), & - idradi = 26 + 5*(maxdustsmall-1) + 1 + ifdragxi = 13, & + ifdragyi = 14, & + ifdragzi = 15, & + iddustevoli = 16, & + iddustevoliend = 16 + (maxdustsmall-1), & + idudtdusti = 17 + (maxdustsmall-1), & + idudtdustiend = 17 + 2*(maxdustsmall-1), & + ideltavxi = 18 + 2*(maxdustsmall-1), & + ideltavxiend = 18 + 3*(maxdustsmall-1), & + ideltavyi = 19 + 3*(maxdustsmall-1), & + ideltavyiend = 19 + 4*(maxdustsmall-1), & + ideltavzi = 20 + 4*(maxdustsmall-1), & + ideltavziend = 20 + 5*(maxdustsmall-1), & + idvix = 21 + 5*(maxdustsmall-1), & + idviy = 22 + 5*(maxdustsmall-1), & + idviz = 23 + 5*(maxdustsmall-1), & + idensgasi = 24 + 5*(maxdustsmall-1), & + icsi = 25 + 5*(maxdustsmall-1), & + idradi = 25 + 5*(maxdustsmall-1) + 1 private @@ -1669,7 +1668,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g else Bj1 = 0.0 endif - fsum(ihdivBBmax) = max( hj*abs(divcurlB(1,j))*Bj1, fsum(ihdivBBmax)) ! ! non-ideal MHD terms ! @@ -2585,7 +2583,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use dim, only:mhd,mhd_nonideal,lightcurve,use_dust,maxdvdx,use_dustgrowth,gr,use_krome,& store_dust_temperature,do_nucleation,update_muGamma,h2chemistry use eos, only:ieos,iopacity_type - use options, only:alpha,ipdv_heating,ishock_heating,psidecayfac,overcleanfac,hdivbbmax_max, & + use options, only:alpha,ipdv_heating,ishock_heating,psidecayfac,overcleanfac, & use_dustfrac,damp,icooling,implicit_radiation use part, only:rhoanddhdrho,iboundary,igas,maxphase,maxvxyzu,nptmass,xyzmh_ptmass,eos_vars, & massoftype,get_partinfo,tstop,strain_from_dvdx,ithick,iradP,sinks_have_heating,& @@ -2618,7 +2616,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use part, only:Omega_k use io, only:warning use physcon, only:c,kboltz - use eos_stamatellos, only:Gpot_cool + use eos_stamatellos, only:Gpot_cool,duSPH integer, intent(in) :: icall type(cellforce), intent(inout) :: cell real, intent(inout) :: fxyzu(:,:) @@ -2662,7 +2660,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv real :: Bxyzi(3),curlBi(3),dvdxi(9),straini(6) real :: xi,yi,zi,B2i,f2i,divBsymmi,betai,frac_divB,divBi,vcleani real :: pri,spsoundi,drhodti,divvi,shearvisc,fac,pdv_work - real :: psii,dtau,hdivbbmax + real :: psii,dtau real :: eni,dudtnonideal real :: dustfraci(maxdusttypes),dustfracisum real :: tstopi(maxdusttypes),tseff,dtdustdenom @@ -3007,6 +3005,7 @@ 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 = fxyz4 endif endif @@ -3030,22 +3029,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv ! new cleaning evolving d/dt (psi/c_h) dBevol(4,i) = -vcleani*fsum(idivBdiffi)*rho1i - psii*dtau - 0.5*psii*divvi - - ! timestep from cleaning - ! 1. the factor of 10 in hdivbbmax is empirical from checking how much - ! spurious B-fields are decreased in colliding flows - ! 2. if overcleaning is on (i.e. hdivbbmax > 1.0), then factor of 2 is - ! from empirical tests to ensure that overcleaning with individual - ! timesteps is stable - if (B2i > 0.) then - hdivbbmax = hi*abs(divBi)/sqrt(B2i) - else - hdivbbmax = 0.0 - endif - hdivbbmax = max( overcleanfac, 10.*hdivbbmax, 10.*fsum(ihdivBBmax) ) - hdivbbmax = min( hdivbbmax, hdivbbmax_max ) - if (hdivbbmax > 1.0) hdivbbmax = 2.0*hdivbbmax - dtclean = C_cour*hi/(hdivbbmax * vwavei + tiny(0.)) + dtclean = C_cour*hi/(vcleani + tiny(0.)) endif endif diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index 6ecf0627c..40a8bf319 100644 --- a/src/main/readwrite_dumps_fortran.f90 +++ b/src/main/readwrite_dumps_fortran.f90 @@ -250,9 +250,9 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ! write stamatellos cooling values if (icooling == 9) then ! .and. doFLD) then ! call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) - call write_array(1,teqi_store,'teqi',npart,k,ipass,idump,nums,ierrs(13)) - call write_array(1,ttherm_store,'ttherm',npart,k,ipass,idump,nums,ierrs(13)) - call write_array(1,opac_store,'opacity',npart,k,ipass,idump,nums,ierrs(13)) + call write_array(1,teqi_store,'teqi',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 ! smoothing length written as real*4 to save disk space call write_array(1,xyzh,xyzh_label,1,npart,k,ipass,idump,nums,nerr,use_kind=4,index=4) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index ae4ef96ff..3ab5e8362 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -127,7 +127,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use eos, only:equationofstate use substepping, only:substep,substep_gr, & substep_sph_gr,substep_sph - use cooling_radapprox, only:radcool_update_energ integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -236,8 +235,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) endif call check_dustprop(npart,dustprop,filfac,mprev,filfacprev) endif - !Alison icooling, vpred is right value here for u, but shouldn't be ...? -! print *, "line 234", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)),"nactive =", nactive !---------------------------------------------------------------------- ! substepping with external and sink particle forces, using dtextforce @@ -388,7 +385,6 @@ 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,1:npart) = vxyzu(4,1:npart) dt_too_small = .false. call derivs(1,npart,nactive,xyzh,vpred,fxyzu,fext,divcurlv,& divcurlB,Bpred,dBevol,radpred,drad,radprop,dustproppred,ddustprop,& @@ -399,7 +395,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) rad = radpred vxyzu(4,1:npart) = vpred(4,1:npart) endif - if (icooling == 9) vxyzu(4,1:npart) = vpred(4,1:npart) if (gr) vxyzu = vpred ! May need primitive variables elsewhere? if (dt_too_small) then @@ -489,7 +484,6 @@ 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) - if (its == 1) call radcool_update_energ(i,ibin(i),dtsph,xyzh(:,i),vxyzu(4,i),fxyzu(4,i),Tfloor) else vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif From 51f071aab74591294d2f4563162e3ce6f1d3c686 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 31 Jul 2024 16:45:44 +0100 Subject: [PATCH 139/182] More updates from upstream --- AUTHORS | 40 +- build/Makefile | 8 +- src/main/H2regions.f90 | 342 +++++++++++ src/main/checksetup.f90 | 36 +- src/main/config.F90 | 4 +- src/main/cons2prim.f90 | 9 +- src/main/cooling.f90 | 8 +- src/main/cooling_radapprox.f90 | 47 +- src/main/deriv.F90 | 1 + src/main/eos.f90 | 25 +- src/main/eos_HIIR.f90 | 125 ++++ src/main/evolve.F90 | 74 ++- src/main/force.F90 | 9 +- src/main/initial.F90 | 14 +- src/main/inject_BHL.f90 | 2 +- src/main/inject_asteroidwind.f90 | 2 +- src/main/part.F90 | 27 +- src/main/{phantom.F90 => phantom.f90} | 0 src/main/physcon.f90 | 1 + src/main/ptmass.F90 | 439 +++++++++++--- src/main/random.f90 | 55 +- src/main/readwrite_dumps_common.f90 | 14 +- src/main/readwrite_dumps_fortran.f90 | 25 +- src/main/readwrite_infile.F90 | 14 +- src/main/step_leapfrog.F90 | 12 +- src/main/subgroup.f90 | 117 +++- src/main/substepping.F90 | 97 +-- src/main/utils_deriv.f90 | 2 +- src/main/utils_sort.f90 | 260 +++++++- src/main/utils_timing.f90 | 16 +- src/main/writeheader.F90 | 12 +- src/setup/set_orbit.f90 | 30 - src/setup/set_star_utils.f90 | 3 +- src/setup/setup_bondi.f90 | 295 +++++++++ src/setup/setup_cluster.f90 | 104 +++- src/setup/setup_grdisc.F90 | 7 +- src/setup/setup_starcluster.f90 | 265 +++++++++ src/setup/setup_testparticles.f90 | 2 +- src/setup/setup_wind.f90 | 821 ++++++++++++++++++++++++++ src/tests/test_fastmath.f90 | 162 +++++ src/tests/test_gr.f90 | 557 +++++++++++++++++ src/tests/test_mpi.f90 | 100 ++++ src/tests/test_ptmass.f90 | 246 +++++++- src/tests/testsuite.F90 | 2 +- src/utils/struct_part.f90 | 8 +- 45 files changed, 4089 insertions(+), 350 deletions(-) create mode 100644 src/main/H2regions.f90 create mode 100644 src/main/eos_HIIR.f90 rename src/main/{phantom.F90 => phantom.f90} (100%) create mode 100644 src/setup/setup_bondi.f90 create mode 100644 src/setup/setup_starcluster.f90 create mode 100644 src/setup/setup_wind.f90 create mode 100644 src/tests/test_fastmath.f90 create mode 100644 src/tests/test_gr.f90 create mode 100644 src/tests/test_mpi.f90 diff --git a/AUTHORS b/AUTHORS index 9f44811cf..649e5eb20 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,12 +13,12 @@ David Liptai Lionel Siess Fangyi (Fitz) Hu Daniel Mentiplay +Yrisch Megha Sharma Arnaud Vericel Mark Hutchison Mats Esseldeurs Rebecca Nealon -Yrisch Elisabeth Borchert Ward Homan Christophe Pinte @@ -26,48 +26,50 @@ Terrence Tricco Stephane Michoulier Simone Ceppi Spencer Magnall -Enrico Ragusa Caitlyn Hardiman +Enrico Ragusa Cristiano Longarini Sergei Biriukov Giovanni Dipierro Roberto Iaconi -Hauke Worpel Amena Faruqi +Hauke Worpel Alison Young Stephen Neilson <36410751+s-neilson@users.noreply.github.com> Martina Toscani Benedetta Veronesi -Thomas Reichardt Sahl Rowther Simon Glover +Thomas Reichardt Jean-François Gonzalez Christopher Russell -Phantom benchmark bot -Jolien Malfait -Alex Pettitt Alessia Franchini +Alex Pettitt +Jolien Malfait +Phantom benchmark bot Kieran Hirsh -Nicole Rodrigues Mike Lau -Nicolás Cuello -Farzana Meru +Nicole Rodrigues David Trevascus +Farzana Meru +Nicolás Cuello Chris Nixon Miguel Gonzalez-Bolivar -Maxime Lombart -Joe Fisher +Benoit Commercon Giulia Ballabio +Joe Fisher +Maxime Lombart +Orsola De Marco Zachary Pellow s-neilson <36410751+s-neilson@users.noreply.github.com> -Benoit Commercon -Orsola De Marco -MICHOULIER Stephane -Stéven Toupin -Taj Jankovič +Ariel Chitan +Chunliang Mu Cox, Samuel -Jeremy Smallwood Hugh Griffiths -Chunliang Mu +Jeremy Smallwood Jorge Cuadra +MICHOULIER Stephane Steven Rieder +Stéven Toupin +Taj Jankovič +rebeccagmartin <74937128+rebeccagmartin@users.noreply.github.com> diff --git a/build/Makefile b/build/Makefile index 1ad43de54..423141b05 100644 --- a/build/Makefile +++ b/build/Makefile @@ -506,7 +506,7 @@ SRCCHEM= fs_data.f90 mol_data.f90 utils_spline.f90 \ # equations of state # SRCMESA= eos_mesa_microphysics.f90 eos_mesa.f90 -SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_stamatellos.f90 eos.f90 +SRCEOS = eos_barotropic.f90 eos_stratified.f90 eos_piecewise.f90 ${SRCMESA} eos_shen.f90 eos_helmholtz.f90 eos_idealplusrad.f90 ionization.F90 eos_gasradrec.f90 eos_HIIR.f90 eos_stamatellos.f90 eos.f90 ifeq ($(HDF5), yes) SRCREADWRITE_DUMPS= utils_hdf5.f90 utils_dumpfiles_hdf5.f90 readwrite_dumps_common.f90 readwrite_dumps_fortran.F90 readwrite_dumps_hdf5.F90 readwrite_dumps.F90 @@ -536,7 +536,7 @@ SOURCES= physcon.f90 ${CONFIG} ${SRCKERNEL} io.F90 units.f90 \ utils_deriv.f90 utils_implicit.f90 radiation_implicit.f90 ${SRCTURB} \ ${SRCINJECT_DEPS} wind_equations.f90 wind.F90 \ ${SRCKROME} memory.f90 ${SRCREADWRITE_DUMPS} ${SRCINJECT} \ - utils_subgroup.f90 utils_kepler.f90 subgroup.f90\ + H2regions.f90 utils_subgroup.f90 utils_kepler.f90 subgroup.f90 \ quitdump.f90 ptmass.F90 \ readwrite_infile.F90 dens.F90 force.F90 deriv.F90 energies.F90 sort_particles.f90 \ utils_shuffleparticles.F90 evwrite.f90 substepping.F90 step_leapfrog.F90 writeheader.F90 ${SRCAN} step_supertimestep.F90 \ @@ -631,7 +631,7 @@ OBJDUMP= $(OBJDUMP1:.F90=.o) # must NOT contain .F90 files or pre-processing options # LIBSETUP=$(BINDIR)/libphantomsetup.a -SRCLIBSETUP=physcon.f90 geometry.f90 random.f90 utils_tables.f90 utils_vectors.f90 stretchmap.f90 \ +SRCLIBSETUP=physcon.f90 geometry.f90 utils_sort.f90 random.f90 utils_tables.f90 utils_vectors.f90 stretchmap.f90 \ utils_binary.f90 set_binary.f90 set_flyby.f90 \ set_hierarchical_utils.f90 \ set_unifdis.f90 set_sphere.f90 set_shock.f90 \ @@ -869,7 +869,7 @@ pyanalysis: libphantom.so # .PHONY: phantom2struct phantom2struct: - ${MAKE} phantomanalysis ANALYSIS="utils_timing.f90 io_structurefn.f90 random.f90 struct_part.f90 analysis_structurefn.f90"\ + ${MAKE} phantomanalysis ANALYSIS="utils_timing.f90 io_structurefn.f90 utils_sort.f90 random.f90 struct_part.f90 analysis_structurefn.f90"\ ANALYSISBIN=$@ ANALYSISONLY=yes cleanphantom2struct: diff --git a/src/main/H2regions.f90 b/src/main/H2regions.f90 new file mode 100644 index 000000000..8d81b4a12 --- /dev/null +++ b/src/main/H2regions.f90 @@ -0,0 +1,342 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module HIIRegion +! +! HIIRegion +! +! :References: Fujii et al. (2021), Hopkins et al. (2012) +! +! :Owner: Yrisch +! +! :Runtime parameters: None +! +! :Dependencies: dim, eos, infile_utils, io, linklist, part, physcon, +! sortutils, timing, units +! +! contains routines to model HII region expansion due to ionization and radiation pressure.. +! routine originally made by Hopkins et al. (2012),reused by Fujii et al. (2021) +! and adapted in Phantom by Yann Bernard + + implicit none + + public :: update_ionrates,update_ionrate, HII_feedback,initialize_H2R,read_options_H2R,write_options_H2R + + integer, parameter, public :: HIIuprate = 8 ! update rate when IND_TIMESTEPS=yes + integer, public :: iH2R = 0 + real , public :: Rmax = 15 ! Maximum HII region radius (pc) to avoid artificial expansion... + real , public :: Mmin = 8 ! Minimum mass (Msun) to produce HII region + integer, public :: nHIIsources = 0 + real , public :: ar + real , public :: mH + + real, parameter :: a = -39.3178 ! + real, parameter :: b = 221.997 ! fitted parameters to compute + real, parameter :: c = -227.456 ! ionisation rate for massive + real, parameter :: d = 117.410 ! extracted from Fujii et al. (2021). + real, parameter :: e = -30.1511 ! (Expressed in function of log(solar masses) and s) + real, parameter :: f = 3.06810 ! + real, parameter :: ar_cgs = 2.7d-13 + real, parameter :: sigd_cgs = 1.d-21 + real :: sigd + real :: hv_on_c + real :: Tion + real :: Rst_max + real :: Minmass + real :: uIon + + private + +contains + + !----------------------------------------------------------------------- + !+ + ! Initialise stellar feedbacks + !+ + !----------------------------------------------------------------------- +subroutine initialize_H2R + use io, only:iprint,iverbose,id,master + use part, only:isionised + use units, only:udist,umass,utime + use physcon, only:mass_proton_cgs,kboltz,pc,eV,solarm + use eos , only:gmw,gamma + isionised(:)=.false. + !calculate the useful constant in code units + mH = gmw*mass_proton_cgs + Tion = 1.e4 + ar = ar_cgs*(utime/udist**3) + sigd = sigd_cgs*udist**2 + hv_on_c = ((18.6*eV)/2.997924d10)*(utime/(udist*umass)) + Rst_max = sqrt(((Rmax*pc)/udist)**2) + Minmass = (Mmin*solarm)/umass + if (gamma>1.) then + uIon = kboltz*Tion/(mH*(gamma-1.))*(utime/udist)**2 + else + uIon = 1.5*(kboltz*Tion/(mH))*(utime/udist)**2 + endif + + mH = mH/umass + + if (id == master .and. iverbose > 1) then + write(iprint,"(a,es18.10,es18.10)") " feedback constants mH,uIon : ", mH,uIon + write(iprint,"(a,es18.10,es18.10)") " Max strögrem radius (code/pc) : ", Rst_max, Rmax + write(iprint,"(a,es18.10,es18.10)") " Min feedback mass (code/Msun) : ", Minmass, Mmin + endif + return +end subroutine initialize_H2R + +!----------------------------------------------------------------------- +!+ +! Calculation of the the ionizing photon rate of all stars (Only for restart) +!+ +!----------------------------------------------------------------------- + +subroutine update_ionrates(nptmass,xyzmh_ptmass,h_acc) + use io, only:iprint,iverbose + use units, only:umass + use part, only:irateion,ihacc,irstrom + use physcon,only:solarm + integer, intent(in) :: nptmass + real, intent(inout) :: xyzmh_ptmass(:,:) + real, intent(in) :: h_acc + real :: logmi,log_Q,mi,hi + integer :: i + nHIIsources = 0 + !$omp parallel do default(none) & + !$omp shared(xyzmh_ptmass,iprint,iverbose,umass)& + !$omp shared(Minmass,h_acc,nptmass)& + !$omp private(logmi,log_Q,mi,hi)& + !$omp reduction(+:nHIIsources) + do i=1,nptmass + mi = xyzmh_ptmass(4,i) + hi = xyzmh_ptmass(ihacc,i) + if (mi > Minmass .and. hi < h_acc) then + logmi = log10(mi*(umass/solarm)) + ! caluclation of the ionizing photon rate of each sources + ! this calculation uses Fujii's formula derived from OSTAR2002 databases + log_Q = (a+b*logmi+c*logmi**2+d*logmi**3+e*logmi**4+f*logmi**5) + xyzmh_ptmass(irateion,i) = log_Q + xyzmh_ptmass(irstrom,i) = -1. + nHIIsources = nHIIsources + 1 + if (iverbose >= 0) then + write(iprint,"(/a,es18.10,es18.10/)")"Massive stars detected : Log Q, Mass : ",log_Q,mi + endif + else + xyzmh_ptmass(irateion,i) = -1. + xyzmh_ptmass(irstrom,i) = -1. + endif + enddo + !$omp end parallel do + if (iverbose > 1) then + write(iprint,"(/a,i8/)") "nb_feedback sources : ",nHIIsources + endif + return +end subroutine update_ionrates + +subroutine update_ionrate(i,xyzmh_ptmass,h_acc) + use io, only:iprint,iverbose + use units, only:umass + use part, only:irateion,ihacc,irstrom + use physcon,only:solarm + integer, intent(in) :: i + real, intent(inout) :: xyzmh_ptmass(:,:) + real, intent(in) :: h_acc + real :: logmi,log_Q,mi,hi + mi = xyzmh_ptmass(4,i) + hi = xyzmh_ptmass(ihacc,i) + if (mi > Minmass .and. hi < h_acc) then + logmi = log10(mi*(umass/solarm)) + ! caluclation of the ionizing photon rate of each sources + ! this calculation uses Fujii's formula derived from OSTAR2002 databases + log_Q = (a+b*logmi+c*logmi**2+d*logmi**3+e*logmi**4+f*logmi**5) + xyzmh_ptmass(irateion,i) = log_Q + xyzmh_ptmass(irstrom,i) = -1. + nHIIsources = nHIIsources + 1 + if (iverbose >= 0) then + write(iprint,"(/a,es18.10,es18.10/)")"Massive stars detected : Log Q, Mass : ",log_Q,mi + endif + else + xyzmh_ptmass(irateion,i) = -1. + xyzmh_ptmass(irstrom,i) = -1. + endif + + if (iverbose > 1) then + write(iprint,"(/a,i8/)") "nb_feedback sources : ",nHIIsources + endif + return +end subroutine update_ionrate + + !----------------------------------------------------------------------- + !+ + ! Main subroutine : Application of the HII feedback using Hopkins's like prescription + !+ + !----------------------------------------------------------------------- + +subroutine HII_feedback(nptmass,npart,xyzh,xyzmh_ptmass,vxyzu,isionised,dt) + use part, only:rhoh,massoftype,ihsoft,igas,irateion,isdead_or_accreted,& + irstrom + use linklist, only:listneigh=>listneigh_global,getneigh_pos,ifirstincell + use sortutils, only:Knnfunc,set_r2func_origin,r2func_origin + use physcon, only:pc,pi + use timing, only:get_timings,increment_timer,itimer_HII + use dim, only:maxvxyzu + use units, only:utime + integer, intent(in) :: nptmass,npart + real, intent(in) :: xyzh(:,:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyzu(:,:) + logical, intent(inout) :: isionised(:) + real, optional, intent(in) :: dt + integer, parameter :: maxcache = 12000 + real, save :: xyzcache(maxcache,3) + integer :: i,k,j,npartin,nneigh + real(kind=4) :: t1,t2,tcpu1,tcpu2 + real :: pmass,Ndot,DNdot,logNdiff,taud,mHII,r,r_in,hcheck + real :: xi,yi,zi,log_Qi,stromi,xj,yj,zj,dx,dy,dz,vkx,vky,vkz + logical :: momflag + + momflag = .false. + r = 0. + r_in = 0. + + if (present(dt)) momflag = .true. + + ! at each new kick we reset all the particles status + isionised(:) = .false. + pmass = massoftype(igas) + + call get_timings(t1,tcpu1) + ! + !-- Rst derivation and thermal feedback + ! + if (nHIIsources > 0) then + do i=1,nptmass + npartin=0 + log_Qi = xyzmh_ptmass(irateion,i) + if (log_Qi <=0.) cycle + Ndot = log_Qi ! instead of working with very large number, we'll work in logspace now + xi = xyzmh_ptmass(1,i) + yi = xyzmh_ptmass(2,i) + zi = xyzmh_ptmass(3,i) + stromi = xyzmh_ptmass(irstrom,i) + if (stromi >= 0. ) then + hcheck = 1.4*stromi + 0.01*Rmax + else + hcheck = Rmax + endif + do while(hcheck <= Rmax) + call getneigh_pos((/xi,yi,zi/),0.,hcheck,3,listneigh,nneigh,xyzh,xyzcache,maxcache,ifirstincell) + call set_r2func_origin(xi,yi,zi) + call Knnfunc(nneigh,r2func_origin,xyzh,listneigh) !! Here still serial version of the quicksort. Parallel version in prep.. + if (nneigh > 0) exit + hcheck = hcheck + 0.01*Rmax ! additive term to allow unresolved case to open + enddo + do k=1,nneigh + j = listneigh(k) + if (.not. isdead_or_accreted(xyzh(4,j))) then + ! ionising photons needed to fully ionise the current particle + DNdot = log10((((pmass*ar*rhoh(xyzh(4,j),pmass))/(mH**2))/utime)) + if (Ndot>DNdot) then + if (.not.(isionised(j))) then + logNdiff = DNdot -Ndot + Ndot = Ndot + log10(1-10**(logNdiff)) + isionised(j)=.true. + if (maxvxyzu >= 4) vxyzu(4,j) = uIon + endif + else + if (k > 1) then + ! end of the HII region + r = sqrt((xi-xyzh(1,j))**2 + (yi-xyzh(2,j))**2 + (zi-xyzh(3,j))**2) + j = listneigh(1) + else + ! unresolved case + r = 0. + endif + exit + endif + endif + enddo + npartin = k + xyzmh_ptmass(irstrom,i) = r + ! + !-- Momentum feedback + ! + if (momflag .and. npartin > 3) then + j = listneigh(1) + r_in = sqrt((xi-xyzh(1,j))**2 + (yi-xyzh(2,j))**2 + (zi-xyzh(3,j))**2) + mHII = ((4.*pi*(r**3-r_in**3)*rhoh(xyzh(4,j),pmass))/3) + if (mHII>3*pmass) then +!$omp parallel do default(none) & +!$omp shared(mHII,listneigh,xyzh,sigd,dt) & +!$omp shared(mH,vxyzu,log_Qi,hv_on_c,npartin,pmass,xi,yi,zi) & +!$omp private(j,dx,dy,dz,vkx,vky,vkz,xj,yj,zj,r,taud) + do k=1,npartin + j = listneigh(1) + xj = xyzh(1,j) + yj = xyzh(2,j) + zj = xyzh(3,j) + dx = xj - xi + dy = yj - yi + dz = zj - zi + r = dx**2 + dy**2 + dz**2 + taud = (rhoh(xyzh(4,j),pmass)/mH)*sigd*r + if (taud > 1.97) taud=1.97 + vkz = (1.+1.5*exp(-taud))*((10**log_Qi)/mHII)*hv_on_c*(dz/r) + vkx = (1.+1.5*exp(-taud))*((10**log_Qi)/mHII)*hv_on_c*(dx/r) + vky = (1.+1.5*exp(-taud))*((10**log_Qi)/mHII)*hv_on_c*(dy/r) + vxyzu(1,j) = vxyzu(1,j) + vkx*dt + vxyzu(2,j) = vxyzu(2,j) + vky*dt + vxyzu(3,j) = vxyzu(3,j) + vkz*dt + enddo +!$omp end parallel do + endif + endif + enddo + endif + call get_timings(t2,tcpu2) + call increment_timer(itimer_HII,t2-t1,tcpu2-tcpu1) + return +end subroutine HII_feedback + +subroutine write_options_H2R(iunit) + use infile_utils, only:write_inopt + use physcon, only:solarm + integer, intent(in) :: iunit + write(iunit,"(/,a)") '# options controlling HII region expansion feedback' + if (iH2R>0) then + call write_inopt(iH2R, 'iH2R', "enable the HII region expansion feedback in star forming reigon", iunit) + call write_inopt(Mmin, 'Mmin', "Minimum star mass to trigger HII region (MSun)", iunit) + call write_inopt(Rmax, 'Rmax', "Maximum radius for HII region (pc)", iunit) + endif +end subroutine write_options_H2R + +subroutine read_options_H2R(name,valstring,imatch,igotall,ierr) + use io, only:fatal + character(len=*), intent(in) :: name,valstring + logical, intent(out) :: imatch,igotall + integer, intent(out) :: ierr + integer, save :: ngot = 0 + character(len=30), parameter :: label = 'read_options_H2R' + imatch = .true. + select case(trim(name)) + case('iH2R') + read(valstring,*,iostat=ierr) iH2R + if (iH2R < 0) call fatal(label,'HII region option out of range') + ngot = ngot + 1 + case('Mmin') + read(valstring,*,iostat=ierr) Mmin + if (Mmin < 8.) call fatal(label,'Minimimum mass can not be inferior to 8 solar masses') + ngot = ngot + 1 + case('Rmax') + read(valstring,*,iostat=ierr) Rmax + if (Rmax < 10.) call fatal(label,'Maximum radius can not be inferior to 10 pc') + ngot = ngot + 1 + case default + imatch = .true. + end select + igotall = (ngot >= 3) +end subroutine read_options_H2R + +end module HIIRegion diff --git a/src/main/checksetup.f90 b/src/main/checksetup.f90 index 9ab68cacf..61827b35b 100644 --- a/src/main/checksetup.f90 +++ b/src/main/checksetup.f90 @@ -14,9 +14,9 @@ module checksetup ! ! :Runtime parameters: None ! -! :Dependencies: boundary, boundary_dyn, centreofmass, dim, dust, eos, -! externalforces, io, metric_tools, nicil, options, part, physcon, -! ptmass, ptmass_radiation, sortutils, timestep, units, utils_gr +! :Dependencies: HIIRegion, boundary, boundary_dyn, centreofmass, dim, +! dust, eos, externalforces, io, metric_tools, nicil, options, part, +! physcon, ptmass, ptmass_radiation, sortutils, timestep, units, utils_gr ! implicit none public :: check_setup @@ -105,7 +105,7 @@ subroutine check_setup(nerror,nwarn,restart) nerror = nerror + 1 endif else - if (polyk < tiny(0.) .and. ieos /= 2 .and. ieos /= 5 .and. ieos /= 17) then + if (polyk < tiny(0.) .and. ieos /= 2 .and. ieos /= 5 .and. ieos /= 17 .and. ieos/= 22) then print*,'WARNING! polyk = ',polyk,' in setup, speed of sound will be zero in equation of state' nwarn = nwarn + 1 endif @@ -239,7 +239,7 @@ subroutine check_setup(nerror,nwarn,restart) nerror = nerror + 1 endif else - if (abs(gamma-1.) > tiny(gamma) .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /=9 .and. ieos /= 17)) then + if (abs(gamma-1.) > tiny(gamma) .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /=9 .and. ieos /= 17 .and. ieos /=22)) then print*,'*** ERROR: using isothermal EOS, but gamma = ',gamma gamma = 1. print*,'*** Resetting gamma to 1, gamma = ',gamma @@ -437,6 +437,10 @@ subroutine check_setup(nerror,nwarn,restart) !--check Regularization imcompatibility ! call check_regnbody (nerror) +! +!--check HII region expansion feedback +! + call check_HIIRegion (nerror) if (.not.h2chemistry .and. maxvxyzu >= 4 .and. icooling == 3 .and. iexternalforce/=iext_corotate .and. nptmass==0) then if (dot_product(xcom,xcom) > 1.e-2) then @@ -528,7 +532,7 @@ end function in_range subroutine check_setup_ptmass(nerror,nwarn,hmin) use dim, only:maxptmass use part, only:nptmass,xyzmh_ptmass,ihacc,ihsoft,gr,iTeff,sinks_have_luminosity,& - ilum,iJ2,ispinx,ispinz,iReff + ilum,iJ2,ispinx,ispinz,iReff,linklist_ptmass use ptmass_radiation, only:isink_radiation use ptmass, only:use_fourthorder integer, intent(inout) :: nerror,nwarn @@ -587,6 +591,7 @@ subroutine check_setup_ptmass(nerror,nwarn,hmin) print*,' ERROR: sink ',i,' mass = ',xyzmh_ptmass(4,i) elseif (xyzmh_ptmass(4,i) < 0.) then print*,' Sink ',i,' has previously merged with another sink' + print*,' Connected to sink : ',linklist_ptmass(i) n = n + 1 endif enddo @@ -1045,5 +1050,24 @@ subroutine check_regnbody (nerror) endif end subroutine check_regnbody +subroutine check_HIIRegion(nerror) + use HIIRegion, only:iH2R + use eos, only:ieos + use dim, only:gr,mpi + integer, intent(inout) :: nerror + if (iH2R > 0 .and. ieos/=21 .and. ieos/=22) then + print "(/,a,/)", "Error: If HII activated, eos == 21 or 22 is mandatory..." + nerror = nerror + 1 + endif + if (iH2R > 0 .and. gr) then + print "(/,a,/)", "Error: Gr is not compatible with HII Region" + nerror = nerror + 1 + endif + if (iH2R > 0 .and. mpi) then + print "(/,a,/)", "Error: MPI is not compatible with HII Region" + nerror = nerror + 1 + endif +end subroutine check_HIIRegion + end module checksetup diff --git a/src/main/config.F90 b/src/main/config.F90 index 5acb64234..97b13a132 100644 --- a/src/main/config.F90 +++ b/src/main/config.F90 @@ -42,7 +42,9 @@ module dim #else integer, parameter :: maxptmass = 1000 #endif - integer, parameter :: nsinkproperties = 19 + integer, parameter :: nsinkproperties = 22 + + logical :: store_ll_ptmass = .false. ! storage of thermal energy or not #ifdef ISOTHERMAL diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 261b5a24f..915c219fa 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -175,7 +175,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& Bevol,Bxyz,dustevol,dustfrac,alphaind) use part, only:isdead_or_accreted,massoftype,igas,rhoh,igasP,iradP,iradxi,ics,imu,iX,iZ,& iohm,ihall,nden_nimhd,eta_nimhd,iambi,get_partinfo,iphase,this_is_a_test,& - ndustsmall,itemp,ikappa,idmu,idgamma,icv + ndustsmall,itemp,ikappa,idmu,idgamma,icv,isionised use part, only:nucleation,igamma use eos, only:equationofstate,ieos,eos_outputs_mu,done_init_eos,init_eos,gmw,X_in,Z_in,gamma use radiation_utils, only:radiation_equation_of_state,get_opacity @@ -215,7 +215,7 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& !$omp parallel do default (none) & !$omp shared(xyzh,vxyzu,npart,rad,eos_vars,radprop,Bevol,Bxyz) & !$omp shared(ieos,nucleation,nden_nimhd,eta_nimhd) & -!$omp shared(alpha,alphamax,iphase,maxphase,maxp,massoftype) & +!$omp shared(alpha,alphamax,iphase,maxphase,maxp,massoftype,isionised) & !$omp shared(use_dustfrac,dustfrac,dustevol,this_is_a_test,ndustsmall,alphaind,dvdx) & !$omp shared(iopacity_type,use_var_comp,do_nucleation,update_muGamma,implicit_radiation) & !$omp private(i,spsound,rhoi,p_on_rhogas,rhogas,gasfrac,uui) & @@ -274,10 +274,11 @@ subroutine cons2prim_everything(npart,xyzh,vxyzu,dvdx,rad,eos_vars,radprop,& uui = vxyzu(4,i) if (uui < 0.) call warning('cons2prim','Internal energy < 0',i,'u',uui) call equationofstate(ieos,p_on_rhogas,spsound,rhogas,xi,yi,zi,temperaturei,eni=uui,& - gamma_local=gammai,mu_local=mui,Xlocal=X_i,Zlocal=Z_i) + gamma_local=gammai,mu_local=mui,Xlocal=X_i,Zlocal=Z_i,isionised=isionised(i)) else !isothermal - call equationofstate(ieos,p_on_rhogas,spsound,rhogas,xi,yi,zi,temperaturei,mu_local=mui) + call equationofstate(ieos,p_on_rhogas,spsound,rhogas,xi,yi,zi,temperaturei,mu_local=mui, & + isionised=isionised(i)) endif eos_vars(igasP,i) = p_on_rhogas*rhogas diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index d333810e8..1952563f7 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -132,7 +132,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) +subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2_in,kappa_in,abund_in,ipart) use io, only:fatal use dim, only:nabundances use eos, only:gmw,gamma,ieos,get_temperature_from_u @@ -143,11 +143,13 @@ 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 + 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) + integer,intent(in),optional:: ipart real, intent(out) :: dudt ! in code units real :: mui,gammai,Tgas,Tdust,K2,kappa real :: abundi(nabn) @@ -184,6 +186,8 @@ subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2 call cooling_Gammie_explicit(xi,yi,zi,ui,dudt) 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) 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 b8b869f39..62dc0eb02 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -64,24 +64,22 @@ end subroutine init_star ! Do cooling calculation ! ! update energy to return evolved energy array. Called from substep -subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,Tfloor) +subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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,rhoh,massoftype,igas - use timestep_ind, only:get_dt + use part, only:xyzmh_ptmass,igas integer,intent(in) :: i - integer(kind=1),intent(in) :: ibini - real,intent(in) :: xyzhi(:),dtsph,Tfloor - real,intent(inout) :: ui - real :: dti,rhoi,coldensi,kappaBari,kappaParti,ri2 + real,intent(in) :: xi,yi,zi,rhoi,Tfloor + real,intent(in) :: ui,dt + real,intent(out)::dudti_cool + real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot real :: cs2,Om2,Hmod2 real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi - dti = get_dt(dtsph,ibini) coldensi = huge(coldensi) poti = Gpot_cool(i) du_FLDi = duFLD(i) @@ -91,14 +89,13 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,Tfloor) tthermi = huge(tthermi) opaci = epsilon(opaci) if (abs(ui) < epsilon(ui)) print *, "ui zero", i - rhoi = rhoh(xyzhi(4),massoftype(igas)) - + if (isink_star > 0) then - ri2 = (xyzhi(1)-xyzmh_ptmass(1,isink_star))**2d0 & - + (xyzhi(2)-xyzmh_ptmass(2,isink_star))**2d0 & - + (xyzhi(3)-xyzmh_ptmass(3,isink_star))**2d0 + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + + (yi-xyzmh_ptmass(2,isink_star))**2d0 & + + (zi-xyzmh_ptmass(3,isink_star))**2d0 else - ri2 = xyzhi(1)**2d0 + xyzhi(2)**2d0 + xyzhi(3)**2d0 + ri2 = xi**2d0 + yi**2d0 + zi**2d0 endif ! get opacities & Ti for ui @@ -164,11 +161,11 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,Tfloor) ! 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(dudti_rad/du_tot) < dtcool_crit) then + + 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) - ui = ui + du_tot*dti - if (ui < umini) ui = umini + dudti_cool = du_tot return endif @@ -186,7 +183,7 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,Tfloor) 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)*dti + "dudt_sph * dti=", dusph(i)*dt elseif (Teqi < epsilon(Teqi)) then print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& "Ti=", Ti, "poti=",poti, "rhoi=", rhoi @@ -209,21 +206,21 @@ subroutine radcool_update_energ(i,ibini,dtsph,xyzhi,ui,Tfloor) ! evolve energy if (tthermi == 0d0) then - ui = ui ! condition if denominator above is zero - elseif ( (dti/tthermi) < TINY(ui) ) then - ui = ui + dudti_cool = 0d0 ! condition if denominator above is zero + elseif ( (dt/tthermi) < TINY(ui) ) then + dudti_cool = 0d0 else - ui = ui*exp(-dti/tthermi) + ueqi*(1.d0-exp(-dti/tthermi)) !code units + dudti_cool = ( ui*exp(-dt/tthermi) + ueqi*(1.d0-exp(-dt/tthermi)) - ui) / dt !code units endif - if (isnan(ui) .or. ui < epsilon(ui)) then + if (isnan(dudti_cool)) 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=",dti,"tthermi=", tthermi,"umini=", umini + print *, "dt=",dt,"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) + call warning("In Stamatellos cooling","energ=NaN or 0. ui=",val=ui) stop endif diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index 4bbab4bdf..d11d5ae4b 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -122,6 +122,7 @@ subroutine derivs(icall,npart,nactive,xyzh,vxyzu,fxyzu,fext,divcurlv,divcurlB,& call do_timing('link',tlast,tcpulast,start=.true.) + ! ! compute disruption of dust particles ! diff --git a/src/main/eos.f90 b/src/main/eos.f90 index a698fe23d..ef1a8293c 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -27,7 +27,7 @@ module eos ! 16 = Shen eos ! 17 = polytropic EOS with varying mu (depending on H2 formation) ! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) -! 21 = read tabulated eos (for use with icooling == 8) +! 21 = read tabulated eos (for use with icooling == 9) ! ! :References: ! Lodato & Pringle (2007) @@ -50,7 +50,7 @@ module eos use part, only:ien_etotal,ien_entropy,ien_type use dim, only:gr implicit none - integer, parameter, public :: maxeos = 21 + integer, parameter, public :: maxeos = 22 real, public :: polyk, polyk2, gamma real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 logical, public :: extract_eos_from_hdr = .false. @@ -104,7 +104,7 @@ module eos ! (and position in the case of the isothermal disc) !+ !---------------------------------------------------------------- -subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gamma_local,mu_local,Xlocal,Zlocal) +subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gamma_local,mu_local,Xlocal,Zlocal,isionised) use io, only:fatal,error,warning use part, only:xyzmh_ptmass, nptmass use units, only:unit_density,unit_pressure,unit_ergg,unit_velocity @@ -118,6 +118,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam use eos_barotropic, only:get_eos_barotropic use eos_piecewise, only:get_eos_piecewise use eos_stamatellos + use eos_HIIR, only:get_eos_HIIR_iso,get_eos_HIIR_adiab integer, intent(in) :: eos_type real, intent(in) :: rhoi,xi,yi,zi real, intent(out) :: ponrhoi,spsoundi @@ -125,6 +126,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam real, intent(in), optional :: eni real, intent(inout), optional :: mu_local,gamma_local real, intent(in) , optional :: Xlocal,Zlocal + logical, intent(in), optional :: isionised integer :: ierr, i real :: r1,r2 real :: mass_r, mass ! defined for generalised Farris prescription @@ -132,6 +134,8 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam real :: cgsrhoi,cgseni,cgspresi,presi,gam1,cgsspsoundi real :: uthermconst,kappaBar,kappaPart real :: enthi,pondensi + logical :: isionisedi + ! ! Check to see if equation of state is compatible with GR cons2prim routines ! @@ -149,7 +153,8 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam if (present(mu_local)) mui = mu_local if (present(Xlocal)) X_i = Xlocal if (present(Zlocal)) Z_i = Zlocal - + if (present(isionised)) isionisedi = isionised + select case(eos_type) case(1) ! @@ -426,6 +431,12 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam if (present(mu_local)) mu_local = 1./imui if (present(gamma_local)) gamma_local = gammai +! case(21) + ! call get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) + + case(22) + call get_eos_HIIR_adiab(polyk,temperature_coef,mui,tempi,ponrhoi,rhoi,eni,gammai,spsoundi,isionisedi) + case(21) ! !--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=9 @@ -468,6 +479,7 @@ subroutine init_eos(eos_type,ierr) use eos_gasradrec, only:init_eos_gasradrec use eos_stamatellos,only:read_optab,init_S07cool,eos_file use dim, only:maxvxyzu,do_radiation + use eos_HIIR, only:init_eos_HIIR integer, intent(in) :: eos_type integer, intent(out) :: ierr integer :: ierr_mesakapp @@ -548,7 +560,10 @@ subroutine init_eos(eos_type,ierr) call read_optab(eos_file,ierr) if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) call init_S07cool - + +! - case(21,22) + case(22) + call init_eos_HIIR() end select done_init_eos = .true. diff --git a/src/main/eos_HIIR.f90 b/src/main/eos_HIIR.f90 new file mode 100644 index 000000000..315d97734 --- /dev/null +++ b/src/main/eos_HIIR.f90 @@ -0,0 +1,125 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module eos_HIIR +! +! eos_HIIR +! +! :References: None +! +! :Owner: Yrisch +! +! :Runtime parameters: None +! +! :Dependencies: io, physcon, units +! + implicit none + + public :: get_eos_HIIR_iso,get_eos_HIIR_adiab,init_eos_HIIR + + real, parameter :: Tion = 10000. + real, parameter :: muioninv = 2. + real, parameter :: muion = 0.5 + + real, public :: polykion + + private + +contains + + !----------------------------------------------------------------------- + !+ + ! Init eos routine + !+ + !----------------------------------------------------------------------- + +subroutine init_eos_HIIR + use physcon, only:kb_on_mh + use units, only:unit_velocity + + polykion = (muioninv*kb_on_mh*Tion)/(unit_velocity**2) + + +end subroutine init_eos_HIIR + + + !----------------------------------------------------------------------- + !+ + ! Main eos routine (isothermal) + !+ + !----------------------------------------------------------------------- +subroutine get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) + real, intent(in) :: polyk,temperature_coef + real, intent(out) :: ponrhoi,spsoundi,mui,tempi + logical, intent(in) :: isionisedi + + ! + !--dual medium isothermal eos + ! + ! :math:`P = c_s^2 \rho` + ! + ! where :math:`c_s^2 \equiv K` is a constant stored in the dump file header + ! + if (isionisedi) then + ponrhoi = polykion + spsoundi = sqrt(ponrhoi) + tempi = Tion + else + ponrhoi = polyk + spsoundi = sqrt(ponrhoi) + tempi = temperature_coef*mui*ponrhoi + endif + + +end subroutine get_eos_HIIR_iso + + + !----------------------------------------------------------------------- + !+ + ! Main eos routine (adiabatic) + !+ + !----------------------------------------------------------------------- +subroutine get_eos_HIIR_adiab(polyk,temperature_coef,mui,tempi,ponrhoi,rhoi,eni,gammai,spsoundi,isionisedi) + use io, only:fatal + real, intent(in) :: polyk,temperature_coef,rhoi,gammai + real, intent(out) :: ponrhoi,spsoundi,mui,tempi + logical, intent(in) :: isionisedi + real, intent(in), optional :: eni + + + if (gammai < tiny(gammai)) call fatal('eos','gamma not set for adiabatic eos',var='gamma',val=gammai) + + + if (isionisedi) then + ponrhoi = polykion + spsoundi = sqrt(ponrhoi) + tempi = Tion + else + if (present(eni)) then + if (eni < 0.) then + !write(iprint,'(a,Es18.4,a,4Es18.4)')'Warning: eos: u = ',eni,' < 0 at {x,y,z,rho} = ',xi,yi,zi,rhoi + call fatal('eos','utherm < 0',var='u',val=eni) + endif + if (gammai > 1.0001) then + ponrhoi = (gammai-1.)*eni ! use this if en is thermal energy + else + ponrhoi = 2./3.*eni ! en is thermal energy and gamma = 1 + endif + else + ponrhoi = polyk*rhoi**(gammai-1.) + endif + spsoundi = sqrt(gammai*ponrhoi) + + tempi = temperature_coef*mui*ponrhoi + endif + + +end subroutine get_eos_HIIR_adiab + + + +end module eos_HIIR + diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index 92c22f776..a5bf47b1d 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -16,12 +16,12 @@ module evolve ! ! :Runtime parameters: None ! -! :Dependencies: analysis, boundary_dyn, centreofmass, checkconserved, dim, -! energies, evwrite, externalforces, fileutils, forcing, inject, io, -! io_summary, mf_write, mpiutils, options, part, partinject, ptmass, -! quitdump, radiation_utils, readwrite_dumps, readwrite_infile, -! step_lf_global, supertimestep, timestep, timestep_ind, timestep_sts, -! timing +! :Dependencies: HIIRegion, analysis, boundary_dyn, centreofmass, +! checkconserved, dim, energies, evwrite, externalforces, fileutils, +! forcing, inject, io, io_summary, mf_write, mpiutils, options, part, +! partinject, ptmass, quitdump, radiation_utils, readwrite_dumps, +! readwrite_infile, step_lf_global, subgroup, substepping, supertimestep, +! timestep, timestep_ind, timestep_sts, timing ! implicit none public :: evol @@ -41,7 +41,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) use checkconserved, only:etot_in,angtot_in,totmom_in,mdust_in,& init_conservation_checks,check_conservation_error,& check_magnetic_stability - use dim, only:maxvxyzu,mhd,periodic,idumpfile + use dim, only:maxvxyzu,mhd,periodic,idumpfile,ind_timesteps use fileutils, only:getnextfilename use options, only:nfulldump,twallmax,nmaxdumps,rhofinal1,iexternalforce,rkill use readwrite_infile, only:write_infile @@ -89,13 +89,19 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) #endif use part, only:npart,nptmass,xyzh,vxyzu,fxyzu,fext,divcurlv,massoftype, & xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dptmass,gravity,iboundary, & - fxyz_ptmass_sinksink,ntot,poten,ndustsmall,accrete_particles_outside_sphere + fxyz_ptmass_sinksink,ntot,poten,ndustsmall,accrete_particles_outside_sphere,& + linklist_ptmass,isionised,dsdt_ptmass,isdead_or_accreted + use part, only:n_group,n_ingroup,n_sing,group_info,nmatrix use quitdump, only:quit use ptmass, only:icreate_sinks,ptmass_create,ipart_rhomax,pt_write_sinkev,calculate_mdot, & - set_integration_precision + set_integration_precision,ptmass_create_stars,use_regnbody,ptmass_create_seeds,& + ipart_createseeds,ipart_createstars use io_summary, only:iosum_nreal,summary_counter,summary_printout,summary_printnow use externalforces, only:iext_spiral use boundary_dyn, only:dynamic_bdy,update_boundaries + use HIIRegion, only:HII_feedback,iH2R,HIIuprate + use subgroup, only:group_identify + use substepping, only:get_force #ifdef MFLOW use mf_write, only:mflow_write #endif @@ -137,6 +143,9 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) logical :: use_global_dt integer :: j,nskip,nskipped,nevwrite_threshold,nskipped_sink,nsinkwrite_threshold character(len=120) :: dumpfile_orig + integer :: dummy,istepHII + + dummy = 0 tprint = 0. nsteps = 0 @@ -276,7 +285,49 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) ! creation of new sink particles ! call ptmass_create(nptmass,npart,ipart_rhomax,xyzh,vxyzu,fxyzu,fext,divcurlv,& - poten,massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,dptmass,time) + poten,massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,linklist_ptmass,dptmass,time) + endif + + if (icreate_sinks == 2) then + ! + ! creation of new seeds into evolved sinks + ! + if (ipart_createseeds /= 0) then + call ptmass_create_seeds(nptmass,ipart_createseeds,xyzmh_ptmass,linklist_ptmass,time) + endif + ! + ! creation of new stars from sinks (cores) + ! + if (ipart_createstars /= 0) then + call ptmass_create_stars(nptmass,ipart_createstars,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink, & + linklist_ptmass,time) + endif + endif + + if (iH2R > 0 .and. id==master) then + istepHII = 1 + if(ind_timesteps) then + istepHII = 2**nbinmax/HIIuprate + if (istepHII==0) istepHII = 1 + endif + if (mod(istepfrac,istepHII)==0 .or. istepfrac==1 .or. (icreate_sinks == 2 .and. ipart_createstars /= 0)) then + call HII_feedback(nptmass,npart,xyzh,xyzmh_ptmass,vxyzu,isionised) + endif + endif + + ! Need to recompute the force when sink or stars are created + if (ipart_rhomax /= 0 .or. ipart_createseeds /= 0 .or. ipart_createstars /= 0) then + if (use_regnbody) then + call group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix) + call get_force(nptmass,npart,0,1,time,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass,vxyz_ptmass,& + fxyz_ptmass,dsdt_ptmass,0.,0.,dummy,.false.,linklist_ptmass,group_info=group_info) + else + call get_force(nptmass,npart,0,1,time,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass,vxyz_ptmass,& + fxyz_ptmass,dsdt_ptmass,0.,0.,dummy,.false.,linklist_ptmass) + endif + if (ipart_createseeds /= 0) ipart_createseeds = 0 ! reset pointer to zero + if (ipart_createstars /= 0) ipart_createstars = 0 ! reset pointer to zero + dummy = 0 endif ! ! Strang splitting: implicit update for half step @@ -284,6 +335,7 @@ subroutine evol(infile,logfile,evfile,dumpfile,flag) if (do_radiation .and. exchange_radiation_energy .and. .not.implicit_radiation) then call update_radenergy(npart,xyzh,fxyzu,vxyzu,rad,radprop,0.5*dt) endif + nsteps = nsteps + 1 ! !--evolve data for one timestep @@ -641,7 +693,7 @@ subroutine print_timinginfo(iprint,nsteps,nsteplast) use io, only:formatreal use timing, only:timer,timers,print_timer,itimer_fromstart,itimer_lastdump,& itimer_step,itimer_link,itimer_balance,itimer_dens,& - itimer_force,itimer_extf,itimer_ev,itimer_io,ntimers + itimer_force,itimer_ev,itimer_io,ntimers integer, intent(in) :: iprint,nsteps,nsteplast real :: dfrac,fracinstep real(kind=4) :: time_fullstep diff --git a/src/main/force.F90 b/src/main/force.F90 index aa5438914..9fcc9b849 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -213,8 +213,8 @@ subroutine force(icall,npart,xyzh,vxyzu,fxyzu,divcurlv,divcurlB,Bevol,dBevol,& use kernel, only:kernel_softening use kdtree, only:expand_fgrav_in_taylor_series use linklist, only:get_distance_from_centre_of_mass - use part, only:xyzmh_ptmass,nptmass,massoftype,maxphase,is_accretable - use ptmass, only:icreate_sinks,rho_crit,r_crit2 + use part, only:xyzmh_ptmass,nptmass,massoftype,maxphase,is_accretable,ihacc + use ptmass, only:icreate_sinks,rho_crit,r_crit2,h_acc use units, only:unit_density #endif #ifdef DUST @@ -435,7 +435,7 @@ subroutine force(icall,npart,xyzh,vxyzu,fxyzu,divcurlv,divcurlB,Bevol,dBevol,& !$omp private(iactivei,iamdusti,iamtypei) & !$omp private(dx,dy,dz,poti,fxi,fyi,fzi,potensoft0,dum,epoti) & !$omp shared(xyzmh_ptmass,nptmass) & -!$omp shared(rhomax,ipart_rhomax,icreate_sinks,rho_crit,r_crit2) & +!$omp shared(rhomax,ipart_rhomax,icreate_sinks,rho_crit,r_crit2,h_acc) & !$omp private(rhomax_thread,ipart_rhomax_thread,use_part,j) & #endif !$omp shared(id) & @@ -682,6 +682,7 @@ subroutine force(icall,npart,xyzh,vxyzu,fxyzu,divcurlv,divcurlB,Bevol,dBevol,& ! use_part = .true. over_ptmass: do j=1,nptmass + if (icreate_sinks==2 .and. xyzmh_ptmass(ihacc,j) 0. .and. & (xyzh(1,i) - xyzmh_ptmass(1,j))**2 & + (xyzh(2,i) - xyzmh_ptmass(2,j))**2 & @@ -3005,7 +3006,7 @@ 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 = fxyz4 + if (icooling == 9) duSPH(i) = fxyz4 endif endif diff --git a/src/main/initial.F90 b/src/main/initial.F90 index 4c9a97aa2..7b8f26032 100644 --- a/src/main/initial.F90 +++ b/src/main/initial.F90 @@ -14,7 +14,7 @@ module initial ! ! :Runtime parameters: None ! -! :Dependencies: analysis, boundary, boundary_dyn, centreofmass, +! :Dependencies: HIIRegion, analysis, boundary, boundary_dyn, centreofmass, ! checkconserved, checkoptions, checksetup, cons2prim, cooling, cpuinfo, ! damping, densityforce, deriv, dim, dust, dust_formation, ! einsteintk_utils, energies, eos, evwrite, extern_gr, externalforces, @@ -131,7 +131,7 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) epot_sinksink,get_ntypes,isdead_or_accreted,dustfrac,ddustevol,& nden_nimhd,dustevol,rhoh,gradh, & Bevol,Bxyz,dustprop,filfac,ddustprop,ndustsmall,iboundary,eos_vars,dvdx, & - n_group,n_ingroup,n_sing,nmatrix,group_info + n_group,n_ingroup,n_sing,nmatrix,group_info,isionised use part, only:pxyzu,dens,metrics,rad,radprop,drad,ithick use densityforce, only:densityiterate use linklist, only:set_linklist @@ -212,7 +212,8 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) use checkconserved, only:get_conserv,etot_in,angtot_in,totmom_in,mdust_in use fileutils, only:make_tags_unique use damping, only:idamp - use subgroup, only:group_identify + use subgroup, only:group_identify,init_subgroup + use HIIRegion, only:iH2R,initialize_H2R,update_ionrates character(len=*), intent(in) :: infile character(len=*), intent(out) :: logfile,evfile,dumpfile logical, intent(in), optional :: noread @@ -496,10 +497,17 @@ subroutine startrun(infile,logfile,evfile,dumpfile,noread) else rhofinal1 = 0.0 endif + if (iH2R > 0 .and. id==master) then + call initialize_H2R + else + isionised = .false. + endif if (nptmass > 0) then if (id==master) write(iprint,"(a,i12)") ' nptmass = ',nptmass + if (iH2R > 0) call update_ionrates(nptmass,xyzmh_ptmass,h_acc) ! compute initial sink-sink forces and get timestep if (use_regnbody) then + call init_subgroup call group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix) call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,dtsinksink,& iexternalforce,time,merge_ij,merge_n,dsdt_ptmass,group_info=group_info) diff --git a/src/main/inject_BHL.f90 b/src/main/inject_BHL.f90 index a23162cc0..ae41283de 100644 --- a/src/main/inject_BHL.f90 +++ b/src/main/inject_BHL.f90 @@ -264,7 +264,7 @@ end subroutine inject_or_update_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_asteroidwind.f90 b/src/main/inject_asteroidwind.f90 index 37072a760..5e61737fe 100644 --- a/src/main/inject_asteroidwind.f90 +++ b/src/main/inject_asteroidwind.f90 @@ -152,7 +152,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/part.F90 b/src/main/part.F90 index 5b5ae5f18..d54c878e5 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -204,19 +204,24 @@ module part integer, parameter :: i_mlast = 17 ! accreted mass of last time integer, parameter :: imassenc = 18 ! mass enclosed in sink softening radius integer, parameter :: iJ2 = 19 ! 2nd gravity moment due to oblateness + integer, parameter :: irstrom = 20 ! Stromgren radius of the stars (icreate_sinks == 2) + integer, parameter :: irateion = 21 ! Inoisation rate of the stars (log)(icreate_sinks == 2) + integer, parameter :: itbirth = 22 ! birth time of the new sink integer, parameter :: ndptmass = 13 ! number of properties to conserve after a accretion phase or merge - real, allocatable :: xyzmh_ptmass(:,:) - real, allocatable :: vxyz_ptmass(:,:) - real, allocatable :: fxyz_ptmass(:,:),fxyz_ptmass_sinksink(:,:),fsink_old(:,:) - real, allocatable :: dsdt_ptmass(:,:),dsdt_ptmass_sinksink(:,:) - real, allocatable :: dptmass(:,:) + integer, allocatable :: linklist_ptmass(:) + real, allocatable :: xyzmh_ptmass(:,:) + real, allocatable :: vxyz_ptmass(:,:) + real, allocatable :: fxyz_ptmass(:,:),fxyz_ptmass_sinksink(:,:),fsink_old(:,:) + real, allocatable :: dsdt_ptmass(:,:),dsdt_ptmass_sinksink(:,:) + real, allocatable :: dptmass(:,:) integer :: nptmass = 0 ! zero by default real :: epot_sinksink character(len=*), parameter :: xyzmh_ptmass_label(nsinkproperties) = & (/'x ','y ','z ','m ','h ',& 'hsoft ','maccreted','spinx ','spiny ','spinz ',& 'tlast ','lum ','Teff ','Reff ','mdotloss ',& - 'mdotav ','mprev ','massenc ','J2 '/) + 'mdotav ','mprev ','massenc ','J2 ','Rstrom ',& + 'rate_ion ','tbirth '/) character(len=*), parameter :: vxyz_ptmass_label(3) = (/'vx','vy','vz'/) ! !--self-gravity @@ -304,6 +309,10 @@ module part integer :: n_sing = 0 ! Gradient of the time transformation function real, allocatable :: gtgrad(:,:) + ! +!-- Regularisation algorithm allocation +! + logical, allocatable :: isionised(:) ! !--derivatives (only needed if derivs is called) ! @@ -449,6 +458,7 @@ subroutine allocate_part call allocate_array('fxyz_ptmass_sinksink', fxyz_ptmass_sinksink, 4, maxptmass) call allocate_array('fsink_old', fsink_old, 4, maxptmass) call allocate_array('dptmass', dptmass, ndptmass,maxptmass) + call allocate_array('linklist_ptmass', linklist_ptmass, maxptmass) call allocate_array('dsdt_ptmass', dsdt_ptmass, 3, maxptmass) call allocate_array('dsdt_ptmass_sinksink', dsdt_ptmass_sinksink, 3, maxptmass) call allocate_array('poten', poten, maxgrav) @@ -497,6 +507,7 @@ subroutine allocate_part call allocate_array('group_info', group_info, 3, maxptmass) call allocate_array("nmatrix", nmatrix, maxptmass, maxptmass) call allocate_array("gtgrad", gtgrad, 3, maxptmass) + call allocate_array('isionised', isionised, maxp) end subroutine allocate_part @@ -540,6 +551,7 @@ subroutine deallocate_part if (allocated(fxyz_ptmass_sinksink)) deallocate(fxyz_ptmass_sinksink) if (allocated(fsink_old)) deallocate(fsink_old) if (allocated(dptmass)) deallocate(dptmass) + if (allocated(linklist_ptmass)) deallocate(linklist_ptmass) if (allocated(dsdt_ptmass)) deallocate(dsdt_ptmass) if (allocated(dsdt_ptmass_sinksink)) deallocate(dsdt_ptmass_sinksink) if (allocated(poten)) deallocate(poten) @@ -580,6 +592,7 @@ subroutine deallocate_part if (allocated(group_info)) deallocate(group_info) if (allocated(nmatrix)) deallocate(nmatrix) if (allocated(gtgrad)) deallocate(gtgrad) + if (allocated(isionised)) deallocate(isionised) end subroutine deallocate_part @@ -597,10 +610,12 @@ subroutine init_part npartoftype(:) = 0 npartoftypetot(:) = 0 massoftype(:) = 0. + isionised(:) = .false. !--initialise point mass arrays to zero xyzmh_ptmass = 0. vxyz_ptmass = 0. dsdt_ptmass = 0. + linklist_ptmass = -1 ! initialise arrays not passed to setup routine to zero if (mhd) then diff --git a/src/main/phantom.F90 b/src/main/phantom.f90 similarity index 100% rename from src/main/phantom.F90 rename to src/main/phantom.f90 diff --git a/src/main/physcon.f90 b/src/main/physcon.f90 index 2577d5fd6..414ba9d14 100644 --- a/src/main/physcon.f90 +++ b/src/main/physcon.f90 @@ -92,6 +92,7 @@ module physcon real(kind=8), parameter :: hours = 3.6d3 real(kind=8), parameter :: days = 8.64d4 real(kind=8), parameter :: years = 3.1556926d7 + real(kind=8), parameter :: myr = 3.1556926d13 ! !--Energy conversion ! diff --git a/src/main/ptmass.F90 b/src/main/ptmass.F90 index e75d1c29d..a5362c8a0 100644 --- a/src/main/ptmass.F90 +++ b/src/main/ptmass.F90 @@ -28,15 +28,18 @@ module ptmass ! - h_soft_sinkgas : *softening length for new sink particles* ! - h_soft_sinksink : *softening length between sink particles* ! - icreate_sinks : *allow automatic sink particle creation* +! - isink_potential : *sink potential(0=1/r,1=surf)* ! - r_crit : *critical radius for point mass creation (no new sinks < r_crit from existing sink)* ! - r_merge_cond : *sinks will merge if bound within this radius* ! - r_merge_uncond : *sinks will unconditionally merge within this separation* +! - r_neigh : *searching radius to detect subgroups* ! - rho_crit_cgs : *density above which sink particles are created (g/cm^3)* +! - use_regnbody : *allow subgroup integration method* ! -! :Dependencies: boundary, dim, eos, eos_barotropic, eos_piecewise, -! extern_geopot, externalforces, fastmath, infile_utils, io, io_summary, -! kdtree, kernel, linklist, mpidomain, mpiutils, options, part, -! ptmass_heating, units, vectorutils +! :Dependencies: HIIRegion, boundary, dim, eos, eos_barotropic, +! eos_piecewise, extern_geopot, externalforces, fastmath, infile_utils, +! io, io_summary, kdtree, kernel, linklist, mpidomain, mpiutils, options, +! part, physcon, ptmass_heating, random, subgroup, units, vectorutils ! use part, only:nsinkproperties,gravity,is_accretable,& ihsoft,ihacc,ispinx,ispiny,ispinz,imacc,iJ2,iReff @@ -50,6 +53,7 @@ module ptmass public :: ptmass_kick, ptmass_drift,ptmass_vdependent_correction public :: ptmass_not_obscured public :: ptmass_accrete, ptmass_create + public :: ptmass_create_stars,ptmass_create_seeds public :: write_options_ptmass, read_options_ptmass public :: update_ptmass public :: calculate_mdot @@ -58,12 +62,17 @@ module ptmass public :: set_integration_precision ! settings affecting routines in module (read from/written to input file) - integer, public :: icreate_sinks = 0 + integer, public :: icreate_sinks = 0 ! 1-standard sink creation scheme 2-Star formation scheme using core prescription + integer, public :: iseed_sf = 313 ! seed used to sample random value for icreate == 2 prescription... + integer, public :: ipart_createstars = 0 ! particle id that needs to create stars after reaching tmax_acc + integer, public :: ipart_createseeds = 0 ! particle id that needs to create seeds after reaching tseeds integer, public :: isink_potential = 0 real, public :: rho_crit_cgs = 1.e-10 real, public :: r_crit = 5.e-3 real, public :: h_acc = 1.e-3 real, public :: f_acc = 0.8 + real, public :: tmax_acc = huge(f_acc) + real, public :: tseeds = huge(f_acc) real, public :: h_soft_sinkgas = 0.0 real, public :: h_soft_sinksink = 0.0 real, public :: r_merge_uncond = 0.0 ! sinks will unconditionally merge if they touch @@ -324,7 +333,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin use extern_geopot, only:get_geopot_force use kernel, only:kernel_softening,radkern use vectorutils, only:unitvec - use part, only:igarg,igid + use part, only:igarg,igid,ihacc integer, intent(in) :: nptmass real, intent(in) :: xyzmh_ptmass(nsinkproperties,nptmass) real, intent(out) :: fxyz_ptmass(4,nptmass) @@ -336,7 +345,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin real, optional, intent(in) :: extrapfac real, optional, intent(in) :: fsink_old(4,nptmass) integer, optional, intent(in) :: group_info(3,nptmass) - real :: xi,yi,zi,pmassi,pmassj,fxi,fyi,fzi,phii + real :: xi,yi,zi,pmassi,pmassj,hacci,haccj,fxi,fyi,fzi,phii real :: ddr,dx,dy,dz,rr2,rr2j,dr3,f1,f2 real :: hsoft1,hsoft21,q2i,qi,psoft,fsoft real :: fextx,fexty,fextz,phiext !,hsofti @@ -383,8 +392,8 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin !$omp parallel do default(none) & !$omp shared(nptmass,xyzmh_ptmass,fxyz_ptmass,merge_ij,r_merge2,dsdt_ptmass,group_info,subsys) & !$omp shared(iexternalforce,ti,h_soft_sinksink,potensoft0,hsoft1,hsoft21) & - !$omp shared(extrapfac,extrap,fsink_old) & - !$omp private(i,j,xi,yi,zi,pmassi,pmassj) & + !$omp shared(extrapfac,extrap,fsink_old,h_acc,icreate_sinks) & + !$omp private(i,j,xi,yi,zi,pmassi,pmassj,hacci,haccj) & !$omp private(gidi,gidj) & !$omp private(dx,dy,dz,rr2,rr2j,ddr,dr3,f1,f2) & !$omp private(fxi,fyi,fzi,phii,dsx,dsy,dsz) & @@ -410,7 +419,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin zi = xyzmh_ptmass(3,i) endif pmassi = xyzmh_ptmass(4,i) - !hsofti = xyzmh_ptmass(5,i) + hacci = xyzmh_ptmass(ihacc,i) if (pmassi < 0.) cycle J2i = xyzmh_ptmass(iJ2,i) @@ -440,7 +449,7 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin dz = zi - xyzmh_ptmass(3,j) endif pmassj = xyzmh_ptmass(4,j) - !hsoftj = xyzmh_ptmass(5,j) + haccj = xyzmh_ptmass(ihacc,j) if (pmassj < 0.) cycle J2j = xyzmh_ptmass(iJ2,j) @@ -494,16 +503,32 @@ subroutine get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,phitot,dtsinksin endif endif if (rr2 < r_merge2) then - if (merge_ij(i)==0) then - merge_n = merge_n + 1 - merge_ij(i) = j + if (icreate_sinks == 2) then + if (hacci==h_acc .and. haccj==h_acc) then + if (merge_ij(i)==0) then + merge_n = merge_n + 1 + merge_ij(i) = j + else + ! if we have already identified a nearby sink, replace the tag with the nearest sink + dx = xi - xyzmh_ptmass(1,merge_ij(i)) + dy = yi - xyzmh_ptmass(2,merge_ij(i)) + dz = zi - xyzmh_ptmass(3,merge_ij(i)) + rr2j = dx*dx + dy*dy + dz*dz + epsilon(rr2j) + if (rr2 < rr2j) merge_ij(i) = j + endif + endif else - ! if we have already identified a nearby sink, replace the tag with the nearest sink - dx = xi - xyzmh_ptmass(1,merge_ij(i)) - dy = yi - xyzmh_ptmass(2,merge_ij(i)) - dz = zi - xyzmh_ptmass(3,merge_ij(i)) - rr2j = dx*dx + dy*dy + dz*dz + epsilon(rr2j) - if (rr2 < rr2j) merge_ij(i) = j + if (merge_ij(i)==0) then + merge_n = merge_n + 1 + merge_ij(i) = j + else + ! if we have already identified a nearby sink, replace the tag with the nearest sink + dx = xi - xyzmh_ptmass(1,merge_ij(i)) + dy = yi - xyzmh_ptmass(2,merge_ij(i)) + dz = zi - xyzmh_ptmass(3,merge_ij(i)) + rr2j = dx*dx + dy*dy + dz*dz + epsilon(rr2j) + if (rr2 < rr2j) merge_ij(i) = j + endif endif endif enddo @@ -600,22 +625,22 @@ subroutine ptmass_drift(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass,group_info,n_ingro integer, optional, intent(in) :: n_ingroup integer, optional, intent(in) :: group_info(:,:) integer :: i,k,istart_ptmass - logical :: woutsub + logical :: wsub if (present(n_ingroup)) then istart_ptmass = n_ingroup + 1 - woutsub = .true. + wsub = .true. else istart_ptmass = 1 - woutsub = .false. + wsub = .false. endif !$omp parallel do schedule(static) default(none) & !$omp shared(nptmass,ckdt,xyzmh_ptmass,vxyz_ptmass) & - !$omp shared(n_ingroup,group_info,woutsub,istart_ptmass) & + !$omp shared(n_ingroup,group_info,wsub,istart_ptmass) & !$omp private(i,k) do k=istart_ptmass,nptmass - if (woutsub) then + if (wsub) then i = group_info(igarg,k) else i = k @@ -636,6 +661,7 @@ end subroutine ptmass_drift !+ !---------------------------------------------------------------- subroutine ptmass_kick(nptmass,dkdt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dsdt_ptmass) + use part, only:iJ2 integer, intent(in) :: nptmass real, intent(in) :: dkdt real, intent(inout) :: vxyz_ptmass(3,nptmass), xyzmh_ptmass(nsinkproperties,nptmass) @@ -652,9 +678,11 @@ subroutine ptmass_kick(nptmass,dkdt,vxyz_ptmass,fxyz_ptmass,xyzmh_ptmass,dsdt_pt vxyz_ptmass(1,i) = vxyz_ptmass(1,i) + dkdt*fxyz_ptmass(1,i) vxyz_ptmass(2,i) = vxyz_ptmass(2,i) + dkdt*fxyz_ptmass(2,i) vxyz_ptmass(3,i) = vxyz_ptmass(3,i) + dkdt*fxyz_ptmass(3,i) - xyzmh_ptmass(ispinx,i) = xyzmh_ptmass(ispinx,i) + dkdt*dsdt_ptmass(1,i) - xyzmh_ptmass(ispiny,i) = xyzmh_ptmass(ispiny,i) + dkdt*dsdt_ptmass(2,i) - xyzmh_ptmass(ispinz,i) = xyzmh_ptmass(ispinz,i) + dkdt*dsdt_ptmass(3,i) + if (xyzmh_ptmass(iJ2,i) > 0.) then + xyzmh_ptmass(ispinx,i) = xyzmh_ptmass(ispinx,i) + dkdt*dsdt_ptmass(1,i) + xyzmh_ptmass(ispiny,i) = xyzmh_ptmass(ispiny,i) + dkdt*dsdt_ptmass(2,i) + xyzmh_ptmass(ispinz,i) = xyzmh_ptmass(ispinz,i) + dkdt*dsdt_ptmass(3,i) + endif endif enddo !$omp end parallel do @@ -768,10 +796,10 @@ end function ptmass_not_obscured !---------------------------------------------------------------- subroutine ptmass_accrete(is,nptmass,xi,yi,zi,hi,vxi,vyi,vzi,fxi,fyi,fzi, & itypei,pmassi,xyzmh_ptmass,vxyz_ptmass,accreted, & - dptmass,time,facc,nbinmax,ibin_wakei,nfaili) + dptmass,linklist_ptmass,time,facc,nbinmax,ibin_wakei,nfaili) !$ use omputils, only:ipart_omp_lock - use part, only: ihacc,ndptmass + use part, only: ihacc,itbirth,ndptmass use kernel, only: radkern2 use io, only: iprint,iverbose,fatal use io_summary, only: iosum_ptmass,maxisink,print_acc @@ -780,6 +808,7 @@ subroutine ptmass_accrete(is,nptmass,xi,yi,zi,hi,vxi,vyi,vzi,fxi,fyi,fzi, & real, intent(inout) :: hi real, intent(in) :: xyzmh_ptmass(nsinkproperties,nptmass) real, intent(in) :: vxyz_ptmass(3,nptmass) + integer, intent(in) :: linklist_ptmass(nptmass) logical, intent(out) :: accreted real, intent(inout) :: dptmass(ndptmass,nptmass) integer(kind=1), intent(in) :: nbinmax @@ -789,7 +818,7 @@ subroutine ptmass_accrete(is,nptmass,xi,yi,zi,hi,vxi,vyi,vzi,fxi,fyi,fzi, & real :: dx,dy,dz,r2,dvx,dvy,dvz,v2,hacc logical, parameter :: iofailreason=.false. integer :: j - real :: mpt,drdv,angmom2,angmomh2,epart,dxj,dyj,dzj,dvxj,dvyj,dvzj,rj2,vj2,epartj + real :: mpt,tbirthi,drdv,angmom2,angmomh2,epart,dxj,dyj,dzj,dvxj,dvyj,dvzj,rj2,vj2,epartj logical :: mostbound !$ external :: omp_set_lock,omp_unset_lock @@ -807,7 +836,23 @@ subroutine ptmass_accrete(is,nptmass,xi,yi,zi,hi,vxi,vyi,vzi,fxi,fyi,fzi, & sinkloop : do i=is,nptmass hacc = xyzmh_ptmass(ihacc,i) mpt = xyzmh_ptmass(4,i) + tbirthi = xyzmh_ptmass(itbirth,i) if (mpt < 0.) cycle + if (icreate_sinks==2) then + if (hacc < h_acc ) cycle + if (tbirthi + tmax_acc < time) then + !$omp master + if (ipart_createstars == 0) ipart_createstars = i + !$omp end master + cycle + endif + if ((tbirthi + tseeds < time) .and. (linklist_ptmass(i) == 0) .and. & + (ipart_createseeds == 0)) then + !$omp master + ipart_createseeds = i + !$omp end master + endif + endif dx = xi - xyzmh_ptmass(1,i) dy = yi - xyzmh_ptmass(2,i) dz = zi - xyzmh_ptmass(3,i) @@ -1017,8 +1062,8 @@ end subroutine update_ptmass !+ !------------------------------------------------------------------------- subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,poten,& - massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,dptmass,time) - use part, only:ihacc,ihsoft,igas,iamtype,get_partinfo,iphase,iactive,maxphase,rhoh, & + massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,linklist_ptmass,dptmass,time) + use part, only:ihacc,ihsoft,itbirth,igas,iamtype,get_partinfo,iphase,iactive,maxphase,rhoh, & ispinx,ispiny,ispinz,eos_vars,igasP,igamma,ndptmass use dim, only:maxp,maxneigh,maxvxyzu,maxptmass,ind_timesteps use kdtree, only:getneigh @@ -1045,6 +1090,7 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote real(4), intent(in) :: divcurlv(:,:),poten(:) real, intent(inout) :: xyzmh_ptmass(:,:),dptmass(ndptmass,maxptmass) real, intent(inout) :: vxyz_ptmass(:,:),fxyz_ptmass(4,maxptmass),fxyz_ptmass_sinksink(4,maxptmass) + integer, intent(inout) :: linklist_ptmass(maxptmass) real, intent(in) :: time integer(kind=1) :: iphasei,ibin_wakei,ibin_itest integer :: nneigh @@ -1061,7 +1107,7 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote real :: q2i,qi,psofti,psoftj,psoftk,fsoft,epot_mass,epot_rad,pmassgas1 real :: hcheck,hcheck2,f_acc_local real(4) :: divvi,potenj_min,poteni - integer :: ifail,nacc,j,k,n,nk,itype,itypej,itypek,ifail_array(inosink_max),id_rhomax,nneigh_act + integer :: ifail,nacc,j,k,n,nk,itype,itypej,itypek,ifail_array(inosink_max),id_rhomax,nneigh_act,new_nptmass logical :: accreted,iactivej,isgasj,isdustj,calc_exact_epot,ForceCreation ifail = 0 @@ -1515,15 +1561,15 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote ! create new point mass, at position of original particle but with zero mass. Then accrete particles within hacc to form sink ! if (ifail==0) then - nptmass = nptmass + 1 - if (nptmass > maxptmass) call fatal('ptmass_create','nptmass > maxptmass') - n = nptmass - xyzmh_ptmass(:,n) = 0. ! zero all quantities by default - xyzmh_ptmass(1:3,n) = (/xi,yi,zi/) - xyzmh_ptmass(4,n) = 0. ! zero mass - xyzmh_ptmass(ihacc,n) = h_acc - xyzmh_ptmass(ihsoft,n) = h_soft_sinkgas - vxyz_ptmass(:,n) = 0. ! zero velocity, get this by accreting + new_nptmass = nptmass + 1 + if (new_nptmass > maxptmass) call fatal('ptmass_create','nptmass > maxptmass') + xyzmh_ptmass(:,new_nptmass) = 0. ! zero all quantities by default + xyzmh_ptmass(1:3,new_nptmass) = (/xi,yi,zi/) + xyzmh_ptmass(4,new_nptmass) = 0. ! zero mass + xyzmh_ptmass(ihacc,new_nptmass) = h_acc + xyzmh_ptmass(ihsoft,new_nptmass) = h_soft_sinkgas + xyzmh_ptmass(itbirth,new_nptmass) = time + vxyz_ptmass(:,new_nptmass) = 0. ! zero velocity, get this by accreting itypej = igas ! default particle type to be accreted pmassj = massoftype(igas) ! default particle mass to be accreted ! @@ -1541,28 +1587,33 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote fxj = fxyzu(1,j) + fext(1,j) fyj = fxyzu(2,j) + fext(2,j) fzj = fxyzu(3,j) + fext(3,j) - call ptmass_accrete(nptmass,nptmass,xyzh(1,j),xyzh(2,j),xyzh(3,j),xyzh(4,j),& + call ptmass_accrete(new_nptmass,new_nptmass,xyzh(1,j),xyzh(2,j),xyzh(3,j),xyzh(4,j),& vxyzu(1,j),vxyzu(2,j),vxyzu(3,j),fxj,fyj,fzj, & itypej,pmassj,xyzmh_ptmass,vxyz_ptmass,accreted, & - dptmass,time,f_acc_local,ibin_wakei,ibin_wakei) + dptmass,linklist_ptmass,time,f_acc_local,ibin_wakei,ibin_wakei) if (accreted) nacc = nacc + 1 enddo ! perform reduction just for this sink - dptmass(:,nptmass) = reduceall_mpi('+',dptmass(:,nptmass)) + dptmass(:,new_nptmass) = reduceall_mpi('+',dptmass(:,new_nptmass)) nacc = int(reduceall_mpi('+', nacc)) ! update ptmass position, spin, velocity, acceleration, and mass - fxyz_ptmass(1:4,n) = 0.0 - fxyz_ptmass_sinksink(1:4,n) = 0.0 - call update_ptmass(dptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass) + fxyz_ptmass(1:4,new_nptmass) = 0.0 + fxyz_ptmass_sinksink(1:4,new_nptmass) = 0.0 + call update_ptmass(dptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,new_nptmass) if (id==id_rhomax) then - write(iprint,"(a,i3,a,4(es10.3,1x),a,i6,a,es10.3)") ' created ptmass #',nptmass,& - ' at (x,y,z,t)=(',xyzmh_ptmass(1:3,nptmass),time,') by accreting ',nacc,' particles: M=',xyzmh_ptmass(4,nptmass) + write(iprint,"(a,i3,a,4(es10.3,1x),a,i6,a,es10.3)") ' created ptmass #',new_nptmass,& + ' at (x,y,z,t)=(',xyzmh_ptmass(1:3,new_nptmass),time,') by accreting ',nacc,' particles: M=',xyzmh_ptmass(4,new_nptmass) endif if (nacc <= 0) call fatal('ptmass_create',' created ptmass but failed to accrete anything') + nptmass = new_nptmass + ! link the new sink to nothing (waiting for age > tseeds) + if (icreate_sinks == 2) then + linklist_ptmass(nptmass) = 0 + endif ! ! open new file to track new sink particle details & and update all sink-tracking files; ! fxyz_ptmass, fxyz_ptmass_sinksink are total force on sinks and sink-sink forces. @@ -1588,6 +1639,165 @@ subroutine ptmass_create(nptmass,npart,itest,xyzh,vxyzu,fxyzu,fext,divcurlv,pote end subroutine ptmass_create +subroutine ptmass_create_seeds(nptmass,itest,xyzmh_ptmass,linklist_ptmass,time) + use part, only:itbirth,ihacc + use random, only:ran2 + use io, only:iprint + integer, intent(inout) :: nptmass + integer, intent(in) :: itest + integer, intent(inout) :: linklist_ptmass(:) + real, intent(inout) :: xyzmh_ptmass(:,:) + real, intent(in) :: time + integer :: j,nseed,n +! +!-- Draw the number of star seeds in the core +! + nseed = floor(4*ran2(iseed_sf)) + if (nseed > 0) then + n = nptmass + linklist_ptmass(itest) = n + 1 !! link the core to the seeds + do j=1,nseed + n = n + 1 + xyzmh_ptmass(:,n) = 0. + xyzmh_ptmass(4,n) = -1. + xyzmh_ptmass(ihacc,n) = -1. + linklist_ptmass(n) = n + 1 !! link this new seed to the next one + enddo + linklist_ptmass(n) = -1 !! null pointer to end the link list + write(iprint,"(a,i3,a,i3,a,es18.10)") ' Star formation prescription : creation of :',& + nseed+1, ' seeds in sink n° :', itest, " t= ",time + nptmass = n + else + write(iprint,"(a,i3,a,i3,a,es18.10)") ' Star formation prescription : creation of :',& + 1, ' seeds in sink n° :', itest, " t= ",time + linklist_ptmass(itest) = -1 !! null pointer to differentiate mono seed to gas clump + endif + +end subroutine ptmass_create_seeds + +subroutine ptmass_create_stars(nptmass,itest,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,linklist_ptmass,time) + use dim, only:maxptmass + use physcon, only:solarm,pi + use io, only:iprint,iverbose + use units, only:umass + use part, only:itbirth,ihacc,ihsoft,ispinx,ispiny,ispinz + use random , only:ran2,gauss_random,divide_unit_seg + use HIIRegion, only:update_ionrate,iH2R + integer, intent(in) :: nptmass,itest + integer, intent(in) :: linklist_ptmass(:) + real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + real, intent(inout) :: fxyz_ptmass(4,maxptmass),fxyz_ptmass_sinksink(4,maxptmass) + real, intent(in) :: time + real, allocatable :: masses(:) + real :: xi(3),vi(3) + integer :: k,n,l + real :: mi,hacci,minmass,mcutoff + real :: a(8),velk,rk,xk(3),vk(3),xcom(3),vcom(3),rvir + + + write(iprint,"(a,es18.10)") "ptmass_create_stars : new stars formed at : ",time + !! save xcom and vcom before placing stars + xi(1) = xyzmh_ptmass(1,itest) + xi(2) = xyzmh_ptmass(2,itest) + xi(3) = xyzmh_ptmass(3,itest) + mi = xyzmh_ptmass(4,itest) + hacci = xyzmh_ptmass(ihacc,itest) + vi(1) = vxyz_ptmass(1,itest) + vi(2) = vxyz_ptmass(2,itest) + vi(3) = vxyz_ptmass(3,itest) + + !! masses sampling method + call ptmass_endsize_lklist(itest,l,n,linklist_ptmass) + allocate(masses(n)) + minmass = 0.08/(mi*(umass/solarm)) + call divide_unit_seg(masses,minmass,n,iseed_sf) + masses = masses*mi + if (iverbose > 1) write(iprint,*) "Mass sharing : ", masses*umass/solarm + + + k=itest + do while(k>0) + !! Position and velocity sampling methods + a(:) = 0. + rvir = 0.7*h_acc + mcutoff = 0.55 + ! + !-- Positions + ! + a(1) = ran2(iseed_sf)*mcutoff + rk = rvir/sqrt((a(1)**(-2./3.)-1.0)) + a(2) = ran2(iseed_sf) + a(3) = ran2(iseed_sf) + xk(3) = (1.0-2.0*a(2))*rk + xk(2) = sqrt(rk**2-xk(3)**2)*sin(2*pi*a(3)) + xk(1) = sqrt(rk**2-xk(3)**2)*cos(2*pi*a(3)) + ! + !-- Velocities + ! + a(5) = 1. + do while(0.1*a(5)> a(6)) + a(4) = ran2(iseed_sf) + a(5) = ran2(iseed_sf) + a(6) = a(4)**2*(1.0 - a(4)**2)**3.5 + enddo + + velk = a(4)*sqrt(2.0)*(1.0 + rk**2)**(-0.25)*sqrt(2.0*mi/rvir) + a(7) = ran2(iseed_sf) + a(8) = ran2(iseed_sf) + vk(3) = (1.0-2.0*a(7))*velk + vk(2) = sqrt(velk**2-vk(3)**2)*sin(2*pi*a(8)) + vk(1) = sqrt(velk**2-vk(3)**2)*cos(2*pi*a(8)) + ! + !-- Star creation + ! + xyzmh_ptmass(ihacc,k) = hacci*1.e-3 + xyzmh_ptmass(ihsoft,k) = h_soft_sinkgas + xyzmh_ptmass(4,k) = masses(n) + xyzmh_ptmass(3,k) = xk(3) + xyzmh_ptmass(2,k) = xk(2) + xyzmh_ptmass(1,k) = xk(1) + xyzmh_ptmass(ispinx,k) = 0. ! + xyzmh_ptmass(ispiny,k) = 0. ! -- No spin for the instant + xyzmh_ptmass(ispinz,k) = 0. ! + vxyz_ptmass(1,k) = vk(1) + vxyz_ptmass(2,k) = vk(2) + vxyz_ptmass(3,k) = vk(3) + fxyz_ptmass(1:4,k) = 0. + fxyz_ptmass_sinksink(1:4,k) = 0. + if (iH2R > 0) call update_ionrate(k,xyzmh_ptmass,h_acc) + + k = linklist_ptmass(k) ! acces to the next point mass in the linked list + n = n - 1 + enddo + k = itest + do while(k>0) + xcom(1) = xyzmh_ptmass(4,k)*xyzmh_ptmass(1,k) + xcom(2) = xyzmh_ptmass(4,k)*xyzmh_ptmass(2,k) + xcom(3) = xyzmh_ptmass(4,k)*xyzmh_ptmass(3,k) + vcom(1) = xyzmh_ptmass(4,k)*vxyz_ptmass(1,k) + vcom(2) = xyzmh_ptmass(4,k)*vxyz_ptmass(2,k) + vcom(3) = xyzmh_ptmass(4,k)*vxyz_ptmass(3,k) + k = linklist_ptmass(k) ! acces to the next point mass in the linked list + enddo + + xcom = xcom/mi + vcom = vcom/mi + + k = itest + do while(k>0) + xyzmh_ptmass(1,k) = xyzmh_ptmass(1,k) - xcom(1) + xi(1) + xyzmh_ptmass(2,k) = xyzmh_ptmass(2,k) - xcom(2) + xi(2) + xyzmh_ptmass(3,k) = xyzmh_ptmass(3,k) - xcom(3) + xi(3) + vxyz_ptmass(1,k) = vxyz_ptmass(1,k) - vcom(1) + vi(1) + vxyz_ptmass(2,k) = vxyz_ptmass(2,k) - vcom(2) + vi(2) + vxyz_ptmass(3,k) = vxyz_ptmass(3,k) - vcom(3) + vi(3) + k = linklist_ptmass(k) ! acces to the next point mass in the linked list + enddo + + deallocate(masses) + +end subroutine ptmass_create_stars + !----------------------------------------------------------------------- !+ ! Merge sinks @@ -1611,15 +1821,17 @@ end subroutine ptmass_create ! negative mass. !+ !----------------------------------------------------------------------- -subroutine merge_sinks(time,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) +subroutine merge_sinks(time,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,linklist_ptmass,merge_ij) use io, only:iprint,warning,iverbose,id,master + use part, only:itbirth real, intent(in) :: time integer, intent(in) :: nptmass,merge_ij(nptmass) + integer, intent(inout) :: linklist_ptmass(nptmass) real, intent(inout) :: xyzmh_ptmass(nsinkproperties,nptmass) real, intent(inout) :: vxyz_ptmass(3,nptmass),fxyz_ptmass(4,nptmass) - integer :: i,j + integer :: i,j,k,l,n real :: rr2,xi,yi,zi,mi,vxi,vyi,vzi,xj,yj,zj,mj,vxj,vyj,vzj,Epot,Ekin - real :: mij,mij1 + real :: mij,mij1,tbirthi,tbirthj logical :: lmerge character(len=15) :: typ @@ -1628,17 +1840,25 @@ subroutine merge_sinks(time,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_i j = merge_ij(i) if (merge_ij(j) == i .and. xyzmh_ptmass(4,j) > 0.) then lmerge = .false. - xi = xyzmh_ptmass(1,i) - yi = xyzmh_ptmass(2,i) - zi = xyzmh_ptmass(3,i) - mi = xyzmh_ptmass(4,i) + tbirthi = xyzmh_ptmass(itbirth,i) + tbirthj = xyzmh_ptmass(itbirth,j) + if (tbirthj 0. .or. l_crit_override) then call write_inopt(f_crit_override,'f_crit_override' ,'unconditional sink formation if rho > f_crit_override*rho_crit',& iunit) @@ -1969,6 +2221,10 @@ subroutine write_options_ptmass(iunit) call write_inopt(f_acc,'f_acc','particles < f_acc*h_acc accreted without checks',iunit) call write_inopt(r_merge_uncond,'r_merge_uncond','sinks will unconditionally merge within this separation',iunit) call write_inopt(r_merge_cond,'r_merge_cond','sinks will merge if bound within this radius',iunit) + if (use_regnbody) then + call write_inopt(use_regnbody, 'use_regnbody', 'allow subgroup integration method', iunit) + call write_inopt(r_neigh, 'r_neigh', 'searching radius to detect subgroups', iunit) + endif end subroutine write_options_ptmass @@ -1979,6 +2235,8 @@ end subroutine write_options_ptmass !----------------------------------------------------------------------- subroutine read_options_ptmass(name,valstring,imatch,igotall,ierr) use io, only:warning,fatal + use subgroup, only:r_neigh + use dim, only:store_ll_ptmass character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotall integer, intent(out) :: ierr @@ -2018,7 +2276,7 @@ subroutine read_options_ptmass(name,valstring,imatch,igotall,ierr) case('f_crit_override') read(valstring,*,iostat=ierr) f_crit_override if (f_crit_override < 0.) f_crit_override = 0. ! reset to zero since a negative value does not make sense - if (f_crit_override > 0. .and. f_crit_override < 100. ) call fatal(label,'Give star formation a chance! Reset to > 100') + if (f_crit_override > 0. .and. f_crit_override < 10. ) call fatal(label,'Give star formation a chance! Reset to > 10') l_crit_override = .true. case('h_soft') ! to ensure backwards compatibility read(valstring,*,iostat=ierr) h_soft @@ -2046,10 +2304,25 @@ subroutine read_options_ptmass(name,valstring,imatch,igotall,ierr) read(valstring,*,iostat=ierr) r_merge_cond if (r_merge_cond > 0. .and. r_merge_cond < r_merge_uncond) call fatal(label,'0 < r_merge_cond < r_merge_uncond') ngot = ngot + 1 + case('tmax_acc') + read(valstring,*,iostat=ierr) tmax_acc + ngot = ngot + 1 + case('tseeds') + read(valstring,*,iostat=ierr) tseeds + ngot = ngot + 1 + case('iseed_sf') + read(valstring,*,iostat=ierr) iseed_sf + ngot = ngot + 1 + case('use_regnbody') + read(valstring,*,iostat=ierr) use_regnbody + case('r_neigh') + read(valstring,*,iostat=ierr) r_neigh case default imatch = .false. end select + if (icreate_sinks ==2) store_ll_ptmass = .true. + !--make sure we have got all compulsory options (otherwise, rewrite input file) if (icreate_sinks > 0) then igotall = (ngot >= 8) diff --git a/src/main/random.f90 b/src/main/random.f90 index e77444401..b5fc3bd88 100644 --- a/src/main/random.f90 +++ b/src/main/random.f90 @@ -15,11 +15,11 @@ module random ! ! :Runtime parameters: None ! -! :Dependencies: None +! :Dependencies: sortutils ! implicit none public :: ran2,get_random,rayleigh_deviate - public :: get_random_pos_on_sphere,gauss_random + public :: get_random_pos_on_sphere,gauss_random,divide_unit_seg real, parameter :: pi = 4.*atan(1.) private @@ -167,4 +167,55 @@ real function gauss_random(iseed) end function gauss_random + +subroutine divide_unit_seg(lengths,mindist,nlengths,iseed) + use sortutils, only:indexx + integer, intent(in) :: nlengths + integer, intent(inout) :: iseed + real, intent(inout) :: lengths(nlengths) + real, intent(inout) :: mindist + real, allocatable :: points(:) + integer, allocatable :: idx(:) + integer :: i,j,np + logical :: close + real :: tmp,dist + + np = nlengths+1 + + allocate(points(np)) + allocate(idx(np)) + points(np) = 1. + points(1) = 0. + tmp = 0. + + if (mindist >= 0.1) then ! override the minimum distance if we are in a bricked situation... + mindist = 0.01 ! we'll have stars less massive than 0.08 solarmasses but it will assure to never brick the sim... + endif + + + do i=2,nlengths + close = .true. + do while (close) + tmp = ran2(iseed) + dist = tmp + do j=2,i-1 + dist = min(abs(points(j)-tmp),dist) + enddo + dist = min(abs(points(np)-tmp),dist) + close = dist 0) print "(1x,58('-'),/,1x,a,'|',5(a9,1x,'|'),/,1x,58('-'))",& diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index 40a8bf319..5d589eef2 100644 --- a/src/main/readwrite_dumps_fortran.f90 +++ b/src/main/readwrite_dumps_fortran.f90 @@ -19,7 +19,7 @@ module readwrite_dumps_fortran ! :Runtime parameters: None ! ! :Dependencies: boundary_dyn, dim, dump_utils, eos, io, memory, -! metric_tools, mpiutils, options, part, readwrite_dumps_common, +! metric_tools, mpiutils, options, part, ptmass, readwrite_dumps_common, ! sphNGutils, timestep ! use dump_utils, only:lenid,ndatatypes,i_int,i_int1,i_int2,i_int4,i_int8,& @@ -48,13 +48,14 @@ module readwrite_dumps_fortran subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) use dim, only:maxp,maxvxyzu,maxalpha,ndivcurlv,ndivcurlB,maxgrav,gravity,use_dust,& lightcurve,use_dustgrowth,store_dust_temperature,gr,do_nucleation,& - ind_timesteps,mhd_nonideal,use_krome,h2chemistry,update_muGamma,mpi + ind_timesteps,mhd_nonideal,use_krome,h2chemistry,update_muGamma,mpi,& + store_ll_ptmass use eos, only:ieos,eos_is_non_ideal,eos_outputs_mu,eos_outputs_gasP use io, only:idump,iprint,real4,id,master,error,warning,nprocs use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,Bevol,Bevol_label,Bxyz,Bxyz_label,npart,maxtypes, & npartoftypetot,update_npartoftypetot, & alphaind,rhoh,divBsymm,maxphase,iphase,iamtype_int1,iamtype_int11, & - nptmass,nsinkproperties,xyzmh_ptmass,xyzmh_ptmass_label,vxyz_ptmass,vxyz_ptmass_label,& + nptmass,nsinkproperties,xyzmh_ptmass,xyzmh_ptmass_label,vxyz_ptmass,vxyz_ptmass_label, linklist_ptmass, & maxptmass,get_pmass,nabundances,abundance,abundance_label,mhd,& divcurlv,divcurlv_label,divcurlB,divcurlB_label,poten,dustfrac,deltav,deltav_label,tstop,& dustfrac_label,tstop_label,dustprop,dustprop_label,eos_vars,eos_vars_label,ndusttypes,ndustsmall,VrelVf,& @@ -312,6 +313,9 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) ilen(2) = int(nptmass,kind=8) call write_array(2,xyzmh_ptmass,xyzmh_ptmass_label,nsinkproperties,nptmass,k,ipass,idump,nums,nerr) call write_array(2,vxyz_ptmass,vxyz_ptmass_label,3,nptmass,k,ipass,idump,nums,nerr) + if (store_ll_ptmass) then + call write_array(2,linklist_ptmass,"linklist_ptmass",nptmass,k,ipass,idump,nums,nerr) + endif if (nerr > 0) call error('write_dump','error writing sink particle arrays') endif enddo @@ -977,9 +981,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto use dump_utils, only:read_array,match_tag use dim, only:use_dust,h2chemistry,maxalpha,maxp,gravity,maxgrav,maxvxyzu,do_nucleation, & use_dustgrowth,maxdusttypes,ndivcurlv,maxphase,gr,store_dust_temperature,& - ind_timesteps,use_krome + ind_timesteps,use_krome,store_ll_ptmass use part, only:xyzh,xyzh_label,vxyzu,vxyzu_label,dustfrac,dustfrac_label,abundance,abundance_label, & - alphaind,poten,xyzmh_ptmass,xyzmh_ptmass_label,vxyz_ptmass,vxyz_ptmass_label, & + alphaind,poten,xyzmh_ptmass,xyzmh_ptmass_label,vxyz_ptmass,vxyz_ptmass_label,linklist_ptmass, & Bevol,Bxyz,Bxyz_label,nabundances,iphase,idust, & eos_vars,eos_vars_label,maxeosvars,dustprop,dustprop_label,divcurlv,divcurlv_label,iX,iZ,imu, & VrelVf,VrelVf_label,dustgasprop,dustgasprop_label,filfac,filfac_label,pxyzu,pxyzu_label,dust_temp, & @@ -997,7 +1001,7 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto logical :: match logical :: got_dustfrac(maxdusttypes) logical :: got_iphase,got_xyzh(4),got_vxyzu(4),got_abund(nabundances),got_alpha(1),got_poten - logical :: got_sink_data(nsinkproperties),got_sink_vels(3),got_Bxyz(3) + logical :: got_sink_data(nsinkproperties),got_sink_vels(3),got_sink_llist,got_Bxyz(3) logical :: got_krome_mols(krome_nmols),got_krome_T,got_krome_gamma,got_krome_mu logical :: got_eosvars(maxeosvars),got_nucleation(n_nucleation),got_ray_tracer logical :: got_psi,got_Tdust,got_dustprop(2),got_VrelVf,got_dustgasprop(4) @@ -1018,6 +1022,7 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto got_poten = .false. got_sink_data = .false. got_sink_vels = .false. + got_sink_llist = .false. got_Bxyz = .false. got_psi = .false. got_eosvars = .false. @@ -1123,6 +1128,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto case(2) call read_array(xyzmh_ptmass,xyzmh_ptmass_label,got_sink_data,ik,1,nptmass,0,idisk1,tag,match,ierr) call read_array(vxyz_ptmass, vxyz_ptmass_label, got_sink_vels,ik,1,nptmass,0,idisk1,tag,match,ierr) + if (store_ll_ptmass) then + call read_array(linklist_ptmass,'linklist_ptmass',got_sink_llist,ik,1,nptmass,0,idisk1,tag,match,ierr) + endif end select select case(iarr) ! MHD arrays can either be in block 1 or block 4 case(1,4) @@ -1144,8 +1152,9 @@ subroutine read_phantom_arrays(i1,i2,noffset,narraylengths,nums,npartread,nparto call check_arrays(i1,i2,noffset,npartoftype,npartread,nptmass,nsinkproperties,massoftype,& alphafile,tfile,phantomdump,got_iphase,got_xyzh,got_vxyzu,got_alpha, & got_krome_mols,got_krome_gamma,got_krome_mu,got_krome_T, & - got_abund,got_dustfrac,got_sink_data,got_sink_vels,got_Bxyz,got_psi,got_dustprop,got_pxyzu,got_VrelVf, & - got_dustgasprop,got_rad,got_radprop,got_Tdust,got_eosvars,got_nucleation,got_iorig,iphase,& + got_abund,got_dustfrac,got_sink_data,got_sink_vels,got_sink_llist,got_Bxyz, & + got_psi,got_dustprop,got_pxyzu,got_VrelVf,got_dustgasprop,got_rad, & + got_radprop,got_Tdust,got_eosvars,got_nucleation,got_iorig,iphase, & xyzh,vxyzu,pxyzu,alphaind,xyzmh_ptmass,Bevol,iorig,iprint,ierr) if (.not. phantomdump) then print *, "Calling set_gas_particle_mass" diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index a116046ef..35bfa31ae 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -123,6 +123,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) use dim, only:maxvxyzu,maxptmass,gravity,sink_radiation,gr,nalpha use part, only:maxp,mhd,maxalpha,nptmass use boundary_dyn, only:write_options_boundary + use HIIRegion, only:write_options_H2R character(len=*), intent(in) :: infile,logfile,evfile,dumpfile integer, intent(in) :: iwritein,iprint integer :: ierr @@ -304,7 +305,8 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) if (gr) call write_options_metric(iwritein) call write_options_gravitationalwaves(iwritein) call write_options_boundary(iwritein) - + call write_options_H2R(iwritein) + if (iwritein /= iprint) close(unit=iwritein) if (iwritein /= iprint) write(iprint,"(/,a)") ' input file '//trim(infile)//' written successfully.' @@ -347,6 +349,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) use damping, only:read_options_damping use gravwaveutils, only:read_options_gravitationalwaves use boundary_dyn, only:read_options_boundary + use HIIRegion, only:read_options_H2R character(len=*), parameter :: label = 'read_infile' character(len=*), intent(in) :: infile character(len=*), intent(out) :: logfile,evfile,dumpfile @@ -359,7 +362,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) logical :: imatch,igotallrequired,igotallturb,igotalllink,igotloops logical :: igotallbowen,igotallcooling,igotalldust,igotallextern,igotallinject,igotallgrowth,igotallporosity logical :: igotallionise,igotallnonideal,igotalleos,igotallptmass,igotalldamping - logical :: igotallprad,igotalldustform,igotallgw,igotallgr,igotallbdy + logical :: igotallprad,igotalldustform,igotallgw,igotallgr,igotallbdy,igotallH2R integer, parameter :: nrequired = 1 ireaderr = 0 @@ -391,6 +394,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) igotallgw = .true. igotallgr = .true. igotallbdy = .true. + igotallH2R = .true. use_Voronoi_limits_file = .false. open(unit=ireadin,err=999,file=infile,status='old',form='formatted') @@ -570,6 +574,7 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) endif if (.not.imatch) call read_options_gravitationalwaves(name,valstring,imatch,igotallgw,ierr) if (.not.imatch) call read_options_boundary(name,valstring,imatch,igotallbdy,ierr) + if (.not.imatch) call read_options_H2R(name,valstring,imatch,igotallH2R,ierr) if (len_trim(name) /= 0 .and. .not.imatch) then call warn('read_infile','unknown variable '//trim(adjustl(name))// & ' in input file, value = '//trim(adjustl(valstring))) @@ -687,8 +692,9 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (beta > 4.) call warn(label,'very high beta viscosity set') #ifndef MCFOST if (maxvxyzu >= 4 .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /= 4 .and. ieos /= 10 .and. & - ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 17 .and. ieos /= 20 .and. ieos/=21)) & - call fatal(label,'only ieos=2 makes sense if storing thermal energy') + ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 17 .and. & + ieos /= 20 .and. ieos/=21 .and. ieos/=22)) & + call fatal(label,'only ieos=2 makes sense if storing thermal energy') #endif if (irealvisc < 0 .or. irealvisc > 12) call fatal(label,'invalid setting for physical viscosity') if (shearparam < 0.) call fatal(label,'stupid value for shear parameter (< 0)') diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 3ab5e8362..a18c9f972 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -98,13 +98,13 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) iamboundary,get_ntypes,npartoftypetot,& dustfrac,dustevol,ddustevol,eos_vars,alphaind,nptmass,& dustprop,ddustprop,dustproppred,pxyzu,dens,metrics,ics,& - filfac,filfacpred,mprev,filfacprev + filfac,filfacpred,mprev,filfacprev,isionised use options, only:avdecayconst,alpha,ieos,alphamax use deriv, only:derivs use timestep, only:dterr,bignumber,tolv use mpiutils, only:reduceall_mpi use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass, & - dsdt_ptmass,fsink_old,ibin_wake,dptmass + dsdt_ptmass,fsink_old,ibin_wake,dptmass,linklist_ptmass use part, only:n_group,n_ingroup,n_sing,gtgrad,group_info,nmatrix use io_summary, only:summary_printout,summary_variable,iosumtvi,iowake, & iosumflrp,iosumflrps,iosumflrc @@ -118,7 +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 timing, only:increment_timer,get_timings,itimer_extf + use timing, only:increment_timer,get_timings,itimer_substep use growth, only:check_dustprop use options, only:use_porosity,icooling use porosity, only:get_filfac @@ -253,14 +253,14 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) 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,fsink_old,nbinmax,ibin_wake,gtgrad,group_info, & - nmatrix,n_group,n_ingroup,n_sing) + dptmass,linklist_ptmass,fsink_old,nbinmax,ibin_wake,gtgrad,group_info, & + nmatrix,n_group,n_ingroup,n_sing,isionised) else call substep_sph(dtsph,npart,xyzh,vxyzu) endif endif call get_timings(t2,tcpu2) - call increment_timer(itimer_extf,t2-t1,tcpu2-tcpu1) + call increment_timer(itimer_substep,t2-t1,tcpu2-tcpu1) timei = timei + dtsph nvfloorps = 0 diff --git a/src/main/subgroup.f90 b/src/main/subgroup.f90 index a754e8d61..1e6e52e28 100644 --- a/src/main/subgroup.f90 +++ b/src/main/subgroup.f90 @@ -15,48 +15,85 @@ module subgroup ! ! :Runtime parameters: None ! -! :Dependencies: io, mpiutils, part, utils_kepler, utils_subgroup +! :Dependencies: io, mpiutils, part, physcon, timing, units, utils_kepler, +! utils_subgroup ! use utils_subgroup implicit none public :: group_identify public :: evolve_groups public :: get_pot_subsys - ! parameters for group identification - real, parameter :: eta_pert = 20 + public :: init_subgroup + ! + !-- parameters for group identification + ! real, parameter :: time_error = 2.5e-14 - real, parameter :: max_step = 100000000 - real, parameter, public :: r_neigh = 0.001 - real, public :: t_crit = 1.e-9 - real, public :: C_bin = 0.02 - real, public :: r_search = 100.*r_neigh + real, parameter :: max_step = 1000000 + real, parameter :: C_bin = 0.02 + real, public :: r_neigh = 0.001 ! default value assume udist = 1 pc + real :: r_search private contains +!----------------------------------------------- +! +! Initialisation routine +! +!----------------------------------------------- +subroutine init_subgroup + use units, only:udist + use physcon, only:pc + + r_neigh = r_neigh*(pc/udist) + r_search = 100.*r_neigh + +end subroutine init_subgroup !----------------------------------------------- ! ! Group identification routines ! !----------------------------------------------- -subroutine group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix) - use io ,only:id,master,iverbose,iprint - integer, intent(in) :: nptmass - real, intent(in) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) - integer, intent(inout) :: group_info(3,nptmass) +subroutine group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix,dtext) + use io, only:id,master,iverbose,iprint + use timing, only:get_timings,increment_timer,itimer_sg_id + integer, intent(in) :: nptmass + real, intent(in) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:) + integer, intent(inout) :: group_info(3,nptmass) + integer, intent(inout) :: n_group,n_ingroup,n_sing integer(kind=1), intent(inout) :: nmatrix(nptmass,nptmass) - integer, intent(inout) :: n_group,n_ingroup,n_sing + real, optional, intent(in) :: dtext + real(kind=4) :: t1,t2,tcpu1,tcpu2 + logical :: large_search + + + large_search = present(dtext) n_group = 0 n_ingroup = 0 n_sing = 0 + if (nptmass > 0) then + + call get_timings(t1,tcpu1) + + if (large_search) then + call matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass,dtext) + else + call matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass) + endif + call form_group(group_info,nmatrix,nptmass,n_group,n_ingroup,n_sing) + + call get_timings(t2,tcpu2) + call increment_timer(itimer_sg_id,t2-t1,tcpu2-tcpu1) - call matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass) - call form_group(group_info,nmatrix,nptmass,n_group,n_ingroup,n_sing) + endif if (id==master .and. iverbose>1) then write(iprint,"(i6,a,i6,a,i6,a)") n_group," groups identified, ",n_ingroup," in a group, ",n_sing," singles..." endif + + + end subroutine group_identify @@ -124,22 +161,28 @@ subroutine dfs(iroot,visited,group_info,nmatrix,nptmass,n_ingroup,ncg) end subroutine dfs -subroutine matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass) +subroutine matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass,dtext) use utils_kepler, only: Espec,extract_a,extract_e,extract_ea - integer, intent(in) :: nptmass + integer, intent(in) :: nptmass + real, intent(in) :: xyzmh_ptmass(:,:) + real, intent(in) :: vxyz_ptmass(:,:) integer(kind=1), intent(out):: nmatrix(nptmass,nptmass) - real, intent(in) :: xyzmh_ptmass(:,:) - real, intent(in) :: vxyz_ptmass(:,:) + real, optional, intent(in) :: dtext real :: xi,yi,zi,vxi,vyi,vzi,mi real :: dx,dy,dz,dvx,dvy,dvz,r2,r,v2,mu - real :: aij,eij,B,rperi + real :: aij,eij,B,rperi,dtexti integer :: i,j + if (present(dtext)) then + dtexti = dtext + else + dtexti = 0. + endif ! !!TODO MPI Proof version of the matrix construction ! !$omp parallel do default(none) & - !$omp shared(nptmass,C_bin,t_crit,nmatrix) & + !$omp shared(nptmass,dtexti,nmatrix,r_neigh) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,r_search) & !$omp private(xi,yi,zi,mi,vxi,vyi,vzi,i,j) & !$omp private(dx,dy,dz,r,r2) & @@ -153,6 +196,7 @@ subroutine matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass) vxi = vxyz_ptmass(1,i) vyi = vxyz_ptmass(2,i) vzi = vxyz_ptmass(3,i) + if (mi < 0 ) cycle do j=1,nptmass if (i==j) cycle dx = xi - xyzmh_ptmass(1,j) @@ -181,7 +225,7 @@ subroutine matrix_construction(xyzmh_ptmass,vxyz_ptmass,nmatrix,nptmass) else call extract_e(dx,dy,dz,dvx,dvy,dvz,mu,r,eij) rperi = aij*(1-eij) - if (rperi0) then + + call get_timings(t1,tcpu1) + if (id==master) then !$omp parallel do default(none)& !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass)& @@ -219,12 +271,17 @@ subroutine evolve_groups(n_group,nptmass,time,tnext,group_info,xyzmh_ptmass,vxyz enddo !$omp end parallel do endif + + call get_timings(t2,tcpu2) + call increment_timer(itimer_sg_evol,t2-t1,tcpu2-tcpu1) + endif call bcast_mpi(xyzmh_ptmass(:,1:nptmass)) call bcast_mpi(vxyz_ptmass(:,1:nptmass)) + end subroutine evolve_groups subroutine integrate_to_time(start_id,end_id,gsize,time,tnext,xyzmh_ptmass,vxyz_ptmass,group_info,fxyz_ptmass,gtgrad) @@ -296,7 +353,7 @@ subroutine integrate_to_time(start_id,end_id,gsize,time,tnext,xyzmh_ptmass,vxyz_ if (step_count_int > max_step) then print*,"MAX STEP NUMBER, ABORT !!!" - call abort + call abort() endif if ((.not.t_end_flag).and.(dt<0.)) then @@ -582,7 +639,7 @@ subroutine get_force_TTL(xyzmh_ptmass,group_info,fxyz_ptmass,gtgrad,om,s_id,e_id integer :: i,j,k,l logical :: init om = 0. - dt_init = 0. + dt_init = huge(om) if (present(ds_init)) then @@ -647,7 +704,7 @@ subroutine get_force_TTL(xyzmh_ptmass,group_info,fxyz_ptmass,gtgrad,om,s_id,e_id enddo om = om*0.5 - if (init) ds_init = dt_init/om + if (init) ds_init = dt_init*om end subroutine get_force_TTL diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index 1040fe6fd..6c0d39274 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -37,6 +37,7 @@ module substepping public :: substep_sph public :: substep_sph_gr public :: substep + public :: get_force private @@ -426,8 +427,8 @@ end subroutine substep_sph !---------------------------------------------------------------- subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dptmass, & - fsink_old,nbinmax,ibin_wake,gtgrad,group_info,nmatrix, & - n_group,n_ingroup,n_sing) + linklist_ptmass,fsink_old,nbinmax,ibin_wake,gtgrad,group_info, & + nmatrix,n_group,n_ingroup,n_sing,isionised) use io, only:iverbose,id,master,iprint,fatal use options, only:iexternalforce use part, only:fxyz_ptmass_sinksink,ndptmass @@ -444,7 +445,9 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) real, intent(inout) :: dptmass(ndptmass,nptmass),fsink_old(:,:),gtgrad(:,:) integer(kind=1), intent(in) :: nbinmax + integer , intent(inout) :: linklist_ptmass(:) integer(kind=1), intent(inout) :: ibin_wake(:),nmatrix(nptmass,nptmass) + logical, intent(in) :: isionised(:) logical :: extf_vdep_flag,done,last_step,accreted integer :: force_count,nsubsteps real :: timei,time_par,dt,t_end_step @@ -481,7 +484,8 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & ! ! Main integration scheme ! - call kick(dk(1),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass,dptmass) + call kick(dk(1),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, & + fext,fxyz_ptmass,dsdt_ptmass,dptmass,linklist_ptmass) if (use_regnbody) then call evolve_groups(n_group,nptmass,time_par,time_par+ck(1)*dt,group_info,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,gtgrad) @@ -489,12 +493,12 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & call drift(ck(1),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass,n_ingroup,group_info) call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,group_info=group_info) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,linklist_ptmass,group_info=group_info) else call drift(ck(1),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,linklist_ptmass,isionised=isionised) endif if (use_fourthorder) then !! FSI 4th order scheme @@ -502,46 +506,55 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & ! FSI extrapolation method (Omelyan 2006) if (use_regnbody) then call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,fsink_old,group_info) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,linklist_ptmass, & + fsink_old,group_info) - call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass,dptmass) + call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& + fext,fxyz_ptmass,dsdt_ptmass,dptmass,linklist_ptmass) call evolve_groups(n_group,nptmass,time_par,time_par+ck(2)*dt,group_info,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,gtgrad) call drift(ck(2),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass,n_ingroup,group_info) call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,group_info=group_info) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,linklist_ptmass, & + group_info=group_info,isionised=isionised) else call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,fsink_old) - call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext,fxyz_ptmass,dsdt_ptmass,dptmass) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,linklist_ptmass,& + fsink_old) + call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,& + fext,fxyz_ptmass,dsdt_ptmass,dptmass,linklist_ptmass) call drift(ck(2),dt,time_par,npart,nptmass,ntypes,xyzh,xyzmh_ptmass,vxyzu,vxyz_ptmass) call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,linklist_ptmass,& + isionised=isionised) ! the last kick phase of the scheme will perform the accretion loop after velocity update endif call kick(dk(3),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext, & - fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) + fxyz_ptmass,dsdt_ptmass,dptmass,linklist_ptmass,ibin_wake,nbinmax,timei, & + fxyz_ptmass_sinksink,accreted) if (use_regnbody) then call group_identify(nptmass,n_group,n_ingroup,n_sing,xyzmh_ptmass,vxyz_ptmass,group_info,nmatrix) call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,group_info=group_info) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,linklist_ptmass, & + group_info=group_info) elseif (accreted) then call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(3),force_count,extf_vdep_flag,linklist_ptmass) endif else !! standard leapfrog scheme ! the last kick phase of the scheme will perform the accretion loop after velocity update call kick(dk(2),dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass,fext, & - fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) + fxyz_ptmass,dsdt_ptmass,dptmass,linklist_ptmass,ibin_wake,nbinmax,timei, & + fxyz_ptmass_sinksink,accreted) if (accreted) then call get_force(nptmass,npart,nsubsteps,ntypes,time_par,dtextforce,xyzh,vxyzu,fext,xyzmh_ptmass, & - vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag) + vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dk(2),force_count,extf_vdep_flag,linklist_ptmass) endif endif @@ -629,7 +642,8 @@ end subroutine drift !---------------------------------------------------------------- subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, & - fext,fxyz_ptmass,dsdt_ptmass,dptmass,ibin_wake,nbinmax,timei,fxyz_ptmass_sinksink,accreted) + fext,fxyz_ptmass,dsdt_ptmass,dptmass,linklist_ptmass,ibin_wake, & + nbinmax,timei,fxyz_ptmass_sinksink,accreted) use part, only:isdead_or_accreted,massoftype,iamtype,iamboundary,iphase,ispinx,ispiny,ispinz,igas,ndptmass use ptmass, only:f_acc,ptmass_accrete,pt_write_sinkev,update_ptmass,ptmass_kick use externalforces, only:accrete_particles @@ -645,6 +659,7 @@ subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, real, intent(inout) :: vxyzu(:,:),fext(:,:) real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(:,:),dsdt_ptmass(:,:) real, intent(inout) :: dptmass(ndptmass,nptmass) + integer, intent(in) :: linklist_ptmass(:) real, optional, intent(inout) :: fxyz_ptmass_sinksink(:,:) real, optional, intent(in) :: timei integer(kind=1), optional, intent(inout) :: ibin_wake(:) @@ -711,7 +726,7 @@ subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, !$omp parallel do default(none) & !$omp shared(maxp,maxphase) & !$omp shared(npart,xyzh,vxyzu,fext,dkdt,iphase,ntypes,massoftype,timei,nptmass,sts_it_n) & - !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,f_acc) & + !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,linklist_ptmass,f_acc) & !$omp shared(iexternalforce) & !$omp shared(nbinmax,ibin_wake) & !$omp private(i,accreted,nfaili,fxi,fyi,fzi) & @@ -750,12 +765,15 @@ subroutine kick(dki,dt,npart,nptmass,ntypes,xyzh,vxyzu,xyzmh_ptmass,vxyz_ptmass, fxi = fext(1,i) fyi = fext(2,i) fzi = fext(3,i) - if (ind_timesteps) ibin_wakei = ibin_wake(i) + if (ind_timesteps) then + ibin_wakei = ibin_wake(i) + itype = iphase(i) + endif call ptmass_accrete(1,nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& vxyzu(1,i),vxyzu(2,i),vxyzu(3,i),fxi,fyi,fzi,& - itype,pmassi,xyzmh_ptmass,vxyz_ptmass,& - accreted,dptmass,timei,f_acc,nbinmax,ibin_wakei,nfaili) + itype,pmassi,xyzmh_ptmass,vxyz_ptmass,accreted, & + dptmass,linklist_ptmass,timei,f_acc,nbinmax,ibin_wakei,nfaili) if (accreted) then naccreted = naccreted + 1 cycle accreteloop @@ -817,7 +835,8 @@ end subroutine kick !---------------------------------------------------------------- subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, & fext,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,dsdt_ptmass,dt,dki, & - force_count,extf_vdep_flag,fsink_old,group_info) + force_count,extf_vdep_flag,linklist_ptmass,fsink_old,group_info,& + isionised) use io, only:iverbose,master,id,iprint,warning,fatal use dim, only:maxp,maxvxyzu,itau_alloc use ptmass, only:get_accel_sink_gas,get_accel_sink_sink,merge_sinks, & @@ -835,6 +854,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, use ptmass_radiation,only:get_rad_accel_from_ptmass,isink_radiation integer, intent(in) :: nptmass,npart,nsubsteps,ntypes integer, intent(inout) :: force_count + integer, intent(inout) :: linklist_ptmass(:) real, intent(inout) :: xyzh(:,:),vxyzu(:,:),fext(:,:) real, intent(inout) :: xyzmh_ptmass(:,:),vxyz_ptmass(:,:),fxyz_ptmass(4,nptmass),dsdt_ptmass(3,nptmass) real, intent(inout) :: dtextforce @@ -842,6 +862,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, logical, intent(in) :: extf_vdep_flag real, optional, intent(inout) :: fsink_old(4,nptmass) integer, optional, intent(in) :: group_info(:,:) + logical, optional, intent(in) :: isionised(:) integer :: merge_ij(nptmass) integer :: merge_n integer :: i,itype @@ -893,7 +914,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass, & extrapfac,fsink_old,group_info) if (merge_n > 0) then - call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,linklist_ptmass,merge_ij) call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass, & extrapfac,fsink_old,group_info) @@ -903,7 +924,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, dtf,iexternalforce,timei,merge_ij,merge_n, & dsdt_ptmass,extrapfac,fsink_old) if (merge_n > 0) then - call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,linklist_ptmass,merge_ij) call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n, & dsdt_ptmass,extrapfac,fsink_old) @@ -914,29 +935,29 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass,group_info=group_info) if (merge_n > 0) then - call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,linklist_ptmass,merge_ij) call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass,group_info=group_info) - fxyz_ptmass_sinksink=fxyz_ptmass - dsdt_ptmass_sinksink=dsdt_ptmass if (iverbose >= 2) write(iprint,*) 'dt(sink-sink) = ',C_force*dtf endif + fxyz_ptmass_sinksink(:,1:nptmass) = fxyz_ptmass (:,1:nptmass) + dsdt_ptmass_sinksink(:,1:nptmass) = dsdt_ptmass (:,1:nptmass) else call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) if (merge_n > 0) then - call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,merge_ij) + call merge_sinks(timei,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,linklist_ptmass,merge_ij) call get_accel_sink_sink(nptmass,xyzmh_ptmass,fxyz_ptmass,epot_sinksink,& dtf,iexternalforce,timei,merge_ij,merge_n,dsdt_ptmass) - fxyz_ptmass_sinksink=fxyz_ptmass - dsdt_ptmass_sinksink=dsdt_ptmass if (iverbose >= 2) write(iprint,*) 'dt(sink-sink) = ',C_force*dtf endif + fxyz_ptmass_sinksink(:,1:nptmass) = fxyz_ptmass (:,1:nptmass) + dsdt_ptmass_sinksink(:,1:nptmass) = dsdt_ptmass (:,1:nptmass) endif endif else - fxyz_ptmass(:,:) = 0. - dsdt_ptmass(:,:) = 0. + fxyz_ptmass(:,1:nptmass) = 0. + dsdt_ptmass(:,1:nptmass) = 0. endif call bcast_mpi(epot_sinksink) call bcast_mpi(dtf) @@ -954,7 +975,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, !$omp shared(dkdt,dt,timei,iexternalforce,extf_vdep_flag,last) & !$omp shared(divcurlv,dphotflag,dphot0,nucleation,extrap) & !$omp shared(abundc,abundo,abundsi,abunde,extrapfac,fsink_old) & - !$omp shared(isink_radiation,itau_alloc,tau) & + !$omp shared(isink_radiation,itau_alloc,tau,isionised) & !$omp private(fextx,fexty,fextz,xi,yi,zi) & !$omp private(i,fonrmaxi,dtphi2i,phii,dtf) & !$omp firstprivate(pmassi,itype) & @@ -1037,7 +1058,7 @@ subroutine get_force(nptmass,npart,nsubsteps,ntypes,timei,dtextforce,xyzh,vxyzu, ! if (maxvxyzu >= 4 .and. itype==igas .and. last) then call cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucleation,dust_temp, & - divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0) + divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0,isionised(i)) endif endif enddo @@ -1079,7 +1100,7 @@ end subroutine get_force !+ !------------------------------------------------------------------------------------ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucleation,dust_temp, & - divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0) + divcurlv,abundc,abunde,abundo,abundsi,dt,dphot0,isionisedi) use dim, only:h2chemistry,do_nucleation,use_krome,update_muGamma,store_dust_temperature use part, only:idK2,idmu,idkappa,idgamma,imu,igamma,nabundances use cooling_ism, only:nabn,dphotflag @@ -1100,6 +1121,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl real, intent(inout) :: abundc,abunde,abundo,abundsi real(kind=8), intent(in) :: dphot0 real, intent(in) :: dt,pmassi + logical, intent(in) :: isionisedi integer, intent(in) :: i real :: dudtcool,rhoi,dphot,pH,pH_tot @@ -1136,7 +1158,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl ! ! COOLING ! - if (icooling > 0 .and. cooling_in_step .and. icooling /= 9) then + if (icooling > 0 .and. cooling_in_step) then if (h2chemistry) then ! ! Call cooling routine, requiring total density, some distance measure and @@ -1155,6 +1177,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) 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) @@ -1162,6 +1186,7 @@ subroutine cooling_abundances_update(i,pmassi,xyzh,vxyzu,eos_vars,abundance,nucl endif #endif ! update internal energy + if (isionisedi) dudtcool = 0. if (cooling_in_step .or. use_krome) vxyzu(4,i) = vxyzu(4,i) + dt * dudtcool diff --git a/src/main/utils_deriv.f90 b/src/main/utils_deriv.f90 index 29fcb1ecc..d45676930 100644 --- a/src/main/utils_deriv.f90 +++ b/src/main/utils_deriv.f90 @@ -16,7 +16,7 @@ module derivutils ! ! :Dependencies: io, mpiutils, timing ! - use timing, only: timers,itimer_dens,itimer_force,itimer_link,itimer_extf,itimer_balance,itimer_cons2prim,& + use timing, only: timers,itimer_dens,itimer_force,itimer_link,itimer_balance,itimer_cons2prim,& itimer_radiation,itimer_rad_save,itimer_rad_neighlist,itimer_rad_arrays,itimer_rad_its,& itimer_rad_flux,itimer_rad_diff,itimer_rad_update,itimer_rad_store diff --git a/src/main/utils_sort.f90 b/src/main/utils_sort.f90 index 97031f2d2..dba9c1ecf 100644 --- a/src/main/utils_sort.f90 +++ b/src/main/utils_sort.f90 @@ -17,7 +17,7 @@ module sortutils ! :Dependencies: None ! implicit none - public :: indexx,indexxfunc,find_rank,r2func,r2func_origin,set_r2func_origin + public :: indexx,indexxfunc,Knnfunc,parqsort,find_rank,r2func,r2func_origin,set_r2func_origin interface indexx module procedure indexx_r4, indexx_i8 end interface indexx @@ -352,6 +352,264 @@ subroutine indexxfunc(n, func, xyzh, indx) end subroutine indexxfunc + +!---------------------------------------------------------------- +!+ +! customised low-memory sorting routine using Quicksort +! sort key value on-the-fly by calling the function func +! which can be any function of the particle positions. +! (Tweaked version of the original one to sort a list of +! neighbours founded using the KD tree) +!+ +!---------------------------------------------------------------- +subroutine Knnfunc(n, func, xyzh, indx) + integer, parameter :: m=7, nstack=500 + integer, intent(in) :: n + real, external :: func + real, intent(in) :: xyzh(:,:) + integer, intent(out) :: indx(n) + + integer :: i,j,k,l,ir,jstack,indxt,itemp + integer :: istack(nstack) + real :: a + + jstack = 0 + l = 1 + ir = n + +1 if (ir - l < m) then + do j = l + 1, ir + indxt = indx(j) + a = func(xyzh(:,indxt)) + do i = j - 1, 1, -1 + if (func(xyzh(:,indx(i))) <= a) goto 2 + indx(i + 1) = indx(i) + enddo + i = 0 +2 indx(i + 1) = indxt + enddo + if (jstack==0) return + ir = istack(jstack) + l = istack(jstack - 1) + jstack = jstack - 2 + else + k = (l + ir)/2 + itemp = indx(k) + indx(k) = indx(l + 1) + indx(l + 1) = itemp + if (func(xyzh(:,indx(l+1))) > func(xyzh(:,indx(ir)))) then + itemp = indx(l + 1) + indx(l + 1) = indx(ir) + indx(ir) = itemp + endif + if (func(xyzh(:,indx(l))) > func(xyzh(:,indx(ir)))) then + itemp = indx(l) + indx(l) = indx(ir) + indx(ir) = itemp + endif + if (func(xyzh(:,indx(l+1))) > func(xyzh(:,indx(l)))) then + itemp = indx(l + 1) + indx(l + 1) = indx(l) + indx(l) = itemp + endif + i = l + 1 + j = ir + indxt = indx(l) + a = func(xyzh(:,indxt)) + +3 continue + i = i + 1 + if (func(xyzh(:,indx(i))) < a) goto 3 +4 continue + j = j - 1 + if (func(xyzh(:,indx(j))) > a) goto 4 + if (j < i) goto 5 + itemp = indx(i) + indx(i) = indx(j) + indx(j) = itemp + goto 3 + +5 indx(l) = indx(j) + indx(j) = indxt + jstack = jstack + 2 + if (jstack > nstack) then + print*,'fatal error!!! stacksize exceeded in sort' + print*,'need to set parameter nstack higher in subroutine indexxfunc ' + stop + endif + if (ir - i + 1 >= j - l) then + istack(jstack) = ir + istack(jstack - 1) = i + ir = j - 1 + else + istack(jstack) = j - 1 + istack(jstack - 1) = l + l = i + endif + endif + + goto 1 +end subroutine Knnfunc + + +!---------------------------------------------------------------- +!+ +! customised low-memory sorting routine using Quicksort +! sort key value on-the-fly by calling the function func +! which can be any function of the particle positions. +! (Tweaked version of the original one to sort a list of +! neighbours founded using the KD tree) (Parallel scheme, approx 2 times faster) +!+ +!---------------------------------------------------------------- +subroutine parqsort(n, arr,func, indx) +!$ use omp_lib,only:omp_get_num_threads + implicit none + integer, parameter :: m=8, nstack=500 + integer, intent(in) :: n + real, intent(in) :: arr(n) + integer, intent(inout) :: indx(n) + real, external :: func + integer :: i,j,k,il,ir,jstack,jqueue,indxt,itemp,nthreads,t,spt,nquick + integer, save :: istack(nstack) + !$omp threadprivate(istack) + integer :: iqueue(nstack) + real :: a + + nthreads = 1 + + !$omp parallel default(none) shared(nthreads) +!$ nthreads = omp_get_num_threads() + !$omp end parallel + + + spt = n/nthreads + + jstack = 0 + jqueue = 0 + iqueue = 0 + istack = 0 + il = 1 + ir = n + + do while (.true.) + + if (ir - il <= spt) then + jqueue = jqueue + 2 + iqueue(jqueue) = ir + iqueue(jqueue - 1) = il + if (jstack==0) exit + ir = istack(jstack) + il = istack(jstack - 1) + jstack = jstack - 2 + else + k = (il + ir)/2 + i = il + j = ir + indxt = indx(k) + a = func(arr(indxt)) + + do while (j>i) + do while(func(arr(indx(i))) < a) + i = i + 1 + enddo + do while (func(arr(indx(j))) > a) + j = j - 1 + enddo + if (j>i) then + itemp = indx(i) + indx(i) = indx(j) + indx(j) = itemp + endif + enddo + jstack = jstack + 2 + if (jstack > nstack) then + print*,'fatal error!!! stacksize exceeded in sort' + print*,'need to set parameter nstack higher in subroutine indexx ' + stop + endif + if (ir - i + 1 >= j - il) then + istack(jstack) = ir + istack(jstack - 1) = i + ir = j - 1 + else + istack(jstack) = j - 1 + istack(jstack - 1) = il + il = i + endif + endif + enddo + + istack = 0 + nquick = jqueue/2 + + + !$omp parallel do default(none) & + !$omp shared(indx,arr,nquick,iqueue)& + !$omp private(i,j,k,il,ir,a,jstack,indxt,itemp) + do t=1,nquick + ir = iqueue(2*t) + il = iqueue(2*t - 1) + jstack = 0 + + do while (.true.) + if (ir - il < m) then + !print*,il,ir + do j = il , ir + indxt = indx(j) + a = func(arr(indxt)) + do i = j - 1, il, -1 + if (func(arr(indx(i))) <= a) goto 5 + indx(i + 1) = indx(i) + enddo + i = il-1 +5 indx(i + 1) = indxt + enddo + if (jstack==0) exit + ir = istack(jstack) + il = istack(jstack - 1) + jstack = jstack - 2 + else + k = (il + ir)/2 + i = il + j = ir + indxt = indx(k) + a = func(arr(indxt)) + + do while (j>i) + do while(func(arr(indx(i))) < a) + i = i + 1 + enddo + do while (func(arr(indx(j))) > a) + j = j - 1 + enddo + if (j>i) then + itemp = indx(i) + indx(i) = indx(j) + indx(j) = itemp + endif + enddo + jstack = jstack + 2 + if (jstack > nstack) then + print*,'fatal error!!! stacksize exceeded in sort' + print*,'need to set parameter nstack higher in subroutine indexx ' + stop + endif + if (ir - i + 1 >= j - il) then + istack(jstack) = ir + istack(jstack - 1) = i + ir = j - 1 + else + istack(jstack) = j - 1 + istack(jstack - 1) = il + il = i + endif + endif + enddo + enddo + +end subroutine parqsort + + !---------------------------------------------------------------- !+ ! Same as indexxfunc, except two particles can have the same diff --git a/src/main/utils_timing.f90 b/src/main/utils_timing.f90 index c9ec91558..9e2de5d71 100644 --- a/src/main/utils_timing.f90 +++ b/src/main/utils_timing.f90 @@ -60,10 +60,13 @@ module timing itimer_rad_update = 19, & itimer_rad_store = 20, & itimer_cons2prim = 21, & - itimer_extf = 22, & - itimer_ev = 23, & - itimer_io = 24 - integer, public, parameter :: ntimers = 24 ! should be equal to the largest itimer index + itimer_substep = 22, & + itimer_sg_id = 23, & + itimer_sg_evol = 24, & + itimer_HII = 25, & + itimer_ev = 26, & + itimer_io = 27 + integer, public, parameter :: ntimers = 27 ! should be equal to the largest itimer index type(timer), public :: timers(ntimers) private @@ -84,6 +87,7 @@ subroutine setup_timers call init_timer(itimer_fromstart , 'all', 0 ) call init_timer(itimer_lastdump , 'last', 0 ) call init_timer(itimer_step , 'step', 0 ) + call init_timer(itimer_HII , 'HII_regions', 0 ) call init_timer(itimer_link , 'tree', itimer_step ) call init_timer(itimer_balance , 'balance', itimer_link ) call init_timer(itimer_dens , 'density', itimer_step ) @@ -102,7 +106,9 @@ subroutine setup_timers call init_timer(itimer_rad_update , 'update', itimer_rad_its ) call init_timer(itimer_rad_store , 'store', itimer_radiation ) call init_timer(itimer_cons2prim , 'cons2prim', itimer_step ) - call init_timer(itimer_extf , 'extf', itimer_step ) + call init_timer(itimer_substep , 'substep', itimer_step ) + call init_timer(itimer_sg_id , 'subg_id', itimer_substep ) + call init_timer(itimer_sg_evol , 'subg_evol', itimer_substep ) call init_timer(itimer_ev , 'write_ev', 0 ) call init_timer(itimer_io , 'write_dump', 0 ) diff --git a/src/main/writeheader.F90 b/src/main/writeheader.F90 index 0d32e639b..a7b5ff448 100644 --- a/src/main/writeheader.F90 +++ b/src/main/writeheader.F90 @@ -80,7 +80,7 @@ subroutine write_header(icall,infile,evfile,logfile,dumpfile,ntot) use io, only:iprint use boundary, only:xmin,xmax,ymin,ymax,zmin,zmax use boundary_dyn, only:dynamic_bdy,rho_thresh_bdy,width_bkg - use options, only:tolh,alpha,alphau,alphaB,ieos,alphamax,use_dustfrac,use_porosity + use options, only:tolh,alpha,alphau,alphaB,ieos,alphamax,use_dustfrac,use_porosity,icooling use part, only:hfact,massoftype,mhd,gravity,periodic,massoftype,npartoftypetot,& labeltype,maxtypes use mpiutils, only:reduceall_mpi @@ -187,10 +187,14 @@ subroutine write_header(icall,infile,evfile,logfile,dumpfile,ntot) endif if (use_dustgrowth) write(iprint,"(1x,a)") 'Dust growth is ON' if (use_porosity) write(iprint,"(1x,a)") 'Dust porosity is ON' - if (cooling_in_step) then - write(iprint,"(1x,a)") 'Cooling is calculated in step' + if (icooling > 0) then + if (cooling_in_step) then + write(iprint,"(1x,a)") 'Cooling is calculated in step' + else + write(iprint,"(1x,a)") 'Cooling is explicitly calculated in force' + endif else - write(iprint,"(1x,a)") 'Cooling is explicitly calculated in force' + write(iprint,"(1x,a)") 'Cooling is OFF' endif if (ufloor > 0.) then write(iprint,"(3(a,Es10.3),a)") ' WARNING! Imposing temperature floor of = ',Tfloor,' K = ', & diff --git a/src/setup/set_orbit.f90 b/src/setup/set_orbit.f90 index 23a25885d..38f3348b3 100644 --- a/src/setup/set_orbit.f90 +++ b/src/setup/set_orbit.f90 @@ -27,36 +27,6 @@ module setorbit ! :Runtime parameters: None ! ! :Dependencies: infile_utils, physcon, setbinary, setflyby, units -! - -! While Campbell elements can be used for unbound orbits, they require -! specifying the true anomaly at the start of the simulation. This is -! not always easy to determine, so the flyby option is provided as an -! alternative. There one specifies the initial separation instead, however -! the choice of angles is more restricted -! -! :References: None -! -! :Owner: Daniel Price -! -! :Runtime parameters: None -! -! :Dependencies: infile_utils, physcon, setbinary, setflyby, units -! - -! While Campbell elements can be used for unbound orbits, they require -! specifying the true anomaly at the start of the simulation. This is -! not always easy to determine, so the flyby option is provided as an -! alternative. There one specifies the initial separation instead, however -! the choice of angles is more restricted -! -! :References: None -! -! :Owner: Daniel Price -! -! :Runtime parameters: None -! -! :Dependencies: physcon ! implicit none public :: set_orbit diff --git a/src/setup/set_star_utils.f90 b/src/setup/set_star_utils.f90 index 73a5d7017..4be4dbe7e 100644 --- a/src/setup/set_star_utils.f90 +++ b/src/setup/set_star_utils.f90 @@ -397,7 +397,8 @@ subroutine set_star_thermalenergy(ieos,den,pres,r,npts,npart,xyzh,vxyzu,rad,eos_ real :: rho_cgs,p_cgs integer :: i1 - i1 = 0 + i1 = 0 + eni = 0. if (present(npin)) i1 = npin ! starting position in particle array if (do_radiation) then diff --git a/src/setup/setup_bondi.f90 b/src/setup/setup_bondi.f90 new file mode 100644 index 000000000..f543019fd --- /dev/null +++ b/src/setup/setup_bondi.f90 @@ -0,0 +1,295 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module setup +! +! Setup for Bondi flow problem, for both relativistic and non-relativistic solution +! +! :References: Liptai & Price (2019), MNRAS 485, 819-842 +! +! :Owner: David Liptai +! +! :Runtime parameters: +! - isol : *(1 = geodesic flow | 2 = sonic point flow)* +! - iswind : *wind option (logical)* +! - np : *desired number of particles (stretch-mapping will only give this approx.)* +! - rmax : *outer edge* +! - rmin : *inner edge* +! +! :Dependencies: bondiexact, centreofmass, dim, externalforces, +! infile_utils, io, kernel, metric_tools, options, part, physcon, +! prompting, setup_params, spherical, stretchmap, timestep, units +! + use physcon, only:pi + use externalforces, only:accradius1,accradius1_hard + use dim, only:gr,maxvxyzu + use metric_tools, only:imet_schwarzschild,imetric + use externalforces, only:mass1 + use setup_params, only:rhozero,npart_total + use io, only:master,fatal + use spherical, only:set_sphere + use options, only:ieos,iexternalforce,nfulldump + use timestep, only:tmax,dtmax + use centreofmass, only:reset_centreofmass + use units, only:set_units,get_G_code + use physcon, only:pc,solarm,gg + use part, only:xyzmh_ptmass,vxyz_ptmass,nptmass,ihacc,igas,set_particle_type,iboundary + use stretchmap, only:get_mass_r,rho_func + use kernel, only:radkern + use prompting, only:prompt + use bondiexact, only:get_bondi_solution,rcrit,isol,iswind + implicit none + + public :: setpart + + private + + real :: gamma_eos,rmax,rmin + integer :: np + + logical, parameter :: set_boundary_particles = .false. + +contains + +!---------------------------------------------------------------- +!+ +! setup for bondi accretion +!+ +!---------------------------------------------------------------- +subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) + integer, intent(in) :: id + integer, intent(inout) :: npart + integer, intent(out) :: npartoftype(:) + real, intent(out) :: xyzh(:,:) + real, intent(out) :: massoftype(:) + real, intent(out) :: vxyzu(:,:) + real, intent(out) :: polyk,gamma,hfact + real, intent(inout) :: time + character(len=20), intent(in) :: fileprefix + integer, parameter :: ntab=10000 + real :: rhotab(ntab) + real :: vol,psep,tff,rhor,vr,ur + real :: r,pos(3),cs2,totmass,approx_m,approx_h + integer :: i,ierr,nx,nbound + character(len=100) :: filename + logical :: iexist + procedure(rho_func), pointer :: density_func +! +!-- Set code units +! + call set_units(G=1.d0,c=1.d0) + print*,' G in code units = ',get_G_code() + +! +!--Set general parameters +! + time = 0. + iexternalforce = 1 + + rmin = 7. + rmax = 8. + np = 10000 + + if (gr) then + if (imetric/=imet_schwarzschild) call fatal('setup_bondi',& + 'You are not using the Schwarzschild metric.') + endif + +! +!-- Read things from setup file +! + filename=trim(fileprefix)//'.setup' + print "(/,1x,63('-'),1(/,1x,a),/,1x,63('-'),/)", 'Bondi Flow.' + inquire(file=filename,exist=iexist) + if (iexist) then + call read_setupfile(filename,ierr) + if (ierr /= 0) then + if (id==master) call write_setupfile(filename) + call fatal('setup','failed to read in all the data from .setup. Aborting') + endif + elseif (id==master) then + print "(a,/)",trim(filename)//' not found: using interactive setup' + if (gr) then + call prompt(' Enter solution type isol (1 = geodesic | 2 = sonic point flow) ',isol,1,2) + call prompt(' Do you want a wind (y/n)? ',iswind) + endif + call prompt(' Enter inner edge: ',rmin,0.) + call prompt(' Enter outer edge: ',rmax,rmin) + call prompt(' Enter the desired number of particles: ',np,0) + call write_setupfile(filename) + print*,' Edit '//trim(filename)//' and rerun phantomsetup' + stop + endif + + if (gr) then + ieos = 2 + gamma = 5./3. + polyk = 1. + else + gamma = 1. + ieos = 1 + cs2 = mass1/(2.*rcrit) + polyk = cs2 + endif + + gamma_eos = gamma ! Note, since non rel bondi is isothermal, solution doesn't depend on gamma + accradius1 = 0. + accradius1_hard = 0. + + if (gr) then + rmin = rmin*mass1 + rmax = rmax*mass1 + endif + + vol = 4./3.*pi*(rmax**3 - rmin**3) + nx = int(np**(1./3.)) + psep = vol**(1./3.)/real(nx) + + call get_rhotab(rhotab,rmin,rmax,mass1,gamma) + + density_func => rhofunc + totmass = get_mass_r(density_func,rmax,rmin) + approx_m = totmass/np + approx_h = hfact*(approx_m/rhofunc(rmin))**(1./3.) + rhozero = totmass/vol + + tff = sqrt(3.*pi/(32.*rhozero)) + tmax = 10.*tff + dtmax = tmax/150. + + print*,'' + print*,' Setup for gas: ' + print*,' min,max radius = ',rmin,rmax + print*,' volume = ',vol ,' particle separation = ',psep + print*,' vol/psep**3 = ',vol/psep**3,' totmass = ',totmass + print*,' free fall time = ',tff ,' tmax = ',tmax + print*,'' + +!--- Add stretched sphere + npart = 0 + npart_total = 0 + call set_sphere('closepacked',id,master,rmin,rmax,psep,hfact,npart,& + xyzh,rhotab=rhotab,nptot=npart_total) + massoftype(:) = totmass/npart + print "(a,i0,/)",' npart = ',npart + + nbound = 0 + do i=1,npart + + pos = xyzh(1:3,i) + r = sqrt(dot_product(pos,pos)) + call get_bondi_solution(rhor,vr,ur,r,mass1,gamma) + vxyzu(1:3,i) = vr*pos/r + if (maxvxyzu >= 4) vxyzu(4,i) = ur + + if (set_boundary_particles) then + if (r + radkern*xyzh(4,i)>rmax .or. r - radkern*xyzh(4,i)= 4) ieos_in = 2 ! Adiabatic equation of state + case(2) ! Young Massive Cluster (S. Jaffa, University of Hertfordshire) default_cluster = "Young Massive Cluster" Rcloud_pc = 5.0 ! Input radius [pc] @@ -110,9 +123,40 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, ieos_in = 1 ! Isothermal equation of state mass_fac = 1.0d5 ! mass code unit: mass_fac * solarm dist_fac = 1.0 ! distance code unit: dist_fac * pc - endif + if (maxvxyzu >= 4) ieos_in = 2 ! Adiabatic equation of state + + case(3) + ! Young Massive Cluster (Yann Bernard, IPAG) + default_cluster = "Embedded cluster" + Rcloud_pc = 10.0 ! Input radius [pc] + Mcloud_msun = 1.0d4 ! Input mass [Msun] + ieos_in = 21 ! Isothermal equation of state + HII + mass_fac = 1.0d4 ! mass code unit: mass_fac * solarm + dist_fac = 1.0 ! distance code unit: dist_fac * pc + iH2R = 1 ! switch HII regions + Rsink_au = 4000. ! Sink radius [au] + mu = 2.35 ! mean molecular weight + if (maxvxyzu >= 4) then + ieos_in = 22 ! Adiabatic equation of state + HII + gamma = 5./3. + Tfloor = 6. + icooling = 6 + Temperature = 40. + endif + + + case default + ! from Bate, Bonnell & Bromm (2003) + default_cluster = "Bate, Bonnell & Bromm (2003)" + Rcloud_pc = 0.1875 ! Input radius [pc] + Mcloud_msun = 50. ! Input mass [Msun] + ieos_in = 8 ! Barotropic equation of state + mass_fac = 1.0 ! mass code unit: mass_fac * solarm + dist_fac = 0.1 ! distance code unit: dist_fac * pc + if (maxvxyzu >= 4) ieos_in = 2 ! Adiabatic equation of state + end select + - if (maxvxyzu >= 4) ieos_in = 2 ! Adiabatic equation of state !--Read values from .setup if (setexists) then @@ -132,7 +176,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call set_units(dist=dist_fac*pc,mass=mass_fac*solarm,G=1.) !--Define remaining variables using the inputs - polyk = kboltz*Temperature/(mu*mass_proton_cgs)*(utime/udist)**2 + polyk = gamma*kboltz*Temperature/(mu*mass_proton_cgs)*(utime/udist)**2 rmax = Rcloud_pc*(pc/udist) r2 = rmax*rmax totmass = Mcloud_msun*(solarm/umass) @@ -153,6 +197,10 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call set_particle_type(i,igas) enddo + if (relax) then + call shuffleparticles(iprint,npart,xyzh,massoftype(1),rsphere=rmax,dsphere=rhozero,dmedium=0.,& + is_setup=.true.,prefix=trim(fileprefix)) + endif !--Set velocities (from pre-made velocity cubes) write(*,"(1x,a)") 'Setting up velocity field on the particles...' vxyzu(:,:) = 0. @@ -167,6 +215,14 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, call normalise_vfield(npart,vxyzu,ierr,ke=epotgrav) if (ierr /= 0) call fatal('setup','error normalising velocity field') + if (maxvxyzu >= 4) then + if (gamma > 1.) then + vxyzu(4,:) = polyk/(gamma*(gamma-1.)) + else + vxyzu(4,:) = 1.5*polyk + endif + endif + !--Setting the centre of mass of the cloud to be zero call reset_centreofmass(npart,xyzh,vxyzu) @@ -175,9 +231,23 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, tmax = 2.*t_ff dtmax = 0.002*t_ff h_acc = Rsink_au*au/udist - r_crit = 2.*h_acc - icreate_sinks = 1 - rho_crit_cgs = 1.d-10 + if (icluster == 3) then + r_crit = h_acc + icreate_sinks = 2 + rho_crit_cgs = 1.d-18 + h_soft_sinkgas = h_acc + tmax_acc = 0.5*(myr/utime) + tseeds = 0.1*(myr/utime) + r_merge_uncond = h_acc + use_regnbody = .true. + r_neigh = 5e-2*h_acc + f_crit_override = 100. + else + r_crit = 2.*h_acc + icreate_sinks = 1 + rho_crit_cgs = 1.d-10 + endif + ieos = ieos_in gmw = mu ! for consistency; gmw will never actually be used endif @@ -211,7 +281,8 @@ subroutine get_input_from_prompts() call prompt('Enter the radius of the sink particles (in au)',Rsink_au) call prompt('Enter the Temperature of the cloud (used for initial sound speed)',Temperature) call prompt('Enter the mean molecular mass (used for initial sound speed)',mu) - if (maxvxyzu < 4) call prompt('Enter the EOS id (1: isothermal, 8: barotropic)',ieos_in) + call prompt('Do you want to relax your cloud',relax) + if (maxvxyzu < 4) call prompt('Enter the EOS id (1: isothermal, 8: barotropic, 21: HII region expansion)',ieos_in) end subroutine get_input_from_prompts !---------------------------------------------------------------- @@ -235,6 +306,7 @@ subroutine write_setupfile(filename) write(iunit,"(/,a)") '# options for sphere' call write_inopt(Mcloud_msun,'M_cloud','mass of cloud in solar masses',iunit) call write_inopt(Rcloud_pc,'R_cloud','radius of cloud in pc',iunit) + call write_inopt(relax, 'relax', 'relax the cloud ?', iunit) write(iunit,"(/,a)") '# options required for initial sound speed' call write_inopt(Temperature,'Temperature','Temperature',iunit) call write_inopt(mu,'mu','mean molecular mass',iunit) diff --git a/src/setup/setup_grdisc.F90 b/src/setup/setup_grdisc.F90 index ed22b212c..2ae3e5427 100644 --- a/src/setup/setup_grdisc.F90 +++ b/src/setup/setup_grdisc.F90 @@ -29,10 +29,9 @@ module setup ! - spin : *spin parameter of black hole |a|<1* ! - theta : *inclination of disc (degrees)* ! -! :Dependencies: dim, eos, extern_lensethirring, externalforces, -! infile_utils, io, kernel, metric, mpidomain, options, part, physcon, -! prompting, setdisc, setorbit, setstar, setunits, setup_params, -! timestep, units +! :Dependencies: eos, extern_lensethirring, externalforces, infile_utils, +! io, kernel, metric, mpidomain, options, part, physcon, prompting, +! setdisc, setorbit, setstar, setunits, setup_params, timestep, units ! use options, only:alpha use setstar, only:star_t diff --git a/src/setup/setup_starcluster.f90 b/src/setup/setup_starcluster.f90 new file mode 100644 index 000000000..429558843 --- /dev/null +++ b/src/setup/setup_starcluster.f90 @@ -0,0 +1,265 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module setup +! +! Setup for simulations of the Galactic Centre +! Adapted by Daniel Price in collaboration with Jorge Cuadra +! +! :References: Paumard et al. (2006) +! +! :Owner: Yrisch +! +! :Runtime parameters: +! - datafile : *filename for star data (m,x,y,z,vx,vy,vz)* +! - h_sink : *sink particle radii in parsec* +! - m_gas : *gas mass resolution in solar masses* +! +! :Dependencies: datafiles, dim, eos, infile_utils, io, part, physcon, +! prompting, ptmass, spherical, timestep, units +! + implicit none + public :: setpart + + ! + ! setup options and default values for these + ! + character(len=120) :: datafile = 'clusterbin.txt' + real :: m_gas = 1.e-6 ! gas mass resolution in Msun + real :: h_sink = 1.e-14 ! sink particle radii in arcsec at 8kpc + + private + +contains + +!---------------------------------------------------------------- +!+ +! setup for galactic centre simulation (no gas) +!+ +!---------------------------------------------------------------- +subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) + use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,ihacc,ihsoft,igas + use units, only:set_units,umass !,udist + use physcon, only:solarm,kpc,pi,au,years,pc + use io, only:fatal,iprint,master + use eos, only:gmw + use timestep, only:dtmax,tmax + use spherical, only:set_sphere + use datafiles, only:find_phantom_datafile + use ptmass, only:use_fourthorder,use_regnbody + integer, intent(in) :: id + integer, intent(inout) :: npart + integer, intent(out) :: npartoftype(:) + real, intent(out) :: xyzh(:,:) + real, intent(out) :: massoftype(:) + real, intent(out) :: polyk,gamma,hfact + real, intent(inout) :: time + character(len=20), intent(in) :: fileprefix + real, intent(out) :: vxyzu(:,:) + character(len=len(fileprefix)+6) :: setupfile + character(len=len(datafile)) :: filename + integer :: ntot + integer :: ierr,i + real :: xcom(3),vcom(3),mtot + real :: psep +! +! units (mass = mass of black hole, length = 1 arcsec at 8kpc) +! + call set_units(mass=solarm,dist=1*pc,G=1.d0) +! +! general parameters +! + xcom = 0. + vcom = 0. + time = 0. + hfact = 1.2 + polyk = 0. + gamma = 5./3. + gmw = 0.6 ! completely ionized, solar abu; eventually needs to be WR abu + dtmax = 1.e-5 + tmax = 0.001 + use_fourthorder = .true. + use_regnbody = .false. + m_gas = 1.e-4 + ntot = 2**21 + ! + ! read setup parameters from the .setup file + ! if file does not exist, then ask for user input + ! + setupfile = trim(fileprefix)//'.setup' + call read_setupfile(setupfile,iprint,ierr) + if (ierr /= 0 .and. id==master) then + call interactive_setup() ! read setup options from user + call write_setupfile(setupfile,iprint) ! write .setup file with defaults + endif +! +! space available for injected gas particles +! + npart = 0 + npartoftype(:) = 0 + massoftype = m_gas*(solarm/umass) ! mass resolution + + xyzh(:,:) = 0. + vxyzu(:,:) = 0. + xyzmh_ptmass(:,:) = 0. + vxyz_ptmass (:,:) = 0. +! +! Read positions, masses and velocities of stars from file +! + filename = find_phantom_datafile(datafile,"starcluster") + call read_ptmass_data(filename,xyzmh_ptmass,vxyz_ptmass,nptmass,ierr) + + mtot = sum(xyzmh_ptmass(4,:)) + + do i=1,nptmass + xcom(1:3) = xcom(1:3) + xyzmh_ptmass(4,i)*xyzmh_ptmass(1:3,i) + vcom(1:3) = vcom(1:3) + xyzmh_ptmass(4,i)*vxyz_ptmass(1:3,i) + enddo + xcom = xcom/mtot + vcom = vcom/mtot + + print*,"xcom",xcom + print*,"vcom",vcom + + do i=1,nptmass + xyzmh_ptmass(1:3,i) = xyzmh_ptmass(1:3,i) - xcom(1:3) + vxyz_ptmass(1:3,i) = vxyz_ptmass(1:3,i) - vcom(1:3) + xyzmh_ptmass(ihacc,i) = h_sink + xyzmh_ptmass(ihsoft,i) = h_sink + enddo + + +! +! setup initial sphere of particles to prevent initialisation problems +! + psep = 1.0 + call set_sphere('random',id,master,0.,10.,psep,hfact,npart,xyzh,np_requested=ntot) + vxyzu(4,:) = 5.317e-4 + npartoftype(igas) = npart + + print*,"npart : ", npart + + if (nptmass == 0) call fatal('setup','no particles setup') + if (ierr /= 0) call fatal('setup','ERROR during setup') + +end subroutine setpart + +!---------------------------------------------------------------- +!+ +! read sink particle masses, positions and velocities from file +!+ +!---------------------------------------------------------------- +subroutine read_ptmass_data(filename,xyzmh_ptmass,vxyz_ptmass,n,ierr) + use io, only:error + use units, only : unit_velocity + character(len=*), intent(in) :: filename + real, intent(out) :: xyzmh_ptmass(:,:), vxyz_ptmass(:,:) + integer, intent(inout) :: n + integer, intent(out) :: ierr + integer :: iunit,n_input + + n_input = n + open(newunit=iunit,file=filename,status='old',action='read',iostat=ierr) + if (ierr /= 0) then + print "(/,2(a,/))",' ERROR opening "'//trim(filename)//'" for read of point mass data', & + ' -> this file should contain m,x,y,z,vx,vy,vz for each point mass, one per line' + endif + do while(ierr==0) + n = n + 1 + if (n > size(xyzmh_ptmass(1,:))) then + ierr = 66 + else + read(iunit,*,iostat=ierr) xyzmh_ptmass(4,n),xyzmh_ptmass(1:3,n),vxyz_ptmass(1:3,n) + endif + vxyz_ptmass(1:3,n) = (vxyz_ptmass(1:3,n)*1.e5)/unit_velocity + if (ierr /= 0) n = n - 1 + enddo + print "(a,i4,a)",' READ',n - n_input,' point masses from '//trim(filename) + if (ierr==66) then + call error('read_ptmass_data','array size exceeded in read_ptmass_data, recompile with MAXPTMASS=n',var='n',ival=n+1) + endif + + ! end of file error is OK + if (ierr < 0) ierr = 0 + +end subroutine read_ptmass_data + +!------------------------------------------ +!+ +! Write setup parameters to .setup file +!+ +!------------------------------------------ +subroutine write_setupfile(filename,iprint) + use infile_utils, only:write_inopt + use dim, only:tagline + character(len=*), intent(in) :: filename + integer, intent(in) :: iprint + integer :: lu,ierr1,ierr2 + + write(iprint,"(a)") ' Writing '//trim(filename)//' with setup options' + open(newunit=lu,file=filename,status='replace',form='formatted') + write(lu,"(a)") '# '//trim(tagline) + write(lu,"(a)") '# input file for Phantom galactic centre setup' + + write(lu,"(/,a)") '# datafile' + call write_inopt(datafile,'datafile','filename for star data (m,x,y,z,vx,vy,vz)',lu,ierr1) + + write(lu,"(/,a)") '# resolution' + call write_inopt(m_gas, 'm_gas','gas mass resolution in solar masses',lu,ierr2) + call write_inopt(h_sink, 'h_sink','sink particle radii in parsec',lu,ierr2) + close(lu) + +end subroutine write_setupfile + +!------------------------------------------ +!+ +! Read setup parameters from input file +!+ +!------------------------------------------ +subroutine read_setupfile(filename,iprint,ierr) + use infile_utils, only:open_db_from_file,inopts,close_db,read_inopt + use dim, only:maxvxyzu + character(len=*), intent(in) :: filename + integer, parameter :: lu = 21 + integer, intent(in) :: iprint + integer, intent(out) :: ierr + integer :: nerr + type(inopts), allocatable :: db(:) + + call open_db_from_file(db,filename,lu,ierr) + if (ierr /= 0) return + write(iprint, '(1x,2a)') 'Setup_Nbody_test: Reading setup options from ',trim(filename) + + nerr = 0 + call read_inopt(datafile,'datafile',db,errcount=nerr) + call read_inopt(m_gas,'m_gas',db,errcount=nerr) + call read_inopt(h_sink,'h_sink',db,errcount=nerr) + + if (nerr > 0) then + print "(1x,a,i2,a)",'Setup_Nbody_test: ',nerr,' error(s) during read of setup file' + ierr = 1 + endif + call close_db(db) + +end subroutine read_setupfile + +!------------------------------------------ +!+ +! Prompt user for setup options +!+ +!------------------------------------------ +subroutine interactive_setup() + use prompting, only:prompt + + print "(2(/,a),/)",'*** Nbody test setup. You can put any cluster of stars that you want to evolve with gas.',& + ' ... With or without primordial binaries, mass(msun), pos (pc), vel(kms)***' + call prompt('Enter filename for star data',datafile,noblank=.true.) + call prompt('Enter sink particle radii in parsec',h_sink,1.e-15,1.e-4) + print "(a)" + +end subroutine interactive_setup + +end module setup diff --git a/src/setup/setup_testparticles.f90 b/src/setup/setup_testparticles.f90 index edbd8ab47..fbc4f0410 100644 --- a/src/setup/setup_testparticles.f90 +++ b/src/setup/setup_testparticles.f90 @@ -100,7 +100,7 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, period = 0. if (gr) call prompt('black hole spin',spin,-1.,1.) - call prompt('select orbit type (1=cirlce, 2=precession, 3=epicycle, 4=vertical-oscillation, 0=custom)',orbtype,0,4) + call prompt('select orbit type (1=circle, 2=precession, 3=epicycle, 4=vertical-oscillation, 0=custom)',orbtype,0,4) select case(orbtype) case(1) ! circular diff --git a/src/setup/setup_wind.f90 b/src/setup/setup_wind.f90 new file mode 100644 index 000000000..e41b19227 --- /dev/null +++ b/src/setup/setup_wind.f90 @@ -0,0 +1,821 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module setup +! +! initial conditions for binary wind accretion / AGB star wind injection +! +! :References: +! Siess et al. 2022, A&A, 667, 75 +! +! :Owner: Lionel Siess +! +! :Runtime parameters: +! - Reff2a : *tight binary primary effective radius (au)* +! - Reff2b : *tight binary secondary effective radius (au)* +! - T_wind : *wind temperature (K)* +! - Teff2a : *tight binary primary effective temperature (K)* +! - Teff2b : *tight binary secondary effective temperature (K)* +! - binary2_a : *tight binary semi-major axis* +! - binary2_e : *tight binary eccentricity* +! - eccentricity : *eccentricity of the binary system* +! - icompanion_star : *set to 1 for a binary system, 2 for a triple system* +! - inclination : *inclination of the tight binary system w.r.t. outer binary (deg)* +! - lum2a : *tight binary primary luminosity (Lsun)* +! - lum2b : *tight binary secondary luminosity (Lsun)* +! - mass_of_particles : *particle mass (Msun, overwritten if iwind_resolution <>0)* +! - primary_Reff : *primary star effective radius (au)* +! - primary_Teff : *primary star effective temperature (K)* +! - primary_lum : *primary star luminosity (Lsun)* +! - primary_mass : *primary star mass (Msun)* +! - primary_racc : *primary star accretion radius (au)* +! - q2 : *tight binary mass ratio* +! - racc2a : *tight binary primary accretion radius* +! - racc2b : *tight binary secondary accretion radius* +! - secondary_Reff : *secondary star effective radius (au)* +! - secondary_Teff : *secondary star effective temperature)* +! - secondary_lum : *secondary star luminosity (Lsun)* +! - secondary_mass : *secondary star mass (Msun)* +! - secondary_racc : *secondary star accretion radius (au)* +! - semi_major_axis : *semi-major axis of the binary system (au)* +! - subst : *star to substitute* +! - temp_exponent : *temperature profile T(r) = T_wind*(r/Reff)^(-temp_exponent)* +! - wind_gamma : *adiabatic index (initial if Krome chemistry used)* +! +! :Dependencies: dim, eos, infile_utils, inject, io, part, physcon, +! prompting, setbinary, sethierarchical, spherical, units +! + use dim, only:isothermal + implicit none + public :: setpart + + private + real, public :: wind_gamma + real, public :: T_wind + real :: temp_exponent + integer :: icompanion_star,iwind + real :: semi_major_axis,semi_major_axis_au,eccentricity + real :: default_particle_mass + real :: primary_lum_lsun,primary_mass_msun,primary_Reff_au,primary_racc_au + real :: secondary_lum_lsun,secondary_mass_msun,secondary_Reff_au,secondary_racc_au + real :: lum2a_lsun,lum2b_lsun,Teff2a,Teff2b,Reff2a_au,Reff2b_au + real :: binary2_a_au,racc2a_au,racc2b_au,binary2_i,q2 + real :: primary_Reff,primary_Teff,primary_lum,primary_mass,primary_racc + real :: secondary_Reff,secondary_Teff,secondary_lum,secondary_mass,secondary_racc + real :: Reff2a,Reff2b + real :: racc2a,racc2b + real :: lum2a,lum2b + real :: binary2_a + real :: binary2_e + integer :: subst + +contains +!---------------------------------------------------------------- +!+ +! default parameter choices +!+ +!---------------------------------------------------------------- +subroutine set_default_parameters_wind() + + wind_gamma = 5./3. + if (isothermal) then + T_wind = 100000. + temp_exponent = 0.5 + ! primary_racc_au = 0.465 + ! primary_mass_msun = 1.5 + ! primary_lum_lsun = 0. + ! primary_Reff_au = 0.465240177008 !100 Rsun + else + T_wind = 3000. + !primary_racc_au = 1. + !primary_mass_msun = 1.5 + !primary_lum_lsun = 20000. + !primary_Reff_au = 0. + endif + icompanion_star = 0 + semi_major_axis = 4.0 + eccentricity = 0. + primary_Teff = 3000. + secondary_Teff = 0. + semi_major_axis_au = 4.0 + default_particle_mass = 1.e-11 + primary_lum_lsun = 5315. + primary_mass_msun = 1.5 + primary_Reff_au = 1. + primary_racc_au = 1. + secondary_lum_lsun = 0. + secondary_mass_msun = 1.0 + secondary_Reff_au = 0. + secondary_racc_au = 0.1 + lum2a_lsun = 0. + lum2b_lsun = 0. + Teff2a = 0. + Teff2b = 0. + Reff2a_au = 0. + Reff2b_au = 0. + binary2_a_au = 0.3 + racc2a_au = 0.1 + racc2b_au = 0.1 + binary2_i = 0. + +end subroutine set_default_parameters_wind + +!---------------------------------------------------------------- +!+ +! setup for uniform particle distributions +!+ +!---------------------------------------------------------------- +subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact,time,fileprefix) + use part, only: xyzmh_ptmass, vxyz_ptmass, nptmass, igas, iTeff, iLum, iReff + use physcon, only: au, solarm, mass_proton_cgs, kboltz, solarl + use units, only: umass,set_units,unit_velocity,utime,unit_energ,udist + use inject, only: set_default_options_inject + use setbinary, only: set_binary + use sethierarchical, only: set_multiple + use io, only: master + use eos, only: gmw,ieos,isink,qfacdisc + use spherical, only: set_sphere + integer, intent(in) :: id + integer, intent(inout) :: npart + integer, intent(out) :: npartoftype(:) + real, intent(out) :: xyzh(:,:) + real, intent(out) :: vxyzu(:,:) + real, intent(out) :: massoftype(:) + real, intent(out) :: polyk,gamma,hfact + real, intent(inout) :: time + character(len=*), intent(in) :: fileprefix + character(len=len(fileprefix)+6) :: filename + integer :: ierr,k + logical :: iexist + + call set_units(dist=au,mass=solarm,G=1.) + call set_default_parameters_wind() + filename = trim(fileprefix)//'.in' + inquire(file=filename,exist=iexist) + if (.not. iexist) call set_default_options_inject() + +!--general parameters +! + time = 0. + filename = trim(fileprefix)//'.setup' + inquire(file=filename,exist=iexist) + if (iexist) call read_setupfile(filename,ierr) + if (.not. iexist .or. ierr /= 0) then + if (id==master) then + call setup_interactive() + call write_setupfile(filename) + endif + endif + +! +!--space available for injected gas particles +! + npart = 0 + npartoftype(:) = 0 + xyzh(:,:) = 0. + vxyzu(:,:) = 0. + xyzmh_ptmass(:,:) = 0. + vxyz_ptmass(:,:) = 0. + + if (icompanion_star == 1) then + call set_binary(primary_mass, & + secondary_mass, & + semi_major_axis, & + eccentricity, & + primary_racc, & + secondary_racc, & + xyzmh_ptmass, vxyz_ptmass, nptmass, ierr) + xyzmh_ptmass(iTeff,1) = primary_Teff + xyzmh_ptmass(iReff,1) = primary_Reff + xyzmh_ptmass(iLum,1) = primary_lum + xyzmh_ptmass(iTeff,2) = secondary_Teff + xyzmh_ptmass(iReff,2) = secondary_Reff + xyzmh_ptmass(iLum,2) = secondary_lum + elseif (icompanion_star == 2) then + !-- hierarchical triple + nptmass = 0 + print "(/,a)",'----------- Hierarchical triple -----------' + print "(a,g10.3,a)",' First hierarchical level primary mass: ', primary_mass_msun + print "(a,g10.3,a)",' First hierarchical level secondary mass: ', secondary_mass_msun + print "(a,g10.3)", ' Wide binary mass ratio: ', secondary_mass/primary_mass + print "(a,g10.3)", ' Tight binary mass ratio: ', q2 + print "(a,g10.3)", ' Star to be substituted: ', abs(subst) +! print "(a,g10.3,a)",' Accretion Radius 1: ', primary_racc!, trim(dist_unit) +! print "(a,g10.3,a)",' Accretion Radius 2a: ', racc2a!, trim(dist_unit) +! print "(a,g10.3,a)",' Accretion Radius 2b: ', racc2b!, trim(dist_unit) + + if (subst>0) then + print "(a,g10.3,a)",' Tight binary orientation referred to: substituted star orbital plane' + else + print "(a,g10.3,a)",' Tight binary orientation referred to: sky' + endif + + + call set_multiple(primary_mass,secondary_mass,semimajoraxis=semi_major_axis,eccentricity=eccentricity, & + accretion_radius1=primary_racc,accretion_radius2=secondary_racc, & + xyzmh_ptmass=xyzmh_ptmass,vxyz_ptmass=vxyz_ptmass,nptmass=nptmass,ierr=ierr) + + if (subst == 12) then + call set_multiple(secondary_mass/(q2+1),secondary_mass*q2/(q2+1),semimajoraxis=binary2_a,eccentricity=binary2_e, & + accretion_radius1=racc2a,accretion_radius2=racc2b, & + xyzmh_ptmass=xyzmh_ptmass,vxyz_ptmass=vxyz_ptmass,nptmass=nptmass,& + posang_ascnode=0.,arg_peri=0.,incl=binary2_i,subst=subst,ierr=ierr) + + xyzmh_ptmass(iTeff,1) = primary_Teff + xyzmh_ptmass(iReff,1) = primary_Reff + xyzmh_ptmass(iLum,1) = primary_lum + xyzmh_ptmass(iTeff,2) = Teff2a + xyzmh_ptmass(iReff,2) = Reff2a + xyzmh_ptmass(iLum,2) = lum2a + xyzmh_ptmass(iTeff,3) = Teff2b + xyzmh_ptmass(iReff,3) = Reff2b + xyzmh_ptmass(iLum,3) = lum2b + + elseif (subst == 11) then + call set_multiple(primary_mass*q2/(q2+1),primary_mass/(q2+1),semimajoraxis=binary2_a,eccentricity=binary2_e, & + accretion_radius1=racc2b,accretion_radius2=primary_racc, & + xyzmh_ptmass=xyzmh_ptmass,vxyz_ptmass=vxyz_ptmass,nptmass=nptmass,& + posang_ascnode=0.,arg_peri=0.,incl=binary2_i,subst=subst,ierr=ierr) + + xyzmh_ptmass(iTeff,1) = primary_Teff + xyzmh_ptmass(iReff,1) = primary_Reff + xyzmh_ptmass(iLum,1) = primary_lum + xyzmh_ptmass(iTeff,2) = secondary_Teff + xyzmh_ptmass(iReff,2) = secondary_Reff + xyzmh_ptmass(iLum,2) = secondary_lum + xyzmh_ptmass(iTeff,3) = Teff2b + xyzmh_ptmass(iReff,3) = Reff2b + xyzmh_ptmass(iLum,3) = lum2b + endif + + print *,'Sink particles summary' + print *,' # mass racc lum Reff' + do k=1,nptmass + print '(i4,2(2x,f9.5),2(2x,es10.3))',k,xyzmh_ptmass(4:5,k),xyzmh_ptmass(iLum,k)/(solarl*utime/unit_energ),& + xyzmh_ptmass(iReff,k)*udist/au + enddo + print *,'' + + else + nptmass = 1 + xyzmh_ptmass(4,1) = primary_mass + xyzmh_ptmass(5,1) = primary_racc + xyzmh_ptmass(iTeff,1) = primary_Teff + xyzmh_ptmass(iReff,1) = primary_Reff + xyzmh_ptmass(iLum,1) = primary_lum + endif + + ! + ! for binary wind simulations the particle mass is IRRELEVANT + ! since it will be over-written on the first call to init_inject + ! + massoftype(igas) = default_particle_mass * (solarm / umass) + + if (isothermal) then + gamma = 1. + if (iwind == 3) then + ieos = 6 + qfacdisc = 0.5*temp_exponent + isink = 1 + T_wind = primary_Teff + else + isink = 1 + ieos = 1 + endif + else + T_wind = 0. + gamma = wind_gamma + endif + polyk = kboltz*T_wind/(mass_proton_cgs * gmw * unit_velocity**2) + +end subroutine setpart + +!---------------------------------------------------------------- +!+ +! determine which problem to set up interactively +!+ +!---------------------------------------------------------------- +subroutine setup_interactive() + use prompting, only:prompt + use physcon, only:au,solarm + use units, only:umass,udist + use io, only:fatal + integer :: ichoice + + if (isothermal) then + iwind = 2 + else + iwind = 1 + call prompt('Type of wind: 1=adia, 2=isoT, 3=T(r)',iwind,1,3) + if (iwind == 2 .or. iwind == 3) then + call fatal('setup','If you choose options 2 or 3, the code must be compiled with SETUP=isowind') + endif + if (iwind == 3) T_wind = primary_Teff + endif + + icompanion_star = 0 + call prompt('Add binary?',icompanion_star,0,2) + + !Hierarchical triple system + if (icompanion_star == 2) then + !select the tight binary + ichoice = 1 + print "(a)",'Star to be substituted by a tight binary' + print "(a)",' 1: primary (2+1)' ,' 2: companion (1+2)' + call prompt('Select star to be substituted',ichoice,1,2) + subst = ichoice+10 + + !select orbital parameters for outer binary + semi_major_axis_au = 15. + eccentricity = 0. + ichoice = 1 + print "(a)",'Orbital parameters first hierarchical level binary' + print "(a)",' 1: semi-axis = 15 au, eccentricity = 0',' 0: custom' + call prompt('select semi-major axis and ecccentricity',ichoice,0,1) + if (ichoice == 0) then + call prompt('enter semi-major axis in au',semi_major_axis_au,0.,100.) + call prompt('enter eccentricity',eccentricity,0.) + endif + semi_major_axis = semi_major_axis_au * au / udist + ichoice = 1 + + !replace companion by tight binary system : 1+2 + if (subst == 12) then + print "(a)",'Primary star parameters (the single wind launching central star)' + print "(a)",' 2: Mass = 1.2 Msun, accretion radius = 0.2568 au',& + ' 1: Mass = 1.5 Msun, accretion radius = 1.2568 au', & + ' 0: custom' + call prompt('select mass and radius of primary',ichoice,0,2) + select case(ichoice) + case(2) + primary_mass_msun = 1.2 + primary_racc_au = 0.2568 + case(1) + primary_mass_msun = 1.5 + primary_racc_au = 1.2568 + case default + primary_mass_msun = 1.5 + primary_racc_au = 1. + call prompt('enter primary mass',primary_mass_msun,0.,100.) + call prompt('enter accretion radius in au ',primary_racc_au,0.) + end select + primary_mass = primary_mass_msun * (solarm / umass) + primary_racc = primary_racc_au * (au / udist) + + ichoice = 1 + print "(a)",'Total mass of tight binary system (1+2)' + print "(a)",' 1: Total mass tight binary = 1.0 Msun',' 0: custom' + secondary_mass_msun = 1. + call prompt('select mass',ichoice,0,1) + select case(ichoice) + case(0) + call prompt('enter total mass tigh binary',secondary_mass_msun,0.,100.) + end select + secondary_mass = secondary_mass_msun * (solarm / umass) + + ichoice = 1 + print "(a)",'Mass ratio and accretion radii of stars in tight orbit:' + print "(a)",' 1: mass ratio m2b/m2a = 1, accretion radius a = 0.01 au, accretion radius b = 0.01 au',' 0: custom' + call prompt('select mass ratio and accretion radii of tight binary',ichoice,0,1) + select case(ichoice) + case(1) + q2 = 1. + racc2a_au = 0.1 + racc2b_au = 0.1 + case default + q2 = 1. + racc2a_au = 0.1 + racc2b_au = 0.1 + call prompt('enter tight binary mass ratio',q2,0.) + call prompt('enter accretion radius a in au ',racc2a_au,0.) + call prompt('enter accretion radius b in au ',racc2b_au,0.) + end select + racc2a = racc2a_au * (au / udist) + racc2b = racc2b_au * (au / udist) + secondary_racc = racc2a !needs to be /=0 otherwise NaNs in set_multiple + + !replace primary by tight binary system : 2+1 + elseif (subst == 11) then + print "(a)",'Stellar parameters of the remote single star (2+1)' + print "(a)",' 1: Mass = 1.0 Msun, accretion radius = 0.1 au',' 0: custom' + call prompt('select mass and radius of remote single star',ichoice,0,1) + select case(ichoice) + case(1) + secondary_mass_msun = 1. + secondary_racc_au = 0.1 + case default + secondary_mass_msun = 1. + secondary_racc_au = 0.1 + call prompt('enter mass of remote single star',secondary_mass_msun,0.,100.) + call prompt('enter accretion radius in au ',secondary_racc_au,0.) + end select + secondary_mass = secondary_mass_msun * (solarm / umass) + secondary_racc = secondary_racc_au * (au / udist) + + ichoice = 1 + print "(a)",'wind-launching star accretion radius in tigh orbit (called primary)' + print "(a)",' 2: accretion radius primary = 0.2568 au',& + ' 1: accretion radius primary = 1.2568 au', & + ' 0: custom' + call prompt('select accretion radius of wind launching star',ichoice,0,2) + select case(ichoice) + case(2) + primary_racc_au = 0.2568 + case(1) + primary_racc_au = 1.2568 + case default + primary_racc_au = 1. + call prompt('enter accretion radius in au ',primary_racc_au,0.) + end select + primary_racc = primary_racc_au * (au / udist) + + ichoice = 1 + print "(a)",'Total mass of the tight binary system (2+1):' + print "(a)",' 2: Total mass tight binary = 1.2 Msun',& + ' 1: Total mass tight binary = 1.5 Msun', & + ' 0: custom' + call prompt('select total mass tight binary',ichoice,0,2) + select case(ichoice) + case(2) + primary_mass_msun = 1.2 + case(1) + primary_mass_msun = 1.5 + case default + primary_mass_msun = 1.5 + call prompt('enter primary mass',primary_mass_msun,0.,100.) + end select + primary_mass = primary_mass_msun * (solarm / umass) + + ichoice = 1 + print "(a)",'Mass ratio and accretion radius of secondary in tight orbit:' + print "(a)",' 1: mass ratio m1b/m1a = 0.3, accretion radius b = 0.01 au',' 0: custom' + call prompt('select mass ratio and accretion radius of tight binary',ichoice,0,1) + select case(ichoice) + case(1) + q2 = 0.3 + racc2b_au = 0.1 + case default + q2 = 0.3 + racc2b_au = 0.1 + call prompt('enter tight binary mass ratio',q2,0.) + call prompt('enter accretion radius b in au ',racc2b_au,0.) + end select + racc2b = racc2b_au * (au / udist) + endif + + ichoice = 1 + print "(a)",'Orbital parameters of tight system:' + print "(a)",' 1: semi-axis = 4 au, eccentricity = 0',' 0: custom' + call prompt('select tight binary semi-major axis and eccentricity',ichoice,0,1) + select case(ichoice) + case(1) + binary2_a_au = 4. + binary2_e = 0. + case default + binary2_a_au = 4. + binary2_e = 0. + call prompt('enter semi-major axis in au',binary2_a_au,0.,semi_major_axis_au) + call prompt('enter eccentricity',binary2_e,0.) + end select + binary2_a = binary2_a_au * au / udist + + ichoice = 1 + print "(a)",'inclination of orbit tight binary w.r.t. outer binary:' + print "(a)",' 1: inclination = 0 deg',' 0: custom' + call prompt('select inclination',ichoice,0,1) + select case(ichoice) + case(1) + binary2_i = 0. + case default + binary2_i = 0. + call prompt('enter inclination',binary2_i,0.,90.) + end select + + !binary or single star case + else + if (icompanion_star == 1) then + print "(a)",'Primary star parameters' + else + print "(a)",'Stellar parameters' + endif + ichoice = 2 + print "(a)",' 3: Mass = 1.2 Msun, accretion radius = 1. au (trans-sonic)',& + ' 2: Mass = 1.2 Msun, accretion radius = 0.2568 au',& + ' 1: Mass = 1.0 Msun, accretion radius = 1.2568 au', & + ' 0: custom' + call prompt('select mass and radius of primary',ichoice,0,3) + select case(ichoice) + case(3) + primary_lum_lsun = 2.d4 + primary_Teff = 5.d4 + primary_mass_msun = 1.2 + primary_racc_au = 1. + wind_gamma = 1.4 + case(2) + primary_mass_msun = 1.2 + primary_racc_au = 0.2568 + case(1) + primary_mass_msun = 1. + primary_racc_au = 1.2568 + case default + primary_mass_msun = 1. + primary_racc_au = 1. + call prompt('enter primary mass',primary_mass_msun,0.,100.) + call prompt('enter accretion radius in au ',primary_racc_au,0.) + end select + primary_mass = primary_mass_msun * (solarm / umass) + primary_racc = primary_racc_au * (au / udist) + + if (icompanion_star == 1) then + ichoice = 1 + print "(a)",'Secondary star parameters' + print "(a)",' 1: Mass = 1.0 Msun, accretion radius = 0.1 au',' 0: custom' + call prompt('select mass and radius of secondary',ichoice,0,1) + select case(ichoice) + case(1) + secondary_mass_msun = 1. + secondary_racc_au = 0.1 + case default + secondary_mass_msun = 1. + secondary_racc_au = 0.1 + call prompt('enter secondary mass',secondary_mass_msun,0.,100.) + call prompt('enter accretion radius in au ',secondary_racc_au,0.) + end select + secondary_mass = secondary_mass_msun * (solarm / umass) + secondary_racc = secondary_racc_au * (au / udist) + + ichoice = 1 + print "(a)",'Orbital parameters' + print "(a)",' 1: semi-axis = 3.7 au, eccentricity = 0',' 0: custom' + call prompt('select semi-major axis and ecccentricity',ichoice,0,1) + select case(ichoice) + case(1) + semi_major_axis_au = 3.7 + eccentricity = 0. + case default + semi_major_axis_au = 1. + eccentricity = 0. + call prompt('enter semi-major axis in au',semi_major_axis_au,0.,100.) + call prompt('enter eccentricity',eccentricity,0.) + end select + semi_major_axis = semi_major_axis_au * au / udist + endif + endif + +end subroutine setup_interactive + +!---------------------------------------------------------------- +!+ +! get luminosity and effective radius in code units +! from various combinations of L, Teff and Reff in physical inuts +!+ +!---------------------------------------------------------------- +subroutine get_lum_and_Reff(lum_lsun,reff_au,Teff,lum,Reff) + use physcon, only:au,steboltz,solarl,pi + use units, only:udist,unit_luminosity + real, intent(inout) :: lum_lsun,reff_au,Teff + real, intent(out) :: lum,Reff + + if (Teff <= tiny(0.) .and. lum_lsun > 0. .and. Reff_au > 0.) then + primary_Teff = (lum_lsun*solarl/(4.*pi*steboltz*(Reff_au*au)**2))**0.25 + elseif (Reff_au <= 0. .and. lum_lsun > 0. .and. Teff > 0.) then + Reff_au = sqrt(lum_lsun*solarl/(4.*pi*steboltz*Teff**4))/au + elseif (Reff_au > 0. .and. lum_lsun <= 0. .and. Teff > 0.) then + lum_lsun = 4.*pi*steboltz*Teff**4*(primary_Reff_au*au)**2/solarl + endif + + lum = lum_lsun*(solarl/unit_luminosity) + Reff = Reff_au*(au/udist) + +end subroutine get_lum_and_Reff + +!---------------------------------------------------------------- +!+ +! write parameters to setup file +!+ +!---------------------------------------------------------------- +subroutine write_setupfile(filename) + use infile_utils, only:write_inopt + character(len=*), intent(in) :: filename + integer, parameter :: iunit = 20 + + print "(a)",' writing setup options file '//trim(filename) + open(unit=iunit,file=filename,status='replace',form='formatted') + write(iunit,"(a)") '# input file for wind setup routine' + + call get_lum_and_Reff(primary_lum_lsun,primary_Reff_au,primary_Teff,primary_lum,primary_Reff) + + if (icompanion_star == 2) then + call get_lum_and_Reff(secondary_lum_lsun,secondary_Reff_au,secondary_Teff,secondary_lum,secondary_Reff) + + call write_inopt(icompanion_star,'icompanion_star','set to 1 for a binary system, 2 for a triple system',iunit) + !-- hierarchical triple + write(iunit,"(/,a)") '# options for hierarchical triple' + call write_inopt(subst,'subst','star to substitute',iunit) + write(iunit,"(/,a)") '# input of primary (wind launching star)' + if (subst == 12) then + call write_inopt(primary_mass_msun,'primary_mass','primary star mass (Msun)',iunit) + call write_inopt(primary_racc_au,'primary_racc','primary star accretion radius (au)',iunit) + call write_inopt(primary_lum_lsun,'primary_lum','primary star luminosity (Lsun)',iunit) + call write_inopt(primary_Teff,'primary_Teff','primary star effective temperature (K)',iunit) + call write_inopt(primary_Reff_au,'primary_Reff','primary star effective radius (au)',iunit) + call write_inopt(semi_major_axis_au,'semi_major_axis','semi-major axis of the binary system (au)',iunit) + call write_inopt(eccentricity,'eccentricity','eccentricity of the binary system',iunit) + write(iunit,"(/,a)") '# input secondary to be replaced by tight binary' + call write_inopt(secondary_mass_msun,'secondary_mass','total mass of secondary tight binary (Msun)',iunit) + call write_inopt(q2,'q2','tight binary mass ratio',iunit) + !-- tight orbital parameters + call write_inopt(binary2_a,'binary2_a','tight binary semi-major axis',iunit) + call write_inopt(binary2_e,'binary2_e','tight binary eccentricity',iunit) + !-- accretion radii, luminosity, radii + call write_inopt(racc2a_au,'racc2a','tight binary primary accretion radius',iunit) + call write_inopt(racc2b_au,'racc2b','tight binary secondary accretion radius',iunit) + call write_inopt(lum2a_lsun,'lum2a','tight binary primary luminosity (Lsun)',iunit) + call write_inopt(lum2b_lsun,'lum2b','tight binary secondary luminosity (Lsun)',iunit) + call write_inopt(Teff2a,'Teff2a','tight binary primary effective temperature (K)',iunit) + call write_inopt(Teff2b,'Teff2b','tight binary secondary effective temperature (K)',iunit) + call write_inopt(Reff2a_au,'Reff2a','tight binary primary effective radius (au)',iunit) + call write_inopt(Reff2b_au,'Reff2b','tight binary secondary effective radius (au)',iunit) + elseif (subst == 11) then + call write_inopt(primary_racc_au,'primary_racc','primary star accretion radius (au)',iunit) + call write_inopt(primary_lum_lsun,'primary_lum','primary star luminosity (Lsun)',iunit) + call write_inopt(primary_Teff,'primary_Teff','primary star effective temperature (K)',iunit) + call write_inopt(primary_Reff_au,'primary_Reff','primary star effective radius (au)',iunit) + write(iunit,"(/,a)") '# input tight binary to create close companion' + call write_inopt(primary_mass_msun,'primary_mass','primary star mass (Msun)',iunit) + call write_inopt(q2,'q2','tight binary mass ratio',iunit) + !-- tight orbital parameters + call write_inopt(binary2_a,'binary2_a','tight binary semi-major axis',iunit) + call write_inopt(binary2_e,'binary2_e','tight binary eccentricity',iunit) + !-- accretion radii + call write_inopt(racc2b_au,'racc2b','tight binary secondary accretion radius',iunit) + call write_inopt(lum2b_lsun,'lum2b','tight binary secondary luminosity (Lsun)',iunit) + call write_inopt(Teff2b,'Teff2b','tight binary secondary effective temperature (K)',iunit) + call write_inopt(Reff2b_au,'Reff2b','tight binary secondary effective radius (au)',iunit) + write(iunit,"(/,a)") '# input of secondary, outer binary' + call write_inopt(secondary_mass_msun,'secondary_mass','secondary star mass (Msun)',iunit) + call write_inopt(secondary_racc_au,'secondary_racc','secondary star accretion radius (au)',iunit) + call write_inopt(secondary_lum_lsun,'secondary_lum','secondary star luminosity (Lsun)',iunit) + call write_inopt(secondary_Teff,'secondary_Teff','secondary star effective temperature)',iunit) + call write_inopt(secondary_Reff_au,'secondary_Reff','secondary star effective radius (au)',iunit) + call write_inopt(semi_major_axis_au,'semi_major_axis','semi-major axis of the binary system (au)',iunit) + call write_inopt(eccentricity,'eccentricity','eccentricity of the binary system',iunit) + endif + call write_inopt(binary2_i,'inclination','inclination of the tight binary system w.r.t. outer binary (deg)',iunit) + !binary or single star + else + call write_inopt(primary_mass_msun,'primary_mass','primary star mass (Msun)',iunit) + call write_inopt(primary_racc_au,'primary_racc','primary star accretion radius (au)',iunit) + call write_inopt(primary_lum_lsun,'primary_lum','primary star luminosity (Lsun)',iunit) + call write_inopt(primary_Teff,'primary_Teff','primary star effective temperature (K)',iunit) + call write_inopt(primary_Reff_au,'primary_Reff','primary star effective radius (au)',iunit) + call write_inopt(icompanion_star,'icompanion_star','set to 1 for a binary system, 2 for a triple system',iunit) + if (icompanion_star == 1) then + call get_lum_and_Reff(secondary_lum_lsun,secondary_Reff_au,secondary_Teff,secondary_lum,secondary_Reff) + + call write_inopt(secondary_mass_msun,'secondary_mass','secondary star mass (Msun)',iunit) + call write_inopt(secondary_racc_au,'secondary_racc','secondary star accretion radius (au)',iunit) + call write_inopt(secondary_lum_lsun,'secondary_lum','secondary star luminosity (Lsun)',iunit) + call write_inopt(secondary_Teff,'secondary_Teff','secondary star effective temperature)',iunit) + call write_inopt(secondary_Reff_au,'secondary_Reff','secondary star effective radius (au)',iunit) + call write_inopt(semi_major_axis_au,'semi_major_axis','semi-major axis of the binary system (au)',iunit) + call write_inopt(eccentricity,'eccentricity','eccentricity of the binary system',iunit) + endif + endif + + call write_inopt(default_particle_mass,'mass_of_particles','particle mass (Msun, overwritten if iwind_resolution <>0)',iunit) + + if (isothermal) then + wind_gamma = 1. + if (iwind == 3) then + call write_inopt(primary_Teff,'T_wind','wind temperature at injection radius (K)',iunit) + call write_inopt(temp_exponent,'temp_exponent','temperature profile T(r) = T_wind*(r/Reff)^(-temp_exponent)',iunit) + else + call write_inopt(T_wind,'T_wind','wind temperature (K)',iunit) + endif + else + call write_inopt(wind_gamma,'wind_gamma','adiabatic index (initial if Krome chemistry used)',iunit) + endif + close(iunit) + +end subroutine write_setupfile + +!---------------------------------------------------------------- +!+ +! Read parameters from setup file +!+ +!---------------------------------------------------------------- +subroutine read_setupfile(filename,ierr) + use infile_utils, only:open_db_from_file,inopts,read_inopt,close_db + use physcon, only:au,steboltz,solarl,solarm,pi + use units, only:udist,umass,utime,unit_energ + character(len=*), intent(in) :: filename + integer, intent(out) :: ierr + integer, parameter :: iunit = 21 + type(inopts), allocatable :: db(:) + integer :: nerr,ichange + + nerr = 0 + ichange = 0 + print "(a)",' reading setup options from '//trim(filename) + call open_db_from_file(db,filename,iunit,ierr) + call read_inopt(primary_mass_msun,'primary_mass',db,min=0.,max=1000.,errcount=nerr) + primary_mass = primary_mass_msun * (solarm / umass) + call read_inopt(primary_lum_lsun,'primary_lum',db,min=0.,max=1e7,errcount=nerr) + primary_lum = primary_lum_lsun * (solarl * utime / unit_energ) + call read_inopt(primary_Teff,'primary_Teff',db,min=0.,errcount=nerr) + call read_inopt(primary_Reff_au,'primary_Reff',db,min=0.,errcount=nerr) + primary_Reff = primary_Reff_au * au / udist + call read_inopt(primary_racc_au,'primary_racc',db,min=0.,errcount=nerr) + primary_racc = primary_racc_au * au / udist + if (primary_racc < tiny(0.)) then + print *,'ERROR: primary accretion radius not defined' + nerr = nerr+1 + endif + + call read_inopt(icompanion_star,'icompanion_star',db,min=0,errcount=nerr) + if (icompanion_star == 1) then + call read_inopt(secondary_mass_msun,'secondary_mass',db,min=0.,max=1000.,errcount=nerr) + secondary_mass = secondary_mass_msun * (solarm / umass) + call read_inopt(secondary_lum_lsun,'secondary_lum',db,min=0.,max=1e7,errcount=nerr) + secondary_lum = secondary_lum_lsun * (solarl * utime / unit_energ) + call read_inopt(secondary_Teff,'secondary_Teff',db,min=0.,errcount=nerr) + call read_inopt(secondary_Reff_au,'secondary_Reff',db,min=0.,errcount=nerr) + secondary_Reff = secondary_Reff_au * au / udist + call read_inopt(secondary_racc_au,'secondary_racc',db,min=0.,errcount=nerr) + secondary_racc = secondary_racc_au * au / udist + if (secondary_racc < tiny(0.)) then + print *,'ERROR: secondary accretion radius not defined' + nerr = nerr+1 + endif + call read_inopt(semi_major_axis_au,'semi_major_axis',db,min=0.,errcount=nerr) + semi_major_axis = semi_major_axis_au * au / udist + call read_inopt(eccentricity,'eccentricity',db,min=0.,errcount=nerr) + elseif (icompanion_star == 2) then + !-- hierarchical triple + call read_inopt(subst,'subst',db,errcount=nerr) + !replace primary by tight binary system : 2+1 + if (subst == 11) then + call read_inopt(secondary_lum_lsun,'secondary_lum',db,min=0.,max=1000.,errcount=nerr) + secondary_lum = secondary_lum_lsun * (solarl * utime / unit_energ) + call read_inopt(secondary_Teff,'secondary_Teff',db,min=0.,max=1000.,errcount=nerr) + call read_inopt(secondary_Reff_au,'secondary_Reff',db,min=0.,max=1000.,errcount=nerr) + secondary_Reff = secondary_Reff_au * au / udist + call read_inopt(secondary_racc_au,'secondary_racc',db,min=0.,max=1000.,errcount=nerr) + secondary_racc = secondary_racc_au * au / udist + elseif (subst == 12) then + call read_inopt(lum2a_lsun,'lum2a',db,errcount=nerr) + lum2a = lum2a_lsun * (solarl * utime / unit_energ) + !secondary_lum_lsun = lum2a_lsun + call read_inopt(Teff2a,'Teff2a',db,errcount=nerr) + call read_inopt(Reff2a_au,'Reff2a',db,errcount=nerr) + Reff2a = Reff2a_au * au / udist + !secondary_Reff = Reff2a + call read_inopt(racc2a_au,'racc2a',db,errcount=nerr) + racc2a = racc2a_au * au / udist + endif + call read_inopt(secondary_mass_msun,'secondary_mass',db,min=0.,max=1000.,errcount=nerr) + secondary_mass = secondary_mass_msun * (solarm / umass) + call read_inopt(semi_major_axis_au,'semi_major_axis',db,min=0.,errcount=nerr) + semi_major_axis = semi_major_axis_au * au / udist + call read_inopt(eccentricity,'eccentricity',db,min=0.,errcount=nerr) + !-- masses + call read_inopt(q2,'q2',db,min=0.,max=1.,errcount=nerr) + !-- tight parameters + call read_inopt(binary2_a_au,'binary2_a',db,errcount=nerr) + binary2_a = binary2_a_au * au / udist + call read_inopt(binary2_e,'binary2_e',db,errcount=nerr) + !-- accretion radii,... + call read_inopt(racc2b_au,'racc2b',db,errcount=nerr) + racc2b = racc2b_au * au / udist + if (racc2b < tiny(0.)) then + print *,'WARNING: secondary accretion radius not defined' + !nerr = nerr+1 + endif + call read_inopt(lum2b_lsun,'lum2b',db,errcount=nerr) + lum2b = lum2b_lsun * (solarl * utime / unit_energ) + call read_inopt(Teff2b,'Teff2b',db,errcount=nerr) + call read_inopt(Reff2b_au,'Reff2b',db,errcount=nerr) + Reff2b = Reff2b_au * au / udist + call read_inopt(binary2_i,'inclination',db,errcount=nerr) + endif + + call read_inopt(default_particle_mass,'mass_of_particles',db,min=0.,errcount=nerr) + + if (isothermal) then + wind_gamma = 1. + call read_inopt(T_wind,'T_wind',db,min=0.,errcount=nerr) + if (iwind == 3) call read_inopt(temp_exponent,'temp_exponent',db,min=0.,max=5.,errcount=nerr) + else + call read_inopt(wind_gamma,'wind_gamma',db,min=1.,max=4.,errcount=nerr) + endif + call close_db(db) + ierr = nerr + call write_setupfile(filename) + +end subroutine read_setupfile + +end module setup diff --git a/src/tests/test_fastmath.f90 b/src/tests/test_fastmath.f90 new file mode 100644 index 000000000..358b25133 --- /dev/null +++ b/src/tests/test_fastmath.f90 @@ -0,0 +1,162 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module testmath +! +! This module performs unit tests of the fast sqrt routines +! +! :References: None +! +! :Owner: Daniel Price +! +! :Runtime parameters: None +! +! :Dependencies: fastmath, io, mpiutils, random +! + implicit none + public :: test_math + + private + +contains + +subroutine test_math(ntests,npass,usefsqrt,usefinvsqrt) + use io, only:id,master + use fastmath, only:checksqrt,testsqrt,finvsqrt + use random, only:ran2 + use mpiutils, only:barrier_mpi + integer, intent(inout) :: ntests,npass + logical, intent(out) :: usefsqrt,usefinvsqrt + integer, parameter :: n = 1000000 + integer, parameter :: stderr = 0 + integer :: ierr,iseed,nerr,i + real, allocatable :: x(:),f(:),y(:) + real :: t1,t2,errmax,tnative + + if (id==master) write(*,"(a,/)") '--> TESTING FAST SQRT ROUTINES' + + usefsqrt = .true. + usefinvsqrt = .true. +! +!--check for errors first +! + call testsqrt(ierr,output=.false.) + if (ierr /= 0) then + ! report errors on any threads + write(*, "(a)") ' *** ERROR with fast sqrt on this architecture ***' + usefsqrt = .false. + usefinvsqrt = .false. + write(*,"(/,a,/)") '<-- FAST SQRT TEST FAILED' + return + endif + + allocate(x(n),f(n),y(n),stat=ierr) + if (ierr /= 0) return + + iseed = -5234 + do i=1,n + x(i) = ran2(iseed)*1.e8 + enddo + + ntests = ntests + 1 + nerr = 0 + do i=1,n + call checksqrt(x(i),5.e-7*x(i),ierr,.false.) + nerr = max(ierr,nerr) + enddo + if (nerr > 0) then + usefsqrt = .false. + usefinvsqrt = .false. + else + npass = npass + 1 + endif + +! +!--check timings for inverse sqrt +! + call cpu_time(t1) + do i=1,n + f(i) = 1./sqrt(x(i)) + enddo + call cpu_time(t2) + tnative = t2-t1 + if (id==master) write(*,"(a,es10.3,a)") ' native 1/sqrt done in ',tnative,' cpu-s' + y = f + + call barrier_mpi + + call cpu_time(t1) + do i=1,n + f(i) = finvsqrt(x(i)) + enddo + call cpu_time(t2) + + ! run tests on all threads, but only report detailed results on master thread + if (id==master) write(*,"(a,es10.3,a)") ' fast 1/sqrt done in ',t2-t1,' cpu-s' + + if ((t2-t1) > tnative) then + if (id==master) write(*,"(a,f4.1)") ' so finvsqrt(x) is SLOWER than 1/sqrt(x) by factor of ',& + (t2-t1)/tnative + usefinvsqrt = .false. + else + if (id==master) write(*,"(a,f4.1)") ' so finvsqrt(x) is FASTER than 1/sqrt(x) by factor of ', & + tnative/(t2-t1) + endif + + errmax = 0. + do i=1,n + errmax = max(errmax,abs(y(i) - f(i))/y(i)) + enddo + if (id==master) write(*,"(1x,a,es10.3)") 'max relative error is ',errmax + if (errmax > 1.e-7) usefinvsqrt = .false. + + if (id==master) write(*,*) + call barrier_mpi +! +!--check timings for sqrt +! + call cpu_time(t1) + do i=1,n + f(i) = sqrt(x(i)) + enddo + call cpu_time(t2) + tnative = t2-t1 + if (id==master) write(*,"(a,es10.3,a)") ' native sqrt done in ',tnative,' cpu-s' + y = f + call barrier_mpi + + call cpu_time(t1) + do i=1,n + f(i) = x(i)*finvsqrt(x(i)) + enddo + call cpu_time(t2) + if (id==master) write(*,"(a,es10.3,a)") ' x*finvsqrt(x) done in ',t2-t1,' cpu-s' + + if ((t2-t1) > tnative) then + if (id==master) write(*,"(a,f4.1)") ' so x*finvsqrt(x) is SLOWER than sqrt(x) by factor of ',& + (t2-t1)/tnative + usefsqrt = .false. + else + if (id==master) write(*,"(a,f4.1)") ' so x*finvsqrt(x) is FASTER than sqrt(x) by factor of ',tnative/(t2-t1) + endif + + errmax = 0. + do i=1,n + errmax = max(errmax,abs(y(i) - f(i))/(y(i) + epsilon(y))) + enddo + if (id==master) write(*,"(1x,a,es10.3)") 'max relative error is ',errmax + if (errmax > 1.e-7) usefinvsqrt = .false. + + if (allocated(x)) deallocate(x) + if (allocated(f)) deallocate(f) + if (allocated(y)) deallocate(y) + + if (id==master) write(*,"(/,a,/)") '<-- FAST SQRT TEST COMPLETE' + call barrier_mpi + +end subroutine test_math + +end module testmath diff --git a/src/tests/test_gr.f90 b/src/tests/test_gr.f90 new file mode 100644 index 000000000..905a15a0d --- /dev/null +++ b/src/tests/test_gr.f90 @@ -0,0 +1,557 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module testgr +! +! Unit tests of General Relativity +! +! :References: Liptai & Price (2019), MNRAS +! +! :Owner: David Liptai +! +! :Runtime parameters: None +! +! :Dependencies: cons2prim, cons2primsolver, eos, extern_gr, inverse4x4, +! io, metric, metric_tools, part, physcon, substepping, testutils, units, +! utils_gr, vectorutils +! + use testutils, only:checkval,checkvalbuf,checkvalbuf_end,update_test_scores + implicit none + + public :: test_gr + + private + +contains +!----------------------------------------------------------------------- +!+ +! Unit tests for General Relativity +!+ +!----------------------------------------------------------------------- +subroutine test_gr(ntests,npass) + use io, only:id,master + use units, only:set_units + use physcon, only:solarm + integer, intent(inout) :: ntests,npass + + call set_units(mass=1.d6*solarm,G=1.d0,c=1.d0) + if (id==master) write(*,"(/,a,/)") '--> TESTING GENERAL RELATIVITY' + call test_combinations_all(ntests,npass) + call test_precession(ntests,npass) + call test_inccirc(ntests,npass) + if (id==master) write(*,"(/,a)") '<-- GR TESTS COMPLETE' + +end subroutine test_gr + +!----------------------------------------------------------------------- +!+ +! Test of orbital precession in the Kerr metric +!+ +!----------------------------------------------------------------------- +subroutine test_precession(ntests,npass) + use metric_tools, only:imetric,imet_kerr,imet_schwarzschild + use metric, only:a + integer, intent(inout) :: ntests,npass + integer :: nerr(6),norbits,nstepsperorbit + real :: dt,period,x0,vy0,tmax,angtol,postol + real :: angmom(3),angmom0(3),xyz(3),vxyz(3) + + write(*,'(/,a)') '--> testing substep_gr (precession)' + if (imetric /= imet_kerr .and. imetric /= imet_schwarzschild) then + write(*,'(/,a)') ' Skipping test! Metric is not Kerr (or Schwarzschild).' + return + endif + + a = 0. + x0 = 90. + vy0 = 0.0521157 + xyz = (/x0,0. ,0./) + vxyz = (/0.,vy0,0./) + period = 2390. ! approximate + norbits = 4 + tmax = norbits*period + nstepsperorbit = 1000 + dt = 0.239 !period/nstepsperorbit + + call integrate_geodesic(tmax,dt,xyz,vxyz,angmom0,angmom) + + angtol = 1.08e-15 + postol = 1.4e-5 + call checkval(angmom(1),angmom0(1),angtol,nerr(1),'error in angmomx') + call checkval(angmom(2),angmom0(2),angtol,nerr(2),'error in angmomy') + call checkval(angmom(3),angmom0(3),angtol,nerr(3),'error in angmomz') + call checkval(xyz(1), 77.606726748045929,postol,nerr(4),'error in final x position') + call checkval(xyz(2),-45.576259888019351,postol,nerr(5),'error in final y position') + call checkval(xyz(3),0.0 ,postol,nerr(6),'error in final z position') + + call update_test_scores(ntests,nerr,npass) + +end subroutine test_precession + +!----------------------------------------------------------------------- +!+ +! Test of inclined circular orbit in the Kerr metric +!+ +!----------------------------------------------------------------------- +subroutine test_inccirc(ntests,npass) + use physcon, only:pi + use metric_tools, only:imetric,imet_kerr + use metric, only:a + integer, intent(inout) :: ntests,npass + integer :: nerr(6),norbits,nstepsperorbit + real :: dt,period,tmax + real :: angmom(3),angmom0(3),xyz(3),vxyz(3) + real :: m,omega,phi,q,r,rdot,rho2,theta,thetadot,vx,vy,vz,x1,y1,z1 + real :: R2,rfinal + + write(*,'(/,a)') '--> testing substep_gr (inclined circular orbit)' + + if (imetric /= imet_kerr) then + write(*,'(/,a)') ' Skipping test! Metric is not Kerr.' + return + endif + + a = 1. + r = 10. + theta = 45.*pi/180. ! convert to radians + phi = 0. + m = 1. + q = sqrt(r**2 - a**2*cos(theta)**2) + rho2 = r**2 + a**2*cos(theta)**2 + omega = q*sqrt(m)/(sin(theta)*(rho2*sqrt(r)+a*q*sqrt(m)*sin(theta))) !shakura 1987 + rdot = 0. + thetadot = 0. + + ! Cartesian coordinates + x1 = sqrt(r**2+a**2)*sin(theta)*cos(phi) + y1 = sqrt(r**2+a**2)*sin(theta)*sin(phi) + z1 = r*cos(theta) + vx = r/sqrt(r**2+a**2)*sin(theta)*cos(phi)*rdot + sqrt(r**2+a**2)*(cos(theta)*cos(phi)*thetadot-sin(theta)*sin(phi)*omega) + vy = r/sqrt(r**2+a**2)*sin(theta)*sin(phi)*rdot + sqrt(r**2+a**2)*(cos(theta)*sin(phi)*thetadot+sin(theta)*cos(phi)*omega) + vz = cos(theta)*rdot-r*sin(theta)*thetadot + + xyz = (/x1,y1,z1/) + vxyz = (/vx,vy,vz/) + + period = 2390. ! approximate + norbits = 4 + tmax = norbits*period + nstepsperorbit = 1000 + dt = 0.239 !period/nstepsperorbit + + call integrate_geodesic(tmax,dt,xyz,vxyz,angmom0,angmom) + + R2 = dot_product(xyz,xyz) + rfinal = sqrt(0.5*(R2-a**2) + 0.5*sqrt((R2-a**2)**2 + 4.*a**2*xyz(3)**2)) + + nerr = 0 + call checkval(angmom(1),angmom0(1),6.e-10,nerr(1),'error in angmomx') + call checkval(angmom(2),angmom0(2),6.e-10,nerr(2),'error in angmomy') + call checkval(angmom(3),angmom0(3),6.e-10,nerr(3),'error in angmomz') + call checkval(rfinal ,r ,5.08e-6,nerr(4),'error in final r position') + + call update_test_scores(ntests,nerr,npass) + +end subroutine test_inccirc + +!----------------------------------------------------------------------- +!+ +! test the geodesic integrator using test particle integration +! and the substep_gr routine +!+ +!----------------------------------------------------------------------- +subroutine integrate_geodesic(tmax,dt,xyz,vxyz,angmom0,angmom) + use io, only:iverbose + use part, only:igas,npartoftype,massoftype,set_particle_type,get_ntypes,ien_type + use substepping, only:substep_gr + use eos, only:ieos + use cons2prim, only:prim2consall + use metric_tools, only:init_metric,unpack_metric + use extern_gr, only:get_grforce_all + real, intent(in) :: tmax,dt + real, intent(inout) :: xyz(3), vxyz(3) + real, intent(out) :: angmom0(3),angmom(3) + integer :: nsteps,ntypes,npart + real :: time,dtextforce,massi,blah + real :: xyzh(4,1),vxyzu(4,1),fext(3,1),pxyzu(4,1),dens(1),metrics(0:3,0:3,2,1),metricderivs(0:3,0:3,3,1) + + npart = 1 + + xyzh = 0. + vxyzu = 0. + pxyzu = 0. + fext = 0. + metrics = 0. + metricderivs = 0. + + xyzh(1:3,1) = xyz(:) + vxyzu(1:3,1) = vxyz(:) + xyzh(4,:) = 1. + vxyzu(4,:) = 0. + massi = 1.e-10 + call set_particle_type(1,igas) + + npartoftype(igas) = npart + massoftype(igas) = massi + ntypes = get_ntypes(npartoftype) + + ! + ! initialise runtime parameters + ! + ieos = 11 + iverbose = 1 + time = 0 + blah = dt + ien_type = 1 + + call init_metric(npart,xyzh,metrics,metricderivs) + call prim2consall(npart,xyzh,metrics,vxyzu,dens,pxyzu,use_dens=.false.) + call get_grforce_all(npart,xyzh,metrics,metricderivs,vxyzu,dens,fext,dtextforce) + call calculate_angmom(xyzh(1:3,1),metrics(:,:,:,1),massi,vxyzu(1:3,1),angmom0) + + nsteps = 0 + do while (time <= tmax) + nsteps = nsteps + 1 + time = time + dt + dtextforce = blah + call substep_gr(npart,ntypes,dt,dtextforce,xyzh,vxyzu,pxyzu,dens,metrics,metricderivs,fext,time) + enddo + + call calculate_angmom(xyzh(1:3,1),metrics(:,:,:,1),massi,vxyzu(1:3,1),angmom) + + xyz(:) = xyzh(1:3,1) + vxyz(:) = vxyzu(1:3,1) + +end subroutine integrate_geodesic + +!----------------------------------------------------------------------- +!+ +! compute the angular momentum for the orbit +!+ +!----------------------------------------------------------------------- +subroutine calculate_angmom(xyzi,metrici,massi,vxyzi,angmomi) + use metric_tools, only:unpack_metric + use vectorutils, only:cross_product3D + use utils_gr, only:dot_product_gr + real, intent(in) :: xyzi(3),metrici(:,:,:),massi,vxyzi(3) + real, intent(out) :: angmomi(3) + real :: alpha_gr,beta_gr_UP(3),bigvi(3),fourvel_space(3),lorentzi,v2i,gammaijdown(3,3) + + call unpack_metric(metrici,betaUP=beta_gr_UP,alpha=alpha_gr,gammaijdown=gammaijdown) + bigvi = (vxyzi+beta_gr_UP)/alpha_gr + v2i = dot_product_gr(bigvi,bigvi,gammaijdown) + lorentzi = 1./sqrt(1.-v2i) + fourvel_space = (lorentzi/alpha_gr)*vxyzi + call cross_product3D(xyzi,fourvel_space,angmomi) ! position cross with four-velocity + angmomi=angmomi*massi + +end subroutine calculate_angmom + +!----------------------------------------------------------------------- +!+ +! Test various combinations of position, velocity and fluid quantities +!+ +!----------------------------------------------------------------------- +subroutine test_combinations_all(ntests,npass) + use eos, only:ieos + integer, intent(inout) :: ntests,npass + integer, parameter :: eos_to_test(2) = (/2,12/) + integer :: i + + do i = 1,size(eos_to_test) + ieos = eos_to_test(i) + call test_combinations(ntests,npass) + enddo + +end subroutine test_combinations_all + +!----------------------------------------------------------------------- +!+ +! Test various combinations of position, velocity and fluid quantities +!+ +!----------------------------------------------------------------------- +subroutine test_combinations(ntests,npass) + use physcon, only:pi + use eos, only:gamma,equationofstate,ieos + use utils_gr, only:dot_product_gr + use metric_tools, only:get_metric,get_metric_derivs,imetric,imet_kerr + use metric, only:metric_type + integer, intent(inout) :: ntests,npass + real :: radii(5),theta(5),phi(5),vx(5),vy(5),vz(5) + real :: utherm(7),density(7),errmax,errmaxg,errmaxc,errmaxd + real :: position(3),v(3),v4(0:3),sqrtg,gcov(0:3,0:3),gcon(0:3,0:3) + real :: ri,thetai,phii,vxi,vyi,vzi,x,y,z,p,t,dens,u,pondens,spsound + real :: dgdx1(0:3,0:3),dgdx2(0:3,0:3),dgdx3(0:3,0:3) + integer :: i,j,k,l,m,n,ii,jj + integer :: ncheck_metric,nfail_metric,ncheck_cons2prim,nfail_cons2prim + integer :: ncheckg,nfailg,ncheckd,nfaild + real, parameter :: tol = 2.e-15 + real, parameter :: tolc = 1.e-12 + real, parameter :: told = 4.e-7 + + write(*,'(/,a)') '--> testing metric and cons2prim with combinations of variables' + write(*,'(a)') ' metric type = '//trim(metric_type) + write(*,'(a,I4,/)') ' eos = ', ieos + + ntests = ntests + 4 + ncheck_metric = 0 + nfail_metric = 0 + ncheckg = 0 + nfailg = 0 + ncheck_cons2prim = 0 + nfail_cons2prim = 0 + ncheckd = 0 + nfaild = 0 + errmax = 0. + errmaxg = 0. + errmaxc = 0. + errmaxd = 0. + + ! ieos=12 + gamma = 5./3. + + radii = (/2.1,2.5,3.0,5.0,10.0/) + theta = (/0.,pi/4.,pi/2.,3.*pi/4.,pi/) + phi = (/0.,pi/4.,pi/2.,pi,3.*pi/2./) + + vx = (/0.,0.25,0.5,0.75,1./) + vy = vx + vz = vx + + utherm = (/1.e-3,1.,10.,100.,1000.,1.e5,1.e7/) + density = (/1.e-10,1.e-5,1.e-3,1.,10.,100.,1000./) + + t = -1. ! initial temperature guess to avoid complier warning + + do i=1,size(radii) + ri = radii(i) + do j=1,size(theta) + thetai = theta(j) + do k=1,size(phi) + phii = phi(k) + x = ri*sin(thetai)*cos(phii) + y = ri*sin(thetai)*sin(phii) + z = ri*cos(thetai) + position = (/x,y,z/) + + call get_metric(position,gcov,gcon,sqrtg) + call test_metric_i(gcov,gcon,sqrtg,ncheck_metric,nfail_metric,errmax,ncheckg,nfailg,errmaxg,tol) + + ! Check below is because Kerr metric derivatives currently badly behaved at the poles + ! Would be nice to remove this... + if ((imetric /= imet_kerr) .or. (x**2 + y**2 > 1.e-12)) then + call get_metric_derivs(position,dgdx1,dgdx2,dgdx3) + call test_metric_derivs_i(position,dgdx1,dgdx2,dgdx3,ncheckd,nfaild,errmaxd,told) + endif + + do l=1,size(vx) + vxi=vx(l) + do m=1,size(vy) + vyi=vy(m) + do n=1,size(vz) + vzi=vz(n) + + v = (/vxi,vyi,vzi/) + v4(0) = 1. + v4(1:3) = v(:) + + ! Only allow valid combinations of position and velocity to be tested. + ! i.e. Not faster than the speed of light locally (U0 real, not imaginary). + if (dot_product_gr(v4,v4,gcov) < 0.) then + do ii=1,size(utherm) + u = utherm(ii) + do jj=1,size(density) + dens = density(jj) + call equationofstate(ieos,pondens,spsound,dens,x,y,z,t,u) + p = pondens*dens + call test_cons2prim_i(position,v,dens,u,p,ncheck_cons2prim,nfail_cons2prim,errmaxc,tolc) + enddo + enddo + endif + + enddo + enddo + enddo + enddo + enddo + enddo + + call checkvalbuf_end('inv * metric = identity',ncheck_metric,nfail_metric,errmax,tol) + call checkvalbuf_end('sqrt g = -det(g)',ncheckg,nfailg,errmaxg,tol) + call checkvalbuf_end('d/dx^i g_munu',ncheckd,nfaild,errmaxd,told) + call checkvalbuf_end('conservative to primitive',ncheck_cons2prim,nfail_cons2prim,errmaxc,tolc) + if (nfail_metric==0) npass = npass + 1 + if (nfailg==0) npass = npass + 1 + if (nfaild==0) npass = npass + 1 + if (nfail_cons2prim==0) npass = npass + 1 + +end subroutine test_combinations + +!---------------------------------------------------------------- +!+ +! Test of the metric +!+ +!---------------------------------------------------------------- +subroutine test_metric_i(gcov,gcon,sqrtg,ncheck,nfail,errmax,ncheckg,nfailg,errmaxg,tol) + use inverse4x4, only:inv4x4 + integer, intent(inout) :: ncheck,nfail,ncheckg,nfailg + real, intent(in) :: gcov(0:3,0:3),gcon(0:3,0:3),sqrtg,tol + real, intent(inout) :: errmax,errmaxg + real, dimension(0:3,0:3) :: gg + real :: sum,det + integer :: i,j + + ! Product of metric and its inverse + gg = 0. + gg = matmul(gcov,gcon) + sum = 0 + do j=0,3 + do i=0,3 + sum = sum + gg(i,j) + enddo + enddo + + ! Check to see that the product is 4 (trace of identity) + call checkvalbuf(sum,4.,tol,'[F]: gddgUU ',nfail,ncheck,errmax) + + !if (nfail /= 0) then + ! print*,' metric ' + ! print "(4(es10.3,1x))",gcov + ! print*,' inverse ' + ! print "(4(es10.3,1x))",gcon + ! print*,' gg ' + ! print "(4(es10.3,1x))",gg + ! print*, 'gdown*gup /= Identity' + !endif + + ! Check that the determinant of the metric matches the one returned + call inv4x4(gcov,gg,det) + call checkvalbuf(-det,sqrtg,tol,'sqrt(g) ',nfailg,ncheckg,errmaxg) + +end subroutine test_metric_i + +!---------------------------------------------------------------- +!+ +! Check that analytic metric derivs give similar answer to +! numerical differences of the metric +!+ +!---------------------------------------------------------------- +subroutine test_metric_derivs_i(x,dgdx1,dgdx2,dgdx3,ncheck,nfail,errmax,tol) + use metric_tools, only:numerical_metric_derivs + real, intent(in) :: x(1:3),dgdx1(0:3,0:3),dgdx2(0:3,0:3),dgdx3(0:3,0:3),tol + integer, intent(inout) :: ncheck,nfail + real, intent(inout) :: errmax + real :: dgdx_1(0:3,0:3),dgdx_2(0:3,0:3),dgdx_3(0:3,0:3) + integer :: j,i + + call numerical_metric_derivs(x,dgdx_1,dgdx_2,dgdx_3) + do j=0,3 + do i=0,3 + call checkvalbuf(dgdx1(i,j),dgdx_1(i,j),tol,'dgcov/dx',nfail,ncheck,errmax) + call checkvalbuf(dgdx2(i,j),dgdx_2(i,j),tol,'dgcov/dy',nfail,ncheck,errmax) + call checkvalbuf(dgdx3(i,j),dgdx_3(i,j),tol,'dgcov/dz',nfail,ncheck,errmax) + enddo + enddo + +end subroutine test_metric_derivs_i + +!---------------------------------------------------------------- +!+ +! Test of the conservative to primitive variable solver +!+ +!---------------------------------------------------------------- +subroutine test_cons2prim_i(x,v,dens,u,p,ncheck,nfail,errmax,tol) + use cons2primsolver, only:conservative2primitive,primitive2conservative + 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 + + real, intent(in) :: x(1:3),v(1:3),dens,p,tol + real, intent(inout) :: u + integer, intent(inout) :: ncheck,nfail + real, intent(inout) :: errmax + real :: metrici(0:3,0:3,2) + real :: rho2,pmom2(1:3),en2,temp + real :: p2,u2,t2,dens2,gamma2,v2(1:3) + real :: pondens2,spsound2 + real :: v_out(1:3),dens_out,u_out,p_out,gamma_out + real :: toli + integer :: ierr,i,j,nfailprev,ien_type + real, parameter :: tolg = 1.e-7, tolp = 1.5e-6 + + ! perturb the state + dens2 = 2.*dens + u2 = 2.*u + t2 = -1. + + call equationofstate(ieos,pondens2,spsound2,dens2,x(1),x(2),x(3),t2,u2) + P2 = pondens2 * dens2 + v2 = v + + over_energy_variables: do i = 1,3 + ! Used for initial guess in conservative2primitive + v_out = v + dens_out = dens + u_out = u + p_out = p + gamma_out = 1. + p/(dens*u) + errmax = 0. + nfailprev = nfail + temp = 1.e7 ! arbitrary initial guess + gamma2 = 1. + P2/(dens2*u2) + + call pack_metric(x,metrici) + if (ieos == 12 .and. i /= 3) then + ! entropy_K and etotal cannot use with gasplusrad eos + cycle + elseif (i == 1) then + ien_type = ien_entropy + toli = 1.5e-11 + elseif (i == 2) then + ien_type = ien_etotal + toli = 1.5e-9 + else + ien_type = ien_entropy_s + toli = 1.5e-11 + endif + + call primitive2conservative(x,metrici,v,dens2,u2,P2,rho2,pmom2,en2,ien_type) + call conservative2primitive(x,metrici,v_out,dens_out,u_out,p_out,temp,gamma_out,rho2,pmom2,en2,ierr,ien_type) + + call checkvalbuf(ierr,0,0,'[F]: ierr (convergence)',nfail,ncheck) + do j=1,3 + call checkvalbuf(v_out(j),v2(j),toli,'[F]: v_out',nfail,ncheck,errmax) + enddo + call checkvalbuf(dens_out,dens2,toli,'[F]: dens_out',nfail,ncheck,errmax) + call checkvalbuf(u_out,u2,toli,'[F]: u_out',nfail,ncheck,errmax) + call checkvalbuf(p_out,p2,tolp,'[F]: p_out',nfail,ncheck,errmax) + call checkvalbuf(gamma_out,gamma2,tolg,'[F]: gamma_out',nfail,ncheck,errmax) + + if (nfail > nfailprev .and. nfail < 10) then + print*,'-- cons2prim test failed with' + print*,' ien_type =',ien_type + print*,' ieos =',ieos + print*,' - IN:' + print*,' x =',x + print*,' v =',v2 + print*,' dens =',dens2 + print*,' u =',u2 + print*,' p =',p2 + print*,' gamma=',gamma2 + print*,' - OUT:' + print*,' v =',v_out + print*,' dens =',dens_out + print*,' u =',u_out + print*,' p =',p_out + print*,' gamma=',gamma_out + print*,'' + endif + enddo over_energy_variables + +end subroutine test_cons2prim_i + +end module testgr diff --git a/src/tests/test_mpi.f90 b/src/tests/test_mpi.f90 new file mode 100644 index 000000000..e318998d9 --- /dev/null +++ b/src/tests/test_mpi.f90 @@ -0,0 +1,100 @@ +!--------------------------------------------------------------------------! +! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! See LICENCE file for usage and distribution conditions ! +! http://phantomsph.github.io/ ! +!--------------------------------------------------------------------------! +module testmpi +! +! MPI unit tests +! +! :References: None +! +! :Owner: David Liptai +! +! :Runtime parameters: None +! +! :Dependencies: io, mpiforce, mpimemory, physcon, testutils, units +! + use testutils, only:checkval,checkvalbuf,checkvalbuf_end,update_test_scores + implicit none + + public :: test_mpi + + private + +contains + +subroutine test_mpi(ntests,npass) + use io, only:id,master + use units, only:set_units + use physcon, only:solarm + integer, intent(inout) :: ntests,npass + + call set_units(mass=1.d6*solarm,G=1.d0,c=1.d0) + if (id==master) write(*,"(/,a,/)") '--> TESTING MPI' + call test_increase_mpi_memory(ntests,npass) + if (id==master) write(*,"(/,a)") '<-- MPI TESTS COMPLETE' + +end subroutine test_mpi + +subroutine test_increase_mpi_memory(ntests,npass) + use mpimemory, only:allocate_mpi_memory,increase_mpi_memory,& + deallocate_mpi_memory,stacksize,force_stack_1,& + push_onto_stack + use mpiforce, only:cellforce + integer, intent(inout) :: ntests,npass + integer, parameter :: new_stacksize=100 + type(cellforce) :: cell + integer :: nerr(3), ncheck(3), i, stacksize_orig + real :: maxerr(3) + + nerr = 0 + ncheck = 0 + maxerr = 0. + + ! Save original stacksize, assuming they're the same for dens and force + stacksize_orig = stacksize + + ! Deallocate existing stack + call deallocate_mpi_memory + + ! Allocate the stacks again at a smaller size. + call allocate_mpi_memory(stacksize_in=new_stacksize) + + ! Write some data to each cell + do i=1,new_stacksize + cell%xpos = [1.,2.,3.] * i + call push_onto_stack(force_stack_1, cell) + enddo + + ! Ensure size of force_stack_1 is what we expect it to be + call checkval(force_stack_1%n,new_stacksize,0,nerr(1),'stacksize after pushing cells') + call update_test_scores(ntests,nerr,npass) + + ! Trigger a stacksize increase - if this doesn't segfault, that's a good sign + call increase_mpi_memory + + ! Ensure stack size hasn't changed + call checkval(force_stack_1%n,new_stacksize,0,nerr(1),'stacksize after mem increase') + call update_test_scores(ntests,nerr,npass) + + ! Check cell data is the same as what was written into cells above + do i=1,new_stacksize + call checkvalbuf(force_stack_1%cells(i)%xpos(1),1.*i,1.e-15,'error in xpos(1) after mem increase',nerr(1),ncheck(1),maxerr(1)) + call checkvalbuf(force_stack_1%cells(i)%xpos(2),2.*i,1.e-15,'error in xpos(2) after mem increase',nerr(2),ncheck(2),maxerr(2)) + call checkvalbuf(force_stack_1%cells(i)%xpos(3),3.*i,1.e-15,'error in xpos(3) after mem increase',nerr(3),ncheck(3),maxerr(3)) + enddo + + call checkvalbuf_end('error in xpos(1) after mem increase asfgd',ncheck(1),nerr(1),maxerr(1),1.e-15) + call checkvalbuf_end('error in xpos(2) after mem increase asfgd',ncheck(2),nerr(2),maxerr(2),1.e-15) + call checkvalbuf_end('error in xpos(3) after mem increase asfgd',ncheck(3),nerr(3),maxerr(3),1.e-15) + call update_test_scores(ntests,nerr,npass) + + ! Reallocate previous stack + call deallocate_mpi_memory + call allocate_mpi_memory(stacksize_in=stacksize_orig) + +end subroutine test_increase_mpi_memory + +end module testmpi diff --git a/src/tests/test_ptmass.f90 b/src/tests/test_ptmass.f90 index 966a77727..19de0ed9c 100644 --- a/src/tests/test_ptmass.f90 +++ b/src/tests/test_ptmass.f90 @@ -14,11 +14,11 @@ module testptmass ! ! :Runtime parameters: None ! -! :Dependencies: boundary, checksetup, deriv, dim, energies, eos, -! extern_binary, externalforces, gravwaveutils, io, kdtree, kernel, -! mpiutils, options, part, physcon, ptmass, random, setbinary, setdisc, -! spherical, step_lf_global, stretchmap, testutils, timestep, timing, -! units +! :Dependencies: HIIRegion, boundary, checksetup, deriv, dim, energies, +! eos, eos_HIIR, extern_binary, externalforces, gravwaveutils, io, +! kdtree, kernel, mpiutils, options, part, physcon, ptmass, random, +! setbinary, setdisc, spherical, step_lf_global, stretchmap, testutils, +! timestep, timing, units ! use testutils, only:checkval,update_test_scores implicit none @@ -40,7 +40,7 @@ subroutine test_ptmass(ntests,npass,string) integer, intent(inout) :: ntests,npass integer :: itmp,ierr,itest,istart logical :: do_test_binary,do_test_accretion,do_test_createsink,do_test_softening - logical :: do_test_chinese_coin,do_test_merger + logical :: do_test_chinese_coin,do_test_merger,do_test_potential,do_test_HII logical :: testall if (id==master) write(*,"(/,a,/)") '--> TESTING PTMASS MODULE' @@ -50,7 +50,9 @@ subroutine test_ptmass(ntests,npass,string) do_test_createsink = .false. do_test_softening = .false. do_test_merger = .false. + do_test_potential = .false. do_test_chinese_coin = .false. + do_test_HII = .false. testall = .false. istart = 1 select case(trim(string)) @@ -64,6 +66,8 @@ subroutine test_ptmass(ntests,npass,string) do_test_softening = .true. case('ptmassmerger') do_test_merger = .true. + case('ptmasspotential') + do_test_potential = .true. case('ptmasschinchen','ptmasscoin','chinchen','coin','chinesecoin') do_test_chinese_coin = .true. case('ptmassfsi','fsi') @@ -71,6 +75,9 @@ subroutine test_ptmass(ntests,npass,string) do_test_binary = .true. do_test_softening = .true. do_test_merger = .true. + case('ptmassHII') + do_test_HII = .true. + case default testall = .true. end select @@ -111,6 +118,10 @@ subroutine test_ptmass(ntests,npass,string) if (do_test_merger .or. testall) call test_merger(ntests,npass) enddo ! + ! Test of sink particle potentials + ! + if (do_test_potential .or. testall) call test_sink_potential(ntests,npass) + ! ! Tests of accrete_particle routine ! if (do_test_accretion .or. testall) then @@ -123,6 +134,8 @@ subroutine test_ptmass(ntests,npass,string) ! if (do_test_createsink .or. testall) call test_createsink(ntests,npass) + if (do_test_HII) call test_HIIregion(ntests,npass) + !reset stuff and clean up temporary files itmp = 201 nptmass = 0 @@ -621,7 +634,8 @@ subroutine test_accretion(ntests,npass,itest) use io, only:id,master use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,massoftype, & npart,npartoftype,xyzh,vxyzu,fxyzu,igas,ihacc,& - isdead_or_accreted,set_particle_type,ndptmass,hfact + isdead_or_accreted,set_particle_type,ndptmass,hfact,& + linklist_ptmass use ptmass, only:ptmass_accrete,update_ptmass use energies, only:compute_energies,angtot,etot,totmom use mpiutils, only:bcast_mpi,reduce_in_place_mpi @@ -701,7 +715,7 @@ subroutine test_accretion(ntests,npass,itest) call ptmass_accrete(1,nptmass,xyzh(1,i),xyzh(2,i),xyzh(3,i),xyzh(4,i),& vxyzu(1,i),vxyzu(2,i),vxyzu(3,i),fxyzu(1,i),fxyzu(2,i),fxyzu(3,i), & igas,massoftype(igas),xyzmh_ptmass,vxyz_ptmass, & - accreted,dptmass_thread,t,1.0,ibin_wakei,ibin_wakei) + accreted,dptmass_thread,linklist_ptmass,t,1.0,ibin_wakei,ibin_wakei) endif enddo !$omp enddo @@ -766,17 +780,19 @@ subroutine test_createsink(ntests,npass) use part, only:init_part,npart,npartoftype,igas,xyzh,massoftype,hfact,rhoh,& iphase,isetphase,fext,divcurlv,vxyzu,fxyzu,poten, & nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,ndptmass, & - dptmass,fxyz_ptmass_sinksink + dptmass,fxyz_ptmass_sinksink,linklist_ptmass use ptmass, only:ptmass_accrete,update_ptmass,icreate_sinks,& - ptmass_create,finish_ptmass,ipart_rhomax,h_acc,rho_crit,rho_crit_cgs + ptmass_create,finish_ptmass,ipart_rhomax,h_acc,rho_crit,rho_crit_cgs, & + ptmass_create_stars,tmax_acc,tseeds,ipart_createseeds,ipart_createstars,& + ptmass_create_seeds use energies, only:compute_energies,angtot,etot,totmom use mpiutils, only:bcast_mpi,reduce_in_place_mpi,reduceloc_mpi,reduceall_mpi use spherical, only:set_sphere use stretchmap, only:rho_func integer, intent(inout) :: ntests,npass - integer :: i,itest,itestp,nfailed(3),imin(1) + integer :: i,itest,itestp,nfailed(4),imin(1) integer :: id_rhomax,ipart_rhomax_global - real :: psep,totmass,r2min,r2,t + real :: psep,totmass,r2min,r2,t,coremass,starsmass real :: etotin,angmomin,totmomin,rhomax,rhomax_test procedure(rho_func), pointer :: density_func @@ -785,8 +801,10 @@ subroutine test_createsink(ntests,npass) iverbose = 1 rho_crit = rho_crit_cgs - do itest=1,2 + do itest=1,3 select case(itest) + case(3) + if (id==master) write(*,"(/,a)") '--> testing sink particle creation (cores and stars prescription)' case(2) if (id==master) write(*,"(/,a)") '--> testing sink particle creation (sin)' case default @@ -827,7 +845,16 @@ subroutine test_createsink(ntests,npass) ! and make sure that gravitational potential energy has been computed ! tree_accuracy = 0. - icreate_sinks = 1 + if (itest==3) then + icreate_sinks = 2 + linklist_ptmass = -1 + tmax_acc = 0. + tseeds = 0. + ipart_createseeds = 1 + ipart_createstars = 1 + else + icreate_sinks = 1 + endif call get_derivs_global() @@ -886,12 +913,31 @@ subroutine test_createsink(ntests,npass) call reduceloc_mpi('max',ipart_rhomax_global,id_rhomax) endif call ptmass_create(nptmass,npart,itestp,xyzh,vxyzu,fxyzu,fext,divcurlv,poten,& - massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,dptmass,0.) + massoftype,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,fxyz_ptmass_sinksink,linklist_ptmass,dptmass,0.) + if (itest==3) then + coremass = 0. + starsmass = 0. + xyzmh_ptmass(4,1) = xyzmh_ptmass(4,1)*6e33 + coremass = xyzmh_ptmass(4,1) + call ptmass_create_seeds(nptmass,ipart_createseeds,xyzmh_ptmass,linklist_ptmass,0.) + call ptmass_create_stars(nptmass,ipart_createstars,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass, & + fxyz_ptmass_sinksink,linklist_ptmass,0.) + do i=1,nptmass + starsmass = starsmass + xyzmh_ptmass(4,i) + enddo + xyzmh_ptmass(4,1) = coremass/6e33 + xyzmh_ptmass(4,:) = 0. + endif ! ! check that creation succeeded ! nfailed(:) = 0 - call checkval(nptmass,1,0,nfailed(1),'nptmass=1') + if (itest == 3) then + call checkval(nptmass,3,3,nfailed(1),'nptmass=nseeds') + call checkval(starsmass-coremass,0.,0.,nfailed(4),'Mass conservation') + else + call checkval(nptmass,1,0,nfailed(1),'nptmass=1') + endif call update_test_scores(ntests,nfailed,npass) ! ! check that linear and angular momentum and energy is conserved @@ -1111,6 +1157,174 @@ subroutine test_merger(ntests,npass) end subroutine test_merger +subroutine test_HIIregion(ntests,npass) + use dim, only:maxp,maxphase,maxvxyzu + use io, only:id,master,iverbose,iprint + use eos_HIIR, only:polykion,init_eos_HIIR + use eos, only:gmw,ieos,polyk,gamma + use deriv, only:get_derivs_global + use part, only:nptmass,xyzmh_ptmass,vxyz_ptmass, & + npart,ihacc,irstrom,xyzh,vxyzu,hfact,igas, & + npartoftype,fxyzu,massoftype,isionised,init_part,& + iphase,isetphase,irateion,irstrom + use ptmass, only:h_acc + use step_lf_global, only:init_step,step + use spherical, only:set_sphere + use units, only:set_units,utime,unit_velocity,udist,umass + use physcon, only:pc,solarm,years,pi,kboltz,mass_proton_cgs + use kernel, only: hfact_default + use kdtree, only:tree_accuracy + use testutils, only: checkval,update_test_scores + use HIIRegion, only:initialize_H2R,update_ionrate,HII_feedback,iH2R,nHIIsources,ar,mH + integer, intent(inout) :: ntests,npass + integer :: np,i,nfailed(1) + real :: totmass,psep + real :: Rstrom,ci,k,rho0 + real :: totvol,nx,rmin,rmax,temp + if (id==master) write(iprint,"(/,a)") '--> testing HII region expansion around massive stars...' + + call set_units(dist=pc,mass=solarm,G=1.d0) + call init_eos_HIIR() + iverbose = 0 + ! + ! initialise arrays to zero + ! + call init_part() + gmw = 1.0 + + xyzmh_ptmass(:,:) = 0. + vxyz_ptmass(:,:) = 0. + + h_acc = 0.002 + + xyzmh_ptmass(4,1) = -1. + xyzmh_ptmass(irateion,1) = 49. ! rate_ion [s^-1] + nptmass = 1 + nHIIsources = 1 + + hfact = 1.2 + gamma = 1. + rmin = 0. + rmax = 2.91*pc/udist + ieos = 21 + tree_accuracy = 0.5 + temp = 1000. +! +!--setup particles +! + np = 1000000 + totvol = 4./3.*pi*rmax**3 + nx = int(np**(1./3.)) + psep = totvol**(1./3.)/real(nx) + npart = 0 + ! only set up particles on master, otherwise we will end up with n duplicates + if (id==master) then + call set_sphere('cubic',id,master,rmin,rmax,psep,hfact,npart,xyzh,np_requested=np) + endif + np = npart + + +! +!--set particle properties +! + totmass = 8.e3*solarm/umass + npartoftype(:) = 0 + npartoftype(igas) = npart + massoftype(:) = 0.0 + massoftype(igas) = totmass/npartoftype(igas) + if (maxphase==maxp) then + do i=1,npart + iphase(i) = isetphase(igas,iactive=.true.) + enddo + endif + + + iH2R = 1 + if (id==master) then + call initialize_H2R + !call HII_feedback(nptmass,npart,xyzh,xyzmh_ptmass,vxyz_ptmass,isionised) + endif + + rho0 = totmass/totvol + + Rstrom = 10**((1./3)*(log10(((3*mH**2)/(4*pi*ar*rho0**2)))+xyzmh_ptmass(irateion,1)+log10(utime))) + xyzmh_ptmass(irstrom,1) = -1. + ci = sqrt(polykion) + k = 0.005 + + polyk = (kboltz*temp)/(gmw*mass_proton_cgs)*((unit_velocity)**2) + vxyzu(:,:) = 0. + fxyzu(:,:) = 0. + if (maxvxyzu >= 4) then + vxyzu(4,:) = polyk + ieos = 22 + endif + + call get_derivs_global() + + call HII_feedback(nptmass,npart,xyzh,xyzmh_ptmass,vxyz_ptmass,isionised) + + call checkval(xyzmh_ptmass(irstrom,1),Rstrom,1.e-2,nfailed(1),'Initial strömgren radius') + + call update_test_scores(ntests,nfailed,npass) + +end subroutine test_HIIregion + +!----------------------------------------------------------------------- +!+ +! Test sink particle surface force, simply that the acceleration +! is the gradient of the potential +!+ +!----------------------------------------------------------------------- +subroutine test_sink_potential(ntests,npass) + use io, only:id,master + use testutils, only:checkval,update_test_scores + use ptmass, only:get_accel_sink_gas,isink_potential + use part, only:npart,npartoftype,nptmass,xyzmh_ptmass,ihacc,iReff + use units, only:set_units + integer, intent(inout) :: ntests,npass + integer :: nfailed(1) + real :: phi1,phi,eps,x0(3) + real :: dphidx,hi,xi,yi,zi,dumxi,dumyi,dumzi,fxi,fyi,fzi,rp + + if (id==master) write(*,"(/,a)") '--> testing sink particle surface force' + nptmass = 1 + npart = 0 + npartoftype = 0 + hi = 0. + x0 = [100.,100.,100.] + rp = 2. + isink_potential = 1 + ! place a single point mass at a random location + xyzmh_ptmass(:,:) = 0. + xyzmh_ptmass(1:3,1) = x0 + xyzmh_ptmass(4,1) = 3.14159 + xyzmh_ptmass(ihacc,1) = 0. + xyzmh_ptmass(iReff,1) = rp ! surface radius = 2 + + call set_units(mass=1.d0,dist=1.d0,G=1.d0) + + ! evaluate sink-gas acceleration at some position + xi = x0(1) + 1.00001*rp + yi = x0(2) + 1.*rp + zi = x0(3) + 1.*rp + fxi = 0.; fyi = 0.; fzi = 0.; phi = 0. + call get_accel_sink_gas(nptmass,xi,yi,zi,hi,xyzmh_ptmass,fxi,fyi,fzi,phi) + ! evaluate sink-gas acceleration at some position + epsilon + eps = 1.e-6 + dumxi = 0.; dumyi = 0.; dumzi = 0.; phi1 = 0. + call get_accel_sink_gas(nptmass,xi+eps,yi,zi,hi,xyzmh_ptmass,dumxi,dumyi,dumzi,phi1) + ! get the derivative of phi and check it equals the acceleration + dphidx = -(phi1 - phi)/eps + + call checkval(dphidx,fxi,3.3e-8,nfailed(1),'dphi/dx = acceleration') + call update_test_scores(ntests,nfailed(1:1),npass) + + ! reset options + isink_potential = 0 + +end subroutine test_sink_potential + !----------------------------------------------------------------------- !+ ! Helper function used in sink particle creation test diff --git a/src/tests/testsuite.F90 b/src/tests/testsuite.F90 index a5c129f0d..daa5e8f4f 100644 --- a/src/tests/testsuite.F90 +++ b/src/tests/testsuite.F90 @@ -447,7 +447,7 @@ subroutine testsuite(string,first,last,ntests,npass,nfail) "|_| /_/ \_\____/____/ " write(*,"(a)") 'TEST SUITE PASSED' - call system("say OK") + call system("say fantastic!") else write(*,"(5(a,/))") & " _____ _ ___ _ ", & diff --git a/src/utils/struct_part.f90 b/src/utils/struct_part.f90 index 781a3c2fd..99640148d 100644 --- a/src/utils/struct_part.f90 +++ b/src/utils/struct_part.f90 @@ -149,10 +149,10 @@ subroutine get_structure_fn(sf,nbins,norder,distmin,distmax,xbins,ncount,npart,x !$omp reduction(+:sf) do ipt=1,npts !$ if (.false.) then - if (mod(ipt,100)==0) then - call cpu_time(tcpu2) - print*,' ipt = ',ipt,tcpu2-tcpu1 - endif + if (mod(ipt,100)==0) then + call cpu_time(tcpu2) + print*,' ipt = ',ipt,tcpu2-tcpu1 + endif !$ endif i = list(ipt) xpt(1) = xyz(1,i) From 7a0c0cefc551ab4e2c03e6dba13c1f296610b9fc Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 31 Jul 2024 17:27:47 +0100 Subject: [PATCH 140/182] Changes Stamatellos EOS to ieos=23 --- src/main/cooling.f90 | 2 +- src/main/cooling_radapprox.f90 | 2 +- src/main/eos.f90 | 26 +++++++++++++------------- src/main/readwrite_infile.F90 | 6 +++--- src/main/step_leapfrog.F90 | 10 +++------- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 1952563f7..abfe84a1b 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -86,7 +86,7 @@ subroutine init_cooling(id,master,iprint,ierr) call init_cooling_ism() if (icooling==8) cooling_in_step = .false. case(9) - if (ieos /= 21 ) call fatal('cooling','icooling=9 requires ieos=21',& + if (ieos /= 23 ) call fatal('cooling','icooling=9 requires ieos=23',& 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) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 62dc0eb02..f5edfaf8b 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -467,7 +467,7 @@ subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr ngot = ngot + 1 case('ieos') read(valstring,*,iostat=ierr) ieosread - if (ieosread /= 21) call fatal('ieosread','For icooling=9, you need ieos=21') + if (ieosread /= 23) call fatal('ieosread','For icooling=9, you need ieos=23') case default imatch = .false. end select diff --git a/src/main/eos.f90 b/src/main/eos.f90 index ef1a8293c..d1869ca66 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -27,7 +27,7 @@ module eos ! 16 = Shen eos ! 17 = polytropic EOS with varying mu (depending on H2 formation) ! 20 = Ideal gas + radiation + various forms of recombination energy from HORMONE (Hirai et al., 2020) -! 21 = read tabulated eos (for use with icooling == 9) +! 23 = read tabulated eos (for use with icooling == 9) ! ! :References: ! Lodato & Pringle (2007) @@ -50,7 +50,7 @@ module eos use part, only:ien_etotal,ien_entropy,ien_type use dim, only:gr implicit none - integer, parameter, public :: maxeos = 22 + integer, parameter, public :: maxeos = 23 real, public :: polyk, polyk2, gamma real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 logical, public :: extract_eos_from_hdr = .false. @@ -431,13 +431,13 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam if (present(mu_local)) mu_local = 1./imui if (present(gamma_local)) gamma_local = gammai -! case(21) - ! call get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) + case(21) + call get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) case(22) call get_eos_HIIR_adiab(polyk,temperature_coef,mui,tempi,ponrhoi,rhoi,eni,gammai,spsoundi,isionisedi) - case(21) + case(23) ! !--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=9 ! @@ -556,14 +556,14 @@ subroutine init_eos(eos_type,ierr) ierr = ierr_option_conflict endif - case(21) + case(21,22) + call init_eos_HIIR() + + case(23) call read_optab(eos_file,ierr) if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) call init_S07cool -! - case(21,22) - case(22) - call init_eos_HIIR() end select done_init_eos = .true. @@ -595,7 +595,7 @@ subroutine finish_eos(eos_type,ierr) ! call finish_eos_mesa - case(21) + case(23) ! Stamatellos deallocation call finish_S07cool @@ -1288,7 +1288,7 @@ logical function eos_outputs_mu(ieos) select case(ieos) case(20) eos_outputs_mu = .true. - case(21) + case(23) eos_outputs_mu = .true. case default eos_outputs_mu = .false. @@ -1374,7 +1374,7 @@ subroutine eosinfo(eos_type,iprint) write(*,'(1x,a,f10.6,a,f10.6)') 'Using fixed composition X = ',X_in,", Z = ",Z_in endif - case(21) + case(23) write(iprint,"(/,a,a)") 'Using tabulated Eos from file:', eos_file, 'and calculated gamma.' end select write(iprint,*) @@ -1430,7 +1430,7 @@ subroutine read_headeropts_eos(ieos,hdr,ierr) if (maxvxyzu >= 4) then if (use_krome) then write(iprint,*) 'KROME eos: initial gamma = 1.666667' - elseif (ieos==21) then + elseif (ieos==23) then write(iprint,*) 'Tabulated eos with derived gamma' else write(iprint,*) 'adiabatic eos: gamma = ',gamma diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index 35bfa31ae..8a7272e4f 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -217,7 +217,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) ! call write_options_eos(iwritein) if (maxvxyzu >= 4 .and. (ieos==2 .or. ieos==5 .or. ieos==10 .or. ieos==15 .or. ieos==12 .or. ieos==16 & - .or. ieos==17 .or. ieos==21) ) then + .or. ieos==17 .or. ieos==21) .or. ieos==23 ) then call write_inopt(ipdv_heating,'ipdv_heating','heating from PdV work (0=off, 1=on)',iwritein) call write_inopt(ishock_heating,'ishock_heating','shock heating (0=off, 1=on)',iwritein) if (mhd) then @@ -693,14 +693,14 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) #ifndef MCFOST if (maxvxyzu >= 4 .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /= 4 .and. ieos /= 10 .and. & ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 17 .and. & - ieos /= 20 .and. ieos/=21 .and. ieos/=22)) & + ieos /= 20 .and. ieos/=21 .and. ieos/=22 .and. ieos/=23)) & call fatal(label,'only ieos=2 makes sense if storing thermal energy') #endif if (irealvisc < 0 .or. irealvisc > 12) call fatal(label,'invalid setting for physical viscosity') if (shearparam < 0.) call fatal(label,'stupid value for shear parameter (< 0)') if (irealvisc==2 .and. shearparam > 1) call error(label,'alpha > 1 for shakura-sunyaev viscosity') if (iverbose > 99 .or. iverbose < -9) call fatal(label,'invalid verboseness setting (two digits only)') - if (icooling > 0 .and. .not.(ieos == 2 .or. ieos == 5 .or. ieos == 17 .or. ieos == 21)) & + if (icooling > 0 .and. .not.(ieos == 2 .or. ieos == 5 .or. ieos == 17 .or. ieos == 21 .or. ieos == 23)) & call fatal(label,'cooling requires adiabatic eos (ieos=2)') if (icooling > 0 .and. (ipdv_heating <= 0 .or. ishock_heating <= 0)) & call fatal(label,'cooling requires shock and work contributions') diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index a18c9f972..d6167ab5b 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -167,7 +167,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) store_itype = (maxphase==maxp .and. ntypes > 1) ialphaloc = 2 nvfloorp = 0 -! print *, "L197 predictor, maxmin abs fxyzu=", maxval(abs(fxyzu(4,1:npart))),minval(abs(fxyzu(4,1:npart))) !$omp parallel do default(none) & !$omp shared(npart,xyzh,vxyzu,fxyzu,iphase,hdtsph,store_itype) & !$omp shared(rad,drad,pxyzu) & @@ -405,7 +404,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) call fatal('step','step too small: bin would exceed maximum') endif endif -! print *, "line 407", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)), "nactive=", nactive + ! ! if using super-timestepping, determine what dt will be used on the next loop ! @@ -422,7 +421,6 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) ! forces we must iterate until velocities agree. !------------------------------------------------------------------------- -! print *, "line 423", "max u=", maxval(vxyzu(4,:)), "max pred", maxval(vpred(4,:)) its = 0 converged = .false. errmaxmean = 0.0 @@ -697,11 +695,9 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) print *, "after 2nd derivs:vpred", maxval(vpred(4,:)), minval(vpred(4,:)) endif endif - if (icooling == 9) then + if (icooling == 9 .and. iverbose >=2) then print *, "end of iteration", maxval(vpred(4,:)), minval(vpred(4,:)) - print *, "end of iteration", maxval(vxyzu(4,:)), minval(vxyzu(4,:)) - print *, "end of iteration, dudt", maxval(fxyzu(4,1:npart)), minval(fxyzu(4,1:npart)) - print *, "End of iteration, nactive=", nactive + print *, "end of iteration", maxval(vxyzu(4,:)), minval(vxyzu(4,:)) endif enddo iterations From 832d111611c04f0796ea185aae5d8d5fd2cf646d Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 31 Jul 2024 17:38:57 +0100 Subject: [PATCH 141/182] [indent-bot] standardised indentation --- src/main/cooling.f90 | 4 +- src/main/cooling_radapprox.f90 | 284 ++++++++++++++--------------- src/main/dens.F90 | 218 +++++++++++----------- src/main/eos.f90 | 14 +- src/main/eos_stamatellos.f90 | 58 +++--- src/main/force.F90 | 14 +- src/main/inject_bondi.f90 | 2 +- src/main/inject_firehose.f90 | 2 +- src/main/inject_galcen_winds.f90 | 2 +- src/main/inject_keplerian.f90 | 2 +- src/main/inject_keplerianshear.f90 | 2 +- src/main/inject_rochelobe.f90 | 2 +- src/main/inject_sim.f90 | 4 +- src/main/inject_sne.f90 | 2 +- src/main/inject_steadydisc.f90 | 2 +- src/main/inject_unifwind.f90 | 2 +- src/main/inject_wind.f90 | 2 +- src/main/inject_windtunnel.f90 | 2 +- src/main/porosity.f90 | 6 +- src/main/radiation_utils.f90 | 10 +- src/main/readwrite_infile.F90 | 2 +- src/main/step_leapfrog.F90 | 8 +- src/utils/moddump_radiotde.f90 | 2 +- 23 files changed, 323 insertions(+), 323 deletions(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index abfe84a1b..0bb572586 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -144,7 +144,7 @@ subroutine energ_cooling(xi,yi,zi,ui,rho,dt,divv,dudt,Tdust_in,mu_in,gamma_in,K2 use cooling_koyamainutsuka, only:cooling_KoyamaInutsuka_explicit,& cooling_KoyamaInutsuka_implicit use cooling_radapprox, only:radcool_update_energ - + 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 @@ -223,7 +223,7 @@ subroutine write_options_cooling(iunit) case(7) call write_options_cooling_gammie_PL(iunit) case(9) - call write_options_cooling_radapprox(iunit) + call write_options_cooling_radapprox(iunit) case default call write_options_cooling_solver(iunit) end select diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index f5edfaf8b..cbc532954 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -63,7 +63,7 @@ end subroutine init_star ! ! Do cooling calculation ! -! update energy to return evolved energy array. Called from substep +! update energy to return evolved energy array. Called from substep subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) use io, only:warning use physcon, only:steboltz,pi,solarl,Rg,kb_on_mh,piontwo,rpiontwo @@ -80,149 +80,149 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) real :: cs2,Om2,Hmod2 real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi - coldensi = huge(coldensi) - poti = Gpot_cool(i) - du_FLDi = duFLD(i) - kappaBari = 0d0 - kappaParti = 0d0 - Teqi = huge(Teqi) - tthermi = huge(tthermi) - opaci = epsilon(opaci) - if (abs(ui) < epsilon(ui)) print *, "ui zero", i - - if (isink_star > 0) then - ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + coldensi = huge(coldensi) + poti = Gpot_cool(i) + du_FLDi = duFLD(i) + kappaBari = 0d0 + kappaParti = 0d0 + Teqi = huge(Teqi) + tthermi = huge(tthermi) + opaci = epsilon(opaci) + if (abs(ui) < epsilon(ui)) print *, "ui zero", i + + if (isink_star > 0) then + ri2 = (xi-xyzmh_ptmass(1,isink_star))**2d0 & + (yi-xyzmh_ptmass(2,isink_star))**2d0 & - + (zi-xyzmh_ptmass(3,isink_star))**2d0 - else - ri2 = xi**2d0 + yi**2d0 + zi**2d0 - endif + + (zi-xyzmh_ptmass(3,isink_star))**2d0 + else + ri2 = xi**2d0 + yi**2d0 + zi**2d0 + endif - ! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + ! get opacities & Ti for ui + call getopac_opdep(ui*unit_ergg,rhoi*unit_density,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 - call warning("In radapprox cooling","cooling method not recognised",ival=od_method) - return - end select + 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 + call warning("In radapprox cooling","cooling method not recognised",ival=od_method) + return + 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 + 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 - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) - umini = umini/unit_ergg + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + umini = umini/unit_ergg - 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 + 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 = duSPH(i) + 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 - return - endif - - Teqi = du_tot * opaci*unit_ergg/utime ! physical units - Teqi = Teqi/4.d0/steboltz - Teqi = Teqi + Tmini4 - du_tot = du_tot + dudti_rad - if (Teqi < Tmini4) then - Teqi = Tmini4**(1.0/4.0) - else - Teqi = Teqi**(1.0/4.0) - endif - teqi_store(i) = Teqi + if (doFLD) then + du_tot = duSPH(i) + du_FLDi + else + du_tot = duSPH(i) + endif - if (Teqi > 9e5) then - print *,"i=",i, "duSPH(i)=", duSPH(i), "duradi=", dudti_rad, "Ti=", Ti, & + ! 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 + return + endif + + Teqi = du_tot * opaci*unit_ergg/utime ! physical units + Teqi = Teqi/4.d0/steboltz + Teqi = Teqi + Tmini4 + du_tot = du_tot + dudti_rad + 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 - elseif (Teqi < epsilon(Teqi)) then - print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& + elseif (Teqi < epsilon(Teqi)) then + print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& "Ti=", Ti, "poti=",poti, "rhoi=", rhoi - elseif (Teqi < Tfloor) then - print *, "Teqi=",Teqi, "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& + elseif (Teqi < Tfloor) then + print *, "Teqi=",Teqi, "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& "Ti=", Ti, "poti=",poti, "rhoi=", rhoi - endif - - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg - - ! calculate thermalization timescale - if ((du_tot) == 0.d0) then - tthermi = 0d0 - else - tthermi = abs((ueqi - ui)/(du_tot)) - endif + endif - 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 - ! 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 *, "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 + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + ueqi = ueqi/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 + 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 + ! 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 *, "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 @@ -230,7 +230,7 @@ end subroutine radcool_update_energ ! ! Do cooling calculation ! -! update energy to return evolved energy array. Called from evolve.F90 +! 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 @@ -262,7 +262,7 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) !$omp private(kappaParti,gmwi,Tmini4,dudti_rad,Teqi,Hstam,HLom,du_tot) & !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,dti) & !$omp shared(maxp,maxphase,ibin) reduction(+:n_uevo) - + overpart: do i=1,npart if (maxphase==maxp) then if (iamtype(iphase(i)) /= igas) cycle @@ -279,13 +279,13 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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 + + (xyzh(3,i)-xyzmh_ptmass(3,isink_star))**2d0 else - ri2 = xyzh(1,i)**2d0 + xyzh(2,i)**2d0 + xyzh(3,i)**2d0 + ri2 = xyzh(1,i)**2d0 + xyzh(2,i)**2d0 + xyzh(3,i)**2d0 endif ! get opacities & Ti for ui @@ -311,7 +311,7 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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) + case (4) ! Modified Lombardi method HLom = presi/abs(gradP_cool(i))/rhoi cs2 = presi/rhoi @@ -339,14 +339,14 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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 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) @@ -373,10 +373,10 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& "Ti=", Ti, "poti=",poti, "rhoi=", rhoi endif - + call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg - + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg @@ -388,7 +388,7 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) endif ttherm_store(i) = tthermi - + ! evolve energy if (tthermi == 0d0) then energ(i) = ui ! condition if denominator above is zero @@ -397,7 +397,7 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) 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 diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 81cd68031..14e3c9c07 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -1664,44 +1664,44 @@ 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) - use io, only:error - use dim, only:maxp - use kernel,only:get_kernel,wab0 - use part, only:get_partinfo,iamgas,igas,maxphase,massoftype - use part, only:rhoanddhdrho - use physcon, only:radconst - use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code - use eos_stamatellos, only:getopac_opdep + use io, only:error + use dim, only:maxp + use kernel,only:get_kernel,wab0 + use part, only:get_partinfo,iamgas,igas,maxphase,massoftype + use part, only:rhoanddhdrho + use physcon, only:radconst + use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code + use eos_stamatellos, only:getopac_opdep #ifdef PERIODIC - use boundary, only:dxbound,dybound,dzbound + use boundary, only:dxbound,dybound,dzbound #endif - type(celldens), intent(in) :: cell - 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(:,:) - real, intent(inout) :: lambda(:),urad_FLD(:) - - integer :: icell,i,iamtypei,iamtypej,j,n - logical :: iactivei,iamgasi,iamdusti,ignoreself - logical :: iactivej,iamgasj,iamdustj - real(kind=8) :: hi,hi1,hi21,hi31,hi41 - real :: rhoi,rho1i,dhdrhoi,pmassi,kappabari,kappaparti,Ti,gmwi - real :: xj,yj,zj,dx,dy,dz - real :: rij2,rij,q2i,qi,hj1,hj,hj21,q2j - real :: wabi,grkerni,gradhi,wkerni,dwkerni - real :: pmassj,rhoj,rho1j,dhdrhoj,kappabarj,kappaPartj,Tj,gmwj - real :: uradi,dradi,dradxi,dradyi,dradzi,runix,runiy,runiz - real :: dT4,R_rad - integer :: ngradh_err - real :: uradself - - ngradh_err = 0 - over_parts: do icell = 1,cell%npcell + type(celldens), intent(in) :: cell + 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(:,:) + real, intent(inout) :: lambda(:),urad_FLD(:) + + integer :: icell,i,iamtypei,iamtypej,j,n + logical :: iactivei,iamgasi,iamdusti,ignoreself + logical :: iactivej,iamgasj,iamdustj + real(kind=8) :: hi,hi1,hi21,hi31,hi41 + real :: rhoi,rho1i,dhdrhoi,pmassi,kappabari,kappaparti,Ti,gmwi + real :: xj,yj,zj,dx,dy,dz + real :: rij2,rij,q2i,qi,hj1,hj,hj21,q2j + real :: wabi,grkerni,gradhi,wkerni,dwkerni + real :: pmassj,rhoj,rho1j,dhdrhoj,kappabarj,kappaPartj,Tj,gmwj + real :: uradi,dradi,dradxi,dradyi,dradzi,runix,runiy,runiz + real :: dT4,R_rad + integer :: ngradh_err + real :: uradself + + ngradh_err = 0 + over_parts: do icell = 1,cell%npcell i = inodeparts(cell%arr_index(icell)) ! note: only active particles have been sent here if (maxphase==maxp) then @@ -1731,103 +1731,103 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra ! get Ti from tabulated eos call getopac_opdep(vxyzu(4,i)*unit_ergg,rhoi*unit_density,kappabari, & kappaparti,Ti,gmwi) - + loop_over_neighbours: do n=1,nneigh j = abs(listneigh(n)) if (i==j) cycle loop_over_neighbours xj = xyzh(1,j) yj = xyzh(2,j) zj = xyzh(3,j) - + dx = cell%xpartvec(ixi,icell) - xj dy = cell%xpartvec(iyi,icell) - yj dz = cell%xpartvec(izi,icell) - zj #ifdef PERIODIC - if (abs(dx) > 0.5*dxbound) dx = dx - dxbound*SIGN(1.0,dx) - if (abs(dy) > 0.5*dybound) dy = dy - dybound*SIGN(1.0,dy) - if (abs(dz) > 0.5*dzbound) dz = dz - dzbound*SIGN(1.0,dz) + if (abs(dx) > 0.5*dxbound) dx = dx - dxbound*SIGN(1.0,dx) + if (abs(dy) > 0.5*dybound) dy = dy - dybound*SIGN(1.0,dy) + if (abs(dz) > 0.5*dzbound) dz = dz - dzbound*SIGN(1.0,dz) #endif - rij2 = dx*dx + dy*dy + dz*dz + TINY(0.) - rij = SQRT(rij2) - q2i = rij2*hi21 - qi = SQRT(q2i) - - hj1 = 1./xyzh(4,j) - hj = 1./hj1 - hj21 = hj1*hj1 - q2j = rij2*hj21 - - is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then - if (maxphase==maxp) then - call get_partinfo(iphase(j),iactivej,iamgasj,iamdustj,iamtypej) - else - iactivej = .true. - iamtypej = igas - iamgasj = .true. - endif - if (.not. iamgasj) cycle loop_over_neighbours - if (.not. iactivej) cycle loop_over_neighbours - ! get kernel quantities - if (gradh(1,i) > 0.) then - gradhi = gradh(1,i) - !elseif (ngradh_err < 20) then - ! call error('force','stored gradh is zero, resetting to 1') - ! gradhi = 1. + rij2 = dx*dx + dy*dy + dz*dz + TINY(0.) + rij = SQRT(rij2) + q2i = rij2*hi21 + qi = SQRT(q2i) + + hj1 = 1./xyzh(4,j) + hj = 1./hj1 + hj21 = hj1*hj1 + q2j = rij2*hj21 + + is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then + if (maxphase==maxp) then + call get_partinfo(iphase(j),iactivej,iamgasj,iamdustj,iamtypej) + else + iactivej = .true. + iamtypej = igas + iamgasj = .true. + endif + if (.not. iamgasj) cycle loop_over_neighbours + if (.not. iactivej) cycle loop_over_neighbours + ! get kernel quantities + if (gradh(1,i) > 0.) then + gradhi = gradh(1,i) + !elseif (ngradh_err < 20) then + ! call error('force','stored gradh is zero, resetting to 1') + ! gradhi = 1. ! ngradh_err = ngradh_err + 1 - else - gradhi = 1. - ngradh_err = ngradh_err + 1 - endif - call get_kernel(q2i,qi,wabi,grkerni) - wkerni = wabi*cnormk*hi21*hi1 - dwkerni = grkerni*cnormk*hi21*hi21*gradh(1,i) - pmassj = massoftype(iamtypej) - call rhoanddhdrho(hj,hj1,rhoj,rho1j,dhdrhoj,pmassj) - call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,& + else + gradhi = 1. + ngradh_err = ngradh_err + 1 + endif + call get_kernel(q2i,qi,wabi,grkerni) + wkerni = wabi*cnormk*hi21*hi1 + dwkerni = grkerni*cnormk*hi21*hi21*gradh(1,i) + pmassj = massoftype(iamtypej) + call rhoanddhdrho(hj,hj1,rhoj,rho1j,dhdrhoj,pmassj) + call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,& kappaBarj,kappaPartj,Tj,gmwj) - uradi = uradi + get_radconst_code()*(Tj**4.0d0)*wkerni*pmassj/rhoj - - ! calculate components of gradient - runix = dx/rij - runiy = dy/rij - runiz = dz/rij - - dT4 = Ti**4d0 - Tj**4d0 - dradxi = dradxi + get_radconst_code()*pmassj*dT4*dwkerni*runix/rhoj - dradyi = dradyi + get_radconst_code()*pmassj*dT4*dwkerni*runiy/rhoj - dradzi = dradzi + get_radconst_code()*pmassj*dT4*dwkerni*runiz/rhoj - - endif is_sph_neighbour - - enddo loop_over_neighbours - - ! add self contribution - - uradi = uradi + cnormk*hi31*get_radconst_code()*(Ti**4d0) & + uradi = uradi + get_radconst_code()*(Tj**4.0d0)*wkerni*pmassj/rhoj + + ! calculate components of gradient + runix = dx/rij + runiy = dy/rij + runiz = dz/rij + + dT4 = Ti**4d0 - Tj**4d0 + dradxi = dradxi + get_radconst_code()*pmassj*dT4*dwkerni*runix/rhoj + dradyi = dradyi + get_radconst_code()*pmassj*dT4*dwkerni*runiy/rhoj + dradzi = dradzi + get_radconst_code()*pmassj*dT4*dwkerni*runiz/rhoj + + endif is_sph_neighbour + + enddo loop_over_neighbours + + ! add self contribution + + uradi = uradi + cnormk*hi31*get_radconst_code()*(Ti**4d0) & *wab0*pmassi/rhoi - if (uradi > 1.d0) print *, "cnormk,hi31,radconst,Ti,wab0,pmassi,rhoi",& + if (uradi > 1.d0) print *, "cnormk,hi31,radconst,Ti,wab0,pmassi,rhoi",& cnormk,hi31,get_radconst_code(),Ti,wab0,pmassi,rhoi,"wabi,wkerni,pmassj,rhoj", & wabi,wkerni,pmassj,rhoj !$omp critical - if (iamgasi .and. uradi > 0d0) urad_FLD(i) = uradi + if (iamgasi .and. uradi > 0d0) urad_FLD(i) = uradi !$omp end critical - !Now calculate flux limiter coefficients - !Calculate in code units (converted to code units in forcei) - dradi = SQRT(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! should this be normalised somehow? - if ((dradi.eq.0.0d0).or.(uradi.eq.0.0d0)) then - R_rad = 0.0d0 - else - R_rad = dradi/(uradi*rhoi*kappaParti/unit_opacity) - endif + !Now calculate flux limiter coefficients + !Calculate in code units (converted to code units in forcei) + dradi = SQRT(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! should this be normalised somehow? + if ((dradi.eq.0.0d0).or.(uradi.eq.0.0d0)) then + R_rad = 0.0d0 + else + R_rad = dradi/(uradi*rhoi*kappaParti/unit_opacity) + endif !$omp critical - lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) + lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) !$omp end critical - if (isnan(lambda(i))) then - print *, "lambda isnan when calculated. i, R_Rad, uradi,dradi,rhoi,",& + if (isnan(lambda(i))) then + print *, "lambda isnan when calculated. i, R_Rad, uradi,dradi,rhoi,",& "kappaParti, Ti",i,R_Rad,uradi,dradi,rhoi,kappaParti,Ti - endif + endif enddo over_parts ! if (ngradh_err > 0) print *, "ngradh_errors = ", ngradh_err diff --git a/src/main/eos.f90 b/src/main/eos.f90 index d1869ca66..861e5e072 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -50,7 +50,7 @@ module eos use part, only:ien_etotal,ien_entropy,ien_type use dim, only:gr implicit none - integer, parameter, public :: maxeos = 23 + integer, parameter, public :: maxeos = 23 real, public :: polyk, polyk2, gamma real, public :: qfacdisc = 0.75, qfacdisc2 = 0.75 logical, public :: extract_eos_from_hdr = .false. @@ -154,7 +154,7 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam if (present(Xlocal)) X_i = Xlocal if (present(Zlocal)) Z_i = Zlocal if (present(isionised)) isionisedi = isionised - + select case(eos_type) case(1) ! @@ -432,11 +432,11 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam if (present(gamma_local)) gamma_local = gammai case(21) - call get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) - + call get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) + case(22) call get_eos_HIIR_adiab(polyk,temperature_coef,mui,tempi,ponrhoi,rhoi,eni,gammai,spsoundi,isionisedi) - + case(23) ! !--interpolate tabulated eos from Stamatellos+(2007). For use with icooling=9 @@ -598,7 +598,7 @@ subroutine finish_eos(eos_type,ierr) case(23) ! Stamatellos deallocation call finish_S07cool - + end select done_init_eos=.false. @@ -1290,7 +1290,7 @@ logical function eos_outputs_mu(ieos) eos_outputs_mu = .true. case(23) eos_outputs_mu = .true. -case default + case default eos_outputs_mu = .false. end select diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index ff3b7a404..11eaa0813 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -32,17 +32,17 @@ module eos_stamatellos contains subroutine init_S07cool() - use part, only:npart,maxradprop + use part, only:npart,maxradprop print *, "Allocating cooling arrays" allocate(gradP_cool(npart)) allocate(Gpot_cool(npart)) allocate(duFLD(npart)) allocate(lambda_fld(npart)) - allocate(urad_FLD(npart)) - allocate(ttherm_store(npart)) - allocate(teqi_store(npart)) + allocate(urad_FLD(npart)) + allocate(ttherm_store(npart)) + allocate(teqi_store(npart)) allocate(opac_store(npart)) - allocate(duSPH(npart)) + allocate(duSPH(npart)) Gpot_cool(:) = 0d0 gradP_cool(:) = 0d0 urad_FLD(:) = 0d0 @@ -51,7 +51,7 @@ subroutine init_S07cool() 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 @@ -69,7 +69,7 @@ subroutine finish_S07cool() if (allocated(ttherm_store)) deallocate(ttherm_store) if (allocated(teqi_store)) deallocate(teqi_store) if (allocated(opac_store)) deallocate(opac_store) - if (allocated(duSPH)) deallocate(duSPH) + if (allocated(duSPH)) deallocate(duSPH) close(iunitst) end subroutine finish_S07cool @@ -108,7 +108,7 @@ end subroutine read_optab ! Main subroutine for interpolating tables to get EOS values ! subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) - use io, only:fatal + use io, only:fatal real, intent(in) :: ui,rhoi real, intent(out) :: kappaBar,kappaPart,Ti,gmwi @@ -130,7 +130,7 @@ subroutine getopac_opdep(ui,rhoi,kappaBar,kappaPart,Ti,gmwi) 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) endif - + if (rhoi < rhomin) then rhoi_ = rhomin else @@ -235,7 +235,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) call warning('getintenerg_opdep','Ti out of range',var='Ti',val=Teqi) endif - + ! interpolate through OPTABLE to obtain equilibrium internal energy if (rhoi < 1.0e-24) then @@ -254,7 +254,7 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) j = j + 1 enddo - + m = (OPTABLE(i-1,j-1,3) - OPTABLE(i-1,j,3))/(OPTABLE(i-1,j-1,2) - OPTABLE(i-1,j,2)) c = OPTABLE(i-1,j,3) - m*OPTABLE(i-1,j,2) @@ -277,25 +277,25 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) end subroutine getintenerg_opdep subroutine get_k_fld(rhoi,eni,i,ki,Ti) - use physcon, only:c,fourpi - use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code - real,intent(in) :: rhoi,eni - integer,intent(in) :: i - real :: kappaBar,gmwi,kappaPart - real,intent(out) :: ki,Ti - - if (lambda_FLD(i) == 0d0) then - ki = 0. - else - call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) - kappaPart = kappaPart/unit_opacity - ! steboltz constant = 4pi/c * arad - ki = 16d0*(fourpi/c)*get_radconst_code()*lambda_FLD(i)*Ti**3 /rhoi/kappaPart - if (isnan(ki)) then - print *, "WARNING k isnan, lambda_FLDi,Ti,rhoi,kappaPart", & + use physcon, only:c,fourpi + use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code + real,intent(in) :: rhoi,eni + integer,intent(in) :: i + real :: kappaBar,gmwi,kappaPart + real,intent(out) :: ki,Ti + + if (lambda_FLD(i) == 0d0) then + ki = 0. + else + call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) + kappaPart = kappaPart/unit_opacity + ! steboltz constant = 4pi/c * arad + ki = 16d0*(fourpi/c)*get_radconst_code()*lambda_FLD(i)*Ti**3 /rhoi/kappaPart + if (isnan(ki)) then + print *, "WARNING k isnan, lambda_FLDi,Ti,rhoi,kappaPart", & lambda_FLD(i), Ti, rhoi,kappaPart - endif - endif + endif + endif end subroutine get_k_fld end module eos_stamatellos diff --git a/src/main/force.F90 b/src/main/force.F90 index 9fcc9b849..466156540 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1203,7 +1203,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g call get_k_fld(rhoi,eni,i,kfldi,Ti) endif endif - + loop_over_neighbours2: do n = 1,nneigh j = abs(listneigh(n)) @@ -1606,7 +1606,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g diffterm = 0d0 print *, "setting diffterm = 0", i, j, rhoj elseif ((kfldj + kfldi) < tiny(0.)) then - diffterm = 0d0 + diffterm = 0d0 else diffterm = 4d0*pmassj/rhoi/rhoj diffterm = diffterm * kfldi * kfldj / (kfldi+kfldj) @@ -1621,7 +1621,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif endif endif - + !--artificial thermal conductivity (need j term) if (maxvxyzu >= 4) then if (gr) then @@ -1748,9 +1748,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g endif if (icooling == 9) then - Gpot_cool(i) = Gpot_cool(i) + pmassj*phii + Gpot_cool(i) = Gpot_cool(i) + pmassj*phii endif - + !--add contribution to particle i's force if (mhd) then !--div B in symmetric form (for source term subtraction) @@ -2008,7 +2008,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g !-- add contribution of 'distant neighbour' (outside r_kernel) gas particle to potential if (iamtypej == igas .and. icooling == 9) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii - + !--self gravity contribution to total energy equation if (gr .and. gravity .and. ien_type == ien_etotal) then fgravxi = fgravxi - dx*fgravj @@ -2021,7 +2021,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g enddo loop_over_neighbours2 if (icooling == 9) gradP_cool(i) = sqrt(gradpx*gradpx + gradpy*gradpy + gradpz*gradpz) - + if (gr .and. gravity .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fgravxi + vyi*fgravyi + vzi*fgravzi endif diff --git a/src/main/inject_bondi.f90 b/src/main/inject_bondi.f90 index 9af9af121..1c2fc22bc 100644 --- a/src/main/inject_bondi.f90 +++ b/src/main/inject_bondi.f90 @@ -220,7 +220,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_firehose.f90 b/src/main/inject_firehose.f90 index 7db1c2759..cf1e5bfb0 100644 --- a/src/main/inject_firehose.f90 +++ b/src/main/inject_firehose.f90 @@ -213,7 +213,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_galcen_winds.f90 b/src/main/inject_galcen_winds.f90 index 5422ba9ff..d52baaf8a 100644 --- a/src/main/inject_galcen_winds.f90 +++ b/src/main/inject_galcen_winds.f90 @@ -226,7 +226,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_keplerian.f90 b/src/main/inject_keplerian.f90 index 7e4f8e221..45376c6ba 100644 --- a/src/main/inject_keplerian.f90 +++ b/src/main/inject_keplerian.f90 @@ -201,7 +201,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_keplerianshear.f90 b/src/main/inject_keplerianshear.f90 index cea2359ae..773fc7d72 100644 --- a/src/main/inject_keplerianshear.f90 +++ b/src/main/inject_keplerianshear.f90 @@ -189,7 +189,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_rochelobe.f90 b/src/main/inject_rochelobe.f90 index 054a264b1..96cd13aca 100644 --- a/src/main/inject_rochelobe.f90 +++ b/src/main/inject_rochelobe.f90 @@ -281,7 +281,7 @@ end subroutine phi_derivs subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_sim.f90 b/src/main/inject_sim.f90 index a305b8dc8..127d1805d 100644 --- a/src/main/inject_sim.f90 +++ b/src/main/inject_sim.f90 @@ -276,7 +276,7 @@ subroutine read_injected_par() injected = .false. endif -end subroutine +end subroutine read_injected_par subroutine update_injected_par() use io, only:error @@ -298,7 +298,7 @@ subroutine update_injected_par() enddo close(iunit) endif -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_sne.f90 b/src/main/inject_sne.f90 index 2152ef1eb..867ad2b88 100644 --- a/src/main/inject_sne.f90 +++ b/src/main/inject_sne.f90 @@ -138,7 +138,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_steadydisc.f90 b/src/main/inject_steadydisc.f90 index eb6d6c128..d7071af77 100644 --- a/src/main/inject_steadydisc.f90 +++ b/src/main/inject_steadydisc.f90 @@ -206,7 +206,7 @@ end subroutine inject_particles_in_annulus subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_unifwind.f90 b/src/main/inject_unifwind.f90 index d2205b97b..80f203a63 100644 --- a/src/main/inject_unifwind.f90 +++ b/src/main/inject_unifwind.f90 @@ -128,7 +128,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_wind.f90 b/src/main/inject_wind.f90 index 43de42245..ed7597fcf 100644 --- a/src/main/inject_wind.f90 +++ b/src/main/inject_wind.f90 @@ -505,7 +505,7 @@ end subroutine inject_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/inject_windtunnel.f90 b/src/main/inject_windtunnel.f90 index 79ee0aac0..62cdf2f33 100644 --- a/src/main/inject_windtunnel.f90 +++ b/src/main/inject_windtunnel.f90 @@ -258,7 +258,7 @@ end subroutine inject_or_update_particles subroutine update_injected_par ! -- placeholder function ! -- does not do anything and will never be used -end subroutine +end subroutine update_injected_par !----------------------------------------------------------------------- !+ diff --git a/src/main/porosity.f90 b/src/main/porosity.f90 index 7b5071b17..a70b3801c 100755 --- a/src/main/porosity.f90 +++ b/src/main/porosity.f90 @@ -789,18 +789,18 @@ end function get_coeffrest real function compute_vstick(mass,size) real, intent(in) ::mass,size compute_vstick = 8.76*((surfenerg**5 * size**4)/(mass**3*youngmod**2))**(1./6.) -end function +end function compute_vstick !--velocity limit between elastic and inelastic bouncing regime real function compute_vyield(vstick) real, intent(in) ::vstick compute_vyield = 10.*vstick -end function +end function compute_vyield !--velocity limit between partial sticking + bouncing regime and full bouncing regime real function compute_vend(vstick) real, intent(in) ::vstick compute_vend = 24343220.*vstick -end function +end function compute_vend end module porosity diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 468a0be97..95dfb16de 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -437,11 +437,11 @@ subroutine get_opacity(opacity_type,density,temperature,kappa,u) kappa = kappa_cgs/unit_opacity case(3) - ! - ! opacity for Stamatellos/Lombardi EOS - ! - call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi) - kappa = kappaPart/unit_opacity + ! + ! opacity for Stamatellos/Lombardi EOS + ! + call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi) + kappa = kappaPart/unit_opacity case default ! ! infinite opacity diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index 8a7272e4f..3fbc5581e 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -306,7 +306,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) call write_options_gravitationalwaves(iwritein) call write_options_boundary(iwritein) call write_options_H2R(iwritein) - + if (iwritein /= iprint) close(unit=iwritein) if (iwritein /= iprint) write(iprint,"(/,a)") ' input file '//trim(infile)//' written successfully.' diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index d6167ab5b..31f81dd81 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -127,7 +127,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use eos, only:equationofstate use substepping, only:substep,substep_gr, & substep_sph_gr,substep_sph - + integer, intent(inout) :: npart integer, intent(in) :: nactive real, intent(in) :: t,dtsph @@ -322,7 +322,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) else vpred(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif - + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vpred(4,i) < ufloor) then @@ -486,7 +486,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) + dti*fxyzu(:,i) endif endif - + if (use_dustgrowth .and. itype==idust) dustprop(:,i) = dustprop(:,i) + dti*ddustprop(:,i) if (itype==igas) then if (mhd) Bevol(:,i) = Bevol(:,i) + dti*dBevol(:,i) @@ -512,7 +512,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) vxyzu(:,i) = vxyzu(:,i) + hdti*fxyzu(:,i) endif endif - + !--floor the thermal energy if requested and required if (ufloor > 0.) then if (vxyzu(4,i) < ufloor) then diff --git a/src/utils/moddump_radiotde.f90 b/src/utils/moddump_radiotde.f90 index 28af40a44..e984c3792 100644 --- a/src/utils/moddump_radiotde.f90 +++ b/src/utils/moddump_radiotde.f90 @@ -409,7 +409,7 @@ subroutine calc_rho0(rhof) enddo write(*,'(a11,1x,es10.2,1x,a12,1x,i3,1x,a10)') ' Get rho0 =', rhof_rho0*unit_density, 'g/cm^-3 with', iter, 'iterations' -end subroutine +end subroutine calc_rho0 !---------------------------------------------------------------- !+ From ff647d920f69f4a046109b36566ca78c3eeda5cb Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 1 Aug 2024 16:13:37 +0100 Subject: [PATCH 142/182] Bugs fixed in icooling=9 --- src/main/cooling_radapprox.f90 | 3 +++ src/main/dens.F90 | 9 ++++++++- src/main/step_leapfrog.F90 | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index cbc532954..89c563a71 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -166,6 +166,9 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) ! 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 endif diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 14e3c9c07..9465f506d 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -348,7 +348,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - if (icooling==9 .and. doFLD) then + 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) endif if (do_export) then @@ -1706,6 +1706,9 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra ! note: only active particles have been sent here if (maxphase==maxp) then call get_partinfo(cell%iphase(icell),iactivei,iamgasi,iamdusti,iamtypei) + if (.not. iamgasi) then + print *, "error not gas", i + endif else iactivei = .true. iamtypei = igas @@ -1729,6 +1732,10 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra !calculate rhoi call rhoanddhdrho(hi,hi1,rhoi,rho1i,dhdrhoi,pmassi) ! get Ti from tabulated eos + if (vxyzu(4,i) < epsilon(vxyzu(4,i))) then + print *, "u=0 in FLD calc", vxyzu(4,i), i,rhoi*unit_density,Ti,& + cell%xpartvec(ixi,icell),cell%xpartvec(iyi,icell) + endif call getopac_opdep(vxyzu(4,i)*unit_ergg,rhoi*unit_density,kappabari, & kappaparti,Ti,gmwi) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 31f81dd81..c0ab8c974 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -384,6 +384,7 @@ 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,& From 952a54025752cd414c4cbec74e1dd276250b8191 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 9 Aug 2024 12:21:26 +0100 Subject: [PATCH 143/182] bug fix for radapprox cooling --- src/main/step_leapfrog.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 8679970a7..713b59446 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -375,6 +375,7 @@ 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 == 8) vpred(4,:) = vxyzu(4,:) ! only evolve u in cooling dt_too_small = .false. call derivs(1,npart,nactive,xyzh,vpred,fxyzu,fext,divcurlv,& divcurlB,Bpred,dBevol,radpred,drad,radprop,dustproppred,ddustprop,& From b8185e54b07e2b0f6202bb94ed6cd616bed0f9d6 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 9 Aug 2024 14:00:20 +0100 Subject: [PATCH 144/182] Fix bugs from merge --- src/main/eos.f90 | 8 ----- src/main/{mpi_memory.F90 => mpi_memory.f90} | 0 src/main/ptmass.F90 | 34 --------------------- src/main/radiation_utils.f90 | 14 ++------- src/main/step_leapfrog.F90 | 13 -------- src/utils/struct_part.f90 | 8 ++--- 6 files changed, 7 insertions(+), 70 deletions(-) rename src/main/{mpi_memory.F90 => mpi_memory.f90} (100%) diff --git a/src/main/eos.f90 b/src/main/eos.f90 index f435ec6b5..b1af14d51 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -429,14 +429,6 @@ subroutine equationofstate(eos_type,ponrhoi,spsoundi,rhoi,xi,yi,zi,tempi,eni,gam tempi = temperaturei if (present(mu_local)) mu_local = 1./imui if (present(gamma_local)) gamma_local = gammai - case(21) - - call get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) - case(22) - - call get_eos_HIIR_adiab(polyk,temperature_coef,mui,tempi,ponrhoi,rhoi,eni,gammai,spsoundi,isionisedi) - - case(21) call get_eos_HIIR_iso(polyk,temperature_coef,mui,tempi,ponrhoi,spsoundi,isionisedi) 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/ptmass.F90 b/src/main/ptmass.F90 index 534982082..505e32623 100644 --- a/src/main/ptmass.F90 +++ b/src/main/ptmass.F90 @@ -1934,40 +1934,6 @@ subroutine merge_sinks(time,nptmass,xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,linklis end subroutine merge_sinks -subroutine ptmass_endsize_lklist(i,k,n,linklist_ptmass) - integer, intent(in) :: linklist_ptmass(:) - integer, intent(in) :: i - integer, intent(out) :: k,n - integer :: l,g - g=i - n = 0 - do while (g>0) - l = g - g = linklist_ptmass(l) - n = n + 1 - enddo - k=l -end subroutine ptmass_endsize_lklist - - -subroutine set_integration_precision - - if (use_fourthorder) then - n_force_order = 3 - ck = ck4 - dk = dk4 - dtfacphi = dtfacphifsi - dtfacphi2 = dtfacphi2fsi - else - n_force_order = 1 - ck = ck2 - dk = dk2 - dtfacphi = dtfacphilf - dtfacphi2 = dtfacphi2lf - endif - -end subroutine set_integration_precision - !----------------------------------------------------------------------- !+ ! helper routine for managing the sink particle linked list diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 95dfb16de..0147e01c7 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -411,15 +411,13 @@ end function get_kappa ! calculate opacities !+ !-------------------------------------------------------------------- -subroutine get_opacity(opacity_type,density,temperature,kappa,u) - use eos_stamatellos, only:getopac_opdep +subroutine get_opacity(opacity_type,density,temperature,kappa) use mesa_microphysics, only:get_kappa_mesa - use units, only:unit_density,unit_opacity,unit_ergg + use units, only:unit_density,unit_opacity real, intent(in) :: density, temperature - real, intent(in), optional :: u real, intent(out) :: kappa integer, intent(in) :: opacity_type - real :: kapt,kapr,rho_cgs,Ti,gmwi,gammai,kapBar,kappaPart + real :: kapt,kapr,rho_cgs select case(opacity_type) case(1) @@ -436,12 +434,6 @@ subroutine get_opacity(opacity_type,density,temperature,kappa,u) ! kappa = kappa_cgs/unit_opacity - case(3) - ! - ! opacity for Stamatellos/Lombardi EOS - ! - call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi) - kappa = kappaPart/unit_opacity case default ! ! infinite opacity diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index edd8b55a7..0859dbbe4 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -124,13 +124,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) use porosity, only:get_filfac use damping, only:idamp use cons2primsolver, only:conservative2primitive,primitive2conservative -<<<<<<< HEAD - use substepping, only:substep,substep_gr, & - substep_sph_gr,substep_sph -======= use substepping, only:substep,substep_gr, & substep_sph_gr,substep_sph ->>>>>>> upstream/master integer, intent(inout) :: npart integer, intent(in) :: nactive @@ -254,18 +249,10 @@ 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 -<<<<<<< HEAD - 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,group_info, & - nmatrix,n_group,n_ingroup,n_sing,isionised) -======= - 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, & group_info,nmatrix,n_group,n_ingroup,n_sing,isionised) ->>>>>>> upstream/master else call substep_sph(dtsph,npart,xyzh,vxyzu) endif diff --git a/src/utils/struct_part.f90 b/src/utils/struct_part.f90 index 99640148d..781a3c2fd 100644 --- a/src/utils/struct_part.f90 +++ b/src/utils/struct_part.f90 @@ -149,10 +149,10 @@ subroutine get_structure_fn(sf,nbins,norder,distmin,distmax,xbins,ncount,npart,x !$omp reduction(+:sf) do ipt=1,npts !$ if (.false.) then - if (mod(ipt,100)==0) then - call cpu_time(tcpu2) - print*,' ipt = ',ipt,tcpu2-tcpu1 - endif + if (mod(ipt,100)==0) then + call cpu_time(tcpu2) + print*,' ipt = ',ipt,tcpu2-tcpu1 + endif !$ endif i = list(ipt) xpt(1) = xyz(1,i) From 8d9ccc73d7822d4c54fed7984c7657f4e13edb5d Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 9 Aug 2024 15:51:12 +0100 Subject: [PATCH 145/182] Fix bug from merge --- src/main/substepping.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index a0d8d4693..ddcb822ac 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -1177,6 +1177,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) 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) From 2ac071a93ee5435ab1ab159fa3d3a3c7f776ef0e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Sat, 10 Aug 2024 10:47:18 +0100 Subject: [PATCH 146/182] Removed non Modified Lombardi cooling options from radiative cooling approximation code --- src/main/cooling.f90 | 4 +- src/main/cooling_radapprox.f90 | 276 +++------------------------------ src/main/eos.f90 | 8 +- src/main/eos_stamatellos.f90 | 15 +- src/main/force.F90 | 15 +- 5 files changed, 34 insertions(+), 284 deletions(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 0bb572586..7f5dac575 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -70,7 +70,7 @@ subroutine init_cooling(id,master,iprint,ierr) 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 cooling_radapprox, only:init_star use viscosity, only:irealvisc integer, intent(in) :: id,master,iprint @@ -88,7 +88,7 @@ subroutine init_cooling(id,master,iprint,ierr) case(9) if (ieos /= 23 ) call fatal('cooling','icooling=9 requires ieos=23',& var='ieos',ival=ieos) - if (irealvisc > 0 .and. od_method == 4) call warning('cooling',& + if (irealvisc > 0) 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) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 89c563a71..e23196acb 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -23,10 +23,9 @@ module cooling_radapprox real :: Lstar = 0d0 ! in units of L_sun real,parameter :: dtcool_crit = 0.0001 ! critical dt_rad/dt_hydro for not applying cooling 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 :: init_star contains @@ -39,8 +38,8 @@ subroutine init_star() rsink2min = 0d0 isink_star = 0 - if (od_method == 4 .and. nptmass == 0) then - print *, "NO central star and using od_method = 4" + if (nptmass == 0) then + print *, "NO central star" elseif (nptmass == 0) then print *, "No stellar heating." elseif (nptmass == 1) then @@ -68,7 +67,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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,& + use eos_stamatellos, only:getopac_opdep,getintenerg_opdep,gradP_cool,& duFLD,doFLD,ttherm_store,teqi_store,opac_store,duSPH use part, only:xyzmh_ptmass,igas integer,intent(in) :: i @@ -81,7 +80,6 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi coldensi = huge(coldensi) - poti = Gpot_cool(i) du_FLDi = duFLD(i) kappaBari = 0d0 kappaParti = 0d0 @@ -104,39 +102,17 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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 - call warning("In radapprox cooling","cooling method not recognised",ival=od_method) - return - end select +! 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 ! Tfloor is from input parameters and is background heating ! Stellar heating @@ -148,7 +124,6 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) umini = umini/unit_ergg - 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 @@ -163,8 +138,6 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) ! 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 @@ -183,18 +156,6 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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 - elseif (Teqi < epsilon(Teqi)) then - print *, "Teqi=0.0", "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& - "Ti=", Ti, "poti=",poti, "rhoi=", rhoi - elseif (Teqi < Tfloor) then - print *, "Teqi=",Teqi, "Tmini4=", Tmini4, "coldensi=", coldensi, "Tfloor=",Tfloor,& - "Ti=", Ti, "poti=",poti, "rhoi=", rhoi - endif - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) ueqi = ueqi/unit_ergg @@ -230,196 +191,6 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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 - 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) & - !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,dti) & - !$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 - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,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 - - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) - ueqi = ueqi/unit_ergg - - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,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 - - subroutine write_options_cooling_radapprox(iunit) use infile_utils, only:write_inopt use eos_stamatellos, only: eos_file @@ -427,35 +198,28 @@ subroutine write_options_cooling_radapprox(iunit) !N.B. Tfloor handled in cooling.F90 call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) - call write_inopt(od_method,'OD method',& - 'Method for estimating optical depth:(1)Stamatellos (2)Lombardi (3)combined (4)modified Lombardi',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) call write_inopt(FLD_opt,'do FLD','Do FLD? (1) yes (0) no',iunit) end subroutine write_options_cooling_radapprox -subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr) + +subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallra,ierr) use io, only:warning,fatal use eos_stamatellos, only: eos_file,doFLD character(len=*), intent(in) :: name,valstring - logical, intent(out) :: imatch,igotallstam + logical, intent(out) :: imatch,igotallra integer, intent(out) :: ierr integer :: ieosread integer, save :: ngot = 0 imatch = .true. - igotallstam = .false. ! cooling options are compulsory + igotallra = .false. ! cooling options are compulsory select case(trim(name)) case('Lstar') read(valstring,*,iostat=ierr) Lstar if (Lstar < 0.) call fatal('Lstar','Luminosity cannot be negative') ngot = ngot + 1 - case('OD method') - read(valstring,*,iostat=ierr) od_method - if (od_method < 1 .or. od_method > 4) then - call fatal('cooling options','od_method must be 1, 2, 3 or 4',var='od_method',ival=od_method) - endif - ngot = ngot + 1 case('EOS_file') read(valstring,*,iostat=ierr) eos_file ngot = ngot + 1 @@ -475,7 +239,7 @@ subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallstam,ierr imatch = .false. end select - if (ngot >= 4) igotallstam = .true. + if (ngot >= 3) igotallra = .true. end subroutine read_options_cooling_radapprox diff --git a/src/main/eos.f90 b/src/main/eos.f90 index b1af14d51..2593a620b 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -476,7 +476,7 @@ subroutine init_eos(eos_type,ierr) use eos_barotropic, only:init_eos_barotropic use eos_shen, only:init_eos_shen_NL3 use eos_gasradrec, only:init_eos_gasradrec - use eos_stamatellos,only:read_optab,init_S07cool,eos_file + use eos_stamatellos,only:read_optab,init_coolra,eos_file use eos_HIIR, only:init_eos_HIIR use dim, only:maxvxyzu,do_radiation use eos_HIIR, only:init_eos_HIIR @@ -564,7 +564,7 @@ subroutine init_eos(eos_type,ierr) call read_optab(eos_file,ierr) if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) - call init_S07cool + call init_coolra end select done_init_eos = .true. @@ -584,7 +584,7 @@ end subroutine init_eos !----------------------------------------------------------------------- subroutine finish_eos(eos_type,ierr) use eos_mesa, only: finish_eos_mesa - use eos_stamatellos, only: finish_S07cool + use eos_stamatellos, only: finish_coolra integer, intent(in) :: eos_type integer, intent(out) :: ierr @@ -599,7 +599,7 @@ subroutine finish_eos(eos_type,ierr) case(23) ! Stamatellos deallocation - call finish_S07cool + call finish_coolra end select done_init_eos=.false. diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 11eaa0813..ff0864126 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -19,23 +19,22 @@ 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 :: duFLD(:),gradP_cool(:),lambda_FLD(:),urad_FLD(:) !gradP_cool=gradP/rho real,allocatable,public :: ttherm_store(:),teqi_store(:),opac_store(:),duSPH(:) character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file logical,public :: doFLD = .True., floor_energy = .False. integer,public :: iunitst=19 integer,save :: nx,ny ! dimensions of optable read in - public :: read_optab,getopac_opdep,init_S07cool,getintenerg_opdep,finish_S07cool + public :: read_optab,getopac_opdep,init_coolra,getintenerg_opdep,finish_coolra public :: get_k_fld contains -subroutine init_S07cool() +subroutine init_coolra() use part, only:npart,maxradprop print *, "Allocating cooling arrays" allocate(gradP_cool(npart)) - allocate(Gpot_cool(npart)) allocate(duFLD(npart)) allocate(lambda_fld(npart)) allocate(urad_FLD(npart)) @@ -43,7 +42,6 @@ subroutine init_S07cool() allocate(teqi_store(npart)) allocate(opac_store(npart)) allocate(duSPH(npart)) - Gpot_cool(:) = 0d0 gradP_cool(:) = 0d0 urad_FLD(:) = 0d0 duFLD(:) = 0d0 @@ -57,12 +55,11 @@ subroutine init_S07cool() else print *, "NOT using FLD. Using cooling only" endif -end subroutine init_S07cool +end subroutine init_coolra -subroutine finish_S07cool() +subroutine finish_coolra() 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) @@ -71,7 +68,7 @@ subroutine finish_S07cool() if (allocated(opac_store)) deallocate(opac_store) if (allocated(duSPH)) deallocate(duSPH) close(iunitst) -end subroutine finish_S07cool +end subroutine finish_coolra subroutine read_optab(eos_file,ierr) use datafiles, only:find_phantom_datafile diff --git a/src/main/force.F90 b/src/main/force.F90 index 466156540..4ddfc195f 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -903,7 +903,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt use eos, only:ieos,eos_is_non_ideal - use eos_stamatellos, only:gradP_cool,Gpot_cool,duFLD,doFLD,getopac_opdep,get_k_fld + use eos_stamatellos, only:gradP_cool,duFLD,doFLD,getopac_opdep,get_k_fld #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -1187,7 +1187,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravzi = 0. if (icooling == 9) then gradP_cool(i) = 0d0 - Gpot_cool(i) = 0d0 if (doFLD) then duFLD(i) = 0d0 kfldi = 0d0 @@ -1731,7 +1730,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifzi) = fsum(ifzi) - runiz*(gradp + fgrav) - projsz fsum(ipot) = fsum(ipot) + pmassj*phii ! no need to symmetrise (see PM07) if (icooling == 9) then - Gpot_cool(i) = Gpot_cool(i) + pmassj*phii gradpx = gradpx + runix*(gradP_cooli + gradP_coolj) gradpy = gradpy + runiy*(gradP_cooli + gradP_coolj) gradpz = gradpz + runiz*(gradP_cooli + gradP_coolj) @@ -1747,10 +1745,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(idendtdissi) = fsum(idendtdissi) + dendissterm endif - if (icooling == 9) then - Gpot_cool(i) = Gpot_cool(i) + pmassj*phii - endif - !--add contribution to particle i's force if (mhd) then !--div B in symmetric form (for source term subtraction) @@ -2006,9 +2000,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fsum(ifzi) = fsum(ifzi) - dz*fgravj fsum(ipot) = fsum(ipot) + pmassj*phii - !-- add contribution of 'distant neighbour' (outside r_kernel) gas particle to potential - if (iamtypej == igas .and. icooling == 9) Gpot_cool(i) = Gpot_cool(i) + pmassj*phii - !--self gravity contribution to total energy equation if (gr .and. gravity .and. ien_type == ien_etotal) then fgravxi = fgravxi - dx*fgravj @@ -2617,7 +2608,7 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use part, only:Omega_k use io, only:warning use physcon, only:c,kboltz - use eos_stamatellos, only:Gpot_cool,duSPH + use eos_stamatellos, only:duSPH integer, intent(in) :: icall type(cellforce), intent(inout) :: cell real, intent(inout) :: fxyzu(:,:) @@ -2816,7 +2807,6 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv !--add self-contribution call kernel_softening(0.,0.,potensoft0,dum) epoti = 0.5*pmassi*(fsum(ipot) + pmassi*potensoft0*hi1) - if ((icooling==9) .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + pmassi*potensoft0*hi1 ! !--add contribution from distant nodes, expand these in Taylor series about node centre ! use xcen directly, -1 is placeholder @@ -2826,7 +2816,6 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv fsum(ifxi) = fsum(ifxi) + fxi fsum(ifyi) = fsum(ifyi) + fyi fsum(ifzi) = fsum(ifzi) + fzi - if ((icooling==9) .and. iamgasi) Gpot_cool(i) = Gpot_cool(i) + poti ! add contribution from distant nodes if (gr .and. ien_type == ien_etotal) then fsum(idudtdissi) = fsum(idudtdissi) + vxi*fxi + vyi*fyi + vzi*fzi endif From 40db47f9b5020a709597998693447e9d808a59cc Mon Sep 17 00:00:00 2001 From: Alison Young Date: Sat, 10 Aug 2024 11:33:26 +0100 Subject: [PATCH 147/182] Removed FLD from radapprox cooling --- src/main/cooling_radapprox.f90 | 31 ++--- src/main/dens.F90 | 195 +-------------------------- src/main/eos_stamatellos.f90 | 45 +------ src/main/force.F90 | 34 +---- src/main/readwrite_dumps_fortran.f90 | 5 +- 5 files changed, 18 insertions(+), 292 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index e23196acb..23cc2c47e 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -23,7 +23,6 @@ module cooling_radapprox real :: Lstar = 0d0 ! in units of L_sun real,parameter :: dtcool_crit = 0.0001 ! critical dt_rad/dt_hydro for not applying cooling integer :: isink_star ! index of sink to use as illuminating star - 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 @@ -68,19 +67,18 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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,& - duFLD,doFLD,ttherm_store,teqi_store,opac_store,duSPH + ttherm_store,teqi_store,opac_store,duSPH use part, only:xyzmh_ptmass,igas integer,intent(in) :: i real,intent(in) :: xi,yi,zi,rhoi,Tfloor real,intent(in) :: ui,dt real,intent(out)::dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 - real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot + real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,HLom,du_tot real :: cs2,Om2,Hmod2 - real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi + real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb coldensi = huge(coldensi) - du_FLDi = duFLD(i) kappaBari = 0d0 kappaParti = 0d0 Teqi = huge(Teqi) @@ -128,11 +126,8 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) opac_store(i) = opaci dudti_rad = 4.d0*steboltz*(Tmini4 - Ti**4.d0)/opaci/unit_ergg*utime! code units - if (doFLD) then - du_tot = duSPH(i) + du_FLDi - else - du_tot = duSPH(i) - endif + du_tot = duSPH(i) + ! 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? @@ -183,7 +178,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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 *, "dudti_rad=", dudti_rad ,"dudt_fld=",du_fldi,"ueqi=",ueqi,"ui=",ui + print *, "dudti_rad=", dudti_rad ,"ueqi=",ueqi,"ui=",ui call warning("In Stamatellos cooling","energ=NaN or 0. ui=",val=ui) stop endif @@ -199,14 +194,13 @@ subroutine write_options_cooling_radapprox(iunit) !N.B. Tfloor handled in cooling.F90 call write_inopt(eos_file,'EOS_file','File containing tabulated EOS values',iunit) call write_inopt(Lstar,'Lstar','Luminosity of host star for calculating Tmin (Lsun)',iunit) - call write_inopt(FLD_opt,'do FLD','Do FLD? (1) yes (0) no',iunit) end subroutine write_options_cooling_radapprox subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallra,ierr) use io, only:warning,fatal - use eos_stamatellos, only: eos_file,doFLD + use eos_stamatellos, only: eos_file character(len=*), intent(in) :: name,valstring logical, intent(out) :: imatch,igotallra integer, intent(out) :: ierr @@ -223,15 +217,6 @@ subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallra,ierr) case('EOS_file') read(valstring,*,iostat=ierr) eos_file ngot = ngot + 1 - case('do FLD') - read(valstring,*,iostat=ierr) FLD_opt - if (FLD_opt < 0) call fatal('FLD_opt','FLD option out of range') - if (FLD_opt == 0) then - doFLD = .false. - elseif (FLD_opt == 1) then - doFLD = .true. - endif - ngot = ngot + 1 case('ieos') read(valstring,*,iostat=ierr) ieosread if (ieosread /= 23) call fatal('ieosread','For icooling=9, you need ieos=23') @@ -239,7 +224,7 @@ subroutine read_options_cooling_radapprox(name,valstring,imatch,igotallra,ierr) imatch = .false. end select - if (ngot >= 3) igotallra = .true. + if (ngot >= 2) igotallra = .true. end subroutine read_options_cooling_radapprox diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 9465f506d..1cae9a211 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -139,8 +139,6 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol use io_summary,only:summary_variable,iosumhup,iosumhdn use timing, only:increment_timer,get_timings,itimer_dens_local,itimer_dens_remote use omputils, only:omp_thread_num,omp_num_threads - use eos_stamatellos, only:doFLD,lambda_FLD,urad_FLD - use options, only:icooling integer, intent(in) :: icall,npart,nactive real, intent(inout) :: xyzh(:,:) real, intent(in) :: vxyzu(:,:),fxyzu(:,:),fext(:,:) @@ -267,8 +265,6 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol !$omp shared(cell_counters) & !$omp shared(thread_complete) & !$omp shared(ncomplete_mpi) & -!$omp shared(icooling) & -!$omp shared(lambda_FLD,urad_FLD,doFLD) & !$omp reduction(+:nlocal) & !$omp private(do_export) & !$omp private(j) & @@ -348,9 +344,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - 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) - endif + if (do_export) then call write_cell(stack_waiting,cell) else @@ -383,9 +377,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - if (icooling==9 .and. doFLD) then - call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) - endif + if (do_export) then call write_cell(stack_waiting,cell) exit local_its @@ -455,9 +447,6 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol cell_xpos=cell%xpos,cell_xsizei=cell%xsizei,cell_rcuti=cell%rcuti) call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - if (icooling==9 .and. doFLD) then - call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) - endif remote_export = .false. remote_export(cell%owner+1) = .true. ! use remote_export array to send back to the owner @@ -518,9 +507,6 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol 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) - if (icooling==9 .and. doFLD) then - call calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gradh,lambda_FLD,urad_FLD) - endif call write_cell(stack_redo,cell) else @@ -1663,181 +1649,4 @@ 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) - use io, only:error - use dim, only:maxp - use kernel,only:get_kernel,wab0 - use part, only:get_partinfo,iamgas,igas,maxphase,massoftype - use part, only:rhoanddhdrho - use physcon, only:radconst - use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code - use eos_stamatellos, only:getopac_opdep -#ifdef PERIODIC - use boundary, only:dxbound,dybound,dzbound -#endif - - type(celldens), intent(in) :: cell - 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(:,:) - real, intent(inout) :: lambda(:),urad_FLD(:) - - integer :: icell,i,iamtypei,iamtypej,j,n - logical :: iactivei,iamgasi,iamdusti,ignoreself - logical :: iactivej,iamgasj,iamdustj - real(kind=8) :: hi,hi1,hi21,hi31,hi41 - real :: rhoi,rho1i,dhdrhoi,pmassi,kappabari,kappaparti,Ti,gmwi - real :: xj,yj,zj,dx,dy,dz - real :: rij2,rij,q2i,qi,hj1,hj,hj21,q2j - real :: wabi,grkerni,gradhi,wkerni,dwkerni - real :: pmassj,rhoj,rho1j,dhdrhoj,kappabarj,kappaPartj,Tj,gmwj - real :: uradi,dradi,dradxi,dradyi,dradzi,runix,runiy,runiz - real :: dT4,R_rad - integer :: ngradh_err - real :: uradself - - ngradh_err = 0 - over_parts: do icell = 1,cell%npcell - i = inodeparts(cell%arr_index(icell)) - ! note: only active particles have been sent here - if (maxphase==maxp) then - call get_partinfo(cell%iphase(icell),iactivei,iamgasi,iamdusti,iamtypei) - if (.not. iamgasi) then - print *, "error not gas", i - endif - else - iactivei = .true. - iamtypei = igas - iamgasi = .true. - endif - - hi = cell%h(icell) - hi1 = 1./hi - hi21 = hi1*hi1 - hi31 = hi1*hi21 - hi41 = hi21*hi21 - - ignoreself = (cell%owner == i) - uradi = 0d0 - dradi = 0d0 - dradxi = 0.0 - dradyi = 0.0 - dradzi = 0.0 - - pmassi = massoftype(iamtypei) - !calculate rhoi - call rhoanddhdrho(hi,hi1,rhoi,rho1i,dhdrhoi,pmassi) - ! get Ti from tabulated eos - if (vxyzu(4,i) < epsilon(vxyzu(4,i))) then - print *, "u=0 in FLD calc", vxyzu(4,i), i,rhoi*unit_density,Ti,& - cell%xpartvec(ixi,icell),cell%xpartvec(iyi,icell) - endif - call getopac_opdep(vxyzu(4,i)*unit_ergg,rhoi*unit_density,kappabari, & - kappaparti,Ti,gmwi) - - loop_over_neighbours: do n=1,nneigh - j = abs(listneigh(n)) - if (i==j) cycle loop_over_neighbours - xj = xyzh(1,j) - yj = xyzh(2,j) - zj = xyzh(3,j) - - dx = cell%xpartvec(ixi,icell) - xj - dy = cell%xpartvec(iyi,icell) - yj - dz = cell%xpartvec(izi,icell) - zj - -#ifdef PERIODIC - if (abs(dx) > 0.5*dxbound) dx = dx - dxbound*SIGN(1.0,dx) - if (abs(dy) > 0.5*dybound) dy = dy - dybound*SIGN(1.0,dy) - if (abs(dz) > 0.5*dzbound) dz = dz - dzbound*SIGN(1.0,dz) -#endif - - rij2 = dx*dx + dy*dy + dz*dz + TINY(0.) - rij = SQRT(rij2) - q2i = rij2*hi21 - qi = SQRT(q2i) - - hj1 = 1./xyzh(4,j) - hj = 1./hj1 - hj21 = hj1*hj1 - q2j = rij2*hj21 - - is_sph_neighbour: if (q2i < radkern2 .or. q2j < radkern2) then - if (maxphase==maxp) then - call get_partinfo(iphase(j),iactivej,iamgasj,iamdustj,iamtypej) - else - iactivej = .true. - iamtypej = igas - iamgasj = .true. - endif - if (.not. iamgasj) cycle loop_over_neighbours - if (.not. iactivej) cycle loop_over_neighbours - ! get kernel quantities - if (gradh(1,i) > 0.) then - gradhi = gradh(1,i) - !elseif (ngradh_err < 20) then - ! call error('force','stored gradh is zero, resetting to 1') - ! gradhi = 1. - ! ngradh_err = ngradh_err + 1 - else - gradhi = 1. - ngradh_err = ngradh_err + 1 - endif - call get_kernel(q2i,qi,wabi,grkerni) - wkerni = wabi*cnormk*hi21*hi1 - dwkerni = grkerni*cnormk*hi21*hi21*gradh(1,i) - pmassj = massoftype(iamtypej) - call rhoanddhdrho(hj,hj1,rhoj,rho1j,dhdrhoj,pmassj) - call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,& - kappaBarj,kappaPartj,Tj,gmwj) - uradi = uradi + get_radconst_code()*(Tj**4.0d0)*wkerni*pmassj/rhoj - - ! calculate components of gradient - runix = dx/rij - runiy = dy/rij - runiz = dz/rij - - dT4 = Ti**4d0 - Tj**4d0 - dradxi = dradxi + get_radconst_code()*pmassj*dT4*dwkerni*runix/rhoj - dradyi = dradyi + get_radconst_code()*pmassj*dT4*dwkerni*runiy/rhoj - dradzi = dradzi + get_radconst_code()*pmassj*dT4*dwkerni*runiz/rhoj - - endif is_sph_neighbour - - enddo loop_over_neighbours - - ! add self contribution - - uradi = uradi + cnormk*hi31*get_radconst_code()*(Ti**4d0) & - *wab0*pmassi/rhoi - if (uradi > 1.d0) print *, "cnormk,hi31,radconst,Ti,wab0,pmassi,rhoi",& - cnormk,hi31,get_radconst_code(),Ti,wab0,pmassi,rhoi,"wabi,wkerni,pmassj,rhoj", & - wabi,wkerni,pmassj,rhoj -!$omp critical - if (iamgasi .and. uradi > 0d0) urad_FLD(i) = uradi -!$omp end critical - !Now calculate flux limiter coefficients - !Calculate in code units (converted to code units in forcei) - dradi = SQRT(dradxi*dradxi + dradyi*dradyi + dradzi*dradzi) ! should this be normalised somehow? - if ((dradi.eq.0.0d0).or.(uradi.eq.0.0d0)) then - R_rad = 0.0d0 - else - R_rad = dradi/(uradi*rhoi*kappaParti/unit_opacity) - endif -!$omp critical - lambda(i) = (2.0d0+R_rad)/(6.0d0+3.0d0*R_rad+R_rad*R_rad) -!$omp end critical - if (isnan(lambda(i))) then - print *, "lambda isnan when calculated. i, R_Rad, uradi,dradi,rhoi,",& - "kappaParti, Ti",i,R_Rad,uradi,dradi,rhoi,kappaParti,Ti - endif - - enddo over_parts -! if (ngradh_err > 0) print *, "ngradh_errors = ", ngradh_err -end subroutine calc_lambda_cell - end module densityforce diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index ff0864126..3f1d692fd 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -19,15 +19,13 @@ module eos_stamatellos implicit none real,allocatable,public :: optable(:,:,:) - real,allocatable,public :: duFLD(:),gradP_cool(:),lambda_FLD(:),urad_FLD(:) !gradP_cool=gradP/rho + real,allocatable,public :: gradP_cool(:)!gradP_cool=gradP/rho real,allocatable,public :: ttherm_store(:),teqi_store(:),opac_store(:),duSPH(:) character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file - logical,public :: doFLD = .True., floor_energy = .False. - integer,public :: iunitst=19 + logical,public :: floor_energy = .False. integer,save :: nx,ny ! dimensions of optable read in public :: read_optab,getopac_opdep,init_coolra,getintenerg_opdep,finish_coolra - public :: get_k_fld contains @@ -35,39 +33,26 @@ subroutine init_coolra() use part, only:npart,maxradprop print *, "Allocating cooling arrays" allocate(gradP_cool(npart)) - allocate(duFLD(npart)) - allocate(lambda_fld(npart)) - allocate(urad_FLD(npart)) allocate(ttherm_store(npart)) allocate(teqi_store(npart)) allocate(opac_store(npart)) allocate(duSPH(npart)) gradP_cool(:) = 0d0 - urad_FLD(:) = 0d0 - duFLD(:) = 0d0 teqi_store(:) = 0d0 ttherm_store(:) = 0d0 opac_store(:) = 0d0 duSPH(:) = 0d0 - open (unit=iunitst,file='EOSinfo.dat',status='replace') - if (doFLD) then - print *, "Using Forgan+ 2009 hybrid cooling method (FLD)" - else - print *, "NOT using FLD. Using cooling only" - endif + print *, "NOT using FLD. Using cooling only" + end subroutine init_coolra subroutine finish_coolra() deallocate(optable) if (allocated(gradP_cool)) deallocate(gradP_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(opac_store)) deallocate(opac_store) if (allocated(duSPH)) deallocate(duSPH) - close(iunitst) end subroutine finish_coolra subroutine read_optab(eos_file,ierr) @@ -273,28 +258,6 @@ subroutine getintenerg_opdep(Teqi, rhoi, ueqi) ueqi = m*rhoi_ + c end subroutine getintenerg_opdep -subroutine get_k_fld(rhoi,eni,i,ki,Ti) - use physcon, only:c,fourpi - use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code - real,intent(in) :: rhoi,eni - integer,intent(in) :: i - real :: kappaBar,gmwi,kappaPart - real,intent(out) :: ki,Ti - - if (lambda_FLD(i) == 0d0) then - ki = 0. - else - call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) - kappaPart = kappaPart/unit_opacity - ! steboltz constant = 4pi/c * arad - ki = 16d0*(fourpi/c)*get_radconst_code()*lambda_FLD(i)*Ti**3 /rhoi/kappaPart - if (isnan(ki)) then - print *, "WARNING k isnan, lambda_FLDi,Ti,rhoi,kappaPart", & - lambda_FLD(i), Ti, rhoi,kappaPart - endif - endif -end subroutine get_k_fld - end module eos_stamatellos diff --git a/src/main/force.F90 b/src/main/force.F90 index 4ddfc195f..5da44e206 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -903,7 +903,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g use part, only:rhoh,dvdx use nicil, only:nimhd_get_jcbcb,nimhd_get_dBdt use eos, only:ieos,eos_is_non_ideal - use eos_stamatellos, only:gradP_cool,duFLD,doFLD,getopac_opdep,get_k_fld + use eos_stamatellos, only:gradP_cool,getopac_opdep #ifdef GRAVITY use kernel, only:kernel_softening use ptmass, only:ptmass_not_obscured @@ -1024,7 +1024,7 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g real :: bigv2j,alphagrj,enthi,enthj real :: dlorentzv,lorentzj,lorentzi_star,lorentzj_star,projbigvi,projbigvj real :: bigvj(1:3),velj(3),metricj(0:3,0:3,2),projbigvstari,projbigvstarj - real :: radPj,fgravxi,fgravyi,fgravzi,kfldi,kfldj,Ti,Tj,diffterm + real :: radPj,fgravxi,fgravyi,fgravzi real :: gradpx,gradpy,gradpz,gradP_cooli=0d0,gradP_coolj=0d0 ! unpack @@ -1187,20 +1187,9 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g fgravzi = 0. if (icooling == 9) then gradP_cool(i) = 0d0 - if (doFLD) then - duFLD(i) = 0d0 - kfldi = 0d0 - kfldj = 0d0 - endif gradpx = 0d0 gradpy = 0d0 gradpz = 0d0 - diffterm = 0d0 - Ti=0 - Tj=0 - if (doFLD .and. dt > 0d0) then - call get_k_fld(rhoi,eni,i,kfldi,Ti) - endif endif loop_over_neighbours2: do n = 1,nneigh @@ -1599,25 +1588,6 @@ subroutine compute_forces(i,iamgasi,iamdusti,xpartveci,hi,hi1,hi21,hi41,gradhi,g gradP_coolj = 0d0 if (usej) then gradp_coolj = pmassj*prj*rho1j*rho1j*grkernj - if (doFLD .and. dt > 0.) then - call get_k_fld(rhoj,enj,j,kfldj,Tj) - if (rhoj == 0d0) then - diffterm = 0d0 - print *, "setting diffterm = 0", i, j, rhoj - elseif ((kfldj + kfldi) < tiny(0.)) then - diffterm = 0d0 - else - diffterm = 4d0*pmassj/rhoi/rhoj - diffterm = diffterm * kfldi * kfldj / (kfldi+kfldj) - diffterm = diffterm * (Ti - Tj) / rij2 - diffterm = diffterm*cnormk*grkerni*(runix*dx + runiy*dy + runiz*dz) - endif - duFLD(i) = duFLD(i) + diffterm - if (isnan(duFLD(i))) then - print *, "kfldi, kfldj, Ti,Tj,diffterm", kfldi,kfldj, Ti,Tj,diffterm - call fatal('force','duFLD is nan') - endif - endif endif endif diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index 208942da0..bd7b57a5a 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:gradP_cool,doFLD,urad_FLD,ttherm_store,teqi_store,opac_store + use eos_stamatellos, only:ttherm_store,teqi_store,opac_store real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -249,8 +249,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) endif endif ! write stamatellos cooling values - if (icooling == 9) then ! .and. doFLD) then -! call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) + if (icooling == 9) then call write_array(1,teqi_store,'teqi',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) From 29d08eec80ea89b37c198b7ab1d842e1ae78cbca Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 19 Sep 2024 10:56:25 +0100 Subject: [PATCH 148/182] Fix bug from merge. --- src/main/radiation_utils.f90 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 4ac9b11ef..95dfb16de 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -411,13 +411,15 @@ end function get_kappa ! calculate opacities !+ !-------------------------------------------------------------------- -subroutine get_opacity(opacity_type,density,temperature,kappa) +subroutine get_opacity(opacity_type,density,temperature,kappa,u) + use eos_stamatellos, only:getopac_opdep use mesa_microphysics, only:get_kappa_mesa - use units, only:unit_density,unit_opacity + use units, only:unit_density,unit_opacity,unit_ergg real, intent(in) :: density, temperature + real, intent(in), optional :: u real, intent(out) :: kappa integer, intent(in) :: opacity_type - real :: kapt,kapr,rho_cgs + real :: kapt,kapr,rho_cgs,Ti,gmwi,gammai,kapBar,kappaPart select case(opacity_type) case(1) From d0c12c4ed11810f4917268413bc3a10c7012eeeb Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 19 Sep 2024 15:55:39 +0100 Subject: [PATCH 149/182] Add changes from master branch --- src/main/readwrite_infile.F90 | 9 +-- src/utils/analysis_disc_stresses.f90 | 71 ++++++++++++++++++------ src/utils/moddump_sphNG2phantom_disc.f90 | 10 ++-- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index 36f75f937..8fa5af9ed 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -217,7 +217,7 @@ subroutine write_infile(infile,logfile,evfile,dumpfile,iwritein,iprint) ! call write_options_eos(iwritein) if (maxvxyzu >= 4 .and. (ieos==2 .or. ieos==5 .or. ieos==10 .or. ieos==15 .or. ieos==12 .or. ieos==16 & - .or. ieos==17 .or. ieos==22 .or. ieos==23) ) then + .or. ieos==17 .or. ieos==21 .or. ieos==22 .or. ieos==23) ) then call write_inopt(ipdv_heating,'ipdv_heating','heating from PdV work (0=off, 1=on)',iwritein) call write_inopt(ishock_heating,'ishock_heating','shock heating (0=off, 1=on)',iwritein) if (mhd) then @@ -692,14 +692,15 @@ subroutine read_infile(infile,logfile,evfile,dumpfile) if (beta > 4.) call warn(label,'very high beta viscosity set') #ifndef MCFOST if (maxvxyzu >= 4 .and. (ieos /= 2 .and. ieos /= 5 .and. ieos /= 4 .and. ieos /= 10 .and. & - ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 17 .and. & - ieos /= 20 .and. ieos/=22 .and. ieos/=23)) & - call fatal(label,'only ieos=2 makes sense if storing thermal energy') + ieos /=11 .and. ieos /=12 .and. ieos /= 15 .and. ieos /= 16 .and. ieos /= 17 .and. & + ieos /= 20 .and. ieos/=21 .and. ieos/=22 .and. ieos/=23)) & + call fatal(label,'only ieos=2 makes sense if storing thermal energy') #endif if (irealvisc < 0 .or. irealvisc > 12) call fatal(label,'invalid setting for physical viscosity') if (shearparam < 0.) call fatal(label,'stupid value for shear parameter (< 0)') if (irealvisc==2 .and. shearparam > 1) call error(label,'alpha > 1 for shakura-sunyaev viscosity') if (iverbose > 99 .or. iverbose < -9) call fatal(label,'invalid verboseness setting (two digits only)') + if (icooling > 0 .and. .not.(ieos == 2 .or. ieos == 5 .or. ieos == 17 .or. ieos == 22 .or. ieos == 23)) & call fatal(label,'cooling requires adiabatic eos (ieos=2)') if (icooling > 0 .and. (ipdv_heating <= 0 .or. ishock_heating <= 0)) & diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index 7751c4da0..ff76e1c4f 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -6,7 +6,8 @@ !--------------------------------------------------------------------------! module analysis ! -! Analysis routine for discs by DF, adapted from a routine by CJN +! Analysis routine for discs by DF, adapted from a routine by CJN. +! Edited for use with variable gammai and mui by AKY ! ! :References: None ! @@ -31,7 +32,7 @@ module analysis real :: rin, rout,dr integer, allocatable,dimension(:) :: ipartbin real, allocatable,dimension(:) :: rad,ninbin,sigma,csbin,vrbin,vphibin, omega - real, allocatable,dimension(:) :: H, toomre_q,epicyc + real, allocatable,dimension(:) :: H, toomre_q,epicyc,part_scaleheight real, allocatable,dimension(:) :: alpha_reyn,alpha_grav,alpha_mag,alpha_art real, allocatable,dimension(:) :: rpart,phipart,vrpart,vphipart, gr,gphi,Br,Bphi real, allocatable,dimension(:,:) :: gravxyz @@ -45,7 +46,7 @@ module analysis subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) use io, only:fatal - use part, only:gravity,mhd + use part, only:gravity,mhd,eos_vars character(len=*), intent(in) :: dumpfile real, intent(in) :: xyzh(:,:),vxyzu(:,:) @@ -85,7 +86,7 @@ subroutine do_analysis(dumpfile,numfile,xyzh,vxyzu,pmass,npart,time,iunit) call transform_to_cylindrical(npart,xyzh,vxyzu) ! Bin particles by radius - call radial_binning(npart,xyzh,vxyzu,pmass) + call radial_binning(npart,xyzh,vxyzu,pmass,eos_vars) ! Calculate stresses call calc_stresses(npart,xyzh,vxyzu,pmass) @@ -362,7 +363,7 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) integer,intent(in) :: npart real,intent(in) :: pmass - real,intent(in) :: xyzh(:,:),vxyzu(:,:) + real,intent(in) :: xyzh(:,:),vxyzu(:,:),eos_vars(:,:) integer :: ibin,ipart,nbinned real :: area,csi @@ -377,6 +378,7 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) allocate(omega(nbins)) allocate(vrbin(nbins)) allocate(vphibin(nbins)) + allocate(part_scaleheight(nbins)) ipartbin(:) = 0 ninbin(:) = 0.0 @@ -385,6 +387,15 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) omega(:) = 0.0 vrbin(:) = 0.0 vphibin(:) = 0.0 + part_scaleheight(:) = 0.0 + + allocate(zsetgas(npart,nbins),stat=iallocerr) + ! If you don't have enough memory to allocate zsetgas, then calculate H the slow way with less memory. + if (iallocerr/=0) then + write(*,'(/,a)') ' WARNING: Could not allocate memory for array zsetgas!' + write(*,'(a)') ' (It possibly requires too much memory)' + write(*,'(a,/)') ' Try calculate scaleheight the slow way.' + endif ! Set up radial bins @@ -423,11 +434,13 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) vrbin(ibin) = vrbin(ibin) + vrpart(ipart) vphibin(ibin) = vphibin(ibin) + vphipart(ipart) omega(ibin) = omega(ibin) + vphipart(ipart)/rad(ibin) - + zsetgas(int(ninbin(ibin)),ibin) = xyzh(3,ipart) endif enddo + call calculate_H(nbins,part_scaleheight,zsetgas,int(ninbin)) + part_scaleheight(:) = part_scaleheight(:) print*, nbinned, ' particles have been binned' where(ninbin(:)/=0) @@ -448,11 +461,11 @@ end subroutine radial_binning !+ !-------------------------------------------------------------- subroutine calc_stresses(npart,xyzh,vxyzu,pmass) - use physcon, only: pi,gg + use physcon, only: pi,gg,kb_on_mh use units, only: print_units, umass,udist,utime,unit_velocity,unit_density,unit_Bfield use dim, only: gravity - use part, only: mhd,rhoh,alphaind - use eos, only: gamma + use part, only: mhd,rhoh,alphaind,eos_vars,imu,itemp + use eos, only: gamma,ieos implicit none @@ -486,7 +499,9 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) call print_units sigma(:) = sigma(:)*umass/(udist*udist) - csbin(:) = csbin(:)*unit_velocity + if (ieos /= 23) then + csbin(:) = csbin(:)*unit_velocity + endif omega(:) = omega(:)/utime Keplog = 1.5 @@ -505,9 +520,8 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) do ipart=1,npart ibin = ipartbin(ipart) - if (ibin<=0) cycle - - cs2 = gamma*(gamma-1)*vxyzu(4,ipart)*unit_velocity*unit_velocity + if (ibin<=0) cycle + dvr = (vrpart(ipart) - vrbin(ibin))*unit_velocity dvphi = (vphipart(ipart) -vphibin(ibin))*unit_velocity @@ -515,6 +529,7 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) alpha_reyn(ibin) = alpha_reyn(ibin) + dvr*dvphi +! Handle constant alpha_sph alpha_art(ibin) = alpha_art(ibin) + alphaind(1,ipart)*xyzh(4,ipart)*udist if (gravity) alpha_grav(ibin) = alpha_grav(ibin) + gr(ipart)*gphi(ipart)/rhopart @@ -592,7 +607,7 @@ subroutine write_radial_data(iunit,output,time) print '(a,a)', 'Writing to file ',output open(iunit,file=output) write(iunit,'("# Disc Stress data at t = ",es20.12)') time - write(iunit,"('#',11(1x,'[',i2.2,1x,a11,']',2x))") & + write(iunit,"('#',12(1x,'[',i2.2,1x,a11,']',2x))") & 1,'radius (AU)', & 2,'sigma (cgs)', & 3,'cs (cgs)', & @@ -603,12 +618,13 @@ subroutine write_radial_data(iunit,output,time) 8,'alpha_reyn',& 9,'alpha_grav',& 10,'alpha_mag',& - 11,'alpha_art' + 11,'alpha_art',& + 12,'particle H (au)' do ibin=1,nbins - write(iunit,'(11(es18.10,1X))') rad(ibin),sigma(ibin),csbin(ibin), & + write(iunit,'(12(es18.10,1X))') rad(ibin),sigma(ibin),csbin(ibin), & omega(ibin),epicyc(ibin),H(ibin), abs(toomre_q(ibin)),alpha_reyn(ibin), & - alpha_grav(ibin),alpha_mag(ibin),alpha_art(ibin) + alpha_grav(ibin),alpha_mag(ibin),alpha_art(ibin),part_scaleheight(ibin) enddo close(iunit) @@ -617,6 +633,26 @@ subroutine write_radial_data(iunit,output,time) end subroutine write_radial_data +subroutine calculate_H(nbin,H,zsetgas,ninbin) +! copied from utils disc + integer, intent(in) :: nbin + real, intent(out) :: H(:) + real, intent(in) :: zsetgas(:,:) + integer, intent(in) :: ninbin(:) + integer :: ii + real :: meanzii + + do ii = 1,nbin + if (ninbin(ii)==0) then + meanzii = 0. + else + meanzii = sum(zsetgas(1:ninbin(ii),ii))/real(ninbin(ii)) + endif + H(ii) = sqrt(sum(((zsetgas(1:ninbin(ii),ii)-meanzii)**2)/(real(ninbin(ii)-1)))) + enddo + +end subroutine calculate_H + !-------------------------------------------------------- !+ ! Deallocate arrays @@ -633,6 +669,7 @@ subroutine deallocate_arrays deallocate(gr,gphi,Br,Bphi,vrbin,vphibin) deallocate(sigma,csbin,H,toomre_q,omega,epicyc) deallocate(alpha_reyn,alpha_grav,alpha_mag,alpha_art) + deallocate(part_scaleheight) end subroutine deallocate_arrays !------------------------------------------------------- diff --git a/src/utils/moddump_sphNG2phantom_disc.f90 b/src/utils/moddump_sphNG2phantom_disc.f90 index 833b765cf..7e7e3a159 100644 --- a/src/utils/moddump_sphNG2phantom_disc.f90 +++ b/src/utils/moddump_sphNG2phantom_disc.f90 @@ -32,7 +32,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) use prompting, only:prompt use physcon, only:au,gg use readwrite_dumps_fortran, only:dt_read_in_fortran - use timestep, only:time,dt,dtmax_max,dtmax_min,dtmax0 + use timestep, only:time,dt,dtmax_max,dtmax_min use centreofmass, only: reset_centreofmass integer, intent(inout) :: npart integer, intent(inout) :: npartoftype(:) @@ -82,9 +82,9 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) nptmass = nptmass + npt do i=1,npt read (iunit,*) junk - read (iunit,'(10E15.6)') (xyzmh_ptmass(j,nptmass),j=1,10) + read (iunit,'(10E15.6)') (xyzmh_ptmass(j,i),j=1,10) read (iunit,*) junk - read (iunit,'(3E15.6)') (vxyz_ptmass(j,nptmass),j=1,3) + read (iunit,'(3E15.6)') (vxyz_ptmass(j,i),j=1,3) enddo close(iunit) endif @@ -97,7 +97,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) enddo close(iunit) - print *, 'dtmax0, dtmax_max,dtmax_min',dtmax0,dtmax_max,dtmax_min + print *, 'dtmax_max,dtmax_min',dtmax_max,dtmax_min newutime = sqrt(au**3/(gg*umass)) print *, "newutime/old", newutime/utime time = time * utime / newutime @@ -177,7 +177,7 @@ subroutine modify_dump(npart,npartoftype,massoftype,xyzh,vxyzu) 'nptmass:', nptmass print *, 'gamma=', gamma print *, 'Timestep info:' - print *, 'dtmax0, dtmax_max,dtmax_min', dtmax0,dtmax_max,dtmax_min + print *, 'dtmax_max,dtmax_min', dtmax_max,dtmax_min print *, 'utime=', utime return From 7bbbd48e49bb631077f3405ca2cfaa71383c138e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 20 Sep 2024 14:51:16 +0100 Subject: [PATCH 150/182] Add radiative cooling approximation to Docs --- .../selfgravity_gravitationalinstability.rst | 7 ++++++ docs/physics/eos-list.rst | 6 +++++ docs/physics/radiation.rst | 22 +++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/docs/examples/selfgravity_gravitationalinstability.rst b/docs/examples/selfgravity_gravitationalinstability.rst index 8146e009e..effb82630 100644 --- a/docs/examples/selfgravity_gravitationalinstability.rst +++ b/docs/examples/selfgravity_gravitationalinstability.rst @@ -17,3 +17,10 @@ In the *setup* file there are the disc parameters, and in the *input* file it is - ieos = 2 , to choose an adiabatic equation of state - icooling = 3, to choose a β cooling prescription with constant β (icooling = 7 prescribes a varying β cooling with the radius) - beta_cool = #, to choose the value of β cooling + +To use the radiative cooling approximation of Young et al. (2024) use: + +- ieos = 23 +- icooling = 9 + +See :doc:`Radiation hydrodynamics in phantom `. \ No newline at end of file diff --git a/docs/physics/eos-list.rst b/docs/physics/eos-list.rst index be573c5a4..977bae36f 100644 --- a/docs/physics/eos-list.rst +++ b/docs/physics/eos-list.rst @@ -124,3 +124,9 @@ | | from HORMONE, Hirai+2020, as used in Lau+2022b | | | | +-----------+----------------------------------------------------------------------------------+ + | 23 | **Tabulated EoS of Stamatellos et al. 2007 (includes opacities)** | + | | | + | | Tabulated equation of state with opacities from Lombardi et al. 2015. For use | + | | with icooling = 9, the radiative cooling approximation (Young et al. 2024). | | + | | | + +-----------+----------------------------------------------------------------------------------+ \ No newline at end of file diff --git a/docs/physics/radiation.rst b/docs/physics/radiation.rst index fdd6b94b4..7cbe49ec2 100644 --- a/docs/physics/radiation.rst +++ b/docs/physics/radiation.rst @@ -103,6 +103,28 @@ the star will just steadily cool. For red giants with a sink particle core a sim is to supply a constant luminosity input from the core (:doc:`sink heating `). This is experimental. Another option would be to include a nuclear burning network (please somebody contribute this). + +Polytropic radiative cooling approximation +------------------------------------------- +This is an alternative to computationally expensive radiative transfer in regimes where radiative cooling is +important. This method estimates the optical depth for each particle and its equilibrium temperature. From +these the new temperature and internal energy is updated at each timestep. The method implemented here is +the "modified Lombardi" method of `Young et al. (2024) `__, + which was based on Stamatellos et al. (2007) and Lombardi et al. (2015). This method is designed for + self-gravitating discs around a central star. Stellar heating is included from the most massive sink particle. + +Use icooling = 9 and ieos = 23 to use the tabulated equation of state which has the opacity tables required +for the cooling calculation. The additional parameters are:: + + EOS_file = myeos.dat ! File containing tabulated EOS values + Lstar = 0.440 ! Luminosity of host star for calculating Tmin (Lsun) + Tfloor = 5.000 ! temperature floor (K); on if > 0 + + +N.B. This version does not currently include radiation from more than one sink particle. This version does not +couple with flux-limited diffusion at the moment. + + Irradiation from stars with phantom + MCFOST --------------------------------------------- In regimes where the radiation diffusion time is relatively short, anything not inside stars From db9c33524fb630208861a7f3461d5ada8a5edb7a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 26 Sep 2024 10:35:56 +0100 Subject: [PATCH 151/182] placeholder for eos_lom.dat --- data/eos/lombardi/README | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 data/eos/lombardi/README diff --git a/data/eos/lombardi/README b/data/eos/lombardi/README new file mode 100644 index 000000000..9120e52cb --- /dev/null +++ b/data/eos/lombardi/README @@ -0,0 +1,10 @@ +The data tables for the equation of state and opacities for the modified Lombardi radiative cooling approximation are too large to be stored in the Phantom git repository. +They will be downloaded automatically when you run the code + +or can be retrieved manually using wget from Zenodo, e.g.: + +wget https://zenodo.org/records/13842491/files/eos_lom.dat + +The files are: + +eos_lom.dat From 5bc139e2973f3a65c5eb6b2fa359121f3848e69c Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 26 Sep 2024 10:59:22 +0100 Subject: [PATCH 152/182] Enable automatic download of EOS/opacity file for modified Lombardi radiative cooling --- .gitignore | 1 + src/main/datafiles.f90 | 2 ++ src/main/eos_stamatellos.f90 | 6 +++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 0a86fba6e..83990d4d7 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ _build *.cmod *.ilm *.stb +eos_lom.dat \ No newline at end of file diff --git a/src/main/datafiles.f90 b/src/main/datafiles.f90 index df791da0b..f41a85938 100644 --- a/src/main/datafiles.f90 +++ b/src/main/datafiles.f90 @@ -75,6 +75,8 @@ function map_dir_to_web(search_dir) result(url) url = 'https://zenodo.org/records/13162815/files/' case('data/starcluster') url = 'https://zenodo.org/records/13164858/files/' + case('data/eos/lombardi') + url = 'https://zenodo.org/records/13842491/files/' case default url = 'https://users.monash.edu.au/~dprice/'//trim(search_dir) end select diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 3f1d692fd..c831e99b8 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -21,7 +21,7 @@ module eos_stamatellos real,allocatable,public :: optable(:,:,:) real,allocatable,public :: gradP_cool(:)!gradP_cool=gradP/rho real,allocatable,public :: ttherm_store(:),teqi_store(:),opac_store(:),duSPH(:) - character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file + character(len=25), public :: eos_file= 'eos_lom.dat' !default name of tabulated EOS file logical,public :: floor_energy = .False. integer,save :: nx,ny ! dimensions of optable read in @@ -62,8 +62,8 @@ subroutine read_optab(eos_file,ierr) integer i,j,errread character(len=120) :: filepath,junk - ! read in data file for interpolation - filepath=find_phantom_datafile(eos_file,'cooling') + ! read in EOS and opacity data file for interpolation + filepath=find_phantom_datafile(eos_file,'eos/lombardi') print *,"EOS file: FILEPATH:",filepath open(10, file=filepath, form="formatted", status="old",iostat=ierr) if (ierr > 0) return From c156cbf570cc59f4f48046e9f36d00085337d426 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 26 Sep 2024 11:07:25 +0100 Subject: [PATCH 153/182] Enable remote download of Lombardi EOS/opacity file --- data/eos/lombardi/README | 10 ++++++++++ src/main/datafiles.f90 | 2 ++ src/main/eos_stamatellos.f90 | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 data/eos/lombardi/README diff --git a/data/eos/lombardi/README b/data/eos/lombardi/README new file mode 100644 index 000000000..9120e52cb --- /dev/null +++ b/data/eos/lombardi/README @@ -0,0 +1,10 @@ +The data tables for the equation of state and opacities for the modified Lombardi radiative cooling approximation are too large to be stored in the Phantom git repository. +They will be downloaded automatically when you run the code + +or can be retrieved manually using wget from Zenodo, e.g.: + +wget https://zenodo.org/records/13842491/files/eos_lom.dat + +The files are: + +eos_lom.dat diff --git a/src/main/datafiles.f90 b/src/main/datafiles.f90 index df791da0b..f41a85938 100644 --- a/src/main/datafiles.f90 +++ b/src/main/datafiles.f90 @@ -75,6 +75,8 @@ function map_dir_to_web(search_dir) result(url) url = 'https://zenodo.org/records/13162815/files/' case('data/starcluster') url = 'https://zenodo.org/records/13164858/files/' + case('data/eos/lombardi') + url = 'https://zenodo.org/records/13842491/files/' case default url = 'https://users.monash.edu.au/~dprice/'//trim(search_dir) end select diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 11eaa0813..5877dcf64 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -21,7 +21,7 @@ module eos_stamatellos 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(:) - character(len=25), public :: eos_file= 'myeos.dat' !default name of tabulated EOS file + 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 integer,save :: nx,ny ! dimensions of optable read in @@ -81,7 +81,7 @@ subroutine read_optab(eos_file,ierr) character(len=120) :: filepath,junk ! read in data file for interpolation - filepath=find_phantom_datafile(eos_file,'cooling') + filepath=find_phantom_datafile(eos_file,'eos/lombardi') print *,"EOS file: FILEPATH:",filepath open(10, file=filepath, form="formatted", status="old",iostat=ierr) if (ierr > 0) return From a8d183f682d45c4222df88f08a85859ccffc2504 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 26 Sep 2024 11:09:30 +0100 Subject: [PATCH 154/182] Added eos_lom.dat to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0a86fba6e..83990d4d7 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ _build *.cmod *.ilm *.stb +eos_lom.dat \ No newline at end of file From 9446bf4f7860c491cac939ae1d3b4b7cb2d8cdda Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 26 Sep 2024 12:20:38 +0100 Subject: [PATCH 155/182] Run bots --- AUTHORS | 3 ++- src/main/cooling.f90 | 6 +++--- src/main/cooling_radapprox.f90 | 16 ++++++++-------- src/main/dens.F90 | 2 +- src/main/eos.f90 | 4 ++-- src/main/eos_stamatellos.f90 | 6 +++--- src/main/force.F90 | 11 ++++++----- src/main/readwrite_dumps_fortran.f90 | 4 ++-- src/utils/analysis_disc_stresses.f90 | 6 +++--- 9 files changed, 30 insertions(+), 28 deletions(-) diff --git a/AUTHORS b/AUTHORS index b1dd08d0b..979f8bf7c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -16,6 +16,7 @@ Yann Bernard Daniel Mentiplay Megha Sharma Arnaud Vericel +Alison Young Mark Hutchison Mats Esseldeurs Rebecca Nealon @@ -34,7 +35,6 @@ Giovanni Dipierro Roberto Iaconi Amena Faruqi Hauke Worpel -Alison Young Stephen Nielson Martina Toscani Benedetta Veronesi @@ -57,6 +57,7 @@ Nicolás Cuello Chris Nixon Miguel Gonzalez-Bolivar Benoit Commercon +Christopher Russell Giulia Ballabio Joe Fisher Maxime Lombart diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 7f5dac575..ad22d5542 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -28,9 +28,9 @@ module cooling ! - icooling : *cooling function (0=off, 1=library (step), 2=library (force),* ! ! :Dependencies: chem, cooling_gammie, cooling_gammie_PL, cooling_ism, -! cooling_koyamainutsuka, cooling_molecular, cooling_solver, -! cooling_radapprox, dim, eos, eos_stamatellos, infile_utils, io, -! options, part, physcon, timestep, units, viscosity +! cooling_koyamainutsuka, cooling_molecular, cooling_radapprox, +! cooling_solver, dim, eos, eos_stamatellos, infile_utils, io, options, +! part, physcon, timestep, units, viscosity ! use options, only:icooling diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 23cc2c47e..925b75fcf 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -1,8 +1,8 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! +! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! module cooling_radapprox ! @@ -13,8 +13,8 @@ module cooling_radapprox ! :Owner: Alison Young ! ! :Runtime parameters: -! - EOS_file : File containing tabulated EOS values -! - Lstar : Luminosity of host star for calculating Tmin (Lsun) +! - EOS_file : *File containing tabulated EOS values* +! - Lstar : *Luminosity of host star for calculating Tmin (Lsun)* ! ! :Dependencies: eos_stamatellos, infile_utils, io, part, physcon, units ! @@ -108,9 +108,9 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) 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 + 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 ! Tfloor is from input parameters and is background heating ! Stellar heating @@ -166,7 +166,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) ! evolve energy if (tthermi == 0d0) then dudti_cool = 0d0 ! condition if denominator above is zero - elseif ( (dt/tthermi) < TINY(ui) ) then + 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 diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 1cae9a211..809b445f8 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -377,7 +377,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol endif call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad) - + if (do_export) then call write_cell(stack_waiting,cell) exit local_its diff --git a/src/main/eos.f90 b/src/main/eos.f90 index 2593a620b..c0ebc16bd 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -44,8 +44,8 @@ module eos ! ! :Dependencies: dim, dump_utils, eos_HIIR, eos_barotropic, eos_gasradrec, ! eos_helmholtz, eos_idealplusrad, eos_mesa, eos_piecewise, eos_shen, -! eos_stratified, infile_utils, io, mesa_microphysics, part, physcon, -! units +! eos_stamatellos, eos_stratified, infile_utils, io, mesa_microphysics, +! part, physcon, units ! use part, only:ien_etotal,ien_entropy,ien_type use dim, only:gr diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index c831e99b8..5fd8da69a 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -14,7 +14,7 @@ module eos_stamatellos ! ! :Runtime parameters: None ! -! :Dependencies: datafiles, part +! :Dependencies: datafiles, io, part ! implicit none @@ -65,12 +65,12 @@ subroutine read_optab(eos_file,ierr) ! read in EOS and opacity data file for interpolation filepath=find_phantom_datafile(eos_file,'eos/lombardi') print *,"EOS file: FILEPATH:",filepath - open(10, file=filepath, form="formatted", status="old",iostat=ierr) + open(10,file=filepath,form="formatted",status="old",iostat=ierr) if (ierr > 0) return do read(10,'(A120)') 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 + if ((index(adjustl(junk),"::") == 0) .and. (index(adjustl(junk),"#") /= 1 )) then !ignore comment lines junk = adjustl(junk) read(junk, *,iostat=errread) nx, ny exit diff --git a/src/main/force.F90 b/src/main/force.F90 index 5da44e206..394d774cf 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -39,11 +39,12 @@ module forces ! ! :Runtime parameters: None ! -! :Dependencies: boundary, cooling, dim, dust, eos, eos_shen, fastmath, -! growth, io, io_summary, kdtree, kernel, linklist, metric_tools, -! mpiderivs, mpiforce, mpimemory, mpiutils, nicil, omputils, options, -! part, physcon, ptmass, ptmass_heating, radiation_utils, timestep, -! timestep_ind, timestep_sts, timing, units, utils_gr, viscosity +! :Dependencies: boundary, cooling, dim, dust, eos, eos_shen, +! eos_stamatellos, fastmath, growth, io, io_summary, kdtree, kernel, +! linklist, metric_tools, mpiderivs, mpiforce, mpimemory, mpiutils, +! nicil, omputils, options, part, physcon, ptmass, ptmass_heating, +! radiation_utils, timestep, timestep_ind, timestep_sts, timing, units, +! utils_gr, viscosity ! use dim, only:maxfsum,maxxpartveciforce,maxp,ndivcurlB,ndivcurlv,& maxdusttypes,maxdustsmall,do_radiation diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index bd7b57a5a..c70fb7f98 100644 --- a/src/main/readwrite_dumps_fortran.f90 +++ b/src/main/readwrite_dumps_fortran.f90 @@ -18,8 +18,8 @@ module readwrite_dumps_fortran ! ! :Runtime parameters: None ! -! :Dependencies: boundary_dyn, dim, dump_utils, eos, io, memory, -! metric_tools, mpiutils, options, part, readwrite_dumps_common, +! :Dependencies: boundary_dyn, dim, dump_utils, eos, eos_stamatellos, io, +! memory, metric_tools, mpiutils, options, part, readwrite_dumps_common, ! sphNGutils, timestep ! use dump_utils, only:lenid,ndatatypes,i_int,i_int1,i_int2,i_int4,i_int8,& diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index ff76e1c4f..b64e60758 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -500,7 +500,7 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) sigma(:) = sigma(:)*umass/(udist*udist) if (ieos /= 23) then - csbin(:) = csbin(:)*unit_velocity + csbin(:) = csbin(:)*unit_velocity endif omega(:) = omega(:)/utime @@ -520,8 +520,8 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) do ipart=1,npart ibin = ipartbin(ipart) - if (ibin<=0) cycle - + if (ibin<=0) cycle + dvr = (vrpart(ipart) - vrbin(ibin))*unit_velocity dvphi = (vphipart(ipart) -vphibin(ibin))*unit_velocity From 35eb04116eae75c2269ec896757f6ef72ad3e6a8 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 26 Sep 2024 13:53:51 +0100 Subject: [PATCH 156/182] Bugfix for gfortran compilation --- src/main/cooling_radapprox.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 925b75fcf..d7475931b 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -76,7 +76,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,HLom,du_tot real :: cs2,Om2,Hmod2 - real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb + real :: opaci,ueqi,umini,tthermi,presi,Hcomb coldensi = huge(coldensi) kappaBari = 0d0 From b85f54a33f72f42c80f39624fac80daeb520c550 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 26 Sep 2024 14:11:16 +0100 Subject: [PATCH 157/182] Bugfix for Github tests --- src/main/eos.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/eos.f90 b/src/main/eos.f90 index bce8ae55b..cbdaf9bf2 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -470,7 +470,7 @@ end subroutine equationofstate subroutine init_eos(eos_type,ierr) use units, only:unit_velocity use physcon, only:Rg - use io, only:error,warning,fatal + use io, only:error,warning use eos_mesa, only:init_eos_mesa use eos_helmholtz, only:eos_helmholtz_init use eos_piecewise, only:init_eos_piecewise @@ -562,7 +562,7 @@ subroutine init_eos(eos_type,ierr) case(23) call read_optab(eos_file,ierr) - if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) + if (ierr > 0) call error('init_eos','Failed to read EOS file',var='ierr',ival=ierr) call init_S07cool end select From 4c113f3b5035c0c7c4df84211e255f8a409a92cc Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 15 Oct 2024 16:07:51 +0100 Subject: [PATCH 158/182] Fix bug in init ieos=23 errors --- src/main/eos.f90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/eos.f90 b/src/main/eos.f90 index c0ebc16bd..5de1c096e 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -469,7 +469,7 @@ end subroutine equationofstate subroutine init_eos(eos_type,ierr) use units, only:unit_velocity use physcon, only:Rg - use io, only:error,warning,fatal + use io, only:error,warning use eos_mesa, only:init_eos_mesa use eos_helmholtz, only:eos_helmholtz_init use eos_piecewise, only:init_eos_piecewise @@ -482,7 +482,7 @@ subroutine init_eos(eos_type,ierr) use eos_HIIR, only:init_eos_HIIR integer, intent(in) :: eos_type integer, intent(out) :: ierr - integer :: ierr_mesakapp + integer :: ierr_mesakapp,ierr_ra ierr = 0 ! @@ -562,8 +562,8 @@ subroutine init_eos(eos_type,ierr) case(23) - call read_optab(eos_file,ierr) - if (ierr > 0) call fatal('init_eos','Failed to read EOS file',var='ierr',ival=ierr) + call read_optab(eos_file,ierr_ra) + if (ierr_ra > 0) call warning('init_eos','Failed to read EOS file') call init_coolra end select From 42a79f0697456966e959221df0c78b43213d24a7 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 15 Oct 2024 16:14:09 +0100 Subject: [PATCH 159/182] Fix bug in ieos=23 init err --- src/main/eos.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/eos.f90 b/src/main/eos.f90 index cbdaf9bf2..8c0af1ce8 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -482,7 +482,7 @@ subroutine init_eos(eos_type,ierr) use dim, only:maxvxyzu,do_radiation integer, intent(in) :: eos_type integer, intent(out) :: ierr - integer :: ierr_mesakapp + integer :: ierr_mesakapp,ierr_ra ierr = 0 ! @@ -561,8 +561,8 @@ subroutine init_eos(eos_type,ierr) call init_eos_HIIR() case(23) - call read_optab(eos_file,ierr) - if (ierr > 0) call error('init_eos','Failed to read EOS file',var='ierr',ival=ierr) + call read_optab(eos_file,ierr_ra) + if (ierr_ra > 0) call warning('init_eos','Failed to read EOS file') call init_S07cool end select From 7207eb8b7fbc2cf7fa2dc26a0f982d76347635fb Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 16 Oct 2024 10:17:48 +0100 Subject: [PATCH 160/182] Removed unused variables --- src/main/dens.F90 | 1 - src/main/radiation_utils.f90 | 2 +- src/main/readwrite_dumps_fortran.f90 | 5 ++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 9465f506d..e6fbd2801 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -1698,7 +1698,6 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra real :: uradi,dradi,dradxi,dradyi,dradzi,runix,runiy,runiz real :: dT4,R_rad integer :: ngradh_err - real :: uradself ngradh_err = 0 over_parts: do icell = 1,cell%npcell diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 95dfb16de..6197de6cb 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -419,7 +419,7 @@ subroutine get_opacity(opacity_type,density,temperature,kappa,u) real, intent(in), optional :: u real, intent(out) :: kappa integer, intent(in) :: opacity_type - real :: kapt,kapr,rho_cgs,Ti,gmwi,gammai,kapBar,kappaPart + real :: kapt,kapr,rho_cgs,Ti,gmwi,kapBar,kappaPart select case(opacity_type) case(1) diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index 208942da0..1ea3cfba4 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:gradP_cool,doFLD,urad_FLD,ttherm_store,teqi_store,opac_store + use eos_stamatellos, only:ttherm_store,teqi_store,opac_store real, intent(in) :: t character(len=*), intent(in) :: dumpfile integer, intent(in), optional :: iorder(:) @@ -249,8 +249,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) endif endif ! write stamatellos cooling values - if (icooling == 9) then ! .and. doFLD) then -! call write_array(1,urad_FLD,'urad',npart,k,ipass,idump,nums,ierrs(13)) + if (icooling == 9) then call write_array(1,teqi_store,'teqi',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) From 0647f6140a20b07abeb39ce67bea8a506cfa7fe6 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 16 Oct 2024 13:48:04 +0100 Subject: [PATCH 161/182] fixes for Github build --- src/main/force.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/force.F90 b/src/main/force.F90 index 5ed29ff4f..bc3096671 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2617,7 +2617,10 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv use part, only:Omega_k use io, only:warning use physcon, only:c,kboltz - use eos_stamatellos, only:Gpot_cool,duSPH +#ifdef GRAVITY + use eos_stamatellos, only:Gpot_cool +#endif + use eos_stamatellos, only:duSPH integer, intent(in) :: icall type(cellforce), intent(inout) :: cell real, intent(inout) :: fxyzu(:,:) @@ -2687,7 +2690,6 @@ subroutine finish_cell_and_store_results(icall,cell,fxyzu,xyzh,vxyzu,poten,dt,dv real :: densi, vxi,vyi,vzi,u0i,dudtcool,dudtheat real :: posi(3),veli(3),gcov(0:3,0:3),metrici(0:3,0:3,2) integer :: ii,ia,ib,ic,ierror - eni = 0. realviscosity = (irealvisc > 0) From 9e14e04cad1d1ab6af6db34c189fc68bd4a5b0a1 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Thu, 17 Oct 2024 15:44:00 +0100 Subject: [PATCH 162/182] Fixes for Github tests --- build/Makefile_setups | 10 - src/main/eos_stamatellos.f90 | 20 +- src/setup/setup_sphere.f90 | 848 ----------------------------------- 3 files changed, 11 insertions(+), 867 deletions(-) delete mode 100644 src/setup/setup_sphere.f90 diff --git a/build/Makefile_setups b/build/Makefile_setups index d5f05236e..3a0897eca 100644 --- a/build/Makefile_setups +++ b/build/Makefile_setups @@ -431,16 +431,6 @@ ifeq ($(SETUP), sphereinbox) KNOWN_SETUP=yes endif -ifeq ($(SETUP), sphere) -# sphere setup - ISOTHERMAL=no - PERIODIC=no - IND_TIMESTEPS=yes - GRAVITY=yes - SETUPFILE= velfield_fromcubes.f90 setup_sphere.f90 - KNOWN_SETUP=yes -endif - ifeq ($(SETUP), shock) # shock tube tests PERIODIC=yes diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 5877dcf64..df4239ba4 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -33,16 +33,18 @@ module eos_stamatellos subroutine init_S07cool() use part, only:npart,maxradprop + use allocutils, only:allocate_array + print *, "Allocating cooling arrays" - allocate(gradP_cool(npart)) - allocate(Gpot_cool(npart)) - allocate(duFLD(npart)) - allocate(lambda_fld(npart)) - allocate(urad_FLD(npart)) - allocate(ttherm_store(npart)) - allocate(teqi_store(npart)) - allocate(opac_store(npart)) - allocate(duSPH(npart)) + 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) Gpot_cool(:) = 0d0 gradP_cool(:) = 0d0 urad_FLD(:) = 0d0 diff --git a/src/setup/setup_sphere.f90 b/src/setup/setup_sphere.f90 deleted file mode 100644 index c297a13b5..000000000 --- a/src/setup/setup_sphere.f90 +++ /dev/null @@ -1,848 +0,0 @@ -!--------------------------------------------------------------------------! -! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2023 The Authors (see AUTHORS) ! -! See LICENCE file for usage and distribution conditions ! -! http://phantomsph.bitbucket.io/ ! -!--------------------------------------------------------------------------! -module setup -! -! This module sets up a sphere-in-a-box: a cold, dense sphere placed in -! a warm medium; the two media are in pressure-equilibrium. -! This currently works for gas-only and two-fluid dust. -! -! :References: None -! -! :Owner: Alison Young -! -! :Runtime parameters: -! - BEfac : *over-density factor of the BE sphere [code units]* -! - BEmass : *mass radius of the BE sphere [code units]* -! - BErad_norm : *normalised radius of the BE sphere* -! - BErad_phys : *physical radius of the BE sphere [code units]* -! - BErho_cen : *central density of the BE sphere [code units]* -! - Bzero : *Magnetic field strength in Gauss* -! - T_sphere : *temperature in sphere* -! - ang_Bomega : *Angle (degrees) between B and rotation axis* -! - angvel : *angular velocity in rad/s* -! - beta_r : *rotational-to-gravitational energy ratio* -! - density_contrast : *density contrast in code units* -! - dist_unit : *distance unit (e.g. au)* -! - dust_to_gas_ratio : *dust-to-gas ratio* -! - form_binary : *the intent is to form a central binary* -! - graindenscgs : *grain density [g/cm^3]* -! - grainsizecgs : *grain size in [cm]* -! - h_acc : *accretion radius (code units)* -! - h_soft_sinksink : *sink-sink softening radius (code units)* -! - iBE_options : *The set of parameters to define the BE sphere* -! - icreate_sinks : *1: create sinks. 0: do not create sinks* -! - lattice : *particle lattice (random,cubic,closepacked,hcp,hexagonal)* -! - lbox : *length of a box side in terms of spherical radii* -! - mass_unit : *mass unit (e.g. solarm)* -! - masstoflux : *mass-to-magnetic flux ratio in units of critical value* -! - ndusttypes : *number of grain sizes* -! - np : *requested number of particles in sphere* -! - r_crit : *critical radius (code units)* -! - r_sphere : *radius of sphere in code units* -! - rho_final : *final maximum density (<=0 to ignore) (cgs units)* -! - rho_pert_amp : *amplitude of density perturbation* -! - rms_mach : *turbulent rms mach number* -! - shuffle_parts : *relax particles by shuffling* -! - sindex : *power-law index, e.g. MRN* -! - smaxcgs : *maximum grain size [cm]* -! - smincgs : *minimum grain size [cm]* -! - totmass_sphere : *mass of sphere in code units* -! - use_BE_sphere : *centrally condense as a BE sphere* -! -! :Dependencies: boundary, centreofmass, datafiles, dim, dust, eos, -! eos_stamatellos, infile_utils, io, kernel, mpidomain, options, part, -! physcon, prompting, ptmass, set_dust, set_dust_options, setup_params, -! spherical, timestep, unifdis, units, utils_shuffleparticles, velfield -! - use part, only:mhd,graindens,grainsize,ndusttypes,ndustsmall - use dim, only:use_dust,maxvxyzu,periodic,maxdustsmall - use options, only:calc_erot - use dust, only:grainsizecgs,graindenscgs - use set_dust_options, only:grainsizeinp,graindensinp,igrainsize,igraindens,& - smincgs,smaxcgs,sindex,dustbinfrac - implicit none - - public :: setpart - - private - !--private module variables - real :: xmini(3), xmaxi(3) - real :: density_contrast,totmass_sphere,r_sphere,T_sphere,cs_sphere - real :: angvel,beta_r,Bzero_G,masstoflux,dtg,ang_Bomega,rms_mach - real :: rho_pert_amp,lbox - real :: BErho_cen,BErad_phys,BErad_norm,BEmass,BEfac - real :: r_crit_setup,h_acc_setup,h_soft_sinksink_setup,rhofinal_setup - real(kind=8) :: udist,umass - integer :: np,iBEparam,icreate_sinks_setup - logical :: BEsphere,binary,mu_not_B,cs_in_code,angvel_not_betar,shuffle_parts - logical :: is_cube = .true. ! if false, then can set a rectangle if BEsphere=false; for backwards compatibility - character(len=20) :: dist_unit,mass_unit,lattice - character(len= 1), parameter :: labelx(3) = (/'x','y','z'/) - -contains - -!---------------------------------------------------------------- -!+ -! setup for a sphere-in-a-box -!+ -!---------------------------------------------------------------- -subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact_out,time,fileprefix) - use physcon, only:pi,solarm,hours,years,au,kboltz,kb_on_mh - use dim, only:maxdusttypes,use_dustgrowth,maxdustlarge - use setup_params, only:rhozero,npart_total,rmax,ihavesetupB - use io, only:master,fatal,iprint - use unifdis, only:set_unifdis - use spherical, only:set_sphere - use boundary, only:set_boundary,xmin,xmax,ymin,ymax,zmin,zmax,dxbound,dybound,dzbound - use prompting, only:prompt - use units, only:set_units,select_unit,utime,unit_density,unit_Bfield,unit_velocity,unit_ergg - use eos, only:polyk2,ieos,gmw - use eos_stamatellos, only:read_optab,getopac_opdep,optable,getintenerg_opdep,eos_file - use part, only:Bxyz,Bextx,Bexty,Bextz,igas,idust,set_particle_type,hfact,dustfrac - use set_dust_options, only:dustbinfrac,set_dust_default_options,set_dust_interactively,dust_method - use dust, only:ilimitdustflux - use timestep, only:dtmax,tmax,dtmax_dratio,dtmax_min - use centreofmass, only:reset_centreofmass - use options, only:nfulldump,rhofinal_cgs,hdivbbmax_max,use_dustfrac - use kernel, only:hfact_default - use mpidomain, only:i_belong - use ptmass, only:icreate_sinks,r_crit,h_acc,h_soft_sinksink - use velfield, only:set_velfield_from_cubes - use datafiles, only:find_phantom_datafile - use set_dust, only:set_dustfrac,set_dustbinfrac - use utils_shuffleparticles, only:shuffleparticles - integer, intent(in) :: id - integer, intent(inout) :: npart - integer, intent(out) :: npartoftype(:) - real, intent(out) :: xyzh(:,:) - real, intent(out) :: vxyzu(:,:) - real, intent(out) :: massoftype(:) - real, intent(out) :: polyk,gamma,hfact_out - real, intent(inout) :: time - character(len=20), intent(in) :: fileprefix - character(len=20), parameter :: filevx = 'cube_v1.dat' - character(len=20), parameter :: filevy = 'cube_v2.dat' - character(len=20), parameter :: filevz = 'cube_v3.dat' - real(kind=8) :: h_acc_in - integer :: i,np_in,npartsphere,npmax,iBElast,ierr - integer :: iBE,ilattice - real :: totmass,vol_box,psep,psep_box,pmass_dusttogas - real :: vol_sphere,dens_sphere,dens_medium,cs_medium,angvel_code,przero - real :: u_sphere,kappaBar,kappaPart,gmwi,gammai,cs_sphere_cgs - real :: t_ff,r2,area,Bzero,rmasstoflux_crit - real :: rxy2,rxyz2,phi,dphi,central_density,edge_density,rmsmach,v2i,turbfac,rhocritTcgs,ui - real, allocatable :: rtab(:),rhotab(:) - logical :: iexist - logical :: make_sinks = .true. ! the default prompt is to ask to make sinks - character(len=120) :: filex,filey,filez - character(len=100) :: filename,cwd - character(len=40) :: fmt - character(len=10) :: h_acc_char - logical :: usebox = .false. - !--Initialise dust distribution, if using dust - if (use_dust) call set_dust_default_options() - - filename = trim(fileprefix)//'.setup' - print "(/,1x,63('-'),1(/,a),/,1x,63('-'),/)",& - ' Sphere setup' - - inquire(file=filename,exist=iexist) - if (iexist) then - call read_setupfile(filename,ierr) - np_in = np - if (ierr /= 0) then - if (id==master) call write_setupfile(filename) - stop - endif - elseif (id==master) then - print "(a,/)",trim(filename)//' not found: using interactive setup' - dist_unit = '1.0d16cm' - mass_unit = 'solarm' - ierr = 1 - do while (ierr /= 0) - call prompt('Enter mass unit (e.g. solarm,jupiterm,earthm)',mass_unit) - call select_unit(mass_unit,umass,ierr) - if (ierr /= 0) print "(a)",' ERROR: mass unit not recognised' - enddo - ierr = 1 - do while (ierr /= 0) - call prompt('Enter distance unit (e.g. au,pc,kpc,0.1pc)',dist_unit) - call select_unit(dist_unit,udist,ierr) - if (ierr /= 0) print "(a)",' ERROR: length unit not recognised' - enddo - ! - ! units - ! - call set_units(dist=udist,mass=umass,G=1.d0) - ! - ! prompt user for settings - ! - npmax = int(2.0/3.0*size(xyzh(1,:))) ! approx max number allowed in sphere given size(xyzh(1,:)) - if (npmax < 300000) then - np = npmax - elseif (npmax < 1000000) then - np = 300000 - else - np = 1000000 - endif - call prompt('Enter the approximate number of particles in the sphere',np,0,npmax) - np_in = np - - lattice = 'closepacked' - ilattice = 3 - call prompt('Enter the type of particle lattice (1=random,2=cubic,3=closepacked,4=hexagonal)',ilattice,0,4) - if (ilattice==1) then - lattice = 'random' - shuffle_parts = .false. - elseif (ilattice==2) then - lattice = 'cubic' - elseif (ilattice==4) then - lattice = 'hexagonal' - endif - - shuffle_parts = .false. - if (ilattice==1) shuffle_parts = .true. - call prompt('Relax particles by shuffling?',shuffle_parts) - - BEsphere = .false. - call prompt('Centrally condense the sphere as a BE sphere?',BEsphere) - - if (.not. BEsphere) then - r_sphere = 4. - call prompt('Enter radius of sphere in units of '//dist_unit,r_sphere,0.) - lbox = 4. - call prompt('Enter the box size in units of spherical radii: ',lbox,1.) - if (.not. is_cube) then - do i=1,3 - xmini(i) = -0.5*(lbox*r_sphere) - xmaxi(i) = -xmini(i) - enddo - endif - - totmass_sphere = 1.0 - call prompt('Enter total mass in sphere in units of '//mass_unit,totmass_sphere,0.) - else - print *, 'deleted' - endif - - call prompt('Enter temperature in sphere',T_sphere,1.,100.) - - call prompt('Enter EOS filename',eos_file) - - if (binary) then - angvel = 1.006d-12 - else - angvel = 1.77d-13 - endif - angvel_not_betar = .true. - beta_r = 0.02 - call prompt('Input angular velocity (true); else input ratio of rotational-to-potential energy ',angvel_not_betar) - if (angvel_not_betar) then - call prompt('Enter angular rotation speed in rad/s ',angvel,0.) - else - call prompt('Enter ratio of rotational-to-potential energy ',beta_r,0.) - endif - - rms_mach = 0. - call prompt('Enter the Mach number of the cloud turbulence',rms_mach,0.) - - if (mhd) then - Bzero_G = 1.0d-4 ! G - masstoflux = 5.0 - ang_Bomega = 180.0 - mu_not_B = .true. - call prompt('Input the mass-to-flux ratio (true); else input the magnetic field strength ',mu_not_B) - if (mu_not_B) then - call prompt('Enter mass-to-flux ratio in units of critical value ',masstoflux,0.) - else - call prompt('Enter magnetic field strength in Gauss ',Bzero_G,0.) - endif - call prompt('Enter the angle (degrees) between B and the rotation axis? ',ang_Bomega) - endif - - if (use_dust) then - !--currently assume one fluid dust - dtg = 0.01 - grainsize = 0. - graindens = 0. - grainsizecgs = 0.1 - graindenscgs = 3. - ndustsmall = 1 - smincgs = 1.e-5 - smaxcgs = 1. - sindex = 3.5 - call prompt('Enter total dust to gas ratio',dtg,0.) - call prompt('How many grain sizes do you want?',ndustsmall,1,maxdustsmall) - ndusttypes = ndustsmall - if (ndusttypes > 1) then - !--grainsizes - call prompt('Enter minimum grain size in cm',smincgs,0.) - call prompt('Enter maximum grain size in cm',smaxcgs,0.) - !--mass distribution - call prompt('Enter power-law index, e.g. MRN',sindex) - !--grain density - call prompt('Enter grain density in g/cm^3',graindenscgs,0.) - else - call prompt('Enter grain size in cm',grainsizecgs,0.) - call prompt('Enter grain density in g/cm^3',graindenscgs,0.) - endif - endif - - if (binary) then - rho_pert_amp = 0.1 - call prompt('Enter the amplitute of the density perturbation ',rho_pert_amp,0.0,0.4) - endif - - ! ask about sink particle details; these will not be saved to the .setup file since they exist in the .in file - ! - call prompt('Do you wish to dynamically create sink particles? ',make_sinks) - if (make_sinks) then - if (binary) then - h_acc_char = '3.35au' - else - h_acc_char = '1.0d-2' - endif - call prompt('Enter the accretion radius of the sink (with units; e.g. au,pc,kpc,0.1pc) ',h_acc_char) - call select_unit(h_acc_char,h_acc_in,ierr) - h_acc_setup = h_acc_in - if (ierr==0 ) h_acc_setup = h_acc_setup/udist - r_crit_setup = 5.0*h_acc_setup - icreate_sinks_setup = 1 - if (binary) h_soft_sinksink_setup = 0.4*h_acc_setup - else - icreate_sinks_setup = 0 - rhofinal_setup = 0.15 - call prompt('Enter final maximum density in g/cm^3 (ignored for <= 0) ',rhofinal_setup) - endif - if (id==master) call write_setupfile(filename) - stop 'please edit .setup file and rerun phantomsetup' - else - stop ! MPI, stop on other threads, interactive on master - endif - ! - ! units - ! - call set_units(dist=udist,mass=umass,G=1.d0) - ! - ! set dust properties - ! - if (use_dust) then - use_dustfrac = .true. - ndustsmall = ndusttypes - if (ndusttypes > 1) then - call set_dustbinfrac(smincgs,smaxcgs,sindex,dustbinfrac(1:ndusttypes),grainsize(1:ndusttypes)) - grainsize(1:ndusttypes) = grainsize(1:ndusttypes)/udist - graindens(1:ndusttypes) = graindenscgs/umass*udist**3 - else - grainsize(1) = grainsizecgs/udist - graindens(1) = graindenscgs/umass*udist**3 - endif - endif - - - - ! general parameters - ! - - vol_sphere = 4./3.*pi*r_sphere**3 - rhozero = totmass_sphere / vol_sphere - dens_sphere = rhozero - - ! call EOS - ieos = 21 - ierr = 0 - call read_optab(eos_file,ierr) - call getintenerg_opdep(T_sphere, dens_sphere*unit_density, u_sphere) - call getopac_opdep(u_sphere,dens_sphere,kappaBar,kappaPart,T_sphere,gmwi) - u_sphere = u_sphere/unit_ergg - time = 0. - if (use_dust) dust_method = 1 - hfact = hfact_default - hfact_out = hfact_default - print *, 'gamma =', gamma, 'u_sphere = ',u_sphere,T_sphere - - rmax = r_sphere - if (angvel_not_betar) then - angvel_code = angvel*utime - else - angvel_code = sqrt(3.0*totmass_sphere*beta_r/r_sphere**3) - angvel = angvel_code/utime - endif - - - totmass = totmass_sphere - t_ff = sqrt(3.*pi/(32.*dens_sphere)) - - przero = dens_sphere * kb_on_mh * T_sphere/gmwi ! code units - gammai = 1.d0 + (przero/u_sphere/dens_sphere) - cs_sphere = sqrt(gammai * przero/dens_sphere) - cs_sphere_cgs = cs_sphere * unit_velocity - polyk = cs_sphere**2 - gamma = 5./3. ! not used but set to keep Phantom happy. - ! - ! setup particles in the sphere; use this routine to get N_sphere as close to np as possible - ! - if (BEsphere) then - call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh, & - rhotab=rhotab(1:iBElast),rtab=rtab(1:iBElast),nptot=npart_total,& - exactN=.true.,np_requested=np,mask=i_belong) - else - call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& - exactN=.true.,np_requested=np,mask=i_belong) - if (trim(lattice)/='random') print "(a,es10.3)",' Particle separation in sphere = ',psep - endif - print "(a)",' Initialised sphere' - npartsphere = npart_total - - ! - ! set particle properties - ! - npartoftype(:) = 0 - npartoftype(igas) = npart - dustfrac = 0. - if (massoftype(igas) < epsilon(massoftype(igas))) massoftype(igas) = totmass/npart_total - do i = 1,npartoftype(igas) - call set_particle_type(i,igas) - if (use_dust .and. dust_method==1) then - if (ndusttypes > 1) then - dustfrac(1:ndusttypes,i) = dustbinfrac(1:ndusttypes)*dtg - else - dustfrac(1,i) = dtg/(1.+dtg) ! call set_dustfrac(dtg,dustfrac(:,i)) - endif - endif - enddo - ! - ! Set two-fluid dust - ! (currently deactivated; will need to re-test before use to ensure it is fully compatible with the current dust algorithms) - ! - if (use_dust .and. dust_method==2) then - ! particle separation in dust sphere & sdjust for close-packed lattice - pmass_dusttogas = 10.*dtg*massoftype(igas) - psep = (vol_sphere/pmass_dusttogas/real(np))**(1./3.) - psep = psep*sqrt(2.)**(1./3.) - call set_sphere(trim(lattice),id,master,0.,r_sphere,psep,hfact,npart,xyzh,nptot=npart_total,& - exactN=.true.,np_requested=np/10,mask=i_belong) - npartoftype(idust) = int(npart_total) - npartoftype(igas) - massoftype(idust) = totmass_sphere*dtg/npartoftype(idust) - - do i = npartoftype(igas)+1,npart - call set_particle_type(i,idust) - enddo - - print "(a,4(i10,1x))", ' particle numbers: (gas_total, gas_sphere, dust, total): ' & - , npartoftype(igas),npartsphere,npartoftype(idust),npart - print "(a,2es10.3)" , ' particle masses: (gas,dust): ',massoftype(igas),massoftype(idust) - else - print "(a,3(i10,1x))", ' particle numbers: (sphere, low-density medium, total): ' & - , npartsphere, npart-npartsphere,npart - print "(a,es10.3)",' particle mass = ',massoftype(igas) - endif - ! - ! shuffle particles - ! - if (shuffle_parts) then - print*, "lets shuffle!" - if (BEsphere) then - call shuffleparticles(iprint,npart,xyzh,massoftype(igas),dmedium=dens_medium,ntab=iBElast, & - rtab=rtab,dtab=rhotab,dcontrast=density_contrast,is_setup=.true.,prefix=trim(fileprefix)) - else - call shuffleparticles(iprint,npart,xyzh,massoftype(igas), & - rsphere=rmax,dsphere=dens_sphere,dmedium=dens_medium,is_setup=.true.,prefix=trim(fileprefix)) - endif - endif - if (BEsphere) deallocate(rtab,rhotab) - ! - ! reset to centre of mass - ! (if random or shuffling, recentering may shift particles outside of the defined range) - ! - if (trim(lattice)/='random' .and. .not.shuffle_parts) call reset_centreofmass(npart,xyzh,vxyzu) - - ! - !--Stretching the spatial distribution to perturb the density profile, if requested - ! - if (binary) then - do i = 1,npart - rxy2 = xyzh(1,i)*xyzh(1,i) + xyzh(2,i)*xyzh(2,i) - rxyz2 = rxy2 + xyzh(3,i)*xyzh(3,i) - if (rxyz2 <= r_sphere**2) then - phi = atan(xyzh(2,i)/xyzh(1,i)) - if (xyzh(1,i) < 0.0) phi = phi + pi - dphi = 0.5*rho_pert_amp*sin(2.0*phi) - phi = phi - dphi - xyzh(1,i) = sqrt(rxy2)*cos(phi) - xyzh(2,i) = sqrt(rxy2)*sin(phi) - endif - enddo - endif - ! - ! Velocity: Turbulent velocity field - ! - vxyzu = 0. - if (rms_mach > 0.) then - call getcwd(cwd) - ! personal hack for J. Wurster since different computer clusters required different velocity fields - if (index(cwd,'gpfs1/scratch/astro/jhw5') > 0 .or. index(cwd,'data/dp187/dc-wurs1') > 0 ) then - ! Kennedy or Dial - filex = find_phantom_datafile(filevx,'velfield_sphng') - filey = find_phantom_datafile(filevy,'velfield_sphng') - filez = find_phantom_datafile(filevz,'velfield_sphng') - else - filex = find_phantom_datafile(filevx,'velfield') - filey = find_phantom_datafile(filevy,'velfield') - filez = find_phantom_datafile(filevz,'velfield') - endif - - call set_velfield_from_cubes(xyzh(:,1:npartsphere),vxyzu(:,:npartsphere),npartsphere, & - filex,filey,filez,1.,r_sphere,.false.,ierr) - if (ierr /= 0) call fatal('setup','error setting up velocity field on clouds') - - rmsmach = 0.0 - print*, 'Turbulence being set by user' - do i = 1,npartsphere - v2i = dot_product(vxyzu(1:3,i),vxyzu(1:3,i)) - rmsmach = rmsmach + v2i/cs_sphere**2 - enddo - rmsmach = sqrt(rmsmach/npartsphere) - if (rmsmach > 0.) then - turbfac = rms_mach/rmsmach ! normalise the energy to the desired mach number - else - turbfac = 0. - endif - do i = 1,npartsphere - vxyzu(1:3,i) = turbfac*vxyzu(1:3,i) - enddo - endif - ! - ! Velocity: uniform rotation (thermal energy & magnetic field too) - ! - do i=1,npart - r2 = dot_product(xyzh(1:3,i),xyzh(1:3,i)) - if (r2 < r_sphere**2) then - vxyzu(1,i) = vxyzu(1,i) - angvel_code*xyzh(2,i) - vxyzu(2,i) = vxyzu(2,i) + angvel_code*xyzh(1,i) - ui = u_sphere - if (maxvxyzu >= 4) vxyzu(4,i) = ui - else - if (maxvxyzu >= 4) vxyzu(4,i) = 1.5*polyk2 - endif - enddo - ! - ! set default runtime parameters if .in file does not exist - ! - filename=trim(fileprefix)//'.in' - inquire(file=filename,exist=iexist) - dtmax = t_ff/100. ! Since this variable can change, always reset it if running phantomsetup - if (.not. iexist) then - if (binary) then - tmax = 1.50*t_ff ! = 13.33 for default settings (Wurster, Price & Bate 2017) - else - tmax = 1.21*t_ff ! = 10.75 for default settings (Wurster, Price & Bate 2016) - endif - ieos = 21 - nfulldump = 1 - calc_erot = .true. - dtmax_dratio = 1.258 - icreate_sinks = icreate_sinks_setup - r_crit = r_crit_setup - h_acc = h_acc_setup - if (binary) h_soft_sinksink = h_soft_sinksink_setup - hdivbbmax_max = 1.0 ! 512. - if (icreate_sinks==1) then - dtmax_min = dtmax/8.0 - else - dtmax_min = 0.0 - rhofinal_cgs = rhofinal_setup - endif - ilimitdustflux = .true. - endif - ! - !--Summarise the sphere - ! - print "(a,i10)",' Input npart_sphere = ',np - print "(1x,50('-'))" - print "(a)",' Quantity (code units) (physical units)' - print "(1x,50('-'))" - fmt = "((a,1pg10.3,3x,1pg10.3),a)" - print fmt,' Total mass : ',totmass,totmass*umass,' g' - print fmt,' Mass in sphere : ',totmass_sphere,totmass_sphere*umass,' g' - print fmt,' Radius of sphere : ',r_sphere,r_sphere*udist,' cm' - if (BEsphere) then - print fmt,' Mean rho sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' - print fmt,' central density : ',central_density,central_density*unit_density,' g/cm^3' - print fmt,' edge density : ',edge_density,edge_density*unit_density,' g/cm^3' - print fmt,' Mean rho medium : ',dens_medium,dens_medium*unit_density,' g/cm^3' - else - print fmt,' Density sphere : ',dens_sphere,dens_sphere*unit_density,' g/cm^3' - endif - print fmt,' cs in sphere : ',cs_sphere,cs_sphere_cgs,' cm/s' - print fmt,' Free fall time : ',t_ff,t_ff*utime/years,' yrs' - print fmt,' Angular velocity : ',angvel_code,angvel,' rad/s' - print fmt,' Turbulent Mach no: ',rms_mach - print fmt,' Omega*t_ff : ',angvel_code*t_ff - - if (use_dust) then - print fmt,' dust-to-gas ratio: ',dtg,dtg,' ' - endif - print "(1x,50('-'))" - -end subroutine setpart - -!---------------------------------------------------------------- -!+ -! write parameters to setup file -!+ -!---------------------------------------------------------------- -subroutine write_setupfile(filename) - use infile_utils, only: write_inopt - character(len=*), intent(in) :: filename - integer, parameter :: iunit = 20 - integer :: i - - print "(a)",' writing setup options file '//trim(filename) - open(unit=iunit,file=filename,status='replace',form='formatted') - write(iunit,"(a)") '# input file for sphere-in-box setup routines' - write(iunit,"(/,a)") '# units' - call write_inopt(dist_unit,'dist_unit','distance unit (e.g. au)',iunit) - call write_inopt(mass_unit,'mass_unit','mass unit (e.g. solarm)',iunit) - - write(iunit,"(/,a)") '# particle resolution & placement' - call write_inopt(np,'np','requested number of particles in sphere',iunit) - call write_inopt(lattice,'lattice','particle lattice (random,cubic,closepacked,hcp,hexagonal)',iunit) - call write_inopt(shuffle_parts,'shuffle_parts','relax particles by shuffling',iunit) - - write(iunit,"(/,a)") '# options for box' - if (.not.BEsphere .and. .not.is_cube) then - ! left here for backwards compatibility and for simplicity if the user requires a rectangle in the future - do i=1,3 - call write_inopt(xmini(i),labelx(i)//'min',labelx(i)//' min',iunit) - call write_inopt(xmaxi(i),labelx(i)//'max',labelx(i)//' max',iunit) - enddo - else - call write_inopt(lbox,'lbox','length of a box side in terms of spherical radii',iunit) - endif - - write(iunit,"(/,a)") '# intended result' - call write_inopt(binary,'form_binary','the intent is to form a central binary',iunit) - - write(iunit,"(/,a)") '# options for sphere' - call write_inopt(BEsphere,'use_BE_sphere','centrally condense as a BE sphere',iunit) - if (.not. BEsphere) then - call write_inopt(r_sphere,'r_sphere','radius of sphere in code units',iunit) - call write_inopt(totmass_sphere,'totmass_sphere','mass of sphere in code units',iunit) - else - call write_inopt(iBEparam,'iBE_options','The set of parameters to define the BE sphere',iunit) - if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) & - call write_inopt(BErho_cen,'BErho_cen','central density of the BE sphere [code units]',iunit) - if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) & - call write_inopt(BErad_phys,'BErad_phys','physical radius of the BE sphere [code units]',iunit) - if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) & - call write_inopt(BErad_norm,'BErad_norm','normalised radius of the BE sphere',iunit) - if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) & - call write_inopt(BEmass,'BEmass','mass radius of the BE sphere [code units]',iunit) - if (iBEparam==4 .or. iBEparam==5) & - call write_inopt(BEfac,'BEfac','over-density factor of the BE sphere [code units]',iunit) - endif - call write_inopt(density_contrast,'density_contrast','density contrast in code units',iunit) - call write_inopt(T_sphere,'T_sphere','temperature in sphere',iunit) - if (angvel_not_betar) then - call write_inopt(angvel,'angvel','angular velocity in rad/s',iunit) - else - call write_inopt(beta_r,'beta_r','rotational-to-gravitational energy ratio',iunit) - endif - call write_inopt(rms_mach,'rms_mach','turbulent rms mach number',iunit) - if (mhd) then - if (mu_not_B) then - call write_inopt(masstoflux,'masstoflux','mass-to-magnetic flux ratio in units of critical value',iunit) - else - call write_inopt(Bzero_G,'Bzero','Magnetic field strength in Gauss',iunit) - endif - call write_inopt(ang_Bomega,'ang_Bomega','Angle (degrees) between B and rotation axis',iunit) - endif - if (use_dust) then - write(iunit,"(/,a)") '# Dust properties' - call write_inopt(dtg,'dust_to_gas_ratio','dust-to-gas ratio',iunit) - call write_inopt(ndusttypes,'ndusttypes','number of grain sizes',iunit) - if (ndusttypes > 1) then - call write_inopt(smincgs,'smincgs','minimum grain size [cm]',iunit) - call write_inopt(smaxcgs,'smaxcgs','maximum grain size [cm]',iunit) - call write_inopt(sindex, 'sindex', 'power-law index, e.g. MRN',iunit) - call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) - else - call write_inopt(grainsizecgs,'grainsizecgs','grain size in [cm]',iunit) - call write_inopt(graindenscgs,'graindenscgs','grain density [g/cm^3]',iunit) - endif - endif - if (binary) then - call write_inopt(rho_pert_amp,'rho_pert_amp','amplitude of density perturbation',iunit) - endif - write(iunit,"(/,a)") '# Sink properties (values in .in file, if present, will take precedence)' - call write_inopt(icreate_sinks_setup,'icreate_sinks','1: create sinks. 0: do not create sinks',iunit) - if (icreate_sinks_setup==1) then - call write_inopt(h_acc_setup,'h_acc','accretion radius (code units)',iunit) - call write_inopt(r_crit_setup,'r_crit','critical radius (code units)',iunit) - if (binary) then - call write_inopt(h_soft_sinksink_setup,'h_soft_sinksink','sink-sink softening radius (code units)',iunit) - endif - else - call write_inopt(rhofinal_setup,'rho_final','final maximum density (<=0 to ignore) (cgs units)',iunit) - endif - close(iunit) - -end subroutine write_setupfile - -!---------------------------------------------------------------- -!+ -! Read parameters from setup file -!+ -!---------------------------------------------------------------- -subroutine read_setupfile(filename,ierr) - use infile_utils, only: open_db_from_file,inopts,read_inopt,close_db - use unifdis, only: is_valid_lattice - use io, only: error - use units, only: select_unit - character(len=*), intent(in) :: filename - integer, intent(out) :: ierr - integer, parameter :: iunit = 21 - integer :: i,nerr,kerr,jerr - type(inopts), allocatable :: db(:) - - !--Read values - print "(a)",' reading setup options from '//trim(filename) - call open_db_from_file(db,filename,iunit,ierr) - call read_inopt(mass_unit,'mass_unit',db,ierr) - call read_inopt(dist_unit,'dist_unit',db,ierr) - call read_inopt(BEsphere,'use_BE_sphere',db,ierr) - call read_inopt(binary,'form_binary',db,ierr) - call read_inopt(np,'np',db,ierr) - call read_inopt(lattice,'lattice',db,ierr) - if (ierr/=0 .or. .not. is_valid_lattice(trim(lattice))) then - print*, ' invalid lattice. Setting to closepacked' - lattice = 'closepacked' - endif - call read_inopt(shuffle_parts,'shuffle_parts',db,ierr) - - call read_inopt(lbox,'lbox',db,jerr) ! for backwards compatibility - if (jerr /= 0) then - do i=1,3 - call read_inopt(xmini(i),labelx(i)//'min',db,ierr) - call read_inopt(xmaxi(i),labelx(i)//'max',db,ierr) - enddo - lbox = -2.0*xmini(1)/r_sphere - endif - - if (.not. BEsphere) then - call read_inopt(r_sphere,'r_sphere',db,ierr) - call read_inopt(totmass_sphere,'totmass_sphere',db,ierr) - else - call read_inopt(iBEparam,'iBE_options',db,ierr) - if (iBEparam==1 .or. iBEparam==2 .or. iBEparam==3) call read_inopt(BErho_cen,'BErho_cen',db,ierr) - if (iBEparam==1 .or. iBEparam==4 .or. iBEparam==6) call read_inopt(BErad_phys,'BErad_phys',db,ierr) - if (iBEparam==2 .or. iBEparam==4 .or. iBEparam==5) call read_inopt(BErad_norm,'BErad_norm',db,ierr) - if (iBEparam==3 .or. iBEparam==5 .or. iBEparam==6) call read_inopt(BEmass,'BEmass',db,ierr) - if (iBEparam==4 .or. iBEparam==5) call read_inopt(BEfac,'BEfac',db,ierr) - endif - - call read_inopt(T_sphere,'T_sphere',db,jerr) - cs_in_code = .false. ! for backwards compatibility - if (jerr /= 0 .and. kerr == 0) then - cs_in_code = .false. - elseif (jerr == 0 .and. kerr /= 0) then - cs_in_code = .true. - else - ierr = ierr + 1 - endif - call read_inopt(angvel,'angvel',db,jerr) - call read_inopt(beta_r,'beta_r',db,kerr) - angvel_not_betar = .true. - if (jerr /= 0 .and. kerr == 0) then - angvel_not_betar = .false. - elseif (jerr == 0 .and. kerr /= 0) then - angvel_not_betar = .true. - else - ierr = ierr + 1 - endif - call read_inopt(rms_mach,'rms_mach',db,ierr) - mu_not_B = .true. - if (mhd) then - call read_inopt(masstoflux,'masstoflux',db,jerr) - call read_inopt(Bzero_G, 'Bzero', db,kerr) - call read_inopt(ang_Bomega,'ang_Bomega',db,ierr) - if (jerr /= 0 .and. kerr == 0) then - mu_not_B = .false. - elseif (jerr == 0 .and. kerr /= 0) then - mu_not_B = .true. - else - ierr = ierr + 1 - endif - endif - if (use_dust) then - call read_inopt(dtg,'dust_to_gas_ratio',db,ierr) - call read_inopt(ndusttypes,'ndusttypes',db,ierr) - if (ndusttypes > 1) then - call read_inopt(smincgs,'smincgs',db,ierr) - call read_inopt(smaxcgs,'smaxcgs',db,ierr) - call read_inopt(sindex,'cs_sphere',db,ierr) - call read_inopt(graindenscgs,'graindenscgs',db,ierr) - else - call read_inopt(grainsizecgs,'grainsizecgs',db,ierr) - call read_inopt(graindenscgs,'graindenscgs',db,ierr) - endif - endif - if (binary) then - call read_inopt(rho_pert_amp,'rho_pert_amp',db,ierr) - endif - call read_inopt(icreate_sinks_setup,'icreate_sinks',db,ierr) - if (icreate_sinks_setup==1) then - call read_inopt(h_acc_setup,'h_acc',db,ierr) - call read_inopt(r_crit_setup,'r_crit',db,ierr) - if (binary) then - call read_inopt(h_soft_sinksink_setup,'h_soft_sinksink',db,ierr) - endif - else - call read_inopt(rhofinal_setup,'rho_final',db,ierr) - endif - call close_db(db) - ! - ! parse units - ! - call select_unit(mass_unit,umass,nerr) - if (nerr /= 0) then - call error('setup_sphereinbox','mass unit not recognised') - ierr = ierr + 1 - endif - call select_unit(dist_unit,udist,nerr) - if (nerr /= 0) then - call error('setup_sphereinbox','length unit not recognised') - ierr = ierr + 1 - endif - - if (ierr > 0) then - print "(1x,a,i2,a)",'Setup_sphereinbox: ',nerr,' error(s) during read of setup file. Re-writing.' - endif - -end subroutine read_setupfile -!---------------------------------------------------------------- - !--Magnetic flux justification - ! This shows how the critical mass-to-flux values translates from CGS to code units. - ! - ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) ! cgs units of g G^-1 cm^-2 - ! convert base units from cgs to code: - ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *unit_Bfield*udist**2/umass - ! where - ! unit_Bfield = umass/(utime*sqrt(umass*udist/4*pi)) = sqrt(4.*pi*umass)/(utime*sqrt(udist)) - ! therefore - ! rmasstoflux_crit = 0.53/(3*pi)*sqrt(5./G) *sqrt(4.*pi*umass)*udist**2/(utime*sqrt(udist)*umass) - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*sqrt(umass)*udist**2/(utime*sqrt(udist)*umass) - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./(G*pi))*udist**1.5/ (sqrt(umass)*utime) - ! where - ! G [cgs] = 1 * udist**3/(umass*utime**2) - ! therefore - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) *udist**1.5/ (sqrt(umass)*utime) / sqrt(udist**3/(umass*utime**2)) - ! rmasstoflux_crit = (2/3)*0.53*sqrt(5./pi) ! code units - -!---------------------------------------------------------------- -end module setup From 55eff86981b9b03eacf017734092a0388e73cd61 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 21 Oct 2024 16:10:56 +0100 Subject: [PATCH 163/182] Edits to enable blob setup to build --- src/main/cooling_radapprox.f90 | 26 ++++++++++++++++---------- src/main/dens.F90 | 18 +++++++++++------- src/main/eos_stamatellos.f90 | 6 ++++-- src/main/radiation_utils.f90 | 6 ++++-- src/utils/analysis_disc_stresses.f90 | 12 ++++++------ 5 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 89c563a71..f55707002 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -77,7 +77,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) real,intent(out)::dudti_cool real :: coldensi,kappaBari,kappaParti,ri2 real :: gmwi,Tmini4,Ti,dudti_rad,Teqi,Hstam,HLom,du_tot - real :: cs2,Om2,Hmod2 + real :: cs2,Om2,Hmod2,rhoi_cgs,ui_cgs real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi coldensi = huge(coldensi) @@ -99,7 +99,9 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) endif ! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + 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 @@ -146,7 +148,7 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) Tmini4 = Tfloor**4d0 endif - call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi*unit_density,umini) + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi_cgs,umini) umini = umini/unit_ergg opaci = (coldensi**2d0)*kappaBari + (1.d0/kappaParti) ! physical units @@ -195,7 +197,8 @@ subroutine radcool_update_energ(i,xi,yi,zi,rhoi,ui,Tfloor,dt,dudti_cool) "Ti=", Ti, "poti=",poti, "rhoi=", rhoi endif - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + rhoi_cgs = rhoi*unit_density + call getintenerg_opdep(Teqi,rhoi_cgs,ueqi) ueqi = ueqi/unit_ergg ! calculate thermalization timescale @@ -248,7 +251,7 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,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 + real :: cs2,Om2,Hmod2,ui_cgs,rhoi_cgs real :: opaci,ueqi,umini,tthermi,poti,presi,Hcomb,du_FLDi integer :: i,ratefile,n_uevo @@ -262,8 +265,8 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) !$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) & - !$omp private(cs2,Om2,Hmod2,opaci,ueqi,umini,tthermi,presi,Hcomb,dti) & + !$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 @@ -292,7 +295,9 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) endif ! get opacities & Ti for ui - call getopac_opdep(ui*unit_ergg,rhoi*unit_density,kappaBari,kappaParti,& + 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 @@ -377,10 +382,11 @@ subroutine radcool_update_energ_loop(dtsph,npart,xyzh,energ,dudt_sph,Tfloor) "Ti=", Ti, "poti=",poti, "rhoi=", rhoi endif - call getintenerg_opdep(Teqi,rhoi*unit_density,ueqi) + 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*unit_density,umini) + call getintenerg_opdep(Tmini4**(1.0/4.0),rhoi_cgs,umini) umini = umini/unit_ergg ! calculate thermalization timescale diff --git a/src/main/dens.F90 b/src/main/dens.F90 index e6fbd2801..b861cb2d8 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -302,6 +302,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol !$omp reduction(max:rhomax) & !$omp private(i) + call init_cell_exchange(xrecvbuf,irequestrecv,thread_complete,ncomplete_mpi,mpitype) !$omp master @@ -1689,14 +1690,14 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra integer :: icell,i,iamtypei,iamtypej,j,n logical :: iactivei,iamgasi,iamdusti,ignoreself logical :: iactivej,iamgasj,iamdustj - real(kind=8) :: hi,hi1,hi21,hi31,hi41 - real :: rhoi,rho1i,dhdrhoi,pmassi,kappabari,kappaparti,Ti,gmwi + real(kind=8) :: hi1,hi21,hi31,hi41,hj1,hj21 + real :: hi,hj,rhoi,rho1i,dhdrhoi,pmassi,kappabari,kappaparti,Ti,gmwi real :: xj,yj,zj,dx,dy,dz - real :: rij2,rij,q2i,qi,hj1,hj,hj21,q2j + real :: rij2,rij,q2i,qi,q2j real :: wabi,grkerni,gradhi,wkerni,dwkerni real :: pmassj,rhoj,rho1j,dhdrhoj,kappabarj,kappaPartj,Tj,gmwj real :: uradi,dradi,dradxi,dradyi,dradzi,runix,runiy,runiz - real :: dT4,R_rad + real :: dT4,R_rad,u_cgs,rho_cgs integer :: ngradh_err ngradh_err = 0 @@ -1735,8 +1736,9 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra print *, "u=0 in FLD calc", vxyzu(4,i), i,rhoi*unit_density,Ti,& cell%xpartvec(ixi,icell),cell%xpartvec(iyi,icell) endif - call getopac_opdep(vxyzu(4,i)*unit_ergg,rhoi*unit_density,kappabari, & - kappaparti,Ti,gmwi) + u_cgs = vxyzu(4,i)*unit_ergg + rho_cgs = rhoi*unit_density + call getopac_opdep(u_cgs,rho_cgs,kappabari,kappaparti,Ti,gmwi) loop_over_neighbours: do n=1,nneigh j = abs(listneigh(n)) @@ -1791,7 +1793,9 @@ subroutine calc_lambda_cell(cell,listneigh,nneigh,xyzh,xyzcache,vxyzu,iphase,gra dwkerni = grkerni*cnormk*hi21*hi21*gradh(1,i) pmassj = massoftype(iamtypej) call rhoanddhdrho(hj,hj1,rhoj,rho1j,dhdrhoj,pmassj) - call getopac_opdep(vxyzu(4,j)*unit_ergg,rhoj*unit_density,& + u_cgs = vxyzu(4,j)*unit_ergg + rho_cgs = rhoj*unit_density + call getopac_opdep(u_cgs,rho_cgs,& kappaBarj,kappaPartj,Tj,gmwj) uradi = uradi + get_radconst_code()*(Tj**4.0d0)*wkerni*pmassj/rhoj diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index df4239ba4..84ec8148e 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -283,13 +283,15 @@ subroutine get_k_fld(rhoi,eni,i,ki,Ti) use units, only:unit_density,unit_ergg,unit_opacity,get_radconst_code real,intent(in) :: rhoi,eni integer,intent(in) :: i - real :: kappaBar,gmwi,kappaPart + real :: kappaBar,gmwi,kappaPart,eni_ergg,rhoi_g real,intent(out) :: ki,Ti if (lambda_FLD(i) == 0d0) then ki = 0. else - call getopac_opdep(eni*unit_ergg,rhoi*unit_density,kappaBar,kappaPart,Ti,gmwi) + eni_ergg = eni*unit_ergg + rhoi_g = rhoi*unit_density + call getopac_opdep(eni_ergg,rhoi_g,kappaBar,kappaPart,Ti,gmwi) kappaPart = kappaPart/unit_opacity ! steboltz constant = 4pi/c * arad ki = 16d0*(fourpi/c)*get_radconst_code()*lambda_FLD(i)*Ti**3 /rhoi/kappaPart diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 6197de6cb..a93458977 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -419,7 +419,7 @@ subroutine get_opacity(opacity_type,density,temperature,kappa,u) real, intent(in), optional :: u real, intent(out) :: kappa integer, intent(in) :: opacity_type - real :: kapt,kapr,rho_cgs,Ti,gmwi,kapBar,kappaPart + real :: kapt,kapr,rho_cgs,Ti,gmwi,kapBar,kappaPart,u_cgs select case(opacity_type) case(1) @@ -440,7 +440,9 @@ subroutine get_opacity(opacity_type,density,temperature,kappa,u) ! ! opacity for Stamatellos/Lombardi EOS ! - call getopac_opdep(u*unit_ergg,density*unit_density,kapBar,kappaPart,Ti,gmwi) + rho_cgs = density*unit_density + u_cgs = u*unit_ergg + call getopac_opdep(u_cgs,rho_cgs,kapBar,kappaPart,Ti,gmwi) kappa = kappaPart/unit_opacity case default ! diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index 211530826..ea1f79c52 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -35,7 +35,7 @@ module analysis real, allocatable,dimension(:) :: H, toomre_q,epicyc,part_scaleheight real, allocatable,dimension(:) :: alpha_reyn,alpha_grav,alpha_mag,alpha_art real, allocatable,dimension(:) :: rpart,phipart,vrpart,vphipart, gr,gphi,Br,Bphi - real, allocatable,dimension(:,:) :: gravxyz + real, allocatable,dimension(:,:) :: gravxyz,zsetgas logical :: write_neighbour_list = .true. ! Write the neighbour list to file, if true @@ -356,7 +356,7 @@ end subroutine transform_to_cylindrical !+ !--------------------------------------------------------------- -subroutine radial_binning(npart,xyzh,vxyzu,pmass) +subroutine radial_binning(npart,xyzh,vxyzu,pmass,eos_vars) use physcon, only:pi use eos, only:get_spsound,ieos use part, only:rhoh,isdead_or_accreted @@ -365,7 +365,7 @@ subroutine radial_binning(npart,xyzh,vxyzu,pmass) real,intent(in) :: pmass real,intent(in) :: xyzh(:,:),vxyzu(:,:),eos_vars(:,:) - integer :: ibin,ipart,nbinned + integer :: ibin,ipart,nbinned,iallocerr real :: area,csi print '(a,I4)', 'Carrying out radial binning, number of bins: ',nbins @@ -464,8 +464,8 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) use physcon, only: pi,gg,kb_on_mh use units, only: print_units, umass,udist,utime,unit_velocity,unit_density,unit_Bfield use dim, only: gravity - use part, only: mhd,rhoh,alphaind,eos_vars,imu,itemp - use eos, only: gamma,ieos + use part, only: mhd,rhoh,alphaind,imu,itemp + use eos, only: ieos implicit none @@ -500,7 +500,7 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) sigma(:) = sigma(:)*umass/(udist*udist) if (ieos /= 21) then - csbin(:) = csbin(:)*unit_velocity + csbin(:) = csbin(:)*unit_velocity endif omega(:) = omega(:)/utime From 2ec3ecc5d15adc62412138253708b823d81d57dd Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 4 Nov 2024 10:51:24 +0000 Subject: [PATCH 164/182] Rad approx cooling: changed to update energy during leapfrog integrator. --- src/main/cooling.f90 | 11 +- src/main/cooling_radapprox.f90 | 302 +++++--------------- src/main/dens.F90 | 13 +- src/main/eos.f90 | 1 + src/main/eos_stamatellos.f90 | 9 +- src/main/force.F90 | 17 +- src/main/{mpi_memory.F90 => mpi_memory.f90} | 0 src/main/readwrite_dumps_fortran.f90 | 4 +- src/main/step_leapfrog.F90 | 47 +-- src/main/substepping.F90 | 11 +- 10 files changed, 133 insertions(+), 282 deletions(-) rename src/main/{mpi_memory.F90 => mpi_memory.f90} (100%) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 0bb572586..f7953f911 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -75,7 +75,6 @@ subroutine init_cooling(id,master,iprint,ierr) integer, intent(in) :: id,master,iprint integer, intent(out) :: ierr - logical :: ex cooling_in_step = .true. ierr = 0 @@ -90,8 +89,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() @@ -132,7 +129,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 +140,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 +184,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..373f8ddc3 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,72 @@ 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 +! print *, "oh no i=",i,"ui=",ui,"tthermi=",tthermi,dt,"ueqi",ueqi,rhoi_cgs + ! print *, exp(-dt/tthermi),1.d0-exp(-dt/tthermi) +! call warning("In radcool_evolve_ui","energ=NaN or 0. ui=",val=utemp) + utemp = ui + endif + endif +!else + ! print *, "no_update", tthermi,dt,ui,ueqi + !endif + if (utemp < ufloor_cgs/unit_ergg) utemp = ufloor_cgs/unit_ergg + if (utemp < 0d0) print *, "ERRRORRR! 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 +153,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 +207,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 +237,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 +247,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..93da87aa1 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) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 932ef9894..66bf377e9 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 @@ -42,14 +42,14 @@ subroutine init_S07cool() 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('ueqi_store',ueqi_store,npart) call allocate_array('opac_store',opac_store,npart) call allocate_array('duSPH',duSPH,npart) 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 @@ -69,7 +69,7 @@ subroutine finish_S07cool() 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) @@ -128,6 +128,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/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/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..db23978fc 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) From b60eef7610eeca6a15ee6b0d8285b5f5f6cab648 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 8 Nov 2024 11:17:58 +0000 Subject: [PATCH 165/182] Rad approx cooling: prevent bug in substepping --- src/main/substepping.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index db23978fc..a0f9a3a75 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -1236,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 From 1b4c4ac8cfa0484b58306f246f912bbd0d917481 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 12 Nov 2024 16:39:18 +0000 Subject: [PATCH 166/182] New setup designed for icooling=9. This sets the temperature/sound speed profile from the luminosity of the central star. Will need generalizing. --- src/setup/setup_disc.f90 | 93 ++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 14 deletions(-) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 590f8a2b4..362322b83 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,7 @@ 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 real, intent(out) :: gamma real :: H_R_atm, cs @@ -705,11 +710,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)) + 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 +2264,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 +2730,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 +2768,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 +3068,8 @@ subroutine read_setupfile(filename,ierr) end select call read_inopt(discstrat,'discstrat',db,errcount=nerr) + call read_inopt(lumdisc,'lumdisc',db,errcount=nerr) + print *, "read lumdisc=", lumdisc if (discstrat==1) then call read_inopt(istrat,'istrat',db,errcount=nerr) call read_inopt(z0_ref,'z0',db,errcount=nerr) @@ -3136,10 +3181,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 +3261,13 @@ 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=ierr) + print *, "read L_star", L_star + call read_inopt(T_bg,'T_bg',db,min=0.,errcount=ierr) + print *, "read T_bg", T_bg + endif + call close_db(db) ierr = nerr if (nerr > 0) then @@ -3492,5 +3546,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 From 1506740b0315ecd29bd596ce6cbf868d30380981 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 12 Nov 2024 16:40:25 +0000 Subject: [PATCH 167/182] removed duplicated opacity table read --- src/main/cooling.f90 | 4 ---- src/main/eos_stamatellos.f90 | 29 +++++++++++++++-------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 0bb572586..946cf2b70 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -90,10 +90,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) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 932ef9894..299cb05a0 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -32,19 +32,19 @@ 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('teqi_store',teqi_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 @@ -53,7 +53,7 @@ subroutine init_S07cool() 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,7 +62,7 @@ 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) @@ -72,7 +72,7 @@ subroutine finish_S07cool() if (allocated(teqi_store)) deallocate(teqi_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 +89,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) From 9ca68cb10b2b360e389cda75fb1abac75e4542eb Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 13 Nov 2024 09:27:05 +0000 Subject: [PATCH 168/182] Deleted unused module imports --- src/main/cooling.f90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index 946cf2b70..e82b0bb47 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -69,7 +69,6 @@ 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 From 27448859f358da0769427c2416eb9a8776e61320 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Wed, 13 Nov 2024 09:29:54 +0000 Subject: [PATCH 169/182] Removed superfluous optab read from cooling.f90 --- src/main/cooling.f90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index f7953f911..610acb7c2 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -69,7 +69,6 @@ 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 @@ -89,8 +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) - 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) From a3b6ba56764c9fb201741bc14ec82587df72e2c2 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 15 Nov 2024 16:59:28 +0000 Subject: [PATCH 170/182] Edits to setup_disc.f90 --- src/main/eos_stamatellos.f90 | 2 +- src/setup/setup_disc.f90 | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 603ad786f..63da59067 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -42,7 +42,7 @@ subroutine init_S07cool() 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',teqi_store,maxp) + call allocate_array('ueqi_store',ueqi_store,maxp) call allocate_array('opac_store',opac_store,maxp) call allocate_array('duSPH',duSPH,maxp) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 362322b83..11ddfc140 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -621,6 +621,7 @@ subroutine equation_of_state(gamma) use options, only:ieos,icooling use options, only:nfulldump,alphau,ipdv_heating,ishock_heating use eos_stamatellos, only:init_S07cool + use physcon, only:twopi real, intent(out) :: gamma real :: H_R_atm, cs @@ -722,7 +723,7 @@ subroutine equation_of_state(gamma) print *, "We can't set up multiple radapprox discs yet :,(" stop else - cs = get_cs_from_lum(L_star(1),R_ref(1)) + cs = get_cs_from_lum(L_star(1),R_ref(1)) / sqrt(twopi) H_R(1) = cs * R_ref(1)**0.5 / sqrt(m1) ! single central star, G=1 endif else @@ -3069,7 +3070,7 @@ subroutine read_setupfile(filename,ierr) call read_inopt(discstrat,'discstrat',db,errcount=nerr) call read_inopt(lumdisc,'lumdisc',db,errcount=nerr) - print *, "read lumdisc=", lumdisc + if (discstrat==1) then call read_inopt(istrat,'istrat',db,errcount=nerr) call read_inopt(z0_ref,'z0',db,errcount=nerr) @@ -3262,10 +3263,8 @@ 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=ierr) - print *, "read L_star", L_star - call read_inopt(T_bg,'T_bg',db,min=0.,errcount=ierr) - print *, "read T_bg", T_bg + 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) From edd51c9d973ff1e10de252485bded93e2479bb92 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 18 Nov 2024 16:27:18 +0000 Subject: [PATCH 171/182] Added eos=23 handling to analysis_disc_stresses.f90 --- src/utils/analysis_disc_stresses.f90 | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) 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 !------------------------------------------------------- From bdffd765f72245b158143272ec7c3e5452f56431 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 25 Nov 2024 11:21:00 +0000 Subject: [PATCH 172/182] finalised sgdisc setup for radiative approx cooling --- src/setup/setup_disc.f90 | 6 +++--- src/utils/analysis_disc_stresses.f90 | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 11ddfc140..403e99694 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -621,7 +621,7 @@ subroutine equation_of_state(gamma) use options, only:ieos,icooling use options, only:nfulldump,alphau,ipdv_heating,ishock_heating use eos_stamatellos, only:init_S07cool - use physcon, only:twopi + use physcon, only:rpiontwo real, intent(out) :: gamma real :: H_R_atm, cs @@ -722,8 +722,8 @@ subroutine equation_of_state(gamma) 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)) / sqrt(twopi) + 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 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 !------------------------------------------------------- From 1d0ab01fcfcf5463e8a4580c9f8134cc6cc46bbb Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 25 Nov 2024 17:12:47 +0000 Subject: [PATCH 173/182] Tidying cooling_radapprox.f90 --- src/main/cooling_radapprox.f90 | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 373f8ddc3..3b7bc7701 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -90,17 +90,11 @@ subroutine radcool_evolve_ui(ui,dt,i,Tfloor,h,uout) ! if tthermi ==0 or dt/thermi is neglible then ui doesn't change if (isnan(utemp) .or. utemp < epsilon(utemp)) then -! print *, "oh no i=",i,"ui=",ui,"tthermi=",tthermi,dt,"ueqi",ueqi,rhoi_cgs - ! print *, exp(-dt/tthermi),1.d0-exp(-dt/tthermi) -! call warning("In radcool_evolve_ui","energ=NaN or 0. ui=",val=utemp) utemp = ui endif endif -!else - ! print *, "no_update", tthermi,dt,ui,ueqi - !endif if (utemp < ufloor_cgs/unit_ergg) utemp = ufloor_cgs/unit_ergg - if (utemp < 0d0) print *, "ERRRORRR! i=",i, ui,ueqi + if (utemp < 0d0) print *, "ERROR! i=",i, ui,ueqi if (present(uout)) then uout = utemp From 01b065d0274b03845ea5e7093607607858b9d951 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 26 Nov 2024 16:01:10 +0000 Subject: [PATCH 174/182] tidying radapprox sgdisc setup --- src/main/cooling_radapprox.f90 | 2 +- src/setup/setup_disc.f90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 3b7bc7701..ead30bd4e 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -111,7 +111,7 @@ end subroutine radcool_evolve_ui ! update energy to return evolved energy array. Called from substep 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 physcon, only:steboltz,pi,solarl,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,ueqi_store,opac_store diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 403e99694..9bd332979 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -3551,7 +3551,7 @@ real function get_cs_from_lum(L_star,r) real,intent(in) :: L_star,r real :: mu - mu = 2.3 !mean molecular mass + mu = 2.381 !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 From 8987fae27075cf251aba2d431519dee7f158104e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 9 Dec 2024 16:52:48 +0000 Subject: [PATCH 175/182] Edit for GitHub build --- src/setup/setup_disc.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 9bd332979..87e5381ce 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -2271,7 +2271,7 @@ subroutine setup_interactive(id) endif if (lumdisc > 0) then !get luminosity ... - call prompt("Enter the luminosity of star",L_star(i)) + call prompt("Enter the luminosity of star",L_star(1)) call prompt("Enter the background temperature e.g. 10 (K)", T_bg) qindex(1) = 0.25 qindex = 0.25 From d580376122967688065c6b6eefe3035d1e20bf9e Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 10 Dec 2024 09:23:05 +0000 Subject: [PATCH 176/182] Edits for GitHub build --- src/utils/analysis_disc_stresses.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index 8fe638193..928403471 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -369,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,ierr + integer :: ibin,ipart,nbinned,iallocerr real :: area,csi print '(a,I4)', 'Carrying out radial binning, number of bins: ',nbins From d22176241b788086e69a45251560f1cf21636e53 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 17 Dec 2024 14:49:26 +0000 Subject: [PATCH 177/182] Bug fixes --- src/main/cooling_radapprox.f90 | 2 +- src/main/eos_stamatellos.f90 | 2 +- src/main/step_leapfrog.F90 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index cc36274c2..97005b8e4 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -112,7 +112,7 @@ subroutine radcool_update_du(i,xi,yi,zi,rhoi,ui,duhydro,Tfloor) use physcon, only:steboltz,pi,solarl,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,& - ttherm_store,teqi_store,opac_store + 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 diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index e45962b7f..9c583c327 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 :: gradP_cool(:)!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 :: floor_energy = .False. integer,public :: iunitst=19 diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 2518e1ba9..d77aac887 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -456,7 +456,7 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp shared(dustevol,ddustevol,use_dustfrac) & !$omp shared(dustprop,ddustprop,dustproppred) & !$omp shared(xyzmh_ptmass,vxyz_ptmass,fxyz_ptmass,nptmass,massoftype) & -!$omp shared(dtsph,ieos,ufloor,icooling) & +!$omp shared(dtsph,ieos,ufloor,icooling,Tfloor) & !$omp shared(ibin,ibin_old,ibin_sts,twas,timei,use_sts,dtsph_next,ibin_wake,sts_it_n) & !$omp shared(ibin_dts,nbinmax) & !$omp private(dti,hdti) & From b3ab6651a9c562ac1af233ce9b927ff22efdd4f8 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Tue, 17 Dec 2024 15:11:29 +0000 Subject: [PATCH 178/182] Fix bug in setup_disc.f90 --- src/setup/setup_disc.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 89ede5bfc..c7e10567e 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -620,7 +620,7 @@ 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 eos_stamatellos, only:init_coolra use physcon, only:rpiontwo real, intent(out) :: gamma real :: H_R_atm, cs @@ -724,7 +724,7 @@ subroutine equation_of_state(gamma) ieos = 23 icooling = 9 gamma = 5./3. ! in case it's needed - call init_S07cool() + call init_coolra() if (ndiscs > 1) then print *, "We can't set up multiple radapprox discs yet :,(" stop From ca0202f1331a37dd2a09c7011f569c657dc7796a Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 20 Dec 2024 16:43:43 +0000 Subject: [PATCH 179/182] Fixing bugs in ModLom cooling --- src/setup/setup_disc.f90 | 4 ++-- src/utils/analysis_disc_stresses.f90 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index 89ede5bfc..c7e10567e 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -620,7 +620,7 @@ 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 eos_stamatellos, only:init_coolra use physcon, only:rpiontwo real, intent(out) :: gamma real :: H_R_atm, cs @@ -724,7 +724,7 @@ subroutine equation_of_state(gamma) ieos = 23 icooling = 9 gamma = 5./3. ! in case it's needed - call init_S07cool() + call init_coolra() if (ndiscs > 1) then print *, "We can't set up multiple radapprox discs yet :,(" stop diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index f90b63227..16b8ec9f8 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -468,8 +468,8 @@ subroutine calc_stresses(npart,xyzh,vxyzu,pmass) use physcon, only: pi,gg,kb_on_mh use units, only: print_units, umass,udist,utime,unit_velocity,unit_density,unit_Bfield use dim, only: gravity - use part, only: mhd,rhoh,alphaind,eos_vars,imu,itemp - use eos, only: gamma,ieos + use part, only: mhd,rhoh,alphaind,imu,itemp + use eos, only: ieos implicit none From 53d3ae3a04f71f9a9637ad3a9ea43b5abe2e79d5 Mon Sep 17 00:00:00 2001 From: Alison Young Date: Fri, 17 Jan 2025 15:05:14 +0000 Subject: [PATCH 180/182] [indent-bot] standardised indentation --- src/main/cooling_radapprox.f90 | 82 +++++++++++++------------- src/main/dens.F90 | 2 +- src/main/force.F90 | 2 +- src/main/inject_windtunnel.f90 | 6 +- src/main/readwrite_dumps_fortran.f90 | 2 +- src/main/step_leapfrog.F90 | 14 ++--- src/main/substepping.F90 | 4 +- src/setup/setup_disc.f90 | 28 ++++----- src/setup/setup_windtunnel.f90 | 4 +- src/utils/analysis_common_envelope.f90 | 8 +-- 10 files changed, 76 insertions(+), 76 deletions(-) diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 97005b8e4..60fe48c13 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -58,47 +58,47 @@ subroutine init_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 + 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 diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 668ff24a9..35984339f 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -451,7 +451,7 @@ subroutine densityiterate(icall,npart,nactive,xyzh,vxyzu,divcurlv,divcurlB,Bevol cell_xpos=cell%xpos,cell_xsizei=cell%xsizei,cell_rcuti=cell%rcuti) call compute_cell(cell,listneigh,nneigh,getdv,getdB,Bevol,xyzh,vxyzu,fxyzu,fext,xyzcache,rad,apr_level) - + remote_export = .false. remote_export(cell%owner+1) = .true. ! use remote_export array to send back to the owner diff --git a/src/main/force.F90 b/src/main/force.F90 index 781d32caf..2172ba966 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -2999,7 +2999,7 @@ 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) then + 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 diff --git a/src/main/inject_windtunnel.f90 b/src/main/inject_windtunnel.f90 index 07f1fa166..daa6537d1 100644 --- a/src/main/inject_windtunnel.f90 +++ b/src/main/inject_windtunnel.f90 @@ -298,10 +298,10 @@ subroutine subtract_star_vcom(nsphere,xyzh,vxyzu) vstar = vstar/real(nbulk) do i=1,nsphere - if (xyzh(1,i) < 2.*Rstar) then + if (xyzh(1,i) < 2.*Rstar) then vxyzu(1:3,i) = vxyzu(1:3,i) - vstar - endif -enddo + endif + enddo end subroutine subtract_star_vcom diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index e8e482b45..4c9e4f6f1 100644 --- a/src/main/readwrite_dumps_fortran.f90 +++ b/src/main/readwrite_dumps_fortran.f90 @@ -250,7 +250,7 @@ subroutine write_fulldump_fortran(t,dumpfile,ntotal,iorder,sphNG) endif endif ! write stamatellos cooling values - if (icooling == 9) then + if (icooling == 9) then 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) diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index d77aac887..70757c3cd 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -179,8 +179,8 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) !$omp private(i,hdti) & !$omp reduction(+:nvfloorp) predictor: do i=1,npart - ! print *, "predictor, i=", i - 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 ! @@ -680,11 +680,11 @@ subroutine step(npart,nactive,t,dtsph,dtextforce,dtnew) pxyzu(:,i) = pxyzu(:,i) - hdtsph*fxyzu(:,i) else 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 + 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 diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index e028f34a3..101639feb 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -335,7 +335,7 @@ 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 @@ -572,7 +572,7 @@ subroutine substep(npart,ntypes,nptmass,dtsph,dtextforce,time,xyzh,vxyzu,fext, & enddo substeps if (icreate_sinks == 2) call ptmass_check_stars(xyzmh_ptmass,linklist_ptmass,nptmass,timei) - + if (nsubsteps > 1) then if (iverbose >=1 .and. id==master) then write(iprint,"(a,i6,3(a,es10.3))") ' using ',nsubsteps,' substeps '//& diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index c7e10567e..f822f3176 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -326,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(/, & @@ -718,7 +718,7 @@ subroutine equation_of_state(gamma) else !-- adiabatic - if (lumdisc > 0) then + if (lumdisc > 0) then !--for radapprox cooling print "(/,a)", ' setting ieos=23 and icooling=9 for radiative cooling approximation' ieos = 23 @@ -728,8 +728,8 @@ subroutine equation_of_state(gamma) 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 + 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 @@ -2279,7 +2279,7 @@ subroutine setup_interactive(id) !get luminosity ... call prompt("Enter the luminosity of star",L_star(1)) call prompt("Enter the background temperature e.g. 10 (K)", T_bg) - qindex(1) = 0.25 + qindex(1) = 0.25 qindex = 0.25 else call prompt('Enter q_index',qindex(1)) @@ -3191,7 +3191,7 @@ subroutine read_setupfile(filename,ierr) 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 .and. lumdisc == 0) then + 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) @@ -3552,15 +3552,15 @@ 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 + 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.381 !mean molecular mass - get_cs_from_lum = sqrt(kb_on_mh/mu) * ( (L_star*solarl/(fourpi*steboltz))**0.125 / & + mu = 2.381 !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 + get_cs_from_lum = get_cs_from_lum/unit_velocity +end function get_cs_from_lum end module setup diff --git a/src/setup/setup_windtunnel.f90 b/src/setup/setup_windtunnel.f90 index 0bbc21f56..d82549f47 100644 --- a/src/setup/setup_windtunnel.f90 +++ b/src/setup/setup_windtunnel.f90 @@ -168,9 +168,9 @@ subroutine setpart(id,npart,npartoftype,xyzh,massoftype,vxyzu,polyk,gamma,hfact, vxyzu(4,i) = presi / ( (gamma-1.) * densi) enddo - deallocate(r,den,pres) + deallocate(r,den,pres) endif - + print*, "udist = ", udist, "; umass = ", umass, "; utime = ", utime end subroutine setpart diff --git a/src/utils/analysis_common_envelope.f90 b/src/utils/analysis_common_envelope.f90 index 7843a5bb2..c1056f118 100644 --- a/src/utils/analysis_common_envelope.f90 +++ b/src/utils/analysis_common_envelope.f90 @@ -1370,7 +1370,7 @@ subroutine output_extra_quantities(time,dumpfile,npart,particlemass,xyzh,vxyzu) .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)) @@ -1385,7 +1385,7 @@ subroutine output_extra_quantities(time,dumpfile,npart,particlemass,xyzh,vxyzu) 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 @@ -1851,7 +1851,7 @@ subroutine recombination_tau(time,npart,particlemass,xyzh,vxyzu) 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),rad(:,i),xyzmh_ptmass,phii,& - epoti,ekini,egasi,eradi,ereci,dum) + 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 @@ -3776,7 +3776,7 @@ subroutine calc_gas_energies(particlemass,poten,xyzh,vxyzu,rad,xyzmh_ptmass,phii egasi = vxyzu(4)*particlemass egasradi = egasi + eradi case(10) ! not tested - eradi = 0. ! not implemented + 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 From 3f066123496ec68255e7a9e16771631142355dab Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 20 Jan 2025 11:40:40 +0000 Subject: [PATCH 181/182] Header bot applied --- src/main/H2regions.f90 | 2 +- src/main/apr.f90 | 2 +- src/main/apr_region.f90 | 2 +- src/main/bondiexact.f90 | 2 +- src/main/bondiexact_gr.f90 | 2 +- src/main/boundary.f90 | 2 +- src/main/boundary_dynamic.f90 | 2 +- src/main/centreofmass.f90 | 2 +- src/main/checkconserved.f90 | 2 +- src/main/checkoptions.F90 | 2 +- src/main/checksetup.f90 | 2 +- src/main/config.F90 | 2 +- src/main/cons2prim.f90 | 2 +- src/main/cons2primsolver.f90 | 2 +- src/main/cooling.f90 | 6 +++--- src/main/cooling_functions.f90 | 2 +- src/main/cooling_gammie.f90 | 2 +- src/main/cooling_gammie_PL.f90 | 2 +- src/main/cooling_ism.f90 | 2 +- src/main/cooling_koyamainutsuka.f90 | 2 +- src/main/cooling_molecular.f90 | 2 +- src/main/cooling_radapprox.f90 | 2 +- src/main/cooling_solver.f90 | 2 +- src/main/cullendehnen.f90 | 2 +- src/main/damping.f90 | 2 +- src/main/datafiles.f90 | 2 +- src/main/dens.F90 | 2 +- src/main/deriv.F90 | 2 +- src/main/dtype_kdtree.F90 | 2 +- src/main/dust.f90 | 2 +- src/main/dust_formation.f90 | 2 +- src/main/energies.F90 | 2 +- src/main/eos.f90 | 2 +- src/main/eos_HIIR.f90 | 2 +- src/main/eos_barotropic.f90 | 2 +- src/main/eos_gasradrec.f90 | 2 +- src/main/eos_helmholtz.f90 | 2 +- src/main/eos_idealplusrad.f90 | 2 +- src/main/eos_mesa.f90 | 2 +- src/main/eos_mesa_microphysics.f90 | 2 +- src/main/eos_piecewise.f90 | 2 +- src/main/eos_shen.f90 | 2 +- src/main/eos_stamatellos.f90 | 4 ++-- src/main/eos_stratified.f90 | 2 +- src/main/evolve.F90 | 2 +- src/main/evwrite.f90 | 2 +- src/main/extern_Bfield.f90 | 2 +- src/main/extern_binary.f90 | 2 +- src/main/extern_binary_gw.f90 | 2 +- src/main/extern_corotate.f90 | 2 +- src/main/extern_densprofile.f90 | 2 +- src/main/extern_geopot.f90 | 2 +- src/main/extern_gnewton.f90 | 2 +- src/main/extern_gr.f90 | 2 +- src/main/extern_gwinspiral.f90 | 2 +- src/main/extern_lensethirring.f90 | 2 +- src/main/extern_prdrag.f90 | 2 +- src/main/extern_spiral.f90 | 2 +- src/main/extern_staticsine.f90 | 2 +- src/main/externalforces.f90 | 2 +- src/main/externalforces_gr.f90 | 2 +- src/main/fastmath.f90 | 2 +- src/main/force.F90 | 2 +- src/main/forcing.F90 | 2 +- src/main/fs_data.f90 | 2 +- src/main/geometry.f90 | 2 +- src/main/gitinfo.f90 | 2 +- src/main/growth.f90 | 2 +- src/main/growth_smol.f90 | 2 +- src/main/h2chem.f90 | 2 +- src/main/initial.F90 | 2 +- src/main/inject_BHL.f90 | 2 +- src/main/inject_bondi.f90 | 2 +- src/main/inject_firehose.f90 | 2 +- src/main/inject_galcen_winds.f90 | 2 +- src/main/inject_keplerian.f90 | 2 +- src/main/inject_keplerianshear.f90 | 2 +- src/main/inject_randomwind.f90 | 2 +- src/main/inject_rochelobe.f90 | 2 +- src/main/inject_sim.f90 | 2 +- src/main/inject_sne.f90 | 2 +- src/main/inject_steadydisc.f90 | 2 +- src/main/inject_unifwind.f90 | 2 +- src/main/inject_wind.f90 | 2 +- src/main/inject_windtunnel.f90 | 3 +-- src/main/interp_metric.f90 | 2 +- src/main/inverse4x4.f90 | 2 +- src/main/io.F90 | 2 +- src/main/ionization.f90 | 2 +- src/main/kdtree.F90 | 2 +- src/main/kernel_WendlandC2.f90 | 2 +- src/main/kernel_WendlandC4.f90 | 2 +- src/main/kernel_WendlandC6.f90 | 2 +- src/main/kernel_cubic.f90 | 2 +- src/main/kernel_quartic.f90 | 2 +- src/main/kernel_quintic.f90 | 2 +- src/main/krome.f90 | 2 +- src/main/linklist_kdtree.F90 | 2 +- src/main/memory.f90 | 2 +- src/main/metric_et.f90 | 2 +- src/main/metric_et_utils.f90 | 2 +- src/main/metric_flrw.f90 | 2 +- src/main/metric_kerr-schild.f90 | 2 +- src/main/metric_kerr.f90 | 2 +- src/main/metric_minkowski.f90 | 2 +- src/main/metric_schwarzschild.f90 | 2 +- src/main/metric_tools.f90 | 2 +- src/main/mf_write.f90 | 2 +- src/main/mol_data.f90 | 2 +- src/main/mpi_balance.F90 | 2 +- src/main/mpi_dens.F90 | 2 +- src/main/mpi_derivs.F90 | 2 +- src/main/mpi_domain.F90 | 2 +- src/main/mpi_force.F90 | 2 +- src/main/mpi_memory.f90 | 2 +- src/main/mpi_tree.F90 | 2 +- src/main/mpi_utils.F90 | 2 +- src/main/nicil_supplement.f90 | 2 +- src/main/options.f90 | 2 +- src/main/part.F90 | 2 +- src/main/partinject.F90 | 2 +- src/main/phantom.f90 | 2 +- src/main/physcon.f90 | 2 +- src/main/porosity.f90 | 2 +- src/main/ptmass.F90 | 2 +- src/main/ptmass_heating.f90 | 2 +- src/main/ptmass_radiation.f90 | 2 +- src/main/quitdump.f90 | 2 +- src/main/radiation_implicit.f90 | 2 +- src/main/radiation_utils.f90 | 2 +- src/main/random.f90 | 2 +- src/main/readwrite_dumps.F90 | 2 +- src/main/readwrite_dumps_common.f90 | 2 +- src/main/readwrite_dumps_fortran.f90 | 6 +++++- src/main/readwrite_dumps_hdf5.F90 | 2 +- src/main/readwrite_infile.F90 | 2 +- src/main/relaxem.f90 | 2 +- src/main/sort_particles.f90 | 2 +- src/main/step_leapfrog.F90 | 8 ++++---- src/main/step_supertimestep.F90 | 2 +- src/main/subgroup.f90 | 2 +- src/main/substepping.F90 | 2 +- src/main/timestep.f90 | 2 +- src/main/tmunu2grid.f90 | 2 +- src/main/units.f90 | 2 +- src/main/utils_allocate.f90 | 2 +- src/main/utils_binary.f90 | 2 +- src/main/utils_cpuinfo.f90 | 2 +- src/main/utils_datafiles.f90 | 2 +- src/main/utils_deriv.f90 | 2 +- src/main/utils_dumpfiles.f90 | 2 +- src/main/utils_dumpfiles_hdf5.f90 | 2 +- src/main/utils_filenames.f90 | 2 +- src/main/utils_gr.f90 | 2 +- src/main/utils_hdf5.f90 | 2 +- src/main/utils_healpix.f90 | 4 ++-- src/main/utils_implicit.f90 | 2 +- src/main/utils_indtimesteps.F90 | 2 +- src/main/utils_infiles.f90 | 2 +- src/main/utils_inject.f90 | 2 +- src/main/utils_kepler.f90 | 2 +- src/main/utils_mathfunc.f90 | 2 +- src/main/utils_omp.F90 | 2 +- src/main/utils_raytracer.f90 | 4 ++-- src/main/utils_shuffleparticles.F90 | 2 +- src/main/utils_sort.f90 | 2 +- src/main/utils_sphNG.f90 | 2 +- src/main/utils_spline.f90 | 2 +- src/main/utils_subgroup.f90 | 2 +- src/main/utils_summary.F90 | 2 +- src/main/utils_supertimestep.F90 | 2 +- src/main/utils_system.f90 | 2 +- src/main/utils_tables.f90 | 2 +- src/main/utils_timing.f90 | 2 +- src/main/utils_vectors.f90 | 2 +- src/main/viscosity.f90 | 2 +- src/main/wind.F90 | 2 +- src/main/wind_equations.f90 | 2 +- src/main/writeheader.F90 | 2 +- src/setup/density_profiles.f90 | 2 +- src/setup/libsetup.f90 | 2 +- src/setup/phantomsetup.F90 | 2 +- src/setup/readwrite_kepler.f90 | 2 +- src/setup/readwrite_mesa.f90 | 2 +- src/setup/relax_star.f90 | 2 +- src/setup/set_Bfield.f90 | 2 +- src/setup/set_binary.f90 | 2 +- src/setup/set_cubic_core.f90 | 2 +- src/setup/set_disc.F90 | 2 +- src/setup/set_dust.f90 | 2 +- src/setup/set_dust_options.f90 | 2 +- src/setup/set_fixedentropycore.f90 | 2 +- src/setup/set_flyby.f90 | 2 +- src/setup/set_hierarchical.f90 | 2 +- src/setup/set_hierarchical_utils.f90 | 2 +- src/setup/set_orbit.f90 | 2 +- src/setup/set_planets.f90 | 2 +- src/setup/set_shock.f90 | 2 +- src/setup/set_slab.f90 | 2 +- src/setup/set_softened_core.f90 | 2 +- src/setup/set_sphere.f90 | 2 +- src/setup/set_star.f90 | 2 +- src/setup/set_star_utils.f90 | 2 +- src/setup/set_unifdis.f90 | 2 +- src/setup/set_units.f90 | 2 +- src/setup/set_vfield.f90 | 2 +- src/setup/setup_BHL.f90 | 2 +- src/setup/setup_alfvenwave.f90 | 2 +- src/setup/setup_asteroidwind.f90 | 2 +- src/setup/setup_binary.f90 | 2 +- src/setup/setup_blob.f90 | 2 +- src/setup/setup_bondi.f90 | 2 +- src/setup/setup_bondiinject.f90 | 2 +- src/setup/setup_chinchen.f90 | 2 +- src/setup/setup_cluster.f90 | 2 +- src/setup/setup_collidingclouds.f90 | 2 +- src/setup/setup_common.f90 | 2 +- src/setup/setup_disc.f90 | 15 ++++++++------- src/setup/setup_dustsettle.f90 | 2 +- src/setup/setup_dustybox.f90 | 2 +- src/setup/setup_dustysedov.f90 | 2 +- src/setup/setup_empty.f90 | 2 +- src/setup/setup_firehose.f90 | 2 +- src/setup/setup_flrw.f90 | 2 +- src/setup/setup_flrwpspec.f90 | 2 +- src/setup/setup_galaxies.f90 | 2 +- src/setup/setup_galcen_stars.f90 | 2 +- src/setup/setup_galdisc.f90 | 2 +- src/setup/setup_grdisc.F90 | 2 +- src/setup/setup_grtde.f90 | 2 +- src/setup/setup_gwdisc.f90 | 2 +- src/setup/setup_hierarchical.f90 | 2 +- src/setup/setup_jadvect.f90 | 2 +- src/setup/setup_kh.f90 | 2 +- src/setup/setup_masstransfer.f90 | 2 +- src/setup/setup_mhdblast.f90 | 2 +- src/setup/setup_mhdrotor.f90 | 2 +- src/setup/setup_mhdsine.f90 | 2 +- src/setup/setup_mhdvortex.f90 | 2 +- src/setup/setup_mhdwave.f90 | 2 +- src/setup/setup_nsdisc.f90 | 2 +- src/setup/setup_orstang.f90 | 2 +- src/setup/setup_params.f90 | 2 +- src/setup/setup_planetdisc.f90 | 2 +- src/setup/setup_prtest.f90 | 2 +- src/setup/setup_quebec.f90 | 2 +- src/setup/setup_radiativebox.f90 | 2 +- src/setup/setup_sedov.f90 | 2 +- src/setup/setup_shock.f90 | 2 +- src/setup/setup_solarsystem.f90 | 2 +- src/setup/setup_sphereinbox.f90 | 2 +- src/setup/setup_srblast.f90 | 2 +- src/setup/setup_srpolytrope.f90 | 2 +- src/setup/setup_star.f90 | 2 +- src/setup/setup_starcluster.f90 | 2 +- src/setup/setup_taylorgreen.f90 | 2 +- src/setup/setup_testparticles.f90 | 2 +- src/setup/setup_tokamak.f90 | 2 +- src/setup/setup_torus.f90 | 2 +- src/setup/setup_turb.f90 | 2 +- src/setup/setup_unifdis.f90 | 2 +- src/setup/setup_wave.f90 | 2 +- src/setup/setup_wavedamp.f90 | 2 +- src/setup/setup_wddisc.f90 | 2 +- src/setup/setup_wind.f90 | 2 +- src/setup/setup_windtunnel.f90 | 8 ++++---- src/setup/stretchmap.f90 | 2 +- src/setup/velfield_fromcubes.f90 | 2 +- src/tests/directsum.f90 | 2 +- src/tests/phantomtest.f90 | 2 +- src/tests/test_apr.f90 | 2 +- src/tests/test_cooling.f90 | 2 +- src/tests/test_corotate.f90 | 2 +- src/tests/test_damping.f90 | 2 +- src/tests/test_derivs.F90 | 2 +- src/tests/test_dust.f90 | 2 +- src/tests/test_eos.f90 | 2 +- src/tests/test_eos_stratified.f90 | 2 +- src/tests/test_externf.f90 | 2 +- src/tests/test_externf_gr.f90 | 2 +- src/tests/test_fastmath.f90 | 2 +- src/tests/test_geometry.f90 | 2 +- src/tests/test_gnewton.f90 | 2 +- src/tests/test_gr.f90 | 2 +- src/tests/test_gravity.f90 | 2 +- src/tests/test_growth.f90 | 2 +- src/tests/test_hierarchical.f90 | 2 +- src/tests/test_indtstep.F90 | 2 +- src/tests/test_iorig.f90 | 2 +- src/tests/test_kdtree.F90 | 2 +- src/tests/test_kernel.f90 | 2 +- src/tests/test_link.F90 | 2 +- src/tests/test_luminosity.F90 | 2 +- src/tests/test_mpi.f90 | 2 +- src/tests/test_nonidealmhd.F90 | 2 +- src/tests/test_part.f90 | 2 +- src/tests/test_poly.f90 | 2 +- src/tests/test_ptmass.f90 | 2 +- src/tests/test_radiation.f90 | 2 +- src/tests/test_rwdump.F90 | 2 +- src/tests/test_sedov.F90 | 2 +- src/tests/test_setdisc.f90 | 2 +- src/tests/test_setstar.f90 | 2 +- src/tests/test_smol.F90 | 2 +- src/tests/test_step.F90 | 2 +- src/tests/test_wind.f90 | 2 +- src/tests/testsuite.F90 | 2 +- src/tests/utils_testsuite.f90 | 2 +- src/utils/acc2ang.f90 | 2 +- src/utils/adaptivemesh.f90 | 2 +- src/utils/analysis_1particle.f90 | 2 +- src/utils/analysis_BRhoOrientation.F90 | 2 +- src/utils/analysis_CoM.f90 | 2 +- src/utils/analysis_GalMerger.f90 | 2 +- src/utils/analysis_MWpdf.f90 | 2 +- src/utils/analysis_NSmerger.f90 | 2 +- src/utils/analysis_alpha.f90 | 2 +- src/utils/analysis_angmom.f90 | 2 +- src/utils/analysis_angmomvec.f90 | 2 +- src/utils/analysis_average_orb_en.f90 | 2 +- src/utils/analysis_binarydisc.f90 | 2 +- src/utils/analysis_bzrms.f90 | 2 +- src/utils/analysis_clumpfind.F90 | 2 +- src/utils/analysis_clumpfindWB23.F90 | 2 +- src/utils/analysis_collidingcloudevolution.f90 | 2 +- src/utils/analysis_collidingcloudhistograms.f90 | 2 +- src/utils/analysis_common_envelope.f90 | 9 +++++---- src/utils/analysis_cooling.f90 | 2 +- src/utils/analysis_disc.f90 | 2 +- src/utils/analysis_disc_MFlow.f90 | 2 +- src/utils/analysis_disc_eccentric.f90 | 2 +- src/utils/analysis_disc_mag.f90 | 2 +- src/utils/analysis_disc_planet.f90 | 2 +- src/utils/analysis_disc_stresses.f90 | 6 +++--- src/utils/analysis_dtheader.f90 | 2 +- src/utils/analysis_dustformation.f90 | 2 +- src/utils/analysis_dustmass.f90 | 2 +- src/utils/analysis_dustydisc.f90 | 2 +- src/utils/analysis_dustywind.f90 | 2 +- src/utils/analysis_energies.f90 | 2 +- src/utils/analysis_etotgr.f90 | 2 +- src/utils/analysis_getneighbours.f90 | 2 +- src/utils/analysis_gws.f90 | 2 +- src/utils/analysis_jet.f90 | 2 +- src/utils/analysis_kdtree.F90 | 2 +- src/utils/analysis_kepler.f90 | 2 +- src/utils/analysis_macctrace.f90 | 2 +- src/utils/analysis_mapping_mass.f90 | 2 +- src/utils/analysis_mcfost.f90 | 2 +- src/utils/analysis_mcfostcmdline.f90 | 2 +- src/utils/analysis_pairing.f90 | 2 +- src/utils/analysis_particle.f90 | 2 +- src/utils/analysis_pdfs.f90 | 2 +- src/utils/analysis_phantom_dump.f90 | 2 +- src/utils/analysis_polytropes.f90 | 2 +- src/utils/analysis_prdrag.f90 | 2 +- src/utils/analysis_protostar_environ.F90 | 2 +- src/utils/analysis_ptmass.f90 | 2 +- src/utils/analysis_radiotde.f90 | 2 +- src/utils/analysis_raytracer.f90 | 4 ++-- src/utils/analysis_sinkmass.f90 | 2 +- src/utils/analysis_sphere.f90 | 2 +- src/utils/analysis_structurefn.f90 | 2 +- src/utils/analysis_tde.f90 | 2 +- src/utils/analysis_tdeoutflow.f90 | 2 +- src/utils/analysis_torus.f90 | 2 +- src/utils/analysis_trackbox.f90 | 2 +- src/utils/analysis_tracks.f90 | 2 +- .../analysis_velocitydispersion_vs_scale.f90 | 2 +- src/utils/analysis_velocityshear.f90 | 2 +- src/utils/analysis_write_kdtree.F90 | 2 +- src/utils/combinedustdumps.f90 | 2 +- src/utils/cubicsolve.f90 | 2 +- src/utils/diffdumps.f90 | 2 +- src/utils/dustywaves.f90 | 2 +- src/utils/einsteintk_utils.f90 | 2 +- src/utils/einsteintk_wrapper.f90 | 2 +- src/utils/ev2kdot.f90 | 2 +- src/utils/ev2mdot.f90 | 2 +- src/utils/evol_dustywaves.f90 | 2 +- src/utils/get_struct_slope.f90 | 2 +- src/utils/getmathflags.f90 | 2 +- src/utils/grid2pdf.f90 | 2 +- src/utils/hdf5utils.f90 | 2 +- src/utils/icosahedron.f90 | 2 +- src/utils/interpolate3D.f90 | 2 +- src/utils/interpolate3D_amr.F90 | 2 +- src/utils/io_grid.f90 | 2 +- src/utils/io_structurefn.f90 | 2 +- src/utils/leastsquares.f90 | 2 +- src/utils/libphantom-splash.f90 | 2 +- src/utils/lombperiod.f90 | 2 +- src/utils/mflow.f90 | 2 +- src/utils/moddump_CoM.f90 | 2 +- src/utils/moddump_LTE_to_rad.f90 | 2 +- src/utils/moddump_addflyby.f90 | 2 +- src/utils/moddump_addplanets.f90 | 2 +- src/utils/moddump_binary.f90 | 2 +- src/utils/moddump_binarystar.f90 | 2 +- src/utils/moddump_changemass.f90 | 2 +- src/utils/moddump_default.f90 | 2 +- src/utils/moddump_disc.f90 | 2 +- src/utils/moddump_dustadd.f90 | 2 +- src/utils/moddump_extenddisc.f90 | 2 +- src/utils/moddump_growthtomultigrain.f90 | 2 +- src/utils/moddump_mergepart.f90 | 2 +- src/utils/moddump_messupSPH.f90 | 2 +- src/utils/moddump_perturbgas.f90 | 2 +- src/utils/moddump_polytrope.f90 | 2 +- src/utils/moddump_rad_to_LTE.f90 | 2 +- src/utils/moddump_radiotde.f90 | 2 +- src/utils/moddump_recalcuT.f90 | 2 +- src/utils/moddump_removeparticles_cylinder.f90 | 2 +- src/utils/moddump_removeparticles_radius.f90 | 2 +- src/utils/moddump_rotate.f90 | 2 +- src/utils/moddump_sink.f90 | 2 +- src/utils/moddump_sinkbinary.f90 | 2 +- src/utils/moddump_sphNG2phantom.f90 | 2 +- src/utils/moddump_sphNG2phantom_addBfield.f90 | 2 +- src/utils/moddump_sphNG2phantom_disc.f90 | 2 +- src/utils/moddump_splitpart.f90 | 2 +- src/utils/moddump_taylorgreen.f90 | 2 +- src/utils/moddump_tidal.f90 | 2 +- src/utils/moddump_torus.f90 | 2 +- src/utils/multirun.f90 | 2 +- src/utils/multirun_mach.f90 | 2 +- src/utils/pdfs.f90 | 2 +- src/utils/phantom2divb.f90 | 2 +- src/utils/phantom2divv.f90 | 2 +- src/utils/phantom2gadget.f90 | 2 +- src/utils/phantom2hdf5.f90 | 2 +- src/utils/phantom2sphNG.f90 | 2 +- src/utils/phantom_moddump.f90 | 2 +- src/utils/phantomanalysis.f90 | 2 +- src/utils/phantomevcompare.f90 | 2 +- src/utils/phantomextractsinks.f90 | 2 +- src/utils/plot_kernel.f90 | 2 +- src/utils/powerspectrums.f90 | 2 +- src/utils/prompting.f90 | 2 +- src/utils/quartic.f90 | 2 +- src/utils/rhomach.f90 | 2 +- src/utils/showarrays.f90 | 2 +- src/utils/showheader.f90 | 2 +- src/utils/solvelinearsystem.f90 | 2 +- src/utils/splitpart.f90 | 2 +- src/utils/struct2struct.f90 | 2 +- src/utils/struct_part.f90 | 2 +- src/utils/tabulate_metric.f90 | 2 +- src/utils/test_binary.f90 | 2 +- src/utils/testbinary.f90 | 2 +- src/utils/utils_disc.f90 | 2 +- src/utils/utils_ephemeris.f90 | 2 +- src/utils/utils_evfiles.f90 | 2 +- src/utils/utils_getneighbours.F90 | 2 +- src/utils/utils_gravwave.f90 | 2 +- src/utils/utils_linalg.f90 | 2 +- src/utils/utils_mpc.f90 | 2 +- src/utils/utils_orbits.f90 | 2 +- src/utils/utils_raytracer_all.f90 | 2 +- src/utils/utils_splitmerge.f90 | 2 +- src/utils/velfield.f90 | 2 +- 461 files changed, 490 insertions(+), 485 deletions(-) diff --git a/src/main/H2regions.f90 b/src/main/H2regions.f90 index 06c762819..b0d0096c9 100644 --- a/src/main/H2regions.f90 +++ b/src/main/H2regions.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/apr.f90 b/src/main/apr.f90 index b645ade72..43a7a2b5f 100644 --- a/src/main/apr.f90 +++ b/src/main/apr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/apr_region.f90 b/src/main/apr_region.f90 index 947ce0464..e802ad6ad 100644 --- a/src/main/apr_region.f90 +++ b/src/main/apr_region.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/bondiexact.f90 b/src/main/bondiexact.f90 index e39ddd970..032fd394b 100644 --- a/src/main/bondiexact.f90 +++ b/src/main/bondiexact.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/bondiexact_gr.f90 b/src/main/bondiexact_gr.f90 index 869fc061a..e25a3a844 100644 --- a/src/main/bondiexact_gr.f90 +++ b/src/main/bondiexact_gr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/boundary.f90 b/src/main/boundary.f90 index 08bb0fd34..b28a99d6a 100644 --- a/src/main/boundary.f90 +++ b/src/main/boundary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/boundary_dynamic.f90 b/src/main/boundary_dynamic.f90 index 88642a872..04d44a1f6 100644 --- a/src/main/boundary_dynamic.f90 +++ b/src/main/boundary_dynamic.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/centreofmass.f90 b/src/main/centreofmass.f90 index 20e905ed0..9104dd36f 100644 --- a/src/main/centreofmass.f90 +++ b/src/main/centreofmass.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/checkconserved.f90 b/src/main/checkconserved.f90 index 4def126fc..f49d065e2 100644 --- a/src/main/checkconserved.f90 +++ b/src/main/checkconserved.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/checkoptions.F90 b/src/main/checkoptions.F90 index d230f40bf..ae69bf5ec 100644 --- a/src/main/checkoptions.F90 +++ b/src/main/checkoptions.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/checksetup.f90 b/src/main/checksetup.f90 index b7bcc4e3b..50e0bc3f0 100644 --- a/src/main/checksetup.f90 +++ b/src/main/checksetup.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/config.F90 b/src/main/config.F90 index 1238e1ea6..11b2924f0 100644 --- a/src/main/config.F90 +++ b/src/main/config.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cons2prim.f90 b/src/main/cons2prim.f90 index 700734b1f..a7e04ed1a 100644 --- a/src/main/cons2prim.f90 +++ b/src/main/cons2prim.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cons2primsolver.f90 b/src/main/cons2primsolver.f90 index 10e81529d..701983c73 100644 --- a/src/main/cons2primsolver.f90 +++ b/src/main/cons2primsolver.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling.f90 b/src/main/cooling.f90 index f467f03a4..f3b0c20f5 100644 --- a/src/main/cooling.f90 +++ b/src/main/cooling.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -29,8 +29,8 @@ module cooling ! ! :Dependencies: chem, cooling_gammie, cooling_gammie_PL, cooling_ism, ! cooling_koyamainutsuka, cooling_molecular, cooling_radapprox, -! cooling_solver, dim, eos, eos_stamatellos, infile_utils, io, options, -! part, physcon, timestep, units, viscosity +! cooling_solver, dim, eos, infile_utils, io, options, part, physcon, +! timestep, units, viscosity ! use options, only:icooling diff --git a/src/main/cooling_functions.f90 b/src/main/cooling_functions.f90 index 229afeaef..c1184e860 100644 --- a/src/main/cooling_functions.f90 +++ b/src/main/cooling_functions.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling_gammie.f90 b/src/main/cooling_gammie.f90 index 3fffe3565..0a5b983de 100644 --- a/src/main/cooling_gammie.f90 +++ b/src/main/cooling_gammie.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling_gammie_PL.f90 b/src/main/cooling_gammie_PL.f90 index 15ae40733..3832bd30b 100644 --- a/src/main/cooling_gammie_PL.f90 +++ b/src/main/cooling_gammie_PL.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling_ism.f90 b/src/main/cooling_ism.f90 index 60d574c75..8c0b6d6da 100644 --- a/src/main/cooling_ism.f90 +++ b/src/main/cooling_ism.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling_koyamainutsuka.f90 b/src/main/cooling_koyamainutsuka.f90 index 2548d180c..91436b40f 100644 --- a/src/main/cooling_koyamainutsuka.f90 +++ b/src/main/cooling_koyamainutsuka.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling_molecular.f90 b/src/main/cooling_molecular.f90 index e953a3175..26dc4f322 100644 --- a/src/main/cooling_molecular.f90 +++ b/src/main/cooling_molecular.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling_radapprox.f90 b/src/main/cooling_radapprox.f90 index 60fe48c13..0f7734b33 100644 --- a/src/main/cooling_radapprox.f90 +++ b/src/main/cooling_radapprox.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cooling_solver.f90 b/src/main/cooling_solver.f90 index 9203b4aae..d3892c8ac 100644 --- a/src/main/cooling_solver.f90 +++ b/src/main/cooling_solver.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/cullendehnen.f90 b/src/main/cullendehnen.f90 index b8c5d2946..42cce4c5d 100644 --- a/src/main/cullendehnen.f90 +++ b/src/main/cullendehnen.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/damping.f90 b/src/main/damping.f90 index d7c83f925..83b552436 100644 --- a/src/main/damping.f90 +++ b/src/main/damping.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/datafiles.f90 b/src/main/datafiles.f90 index f41a85938..82266c041 100644 --- a/src/main/datafiles.f90 +++ b/src/main/datafiles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/dens.F90 b/src/main/dens.F90 index 35984339f..a0e14c64a 100644 --- a/src/main/dens.F90 +++ b/src/main/dens.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/deriv.F90 b/src/main/deriv.F90 index cd7149405..59b3740e4 100644 --- a/src/main/deriv.F90 +++ b/src/main/deriv.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/dtype_kdtree.F90 b/src/main/dtype_kdtree.F90 index fcb1a04f5..9312269b1 100644 --- a/src/main/dtype_kdtree.F90 +++ b/src/main/dtype_kdtree.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/dust.f90 b/src/main/dust.f90 index 8270c5ea9..53973ebb5 100644 --- a/src/main/dust.f90 +++ b/src/main/dust.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/dust_formation.f90 b/src/main/dust_formation.f90 index f32754011..c581209d7 100644 --- a/src/main/dust_formation.f90 +++ b/src/main/dust_formation.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/energies.F90 b/src/main/energies.F90 index acea5414a..0afe7fb6a 100644 --- a/src/main/energies.F90 +++ b/src/main/energies.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos.f90 b/src/main/eos.f90 index 7606c7110..c0a82fb4b 100644 --- a/src/main/eos.f90 +++ b/src/main/eos.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_HIIR.f90 b/src/main/eos_HIIR.f90 index a0ec8b61c..128c1f57a 100644 --- a/src/main/eos_HIIR.f90 +++ b/src/main/eos_HIIR.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_barotropic.f90 b/src/main/eos_barotropic.f90 index 93f32e64c..461785a6f 100644 --- a/src/main/eos_barotropic.f90 +++ b/src/main/eos_barotropic.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_gasradrec.f90 b/src/main/eos_gasradrec.f90 index 831a9302e..d36e8ef9f 100644 --- a/src/main/eos_gasradrec.f90 +++ b/src/main/eos_gasradrec.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_helmholtz.f90 b/src/main/eos_helmholtz.f90 index 882967eba..97b90a2c3 100644 --- a/src/main/eos_helmholtz.f90 +++ b/src/main/eos_helmholtz.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_idealplusrad.f90 b/src/main/eos_idealplusrad.f90 index 72ecc22db..1b7e302bc 100644 --- a/src/main/eos_idealplusrad.f90 +++ b/src/main/eos_idealplusrad.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_mesa.f90 b/src/main/eos_mesa.f90 index 216f04deb..d562107fe 100644 --- a/src/main/eos_mesa.f90 +++ b/src/main/eos_mesa.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_mesa_microphysics.f90 b/src/main/eos_mesa_microphysics.f90 index 903fef912..f12d50290 100644 --- a/src/main/eos_mesa_microphysics.f90 +++ b/src/main/eos_mesa_microphysics.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_piecewise.f90 b/src/main/eos_piecewise.f90 index 8462e4bcf..8797dc8eb 100644 --- a/src/main/eos_piecewise.f90 +++ b/src/main/eos_piecewise.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_shen.f90 b/src/main/eos_shen.f90 index 7c2548677..30d7a10df 100644 --- a/src/main/eos_shen.f90 +++ b/src/main/eos_shen.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/eos_stamatellos.f90 b/src/main/eos_stamatellos.f90 index 9c583c327..297d86e92 100644 --- a/src/main/eos_stamatellos.f90 +++ b/src/main/eos_stamatellos.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -14,7 +14,7 @@ module eos_stamatellos ! ! :Runtime parameters: None ! -! :Dependencies: datafiles, io, part +! :Dependencies: allocutils, datafiles, dim, io ! implicit none diff --git a/src/main/eos_stratified.f90 b/src/main/eos_stratified.f90 index 37f9bcd14..ed1e556c8 100644 --- a/src/main/eos_stratified.f90 +++ b/src/main/eos_stratified.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/evolve.F90 b/src/main/evolve.F90 index b899b6d5a..c7bee8645 100644 --- a/src/main/evolve.F90 +++ b/src/main/evolve.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/evwrite.f90 b/src/main/evwrite.f90 index 8c8e5b76f..6014ead89 100644 --- a/src/main/evwrite.f90 +++ b/src/main/evwrite.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_Bfield.f90 b/src/main/extern_Bfield.f90 index 1b4319e70..7314b7364 100644 --- a/src/main/extern_Bfield.f90 +++ b/src/main/extern_Bfield.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_binary.f90 b/src/main/extern_binary.f90 index 1602453fc..c14f4cabb 100644 --- a/src/main/extern_binary.f90 +++ b/src/main/extern_binary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_binary_gw.f90 b/src/main/extern_binary_gw.f90 index db906d239..a1638d00f 100644 --- a/src/main/extern_binary_gw.f90 +++ b/src/main/extern_binary_gw.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_corotate.f90 b/src/main/extern_corotate.f90 index e8d9bfff8..0d7165966 100644 --- a/src/main/extern_corotate.f90 +++ b/src/main/extern_corotate.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_densprofile.f90 b/src/main/extern_densprofile.f90 index c106668f8..f203ddd37 100644 --- a/src/main/extern_densprofile.f90 +++ b/src/main/extern_densprofile.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_geopot.f90 b/src/main/extern_geopot.f90 index f56ecb54a..6188bb3ec 100644 --- a/src/main/extern_geopot.f90 +++ b/src/main/extern_geopot.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_gnewton.f90 b/src/main/extern_gnewton.f90 index 8d60fe62e..54cf20862 100644 --- a/src/main/extern_gnewton.f90 +++ b/src/main/extern_gnewton.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_gr.f90 b/src/main/extern_gr.f90 index 7043299e2..04f5ca1bf 100644 --- a/src/main/extern_gr.f90 +++ b/src/main/extern_gr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_gwinspiral.f90 b/src/main/extern_gwinspiral.f90 index 460cb5c3b..3cbe98ba8 100644 --- a/src/main/extern_gwinspiral.f90 +++ b/src/main/extern_gwinspiral.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_lensethirring.f90 b/src/main/extern_lensethirring.f90 index e1f318e46..3c71db58a 100644 --- a/src/main/extern_lensethirring.f90 +++ b/src/main/extern_lensethirring.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_prdrag.f90 b/src/main/extern_prdrag.f90 index da3f311ff..4e068b85d 100644 --- a/src/main/extern_prdrag.f90 +++ b/src/main/extern_prdrag.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_spiral.f90 b/src/main/extern_spiral.f90 index f27a06d9f..3b787f06d 100644 --- a/src/main/extern_spiral.f90 +++ b/src/main/extern_spiral.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/extern_staticsine.f90 b/src/main/extern_staticsine.f90 index 8d71b1c14..1eb65eceb 100644 --- a/src/main/extern_staticsine.f90 +++ b/src/main/extern_staticsine.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/externalforces.f90 b/src/main/externalforces.f90 index aa5aad3ba..d8decef4f 100644 --- a/src/main/externalforces.f90 +++ b/src/main/externalforces.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/externalforces_gr.f90 b/src/main/externalforces_gr.f90 index 4219f96ae..d98c843bc 100644 --- a/src/main/externalforces_gr.f90 +++ b/src/main/externalforces_gr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/fastmath.f90 b/src/main/fastmath.f90 index 59bb2a052..2bb053879 100644 --- a/src/main/fastmath.f90 +++ b/src/main/fastmath.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/force.F90 b/src/main/force.F90 index 2172ba966..209f62f2c 100644 --- a/src/main/force.F90 +++ b/src/main/force.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/forcing.F90 b/src/main/forcing.F90 index a0db37a7a..fd1348ee2 100644 --- a/src/main/forcing.F90 +++ b/src/main/forcing.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/fs_data.f90 b/src/main/fs_data.f90 index 2e5c0718f..784df1d71 100644 --- a/src/main/fs_data.f90 +++ b/src/main/fs_data.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/geometry.f90 b/src/main/geometry.f90 index d90782a91..5502bdb50 100644 --- a/src/main/geometry.f90 +++ b/src/main/geometry.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/gitinfo.f90 b/src/main/gitinfo.f90 index 8ea06264e..e77601eda 100644 --- a/src/main/gitinfo.f90 +++ b/src/main/gitinfo.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/growth.f90 b/src/main/growth.f90 index a2d35aec7..4c8c46d3c 100644 --- a/src/main/growth.f90 +++ b/src/main/growth.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/growth_smol.f90 b/src/main/growth_smol.f90 index 0a818364f..c1a88b3f4 100644 --- a/src/main/growth_smol.f90 +++ b/src/main/growth_smol.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/h2chem.f90 b/src/main/h2chem.f90 index a79faa951..38f7580c2 100644 --- a/src/main/h2chem.f90 +++ b/src/main/h2chem.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/initial.F90 b/src/main/initial.F90 index 67b480e15..9c638fa74 100644 --- a/src/main/initial.F90 +++ b/src/main/initial.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_BHL.f90 b/src/main/inject_BHL.f90 index ae41283de..37bde82e0 100644 --- a/src/main/inject_BHL.f90 +++ b/src/main/inject_BHL.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_bondi.f90 b/src/main/inject_bondi.f90 index 1c2fc22bc..e23e24f0b 100644 --- a/src/main/inject_bondi.f90 +++ b/src/main/inject_bondi.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_firehose.f90 b/src/main/inject_firehose.f90 index cf1e5bfb0..de0e176f6 100644 --- a/src/main/inject_firehose.f90 +++ b/src/main/inject_firehose.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_galcen_winds.f90 b/src/main/inject_galcen_winds.f90 index d52baaf8a..c6e588617 100644 --- a/src/main/inject_galcen_winds.f90 +++ b/src/main/inject_galcen_winds.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_keplerian.f90 b/src/main/inject_keplerian.f90 index 45376c6ba..45617faf4 100644 --- a/src/main/inject_keplerian.f90 +++ b/src/main/inject_keplerian.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_keplerianshear.f90 b/src/main/inject_keplerianshear.f90 index 773fc7d72..56321d07d 100644 --- a/src/main/inject_keplerianshear.f90 +++ b/src/main/inject_keplerianshear.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_randomwind.f90 b/src/main/inject_randomwind.f90 index cb8abf630..f7e55be2a 100644 --- a/src/main/inject_randomwind.f90 +++ b/src/main/inject_randomwind.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_rochelobe.f90 b/src/main/inject_rochelobe.f90 index ab2861afe..75f27b783 100644 --- a/src/main/inject_rochelobe.f90 +++ b/src/main/inject_rochelobe.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_sim.f90 b/src/main/inject_sim.f90 index 127d1805d..35f14e6ae 100644 --- a/src/main/inject_sim.f90 +++ b/src/main/inject_sim.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_sne.f90 b/src/main/inject_sne.f90 index 867ad2b88..c97a17c15 100644 --- a/src/main/inject_sne.f90 +++ b/src/main/inject_sne.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_steadydisc.f90 b/src/main/inject_steadydisc.f90 index d7071af77..6ad32175c 100644 --- a/src/main/inject_steadydisc.f90 +++ b/src/main/inject_steadydisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_unifwind.f90 b/src/main/inject_unifwind.f90 index 80f203a63..13fd8e897 100644 --- a/src/main/inject_unifwind.f90 +++ b/src/main/inject_unifwind.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_wind.f90 b/src/main/inject_wind.f90 index ed7597fcf..378e6df8a 100644 --- a/src/main/inject_wind.f90 +++ b/src/main/inject_wind.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inject_windtunnel.f90 b/src/main/inject_windtunnel.f90 index daa6537d1..f45131e06 100644 --- a/src/main/inject_windtunnel.f90 +++ b/src/main/inject_windtunnel.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -19,7 +19,6 @@ module inject ! - 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)* ! - rho_inf : *ambient density (code units)* ! - v_inf : *wind speed (code units)* diff --git a/src/main/interp_metric.f90 b/src/main/interp_metric.f90 index a6037037d..e22c1a07a 100644 --- a/src/main/interp_metric.f90 +++ b/src/main/interp_metric.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/inverse4x4.f90 b/src/main/inverse4x4.f90 index 2107fae70..39fd24554 100644 --- a/src/main/inverse4x4.f90 +++ b/src/main/inverse4x4.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/io.F90 b/src/main/io.F90 index 97e2bb204..0f336c3ca 100644 --- a/src/main/io.F90 +++ b/src/main/io.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/ionization.f90 b/src/main/ionization.f90 index 7141b2d2f..5e22c1b14 100644 --- a/src/main/ionization.f90 +++ b/src/main/ionization.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/kdtree.F90 b/src/main/kdtree.F90 index 54d88049b..7b3a60314 100644 --- a/src/main/kdtree.F90 +++ b/src/main/kdtree.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/kernel_WendlandC2.f90 b/src/main/kernel_WendlandC2.f90 index 3b1c4f38c..f1b3167ab 100644 --- a/src/main/kernel_WendlandC2.f90 +++ b/src/main/kernel_WendlandC2.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/kernel_WendlandC4.f90 b/src/main/kernel_WendlandC4.f90 index 6a0ded877..2c6c899b7 100644 --- a/src/main/kernel_WendlandC4.f90 +++ b/src/main/kernel_WendlandC4.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/kernel_WendlandC6.f90 b/src/main/kernel_WendlandC6.f90 index c6e54af66..45255d139 100644 --- a/src/main/kernel_WendlandC6.f90 +++ b/src/main/kernel_WendlandC6.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/kernel_cubic.f90 b/src/main/kernel_cubic.f90 index 6ec8230a9..9b52948c6 100644 --- a/src/main/kernel_cubic.f90 +++ b/src/main/kernel_cubic.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/kernel_quartic.f90 b/src/main/kernel_quartic.f90 index de96a3432..9779b16fd 100644 --- a/src/main/kernel_quartic.f90 +++ b/src/main/kernel_quartic.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/kernel_quintic.f90 b/src/main/kernel_quintic.f90 index 82e735192..284b36048 100644 --- a/src/main/kernel_quintic.f90 +++ b/src/main/kernel_quintic.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/krome.f90 b/src/main/krome.f90 index 4ece40748..567b1611f 100644 --- a/src/main/krome.f90 +++ b/src/main/krome.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/linklist_kdtree.F90 b/src/main/linklist_kdtree.F90 index 96ea0ea7f..8e1ccca45 100644 --- a/src/main/linklist_kdtree.F90 +++ b/src/main/linklist_kdtree.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/memory.f90 b/src/main/memory.f90 index 809c17221..678390112 100644 --- a/src/main/memory.f90 +++ b/src/main/memory.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_et.f90 b/src/main/metric_et.f90 index cd93c9c3b..f95e87c39 100644 --- a/src/main/metric_et.f90 +++ b/src/main/metric_et.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_et_utils.f90 b/src/main/metric_et_utils.f90 index a3c3bebf5..6dc984f52 100644 --- a/src/main/metric_et_utils.f90 +++ b/src/main/metric_et_utils.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_flrw.f90 b/src/main/metric_flrw.f90 index 67127f46e..ce5aa4751 100644 --- a/src/main/metric_flrw.f90 +++ b/src/main/metric_flrw.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_kerr-schild.f90 b/src/main/metric_kerr-schild.f90 index 59ada6922..989386a3f 100644 --- a/src/main/metric_kerr-schild.f90 +++ b/src/main/metric_kerr-schild.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_kerr.f90 b/src/main/metric_kerr.f90 index b270e4111..6ada2574c 100644 --- a/src/main/metric_kerr.f90 +++ b/src/main/metric_kerr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_minkowski.f90 b/src/main/metric_minkowski.f90 index 8164301c0..68532f133 100644 --- a/src/main/metric_minkowski.f90 +++ b/src/main/metric_minkowski.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_schwarzschild.f90 b/src/main/metric_schwarzschild.f90 index 6add9d242..c48ea5c54 100644 --- a/src/main/metric_schwarzschild.f90 +++ b/src/main/metric_schwarzschild.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/metric_tools.f90 b/src/main/metric_tools.f90 index 05b485fcb..f7c66bf78 100644 --- a/src/main/metric_tools.f90 +++ b/src/main/metric_tools.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mf_write.f90 b/src/main/mf_write.f90 index 486ec1bf7..070d9bab6 100644 --- a/src/main/mf_write.f90 +++ b/src/main/mf_write.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mol_data.f90 b/src/main/mol_data.f90 index fe91bae89..6e50ce28b 100644 --- a/src/main/mol_data.f90 +++ b/src/main/mol_data.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_balance.F90 b/src/main/mpi_balance.F90 index 1679dda42..0ed1f725a 100644 --- a/src/main/mpi_balance.F90 +++ b/src/main/mpi_balance.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_dens.F90 b/src/main/mpi_dens.F90 index 9986c8219..c74710b58 100644 --- a/src/main/mpi_dens.F90 +++ b/src/main/mpi_dens.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_derivs.F90 b/src/main/mpi_derivs.F90 index 1847cbd6c..31a2dafe9 100644 --- a/src/main/mpi_derivs.F90 +++ b/src/main/mpi_derivs.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_domain.F90 b/src/main/mpi_domain.F90 index b58c49fed..ab339c61a 100644 --- a/src/main/mpi_domain.F90 +++ b/src/main/mpi_domain.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_force.F90 b/src/main/mpi_force.F90 index f4ff7722e..4e461bac3 100644 --- a/src/main/mpi_force.F90 +++ b/src/main/mpi_force.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_memory.f90 b/src/main/mpi_memory.f90 index 5d635f2d4..465ce6d07 100644 --- a/src/main/mpi_memory.f90 +++ b/src/main/mpi_memory.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_tree.F90 b/src/main/mpi_tree.F90 index 8b24ace8c..47088e71f 100644 --- a/src/main/mpi_tree.F90 +++ b/src/main/mpi_tree.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/mpi_utils.F90 b/src/main/mpi_utils.F90 index 03816c05d..561ab84f8 100644 --- a/src/main/mpi_utils.F90 +++ b/src/main/mpi_utils.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/nicil_supplement.f90 b/src/main/nicil_supplement.f90 index c0d5fbfd3..40c5fc49d 100644 --- a/src/main/nicil_supplement.f90 +++ b/src/main/nicil_supplement.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/options.f90 b/src/main/options.f90 index f49271fca..d16ae7d8a 100644 --- a/src/main/options.f90 +++ b/src/main/options.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/part.F90 b/src/main/part.F90 index 6f7655daa..d74023513 100644 --- a/src/main/part.F90 +++ b/src/main/part.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/partinject.F90 b/src/main/partinject.F90 index 697a46be1..3e97a8d2a 100644 --- a/src/main/partinject.F90 +++ b/src/main/partinject.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/phantom.f90 b/src/main/phantom.f90 index 798802b99..51bf2f8fd 100644 --- a/src/main/phantom.f90 +++ b/src/main/phantom.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/physcon.f90 b/src/main/physcon.f90 index 414ba9d14..ed22fdda0 100644 --- a/src/main/physcon.f90 +++ b/src/main/physcon.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/porosity.f90 b/src/main/porosity.f90 index a70b3801c..f10ac1c76 100755 --- a/src/main/porosity.f90 +++ b/src/main/porosity.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/ptmass.F90 b/src/main/ptmass.F90 index 399cd3ec9..cf1ceb869 100644 --- a/src/main/ptmass.F90 +++ b/src/main/ptmass.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/ptmass_heating.f90 b/src/main/ptmass_heating.f90 index 2095b88f3..009415edb 100644 --- a/src/main/ptmass_heating.f90 +++ b/src/main/ptmass_heating.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/ptmass_radiation.f90 b/src/main/ptmass_radiation.f90 index dc175ff8d..0913abc0f 100644 --- a/src/main/ptmass_radiation.f90 +++ b/src/main/ptmass_radiation.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/quitdump.f90 b/src/main/quitdump.f90 index 5f0159905..dc60f14fb 100644 --- a/src/main/quitdump.f90 +++ b/src/main/quitdump.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/radiation_implicit.f90 b/src/main/radiation_implicit.f90 index 0a79918d8..bf2de152d 100644 --- a/src/main/radiation_implicit.f90 +++ b/src/main/radiation_implicit.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/radiation_utils.f90 b/src/main/radiation_utils.f90 index 19b176db9..214045ce4 100644 --- a/src/main/radiation_utils.f90 +++ b/src/main/radiation_utils.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/random.f90 b/src/main/random.f90 index dd2ba97c1..fcc0b2f56 100644 --- a/src/main/random.f90 +++ b/src/main/random.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/readwrite_dumps.F90 b/src/main/readwrite_dumps.F90 index ff82e7935..20bf8bdcd 100644 --- a/src/main/readwrite_dumps.F90 +++ b/src/main/readwrite_dumps.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/readwrite_dumps_common.f90 b/src/main/readwrite_dumps_common.f90 index df6fc8a8b..b54f1f1e8 100644 --- a/src/main/readwrite_dumps_common.f90 +++ b/src/main/readwrite_dumps_common.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/readwrite_dumps_fortran.f90 b/src/main/readwrite_dumps_fortran.f90 index 4c9e4f6f1..4c098e8d5 100644 --- a/src/main/readwrite_dumps_fortran.f90 +++ b/src/main/readwrite_dumps_fortran.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -18,6 +18,10 @@ module readwrite_dumps_fortran ! ! :Runtime parameters: None ! +! :Dependencies: boundary_dyn, dim, dump_utils, eos, eos_stamatellos, io, +! memory, metric_tools, mpiutils, options, part, readwrite_dumps_common, +! sphNGutils, timestep +! ! :Dependencies: boundary_dyn, dim, dump_utils, eos, eos_stamatellos, io, ! memory, metric_tools, mpiutils, options, part, readwrite_dumps_common, diff --git a/src/main/readwrite_dumps_hdf5.F90 b/src/main/readwrite_dumps_hdf5.F90 index 3e929d7b4..9613c45c1 100644 --- a/src/main/readwrite_dumps_hdf5.F90 +++ b/src/main/readwrite_dumps_hdf5.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/readwrite_infile.F90 b/src/main/readwrite_infile.F90 index 73c164b9a..74494b1a1 100644 --- a/src/main/readwrite_infile.F90 +++ b/src/main/readwrite_infile.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/relaxem.f90 b/src/main/relaxem.f90 index f7cfe238f..ad1694c76 100644 --- a/src/main/relaxem.f90 +++ b/src/main/relaxem.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/sort_particles.f90 b/src/main/sort_particles.f90 index 89cba893a..da0b3ce0f 100644 --- a/src/main/sort_particles.f90 +++ b/src/main/sort_particles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/step_leapfrog.F90 b/src/main/step_leapfrog.F90 index 70757c3cd..17743f106 100644 --- a/src/main/step_leapfrog.F90 +++ b/src/main/step_leapfrog.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -23,9 +23,9 @@ module step_lf_global ! :Runtime parameters: None ! ! :Dependencies: boundary_dyn, cons2prim, cons2primsolver, cooling, -! damping, deriv, dim, eos, extern_gr, growth, io, io_summary, -! metric_tools, mpiutils, options, part, porosity, substepping, timestep, -! timestep_ind, timestep_sts, timing +! cooling_radapprox, damping, deriv, dim, eos, extern_gr, growth, io, +! io_summary, metric_tools, mpiutils, options, part, porosity, +! substepping, timestep, timestep_ind, timestep_sts, timing ! use dim, only:maxp,maxvxyzu,do_radiation,ind_timesteps use part, only:vpred,Bpred,dustpred,ppred diff --git a/src/main/step_supertimestep.F90 b/src/main/step_supertimestep.F90 index 413f0615b..fcfac1af9 100644 --- a/src/main/step_supertimestep.F90 +++ b/src/main/step_supertimestep.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/subgroup.f90 b/src/main/subgroup.f90 index beaa78c08..e1f657582 100644 --- a/src/main/subgroup.f90 +++ b/src/main/subgroup.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/substepping.F90 b/src/main/substepping.F90 index 101639feb..50bf93222 100644 --- a/src/main/substepping.F90 +++ b/src/main/substepping.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/timestep.f90 b/src/main/timestep.f90 index 99bd0e172..4b98485eb 100644 --- a/src/main/timestep.f90 +++ b/src/main/timestep.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/tmunu2grid.f90 b/src/main/tmunu2grid.f90 index 754f63a6d..a208373e3 100644 --- a/src/main/tmunu2grid.f90 +++ b/src/main/tmunu2grid.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/units.f90 b/src/main/units.f90 index a859c768d..67c5b290d 100644 --- a/src/main/units.f90 +++ b/src/main/units.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_allocate.f90 b/src/main/utils_allocate.f90 index d3c704cc1..e3b7e425e 100644 --- a/src/main/utils_allocate.f90 +++ b/src/main/utils_allocate.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_binary.f90 b/src/main/utils_binary.f90 index 5f9ca8851..d7f8f920c 100644 --- a/src/main/utils_binary.f90 +++ b/src/main/utils_binary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_cpuinfo.f90 b/src/main/utils_cpuinfo.f90 index 5e50794c9..d1ec67a2a 100644 --- a/src/main/utils_cpuinfo.f90 +++ b/src/main/utils_cpuinfo.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_datafiles.f90 b/src/main/utils_datafiles.f90 index 2e6173808..ec5f1f6f4 100644 --- a/src/main/utils_datafiles.f90 +++ b/src/main/utils_datafiles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_deriv.f90 b/src/main/utils_deriv.f90 index d45676930..2b00f52ef 100644 --- a/src/main/utils_deriv.f90 +++ b/src/main/utils_deriv.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_dumpfiles.f90 b/src/main/utils_dumpfiles.f90 index 81b669cc8..dad40e34d 100644 --- a/src/main/utils_dumpfiles.f90 +++ b/src/main/utils_dumpfiles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_dumpfiles_hdf5.f90 b/src/main/utils_dumpfiles_hdf5.f90 index 581d06cd8..f091cd564 100644 --- a/src/main/utils_dumpfiles_hdf5.f90 +++ b/src/main/utils_dumpfiles_hdf5.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_filenames.f90 b/src/main/utils_filenames.f90 index 108eb2a52..b7d1e3145 100644 --- a/src/main/utils_filenames.f90 +++ b/src/main/utils_filenames.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_gr.f90 b/src/main/utils_gr.f90 index 6ecc4be43..76bf593a4 100644 --- a/src/main/utils_gr.f90 +++ b/src/main/utils_gr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_hdf5.f90 b/src/main/utils_hdf5.f90 index 2afa77842..4bc07b1e9 100644 --- a/src/main/utils_hdf5.f90 +++ b/src/main/utils_hdf5.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_healpix.f90 b/src/main/utils_healpix.f90 index 407761514..d0793740d 100644 --- a/src/main/utils_healpix.f90 +++ b/src/main/utils_healpix.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -20,7 +20,7 @@ module healpix ! ! :References: K. M. Górski et al, 2005, ApJ, 622, 759 ! -! :Owner: Mats Esseldeurs +! :Owner: Lionel Siess ! ! :Runtime parameters: None ! diff --git a/src/main/utils_implicit.f90 b/src/main/utils_implicit.f90 index 63fc4e843..7622f9bd2 100644 --- a/src/main/utils_implicit.f90 +++ b/src/main/utils_implicit.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_indtimesteps.F90 b/src/main/utils_indtimesteps.F90 index 14ad9f826..43d52a6cf 100644 --- a/src/main/utils_indtimesteps.F90 +++ b/src/main/utils_indtimesteps.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_infiles.f90 b/src/main/utils_infiles.f90 index 4134a8114..8f197386a 100644 --- a/src/main/utils_infiles.f90 +++ b/src/main/utils_infiles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_inject.f90 b/src/main/utils_inject.f90 index ca43b16ff..a11d2173b 100644 --- a/src/main/utils_inject.f90 +++ b/src/main/utils_inject.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_kepler.f90 b/src/main/utils_kepler.f90 index dfed7696b..abfa10d0d 100644 --- a/src/main/utils_kepler.f90 +++ b/src/main/utils_kepler.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_mathfunc.f90 b/src/main/utils_mathfunc.f90 index e133bdbb7..e23c719c1 100644 --- a/src/main/utils_mathfunc.f90 +++ b/src/main/utils_mathfunc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_omp.F90 b/src/main/utils_omp.F90 index eca6876fc..3e2155bfb 100644 --- a/src/main/utils_omp.F90 +++ b/src/main/utils_omp.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_raytracer.f90 b/src/main/utils_raytracer.f90 index fe327480b..d2c8e59f0 100644 --- a/src/main/utils_raytracer.f90 +++ b/src/main/utils_raytracer.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -16,7 +16,7 @@ module raytracer ! ! :References: Esseldeurs M., Siess L. et al, 2023, A&A, 674, A122 ! -! :Owner: Mats Esseldeurs +! :Owner: Lionel Siess ! ! :Runtime parameters: None ! diff --git a/src/main/utils_shuffleparticles.F90 b/src/main/utils_shuffleparticles.F90 index 21f57473b..5a5429a4e 100644 --- a/src/main/utils_shuffleparticles.F90 +++ b/src/main/utils_shuffleparticles.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_sort.f90 b/src/main/utils_sort.f90 index 4ffbf6bd3..f0e191f27 100644 --- a/src/main/utils_sort.f90 +++ b/src/main/utils_sort.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_sphNG.f90 b/src/main/utils_sphNG.f90 index c0fe72c0a..b2c7958fa 100644 --- a/src/main/utils_sphNG.f90 +++ b/src/main/utils_sphNG.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_spline.f90 b/src/main/utils_spline.f90 index 2d97899f7..c5b0e78a2 100644 --- a/src/main/utils_spline.f90 +++ b/src/main/utils_spline.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_subgroup.f90 b/src/main/utils_subgroup.f90 index 91f20f713..5b9c5cbb7 100644 --- a/src/main/utils_subgroup.f90 +++ b/src/main/utils_subgroup.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_summary.F90 b/src/main/utils_summary.F90 index e3c780c39..5c5610503 100644 --- a/src/main/utils_summary.F90 +++ b/src/main/utils_summary.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_supertimestep.F90 b/src/main/utils_supertimestep.F90 index 4f59faa67..38132efb2 100644 --- a/src/main/utils_supertimestep.F90 +++ b/src/main/utils_supertimestep.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_system.f90 b/src/main/utils_system.f90 index 35c718e1b..2d127b352 100644 --- a/src/main/utils_system.f90 +++ b/src/main/utils_system.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_tables.f90 b/src/main/utils_tables.f90 index 747b7663e..1c053e4a1 100644 --- a/src/main/utils_tables.f90 +++ b/src/main/utils_tables.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_timing.f90 b/src/main/utils_timing.f90 index 9e2de5d71..69952d00c 100644 --- a/src/main/utils_timing.f90 +++ b/src/main/utils_timing.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/utils_vectors.f90 b/src/main/utils_vectors.f90 index e529d5f36..8273a8f0b 100644 --- a/src/main/utils_vectors.f90 +++ b/src/main/utils_vectors.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/viscosity.f90 b/src/main/viscosity.f90 index c5d17fbba..f380c7a13 100644 --- a/src/main/viscosity.f90 +++ b/src/main/viscosity.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/wind.F90 b/src/main/wind.F90 index 3bb364228..a87fc9bac 100644 --- a/src/main/wind.F90 +++ b/src/main/wind.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/wind_equations.f90 b/src/main/wind_equations.f90 index db79e9431..3ecf38737 100644 --- a/src/main/wind_equations.f90 +++ b/src/main/wind_equations.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/main/writeheader.F90 b/src/main/writeheader.F90 index 9361aeb6f..81f850b67 100644 --- a/src/main/writeheader.F90 +++ b/src/main/writeheader.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/density_profiles.f90 b/src/setup/density_profiles.f90 index 6189b73bc..bf661310e 100644 --- a/src/setup/density_profiles.f90 +++ b/src/setup/density_profiles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/libsetup.f90 b/src/setup/libsetup.f90 index fc36e5e26..03ae823c1 100644 --- a/src/setup/libsetup.f90 +++ b/src/setup/libsetup.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/phantomsetup.F90 b/src/setup/phantomsetup.F90 index e24b9669a..a37ab0460 100644 --- a/src/setup/phantomsetup.F90 +++ b/src/setup/phantomsetup.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/readwrite_kepler.f90 b/src/setup/readwrite_kepler.f90 index 41f73b86f..436f4192b 100644 --- a/src/setup/readwrite_kepler.f90 +++ b/src/setup/readwrite_kepler.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/readwrite_mesa.f90 b/src/setup/readwrite_mesa.f90 index 70bb69dbd..f5571cb52 100644 --- a/src/setup/readwrite_mesa.f90 +++ b/src/setup/readwrite_mesa.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/relax_star.f90 b/src/setup/relax_star.f90 index 3512837cc..4a3f8b685 100644 --- a/src/setup/relax_star.f90 +++ b/src/setup/relax_star.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_Bfield.f90 b/src/setup/set_Bfield.f90 index 489904342..07ac2606f 100644 --- a/src/setup/set_Bfield.f90 +++ b/src/setup/set_Bfield.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_binary.f90 b/src/setup/set_binary.f90 index d5ae33da4..f6cd7d46b 100644 --- a/src/setup/set_binary.f90 +++ b/src/setup/set_binary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_cubic_core.f90 b/src/setup/set_cubic_core.f90 index 0daa194be..f2ea911ef 100644 --- a/src/setup/set_cubic_core.f90 +++ b/src/setup/set_cubic_core.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_disc.F90 b/src/setup/set_disc.F90 index 505713346..e7ad09e09 100644 --- a/src/setup/set_disc.F90 +++ b/src/setup/set_disc.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_dust.f90 b/src/setup/set_dust.f90 index 346b1ae8b..2dd02905f 100644 --- a/src/setup/set_dust.f90 +++ b/src/setup/set_dust.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_dust_options.f90 b/src/setup/set_dust_options.f90 index c97bbf0ca..2c887de00 100644 --- a/src/setup/set_dust_options.f90 +++ b/src/setup/set_dust_options.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_fixedentropycore.f90 b/src/setup/set_fixedentropycore.f90 index 5466782fd..6f6dae91d 100644 --- a/src/setup/set_fixedentropycore.f90 +++ b/src/setup/set_fixedentropycore.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_flyby.f90 b/src/setup/set_flyby.f90 index 783ae37a9..b7c1e8dbb 100644 --- a/src/setup/set_flyby.f90 +++ b/src/setup/set_flyby.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_hierarchical.f90 b/src/setup/set_hierarchical.f90 index c52aeabd6..719d21de6 100644 --- a/src/setup/set_hierarchical.f90 +++ b/src/setup/set_hierarchical.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_hierarchical_utils.f90 b/src/setup/set_hierarchical_utils.f90 index 6921d5daa..6ec8e40f9 100644 --- a/src/setup/set_hierarchical_utils.f90 +++ b/src/setup/set_hierarchical_utils.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_orbit.f90 b/src/setup/set_orbit.f90 index 605a8a467..0650dc4a4 100644 --- a/src/setup/set_orbit.f90 +++ b/src/setup/set_orbit.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_planets.f90 b/src/setup/set_planets.f90 index 8abcb545c..e845a1c6a 100644 --- a/src/setup/set_planets.f90 +++ b/src/setup/set_planets.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_shock.f90 b/src/setup/set_shock.f90 index e0623f797..52ee7fcac 100644 --- a/src/setup/set_shock.f90 +++ b/src/setup/set_shock.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_slab.f90 b/src/setup/set_slab.f90 index 61c00f7ce..af98e0519 100644 --- a/src/setup/set_slab.f90 +++ b/src/setup/set_slab.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_softened_core.f90 b/src/setup/set_softened_core.f90 index a7d546658..79ae80d79 100644 --- a/src/setup/set_softened_core.f90 +++ b/src/setup/set_softened_core.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_sphere.f90 b/src/setup/set_sphere.f90 index e3358f9fd..9b945ec1e 100644 --- a/src/setup/set_sphere.f90 +++ b/src/setup/set_sphere.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_star.f90 b/src/setup/set_star.f90 index 52a412be1..8423c3a94 100644 --- a/src/setup/set_star.f90 +++ b/src/setup/set_star.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_star_utils.f90 b/src/setup/set_star_utils.f90 index 400ea6a19..a9b704fa6 100644 --- a/src/setup/set_star_utils.f90 +++ b/src/setup/set_star_utils.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_unifdis.f90 b/src/setup/set_unifdis.f90 index 782d6c3af..3b9d07d8a 100644 --- a/src/setup/set_unifdis.f90 +++ b/src/setup/set_unifdis.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_units.f90 b/src/setup/set_units.f90 index 218eedae7..6cb6bf2b8 100644 --- a/src/setup/set_units.f90 +++ b/src/setup/set_units.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/set_vfield.f90 b/src/setup/set_vfield.f90 index 68d2d03e3..7370bbe77 100644 --- a/src/setup/set_vfield.f90 +++ b/src/setup/set_vfield.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_BHL.f90 b/src/setup/setup_BHL.f90 index 560081f1b..b014bc51d 100644 --- a/src/setup/setup_BHL.f90 +++ b/src/setup/setup_BHL.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_alfvenwave.f90 b/src/setup/setup_alfvenwave.f90 index 8bc9e10f9..d3c145e26 100644 --- a/src/setup/setup_alfvenwave.f90 +++ b/src/setup/setup_alfvenwave.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_asteroidwind.f90 b/src/setup/setup_asteroidwind.f90 index de849ec48..a8581f17c 100644 --- a/src/setup/setup_asteroidwind.f90 +++ b/src/setup/setup_asteroidwind.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_binary.f90 b/src/setup/setup_binary.f90 index 37d450fbf..2b7e7fe37 100644 --- a/src/setup/setup_binary.f90 +++ b/src/setup/setup_binary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_blob.f90 b/src/setup/setup_blob.f90 index d569cfb5b..6ff6cca8d 100644 --- a/src/setup/setup_blob.f90 +++ b/src/setup/setup_blob.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_bondi.f90 b/src/setup/setup_bondi.f90 index f543019fd..c76c41ff5 100644 --- a/src/setup/setup_bondi.f90 +++ b/src/setup/setup_bondi.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_bondiinject.f90 b/src/setup/setup_bondiinject.f90 index cd39849b1..3b4556aba 100644 --- a/src/setup/setup_bondiinject.f90 +++ b/src/setup/setup_bondiinject.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_chinchen.f90 b/src/setup/setup_chinchen.f90 index 66c97168a..ee3267698 100644 --- a/src/setup/setup_chinchen.f90 +++ b/src/setup/setup_chinchen.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_cluster.f90 b/src/setup/setup_cluster.f90 index 157414cfa..4e6ae3331 100644 --- a/src/setup/setup_cluster.f90 +++ b/src/setup/setup_cluster.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_collidingclouds.f90 b/src/setup/setup_collidingclouds.f90 index ff9553b42..a7c7758ab 100644 --- a/src/setup/setup_collidingclouds.f90 +++ b/src/setup/setup_collidingclouds.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_common.f90 b/src/setup/setup_common.f90 index 9a51767e0..b372f17ac 100644 --- a/src/setup/setup_common.f90 +++ b/src/setup/setup_common.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_disc.f90 b/src/setup/setup_disc.f90 index f822f3176..89b414d11 100644 --- a/src/setup/setup_disc.f90 +++ b/src/setup/setup_disc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -65,6 +65,7 @@ module setup ! - ibinary : *binary orbit (0=bound,1=unbound [flyby])* ! - ipotential : *potential (1=central point mass,* ! - istrat : *temperature prescription (0=MAPS, 1=Dartois)* +! - lumdisc : *Set qindex from stellar luminosity (ieos=23) (0=no 1=yes)* ! - m1 : *first hierarchical level primary mass* ! - m2 : *first hierarchical level secondary mass* ! - mass_unit : *mass unit (e.g. solarm,jupiterm,earthm)* @@ -87,12 +88,12 @@ module setup ! - use_mcfost : *use the mcfost library* ! - z0 : *z scaling factor* ! -! :Dependencies: centreofmass, dim, dust, eos, extern_binary, -! extern_corotate, extern_lensethirring, externalforces, fileutils, -! growth, infile_utils, io, kernel, memory, options, part, physcon, -! porosity, prompting, radiation_utils, set_dust, set_dust_options, -! setbinary, setdisc, setflyby, sethierarchical, spherical, timestep, -! units, vectorutils +! :Dependencies: centreofmass, dim, dust, eos, eos_stamatellos, +! extern_binary, extern_corotate, extern_lensethirring, externalforces, +! fileutils, growth, infile_utils, io, kernel, memory, options, part, +! physcon, porosity, prompting, radiation_utils, set_dust, +! set_dust_options, setbinary, setdisc, setflyby, sethierarchical, +! spherical, timestep, units, vectorutils ! use dim, only:use_dust,maxalpha,use_dustgrowth,maxdusttypes,& maxdustlarge,maxdustsmall,compiled_with_mcfost diff --git a/src/setup/setup_dustsettle.f90 b/src/setup/setup_dustsettle.f90 index 5a58e68c5..3d560d2a6 100644 --- a/src/setup/setup_dustsettle.f90 +++ b/src/setup/setup_dustsettle.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_dustybox.f90 b/src/setup/setup_dustybox.f90 index 00d9bae08..89f49dabc 100644 --- a/src/setup/setup_dustybox.f90 +++ b/src/setup/setup_dustybox.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_dustysedov.f90 b/src/setup/setup_dustysedov.f90 index 918becd15..d953c7c63 100644 --- a/src/setup/setup_dustysedov.f90 +++ b/src/setup/setup_dustysedov.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_empty.f90 b/src/setup/setup_empty.f90 index 22c3a0893..cba1d2711 100644 --- a/src/setup/setup_empty.f90 +++ b/src/setup/setup_empty.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_firehose.f90 b/src/setup/setup_firehose.f90 index c6256bcf0..795ea58b4 100644 --- a/src/setup/setup_firehose.f90 +++ b/src/setup/setup_firehose.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_flrw.f90 b/src/setup/setup_flrw.f90 index 5dab4626a..9776a71fa 100644 --- a/src/setup/setup_flrw.f90 +++ b/src/setup/setup_flrw.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_flrwpspec.f90 b/src/setup/setup_flrwpspec.f90 index 69aa34256..163b44b3b 100644 --- a/src/setup/setup_flrwpspec.f90 +++ b/src/setup/setup_flrwpspec.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_galaxies.f90 b/src/setup/setup_galaxies.f90 index ea8d68924..4dccae5a7 100644 --- a/src/setup/setup_galaxies.f90 +++ b/src/setup/setup_galaxies.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_galcen_stars.f90 b/src/setup/setup_galcen_stars.f90 index b7d08a395..6573c1fcf 100644 --- a/src/setup/setup_galcen_stars.f90 +++ b/src/setup/setup_galcen_stars.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_galdisc.f90 b/src/setup/setup_galdisc.f90 index 37e1ac6c2..604c8db3d 100644 --- a/src/setup/setup_galdisc.f90 +++ b/src/setup/setup_galdisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_grdisc.F90 b/src/setup/setup_grdisc.F90 index 605d9daa3..54bfa00ef 100644 --- a/src/setup/setup_grdisc.F90 +++ b/src/setup/setup_grdisc.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_grtde.f90 b/src/setup/setup_grtde.f90 index 1fb776d80..9339f613f 100644 --- a/src/setup/setup_grtde.f90 +++ b/src/setup/setup_grtde.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_gwdisc.f90 b/src/setup/setup_gwdisc.f90 index 6f74be36a..4ae33cfdc 100644 --- a/src/setup/setup_gwdisc.f90 +++ b/src/setup/setup_gwdisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_hierarchical.f90 b/src/setup/setup_hierarchical.f90 index cad18867d..450387455 100644 --- a/src/setup/setup_hierarchical.f90 +++ b/src/setup/setup_hierarchical.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_jadvect.f90 b/src/setup/setup_jadvect.f90 index 15b8fc00e..f4139a227 100644 --- a/src/setup/setup_jadvect.f90 +++ b/src/setup/setup_jadvect.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_kh.f90 b/src/setup/setup_kh.f90 index 5e847d5f8..b89ace95f 100644 --- a/src/setup/setup_kh.f90 +++ b/src/setup/setup_kh.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_masstransfer.f90 b/src/setup/setup_masstransfer.f90 index 15bf86aed..0f87b254d 100644 --- a/src/setup/setup_masstransfer.f90 +++ b/src/setup/setup_masstransfer.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_mhdblast.f90 b/src/setup/setup_mhdblast.f90 index 12189204f..3f716547f 100644 --- a/src/setup/setup_mhdblast.f90 +++ b/src/setup/setup_mhdblast.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_mhdrotor.f90 b/src/setup/setup_mhdrotor.f90 index 25f1d5402..28f7348cf 100644 --- a/src/setup/setup_mhdrotor.f90 +++ b/src/setup/setup_mhdrotor.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_mhdsine.f90 b/src/setup/setup_mhdsine.f90 index 0c1fa5b0a..c518efea2 100644 --- a/src/setup/setup_mhdsine.f90 +++ b/src/setup/setup_mhdsine.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_mhdvortex.f90 b/src/setup/setup_mhdvortex.f90 index 8ea65ad98..3fbeb1302 100644 --- a/src/setup/setup_mhdvortex.f90 +++ b/src/setup/setup_mhdvortex.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_mhdwave.f90 b/src/setup/setup_mhdwave.f90 index db858458b..e31ce715a 100644 --- a/src/setup/setup_mhdwave.f90 +++ b/src/setup/setup_mhdwave.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_nsdisc.f90 b/src/setup/setup_nsdisc.f90 index bb9577f02..4879ecc79 100644 --- a/src/setup/setup_nsdisc.f90 +++ b/src/setup/setup_nsdisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_orstang.f90 b/src/setup/setup_orstang.f90 index 04645cf0b..fd2091431 100644 --- a/src/setup/setup_orstang.f90 +++ b/src/setup/setup_orstang.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_params.f90 b/src/setup/setup_params.f90 index 9be2eadb7..3c5f74d0e 100644 --- a/src/setup/setup_params.f90 +++ b/src/setup/setup_params.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_planetdisc.f90 b/src/setup/setup_planetdisc.f90 index 8e8ecb444..ff0ff00a9 100644 --- a/src/setup/setup_planetdisc.f90 +++ b/src/setup/setup_planetdisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_prtest.f90 b/src/setup/setup_prtest.f90 index 4ad6b335a..179d9d5fe 100644 --- a/src/setup/setup_prtest.f90 +++ b/src/setup/setup_prtest.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_quebec.f90 b/src/setup/setup_quebec.f90 index 0ce9bde95..29fc13474 100644 --- a/src/setup/setup_quebec.f90 +++ b/src/setup/setup_quebec.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_radiativebox.f90 b/src/setup/setup_radiativebox.f90 index b30ea361b..0d9b69b85 100644 --- a/src/setup/setup_radiativebox.f90 +++ b/src/setup/setup_radiativebox.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_sedov.f90 b/src/setup/setup_sedov.f90 index 49884983f..74ea7f3f4 100644 --- a/src/setup/setup_sedov.f90 +++ b/src/setup/setup_sedov.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_shock.f90 b/src/setup/setup_shock.f90 index 478846475..7eb81e598 100644 --- a/src/setup/setup_shock.f90 +++ b/src/setup/setup_shock.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_solarsystem.f90 b/src/setup/setup_solarsystem.f90 index 4dcb7a861..396b87636 100644 --- a/src/setup/setup_solarsystem.f90 +++ b/src/setup/setup_solarsystem.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_sphereinbox.f90 b/src/setup/setup_sphereinbox.f90 index f75b6e85f..c0be1e66c 100644 --- a/src/setup/setup_sphereinbox.f90 +++ b/src/setup/setup_sphereinbox.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_srblast.f90 b/src/setup/setup_srblast.f90 index 79e38118b..e77936cac 100644 --- a/src/setup/setup_srblast.f90 +++ b/src/setup/setup_srblast.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_srpolytrope.f90 b/src/setup/setup_srpolytrope.f90 index f387060b3..6d4480660 100644 --- a/src/setup/setup_srpolytrope.f90 +++ b/src/setup/setup_srpolytrope.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_star.f90 b/src/setup/setup_star.f90 index 5e17d98c6..067536167 100644 --- a/src/setup/setup_star.f90 +++ b/src/setup/setup_star.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_starcluster.f90 b/src/setup/setup_starcluster.f90 index 89b712b14..0fe624348 100644 --- a/src/setup/setup_starcluster.f90 +++ b/src/setup/setup_starcluster.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_taylorgreen.f90 b/src/setup/setup_taylorgreen.f90 index 32f7ae24d..c75354829 100644 --- a/src/setup/setup_taylorgreen.f90 +++ b/src/setup/setup_taylorgreen.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_testparticles.f90 b/src/setup/setup_testparticles.f90 index fbc4f0410..d7e84741c 100644 --- a/src/setup/setup_testparticles.f90 +++ b/src/setup/setup_testparticles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_tokamak.f90 b/src/setup/setup_tokamak.f90 index 6fe6d3ebb..3b65bf4d8 100644 --- a/src/setup/setup_tokamak.f90 +++ b/src/setup/setup_tokamak.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_torus.f90 b/src/setup/setup_torus.f90 index ed8b9470f..aa7521de2 100644 --- a/src/setup/setup_torus.f90 +++ b/src/setup/setup_torus.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_turb.f90 b/src/setup/setup_turb.f90 index 6910265f4..192b5dd47 100644 --- a/src/setup/setup_turb.f90 +++ b/src/setup/setup_turb.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_unifdis.f90 b/src/setup/setup_unifdis.f90 index 45b2c1abe..6fcab5bb0 100644 --- a/src/setup/setup_unifdis.f90 +++ b/src/setup/setup_unifdis.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_wave.f90 b/src/setup/setup_wave.f90 index 3a0816ee0..4ecafafe0 100644 --- a/src/setup/setup_wave.f90 +++ b/src/setup/setup_wave.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_wavedamp.f90 b/src/setup/setup_wavedamp.f90 index 8b6901518..41e627504 100644 --- a/src/setup/setup_wavedamp.f90 +++ b/src/setup/setup_wavedamp.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_wddisc.f90 b/src/setup/setup_wddisc.f90 index 39d9101a1..969eb80dc 100644 --- a/src/setup/setup_wddisc.f90 +++ b/src/setup/setup_wddisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_wind.f90 b/src/setup/setup_wind.f90 index e41b19227..86062ad12 100644 --- a/src/setup/setup_wind.f90 +++ b/src/setup/setup_wind.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/setup_windtunnel.f90 b/src/setup/setup_windtunnel.f90 index d82549f47..5b16524f4 100644 --- a/src/setup/setup_windtunnel.f90 +++ b/src/setup/setup_windtunnel.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -18,7 +18,6 @@ module setup ! - gamma : *adiabatic index* ! - handled_layers : *number of handled layers* ! - lattice_type : *0: cubic, 1: close-packed cubic* -! - nstar : *number of particles resolving gas sphere* ! - pres_inf : *wind pressure / dyn cm^2* ! - rho_inf : *wind density / g cm^-3* ! - v_inf : *wind speed / km s^-1* @@ -27,8 +26,9 @@ module setup ! - wind_radius : *injection radius in units of Rstar* ! ! :Dependencies: dim, eos, extern_densprofile, infile_utils, inject, io, -! kernel, mpidomain, part, physcon, rho_profile, setstar_utils, setunits, -! setup_params, table_utils, timestep, unifdis, units +! kernel, mpidomain, part, physcon, relaxstar, rho_profile, +! setstar_utils, setunits, setup_params, table_utils, timestep, unifdis, +! units ! use io, only:master,fatal use inject, only:init_inject,nstar,Rstar,lattice_type,handled_layers,& diff --git a/src/setup/stretchmap.f90 b/src/setup/stretchmap.f90 index cea129eca..9da968dd5 100644 --- a/src/setup/stretchmap.f90 +++ b/src/setup/stretchmap.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/setup/velfield_fromcubes.f90 b/src/setup/velfield_fromcubes.f90 index 9145c4c04..75c577b83 100644 --- a/src/setup/velfield_fromcubes.f90 +++ b/src/setup/velfield_fromcubes.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/directsum.f90 b/src/tests/directsum.f90 index d4ac696f5..f0349e6f0 100644 --- a/src/tests/directsum.f90 +++ b/src/tests/directsum.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/phantomtest.f90 b/src/tests/phantomtest.f90 index dd310aa6f..5d846b830 100644 --- a/src/tests/phantomtest.f90 +++ b/src/tests/phantomtest.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_apr.f90 b/src/tests/test_apr.f90 index eebb5c0f5..668999fe1 100644 --- a/src/tests/test_apr.f90 +++ b/src/tests/test_apr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_cooling.f90 b/src/tests/test_cooling.f90 index 41db26289..42328a2c9 100644 --- a/src/tests/test_cooling.f90 +++ b/src/tests/test_cooling.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_corotate.f90 b/src/tests/test_corotate.f90 index 95d1d1b00..e8f3d069e 100644 --- a/src/tests/test_corotate.f90 +++ b/src/tests/test_corotate.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_damping.f90 b/src/tests/test_damping.f90 index ca00a1b95..1972be85b 100644 --- a/src/tests/test_damping.f90 +++ b/src/tests/test_damping.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_derivs.F90 b/src/tests/test_derivs.F90 index cd24aa515..02692bb28 100644 --- a/src/tests/test_derivs.F90 +++ b/src/tests/test_derivs.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_dust.f90 b/src/tests/test_dust.f90 index c025207f5..588fc4f43 100644 --- a/src/tests/test_dust.f90 +++ b/src/tests/test_dust.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_eos.f90 b/src/tests/test_eos.f90 index 44f09afe8..7efc43216 100644 --- a/src/tests/test_eos.f90 +++ b/src/tests/test_eos.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_eos_stratified.f90 b/src/tests/test_eos_stratified.f90 index 20ecf3f4f..06e5d5db6 100644 --- a/src/tests/test_eos_stratified.f90 +++ b/src/tests/test_eos_stratified.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_externf.f90 b/src/tests/test_externf.f90 index 13433ddb4..e3e7def04 100644 --- a/src/tests/test_externf.f90 +++ b/src/tests/test_externf.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_externf_gr.f90 b/src/tests/test_externf_gr.f90 index ca7529063..4e4adc400 100644 --- a/src/tests/test_externf_gr.f90 +++ b/src/tests/test_externf_gr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_fastmath.f90 b/src/tests/test_fastmath.f90 index 358b25133..87a48d187 100644 --- a/src/tests/test_fastmath.f90 +++ b/src/tests/test_fastmath.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_geometry.f90 b/src/tests/test_geometry.f90 index b32735f05..63b24dbe3 100644 --- a/src/tests/test_geometry.f90 +++ b/src/tests/test_geometry.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_gnewton.f90 b/src/tests/test_gnewton.f90 index ebc352296..d4685fd0f 100644 --- a/src/tests/test_gnewton.f90 +++ b/src/tests/test_gnewton.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_gr.f90 b/src/tests/test_gr.f90 index bdc1ad0fa..d3e3f9cac 100644 --- a/src/tests/test_gr.f90 +++ b/src/tests/test_gr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_gravity.f90 b/src/tests/test_gravity.f90 index 9fda4eb76..cbe1756e7 100644 --- a/src/tests/test_gravity.f90 +++ b/src/tests/test_gravity.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_growth.f90 b/src/tests/test_growth.f90 index 01190a85b..22cbceed4 100644 --- a/src/tests/test_growth.f90 +++ b/src/tests/test_growth.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_hierarchical.f90 b/src/tests/test_hierarchical.f90 index 9d5f6899a..8c49c44ce 100644 --- a/src/tests/test_hierarchical.f90 +++ b/src/tests/test_hierarchical.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_indtstep.F90 b/src/tests/test_indtstep.F90 index 30d101661..63b485bd3 100644 --- a/src/tests/test_indtstep.F90 +++ b/src/tests/test_indtstep.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_iorig.f90 b/src/tests/test_iorig.f90 index 5dcfde5b1..4b9b28fce 100644 --- a/src/tests/test_iorig.f90 +++ b/src/tests/test_iorig.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_kdtree.F90 b/src/tests/test_kdtree.F90 index ddb4730c2..262bbec6e 100644 --- a/src/tests/test_kdtree.F90 +++ b/src/tests/test_kdtree.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_kernel.f90 b/src/tests/test_kernel.f90 index 6169a18f7..33a9b0669 100644 --- a/src/tests/test_kernel.f90 +++ b/src/tests/test_kernel.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_link.F90 b/src/tests/test_link.F90 index 95c8a961a..b03d18d6a 100644 --- a/src/tests/test_link.F90 +++ b/src/tests/test_link.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_luminosity.F90 b/src/tests/test_luminosity.F90 index dab7dc68f..477928f1b 100644 --- a/src/tests/test_luminosity.F90 +++ b/src/tests/test_luminosity.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_mpi.f90 b/src/tests/test_mpi.f90 index e318998d9..1dad34040 100644 --- a/src/tests/test_mpi.f90 +++ b/src/tests/test_mpi.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_nonidealmhd.F90 b/src/tests/test_nonidealmhd.F90 index e03bab93d..301d76617 100644 --- a/src/tests/test_nonidealmhd.F90 +++ b/src/tests/test_nonidealmhd.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_part.f90 b/src/tests/test_part.f90 index aa4086b6f..58f6b732f 100644 --- a/src/tests/test_part.f90 +++ b/src/tests/test_part.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_poly.f90 b/src/tests/test_poly.f90 index a5bb1b56c..beeabb8d9 100644 --- a/src/tests/test_poly.f90 +++ b/src/tests/test_poly.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_ptmass.f90 b/src/tests/test_ptmass.f90 index da7f7dac6..43befbe71 100644 --- a/src/tests/test_ptmass.f90 +++ b/src/tests/test_ptmass.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_radiation.f90 b/src/tests/test_radiation.f90 index d13b5a249..43f56594a 100644 --- a/src/tests/test_radiation.f90 +++ b/src/tests/test_radiation.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_rwdump.F90 b/src/tests/test_rwdump.F90 index 509de2039..9139e4bb7 100644 --- a/src/tests/test_rwdump.F90 +++ b/src/tests/test_rwdump.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_sedov.F90 b/src/tests/test_sedov.F90 index 9e96630d7..2eea5378f 100644 --- a/src/tests/test_sedov.F90 +++ b/src/tests/test_sedov.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_setdisc.f90 b/src/tests/test_setdisc.f90 index 2f7bf026f..bcaa54768 100644 --- a/src/tests/test_setdisc.f90 +++ b/src/tests/test_setdisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_setstar.f90 b/src/tests/test_setstar.f90 index a68ffb84a..5d317a32f 100644 --- a/src/tests/test_setstar.f90 +++ b/src/tests/test_setstar.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_smol.F90 b/src/tests/test_smol.F90 index 7b26c1b65..56ca792ad 100644 --- a/src/tests/test_smol.F90 +++ b/src/tests/test_smol.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_step.F90 b/src/tests/test_step.F90 index 9bd8f7ad8..66dcaf838 100644 --- a/src/tests/test_step.F90 +++ b/src/tests/test_step.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/test_wind.f90 b/src/tests/test_wind.f90 index 65de7fb84..5563b3673 100644 --- a/src/tests/test_wind.f90 +++ b/src/tests/test_wind.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/testsuite.F90 b/src/tests/testsuite.F90 index 86db01be7..1b0c51f70 100644 --- a/src/tests/testsuite.F90 +++ b/src/tests/testsuite.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/tests/utils_testsuite.f90 b/src/tests/utils_testsuite.f90 index 512d25766..11ab2b1ed 100644 --- a/src/tests/utils_testsuite.f90 +++ b/src/tests/utils_testsuite.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/acc2ang.f90 b/src/utils/acc2ang.f90 index 56058bbb5..b557d5745 100644 --- a/src/utils/acc2ang.f90 +++ b/src/utils/acc2ang.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/adaptivemesh.f90 b/src/utils/adaptivemesh.f90 index 2072329a5..28276fb6e 100644 --- a/src/utils/adaptivemesh.f90 +++ b/src/utils/adaptivemesh.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_1particle.f90 b/src/utils/analysis_1particle.f90 index eb96fac59..5678f83b1 100644 --- a/src/utils/analysis_1particle.f90 +++ b/src/utils/analysis_1particle.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_BRhoOrientation.F90 b/src/utils/analysis_BRhoOrientation.F90 index 73170e3e6..527abd7a5 100644 --- a/src/utils/analysis_BRhoOrientation.F90 +++ b/src/utils/analysis_BRhoOrientation.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_CoM.f90 b/src/utils/analysis_CoM.f90 index b50fa4f5c..3b788985c 100644 --- a/src/utils/analysis_CoM.f90 +++ b/src/utils/analysis_CoM.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_GalMerger.f90 b/src/utils/analysis_GalMerger.f90 index 6f4e0c1fb..ee7e2d1c9 100644 --- a/src/utils/analysis_GalMerger.f90 +++ b/src/utils/analysis_GalMerger.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_MWpdf.f90 b/src/utils/analysis_MWpdf.f90 index 84f49013c..c3e0ce64e 100644 --- a/src/utils/analysis_MWpdf.f90 +++ b/src/utils/analysis_MWpdf.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_NSmerger.f90 b/src/utils/analysis_NSmerger.f90 index c96e57d0d..c189b9f7b 100644 --- a/src/utils/analysis_NSmerger.f90 +++ b/src/utils/analysis_NSmerger.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_alpha.f90 b/src/utils/analysis_alpha.f90 index d96f6fe49..41b589c69 100644 --- a/src/utils/analysis_alpha.f90 +++ b/src/utils/analysis_alpha.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_angmom.f90 b/src/utils/analysis_angmom.f90 index ce25dbc04..6f206b8eb 100644 --- a/src/utils/analysis_angmom.f90 +++ b/src/utils/analysis_angmom.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_angmomvec.f90 b/src/utils/analysis_angmomvec.f90 index eac98cd34..f3eac67b4 100644 --- a/src/utils/analysis_angmomvec.f90 +++ b/src/utils/analysis_angmomvec.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_average_orb_en.f90 b/src/utils/analysis_average_orb_en.f90 index c1c99003e..660d797ef 100644 --- a/src/utils/analysis_average_orb_en.f90 +++ b/src/utils/analysis_average_orb_en.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_binarydisc.f90 b/src/utils/analysis_binarydisc.f90 index 0894b7133..faf733e4c 100644 --- a/src/utils/analysis_binarydisc.f90 +++ b/src/utils/analysis_binarydisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_bzrms.f90 b/src/utils/analysis_bzrms.f90 index d8425a483..652379261 100644 --- a/src/utils/analysis_bzrms.f90 +++ b/src/utils/analysis_bzrms.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_clumpfind.F90 b/src/utils/analysis_clumpfind.F90 index 809036724..58c396a92 100644 --- a/src/utils/analysis_clumpfind.F90 +++ b/src/utils/analysis_clumpfind.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_clumpfindWB23.F90 b/src/utils/analysis_clumpfindWB23.F90 index 00e59de56..5752b6cbf 100644 --- a/src/utils/analysis_clumpfindWB23.F90 +++ b/src/utils/analysis_clumpfindWB23.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_collidingcloudevolution.f90 b/src/utils/analysis_collidingcloudevolution.f90 index 110cd4842..9e7ad1fed 100644 --- a/src/utils/analysis_collidingcloudevolution.f90 +++ b/src/utils/analysis_collidingcloudevolution.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_collidingcloudhistograms.f90 b/src/utils/analysis_collidingcloudhistograms.f90 index 11345d4ce..9e73525b9 100644 --- a/src/utils/analysis_collidingcloudhistograms.f90 +++ b/src/utils/analysis_collidingcloudhistograms.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_common_envelope.f90 b/src/utils/analysis_common_envelope.f90 index c1056f118..349d78b79 100644 --- a/src/utils/analysis_common_envelope.f90 +++ b/src/utils/analysis_common_envelope.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -15,9 +15,10 @@ module analysis ! :Runtime parameters: None ! ! :Dependencies: centreofmass, dim, dust_formation, energies, eos, -! eos_gasradrec, eos_mesa, extern_corotate, io, ionization_mod, kernel, -! mesa_microphysics, part, physcon, prompting, ptmass, setbinary, -! sortutils, table_utils, units, vectorutils +! eos_gasradrec, eos_idealplusrad, eos_mesa, extern_corotate, io, +! ionization_mod, kernel, mesa_microphysics, part, physcon, prompting, +! ptmass, radiation_utils, setbinary, sortutils, table_utils, units, +! vectorutils ! use part, only:xyzmh_ptmass,vxyz_ptmass,nptmass,poten,ihsoft,ihacc,& diff --git a/src/utils/analysis_cooling.f90 b/src/utils/analysis_cooling.f90 index ed70fc07e..34823a056 100644 --- a/src/utils/analysis_cooling.f90 +++ b/src/utils/analysis_cooling.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_disc.f90 b/src/utils/analysis_disc.f90 index 1f3e9f07f..d4606b8c3 100644 --- a/src/utils/analysis_disc.f90 +++ b/src/utils/analysis_disc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_disc_MFlow.f90 b/src/utils/analysis_disc_MFlow.f90 index 9cb995cae..73f858591 100644 --- a/src/utils/analysis_disc_MFlow.f90 +++ b/src/utils/analysis_disc_MFlow.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_disc_eccentric.f90 b/src/utils/analysis_disc_eccentric.f90 index caf029f94..abdc3004c 100644 --- a/src/utils/analysis_disc_eccentric.f90 +++ b/src/utils/analysis_disc_eccentric.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_disc_mag.f90 b/src/utils/analysis_disc_mag.f90 index 10f91136d..9152c0c91 100644 --- a/src/utils/analysis_disc_mag.f90 +++ b/src/utils/analysis_disc_mag.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_disc_planet.f90 b/src/utils/analysis_disc_planet.f90 index aad84a586..647fa7bab 100644 --- a/src/utils/analysis_disc_planet.f90 +++ b/src/utils/analysis_disc_planet.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_disc_stresses.f90 b/src/utils/analysis_disc_stresses.f90 index 16b8ec9f8..2c2d5112b 100644 --- a/src/utils/analysis_disc_stresses.f90 +++ b/src/utils/analysis_disc_stresses.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -18,8 +18,8 @@ module analysis ! - rin : *Inner Disc Radius* ! - rout : *Outer Disc Radius* ! -! :Dependencies: dim, eos, getneighbours, infile_utils, io, kernel, part, -! physcon, prompting, units +! :Dependencies: dim, eos, eos_stamatellos, getneighbours, infile_utils, +! io, kernel, part, physcon, prompting, units ! use getneighbours, only:generate_neighbour_lists, read_neighbours, write_neighbours, & neighcount,neighb,neighmax diff --git a/src/utils/analysis_dtheader.f90 b/src/utils/analysis_dtheader.f90 index d36b73452..ff1c092e9 100644 --- a/src/utils/analysis_dtheader.f90 +++ b/src/utils/analysis_dtheader.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_dustformation.f90 b/src/utils/analysis_dustformation.f90 index 9eaa95ee3..04dbffd51 100644 --- a/src/utils/analysis_dustformation.f90 +++ b/src/utils/analysis_dustformation.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_dustmass.f90 b/src/utils/analysis_dustmass.f90 index a072aedbe..e6043f85d 100644 --- a/src/utils/analysis_dustmass.f90 +++ b/src/utils/analysis_dustmass.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_dustydisc.f90 b/src/utils/analysis_dustydisc.f90 index c7f2d879b..aa9868e48 100644 --- a/src/utils/analysis_dustydisc.f90 +++ b/src/utils/analysis_dustydisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_dustywind.f90 b/src/utils/analysis_dustywind.f90 index 74f071edb..3bd279ff9 100644 --- a/src/utils/analysis_dustywind.f90 +++ b/src/utils/analysis_dustywind.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_energies.f90 b/src/utils/analysis_energies.f90 index 4d4288b74..1b9aaa57c 100644 --- a/src/utils/analysis_energies.f90 +++ b/src/utils/analysis_energies.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_etotgr.f90 b/src/utils/analysis_etotgr.f90 index be1a500aa..4513ab1d9 100644 --- a/src/utils/analysis_etotgr.f90 +++ b/src/utils/analysis_etotgr.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_getneighbours.f90 b/src/utils/analysis_getneighbours.f90 index f5fffe2a0..aa8ba69c0 100644 --- a/src/utils/analysis_getneighbours.f90 +++ b/src/utils/analysis_getneighbours.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_gws.f90 b/src/utils/analysis_gws.f90 index 70b12ab2b..3f2b06994 100644 --- a/src/utils/analysis_gws.f90 +++ b/src/utils/analysis_gws.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_jet.f90 b/src/utils/analysis_jet.f90 index 86c86dca8..52195d612 100644 --- a/src/utils/analysis_jet.f90 +++ b/src/utils/analysis_jet.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_kdtree.F90 b/src/utils/analysis_kdtree.F90 index ef83ee5e3..ca9487c7d 100644 --- a/src/utils/analysis_kdtree.F90 +++ b/src/utils/analysis_kdtree.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_kepler.f90 b/src/utils/analysis_kepler.f90 index e057510cb..8dd0d235a 100644 --- a/src/utils/analysis_kepler.f90 +++ b/src/utils/analysis_kepler.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_macctrace.f90 b/src/utils/analysis_macctrace.f90 index 26b1e224c..86bcb4812 100644 --- a/src/utils/analysis_macctrace.f90 +++ b/src/utils/analysis_macctrace.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_mapping_mass.f90 b/src/utils/analysis_mapping_mass.f90 index 892b5fb4c..26cd4a3b5 100644 --- a/src/utils/analysis_mapping_mass.f90 +++ b/src/utils/analysis_mapping_mass.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_mcfost.f90 b/src/utils/analysis_mcfost.f90 index 05259161b..5ccc741a4 100644 --- a/src/utils/analysis_mcfost.f90 +++ b/src/utils/analysis_mcfost.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_mcfostcmdline.f90 b/src/utils/analysis_mcfostcmdline.f90 index 2e3b10dc9..5c4df9283 100644 --- a/src/utils/analysis_mcfostcmdline.f90 +++ b/src/utils/analysis_mcfostcmdline.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_pairing.f90 b/src/utils/analysis_pairing.f90 index fbef57fe5..1f47f4293 100644 --- a/src/utils/analysis_pairing.f90 +++ b/src/utils/analysis_pairing.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_particle.f90 b/src/utils/analysis_particle.f90 index 5691ff0a9..8b0ab9363 100644 --- a/src/utils/analysis_particle.f90 +++ b/src/utils/analysis_particle.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_pdfs.f90 b/src/utils/analysis_pdfs.f90 index 96c64fc73..3e65e3056 100644 --- a/src/utils/analysis_pdfs.f90 +++ b/src/utils/analysis_pdfs.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_phantom_dump.f90 b/src/utils/analysis_phantom_dump.f90 index 0ffc60048..e12698e52 100644 --- a/src/utils/analysis_phantom_dump.f90 +++ b/src/utils/analysis_phantom_dump.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_polytropes.f90 b/src/utils/analysis_polytropes.f90 index c112085a3..510a5c539 100644 --- a/src/utils/analysis_polytropes.f90 +++ b/src/utils/analysis_polytropes.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_prdrag.f90 b/src/utils/analysis_prdrag.f90 index 8372c5c23..7ad9bb6c4 100644 --- a/src/utils/analysis_prdrag.f90 +++ b/src/utils/analysis_prdrag.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_protostar_environ.F90 b/src/utils/analysis_protostar_environ.F90 index 895d04933..64df5ed00 100644 --- a/src/utils/analysis_protostar_environ.F90 +++ b/src/utils/analysis_protostar_environ.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_ptmass.f90 b/src/utils/analysis_ptmass.f90 index 85477e1d4..e2a0869d7 100644 --- a/src/utils/analysis_ptmass.f90 +++ b/src/utils/analysis_ptmass.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_radiotde.f90 b/src/utils/analysis_radiotde.f90 index 918e8473b..06ee1f9fb 100644 --- a/src/utils/analysis_radiotde.f90 +++ b/src/utils/analysis_radiotde.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_raytracer.f90 b/src/utils/analysis_raytracer.f90 index f70a7589a..202a1646d 100644 --- a/src/utils/analysis_raytracer.f90 +++ b/src/utils/analysis_raytracer.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! @@ -10,7 +10,7 @@ module analysis ! ! :References: Esseldeurs M., Siess L. et al, 2023, A&A, 674, A122 ! -! :Owner: Mats Esseldeurs +! :Owner: Lionel Siess ! ! :Runtime parameters: None ! diff --git a/src/utils/analysis_sinkmass.f90 b/src/utils/analysis_sinkmass.f90 index 7993d3664..7327637cd 100644 --- a/src/utils/analysis_sinkmass.f90 +++ b/src/utils/analysis_sinkmass.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_sphere.f90 b/src/utils/analysis_sphere.f90 index a74eab303..cd25734e2 100644 --- a/src/utils/analysis_sphere.f90 +++ b/src/utils/analysis_sphere.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_structurefn.f90 b/src/utils/analysis_structurefn.f90 index 0e91bedde..ed2a4350d 100644 --- a/src/utils/analysis_structurefn.f90 +++ b/src/utils/analysis_structurefn.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_tde.f90 b/src/utils/analysis_tde.f90 index e0aa5ae7e..92b1d90a9 100644 --- a/src/utils/analysis_tde.f90 +++ b/src/utils/analysis_tde.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_tdeoutflow.f90 b/src/utils/analysis_tdeoutflow.f90 index 3012ee514..39a5803ae 100644 --- a/src/utils/analysis_tdeoutflow.f90 +++ b/src/utils/analysis_tdeoutflow.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_torus.f90 b/src/utils/analysis_torus.f90 index f6a745703..691ad3f0f 100644 --- a/src/utils/analysis_torus.f90 +++ b/src/utils/analysis_torus.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_trackbox.f90 b/src/utils/analysis_trackbox.f90 index efbe6e251..36bf71ec8 100644 --- a/src/utils/analysis_trackbox.f90 +++ b/src/utils/analysis_trackbox.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_tracks.f90 b/src/utils/analysis_tracks.f90 index 3812cc3b4..d76fb87e9 100644 --- a/src/utils/analysis_tracks.f90 +++ b/src/utils/analysis_tracks.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_velocitydispersion_vs_scale.f90 b/src/utils/analysis_velocitydispersion_vs_scale.f90 index ec46ee0b6..780e202c8 100644 --- a/src/utils/analysis_velocitydispersion_vs_scale.f90 +++ b/src/utils/analysis_velocitydispersion_vs_scale.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_velocityshear.f90 b/src/utils/analysis_velocityshear.f90 index da5209758..bdabd4bb2 100644 --- a/src/utils/analysis_velocityshear.f90 +++ b/src/utils/analysis_velocityshear.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/analysis_write_kdtree.F90 b/src/utils/analysis_write_kdtree.F90 index f27f4d623..49c053119 100644 --- a/src/utils/analysis_write_kdtree.F90 +++ b/src/utils/analysis_write_kdtree.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/combinedustdumps.f90 b/src/utils/combinedustdumps.f90 index 7dbbdf2d5..ca540af85 100755 --- a/src/utils/combinedustdumps.f90 +++ b/src/utils/combinedustdumps.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/cubicsolve.f90 b/src/utils/cubicsolve.f90 index 3d88f97f5..62d6ef21d 100644 --- a/src/utils/cubicsolve.f90 +++ b/src/utils/cubicsolve.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/diffdumps.f90 b/src/utils/diffdumps.f90 index 9423c6960..bfa6af00a 100644 --- a/src/utils/diffdumps.f90 +++ b/src/utils/diffdumps.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/dustywaves.f90 b/src/utils/dustywaves.f90 index 2d671513f..b377ae47b 100644 --- a/src/utils/dustywaves.f90 +++ b/src/utils/dustywaves.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/einsteintk_utils.f90 b/src/utils/einsteintk_utils.f90 index 3268df976..f7bcb00f2 100644 --- a/src/utils/einsteintk_utils.f90 +++ b/src/utils/einsteintk_utils.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/einsteintk_wrapper.f90 b/src/utils/einsteintk_wrapper.f90 index 96544a28f..cfc924198 100644 --- a/src/utils/einsteintk_wrapper.f90 +++ b/src/utils/einsteintk_wrapper.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/ev2kdot.f90 b/src/utils/ev2kdot.f90 index dced7d521..d5a089835 100644 --- a/src/utils/ev2kdot.f90 +++ b/src/utils/ev2kdot.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/ev2mdot.f90 b/src/utils/ev2mdot.f90 index 40374442b..e503bc698 100644 --- a/src/utils/ev2mdot.f90 +++ b/src/utils/ev2mdot.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/evol_dustywaves.f90 b/src/utils/evol_dustywaves.f90 index e9584604c..605013076 100644 --- a/src/utils/evol_dustywaves.f90 +++ b/src/utils/evol_dustywaves.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/get_struct_slope.f90 b/src/utils/get_struct_slope.f90 index 789e39854..2c0747f9d 100644 --- a/src/utils/get_struct_slope.f90 +++ b/src/utils/get_struct_slope.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/getmathflags.f90 b/src/utils/getmathflags.f90 index fbe9f872e..b94a31618 100644 --- a/src/utils/getmathflags.f90 +++ b/src/utils/getmathflags.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/grid2pdf.f90 b/src/utils/grid2pdf.f90 index 8ae7ad563..9dbca14d5 100644 --- a/src/utils/grid2pdf.f90 +++ b/src/utils/grid2pdf.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/hdf5utils.f90 b/src/utils/hdf5utils.f90 index 34031f068..2ac266ce0 100644 --- a/src/utils/hdf5utils.f90 +++ b/src/utils/hdf5utils.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/icosahedron.f90 b/src/utils/icosahedron.f90 index d0b00c594..cd49110e8 100644 --- a/src/utils/icosahedron.f90 +++ b/src/utils/icosahedron.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/interpolate3D.f90 b/src/utils/interpolate3D.f90 index 3b9e849f5..2939ebf71 100644 --- a/src/utils/interpolate3D.f90 +++ b/src/utils/interpolate3D.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/interpolate3D_amr.F90 b/src/utils/interpolate3D_amr.F90 index 49a9eb8b7..fec80e703 100644 --- a/src/utils/interpolate3D_amr.F90 +++ b/src/utils/interpolate3D_amr.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/io_grid.f90 b/src/utils/io_grid.f90 index a54cec7fe..bdaf0fdc1 100644 --- a/src/utils/io_grid.f90 +++ b/src/utils/io_grid.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/io_structurefn.f90 b/src/utils/io_structurefn.f90 index 00af14e20..737dce118 100644 --- a/src/utils/io_structurefn.f90 +++ b/src/utils/io_structurefn.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/leastsquares.f90 b/src/utils/leastsquares.f90 index f71fd3473..12e196ad2 100644 --- a/src/utils/leastsquares.f90 +++ b/src/utils/leastsquares.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/libphantom-splash.f90 b/src/utils/libphantom-splash.f90 index 2c0fc772a..e4dac4ffe 100644 --- a/src/utils/libphantom-splash.f90 +++ b/src/utils/libphantom-splash.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/lombperiod.f90 b/src/utils/lombperiod.f90 index d9b7a668e..a29f4f34d 100644 --- a/src/utils/lombperiod.f90 +++ b/src/utils/lombperiod.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/mflow.f90 b/src/utils/mflow.f90 index ea284e3fa..f746e22d5 100644 --- a/src/utils/mflow.f90 +++ b/src/utils/mflow.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_CoM.f90 b/src/utils/moddump_CoM.f90 index 72df6ef41..e745410ea 100644 --- a/src/utils/moddump_CoM.f90 +++ b/src/utils/moddump_CoM.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_LTE_to_rad.f90 b/src/utils/moddump_LTE_to_rad.f90 index 58e9a135a..8b9eef3dc 100644 --- a/src/utils/moddump_LTE_to_rad.f90 +++ b/src/utils/moddump_LTE_to_rad.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_addflyby.f90 b/src/utils/moddump_addflyby.f90 index 59bb9ca36..984e56461 100644 --- a/src/utils/moddump_addflyby.f90 +++ b/src/utils/moddump_addflyby.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_addplanets.f90 b/src/utils/moddump_addplanets.f90 index 9f913bb0c..d949cc72a 100644 --- a/src/utils/moddump_addplanets.f90 +++ b/src/utils/moddump_addplanets.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_binary.f90 b/src/utils/moddump_binary.f90 index c4c1077c3..9ce469f01 100644 --- a/src/utils/moddump_binary.f90 +++ b/src/utils/moddump_binary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_binarystar.f90 b/src/utils/moddump_binarystar.f90 index 4e15def00..31fc2fb36 100644 --- a/src/utils/moddump_binarystar.f90 +++ b/src/utils/moddump_binarystar.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_changemass.f90 b/src/utils/moddump_changemass.f90 index a407d17e7..002e5485f 100644 --- a/src/utils/moddump_changemass.f90 +++ b/src/utils/moddump_changemass.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_default.f90 b/src/utils/moddump_default.f90 index 0ae0f2a97..f5bb27df0 100644 --- a/src/utils/moddump_default.f90 +++ b/src/utils/moddump_default.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_disc.f90 b/src/utils/moddump_disc.f90 index 13a7bd473..9c6127164 100644 --- a/src/utils/moddump_disc.f90 +++ b/src/utils/moddump_disc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_dustadd.f90 b/src/utils/moddump_dustadd.f90 index 588a74707..1c233141a 100644 --- a/src/utils/moddump_dustadd.f90 +++ b/src/utils/moddump_dustadd.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_extenddisc.f90 b/src/utils/moddump_extenddisc.f90 index 1f16281da..78329d998 100644 --- a/src/utils/moddump_extenddisc.f90 +++ b/src/utils/moddump_extenddisc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_growthtomultigrain.f90 b/src/utils/moddump_growthtomultigrain.f90 index bcc8ab7c4..7dd2834de 100644 --- a/src/utils/moddump_growthtomultigrain.f90 +++ b/src/utils/moddump_growthtomultigrain.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_mergepart.f90 b/src/utils/moddump_mergepart.f90 index 17d42b67b..428c14290 100644 --- a/src/utils/moddump_mergepart.f90 +++ b/src/utils/moddump_mergepart.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_messupSPH.f90 b/src/utils/moddump_messupSPH.f90 index 1f0b8a257..f3f1e9a3d 100644 --- a/src/utils/moddump_messupSPH.f90 +++ b/src/utils/moddump_messupSPH.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_perturbgas.f90 b/src/utils/moddump_perturbgas.f90 index 8e895aafa..55ef6640f 100644 --- a/src/utils/moddump_perturbgas.f90 +++ b/src/utils/moddump_perturbgas.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_polytrope.f90 b/src/utils/moddump_polytrope.f90 index ed9554b90..2c005174b 100644 --- a/src/utils/moddump_polytrope.f90 +++ b/src/utils/moddump_polytrope.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_rad_to_LTE.f90 b/src/utils/moddump_rad_to_LTE.f90 index 7b14b0ee0..7b59c4e88 100644 --- a/src/utils/moddump_rad_to_LTE.f90 +++ b/src/utils/moddump_rad_to_LTE.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_radiotde.f90 b/src/utils/moddump_radiotde.f90 index e984c3792..baff749a9 100644 --- a/src/utils/moddump_radiotde.f90 +++ b/src/utils/moddump_radiotde.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_recalcuT.f90 b/src/utils/moddump_recalcuT.f90 index 814c275cf..2df2046fd 100644 --- a/src/utils/moddump_recalcuT.f90 +++ b/src/utils/moddump_recalcuT.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_removeparticles_cylinder.f90 b/src/utils/moddump_removeparticles_cylinder.f90 index eed6b214f..a6a18a7e4 100644 --- a/src/utils/moddump_removeparticles_cylinder.f90 +++ b/src/utils/moddump_removeparticles_cylinder.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_removeparticles_radius.f90 b/src/utils/moddump_removeparticles_radius.f90 index 65bad1b90..92364653a 100644 --- a/src/utils/moddump_removeparticles_radius.f90 +++ b/src/utils/moddump_removeparticles_radius.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_rotate.f90 b/src/utils/moddump_rotate.f90 index 34a6a069f..fb84d7701 100644 --- a/src/utils/moddump_rotate.f90 +++ b/src/utils/moddump_rotate.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_sink.f90 b/src/utils/moddump_sink.f90 index 01c4c3506..f892a54e4 100644 --- a/src/utils/moddump_sink.f90 +++ b/src/utils/moddump_sink.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_sinkbinary.f90 b/src/utils/moddump_sinkbinary.f90 index 46a128db7..85208392a 100644 --- a/src/utils/moddump_sinkbinary.f90 +++ b/src/utils/moddump_sinkbinary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_sphNG2phantom.f90 b/src/utils/moddump_sphNG2phantom.f90 index ad1b1feb7..d54c19066 100644 --- a/src/utils/moddump_sphNG2phantom.f90 +++ b/src/utils/moddump_sphNG2phantom.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_sphNG2phantom_addBfield.f90 b/src/utils/moddump_sphNG2phantom_addBfield.f90 index e33c1cb92..2e850e669 100644 --- a/src/utils/moddump_sphNG2phantom_addBfield.f90 +++ b/src/utils/moddump_sphNG2phantom_addBfield.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_sphNG2phantom_disc.f90 b/src/utils/moddump_sphNG2phantom_disc.f90 index 7e7e3a159..fe2a452f2 100644 --- a/src/utils/moddump_sphNG2phantom_disc.f90 +++ b/src/utils/moddump_sphNG2phantom_disc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_splitpart.f90 b/src/utils/moddump_splitpart.f90 index 9f932cffc..6cc36bb0a 100644 --- a/src/utils/moddump_splitpart.f90 +++ b/src/utils/moddump_splitpart.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_taylorgreen.f90 b/src/utils/moddump_taylorgreen.f90 index f165d49b6..3df62ba91 100644 --- a/src/utils/moddump_taylorgreen.f90 +++ b/src/utils/moddump_taylorgreen.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_tidal.f90 b/src/utils/moddump_tidal.f90 index a4a1b4b51..c5277d7f0 100644 --- a/src/utils/moddump_tidal.f90 +++ b/src/utils/moddump_tidal.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/moddump_torus.f90 b/src/utils/moddump_torus.f90 index 3de87ae9a..90871d7a2 100644 --- a/src/utils/moddump_torus.f90 +++ b/src/utils/moddump_torus.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/multirun.f90 b/src/utils/multirun.f90 index 5536cdcf5..d883477d4 100644 --- a/src/utils/multirun.f90 +++ b/src/utils/multirun.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/multirun_mach.f90 b/src/utils/multirun_mach.f90 index df2cb5b97..5ac108350 100644 --- a/src/utils/multirun_mach.f90 +++ b/src/utils/multirun_mach.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/pdfs.f90 b/src/utils/pdfs.f90 index fd306041d..e92a23c56 100644 --- a/src/utils/pdfs.f90 +++ b/src/utils/pdfs.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantom2divb.f90 b/src/utils/phantom2divb.f90 index cac56bccd..508d41c92 100644 --- a/src/utils/phantom2divb.f90 +++ b/src/utils/phantom2divb.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantom2divv.f90 b/src/utils/phantom2divv.f90 index 0befaad7d..e2187bc36 100644 --- a/src/utils/phantom2divv.f90 +++ b/src/utils/phantom2divv.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantom2gadget.f90 b/src/utils/phantom2gadget.f90 index 1681ff9cc..4471bf6f2 100644 --- a/src/utils/phantom2gadget.f90 +++ b/src/utils/phantom2gadget.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantom2hdf5.f90 b/src/utils/phantom2hdf5.f90 index d4d032e0c..dd6031996 100644 --- a/src/utils/phantom2hdf5.f90 +++ b/src/utils/phantom2hdf5.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantom2sphNG.f90 b/src/utils/phantom2sphNG.f90 index b4532fbef..358f15cc4 100644 --- a/src/utils/phantom2sphNG.f90 +++ b/src/utils/phantom2sphNG.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantom_moddump.f90 b/src/utils/phantom_moddump.f90 index a6ed9bb0d..441853aac 100644 --- a/src/utils/phantom_moddump.f90 +++ b/src/utils/phantom_moddump.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantomanalysis.f90 b/src/utils/phantomanalysis.f90 index 94ccc3695..5767dae0d 100644 --- a/src/utils/phantomanalysis.f90 +++ b/src/utils/phantomanalysis.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantomevcompare.f90 b/src/utils/phantomevcompare.f90 index 8a0d15062..efbb4eb9a 100644 --- a/src/utils/phantomevcompare.f90 +++ b/src/utils/phantomevcompare.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/phantomextractsinks.f90 b/src/utils/phantomextractsinks.f90 index 1e4577fde..3cc2a7c07 100644 --- a/src/utils/phantomextractsinks.f90 +++ b/src/utils/phantomextractsinks.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/plot_kernel.f90 b/src/utils/plot_kernel.f90 index 35b176884..fe7789391 100644 --- a/src/utils/plot_kernel.f90 +++ b/src/utils/plot_kernel.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/powerspectrums.f90 b/src/utils/powerspectrums.f90 index de772a8b6..4447e2c32 100644 --- a/src/utils/powerspectrums.f90 +++ b/src/utils/powerspectrums.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/prompting.f90 b/src/utils/prompting.f90 index b68033c5f..60810ef1d 100644 --- a/src/utils/prompting.f90 +++ b/src/utils/prompting.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/quartic.f90 b/src/utils/quartic.f90 index 4ae9ee375..6d03dec7d 100644 --- a/src/utils/quartic.f90 +++ b/src/utils/quartic.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/rhomach.f90 b/src/utils/rhomach.f90 index 8164eb3a2..04597f46c 100644 --- a/src/utils/rhomach.f90 +++ b/src/utils/rhomach.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/showarrays.f90 b/src/utils/showarrays.f90 index 64762b59c..090a9f8ce 100644 --- a/src/utils/showarrays.f90 +++ b/src/utils/showarrays.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/showheader.f90 b/src/utils/showheader.f90 index b70b1a884..c97969471 100644 --- a/src/utils/showheader.f90 +++ b/src/utils/showheader.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/solvelinearsystem.f90 b/src/utils/solvelinearsystem.f90 index fefb6c08e..30f760d9b 100644 --- a/src/utils/solvelinearsystem.f90 +++ b/src/utils/solvelinearsystem.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/splitpart.f90 b/src/utils/splitpart.f90 index c6847e607..8bf2ef2f3 100644 --- a/src/utils/splitpart.f90 +++ b/src/utils/splitpart.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/struct2struct.f90 b/src/utils/struct2struct.f90 index 2d22707f3..f2d2b763e 100644 --- a/src/utils/struct2struct.f90 +++ b/src/utils/struct2struct.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/struct_part.f90 b/src/utils/struct_part.f90 index 99640148d..8bf30340d 100644 --- a/src/utils/struct_part.f90 +++ b/src/utils/struct_part.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/tabulate_metric.f90 b/src/utils/tabulate_metric.f90 index c02d2a870..70b982172 100644 --- a/src/utils/tabulate_metric.f90 +++ b/src/utils/tabulate_metric.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/test_binary.f90 b/src/utils/test_binary.f90 index 4dd432524..84b8132ff 100644 --- a/src/utils/test_binary.f90 +++ b/src/utils/test_binary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/testbinary.f90 b/src/utils/testbinary.f90 index f7da761f8..93a804d70 100644 --- a/src/utils/testbinary.f90 +++ b/src/utils/testbinary.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_disc.f90 b/src/utils/utils_disc.f90 index 0e47329c6..ba3f37dec 100644 --- a/src/utils/utils_disc.f90 +++ b/src/utils/utils_disc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_ephemeris.f90 b/src/utils/utils_ephemeris.f90 index 91ad77224..f24868aeb 100644 --- a/src/utils/utils_ephemeris.f90 +++ b/src/utils/utils_ephemeris.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_evfiles.f90 b/src/utils/utils_evfiles.f90 index 515da58e6..65d714c29 100644 --- a/src/utils/utils_evfiles.f90 +++ b/src/utils/utils_evfiles.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_getneighbours.F90 b/src/utils/utils_getneighbours.F90 index d63d33e1c..19bbab221 100644 --- a/src/utils/utils_getneighbours.F90 +++ b/src/utils/utils_getneighbours.F90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_gravwave.f90 b/src/utils/utils_gravwave.f90 index 5f568aaad..006aedd9c 100644 --- a/src/utils/utils_gravwave.f90 +++ b/src/utils/utils_gravwave.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_linalg.f90 b/src/utils/utils_linalg.f90 index c4c6c22bd..2f96b13ea 100644 --- a/src/utils/utils_linalg.f90 +++ b/src/utils/utils_linalg.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_mpc.f90 b/src/utils/utils_mpc.f90 index 3a90abd94..2bbdf9430 100644 --- a/src/utils/utils_mpc.f90 +++ b/src/utils/utils_mpc.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_orbits.f90 b/src/utils/utils_orbits.f90 index a92cd3da9..9347780f4 100644 --- a/src/utils/utils_orbits.f90 +++ b/src/utils/utils_orbits.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_raytracer_all.f90 b/src/utils/utils_raytracer_all.f90 index a257b00c4..37102bec1 100644 --- a/src/utils/utils_raytracer_all.f90 +++ b/src/utils/utils_raytracer_all.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/utils_splitmerge.f90 b/src/utils/utils_splitmerge.f90 index 87ec4670c..87923d06d 100644 --- a/src/utils/utils_splitmerge.f90 +++ b/src/utils/utils_splitmerge.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! diff --git a/src/utils/velfield.f90 b/src/utils/velfield.f90 index 4792a65f7..ef7aff52f 100644 --- a/src/utils/velfield.f90 +++ b/src/utils/velfield.f90 @@ -1,6 +1,6 @@ !--------------------------------------------------------------------------! ! The Phantom Smoothed Particle Hydrodynamics code, by Daniel Price et al. ! -! Copyright (c) 2007-2024 The Authors (see AUTHORS) ! +! Copyright (c) 2007-2025 The Authors (see AUTHORS) ! ! See LICENCE file for usage and distribution conditions ! ! http://phantomsph.github.io/ ! !--------------------------------------------------------------------------! From c8cbbbe6088eb36e14c805b98f255689f1380aeb Mon Sep 17 00:00:00 2001 From: Alison Young Date: Mon, 20 Jan 2025 11:43:28 +0000 Subject: [PATCH 182/182] [format-bot] end if -> endif; end do -> enddo; if( -> if ( --- src/setup/readwrite_mesa.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/setup/readwrite_mesa.f90 b/src/setup/readwrite_mesa.f90 index f5571cb52..6223034dc 100644 --- a/src/setup/readwrite_mesa.f90 +++ b/src/setup/readwrite_mesa.f90 @@ -194,7 +194,7 @@ subroutine read_mesa(filepath,rho,r,pres,m,ene,temp,X_in,Z_in,Xfrac,Yfrac,Mstar, enddo over_directions close(iu) - if(min(minval(pres),minval(rho))<0d0)ierr = 1 + if (min(minval(pres),minval(rho))<0d0)ierr = 1 if (ierr /= 0) then print "(a,/)",' ERROR reading MESA file [missing required columns]'