Skip to content

Refactor of CS coil modelling (iohcl switch) #4205

@grmtrkngtn

Description

@grmtrkngtn

CS coil modelling in PROCESS

The current codebase lacks a single coherent definition of what iohcl means. In practice it is used to control:

  • whether a CS coil is counted in PF/CS circuit bookkeeping
  • whether some CS electrical calculations are performed
  • whether certain PF coil locations are allowed
  • whether some CS-specific output should appear

Switch ==iohcl== controls whether a central solenoid is present. A value of 1 denotes that this coil is present, and should be assigned a non-zero thickness dr_cs. A value of ==iohcl== = 0 denotes that no central solenoid is present, in which case the thickness dr_cs should be zero. No PF coils should be located at positions defined by i_pf_location(j) = 1 if no central solenoid is present.

The documentation tell us that we can either model "no CS at all" or include a CS, but the code and outputs show that it really behaves more like “CS not actively driving during flat-top” in at least some paths.

As a result, CS geometry can still exist in the radial build while PF/CS electrical logic and output partially assume the CS is absent, leading to inconsistent state, confusing output, and poorly implemented branching. All while the user may think they have not included a CS at all.

This needs a proper refactor and a clearer model of the intended operating modes.

Desired model states

There are at least three physically distinct cases we want to represent:

  1. CS present and driving current during flat-top
  2. CS present, used for start-up / ramp-up, but not used to drive flat-top current
    (e.g. NBI or another system sustains flat-top current)
  3. No CS coil present at all

Issues in current code

PFCoil still constructs CS state even when iohcl == 0

In pfcoil.py, the PF model:

  • conditionally increments the PF+CS coil count only if iohcl != 0
  • but still computes CS pulse-start current density unconditionally
  • and still calls self.cs_coil.calculate_cs_geometry(...) unconditionally inside PFCoil.pfcoil()

This means CS-related state is still created in memory even in the “no CS” branch, and the branching happens too late / inconsistently.

CS logic is split across PFCoil and CSCoil

PFCoil owns significant CS logic directly:

  • CS current-density ratios and waveform logic
  • CS filament count / use in efc
  • CS flux / volt-second calculations
  • CS-specific conditional branches keyed on iohcl

At the same time, there is already a CSCoil path (calculate_cs_geometry, place_cs_filaments, ohcalc, output routines), so CS responsibility is split between classes instead of being isolated cleanly.

This makes it unclear where the authoritative CS state machine should live.

build.py treats CS as physically present in the radial build

build.py always includes CS quantities in the inboard radial build output:

  • Central solenoid
  • CS precompression
  • CS precompresion to TF coil radial gap

and the cumulative radius logic includes these quantities directly.

The sample output shows these CS components appearing in the radial build:

  • dr_cs
  • dr_cs_precomp
  • dr_cs_tf_gap

4) Output becomes inconsistent when iohcl == 0

OUT.DAT includes CS-specific PF output still being emitted in the no-CS case, including:

  • CS current ratios:
    • f_j_cs_start_pulse_end_flat_top = 0.9
    • f_j_cs_start_end_flat_top = 1.0
  • CS coil entries in volt-second summaries
  • “Number of PF circuits including CS and plasma”
  • CS-labelled PF waveform output

At the same time, pfcoil.py also has a branch that prints “No central solenoid included” when iohcl == 0.

So the present behaviour mixes “no CS” with “CS still exists”.

Steps to resolve

  • Start from the premise of 3 CS states outlined above
  • Centralise the branching for CS (might not be so straight forward)
  • If it's possible, refactor CS calculations out of PFCoil class
    • otherwise implement appropriate branching
    • Refactor CS output to CSCoil class
  • Update docs.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions