Skip to content

Add NeutronWallLoading objective#2076

Draft
tokamaster wants to merge 23 commits intoPlasmaControl:masterfrom
tokamaster:em/nwl
Draft

Add NeutronWallLoading objective#2076
tokamaster wants to merge 23 commits intoPlasmaControl:masterfrom
tokamaster:em/nwl

Conversation

@tokamaster
Copy link
Copy Markdown
Collaborator

This PR adds a NeutronWallLoading objective that computes DT neutron wall loading on a constant-offset surface derived from the equilibrium boundary, enabling it as a target for equilibrium/wall optimization.

Reference:
https://iopscience.iop.org/article/10.1088/1741-4326/ac6a67/

@tokamaster tokamaster requested a review from dpanici February 3, 2026 21:23
@dpanici dpanici requested review from dpanici and removed request for dpanici February 4, 2026 01:40
@YigitElma YigitElma deleted the branch PlasmaControl:master March 3, 2026 00:56
@YigitElma YigitElma closed this Mar 3, 2026
@f0uriest
Copy link
Copy Markdown
Member

f0uriest commented Mar 3, 2026

Why was this closed?

@YigitElma YigitElma reopened this Mar 3, 2026
@YigitElma
Copy link
Copy Markdown
Collaborator

Why was this closed?

Oh I think when I merged #2016 and deleted the branch, it automatically closed this one since this was pointing to that. Should we change the target branch to master now? I restored the other branch just in case.

_units = "(MW/m^2)"
_print_value_fmt = "Neutron wall loading: "

def __init__(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We should make this the most general one (where either surface or eq may be free), can you update it to the one with the more general logic?

Copy link
Copy Markdown
Collaborator

@dpanici dpanici left a comment

Choose a reason for hiding this comment

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

  • update your PR with the original branch it was pointed to (PlasmaControl:dp/offset-differentiable)
  • then update your PR with PlasmaControl:master (we can also point this PR towards master then and the tests will run)
  • update the NWL objective to be the more general one where either surface or eq may vary, or both of them
  • Add tests (the objectives have tests in tests/test_objective_funs.py which must be added, see the way the tests for PlasmaVesselDistance are setup in that function)
    • you will need to add the NWL objective to the two "specials" lists (first second) in that function, as they require special logic and separate unique tests. again see how PlasmaVesselDistance is done: first second)
    • and maybe if we can think of another good test beyond these basic ones which only test the numerics (is the objective scalar value approx constant with resolution, and is there no NaN when computing it reverse mode gradient), so a test for correctness would also be good (I have at the moment no ideas on a good one though, maybe an axisym eq and surface and assert the NWL is (approximately) independent of phi?

@dpanici
Copy link
Copy Markdown
Collaborator

dpanici commented Mar 26, 2026

Ah wait I just remembered, this one we are making an offset surface as the equilibrium is changing. I guess we can leave it as is for now, since iirc this way worked better than just a general thing?

Might also be good, if we can, to have all four options available:

  • fixed eq free vessel (given)
  • free eq fixed vessel (given)
  • free eq free vessel (given)
  • free eq conformal vessel (computed on the fly)

Though you tested this more than I have. Do you think there would be use case for more than just the free eq conformal vessel (how it is right now)? I would think there could at least be a use for fixing the eq and allowing the vessel to change, though I doubt anyone will be scoping out their vacuum vessel design within DESC (there are better ways using e.g. Parastell for that, instead of relying on the DESC FourierRZToroidalSurface representation of the vessel which can't do sharp edges which might exist in reality)

The most general implementation would be to have all 4 options available as modes of operation for this objective

@tokamaster
Copy link
Copy Markdown
Collaborator Author

I agree having the 4 options available is the best strategy. Note that what we are 'modeling' here is the armor/first wall. I think [free eq + free vessel] has some challenges constraining the eq within the vessel etc. I am not sure how useful [free eq + fixed vessel] is, since normally the equilibrium 'design' predates the vessel design. Maybe for light 'adjustments' makes sense.

[fixed eq + free vessel] is definitely useful, but I remember having some issues constraining the vessel too.

I believe [free eq + conformal vessel] is the most useful of all. My intuition tells me that the optimal way of designing a wall enclosing a volume minimizing the 'vacuum' space is conformal. We really want to minimize this 'vacuum' space in a power plant since we do not want to 'waste' magnetic field. Of course there are some exceptions with divertors, heating systems, etc.

This implementation only supports [free eq + conformal vessel] as you pointed out. We can inherit the same logic in PlasmaVesselDistance, and we could have the other options too.

@tokamaster tokamaster changed the base branch from dp/offset-differentiable to master March 27, 2026 20:28
@tokamaster
Copy link
Copy Markdown
Collaborator Author

I'm not totally sure the rebase worked out...

I have generalized the objective function a la PlasmaVesselDistance.
Now it is capable of [free eq + conformal wall] (legacy method), as well as [free eq + free wall], [free eq + fixed wall], [fixed eq + free wall]. offset is only required for the legacy method to determine the distance between the conformal wall and the LCFS. Legacy method works with surface=None. Other methods need a surface object (FourierRZToroidalSurface) as an input.

I've added the following tests:

  • output shape matches surface_grid.num_nodes.
  • output values are nonnegative.
  • doubling electron_density.params on a copied equilibrium and check the wall loading scales like scale**2.
  • surface-area-weighted mean should approximately match 0.8*P_fusion/S.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 27, 2026

Memory benchmark result

|               Test Name                |      %Δ      |    Master (MB)     |      PR (MB)       |    Δ (MB)    |    Time PR (s)     |  Time Master (s)   |
| -------------------------------------- | ------------ | ------------------ | ------------------ | ------------ | ------------------ | ------------------ |
  test_objective_jac_w7x                 |   -1.33 %    |     4.116e+03      |     4.061e+03      |    -54.85    |       42.27        |       39.05        |
  test_proximal_jac_w7x_with_eq_update   |   -0.84 %    |     6.559e+03      |     6.504e+03      |    -55.39    |       156.31       |       158.92       |
  test_proximal_freeb_jac                |    0.41 %    |     1.342e+04      |     1.348e+04      |    54.50     |       93.54        |       93.44        |
  test_proximal_freeb_jac_blocked        |    0.40 %    |     7.713e+03      |     7.744e+03      |    30.92     |       84.22        |       82.82        |
  test_proximal_freeb_jac_batched        |    0.40 %    |     7.689e+03      |     7.719e+03      |    30.55     |       84.03        |       83.31        |
  test_proximal_jac_ripple               |    0.29 %    |     3.624e+03      |     3.634e+03      |    10.61     |       61.46        |       60.35        |
  test_proximal_jac_ripple_bounce1d      |   -0.37 %    |     3.755e+03      |     3.741e+03      |    -13.99    |       74.14        |       75.23        |
  test_eq_solve                          |    0.82 %    |     2.256e+03      |     2.274e+03      |    18.59     |       90.74        |       90.54        |

For the memory plots, go to the summary of Memory Benchmarks workflow and download the artifact.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 27, 2026

Codecov Report

❌ Patch coverage is 87.58621% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.42%. Comparing base (d628bca) to head (cae8c0c).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
desc/objectives/_geometry.py 87.58% 18 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2076      +/-   ##
==========================================
- Coverage   94.45%   94.42%   -0.04%     
==========================================
  Files         101      101              
  Lines       28593    28737     +144     
==========================================
+ Hits        27008    27134     +126     
- Misses       1585     1603      +18     
Files with missing lines Coverage Δ
desc/geometry/surface.py 97.67% <ø> (ø)
desc/objectives/__init__.py 100.00% <ø> (ø)
desc/objectives/_geometry.py 94.35% <87.58%> (-2.44%) ⬇️

... and 2 files with indirect coverage changes

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants