Last update: Nov 25, 2019.
This notebook contains a demonstration how to analyse the 3D filtered moms data with the 1D radial profile rprof data from PPMstar 3D hydrodynamic simulations.
The examples are for the project H-core-M25
(this is the project identifier), the H-core convection simulations of a 25M$_\odot$ star.
Two runs are used:
M29
: $768^3$ gridM35
: $1536^3$ gridM29
, M35
are the run identifier. Keep run and project identifier attached to all derived data products.
Both runs have 1000x heating which increases their convective velocities by a factor of 10.
For each run there are two types of data to be read for this demo:
The data is staged on the UVic Astrophysics Simulation Data Repository (ASDR) mounted in /data/ASDR
. The repository contains the project folder H-core-M25
.
The server defaults each notebook to %pylab ipympl
In [ ]:
## use this for final run to export with images to pdf, markdown or html
#%pylab inline
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as color
import nugridpy.utils as utils
import logging
import collections
import itertools
import sys
import os
# you can use sys.path.insert to add your own cloned copy of PyPPM which you can modify
# sys.path.insert(0,'/home/user/home/PyPPM/')
from ppmpy import ppm
# plotting utilities
ifig = 0
ptrack = {}
cb = utils.linestylecb # colours
# create smaller labelsizes on axes
plt.rc('xtick', labelsize=7)
plt.rc('ytick', labelsize=7)
# named tuple for using rprofs and momsdata
hydro = collections.namedtuple('hydro', ['moms','rprof'])
# turn off matplotlib messages
logging.getLogger("matplotlib").setLevel(logging.CRITICAL)
In [ ]:
%%bash
ls /data/ASDR/PPMstar/H-core-M25/
Due to how the moments data are decompressed the quantities written into the moms data file can be written in any order and do not contain any metadata to notify the MomsDataSet class what quantities are where in the large array. The quantities can be called with an index or their name IF you define the $\textit{var_list}$ variable in the MomsDataSet instantiation. For the runs being looked at here, the momsdata indices and their appropriate quantities are:
index | quantity |
---|---|
0 | x |
1 | $\vec{u_{x}}$ |
2 | $\vec{u_{y}}$ |
3 | $\vec{u_{z}}$ |
4 | $\lvert\vec{u_{t}}\rvert$ |
5 | $\lvert\vec{u_{r}}\rvert$ |
6 | $\lvert\vec{\omega}\rvert$ |
7 | P |
8 | rho |
9 | fv |
$\mu$ = fv $\times$ $\mu_{\mathrm{cld}}$ + (1 - fv) $\times$ $\mu_{\mathrm{air}}$
T = $\frac{P \mu}{\rho R_{gas}}$
$R_{gas}$ = 8.314462
$\vec{\omega}$ = $\vec{\nabla} \times \vec{u}$
$R_{gas}$, and all other quantities, are in code units which are defined in this file:
In [ ]:
%%bash
cat ./code-units.txt
We can find out how to instantiate the MomsDataSet object within the notebook as:
In [ ]:
ppm.MomsDataSet?
All class methods contain doc strings that describe the arguments and outputs.
In [ ]:
# paths to data
dir_repo = '/data/ASDR/PPMstar'
dir_project = 'H-core-M25'
# the runs and their resolutions
runs = ['M29', 'M35']
resolution = ['768', '1536']
# dumps for each run we could analyze
dumps = [650, 375]
# are we using high resolution?
use_highres = False
if use_highres:
use_run = [False, True]
else:
use_run = [True, False]
# grab the appropriate runid, runresolution and dump
runid, runresolution, mydump = itertools.compress(runs+resolution+dumps, use_run*3)
# create the hydro object
var_list = ['xc','ux','uy','uz','|ur|','|ut|','|w|','P','rho','fv']
dir_repo = os.path.join(dir_repo, dir_project, '{:s}-{:s}'.format(runid, runresolution))
myhydro = hydro(ppm.MomsDataSet(dir_name=os.path.join(dir_repo, 'myavsbq'), init_dump_read=mydump,
dumps_in_mem=2, var_list=var_list,
rprofset=ppm.RprofSet(os.path.join(dir_repo, 'prfs'))),
ppm.RprofSet(os.path.join(dir_repo, 'prfs')))
In [ ]:
# 3D datacube of the cartesian coordinates at this dump
x,y,z=myhydro.moms.get_cgrid()
# it is formatted such that var[z,y,x] refers to the variable at the (z,y,x) coordinates that those
# indices correspond to. The indexing goes from negative to positive
moms_ngridpoints = myhydro.moms.moms_ngridpoints
print('The unique x,y,z coordinates are:')
print(x[np.random.randint(0,moms_ngridpoints), np.random.randint(0,moms_ngridpoints), :])
# to convert to spherical coordinates
r,theta,phi=myhydro.moms.get_sgrid()
In [ ]:
# breakdown of cells and shapes of the simulations
ppmstar_dim = len(myhydro.rprof.get('R',fname=0,resolution='h'))
print('The original PPMStar simulation was run with a cubic dimension of ('+','.join(3*[str(ppmstar_dim)])+
') while the moments data is downsampled by a factor of 4 with a cubic dimension of ('+
','.join(map(str,x.shape))+')')
print('')
# spatial resolution for momsdata compared with rprofs (simulation)
deex_ppmstar = myhydro.rprof.get('deex',fname=0)
print('The grid resolution of the original PPMStar simulation is {:.2f}Mm while the moms data is {:.2f}Mm'
.format(deex_ppmstar,np.diff(x[0,0,:])[0]))
In [ ]:
# temporal resolution is in the rprof data
print('The temporal resolution of the moms data is the same as the PPMStar output which averages around {:0.2f}'.
format(np.mean(np.diff(myhydro.rprof.get_history().get('time(mins)')))),'minutes of star time per dump')
print('')
print('The run-time temporal resolution of the PPMStar output averages around {:0.2f}'.
format(np.mean(myhydro.rprof.get_history().get('dt(secs)'))),'seconds per cycle')
In [ ]:
# this ensures that I can open an close the figure that was plotted within this cell.
# It doesn't matter in what order I run the notebook cells, this keeps track of it
celln = 0
# configure plots
close_local = ppm.close_plot(celln,ifig,ptrack)
if close_local[0]:
plt.close(fig); ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
else:
ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
# set the colour/linestyle counter to 0 and create axes
cbc = 0
ax = fig.add_subplot(111)
# histogram of radius values
hist_data = ax.hist(r.flatten(),86)
# plot details
xmax = np.max(x)
ylims = [0,np.max(hist_data[0])]
ax.vlines(xmax,*ylims,linestyles='--',lw=0.5)
ax.set_xlabel('r / Mm')
ax.set_ylabel('')
ax.set_ylim(ylims)
In [ ]:
# extent in x,y
extent=[np.min(x),np.max(x),np.min(y),np.max(y)]
# the take a slice at z=0. This is halfway through the indices
slice_num = int(moms_ngridpoints/2)
In [ ]:
# this ensures that I can open an close the figure that was plotted within this cell.
# It doesn't matter in what order I run the notebook cells, this keeps track of it
celln = 1
# configure plots
close_local = ppm.close_plot(celln,ifig,ptrack)
if close_local[0]:
plt.close(fig); ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
else:
ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
# set the colour/linestyle counter to 0 and create axes
cbc = 0
ax = plt.axes([0.01, 0.98, 0.88, 0.98])
ax.imshow(r[:,:,slice_num],extent=extent)
# plot details
ax.set_ylabel('y / Mm')
ax.set_xlabel('x / Mm')
# create a colorbar for the imshow data, use a new axes for it
cax = fig.add_axes([0.90, 0.98, 0.08, 0.98])
cbar1 = fig.colorbar(ax.images[0], cax=cax, orientation='vertical',format='%d',
label=r'r / Mm')
We can simply construct the magnitude of the tangential velocity from the cartesian vector velocity components
In [ ]:
# get the cartesian velocity components
ux = myhydro.moms.get('ux',fname=mydump)
uy = myhydro.moms.get('uy',fname=mydump)
uz = myhydro.moms.get('uz',fname=mydump)
# convert to spherical components
ur, utheta, uphi = myhydro.moms.get_spherical_components(ux, uy, uz)
u_perp = np.sqrt(np.power(utheta,2.0) + np.power(uphi,2.0))
# store for later, |u|
u_cartesian = myhydro.moms.norm(ux, uy, uz)
u_spherical = myhydro.moms.norm(ur, utheta, uphi)
# they are practically the same
print((u_cartesian - u_spherical).mean(), (u_cartesian - u_spherical).std())
In [ ]:
# this ensures that I can open an close the figure that was plotted within this cell.
# It doesn't matter in what order I run the notebook cells, this keeps track of it
celln = 2
# configure plots
close_local = ppm.close_plot(celln,ifig,ptrack)
if close_local[0]:
plt.close(fig); ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
else:
ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
# set the colour/linestyle counter to 0 and create axes
cbc = 0
ax = plt.axes([0.01, 0.98, 0.88, 0.98])
# get the tangential velocity and make it km/s rather than Mm/s
ax.imshow(u_perp[:,:,slice_num]*1e3,extent=extent,vmin=0)
# plot details
ax.set_ylabel('y / Mm')
ax.set_xlabel('x / Mm')
# create a colorbar for the imshow data, use a new axes for it
cax = fig.add_axes([0.90, 0.98, 0.08, 0.98])
cbar1 = fig.colorbar(ax.images[0], cax=cax, orientation='vertical',format='%.0f',
label=r'$u_{\perp}$ / km s$^{-1}$')
In [ ]:
# for rprofs we will grab the spherical averages directly
T9_rprof = myhydro.rprof.compute_T9(fname=mydump)
R_rprof = myhydro.rprof.get('R',fname=mydump,resolution='l')
# for moments data we will have to use the base components and compute T9
cldmu = myhydro.rprof.get('cldmu',fname=0)
airmu = myhydro.rprof.get('airmu',fname=0)
Rgas = 8.314462
# calculate mu for T
fv = myhydro.moms.get('fv',fname=mydump)
mu = cldmu * fv + (1-fv)*airmu
P = myhydro.moms.get('P',fname=mydump)
rho = myhydro.moms.get('rho',fname=mydump)
T9 = (mu * P) / (Rgas * rho)
# get the radial profile of T
T9_moms, R_moms = myhydro.moms.get_rprof(T9)
In [ ]:
# this ensures that I can open an close the figure that was plotted within this cell.
# It doesn't matter in what order I run the notebook cells, this keeps track of it
celln = 3
# configure plots
close_local = ppm.close_plot(celln,ifig,ptrack)
if close_local[0]:
plt.close(fig); ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
else:
ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
# set the colour/linestyle counter to 0 and create axes
cbc = 0
ax = fig.add_subplot(111)
ax.plot(R_rprof, T9_rprof, label='Rprof', color=cb(cbc)[2], ls=cb(cbc)[0])
cbc += 1
ax.plot(R_moms, T9_moms, label='MomsData', color=cb(cbc)[2], ls=cb(cbc)[0])
cbc += 1
# plot details
ax.set_ylabel('T9')
ax.set_xlabel('r / Mm')
ax.set_xlim([0, R_rprof.max()])
ax.legend(frameon=False,fontsize=8)
In [ ]:
U_rprof = myhydro.rprof.get('|U|',fname=mydump)
# we computed |U| from the cartesian components of U as well as spherical and they are the same on the
# entire grid. Use cartesian
U_moms, R_moms = myhydro.moms.get_rprof(u_cartesian)
In [ ]:
# this ensures that I can open an close the figure that was plotted within this cell.
# It doesn't matter in what order I run the notebook cells, this keeps track of it
celln = 4
# configure plots
close_local = ppm.close_plot(celln,ifig,ptrack)
if close_local[0]:
plt.close(fig); ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
else:
ifig += 1; fig = plt.figure(ifig,figsize=(3.5,2.5),dpi=300)
ppm.add_plot(celln,ifig,ptrack)
# set the colour/linestyle counter to 0 and create axes
cbc = 0
ax = fig.add_subplot(111)
# convert to km/s
ax.plot(R_rprof, U_rprof*1e3, label='Rprof', color=cb(cbc)[2], ls=cb(cbc)[0])
cbc += 1
ax.plot(R_moms, U_moms*1e3, label='MomsData', color=cb(cbc)[2], ls=cb(cbc)[0])
cbc += 1
# plot details
ax.set_ylabel('|U| / km s$^{-1}$')
ax.set_xlabel('r / Mm')
ax.set_xlim([0, R_rprof.max()])
ax.set_ylim([0,16])
ax.legend(frameon=False,fontsize=8)
In [ ]: