Skip to content

Dipole and passive coil arrays branch#483

Open
akaptano wants to merge 30 commits intomasterfrom
passive_coil_arrays
Open

Dipole and passive coil arrays branch#483
akaptano wants to merge 30 commits intomasterfrom
passive_coil_arrays

Conversation

@akaptano
Copy link
Copy Markdown
Contributor

Hi all, this has been a long while coming, but I have my branch cleaned up that does the following:

  1. Implements dipole array optimization (including merging in Jake Halpbern's functionality he nicely shared with me)
  2. Implements passive array optimization
  3. Implements Jax-based net force, net torque, pointwise force, pointwise torque objectives for optimization. Note that MixedLpCurveForce and similar functions starting with 'Mixed' should be used if the number of coils is greater than 20 or 30. The reason is that the tree dependencies in SIMSOPT grow exponentially fast and slow down the code to a halt if any of the objective functions create a BiotSavart class object inside of them (as the default LpCurveForce and other functions do!). As far as I know, this big issue is not seen elsewhere because it requires a fair number of coils to see it, and it also requires that there is an objective that itself creates a BiotSavart object.
  4. Adds a tutorial file to the SIMSOPT documentation on minimal, advanced, and passive dipole coil array optimization
  5. Adds a fair number of new example files, including the two files for the tutorial in 3_Advanced/ including dipole_array_tutorial.py and dipole_array_tutorial_advanced.py. There are also files for running advanced scripts and coil force Pareto scans in 3_Advanced/dipole_coil_optimization, 3_Advanced/passive_coil_optimization, and 3_Advanced/coil_force_optimization.

The code is caught up and merged with several other branches, including master, Siena's coil forces branch, somewhat Jake Halpbern's dipole optimization branch, etc.

@akaptano akaptano added the enhancement New feature or request label Apr 21, 2025
@akaptano akaptano self-assigned this Apr 21, 2025
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 21, 2025

Codecov Report

❌ Patch coverage is 94.36620% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.39%. Comparing base (b1eb111) to head (79357fc).

Files with missing lines Patch % Lines
...simsopt/util/coil_optimization_helper_functions.py 73.58% 14 Missing ⚠️
src/simsopt/field/coil.py 89.47% 10 Missing ⚠️
src/simsopt/util/dipole_array_helper_functions.py 97.83% 7 Missing ⚠️
...rc/simsopt/geo/curveplanarellipticalcylindrical.py 98.82% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #483      +/-   ##
==========================================
+ Coverage   89.97%   90.39%   +0.42%     
==========================================
  Files          84       86       +2     
  Lines       17364    18398    +1034     
==========================================
+ Hits        15623    16631    +1008     
- Misses       1741     1767      +26     
Flag Coverage Δ
unittests 90.39% <94.36%> (+0.42%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@kchammond
Copy link
Copy Markdown
Contributor

@akaptano Thanks for adding unit tests for the wireframe features! I have made a couple of changes, and I think they are now behaving as expected.

@landreman
Copy link
Copy Markdown
Contributor

@akaptano A lot of the 166 files (!!!) changed in this PR have edits that are merely just adjusting spaces or removing \ at the ends of lines, with no change to functionality. Any chance you could create and merge a separate PR for all those formatting changes first? That would make it a lot easier to spot and digest the actual changes to substance in this PR.

@akaptano
Copy link
Copy Markdown
Contributor Author

akaptano commented May 6, 2025

@landreman Will do. I assume this is because I run ./run_autopep before I commit things. Isn't this supposed to be the standard practice?

@mishapadidar @mbkumar The latest version of the branch (as of this time) now has the force and torque calculations completely revamped. Unfortunately, this does not seem to fix issue #485 though it fixes #487 by removing all the BiotSavart functionality within the objective function. It also generalizes the calculation so that the list of coils can have differing number of quadrature points and so forth. Some work still to do still to fix the Taylor test issue so that the CI passes.

@landreman
Copy link
Copy Markdown
Contributor

Thanks for PR#498 with autopep, which I just merged. As a result, once master is merged into passive_coil_arrays, it should simplify this PR a lot. However when I tried to merge, there were a bunch of conflicts, and some of them I wasn't sure how to resolve. @akaptano can you merge master into passive_coil_arrays and resolve these?

@akaptano
Copy link
Copy Markdown
Contributor Author

akaptano commented May 7, 2025

@landreman Just resolved those merge conflicts, thanks! We are down to 82 changed files but many of them are small edits!

Copy link
Copy Markdown
Contributor

@andrewgiuliani andrewgiuliani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haven't finished reading the PR, but here are some interim comments

base_coils = coils[:ncoils]
bs = BiotSavart(coils)
bs.set_points(s.gamma().reshape((-1, 3)))
calculate_on_axis_B(bs, s)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not really the magnetic axis that you're calculating the the modB average right?

base_curves:
The curve objects for the dipoles in the array.
eps: float
Controls how inboard a dipole can be without being removed.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the docstring reflect how is a dipole classified as inboard?

can you clarify what eps actually is?

base_curves_TF:
The curve objects for the TF (modular) coils in the array.
eps: float
controls how close a TF-dipole coil distance can be before being removed.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above, can the docstring reflect how interlinking coils are detected + what is eps?

The width (radius) of a rectangular (circular) cross section dipole coil
b: float
The length (radius) of a rectangular (circular) cross section dipole coil
nturns_TF: int
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing regularization in the args docstring

TF_a: minor radius of the TF coils (in R direction)
TF_b: minor radius of the TF coils (in Z direction)
fixed_geo_tfs: whether to fix the geometric degrees of freedom of the TF coils
numquadpoints: number of quadrature points representing each coil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

order, planar_tfs missing from the docstring

outdir: str
The output directory for the generated curves.
"""
from simsopt.geo import curves_to_vtk
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few of these functions import curves_to_vtk could make the code cleaner by making it a global import like numpy is

planar_tfs: bool
Whether to use planar TF coils.
outdir: str
The output directory for the generated curves.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

many function arguments missing from docstring



def calculate_on_axis_B(bs, s):
def calculate_on_axis_B(bs, s, print_out=True):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring missing print_out arg

def make_Bnormal_plots(bs, s_plot, out_dir='', bs_filename="Bnormal", B_axis=None):
"""
Plot Bnormal on plasma surface from a MagneticField object.
Do this quite a bit in the permanent magnet optimization
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring missing B_axis arg

z[k] += y[k]
else:
z[k] = y[k].copy()
z[k] = y[k].copy() # why copy here but not in subtract?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete the comment?

@@ -22,20 +22,15 @@ class BiotSavart(sopp.BiotSavart, MagneticField):
coils: A list of :obj:`simsopt.field.coil.Coil` objects.
Copy link
Copy Markdown
Contributor

@mishapadidar mishapadidar May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing documentation for psc_array. Discuss how this affects computation.

self._coils = coils
self.psc_array = psc_array
sopp.BiotSavart.__init__(self, coils)
MagneticField.__init__(self, depends_on=coils)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BiotSavart doesnt depend on psc_array?

and currents in the PSCs and the TFs.
"""

def __init__(self, base_psc_curves, coils_TF, eval_points, a_list, b_list, nfp=1,
Copy link
Copy Markdown
Contributor

@mishapadidar mishapadidar May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation of arguments. add discussion of cross section a_list, etc

return self.get_value()


class PSCArray():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generally we need consensus on having non-Optimizables

ncoils = len(self._coils)
if any([not self.fieldcache_get_status(f'B_{i}') for i in range(ncoils)]):
assert compute_derivatives >= 0
self.compute(compute_derivatives)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets double check that we can remove this without affect to functionality. We can default to leaving it unless necessary to remove

assert compute_derivatives >= 0
self.compute(compute_derivatives)
self._dB_by_dcoilcurrents = [self.fieldcache_get_or_create(f'B_{i}', [npoints, 3]) for i in range(ncoils)]
return self._dB_by_dcoilcurrents
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double check that we don't need to be setting self._dB_by_dcoilcurrents

**args
)

gammas = np.array([c.gamma() for c in psc_curves])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar computation happening in recompute_currents. Should we consolidate these operations?

self.biot_savart_total.set_points(self.eval_points)
# Optimizable.__init__(self, depends_on=[self.coils, self.coils_TF])

def vjp_setup(self, v_currents):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add dosctring describing use of this function

akaptano added 30 commits May 9, 2025 13:11
…e sure the unit tests and examples run well again.
…. Still have some issues from newly merged code slightly changing test outputs.
…_to_vtk, which needed fixing in all the example files.
…gain so I can better see what the current differences are with master now.
…n both dipoles and TF coils are saved jointly, with different number of quadrature points.
…ss, which seems to be required for the PSC arrays.
… force_and_torque_overhaul branch so committing for now and will revisit. Otherwise, got the QASH scripts working better with a single wout Schuett henneberg file.
…e curveplanarellipticalcylindrical is not exported.
…stic, and fixed the dipole array example doc file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants