|
599 | 599 | "print(f\"Original beta_0 = {profiles_topeol.Beta0} vs. Fitted from Lao85 = {beta_0}.\")" |
600 | 600 | ] |
601 | 601 | }, |
| 602 | + { |
| 603 | + "cell_type": "markdown", |
| 604 | + "metadata": {}, |
| 605 | + "source": [ |
| 606 | + "Supposing an explicit parameterisation of the profiles is unknown and you have access to data describing the profiles. The `GeneralPprimeFFprime` profiles class enables you to use the raw data. \n", |
| 607 | + "\n", |
| 608 | + "As always the plasma current density is given by:\n", |
| 609 | + "\n", |
| 610 | + " $$J_{p}(\\psi, R, Z) = \\lambda\\big[ \\frac{R}{R_{0}} p'(\\tilde{\\psi}) + \\frac{R_0}{R} \\frac{1}{\\mu_0} F F'(\\tilde{\\psi}) \\big] \\quad (R,Z) \\in \\Omega_p, $$\n", |
| 611 | + "\n", |
| 612 | + "where the pressure, $p(\\tilde{\\psi})$, and toroidal magnetic field, $F(\\tilde{\\psi})$, profiles are now given by data arrays. \n", |
| 613 | + "\n", |
| 614 | + "By passing these data arrays either directly as `pprime_data` or `p_data` (and also `ffprime_data` or `f_data`), FreeGSNKE will interpolate the data and use them directly in the plasma current density above. \n", |
| 615 | + "\n", |
| 616 | + "The required parameters are:\n", |
| 617 | + "- `Ip` (total plasma current).\n", |
| 618 | + "- `fvac` ($rB_{tor}$, vacuum toroidal field strength).\n", |
| 619 | + "- `psi_n` ($\\tilde{\\psi}$, normalised poloidal flux at which data arrays corresponding, should be increasing).\n", |
| 620 | + "- `pprime_data` or `p_data` (array of $p'(\\tilde{\\psi})$ or $p(\\tilde{\\psi})$ values at the normalised poloidal flux values in `psi_n`).\n", |
| 621 | + "- `ffprime_data` or `f_data` (array of $FF'(\\tilde{\\psi})$ or $F(\\tilde{\\psi})$ values at the normalised poloidal flux values in `psi_n`).\n", |
| 622 | + "- `Ip_logic` (if False, `Ip` is not used, if True, `Ip` is used to normalise $J_p$ and find $\\lambda$)." |
| 623 | + ] |
| 624 | + }, |
| 625 | + { |
| 626 | + "cell_type": "code", |
| 627 | + "execution_count": null, |
| 628 | + "metadata": {}, |
| 629 | + "outputs": [], |
| 630 | + "source": [ |
| 631 | + "from freegsnke.jtor_update import GeneralPprimeFFprime\n", |
| 632 | + "\n", |
| 633 | + "psi_n = np.linspace(0,1,11)\n", |
| 634 | + "\n", |
| 635 | + "pprime_data = np.array([208061.72441505, 204110.95531309, 194359.61041113, 179811.09692964,\n", |
| 636 | + " 161053.35395914, 138602.79928382, 113000.64896365, 84893.04354249,\n", |
| 637 | + " 55164.04720078, 25298.53358472, 0. ])\n", |
| 638 | + "\n", |
| 639 | + "ffprime_data = np.array([0.58961295, 0.57841712, 0.5507834 , 0.50955529, 0.45639891,\n", |
| 640 | + " 0.3927777 , 0.32022539, 0.24057302, 0.1563259 , 0.07169191,\n", |
| 641 | + " 0. ])\n", |
| 642 | + "\n", |
| 643 | + "p_data = np.array([126175.75656716, 105510.77120406, 85544.30596718, 66798.45790761,\n", |
| 644 | + " 49722.32952766, 34710.90959473, 22106.93373 , 12194.53794856,\n", |
| 645 | + " 5182.93833357, 1168.13190975, 0. ])\n", |
| 646 | + "\n", |
| 647 | + "f_data = np.array([0.98240673, 0.92086948, 0.85722645, 0.79283784, 0.72925299,\n", |
| 648 | + " 0.66837871, 0.61261316, 0.56490234, 0.52855955, 0.50657733,\n", |
| 649 | + " 0.5 ])\n", |
| 650 | + "\n", |
| 651 | + "\n", |
| 652 | + "# the following three setups are equivalent\n", |
| 653 | + "profiles_general = GeneralPprimeFFprime(\n", |
| 654 | + " eq=eq,\n", |
| 655 | + " Ip=6e5,\n", |
| 656 | + " fvac=0.5,\n", |
| 657 | + " psi_n=psi_n,\n", |
| 658 | + " pprime_data=pprime_data,\n", |
| 659 | + " ffprime_data=ffprime_data,\n", |
| 660 | + " p_data=p_data,\n", |
| 661 | + " f_data=f_data,\n", |
| 662 | + ")\n", |
| 663 | + "\n", |
| 664 | + "# profiles_general = GeneralPprimeFFprime(\n", |
| 665 | + "# eq=eq,\n", |
| 666 | + "# Ip=6e5,\n", |
| 667 | + "# fvac=0.5,\n", |
| 668 | + "# psi_n=psi_n,\n", |
| 669 | + "# pprime_data=pprime_data,\n", |
| 670 | + "# ffprime_data=ffprime_data,\n", |
| 671 | + "# p_data=None,\n", |
| 672 | + "# f_data=None,\n", |
| 673 | + "# )\n", |
| 674 | + "\n", |
| 675 | + "# profiles_general = GeneralPprimeFFprime(\n", |
| 676 | + "# eq=eq,\n", |
| 677 | + "# Ip=6e5,\n", |
| 678 | + "# fvac=0.5,\n", |
| 679 | + "# psi_n=psi_n,\n", |
| 680 | + "# pprime_data=None,\n", |
| 681 | + "# ffprime_data=None,\n", |
| 682 | + "# p_data=p_data,\n", |
| 683 | + "# f_data=f_data,\n", |
| 684 | + "# )" |
| 685 | + ] |
| 686 | + }, |
| 687 | + { |
| 688 | + "cell_type": "code", |
| 689 | + "execution_count": null, |
| 690 | + "metadata": {}, |
| 691 | + "outputs": [], |
| 692 | + "source": [ |
| 693 | + "# instatiate new equilibrium object\n", |
| 694 | + "eq_general = deepcopy(eq)\n", |
| 695 | + "\n", |
| 696 | + "# call solver with new profile object\n", |
| 697 | + "GSStaticSolver.solve(eq=eq_general, \n", |
| 698 | + " profiles=profiles_general, \n", |
| 699 | + " constrain=None, \n", |
| 700 | + " target_relative_tolerance=1e-9)\n", |
| 701 | + "\n", |
| 702 | + "\n", |
| 703 | + "# plot the resulting equilbria \n", |
| 704 | + "fig1, ax1 = plt.subplots(1, 1, figsize=(4, 8), dpi=80)\n", |
| 705 | + "ax1.grid(True, which='both')\n", |
| 706 | + "eq_general.plot(axis=ax1, show=False)\n", |
| 707 | + "eq_general.tokamak.plot(axis=ax1, show=False)\n", |
| 708 | + "ax1.set_xlim(0.1, 2.15)\n", |
| 709 | + "ax1.set_ylim(-2.25, 2.25)\n", |
| 710 | + "plt.tight_layout()" |
| 711 | + ] |
| 712 | + }, |
602 | 713 | { |
603 | 714 | "cell_type": "markdown", |
604 | 715 | "metadata": {}, |
|
0 commit comments