From a5303c868402bec6b1a4b46dccb4c7fef4c829d7 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Mon, 27 Jun 2016 11:09:43 +0800 Subject: calc_mass_potential.py: implement gravitational pontential calculation --- calc_mass_potential.py | 97 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 10 deletions(-) diff --git a/calc_mass_potential.py b/calc_mass_potential.py index c1300b9..eca425c 100755 --- a/calc_mass_potential.py +++ b/calc_mass_potential.py @@ -2,9 +2,12 @@ # # Weitian LI # Created: 2016-06-24 -# Updated: 2016-06-26 +# Updated: 2016-06-27 # # Change logs: +# 2016-06-27: +# * Implement potential profile calculation: +# methods 'calc_density_total()' and 'calc_potential()' # 2016-06-26: # * Add document on gravitational potential calculation # 2016-06-25: @@ -129,6 +132,9 @@ m_gas_profile = mass_gas_profile.txt # output total (gravitational) mass profile m_total_profile = mass_total_profile.txt +# output total mass density profile +rho_total_profile = rho_total_profile.txt + # output gravitational potential profile potential_profile = potential_profile.txt ------------------------------------------------------------ @@ -189,6 +195,8 @@ class DensityProfile: m_gas = None # total (gravitational) mass profile: M_total(>> Fitting spline to total mass profile ...") + self.m_total_spline = interpolate.InterpolatedUnivariateSpline( + x=self.radius, y=self.m_total, ext="const") + for i, r in enumerate(self.radius): + rho_total[i] = (derivative(self.m_total_spline, r, + dx=0.01*au.kpc.to(au.cm)) / + (4 * np.pi * r**2)) + self.rho_total = rho_total + if verbose: + print(">>> Fitting spline to total mass density profile ...") + self.rho_total_spline = interpolate.InterpolatedUnivariateSpline( + x=self.radius, y=rho_total, ext="const") + def calc_potential(self, verbose=True): """ Calculate the gravitational potential profile. + + NOTE: + The integral in the potential formula can only be integrated + to the largest radius of availability. + This limitation will affect the absolute values of the calculated + potentials, but not the shape of the potential profile. """ - pass + def _int_inner(x): + return x**2 * self.rho_total_spline(x) + + def _int_outer(x): + return x * self.rho_total_spline(x) + + if self.rho_total is None: + self.calc_density_total(verbose=verbose) + potential = np.zeros(self.radius.shape) + if verbose: + print("Calculating the potential profile (#%d): ..." % + len(self.radius), end="", flush=True) + r_max = max(self.radius) + for i, r in enumerate(self.radius): + if verbose and (i+1) % 50 == 0: + print("%d..." % (i+1), end="", flush=True) + potential[i] = - 4 * np.pi * ac.G.cgs.value * ( + (1/r) * integrate.quad(_int_inner, a=0.0, b=r, + epsabs=1e-5*au.kpc.to(au.cm), + epsrel=1e-3)[0] + + integrate.quad(_int_outer, a=r, b=r_max, + epsabs=1e-5*au.kpc.to(au.cm), + epsrel=1e-3)[0]) + if verbose: + print("DONE!", flush=True) + self.potential = potential + return potential def plot(self, profile, ax=None, fig=None): pass @@ -403,6 +464,16 @@ class DensityProfile: self.radius_err, self.m_total]) header = "radius[cm] radius_err[cm] mass_total(