-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
397 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Anisotropic Hernquist DF of the Osipkov-Merritt type | ||
==================================================== | ||
|
||
.. autoclass:: galpy.df.osipkovmerrittHernquistdf | ||
:members: __init__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# Class that implements the anisotropic spherical Hernquist DF with radially | ||
# varying anisotropy of the Osipkov-Merritt type | ||
import numpy | ||
from ..util import conversion | ||
from ..potential import evaluatePotentials, HernquistPotential | ||
from .osipkovmerrittdf import osipkovmerrittdf | ||
|
||
class osipkovmerrittHernquistdf(osipkovmerrittdf): | ||
"""Class that implements the anisotropic spherical Hernquist DF with radially varying anisotropy of the Osipkov-Merritt type | ||
.. math:: | ||
\\beta(r) = \\frac{1}{1+r_a^2/r^2} | ||
with :math:`r_a` the anistropy radius. | ||
""" | ||
def __init__(self,pot=None,ra=1.4,ro=None,vo=None): | ||
""" | ||
NAME: | ||
__init__ | ||
PURPOSE: | ||
Initialize a Hernquist DF with Osipkov-Merritt anisotropy | ||
INPUT: | ||
pot - Hernquist potential which determines the DF | ||
ra - anisotropy radius (can be a Quantity) | ||
OUTPUT: | ||
None | ||
HISTORY: | ||
2020-11-12 - Written - Bovy (UofT) | ||
""" | ||
assert isinstance(pot,HernquistPotential), \ | ||
'pot= must be potential.HernquistPotential' | ||
osipkovmerrittdf.__init__(self,pot=pot,ra=ra,ro=ro,vo=vo) | ||
self._psi0= -evaluatePotentials(self._pot,0,0,use_physical=False) | ||
self._GMa = self._psi0*self._pot.a**2. | ||
self._a2overra2= self._pot.a**2./self._ra2 | ||
self._fQnorm= 1./numpy.sqrt(2.)/(2*numpy.pi)**3/self._GMa**1.5 | ||
|
||
def fQ(self,Q): | ||
""" | ||
NAME: | ||
fQ | ||
PURPOSE | ||
Calculate the f(Q) portion of an Osipkov-Merritt Hernquist distribution function | ||
INPUT: | ||
Q - The Osipkov-Merritt 'energy' E-L^2/[2ra^2] (can be Quantity) | ||
OUTPUT: | ||
fQ - The value of the f(Q) portion of the DF | ||
HISTORY: | ||
2020-11-12 - Written - Bovy (UofT) | ||
""" | ||
Qtilde= conversion.parse_energy(Q,vo=self._vo)/self._psi0 | ||
# Handle potential Q outside of bounds | ||
Qtilde_out = numpy.where(numpy.logical_or(Qtilde<0,Qtilde>1))[0] | ||
if len(Qtilde_out)>0: | ||
# Dummy variable now and 0 later, prevents numerical issues | ||
Qtilde[Qtilde_out]=0.5 | ||
sqrtQtilde= numpy.sqrt(Qtilde) | ||
# The 'ergodic' part | ||
fQ= sqrtQtilde/(1-Qtilde)**2.\ | ||
*((1.-2.*Qtilde)*(8.*Qtilde**2.-8.*Qtilde-3.)\ | ||
+((3.*numpy.arcsin(sqrtQtilde))\ | ||
/numpy.sqrt(Qtilde*(1.-Qtilde)))) | ||
# The other part | ||
fQ+= 8.*self._a2overra2*sqrtQtilde*(1.-2.*Qtilde) | ||
if len(Qtilde_out) > 0: | ||
fQ[Qtilde_out]= 0. | ||
return self._fQnorm*fQ | ||
|
||
def _icmf(self,ms): | ||
'''Analytic expression for the normalized inverse cumulative mass | ||
function. The argument ms is normalized mass fraction [0,1]''' | ||
return self._pot.a*numpy.sqrt(ms)/(1-numpy.sqrt(ms)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# Class that implements anisotropic DFs of the Osipkov-Merritt type | ||
import numpy | ||
from scipy import integrate, special | ||
from ..util import conversion | ||
from ..potential import evaluatePotentials | ||
from .sphericaldf import anisotropicsphericaldf | ||
|
||
class osipkovmerrittdf(anisotropicsphericaldf): | ||
"""Class that implements anisotropic DFs of the Osipkov-Merritt type with radially varying anisotropy | ||
.. math:: | ||
\\beta(r) = \\frac{1}{1+r_a^2/r^2} | ||
with :math:`r_a` the anistropy radius. | ||
""" | ||
def __init__(self,pot=None,ra=1.4,scale=None,ro=None,vo=None): | ||
""" | ||
NAME: | ||
__init__ | ||
PURPOSE: | ||
Initialize a DF with Osipkov-Merritt anisotropy | ||
INPUT: | ||
pot - Hernquist potential which determines the DF | ||
ra - anisotropy radius (can be a Quantity) | ||
scale - Characteristic scale radius to aid sampling calculations. | ||
Not necessary, and will also be overridden by value from pot | ||
if available. | ||
OUTPUT: | ||
None | ||
HISTORY: | ||
2020-11-12 - Written - Bovy (UofT) | ||
""" | ||
anisotropicsphericaldf.__init__(self,pot=pot,scale=scale,ro=ro,vo=vo) | ||
self._ra= -conversion.parse_length(ra,ro=self._ro) | ||
self._ra2= self._ra**2. | ||
|
||
def _call_internal(self,*args): | ||
""" | ||
NAME: | ||
_call_internal | ||
PURPOSE: | ||
Evaluate the DF for an Osipkov-Merritt-anisotropy DF | ||
INPUT: | ||
E - The energy | ||
L - The angular momentum | ||
OUTPUT: | ||
fH - The value of the DF | ||
HISTORY: | ||
2020-11-12 - Written - Bovy (UofT) | ||
""" | ||
E, L, _= args | ||
return self.fQ(-E-0.5*L**2./self._ra2) | ||
|
||
def _sample_eta(self,r,n=1): | ||
"""Sample the angle eta which defines radial vs tangential velocities""" | ||
# cumulative distribution of x = cos eta satisfies | ||
# x/(sqrt(A+1 -A* x^2)) = 2 b - 1 = c | ||
# where b \in [0,1] and A = (r/ra)^2 | ||
# Solved by | ||
# x = c sqrt(1+[r/ra]^2) / sqrt( [r/ra]^2 c^2 + 1 ) for c > 0 [b > 0.5] | ||
# and symmetric wrt c | ||
c= numpy.random.uniform(size=n) | ||
x= c*numpy.sqrt(1+r**2./self._ra2)/numpy.sqrt(r**2./self._ra2*c**2.+1) | ||
x*= numpy.random.choice([1.,-1.],size=n) | ||
return numpy.arccos(x) | ||
|
||
def _p_v_at_r(self,v,r): | ||
"""p( v*sqrt[1+r^2/ra^2*sin^2eta] | r) used in sampling """ | ||
return self.fQ(-evaluatePotentials(self._pot,r,0,use_physical=False)\ | ||
-0.5*v**2.)*v**2. | ||
|
||
def _sample_v(self,r,eta,n=1): | ||
"""Generate velocity samples""" | ||
# Use super-class method to obtain v*[1+r^2/ra^2*sin^2eta] | ||
out= super(osipkovmerrittdf,self)._sample_v(r,eta,n=n) | ||
# Transform to v | ||
return out/numpy.sqrt(1.+r**2./self._ra2*numpy.sin(eta)**2.) | ||
|
||
def _vmomentdensity(self,r,n,m): | ||
if m%2 == 1 or n%2 == 1: | ||
return 0. | ||
psir= -evaluatePotentials(self._pot,r,0,use_physical=False) | ||
return 2.*numpy.pi*integrate.quad(lambda v: v**(2.+m+n) | ||
*self.fQ(-evaluatePotentials(self._pot,r,0, | ||
use_physical=False) | ||
-0.5*v**2.), | ||
0.,self._vmax_at_r(self._pot,r))[0]\ | ||
*special.gamma(m/2.+1.)*special.gamma((n+1)/2.)/\ | ||
special.gamma(0.5*(m+n+3.))/(1+r**2./self._ra2)**(m/2+1) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.