### Quadcoil Optimization Setup and Execution Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb This Python code snippet demonstrates how to set up and execute the optimization process for a quadcoil system. It includes defining the optimizer, setting up objectives and constraints, and running the optimization with specified parameters like maxiter and xtol. The optimized equilibrium is then saved. ```python optimizer = Optimizer('fmin-auglag-bfgs') if True: # not os.path.exists('dipole_' + wout_file + '_eq.h5'): eqb, history = desc_eq.optimize( objective=objective, constraints=constraints, optimizer=optimizer, maxiter=500, # For now fails at iter #2 copy=True, verbose=3, xtol=1e-8, ) eqb.save('dipole_' + wout_file + '_low_res_eq.h5') else: eqb = desc.io.load('dipole_' + wout_file + '_low_res_eq.h5') ``` -------------------------------- ### Run QUADCOIL with NESCOIL Example Source: https://github.com/lankef/quadcoil/blob/main/docs/tutorial_outputs.md This code snippet demonstrates how to run the QUADCOIL algorithm with the NESCOIL problem. It configures parameters such as nfp, stellsym, mpol, ntor, and plasma properties. It also specifies the objective function ('f_B'), constraint ('K_theta'), and output metrics ('f_B', 'f_K'). The output includes a dictionary of metrics and gradients, problem configurations, Fourier coefficients, and optimization status. ```python print('Running quadcoil, with auto-generated ') 'winding surface and K_theta constraint.') out_dict, qp, phi_mn, status = quadcoil( nfp=cp.nfp, stellsym=cp.stellsym, mpol=cp.mpol, ntor=cp.ntor, plasma_dofs=plasma_surface.get_dofs(), plasma_mpol=plasma_surface.mpol, plasma_ntor=plasma_surface.ntor, net_poloidal_current_amperes=cp.net_poloidal_current_amperes, net_toroidal_current_amperes=cp.net_toroidal_current_amperes, plasma_coil_distance=plasma_surface.minor_radius(), # Setting the objective to f_B. Use auto-scaling. objective_name='f_B', # Set the constraint to K_theta. Use auto-scaling. constraint_name=('K_theta',), constraint_type=('>=',), constraint_value=(0.,), constraint_unit=(None,), # Set the output metrics to f_B and f_K metric_name=('f_B', 'f_K'), maxiter_inner=1500, maxiter_outer=10, ftol_inner=0, xtol_inner=0, ) ``` -------------------------------- ### Initialize QUADCOIL Proxy Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Configures and builds a QuadcoilProxy object to define the optimization objective for plasma coil surfaces. This setup includes defining coil parameters, metric targets, and grid resolutions. ```python objective_dummy = QuadcoilProxy( eq=desc_eq, quadcoil_args={ 'mpol': mpol, 'ntor': ntor, 'plasma_coil_distance':0.1, }, metric_name='f_max_Phi2', metric_target=0., metric_weight=1., plasma_M_theta=plasma_M_theta, plasma_N_phi=plasma_N_phi, normalize=False, normalize_target=False, name="QUADCOIL Proxy", verbose=False, ) objective_dummy.build() _, qp_dummy, _, _ = objective_dummy.compute_full(*objective_dummy.xs(desc_eq)) ``` -------------------------------- ### Run QUADCOIL for Sheet Current Coil Generation (Python) Source: https://github.com/lankef/quadcoil/blob/main/docs/tutorial_inputs.md This snippet shows a minimal example of using the quadcoil.quadcoil() wrapper to generate a sheet current coil set. It loads an equilibrium's boundary using simsopt, defines parameters for the coil optimization, and then plots the resulting current potential. The function handles plasma boundary definition, sheet current properties, coil-plasma distance, objective functions, constraints, and metrics. ```python from quadcoil import quadcoil from simsopt import load from quadcoil.objective import Phi_with_net_current import matplotlib.pyplot as plt # Loading an equilibrium's boundary using simsopt # Assuming Vmec is available and the file exists # equil_qs = Vmec('wout_LandremanPaul2021_QA_lowres.nc', keep_all_files=True) # plasma_surface = equil_qs.boundary # net_poloidal_current_amperes = equil_qs.external_current() # Placeholder for actual plasma surface and current data class MockPlasmaSurface: def __init__(self, nfp, stellsym, mpol, ntor, minor_radius): self.nfp = nfp self.stellsym = stellsym self.mpol = mpol self.ntor = ntor self._minor_radius = minor_radius def get_dofs(self): return [] # Placeholder def external_current(self): return 1.0 # Placeholder def minor_radius(self): return self._minor_radius # Mock data for demonstration equil_qs_mock = MockPlasmaSurface(nfp=1, stellsym=True, mpol=4, ntor=4, minor_radius=1.0) plasma_surface = equil_qs_mock net_poloidal_current_amperes = 1.0 nescoil_out_dict, nescoil_qp, nescoil_phi_mn, _ = quadcoil( nfp=plasma_surface.nfp, stellsym=plasma_surface.stellsym, mpol=4, # 4 poloidal harmonics for the current potential ntor=4, # 4 toroidal harmonics for the current potential plasma_dofs=plasma_surface.get_dofs(), plasma_mpol=plasma_surface.mpol, plasma_ntor=plasma_surface.ntor, net_poloidal_current_amperes=net_poloidal_current_amperes, net_toroidal_current_amperes=0., plasma_coil_distance=plasma_surface.minor_radius(), # Set the objective to # f_B objective_name='f_B', objective_weight=None, objective_unit=None, # Set the output metrics to f_B and f_K metric_name=('f_B', 'f_K') ) # Plotting the solution (mocked for demonstration) # plt.contour( # nescoil_qp.quadpoints_phi, # nescoil_qp.quadpoints_theta, # Phi_with_net_current(nescoil_qp, nescoil_phi_mn), # levels=40 # ) # plt.show() print("QUADCOIL execution simulated.") ``` -------------------------------- ### Import Libraries for REGCOIL and QUADCOIL Source: https://github.com/lankef/quadcoil/blob/main/tests/regcoil.ipynb Imports essential Python libraries and modules from the quadcoil package, including unittest, various quantity functions, and jax.numpy for numerical operations. This setup is necessary for running REGCOIL and performing related tests. ```python import unittest from quadcoil.quantity import winding_surface_B, Bnormal, f_B, f_K, K, K2 from quadcoil.quantity.current import _f_K, _K, _K2 from quadcoil import gen_winding_surface_arc, quadcoil import jax.numpy as jnp from jax import eval_shape ``` -------------------------------- ### GET /quadcoil/coils/convert Source: https://github.com/lankef/quadcoil/blob/main/examples/topology_and_cutting.ipynb Converts optimized quadcoil parameters into discrete filament coils for further magnetic analysis. ```APIDOC ## GET /quadcoil/coils/convert ### Description Transforms the quadcoil optimization output into a set of filament coils suitable for Biot-Savart calculations. ### Method GET ### Endpoint /quadcoil/coils/convert ### Parameters #### Query Parameters - **coils_per_half_period** (int) - Required - Number of coils to generate per half field period. - **order** (int) - Required - Polynomial order for curve representation. ### Response #### Success Response (200) - **coils** (list) - List of coil objects ready for magnetic field calculation. ``` -------------------------------- ### Initialize Quadcoil Environment Source: https://github.com/lankef/quadcoil/blob/main/examples/dipole_density.ipynb Configures the JAX environment, imports necessary libraries, and initializes the device context for Quadcoil simulations. ```python import os os.environ["XLA_PYTHON_CLIENT_PREALLOCATE"] = "false" from quadcoil import quadcoil from simsopt import load from simsopt.field import CurrentPotentialFourier, CurrentPotentialSolve import jax import matplotlib.pyplot as plt import numpy as np import jax.numpy as jnp from jax import block_until_ready, devices, config import time devices() ``` -------------------------------- ### High-Resolution Problem Setup for Plotting Source: https://github.com/lankef/quadcoil/blob/main/examples/curvature.ipynb This section describes the process of creating a high-resolution QuadcoilParams object specifically for generating plots. It involves re-initializing the winding surface with denser quadpoints. ```APIDOC ## POST /api/quadcoil/setup_plotting ### Description Sets up a high-resolution QuadcoilParams object for plotting purposes. ### Method POST ### Endpoint /api/quadcoil/setup_plotting ### Parameters #### Request Body - **qp** (object) - The original QuadcoilParams object. - **quadpoints_phi** (array of floats) - Dense array of phi quadpoints. - **quadpoints_theta** (array of floats) - Dense array of theta quadpoints. ### Request Example ```json { "qp": { /* existing QuadcoilParams object */ }, "quadpoints_phi": [ 0.0, 0.005025125628140704, 0.010050251256281407, /* ... more points ... */ 1.0 ], "quadpoints_theta": [ 0.0, 0.005025125628140704, 0.010050251256281407, /* ... more points ... */ 1.0 ] } ``` ### Response #### Success Response (200) - **qp_for_plotting** (object) - The high-resolution QuadcoilParams object ready for plotting. #### Response Example ```json { "qp_for_plotting": { /* high-resolution QuadcoilParams object */ } } ``` ``` -------------------------------- ### Initialize SurfaceRZFourierJAX for Geometry Representation Source: https://context7.com/lankef/quadcoil/llms.txt Illustrates how to create a JAX-compatible surface representation either by importing from SIMSOPT or by direct initialization with Fourier coefficients. ```python from quadcoil import SurfaceRZFourierJAX import jax.numpy as jnp from simsopt.geo import SurfaceRZFourier simsopt_surf = SurfaceRZFourier(nfp=2, stellsym=True, mpol=4, ntor=4) jax_surf = SurfaceRZFourierJAX.from_simsopt(simsopt_surf) quadpoints_phi = jnp.linspace(0, 1, 64, endpoint=False) quadpoints_theta = jnp.linspace(0, 1, 64, endpoint=False) dofs = jnp.zeros(45) jax_surf = SurfaceRZFourierJAX( nfp=2, stellsym=True, mpol=4, ntor=4, quadpoints_phi=quadpoints_phi, quadpoints_theta=quadpoints_theta, dofs=dofs ) ``` -------------------------------- ### UserWarning in Quadcoil Optimization Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb This UserWarning indicates that redundant arguments ('plasma_quadpoints_phi', 'plasma_quadpoints_theta') were detected during the QUADCOIL optimization setup. These arguments are automatically derived from the equilibrium or other parameters, and the provided values are discarded. ```text /home/lankef/code/DESC/desc/objectives/_quadcoil.py:166: UserWarning: QUADCOIL: Redundant arguments detected: {'plasma_quadpoints_phi', 'plasma_quadpoints_theta'}. These arguments are extracted from the equilibrium, or specified by other parameters. The provided values will be discarded. ``` -------------------------------- ### Initialize Quadcoil Environment Source: https://github.com/lankef/quadcoil/blob/main/examples/curvature.ipynb Imports necessary libraries for quadcoil operations, including JAX for numerical computation and SIMSOPT for surface loading. ```python from quadcoil import quadcoil from quadcoil.quantity import Phi_with_net_current import matplotlib.pyplot as plt import numpy as np import jax.numpy as jnp import time from simsopt import load import jax jax.config.update('jax_enable_x64', True) ``` -------------------------------- ### Plotting Coil Configurations Source: https://github.com/lankef/quadcoil/blob/main/examples/curvature.ipynb This section provides an example of plotting the magnetic field contours for different coil configurations (slack, softmax, and REGCOIL) using Matplotlib. It displays the $K\cdot\nabla K$ values for each configuration. ```APIDOC ## POST /api/quadcoil/plot ### Description Generates contour plots of magnetic field configurations for comparison. ### Method POST ### Endpoint /api/quadcoil/plot ### Parameters #### Request Body - **qp** (object) - QuadcoilParams object for the slack mode. - **dofs** (object) - Degrees of freedom for the slack mode. - **qp2** (object) - QuadcoilParams object for the softmax mode. - **dofs2** (object) - Degrees of freedom for the softmax mode. - **regcoil_dofs** (object) - Degrees of freedom for the REGCOIL configuration. - **f_max_K_dot_grad_K_cyl_new** (float) - $K\cdot\nabla K$ value for slack mode. - **f_max_K_dot_grad_K_cyl_new2** (float) - $K\cdot\nabla K$ value for softmax mode. - **f_max_K_dot_grad_K_cyl_ref** (float) - $K\cdot\nabla K$ value for REGCOIL. ### Request Example ```json { "qp": { /* slack QuadcoilParams object */ }, "dofs": {"max_KK_cyl": [], "phi": []}, "qp2": { /* softmax QuadcoilParams object */ }, "dofs2": {"phi": []}, "regcoil_dofs": { /* REGCOIL dofs */ }, "f_max_K_dot_grad_K_cyl_new": 7.205641928235058e+13, "f_max_K_dot_grad_K_cyl_new2": 7.226761871295473e+13, "f_max_K_dot_grad_K_cyl_ref": 1.83350449086104e+14 } ``` ### Response #### Success Response (200) - **plot_result** (string) - A message indicating the plot generation status. #### Response Example ```json { "plot_result": "
" } ``` ``` -------------------------------- ### Initialize Quadcoil Environment Source: https://github.com/lankef/quadcoil/blob/main/examples/topology_and_cutting.ipynb Imports necessary libraries and loads plasma surface data for the Quadcoil optimization workflow. It configures JAX for 64-bit precision and defines the net poloidal current. ```python from quadcoil import quadcoil from quadcoil.quantity import K_theta, Phi_with_net_current, K2, K from quadcoil.io import simsopt_coil_from_qp import matplotlib.pyplot as plt import numpy as np import jax.numpy as jnp import time from simsopt import load from simsopt.geo import curves_to_vtk from simsopt.field import BiotSavart from simsopt.objectives.fluxobjective import SquaredFlux _, plasma_surface = load('surfaces.json') net_poloidal_current_amperes = 11884578.094260072 import jax jax.config.update('jax_enable_x64', True) ``` -------------------------------- ### Objective and Constraint Configuration (Python) Source: https://github.com/lankef/quadcoil/blob/main/docs/quadcoil.md Defines the configuration for objective functions and constraints in the QUADCOIL optimization. This includes specifying names, weights, units for normalization, and constraint types. These parameters guide the optimization process towards desired coil properties. ```python objective_name = 'f_B_normalized_by_Bnormal_IG' objective_weight = None objective_unit = None constraint_name = () constraint_type = () constraint_unit = () constraint_value = () ``` -------------------------------- ### Initialize Quadcoil Dipole Problem Environment Source: https://github.com/lankef/quadcoil/blob/main/examples/taylor_test.ipynb This snippet imports necessary JAX and Quadcoil modules and sets up the initial parameters for a dipole problem, including surface loading and physical constants. ```python import time import jax import jax.numpy as jnp import numpy as np from jax import block_until_ready from quadcoil import quadcoil from quadcoil.quantity import f_B from simsopt import load winding_surface, plasma_surface = load('surfaces.json') net_poloidal_current_amperes = 11884578.094260072 mpol = 12 ntor = 12 separation = 0.1 f_B_target = 1e-3 unit_Phi = 1e5 unit_l1_Phi = 1e6 ``` -------------------------------- ### Import Libraries for Quadcoil and Simsopt Source: https://github.com/lankef/quadcoil/blob/main/examples/simple_example.ipynb Imports the necessary quadcoil and simsopt libraries to begin the plasma equilibrium calculation. ```python from quadcoil import quadcoil from simsopt.mhd import Vmec ``` -------------------------------- ### Import and Evaluate QUADCOIL Quantities Source: https://github.com/lankef/quadcoil/blob/main/docs/quantity.md Shows how to import specific physical quantities directly from the quadcoil.quantity module and evaluate them using plasma parameters and Fourier coefficients. ```python from quadcoil.quantity import K_theta print(K_theta(qp, phi_mn)) ``` -------------------------------- ### Initialize QUADCOIL Optimization Source: https://github.com/lankef/quadcoil/blob/main/tests/regcoil.ipynb This snippet demonstrates how to invoke the quadcoil function with necessary plasma geometry parameters, current constraints, and solver configuration settings. ```python nescoil_out_dict, nescoil_qp, nescoil_phi_mn, _ = quadcoil( nfp=nfp, stellsym=stellsym, mpol=mpol, ntor=ntor, plasma_dofs=plasma_dofs, plasma_mpol=plasma_mpol, plasma_ntor=plasma_ntor, net_poloidal_current_amperes=net_poloidal_current_amperes, net_toroidal_current_amperes=net_toroidal_current_amperes, plasma_coil_distance=plasma_coil_distance, metric_name=metric_name, verbose=verbose, ) ``` -------------------------------- ### Compare REGCOIL Solutions using Simsopt Source: https://github.com/lankef/quadcoil/blob/main/examples/regcoil.ipynb Extracts the winding surface from the QUADCOIL solution, sets up a CurrentPotentialSolve object from Simsopt, and solves for the current potential using Tikhonov regularization. It then plots the Fourier coefficients of the current potential from both QUADCOIL and Simsopt, and prints the f_B values for comparison. ```python # Extract the winding surface and run REGCOIL ws1 = regcoil1_qp.winding_surface.to_simsopt() cp1 = CurrentPotentialFourier( ws1, mpol=mpol, ntor=ntor, net_poloidal_current_amperes=net_poloidal_current_amperes, net_toroidal_current_amperes=0., stellsym=True) cpst1 = CurrentPotentialSolve(cp1, plasma_surface, 0) regcoil1_phi_mn = regcoil1_dofs['phi'] regcoil1_phi_mn_ans, regcoil1_f_B_ans, regcoil1_f_K_ans = cpst1.solve_tikhonov(lam=0.01) plt.title('Fourier coefficients of the current potential') plt.plot(regcoil1_phi_mn, label='REGCOIL sln (from QUADCOIL)') plt.plot(regcoil1_phi_mn_ans, label='REGCOIL sln (from Simsopt) ') plt.legend() print('QUADCOIL f_B:', regcoil1_out_dict['f_B']['value']) print('REGCOIL f_B: ', regcoil1_f_B_ans) ``` -------------------------------- ### Configure QUADCOIL Objectives and Constraints Source: https://github.com/lankef/quadcoil/blob/main/docs/quantity.md Demonstrates how to pass objective and constraint names, types, and values into the quadcoil function to define the optimization problem. ```python phi_mn, out_dict, qp, status = quadcoil( ... objective_name=('f_B',), constraint_name=('K_theta',), constraint_type=('>=',), constraint_value=(0.,), constraint_unit=(None,), metric_name=('f_B',), ... ) ``` -------------------------------- ### Configure and Build Quadcoil Proxy Objective Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Sets up the QuadcoilProxy objective by defining metric targets, weights, and plasma parameters for optimization. ```python quadcoil_kwargs_obj = quadcoil_kwargs.copy() quadcoil_kwargs_obj['plasma_coil_distance'] = separation quadcoil_objective = QuadcoilProxy( eq=desc_eq, quadcoil_args=quadcoil_kwargs_obj, metric_name=('f_max_Phi',), metric_target=np.array([0.,]), metric_weight=np.array([1./f_Phi_crtl,]), plasma_M_theta=plasma_M_theta, plasma_N_phi=plasma_N_phi, normalize=False, normalize_target=False, name="QUADCOIL Proxy", verbose=0, ) quadcoil_objective.build() ``` -------------------------------- ### Import Simsopt Data Loading Utilities Source: https://github.com/lankef/quadcoil/blob/main/examples/regcoil.ipynb Imports functions from the Simsopt library for loading pre-existing surface data and defining current potentials. This is necessary for setting up the problem with existing configurations. ```python from simsopt import load from simsopt.field import CurrentPotentialFourier, CurrentPotentialSolve ``` -------------------------------- ### Initialize Linear Grids for DESC Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Creates LinearGrid instances for the plasma surface, axis, and edge to be used in equilibrium computations. ```python qsgrid = LinearGrid(M=desc_eq.M_grid, N=desc_eq.N_grid, NFP=desc_eq.NFP, rho=np.array([0.1, 1.0]), sym=True) iotagridaxis = LinearGrid(M=desc_eq.M_grid, N=desc_eq.N_grid, NFP=desc_eq.NFP, rho=np.array([0.01]), sym=True) iotagridedge = LinearGrid(M=desc_eq.M_grid, N=desc_eq.N_grid, NFP=desc_eq.NFP, rho=np.array([1.0]), sym=True) ``` -------------------------------- ### Objective Building and Timing Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb This output shows the process of building various objectives for the optimization, such as 'volume', 'aspect ratio', and 'rotational transform'. It also includes timing information for 'Precomputing transforms' and 'Objective build', providing insights into the computational cost of different objective functions. ```text Building objective: volume Precomputing transforms Timer: Precomputing transforms = 40.2 ms Building objective: aspect ratio Precomputing transforms Timer: Precomputing transforms = 39.7 ms Building objective: QS two-term Precomputing transforms Timer: Precomputing transforms = 82.2 ms Building objective: rotational transform Precomputing transforms Timer: Precomputing transforms = 38.5 ms Building objective: rotational transform Precomputing transforms Timer: Precomputing transforms = 38.9 ms Building objective: QUADCOIL Proxy Precomputing transforms Timer: Precomputing transforms = 178 ms Timer: Objective build = 550 ms Building objective: fixed Psi Building objective: self_consistency R Building objective: self_consistency Z Building objective: lambda gauge Building objective: axis R self consistency Building objective: axis Z self consistency Timer: Objective build = 48.5 ms Building objective: force Precomputing transforms Timer: Precomputing transforms = 753 ms Timer: Objective build = 808 ms Timer: LinearConstraintProjection build = 2.62 sec Timer: LinearConstraintProjection build = 100 ms Number of parameters: 1066 Number of objectives: 500 Number of equality constraints: 4224 Number of inequality constraints: 0 Timer: Initializing the optimization = 4.41 sec ``` -------------------------------- ### Compare Optimization Results (Slack vs. Softmax) Source: https://github.com/lankef/quadcoil/blob/main/examples/curvature.ipynb Prints and compares key metrics such as 'f_B' and 'f_max_K_dot_grad_K_cyl' obtained from QUADCOIL using 'slack' and 'softmax' smoothing modes, alongside results from REGCOIL. It also lists the free variables identified for each mode. Dependencies include 'out_dict', 'out_dict2', 'dofs', 'dofs2', 'regcoil_out_dict', and 'f_B_ref'. ```python f_max_K_dot_grad_K_cyl_new = out_dict['f_max_K_dot_grad_K_cyl']['value'] f_max_K_dot_grad_K_cyl_new2 = out_dict2['f_max_K_dot_grad_K_cyl']['value'] print('List of free variables (slack): ', dofs.keys()) print('List of free variables (softmax):', dofs2.keys()) print('f_B of QUADCOIL (slack): ', out_dict['f_B']['value']) print('f_B of QUADCOIL (softmax):', out_dict2['f_B']['value']) print('f_B of REGCOIL: ', regcoil_out_dict['f_B']['value']) print('Max K dot grad K (cylindrical) of QUADCOIL (slack): ', f_max_K_dot_grad_K_cyl_new) print('Max K dot grad K (cylindrical) of QUADCOIL (softmax):', f_max_K_dot_grad_K_cyl_new2) print('Max K dot grad K (cylindrical) of REGCOIL: ', f_max_K_dot_grad_K_cyl_ref) ``` -------------------------------- ### Initialize Quadcoil Simulation Source: https://github.com/lankef/quadcoil/blob/main/examples/topology_and_cutting.ipynb Initializes the quadcoil simulation with specified plasma surface parameters, magnetic field objectives, and current constraints. It sets up the problem for solving the magnetic field configuration. ```python print('Running quadcoil, with auto-generated ') 'winding surface and K_theta constraint.') out_dict_lse, qp_lse, dofs_lse, status_lse = quadcoil( nfp=plasma_surface.nfp, stellsym=plasma_surface.stellsym, mpol=4, ntor=4, plasma_dofs=plasma_surface.get_dofs(), plasma_mpol=plasma_surface.mpol, plasma_ntor=plasma_surface.ntor, net_poloidal_current_amperes=net_poloidal_current_amperes, net_toroidal_current_amperes=0., plasma_coil_distance=plasma_surface.minor_radius(), # Set the objective to # f_B objective_name='f_B', # Set the constraint to K_theta constraint_name=('K_theta',), constraint_type=('>=',), constraint_value=np.array([0.,]), constraint_unit=(None,), # Set the output metrics to f_B and f_K metric_name=('f_B', 'f_K'), smoothing='approx' ) ``` -------------------------------- ### Solve Unconstrained NESCOIL Problem with quadcoil Source: https://context7.com/lankef/quadcoil/llms.txt Demonstrates how to initialize a plasma equilibrium from VMEC and perform an unconstrained optimization to minimize the normal magnetic field on the plasma surface. ```python from quadcoil import quadcoil from simsopt.mhd import Vmec import jax.numpy as jnp equil = Vmec('wout_LandremanPaul2021_QA_lowres.nc', keep_all_files=True) plasma_surface = equil.boundary net_poloidal_current = equil.external_current() out_dict, qp, dofs_opt, solve_results = quadcoil( nfp=plasma_surface.nfp, stellsym=plasma_surface.stellsym, mpol=4, ntor=4, plasma_dofs=plasma_surface.get_dofs(), plasma_mpol=plasma_surface.mpol, plasma_ntor=plasma_surface.ntor, net_poloidal_current_amperes=net_poloidal_current, net_toroidal_current_amperes=0., plasma_coil_distance=plasma_surface.minor_radius(), objective_name='f_B', objective_weight=None, objective_unit=None, metric_name=('f_B', 'f_K'), verbose=1 ) print(f"f_B = {out_dict['f_B']['value']}") print(f"f_K = {out_dict['f_K']['value']}") print(f"Optimal phi dofs shape: {dofs_opt['phi'].shape}") ``` -------------------------------- ### Initial C Factor and Growth Rate (Python) Source: https://github.com/lankef/quadcoil/blob/main/docs/quadcoil.md Sets the initial value for the `c` factor and its growth rate in the augmented Lagrangian method. These parameters, described in 'Constrained Optimization and Lagrange Multiplier Methods', influence the convergence behavior of the outer optimization loop. ```python c_init = 1. c_growth_rate = 1.2 ``` -------------------------------- ### Integrate QUADCOIL with DESC Equilibrium Source: https://context7.com/lankef/quadcoil/llms.txt Shows how to interface QUADCOIL with the DESC equilibrium code to extract plasma boundaries and currents. It includes setting up optimization parameters and generating scaling factors for objectives and constraints. ```python from quadcoil.io import quadcoil_desc, generate_desc_scaling from desc.equilibrium import Equilibrium from desc.objectives.normalization import compute_scaling_factors eq = Equilibrium.load('equilibrium.h5') out_dict, qp, dofs_opt, solve_results = quadcoil_desc( desc_eq=eq, vacuum=False, plasma_M_theta=32, plasma_N_phi=32, objective_name='f_B', constraint_name=('f_max_K2',), constraint_type=('<=',), constraint_value=[5e11] ) scales = compute_scaling_factors(eq) obj_unit, cons_unit = generate_desc_scaling(objective_name='f_B', constraint_name=('f_max_K2',), scales=scales) ``` -------------------------------- ### Build Quadcoil Objective Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Initializes the optimization objective by precomputing necessary transforms. ```python quadcoil_objective_new.build() ``` -------------------------------- ### Import Libraries for DESC and SIMSOPT Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Imports necessary libraries from DESC, SIMSOPT, and other Python packages for magnetic field calculations and optimization. It also sets the computation device to GPU using JAX. ```python from quadcoil import quadcoil from desc import set_device set_device("gpu") import desc from desc.objectives import QuadcoilProxy, ObjectiveFunction from simsopt.util import MpiPartition, log from simsopt.mhd import Vmec, Boozer, Quasisymmetry from simsopt.objectives import LeastSquaresProblem from simsopt.solve import least_squares_mpi_solve from simsopt.field import CurrentPotentialFourier, CurrentPotentialSolve import matplotlib.pyplot as plt import numpy as np import jax.numpy as jnp from jax import block_until_ready, devices, config import time devices() ``` -------------------------------- ### JAX and Simsopt Integration Source: https://github.com/lankef/quadcoil/blob/main/docs/quadcoil.io.md Endpoints for JAX differentiation support and Simsopt coil potential conversion. ```APIDOC ## POST /quadcoil/io/jax/gen_quadcoil_for_diff ### Description Generates a quadcoil configuration optimized for JAX-based automatic differentiation. ### Method POST ### Endpoint /quadcoil/io/jax/gen_quadcoil_for_diff ### Response #### Success Response (200) - **diff_model** (object) - A JAX-compatible quadcoil model instance. ## POST /quadcoil/io/simsopt/quadcoil_to_simsopt_cp ### Description Converts quadcoil quadpoints and degrees of freedom into a Simsopt coil potential format. ### Method POST ### Endpoint /quadcoil/io/simsopt/quadcoil_to_simsopt_cp ### Parameters #### Request Body - **qp** (object) - Required - Quadcoil quadpoints object. - **dofs** (array) - Required - Degrees of freedom array. ### Response #### Success Response (200) - **cp** (object) - The resulting Simsopt coil potential object. ``` -------------------------------- ### Importing DESC Optimization Components (Python) Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Imports necessary classes and functions from the 'desc' library for setting up and performing plasma equilibrium optimization. This includes objective functions, grid definitions, and optimizers. ```python from desc.grid import LinearGrid from desc.objectives import ( ObjectiveFunction, ForceBalance, FixPressure, FixCurrent, FixPsi, QuasisymmetryTwoTerm, RotationalTransform, QuadcoilProxy, Volume, AspectRatio ) from desc.optimize import Optimizer ``` -------------------------------- ### Load Equilibrium and Configure JAX Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Loads a magnetic equilibrium from a specified file ('wout_LandremanPaul2021_QA_lowres.nc') into DESC and enables 64-bit precision for JAX computations. ```python # Loading equilibrium into DESC # wout_file = 'wout_li383_low_res_reference' # wout_file = 'wout_LandremanPaul2021_QA_lowres' # "wout_muse++.nc" desc_eq = desc.vmec.VMECIO.load(wout_file + '.nc') config.update('jax_enable_x64', True) ``` -------------------------------- ### NESCOIL Comparison Source: https://github.com/lankef/quadcoil/blob/main/examples/topology_and_cutting.ipynb This section shows how to run NESCOIL with auto-generated winding surfaces for comparison purposes. ```APIDOC ## Running NESCOIL for comparison ### Description This code snippet demonstrates running the NESCOIL algorithm with automatically generated winding surfaces. ### Method POST ### Endpoint /quadcoil/nescoil ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **nfp** (int) - Number of field periods. - **stellsym** (bool) - Whether stellarator symmetry is enforced. - **mpol** (int) - Poloidal mode number for the coil. - **ntor** (int) - Toroidal mode number for the coil. - **plasma_dofs** (array) - Degrees of freedom for the plasma surface. - **plasma_mpol** (int) - Poloidal mode number for the plasma surface. - **plasma_ntor** (int) - Toroidal mode number for the plasma surface. - **net_poloidal_current_amperes** (float) - Total poloidal current in amperes. - **net_toroidal_current_amperes** (float) - Total toroidal current in amperes. - **plasma_coil_distance** (float) - Distance between plasma and coil. - **objective_name** (string) - Name of the objective function (e.g., 'f_B'). - **objective_weight** (float or None) - Weight for the objective function. - **objective_unit** (string or None) - Unit for the objective function. - **metric_name** (tuple of strings) - Names of the metrics to output (e.g., ('f_B', 'f_K')). ### Request Example ```json { "nfp": 1, "stellsym": false, "mpol": 4, "ntor": 4, "plasma_dofs": [ ... ], "plasma_mpol": 4, "plasma_ntor": 4, "net_poloidal_current_amperes": 11884578.094260072, "net_toroidal_current_amperes": 0.0, "plasma_coil_distance": 1.0, "objective_name": "f_B", "objective_weight": null, "objective_unit": null, "metric_name": ["f_B", "f_K"] } ``` ### Response #### Success Response (200) - **nescoil_out_dict** (dict) - Dictionary containing output metrics and status. - **nescoil_qp** (object) - Quadcoil problem object. - **nescoil_dofs** (array) - Degrees of freedom for the generated coils. - **nescoil_status** (object) - Status of the NESCOIL run. #### Response Example ```json { "nescoil_out_dict": { "f_B": 0.123, "f_K": 0.456 }, "nescoil_qp": { ... }, "nescoil_dofs": [ ... ], "nescoil_status": "success" } ``` ``` -------------------------------- ### Convert QUADCOIL Results to SIMSOPT Source: https://context7.com/lankef/quadcoil/llms.txt Provides the workflow to convert optimized QUADCOIL results into a SIMSOPT CurrentPotentialFourier object. This enables further analysis such as coil cutting and winding pack generation. ```python from quadcoil.io import quadcoil_to_simsopt_cp # Assuming qp and dofs_opt are obtained from a previous optimization cp_simsopt = quadcoil_to_simsopt_cp(qp, dofs_opt) print(f"Current potential dofs: {cp_simsopt.get_dofs()}") print(f"Winding surface: {cp_simsopt.winding_surface}") ``` -------------------------------- ### Load Plasma Surface and Set Parameters Source: https://github.com/lankef/quadcoil/blob/main/examples/dipole_density.ipynb Loads the plasma surface geometry from a JSON file and defines the physical parameters for the coil optimization. ```python winding_surface, plasma_surface = load('surfaces.json') net_poloidal_current_amperes = 11884578.094260072 mpol = 4 ntor = 4 jax.config.update('jax_enable_x64', False) # Settings separation = 0.1 mpol = 12 ntor = 12 nfp = plasma_surface.nfp plasma_M_theta = 16 plasma_N_phi = 32 ``` -------------------------------- ### Python: Taylor Testing for QUADCOIL with Log-Sum-Exp Smoothing Source: https://github.com/lankef/quadcoil/blob/main/examples/taylor_test.ipynb This comment indicates an intention to perform Taylor testing for QUADCOIL using a log-sum-exp function for smoothing absolute values. This suggests an alternative smoothing method compared to 'slack'. ```python # Taylor testing for QUADCOIL using the # log-sum-exp function to smooth absolute ``` -------------------------------- ### Comparing REGCOIL Solutions Source: https://github.com/lankef/quadcoil/blob/main/examples/regcoil.ipynb This code compares the Fourier coefficients of the current potential obtained from REGCOIL (both from QUADCOIL and Simsopt) and prints the magnetic field values (f_B) for both methods. It also includes a warning about potential differences in f_B calculations. ```python # Comparing with REGCOIL cp = CurrentPotentialFourier( winding_surface, mpol=4, ntor=4, net_poloidal_current_amperes=11884578.094260072, net_toroidal_current_amperes=0, stellsym=True) cpst = CurrentPotentialSolve(cp, plasma_surface, jnp.zeros(1024)) regcoil2_phi_mn_ans, regcoil2_f_B_ans, regcoil2_f_K_ans = cpst.solve_tikhonov(lam=0.01) plt.title('Fourier coefficients of the current potential') plt.plot(regcoil1_phi_mn, label='REGCOIL sln (from QUADCOIL)') plt.plot(regcoil1_phi_mn_ans, label='REGCOIL sln (from Simsopt) ') plt.legend() print('QUADCOIL f_B:', regcoil2_out_dict['f_B']['value']) print('REGCOIL f_B: ', regcoil2_f_B_ans) ``` -------------------------------- ### Evaluating and Plotting Coil Surfaces (Python) Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb This snippet evaluates and plots the surface of the 'regcoili_qp' object using its 'to_simsopt()' method, which is likely part of a larger simulation or analysis workflow. ```python regcoili_qp.eval_surface.to_simsopt().plot() ``` -------------------------------- ### Configuring Quadcoil Optimization Parameters (Python) Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Sets up keyword arguments for a quadcoil optimization. It defines objectives like minimizing peak dipole density ('f_max_Phi2') and constraints such as an upper bound on 'f_B', using the calculated normalization factors and target values. ```python quadcoil_kwargs = { 'mpol': mpol, 'ntor': ntor, 'winding_quadpoints_phi': winding_quadpoints_phi, 'winding_quadpoints_theta': winding_quadpoints_theta, 'plasma_quadpoints_phi': plasma_quadpoints_phi, 'plasma_quadpoints_theta': plasma_quadpoints_theta, 'objective_name': 'f_max_Phi2', # Minimizing peak dipole density 'objective_unit': unit_Phi2, # under an f_B constraint 'constraint_name': ('f_B',), 'constraint_type': ('<=',), 'constraint_unit': (f_B_target,), 'constraint_value': np.array([f_B_target,]), # 'verbose':1, } ``` -------------------------------- ### Export Plasma Surfaces to VTK Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Converts plasma surface objects to Simsopt format and exports them as VTK files for visualization. ```python qp_obj.plasma_surface.to_simsopt().to_vtk('plasma_before') qp_qss.plasma_surface.to_simsopt().to_vtk('plasma_after') ``` -------------------------------- ### Loading Simulation Data (Python) Source: https://github.com/lankef/quadcoil/blob/main/examples/quasi_single_stage.ipynb Loads simulation results for 'regcoil' from a .npy file. It extracts various plasma and field parameters including 'regcoili_qp', time lists, and field components (f_B, f_K) for both answered and tested configurations. ```python dict = jnp.load('regcoil_' + wout_file + '_low_res.npy', allow_pickle=True).item() regcoili_qp = dict['regcoili_qp'] time_regcoil_list = dict['time_regcoil_list'] phi_ans_list = dict['phi_ans_list'] f_B_ans_list = dict['f_B_ans_list'] f_K_ans_list = dict['f_K_ans_list'] time_quadcoil_list = dict['time_quadcoil_list'] phi_test_list = dict['phi_test_list'] f_B_test_list = dict['f_B_test_list'] f_K_test_list = dict['f_K_test_list'] ``` -------------------------------- ### Load Plasma Surface Data with Simsopt Source: https://github.com/lankef/quadcoil/blob/main/examples/simple_example.ipynb Loads the plasma equilibrium data from a file using Vmec from simsopt. It extracts the boundary surface and calculates the external poloidal current. ```python equil_qs = Vmec('wout_LandremanPaul2021_QA_lowres.nc', keep_all_files=True) plasma_surface = equil_qs.boundary net_poloidal_current_amperes = equil_qs.external_current() ``` -------------------------------- ### POST /quadcoil/optimize Source: https://github.com/lankef/quadcoil/blob/main/examples/topology_and_cutting.ipynb Executes the quadcoil optimization process with specified plasma parameters, current constraints, and objective functions. ```APIDOC ## POST /quadcoil/optimize ### Description Runs the quadcoil optimization algorithm to generate a winding surface that satisfies specific physical constraints such as K_theta. ### Method POST ### Endpoint /quadcoil/optimize ### Parameters #### Request Body - **nfp** (int) - Required - Number of field periods. - **stellsym** (bool) - Required - Stellarator symmetry flag. - **mpol** (int) - Required - Poloidal mode number. - **ntor** (int) - Required - Toroidal mode number. - **net_poloidal_current_amperes** (float) - Required - Total poloidal current. - **objective_name** (string) - Required - The objective function to minimize (e.g., 'f_B'). - **constraint_name** (tuple) - Optional - List of constraints to apply. - **constraint_type** (tuple) - Optional - Comparison operators for constraints. ### Response #### Success Response (200) - **out_dict** (dict) - Dictionary containing optimized values and gradients for the requested metrics. - **qp** (object) - Optimized quadcoil object. - **dofs** (array) - Degrees of freedom resulting from optimization. ```