https://github.com/jadexter/grtrans
Tip revision: c76cb11fa1396516f38ba6f972c68fbb5b5ae984 authored by Jason Dexter on 08 March 2021, 22:06:47 UTC
testing new intel compiler fix
testing new intel compiler fix
Tip revision: c76cb11
kerr.f90
module kerr
use class_four_Vector
use math, only: dot_product
use phys_constants, only: msun, G, c, sigt, pi, mp
implicit none
interface surf_integral
module procedure surf_integral
module procedure th_integral
module procedure ph_integral
end interface
interface kerr_metric
module procedure blmetric_cov
module procedure blmetric_con
module procedure blmetric_cov_real
module procedure blmetric_con_real
module procedure ksmetric_cov
! module procedure ksmetric_con
! module procedure kstmetric_sph
! module procedure kstmetric_car
end interface
interface lnrf_frame
module procedure lnrf_frame
module procedure lnrf_frame_inv
module procedure lnrf_frame_real
module procedure lnrf_frame_inv_real
end interface
interface bl2ks
module procedure bl2ks_phi
module procedure bl2ks_time
module procedure bl2ks_phi_single
module procedure bl2ks_time_single
end interface
interface uks2ubl
module procedure uks2ubl
end interface
! interface calc_kb_ang
! module procedure calc_kb_ang
! end interface
interface calcg
module procedure calcg
end interface
interface comoving_ortho
module procedure comoving_ortho
end interface
interface calc_rms
module procedure calc_rms
end interface
interface krolikc
module procedure krolikc
end interface
interface ledd
module procedure ledd
end interface
interface calc_polar_psi
module procedure calc_polar_psi
end interface
interface calc_polvec
module procedure calc_polvec
end interface
interface calc_kappapw
module procedure calc_kappapw
end interface
interface calc_u0
module procedure calc_u0
end interface
interface rms_vel
module procedure rms_vel
end interface
interface calc_plunging_vel
module procedure calc_plunging_vel
end interface calc_plunging_vel
contains
function ledd(m) result(leddval)
real(kind=8) :: leddval
real, intent(in) :: m
! Eddington luminosity
leddval=4.*pi*G*m*msun*mp*c/sigt
end function ledd
function calc_rms(a) result(rms)
real, intent(in) :: a
real :: rms,z1,z2
z1=1.+(1.-a*a)**(1./3.)*((1.+a)**(1./3.)+(1.-a)**(1./3.))
z2=sqrt(3.*a*a+z1*z1)
rms=3.+z2-sign(sqrt((3.-z1)*(3.+z1+2.*z2)),a)
end function calc_rms
function krolikc(r,a) result(kc)
real, intent(in) :: a
real :: rms, pi
real, dimension(:), intent(in) :: r
real, dimension(size(r)) :: kc,y,yms,y1,y2,y3,arg1,arg2,arg3,arg4
pi=acos(-1.)
rms=calc_rms(a)
y=sqrt(r)
yms=sqrt(rms)
y1=2d0*cos(1./3.*(acos(a)-pi))
y2=2d0*cos(1./3.*(acos(a)+pi))
y3=-2d0*cos(1./3.*acos(a))
arg1=3.*a/(2d0*y)
arg2=3.*(y1-a)**2d0/(y*y1*(y1-y2)*(y1-y3))
arg3=3.*(y2-a)**2d0/(y*y2*(y2-y1)*(y2-y3))
arg4=3.*(y3-a)**2d0/(y*y3*(y3-y1)*(y3-y2))
kc=1.-yms/y-arg1*log(y/yms)-arg2*log((y-y1)/(yms-y1))- &
arg3*log((y-y2)/(yms-y2))-arg4*log((y-y3)/(yms-y3))
! write(6,*) 'krolikc: ',kc,arg1,arg2,arg3,arg4,y1,y2,y3
! write(6,*) 'krolikc: ',a,yms,(y-y2)/(yms-y2), (y-y1)/(yms-y1),(y-y3)/(yms-y3)
end function krolikc
function uks2ubl(fut,r,a) result(fu)
! Converts a Kerr-Schild spherical 4-velocity to a Boyer-Lindquist one.
! JAD 11/10/2008
type (four_vector), dimension(:), intent(in) :: fut
real(kind=8), dimension(:), intent(in) :: r
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(r)) :: delta
type (four_vector), dimension(size(fut)) :: fu
delta=r**2d0-2d0*r+a**2
fu=fut
! from Font+1999
fu%data(1)=fut%data(1)-2d0*r/delta*fut%data(2)
fu%data(4)=fut%data(4)-a/delta*fut%data(2)
end function uks2ubl
function bl2ks_time(r,x,a,time) result(xtilde)
real(kind=8), dimension(:), intent(in) :: r,x
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(x)) :: xtilde
integer, intent(in) :: time
! Function to convert t/phi from Boyer-Lindquist coordinates to Kerr-Schild coordinates as shown in PF98 and FIP99
xtilde=x+log(r**2-2*r+a**2)+1./(2d0*sqrt(1.-a**2))*log((r-1.-sqrt(1.-a**2))/(r-1+sqrt(1.-a**2)))
end function bl2ks_time
function bl2ks_phi(r,x,a) result(xtilde)
real(kind=8), dimension(:), intent(in) :: r,x
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(x)) :: xtilde
! Function to convert t/phi from Boyer-Lindquist coordinates to Kerr-Schild coordinates as shown in PF98 and FIP99
xtilde=x+a/(2d0*sqrt(1.-a**2))*log((r-1.-sqrt(1.-a**2))/(r-1.+sqrt(1.-a**2)))
end function bl2ks_phi
function bl2ks_time_single(r,x,a,time) result(xtilde)
real(kind=8), intent(in) :: r,x
real(kind=8), intent(in) :: a
real(kind=8) :: xtilde
integer, intent(in) :: time
! Function to convert t/phi from Boyer-Lindquist coordinates to Kerr-Schild coordinates as shown in PF98 and FIP99
xtilde=x+log(r**2-2*r+a**2)+1./(2d0*sqrt(1.-a**2))*log((r-1.-sqrt(1.-a**2))/(r-1+sqrt(1.-a**2)))
end function bl2ks_time_single
function bl2ks_phi_single(r,x,a) result(xtilde)
real(kind=8), intent(in) :: r,x
real(kind=8), intent(in) :: a
real(kind=8) :: xtilde
! Function to convert t/phi from Boyer-Lindquist coordinates to Kerr-Schild coordinates as shown in PF98 and FIP99
xtilde=x+a/(2d0*sqrt(1.-a**2))*log((r-1.-sqrt(1.-a**2))/(r-1.+sqrt(1.-a**2)))
end function bl2ks_phi_single
FUNCTION CALCG(U,MU,Q2,L,A,TPM,TPR,SU,SM,VRL,VTL,VPL) result(g)
real(kind=8), dimension(:), intent(in) :: su,sm,u,mu,tpm,tpr,vrl,vtl,vpl,q2,l
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(u)) :: zero,r,z1,z2,rms,d,ar,rho,enu, &
emu1,emu2,epsi,om,sr,st,omega,gam,rr,tt,g
real(kind=8) :: one,two,tres,third
! see 2/25/99 notes, p.17
zero=0.d0
ONE=1.d0
TWO=2D0
TRES=3.d0
THIRD=ONE/TRES
R=ONE/U
Z1=ONE+(ONE-A*A)**THIRD*((ONE+A)**THIRD+(ONE-A)**THIRD)
Z2=SQRT(TRES*A*A+Z1*Z1)
RMS=TRES+Z2-SIGN(1.d0,A)*SQRT((TRES-Z1)*(TRES+Z1+TWO*Z2))
D=R*R-TWO*R+A*A
AR=(R*R+A*A)**2-A*A*D*(ONE-MU*MU)
RHO=R*R+A*A*MU*MU
ENU=SQRT(D*RHO/AR)
EMU1=SQRT(RHO/D)
EMU2=SQRT(RHO)
EPSI=SQRT(ONE-MU*MU)*SQRT(AR/RHO)
OM=TWO*A*R/AR
SR=(-ONE)**TPR*SU
ST=-(-ONE)**TPM*SM
! Now, compute velocities in LNRF
OMEGA=ENU/EPSI*VPL+OM
omega=merge(omega,zero,epsi.ne.0d0)
GAM=ONE/SQRT(ONE-(VRL*VRL+VTL*VTL+VPL*VPL))
! Now, compute R(r) and Theta(theta):
RR=-A*A*Q2*U**4+TWO*U**3*(Q2+(A-L)**2)+U*U*(A*A-Q2-L*L)+ONE
TT=(Q2+MU*MU*(A*A-L*L-Q2)-A*A*MU**4)/(ONE-MU*MU)
tt=merge(sqrt(tt),zero,tt.ge.0d0)
rr=merge(sqrt(rr)*r*r,zero,rr.ge.0d0)
! Now, we can compute the redshift:
G=ENU/GAM/(ONE-L*OMEGA-EMU1*ENU*VRL/RHO*SR*RR-EMU2*ENU*VTL/RHO*ST*TT)
END FUNCTION CALCG
function calc_kb_ang(k,b,u,r,th,a) result(ang)
! Calculate angle between wave-vector and magnetic field in fluid
! frame based on Broderick (2004) covariant method
! JAD 2/8/2011
type (four_vector), dimension(:), intent(in) :: k,b,u
real(kind=8), dimension(:), intent(in) :: r,th
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(r)) :: bdotk,bdotb,kdotk,om,angnorm,ang,zero,one, &
angmin,angmax, cdot2
real(kind=8), dimension(size(r),10) :: metric
real(kind=8), dimension(10,size(r)) :: tmetric
zero=0.d0; one=1.d0; angmin=-.9999d0; angmax=0.9999d0
metric=kerr_metric(r,th,a); tmetric=transpose(metric)
call assign_metric(b,tmetric)
call assign_metric(u,tmetric)
call assign_metric(k,tmetric)
! write(6,*) 'metric: ',b(1)%metric, u(1)%metric,k(1)%metric
! write(6,*) 'vectors: ',b(1)%data,u(1)%data,k(1)%data
bdotk=b*k
bdotb=b*b
kdotk=k*k
om=-k*u
! angnorm=bdotk/sqrt(om*om)/sqrt(bdotb)
! ang=acos(merge(merge(angnorm,angmax,angnorm.le.0.9999d0),angmin, &
! angnorm.ge.-.9999d0))
cdot2=bdotk*bdotk/bdotb/(kdotk+om*om)
! write(6,*) 'kb: ',r,th,a
! write(6,*) 'kb: ',k(1)%data, b(1)%data, u(1)%data
! write(6,*) 'cdot2: ',cdot2,bdotk,bdotb,kdotk,om*om
cdot2=merge(merge(cdot2,zero,cdot2.ge.0.d0),one,cdot2.le.1.d0)
ang=acos(sign(1d0,bdotk)*sqrt(cdot2))
end function calc_kb_ang
function calc_nullp(q2,l,a,r,mu,su,smu,rcomp,thcomp) result(k)
real(kind=8), intent(in) :: q2,l,a
real(kind=8), dimension(:), intent(in) :: r,mu,su,smu
integer, intent(in), optional :: rcomp,thcomp
real(kind=8), dimension(size(r)) :: zero,Mfunc,Ufunc, &
rho2,delta,u,pu,pt,pmu,pphi,Rfunc
type (four_Vector), dimension(size(r)) :: k
zero=0d0
u=1d0/r
rho2=r*r+a*a*mu*mu
delta=r*r-2.d0*r+a*a
Mfunc=q2+(a*a-q2-l*l)*mu*mu-a*a*mu*mu*mu*mu
Mfunc=merge(Mfunc,zero,Mfunc.gt.0d0)
if(present(thcomp)) then
! This is negative of RB94 to account for dlambda -> -dlambda for forward in time.
! see 12/11/12 notes
pmu=1d0/rho2*smu*sqrt(Mfunc/(1.d0-mu*mu))
! write(6,*) 'thcomp'
else
pmu=-smu*sqrt(Mfunc)/rho2
endif
Ufunc=1.d0+(a*a-q2-l*l)*u*u+2.d0*((a-l)**2+q2)*u*u*u- &
a*a*q2*u*u*u*u
Ufunc=merge(Ufunc,zero,Ufunc.gt.0d0)
if(present(rcomp)) then
Rfunc=R*R*sqrt(Ufunc)
pu=su*Rfunc/rho2
! write(6,*) 'rcomp'
else
pu=-su*sqrt(Ufunc)/rho2
endif
pt=(-a*(a*(1.d0-mu*mu)-l)+(r*r+a*a)/delta*(r*r+a*a-a*l))/rho2
pphi=(-a+l/(1.d0-mu*mu)+a/delta*(r*r+a*a-a*l))/rho2
k%data(1)=pt; k%data(2)=pu; k%data(3)=pmu; k%data(4)=pphi
! write(6,*) 'nullp: ',pt,pu,pmu,pphi
end function calc_nullp
function blmetric_con_real(r,th,a,con) result(blmetric)
! Returns boyer-lindquist covariant metric components
! JAD 10/1/2008, fortran 3/28/2011
real, dimension(:), intent(in) :: r,th
real, intent(in) :: a
integer, intent(in) :: con
real, dimension(size(r),10) :: blmetric
! real, dimension(10,size(r)) :: gmunu
real, dimension(size(r)) :: cth,sth,delta, &
rho2,sigma
cth=cos(th); sth=sin(th)
delta=r*r-2.*r+a*a
rho2=r*r+a*a*cth*cth
sigma=(r*r+a*a)**2-a*a*delta*sth*sth
blmetric=0d0
blmetric(:,1)=-((r*r+a*a)**2-a*a*delta*sth*sth)/rho2/delta
blmetric(:,4)=-2*a*r/rho2/delta
blmetric(:,5)=delta/rho2
blmetric(:,8)=1./rho2
blmetric(:,10)=(delta-a*a*sth*sth)/delta/rho2/sth/sth
! gmunu=transpose(blmetric)
end function blmetric_con_real
function ksmetric_cov(r,th,ph,a) result(ksmetric)
! Returns boyer-lindquist covariant metric components
! JAD 10/1/2008, fortran 3/28/2011
! Doesn't actually depend on ph unless you're doing tilted metric!
real(8), dimension(:), intent(in) :: r,th,ph
real(8), intent(in) :: a
real(8), dimension(size(r),10) :: ksmetric
real(8), dimension(size(r)) :: ctheta,stheta,rho2,psi4
ctheta=cos(th); stheta=sin(th)
rho2=r**2+a**2*ctheta**2
psi4=2d0*r/rho2
ksmetric=0.
ksmetric(:,1)=-(1.-psi4)
ksmetric(:,2)=psi4
ksmetric(:,4)=-a*stheta**2*psi4
ksmetric(:,5)=1.+psi4
ksmetric(:,7)=-a*stheta**2*(1.+psi4)
ksmetric(:,8)=rho2
ksmetric(:,10)=stheta**2*(rho2+a**2*(1.+2d0*r/rho2)*stheta**2)
! write(6,*) 'ksmetric kerr: ',ksmetric(1,:)
end function ksmetric_cov
function blmetric_con(r,th,a,con) result(blmetric)
! Returns boyer-lindquist covariant metric components
! JAD 10/1/2008, fortran 3/28/2011
real(kind=8), dimension(:), intent(in) :: r,th
real(kind=8), intent(in) :: a
integer, intent(in) :: con
real(kind=8), dimension(size(r),10) :: blmetric
! real(kind=8), dimension(10,size(r)) :: gmunu
real(kind=8), dimension(size(r)) :: cth,sth,delta, &
rho2,sigma
cth=cos(th); sth=sin(th)
delta=r*r-2d0*r+a*a
rho2=r*r+a*a*cth*cth
sigma=(r*r+a*a)**2-a*a*delta*sth*sth
blmetric=0d0
blmetric(:,1)=-((r*r+a*a)**2-a*a*delta*sth*sth)/rho2/delta
blmetric(:,4)=-2d0*a*r/rho2/delta
blmetric(:,5)=delta/rho2
blmetric(:,8)=1d0/rho2
blmetric(:,10)=(delta-a*a*sth*sth)/delta/rho2/sth/sth
! gmunu=transpose(blmetric)
end function blmetric_con
function blmetric_cov_real(r,th,a) result(blmetric)
! Returns boyer-lindquist covariant metric components
! JAD 10/1/2008, fortran 3/28/2011
real, dimension(:), intent(in) :: r,th
real, intent(in) :: a
real, dimension(size(r),10) :: blmetric
! real, dimension(10,size(r)) :: gmunu
real, dimension(size(r)) :: cth,sth,delta, &
rho2,sigma
cth=cos(th); sth=sin(th)
delta=r*r-2.*r+a*a
rho2=r*r+a*a*cth*cth
sigma=(r*r+a*a)**2-a*a*delta*sth*sth
blmetric=0d0
blmetric(:,1)=-(delta-a*a*sth*sth)/rho2
blmetric(:,4)=-2.*a*r*sth*sth/rho2
blmetric(:,5)=rho2/delta
blmetric(:,8)=rho2
blmetric(:,10)=sigma/rho2*sth*sth
end function blmetric_cov_real
function blmetric_cov(r,th,a) result(blmetric)
! Returns boyer-lindquist covariant metric components
! JAD 10/1/2008, fortran 3/28/2011
real(kind=8), dimension(:), intent(in) :: r,th
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(r),10) :: blmetric
! real(kind=8), dimension(10,size(r)) :: gmunu
real(kind=8), dimension(size(r)) :: cth,sth,delta, &
rho2,sigma
cth=cos(th); sth=sin(th)
delta=r*r-2d0*r+a*a
rho2=r*r+a*a*cth*cth
sigma=(r*r+a*a)**2-a*a*delta*sth*sth
blmetric=0d0
blmetric(:,1)=-(delta-a*a*sth*sth)/rho2
blmetric(:,4)=-2d0*a*r*sth*sth/rho2
blmetric(:,5)=rho2/delta
blmetric(:,8)=rho2
blmetric(:,10)=sigma/rho2*sth*sth
end function blmetric_cov
subroutine lnrf_frame(vr,vt,omega,r,a,th,vrl,vtl,vpl)
real(kind=8), dimension(:), intent(in) :: vr,vt,omega,r,th
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(r)), intent(out) :: vrl,vtl,vpl
real(kind=8), dimension(size(r)) :: zero,d,ar,rho,enu,emu1, &
emu2,epsi,om,mu
zero=0d0
mu=cos(th)
D=R*R-2d0*R+A*A
AR=(R*R+A*A)**2-A*A*D*(1.-MU*MU)
RHO=R*R+A*A*MU*MU
ENU=SQRT(D*RHO/AR)
EMU1=SQRT(RHO/D)
EMU2=SQRT(RHO)
EPSI=SQRT(1.-MU*MU)*SQRT(AR/RHO)
OM=2d0*A*R/AR
VRL=EMU1/ENU*VR
VTL=EMU2/ENU*VT
VPL=EPSI/ENU*(OMEGA-OM)
VRL=MERGE(VRL,ZERO,D.GT.0d0)
VTL=MERGE(VTL,ZERO,D.GT.0d0)
! VPL=MERGE(VPL,ZERO,(D.GT.0d0.AND.ABS(MU).LT.1d0))
VPL=MERGE(VPL,ZERO,D.GT.0d0)
end subroutine lnrf_frame
subroutine lnrf_frame_real(vr,vt,omega,r,a,th,vrl,vtl,vpl)
real, dimension(:), intent(in) :: vr,vt,omega,r,th
real, intent(in) :: a
real, dimension(size(r)), intent(out) :: vrl,vtl,vpl
real, dimension(size(r)) :: zero,d,ar,rho,enu,emu1, &
emu2,epsi,om,mu
zero=0d0
mu=cos(th)
D=R*R-2.*R+A*A
AR=(R*R+A*A)**2-A*A*D*(1.-MU*MU)
RHO=R*R+A*A*MU*MU
ENU=SQRT(D*RHO/AR)
EMU1=SQRT(RHO/D)
EMU2=SQRT(RHO)
EPSI=SQRT(1.-MU*MU)*SQRT(AR/RHO)
OM=2.*A*R/AR
VRL=EMU1/ENU*VR
VTL=EMU2/ENU*VT
VPL=EPSI/ENU*(OMEGA-OM)
VRL=MERGE(VRL,ZERO,D.GT.0d0)
VTL=MERGE(VTL,ZERO,D.GT.0d0)
VPL=MERGE(VPL,ZERO,D.GT.0d0)
end subroutine lnrf_frame_real
subroutine lnrf_frame_inv(vr,vt,omega,r,a,th,vrl,vtl,vpl,inv)
real(kind=8), dimension(:), intent(in) :: vr,vt,omega,r,th
real(kind=8), intent(in) :: a
integer, intent(in) :: inv
real(kind=8), dimension(size(r)), intent(out) :: vrl,vtl,vpl
real(kind=8), dimension(size(r)) :: zero,d,ar,rho,enu,emu1, &
emu2,epsi,om,mu
zero=0d0
mu=cos(th)
D=R*R-2.*R+A*A
AR=(R*R+A*A)**2-A*A*D*(1.-MU*MU)
RHO=R*R+A*A*MU*MU
ENU=SQRT(D*RHO/AR)
EMU1=SQRT(RHO/D)
EMU2=SQRT(RHO)
EPSI=SQRT(1.-MU*MU)*SQRT(AR/RHO)
OM=2.*A*R/AR
VRL=ENU/EMU1*VR
VTL=ENU/EMU2*VT
VPL=ENU/EPSI*OMEGA+OM
VRL=MERGE(VRL,ZERO,D.GT.0d0)
VTL=MERGE(VTL,ZERO,D.GT.0d0)
VPL=MERGE(VPL,ZERO,D.GT.0d0)
end subroutine lnrf_frame_inv
subroutine lnrf_frame_inv_real(vr,vt,omega,r,a,th,vrl,vtl, &
vpl,inv)
real, dimension(:), intent(in) :: vr,vt,omega,r,th
real, intent(in) :: a
integer, intent(in) :: inv
real, dimension(size(r)), intent(out) :: vrl,vtl,vpl
real, dimension(size(r)) :: zero,d,ar,rho,enu,emu1, &
emu2,epsi,om,mu
zero=0d0
mu=cos(th)
D=R*R-2.*R+A*A
AR=(R*R+A*A)**2-A*A*D*(1.-MU*MU)
RHO=R*R+A*A*MU*MU
ENU=SQRT(D*RHO/AR)
EMU1=SQRT(RHO/D)
EMU2=SQRT(RHO)
EPSI=SQRT(1.-MU*MU)*SQRT(AR/RHO)
OM=2.*A*R/AR
VRL=ENU/EMU1*VR
VTL=ENU/EMU2*VT
VPL=ENU/EPSI*OMEGA+OM
VRL=MERGE(VRL,ZERO,D.GT.0d0)
VTL=MERGE(VTL,ZERO,D.GT.0d0)
VPL=MERGE(VPL,ZERO,D.GT.0d0)
end subroutine lnrf_frame_inv_real
subroutine transport_perpk(kvec,r,th,a,metric,Kap1,Kap2,f1, &
f2,f3)
! Calculate components of parallel transported vector with
! Walker-Penrose constants Kap1, Kap2 at locations
!r,th in Boyer-Lindquist coordinates assuming f0=0.
! JAD 2/22/2011 from notes
real(kind=8), intent(in), dimension(:) :: r,th
type (four_Vector), dimension(:), intent(in) :: kvec
real(kind=8), intent(in) :: a,Kap1,Kap2
real(kind=8), intent(in), dimension(:,:) :: metric
real(kind=8), intent(out), dimension(size(r)) :: f1,f2,f3
real(kind=8), dimension(size(r)) :: g03,g11,g22,g33, &
cth,sth,k0,k1,k2,k3,gam1,gam2,gam3,del1,del2,del3,denom
! ! write(6,*) 'perpk', size(metric,1), size(metric,2)
g03=metric(:,4); g11=metric(:,5)
g22=metric(:,8); g33=metric(:,10)
! ! write(6,*) 'perpk metric'
cth=cos(th); sth=sin(th)
! ! write(6,*) 'perpk kk: ',kvec%data(1),
! & kvec%data(2),kvec%data(3),
! & kvec%data(4),kvec*kvec
k0=kvec%data(1); k1=kvec%data(2)
k2=kvec%data(3); k3=kvec%data(4)
! ! write(6,*) 'perpk k'
gam1=a*cth*k0-a*a*cth*sth*sth*k3
gam2=r*(r*r+a*a)*sth*k3-a*r*sth*k0
gam3=a*a*cth*sth*sth*k1-r*(r*r+a*a)*sth*k2
del1=r*k0-r*a*sth*sth*k3
! del2=a*cth*sth*(r*r+a*a)*k3-a*a*sth*cth*k0
! sign changed 8/24/2015 see notes! leads to small changes ~% usually
del2=-a*cth*sth*(r*r+a*a)*k3+a*a*sth*cth*k0
del3=r*a*sth*sth*k1+a*cth*sth*(r*r+a*a)*k2
! new version based on mathematica notebook 2/23/2015 trying to avoid denominator problems
! changed back to version in mathematica notebook now that i am using correct initial Kap1, Kap2 and not swapped
denom=(gam2*del1-gam1*del2)*(g33*k3+g03*k0)+(gam3*del2-gam2*del3)*g11*k1-(gam3*del1-gam1*del3)*g22*k2
f1=(gam2*Kap1-del2*Kap2)*(g33*k3+g03*k0)-g22*k2*(gam3*Kap1-del3*Kap2)
f2=(del1*Kap2-gam1*Kap1)*(g33*k3+g03*k0)+g11*k1*(gam3*Kap1-del3*Kap2)
f3=g22*k2*(gam1*Kap1-del1*Kap2)-g11*k1*(gam2*Kap1-del2*Kap2)
! f1=(gam2*Kap2-del2*Kap1)*(g33*k3+g03*k0)-g22*k2*(gam3*Kap2-del3*Kap1)
! f2=(del1*Kap1-gam1*Kap2)*(g33*k3+g03*k0)+g11*k1*(gam3*Kap2-del3*Kap1)
! f3=g22*k2*(gam1*Kap2-del1*Kap1)-g11*k1*(gam2*Kap2-del2*Kap1)
where(abs(denom).gt.0d0)
f1=f1/denom
f2=f2/denom
f3=f3/denom
endwhere
end subroutine transport_perpk
subroutine comoving_ortho(r,th,a,alpha,beta,mus,u,b,k, &
s2xi,c2xi,ang,g,cosne)
type (four_Vector), dimension(:), intent(in) :: u,b,k
real(kind=8), dimension(:), intent(in) :: r,th
real(kind=8), intent(in) :: a,alpha,beta,mus
real(kind=8), intent(out), dimension(size(r)) :: s2xi,c2xi, &
ang,g,cosne
type (four_vector), dimension(size(r)) :: bhat,khat,aa
real(kind=8), dimension(size(r),3) :: aahat
call comoving_ortho_core(r,th,a,alpha,beta,mus,u,b,k,s2xi, &
c2xi,ang,g,cosne,aa,aahat,bhat,khat)
return
end subroutine comoving_ortho
subroutine comoving_ortho_debug(r,th,a,alpha,beta,mus,u,b,k, &
s2xi,c2xi,ang,g,cosne,aahat,aat,aar,aath,aaph,kht,khr,khth,khph, &
bht,bhr,bhth,bhph)
type (four_Vector), dimension(:), intent(in) :: u,b,k
real(kind=8), dimension(:), intent(in) :: r,th
real(kind=8), intent(in) :: a,alpha,beta,mus
real(kind=8), intent(out), dimension(size(r)) :: s2xi,c2xi, &
ang,g,cosne
type (four_vector), dimension(size(r)) :: bhat,khat,aa
real(kind=8), dimension(size(r),3), intent(out) :: aahat
real(kind=8), dimension(size(r)), intent(out) :: bht,bhr,bhth,bhph, &
aat,aar,aath,aaph,kht,khr,khth,khph
call comoving_ortho_core(r,th,a,alpha,beta,mus,u,b,k,s2xi, &
c2xi,ang,g,cosne,aa,aahat,bhat,khat)
bht=bhat%data(1); bhr=bhat%data(2); bhth=bhat%data(3)
bhph=bhat%data(4); kht=khat%data(1); khr=khat%data(2)
khth=khat%data(3); khph=khat%data(4)
aat=aa%data(1); aar=aa%data(2); aath=aa%data(3)
aaph=aa%data(4)
return
end subroutine comoving_ortho_debug
subroutine comoving_ortho_core(r,th,a,alpha,beta,mus,u,b,k, &
s2xi,c2xi,ang,g,cosne,aa,aahat,bhat,khat)
! Transform four-velocity u, magnetic field b and wave-vector k to the
! co-moving orthonormal frame following Beckwith et al (2008) and
! Shcherbakov & Huang (2011)
! JAD 2/14/2011, fortran 3/27/2011
! implicit none
type (four_Vector), dimension(:), intent(in) :: u,b,k
real(kind=8), dimension(:), intent(in) :: r,th
real(kind=8), intent(in) :: a,alpha,beta,mus
real(kind=8), intent(out), dimension(size(r)) :: s2xi,c2xi, &
ang,g,cosne
type (four_Vector), dimension(size(r)) :: uhat!, &
! bhat,khat
type (four_vector), dimension(size(r)), intent(out) :: bhat,khat,aa
real(kind=8), dimension(size(r),10) :: metric
real(kind=8), dimension(10,size(r)) :: tmetric
real(kind=8), dimension(size(r)) :: gtt,gtp,grr,gmm,gpp,ut, &
ur,um,up,urc,umc,utc,upc,np2,nm2,nr2,uhatt,uhatr,uhatm, &
bhatt,bhatr,bhatm,bhatp,khatt,khatr,khatm,khatp,aahatt, &
aahatm,aahatr,aahatp,delta,al1,al2,al3,uhatp,ahatt,ahatm, &
ahatr,ahatp,bdotb,bdotk,kdotk,om,om2,knorm,anorm,bpdotbp, &
bpdotbb,aadotbp,sxi,cxi,eps,one,mone,angnorm,angmin,angmax, &
cxitest,sxitest,xi,be1,be2
real(kind=8), dimension(size(r),3) :: bbhat,bphat
! real(kind=8), dimension(size(r),3) :: aahat &
! ,bbhat
real(kind=8), dimension(size(r),3), intent(out) :: aahat
type (four_Vector), dimension(size(r)) :: &
ekt,ekr,ekm,ekp,stb,srb,spb,smb,ahat
integer :: i, nr, testindx
real(kind=8) :: kap1,kap2
one=1d0; mone=-one; angmin=-0.99d0; angmax=0.99d0
eps=epsilon(eps)
metric=kerr_metric(r,th,a); tmetric=transpose(metric)
! Co-variant metric components
gtt=metric(:,1) ; gtp=metric(:,4) ; grr=metric(:,5)
gmm=metric(:,8) ; gpp=metric(:,10)
! Gather all possible four-velocity components to simplify things:
ut=u%data(1) ; ur=u%data(2) ; um=u%data(3) ; up=u%data(4)
utc=gtt*ut+gtp*up; upc=gpp*up+gtp*ut ; urc=grr*ur ; umc=um*gmm
nr=size(r)
! Find parallel transported basis e^\th, e^ph everywhere on
! ray from complex Walker-Penrose constant
! (see 2/22/2011 notes, Chandrasekhar 1983 and CS77, CPS80)
! Kap1=beta
! Kap2=-alpha-a*sqrt(1.-mus*mus)
! JAD 10/5/2015
! Kap1, Kap2 changed to be consistent with my math. accompanying change in transport_perpk leaves everything unchanged and makes it more clear.
Kap1=alpha+a*sqrt(1.-mus*mus)
Kap2=-beta
if((Kap1.ne.0d0).or.(Kap2.ne.0d0)) then
call transport_perpk(k,r,th,a,metric,Kap1,Kap2,al1,al2,al3)
else
al1=0d0; al2=0d0; al3=1d0/sqrt(metric(:,10))
endif
aa%data(1)=0d0;aa%data(2)=al1;aa%data(3)=al2;aa%data(4)=al3
call assign_metric(aa,tmetric)
! Kulkarni+2011 normalizations:
delta=r*r+a*a-2.*r
nr2=-grr*(utc*ut+upc*up)*(1.+umc*um)
nm2=gmm*(1.+umc*um)
np2=-(utc*ut+upc*up)*delta*sin(th)*sin(th)
ekt=(-1d0)*u
ekr%data(1)=(urc*ut)/sqrt(nr2); ekr%data(2)=-(utc*ut+upc*up) &
/sqrt(nr2)
ekr%data(3)=0d0; ekr%data(4)=(urc*up)/sqrt(nr2)
ekm%data(1)=(umc*ut)/sqrt(nm2); ekm%data(2)=(umc*ur)/sqrt(nm2)
ekm%data(3)=(1+umc*um)/sqrt(nm2); ekm%data(4)=(umc*up)/sqrt(nm2)
ekp%data(1)=upc/sqrt(np2); ekp%data(2)=0d0; ekp%data(3)=0d0
ekp%data(4)=-utc/sqrt(np2)
call assign_metric(ekt,tmetric); call assign_metric(ekm,tmetric)
call assign_metric(ekp,tmetric); call assign_metric(ekr,tmetric)
uhatt=ekt*u; uhatr=ekr*u; uhatm=ekm*u; uhatp=ekp*u
bhatt=ekt*b; bhatr=ekr*b; bhatm=ekm*b; bhatp=ekp*b
khatt=ekt*k; khatr=ekr*k; khatm=ekm*k; khatp=ekp*k
ahatt=ekt*aa; ahatr=ekr*aa; ahatm=ekm*aa; ahatp=ekp*aa
uhat%data(1)=uhatt; uhat%data(2)=uhatr; uhat%data(3)=uhatm; uhat%data(4)=uhatp
! now transform b, k:
bhat%data(1)=bhatt; bhat%data(2)=bhatr; bhat%data(3)=bhatm; bhat%data(4)=bhatp
khat%data(1)=khatt; khat%data(2)=khatr; khat%data(3)=khatm; khat%data(4)=khatp
ahat%data(1)=ahatt; ahat%data(2)=ahatr; ahat%data(3)=ahatm; ahat%data(4)=ahatp
call assign_metric(b,tmetric); call assign_metric(u,tmetric)
kdotk=khatr*khatr+khatm*khatm+khatp*khatp
! write(6,*) 'metric ortho: ',b(1)%metric,u(1)%metric,k(1)%metric
! write(6,*) 'vector ortho: ',b(1)%data,u(1)%data,k(1)%data
bdotk=b*k; bdotb=b*b
om=-k*u; om2=om*om
aahat(:,1)=ahatr-khat%data(2)*ahatt/khat%data(1)
aahat(:,2)=ahatm-khat%data(3)*ahatt/khat%data(1)
aahat(:,3)=ahatp-khat%data(4)*ahatt/khat%data(1)
! write(6,*) 'comoving ortho aa 2: ',aa%data(2)
! write(6,*) 'comoving ortho aa 3: ',aa%data(3)
! write(6,*) 'comoving ortho aa 4: ',aa%data(4)
! write(6,*) 'comoving ortho ahatt: ',ahatt
! write(6,*) 'comoving ortho khatt: ',khat%data(1)
! write(6,*) 'comoving ortho aahat 1: ',aahat(:,1)
! write(6,*) 'comoving ortho aahat 2: ',aahat(:,2)
! write(6,*) 'comoving ortho aahat 3: ',aahat(:,3)
! anorm=dot_product(aahat,aahat)
! write(6,*) 'anorm: ',anorm
! aahat(:,1)=aahat(:,1)/sqrt(anorm)
! aahat(:,2)=aahat(:,2)/sqrt(anorm)
! aahat(:,3)=aahat(:,3)/sqrt(anorm)
knorm=khatr*khatr+khatm*khatm+khatp*khatp
bbhat(:,1)=-(aahat(:,2)*khatp-aahat(:,3)*khatm)/sqrt(knorm)
bbhat(:,2)=-(aahat(:,3)*khatr-aahat(:,1)*khatp)/sqrt(knorm)
bbhat(:,3)=-(aahat(:,1)*khatm-aahat(:,2)*khatr)/sqrt(knorm)
bdotk=bhat%data(2)*khatr+bhat%data(3)*khatm+bhat%data(4)*khatp
! bphat(:,1)=bhat%data(2)-khatr*bdotk/knorm
! bphat(:,2)=bhat%data(3)-khatm*bdotk/knorm
! bphat(:,3)=bhat%data(4)-khatp*bdotk/knorm
! aadotbp=dot_product(aahat,bphat)
! bpdotbp=dot_product(bphat,bphat)
! bpdotbb=dot_product(bphat,bbhat)
! write(6,*) 'test aadotbp: ',aadotbp/sqrt(bpdotbp)
! write(6,*) 'test aadotbp 2: ',(aahat(:,1)*bhat%data(2)+aahat(:,2)*bhat%data(3)+bhat%data(4)*aahat(:,3))/ &
! sqrt((aahat(:,1)*bhat%data(2)+aahat(:,2)*bhat%data(3)+aahat(:,3)*bhat%data(4))**2.+(bbhat(:,1) &
! *bhat%data(2)+bbhat(:,2)*bhat%data(3)+bbhat(:,3)*bhat%data(4))**2.)
! write(6,*) 'test aadotbp max: ',maxval(abs(aadotbp-aahat(:,1)*bhat%data(2)+aahat(:,2)*bhat%data(3)+bhat%data(4)*aahat(:,3)))
! Now compute angle between polarization basis and magnetic field:
! if field is zero, emissivity = 0 so arbitrary angles to prevent NaNs
where(bdotb.gt.0d0)
aadotbp=bhat%data(2)*aahat(:,1)+bhat%data(3)*aahat(:,2)+bhat%data(4)*aahat(:,3)
bpdotbb=bhat%data(2)*bbhat(:,1)+bhat%data(3)*bbhat(:,2)+bhat%data(4)*bbhat(:,3)
s2xi=-2d0*aadotbp*bpdotbb/(aadotbp**2d0+bpdotbb**2d0)
c2xi=(bpdotbb*bpdotbb-aadotbp*aadotbp)/(aadotbp**2d0+bpdotbb**2d0)
angnorm=bdotk/sqrt(knorm)/sqrt(bdotb)
elsewhere
s2xi=0d0
c2xi=one
angnorm=0.5d0
endwhere
ang=acos(merge(merge(angnorm,angmax,angnorm.le.angmax),angmin, &
angnorm.ge.angmin))
! CHANGED SIGN following \nu = -u^\mu k_\mu = -u^t k_t = k^t in comoving ortho so g = 1 / k^t
g=1d0/khat%data(1)
cosne=g*sqrt(beta*beta+mus*mus*(alpha*alpha-a*a))/r
! if(any(isnan(s2xi)).or.any(isnan(c2xi))) then
! write(6,*) 'NaN in comoving ortho aadotbp: ',aadotbp
! write(6,*) 'NaN in comoving ortho bpdotbb: ',bpdotbb
! write(6,*) 'NaN in comoving ortho ahat: ',aa%data(2),aa%data(3),aa%data(4)
! write(6,*) 'NaN in comoving ortho Kpw: ',Kap1,Kap2
! endif
end subroutine comoving_ortho_core
subroutine comoving_ortho_debug_old(r,th,a,alpha,beta,mus,u,b,k, &
s2xi,c2xi,ang,g,aa,aahat,bhat,khat)
! Transform four-velocity u, magnetic field b and wave-vector k to the
! co-moving orthonormal frame following Beckwith et al (2008) and
! Shcherbakov & Huang (2011)
! JAD 2/14/2011, fortran 3/27/2011
! implicit none
type (four_Vector), dimension(:), intent(in) :: u,b,k
real(kind=8), dimension(:), intent(in) :: r,th
real(kind=8), intent(in) :: a,alpha,beta,mus
real(kind=8), intent(out), dimension(size(r)) :: s2xi,c2xi, &
ang,g
type (four_Vector), dimension(size(r)) :: uhat, &
bhat,khat
real(kind=8), dimension(size(r),10) :: metric
real(kind=8), dimension(10,size(r)) :: tmetric
real(kind=8), dimension(size(r)) :: gtt,gtp,grr,gmm,gpp,ut, &
ur,um,up,urc,umc,utc,upc,np2,nm2,nr2,uhatt,uhatr,uhatm, &
bhatt,bhatr,bhatm,bhatp,khatt,khatr,khatm,khatp,aahatt, &
aahatm,aahatr,aahatp,delta,al1,al2,al3,uhatp,ahatt,ahatm, &
ahatr,ahatp,bdotb,bdotk,kdotk,om,om2,knorm,bpdotbp, &
bpdotbb,aadotbp,sxi,cxi,eps,one,mone,angnorm,angmin,angmax
real(kind=8), dimension(size(r),3) :: aahat &
,bbhat
real(kind=8), dimension(size(r),3) :: bphat
type (four_Vector), dimension(size(r)) :: &
ekt,ekr,ekm,ekp,stb,srb,spb,smb,aa,ahat
integer :: i, nr
real(kind=8) :: kap1,kap2
eps=epsilon(eps)
metric=kerr_metric(r,th,a); tmetric=transpose(metric)
! Co-variant metric components
! call assign_metric(u,tmetric); call assign_metric(b,tmetric)
! call assign_metric(k,tmetric)
gtt=metric(:,1) ; gtp=metric(:,4) ; grr=metric(:,5)
gmm=metric(:,8) ; gpp=metric(:,10)
! write(6,*) 'ut ',size(r),size(th),a,alpha,beta,mus,size(u), &
! size(b), size(k)
! Gather all possible four-velocity components to simplify things:
ut=u%data(1) ; ur=u%data(2) ; um=u%data(3) ; up=u%data(4)
utc=gtt*ut+gtp*up; upc=gpp*up+gtp*ut ; urc=grr*ur ; umc=um*gmm
nr=size(r)
! write(6,*) 'a: ',a
! ! write(6,*) 'kap', nr
! Find parallel transported basis e^\th, e^ph everywhere on
! ray from complex Walker-Penrose constant
! (see 2/22 notes, Chandrasekhar 1983 and CS77, CPS80)
Kap1=beta
Kap2=-alpha-a*sqrt(1.-mus*mus)
! write(6,*) 'perpk call',Kap1,Kap2,alpha,beta
if((Kap1.ne.0d0).or.(Kap2.ne.0d0)) then
call transport_perpk(k,r,th,a,metric,Kap1,Kap2,al1,al2,al3)
write(6,*) 'out', metric(1,:)
write(6,*) 'out', al1(1)*sqrt(metric(1,5)), sqrt(metric(1,8))*al2(1), sqrt(metric(1,10))*al3(1)
else
al1=0d0; al2=0d0; al3=1d0/sqrt(metric(:,10))
endif
aa%data(1)=0d0;aa%data(2)=al1;aa%data(3)=al2;aa%data(4)=al3
call assign_metric(aa,tmetric)
! ! write(6,*) 'kdota: ',maxval(abs(k*aa)),maxval(abs(aa*aa-1))
! ! write(6,*) 'perpk'
! Kulkarni+2011 normalizations:
delta=r*r+a*a-2d0*r
! write(6,*) 'delta: ',r,a,delta,grr
nr2=-grr*(utc*ut+upc*up)*(1.+umc*um)
! ! write(6,*) 'nr2: ',utc,ut,upc,up,umc,um,nr2
nm2=gmm*(1.+umc*um)
np2=-(utc*ut+upc*up)*delta*sin(th)*sin(th)
ekt=u
ekr%data(1)=(urc*ut)/sqrt(nr2); ekr%data(2)=-(utc*ut+upc*up) &
/sqrt(nr2)
ekr%data(3)=0d0; ekr%data(4)=(urc*up)/sqrt(nr2)
ekm%data(1)=(umc*ut)/sqrt(nm2); ekm%data(2)=(umc*ur)/sqrt(nm2)
ekm%data(3)=(1+umc*um)/sqrt(nm2); ekm%data(4)=(umc*up)/sqrt(nm2)
ekp%data(1)=upc/sqrt(np2); ekp%data(2)=0d0; ekp%data(3)=0d0
ekp%data(4)=-utc/sqrt(np2)
! write(6,*) 'ek'!, urc, up, umc
call assign_metric(ekt,tmetric); call assign_metric(ekm,tmetric)
call assign_metric(ekp,tmetric); call assign_metric(ekr,tmetric)
! write(6,*) 'ek', maxval(abs(ekt*ekt+1)), maxval(abs(ekp*ekp-1))
! write(6,*) 'ek', maxval(abs(ekr*ekr-1)), maxval(abs(ekm*ekm-1))
! write(6,*) 'ek', maxval(abs(ekt*ekp)), maxval(abs(ekt*ekr)), &
! maxval(abs(ekt*ekm)), maxval(abs(ekr*ekm)),maxval(abs(ekr*ekp))
uhatt=ekt*u
uhatr=ekr*u
uhatm=ekm*u
uhatp=ekp*u
bhatt=ekt*b
bhatr=ekr*b
bhatm=ekm*b
bhatp=ekp*b
! write(6,*) 'bt: ',maxval(abs(bhatt)),maxval(abs(uhatt+1))
! write(6,*) 'bhat: ',maxval(abs(bhatr)),maxval(abs(bhatm)), &
! maxval(abs(bhatp))
! write(6,*) 'uhatr: ',uhatr,uhatp
khatt=ekt*k
khatr=ekr*k
khatm=ekm*k
khatp=ekp*k
ahatt=ekt*aa
ahatr=ekr*aa
ahatm=ekm*aa
ahatp=ekp*aa
! write(6,*) 'khatt: ', &
! maxval(abs(khatt*khatt-khatr*khatr-khatm*khatm-khatp*khatp))
! ! write(6,*) 'ahatt: ',maxval(abs(ahatt)),maxval(abs(ahatr*ahatr+ &
! ahatm*ahatm+ahatp*ahatp-1))
uhat%data(1)=uhatt
uhat%data(2)=uhatr
uhat%data(3)=uhatm
uhat%data(4)=uhatp
! write(6,*) 'uhat: ',maxval(abs(uhatt+1))
! now transform b, k:
bhat%data(1)=bhatt
bhat%data(2)=bhatr
bhat%data(3)=bhatm
bhat%data(4)=bhatp
khat%data(1)=khatt
khat%data(2)=khatr
khat%data(3)=khatm
khat%data(4)=khatp
ahat%data(1)=ahatt
ahat%data(2)=ahatr
ahat%data(3)=ahatm
ahat%data(4)=ahatp
! write(6,*) 'ahatt: ',maxval(abs(ahatt))
call assign_metric(b,tmetric)
call assign_metric(u,tmetric)
! write(6,*) 'udotu: ',u*u
! write(6,*) 'fb: ',maxval(abs(b*u)),maxval(sqrt(b*b)), &
! maxval(abs(1+u*u)),maxval(abs(k*k))
! write(6,*) 'bhat: ',b*b-(bhatt**2+bhatr**2+bhatm**2+bhatp**2)
! call assign_metric(khat,metric)
! write(6,*) 'uhatr: ',uhatr
! write(6,*) 'uhatm: ',uhatm
! write(6,*) 'uhatp: ',uhatp
kdotk=khatr*khatr+khatm*khatm+khatp*khatp
bdotk=b*k
bdotb=b*b
!! write(6,*) 'kk: ',k*k
! write(6,*) 'bdotb: ',bdotb!,bdotk,sqrt(bdotb),maxval(bdotk/sqrt(bdotb))
om=-k*u; om2=om*om
! write(6,*) 'khat: ',-khatt*uhatt,om
! write(6,*) 'uhat: ',uhatt
! ! write(6,*) 'om: ',om2, om, om2-kdotk
aahat(:,1)=ahatr-khat%data(2)*ahatt/khat%data(1)
aahat(:,2)=ahatm-khat%data(3)*ahatt/khat%data(1)
aahat(:,3)=ahatp-khat%data(4)*ahatt/khat%data(1)
! ! write(6,*) 'sane: ',maxval(abs(ahatt-khat%data(1)*ahatt/khat &
! %data(1)))
! ! write(6,*) 'adota: ',maxval(abs(aahat(:,1)**2+aahat(:,2)**2 &
! +aahat(:,3)**2-1))
knorm=khatr*khatr+khatm*khatm+khatp*khatp
! ! write(6,*) 'knorm: ',knorm
bbhat(:,1)=(aahat(:,2)*khatp-aahat(:,3)*khatm)/sqrt(knorm)
bbhat(:,2)=(aahat(:,3)*khatr-aahat(:,1)*khatp)/sqrt(knorm)
bbhat(:,3)=(aahat(:,1)*khatm-aahat(:,2)*khatr)/sqrt(knorm)
! ! write(6,*) 'aabb: ',maxval(abs(aahat(:,1))),
! & maxval(abs(aahat(:,2))),maxval(abs(aahat(:,3))),
! & maxval(abs(bbhat(:,1))),maxval(abs(bbhat(:,2))),
! & maxval(abs(bbhat(:,3)))
! ! write(6,*) 'aabb2: ',aahat
! ! write(6,*) 'khat: ',khatr,khatm,khatp
! ! write(6,*) 'aadotbb: ',bbhat(:,1)*aahat(:,1)+aahat(:,2)*bbhat(
! :,2)+aahat(:,3)*bbhat(:,3)
! write(6,*) 'bbdotbb: ',maxval(abs(bbhat(:,1)**2+bbhat(:,2)**2
! +bbhat(:,3)**2-1))
! Find perpendicular magnetic field:
! ! write(6,*) 'bdotk: ',maxval(abs(khatr*bhatr+khatm*bhatm+
! khatp*khatp-bdotk))
! ! write(6,*) 'abperp: ',maxval(abs(aahat(:,1)*bbhat(:,1)+
! aahat(:,2)*bbhat(:,2)+aahat(:,3)*bbhat(:,3))),
! maxval(abs(aahat(:,1)*khatr+aahat(:,2)*khatm+aahat(:,3)*khatp)),
! maxval(abs(bbhat(:,1)*khatr+bbhat(:,2)*khatm+bbhat(:,3)*khatp)),
! maxval(abs(dot_product(aahat,bbhat)))
bdotk=bhat%data(2)*khatr+bhat%data(3)*khatm+bhat%data(4)*khatp
! write(6,*) 'bphat: ',maxval(abs(bhat%data(1)))
! write(6,*) 'bphat: ',maxval(abs(bhat%data(2)))
bphat(:,1)=bhat%data(2)-khatr*bdotk/knorm
bphat(:,2)=bhat%data(3)-khatm*bdotk/knorm
bphat(:,3)=bhat%data(4)-khatp*bdotk/knorm
! write(6,*) 'bphat: ',maxval(abs(bphat(:,1)*khatr+bphat(:,2)*
! & khatm+bphat(:,3)*khatp))
aadotbp=dot_product(aahat,bphat)
bpdotbp=dot_product(bphat,bphat)
bpdotbb=dot_product(bphat,bbhat)
write(6,*) 'aabb: ',maxval(abs(dot_product(aahat,aahat)-1)), &
maxval(abs(dot_product(bbhat,bbhat)-1))
write(6,*) 'dot: ',maxval(aadotbp),bpdotbp,bpdotbb
! Now compute angle between polarization basis and magnetic field:
one=1d0; mone=-one; angmin=-.9999d0; angmax=-1d0*angmin
where(bpdotbp.gt.0d0)
aadotbp=bhat%data(2)*aahat(:,1)+bhat%data(3)*aahat(:,2)+bhat%data(4)*aahat(:,3)
bpdotbb=bhat%data(2)*bbhat(:,1)+bhat%data(3)*bbhat(:,2)+bhat%data(4)*bbhat(:,3)
s2xi=-2d0*aadotbp*bpdotbb/(aadotbp**2d0+bpdotbb**2d0)
c2xi=(bpdotbb*bpdotbb-aadotbp*aadotbp)/(aadotbp**2d0+bpdotbb**2d0)
sxi=aadotbp/sqrt(bpdotbp)
cxi=-bpdotbb/sqrt(bpdotbp)
angnorm=bdotk/sqrt(knorm)/sqrt(bdotb)
! where(
elsewhere
sxi=0d0
cxi=one
angnorm=0.5d0
endwhere
! write(6,*) 'cxi: ',cxi
! s2xi=2.*sxi*cxi; c2xi=cxi*cxi-sxi*sxi
! write(6,*) 'angnorm', angnorm
! write(6,*) 'bdotk: ',bdotk/sqrt(knorm)/sqrt(bdotb)
! write(6,*) 'knorm: ',knorm
! write(6,*) 'bdotb: ',bdotb
! write(6,*) 'bdotk: ',(b*k)**2/om2/bdotb
! write(6,*) 'mone',merge(merge(angnorm,one,angnorm.le.1d0),mone,
! & angnorm.ge.-1d0)
! ! write(6,*) 'mone',merge(angnorm,mone,angnorm.ge.-1d0)
ang=acos(merge(merge(angnorm,angmax,angnorm.le..9999d0),angmin, &
angnorm.ge.-.9999d0))
! write(6,*) 'sc: ',cxi*cxi+sxi*sxi
! write(6,*) 'ang: ',ang
g=-1./khat%data(1)
end subroutine comoving_ortho_debug_old
subroutine calc_polar_psi(r,muf,q2,a,alpha,beta,rshift,mus,p, &
c2psi,s2psi,cosne)
real(kind=8), dimension(:), intent(in) :: r,muf,q2, &
alpha,beta,rshift
type (four_vector), dimension(:), intent(in) :: p
real(kind=8), intent(in) :: a, mus
type (four_vector), dimension(size(r)) :: f
real(kind=8), dimension(size(r)), intent(out) :: cosne,s2psi,c2psi
real(kind=8), dimension(size(r)) :: kappa1, kappa2, gammac, num, denom, polarpsi
complex, dimension(size(r)) :: kappa_pw
! write(6,*) 'polar psi: ',size(r)
! Components of vector in plane of disk
f=calc_polvec(r,muf,p,a,0.d0)
! penrose-walker constant for that vector
kappa_pw=calc_kappapw(a,r,muf,p,f)
kappa2=real(kappa_pw)
kappa1=-aimag(kappa_pw)
gammac=-alpha-a*(1.d0-mus**2)
! CPS80 but I think these are relative to e^\theta, e.g., \beta axis
! c2psi=(gammac*kappa1-beta*kappa2)/(gammac**2d0+beta**2d0)
! s2psi=(-gammac*kappa2-beta*kappa1)/(gammac**2d0+beta**2d0)
! Eric's (relative to \alpha axis)
denom=(beta*kappa2-gammac*kappa1)!/(gammac**2d0+beta**2d0)
num=(-beta*kappa1-gammac*kappa2)!/(gammac**2d0+beta**2d0)
! Eric's equation for polarpsi (seems to disagree with CPS80...)
polarpsi=atan2(denom,num)
s2psi=sin(2d0*polarpsi); c2psi=cos(2d0*polarpsi)
! polarization angle for that vector transported to infinity
! num=-gammac*kappa2-beta*kappa1
! denom=gammac*kappa1-beta*kappa2
! polarpsi=0.5d0*atan(num/denom)
! s2psi=2d0*num*denom/(gammac**2d0+beta**2d0)**2d0
! s2psi=2d0*kappa1*kappa2*(beta**2d0-gammac**2d0)/(beta**2d0+gammac**2d0)**2d0
! c2psi=(denom**2d0-num**2d0)/(gammac**2d0+beta**2d0)**2d0
! c2psi=((gammac**2d0-beta**2d0)*kappa1**2d0-4d0*beta*gammac*kappa1*kappa2+ &
! (beta**2d0-gammac**2d0)*kappa2**2d0)/(gammac**2d0+beta**2d0)**2d0
! c2psi=sqrt(1d0-s2psi**2d0)
! c2psi=2d0*denom**2d0/(gammac**2d0+beta**2d0)**2d0-1d0
! c2psi=cos(2d0*polarpsi); s2psi=sin(2d0*polarpsi)
! write(6,*) 's2psi: ',2d0*num*denom/(gammac**2d0+beta**2d0)**2d0, sin(2d0*polarpsi)
! write(6,*) 'c2psi: ',(denom**2d0-num**2d0)/(gammac**2d0+beta**2d0)**2d0, cos(2d0*polarpsi)
cosne=rshift*sqrt(q2)/r
end subroutine
function calc_polvec(r,mu,p,a,psi) result(fourf)
real(kind=8), dimension(:), intent(in) :: r, mu
real(kind=8), intent(in) :: a, psi
type (four_vector), dimension(:), intent(in) :: p
real(kind=8), dimension(size(r)) :: ptt, prt, ptht, ppht, &
vel
real(kind=8), dimension(10,size(r)) :: tmetric
real(kind=8), dimension(size(r),10) :: metric
type (four_vector), dimension(size(r)) :: fourf
real(kind=8), dimension(size(r)) :: delta,ar,om,rho,frl,fthl, &
fphl,frp,fthp,fphp,fr,fth,fph,normf,epsi,enu
! Calculate polarization vector assuming convention f^0=0, using Agol (1997)
! LNRF momentum:
delta=r**2-2.d0*r+a**2
AR=(R*R+A*A)**2-A*A*delta*(1.d0-mu*mu)
OM=2.d0*A*R/AR; rho=r**2+a**2*mu**2
ptt=r*sqrt(delta/AR)*p%data(1)
prt=r/sqrt(delta)*p%data(2)
ptht=r*p%data(3)
ppht=sqrt(AR)/r*(p%data(4)-om*p%data(1))
! LNRF velocity for a Keplerian disk:
vel=1.d0/(r**(3.d0/2.d0)+a)
EPSI=SQRT(1.d0-mu*mu)*SQRT(AR/RHO)
ENU=SQRT(delta*RHO/AR)
vel=EPSI/ENU*(vel-om)
frl=sqrt(delta)/r*(vel*(ptt-prt**2/ptt)-ppht)
fthl=-vel*prt*ptht/ptt/r
fphl=r*prt/sqrt(AR)*(1.d0-vel*ppht/ptt)
frp=sqrt(delta)*ptht*prt/r*(-1.d0+vel*ppht/ptt)
fthp=1.d0/r*(prt**2+(1.d0+vel**2)*ppht**2-2.d0*vel*ppht*ptt+vel*ptht**2*ppht/ptt)
fphp=r*ptht/sqrt(AR)*(-(1.d0+vel**2)*ppht+vel*ptt+vel*ppht**2/ptt)
fr=cos(psi)*frl+sin(psi)*frp
fth=cos(psi)*fthl+sin(psi)*fthp
fph=cos(psi)*fphl+sin(psi)*fphp
fourf%data(1)=0.*fr
fourf%data(2)=fr
fourf%data(3)=fth
fourf%data(4)=fph
! Now normalize:
metric=kerr_metric(r,acos(mu),a); tmetric=transpose(metric)
call assign_metric(fourf,tmetric)
normf=fourf*fourf
fourf%data(1)=fourf%data(1)/sqrt(normf)
fourf%data(2)=fourf%data(2)/sqrt(normf)
fourf%data(3)=fourf%data(3)/sqrt(normf)
fourf%data(4)=fourf%data(4)/sqrt(normf)
return
end function calc_polvec
function calc_kappapw(a,r,mu,p,f) result(kappapw)
real(kind=8), intent(in), dimension(:) :: r,mu
type (four_vector), intent(in), dimension(:) :: p
type (four_vector), intent(in), dimension(:) :: f
complex, dimension(size(r)) :: kappapw
real(kind=8), intent(in) :: a
real(kind=8), dimension(size(r)) :: alpha,beta
! Calculates the complex Penrose-Walker constant for some four-vector
! f perpendicular to p
! JAD 10/23/2008
! Calculate complex Penrose-Walker constant
alpha=(p%data(1)*f%data(2)-p%data(2)*f%data(1))+a*(1.d0-mu**2)* &
(p%data(2)*f%data(4)-p%data(4)*f%data(2))
beta=(r**2+a**2)*sqrt(1.d0-mu**2)*(p%data(4)*f%data(3)-p%data(3)*f%data(4))&
-a*sqrt(1.d0-mu**2)*(p%data(1)*f%data(3)-p%data(3)*f%data(1))
kappapw=cmplx(alpha,-beta)*cmplx(r,-a*mu)
return
end function calc_kappapw
function surf_integral(x,r,th,ph,a) result (s)
! calculate radial profile of angle-integrated quantity x assuming uniform ph
! JAD 2/23/2013
real(8), intent(in), dimension(:,:,:) :: x,r,th,ph
real(8), intent(in) :: a
real(8), dimension(size(r,1),size(r,2),size(r,3)) :: dth, gdet
integer :: nx1,nx2,nx3
real(8) :: dph
real(8), dimension(size(r,1)) :: s
dph=ph(1,1,2)-ph(1,1,1)
gdet=(r**2d0+a**2d0*cos(th)**2d0)*sin(th)
nx1=size(r,1); nx2=size(r,2); nx3=size(r,3)
dth(:,2:nx2,:)=th(:,2:nx2,:)-th(:,1:nx2-1,:)
dth(:,1,:)=dth(:,nx2,:)
s=sum(sum(x*gdet*dth*dph,3),2)
end function surf_integral
function th_integral(x,r,th,ph,a,onlyth) result (s)
! calculate radial profile of angle-integrated quantity x assuming uniform ph
! JAD 2/23/2013
real(8), intent(in), dimension(:,:,:) :: x,r,th,ph
real(8), intent(in) :: a
real(8), dimension(size(r,1),size(r,2),size(r,3)) :: dth, gdet
integer :: nx1,nx2,nx3
real(8) :: dph
real(8), dimension(size(r,1),size(r,3)) :: s
integer, intent(in) :: onlyth
dph=ph(1,1,2)-ph(1,1,1)
gdet=(r**2d0+a**2d0*cos(th)**2d0)*sin(th)
nx1=size(r,1); nx2=size(r,2); nx3=size(r,3)
dth(:,2:nx2,:)=th(:,2:nx2,:)-th(:,1:nx2-1,:)
dth(:,1,:)=dth(:,nx2,:)
s=sum(x*gdet*dth*dph,2)*nx3
end function th_integral
function ph_integral(x,r,th,ph,a,onlyth,onlyph) result (s)
! calculate radial profile of angle-integrated quantity x assuming uniform ph
! JAD 2/23/2013
real(8), intent(in), dimension(:,:,:) :: x,r,th,ph
real(8), intent(in) :: a
real(8), dimension(size(r,1),size(r,2),size(r,3)) :: dth, gdet
integer :: nx1,nx2,nx3
real(8) :: dph
real(8), dimension(size(r,1),size(r,2)) :: s
integer, intent(in) :: onlyth, onlyph
dph=ph(1,1,2)-ph(1,1,1)
gdet=(r**2d0+a**2d0*cos(th)**2d0)*sin(th)
nx1=size(r,1); nx2=size(r,2); nx3=size(r,3)
dth(:,2:nx2,:)=th(:,2:nx2,:)-th(:,1:nx2-1,:)
dth(:,1,:)=dth(:,nx2,:)
s=sum(x*gdet*dth*dph,3)*nx2
! write(6,*) 'ph integral: ',minval(s),maxval(s),minval(x),maxval(x)
end function ph_integral
function calc_u0(metric,vr,vth,vph) result(u0)
! calculate u0 from three-velocity in BL coordinates
real(8), intent(in), dimension(:) :: vr,vth,vph
real(8), intent(in), dimension(:,:) :: metric
real(8), dimension(size(vr)) :: u0
u0 = sqrt(-1d0/(metric(:,1) + metric(:,5)*vr**2d0 + metric(:,8)*vth**2d0 &
+ metric(:,10)*vph**2d0 + 2d0*metric(:,4)*vph))
end function calc_u0
subroutine calc_rms_constants(a,ems,lms,rms)
real(8), intent(in) :: a
real(8), intent(out) :: ems,lms,rms
real(8) :: v
rms = dble(calc_rms(real(a)))
v = 1d0/sqrt(rms)
ems = (1d0-2d0*v*v+a*v*v*v)/sqrt(1d0-3d0*v*v+2d0*a*v*v*v)
lms = rms*v*(1d0-2d0*a*v*v*v+a*a*v*v*v*v)/sqrt(1d0-3d0*v*v+2d0*a*v*v*v)
return
end subroutine calc_rms_constants
function calc_plunging_vel(a,r) result(fu)
real(8), intent(in) :: a
real(8), dimension(:), intent(in) :: r
type (four_vector), dimension(size(r)) :: fu
real(8) :: ems,lms,rms,rh
real(8), dimension(size(r)) :: pt,pr,pphi,th,denom
real(8), dimension(size(r),10) :: metriccon
! this is way based on Hughes (2000, 2001), Schnittman PhD. equivalently there is analytic way from old code that seems to give ~same result.
call calc_rms_constants(a,ems,lms,rms)
! write(6,*) 'kerr plunging vel rms constants: ',ems,lms,rms,minval(r),maxval(r)
th = pi/2d0
metriccon = kerr_metric(r,th,a,1)
pt = -metriccon(:,1)*ems + metriccon(:,4)*lms
denom = -metriccon(:,5)*(1d0+metriccon(:,1)*ems*ems-2d0*metriccon(:,4)*ems*lms+metriccon(:,10)*lms*lms)
where(denom.gt.0.)
pr = -sqrt(denom)
elsewhere
pr = 0d0
endwhere
! pr = -sqrt(-metriccon(:,5)*(1d0+metriccon(:,1)*ems*ems-2d0*metriccon(:,4)*ems*lms+metriccon(:,10)*lms*lms))
pphi = -metriccon(:,4)*ems+metriccon(:,10)*lms
fu%data(1)=pt
fu%data(2)=pr
fu%data(3)=0d0
fu%data(4)=pphi
! write(6,*) 'kerr plunging vel fu: ',minval(pt),maxval(pt),minval(pr),maxval(pr),minval(pphi),maxval(pphi)
end function calc_plunging_vel
function rms_vel(a,th,r) result(fu)
real(8), intent(in) :: a
real(8), intent(in), dimension(:) :: th,r
type (four_vector), dimension(size(r)) :: fu,fueq
real(8), dimension(size(r)) :: vrl,vtl,vpl,vrr,vtt,vpp,u0,theq
real(8), dimension(size(r),10) :: metric
! plunging four-velocity in equatorial plane
fueq = calc_plunging_vel(a,r)
theq = pi/2d0
! transform to lnrf
call lnrf_frame(fueq%data(2)/fueq%data(1),fueq%data(3)/fueq%data(1), &
fueq%data(4)/fueq%data(1),r,a,theq,vrl,vtl,vpl)
! write(6,*) 'kerr rms_vel lnrf 1: ',maxval(vrl),minval(vrl),maxval(vpl),minval(vpl)
! invert but at real \theta outside equatorial plane
call lnrf_frame(vrl,vtl,vpl,r,a,th,vrr,vtt,vpp,1)
metric=kerr_metric(r,th,a)
u0=calc_u0(metric,vrr,vtt,vpp)
! write(6,*) 'kerr rms_vel u0: ',minval(u0),maxval(u0)
fu%data(1)=u0; fu%data(2)=u0*vrr; fu%data(3)=u0*vtt; fu%data(4)=u0*vpp
! now test
call assign_metric(fu,transpose(metric))
! write(6,*) 'kerr rms_vel udotu: ',maxval(abs(fu*fu+1d0))
end function rms_vel
end module kerr