Skip to content

Analysis and Plotting Tools for HDF5 simulation data of meshless/moving-mesh hydrodynamical disks

Notifications You must be signed in to change notification settings

djmunoz/disk_data_analysis

Repository files navigation

disk_data_analysis - Analysis and Plotting Tools for HDF5 simulation data of meshless/moving-mesh hydrodynamical disks

example_figures/disk_images.png

1   Overview

A Python package!

2   Installation

You need to have git installed. In addition, you need the NumPy and SciPy Python packages.

git clone https://github.com/djmunoz/disk_data_analysis.git

cd disk_data_analysis

sudo python setup.py install

That is all!

3   Examples

3.1   Reading-in and plotting data

First of all, load the package and check the functions/attributes in it:

import disk_data_analysis.circumbinary as dda

dir(dda)

The most basic function in that list is get_snapshot_data, which can be used to give

snap = dda.get_snapshot_data('./data/snap_',0,['POS','VEL','R'])

which will only contain the requested quantities POS (positions) and VEL (velocities). You can double-check the attributes of the snap data structure by doing

dir(snap.gas)

You can see the distribution of particles/mesh generating points by plotting the positions

import matplotlib.pyplot as plt

x = snap.gas.POS[:,0]
y = snap.gas.POS[:,1]
box = snap.header.boxsize
plt.plot(x,y,'b.',ms=2.4)
plt.xlim(0.5 * box - 2.5, 0.5 * box + 2.5)
plt.ylim(0.5 * box - 2.5, 0.5 * box + 2.5)
plt.xlabel(r'$x$',size=18)
plt.ylabel(r'$y$',size=18)
plt.show()

example_figures/figure_points.png

3.1.1   Voronoi mesh

You can compare the mesh-generating scatter plot above with the associated Voronoi grid. Fortunately, Python has built-in Voronoi routines in 2-D.

from scipy.spatial import Voronoi, voronoi_plot_2d
ind = snap.gas.R < 3.8
points = np.array([snap.gas.POS[ind,0],snap.gas.POS[ind,1]]).T

vor = Voronoi(points)

fig = plt.figure(figsize=(4.5,4.5))
voronoi_plot_2d(vor,show_points=False,show_vertices=False)
plt.xlim(0.5 * snap.header.boxsize - 2.5, 0.5 * snap.header.boxsize + 2.5)
plt.ylim(0.5 * snap.header.boxsize - 2.5, 0.5 * snap.header.boxsize + 2.5)
plt.xlabel(r'$x$',size=18)
plt.ylabel(r'$y$',size=18)
plt.axes().set_aspect('equal')
plt.show()

example_figures/voronoi_mesh.png

3.2   Computing radial profiles

3.3   Mapping onto polar grids

Often, SPH and moving-mesh simulations of disks will be compared to simulation results obtained with polar-grid codes. In particular, comparison of azimuthally-averaged quantities is common practice. While azimuthal averaging is trivial in polar grids, it requires some tinkering when computational cells (or particles) are not placed in regular intervals in radius. One way around this is to remap the fluid's primitive variables into a structured grid of points.

import numpy as np

# We need the density and positions
snap = dda.get_snapshot_data('./data/snap_',0,['POS','RHO'])


# get a sense of the dynamical range in radius in the simulation
Rmin, Rmax = 1.0, 80.0
NR, Nphi = 200, 400
grid = dda.grid_polar(NR = NR, Nphi = Nphi,Rmin=1.0,Rmax= 80.0,scale='log')
grid.X, grid.Y = grid.X + snap.header.boxsize * 0.5, grid.Y  +  snap.header.boxsize * 0.5

rho_interp = dda.disk_interpolate_primitive_quantities(snap,[grid.X,grid.Y],quantities=['RHO'])[0]

# And now we can plot the density field of this structured grid
fig = plt.figure(figsize=(5,4.5))
fig.subplots_adjust(top=0.97,right=0.95,left=0.1,bottom=0.12)
ax = fig.add_subplot(111)
ax.scatter(grid.X,grid.Y,c=rho_interp ,lw=0)
ax.axis([76,84,76,84])
ax.set_xlabel(r'$x$',size=18)
ax.set_ylabel(r'$y$',size=18)
ax.set_aspect(1.0)
plt.show()

example_figures/polar_grid1.png

An interpolated, structured grid can be used to map AREPO snapshots into data readable by other codes like FARGO and PLUTO. But you might find other used for the polar regridding, such as computing radial profiles for diverse quantities. In such case, since AREPO (and SPH) simulation will in general have unevenly populated resolution elements, you might want to have a "nested" polar grid such as:

grid_in = dda.grid_polar(NR = 80, Nphi = 600, Rmin = 1.0, Rmax= 4.0, scale='linear')
grid_in.X, grid_in.Y = grid_in.X + snap.header.boxsize * 0.5, grid_in.Y  +  snap.header.boxsize * 0.5
grid_out = dda.grid_polar(NR = 140, Nphi = 300, Rmin = 4.0, Rmax= 80.0, scale='log')
grid_out.X, grid_out.Y = grid_out.X + snap.header.boxsize * 0.5, grid_out.Y  +  snap.header.boxsize * 0.5

