{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3D AMRVAC" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We create a Magritte model from a snapshot of 3D AMRVAC hydrodynamics simulation.\n", "The hydro model was kindly provided by Jan Bolte.\n", "Currently, the AMRVAC binary files can not yet be used directly to extract the snapshot data.\n", "Hence we use the corresponding `.vtu` files." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Import the required functionalty." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import magritte.setup as setup # Model setup\n", "import magritte.core as magritte # Core functionality\n", "import magritte.mesher as mesher\n", "import numpy as np # Data structures\n", "import vtk # Reading the model\n", "import warnings # Hide warnings\n", "warnings.filterwarnings('ignore') # especially for yt\n", "import yt # 3D plotting\n", "import os\n", "\n", "from tqdm import tqdm # Progress bars\n", "from astropy import constants # Unit conversions\n", "from vtk.util.numpy_support import vtk_to_numpy # Converting data\n", "from scipy.spatial import Delaunay, cKDTree # Finding neighbors\n", "from yt.funcs import mylog # To avoid yt output \n", "mylog.setLevel(40) # as error messages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define a working directory (you will have to change this; it must be an **absolute path**)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "wdir = \"/lhome/thomasc/Magritte-examples/AMRVAC_3D/\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create the working directory." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "!mkdir -p $wdir" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define file names." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "input_file = os.path.join(wdir, 'model_AMRVAC_3D.vtu' ) # AMRVAC snapshot\n", "model_file = os.path.join(wdir, 'model_AMRVAC_3D.hdf5') # Resulting Magritte model\n", "lamda_file = os.path.join(wdir, 'co.txt' ) # Line data file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use a snapshot and data file that can be downloaded with the following links." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "input_link = \"https://owncloud.ster.kuleuven.be/index.php/s/mqtDyDSMPm2TjmG/download\"\n", "lamda_link = \"https://home.strw.leidenuniv.nl/~moldata/datafiles/co.dat\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dowload the snapshot and the linedata (``%%capture`` is just used to suppress the output)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "%%capture\n", "!wget $input_link --output-document $input_file\n", "!wget $lamda_link --output-document $lamda_file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extract data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The script below extracts the required data from the snapshot `.vtu` file." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|███████████████████████████████████████| 89/89 [00:00<00:00, 307237.08it/s]\n", "100%|████████████████████████████████| 297984/297984 [00:04<00:00, 73535.32it/s]\n", "100%|██████████████████████████████| 2141089/2141089 [00:21<00:00, 99629.04it/s]\n" ] } ], "source": [ "# Create a vtk reader to read the AMRVAC file and extract its contents.\n", "reader = vtk.vtkXMLUnstructuredGridReader()\n", "reader.SetFileName(input_file)\n", "reader.Update()\n", "\n", "# Extract the grid output\n", "grid = reader.GetOutput()\n", "\n", "# Extract the number of cells\n", "ncells = grid.GetNumberOfCells() \n", "\n", "# Extract cell data\n", "cellData = grid.GetCellData()\n", "for i in tqdm(range(cellData.GetNumberOfArrays())):\n", " array = cellData.GetArray(i)\n", " if (array.GetName() == 'rho'):\n", " rho = vtk_to_numpy(array)\n", " if (array.GetName() == 'temperature'):\n", " tmp = vtk_to_numpy(array)\n", " if (array.GetName() == 'v1'):\n", " v_x = vtk_to_numpy(array)\n", " if (array.GetName() == 'v2'):\n", " v_y = vtk_to_numpy(array)\n", " if (array.GetName() == 'v3'):\n", " v_z = vtk_to_numpy(array)\n", "\n", "# Convert rho (total density) to abundances\n", "nH2 = rho * 1.0e+6 * constants.N_A.si.value / 2.02\n", "nCO = nH2 * 1.0e-4\n", "\n", "# Convenience arrays\n", "zeros = np.zeros(ncells)\n", "ones = np.ones (ncells)\n", "\n", "# Convert to fractions of the speed of light\n", "velocity = np.array((v_x, v_y, v_z)).transpose() / constants.c.cgs.value\n", "\n", "# Define turbulence at 150 m/s\n", "trb = (150.0/constants.c.si.value)**2 * ones\n", "\n", "# Extract cell centres as Magritte points\n", "centres = []\n", "for c in tqdm(range(ncells)):\n", " cell = grid.GetCell(c)\n", " centre = np.zeros(3)\n", " for i in range(8):\n", " centre = centre + np.array(cell.GetPoints().GetPoint(i))\n", " centre = 0.125 * centre\n", " centres.append(centre)\n", "centres = np.array(centres)\n", "centres *= 1.0e-2 # convert [cm] to [m]\n", "position = centres\n", "\n", "# We assume that the geometry to be rectangular. We still need to define the boundary however.\n", "# For adaptive mesh refinement models, we put a boundary box around it (to ensure that we have a convex boundary around the model; this is mainly important for imaging the model).\n", "\n", "delta_xyz = (np.max(centres, axis=0) - np.min(centres, axis=0))/2.0#half the width in each direction\n", "center_xyz = (np.max(centres, axis=0) + np.min(centres, axis=0))/2.0\n", "xyz_max = center_xyz + 1.001*delta_xyz\n", "xyz_min = center_xyz - 1.001*delta_xyz\n", "\n", "# Add a boundary box around the model, putting the boundary points on a regular grid\n", "box = mesher.create_cubic_uniform_hull(xyz_min, xyz_max, order=5)#the boundary box contains 2**order+1 points in each direction.\n", "nbox = len(box)\n", "\n", "# Find closest points, in order to extrapolate the values towards the boundary box.\n", "corresp_points = cKDTree(position).query(box)[1]\n", "\n", "# Map data of model to box\n", "position_box = box\n", "velocity_box = velocity[corresp_points]\n", "nCO_box = nCO [corresp_points]\n", "nH2_box = nH2 [corresp_points]\n", "tmp_box = tmp [corresp_points]\n", "trb_box = trb [corresp_points]\n", "\n", "#and extend data arrays\n", "nCO = np.concatenate((nCO_box, nCO))\n", "nH2 = np.concatenate((nH2_box, nH2))\n", "zeros = np.concatenate((np.zeros(nbox), zeros))\n", "ones = np.concatenate((np.ones(nbox), ones))\n", "velocity = np.concatenate((velocity_box, velocity), axis=0)\n", "tmp = np.concatenate((tmp_box, tmp))\n", "trb = np.concatenate((trb_box, trb))\n", "position = np.concatenate((box, position), axis=0)\n", "\n", "\n", "# Extract Delaunay vertices (= Voronoi neighbors)\n", "delaunay = Delaunay(position)\n", "(indptr, indices) = delaunay.vertex_neighbor_vertices\n", "neighbors = [indices[indptr[k]:indptr[k+1]] for k in range(len(position))]\n", "nbs = [n for sublist in neighbors for n in sublist]\n", "n_nbs = [len(sublist) for sublist in neighbors]\n", "\n", "# Compute the indices of the boundary particles of the mesh, extracted from the Delaunay vertices\n", "# Note: technically, we already know the boundary (the constructed box), but as we compute a Delaunay triangulation either way to find the neighbors, we might as well use it to compute the boundary points.\n", "boundary = set([])\n", "for i in tqdm(range(delaunay.neighbors.shape[0])):\n", " for k in range(4):\n", " if (delaunay.neighbors[i][k] == -1):\n", " nk1,nk2,nk3 = (k+1)%4, (k+2)%4, (k+3)%4 \n", " boundary.add(delaunay.simplices[i][nk1])\n", " boundary.add(delaunay.simplices[i][nk2])\n", " boundary.add(delaunay.simplices[i][nk3])\n", "\n", "boundary = list(boundary)\n", "boundary = np.array(boundary)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now all data is read, we can use it to construct a Magritte model.\n", "\n", "