hiddenSymmetries / simsopt

Simons Stellarator Optimizer Code
https://simsopt.readthedocs.io
MIT License
83 stars 43 forks source link

CurveXYZFourierSymmetries #404

Closed andrewgiuliani closed 2 months ago

andrewgiuliani commented 3 months ago

This pull request introduces a new helical curve representation called CurveXYZHelical. This curve is different from CurveXYZFourier because it can have discrete rotational symmetry. It can also be stellarator symmetric, or not.

We currently support a helical curve representation CurveHelical, but this curve is restricted to lie on a torus. The new CurveXYZHelical is not restricted to lie on a torus, and can represent curves like the one below. Viewing from above, the CurveXYZHelical appears to lie on a torus helical_top

but profile view reveals that it clearly does not: helical_side

When CurveXYZHelical is stellarator symmetric, then necessarily the curve must pass through the point (x0, 0, 0). If you do not want this, then the user can apply stellarator symmetry to a non-stellarator symmetric CurveXYZHelical curve and obtain a stellsym magnetic field from those two curves.

codecov[bot] commented 3 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 91.60%. Comparing base (d830719) to head (6841058).

Additional details and impacted files ```diff @@ Coverage Diff @@ ## master #404 +/- ## ========================================== + Coverage 91.55% 91.60% +0.04% ========================================== Files 74 75 +1 Lines 12911 12987 +76 ========================================== + Hits 11821 11897 +76 Misses 1090 1090 ``` | [Flag](https://app.codecov.io/gh/hiddenSymmetries/simsopt/pull/404/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hiddenSymmetries) | Coverage Δ | | |---|---|---| | [unittests](https://app.codecov.io/gh/hiddenSymmetries/simsopt/pull/404/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hiddenSymmetries) | `91.60% <100.00%> (+0.04%)` | :arrow_up: | Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hiddenSymmetries#carryforward-flags-in-the-pull-request-comment) to find out more.

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

andrewgiuliani commented 3 months ago

Here is a small generalization you could consider: in the transformation from \hat{x},\hat{y} to x,y, the angle in the rotation matrix could be multiplied by some integer. This would allow for curves for which you need to go around multiple times toroidally before they close. Not critical, just an idea.

sounds like a good idea, I'll add this to the PR in the coming days.

andrewgiuliani commented 2 months ago

I've introduced support for curves to wrap toroidally ntor times before biting its tail. This allows us to represent some more interesting curves with nfp-fold discrete rotational symmetry that pass ntor times toroidally before biting their tail. In addition to helical coils, we can now represent knots such as a trefoil:

trefoil

This trefoil has nfp=3 and ntor=2. I've added a unit test to verify this in geo.test_curve.Testing.test_trefoil_stellsym and geo.test_curve.Testing.test_trefoil_nonstellsym.

A few things to note:

  1. Since this is a much larger class of curves, i.e., not just helical curves, I've renamed the class to be CurveXYZFourierSymmetries, reflecting that the class has symmetries baked in (rotational and stellarator symmetries), that CurveXYZFourier does not.

  2. Note that ntor and nfp must be coprime, or else the actual nfp of the curve is nfp//gcd(nfp,ntor) and the actual ntor of the curve is ntor//gcd(nfp, ntor). To avoid confusion, we assert that gcd(nfp, ntor)=1 at instantiation of the class.

  3. When ntor=1 the usual relation showing rotational symmetry holds, i.e. gamma(theta + 1/nfp) = R(1/nfp) * gamma(theta), where R(alpha) is a rotation matrix. When ntor>1, a more general relation holds gamma(theta + 1/nfp) = R(ntor/nfp) * gamma(theta). This still results in a curve with nfp-fold discrete rotational symmetry.