X = np.append(grid_in.X,grid_out.X)
Y = np.append(grid_in.Y,grid_out.Y)

You can repeat the re-gridding step as before

rho_interp = dda.disk_interpolate_primitive_quantities(snap,[X,Y],quantities=['RHO'])[0]
fig = plt.figure(figsize=(5,4.5))
fig.subplots_adjust(top=0.97,right=0.95,left=0.1,bottom=0.12)
ax = fig.add_subplot(111)
ax.scatter(X,Y,c=rho_interp ,lw=0,s=8)
ax.axis([73,87,73,87])
ax.set_xlabel(r'$x$',size=18)
ax.set_ylabel(r'$y$',size=18)
ax.set_aspect(1.0)
plt.show()

and plot the color-coded cell locations as before

example_figures/polar_grid2.png

A uniform (and linear) sampling in R and phi allows us to create an reconstructed image plot in polar coordinates

Rmin, Rmax = 1.0, 7.0
NR, Nphi = 300, 500
R, phi = np.meshgrid(np.arange(Rmin,Rmax,(Rmax-Rmin)/NR),\
                     np.linspace(0,2*np.pi-np.pi/Nphi,Nphi))
X, Y = R * np.cos(phi) + snap.header.boxsize * 0.5, R * np.sin(phi) + snap.header.boxsize * 0.5
rho_interp = dda.disk_interpolate_primitive_quantities(snap,[X,Y],quantities=['RHO'])[0]


fig = plt.figure(figsize=(8,5))
fig.subplots_adjust(top=0.97,right=0.95,left=0.1,bottom=0.12)
ax = fig.add_subplot(111)
ax.imshow(rho_interp, origin='lower',interpolation='bilinear',
       extent=[R.min(),R.max(),phi.min()/np.pi,phi.max()/np.pi])
ax.set_xlabel(r'$R$',size=18)
ax.set_ylabel(r'$\phi/\pi$',size=18)
X0, X1 = ax.get_xlim()
Y0, Y1 = ax.get_ylim()
ax.set_aspect(float((X1-X0)/(Y1-Y0)/1.6))
plt.show()

example_figures/polar_coord_plot.png

3.3.1   Using re-gridded data to plot radial profiles

Simple quantities such as "first order" primitive variables RHO, VELPHI and VELR can be evaluated over a strucured grid and plotted as a function or R. A simple average can be used to compute the radial profile for all these quantities.

snap = dda.get_snapshot_data('./data/snap_',0,['POS','RHO','VELPHI','VELR'])

Rmin, Rmax = 1.0, 15.0
NR, Nphi = 300, 500
R, phi = np.meshgrid(np.arange(Rmin,Rmax,(Rmax-Rmin)/NR),\
np.linspace(0,2*np.pi-np.pi/Nphi,Nphi))
X, Y = R * np.cos(phi) + snap.header.boxsize * 0.5, R * np.sin(phi) + snap.header.boxsize * 0.5
rho_interp,velphi_interp,velr_interp  = dda.disk_interpolate_primitive_quantities(snap,[X,Y],quantities=['RHO','VELPHI','VELR'])

Rvals = R.mean(axis=0)
sigma0 = rho_interp.mean()
sigma_av = rho_interp.mean(axis=0)
velphi_av = velphi_interp.mean(axis=0)
velr_av = velr_interp.mean(axis=0)

fig = plt.figure(figsize=(16,4))
ax = fig.add_subplot(1,3,1)
ax.plot(R,rho_interp/sigma0,'b.',ms=2.5)
ax.plot(Rvals,sigma_av/sigma0,color='darkred',lw=5.0,alpha=0.6)

ax = fig.add_subplot(1,3,2)
ax.plot(R,velphi_interp,'b.',ms=2.5)
ax.plot(Rvals,velphi_av,color='darkred',lw=5.0,alpha=0.6)

ax = fig.add_subplot(1,3,3)
ax.plot(R,velr_interp,'b.',ms=2.5)
ax.plot(Rvals,velr_av,color='darkred',lw=5.0,alpha=0.6)

plt.show()

example_figures/examples_profiles.png

Computing other basic quantities, such as the mass accretion profile in disks, can be non-trivial. In conservative, finite-volume codes, one can in principle store the flux of any conserved quantity across a given radial location provided: (1) the cell boundaries align with the radial coordinate (i.e., the a cylindrical grid is used to discretize the domain) and (2) the quantity under question is directly evolved in a conservative manner (i.e., by used of a Godunov-like scheme). AREPO simulations fail to meet the first requirement, since the mesh is unstructured. In such case, interpolation is left as the most straightforward tool to compute the flux of conserved quantities crossing a boundary at a specific value of radius R.

For the mass accretion rate:

example_figures/equation_1.png

3.4   Displaying 2-D fields without pre-computed image data

About

Analysis and Plotting Tools for HDF5 simulation data of meshless/moving-mesh hydrodynamical disks

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages