{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3D AMRVAC - Reduction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We reduce (or resample) the Magritte model of the 3D AMRVAC snapshot that was created in the [previous example](1_create_AMRVAC_3D.ipynb) using the methods explained in [Ceulemans et al. (2024) in prep]. This is an improvement over the previous implementation of [De Ceuster et al. (2020)](https://ui.adsabs.harvard.edu/abs/2020MNRAS.499.5194D/abstract)." ] }, { "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 magrittetorch.tools.radiativetransferutils as rtutils\n", "import magrittetorch.tools.setup as setup\n", "import magrittetorch.tools.mesher as mesher\n", "import torch\n", "from magrittetorch.model.model import Model # Model class\n", "from magrittetorch.model.geometry.geometry import GeometryType # GeometryType enum\n", "from magrittetorch.model.geometry.boundary import BoundaryType # BoundaryType enum\n", "import numpy as np # Data structures\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, units # Unit conversions\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). We assume here that the scripts of the [previous example](1_create_AMRVAC_3D.ipynb) have already been executed and go back to that working directory." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "wdir = \"/lhome/thomasc/Magrittetorch-examples/AMRVAC_3D/\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define file names." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "model_file = os.path.join(wdir, 'model_AMRVAC_3D.hdf5') # Original Magritte model\n", "lamda_file = os.path.join(wdir, 'co.txt' ) # Line data file\n", "redux_file = os.path.join(wdir, 'model_AMRVAC_3D_red' ) # Reduced Magritte model (no extension!)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Load the original model." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Reading model from: /lhome/thomasc/Magrittetorch-examples/AMRVAC_3D/model_AMRVAC_3D.hdf5\n", "Reading Magrittetorch model\n" ] } ], "source": [ "original_model = Model(model_file)\n", "original_model.read()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Extract the data from the model by casting it into numpy arrays." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "position = original_model.geometry.points.position.get_astropy()\n", "velocity = original_model.geometry.points.velocity.get_astropy()\n", "boundary = original_model.geometry.boundary.boundary2point.get()#indices, so need no units\n", "nCO = original_model.chemistry.species.abundance.get_astropy()[:,0]\n", "nH2 = original_model.chemistry.species.abundance.get_astropy()[:,1]\n", "tmp = original_model.thermodynamics.temperature.gas.get_astropy()\n", "trb = original_model.thermodynamics.turbulence.vturb.get_astropy()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use the (new) built-in remeshing procedure for point clouds" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "new interior points: 30635\n", "number boundary points: 1538\n" ] } ], "source": [ "positions_reduced, nb_boundary = mesher.remesh_point_cloud(position, nCO, max_depth=9, threshold= 4e-1, hullorder=4)\n", "boundary_reduced = positions_reduced[:nb_boundary,:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compare the number of points in the original and the reduced mesh." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "npoints = original_model.parameters.npoints.get()\n", "npoints_reduced = len(positions_reduced)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "npoints original = 304130\n", "npoints reduced = 32173\n", "reduction factor = 9.452957448792466\n" ] } ], "source": [ "print('npoints original =', npoints)\n", "print('npoints reduced =', npoints_reduced)\n", "print('reduction factor =', npoints/npoints_reduced)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Interpolate the data to the reduced mesh. Effectively we find out which points in the original mesh are closes to which point in the reduced mesh and we simpliy map the data between the correpsonding points." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# Find closest points\n", "corresp_points = cKDTree(position).query(positions_reduced)[1]\n", "\n", "# Map data\n", "position_reduced = positions_reduced\n", "velocity_reduced = velocity[corresp_points]\n", "nCO_reduced = nCO [corresp_points]\n", "nH2_reduced = nH2 [corresp_points]\n", "tmp_reduced = tmp [corresp_points]\n", "trb_reduced = trb [corresp_points]\n", "\n", "# Extract Delaunay vertices (= Voronoi neighbors)\n", "delaunay = Delaunay(position_reduced)\n", "(indptr, indices) = delaunay.vertex_neighbor_vertices\n", "neighbors = [indices[indptr[k]:indptr[k+1]] for k in range(npoints_reduced)]\n", "nbs = [n for sublist in neighbors for n in sublist]\n", "n_nbs = [len(sublist) for sublist in neighbors]\n", "\n", "# Convenience arrays\n", "zeros = np.zeros(npoints_reduced)\n", "ones = np.ones (npoints_reduced)\n", "\n", "# map to torch\n", "# The reduction places boundary indices at start of list\n", "boundary_torch = torch.arange((nb_boundary), dtype=torch.int64)\n", "nbs_torch = torch.tensor(nbs, dtype=torch.int64)\n", "n_nbs_torch = torch.tensor(n_nbs, dtype=torch.int64)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now all data is read, we can use it to construct a Magrittetorch model.\n", "\n", "