Skip to content

Commit

Permalink
(#612) fixed bug with relaxation in Kerr metric; now shift star away …
Browse files Browse the repository at this point in the history
…from origin during relaxation
  • Loading branch information
danieljprice committed Jan 20, 2025
1 parent 92e515b commit f90f54c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 25 deletions.
60 changes: 48 additions & 12 deletions src/setup/relax_star.f90
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np
logical, intent(in), optional :: write_dumps
real, intent(out), optional :: density_error,energy_error
integer :: nits,nerr,nwarn,iunit,i1
real :: t,dt,dtmax,rmserr,rstar,mstar,tdyn
real :: t,dt,dtmax,rmserr,rstar,mstar,tdyn,x0(3)
real :: entrop(nt),utherm(nt),mr(nt),rmax,dtext,dtnew
logical :: converged,use_step,restart
logical, parameter :: fix_entrop = .true. ! fix entropy instead of thermal energy
Expand All @@ -111,6 +111,8 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np
! save settings and set a bunch of options
!
ierr = 0
x0 = 0.
if (gr) x0 = [1000.,0.,0.] ! for GR need to shift star away from origin to avoid singularities
rstar = maxval(r)
mr = get_mr(rho,r)
mstar = mr(nt)
Expand All @@ -135,6 +137,7 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np

call set_options_for_relaxation(tdyn)
call summary_initialise()
if (gr) call shift_star_origin(i1,npart,xyzh,x0)
!
! check particle setup is sensible
!
Expand Down Expand Up @@ -177,15 +180,15 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np
ierr = ierr_no_pressure
return
endif
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,rad,nt,mr,rho,&
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,x0,rad,nt,mr,rho,&
utherm,entrop,fix_entrop,rmax,rmserr)
!
! compute derivatives the first time around (needed if using actual step routine)
!
t = 0.
call allocate_memory(int(min(2*npart,maxp),kind=8))
call get_derivs_global()
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,rad,nt,mr,rho,&
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,x0,rad,nt,mr,rho,&
utherm,entrop,fix_entrop,rmax,rmserr)
call compute_energies(t)
!
Expand Down Expand Up @@ -236,7 +239,7 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np
!
! reset thermal energy and calculate information
!
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,rad,nt,mr,&
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,x0,rad,nt,mr,&
rho,utherm,entrop,fix_entrop,rmax,rmserr)
!
! compute energies and check for convergence
Expand Down Expand Up @@ -272,26 +275,34 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np
!
if (mod(nits,100)==0 .or. ((nits==maxits .or. converged).and.nits > 1)) then
filename = getnextfilename(filename)

!
! before writing a file, set the real thermal energy profile
! so the file is useable as a starting file for the main calculation
!
if (use_var_comp) call set_star_composition(use_var_comp,&
eos_outputs_mu(ieos_prev),npart,xyzh,&
Xfrac,Yfrac,mu,mr,mstar,eos_vars,npin=i1)
Xfrac,Yfrac,mu,mr,mstar,eos_vars,npin=i1,x0=x0)

if (maxvxyzu==4) call set_star_thermalenergy(ieos_prev,rho,pr,&
r,nt,npart,xyzh,vxyzu,rad,eos_vars,.true.,&
use_var_comp=.false.,initialtemp=1.e3,npin=i1)
use_var_comp=.false.,initialtemp=1.e3,npin=i1,x0=x0)

! write relaxation snapshots
if (write_files) call write_fulldump(t,filename)
if (write_files) then
! move star back to 0,0,0
if (gr) call shift_star_origin(i1,npart,xyzh,-x0)
! write snapshot
call write_fulldump(t,filename)
! move star back to 100,0,0
if (gr) call shift_star_origin(i1,npart,xyzh,x0)
endif

! flush the relax.ev file
call flush(iunit)

! restore the fake thermal energy profile
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,rad,nt,mr,rho,&
call reset_u_and_get_errors(i1,npart,xyzh,vxyzu,x0,rad,nt,mr,rho,&
utherm,entrop,fix_entrop,rmax,rmserr)
endif
endif
Expand Down Expand Up @@ -321,6 +332,9 @@ subroutine relax_star(nt,rho,pr,r,npart,xyzh,use_var_comp,Xfrac,Yfrac,mu,ierr,np
!
call restore_original_options(i1,npart)

! move star back to 0,0,0
if (gr) call shift_star_origin(i1,npart,xyzh,-x0)

end subroutine relax_star

!----------------------------------------------------------------
Expand Down Expand Up @@ -387,14 +401,36 @@ subroutine shift_particles(i1,npart,xyzh,vxyzu,dtmin)

end subroutine shift_particles

!----------------------------------------------------------------
!+
! shift the origin of the star, mainly to avoid coordinate
! singularities in GR code
!+
!----------------------------------------------------------------
subroutine shift_star_origin(i1,npart,xyzh,x0)
integer, intent(in) :: i1,npart
real, intent(inout) :: xyzh(:,:)
real, intent(in) :: x0(3)
integer :: i

!$omp parallel do schedule(guided) default(none) &
!$omp shared(xyzh,x0) &
!$omp private(i)
do i=i1+1,npart
xyzh(1:3,i) = xyzh(1:3,i) + x0
enddo
!$omp end parallel do

end subroutine shift_star_origin

!----------------------------------------------------------------
!+
! reset the thermal energy to be exactly p(r)/((gam-1)*rho(r))
! according to the desired p(r) and rho(r)
! also compute error between true rho(r) and desired rho(r)
!+
!----------------------------------------------------------------
subroutine reset_u_and_get_errors(i1,npart,xyzh,vxyzu,rad,nt,mr,rho,&
subroutine reset_u_and_get_errors(i1,npart,xyzh,vxyzu,x0,rad,nt,mr,rho,&
utherm,entrop,fix_entrop,rmax,rmserr)
use table_utils, only:yinterp
use part, only:rhoh,massoftype,igas,maxvxyzu
Expand All @@ -403,7 +439,7 @@ subroutine reset_u_and_get_errors(i1,npart,xyzh,vxyzu,rad,nt,mr,rho,&
use eos, only:gamma
use setstar_utils, only:get_mass_coord
integer, intent(in) :: i1,npart,nt
real, intent(in) :: xyzh(:,:),mr(nt),rho(nt),utherm(nt),entrop(nt)
real, intent(in) :: xyzh(:,:),x0(3),mr(nt),rho(nt),utherm(nt),entrop(nt)
real, intent(inout) :: vxyzu(:,:),rad(:,:)
real, intent(out) :: rmax,rmserr
logical, intent(in) :: fix_entrop
Expand All @@ -415,11 +451,11 @@ subroutine reset_u_and_get_errors(i1,npart,xyzh,vxyzu,rad,nt,mr,rho,&
rmax = 0.
rmserr = 0.

call get_mass_coord(i1,npart,xyzh,mass_enclosed_r)
call get_mass_coord(i1,npart,xyzh,mass_enclosed_r,x0)
mstar = mr(nt)

do i = i1+1,npart
ri = sqrt(dot_product(xyzh(1:3,i),xyzh(1:3,i)))
ri = sqrt(dot_product(xyzh(1:3,i)-x0,xyzh(1:3,i)-x0))
massri = mass_enclosed_r(i-i1)
rhor = yinterp(rho,mr,massri) ! analytic rho(r)

Expand Down
34 changes: 21 additions & 13 deletions src/setup/set_star_utils.f90
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,12 @@ end subroutine set_stellar_core
! this gives the mass enclosed EXCLUSIVE of self, i.e. m(<r)
!+
!----------------------------------------------------------------
subroutine get_mass_coord(i1,npart,xyzh,mass_enclosed_r)
subroutine get_mass_coord(i1,npart,xyzh,mass_enclosed_r,x0)
use dim, only:use_apr
use part, only:igas,apr_level,massoftype,aprmassoftype
use sortutils, only:sort_by_radius
integer, intent(in) :: i1,npart
real, intent(in) :: xyzh(:,:)
real, intent(in) :: xyzh(:,:),x0(3)
real, intent(out), allocatable :: mass_enclosed_r(:)
integer, allocatable :: iorder(:)
real :: massri,mass_at_r,pmassi,r2,r2prev
Expand All @@ -373,7 +373,7 @@ subroutine get_mass_coord(i1,npart,xyzh,mass_enclosed_r)
allocate(mass_enclosed_r(npart-i1),iorder(npart-i1))

! sort particles by radius
call sort_by_radius(npart-i1,xyzh(:,i1+1:npart),iorder)
call sort_by_radius(npart-i1,xyzh(:,i1+1:npart),iorder,x0)

! calculate cumulative mass
massri = 0.
Expand All @@ -387,7 +387,7 @@ subroutine get_mass_coord(i1,npart,xyzh,mass_enclosed_r)
else
pmassi = massoftype(igas)
endif
r2 = dot_product(xyzh(1:3,j),xyzh(1:3,j))
r2 = dot_product(xyzh(1:3,j)-x0,xyzh(1:3,j)-x0)
!
! key point here is to handle the situation where particles are at the same
! radius, in which case they should get the same mass coordinate so that
Expand All @@ -414,24 +414,28 @@ end subroutine get_mass_coord
!+
!-----------------------------------------------------------------------
subroutine set_star_composition(use_var_comp,use_mu,npart,xyzh,Xfrac,Yfrac,&
mu,mtab,Mstar,eos_vars,npin)
mu,mtab,Mstar,eos_vars,npin,x0)
use part, only:iX,iZ,imu ! borrow the unused linklist array for the sort
use table_utils, only:yinterp
logical, intent(in) :: use_var_comp,use_mu
integer, intent(in) :: npart
real, intent(in) :: xyzh(:,:)
real, intent(in) :: Xfrac(:),Yfrac(:),mu(:),mtab(:),Mstar
real, intent(out) :: eos_vars(:,:)
real, intent(in), optional :: x0(3)
integer, intent(in), optional :: npin
real, allocatable :: mass_enclosed_r(:)
real :: massri
real :: massri,xorigin(3)
integer :: i,i1

i1 = 0
if (present(npin)) i1 = npin ! starting position in particle array

xorigin = 0.
if (present(x0)) xorigin = x0

! this does NOT work with MPI
call get_mass_coord(i1,npart,xyzh,mass_enclosed_r)
call get_mass_coord(i1,npart,xyzh,mass_enclosed_r,xorigin)

do i = i1+1,npart
massri = mass_enclosed_r(i-i1)/Mstar
Expand All @@ -450,7 +454,7 @@ end subroutine set_star_composition
!+
!-----------------------------------------------------------------------
subroutine set_star_thermalenergy(ieos,den,pres,r,npts,npart,xyzh,vxyzu,rad,eos_vars,&
relaxed,use_var_comp,initialtemp,npin)
relaxed,use_var_comp,initialtemp,npin,x0)
use part, only:do_radiation,rhoh,massoftype,igas,itemp,igasP,iX,iZ,imu,iradxi
use eos, only:equationofstate,calc_temp_and_ene,gamma,gmw
use radiation_utils, only:ugas_from_Tgas,radxi_from_Trad
Expand All @@ -463,15 +467,19 @@ subroutine set_star_thermalenergy(ieos,den,pres,r,npts,npart,xyzh,vxyzu,rad,eos_
logical, intent(in) :: relaxed,use_var_comp
real, intent(in) :: initialtemp
integer, intent(in), optional :: npin
real, intent(in), optional :: x0(3)
integer :: eos_type,i,ierr
real :: xi,yi,zi,hi,presi,densi,tempi,eni,ri,p_on_rhogas,spsoundi
real :: rho_cgs,p_cgs
real :: rho_cgs,p_cgs,xorigin(3)
integer :: i1

i1 = 0
eni = 0. ! to prevent compiler warning
if (present(npin)) i1 = npin ! starting position in particle array

xorigin = 0.
if (present(x0)) xorigin = x0

if (do_radiation) then
eos_type=12 ! Calculate temperature from both gas and radiation pressure
else
Expand All @@ -484,7 +492,7 @@ subroutine set_star_thermalenergy(ieos,den,pres,r,npts,npart,xyzh,vxyzu,rad,eos_
presi = eos_vars(igasP,i) ! retrieve pressure from relax_star calculated with the fake (ieos=2) internal energy
else
! Interpolate density and pressure from table
ri = sqrt(dot_product(xyzh(1:3,i),xyzh(1:3,i)))
ri = sqrt(dot_product(xyzh(1:3,i)-xorigin,xyzh(1:3,i)-xorigin))
densi = yinterp(den(1:npts),r(1:npts),ri)
presi = yinterp(pres(1:npts),r(1:npts),ri)
endif
Expand All @@ -495,9 +503,9 @@ subroutine set_star_thermalenergy(ieos,den,pres,r,npts,npart,xyzh,vxyzu,rad,eos_
case(16) ! Shen EoS
vxyzu(4,i) = initialtemp
case(15) ! Helmholtz EoS
xi = xyzh(1,i)
yi = xyzh(2,i)
zi = xyzh(3,i)
xi = xyzh(1,i) - xorigin(1)
yi = xyzh(2,i) - xorigin(2)
zi = xyzh(3,i) - xorigin(3)
tempi = initialtemp
call equationofstate(ieos,p_on_rhogas,spsoundi,densi,xi,yi,zi,tempi,eni)
vxyzu(4,i) = eni
Expand Down

0 comments on commit f90f54c

Please sign in to comment.