Skip to content

Commit 5eeaeff

Browse files
authored
Refactor CS coil stress routines and variables (#3962)
* Refactor axial stress calculation in CSCoil class to improve parameter handling and documentation * 🔄 - Rename axial_stress method to `calculate_cs_self_peak_midplane_axial_stress` and update references in tests * 🔄 - Rename variable `sig_axial` to `stress_z_cs_self_peak_midplane` and update references in PFCoil and CSCoil classes * 🔄 - Rename axial_force variable to `forc_z_cs_self_peak_midplane` and update references in PFCoil and CSCoil classes * 📝 Update axial stress calculation in CSCoil class to use average axial stress at coil interface * Update tests * 🔄 - Update plot_cs_coil_structure to include peak magnetic field, axial force, and stress in the plot output 🔄 - Refactor test cases for calculate_cs_self_peak_midplane_axial_stress to ensure proper assertions and formatting
1 parent 85151cc commit 5eeaeff

File tree

6 files changed

+186
-180
lines changed

6 files changed

+186
-180
lines changed

documentation/eng-models/central-solenoid.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,38 @@ The peak field at the bore of the central solenoid will not be the same as that
123123

124124
-----------
125125

126-
### Axial stresses | `axial_stress()`
126+
### Axial stresses | `calculate_cs_self_peak_midplane_axial_stress()`
127+
128+
129+
The vertical (axial) force for a "thin-walled" solenoid ($\alpha = 1$) at the midplane is given by[^2]:
130+
131+
$$
132+
F_{z}(0)=\frac{\mu_0}{2}\left(\frac{N I}{2 \times dz_{\text{half}}}\right) \times \\
133+
\left(2dz_{\text{half}} \sqrt{4r_{\text{CS,outer}}^2 + dz_{\text{half}}^2} \left[K(k_b) - E(k_b)\right]\\
134+
- 2dz_{\text{half}} \sqrt{4r_{\text{CS,outer}}^2 + 4dz_{\text{half}}^2} \left[K(k_{2b}) - E(k_{2b})\right] \right)
135+
$$
136+
137+
where the modulus $k_{2b}$ is given by
138+
139+
$$
140+
k_{2b} = \sqrt{\frac{4r_{\text{CS,outer}}^2}{4r_{\text{CS,outer}}^2+4dz_{\text{half}}^2}}
141+
$$
142+
143+
and $k_b$ is given by:
144+
145+
$$
146+
k_{2b} = \sqrt{\frac{4r_{\text{CS,outer}}^2}{4r_{\text{CS,outer}}^2+dz_{\text{half}}^2}}
147+
$$
148+
149+
Here $K(k)$ and $E(k)$ are the complete elliptic integrals, respectively of the first and second kinds.
150+
151+
152+
The axial compressive force at $z$ in an isolated solenoid increases from 0 at $z = dz_{\text{half}}$
153+
to the maximum at the midplane, $F_{z}(0)$.
154+
155+
156+
157+
--------------------------
127158

128159

129160
### Hoop stress | `hoop_stress()`
@@ -290,4 +321,5 @@ constraints (26 and 27) are activated.
290321

291322

292323
[^1]: M. N. Wilson, Superconducting Magnets. Oxford University Press, USA, 1983, ISBN 13: 9780198548102
324+
[^2]: Case Studies in Superconducting Magnets. Boston, MA: Springer US, 2009. doi: https://doi.org/10.1007/b112047.
293325

process/data_structure/pfcoil_variables.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929

3030
ssq0: float = None
3131

32-
sig_axial: float = None
32+
stress_z_cs_self_peak_midplane: float = None
33+
"""Peak axial stress (z) in central solenoid at midplane due to its own field (when at peak current) (Pa)"""
3334

3435
sig_hoop: float = None
3536

36-
axial_force: float = None
37+
forc_z_cs_self_peak_midplane: float = None
38+
"""Axial force (z) on central solenoid at midplane due to its own field (when at peak current) (N)"""
3739

3840
r_pf_cs_current_filaments: list[float] = None
3941
"""array of radial positions of current filaments in central solenoid"""
@@ -567,9 +569,9 @@ def init_pfcoil_module():
567569
global nfxf
568570
global ricpf
569571
global ssq0
570-
global sig_axial
572+
global stress_z_cs_self_peak_midplane
571573
global sig_hoop
572-
global axial_force
574+
global forc_z_cs_self_peak_midplane
573575
global r_pf_cs_current_filaments
574576
global z_pf_cs_current_filaments
575577
global c_pf_cs_current_filaments
@@ -587,9 +589,9 @@ def init_pfcoil_module():
587589
nfxf = 0
588590
ricpf = 0.0
589591
ssq0 = 0.0
590-
sig_axial = 0.0
592+
stress_z_cs_self_peak_midplane = 0.0
591593
sig_hoop = 0.0
592-
axial_force = 0.0
594+
forc_z_cs_self_peak_midplane = 0.0
593595

594596
r_pf_cs_current_filaments = np.zeros(NFIXMX)
595597
z_pf_cs_current_filaments = np.zeros(NFIXMX)

process/io/plot_proc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9131,7 +9131,9 @@ def plot_cs_coil_structure(axis, fig, mfile_data, scan, colour_scheme=1):
91319131
f"CS poloidal area: {mfile_data.data['a_cs_poloidal'].get_scan(scan):.4f} m$^2$\n"
91329132
f"$N_{{\\text{{turns}}}}:$ {mfile_data.data['n_pf_coil_turns[n_cs_pf_coils-1]'].get_scan(scan):,.2f}\n"
91339133
f"$I_{{\\text{{peak}}}}:$ {mfile_data.data['c_pf_cs_coils_peak_ma[n_cs_pf_coils-1]'].get_scan(scan):.3f}$ \\ MA$\n"
9134-
f"$B_{{\\text{{peak}}}}:$ {mfile_data.data['b_pf_coil_peak[n_cs_pf_coils-1]'].get_scan(scan):.3f}$ \\ T$\n\n"
9134+
f"$B_{{\\text{{peak}}}}:$ {mfile_data.data['b_pf_coil_peak[n_cs_pf_coils-1]'].get_scan(scan):.3f}$ \\ T$\n"
9135+
f"$F_{{\\text{{z,self,peak}}}}:$ {mfile_data.data['forc_z_cs_self_peak_midplane'].get_scan(scan) / 1e6:.3f}$ \\ MN$\n"
9136+
f"$\\sigma_{{\\text{{z,self,peak}}}}:$ {mfile_data.data['stress_z_cs_self_peak_midplane'].get_scan(scan) / 1e6:.3f}$ \\ MPa$ "
91359137
)
91369138

