|
337 | 337 | "cell_type": "markdown", |
338 | 338 | "metadata": {}, |
339 | 339 | "source": [ |
340 | | - "We can visualise the poloidal flux produced by the unstable mode using the following code. We can also do this for other (stable) modes if required (just change the index `i` in the cell below)." |
| 340 | + "We can visualise the poloidal flux produced by the unstable mode using the following code. We can also do this for other (stable) modes if required (just change the index `i` in the cell below).\n", |
| 341 | + "\n", |
| 342 | + "The physical metal currents $\\vec{I}_m$ and normal-mode currents $\\vec{I}_d$ are related by\n", |
| 343 | + "\n", |
| 344 | + "$$\\vec{I}_m = P\\vec{I}_d.$$\n", |
| 345 | + "\n", |
| 346 | + "Writing the physical-metal Green maps as $G_m$, the flux is therefore\n", |
| 347 | + "\n", |
| 348 | + "$$\\psi = \\vec{I}_m^T G_m = \\vec{I}_d^T P^T G_m.$$\n", |
| 349 | + "\n", |
| 350 | + "Thus the Green maps per unit normal-mode current are $G_d=P^T G_m$. Notice that this is a covector transformation: $P^{-1}$ is used to recover modal currents from physical currents, but it is not the transformation for the Green maps." |
341 | 351 | ] |
342 | 352 | }, |
343 | 353 | { |
|
348 | 358 | "source": [ |
349 | 359 | "# mode number (choose which one you want to visualise)\n", |
350 | 360 | "i = idx # default is unstable mode\n", |
351 | | - "mode_currents = np.real(modes[:,i])\n", |
| 361 | + "mode_currents = np.real(modes[:-1, i])\n", |
352 | 362 | "\n", |
353 | 363 | "# the associated instability timescale and growth rate\n", |
354 | 364 | "print(f\"Mode {i} ---> {'stable' if np.real(timescales[i]) < 0 else 'unstable'}\")\n", |
355 | 365 | "print(f\"Growth rate = {np.real(growth_rates[i]):.2e} [1/s]\")\n", |
356 | 366 | "print(f\"Timescale = {np.real(timescales[i]):.2e} [s]\")\n", |
357 | 367 | "\n", |
358 | | - "# multiply each metal current (from the eigenvector) with its corresponding Greens matrix and sum\n", |
359 | | - "# (don't forget to omit the plasma current mode, i.e. the final element)\n", |
360 | | - "flux = np.sum(mode_currents[0:-1, np.newaxis, np.newaxis] * nonlinear_solver.vessel_modes_greens[i], axis=0)\n", |
| 368 | + "# Contract the modal currents with the modal Green maps G_d = P.T @ G_m.\n", |
| 369 | + "# The final eigenvector element, representing plasma current, was omitted above.\n", |
| 370 | + "flux = np.einsum(\"i,ijk->jk\", mode_currents, nonlinear_solver.vessel_modes_greens)\n", |
361 | 371 | "\n", |
362 | 372 | "# plot\n", |
363 | 373 | "fig, ax = plt.subplots(1, 1, figsize=(5, 8), dpi=60)\n", |
|
743 | 753 | "cell_type": "markdown", |
744 | 754 | "metadata": {}, |
745 | 755 | "source": [ |
746 | | - "Again, we can plot how these look using similar code as before, except we need to remember that now we've done a mode decomposition, the eigenmode currents $\\vec{I}_d$ need to be transformed back into the original metal currents $\\vec{I}_m$. This is done in the plotting cell below." |
| 756 | + "Again, we can plot how these look using similar code as before. Here we explicitly transform the retained normal-mode currents back to physical metal currents using $\\vec{I}_m=P\\vec{I}_d$, then contract those currents with the physical-metal Green maps $G_m$. This is equivalent to contracting $\\vec{I}_d$ with the corresponding retained rows of $G_d=P^T G_m$." |
747 | 757 | ] |
748 | 758 | }, |
749 | 759 | { |
|
784 | 794 | "\n", |
785 | 795 | "# this function transforms the (decomposed) mode currents back to regular metal currents\n", |
786 | 796 | "# (don't forget to omit the plasma current mode, i.e. the final element)\n", |
787 | | - "mode_currents = nonlinear_solver_option_1.evol_metal_curr.IdtoIvessel(np.real(modes[0:-1,i]))\n", |
| 797 | + "mode_currents = nonlinear_solver_option_1.evol_metal_curr.IdtoIvessel(\n", |
| 798 | + " np.real(modes[:-1, i])\n", |
| 799 | + ")\n", |
788 | 800 | "\n", |
789 | 801 | "# the associated instability timescale and growth rate\n", |
790 | 802 | "print(f\"Mode {i} ---> {'stable' if np.real(timescales[i]) < 0 else 'unstable'}\")\n", |
791 | 803 | "print(f\"Growth rate = {np.real(growth_rates[i]):.2e} [1/s]\")\n", |
792 | 804 | "print(f\"Timescale = {np.real(timescales[i]):.2e} [s]\")\n", |
793 | 805 | "\n", |
794 | | - "# multiply each metal current (from the eigenvector) with its corresponding Greens matrix and sum\n", |
795 | | - "flux = np.sum(mode_currents[:, np.newaxis, np.newaxis] * nonlinear_solver_option_1.vessel_modes_greens[i], axis=0)\n", |
| 806 | + "# Contract reconstructed physical currents with the physical-metal Green maps.\n", |
| 807 | + "flux = np.einsum(\"i,ijk->jk\", mode_currents, eq._vgreen)\n", |
796 | 808 | "\n", |
797 | 809 | "# plot\n", |
798 | 810 | "fig, ax = plt.subplots(1, 1, figsize=(5, 8), dpi=60)\n", |
|
0 commit comments