diff options
-rw-r--r-- | Tools/Algorithms/psatd.ipynb | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/Tools/Algorithms/psatd.ipynb b/Tools/Algorithms/psatd.ipynb new file mode 100644 index 000000000..c2f326e41 --- /dev/null +++ b/Tools/Algorithms/psatd.ipynb @@ -0,0 +1,721 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "import sympy as sp\n", + "from sympy import *\n", + "\n", + "sp.init_session()\n", + "sp.init_printing()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Selection of algorithm:\n", + "- `divE_cleaning` (bool: `True`, `False`): \"$\\text{div}(\\boldsymbol{E})$ cleaning\" using the additional scalar field $F$;\n", + "\n", + "- `divB_cleaning` (bool: `True`, `False`): \"$\\text{div}(\\boldsymbol{B})$ cleaning\" using the additional scalar field $G$;\n", + "\n", + "- `J_in_time` (str: `'constant'`, `'linear'`, `'quadratic'`): $\\boldsymbol{J}$ constant, linear, or quadratic in time;\n", + "\n", + "- `rho_in_time` (str: `'constant'`, `'linear'`, `'quadratic'`): $\\rho$ constant, linear, or quadratic in time.\n", + "\n", + "In the notebook, the constant, linear, and quadratic coefficients of $\\boldsymbol{J}$ and $\\rho$ are denoted with the suffixes `_c0`, `_c1`, `_c2`, respectively. However, the corresponding coefficients in the displayed equations are denoted with the prefixes $\\gamma$, $\\beta$, and $\\alpha$, respectively. For example, if $\\rho$ is quadratic in time, it will be denoted as `rho = rho_c0 + rho_c1*(t-tn) + rho_c2*(t-tn)**2` in the notebook and $\\rho(t) = \\gamma_{\\rho} + \\beta_{\\rho} (t-t_n) + \\alpha_{\\rho} (t-t_n)^2$ in the displayed equations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "divE_cleaning = True\n", + "divB_cleaning = True\n", + "J_in_time = 'constant'\n", + "rho_in_time = 'constant'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Auxiliary functions:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def check_diag(W, D, P, invP):\n", + " \"\"\"\n", + " Check diagonalization of W as P*D*P**(-1).\n", + " \"\"\"\n", + " Wd = P * D * invP\n", + " for i in range(Wd.shape[0]):\n", + " for j in range(Wd.shape[1]):\n", + " Wd[i,j] = Wd[i,j].expand().simplify()\n", + " diff = W[i,j] - Wd[i,j]\n", + " diff = diff.expand().simplify()\n", + " assert (diff == 0), f'Diagonalization failed: W[{i},{j}] - Wd[{i},{j}] = {diff} is not zero'\n", + "\n", + "def simple_mat(W):\n", + " \"\"\"\n", + " Simplify matrix W.\n", + " \"\"\"\n", + " for i in range(W.shape[0]):\n", + " for j in range(W.shape[1]):\n", + " W[i,j] = W[i,j].expand().simplify()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Definition of symbols:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define dimensionality parameter used throughout the notebook\n", + "dim = 6\n", + "if divE_cleaning:\n", + " dim += 1\n", + "if divB_cleaning:\n", + " dim += 1\n", + "\n", + "# Define symbols for physical constants\n", + "c = sp.symbols(r'c', real=True, positive=True)\n", + "mu0 = sp.symbols(r'\\mu_0', real=True, positive=True)\n", + "\n", + "# Define symbols for time variables\n", + "# (s is auxiliary variable used in integral over time)\n", + "s = sp.symbols(r's', real=True, positive=True)\n", + "t = sp.symbols(r't', real=True, positive=True)\n", + "tn = sp.symbols(r't_n', real=True, positive=True)\n", + "dt = sp.symbols(r'\\Delta{t}', real=True, positive=True)\n", + "\n", + "# The assumption that kx, ky and kz are positive is general enough\n", + "# and makes it easier for SymPy to perform some of the calculations\n", + "kx = sp.symbols(r'k_x', real=True, positive=True)\n", + "ky = sp.symbols(r'k_y', real=True, positive=True)\n", + "kz = sp.symbols(r'k_z', real=True, positive=True)\n", + "\n", + "# Define symbols for the Cartesian components of the electric field\n", + "Ex = sp.symbols(r'E^x')\n", + "Ey = sp.symbols(r'E^y')\n", + "Ez = sp.symbols(r'E^z')\n", + "E = Matrix([[Ex], [Ey], [Ez]])\n", + "\n", + "# Define symbols for the Cartesian components of the magnetic field\n", + "Bx = sp.symbols(r'B^x')\n", + "By = sp.symbols(r'B^y')\n", + "Bz = sp.symbols(r'B^z')\n", + "B = Matrix([[Bx], [By], [Bz]])\n", + "\n", + "# Define symbol for the scalar field F used with div(E) cleaning\n", + "if divE_cleaning:\n", + " F = sp.symbols(r'F')\n", + "\n", + "# Define symbol for the scalar field G used with div(B) cleaning\n", + "if divB_cleaning:\n", + " G = sp.symbols(r'G')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### First-order ODEs for $\\boldsymbol{E}$, $\\boldsymbol{B}$, $F$ and $G$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define first-order time derivatives of the electric field\n", + "dEx_dt = I*c**2*(ky*Bz-kz*By) \n", + "dEy_dt = I*c**2*(kz*Bx-kx*Bz)\n", + "dEz_dt = I*c**2*(kx*By-ky*Bx)\n", + "\n", + "# Define first-order time derivatives of the magnetic field\n", + "dBx_dt = -I*(ky*Ez-kz*Ey)\n", + "dBy_dt = -I*(kz*Ex-kx*Ez)\n", + "dBz_dt = -I*(kx*Ey-ky*Ex)\n", + "\n", + "# Define first-order time derivative of the scalar field F used with div(E) cleaning,\n", + "# and related additional terms in the first-order time derivative of the electric field\n", + "if divE_cleaning:\n", + " dEx_dt += I*c**2*F*kx \n", + " dEy_dt += I*c**2*F*ky\n", + " dEz_dt += I*c**2*F*kz\n", + " dF_dt = I*(kx*Ex+ky*Ey+kz*Ez)\n", + "\n", + "# Define first-order time derivative of the scalar field G used with div(B) cleaning,\n", + "# and related additional terms in the first-order time derivative of the magnetic field\n", + "if divB_cleaning:\n", + " dBx_dt += I*c**2*G*kx\n", + " dBy_dt += I*c**2*G*ky\n", + " dBz_dt += I*c**2*G*kz\n", + " dG_dt = I*(kx*Bx+ky*By+kz*Bz)\n", + "\n", + "# Define array of first-order time derivatives of the electric and magnetic fields\n", + "dE_dt = Matrix([[dEx_dt], [dEy_dt], [dEz_dt]])\n", + "dB_dt = Matrix([[dBx_dt], [dBy_dt], [dBz_dt]])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linear system of ODEs for $\\boldsymbol{E}$, $\\boldsymbol{B}$, $F$ and $G$:\n", + "$$\n", + "\\frac{\\partial}{\\partial t}\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E} \\\\\n", + "\\boldsymbol{B} \\\\\n", + "F \\\\\n", + "G\n", + "\\end{bmatrix}\n", + "= M\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E} \\\\\n", + "\\boldsymbol{B} \\\\\n", + "F \\\\\n", + "G\n", + "\\end{bmatrix}\n", + "-\\mu_0 c^2 \n", + "\\begin{bmatrix}\n", + "\\boldsymbol{J} \\\\\n", + "\\boldsymbol{0} \\\\\n", + "\\rho \\\\\n", + " 0\n", + "\\end{bmatrix}\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Define array of all fields\n", + "fields_list = [Ex, Ey, Ez, Bx, By, Bz]\n", + "if divE_cleaning:\n", + " fields_list.append(F)\n", + "if divB_cleaning:\n", + " fields_list.append(G)\n", + "EBFG = zeros(dim, 1)\n", + "for i in range(EBFG.shape[0]):\n", + " EBFG[i] = fields_list[i]\n", + "\n", + "# Define array of first-order time derivatives of all fields\n", + "fields_list = [dEx_dt, dEy_dt, dEz_dt, dBx_dt, dBy_dt, dBz_dt]\n", + "if divE_cleaning:\n", + " fields_list.append(dF_dt)\n", + "if divB_cleaning:\n", + " fields_list.append(dG_dt)\n", + "dEBFG_dt = zeros(dim, 1)\n", + "for i in range(dEBFG_dt.shape[0]):\n", + " dEBFG_dt[i] = fields_list[i]\n", + "dEBFG_dt = dEBFG_dt.expand()\n", + "\n", + "# Define matrix M representing the linear system of ODEs\n", + "M = zeros(dim)\n", + "for i in range(M.shape[0]):\n", + " for j in range(M.shape[1]):\n", + " M[i,j] = dEBFG_dt[i].coeff(EBFG[j], 1)\n", + "print(r'M = ')\n", + "display(M)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solution of linear system of ODEs for $\\boldsymbol{E}$, $\\boldsymbol{B}$, $F$ and $G$:\n", + "\n", + "The solution of the linear system of ODEs above is given by the superposition of the **general solution of the homogeneous system** (denoted with the subscript \"h\"),\n", + "\n", + "$$\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E}_h(t) \\\\\n", + "\\boldsymbol{B}_h(t) \\\\\n", + "F_h(t) \\\\\n", + "G_h(t)\n", + "\\end{bmatrix}\n", + "= e^{M (t-t_n)}\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E}(t_n) \\\\\n", + "\\boldsymbol{B}(t_n) \\\\\n", + "F(t_n) \\\\\n", + "G(t_n)\n", + "\\end{bmatrix} \\,,\n", + "$$\n", + "\n", + "and the **particular solution of the non-homogeneous system** (denoted with the subscript \"nh\"),\n", + "\n", + "$$\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E}_{nh}(t) \\\\\n", + "\\boldsymbol{B}_{nh}(t) \\\\\n", + "F_{nh}(t) \\\\\n", + "G_{nh}(t)\n", + "\\end{bmatrix}\n", + "= -\\mu_0 c^2 e^{M t} \\left(\\int_{t_n}^t e^{-M s}\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{J} \\\\\n", + "\\boldsymbol{0} \\\\\n", + "\\rho \\\\\n", + "0\n", + "\\end{bmatrix}\n", + "ds\\right) \\,.\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Diagonalization of $M = P D P^{-1}$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "# Compute matrices of eigenvectors and eigenvalues for diagonalization of M\n", + "P, D = M.diagonalize()\n", + "invP = P**(-1)\n", + "expD = exp(D)\n", + "check_diag(M, D, P, invP)\n", + "print('P = ')\n", + "display(P)\n", + "print('D = ')\n", + "display(D)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Diagonalization of $W_1 = M (t-t_n) = P_1 D_1 P_1^{-1}$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "# Compute matrices of eigenvectors and eigenvalues for diagonalization of W1\n", + "P1 = P\n", + "D1 = D * (t-tn)\n", + "invP1 = invP\n", + "expD1 = exp(D1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Diagonalization of $W_2 = M t = P_2 D_2 P_2^{-1}$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "# Compute matrices of eigenvectors and eigenvalues for diagonalization of W2\n", + "P2 = P\n", + "D2 = D * t\n", + "invP2 = invP\n", + "expD2 = exp(D2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Diagonalization of $W_3 = -M s = P_3 D_3 P_3^{-1}$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "# Compute matrices of eigenvectors and eigenvalues for diagonalization of W3\n", + "P3 = P\n", + "D3 = (-1) * D * s\n", + "invP3 = invP\n", + "expD3 = exp(D3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### General solution (homogeneous system):\n", + "\n", + "$$\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E}_h(t) \\\\\n", + "\\boldsymbol{B}_h(t) \\\\\n", + "F_h(t) \\\\\n", + "G_h(t)\n", + "\\end{bmatrix}\n", + "= e^{M (t-t_n)}\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E}(t_n) \\\\\n", + "\\boldsymbol{B}(t_n) \\\\\n", + "F(t_n) \\\\\n", + "G(t_n)\n", + "\\end{bmatrix}\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "# Compute exp(W1) = exp(M*(t-tn))\n", + "expW1 = P1 * expD1 * invP1\n", + "\n", + "# Compute general solution at time t = tn+dt\n", + "EBFG_h = expW1 * EBFG \n", + "EBFG_h_new = EBFG_h.subs(t, tn+dt)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Definition of $\\boldsymbol{J}$ and $\\rho$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define J\n", + "Jx_c0 = sp.symbols(r'\\gamma_{J_x}', real=True)\n", + "Jy_c0 = sp.symbols(r'\\gamma_{J_y}', real=True)\n", + "Jz_c0 = sp.symbols(r'\\gamma_{J_z}', real=True)\n", + "Jx = Jx_c0\n", + "Jy = Jy_c0\n", + "Jz = Jz_c0\n", + "if J_in_time == 'linear':\n", + " Jx_c1 = sp.symbols(r'\\beta_{J_x}', real=True)\n", + " Jy_c1 = sp.symbols(r'\\beta_{J_y}', real=True)\n", + " Jz_c1 = sp.symbols(r'\\beta_{J_z}', real=True)\n", + " Jx += Jx_c1*(s-tn)\n", + " Jy += Jy_c1*(s-tn)\n", + " Jz += Jz_c1*(s-tn)\n", + "if J_in_time == 'quadratic':\n", + " Jx_c1 = sp.symbols(r'\\beta_{J_x}', real=True)\n", + " Jy_c1 = sp.symbols(r'\\beta_{J_y}', real=True)\n", + " Jz_c1 = sp.symbols(r'\\beta_{J_z}', real=True)\n", + " Jx_c2 = sp.symbols(r'\\alpha_{J_x}', real=True)\n", + " Jy_c2 = sp.symbols(r'\\alpha_{J_y}', real=True)\n", + " Jz_c2 = sp.symbols(r'\\alpha_{J_z}', real=True)\n", + " Jx += Jx_c1*(s-tn) + Jx_c2*(s-tn)**2\n", + " Jy += Jy_c1*(s-tn) + Jy_c2*(s-tn)**2\n", + " Jz += Jz_c1*(s-tn) + Jz_c2*(s-tn)**2\n", + "\n", + "# Define rho\n", + "if divE_cleaning:\n", + " rho_c0 = sp.symbols(r'\\gamma_{\\rho}', real=True)\n", + " rho = rho_c0\n", + " if rho_in_time == 'linear':\n", + " rho_c1 = sp.symbols(r'\\beta_{\\rho}', real=True)\n", + " rho += rho_c1*(s-tn)\n", + " if rho_in_time == 'quadratic':\n", + " rho_c1 = sp.symbols(r'\\beta_{\\rho}', real=True)\n", + " rho_c2 = sp.symbols(r'\\alpha_{\\rho}', real=True)\n", + " rho += rho_c1*(s-tn) + rho_c2*(s-tn)**2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Particular solution (non-homogeneous system):\n", + "\n", + "$$\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{E}_{nh}(t) \\\\\n", + "\\boldsymbol{B}_{nh}(t) \\\\\n", + "F_{nh}(t) \\\\\n", + "G_{nh}(t)\n", + "\\end{bmatrix}\n", + "= -\\mu_0 c^2 e^{M t} \\left(\\int_{t_n}^t e^{-M s}\n", + "\\begin{bmatrix}\n", + "\\boldsymbol{J} \\\\\n", + "\\boldsymbol{0} \\\\\n", + "\\rho \\\\\n", + "0\n", + "\\end{bmatrix}\n", + "ds\\right)\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "%%time \n", + "\n", + "# Define array of source terms\n", + "fields_list = [Jx, Jy, Jz, 0, 0, 0]\n", + "if divE_cleaning:\n", + " fields_list.append(rho)\n", + "if divB_cleaning:\n", + " fields_list.append(0)\n", + "S = zeros(dim, 1)\n", + "for i in range(S.shape[0]):\n", + " S[i] = -mu0*c**2 * fields_list[i]\n", + "\n", + "# Compute integral of exp(W3)*S over s (assuming |k| is not zero)\n", + "integral = zeros(dim, 1)\n", + "tmp = expD3 * invP3 * S\n", + "simple_mat(tmp)\n", + "for i in range(dim):\n", + " r = integrate(tmp[i], (s, tn, t))\n", + " integral[i] = r\n", + " \n", + "# Compute particular solution at time t = tn+dt\n", + "tmp = invP2 * P3\n", + "simple_mat(tmp)\n", + "EBFG_nh = P2 * expD2 * tmp * integral\n", + "EBFG_nh_new = EBFG_nh.subs(t, tn+dt)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Verification of the solution:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "for i in range(EBFG.shape[0]):\n", + " lhs = dEBFG_dt[i] + S[i]\n", + " lhs = lhs.subs(s, tn) # sources were written as functions of s\n", + " rhs = (EBFG_h[i] + EBFG_nh[i]).diff(t)\n", + " rhs = rhs.subs(t, tn) # results were written as functions of t\n", + " rhs = rhs.simplify()\n", + " diff = lhs - rhs\n", + " diff = diff.simplify()\n", + " assert (diff == 0), f'Integration of linear system of ODEs failed'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coefficients of PSATD equations (homogeneous system):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "L = ['Ex', 'Ey', 'Ez', 'Bx', 'By', 'Bz']\n", + "R = ['Ex', 'Ey', 'Ez', 'Bx', 'By', 'Bz']\n", + "if divE_cleaning:\n", + " L.append('F')\n", + " R.append('F')\n", + "if divB_cleaning:\n", + " L.append('G')\n", + " R.append('G')\n", + "\n", + "# Compute individual coefficients in the update equations\n", + "coeff_h = dict()\n", + "for i in range(dim):\n", + " for j in range(dim):\n", + " key = (L[i], R[j])\n", + " coeff_h[key] = EBFG_h_new[i].coeff(EBFG[j], 1).expand().simplify().rewrite(cos).trigsimp().simplify()\n", + " print(f'Coefficient of {L[i]} with respect to {R[j]}:')\n", + " display(coeff_h[key])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coefficients of PSATD equations (non-homogeneous system):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "L = ['Ex', 'Ey', 'Ez', 'Bx', 'By', 'Bz']\n", + "R = ['Jx_c0', 'Jy_c0', 'Jz_c0']\n", + "if J_in_time == 'linear':\n", + " R.append('Jx_c1')\n", + " R.append('Jy_c1')\n", + " R.append('Jz_c1')\n", + "if J_in_time == 'quadratic':\n", + " R.append('Jx_c1')\n", + " R.append('Jy_c1')\n", + " R.append('Jz_c1')\n", + " R.append('Jx_c2')\n", + " R.append('Jy_c2')\n", + " R.append('Jz_c2')\n", + "if divE_cleaning:\n", + " L.append('F')\n", + " R.append('rho_c0')\n", + " if rho_in_time == 'linear':\n", + " R.append('rho_c1')\n", + " if rho_in_time == 'quadratic':\n", + " R.append('rho_c1')\n", + " R.append('rho_c2')\n", + "if divB_cleaning:\n", + " L.append('G')\n", + "\n", + "cs = [Jx_c0, Jy_c0, Jz_c0]\n", + "if J_in_time == 'linear':\n", + " cs.append(Jx_c1)\n", + " cs.append(Jy_c1)\n", + " cs.append(Jz_c1)\n", + "if J_in_time == 'quadratic':\n", + " cs.append(Jx_c1)\n", + " cs.append(Jy_c1)\n", + " cs.append(Jz_c1)\n", + " cs.append(Jx_c2)\n", + " cs.append(Jy_c2)\n", + " cs.append(Jz_c2)\n", + "if divE_cleaning:\n", + " cs.append(rho_c0)\n", + " if rho_in_time == 'linear':\n", + " cs.append(rho_c1)\n", + " if rho_in_time == 'quadratic':\n", + " cs.append(rho_c1)\n", + " cs.append(rho_c2)\n", + " \n", + "# Compute individual coefficients in the update equation\n", + "coeff_nh = dict()\n", + "for i in range(len(L)):\n", + " for j in range(len(R)):\n", + " key = (L[i], R[j])\n", + " coeff_nh[key] = EBFG_nh_new[i].expand().coeff(cs[j], 1).expand().simplify().rewrite(cos).trigsimp().simplify()\n", + " print(f'Coefficient of {L[i]} with respect to {R[j]}:')\n", + " display(coeff_nh[key])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coefficients of PSATD equations:\n", + "\n", + "Display the coefficients of the update equations one by one. For example, `coeff_h[('Ex', 'By')]` displays the coefficient of $E^x$ with respect to $B^y$ (resulting from the solution of the homogeneous system, hence the `_h` suffix), while `coeff_nh[('Ex', 'Jx_c0')]` displays the coefficient of $E^x$ with respect to $\\gamma_{J_x}$ (resulting from the solution of the non-homogeneous system, hence the `_nh` suffix). Note that $\\gamma_{J_x}$ is denoted as `Jx_c0` in the notebook, as described in the beginning." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "coeff_h[('Ex', 'By')]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "coeff_nh[('Ex', 'Jx_c0')]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} |