|
| 1 | +from pathlib import Path |
| 2 | + |
| 3 | +import matplotlib.pyplot as plt |
| 4 | +import numpy as np |
| 5 | + |
| 6 | +from bluemira.base.constants import MU_0, MU_0_2PI, MU_0_4PI |
| 7 | +from bluemira.base.file import get_bluemira_path |
| 8 | +from bluemira.magnets.case_tf import create_case_tf_from_dict |
| 9 | +from bluemira.materials import MaterialCache |
| 10 | + |
| 11 | +material_path = get_bluemira_path("magnets", subfolder="examples") |
| 12 | +material_file = Path(material_path, "materials_mag.json") |
| 13 | +MATERIAL_CACHE = MaterialCache() |
| 14 | +MATERIAL_CACHE.load_from_file(material_file) |
| 15 | + |
| 16 | +case_tf_dict = { |
| 17 | + "name_in_registry": "TrapezoidalCaseTF", |
| 18 | + "name": "TrapezoidalCaseTF", |
| 19 | + "Ri": 3.708571428571428, |
| 20 | + "dy_ps": 0.05733333333333333, |
| 21 | + "dy_vault": 0.4529579163961617, |
| 22 | + "theta_TF": 22.5, |
| 23 | + "mat_case": "SS316-LN", |
| 24 | + "WPs": [ |
| 25 | + { |
| 26 | + "name_in_registry": "WindingPack", |
| 27 | + "name": "WindingPack", |
| 28 | + "conductor": { |
| 29 | + "name_in_registry": "SymmetricConductor", |
| 30 | + "name": "SymmetricConductor", |
| 31 | + "cable": { |
| 32 | + "name_in_registry": "DummyRectangularCableLTS", |
| 33 | + "name": "DummyRectangularCableLTS", |
| 34 | + "n_sc_strand": 321, |
| 35 | + "n_stab_strand": 476, |
| 36 | + "d_cooling_channel": 0.01, |
| 37 | + "void_fraction": 0.7, |
| 38 | + "cos_theta": 0.97, |
| 39 | + "sc_strand": { |
| 40 | + "name_in_registry": "SuperconductingStrand", |
| 41 | + "name": "Nb3Sn_strand", |
| 42 | + "d_strand": 0.001, |
| 43 | + "temperature": 5.7, |
| 44 | + "materials": [ |
| 45 | + {"material": "Nb3Sn - WST", "fraction": 0.5}, |
| 46 | + {"material": "Copper100", "fraction": 0.5}, |
| 47 | + ], |
| 48 | + }, |
| 49 | + "stab_strand": { |
| 50 | + "name_in_registry": "Strand", |
| 51 | + "name": "Stabilizer", |
| 52 | + "d_strand": 0.001, |
| 53 | + "temperature": 5.7, |
| 54 | + "materials": [{"material": "Copper300", "fraction": 1.0}], |
| 55 | + }, |
| 56 | + "dx": 0.034648435154495685, |
| 57 | + "aspect_ratio": 1.2, |
| 58 | + }, |
| 59 | + "mat_jacket": "SS316-LN", |
| 60 | + "mat_ins": "DummyInsulator", |
| 61 | + "dx_jacket": 0.0030808556812487366, |
| 62 | + "dx_ins": 0.001, |
| 63 | + }, |
| 64 | + "nx": 25, |
| 65 | + "ny": 6, |
| 66 | + }, |
| 67 | + { |
| 68 | + "name_in_registry": "WindingPack", |
| 69 | + "name": "WindingPack", |
| 70 | + "conductor": { |
| 71 | + "name_in_registry": "SymmetricConductor", |
| 72 | + "name": "SymmetricConductor", |
| 73 | + "cable": { |
| 74 | + "name_in_registry": "DummyRectangularCableLTS", |
| 75 | + "name": "DummyRectangularCableLTS", |
| 76 | + "n_sc_strand": 321, |
| 77 | + "n_stab_strand": 476, |
| 78 | + "d_cooling_channel": 0.01, |
| 79 | + "void_fraction": 0.7, |
| 80 | + "cos_theta": 0.97, |
| 81 | + "sc_strand": { |
| 82 | + "name_in_registry": "SuperconductingStrand", |
| 83 | + "name": "Nb3Sn_strand", |
| 84 | + "d_strand": 0.001, |
| 85 | + "temperature": 5.7, |
| 86 | + "materials": [ |
| 87 | + {"material": "Nb3Sn - WST", "fraction": 0.5}, |
| 88 | + {"material": "Copper100", "fraction": 0.5}, |
| 89 | + ], |
| 90 | + }, |
| 91 | + "stab_strand": { |
| 92 | + "name_in_registry": "Strand", |
| 93 | + "name": "Stabilizer", |
| 94 | + "d_strand": 0.001, |
| 95 | + "temperature": 5.7, |
| 96 | + "materials": [{"material": "Copper300", "fraction": 1.0}], |
| 97 | + }, |
| 98 | + "dx": 0.034648435154495685, |
| 99 | + "aspect_ratio": 1.2, |
| 100 | + }, |
| 101 | + "mat_jacket": "SS316-LN", |
| 102 | + "mat_ins": "DummyInsulator", |
| 103 | + "dx_jacket": 0.0030808556812487366, |
| 104 | + "dx_ins": 0.001, |
| 105 | + }, |
| 106 | + "nx": 18, |
| 107 | + "ny": 1, |
| 108 | + }, |
| 109 | + ], |
| 110 | +} |
| 111 | + |
| 112 | +case_tf = create_case_tf_from_dict(case_tf_dict) |
| 113 | + |
| 114 | +case_tf.plot(show=True, homogenized=False) |
| 115 | + |
| 116 | +# Machine parameters (should match the original setup) |
| 117 | +R0 = 8.6 |
| 118 | +B0 = 4.39 |
| 119 | +A = 2.8 |
| 120 | +n_TF = 16 |
| 121 | +ripple = 6e-3 |
| 122 | +# operational current per conductor |
| 123 | +Iop = 70.0e3 |
| 124 | +# Safety factor to be considered on the allowable stress |
| 125 | +safety_factor = 1.5 * 1.3 |
| 126 | + |
| 127 | +# Derived values |
| 128 | +a = R0 / A |
| 129 | +d = 1.82 |
| 130 | +Ri = R0 - a - d |
| 131 | +Re = (R0 + a) * (1 / ripple) ** (1 / n_TF) |
| 132 | +B_TF_i = 1.08 * (MU_0_2PI * n_TF * (B0 * R0 / MU_0_2PI / n_TF) / Ri) |
| 133 | +pm = B_TF_i**2 / (2 * MU_0) |
| 134 | +t_z = 0.5 * np.log(Re / Ri) * MU_0_4PI * n_TF * (B0 * R0 / MU_0_2PI / n_TF) ** 2 |
| 135 | +T_sc = 4.2 |
| 136 | +T_margin = 1.5 |
| 137 | +T_op = T_sc + T_margin |
| 138 | +S_Y = 1e9 / safety_factor |
| 139 | +n_cond = int(np.floor((B0 * R0 / MU_0_2PI / n_TF) / Iop)) |
| 140 | + |
| 141 | +# Layout and WP parameters |
| 142 | +layout = "auto" |
| 143 | +wp_reduction_factor = 0.75 |
| 144 | +min_gap_x = 2 * (R0 * 2 / 3 * 1e-2) # 2 * dr_plasma_side |
| 145 | +n_layers_reduction = 4 |
| 146 | + |
| 147 | +# Optimization parameters already defined earlier |
| 148 | +bounds_cond_jacket = np.array([1e-5, 0.2]) |
| 149 | +bounds_dy_vault = np.array([0.1, 2]) |
| 150 | +max_niter = 100 |
| 151 | +err = 1e-6 |
| 152 | + |
| 153 | +# optimize number of stabilizer strands |
| 154 | +sc_strand = case_tf.WPs[0].conductor.cable.sc_strand |
| 155 | +Ic_sc = sc_strand.Ic(B=B_TF_i, temperature=T_op) |
| 156 | +case_tf.WPs[0].conductor.cable.n_sc_strand = int(np.ceil(Iop / Ic_sc)) |
| 157 | + |
| 158 | +from bluemira.magnets.utils import delayed_exp_func |
| 159 | + |
| 160 | +Tau_discharge = 20 # [s] |
| 161 | +t_delay = 3 # [s] |
| 162 | +t0 = 0 # [s] |
| 163 | +hotspot_target_temperature = 250.0 # [K] |
| 164 | + |
| 165 | +tf = Tau_discharge |
| 166 | +T_for_hts = T_op |
| 167 | +I_fun = delayed_exp_func(Iop, Tau_discharge, t_delay) |
| 168 | +B_fun = delayed_exp_func(B_TF_i, Tau_discharge, t_delay) |
| 169 | + |
| 170 | +print("cable") |
| 171 | +print(case_tf.WPs[0].conductor.cable) |
| 172 | + |
| 173 | +case_tf.WPs[0].conductor.cable.optimize_n_stab_ths( |
| 174 | + t0, |
| 175 | + tf, |
| 176 | + T_for_hts, |
| 177 | + hotspot_target_temperature, |
| 178 | + B_fun, |
| 179 | + I_fun, |
| 180 | + bounds=[1, 10000], |
| 181 | + show=True, |
| 182 | +) |
| 183 | + |
| 184 | +# Optimize case with structural constraints |
| 185 | +case_tf.optimize_jacket_and_vault( |
| 186 | + pm=pm, |
| 187 | + fz=t_z, |
| 188 | + temperature=T_op, |
| 189 | + B=B_TF_i, |
| 190 | + allowable_sigma=S_Y, |
| 191 | + bounds_cond_jacket=bounds_cond_jacket, |
| 192 | + bounds_dy_vault=bounds_dy_vault, |
| 193 | + layout=layout, |
| 194 | + wp_reduction_factor=wp_reduction_factor, |
| 195 | + min_gap_x=min_gap_x, |
| 196 | + n_layers_reduction=n_layers_reduction, |
| 197 | + max_niter=max_niter, |
| 198 | + eps=err, |
| 199 | + n_conds=n_cond, |
| 200 | +) |
| 201 | + |
| 202 | +case_tf.plot_convergence() |
| 203 | + |
| 204 | +show = True |
| 205 | +homogenized = True |
| 206 | +if show: |
| 207 | + scalex = np.array([2, 1]) |
| 208 | + scaley = np.array([1, 1.2]) |
| 209 | + |
| 210 | + ax = case_tf.plot(homogenized=homogenized) |
| 211 | + ax.set_aspect("equal") |
| 212 | + |
| 213 | + # Fix the x and y limits |
| 214 | + ax.set_xlim(-scalex[0] * case_tf.dx_i, scalex[1] * case_tf.dx_i) |
| 215 | + ax.set_ylim(scaley[0] * 0, scaley[1] * case_tf.Ri) |
| 216 | + |
| 217 | + deltax = [-case_tf.dx_i / 2, case_tf.dx_i / 2] |
| 218 | + |
| 219 | + ax.plot( |
| 220 | + [-scalex[0] * case_tf.dx_i, -case_tf.dx_i / 2], [case_tf.Ri, case_tf.Ri], "k:" |
| 221 | + ) |
| 222 | + |
| 223 | + for i in range(len(case_tf.WPs)): |
| 224 | + ax.plot( |
| 225 | + [-scalex[0] * case_tf.dx_i, -case_tf.dx_i / 2], |
| 226 | + [case_tf.R_wp_i[i], case_tf.R_wp_i[i]], |
| 227 | + "k:", |
| 228 | + ) |
| 229 | + |
| 230 | + ax.plot( |
| 231 | + [-scalex[0] * case_tf.dx_i, -case_tf.dx_i / 2], |
| 232 | + [case_tf.R_wp_k[-1], case_tf.R_wp_k[-1]], |
| 233 | + "k:", |
| 234 | + ) |
| 235 | + ax.plot( |
| 236 | + [-scalex[0] * case_tf.dx_i, -case_tf.dx_i / 2], [case_tf.Rk, case_tf.Rk], "k:" |
| 237 | + ) |
| 238 | + |
| 239 | + ax.set_title("Equatorial cross section of the TF WP") |
| 240 | + ax.set_xlabel("Toroidal direction [m]") |
| 241 | + ax.set_ylabel("Radial direction [m]") |
| 242 | + |
| 243 | + plt.show() |
| 244 | + |
| 245 | +I_sc = case_tf.WPs[0].conductor.cable.sc_strand.Ic(B=B_TF_i, temperature=T_op) |
| 246 | +I_max = I_sc * case_tf.WPs[0].conductor.cable.n_sc_strand |
| 247 | +I_TF_max = I_max * case_tf.n_conductors |
| 248 | +print(I_max) |
| 249 | +print(I_TF_max) |
| 250 | +I_TF = R0 * B0 / (MU_0_2PI * n_TF) |
| 251 | +print(I_TF) |
0 commit comments