91379139
axis.text(

process/pfcoil.py

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2208,8 +2208,8 @@ def outpf(self):
22082208
op.ovarre(
22092209
self.outfile,
22102210
"Axial stress in CS steel (Pa)",
2211-
"(sig_axial)",
2212-
pfcoil_variables.sig_axial,
2211+
"(stress_z_cs_self_peak_midplane)",
2212+
pfcoil_variables.stress_z_cs_self_peak_midplane,
22132213
"OP ",
22142214
)
22152215
op.ovarre(
@@ -2222,8 +2222,8 @@ def outpf(self):
22222222
op.ovarre(
22232223
self.outfile,
22242224
"Axial force in CS (N)",
2225-
"(axial_force)",
2226-
pfcoil_variables.axial_force,
2225+
"(forc_z_cs_self_peak_midplane)",
2226+
pfcoil_variables.forc_z_cs_self_peak_midplane,
22272227
"OP ",
22282228
)
22292229
op.ovarre(
@@ -3343,8 +3343,21 @@ def ohcalc(self):
33433343
)
33443344

33453345
# New calculation from Y. Iwasa for axial stress
3346-
pfcoil_variables.sig_axial, pfcoil_variables.axial_force = (
3347-
self.axial_stress()
3346+
(
3347+
pfcoil_variables.stress_z_cs_self_peak_midplane,
3348+
pfcoil_variables.forc_z_cs_self_peak_midplane,
3349+
) = self.calculate_cs_self_peak_midplane_axial_stress(
3350+
r_cs_outer=pfcoil_variables.r_pf_coil_outer[
3351+
pfcoil_variables.n_cs_pf_coils - 1
3352+
],
3353+
r_cs_inner=pfcoil_variables.r_pf_coil_inner[
3354+
pfcoil_variables.n_cs_pf_coils - 1
3355+
],
3356+
dz_cs_half=pfcoil_variables.dz_cs_full / 2.0,
3357+
c_cs_peak=pfcoil_variables.c_pf_cs_coils_peak_ma[
3358+
pfcoil_variables.n_cs_pf_coils - 1
3359+
]
3360+
* 1.0e6,
33483361
)
33493362

33503363
# Allowable (hoop) stress (Pa) alstroh
@@ -3372,8 +3385,11 @@ def ohcalc(self):
33723385

33733386
if pfcoil_variables.i_cs_stress == 1:
33743387
pfcoil_variables.s_shear_cs_peak = max(
3375-
abs(pfcoil_variables.sig_hoop - pfcoil_variables.sig_axial),
3376-
abs(pfcoil_variables.sig_axial - 0.0e0),
3388+
abs(
3389+
pfcoil_variables.sig_hoop
3390+
- pfcoil_variables.stress_z_cs_self_peak_midplane
3391+
),
3392+
abs(pfcoil_variables.stress_z_cs_self_peak_midplane - 0.0e0),
33773393
abs(0.0e0 - pfcoil_variables.sig_hoop),
33783394
)
33793395
else:
@@ -3679,65 +3695,81 @@ def output_cs_structure(self):
36793695
"OP ",
36803696
)
36813697

3682-
def axial_stress(self):
3683-
"""Calculation of axial stress of central solenoid.
3698+
def calculate_cs_self_peak_midplane_axial_stress(
3699+
self,
3700+
r_cs_outer: float,
3701+
r_cs_inner: float,
3702+
dz_cs_half: float,
3703+
c_cs_peak: float,
3704+
) -> tuple[float, float]:
3705+
"""
3706+
Calculate axial stress and axial force for the central solenoid.
3707+
3708+
:param float r_cs_outer: Outer radius of the central solenoid (m).
3709+
:param float r_cs_inner: Inner radius of the central solenoid (m).
3710+
:param float dz_cs_half: Half-height of the central solenoid (m).
3711+
:param float c_cs_peak: Peak CS coil current (A).
36843712
3685-
author: J Morris, CCFE, Culham Science Centre
3686-
This routine calculates the axial stress of the central solenoid
3687-
from "Case studies in superconducting magnets", Y. Iwasa, Springer
3713+
:returns: A tuple containing the unsmeared axial stress and the axial force.
3714+
:rtype: tuple(float, float)
3715+
The first element is the unsmeared axial stress in MPa.
3716+
The second element is the axial force in newtons (N).
36883717
3689-
:return: unsmeared axial stress [MPa], axial force [N]
3690-
:rtype: tuple[float, float]
3691-
"""
3692-
b = pfcoil_variables.r_pf_coil_outer[pfcoil_variables.n_cs_pf_coils - 1]
3718+
:note:
3719+
The axial force is computed using elliptic-integral based terms and the
3720+
unsmeared axial stress is obtained by dividing the axial force by
3721+
the effective steel area associated with the CS turns.
36933722
3694-
# Half height of central Solenoid [m]
3695-
hl = pfcoil_variables.z_pf_coil_upper[pfcoil_variables.n_cs_pf_coils - 1]
3723+
:references:
3724+
- Case Studies in Superconducting Magnets. Boston, MA: Springer US, 2009.
3725+
doi: https://doi.org/10.1007/b112047.
36963726
3697-
# Central Solenoid current [A]
3698-
ni = (
3699-
pfcoil_variables.c_pf_cs_coils_peak_ma[pfcoil_variables.n_cs_pf_coils - 1]
3700-
* 1.0e6
3701-
)
3727+
"""
37023728

37033729
# kb term for elliptical integrals
37043730
# kb2 = SQRT((4.0e0*b**2)/(4.0e0*b**2 + hl**2))
3705-
kb2 = (4.0e0 * b**2) / (4.0e0 * b**2 + hl**2)
3731+
kb2 = (4.0e0 * r_cs_outer**2) / (4.0e0 * r_cs_outer**2 + dz_cs_half**2)
37063732

37073733
# k2b term for elliptical integrals
37083734
# k2b2 = SQRT((4.0e0*b**2)/(4.0e0*b**2 + 4.0e0*hl**2))
3709-
k2b2 = (4.0e0 * b**2) / (4.0e0 * b**2 + 4.0e0 * hl**2)
3735+
k2b2 = (4.0e0 * r_cs_outer**2) / (4.0e0 * r_cs_outer**2 + 4.0e0 * dz_cs_half**2)
37103736

37113737
# term 1
3712-
axial_term_1 = -(constants.RMU0 / 2.0e0) * (ni / (2.0e0 * hl)) ** 2
3738+
axial_term_1 = (
3739+
-(constants.RMU0 / 2.0e0) * (c_cs_peak / (2.0e0 * dz_cs_half)) ** 2
3740+
)
37133741

37143742
# term 2
37153743
ekb2_1 = ellipk(kb2)
37163744
ekb2_2 = ellipe(kb2)
37173745
axial_term_2 = (
3718-
2.0e0 * hl * (math.sqrt(4.0e0 * b**2 + hl**2)) * (ekb2_1 - ekb2_2)
3746+
2.0e0
3747+
* dz_cs_half
3748+
* (math.sqrt(4.0e0 * r_cs_outer**2 + dz_cs_half**2))
3749+
* (ekb2_1 - ekb2_2)
37193750
)
37203751

37213752
# term 3
37223753
ek2b2_1 = ellipk(k2b2)
37233754
ek2b2_2 = ellipe(k2b2)
37243755
axial_term_3 = (
3725-
2.0e0 * hl * (math.sqrt(4.0e0 * b**2 + 4.0e0 * hl**2)) * (ek2b2_1 - ek2b2_2)
3756+
2.0e0
3757+
* dz_cs_half
3758+
* (math.sqrt(4.0e0 * r_cs_outer**2 + 4.0e0 * dz_cs_half**2))
3759+
* (ek2b2_1 - ek2b2_2)
37263760
)
37273761

37283762
# calculate axial force [N]
3729-
axial_force = axial_term_1 * (axial_term_2 - axial_term_3)
3763+
forc_z_cs_self_peak_midplane = axial_term_1 * (axial_term_2 - axial_term_3)
37303764

37313765
# axial area [m2]
3732-
area_ax = constants.PI * (
3733-
pfcoil_variables.r_pf_coil_outer[pfcoil_variables.n_cs_pf_coils - 1] ** 2
3734-
- pfcoil_variables.r_pf_coil_inner[pfcoil_variables.n_cs_pf_coils - 1] ** 2
3735-
)
3766+
area_ax = constants.PI * (r_cs_outer**2 - r_cs_inner**2)
37363767

3737-
# calculate unsmeared axial stress [MPa]
3738-
s_axial = axial_force / (pfcoil_variables.f_a_cs_turn_steel * 0.5 * area_ax)
3768+
# Calculate unsmeared axial stress
3769+
# Average axial stress at the interface of each half of the coil
3770+
s_axial = forc_z_cs_self_peak_midplane / (0.5 * area_ax)
37393771

3740-
return s_axial, axial_force
3772+
return s_axial, forc_z_cs_self_peak_midplane
37413773

37423774
def hoop_stress(self, r):
37433775
"""Calculation of hoop stress of central solenoid.

0 commit comments

Comments
 (0)