"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Introducing sparse matrices\n",
"\n",
"This is a rerun of the 2D_Transient_Assignment with two differences:\n",
"\n",
"1. It imports common functions from a new python module called module_2D.py\n",
"\n",
"1. It uses the scipy.sparse compressed storage format for rows (csr) with\n",
" the sparse solver spsolve"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"lines_to_next_cell": 2,
"nbgrader": {
"grade": false,
"grade_id": "cell-e58a84ffce31f93a",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"It looks like I've been imported by another python script\n",
"My file location is: \n",
"/Users/phil/repos/eosc213_students/notebooks/2D_Assignment_sparse/module_2D.py\n",
"\n"
]
}
],
"source": [
"import time\n",
"\n",
"import matplotlib.cm as cmap\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from module_2D import Boundary_Def\n",
"from module_2D import build_2D_matrix\n",
"from module_2D import mat2vec\n",
"from module_2D import Problem_Def\n",
"from module_2D import vec2mat\n",
"from mpl_toolkits.axes_grid1 import AxesGrid\n",
"from scipy.sparse import csr_matrix\n",
"from scipy.sparse.linalg import spsolve"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Set up the boundary values"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"c0 = 1 # mg/L"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"nbgrader": {
"grade": false,
"grade_id": "cell-f97ab996f12bd2f2",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"# Here we create 4 boundaries, west has a constant concentration at c0, east has a constant boundary at 0;\n",
"west = Boundary_Def(\"const\", val=c0)\n",
"east = Boundary_Def(\"const\", val=0)\n",
"\n",
"# For 1D problem, the used boundaries are west and east.\n",
"\n",
"# The other south and north boundaries have a zero flux (impermeable)\n",
"\n",
"north = Boundary_Def(\"flux\", val=0)\n",
"south = Boundary_Def(\"flux\", val=0)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"nbgrader": {
"grade": false,
"grade_id": "cell-ea536fa5b54285e2",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"bc_dict = {\"west\": west, \"north\": north, \"east\": east, \"south\": south}\n",
"# The latter array bc_dict will be sent to the different functions"
]
},
{
"cell_type": "markdown",
"metadata": {
"nbgrader": {
"grade": false,
"grade_id": "cell-7bfb0e282680103b",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"source": [
"## Set up the diffusivity matrix\n",
"\n",
"Going from 1 to 2 dimensions changes nothing conceptually. There are, however a couple of changes required for the coding perspective. Indeed, whether the problem is 1D or 2D or 3D, the stucture of the system of equation Ac = b is the same. Matrix $A$ will always be a $n \\times n$ matrix, while $c$ and $b$ will always be column vector of size $n$. In 2D, $n = n_x \\times n_y$, while in 3D, it will be $n = n_x \\times n_y \\times n_z$. The individual equation for a cell still\n",
"produces a single row in the A and b matrices, but in 2D that cell has 4 neighbours instead\n",
"of 2, and 3D it has 6 neighbors intead of 4.\n",
"\n",
"However, the fact is that in every case, the solution is stored in one vector, representing either a 1/2/3D solution. For these higher dimension problems, a two-way conversion between vector and matrix is required. To plot the 2D result, for example, we will use colourmap plots, which require the solution to be plotted to be represented as a 2D array (matrix).\n",
"\n",
"The function vec2mat(...) (specifically $vector\\ to\\ matrix$) does this: it converts a vector into the relevant 2D matrix, using n_x and n_y.\n",
"\n",
"The reverse function is usually required to initialize the initial condition. It is mac2vec(...). These two functions are defined here below."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"decreasing_factor = 0.1 # Feel free to change if you want to see the impact\n",
"# (you can go higher than 1 ... But be careful, if diffusion speeds up significantly,\n",
"# the accuracy with respect to the chosen timestep might not be so good if you speed things up! )\n",
"# Initial value is 0.01"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"lines_to_next_cell": 2,
"nbgrader": {
"grade": false,
"grade_id": "cell-42d47ff484f9a502",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [],
"source": [
"Diff = 2e-9 * 100 * 24 * 3600 # dmĀ²/day"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"lines_to_next_cell": 2,
"nbgrader": {
"grade": false,
"grade_id": "cell-b9bd7eaf90619a64",
"locked": true,
"schema_version": 1,
"solution": false
}
},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"