|
69 | 69 | "\n", |
70 | 70 | "for key in current_values.keys():\n", |
71 | 71 | " eq.tokamak[key].current = current_values[key]\n", |
| 72 | + "eq.tokamak[\"P6\"].current += 100\n", |
72 | 73 | "\n", |
73 | 74 | "# carry out forward solve\n", |
74 | 75 | "GSStaticSolver.solve(eq=eq, \n", |
|
920 | 921 | "ax2.grid(zorder=0, alpha=0.75)\n", |
921 | 922 | "ax2.plot(psi_n, profiles.ffprime(psi_n), color='k', linewidth=1, marker='x', markersize=2, zorder=10)\n", |
922 | 923 | "ax2.set_xlabel(r'$\\hat{\\psi}$')\n", |
923 | | - "ax2.set_ylabel(r\"$FF'(\\hat{\\psi})$\")\n" |
| 924 | + "ax2.set_ylabel(r\"$FF'(\\hat{\\psi})$\")" |
| 925 | + ] |
| 926 | + }, |
| 927 | + { |
| 928 | + "cell_type": "code", |
| 929 | + "execution_count": null, |
| 930 | + "metadata": {}, |
| 931 | + "outputs": [], |
| 932 | + "source": [ |
| 933 | + "# plot the p and F profiles\n", |
| 934 | + "\n", |
| 935 | + "psi_n = eq.psiN_1D(N=65)\n", |
| 936 | + "\n", |
| 937 | + "fig1, (ax1, ax2) = plt.subplots(1, 2, figsize=(15,6), dpi=80)\n", |
| 938 | + "ax1.grid(zorder=0, alpha=0.75)\n", |
| 939 | + "ax1.plot(psi_n, profiles.pressure(psi_n), color='k', linewidth=1, marker='x', markersize=2, zorder=10)\n", |
| 940 | + "ax1.set_xlabel(r'$\\hat{\\psi}$')\n", |
| 941 | + "ax1.set_ylabel(r\"$p(\\hat{\\psi})$\")\n", |
| 942 | + "ax1.ticklabel_format(axis='y', scilimits=(0,0))\n", |
| 943 | + "\n", |
| 944 | + "ax2.grid(zorder=0, alpha=0.75)\n", |
| 945 | + "ax2.plot(psi_n, profiles.fpol(psi_n), color='k', linewidth=1, marker='x', markersize=2, zorder=10)\n", |
| 946 | + "ax2.set_xlabel(r'$\\hat{\\psi}$')\n", |
| 947 | + "ax2.set_ylabel(r\"$F(\\hat{\\psi})$\")\n" |
924 | 948 | ] |
925 | 949 | }, |
926 | 950 | { |
|
996 | 1020 | "plt.tight_layout()" |
997 | 1021 | ] |
998 | 1022 | }, |
999 | | - { |
1000 | | - "cell_type": "code", |
1001 | | - "execution_count": null, |
1002 | | - "metadata": {}, |
1003 | | - "outputs": [], |
1004 | | - "source": [ |
1005 | | - "# # plot 1D_jtor\n", |
1006 | | - "# fig1, ax1 = plt.subplots(1, 1, figsize=(6,6), dpi=80)\n", |
1007 | | - "# ax1.grid(zorder=0, alpha=0.75)\n", |
1008 | | - "# ax1.plot(eq.psiN_1D(N=101), eq.jtor_1D(N=101), color='k', linewidth=1, marker='x', markersize=2, zorder=10)\n", |
1009 | | - "# ax1.set_xlabel(r'$\\hat{\\psi}$')\n", |
1010 | | - "# ax1.set_ylabel(r\"$J_{tor}(\\hat{\\psi})$\")" |
1011 | | - ] |
1012 | | - }, |
1013 | 1023 | { |
1014 | 1024 | "cell_type": "markdown", |
1015 | 1025 | "metadata": {}, |
|
1054 | 1064 | "\n", |
1055 | 1065 | "plt.tight_layout()" |
1056 | 1066 | ] |
| 1067 | + }, |
| 1068 | + { |
| 1069 | + "cell_type": "markdown", |
| 1070 | + "metadata": {}, |
| 1071 | + "source": [ |
| 1072 | + "### Flux averaged quantities\n", |
| 1073 | + "\n", |
| 1074 | + "The `equilibrium` class provides a method to calculate the \"flux averaged\" value of a user-defined 2D scalar field $f(R,Z)$, using [line integrals](https://tutorial.math.lamar.edu/classes/calciii/LineIntegralsPtI.aspx), on a given (normalised) flux surface of $\\psi_n$ (within the last closed flux surface). The flux average $\\langle f \\rangle$ is given by\n", |
| 1075 | + "\n", |
| 1076 | + "$$\n", |
| 1077 | + "\\langle f \\rangle (\\psi_n) = \\frac{ \\int_{C(\\psi_n)} \\frac{f(R,Z)}{B_{\\text{pol}}(R,Z)}\\, ds}{ \\int_{C(\\psi_n)} \\frac{1}{B_{\\text{pol}}(R,Z)} \\, ds },\n", |
| 1078 | + "$$\n", |
| 1079 | + "\n", |
| 1080 | + "where:\n", |
| 1081 | + "- $f(R,Z)$ = 2D scalar field function (e.g. the plasma current density function $J_p(R,Z)$).\n", |
| 1082 | + "- $\\psi_n$ = value of normalised flux at which to evaluate line integrals.\n", |
| 1083 | + "- $C(\\psi_n)$ = curve of $(R, Z)$ points satisfying $\\psi_n = \\text{const}$ (i.e. a flux contour).\n", |
| 1084 | + "- $B_{\\text{pol}}(R,Z)$ = 2D scalar poloidal magnetic field function.\n", |
| 1085 | + "- $ds$ = the arc length element (where $ds = \\sqrt{(dR/dl)^2 + (dZ/dl)^2} dl$ and $l \\in [0,L]$ is a parameterised length going from the beginning to the end of the contour).\n", |
| 1086 | + "\n", |
| 1087 | + "The definition of the flux average was taken from [Song et al. (2024)](https://www.mdpi.com/2571-6182/7/4/45)." |
| 1088 | + ] |
| 1089 | + }, |
| 1090 | + { |
| 1091 | + "cell_type": "markdown", |
| 1092 | + "metadata": {}, |
| 1093 | + "source": [ |
| 1094 | + "Here we will calculate the flux averaged values of the plasma current density by first defining a function that returns the current density at arbitrary $(R,Z)$ locations. " |
| 1095 | + ] |
| 1096 | + }, |
| 1097 | + { |
| 1098 | + "cell_type": "code", |
| 1099 | + "execution_count": null, |
| 1100 | + "metadata": {}, |
| 1101 | + "outputs": [], |
| 1102 | + "source": [ |
| 1103 | + "from scipy.interpolate import RectBivariateSpline\n", |
| 1104 | + "\n", |
| 1105 | + "def f(R,Z):\n", |
| 1106 | + " jtor = RectBivariateSpline(eq.R_1D, eq.Z_1D, eq._profiles.jtor)\n", |
| 1107 | + " return jtor(R, Z, grid=False)" |
| 1108 | + ] |
| 1109 | + }, |
| 1110 | + { |
| 1111 | + "cell_type": "markdown", |
| 1112 | + "metadata": {}, |
| 1113 | + "source": [ |
| 1114 | + "Next we can call the method in the equilibrium object and plot the results. Given the notation above, we note that $\\psi_n$ and $\\hat{\\psi}$ are equivalent. " |
| 1115 | + ] |
| 1116 | + }, |
| 1117 | + { |
| 1118 | + "cell_type": "code", |
| 1119 | + "execution_count": null, |
| 1120 | + "metadata": {}, |
| 1121 | + "outputs": [], |
| 1122 | + "source": [ |
| 1123 | + "# call the method\n", |
| 1124 | + "flux_averaged_jtor, psi_n = eq.flux_averaged_function(\n", |
| 1125 | + " f=f,\n", |
| 1126 | + " psi_n=np.linspace(0.0,1.0,101)\n", |
| 1127 | + " )" |
| 1128 | + ] |
| 1129 | + }, |
| 1130 | + { |
| 1131 | + "cell_type": "code", |
| 1132 | + "execution_count": null, |
| 1133 | + "metadata": {}, |
| 1134 | + "outputs": [], |
| 1135 | + "source": [ |
| 1136 | + "# plot\n", |
| 1137 | + "fig1, ax1 = plt.subplots(1, 1, figsize=(6,6), dpi=80)\n", |
| 1138 | + "ax1.grid(zorder=0, alpha=0.75)\n", |
| 1139 | + "ax1.plot(psi_n, flux_averaged_jtor, color='k', linewidth=1, marker='x', markersize=2, zorder=10)\n", |
| 1140 | + "ax1.set_xlabel(r'$\\hat{\\psi}$')\n", |
| 1141 | + "ax1.set_ylabel(r\"$\\langle J_p \\rangle (\\hat{\\psi})$\")" |
| 1142 | + ] |
| 1143 | + }, |
| 1144 | + { |
| 1145 | + "cell_type": "code", |
| 1146 | + "execution_count": null, |
| 1147 | + "metadata": {}, |
| 1148 | + "outputs": [], |
| 1149 | + "source": [ |
| 1150 | + "# # for example you could flux average other quantities of interest\n", |
| 1151 | + "\n", |
| 1152 | + "# # 1/R\n", |
| 1153 | + "# def f(R,Z):\n", |
| 1154 | + "# g = RectBivariateSpline(eq.R_1D, eq.Z_1D, 1/eq.R)\n", |
| 1155 | + "# return g(R, Z, grid=False)" |
| 1156 | + ] |
1057 | 1157 | } |
1058 | 1158 | ], |
1059 | 1159 | "metadata": { |
|
0 commit comments