Source code for gala.potential.potential.builtin.special

# Third-party
import astropy.units as u
import numpy as np

# Project
from gala.potential.potential.builtin.core import (
    HernquistPotential,
    LogarithmicPotential,
    MiyamotoNagaiPotential,
    MN3ExponentialDiskPotential,
    NFWPotential,
    PowerLawCutoffPotential,
)
from gala.potential.potential.ccompositepotential import CCompositePotential
from gala.units import galactic

__all__ = [
    "LM10Potential",
    "MilkyWayPotential",
    "MilkyWayPotential2022",
    "BovyMWPotential2014",
]


[docs] class LM10Potential(CCompositePotential): """ The Galactic potential used by Law and Majewski (2010) to represent the Milky Way as a three-component sum of disk, bulge, and halo. The disk potential is an axisymmetric :class:`~gala.potential.MiyamotoNagaiPotential`, the bulge potential is a spherical :class:`~gala.potential.HernquistPotential`, and the halo potential is a triaxial :class:`~gala.potential.LogarithmicPotential`. Default parameters are fixed to those found in LM10 by fitting N-body simulations to the Sagittarius stream. Parameters ---------- units : `~gala.units.UnitSystem` (optional) Set of non-reducable units that specify (at minimum) the length, mass, time, and angle units. disk : dict (optional) Parameters to be passed to the :class:`~gala.potential.MiyamotoNagaiPotential`. bulge : dict (optional) Parameters to be passed to the :class:`~gala.potential.HernquistPotential`. halo : dict (optional) Parameters to be passed to the :class:`~gala.potential.LogarithmicPotential`. Note: in subclassing, order of arguments must match order of potential components added at bottom of init. """ def __init__(self, units=galactic, disk=dict(), bulge=dict(), halo=dict()): default_disk = dict(m=1e11 * u.Msun, a=6.5 * u.kpc, b=0.26 * u.kpc) default_bulge = dict(m=3.4e10 * u.Msun, c=0.7 * u.kpc) default_halo = dict( q1=1.38, q2=1.0, q3=1.36, r_h=12.0 * u.kpc, phi=97 * u.degree, v_c=np.sqrt(2) * 121.858 * u.km / u.s, ) for k, v in default_disk.items(): if k not in disk: disk[k] = v for k, v in default_bulge.items(): if k not in bulge: bulge[k] = v for k, v in default_halo.items(): if k not in halo: halo[k] = v super().__init__() self["disk"] = MiyamotoNagaiPotential(units=units, **disk) self["bulge"] = HernquistPotential(units=units, **bulge) self["halo"] = LogarithmicPotential(units=units, **halo) self.lock = True
[docs] class MilkyWayPotential(CCompositePotential): """ A simple mass-model for the Milky Way consisting of a spherical nucleus and bulge, a Miyamoto-Nagai disk, and a spherical NFW dark matter halo. The disk model is taken from `Bovy (2015) <https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B/abstract>`_ - if you use this potential, please also cite that work. Default parameters are fixed by fitting to a compilation of recent mass measurements of the Milky Way, from 10 pc to ~150 kpc. Parameters ---------- units : `~gala.units.UnitSystem` (optional) Set of non-reducable units that specify (at minimum) the length, mass, time, and angle units. disk : dict (optional) Parameters to be passed to the :class:`~gala.potential.MiyamotoNagaiPotential`. bulge : dict (optional) Parameters to be passed to the :class:`~gala.potential.HernquistPotential`. halo : dict (optional) Parameters to be passed to the :class:`~gala.potential.NFWPotential`. nucleus : dict (optional) Parameters to be passed to the :class:`~gala.potential.HernquistPotential`. Note: in subclassing, order of arguments must match order of potential components added at bottom of init. """ def __init__(self, units=galactic, disk=None, halo=None, bulge=None, nucleus=None): default_disk = dict(m=6.8e10 * u.Msun, a=3.0 * u.kpc, b=0.28 * u.kpc) default_bulge = dict(m=5e9 * u.Msun, c=1.0 * u.kpc) default_nucl = dict(m=1.71e9 * u.Msun, c=0.07 * u.kpc) default_halo = dict(m=5.4e11 * u.Msun, r_s=15.62 * u.kpc) if disk is None: disk = dict() if halo is None: halo = dict() if bulge is None: bulge = dict() if nucleus is None: nucleus = dict() for k, v in default_disk.items(): if k not in disk: disk[k] = v for k, v in default_bulge.items(): if k not in bulge: bulge[k] = v for k, v in default_halo.items(): if k not in halo: halo[k] = v for k, v in default_nucl.items(): if k not in nucleus: nucleus[k] = v super().__init__() self["disk"] = MiyamotoNagaiPotential(units=units, **disk) self["bulge"] = HernquistPotential(units=units, **bulge) self["nucleus"] = HernquistPotential(units=units, **nucleus) self["halo"] = NFWPotential(units=units, **halo) self.lock = True
[docs] class MilkyWayPotential2022(CCompositePotential): """ A mass-model for the Milky Way consisting of a spherical nucleus and bulge, a 3-component sum of Miyamoto-Nagai disks to represent an exponential disk, and a spherical NFW dark matter halo. The disk model is fit to the Eilers et al. 2019 rotation curve for the radial dependence, and the shape of the phase-space spiral in the solar neighborhood is used to set the vertical structure in Darragh-Ford et al. 2023. Other parameters are fixed by fitting to a compilation of recent mass measurements of the Milky Way, from 10 pc to ~150 kpc. Parameters ---------- units : `~gala.units.UnitSystem` (optional) Set of non-reducable units that specify (at minimum) the length, mass, time, and angle units. disk : dict (optional) Parameters to be passed to the :class:`~gala.potential.MN3ExponentialDiskPotential`. bulge : dict (optional) Parameters to be passed to the :class:`~gala.potential.HernquistPotential`. halo : dict (optional) Parameters to be passed to the :class:`~gala.potential.NFWPotential`. nucleus : dict (optional) Parameters to be passed to the :class:`~gala.potential.HernquistPotential`. Note: in subclassing, order of arguments must match order of potential components added at bottom of init. """ def __init__(self, units=galactic, disk=None, halo=None, bulge=None, nucleus=None): default_disk = dict(m=4.7717e10 * u.Msun, h_R=2.6 * u.kpc, h_z=0.3 * u.kpc) default_bulge = dict(m=5e9 * u.Msun, c=1.0 * u.kpc) default_nucl = dict(m=1.8142e9 * u.Msun, c=0.0688867 * u.kpc) default_halo = dict(m=5.5427e11 * u.Msun, r_s=15.626 * u.kpc) if disk is None: disk = dict() if halo is None: halo = dict() if bulge is None: bulge = dict() if nucleus is None: nucleus = dict() for k, v in default_disk.items(): if k not in disk: disk[k] = v for k, v in default_bulge.items(): if k not in bulge: bulge[k] = v for k, v in default_halo.items(): if k not in halo: halo[k] = v for k, v in default_nucl.items(): if k not in nucleus: nucleus[k] = v super().__init__() self["disk"] = MN3ExponentialDiskPotential(units=units, **disk) self["bulge"] = HernquistPotential(units=units, **bulge) self["nucleus"] = HernquistPotential(units=units, **nucleus) self["halo"] = NFWPotential(units=units, **halo) self.lock = True
[docs] class BovyMWPotential2014(CCompositePotential): """ An implementation of the ``MWPotential2014`` `from galpy <https://galpy.readthedocs.io/en/latest/potential.html>`_ and described in `Bovy (2015) <https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B/abstract>`_. This potential consists of a spherical bulge and dark matter halo, and a Miyamoto-Nagai disk component. .. note:: Because it internally uses the PowerLawCutoffPotential, this potential requires GSL to be installed, and Gala must have been built and installed with GSL support enaled (the default behavior). See http://gala.adrian.pw/en/latest/install.html for more information. Parameters ---------- units : `~gala.units.UnitSystem` (optional) Set of non-reducable units that specify (at minimum) the length, mass, time, and angle units. disk : dict (optional) Parameters to be passed to the :class:`~gala.potential.MiyamotoNagaiPotential`. bulge : dict (optional) Parameters to be passed to the :class:`~gala.potential.PowerLawCutoffPotential`. halo : dict (optional) Parameters to be passed to the :class:`~gala.potential.NFWPotential`. Note: in subclassing, order of arguments must match order of potential components added at bottom of init. """ def __init__(self, units=galactic, disk=None, halo=None, bulge=None): default_disk = dict(m=68193902782.346756 * u.Msun, a=3.0 * u.kpc, b=280 * u.pc) default_bulge = dict(m=4501365375.06545 * u.Msun, alpha=1.8, r_c=1.9 * u.kpc) default_halo = dict(m=4.3683325e11 * u.Msun, r_s=16 * u.kpc) if disk is None: disk = dict() if halo is None: halo = dict() if bulge is None: bulge = dict() for k, v in default_disk.items(): if k not in disk: disk[k] = v for k, v in default_bulge.items(): if k not in bulge: bulge[k] = v for k, v in default_halo.items(): if k not in halo: halo[k] = v super().__init__() self["disk"] = MiyamotoNagaiPotential(units=units, **disk) self["bulge"] = PowerLawCutoffPotential(units=units, **bulge) self["halo"] = NFWPotential(units=units, **halo) self.lock = True
# -------------------------------------------------------------------- # class TriaxialMWPotential(CCompositePotential): # def __init__(self, units=galactic, # disk=dict(), bulge=dict(), halo=dict()): # """ Axis ratio values taken from Jing & Suto (2002). Other # parameters come from a by-eye fit to Bovy's MW2014Potential. # Choice of v_c sets circular velocity at Sun to 220 km/s # """ # default_disk = dict(m=7E10, a=3.5, b=0.14) # default_bulge = dict(m=1E10, c=1.1) # default_halo = dict(a=1., b=0.75, c=0.55, # v_c=0.239225, r_s=30., # phi=0., theta=0., psi=0.) # for k, v in default_disk.items(): # if k not in disk: # disk[k] = v # for k, v in default_bulge.items(): # if k not in bulge: # bulge[k] = v # for k, v in default_halo.items(): # if k not in halo: # halo[k] = v # kwargs = dict() # kwargs["disk"] = MiyamotoNagaiPotential(units=units, **disk) # kwargs["bulge"] = HernquistPotential(units=units, **bulge) # kwargs["halo"] = LeeSutoTriaxialNFWPotential(units=units, **halo) # super(TriaxialMWPotential, self).__init__(**kwargs) # --------------------------------------------------------------------